clock.c (bd072111e7319d90a7b8127f91c2806b9a6f279e) | clock.c (ef12379f205bed7e92434e12ddd44e62d13bebe1) |
---|---|
1/* 2 * arch/arm/mach-ep93xx/clock.c 3 * Clock control for Cirrus EP93xx chips. 4 * 5 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by --- 8 unchanged lines hidden (view full) --- 17#include <linux/string.h> 18#include <linux/io.h> 19 20#include <asm/clkdev.h> 21#include <asm/div64.h> 22#include <mach/hardware.h> 23 24 | 1/* 2 * arch/arm/mach-ep93xx/clock.c 3 * Clock control for Cirrus EP93xx chips. 4 * 5 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by --- 8 unchanged lines hidden (view full) --- 17#include <linux/string.h> 18#include <linux/io.h> 19 20#include <asm/clkdev.h> 21#include <asm/div64.h> 22#include <mach/hardware.h> 23 24 |
25/* 26 * The EP93xx has two external crystal oscillators. To generate the 27 * required high-frequency clocks, the processor uses two phase-locked- 28 * loops (PLLs) to multiply the incoming external clock signal to much 29 * higher frequencies that are then divided down by programmable dividers 30 * to produce the needed clocks. The PLLs operate independently of one 31 * another. 32 */ 33#define EP93XX_EXT_CLK_RATE 14745600 34#define EP93XX_EXT_RTC_RATE 32768 35 36 | |
37struct clk { 38 unsigned long rate; 39 int users; 40 int sw_locked; | 25struct clk { 26 unsigned long rate; 27 int users; 28 int sw_locked; |
41 u32 enable_reg; | 29 void __iomem *enable_reg; |
42 u32 enable_mask; 43 44 unsigned long (*get_rate)(struct clk *clk); | 30 u32 enable_mask; 31 32 unsigned long (*get_rate)(struct clk *clk); |
33 int (*set_rate)(struct clk *clk, unsigned long rate); |
|
45}; 46 47 48static unsigned long get_uart_rate(struct clk *clk); 49 | 34}; 35 36 37static unsigned long get_uart_rate(struct clk *clk); 38 |
39static int set_keytchclk_rate(struct clk *clk, unsigned long rate); |
|
50 | 40 |
41 |
|
51static struct clk clk_uart1 = { 52 .sw_locked = 1, | 42static struct clk clk_uart1 = { 43 .sw_locked = 1, |
53 .enable_reg = EP93XX_SYSCON_DEVICE_CONFIG, 54 .enable_mask = EP93XX_SYSCON_DEVICE_CONFIG_U1EN, | 44 .enable_reg = EP93XX_SYSCON_DEVCFG, 45 .enable_mask = EP93XX_SYSCON_DEVCFG_U1EN, |
55 .get_rate = get_uart_rate, 56}; 57static struct clk clk_uart2 = { 58 .sw_locked = 1, | 46 .get_rate = get_uart_rate, 47}; 48static struct clk clk_uart2 = { 49 .sw_locked = 1, |
59 .enable_reg = EP93XX_SYSCON_DEVICE_CONFIG, 60 .enable_mask = EP93XX_SYSCON_DEVICE_CONFIG_U2EN, | 50 .enable_reg = EP93XX_SYSCON_DEVCFG, 51 .enable_mask = EP93XX_SYSCON_DEVCFG_U2EN, |
61 .get_rate = get_uart_rate, 62}; 63static struct clk clk_uart3 = { 64 .sw_locked = 1, | 52 .get_rate = get_uart_rate, 53}; 54static struct clk clk_uart3 = { 55 .sw_locked = 1, |
65 .enable_reg = EP93XX_SYSCON_DEVICE_CONFIG, 66 .enable_mask = EP93XX_SYSCON_DEVICE_CONFIG_U3EN, | 56 .enable_reg = EP93XX_SYSCON_DEVCFG, 57 .enable_mask = EP93XX_SYSCON_DEVCFG_U3EN, |
67 .get_rate = get_uart_rate, 68}; 69static struct clk clk_pll1; 70static struct clk clk_f; 71static struct clk clk_h; 72static struct clk clk_p; 73static struct clk clk_pll2; 74static struct clk clk_usb_host = { 75 .enable_reg = EP93XX_SYSCON_PWRCNT, 76 .enable_mask = EP93XX_SYSCON_PWRCNT_USH_EN, 77}; | 58 .get_rate = get_uart_rate, 59}; 60static struct clk clk_pll1; 61static struct clk clk_f; 62static struct clk clk_h; 63static struct clk clk_p; 64static struct clk clk_pll2; 65static struct clk clk_usb_host = { 66 .enable_reg = EP93XX_SYSCON_PWRCNT, 67 .enable_mask = EP93XX_SYSCON_PWRCNT_USH_EN, 68}; |
69static struct clk clk_keypad = { 70 .sw_locked = 1, 71 .enable_reg = EP93XX_SYSCON_KEYTCHCLKDIV, 72 .enable_mask = EP93XX_SYSCON_KEYTCHCLKDIV_KEN, 73 .set_rate = set_keytchclk_rate, 74}; 75static struct clk clk_pwm = { 76 .rate = EP93XX_EXT_CLK_RATE, 77}; |
|
78 79/* DMA Clocks */ 80static struct clk clk_m2p0 = { 81 .enable_reg = EP93XX_SYSCON_PWRCNT, 82 .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P0, 83}; 84static struct clk clk_m2p1 = { 85 .enable_reg = EP93XX_SYSCON_PWRCNT, --- 39 unchanged lines hidden (view full) --- 125 .enable_reg = EP93XX_SYSCON_PWRCNT, 126 .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2M1, 127}; 128 129#define INIT_CK(dev,con,ck) \ 130 { .dev_id = dev, .con_id = con, .clk = ck } 131 132static struct clk_lookup clocks[] = { | 78 79/* DMA Clocks */ 80static struct clk clk_m2p0 = { 81 .enable_reg = EP93XX_SYSCON_PWRCNT, 82 .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P0, 83}; 84static struct clk clk_m2p1 = { 85 .enable_reg = EP93XX_SYSCON_PWRCNT, --- 39 unchanged lines hidden (view full) --- 125 .enable_reg = EP93XX_SYSCON_PWRCNT, 126 .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2M1, 127}; 128 129#define INIT_CK(dev,con,ck) \ 130 { .dev_id = dev, .con_id = con, .clk = ck } 131 132static struct clk_lookup clocks[] = { |
133 INIT_CK("apb:uart1", NULL, &clk_uart1), 134 INIT_CK("apb:uart2", NULL, &clk_uart2), 135 INIT_CK("apb:uart3", NULL, &clk_uart3), 136 INIT_CK(NULL, "pll1", &clk_pll1), 137 INIT_CK(NULL, "fclk", &clk_f), 138 INIT_CK(NULL, "hclk", &clk_h), 139 INIT_CK(NULL, "pclk", &clk_p), 140 INIT_CK(NULL, "pll2", &clk_pll2), 141 INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), 142 INIT_CK(NULL, "m2p0", &clk_m2p0), 143 INIT_CK(NULL, "m2p1", &clk_m2p1), 144 INIT_CK(NULL, "m2p2", &clk_m2p2), 145 INIT_CK(NULL, "m2p3", &clk_m2p3), 146 INIT_CK(NULL, "m2p4", &clk_m2p4), 147 INIT_CK(NULL, "m2p5", &clk_m2p5), 148 INIT_CK(NULL, "m2p6", &clk_m2p6), 149 INIT_CK(NULL, "m2p7", &clk_m2p7), 150 INIT_CK(NULL, "m2p8", &clk_m2p8), 151 INIT_CK(NULL, "m2p9", &clk_m2p9), 152 INIT_CK(NULL, "m2m0", &clk_m2m0), 153 INIT_CK(NULL, "m2m1", &clk_m2m1), | 133 INIT_CK("apb:uart1", NULL, &clk_uart1), 134 INIT_CK("apb:uart2", NULL, &clk_uart2), 135 INIT_CK("apb:uart3", NULL, &clk_uart3), 136 INIT_CK(NULL, "pll1", &clk_pll1), 137 INIT_CK(NULL, "fclk", &clk_f), 138 INIT_CK(NULL, "hclk", &clk_h), 139 INIT_CK(NULL, "pclk", &clk_p), 140 INIT_CK(NULL, "pll2", &clk_pll2), 141 INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), 142 INIT_CK("ep93xx-keypad", NULL, &clk_keypad), 143 INIT_CK(NULL, "pwm_clk", &clk_pwm), 144 INIT_CK(NULL, "m2p0", &clk_m2p0), 145 INIT_CK(NULL, "m2p1", &clk_m2p1), 146 INIT_CK(NULL, "m2p2", &clk_m2p2), 147 INIT_CK(NULL, "m2p3", &clk_m2p3), 148 INIT_CK(NULL, "m2p4", &clk_m2p4), 149 INIT_CK(NULL, "m2p5", &clk_m2p5), 150 INIT_CK(NULL, "m2p6", &clk_m2p6), 151 INIT_CK(NULL, "m2p7", &clk_m2p7), 152 INIT_CK(NULL, "m2p8", &clk_m2p8), 153 INIT_CK(NULL, "m2p9", &clk_m2p9), 154 INIT_CK(NULL, "m2m0", &clk_m2m0), 155 INIT_CK(NULL, "m2m1", &clk_m2m1), |
154}; 155 156 157int clk_enable(struct clk *clk) 158{ 159 if (!clk->users++ && clk->enable_reg) { 160 u32 value; 161 162 value = __raw_readl(clk->enable_reg); | 156}; 157 158 159int clk_enable(struct clk *clk) 160{ 161 if (!clk->users++ && clk->enable_reg) { 162 u32 value; 163 164 value = __raw_readl(clk->enable_reg); |
165 value |= clk->enable_mask; |
|
163 if (clk->sw_locked) | 166 if (clk->sw_locked) |
164 __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); 165 __raw_writel(value | clk->enable_mask, clk->enable_reg); | 167 ep93xx_syscon_swlocked_write(value, clk->enable_reg); 168 else 169 __raw_writel(value, clk->enable_reg); |
166 } 167 168 return 0; 169} 170EXPORT_SYMBOL(clk_enable); 171 172void clk_disable(struct clk *clk) 173{ 174 if (!--clk->users && clk->enable_reg) { 175 u32 value; 176 177 value = __raw_readl(clk->enable_reg); | 170 } 171 172 return 0; 173} 174EXPORT_SYMBOL(clk_enable); 175 176void clk_disable(struct clk *clk) 177{ 178 if (!--clk->users && clk->enable_reg) { 179 u32 value; 180 181 value = __raw_readl(clk->enable_reg); |
182 value &= ~clk->enable_mask; |
|
178 if (clk->sw_locked) | 183 if (clk->sw_locked) |
179 __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); 180 __raw_writel(value & ~clk->enable_mask, clk->enable_reg); | 184 ep93xx_syscon_swlocked_write(value, clk->enable_reg); 185 else 186 __raw_writel(value, clk->enable_reg); |
181 } 182} 183EXPORT_SYMBOL(clk_disable); 184 185static unsigned long get_uart_rate(struct clk *clk) 186{ 187 u32 value; 188 --- 8 unchanged lines hidden (view full) --- 197{ 198 if (clk->get_rate) 199 return clk->get_rate(clk); 200 201 return clk->rate; 202} 203EXPORT_SYMBOL(clk_get_rate); 204 | 187 } 188} 189EXPORT_SYMBOL(clk_disable); 190 191static unsigned long get_uart_rate(struct clk *clk) 192{ 193 u32 value; 194 --- 8 unchanged lines hidden (view full) --- 203{ 204 if (clk->get_rate) 205 return clk->get_rate(clk); 206 207 return clk->rate; 208} 209EXPORT_SYMBOL(clk_get_rate); 210 |
211static int set_keytchclk_rate(struct clk *clk, unsigned long rate) 212{ 213 u32 val; 214 u32 div_bit; |
|
205 | 215 |
216 val = __raw_readl(clk->enable_reg); 217 218 /* 219 * The Key Matrix and ADC clocks are configured using the same 220 * System Controller register. The clock used will be either 221 * 1/4 or 1/16 the external clock rate depending on the 222 * EP93XX_SYSCON_KEYTCHCLKDIV_KDIV/EP93XX_SYSCON_KEYTCHCLKDIV_ADIV 223 * bit being set or cleared. 224 */ 225 div_bit = clk->enable_mask >> 15; 226 227 if (rate == EP93XX_KEYTCHCLK_DIV4) 228 val |= div_bit; 229 else if (rate == EP93XX_KEYTCHCLK_DIV16) 230 val &= ~div_bit; 231 else 232 return -EINVAL; 233 234 ep93xx_syscon_swlocked_write(val, clk->enable_reg); 235 clk->rate = rate; 236 return 0; 237} 238 239int clk_set_rate(struct clk *clk, unsigned long rate) 240{ 241 if (clk->set_rate) 242 return clk->set_rate(clk, rate); 243 244 return -EINVAL; 245} 246EXPORT_SYMBOL(clk_set_rate); 247 248 |
|
206static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; 207static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; 208static char pclk_divisors[] = { 1, 2, 4, 8 }; 209 210/* 211 * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS 212 */ 213static unsigned long calc_pll_rate(u32 config_word) --- 67 unchanged lines hidden --- | 249static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; 250static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; 251static char pclk_divisors[] = { 1, 2, 4, 8 }; 252 253/* 254 * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS 255 */ 256static unsigned long calc_pll_rate(u32 config_word) --- 67 unchanged lines hidden --- |