aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Victor <andrew@sanpeople.com>2006-09-27 05:50:59 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-09-28 06:52:06 -0400
commit2eeaaa21de68cb8869d3a54438a9224321d3dd03 (patch)
tree3d81cac00241b7a4239497d60bc409210ba42429
parent72729910c38ca5b4736032c15dc3f9d48fe4f68a (diff)
[ARM] 3866/1: AT91 clock update
This patch makes the AT91 clock.c support processor-generic (AT91RM9200 and AT91SAM9xxx). The clocks supported by a particular AT91 processor are defined in the processor-specific file and are registered with clock.c at startup. Signed-off-by: Andrew Victor <andrew@sanpeople.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mach-at91rm9200/at91rm9200.c154
-rw-r--r--arch/arm/mach-at91rm9200/board-1arm.c7
-rw-r--r--arch/arm/mach-at91rm9200/board-carmeva.c7
-rw-r--r--arch/arm/mach-at91rm9200/board-csb337.c7
-rw-r--r--arch/arm/mach-at91rm9200/board-csb637.c7
-rw-r--r--arch/arm/mach-at91rm9200/board-dk.c7
-rw-r--r--arch/arm/mach-at91rm9200/board-eb9200.c7
-rw-r--r--arch/arm/mach-at91rm9200/board-ek.c7
-rw-r--r--arch/arm/mach-at91rm9200/board-kafa.c7
-rw-r--r--arch/arm/mach-at91rm9200/board-kb9202.c7
-rw-r--r--arch/arm/mach-at91rm9200/clock.c324
-rw-r--r--arch/arm/mach-at91rm9200/clock.h30
-rw-r--r--arch/arm/mach-at91rm9200/generic.h6
13 files changed, 299 insertions, 278 deletions
diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91rm9200/at91rm9200.c
index e21cb845d112..ae04cbdf0bff 100644
--- a/arch/arm/mach-at91rm9200/at91rm9200.c
+++ b/arch/arm/mach-at91rm9200/at91rm9200.c
@@ -17,6 +17,7 @@
17 17
18#include <asm/hardware.h> 18#include <asm/hardware.h>
19#include "generic.h" 19#include "generic.h"
20#include "clock.h"
20 21
21static struct map_desc at91rm9200_io_desc[] __initdata = { 22static struct map_desc at91rm9200_io_desc[] __initdata = {
22 { 23 {
@@ -102,9 +103,160 @@ static struct map_desc at91rm9200_io_desc[] __initdata = {
102 }, 103 },
103}; 104};
104 105
105void __init at91rm9200_map_io(void) 106/* --------------------------------------------------------------------
107 * Clocks
108 * -------------------------------------------------------------------- */
109
110/*
111 * The peripheral clocks.
112 */
113static struct clk udc_clk = {
114 .name = "udc_clk",
115 .pmc_mask = 1 << AT91RM9200_ID_UDP,
116 .type = CLK_TYPE_PERIPHERAL,
117};
118static struct clk ohci_clk = {
119 .name = "ohci_clk",
120 .pmc_mask = 1 << AT91RM9200_ID_UHP,
121 .type = CLK_TYPE_PERIPHERAL,
122};
123static struct clk ether_clk = {
124 .name = "ether_clk",
125 .pmc_mask = 1 << AT91RM9200_ID_EMAC,
126 .type = CLK_TYPE_PERIPHERAL,
127};
128static struct clk mmc_clk = {
129 .name = "mci_clk",
130 .pmc_mask = 1 << AT91RM9200_ID_MCI,
131 .type = CLK_TYPE_PERIPHERAL,
132};
133static struct clk twi_clk = {
134 .name = "twi_clk",
135 .pmc_mask = 1 << AT91RM9200_ID_TWI,
136 .type = CLK_TYPE_PERIPHERAL,
137};
138static struct clk usart0_clk = {
139 .name = "usart0_clk",
140 .pmc_mask = 1 << AT91RM9200_ID_US0,
141 .type = CLK_TYPE_PERIPHERAL,
142};
143static struct clk usart1_clk = {
144 .name = "usart1_clk",
145 .pmc_mask = 1 << AT91RM9200_ID_US1,
146 .type = CLK_TYPE_PERIPHERAL,
147};
148static struct clk usart2_clk = {
149 .name = "usart2_clk",
150 .pmc_mask = 1 << AT91RM9200_ID_US2,
151 .type = CLK_TYPE_PERIPHERAL,
152};
153static struct clk usart3_clk = {
154 .name = "usart3_clk",
155 .pmc_mask = 1 << AT91RM9200_ID_US3,
156 .type = CLK_TYPE_PERIPHERAL,
157};
158static struct clk spi_clk = {
159 .name = "spi_clk",
160 .pmc_mask = 1 << AT91RM9200_ID_SPI,
161 .type = CLK_TYPE_PERIPHERAL,
162};
163static struct clk pioA_clk = {
164 .name = "pioA_clk",
165 .pmc_mask = 1 << AT91RM9200_ID_PIOA,
166 .type = CLK_TYPE_PERIPHERAL,
167};
168static struct clk pioB_clk = {
169 .name = "pioB_clk",
170 .pmc_mask = 1 << AT91RM9200_ID_PIOB,
171 .type = CLK_TYPE_PERIPHERAL,
172};
173static struct clk pioC_clk = {
174 .name = "pioC_clk",
175 .pmc_mask = 1 << AT91RM9200_ID_PIOC,
176 .type = CLK_TYPE_PERIPHERAL,
177};
178static struct clk pioD_clk = {
179 .name = "pioD_clk",
180 .pmc_mask = 1 << AT91RM9200_ID_PIOD,
181 .type = CLK_TYPE_PERIPHERAL,
182};
183
184static struct clk *periph_clocks[] __initdata = {
185 &pioA_clk,
186 &pioB_clk,
187 &pioC_clk,
188 &pioD_clk,
189 &usart0_clk,
190 &usart1_clk,
191 &usart2_clk,
192 &usart3_clk,
193 &mmc_clk,
194 &udc_clk,
195 &twi_clk,
196 &spi_clk,
197 // ssc 0 .. ssc2
198 // tc0 .. tc5
199 &ohci_clk,
200 &ether_clk,
201 // irq0 .. irq6
202};
203
204/*
205 * The four programmable clocks.
206 * You must configure pin multiplexing to bring these signals out.
207 */
208static struct clk pck0 = {
209 .name = "pck0",
210 .pmc_mask = AT91_PMC_PCK0,
211 .type = CLK_TYPE_PROGRAMMABLE,
212 .id = 0,
213};
214static struct clk pck1 = {
215 .name = "pck1",
216 .pmc_mask = AT91_PMC_PCK1,
217 .type = CLK_TYPE_PROGRAMMABLE,
218 .id = 1,
219};
220static struct clk pck2 = {
221 .name = "pck2",
222 .pmc_mask = AT91_PMC_PCK2,
223 .type = CLK_TYPE_PROGRAMMABLE,
224 .id = 2,
225};
226static struct clk pck3 = {
227 .name = "pck3",
228 .pmc_mask = AT91_PMC_PCK3,
229 .type = CLK_TYPE_PROGRAMMABLE,
230 .id = 3,
231};
232
233static void __init at91rm9200_register_clocks(void)
106{ 234{
235 int i;
236
237 for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
238 clk_register(periph_clocks[i]);
239
240 clk_register(&pck0);
241 clk_register(&pck1);
242 clk_register(&pck2);
243 clk_register(&pck3);
244}
245
246
247/* --------------------------------------------------------------------
248 * AT91RM9200 processor initialization
249 * -------------------------------------------------------------------- */
250void __init at91rm9200_initialize(unsigned long main_clock)
251{
252 /* Map peripherals */
107 iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); 253 iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
254
255 /* Init clock subsystem */
256 at91_clock_init(main_clock);
257
258 /* Register the processor-specific clocks */
259 at91rm9200_register_clocks();
108} 260}
109 261
110/* 262/*
diff --git a/arch/arm/mach-at91rm9200/board-1arm.c b/arch/arm/mach-at91rm9200/board-1arm.c
index dc79e0992af7..d2aa9c4a8b24 100644
--- a/arch/arm/mach-at91rm9200/board-1arm.c
+++ b/arch/arm/mach-at91rm9200/board-1arm.c
@@ -34,7 +34,6 @@
34#include <asm/mach/map.h> 34#include <asm/mach/map.h>
35#include <asm/mach/irq.h> 35#include <asm/mach/irq.h>
36 36
37#include <asm/hardware.h>
38#include <asm/arch/board.h> 37#include <asm/arch/board.h>
39#include <asm/arch/gpio.h> 38#include <asm/arch/gpio.h>
40 39
@@ -62,10 +61,8 @@ static struct at91_uart_config __initdata onearm_uart_config = {
62 61
63static void __init onearm_map_io(void) 62static void __init onearm_map_io(void)
64{ 63{
65 at91rm9200_map_io(); 64 /* Initialize processor: 18.432 MHz crystal */
66 65 at91rm9200_initialize(18432000);
67 /* Initialize clocks: 18.432 MHz crystal */
68 at91_clock_init(18432000);
69 66
70 /* Setup the serial ports and console */ 67 /* Setup the serial ports and console */
71 at91_init_serial(&onearm_uart_config); 68 at91_init_serial(&onearm_uart_config);
diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c
index 2c138b542ebe..6af252bcb083 100644
--- a/arch/arm/mach-at91rm9200/board-carmeva.c
+++ b/arch/arm/mach-at91rm9200/board-carmeva.c
@@ -35,7 +35,6 @@
35#include <asm/mach/map.h> 35#include <asm/mach/map.h>
36#include <asm/mach/irq.h> 36#include <asm/mach/irq.h>
37 37
38#include <asm/hardware.h>
39#include <asm/arch/board.h> 38#include <asm/arch/board.h>
40#include <asm/arch/gpio.h> 39#include <asm/arch/gpio.h>
41 40
@@ -63,10 +62,8 @@ static struct at91_uart_config __initdata carmeva_uart_config = {
63 62
64static void __init carmeva_map_io(void) 63static void __init carmeva_map_io(void)
65{ 64{
66 at91rm9200_map_io(); 65 /* Initialize processor: 20.000 MHz crystal */
67 66 at91rm9200_initialize(20000000);
68 /* Initialize clocks: 20.000 MHz crystal */
69 at91_clock_init(20000000);
70 67
71 /* Setup the serial ports and console */ 68 /* Setup the serial ports and console */
72 at91_init_serial(&carmeva_uart_config); 69 at91_init_serial(&carmeva_uart_config);
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c
index 794d3fbb449b..f74b483329c0 100644
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ b/arch/arm/mach-at91rm9200/board-csb337.c
@@ -34,7 +34,6 @@
34#include <asm/mach/map.h> 34#include <asm/mach/map.h>
35#include <asm/mach/irq.h> 35#include <asm/mach/irq.h>
36 36
37#include <asm/hardware.h>
38#include <asm/arch/board.h> 37#include <asm/arch/board.h>
39#include <asm/arch/gpio.h> 38#include <asm/arch/gpio.h>
40 39
@@ -62,10 +61,8 @@ static struct at91_uart_config __initdata csb337_uart_config = {
62 61
63static void __init csb337_map_io(void) 62static void __init csb337_map_io(void)
64{ 63{
65 at91rm9200_map_io(); 64 /* Initialize processor: 3.6864 MHz crystal */
66 65 at91rm9200_initialize(3686400);
67 /* Initialize clocks: 3.6864 MHz crystal */
68 at91_clock_init(3686400);
69 66
70 /* Setup the LEDs */ 67 /* Setup the LEDs */
71 at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1); 68 at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c
index c8b6f334246a..880350997a3b 100644
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ b/arch/arm/mach-at91rm9200/board-csb637.c
@@ -33,7 +33,6 @@
33#include <asm/mach/map.h> 33#include <asm/mach/map.h>
34#include <asm/mach/irq.h> 34#include <asm/mach/irq.h>
35 35
36#include <asm/hardware.h>
37#include <asm/arch/board.h> 36#include <asm/arch/board.h>
38#include <asm/arch/gpio.h> 37#include <asm/arch/gpio.h>
39 38
@@ -61,10 +60,8 @@ static struct at91_uart_config __initdata csb637_uart_config = {
61 60
62static void __init csb637_map_io(void) 61static void __init csb637_map_io(void)
63{ 62{
64 at91rm9200_map_io(); 63 /* Initialize processor: 3.6864 MHz crystal */
65 64 at91rm9200_initialize(3686400);
66 /* Initialize clocks: 3.6864 MHz crystal */
67 at91_clock_init(3686400);
68 65
69 /* Setup the LEDs */ 66 /* Setup the LEDs */
70 at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); 67 at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c
index 65873037e02a..23ea9d63b986 100644
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ b/arch/arm/mach-at91rm9200/board-dk.c
@@ -37,7 +37,6 @@
37#include <asm/mach/map.h> 37#include <asm/mach/map.h>
38#include <asm/mach/irq.h> 38#include <asm/mach/irq.h>
39 39
40#include <asm/hardware.h>
41#include <asm/arch/board.h> 40#include <asm/arch/board.h>
42#include <asm/arch/gpio.h> 41#include <asm/arch/gpio.h>
43 42
@@ -65,10 +64,8 @@ static struct at91_uart_config __initdata dk_uart_config = {
65 64
66static void __init dk_map_io(void) 65static void __init dk_map_io(void)
67{ 66{
68 at91rm9200_map_io(); 67 /* Initialize processor: 18.432 MHz crystal */
69 68 at91rm9200_initialize(18432000);
70 /* Initialize clocks: 18.432 MHz crystal */
71 at91_clock_init(18432000);
72 69
73 /* Setup the LEDs */ 70 /* Setup the LEDs */
74 at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); 71 at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c
index a3e2df968a66..2ceb267585ad 100644
--- a/arch/arm/mach-at91rm9200/board-eb9200.c
+++ b/arch/arm/mach-at91rm9200/board-eb9200.c
@@ -35,7 +35,6 @@
35#include <asm/mach/map.h> 35#include <asm/mach/map.h>
36#include <asm/mach/irq.h> 36#include <asm/mach/irq.h>
37 37
38#include <asm/hardware.h>
39#include <asm/arch/board.h> 38#include <asm/arch/board.h>
40#include <asm/arch/gpio.h> 39#include <asm/arch/gpio.h>
41 40
@@ -63,10 +62,8 @@ static struct at91_uart_config __initdata eb9200_uart_config = {
63 62
64static void __init eb9200_map_io(void) 63static void __init eb9200_map_io(void)
65{ 64{
66 at91rm9200_map_io(); 65 /* Initialize processor: 18.432 MHz crystal */
67 66 at91rm9200_initialize(18432000);
68 /* Initialize clocks: 18.432 MHz crystal */
69 at91_clock_init(18432000);
70 67
71 /* Setup the serial ports and console */ 68 /* Setup the serial ports and console */
72 at91_init_serial(&eb9200_uart_config); 69 at91_init_serial(&eb9200_uart_config);
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c
index 868192351dda..8cd83364cd80 100644
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ b/arch/arm/mach-at91rm9200/board-ek.c
@@ -37,7 +37,6 @@
37#include <asm/mach/map.h> 37#include <asm/mach/map.h>
38#include <asm/mach/irq.h> 38#include <asm/mach/irq.h>
39 39
40#include <asm/hardware.h>
41#include <asm/arch/board.h> 40#include <asm/arch/board.h>
42#include <asm/arch/gpio.h> 41#include <asm/arch/gpio.h>
43 42
@@ -65,10 +64,8 @@ static struct at91_uart_config __initdata ek_uart_config = {
65 64
66static void __init ek_map_io(void) 65static void __init ek_map_io(void)
67{ 66{
68 at91rm9200_map_io(); 67 /* Initialize processor: 18.432 MHz crystal */
69 68 at91rm9200_initialize(18432000);
70 /* Initialize clocks: 18.432 MHz crystal */
71 at91_clock_init(18432000);
72 69
73 /* Setup the LEDs */ 70 /* Setup the LEDs */
74 at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2); 71 at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91rm9200/board-kafa.c
index bf760c5e0c46..d9a6b7e7d63a 100644
--- a/arch/arm/mach-at91rm9200/board-kafa.c
+++ b/arch/arm/mach-at91rm9200/board-kafa.c
@@ -34,7 +34,6 @@
34#include <asm/mach/map.h> 34#include <asm/mach/map.h>
35#include <asm/mach/irq.h> 35#include <asm/mach/irq.h>
36 36
37#include <asm/hardware.h>
38#include <asm/arch/board.h> 37#include <asm/arch/board.h>
39#include <asm/arch/gpio.h> 38#include <asm/arch/gpio.h>
40 39
@@ -62,10 +61,8 @@ static struct at91_uart_config __initdata kafa_uart_config = {
62 61
63static void __init kafa_map_io(void) 62static void __init kafa_map_io(void)
64{ 63{
65 at91rm9200_map_io(); 64 /* Initialize processor: 18.432 MHz crystal */
66 65 at91rm9200_initialize(18432000);
67 /* Initialize clocks: 18.432 MHz crystal */
68 at91_clock_init(18432000);
69 66
70 /* Set up the LEDs */ 67 /* Set up the LEDs */
71 at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4); 68 at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c
index f06d2b54cc9a..935238ffa330 100644
--- a/arch/arm/mach-at91rm9200/board-kb9202.c
+++ b/arch/arm/mach-at91rm9200/board-kb9202.c
@@ -35,7 +35,6 @@
35#include <asm/mach/map.h> 35#include <asm/mach/map.h>
36#include <asm/mach/irq.h> 36#include <asm/mach/irq.h>
37 37
38#include <asm/hardware.h>
39#include <asm/arch/board.h> 38#include <asm/arch/board.h>
40#include <asm/arch/gpio.h> 39#include <asm/arch/gpio.h>
41 40
@@ -63,10 +62,8 @@ static struct at91_uart_config __initdata kb9202_uart_config = {
63 62
64static void __init kb9202_map_io(void) 63static void __init kb9202_map_io(void)
65{ 64{
66 at91rm9200_map_io(); 65 /* Initialize processor: 10 MHz crystal */
67 66 at91rm9200_initialize(10000000);
68 /* Initialize clocks: 10 MHz crystal */
69 at91_clock_init(10000000);
70 67
71 /* Set up the LEDs */ 68 /* Set up the LEDs */
72 at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18); 69 at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c
index 5b7892277bee..a43b061a7c85 100644
--- a/arch/arm/mach-at91rm9200/clock.c
+++ b/arch/arm/mach-at91rm9200/clock.c
@@ -29,7 +29,7 @@
29 29
30#include <asm/hardware.h> 30#include <asm/hardware.h>
31 31
32#include "generic.h" 32#include "clock.h"
33 33
34 34
35/* 35/*
@@ -38,23 +38,15 @@
38 * PLLB be used at other rates (on boards that don't need USB), etc. 38 * PLLB be used at other rates (on boards that don't need USB), etc.
39 */ 39 */
40 40
41struct clk { 41#define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY)
42 const char *name; /* unique clock name */ 42#define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE)
43 const char *function; /* function of the clock */ 43#define clk_is_peripheral(x) ((x)->type & CLK_TYPE_PERIPHERAL)
44 struct device *dev; /* device associated with function */ 44
45 unsigned long rate_hz; 45
46 struct clk *parent; 46static LIST_HEAD(clocks);
47 u32 pmc_mask; 47static DEFINE_SPINLOCK(clk_lock);
48 void (*mode)(struct clk *, int);
49 unsigned id:2; /* PCK0..3, or 32k/main/a/b */
50 unsigned primary:1;
51 unsigned pll:1;
52 unsigned programmable:1;
53 u16 users;
54};
55 48
56static spinlock_t clk_lock; 49static u32 at91_pllb_usb_init;
57static u32 at91_pllb_usb_init;
58 50
59/* 51/*
60 * Four primary clock sources: two crystal oscillators (32K, main), and 52 * Four primary clock sources: two crystal oscillators (32K, main), and
@@ -67,21 +59,20 @@ static struct clk clk32k = {
67 .rate_hz = AT91_SLOW_CLOCK, 59 .rate_hz = AT91_SLOW_CLOCK,
68 .users = 1, /* always on */ 60 .users = 1, /* always on */
69 .id = 0, 61 .id = 0,
70 .primary = 1, 62 .type = CLK_TYPE_PRIMARY,
71}; 63};
72static struct clk main_clk = { 64static struct clk main_clk = {
73 .name = "main", 65 .name = "main",
74 .pmc_mask = AT91_PMC_MOSCS, /* in PMC_SR */ 66 .pmc_mask = AT91_PMC_MOSCS, /* in PMC_SR */
75 .id = 1, 67 .id = 1,
76 .primary = 1, 68 .type = CLK_TYPE_PRIMARY,
77}; 69};
78static struct clk plla = { 70static struct clk plla = {
79 .name = "plla", 71 .name = "plla",
80 .parent = &main_clk, 72 .parent = &main_clk,
81 .pmc_mask = AT91_PMC_LOCKA, /* in PMC_SR */ 73 .pmc_mask = AT91_PMC_LOCKA, /* in PMC_SR */
82 .id = 2, 74 .id = 2,
83 .primary = 1, 75 .type = CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
84 .pll = 1,
85}; 76};
86 77
87static void pllb_mode(struct clk *clk, int is_on) 78static void pllb_mode(struct clk *clk, int is_on)
@@ -94,6 +85,7 @@ static void pllb_mode(struct clk *clk, int is_on)
94 } else 85 } else
95 value = 0; 86 value = 0;
96 87
88 // REVISIT: Add work-around for AT91RM9200 Errata #26 ?
97 at91_sys_write(AT91_CKGR_PLLBR, value); 89 at91_sys_write(AT91_CKGR_PLLBR, value);
98 90
99 do { 91 do {
@@ -107,8 +99,7 @@ static struct clk pllb = {
107 .pmc_mask = AT91_PMC_LOCKB, /* in PMC_SR */ 99 .pmc_mask = AT91_PMC_LOCKB, /* in PMC_SR */
108 .mode = pllb_mode, 100 .mode = pllb_mode,
109 .id = 3, 101 .id = 3,
110 .primary = 1, 102 .type = CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
111 .pll = 1,
112}; 103};
113 104
114static void pmc_sys_mode(struct clk *clk, int is_on) 105static void pmc_sys_mode(struct clk *clk, int is_on)
@@ -133,41 +124,6 @@ static struct clk uhpck = {
133 .mode = pmc_sys_mode, 124 .mode = pmc_sys_mode,
134}; 125};
135 126
136#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
137/*
138 * The four programmable clocks can be parented by any primary clock.
139 * You must configure pin multiplexing to bring these signals out.
140 */
141static struct clk pck0 = {
142 .name = "pck0",
143 .pmc_mask = AT91_PMC_PCK0,
144 .mode = pmc_sys_mode,
145 .programmable = 1,
146 .id = 0,
147};
148static struct clk pck1 = {
149 .name = "pck1",
150 .pmc_mask = AT91_PMC_PCK1,
151 .mode = pmc_sys_mode,
152 .programmable = 1,
153 .id = 1,
154};
155static struct clk pck2 = {
156 .name = "pck2",
157 .pmc_mask = AT91_PMC_PCK2,
158 .mode = pmc_sys_mode,
159 .programmable = 1,
160 .id = 2,
161};
162static struct clk pck3 = {
163 .name = "pck3",
164 .pmc_mask = AT91_PMC_PCK3,
165 .mode = pmc_sys_mode,
166 .programmable = 1,
167 .id = 3,
168};
169#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
170
171 127
172/* 128/*
173 * The master clock is divided from the CPU clock (by 1-4). It's used for 129 * The master clock is divided from the CPU clock (by 1-4). It's used for
@@ -187,131 +143,21 @@ static void pmc_periph_mode(struct clk *clk, int is_on)
187 at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask); 143 at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask);
188} 144}
189 145
190static struct clk udc_clk = { 146static struct clk __init *at91_css_to_clk(unsigned long css)
191 .name = "udc_clk", 147{
192 .parent = &mck, 148 switch (css) {
193 .pmc_mask = 1 << AT91RM9200_ID_UDP, 149 case AT91_PMC_CSS_SLOW:
194 .mode = pmc_periph_mode, 150 return &clk32k;
195}; 151 case AT91_PMC_CSS_MAIN:
196static struct clk ohci_clk = { 152 return &main_clk;
197 .name = "ohci_clk", 153 case AT91_PMC_CSS_PLLA:
198 .parent = &mck, 154 return &plla;
199 .pmc_mask = 1 << AT91RM9200_ID_UHP, 155 case AT91_PMC_CSS_PLLB:
200 .mode = pmc_periph_mode, 156 return &pllb;
201}; 157 }
202static struct clk ether_clk = {
203 .name = "ether_clk",
204 .parent = &mck,
205 .pmc_mask = 1 << AT91RM9200_ID_EMAC,
206 .mode = pmc_periph_mode,
207};
208static struct clk mmc_clk = {
209 .name = "mci_clk",
210 .parent = &mck,
211 .pmc_mask = 1 << AT91RM9200_ID_MCI,
212 .mode = pmc_periph_mode,
213};
214static struct clk twi_clk = {
215 .name = "twi_clk",
216 .parent = &mck,
217 .pmc_mask = 1 << AT91RM9200_ID_TWI,
218 .mode = pmc_periph_mode,
219};
220static struct clk usart0_clk = {
221 .name = "usart0_clk",
222 .parent = &mck,
223 .pmc_mask = 1 << AT91RM9200_ID_US0,
224 .mode = pmc_periph_mode,
225};
226static struct clk usart1_clk = {
227 .name = "usart1_clk",
228 .parent = &mck,
229 .pmc_mask = 1 << AT91RM9200_ID_US1,
230 .mode = pmc_periph_mode,
231};
232static struct clk usart2_clk = {
233 .name = "usart2_clk",
234 .parent = &mck,
235 .pmc_mask = 1 << AT91RM9200_ID_US2,
236 .mode = pmc_periph_mode,
237};
238static struct clk usart3_clk = {
239 .name = "usart3_clk",
240 .parent = &mck,
241 .pmc_mask = 1 << AT91RM9200_ID_US3,
242 .mode = pmc_periph_mode,
243};
244static struct clk spi_clk = {
245 .name = "spi0_clk",
246 .parent = &mck,
247 .pmc_mask = 1 << AT91RM9200_ID_SPI,
248 .mode = pmc_periph_mode,
249};
250static struct clk pioA_clk = {
251 .name = "pioA_clk",
252 .parent = &mck,
253 .pmc_mask = 1 << AT91RM9200_ID_PIOA,
254 .mode = pmc_periph_mode,
255};
256static struct clk pioB_clk = {
257 .name = "pioB_clk",
258 .parent = &mck,
259 .pmc_mask = 1 << AT91RM9200_ID_PIOB,
260 .mode = pmc_periph_mode,
261};
262static struct clk pioC_clk = {
263 .name = "pioC_clk",
264 .parent = &mck,
265 .pmc_mask = 1 << AT91RM9200_ID_PIOC,
266 .mode = pmc_periph_mode,
267};
268static struct clk pioD_clk = {
269 .name = "pioD_clk",
270 .parent = &mck,
271 .pmc_mask = 1 << AT91RM9200_ID_PIOD,
272 .mode = pmc_periph_mode,
273};
274
275static struct clk *const clock_list[] = {
276 /* four primary clocks -- MUST BE FIRST! */
277 &clk32k,
278 &main_clk,
279 &plla,
280 &pllb,
281
282 /* PLLB children (USB) */
283 &udpck,
284 &uhpck,
285
286#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
287 /* programmable clocks */
288 &pck0,
289 &pck1,
290 &pck2,
291 &pck3,
292#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
293
294 /* MCK and peripherals */
295 &mck,
296 &usart0_clk,
297 &usart1_clk,
298 &usart2_clk,
299 &usart3_clk,
300 &mmc_clk,
301 &udc_clk,
302 &twi_clk,
303 &spi_clk,
304 &pioA_clk,
305 &pioB_clk,
306 &pioC_clk,
307 &pioD_clk,
308 // ssc0..ssc2
309 // tc0..tc5
310 // irq0..irq6
311 &ohci_clk,
312 &ether_clk,
313};
314 158
159 return NULL;
160}
315 161
316/* 162/*
317 * Associate a particular clock with a function (eg, "uart") and device. 163 * Associate a particular clock with a function (eg, "uart") and device.
@@ -329,14 +175,12 @@ void __init at91_clock_associate(const char *id, struct device *dev, const char
329 clk->dev = dev; 175 clk->dev = dev;
330} 176}
331 177
332/* clocks are all static for now; no refcounting necessary */ 178/* clocks cannot be de-registered no refcounting necessary */
333struct clk *clk_get(struct device *dev, const char *id) 179struct clk *clk_get(struct device *dev, const char *id)
334{ 180{
335 int i; 181 struct clk *clk;
336
337 for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
338 struct clk *clk = clock_list[i];
339 182
183 list_for_each_entry(clk, &clocks, node) {
340 if (strcmp(id, clk->name) == 0) 184 if (strcmp(id, clk->name) == 0)
341 return clk; 185 return clk;
342 if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0) 186 if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0)
@@ -424,7 +268,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
424 unsigned prescale; 268 unsigned prescale;
425 unsigned long actual; 269 unsigned long actual;
426 270
427 if (!clk->programmable) 271 if (!clk_is_programmable(clk))
428 return -EINVAL; 272 return -EINVAL;
429 spin_lock_irqsave(&clk_lock, flags); 273 spin_lock_irqsave(&clk_lock, flags);
430 274
@@ -446,7 +290,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
446 unsigned prescale; 290 unsigned prescale;
447 unsigned long actual; 291 unsigned long actual;
448 292
449 if (!clk->programmable) 293 if (!clk_is_programmable(clk))
450 return -EINVAL; 294 return -EINVAL;
451 if (clk->users) 295 if (clk->users)
452 return -EBUSY; 296 return -EBUSY;
@@ -484,7 +328,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
484 328
485 if (clk->users) 329 if (clk->users)
486 return -EBUSY; 330 return -EBUSY;
487 if (!parent->primary || !clk->programmable) 331 if (!clk_is_primary(parent) || !clk_is_programmable(clk))
488 return -EINVAL; 332 return -EINVAL;
489 spin_lock_irqsave(&clk_lock, flags); 333 spin_lock_irqsave(&clk_lock, flags);
490 334
@@ -497,6 +341,18 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
497} 341}
498EXPORT_SYMBOL(clk_set_parent); 342EXPORT_SYMBOL(clk_set_parent);
499 343
344/* establish PCK0..PCK3 parentage and rate */
345static void init_programmable_clock(struct clk *clk)
346{
347 struct clk *parent;
348 u32 pckr;
349
350 pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
351 parent = at91_css_to_clk(pckr & AT91_PMC_CSS);
352 clk->parent = parent;
353 clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
354}
355
500#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ 356#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
501 357
502/*------------------------------------------------------------------------*/ 358/*------------------------------------------------------------------------*/
@@ -506,6 +362,7 @@ EXPORT_SYMBOL(clk_set_parent);
506static int at91_clk_show(struct seq_file *s, void *unused) 362static int at91_clk_show(struct seq_file *s, void *unused)
507{ 363{
508 u32 scsr, pcsr, sr; 364 u32 scsr, pcsr, sr;
365 struct clk *clk;
509 unsigned i; 366 unsigned i;
510 367
511 seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR)); 368 seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR));
@@ -523,9 +380,8 @@ static int at91_clk_show(struct seq_file *s, void *unused)
523 380
524 seq_printf(s, "\n"); 381 seq_printf(s, "\n");
525 382
526 for (i = 0; i < ARRAY_SIZE(clock_list); i++) { 383 list_for_each_entry(clk, &clocks, node) {
527 char *state; 384 char *state;
528 struct clk *clk = clock_list[i];
529 385
530 if (clk->mode == pmc_sys_mode) 386 if (clk->mode == pmc_sys_mode)
531 state = (scsr & clk->pmc_mask) ? "on" : "off"; 387 state = (scsr & clk->pmc_mask) ? "on" : "off";
@@ -570,6 +426,28 @@ postcore_initcall(at91_clk_debugfs_init);
570 426
571/*------------------------------------------------------------------------*/ 427/*------------------------------------------------------------------------*/
572 428
429/* Register a new clock */
430int __init clk_register(struct clk *clk)
431{
432 if (clk_is_peripheral(clk)) {
433 clk->parent = &mck;
434 clk->mode = pmc_periph_mode;
435 list_add_tail(&clk->node, &clocks);
436 }
437#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
438 else if (clk_is_programmable(clk)) {
439 clk->mode = pmc_sys_mode;
440 init_programmable_clock(clk);
441 list_add_tail(&clk->node, &clocks);
442 }
443#endif
444
445 return 0;
446}
447
448
449/*------------------------------------------------------------------------*/
450
573static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg) 451static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg)
574{ 452{
575 unsigned mul, div; 453 unsigned mul, div;
@@ -640,20 +518,17 @@ fail:
640 return 0; 518 return 0;
641} 519}
642 520
643
644/* 521/*
645 * Several unused clocks may be active. Turn them off. 522 * Several unused clocks may be active. Turn them off.
646 */ 523 */
647static void at91_periphclk_reset(void) 524static void __init at91_periphclk_reset(void)
648{ 525{
649 unsigned long reg; 526 unsigned long reg;
650 int i; 527 struct clk *clk;
651 528
652 reg = at91_sys_read(AT91_PMC_PCSR); 529 reg = at91_sys_read(AT91_PMC_PCSR);
653 530
654 for (i = 0; i < ARRAY_SIZE(clock_list); i++) { 531 list_for_each_entry(clk, &clocks, node) {
655 struct clk *clk = clock_list[i];
656
657 if (clk->mode != pmc_periph_mode) 532 if (clk->mode != pmc_periph_mode)
658 continue; 533 continue;
659 534
@@ -664,11 +539,25 @@ static void at91_periphclk_reset(void)
664 at91_sys_write(AT91_PMC_PCDR, reg); 539 at91_sys_write(AT91_PMC_PCDR, reg);
665} 540}
666 541
542static struct clk *const standard_pmc_clocks[] __initdata = {
543 /* four primary clocks */
544 &clk32k,
545 &main_clk,
546 &plla,
547 &pllb,
548
549 /* PLLB children (USB) */
550 &udpck,
551 &uhpck,
552
553 /* MCK */
554 &mck
555};
556
667int __init at91_clock_init(unsigned long main_clock) 557int __init at91_clock_init(unsigned long main_clock)
668{ 558{
669 unsigned tmp, freq, mckr; 559 unsigned tmp, freq, mckr;
670 560 int i;
671 spin_lock_init(&clk_lock);
672 561
673 /* 562 /*
674 * When the bootloader initialized the main oscillator correctly, 563 * When the bootloader initialized the main oscillator correctly,
@@ -709,11 +598,15 @@ int __init at91_clock_init(unsigned long main_clock)
709 * For now, assume this parentage won't change. 598 * For now, assume this parentage won't change.
710 */ 599 */
711 mckr = at91_sys_read(AT91_PMC_MCKR); 600 mckr = at91_sys_read(AT91_PMC_MCKR);
712 mck.parent = clock_list[mckr & AT91_PMC_CSS]; 601 mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
713 freq = mck.parent->rate_hz; 602 freq = mck.parent->rate_hz;
714 freq /= (1 << ((mckr >> 2) & 3)); /* prescale */ 603 freq /= (1 << ((mckr >> 2) & 3)); /* prescale */
715 mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */ 604 mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */
716 605
606 /* Register the PMC's standard clocks */
607 for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
608 list_add_tail(&standard_pmc_clocks[i]->node, &clocks);
609
717 /* MCK and CPU clock are "always on" */ 610 /* MCK and CPU clock are "always on" */
718 clk_enable(&mck); 611 clk_enable(&mck);
719 612
@@ -722,35 +615,8 @@ int __init at91_clock_init(unsigned long main_clock)
722 (unsigned) main_clock / 1000000, 615 (unsigned) main_clock / 1000000,
723 ((unsigned) main_clock % 1000000) / 1000); 616 ((unsigned) main_clock % 1000000) / 1000);
724 617
725#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
726 /* establish PCK0..PCK3 parentage */
727 for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) {
728 struct clk *clk = clock_list[tmp], *parent;
729 u32 pckr;
730
731 if (!clk->programmable)
732 continue;
733
734 pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
735 parent = clock_list[pckr & AT91_PMC_CSS];
736 clk->parent = parent;
737 clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
738
739 if (clk->users == 0) {
740 /* not being used, so switch it off */
741 at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask);
742 }
743 }
744#else
745 /* disable all programmable clocks */ 618 /* disable all programmable clocks */
746 at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); 619 at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3);
747#endif
748
749 /* enable the PIO clocks */
750 clk_enable(&pioA_clk);
751 clk_enable(&pioB_clk);
752 clk_enable(&pioC_clk);
753 clk_enable(&pioD_clk);
754 620
755 /* disable all other unused peripheral clocks */ 621 /* disable all other unused peripheral clocks */
756 at91_periphclk_reset(); 622 at91_periphclk_reset();
diff --git a/arch/arm/mach-at91rm9200/clock.h b/arch/arm/mach-at91rm9200/clock.h
new file mode 100644
index 000000000000..0592e662ab37
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/clock.h
@@ -0,0 +1,30 @@
1/*
2 * linux/arch/arm/mach-at91rm9200/clock.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#define CLK_TYPE_PRIMARY 0x1
10#define CLK_TYPE_PLL 0x2
11#define CLK_TYPE_PROGRAMMABLE 0x4
12#define CLK_TYPE_PERIPHERAL 0x8
13
14
15struct clk {
16 struct list_head node;
17 const char *name; /* unique clock name */
18 const char *function; /* function of the clock */
19 struct device *dev; /* device associated with function */
20 unsigned long rate_hz;
21 struct clk *parent;
22 u32 pmc_mask;
23 void (*mode)(struct clk *, int);
24 unsigned id:2; /* PCK0..3, or 32k/main/a/b */
25 unsigned type; /* clock type */
26 u16 users;
27};
28
29
30extern int __init clk_register(struct clk *clk);
diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h
index 7979d8ab7e07..c44e0e074682 100644
--- a/arch/arm/mach-at91rm9200/generic.h
+++ b/arch/arm/mach-at91rm9200/generic.h
@@ -8,6 +8,9 @@
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10 10
11 /* Processors */
12extern void __init at91rm9200_initialize(unsigned long main_clock);
13
11 /* Interrupts */ 14 /* Interrupts */
12extern void __init at91rm9200_init_irq(unsigned int priority[]); 15extern void __init at91rm9200_init_irq(unsigned int priority[]);
13extern void __init at91_aic_init(unsigned int priority[]); 16extern void __init at91_aic_init(unsigned int priority[]);
@@ -17,9 +20,6 @@ extern void __init at91_gpio_irq_setup(unsigned banks);
17struct sys_timer; 20struct sys_timer;
18extern struct sys_timer at91rm9200_timer; 21extern struct sys_timer at91rm9200_timer;
19 22
20 /* Memory Map */
21extern void __init at91rm9200_map_io(void);
22
23 /* Clocks */ 23 /* Clocks */
24extern int __init at91_clock_init(unsigned long main_clock); 24extern int __init at91_clock_init(unsigned long main_clock);
25struct device; 25struct device;