diff options
Diffstat (limited to 'target/linux/ipq806x/patches/0169-clk-qcom-Add-support-for-Krait-clocks.patch')
-rw-r--r-- | target/linux/ipq806x/patches/0169-clk-qcom-Add-support-for-Krait-clocks.patch | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/target/linux/ipq806x/patches/0169-clk-qcom-Add-support-for-Krait-clocks.patch b/target/linux/ipq806x/patches/0169-clk-qcom-Add-support-for-Krait-clocks.patch new file mode 100644 index 0000000..9b76f59 --- /dev/null +++ b/target/linux/ipq806x/patches/0169-clk-qcom-Add-support-for-Krait-clocks.patch @@ -0,0 +1,203 @@ +From 63ecfef8560631a15ee13129b2778cd4dffbcfe2 Mon Sep 17 00:00:00 2001 +From: Stephen Boyd <sboyd@codeaurora.org> +Date: Wed, 18 Jun 2014 14:18:31 -0700 +Subject: [PATCH 169/182] clk: qcom: Add support for Krait clocks + +The Krait clocks are made up of a series of muxes and a divider +that choose between a fixed rate clock and dedicated HFPLLs for +each CPU. Instead of using mmio accesses to remux parents, the +Krait implementation exposes the remux control via cp15 +registers. Support these clocks. + +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + drivers/clk/qcom/Kconfig | 4 ++ + drivers/clk/qcom/Makefile | 1 + + drivers/clk/qcom/clk-krait.c | 121 ++++++++++++++++++++++++++++++++++++++++++ + drivers/clk/qcom/clk-krait.h | 22 ++++++++ + 4 files changed, 148 insertions(+) + create mode 100644 drivers/clk/qcom/clk-krait.c + create mode 100644 drivers/clk/qcom/clk-krait.h + +diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig +index de8ba31..70b6a7c 100644 +--- a/drivers/clk/qcom/Kconfig ++++ b/drivers/clk/qcom/Kconfig +@@ -61,3 +61,7 @@ config QCOM_HFPLL + Support for the high-frequency PLLs present on Qualcomm devices. + Say Y if you want to support CPU frequency scaling on devices + such as MSM8974, APQ8084, etc. ++ ++config KRAIT_CLOCKS ++ bool ++ select KRAIT_L2_ACCESSORS +diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile +index d0d8e3d..6482165 100644 +--- a/drivers/clk/qcom/Makefile ++++ b/drivers/clk/qcom/Makefile +@@ -7,6 +7,7 @@ clk-qcom-y += clk-rcg.o + clk-qcom-y += clk-rcg2.o + clk-qcom-y += clk-branch.o + clk-qcom-y += clk-generic.o ++clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o + clk-qcom-y += clk-hfpll.o + clk-qcom-y += reset.o + +diff --git a/drivers/clk/qcom/clk-krait.c b/drivers/clk/qcom/clk-krait.c +new file mode 100644 +index 0000000..4283426 +--- /dev/null ++++ b/drivers/clk/qcom/clk-krait.c +@@ -0,0 +1,121 @@ ++/* ++ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/io.h> ++#include <linux/delay.h> ++#include <linux/err.h> ++#include <linux/clk-provider.h> ++#include <linux/spinlock.h> ++ ++#include <asm/krait-l2-accessors.h> ++ ++#include "clk-krait.h" ++ ++/* Secondary and primary muxes share the same cp15 register */ ++static DEFINE_SPINLOCK(kpss_clock_reg_lock); ++ ++#define LPL_SHIFT 8 ++static void __kpss_mux_set_sel(struct mux_clk *mux, int sel) ++{ ++ unsigned long flags; ++ u32 regval; ++ ++ spin_lock_irqsave(&kpss_clock_reg_lock, flags); ++ regval = krait_get_l2_indirect_reg(mux->offset); ++ regval &= ~(mux->mask << mux->shift); ++ regval |= (sel & mux->mask) << mux->shift; ++ if (mux->priv) { ++ regval &= ~(mux->mask << (mux->shift + LPL_SHIFT)); ++ regval |= (sel & mux->mask) << (mux->shift + LPL_SHIFT); ++ } ++ krait_set_l2_indirect_reg(mux->offset, regval); ++ spin_unlock_irqrestore(&kpss_clock_reg_lock, flags); ++ ++ /* Wait for switch to complete. */ ++ mb(); ++ udelay(1); ++} ++ ++static int kpss_mux_set_sel(struct mux_clk *mux, int sel) ++{ ++ mux->en_mask = sel; ++ /* Don't touch mux if CPU is off as it won't work */ ++ if (__clk_is_enabled(mux->hw.clk)) ++ __kpss_mux_set_sel(mux, sel); ++ return 0; ++} ++ ++static int kpss_mux_get_sel(struct mux_clk *mux) ++{ ++ u32 sel; ++ ++ sel = krait_get_l2_indirect_reg(mux->offset); ++ sel >>= mux->shift; ++ sel &= mux->mask; ++ mux->en_mask = sel; ++ ++ return sel; ++} ++ ++static int kpss_mux_enable(struct mux_clk *mux) ++{ ++ __kpss_mux_set_sel(mux, mux->en_mask); ++ return 0; ++} ++ ++static void kpss_mux_disable(struct mux_clk *mux) ++{ ++ __kpss_mux_set_sel(mux, mux->safe_sel); ++} ++ ++const struct clk_mux_ops clk_mux_ops_kpss = { ++ .enable = kpss_mux_enable, ++ .disable = kpss_mux_disable, ++ .set_mux_sel = kpss_mux_set_sel, ++ .get_mux_sel = kpss_mux_get_sel, ++}; ++EXPORT_SYMBOL_GPL(clk_mux_ops_kpss); ++ ++/* ++ * The divider can divide by 2, 4, 6 and 8. But we only really need div-2. So ++ * force it to div-2 during handoff and treat it like a fixed div-2 clock. ++ */ ++static int kpss_div2_get_div(struct div_clk *div) ++{ ++ unsigned long flags; ++ u32 regval; ++ int val; ++ ++ spin_lock_irqsave(&kpss_clock_reg_lock, flags); ++ regval = krait_get_l2_indirect_reg(div->offset); ++ val = (regval >> div->shift) & div->mask; ++ regval &= ~(div->mask << div->shift); ++ if (div->priv) ++ regval &= ~(div->mask << (div->shift + LPL_SHIFT)); ++ krait_set_l2_indirect_reg(div->offset, regval); ++ spin_unlock_irqrestore(&kpss_clock_reg_lock, flags); ++ ++ val = (val + 1) * 2; ++ WARN(val != 2, "Divider %s was configured to div-%d instead of 2!\n", ++ __clk_get_name(div->hw.clk), val); ++ ++ return 2; ++} ++ ++const struct clk_div_ops clk_div_ops_kpss_div2 = { ++ .get_div = kpss_div2_get_div, ++}; ++EXPORT_SYMBOL_GPL(clk_div_ops_kpss_div2); +diff --git a/drivers/clk/qcom/clk-krait.h b/drivers/clk/qcom/clk-krait.h +new file mode 100644 +index 0000000..9c3eb38 +--- /dev/null ++++ b/drivers/clk/qcom/clk-krait.h +@@ -0,0 +1,22 @@ ++/* ++ * Copyright (c) 2013, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __SOC_QCOM_CLOCK_KRAIT_H ++#define __SOC_QCOM_CLOCK_KRAIT_H ++ ++#include <linux/clk/msm-clk-generic.h> ++ ++extern const struct clk_mux_ops clk_mux_ops_kpss; ++extern const struct clk_div_ops clk_div_ops_kpss_div2; ++ ++#endif +-- +1.7.10.4 + |