diff options
author | Rabin Vincent <rabin.vincent@stericsson.com> | 2010-03-11 11:59:57 +0530 |
---|---|---|
committer | John Rigby <john.rigby@linaro.org> | 2010-09-02 22:44:38 -0600 |
commit | 795b7a2c7638ab660275f6c4b8e7c70e45a92048 (patch) | |
tree | a2f50cbde0d1b41712b05a513b2cee49c78369e1 /arch | |
parent | a444ceef7dc20ce466524c5dbec485cabb364ac8 (diff) | |
download | linux-2.6.34-ux500-795b7a2c7638ab660275f6c4b8e7c70e45a92048.tar.gz |
u8500-clock: pullback changes from mainline
Minor rework of the addresses/offsets being stored, kernel doc comments,
and macros instead of some magic values.
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Diffstat (limited to 'arch')
-rwxr-xr-x | arch/arm/mach-ux500/clock.c | 120 | ||||
-rwxr-xr-x | arch/arm/mach-ux500/clock.h | 79 | ||||
-rw-r--r-- | arch/arm/mach-ux500/cpu-db8500.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/db8500-regs.h | 2 | ||||
-rwxr-xr-x | arch/arm/mach-ux500/include/mach/prcmu-regs.h | 41 |
5 files changed, 160 insertions, 84 deletions
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index ec865f52e4a..ee6eb5f2719 100755 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -1,7 +1,6 @@ /* - * linux/arch/arm/mach-u8500/clock.c - * - * Copyright (C) ST Ericsson + * Copyright (C) 2009 ST-Ericsson + * Copyright (C) 2009 STMicroelectronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,15 +12,61 @@ #include <linux/errno.h> #include <linux/err.h> #include <linux/clk.h> +#include <linux/io.h> #include <linux/mutex.h> #include <asm/clkdev.h> -#include <asm/io.h> #include <mach/hardware.h> -#include <mach/prcmu-regs.h> #include "clock.h" +#define PRCC_PCKEN 0x00 +#define PRCC_PCKDIS 0x04 +#define PRCC_KCKEN 0x08 +#define PRCC_KCKDIS 0x0C + +#define PRCM_YYCLKEN0_MGT_SET 0x510 +#define PRCM_YYCLKEN1_MGT_SET 0x514 +#define PRCM_YYCLKEN0_MGT_CLR 0x518 +#define PRCM_YYCLKEN1_MGT_CLR 0x51C +#define PRCM_YYCLKEN0_MGT_VAL 0x520 +#define PRCM_YYCLKEN1_MGT_VAL 0x524 + +#define PRCM_SVAMMDSPCLK_MGT 0x008 +#define PRCM_SIAMMDSPCLK_MGT 0x00C +#define PRCM_SGACLK_MGT 0x014 +#define PRCM_UARTCLK_MGT 0x018 +#define PRCM_MSP02CLK_MGT 0x01C +#define PRCM_MSP1CLK_MGT 0x288 +#define PRCM_I2CCLK_MGT 0x020 +#define PRCM_SDMMCCLK_MGT 0x024 +#define PRCM_SLIMCLK_MGT 0x028 +#define PRCM_PER1CLK_MGT 0x02C +#define PRCM_PER2CLK_MGT 0x030 +#define PRCM_PER3CLK_MGT 0x034 +#define PRCM_PER5CLK_MGT 0x038 +#define PRCM_PER6CLK_MGT 0x03C +#define PRCM_PER7CLK_MGT 0x040 +#define PRCM_LCDCLK_MGT 0x044 +#define PRCM_BMLCLK_MGT 0x04C +#define PRCM_HSITXCLK_MGT 0x050 +#define PRCM_HSIRXCLK_MGT 0x054 +#define PRCM_HDMICLK_MGT 0x058 +#define PRCM_APEATCLK_MGT 0x05C +#define PRCM_APETRACECLK_MGT 0x060 +#define PRCM_MCDECLK_MGT 0x064 +#define PRCM_IPI2CCLK_MGT 0x068 +#define PRCM_DSIALTCLK_MGT 0x06C +#define PRCM_DMACLK_MGT 0x074 +#define PRCM_B2R2CLK_MGT 0x078 +#define PRCM_TVCLK_MGT 0x07C +#define PRCM_UNIPROCLK_MGT 0x278 +#define PRCM_SSPCLK_MGT 0x280 +#define PRCM_RNGCLK_MGT 0x284 +#define PRCM_UICCCLK_MGT 0x27C + +#define PRCM_MGT_ENABLE (1 << 8) + static DEFINE_SPINLOCK(clocks_lock); static void __clk_enable(struct clk *clk) @@ -42,9 +87,6 @@ int clk_enable(struct clk *clk) { unsigned long flags; - if (!clk || IS_ERR(clk)) - return -EINVAL; - spin_lock_irqsave(&clocks_lock, flags); __clk_enable(clk); spin_unlock_irqrestore(&clocks_lock, flags); @@ -71,9 +113,6 @@ void clk_disable(struct clk *clk) { unsigned long flags; - if (!clk || IS_ERR(clk)) - return; - WARN_ON(!clk->enabled); spin_lock_irqsave(&clocks_lock, flags); @@ -101,38 +140,51 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + /* TODO */ + return rate; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + clk->rate = rate; + return 0; +} +EXPORT_SYMBOL(clk_set_rate); + static void clk_prcmu_enable(struct clk *clk) { - void __iomem *cg_set_reg = (void __iomem *)PRCM_YYCLKEN0_MGT_SET - + clk->prcmu_cg_off; + void __iomem *cg_set_reg = __io_address(U8500_PRCMU_BASE) + + PRCM_YYCLKEN0_MGT_SET + clk->prcmu_cg_off; writel(1 << clk->prcmu_cg_bit, cg_set_reg); } static void clk_prcmu_disable(struct clk *clk) { - void __iomem *cg_clr_reg = (void __iomem *)PRCM_YYCLKEN0_MGT_CLR - + clk->prcmu_cg_off; + void __iomem *cg_clr_reg = __io_address(U8500_PRCMU_BASE) + + PRCM_YYCLKEN0_MGT_CLR + clk->prcmu_cg_off; writel(1 << clk->prcmu_cg_bit, cg_clr_reg); } /* ED doesn't have the combined set/clr registers */ - static void clk_prcmu_ed_enable(struct clk *clk) { - unsigned int val = readl(clk->prcmu_cg_mgt); + void __iomem *addr = __io_address(U8500_PRCMU_BASE) + + clk->prcmu_cg_mgt; - val |= 1 << 8; - writel(val, clk->prcmu_cg_mgt); + writel(readl(addr) | PRCM_MGT_ENABLE, addr); } static void clk_prcmu_ed_disable(struct clk *clk) { - unsigned int val = readl(clk->prcmu_cg_mgt); + void __iomem *addr = __io_address(U8500_PRCMU_BASE) + + clk->prcmu_cg_mgt; - val &= ~(1 << 8); - writel(val, clk->prcmu_cg_mgt); + writel(readl(addr) & ~PRCM_MGT_ENABLE, addr); } static struct clkops clk_prcmu_ops = { @@ -140,22 +192,35 @@ static struct clkops clk_prcmu_ops = { .disable = clk_prcmu_disable, }; +static unsigned int clkrst_base[] = { + [1] = U8500_CLKRST1_BASE, + [2] = U8500_CLKRST2_BASE, + [3] = U8500_CLKRST3_BASE, + [5] = U8500_CLKRST5_BASE, + [6] = U8500_CLKRST6_BASE, + [7] = U8500_CLKRST7_BASE_ED, +}; + static void clk_prcc_enable(struct clk *clk) { + void __iomem *addr = __io_address(clkrst_base[clk->cluster]); + if (clk->prcc_kernel != -1) - writel(1 << (clk->prcc_kernel), clk->prcc_base + 0x8); + writel(1 << clk->prcc_kernel, addr + PRCC_KCKEN); if (clk->prcc_bus != -1) - writel(1 << (clk->prcc_bus), clk->prcc_base + 0x0); + writel(1 << clk->prcc_bus, addr + PRCC_PCKEN); } static void clk_prcc_disable(struct clk *clk) { + void __iomem *addr = __io_address(clkrst_base[clk->cluster]); + if (clk->prcc_bus != -1) - writel(1 << (clk->prcc_bus), clk->prcc_base + 0x4); + writel(1 << clk->prcc_bus, addr + PRCC_PCKDIS); if (clk->prcc_kernel != -1) - writel(1 << (clk->prcc_kernel), clk->prcc_base + 0xc); + writel(1 << clk->prcc_kernel, addr + PRCC_KCKDIS); } static struct clkops clk_prcc_ops = { @@ -572,7 +637,8 @@ int __init clk_init(void) clk_prcmu_ops.enable = clk_prcmu_ed_enable; clk_prcmu_ops.disable = clk_prcmu_ed_disable; } else if (cpu_is_u8500v1()) { - void __iomem *sdmmclkmgt = (void __iomem *) PRCM_SDMMCCLK_MGT; + void __iomem *sdmmclkmgt = __io_address(U8500_PRCMU_BASE) + + PRCM_SDMMCCLK_MGT; unsigned int val; /* Switch SDMMCCLK to 52Mhz instead of 104Mhz */ diff --git a/arch/arm/mach-ux500/clock.h b/arch/arm/mach-ux500/clock.h index bcf246dcfa4..fb8534c4972 100755 --- a/arch/arm/mach-ux500/clock.h +++ b/arch/arm/mach-ux500/clock.h @@ -1,11 +1,22 @@ /* - * Copyright (C) ST Ericsson + * Copyright (C) 2010 ST-Ericsson + * Copyright (C) 2009 STMicrolectronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +/** + * struct clkops - ux500 clock operations + * @enable: function to enable the clock + * @disable: function to disable the clock + * @get_rate: function to get the current clock rate + * + * This structure contains function pointers to functions that will be used to + * control the clock. All of these functions are optional. If get_rate is + * NULL, the rate in the struct clk will be used. + */ extern int __init clk_init(void); struct clkops { @@ -14,6 +25,46 @@ struct clkops { unsigned long (*get_rate) (struct clk *); }; +/** + * struct clk - ux500 clock structure + * @ops: pointer to clkops struct used to control this clock + * @name: name, for debugging + * @enabled: refcount. positive if enabled, zero if disabled + * @rate: fixed rate for clocks which don't implement + * ops->getrate + * @prcmu_cg_off: address offset of the combined enable/disable register + * (used on u8500v1) + * @prcmu_cg_bit: bit in the combined enable/disable register (used on + * u8500v1) + * @prcmu_cg_mgt: address of the enable/disable register (used on + * u8500ed) + * @cluster: peripheral cluster number + * @prcc_bus: bit for the bus clock in the peripheral's CLKRST + * @prcc_kernel: bit for the kernel clock in the peripheral's CLKRST. + * -1 if no kernel clock exists. + * @parent_cluster: pointer to parent's cluster clk struct + * @parent_periph: pointer to parent's peripheral clk struct + * + * Peripherals are organised into clusters, and each cluster has an associated + * bus clock. Some peripherals also have a parent peripheral clock. + * + * In order to enable a clock for a peripheral, we need to enable: + * (1) the parent cluster (bus) clock at the PRCMU level + * (2) the parent peripheral clock (if any) at the PRCMU level + * (3) the peripheral's bus & kernel clock at the PRCC level + * + * (1) and (2) are handled by defining clk structs (DEFINE_PRCMU_CLK) for each + * of the cluster and peripheral clocks, and hooking these as the parents of + * the individual peripheral clocks. + * + * (3) is handled by specifying the bits in the PRCC control registers required + * to enable these clocks and modifying them in the ->enable and + * ->disable callbacks of the peripheral clocks (DEFINE_PRCC_CLK). + * + * This structure describes both the PRCMU-level clocks and PRCC-level clocks. + * The prcmu_* fields are only used for the PRCMU clocks, and the cluster, + * prcc, and parent pointers are only used for the PRCC-level clocks. + */ struct clk { const struct clkops *ops; const char *name; @@ -26,11 +77,11 @@ struct clk { unsigned int prcmu_cg_off; unsigned int prcmu_cg_bit; - void __iomem *prcmu_cg_mgt; + unsigned int prcmu_cg_mgt; /* The rest are only for PRCC clks */ - void __iomem *prcc_base; + int cluster; unsigned int prcc_bus; unsigned int prcc_kernel; @@ -44,7 +95,7 @@ struct clk clk_##_name = { \ .ops = &clk_prcmu_ops, \ .prcmu_cg_off = _cg_off, \ .prcmu_cg_bit = _cg_bit, \ - .prcmu_cg_mgt = (void __iomem *)PRCM_##_reg##_MGT \ + .prcmu_cg_mgt = PRCM_##_reg##_MGT \ } #define DEFINE_PRCMU_CLK_RATE(_name, _cg_off, _cg_bit, _reg, _rate) \ @@ -54,18 +105,18 @@ struct clk clk_##_name = { \ .prcmu_cg_off = _cg_off, \ .prcmu_cg_bit = _cg_bit, \ .rate = _rate, \ - .prcmu_cg_mgt = (void __iomem *)PRCM_##_reg##_MGT \ + .prcmu_cg_mgt = PRCM_##_reg##_MGT \ } -#define DEFINE_PRCC_CLK(_pclust, _name, _bus_en, _kernel_en, _kernclk) \ -struct clk clk_##_name = { \ - .name = #_name, \ - .ops = &clk_prcc_ops, \ - .prcc_base = (void __iomem *)IO_ADDRESS(U8500_CLKRST##_pclust##_BASE), \ - .prcc_bus = _bus_en, \ - .prcc_kernel = _kernel_en, \ - .parent_cluster = &clk_per##_pclust##clk, \ - .parent_periph = _kernclk \ +#define DEFINE_PRCC_CLK(_pclust, _name, _bus_en, _kernel_en, _kernclk) \ +struct clk clk_##_name = { \ + .name = #_name, \ + .ops = &clk_prcc_ops, \ + .cluster = _pclust, \ + .prcc_bus = _bus_en, \ + .prcc_kernel = _kernel_en, \ + .parent_cluster = &clk_per##_pclust##clk, \ + .parent_periph = _kernclk \ } #define CLK(_clk, _devname, _conname) \ diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index fb7def59b22..236934529fe 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -31,7 +31,7 @@ static struct map_desc u8500_io_desc[] __initdata = { }; static struct map_desc u8500_ed_io_desc[] __initdata = { - __IO_DEV_DESC(U8500_CLKRST7_BASE, SZ_4K), + __IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_4K), __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), __IO_DEV_DESC(U8500_MTU1_BASE_ED, SZ_4K), }; diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h index e3d62b94ffc..f0dcaa0cee3 100644 --- a/arch/arm/mach-ux500/include/mach/db8500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h @@ -46,7 +46,7 @@ #define U8500_MTU0_BASE_ED (U8500_PER7_BASE_ED + 0xa000) #define U8500_MTU1_BASE_ED (U8500_PER7_BASE_ED + 0xb000) #define U8500_TZPC0_BASE_ED (U8500_PER7_BASE_ED + 0xc000) -#define U8500_CLKRST7_BASE (U8500_PER7_BASE_ED + 0xf000) +#define U8500_CLKRST7_BASE_ED (U8500_PER7_BASE_ED + 0xf000) #define U8500_UART0_BASE (U8500_PER1_BASE + 0x0000) #define U8500_UART1_BASE (U8500_PER1_BASE + 0x1000) diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h index 6f4c36cd7f5..c2c8d503553 100755 --- a/arch/arm/mach-ux500/include/mach/prcmu-regs.h +++ b/arch/arm/mach-ux500/include/mach/prcmu-regs.h @@ -66,45 +66,4 @@ /* System reset register */ #define PRCM_APE_SOFTRST (_PRCMU_BASE + 0x228) -/* Clock management */ -#define PRCM_YYCLKEN0_MGT_SET (_PRCMU_BASE + 0x510) -#define PRCM_YYCLKEN1_MGT_SET (_PRCMU_BASE + 0x514) -#define PRCM_YYCLKEN0_MGT_CLR (_PRCMU_BASE + 0x518) -#define PRCM_YYCLKEN1_MGT_CLR (_PRCMU_BASE + 0x51C) -#define PRCM_YYCLKEN0_MGT_VAL (_PRCMU_BASE + 0x520) -#define PRCM_YYCLKEN1_MGT_VAL (_PRCMU_BASE + 0x524) - -#define PRCM_SVAMMDSPCLK_MGT (_PRCMU_BASE + 0x008) -#define PRCM_SIAMMDSPCLK_MGT (_PRCMU_BASE + 0x00C) -#define PRCM_SGACLK_MGT (_PRCMU_BASE + 0x014) -#define PRCM_UARTCLK_MGT (_PRCMU_BASE + 0x018) -#define PRCM_MSP02CLK_MGT (_PRCMU_BASE + 0x01C) -#define PRCM_MSP1CLK_MGT (_PRCMU_BASE + 0x288) -#define PRCM_I2CCLK_MGT (_PRCMU_BASE + 0x020) -#define PRCM_SDMMCCLK_MGT (_PRCMU_BASE + 0x024) -#define PRCM_SLIMCLK_MGT (_PRCMU_BASE + 0x028) -#define PRCM_PER1CLK_MGT (_PRCMU_BASE + 0x02C) -#define PRCM_PER2CLK_MGT (_PRCMU_BASE + 0x030) -#define PRCM_PER3CLK_MGT (_PRCMU_BASE + 0x034) -#define PRCM_PER5CLK_MGT (_PRCMU_BASE + 0x038) -#define PRCM_PER6CLK_MGT (_PRCMU_BASE + 0x03C) -#define PRCM_PER7CLK_MGT (_PRCMU_BASE + 0x040) -#define PRCM_LCDCLK_MGT (_PRCMU_BASE + 0x044) -#define PRCM_BMLCLK_MGT (_PRCMU_BASE + 0x04C) -#define PRCM_HSITXCLK_MGT (_PRCMU_BASE + 0x050) -#define PRCM_HSIRXCLK_MGT (_PRCMU_BASE + 0x054) -#define PRCM_HDMICLK_MGT (_PRCMU_BASE + 0x058) -#define PRCM_APEATCLK_MGT (_PRCMU_BASE + 0x05C) -#define PRCM_APETRACECLK_MGT (_PRCMU_BASE + 0x060) -#define PRCM_MCDECLK_MGT (_PRCMU_BASE + 0x064) -#define PRCM_IPI2CCLK_MGT (_PRCMU_BASE + 0x068) -#define PRCM_DSIALTCLK_MGT (_PRCMU_BASE + 0x06C) -#define PRCM_DMACLK_MGT (_PRCMU_BASE + 0x074) -#define PRCM_B2R2CLK_MGT (_PRCMU_BASE + 0x078) -#define PRCM_TVCLK_MGT (_PRCMU_BASE + 0x07C) -#define PRCM_UNIPROCLK_MGT (_PRCMU_BASE + 0x278) -#define PRCM_SSPCLK_MGT (_PRCMU_BASE + 0x280) -#define PRCM_RNGCLK_MGT (_PRCMU_BASE + 0x284) -#define PRCM_UICCCLK_MGT (_PRCMU_BASE + 0x27C) - #endif /* __MACH_PRCMU__REGS_H */ |