aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches/0169-clk-qcom-Add-support-for-Krait-clocks.patch
diff options
context:
space:
mode:
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.patch203
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 0000000000..9b76f59508
--- /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
+