From 91f8ed835ffb34b4108cc16eefd3303e4068bee0 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 19 Jun 2006 13:20:23 +0100 Subject: [ARM] 3578/1: AT91RM9200 Clock update Patch from Andrew Victor Some updates to the clock infrastructure for the AT91RM9200. 1. Hard-coded values replaced with names defined in at91rm9200_sys.h. 2. Added the four PIO clocks, which are enabled at startup. 3. At startup, disable all unused clocks. 4. Minor bugfix for usage counts associated with MCK. [Patch from David Brownell] 5. Added at91_clock_associate() function to associate device & function with a particular clock. [Patch from David Brownell] Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/clock.c | 121 ++++++++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 20 deletions(-) (limited to 'arch/arm/mach-at91rm9200/clock.c') diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c index 8b95467c6d61..30042d2bac5f 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91rm9200/clock.c @@ -32,8 +32,6 @@ #include "generic.h" -#undef DEBUG - /* * There's a lot more which can be done with clocks, including cpufreq * integration, slow clock mode support (for system suspend), letting @@ -41,7 +39,9 @@ */ struct clk { - const char *name; + const char *name; /* unique clock name */ + const char *function; /* function of the clock */ + struct device *dev; /* device associated with function */ unsigned long rate_hz; struct clk *parent; u32 pmc_mask; @@ -71,15 +71,14 @@ static struct clk clk32k = { }; static struct clk main_clk = { .name = "main", - .pmc_mask = 1 << 0, /* in PMC_SR */ - .users = 1, + .pmc_mask = AT91_PMC_MOSCS, /* in PMC_SR */ .id = 1, .primary = 1, }; static struct clk plla = { .name = "plla", .parent = &main_clk, - .pmc_mask = 1 << 1, /* in PMC_SR */ + .pmc_mask = AT91_PMC_LOCKA, /* in PMC_SR */ .id = 2, .primary = 1, .pll = 1, @@ -105,7 +104,7 @@ static void pllb_mode(struct clk *clk, int is_on) static struct clk pllb = { .name = "pllb", .parent = &main_clk, - .pmc_mask = 1 << 2, /* in PMC_SR */ + .pmc_mask = AT91_PMC_LOCKB, /* in PMC_SR */ .mode = pllb_mode, .id = 3, .primary = 1, @@ -177,8 +176,7 @@ static struct clk pck3 = { */ static struct clk mck = { .name = "mck", - .pmc_mask = 1 << 3, /* in PMC_SR */ - .users = 1, /* (must be) always on */ + .pmc_mask = AT91_PMC_MCKRDY, /* in PMC_SR */ }; static void pmc_periph_mode(struct clk *clk, int is_on) @@ -249,6 +247,30 @@ static struct clk spi_clk = { .pmc_mask = 1 << AT91_ID_SPI, .mode = pmc_periph_mode, }; +static struct clk pioA_clk = { + .name = "pioA_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_PIOA, + .mode = pmc_periph_mode, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_PIOB, + .mode = pmc_periph_mode, +}; +static struct clk pioC_clk = { + .name = "pioC_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_PIOC, + .mode = pmc_periph_mode, +}; +static struct clk pioD_clk = { + .name = "pioD_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_PIOD, + .mode = pmc_periph_mode, +}; static struct clk *const clock_list[] = { /* four primary clocks -- MUST BE FIRST! */ @@ -279,21 +301,46 @@ static struct clk *const clock_list[] = { &udc_clk, &twi_clk, &spi_clk, + &pioA_clk, + &pioB_clk, + &pioC_clk, + &pioD_clk, // ssc0..ssc2 // tc0..tc5 + // irq0..irq6 &ohci_clk, ðer_clk, }; +/* + * Associate a particular clock with a function (eg, "uart") and device. + * The drivers can then request the same 'function' with several different + * devices and not care about which clock name to use. + */ +void __init at91_clock_associate(const char *id, struct device *dev, const char *func) +{ + struct clk *clk = clk_get(NULL, id); + + if (!dev || !clk || !IS_ERR(clk_get(dev, func))) + return; + + clk->function = func; + clk->dev = dev; +} + /* clocks are all static for now; no refcounting necessary */ struct clk *clk_get(struct device *dev, const char *id) { int i; for (i = 0; i < ARRAY_SIZE(clock_list); i++) { - if (strcmp(id, clock_list[i]->name) == 0) - return clock_list[i]; + struct clk *clk = clock_list[i]; + + if (strcmp(id, clk->name) == 0) + return clk; + if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0) + return clk; } return ERR_PTR(-ENOENT); @@ -593,6 +640,30 @@ fail: return 0; } + +/* + * Several unused clocks may be active. Turn them off. + */ +static void at91_periphclk_reset(void) +{ + unsigned long reg; + int i; + + reg = at91_sys_read(AT91_PMC_PCSR); + + for (i = 0; i < ARRAY_SIZE(clock_list); i++) { + struct clk *clk = clock_list[i]; + + if (clk->mode != pmc_periph_mode) + continue; + + if (clk->users > 0) + reg &= ~clk->pmc_mask; + } + + at91_sys_write(AT91_PMC_PCDR, reg); +} + int __init at91_clock_init(unsigned long main_clock) { unsigned tmp, freq, mckr; @@ -626,7 +697,6 @@ int __init at91_clock_init(unsigned long main_clock) */ at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M; pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); - at91_sys_write(AT91_PMC_PCDR, (1 << AT91_ID_UHP) | (1 << AT91_ID_UDP)); at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP); at91_sys_write(AT91_CKGR_PLLBR, 0); at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP); @@ -640,11 +710,13 @@ int __init at91_clock_init(unsigned long main_clock) */ mckr = at91_sys_read(AT91_PMC_MCKR); mck.parent = clock_list[mckr & AT91_PMC_CSS]; - mck.parent->users++; freq = mck.parent->rate_hz; freq /= (1 << ((mckr >> 2) & 3)); /* prescale */ mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */ + /* MCK and CPU clock are "always on" */ + clk_enable(&mck); + printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n", freq / 1000000, (unsigned) mck.rate_hz / 1000000, (unsigned) main_clock / 1000000, @@ -663,19 +735,28 @@ int __init at91_clock_init(unsigned long main_clock) continue; pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); - parent = clock_list[pckr & 3]; + parent = clock_list[pckr & AT91_PMC_CSS]; clk->parent = parent; clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3)); + + if (clk->users == 0) { + /* not being used, so switch it off */ + at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask); + } } #else - /* disable unused clocks */ + /* disable all programmable clocks */ at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); -#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ +#endif - /* FIXME several unused clocks may still be active... provide - * a CONFIG option to turn off all unused clocks at some point - * before driver init starts. - */ + /* enable the PIO clocks */ + clk_enable(&pioA_clk); + clk_enable(&pioB_clk); + clk_enable(&pioC_clk); + clk_enable(&pioD_clk); + + /* disable all other unused peripheral clocks */ + at91_periphclk_reset(); return 0; } -- cgit v1.2.3 From 55c20c0af7fe7d5d09af4addfafcfe3bdc500f5d Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 20 Jun 2006 19:31:39 +0100 Subject: [ARM] 3599/1: AT91RM9200 remove global variables Patch from Andrew Victor This patch removes some now unnecessary global variables - at91_master_clock, at91_serial_map, at91_console_port. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/clock.c | 5 +---- arch/arm/mach-at91rm9200/common.c | 11 ----------- include/asm-arm/arch-at91rm9200/board.h | 7 ------- 3 files changed, 1 insertion(+), 22 deletions(-) (limited to 'arch/arm/mach-at91rm9200/clock.c') diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c index 30042d2bac5f..fe71b834899b 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91rm9200/clock.c @@ -28,10 +28,10 @@ #include #include -#include /* for master clock global */ #include "generic.h" + /* * There's a lot more which can be done with clocks, including cpufreq * integration, slow clock mode support (for system suspend), letting @@ -722,9 +722,6 @@ int __init at91_clock_init(unsigned long main_clock) (unsigned) main_clock / 1000000, ((unsigned) main_clock % 1000000) / 1000); - /* FIXME get rid of master_clock global */ - at91_master_clock = mck.rate_hz; - #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS /* establish PCK0..PCK3 parentage */ for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) { diff --git a/arch/arm/mach-at91rm9200/common.c b/arch/arm/mach-at91rm9200/common.c index 40d29a73b5c5..1da68966e77f 100644 --- a/arch/arm/mach-at91rm9200/common.c +++ b/arch/arm/mach-at91rm9200/common.c @@ -108,14 +108,3 @@ void __init at91rm9200_map_io(void) iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); } - -unsigned long at91_master_clock; - -EXPORT_SYMBOL(at91_master_clock); - - -int at91_serial_map[AT91_NR_UART]; -int at91_console_port; - -EXPORT_SYMBOL(at91_serial_map); -EXPORT_SYMBOL(at91_console_port); diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91rm9200/board.h index 587948d56753..1fdd70b23809 100644 --- a/include/asm-arm/arch-at91rm9200/board.h +++ b/include/asm-arm/arch-at91rm9200/board.h @@ -31,13 +31,6 @@ #ifndef __ASM_ARCH_BOARD_H #define __ASM_ARCH_BOARD_H - /* Clocks */ -extern unsigned long at91_master_clock; - - /* Serial Port */ -extern int at91_serial_map[AT91_NR_UART]; -extern int at91_console_port; - #include #include #include -- cgit v1.2.3 From ea75ee9ab8835ece099589c729574aa8aa94c0a6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 20 Jun 2006 19:53:16 +0100 Subject: [ARM] Include asm/hardware.h not asm/arch/hardware.h Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/board-carmeva.c | 2 +- arch/arm/mach-at91rm9200/board-csb337.c | 2 +- arch/arm/mach-at91rm9200/board-csb637.c | 2 +- arch/arm/mach-at91rm9200/board-dk.c | 2 +- arch/arm/mach-at91rm9200/board-eb9200.c | 2 +- arch/arm/mach-at91rm9200/board-ek.c | 2 +- arch/arm/mach-at91rm9200/board-kafa.c | 2 +- arch/arm/mach-at91rm9200/board-kb9202.c | 2 +- arch/arm/mach-at91rm9200/clock.c | 2 +- arch/arm/mach-at91rm9200/common.c | 2 +- arch/arm/mach-at91rm9200/devices.c | 2 +- arch/arm/mach-at91rm9200/gpio.c | 2 +- arch/arm/mach-netx/fb.c | 2 +- arch/arm/mach-pnx4008/serial.c | 2 +- include/asm-arm/arch-at91rm9200/memory.h | 2 +- include/asm-arm/arch-at91rm9200/system.h | 2 +- include/asm-arm/arch-at91rm9200/timex.h | 2 +- include/asm-arm/arch-at91rm9200/uncompress.h | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) (limited to 'arch/arm/mach-at91rm9200/clock.c') diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c index 9183cb75ccd0..2c138b542ebe 100644 --- a/arch/arm/mach-at91rm9200/board-carmeva.c +++ b/arch/arm/mach-at91rm9200/board-carmeva.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c index 3b9de181ae32..e94645d77f7a 100644 --- a/arch/arm/mach-at91rm9200/board-csb337.c +++ b/arch/arm/mach-at91rm9200/board-csb337.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c index 2c4470d110da..67d5f7786cdb 100644 --- a/arch/arm/mach-at91rm9200/board-csb637.c +++ b/arch/arm/mach-at91rm9200/board-csb637.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c index eb02ca95be79..48d7390fa584 100644 --- a/arch/arm/mach-at91rm9200/board-dk.c +++ b/arch/arm/mach-at91rm9200/board-dk.c @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c index c7e4546a262d..a3e2df968a66 100644 --- a/arch/arm/mach-at91rm9200/board-eb9200.c +++ b/arch/arm/mach-at91rm9200/board-eb9200.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c index 4d7468e42679..72202ed830ad 100644 --- a/arch/arm/mach-at91rm9200/board-ek.c +++ b/arch/arm/mach-at91rm9200/board-ek.c @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91rm9200/board-kafa.c index 35d459fdfcf1..bf760c5e0c46 100644 --- a/arch/arm/mach-at91rm9200/board-kafa.c +++ b/arch/arm/mach-at91rm9200/board-kafa.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c index 6ba65ef48809..f06d2b54cc9a 100644 --- a/arch/arm/mach-at91rm9200/board-kb9202.c +++ b/arch/arm/mach-at91rm9200/board-kb9202.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c index fe71b834899b..edc2cc837ae6 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91rm9200/clock.c @@ -27,7 +27,7 @@ #include #include -#include +#include #include "generic.h" diff --git a/arch/arm/mach-at91rm9200/common.c b/arch/arm/mach-at91rm9200/common.c index 1da68966e77f..e836f8537a1d 100644 --- a/arch/arm/mach-at91rm9200/common.c +++ b/arch/arm/mach-at91rm9200/common.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include "generic.h" static struct map_desc at91rm9200_io_desc[] __initdata = { diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c index bf753e306a3a..1cf85d231baa 100644 --- a/arch/arm/mach-at91rm9200/devices.c +++ b/arch/arm/mach-at91rm9200/devices.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c index 3430ea054662..83c34747087b 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91rm9200/gpio.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include static const u32 pio_controller_offset[4] = { diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c index e169b683e4de..ef0ab6115c0b 100644 --- a/arch/arm/mach-netx/fb.c +++ b/arch/arm/mach-netx/fb.c @@ -24,7 +24,7 @@ #include #include -#include +#include struct clk {}; diff --git a/arch/arm/mach-pnx4008/serial.c b/arch/arm/mach-pnx4008/serial.c index 2e1e04cc048c..10322384e45d 100644 --- a/arch/arm/mach-pnx4008/serial.c +++ b/arch/arm/mach-pnx4008/serial.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include diff --git a/include/asm-arm/arch-at91rm9200/memory.h b/include/asm-arm/arch-at91rm9200/memory.h index 462f1f0ad67c..3c327c404373 100644 --- a/include/asm-arm/arch-at91rm9200/memory.h +++ b/include/asm-arm/arch-at91rm9200/memory.h @@ -21,7 +21,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#include +#include #define PHYS_OFFSET (AT91_SDRAM_BASE) diff --git a/include/asm-arm/arch-at91rm9200/system.h b/include/asm-arm/arch-at91rm9200/system.h index 945e66507a78..8a2ff472e4cf 100644 --- a/include/asm-arm/arch-at91rm9200/system.h +++ b/include/asm-arm/arch-at91rm9200/system.h @@ -21,7 +21,7 @@ #ifndef __ASM_ARCH_SYSTEM_H #define __ASM_ARCH_SYSTEM_H -#include +#include static inline void arch_idle(void) { diff --git a/include/asm-arm/arch-at91rm9200/timex.h b/include/asm-arm/arch-at91rm9200/timex.h index 3f112dd12587..88687cefe6eb 100644 --- a/include/asm-arm/arch-at91rm9200/timex.h +++ b/include/asm-arm/arch-at91rm9200/timex.h @@ -21,7 +21,7 @@ #ifndef __ASM_ARCH_TIMEX_H #define __ASM_ARCH_TIMEX_H -#include +#include #define CLOCK_TICK_RATE (AT91_SLOW_CLOCK) diff --git a/include/asm-arm/arch-at91rm9200/uncompress.h b/include/asm-arm/arch-at91rm9200/uncompress.h index 7b38497c24b5..ec7811ab0a52 100644 --- a/include/asm-arm/arch-at91rm9200/uncompress.h +++ b/include/asm-arm/arch-at91rm9200/uncompress.h @@ -21,7 +21,7 @@ #ifndef __ASM_ARCH_UNCOMPRESS_H #define __ASM_ARCH_UNCOMPRESS_H -#include +#include /* * The following code assumes the serial port has already been -- cgit v1.2.3