SPEAr: Move to common clock framework
v2 cover SPEAr: Move to common clock framework
Hello,
SPEAr now supports common clock framework. This patchset contains changes related to this.
V1->V2:
- Removed first seven commits as they are directly picked by Mike into his next.
- Moved SPEAr clock support to drivers/clk/spear/ from arch/arm/
- Fixed error handling issues in spear clk drivers
- Rearranged patches to get git bisect working
This patchset is rebased over:
- clk: add a fixed factor clock - by Sascha Hauer
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-March/090680.html
- common clk framework misc fixes - by Mike Turquette
https://lkml.org/lkml/2012/4/11/780
- V4: pinctrl: Add SPEAr pinctrl support
http://www.spinics.net/lists/arm-kernel/msg169387.html
- V3: SPEAr DT support updates
http://comments.gmane.org/gmane.linux.drivers.devicetree/14197
Viresh Kumar (6):
SPEAr: clk: Add VCO-PLL Synthesizer clock
SPEAr: clk: Add Auxiliary Synthesizer clock
SPEAr: clk: Add Fractional Synthesizer clock
SPEAr: clk: Add General Purpose Timer Synthesizer clock
SPEAr: Call clk_prepare() before calling clk_enable
SPEAr: Switch to common clock framework
MAINTAINERS | 4 +- arch/arm/Kconfig | 1 + arch/arm/mach-spear3xx/Makefile | 2 +- arch/arm/mach-spear3xx/clock.c | 892 -------------------- arch/arm/mach-spear3xx/include/mach/generic.h | 4 +- arch/arm/mach-spear3xx/include/mach/misc_regs.h | 2 + arch/arm/mach-spear3xx/include/mach/spear.h | 13 + arch/arm/mach-spear3xx/spear300.c | 1 - arch/arm/mach-spear3xx/spear310.c | 1 - arch/arm/mach-spear3xx/spear320.c | 12 +- arch/arm/mach-spear3xx/spear3xx.c | 2 + arch/arm/mach-spear6xx/Makefile | 2 +- arch/arm/mach-spear6xx/clock.c | 789 ------------------ arch/arm/mach-spear6xx/include/mach/misc_regs.h | 2 + arch/arm/mach-spear6xx/spear6xx.c | 5 +- arch/arm/plat-spear/Makefile | 2 +- arch/arm/plat-spear/clock.c | 1005 ----------------------- arch/arm/plat-spear/include/plat/clock.h | 249 ------ arch/arm/plat-spear/time.c | 8 +- drivers/clk/Makefile | 3 + drivers/clk/spear/Makefile | 8 + drivers/clk/spear/clk-aux-synth.c | 187 +++++ drivers/clk/spear/clk-frac-synth.c | 156 ++++ drivers/clk/spear/clk-gpt-synth.c | 145 ++++ drivers/clk/spear/clk-vco-pll.c | 346 ++++++++ drivers/clk/spear/clk.h | 152 ++++ drivers/clk/spear/spear3xx_clock.c | 612 ++++++++++++++ drivers/clk/spear/spear6xx_clock.c | 342 ++++++++ 28 files changed, 1992 insertions(+), 2955 deletions(-) delete mode 100644 arch/arm/mach-spear3xx/clock.c delete mode 100644 arch/arm/mach-spear6xx/clock.c delete mode 100644 arch/arm/plat-spear/clock.c delete mode 100644 arch/arm/plat-spear/include/plat/clock.h create mode 100644 drivers/clk/spear/Makefile create mode 100644 drivers/clk/spear/clk-aux-synth.c create mode 100644 drivers/clk/spear/clk-frac-synth.c create mode 100644 drivers/clk/spear/clk-gpt-synth.c create mode 100644 drivers/clk/spear/clk-vco-pll.c create mode 100644 drivers/clk/spear/clk.h create mode 100644 drivers/clk/spear/spear3xx_clock.c create mode 100644 drivers/clk/spear/spear6xx_clock.c
Signature · 1 line
1.7.9
PATCH v2 1/6 SPEAr: clk: Add VCO-PLL Synthesizer clock
All SPEAr SoC's contain PLLs. Their Fout is derived based on following equations
- In normal mode
vco = (2 * M[15:8] * Fin)/N
- In Dithered mode
vco = (2 * M[15:0] * Fin)/(256 * N)
pll_rate = vco/2^p
vco and pll are very closely bound to each other,
"vco needs to program: mode, m & n" and "pll needs to program p", both share common enable/disable logic and registers.
This patch adds in support for this type of clock.
--- drivers/clk/Makefile | 3 + drivers/clk/spear/Makefile | 5 + drivers/clk/spear/clk-vco-pll.c | 346 +++++++++++++++++++++++++++++++++++++++ drivers/clk/spear/clk.h | 76 +++++++++ 4 files changed, 430 insertions(+), 0 deletions(-) create mode 100644 drivers/clk/spear/Makefile create mode 100644 drivers/clk/spear/clk-vco-pll.c create mode 100644 drivers/clk/spear/clk.h
drivers/clk/Makefile +3 -0
@@ -2,3 +2,6 @@ obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ clk-mux.o clk-divider.o clk-fixed-factor.o + +# SoCs specific +obj-$(CONFIG_PLAT_SPEAR) += spear/
drivers/clk/spear/Makefile new file +5 -0
@@ -0,0 +1,5 @@ +# +# SPEAr Clock specific Makefile +# + +obj-y += clk-vco-pll.o
drivers/clk/spear/clk-vco-pll.c new file +346 -0
346 lines not on this page · raw message
drivers/clk/spear/clk.h new file +76 -0
76 lines not on this page · raw message
Signature · 1 line
1.7.9
PATCH v2 1/6 SPEAr: clk: Add VCO-PLL Synthesizer clock
Quoted 10 lines · Viresh Kumar
All SPEAr SoC's contain PLLs. Their Fout is derived based on following equations
- In normal mode
?vco = (2 * M[15:8] * Fin)/N- In Dithered mode
?vco = (2 * M[15:0] * Fin)/(256 * N)
pll_rate= vco/2^p
Quoted 7 lines
vco and pll are very closely bound to each other,
"vco needs to program: mode, m & n" and "pll needs to program p", both share common enable/disable logic and registers.This patch adds in support for this type of clock.
Signed-off-by Viresh Kumar <[email protected]>
Hi Viresh,
I took a quick glance through this code from the perspective of common clk conformance and it looks good.
Regards,
Mike
Quoted 469 lines
---
?drivers/clk/Makefile ? ? ? ? ? ?| ? ?3 + ?drivers/clk/spear/Makefile ? ? ?| ? ?5 + ?drivers/clk/spear/clk-vco-pll.c | ?346 +++++++++++++++++++++++++++++++++++++++ ?drivers/clk/spear/clk.h ? ? ? ? | ? 76 +++++++++?4 files changed, 430 insertions(+), 0 deletions(-) ?create mode 100644
drivers/clk/spear/Makefile?create mode 100644drivers/clk/spear/clk-vco-pll.c?create mode 100644drivers/clk/spear/clk.hdrivers/clk/Makefile +0
-0@@ -2,3 +2,6 @@?obj-$(CONFIG_CLKDEV_LOOKUP) ? ?+= clkdev.o ?obj-$(CONFIG_COMMON_CLK) ? ? ? += clk.o clk-fixed-rate.o clk-gate.o \
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clk-mux.o clk-divider.o clk-fixed-factor.odrivers/clk/Makefile +3
-0+ +# SoCs specific +obj-$(CONFIG_PLAT_SPEAR) ? ? ? += spear/drivers/clk/spear/Makefile new file +5
-0@@ -0,0 +1,5 @@ +# +# SPEAr Clock specific Makefile +# + +obj-y ?+= clk-vco-pll.odrivers/clk/spear/clk-vco-pll.c new file +346
-0@@ -0,0 +1,346 @@ +/* +* Copyright (C) 2012 ST Microelectronics +* Viresh Kumar <[email protected]> +* +* This file is licensed under the terms of the GNU General Public +* License version 2. This program is licensed "as is" without any +* warranty of any kind, whether express or implied. +* +* VCO-PLL clock implementation +*/ + +#define pr_fmt (fmt) "clk-vco-pll: " fmt + +#include <linux/clk-provider.h> +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/err.h> +#include "clk.h" + +/* +* DOC: VCO-PLL clock +* +* VCO and PLL rate are derived from following equations: +* +* In normal mode +* vco = (2 * M[15:8] * Fin)/N +* +* In Dithered mode +* vco = (2 * M[15:0] * Fin)/(256 * N) +* +* pll_rate = pll/2^p +* +* vco and pll are very closely bound to each other, "vco needs to program: +* mode, m & n" and "pll needs to program p", both share common enable/disable +* logic. +* +* clk_register_vco_pll() registers instances of both vco & pll. +* CLK_SET_RATE_PARENT flag is forced for pll, as it will always pass its +* set_rate to vco. A single rate table exists for both the clocks, which +* configures m, n and p. +*/ + +/* PLL_CTR register masks */ +#define PLL_MODE_NORMAL ? ? ? ? ? ? ? ?0 +#define PLL_MODE_FRACTION ? ? ?1 +#define PLL_MODE_DITH_DSM ? ? ?2 +#define PLL_MODE_DITH_SSM ? ? ?3 +#define PLL_MODE_MASK ? ? ? ? ?3 +#define PLL_MODE_SHIFT ? ? ? ? 3 +#define PLL_ENABLE ? ? ? ? ? ? 2 + +#define PLL_LOCK_SHIFT ? ? ? ? 0 +#define PLL_LOCK_MASK ? ? ? ? ?1 + +/* PLL FRQ register masks */ +#define PLL_NORM_FDBK_M_MASK ? 0xFF +#define PLL_NORM_FDBK_M_SHIFT ?24 +#define PLL_DITH_FDBK_M_MASK ? 0xFFFF +#define PLL_DITH_FDBK_M_SHIFT ?16 +#define PLL_DIV_P_MASK ? ? ? ? 0x7 +#define PLL_DIV_P_SHIFT ? ? ? ? ? ? ? ?8 +#define PLL_DIV_N_MASK ? ? ? ? 0xFF +#define PLL_DIV_N_SHIFT ? ? ? ? ? ? ? ?0 + +#define to_clk_vco (_hw) container_of(_hw, struct clk_vco, hw) +#define to_clk_pll (_hw) container_of(_hw, struct clk_pll, hw) + +/* Calculates pll clk rate for specific value of mode, m, n and p */ +static unsigned long pll_calc_rate (struct pll_rate_tbl *rtbl, + ? ? ? ? ? ? ? unsigned long prate, int index, unsigned long *pll_rate) +{ + ? ? ? unsigned long rate = prate; + ? ? ? unsigned int mode; + + ? ? ? mode = rtbl[index].mode ? 256 : 1; + ? ? ? rate = (((2 * rate / 10000) * rtbl[index].m) / (mode * rtbl[index].n)); + + ? ? ? if (pll_rate) + ? ? ? ? ? ? ? *pll_rate = (rate / (1 << rtbl[index].p)) * 10000; + + ? ? ? return rate * 10000; +} + +static long clk_pll_round_rate_index (struct clk_hw *hw,unsigned long drate, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long *prate, int *index) +{ + ? ? ? struct clk_pll *pll = to_clk_pll(hw); + ? ? ? unsigned long prev_rate, vco_prev_rate, rate = 0; + ? ? ? unsigned long vco_parent_rate = + ? ? ? ? ? ? ? __clk_get_rate(__clk_get_parent(__clk_get_parent(hw->clk))); + + ? ? ? if (!prate) { + ? ? ? ? ? ? ? pr_err("%s: prate is must for pll clk\n", __func__); + ? ? ? ? ? ? ? return -EINVAL; + ? ? ? } + + ? ? ? for (*index = 0; *index < pll->vco->rtbl_cnt; (*index)++) { + ? ? ? ? ? ? ? prev_rate = rate; + ? ? ? ? ? ? ? vco_prev_rate = *prate; + ? ? ? ? ? ? ? *prate = pll_calc_rate(pll->vco->rtbl, vco_parent_rate, *index, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &rate); + ? ? ? ? ? ? ? if (drate < rate) { + ? ? ? ? ? ? ? ? ? ? ? /* previous clock was best */ + ? ? ? ? ? ? ? ? ? ? ? if (*index) { + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rate = prev_rate; + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *prate = vco_prev_rate; + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (*index)--; + ? ? ? ? ? ? ? ? ? ? ? } + ? ? ? ? ? ? ? ? ? ? ? break; + ? ? ? ? ? ? ? } + ? ? ? } + + ? ? ? return rate; +} + +static long clk_pll_round_rate (struct clk_hw *hw,unsigned long drate, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long *prate) +{ + ? ? ? int unused; + + ? ? ? return clk_pll_round_rate_index(hw, drate, prate, &unused); +} + +static unsigned long clk_pll_recalc_rate (struct clk_hw *hw,unsigned long + ? ? ? ? ? ? ? parent_rate) +{ + ? ? ? struct clk_pll *pll = to_clk_pll(hw); + ? ? ? unsigned long flags = 0; + ? ? ? unsigned int p; + + ? ? ? if (pll->vco->lock) + ? ? ? ? ? ? ? spin_lock_irqsave(pll->vco->lock, flags); + + ? ? ? p = readl_relaxed(pll->vco->cfg_reg); + + ? ? ? if (pll->vco->lock) + ? ? ? ? ? ? ? spin_unlock_irqrestore(pll->vco->lock, flags); + + ? ? ? p = (p >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK; + + ? ? ? return parent_rate / (1 << p); +} + +static int clk_pll_set_rate (struct clk_hw *hw,unsigned long drate) +{ + ? ? ? struct clk_pll *pll = to_clk_pll(hw); + ? ? ? struct pll_rate_tbl *rtbl = pll->vco->rtbl; + ? ? ? unsigned long flags = 0, val; + ? ? ? int i; + + ? ? ? clk_pll_round_rate_index(hw, drate, NULL, &i); + + ? ? ? if (pll->vco->lock) + ? ? ? ? ? ? ? spin_lock_irqsave(pll->vco->lock, flags); + + ? ? ? val = readl_relaxed(pll->vco->cfg_reg); + ? ? ? val &= ~(PLL_DIV_P_MASK << PLL_DIV_P_SHIFT); + ? ? ? val |= (rtbl[i].p & PLL_DIV_P_MASK) << PLL_DIV_P_SHIFT; + ? ? ? writel_relaxed(val, pll->vco->cfg_reg); + + ? ? ? if (pll->vco->lock) + ? ? ? ? ? ? ? spin_unlock_irqrestore(pll->vco->lock, flags); + + ? ? ? return 0; +} + +static struct clk_ops clk_pll_ops = { + ? ? ? .recalc_rate = clk_pll_recalc_rate, + ? ? ? .round_rate = clk_pll_round_rate, + ? ? ? .set_rate = clk_pll_set_rate, +}; + +static inline unsigned long vco_calc_rate (struct clk_hw *hw, + ? ? ? ? ? ? ? unsigned long prate, int index) +{ + ? ? ? struct clk_vco *vco = to_clk_vco(hw); + + ? ? ? return pll_calc_rate(vco->rtbl, prate, index, NULL); +} + +static long clk_vco_round_rate (struct clk_hw *hw,unsigned long drate, + ? ? ? ? ? ? ? unsigned long *prate) +{ + ? ? ? struct clk_vco *vco = to_clk_vco(hw); + ? ? ? int unused; + + ? ? ? return clk_round_rate_index(hw, drate, vco_calc_rate, vco->rtbl_cnt, + ? ? ? ? ? ? ? ? ? ? ? &unused); +} + +static unsigned long clk_vco_recalc_rate (struct clk_hw *hw, + ? ? ? ? ? ? ? unsigned long parent_rate) +{ + ? ? ? struct clk_vco *vco = to_clk_vco(hw); + ? ? ? unsigned long flags = 0; + ? ? ? unsigned int num = 2, den = 0, val, mode = 0; + + ? ? ? if (vco->lock) + ? ? ? ? ? ? ? spin_lock_irqsave(vco->lock, flags); + + ? ? ? mode = (readl_relaxed(vco->mode_reg) >> PLL_MODE_SHIFT) & PLL_MODE_MASK; + + ? ? ? val = readl_relaxed(vco->cfg_reg); + + ? ? ? if (vco->lock) + ? ? ? ? ? ? ? spin_unlock_irqrestore(vco->lock, flags); + + ? ? ? den = (val >> PLL_DIV_N_SHIFT) & PLL_DIV_N_MASK; + + ? ? ? /* calculate numerator & denominator */ + ? ? ? if (!mode) { + ? ? ? ? ? ? ? /* Normal mode */ + ? ? ? ? ? ? ? num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK; + ? ? ? } else { + ? ? ? ? ? ? ? /* Dithered mode */ + ? ? ? ? ? ? ? num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK; + ? ? ? ? ? ? ? den *= 256; + ? ? ? } + + ? ? ? if (!den) { + ? ? ? ? ? ? ? WARN(1, "%s: denominator can't be zero\n", __func__); + ? ? ? ? ? ? ? return 0; + ? ? ? } + + ? ? ? return (((parent_rate / 10000) * num) / den) * 10000; +} + +/* Configures new clock rate of vco */ +static int clk_vco_set_rate (struct clk_hw *hw,unsigned long drate) +{ + ? ? ? struct clk_vco *vco = to_clk_vco(hw); + ? ? ? struct pll_rate_tbl *rtbl = vco->rtbl; + ? ? ? unsigned long flags = 0, val; + ? ? ? int i; + + ? ? ? clk_round_rate_index(hw, drate, vco_calc_rate, vco->rtbl_cnt, &i); + + ? ? ? if (vco->lock) + ? ? ? ? ? ? ? spin_lock_irqsave(vco->lock, flags); + + ? ? ? val = readl_relaxed(vco->mode_reg); + ? ? ? val &= ~(PLL_MODE_MASK << PLL_MODE_SHIFT); + ? ? ? val |= (rtbl[i].mode & PLL_MODE_MASK) << PLL_MODE_SHIFT; + ? ? ? writel_relaxed(val, vco->mode_reg); + + ? ? ? val = readl_relaxed(vco->cfg_reg); + ? ? ? val &= ~(PLL_DIV_N_MASK << PLL_DIV_N_SHIFT); + ? ? ? val |= (rtbl[i].n & PLL_DIV_N_MASK) << PLL_DIV_N_SHIFT; + + ? ? ? val &= ~(PLL_DITH_FDBK_M_MASK << PLL_DITH_FDBK_M_SHIFT); + ? ? ? if (rtbl[i].mode) + ? ? ? ? ? ? ? val |= (rtbl[i].m & PLL_DITH_FDBK_M_MASK) << + ? ? ? ? ? ? ? ? ? ? ? PLL_DITH_FDBK_M_SHIFT; + ? ? ? else + ? ? ? ? ? ? ? val |= (rtbl[i].m & PLL_NORM_FDBK_M_MASK) << + ? ? ? ? ? ? ? ? ? ? ? PLL_NORM_FDBK_M_SHIFT; + + ? ? ? writel_relaxed(val, vco->cfg_reg); + + ? ? ? if (vco->lock) + ? ? ? ? ? ? ? spin_unlock_irqrestore(vco->lock, flags); + + ? ? ? return 0; +} + +static struct clk_ops clk_vco_ops = { + ? ? ? .recalc_rate = clk_vco_recalc_rate, + ? ? ? .round_rate = clk_vco_round_rate, + ? ? ? .set_rate = clk_vco_set_rate, +}; + +struct clk *clk_register_vco_pll (const char *vco_name,const char *pll_name, + ? ? ? ? ? ? ? const char *vco_gate_name, const char *parent_name, + ? ? ? ? ? ? ? unsigned long flags, void __iomem *mode_reg, void __iomem + ? ? ? ? ? ? ? *cfg_reg, struct pll_rate_tbl *rtbl, u8 rtbl_cnt, + ? ? ? ? ? ? ? spinlock_t *lock, struct clk **pll_clk, + ? ? ? ? ? ? ? struct clk **vco_gate_clk) +{ + ? ? ? struct clk_vco *vco; + ? ? ? struct clk_pll *pll; + ? ? ? struct clk *vco_clk, *tpll_clk, *tvco_gate_clk; + ? ? ? const char **vco_parent_name; + + ? ? ? if (!vco_name || !pll_name || !parent_name || !mode_reg || !cfg_reg || + ? ? ? ? ? ? ? ? ? ? ? !rtbl || !rtbl_cnt) { + ? ? ? ? ? ? ? pr_err("Invalid arguments passed"); + ? ? ? ? ? ? ? return ERR_PTR(-EINVAL); + ? ? ? } + + ? ? ? vco = kzalloc(sizeof(*vco), GFP_KERNEL); + ? ? ? if (!vco) { + ? ? ? ? ? ? ? pr_err("could not allocate vco clk\n"); + ? ? ? ? ? ? ? return ERR_PTR(-ENOMEM); + ? ? ? } + + ? ? ? pll = kzalloc(sizeof(*pll), GFP_KERNEL); + ? ? ? if (!pll) { + ? ? ? ? ? ? ? pr_err("could not allocate pll clk\n"); + ? ? ? ? ? ? ? goto free_vco; + ? ? ? } + + ? ? ? /* struct clk_vco assignments */ + ? ? ? vco->mode_reg = mode_reg; + ? ? ? vco->cfg_reg = cfg_reg; + ? ? ? vco->rtbl = rtbl; + ? ? ? vco->rtbl_cnt = rtbl_cnt; + ? ? ? vco->lock = lock; + ? ? ? pll->vco = vco; + + ? ? ? if (vco_gate_name) { + ? ? ? ? ? ? ? tvco_gate_clk = clk_register_gate(NULL, vco_gate_name, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? parent_name, 0, mode_reg, PLL_ENABLE, 0, lock); + ? ? ? ? ? ? ? if (IS_ERR_OR_NULL(tvco_gate_clk)) + ? ? ? ? ? ? ? ? ? ? ? goto free_pll; + + ? ? ? ? ? ? ? if (vco_gate_clk) + ? ? ? ? ? ? ? ? ? ? ? *vco_gate_clk = tvco_gate_clk; + ? ? ? ? ? ? ? vco_parent_name = &vco_gate_name; + ? ? ? } else { + ? ? ? ? ? ? ? vco_parent_name = &parent_name; + ? ? ? } + + ? ? ? vco_clk = clk_register(NULL, vco_name, &clk_vco_ops, &vco->hw, + ? ? ? ? ? ? ? ? ? ? ? vco_parent_name, 1, flags); + ? ? ? if (IS_ERR_OR_NULL(vco_clk)) + ? ? ? ? ? ? ? goto free_pll; + + ? ? ? tpll_clk = clk_register(NULL, pll_name, &clk_pll_ops, &pll->hw, + ? ? ? ? ? ? ? ? ? ? ? &vco_name, 1, CLK_SET_RATE_PARENT); + ? ? ? if (IS_ERR_OR_NULL(tpll_clk)) + ? ? ? ? ? ? ? goto free_pll; + + ? ? ? if (pll_clk) + ? ? ? ? ? ? ? *pll_clk = tpll_clk; + + ? ? ? return vco_clk; + +free_pll: + ? ? ? kfree(pll); +free_vco: + ? ? ? kfree(vco); + + ? ? ? pr_err("Failed to register vco pll clock\n"); + + ? ? ? return ERR_PTR(-ENOMEM); +}drivers/clk/spear/clk.h new file +76
-1@@ -0,0 +1,76 @@ +/* +* Clock framework definitions for SPEAr platform +* +* Copyright (C) 2012 ST Microelectronics +* Viresh Kumar <[email protected]> +* +* This file is licensed under the terms of the GNU General Public +* License version 2. This program is licensed "as is" without any +* warranty of any kind, whether express or implied. +*/ + +#ifndef __PLAT_CLOCK_H +#define __PLAT_CLOCK_H + +#include <linux/clk-provider.h> +#include <linux/spinlock_types.h> +#include <linux/types.h> + +/* VCO-PLL clk */ +struct pll_rate_tbl { + ? ? ? u8 mode; + ? ? ? u16 m; + ? ? ? u8 n; + ? ? ? u8 p; +}; + +struct clk_vco { + ? ? ? struct ? ? ? ? ? ? ? ? ?clk_hw hw; + ? ? ? void __iomem ? ? ? ? ? ?*mode_reg; + ? ? ? void __iomem ? ? ? ? ? ?*cfg_reg; + ? ? ? struct pll_rate_tbl ? ? *rtbl; + ? ? ? u8 ? ? ? ? ? ? ? ? ? ? ?rtbl_cnt; + ? ? ? spinlock_t ? ? ? ? ? ? ?*lock; +}; + +struct clk_pll { + ? ? ? struct ? ? ? ? ? ? ? ? ?clk_hw hw; + ? ? ? struct clk_vco ? ? ? ? ?*vco; + ? ? ? const char ? ? ? ? ? ? ?*parent[1]; + ? ? ? spinlock_t ? ? ? ? ? ? ?*lock; +}; + +typedef unsigned long (*clk_calc_rate )(struct clk_hw *hw,unsigned long prate, + ? ? ? ? ? ? ? int index); + +/* clk register routines */ +struct clk *clk_register_vco_pll (const char *vco_name,const char *pll_name, + ? ? ? ? ? ? ? const char *vco_gate_name, const char *parent_name, + ? ? ? ? ? ? ? unsigned long flags, void __iomem *mode_reg, void __iomem + ? ? ? ? ? ? ? *cfg_reg, struct pll_rate_tbl *rtbl, u8 rtbl_cnt, + ? ? ? ? ? ? ? spinlock_t *lock, struct clk **pll_clk, + ? ? ? ? ? ? ? struct clk **vco_gate_clk); + +static inline long clk_round_rate_index (struct clk_hw *hw,unsigned long drate, + ? ? ? ? ? ? ? clk_calc_rate calc_rate, u8 rtbl_cnt, int *index) +{ + ? ? ? unsigned long prev_rate, rate = 0; + ? ? ? unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk)); + + ? ? ? for (*index = 0; *index < rtbl_cnt; (*index)++) { + ? ? ? ? ? ? ? prev_rate = rate; + ? ? ? ? ? ? ? rate = calc_rate(hw, parent_rate, *index); + ? ? ? ? ? ? ? if (drate < rate) { + ? ? ? ? ? ? ? ? ? ? ? /* previous clock was best */ + ? ? ? ? ? ? ? ? ? ? ? if (*index) { + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rate = prev_rate; + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (*index)--; + ? ? ? ? ? ? ? ? ? ? ? } + ? ? ? ? ? ? ? ? ? ? ? break; + ? ? ? ? ? ? ? } + ? ? ? } + + ? ? ? return rate; +} + +#endif /* __PLAT_CLOCK_H */ --1.7.9
PATCH v2 1/6 SPEAr: clk: Add VCO-PLL Synthesizer clock
In reply to Viresh KumarHi Viresh,
Sent my first email too quickly. A couple of small questions below.
Quoted 9 lines · Viresh Kumar
drivers/clk/spear/clk.h new file +3
-0@@ -0,0 +1,76 @@ +/* +* Clock framework definitions for SPEAr platform +*
drivers/clk/spear/clk.h line 13
Quoted 10 lines
drivers/clk/spear/clk.h new file +10
-0+* Copyright (C) 2012 ST Microelectronics +* Viresh Kumar <[email protected]> +* +* This file is licensed under the terms of the GNU General Public +* License version 2. This program is licensed "as is" without any +* warranty of any kind, whether express or implied. +*/ + +#ifndef __PLAT_CLOCK_H +#define __PLAT_CLOCK_H
Any reason to use __PLAT_CLOCK_H from drivers/clk/ now? Is it copy/paste from your old platform code?
...
Quoted 11 lines
drivers/clk/spear/clk.h new file +11
-0+static inline long clk_round_rate_index (struct clk_hw *hw,unsigned long drate, + ? ? ? ? ? ? ? clk_calc_rate calc_rate, u8 rtbl_cnt, int *index) +{ + ? ? ? unsigned long prev_rate, rate = 0; + ? ? ? unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk)); + + ? ? ? for (*index = 0; *index < rtbl_cnt; (*index)++) { + ? ? ? ? ? ? ? prev_rate = rate; + ? ? ? ? ? ? ? rate = calc_rate(hw, parent_rate, *index); + ? ? ? ? ? ? ? if (drate < rate) { + ? ? ? ? ? ? ? ? ? ? ? /* previous clock was best */
drivers/clk/spear/clk.h line 34
Quoted 10 lines
drivers/clk/spear/clk.h new file +10
-0+ ? ? ? ? ? ? ? ? ? ? ? if (*index) { + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rate = prev_rate; + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (*index)--; + ? ? ? ? ? ? ? ? ? ? ? } + ? ? ? ? ? ? ? ? ? ? ? break; + ? ? ? ? ? ? ? } + ? ? ? } + + ? ? ? return rate; +}
Any reason for this code to exist in a header? I prefer code in C files. Also it is a bit large for an inline function.
Thanks,
Mike
PATCH v2 1/6 SPEAr: clk: Add VCO-PLL Synthesizer clock
Quoted 15 lines · Mike
Quoted 14 lines · Viresh Kumar
drivers/clk/spear/clk.h new file +8
-0@@ -0,0 +1,76 @@ +/* +* Clock framework definitions for SPEAr platform +* +* Copyright (C) 2012 ST Microelectronics +* Viresh Kumar <[email protected]> +* +* This file is licensed under the terms of the GNU General Public +* License version 2. This program is licensed "as is" without any
Quoted 8 lines
drivers/clk/spear/clk.h line 13
Quoted 5 lines
drivers/clk/spear/clk.h new file +5
-0+* warranty of any kind, whether express or implied. +*/ + +#ifndef __PLAT_CLOCK_H +#define __PLAT_CLOCK_HAny reason to use
__PLAT_CLOCK_Hfromdrivers/clk/now? Is it copy/paste from your old platform code?
Ya. Will fix it to __SPEAR_CLK_H
Quoted 16 lines
Quoted 16 lines
drivers/clk/spear/clk.h new file +16
-0+static inline long clk_round_rate_index (struct clk_hw *hw,unsigned long drate, +clk_calc_rate calc_rate,u8 rtbl_cnt,int *index) +{ +unsigned long prev_rate, rate =0 ; +unsigned long parent_rate =__clk_get_rate (__clk_get_parent (hw->clk)); + +for (*index =0 ; *index < rtbl_cnt; (*index)++) { + prev_rate = rate; + rate =calc_rate (hw, parent_rate, *index); +if (drate < rate) { +/* previous clock was best */ +if (*index) { + rate = prev_rate; + (*index)--; + } +break ;
Quoted 8 lines
drivers/clk/spear/clk.h line 34
Quoted 5 lines
drivers/clk/spear/clk.h new file +5
-0+ } + } + +return rate; +}Any reason for this code to exist in a header? I prefer code in C files. Also it is a bit large for an inline function.
There is no C file common to entire SPEAr clock framework, so kept it in header. Because this is called only from 2-3 places, inline would also be fine.
But if you insist, i can create clk.c in spear, where i can keep it.
Signature · 1 line
viresh
PATCH v2 2/6 SPEAr: clk: Add Auxiliary Synthesizer clock
In reply to Viresh KumarAll SPEAr SoC's contain Auxiliary Synthesizers. Their Fout is derived based on values of eq, x and y.
Fout from synthesizer can be given from two equations:
Fout1 = (Fin * X/Y)/2 EQ1
Fout2 = Fin * X/Y EQ2
This patch adds in support for this type of clock.
--- drivers/clk/spear/Makefile | 2 +- drivers/clk/spear/clk-aux-synth.c | 187 +++++++++++++++++++++++++++++++++++++ drivers/clk/spear/clk.h | 43 +++++++++ 3 files changed, 231 insertions(+), 1 deletions(-) create mode 100644 drivers/clk/spear/clk-aux-synth.c
drivers/clk/spear/Makefile +1 -1
@@ -2,4 +2,4 @@ # SPEAr Clock specific Makefile # -obj-y += clk-vco-pll.o +obj-y += clk-aux-synth.o clk-vco-pll.o
drivers/clk/spear/clk-aux-synth.c new file +187 -0
187 lines not on this page · raw message
drivers/clk/spear/clk.h +43 -0
55 lines not on this page · raw message
Signature · 1 line
1.7.9
PATCH v2 2/6 SPEAr: clk: Add Auxiliary Synthesizer clock
Quoted 8 lines · Viresh Kumar
All SPEAr SoC's contain Auxiliary Synthesizers. Their Fout is derived based on
values of eq, x and y.Fout from synthesizer can be given from two equations:
Fout1 = (Fin * X/Y)/2 EQ1
Fout2 = Fin * X/Y EQ2
Quoted 6 lines
This patch adds in support for this type of clock.
Signed-off-by Viresh Kumar <[email protected]>--- drivers/clk/spear/Makefile | 2 +- drivers/clk/spear/clk-aux-synth.c | 187
Hi Mike,
What are your plans for this patchset? Can you push this in v3.5? SPEAr dependency patches are already pushed by Arnd and are present in linux-next now.
Please squash following fixup with this patch while applying:
From: Viresh Kumar <[email protected]>
Date: Fri, 20 Apr 2012 17:08:40 +0530
Subject: [PATCH] fixup! SPEAr: clk: Add Auxiliary Synthesizer clock
Set aux->masks to masks if it is valid.
--- drivers/clk/spear/clk-aux-synth.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
(quoted diff) +0 -0
b/drivers/clk/spear/clk-aux-synth.c
index 1a7ab7d..e01a350 100644
drivers/clk/spear/clk-aux-synth.c +0 -0
@@ -154,6 +154,8 @@ struct clk *clk_register_aux(const char *aux_name,
const char *gate_name,
/* struct clk_aux assignments */
if (!masks)
aux->masks = &default_aux_masks;
+ else
+ aux->masks = masks;
aux->reg = reg;
aux->rtbl = rtbl;
--
Viresh
PATCH v2 3/6 SPEAr: clk: Add Fractional Synthesizer clock
In reply to Viresh KumarAll SPEAr SoC's contain Fractional Synthesizers. Their Fout is derived from following equations:
Fout = Fin / (2 * div) (division factor)
div is 17 bits:-
0-13 (fractional part)
14-16 (integer part)
div is (16-14 bits).(13-0 bits) (in binary)
Fout = Fin/(2 * div)
Fout = ((Fin / 10000)/(2 * div)) * 10000
Fout = (2^14 * (Fin / 10000)/(2^14 * (2 * div))) * 10000
Fout = (((Fin / 10000) << 14)/(2 * (div << 14))) * 10000div << 14 is simply 17 bit value written at register.
This patch adds in support for this type of clock.
--- drivers/clk/spear/Makefile | 2 +- drivers/clk/spear/clk-frac-synth.c | 156 ++++++++++++++++++++++++++++++++++++ drivers/clk/spear/clk.h | 16 ++++ 3 files changed, 173 insertions(+), 1 deletions(-) create mode 100644 drivers/clk/spear/clk-frac-synth.c
drivers/clk/spear/Makefile +1 -1
@@ -2,4 +2,4 @@ # SPEAr Clock specific Makefile # -obj-y += clk-aux-synth.o clk-vco-pll.o +obj-y += clk-aux-synth.o clk-frac-synth.o clk-vco-pll.o
drivers/clk/spear/clk-frac-synth.c new file +156 -0
156 lines not on this page · raw message
drivers/clk/spear/clk.h +16 -0
@@ -55,6 +55,19 @@ struct clk_aux {spinlock_t *lock; }; +/* Fractional Synth clk */ +struct frac_rate_tbl { +u32 div; +}; + +struct clk_frac { +struct clk_hw hw; +void __iomem *reg; +struct frac_rate_tbl *rtbl; +u8 rtbl_cnt; +spinlock_t *lock; +}; +/* VCO-PLL clk */ struct pll_rate_tbl {u8 mode;
@@ -87,6 +100,9 @@ struct clk *clk_register_aux(const char *aux_name, const char *gate_name, const char *parent_name, unsigned long flags, void __iomem *reg, struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl, u8 rtbl_cnt, spinlock_t *lock, struct clk **gate_clk); +struct clk *clk_register_frac (const char *name,const char *parent_name, +unsigned long flags,void __iomem *reg, +struct frac_rate_tbl *rtbl,u8 rtbl_cnt,spinlock_t *lock);struct clk *clk_register_vco_pll (const char *vco_name,const char *pll_name,const char *vco_gate_name,const char *parent_name, unsigned long flags, void __iomem *mode_reg, void __iomem
Signature · 1 line
1.7.9
PATCH v2 4/6 SPEAr: clk: Add General Purpose Timer Synthesizer clock
In reply to Viresh KumarAll SPEAr SoC's contain GPT Synthesizers. Their Fout is derived from following equations:
Fout= Fin/((2 ^ (N+1)) * (M+1))
This patch adds in support for this type of clock.
--- drivers/clk/spear/Makefile | 2 +- drivers/clk/spear/clk-gpt-synth.c | 145 +++++++++++++++++++++++++++++++++++++ drivers/clk/spear/clk.h | 17 +++++ 3 files changed, 163 insertions(+), 1 deletions(-) create mode 100644 drivers/clk/spear/clk-gpt-synth.c
drivers/clk/spear/Makefile +1 -1
@@ -2,4 +2,4 @@ # SPEAr Clock specific Makefile # -obj-y += clk-aux-synth.o clk-frac-synth.o clk-vco-pll.o +obj-y += clk-aux-synth.o clk-frac-synth.o clk-gpt-synth.o clk-vco-pll.o
drivers/clk/spear/clk-gpt-synth.c new file +145 -0
145 lines not on this page · raw message
drivers/clk/spear/clk.h +17 -0
@@ -68,6 +68,20 @@ struct clk_frac {spinlock_t *lock; }; +/* GPT clk */ +struct gpt_rate_tbl { +u16 mscale; +u16 nscale; +}; + +struct clk_gpt { +struct clk_hw hw; +void __iomem *reg; +struct gpt_rate_tbl *rtbl; +u8 rtbl_cnt; +spinlock_t *lock; +}; +/* VCO-PLL clk */ struct pll_rate_tbl {u8 mode;
@@ -103,6 +117,9 @@ struct clk *clk_register_aux(const char *aux_name, const char *gate_name,struct clk *clk_register_frac (const char *name,const char *parent_name,unsigned long flags,void __iomem *reg,struct frac_rate_tbl *rtbl,u8 rtbl_cnt,spinlock_t *lock); +struct clk *clk_register_gpt (const char *name,const char *parent_name,unsigned +long flags,void __iomem *reg,struct gpt_rate_tbl *rtbl,u8 + rtbl_cnt,spinlock_t *lock);struct clk *clk_register_vco_pll (const char *vco_name,const char *pll_name,const char *vco_gate_name,const char *parent_name, unsigned long flags, void __iomem *mode_reg, void __iomem
Signature · 1 line
1.7.9
PATCH v2 5/6 SPEAr: Call clk_prepare() before calling clk_enable
In reply to Viresh KumarWith common clock framework, it is must to call clk_{un}prepare() before/after clk_{dis}enable. This patch fixes this for SPEAr timer.
--- arch/arm/plat-spear/time.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
arch/arm/plat-spear/time.c +4 -4
@@ -218,10 +218,10 @@ void __init spear_setup_timer(resource_size_t base, int irq) goto err_iomap; } - ret =clk_enable (gpt_clk); + ret =clk_prepare_enable (gpt_clk);if (ret <0 ) { -pr_err ("%s:couldn't enable gpt clock\n" , __func__); - goto err_clk; +pr_err ("%s:couldn't prepare-enable gpt clock\n" , __func__); + goto err_prepare_enable_clk; }spear_clockevent_init (irq);
@@ -229,7 +229,7 @@ void __init spear_setup_timer(resource_size_t base, int irq)return ; -err_clk: +err_prepare_enable_clk:clk_put (gpt_clk); err_iomap:iounmap (gpt_base);
Signature · 1 line
1.7.9
A message that is not in the archive (sent off-list or not yet received): ddade82f0666c3186b8a694aa2b79acd3f7e5d50.1334852395.git.viresh.kumar@st.com
PATCH v2 6/6 SPEAr: Switch to common clock framework
Quoted 7 lines · Viresh Kumar
SPEAr SoCs used its own clock framework since now. From now on they will move to use common clock framework.
This patch updates existing SPEAr machine support to adapt for common clock framework.
Signed-off-by Viresh Kumar <[email protected]>
Quoted 15 lines
--- MAINTAINERS | 4 +- arch/arm/Kconfig | 1 + arch/arm/mach-spear3xx/Makefile | 2 +- arch/arm/mach-spear3xx/clock.c | 892 -------------------- arch/arm/mach-spear3xx/include/mach/generic.h | 4 +- arch/arm/mach-spear3xx/include/mach/misc_regs.h | 2 + arch/arm/mach-spear3xx/include/mach/spear.h | 13 + arch/arm/mach-spear3xx/spear300.c | 1 - arch/arm/mach-spear3xx/spear310.c | 1 - arch/arm/mach-spear3xx/spear320.c | 12 +- arch/arm/mach-spear3xx/spear3xx.c | 2 + arch/arm/mach-spear6xx/Makefile | 2 +- arch/arm/mach-spear6xx/clock.c | 789 ------------------ arch/arm/mach-spear6xx/include/mach/misc_regs.h | 2 +
Quoted 8 lines
arch/arm/mach-spear6xx/spear6xx.c | 5 +- arch/arm/plat-spear/Makefile | 2 +- arch/arm/plat-spear/clock.c | 1005 ----------------------- arch/arm/plat-spear/include/plat/clock.h | 249 ------ drivers/clk/spear/Makefile | 3 + drivers/clk/spear/spear3xx_clock.c | 612 ++++++++++++++ drivers/clk/spear/spear6xx_clock.c | 342 ++++++++ 21 files changed, 994 insertions(+), 2951 deletions(-)
Great diffstat!
Arnd
PATCH v2 6/6 SPEAr: Switch to common clock framework
Quoted 4 lines · Arnd Bergmann
Quoted 3 lines · Viresh Kumar
Quoted 3 lines
SPEAr SoCs used its own clock framework since now. From now on they will move to use common clock framework.
Quoted 8 lines
Quoted 4 lines
Quoted 4 lines
This patch updates existing SPEAr machine support to adapt for common clock framework.
Signed-off-by Viresh Kumar <[email protected]>Acked-by Arnd Bergmann <[email protected]>Quoted 1 line
Quoted 1 line
21 files changed, 994 insertions(+), 2951 deletions(-)Great diffstat!
Thanks Arnd.
For this set to go through Mike's tree, we would require earlier pull request of 3xx DT and pinmux to be upstreamed. When are you planning to do that? After that i will ask Mike to apply these patches on latest linux-next. :)
Signature · 1 line
viresh
PATCH v2 6/6 SPEAr: Switch to common clock framework
Quoted 3 lines · Viresh Kumar
For this set to go through Mike's tree, we would require earlier pull request of 3xx DT and pinmux to be upstreamed. When are you planning to do that? After that i will ask Mike to apply these patches on latest linux-next. :)
I plan to do it as soon as possible, but I've been procrastinating this and let Olof take care of the merges in the last few weeks.
On the plus side, I've got the number of unread mails down from ~20000 to 640 (your pull request is among those), built a new kernel for my laptop, cleaned up my git trees and bought a new vaccuum cleaner. Now I'll just pay the taxes and I'll be right with you there.
Sorry for the delay.
Arnd
PATCH v2 6/6 SPEAr: Switch to common clock framework
Quoted 2 lines · Arnd Bergmann
I plan to do it as soon as possible, but I've been procrastinating this and let Olof take care of the merges in the last few weeks.
:)
Quoted 4 lines
On the plus side, I've got the number of unread mails down from ~20000 to 640 (your pull request is among those), built a new kernel for my laptop, cleaned up my git trees and bought a new vaccuum cleaner. Now I'll just pay the taxes and I'll be right with you there.
Don't worry. I will not let you sit free. I am preparing another set of patches for you to review. :)
Quoted 1 line
Sorry for the delay.
No Probs.
--
Viresh
PATCH v2 6/6 SPEAr: Switch to common clock framework
In reply to a message not in the archive[resending to lakml since message length was too long]
Quoted 7 lines · Viresh Kumar
SPEAr SoCs used its own clock framework since now. From now on they will move to use common clock framework.
This patch updates existing SPEAr machine support to adapt for common clock framework.
Signed-off-by Viresh Kumar <[email protected]>
Hi Viresh,
This series looks good to me, except for the two small comments I had in patch 1/6.
I also think that this code will not be affected by the changes to struct clk_hw which are expected from Saravana. Hopefully you have avoided a big rebase.
I'll take these into my clk-next branch unless Arnd has any objection based on arm-soc collisions.
Thanks,
Mike
A message that is not in the archive (sent off-list or not yet received): CAJOA=zOvyJ9pqEqnhmU1CqHy1uPUOyC=c7VtKjkjK91cbHkGHw@mail.gmail.com
PATCH v2 6/6 SPEAr: Switch to common clock framework
Quoted 6 lines · Mike
I also think that this code will not be affected by the changes to struct
clk_hwwhich are expected from Saravana. Hopefully you have avoided a big rebase.I'll take these into my clk-next branch unless Arnd has any objection based on arm-soc collisions.
That sounds good.
I will send V3, for it. That will contain two additional dependency patches:
- clk: add a fixed factor clock - by Sascha Hauer
- CLKDEV: Add helper routines to allocate and add clkdevs for given struct clk *
Signature · 1 line
viresh