]> nv-tegra.nvidia Code Review - linux-3.10.git/blob - arch/arm/mach-pxa/pxa3xx.c
[ARM] 4638/1: pxa: use PXA3xx specific macros to define clks
[linux-3.10.git] / arch / arm / mach-pxa / pxa3xx.c
1 /*
2  * linux/arch/arm/mach-pxa/pxa3xx.c
3  *
4  * code specific to pxa3xx aka Monahans
5  *
6  * Copyright (C) 2006 Marvell International Ltd.
7  *
8  * 2007-09-02: eric miao <eric.miao@marvell.com>
9  *             initial version
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  */
15
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/pm.h>
20 #include <linux/platform_device.h>
21 #include <linux/irq.h>
22
23 #include <asm/hardware.h>
24 #include <asm/arch/pxa3xx-regs.h>
25 #include <asm/arch/ohci.h>
26 #include <asm/arch/pm.h>
27 #include <asm/arch/dma.h>
28 #include <asm/arch/ssp.h>
29
30 #include "generic.h"
31 #include "devices.h"
32 #include "clock.h"
33
34 /* Crystal clock: 13MHz */
35 #define BASE_CLK        13000000
36
37 /* Ring Oscillator Clock: 60MHz */
38 #define RO_CLK          60000000
39
40 #define ACCR_D0CS       (1 << 26)
41
42 /* crystal frequency to static memory controller multiplier (SMCFS) */
43 static unsigned char smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
44
45 /* crystal frequency to HSIO bus frequency multiplier (HSS) */
46 static unsigned char hss_mult[4] = { 8, 12, 16, 0 };
47
48 /*
49  * Get the clock frequency as reflected by CCSR and the turbo flag.
50  * We assume these values have been applied via a fcs.
51  * If info is not 0 we also display the current settings.
52  */
53 unsigned int pxa3xx_get_clk_frequency_khz(int info)
54 {
55         unsigned long acsr, xclkcfg;
56         unsigned int t, xl, xn, hss, ro, XL, XN, CLK, HSS;
57
58         /* Read XCLKCFG register turbo bit */
59         __asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
60         t = xclkcfg & 0x1;
61
62         acsr = ACSR;
63
64         xl  = acsr & 0x1f;
65         xn  = (acsr >> 8) & 0x7;
66         hss = (acsr >> 14) & 0x3;
67
68         XL = xl * BASE_CLK;
69         XN = xn * XL;
70
71         ro = acsr & ACCR_D0CS;
72
73         CLK = (ro) ? RO_CLK : ((t) ? XN : XL);
74         HSS = (ro) ? RO_CLK : hss_mult[hss] * BASE_CLK;
75
76         if (info) {
77                 pr_info("RO Mode clock: %d.%02dMHz (%sactive)\n",
78                         RO_CLK / 1000000, (RO_CLK % 1000000) / 10000,
79                         (ro) ? "" : "in");
80                 pr_info("Run Mode clock: %d.%02dMHz (*%d)\n",
81                         XL / 1000000, (XL % 1000000) / 10000, xl);
82                 pr_info("Turbo Mode clock: %d.%02dMHz (*%d, %sactive)\n",
83                         XN / 1000000, (XN % 1000000) / 10000, xn,
84                         (t) ? "" : "in");
85                 pr_info("HSIO bus clock: %d.%02dMHz\n",
86                         HSS / 1000000, (HSS % 1000000) / 10000);
87         }
88
89         return CLK;
90 }
91
92 /*
93  * Return the current static memory controller clock frequency
94  * in units of 10kHz
95  */
96 unsigned int pxa3xx_get_memclk_frequency_10khz(void)
97 {
98         unsigned long acsr;
99         unsigned int smcfs, clk = 0;
100
101         acsr = ACSR;
102
103         smcfs = (acsr >> 23) & 0x7;
104         clk = (acsr & ACCR_D0CS) ? RO_CLK : smcfs_mult[smcfs] * BASE_CLK;
105
106         return (clk / 10000);
107 }
108
109 /*
110  * Return the current HSIO bus clock frequency
111  */
112 static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
113 {
114         unsigned long acsr;
115         unsigned int hss, hsio_clk;
116
117         acsr = ACSR;
118
119         hss = (acsr >> 14) & 0x3;
120         hsio_clk = (acsr & ACCR_D0CS) ? RO_CLK : hss_mult[hss] * BASE_CLK;
121
122         return hsio_clk;
123 }
124
125 static void clk_pxa3xx_cken_enable(struct clk *clk)
126 {
127         unsigned long mask = 1ul << (clk->cken & 0x1f);
128
129         local_irq_disable();
130
131         if (clk->cken < 32)
132                 CKENA |= mask;
133         else
134                 CKENB |= mask;
135
136         local_irq_enable();
137 }
138
139 static void clk_pxa3xx_cken_disable(struct clk *clk)
140 {
141         unsigned long mask = 1ul << (clk->cken & 0x1f);
142
143         local_irq_disable();
144
145         if (clk->cken < 32)
146                 CKENA &= ~mask;
147         else
148                 CKENB &= ~mask;
149
150         local_irq_enable();
151 }
152
153 static const struct clkops clk_pxa3xx_cken_ops = {
154         .enable         = clk_pxa3xx_cken_enable,
155         .disable        = clk_pxa3xx_cken_disable,
156 };
157
158 static const struct clkops clk_pxa3xx_hsio_ops = {
159         .enable         = clk_pxa3xx_cken_enable,
160         .disable        = clk_pxa3xx_cken_disable,
161         .getrate        = clk_pxa3xx_hsio_getrate,
162 };
163
164 #define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev)  \
165         {                                               \
166                 .name   = _name,                        \
167                 .dev    = _dev,                         \
168                 .ops    = &clk_pxa3xx_cken_ops,         \
169                 .rate   = _rate,                        \
170                 .cken   = CKEN_##_cken,                 \
171                 .delay  = _delay,                       \
172         }
173
174 #define PXA3xx_CK(_name, _cken, _ops, _dev)             \
175         {                                               \
176                 .name   = _name,                        \
177                 .dev    = _dev,                         \
178                 .ops    = _ops,                         \
179                 .cken   = CKEN_##_cken,                 \
180         }
181
182 static struct clk pxa3xx_clks[] = {
183         PXA3xx_CK("LCDCLK", LCD,    &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
184         PXA3xx_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL),
185
186         PXA3xx_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
187         PXA3xx_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
188         PXA3xx_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
189
190         PXA3xx_CKEN("I2CCLK", I2C,  32842000, 0, &pxa_device_i2c.dev),
191         PXA3xx_CKEN("UDCCLK", UDC,  48000000, 5, &pxa_device_udc.dev),
192 };
193
194 void __init pxa3xx_init_irq(void)
195 {
196         /* enable CP6 access */
197         u32 value;
198         __asm__ __volatile__("mrc p15, 0, %0, c15, c1, 0\n": "=r"(value));
199         value |= (1 << 6);
200         __asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value));
201
202         pxa_init_irq_low();
203         pxa_init_irq_high();
204         pxa_init_irq_gpio(128);
205 }
206
207 /*
208  * device registration specific to PXA3xx.
209  */
210
211 static struct platform_device *devices[] __initdata = {
212         &pxa_device_mci,
213         &pxa_device_udc,
214         &pxa_device_fb,
215         &pxa_device_ffuart,
216         &pxa_device_btuart,
217         &pxa_device_stuart,
218         &pxa_device_i2c,
219         &pxa_device_i2s,
220         &pxa_device_ficp,
221         &pxa_device_rtc,
222 };
223
224 static int __init pxa3xx_init(void)
225 {
226         int ret = 0;
227
228         if (cpu_is_pxa3xx()) {
229                 clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
230
231                 if ((ret = pxa_init_dma(32)))
232                         return ret;
233
234                 return platform_add_devices(devices, ARRAY_SIZE(devices));
235         }
236         return 0;
237 }
238
239 subsys_initcall(pxa3xx_init);