aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/ar7
diff options
context:
space:
mode:
authorFlorian Fainelli <florian@openwrt.org>2010-01-27 03:10:06 -0500
committerRalf Baechle <ralf@linux-mips.org>2010-02-27 06:53:16 -0500
commit780019ddf02f214ad61e641b57b8ac30c837e2a7 (patch)
tree2d0a01efc4d508057bcfaa7b3df5b3e490c249ed /arch/mips/ar7
parent5f3c909881d5deebb9a3ddc836a15937e76daefc (diff)
MIPS: AR7: Implement clock API
This patch makes the ar7 clock code implement the Linux clk API. Drivers using the various clocks available in the SoC are updated accordingly. Signed-off-by: Florian Fainelli <florian@openwrt.org> Acked-by: Wim Van Sebroeck <wim@iguana.be> To: linux-mips@linux-mips.org Cc: Wim Van Sebroeck <wim@iguana.be> Cc: netdev@vger.kernel.org Cc: David Miller <davem@davemloft.net> Patchwork: http://patchwork.linux-mips.org/patch/881/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/ar7')
-rw-r--r--arch/mips/ar7/clock.c109
-rw-r--r--arch/mips/ar7/platform.c10
-rw-r--r--arch/mips/ar7/time.c12
3 files changed, 99 insertions, 32 deletions
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
index cc65c8eb391b..fc0e7154e8d6 100644
--- a/arch/mips/ar7/clock.c
+++ b/arch/mips/ar7/clock.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> 2 * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org> 3 * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
4 * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -24,6 +25,8 @@
24#include <linux/delay.h> 25#include <linux/delay.h>
25#include <linux/gcd.h> 26#include <linux/gcd.h>
26#include <linux/io.h> 27#include <linux/io.h>
28#include <linux/err.h>
29#include <linux/clk.h>
27 30
28#include <asm/addrspace.h> 31#include <asm/addrspace.h>
29#include <asm/mach-ar7/ar7.h> 32#include <asm/mach-ar7/ar7.h>
@@ -94,12 +97,16 @@ struct tnetd7200_clocks {
94 struct tnetd7200_clock usb; 97 struct tnetd7200_clock usb;
95}; 98};
96 99
97int ar7_cpu_clock = 150000000; 100static struct clk bus_clk = {
98EXPORT_SYMBOL(ar7_cpu_clock); 101 .rate = 125000000,
99int ar7_bus_clock = 125000000; 102};
100EXPORT_SYMBOL(ar7_bus_clock); 103
101int ar7_dsp_clock; 104static struct clk cpu_clk = {
102EXPORT_SYMBOL(ar7_dsp_clock); 105 .rate = 150000000,
106};
107
108static struct clk dsp_clk;
109static struct clk vbus_clk;
103 110
104static void approximate(int base, int target, int *prediv, 111static void approximate(int base, int target, int *prediv,
105 int *postdiv, int *mul) 112 int *postdiv, int *mul)
@@ -185,7 +192,7 @@ static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
185 base_clock = AR7_XTAL_CLOCK; 192 base_clock = AR7_XTAL_CLOCK;
186 break; 193 break;
187 case BOOT_PLL_SOURCE_CPU: 194 case BOOT_PLL_SOURCE_CPU:
188 base_clock = ar7_cpu_clock; 195 base_clock = cpu_clk.rate;
189 break; 196 break;
190 } 197 }
191 198
@@ -212,11 +219,11 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
212 u32 *bootcr, u32 frequency) 219 u32 *bootcr, u32 frequency)
213{ 220{
214 int prediv, postdiv, mul; 221 int prediv, postdiv, mul;
215 int base_clock = ar7_bus_clock; 222 int base_clock = bus_clk.rate;
216 223
217 switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) { 224 switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
218 case BOOT_PLL_SOURCE_BUS: 225 case BOOT_PLL_SOURCE_BUS:
219 base_clock = ar7_bus_clock; 226 base_clock = bus_clk.rate;
220 break; 227 break;
221 case BOOT_PLL_SOURCE_REF: 228 case BOOT_PLL_SOURCE_REF:
222 base_clock = AR7_REF_CLOCK; 229 base_clock = AR7_REF_CLOCK;
@@ -225,7 +232,7 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
225 base_clock = AR7_XTAL_CLOCK; 232 base_clock = AR7_XTAL_CLOCK;
226 break; 233 break;
227 case BOOT_PLL_SOURCE_CPU: 234 case BOOT_PLL_SOURCE_CPU:
228 base_clock = ar7_cpu_clock; 235 base_clock = cpu_clk.rate;
229 break; 236 break;
230 } 237 }
231 238
@@ -247,18 +254,18 @@ static void __init tnetd7300_init_clocks(void)
247 ioremap_nocache(UR8_REGS_CLOCKS, 254 ioremap_nocache(UR8_REGS_CLOCKS,
248 sizeof(struct tnetd7300_clocks)); 255 sizeof(struct tnetd7300_clocks));
249 256
250 ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT, 257 bus_clk.rate = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
251 &clocks->bus, bootcr, AR7_AFE_CLOCK); 258 &clocks->bus, bootcr, AR7_AFE_CLOCK);
252 259
253 if (*bootcr & BOOT_PLL_ASYNC_MODE) 260 if (*bootcr & BOOT_PLL_ASYNC_MODE)
254 ar7_cpu_clock = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT, 261 cpu_clk.rate = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
255 &clocks->cpu, bootcr, AR7_AFE_CLOCK); 262 &clocks->cpu, bootcr, AR7_AFE_CLOCK);
256 else 263 else
257 ar7_cpu_clock = ar7_bus_clock; 264 cpu_clk.rate = bus_clk.rate;
258 265
259 if (ar7_dsp_clock == 250000000) 266 if (dsp_clk.rate == 250000000)
260 tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp, 267 tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
261 bootcr, ar7_dsp_clock); 268 bootcr, dsp_clk.rate);
262 269
263 iounmap(clocks); 270 iounmap(clocks);
264 iounmap(bootcr); 271 iounmap(bootcr);
@@ -343,20 +350,20 @@ static void __init tnetd7200_init_clocks(void)
343 printk(KERN_INFO "Clocks: Setting DSP clock\n"); 350 printk(KERN_INFO "Clocks: Setting DSP clock\n");
344 calculate(dsp_base, TNETD7200_DEF_DSP_CLK, 351 calculate(dsp_base, TNETD7200_DEF_DSP_CLK,
345 &dsp_prediv, &dsp_postdiv, &dsp_mul); 352 &dsp_prediv, &dsp_postdiv, &dsp_mul);
346 ar7_bus_clock = 353 bus_clk.rate =
347 ((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv; 354 ((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;
348 tnetd7200_set_clock(dsp_base, &clocks->dsp, 355 tnetd7200_set_clock(dsp_base, &clocks->dsp,
349 dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2, 356 dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
350 ar7_bus_clock); 357 bus_clk.rate);
351 358
352 printk(KERN_INFO "Clocks: Setting CPU clock\n"); 359 printk(KERN_INFO "Clocks: Setting CPU clock\n");
353 calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv, 360 calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
354 &cpu_postdiv, &cpu_mul); 361 &cpu_postdiv, &cpu_mul);
355 ar7_cpu_clock = 362 cpu_clk.rate =
356 ((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv; 363 ((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;
357 tnetd7200_set_clock(cpu_base, &clocks->cpu, 364 tnetd7200_set_clock(cpu_base, &clocks->cpu,
358 cpu_prediv, cpu_postdiv, -1, cpu_mul, 365 cpu_prediv, cpu_postdiv, -1, cpu_mul,
359 ar7_cpu_clock); 366 cpu_clk.rate);
360 367
361 } else 368 } else
362 if (*bootcr & BOOT_PLL_2TO1_MODE) { 369 if (*bootcr & BOOT_PLL_2TO1_MODE) {
@@ -365,48 +372,90 @@ static void __init tnetd7200_init_clocks(void)
365 printk(KERN_INFO "Clocks: Setting CPU clock\n"); 372 printk(KERN_INFO "Clocks: Setting CPU clock\n");
366 calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv, 373 calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
367 &cpu_postdiv, &cpu_mul); 374 &cpu_postdiv, &cpu_mul);
368 ar7_cpu_clock = ((cpu_base / cpu_prediv) * cpu_mul) 375 cpu_clk.rate = ((cpu_base / cpu_prediv) * cpu_mul)
369 / cpu_postdiv; 376 / cpu_postdiv;
370 tnetd7200_set_clock(cpu_base, &clocks->cpu, 377 tnetd7200_set_clock(cpu_base, &clocks->cpu,
371 cpu_prediv, cpu_postdiv, -1, cpu_mul, 378 cpu_prediv, cpu_postdiv, -1, cpu_mul,
372 ar7_cpu_clock); 379 cpu_clk.rate);
373 380
374 printk(KERN_INFO "Clocks: Setting DSP clock\n"); 381 printk(KERN_INFO "Clocks: Setting DSP clock\n");
375 calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv, 382 calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
376 &dsp_postdiv, &dsp_mul); 383 &dsp_postdiv, &dsp_mul);
377 ar7_bus_clock = ar7_cpu_clock / 2; 384 bus_clk.rate = cpu_clk.rate / 2;
378 tnetd7200_set_clock(dsp_base, &clocks->dsp, 385 tnetd7200_set_clock(dsp_base, &clocks->dsp,
379 dsp_prediv, dsp_postdiv * 2, dsp_postdiv, 386 dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
380 dsp_mul * 2, ar7_bus_clock); 387 dsp_mul * 2, bus_clk.rate);
381 } else { 388 } else {
382 printk(KERN_INFO "Clocks: Sync 1:1 mode\n"); 389 printk(KERN_INFO "Clocks: Sync 1:1 mode\n");
383 390
384 printk(KERN_INFO "Clocks: Setting DSP clock\n"); 391 printk(KERN_INFO "Clocks: Setting DSP clock\n");
385 calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv, 392 calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
386 &dsp_postdiv, &dsp_mul); 393 &dsp_postdiv, &dsp_mul);
387 ar7_bus_clock = ((dsp_base / dsp_prediv) * dsp_mul) 394 bus_clk.rate = ((dsp_base / dsp_prediv) * dsp_mul)
388 / dsp_postdiv; 395 / dsp_postdiv;
389 tnetd7200_set_clock(dsp_base, &clocks->dsp, 396 tnetd7200_set_clock(dsp_base, &clocks->dsp,
390 dsp_prediv, dsp_postdiv * 2, dsp_postdiv, 397 dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
391 dsp_mul * 2, ar7_bus_clock); 398 dsp_mul * 2, bus_clk.rate);
392 399
393 ar7_cpu_clock = ar7_bus_clock; 400 cpu_clk.rate = bus_clk.rate;
394 } 401 }
395 402
396 printk(KERN_INFO "Clocks: Setting USB clock\n"); 403 printk(KERN_INFO "Clocks: Setting USB clock\n");
397 usb_base = ar7_bus_clock; 404 usb_base = bus_clk.rate;
398 calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv, 405 calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,
399 &usb_postdiv, &usb_mul); 406 &usb_postdiv, &usb_mul);
400 tnetd7200_set_clock(usb_base, &clocks->usb, 407 tnetd7200_set_clock(usb_base, &clocks->usb,
401 usb_prediv, usb_postdiv, -1, usb_mul, 408 usb_prediv, usb_postdiv, -1, usb_mul,
402 TNETD7200_DEF_USB_CLK); 409 TNETD7200_DEF_USB_CLK);
403 410
404 ar7_dsp_clock = ar7_cpu_clock; 411 dsp_clk.rate = cpu_clk.rate;
405 412
406 iounmap(clocks); 413 iounmap(clocks);
407 iounmap(bootcr); 414 iounmap(bootcr);
408} 415}
409 416
417/*
418 * Linux clock API
419 */
420int clk_enable(struct clk *clk)
421{
422 return 0;
423}
424EXPORT_SYMBOL(clk_enable);
425
426void clk_disable(struct clk *clk)
427{
428}
429EXPORT_SYMBOL(clk_disable);
430
431unsigned long clk_get_rate(struct clk *clk)
432{
433 return clk->rate;
434}
435EXPORT_SYMBOL(clk_get_rate);
436
437struct clk *clk_get(struct device *dev, const char *id)
438{
439 if (!strcmp(id, "bus"))
440 return &bus_clk;
441 /* cpmac and vbus share the same rate */
442 if (!strcmp(id, "cpmac"))
443 return &vbus_clk;
444 if (!strcmp(id, "cpu"))
445 return &cpu_clk;
446 if (!strcmp(id, "dsp"));
447 return &dsp_clk;
448 if (!strcmp(id, "vbus"))
449 return &vbus_clk;
450 return ERR_PTR(-ENOENT);
451}
452EXPORT_SYMBOL(clk_get);
453
454void clk_put(struct clk *clk)
455{
456}
457EXPORT_SYMBOL(clk_put);
458
410int __init ar7_init_clocks(void) 459int __init ar7_init_clocks(void)
411{ 460{
412 switch (ar7_chip_id()) { 461 switch (ar7_chip_id()) {
@@ -415,12 +464,14 @@ int __init ar7_init_clocks(void)
415 tnetd7200_init_clocks(); 464 tnetd7200_init_clocks();
416 break; 465 break;
417 case AR7_CHIP_7300: 466 case AR7_CHIP_7300:
418 ar7_dsp_clock = tnetd7300_dsp_clock(); 467 dsp_clk.rate = tnetd7300_dsp_clock();
419 tnetd7300_init_clocks(); 468 tnetd7300_init_clocks();
420 break; 469 break;
421 default: 470 default:
422 break; 471 break;
423 } 472 }
473 /* adjust vbus clock rate */
474 vbus_clk.rate = bus_clk.rate / 2;
424 475
425 return 0; 476 return 0;
426} 477}
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index 5a3fa9407710..1db191cd49c3 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -35,6 +35,7 @@
35#include <linux/phy.h> 35#include <linux/phy.h>
36#include <linux/phy_fixed.h> 36#include <linux/phy_fixed.h>
37#include <linux/gpio.h> 37#include <linux/gpio.h>
38#include <linux/clk.h>
38 39
39#include <asm/addrspace.h> 40#include <asm/addrspace.h>
40#include <asm/mach-ar7/ar7.h> 41#include <asm/mach-ar7/ar7.h>
@@ -507,13 +508,18 @@ static int __init ar7_register_devices(void)
507 u32 *bootcr, val; 508 u32 *bootcr, val;
508#ifdef CONFIG_SERIAL_8250 509#ifdef CONFIG_SERIAL_8250
509 static struct uart_port uart_port[2] __initdata; 510 static struct uart_port uart_port[2] __initdata;
511 struct clk *bus_clk;
510 512
511 memset(uart_port, 0, sizeof(struct uart_port) * 2); 513 memset(uart_port, 0, sizeof(struct uart_port) * 2);
512 514
515 bus_clk = clk_get(NULL, "bus");
516 if (IS_ERR(bus_clk))
517 panic("unable to get bus clk\n");
518
513 uart_port[0].type = PORT_16550A; 519 uart_port[0].type = PORT_16550A;
514 uart_port[0].line = 0; 520 uart_port[0].line = 0;
515 uart_port[0].irq = AR7_IRQ_UART0; 521 uart_port[0].irq = AR7_IRQ_UART0;
516 uart_port[0].uartclk = ar7_bus_freq() / 2; 522 uart_port[0].uartclk = clk_get_rate(bus_clk) / 2;
517 uart_port[0].iotype = UPIO_MEM32; 523 uart_port[0].iotype = UPIO_MEM32;
518 uart_port[0].mapbase = AR7_REGS_UART0; 524 uart_port[0].mapbase = AR7_REGS_UART0;
519 uart_port[0].membase = ioremap(uart_port[0].mapbase, 256); 525 uart_port[0].membase = ioremap(uart_port[0].mapbase, 256);
@@ -528,7 +534,7 @@ static int __init ar7_register_devices(void)
528 uart_port[1].type = PORT_16550A; 534 uart_port[1].type = PORT_16550A;
529 uart_port[1].line = 1; 535 uart_port[1].line = 1;
530 uart_port[1].irq = AR7_IRQ_UART1; 536 uart_port[1].irq = AR7_IRQ_UART1;
531 uart_port[1].uartclk = ar7_bus_freq() / 2; 537 uart_port[1].uartclk = clk_get_rate(bus_clk) / 2;
532 uart_port[1].iotype = UPIO_MEM32; 538 uart_port[1].iotype = UPIO_MEM32;
533 uart_port[1].mapbase = UR8_REGS_UART1; 539 uart_port[1].mapbase = UR8_REGS_UART1;
534 uart_port[1].membase = ioremap(uart_port[1].mapbase, 256); 540 uart_port[1].membase = ioremap(uart_port[1].mapbase, 256);
diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c
index a1fba894daa2..5fb8a0134085 100644
--- a/arch/mips/ar7/time.c
+++ b/arch/mips/ar7/time.c
@@ -20,11 +20,21 @@
20 20
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/time.h> 22#include <linux/time.h>
23#include <linux/err.h>
24#include <linux/clk.h>
23 25
24#include <asm/time.h> 26#include <asm/time.h>
25#include <asm/mach-ar7/ar7.h> 27#include <asm/mach-ar7/ar7.h>
26 28
27void __init plat_time_init(void) 29void __init plat_time_init(void)
28{ 30{
29 mips_hpt_frequency = ar7_cpu_freq() / 2; 31 struct clk *cpu_clk;
32
33 cpu_clk = clk_get(NULL, "cpu");
34 if (IS_ERR(cpu_clk)) {
35 printk(KERN_ERR "unable to get cpu clock\n");
36 return;
37 }
38
39 mips_hpt_frequency = clk_get_rate(cpu_clk) / 2;
30} 40}