Commit 2eeaaa21 authored by Andrew Victor's avatar Andrew Victor Committed by Russell King

[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: default avatarAndrew Victor <andrew@sanpeople.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 72729910
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <asm/hardware.h> #include <asm/hardware.h>
#include "generic.h" #include "generic.h"
#include "clock.h"
static struct map_desc at91rm9200_io_desc[] __initdata = { static struct map_desc at91rm9200_io_desc[] __initdata = {
{ {
...@@ -102,9 +103,160 @@ static struct map_desc at91rm9200_io_desc[] __initdata = { ...@@ -102,9 +103,160 @@ static struct map_desc at91rm9200_io_desc[] __initdata = {
}, },
}; };
void __init at91rm9200_map_io(void) /* --------------------------------------------------------------------
* Clocks
* -------------------------------------------------------------------- */
/*
* The peripheral clocks.
*/
static struct clk udc_clk = {
.name = "udc_clk",
.pmc_mask = 1 << AT91RM9200_ID_UDP,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk ohci_clk = {
.name = "ohci_clk",
.pmc_mask = 1 << AT91RM9200_ID_UHP,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk ether_clk = {
.name = "ether_clk",
.pmc_mask = 1 << AT91RM9200_ID_EMAC,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk mmc_clk = {
.name = "mci_clk",
.pmc_mask = 1 << AT91RM9200_ID_MCI,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk twi_clk = {
.name = "twi_clk",
.pmc_mask = 1 << AT91RM9200_ID_TWI,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk usart0_clk = {
.name = "usart0_clk",
.pmc_mask = 1 << AT91RM9200_ID_US0,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk usart1_clk = {
.name = "usart1_clk",
.pmc_mask = 1 << AT91RM9200_ID_US1,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk usart2_clk = {
.name = "usart2_clk",
.pmc_mask = 1 << AT91RM9200_ID_US2,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk usart3_clk = {
.name = "usart3_clk",
.pmc_mask = 1 << AT91RM9200_ID_US3,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk spi_clk = {
.name = "spi_clk",
.pmc_mask = 1 << AT91RM9200_ID_SPI,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk pioA_clk = {
.name = "pioA_clk",
.pmc_mask = 1 << AT91RM9200_ID_PIOA,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk pioB_clk = {
.name = "pioB_clk",
.pmc_mask = 1 << AT91RM9200_ID_PIOB,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk pioC_clk = {
.name = "pioC_clk",
.pmc_mask = 1 << AT91RM9200_ID_PIOC,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk pioD_clk = {
.name = "pioD_clk",
.pmc_mask = 1 << AT91RM9200_ID_PIOD,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk *periph_clocks[] __initdata = {
&pioA_clk,
&pioB_clk,
&pioC_clk,
&pioD_clk,
&usart0_clk,
&usart1_clk,
&usart2_clk,
&usart3_clk,
&mmc_clk,
&udc_clk,
&twi_clk,
&spi_clk,
// ssc 0 .. ssc2
// tc0 .. tc5
&ohci_clk,
&ether_clk,
// irq0 .. irq6
};
/*
* The four programmable clocks.
* You must configure pin multiplexing to bring these signals out.
*/
static struct clk pck0 = {
.name = "pck0",
.pmc_mask = AT91_PMC_PCK0,
.type = CLK_TYPE_PROGRAMMABLE,
.id = 0,
};
static struct clk pck1 = {
.name = "pck1",
.pmc_mask = AT91_PMC_PCK1,
.type = CLK_TYPE_PROGRAMMABLE,
.id = 1,
};
static struct clk pck2 = {
.name = "pck2",
.pmc_mask = AT91_PMC_PCK2,
.type = CLK_TYPE_PROGRAMMABLE,
.id = 2,
};
static struct clk pck3 = {
.name = "pck3",
.pmc_mask = AT91_PMC_PCK3,
.type = CLK_TYPE_PROGRAMMABLE,
.id = 3,
};
static void __init at91rm9200_register_clocks(void)
{ {
int i;
for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
clk_register(periph_clocks[i]);
clk_register(&pck0);
clk_register(&pck1);
clk_register(&pck2);
clk_register(&pck3);
}
/* --------------------------------------------------------------------
* AT91RM9200 processor initialization
* -------------------------------------------------------------------- */
void __init at91rm9200_initialize(unsigned long main_clock)
{
/* Map peripherals */
iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
/* Init clock subsystem */
at91_clock_init(main_clock);
/* Register the processor-specific clocks */
at91rm9200_register_clocks();
} }
/* /*
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/hardware.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/gpio.h> #include <asm/arch/gpio.h>
...@@ -62,10 +61,8 @@ static struct at91_uart_config __initdata onearm_uart_config = { ...@@ -62,10 +61,8 @@ static struct at91_uart_config __initdata onearm_uart_config = {
static void __init onearm_map_io(void) static void __init onearm_map_io(void)
{ {
at91rm9200_map_io(); /* Initialize processor: 18.432 MHz crystal */
at91rm9200_initialize(18432000);
/* Initialize clocks: 18.432 MHz crystal */
at91_clock_init(18432000);
/* Setup the serial ports and console */ /* Setup the serial ports and console */
at91_init_serial(&onearm_uart_config); at91_init_serial(&onearm_uart_config);
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/hardware.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/gpio.h> #include <asm/arch/gpio.h>
...@@ -63,10 +62,8 @@ static struct at91_uart_config __initdata carmeva_uart_config = { ...@@ -63,10 +62,8 @@ static struct at91_uart_config __initdata carmeva_uart_config = {
static void __init carmeva_map_io(void) static void __init carmeva_map_io(void)
{ {
at91rm9200_map_io(); /* Initialize processor: 20.000 MHz crystal */
at91rm9200_initialize(20000000);
/* Initialize clocks: 20.000 MHz crystal */
at91_clock_init(20000000);
/* Setup the serial ports and console */ /* Setup the serial ports and console */
at91_init_serial(&carmeva_uart_config); at91_init_serial(&carmeva_uart_config);
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/hardware.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/gpio.h> #include <asm/arch/gpio.h>
...@@ -62,10 +61,8 @@ static struct at91_uart_config __initdata csb337_uart_config = { ...@@ -62,10 +61,8 @@ static struct at91_uart_config __initdata csb337_uart_config = {
static void __init csb337_map_io(void) static void __init csb337_map_io(void)
{ {
at91rm9200_map_io(); /* Initialize processor: 3.6864 MHz crystal */
at91rm9200_initialize(3686400);
/* Initialize clocks: 3.6864 MHz crystal */
at91_clock_init(3686400);
/* Setup the LEDs */ /* Setup the LEDs */
at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1); at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/hardware.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/gpio.h> #include <asm/arch/gpio.h>
...@@ -61,10 +60,8 @@ static struct at91_uart_config __initdata csb637_uart_config = { ...@@ -61,10 +60,8 @@ static struct at91_uart_config __initdata csb637_uart_config = {
static void __init csb637_map_io(void) static void __init csb637_map_io(void)
{ {
at91rm9200_map_io(); /* Initialize processor: 3.6864 MHz crystal */
at91rm9200_initialize(3686400);
/* Initialize clocks: 3.6864 MHz crystal */
at91_clock_init(3686400);
/* Setup the LEDs */ /* Setup the LEDs */
at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/hardware.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/gpio.h> #include <asm/arch/gpio.h>
...@@ -65,10 +64,8 @@ static struct at91_uart_config __initdata dk_uart_config = { ...@@ -65,10 +64,8 @@ static struct at91_uart_config __initdata dk_uart_config = {
static void __init dk_map_io(void) static void __init dk_map_io(void)
{ {
at91rm9200_map_io(); /* Initialize processor: 18.432 MHz crystal */
at91rm9200_initialize(18432000);
/* Initialize clocks: 18.432 MHz crystal */
at91_clock_init(18432000);
/* Setup the LEDs */ /* Setup the LEDs */
at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/hardware.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/gpio.h> #include <asm/arch/gpio.h>
...@@ -63,10 +62,8 @@ static struct at91_uart_config __initdata eb9200_uart_config = { ...@@ -63,10 +62,8 @@ static struct at91_uart_config __initdata eb9200_uart_config = {
static void __init eb9200_map_io(void) static void __init eb9200_map_io(void)
{ {
at91rm9200_map_io(); /* Initialize processor: 18.432 MHz crystal */
at91rm9200_initialize(18432000);
/* Initialize clocks: 18.432 MHz crystal */
at91_clock_init(18432000);
/* Setup the serial ports and console */ /* Setup the serial ports and console */
at91_init_serial(&eb9200_uart_config); at91_init_serial(&eb9200_uart_config);
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/hardware.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/gpio.h> #include <asm/arch/gpio.h>
...@@ -65,10 +64,8 @@ static struct at91_uart_config __initdata ek_uart_config = { ...@@ -65,10 +64,8 @@ static struct at91_uart_config __initdata ek_uart_config = {
static void __init ek_map_io(void) static void __init ek_map_io(void)
{ {
at91rm9200_map_io(); /* Initialize processor: 18.432 MHz crystal */
at91rm9200_initialize(18432000);
/* Initialize clocks: 18.432 MHz crystal */
at91_clock_init(18432000);
/* Setup the LEDs */ /* Setup the LEDs */
at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2); at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/hardware.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/gpio.h> #include <asm/arch/gpio.h>
...@@ -62,10 +61,8 @@ static struct at91_uart_config __initdata kafa_uart_config = { ...@@ -62,10 +61,8 @@ static struct at91_uart_config __initdata kafa_uart_config = {
static void __init kafa_map_io(void) static void __init kafa_map_io(void)
{ {
at91rm9200_map_io(); /* Initialize processor: 18.432 MHz crystal */
at91rm9200_initialize(18432000);
/* Initialize clocks: 18.432 MHz crystal */
at91_clock_init(18432000);
/* Set up the LEDs */ /* Set up the LEDs */
at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4); at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/hardware.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/gpio.h> #include <asm/arch/gpio.h>
...@@ -63,10 +62,8 @@ static struct at91_uart_config __initdata kb9202_uart_config = { ...@@ -63,10 +62,8 @@ static struct at91_uart_config __initdata kb9202_uart_config = {
static void __init kb9202_map_io(void) static void __init kb9202_map_io(void)
{ {
at91rm9200_map_io(); /* Initialize processor: 10 MHz crystal */
at91rm9200_initialize(10000000);
/* Initialize clocks: 10 MHz crystal */
at91_clock_init(10000000);
/* Set up the LEDs */ /* Set up the LEDs */
at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18); at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include <asm/hardware.h> #include <asm/hardware.h>
#include "generic.h" #include "clock.h"
/* /*
...@@ -38,22 +38,14 @@ ...@@ -38,22 +38,14 @@
* PLLB be used at other rates (on boards that don't need USB), etc. * PLLB be used at other rates (on boards that don't need USB), etc.
*/ */
struct clk { #define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY)
const char *name; /* unique clock name */ #define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE)
const char *function; /* function of the clock */ #define clk_is_peripheral(x) ((x)->type & CLK_TYPE_PERIPHERAL)
struct device *dev; /* device associated with function */
unsigned long rate_hz;
struct clk *parent; static LIST_HEAD(clocks);
u32 pmc_mask; static DEFINE_SPINLOCK(clk_lock);
void (*mode)(struct clk *, int);
unsigned id:2; /* PCK0..3, or 32k/main/a/b */
unsigned primary:1;
unsigned pll:1;
unsigned programmable:1;
u16 users;
};
static spinlock_t clk_lock;
static u32 at91_pllb_usb_init; static u32 at91_pllb_usb_init;
/* /*
...@@ -67,21 +59,20 @@ static struct clk clk32k = { ...@@ -67,21 +59,20 @@ static struct clk clk32k = {
.rate_hz = AT91_SLOW_CLOCK, .rate_hz = AT91_SLOW_CLOCK,
.users = 1, /* always on */ .users = 1, /* always on */
.id = 0, .id = 0,
.primary = 1, .type = CLK_TYPE_PRIMARY,
}; };
static struct clk main_clk = { static struct clk main_clk = {
.name = "main", .name = "main",
.pmc_mask = AT91_PMC_MOSCS, /* in PMC_SR */ .pmc_mask = AT91_PMC_MOSCS, /* in PMC_SR */
.id = 1, .id = 1,
.primary = 1, .type = CLK_TYPE_PRIMARY,
}; };
static struct clk plla = { static struct clk plla = {
.name = "plla", .name = "plla",
.parent = &main_clk, .parent = &main_clk,
.pmc_mask = AT91_PMC_LOCKA, /* in PMC_SR */ .pmc_mask = AT91_PMC_LOCKA, /* in PMC_SR */
.id = 2, .id = 2,
.primary = 1, .type = CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
.pll = 1,
}; };
static void pllb_mode(struct clk *clk, int is_on) static void pllb_mode(struct clk *clk, int is_on)
...@@ -94,6 +85,7 @@ static void pllb_mode(struct clk *clk, int is_on) ...@@ -94,6 +85,7 @@ static void pllb_mode(struct clk *clk, int is_on)
} else } else
value = 0; value = 0;
// REVISIT: Add work-around for AT91RM9200 Errata #26 ?
at91_sys_write(AT91_CKGR_PLLBR, value); at91_sys_write(AT91_CKGR_PLLBR, value);
do { do {
...@@ -107,8 +99,7 @@ static struct clk pllb = { ...@@ -107,8 +99,7 @@ static struct clk pllb = {
.pmc_mask = AT91_PMC_LOCKB, /* in PMC_SR */ .pmc_mask = AT91_PMC_LOCKB, /* in PMC_SR */
.mode = pllb_mode, .mode = pllb_mode,
.id = 3, .id = 3,
.primary = 1, .type = CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
.pll = 1,
}; };
static void pmc_sys_mode(struct clk *clk, int is_on) static void pmc_sys_mode(struct clk *clk, int is_on)
...@@ -133,41 +124,6 @@ static struct clk uhpck = { ...@@ -133,41 +124,6 @@ static struct clk uhpck = {
.mode = pmc_sys_mode, .mode = pmc_sys_mode,
}; };
#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
/*
* The four programmable clocks can be parented by any primary clock.
* You must configure pin multiplexing to bring these signals out.
*/
static struct clk pck0 = {
.name = "pck0",
.pmc_mask = AT91_PMC_PCK0,
.mode = pmc_sys_mode,
.programmable = 1,
.id = 0,
};
static struct clk pck1 = {
.name = "pck1",
.pmc_mask = AT91_PMC_PCK1,
.mode = pmc_sys_mode,
.programmable = 1,
.id = 1,
};
static struct clk pck2 = {
.name = "pck2",
.pmc_mask = AT91_PMC_PCK2,
.mode = pmc_sys_mode,
.programmable = 1,
.id = 2,
};
static struct clk pck3 = {
.name = "pck3",
.pmc_mask = AT91_PMC_PCK3,
.mode = pmc_sys_mode,
.programmable = 1,
.id = 3,
};
#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
/* /*
* The master clock is divided from the CPU clock (by 1-4). It's used for * 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,131 +143,21 @@ static void pmc_periph_mode(struct clk *clk, int is_on)
at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask); at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask);
} }
static struct clk udc_clk = { static struct clk __init *at91_css_to_clk(unsigned long css)
.name = "udc_clk", {
.parent = &mck, switch (css) {
.pmc_mask = 1 << AT91RM9200_ID_UDP, case AT91_PMC_CSS_SLOW:
.mode = pmc_periph_mode, return &clk32k;
}; case AT91_PMC_CSS_MAIN:
static struct clk ohci_clk = { return &main_clk;
.name = "ohci_clk", case AT91_PMC_CSS_PLLA:
.parent = &mck, return &plla;
.pmc_mask = 1 << AT91RM9200_ID_UHP, case AT91_PMC_CSS_PLLB:
.mode = pmc_periph_mode, return &pllb;
}; }
static struct clk ether_clk = {
.name = "ether_clk",
.parent = &mck,
.pmc_mask = 1 << AT91RM9200_ID_EMAC,
.mode = pmc_periph_mode,
};
static struct clk mmc_clk = {
.name = "mci_clk",
.parent = &mck,
.pmc_mask = 1 << AT91RM9200_ID_MCI,
.mode = pmc_periph_mode,
};
static struct clk twi_clk = {
.name = "twi_clk",
.parent = &mck,
.pmc_mask = 1 << AT91RM9200_ID_TWI,
.mode = pmc_periph_mode,
};
static struct clk usart0_clk = {
.name = "usart0_clk",
.parent = &mck,
.pmc_mask = 1 << AT91RM9200_ID_US0,
.mode = pmc_periph_mode,
};
static struct clk usart1_clk = {
.name = "usart1_clk",
.parent = &mck,
.pmc_mask = 1 << AT91RM9200_ID_US1,
.mode = pmc_periph_mode,
};
static struct clk usart2_clk = {
.name = "usart2_clk",
.parent = &mck,
.pmc_mask = 1 << AT91RM9200_ID_US2,
.mode = pmc_periph_mode,
};
static struct clk usart3_clk = {
.name = "usart3_clk",
.parent = &mck,
.pmc_mask = 1 << AT91RM9200_ID_US3,
.mode = pmc_periph_mode,
};
static struct clk spi_clk = {
.name = "spi0_clk",
.parent = &mck,
.pmc_mask = 1 << AT91RM9200_ID_SPI,
.mode = pmc_periph_mode,
};
static struct clk pioA_clk = {
.name = "pioA_clk",
.parent = &mck,
.pmc_mask = 1 << AT91RM9200_ID_PIOA,
.mode = pmc_periph_mode,
};
static struct clk pioB_clk = {
.name = "pioB_clk",
.parent = &mck,
.pmc_mask = 1 << AT91RM9200_ID_PIOB,
.mode = pmc_periph_mode,
};
static struct clk pioC_clk = {
.name = "pioC_clk",
.parent = &mck,
.pmc_mask = 1 << AT91RM9200_ID_PIOC,
.mode = pmc_periph_mode,
};
static struct clk pioD_clk = {
.name = "pioD_clk",
.parent = &mck,
.pmc_mask = 1 << AT91RM9200_ID_PIOD,
.mode = pmc_periph_mode,
};
static struct clk *const clock_list[] = {
/* four primary clocks -- MUST BE FIRST! */
&clk32k,
&main_clk,
&plla,
&pllb,
/* PLLB children (USB) */
&udpck,
&uhpck,
#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
/* programmable clocks */
&pck0,
&pck1,
&pck2,
&pck3,
#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
/* MCK and peripherals */
&mck,
&usart0_clk,
&usart1_clk,
&usart2_clk,
&usart3_clk,
&mmc_clk,
&udc_clk,
&twi_clk,
&spi_clk,
&pioA_clk,
&pioB_clk,
&pioC_clk,
&pioD_clk,
// ssc0..ssc2
// tc0..tc5
// irq0..irq6
&ohci_clk,
&ether_clk,
};
return NULL;
}
/* /*
* Associate a particular clock with a function (eg, "uart") and device. * 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,14 +175,12 @@ void __init at91_clock_associate(const char *id, struct device *dev, const char
clk->dev = dev; clk->dev = dev;
} }
/* clocks are all static for now; no refcounting necessary */ /* clocks cannot be de-registered no refcounting necessary */
struct clk *clk_get(struct device *dev, const char *id) struct clk *clk_get(struct device *dev, const char *id)
{ {
int i; struct clk *clk;
for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
struct clk *clk = clock_list[i];
list_for_each_entry(clk, &clocks, node) {
if (strcmp(id, clk->name) == 0) if (strcmp(id, clk->name) == 0)
return clk; return clk;
if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0) 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,7 +268,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
unsigned prescale; unsigned prescale;
unsigned long actual; unsigned long actual;
if (!clk->programmable) if (!clk_is_programmable(clk))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&clk_lock, flags); spin_lock_irqsave(&clk_lock, flags);
...@@ -446,7 +290,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) ...@@ -446,7 +290,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
unsigned prescale; unsigned prescale;
unsigned long actual; unsigned long actual;
if (!clk->programmable) if (!clk_is_programmable(clk))
return -EINVAL; return -EINVAL;
if (clk->users) if (clk->users)
return -EBUSY; return -EBUSY;
...@@ -484,7 +328,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) ...@@ -484,7 +328,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
if (clk->users) if (clk->users)
return -EBUSY; return -EBUSY;
if (!parent->primary || !clk->programmable) if (!clk_is_primary(parent) || !clk_is_programmable(clk))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&clk_lock, flags); spin_lock_irqsave(&clk_lock, flags);
...@@ -497,6 +341,18 @@ int clk_set_parent(struct clk *clk, struct clk *parent) ...@@ -497,6 +341,18 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
} }
EXPORT_SYMBOL(clk_set_parent); EXPORT_SYMBOL(clk_set_parent);
/* establish PCK0..PCK3 parentage and rate */
static void init_programmable_clock(struct clk *clk)
{
struct clk *parent;
u32 pckr;
pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
parent = at91_css_to_clk(pckr & AT91_PMC_CSS);
clk->parent = parent;
clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
}
#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ #endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
...@@ -506,6 +362,7 @@ EXPORT_SYMBOL(clk_set_parent); ...@@ -506,6 +362,7 @@ EXPORT_SYMBOL(clk_set_parent);
static int at91_clk_show(struct seq_file *s, void *unused) static int at91_clk_show(struct seq_file *s, void *unused)
{ {
u32 scsr, pcsr, sr; u32 scsr, pcsr, sr;
struct clk *clk;
unsigned i; unsigned i;
seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR)); 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,9 +380,8 @@ static int at91_clk_show(struct seq_file *s, void *unused)
seq_printf(s, "\n"); seq_printf(s, "\n");
for (i = 0; i < ARRAY_SIZE(clock_list); i++) { list_for_each_entry(clk, &clocks, node) {
char *state; char *state;
struct clk *clk = clock_list[i];
if (clk->mode == pmc_sys_mode) if (clk->mode == pmc_sys_mode)
state = (scsr & clk->pmc_mask) ? "on" : "off"; state = (scsr & clk->pmc_mask) ? "on" : "off";
...@@ -568,6 +424,28 @@ postcore_initcall(at91_clk_debugfs_init); ...@@ -568,6 +424,28 @@ postcore_initcall(at91_clk_debugfs_init);
#endif #endif
/*------------------------------------------------------------------------*/
/* Register a new clock */
int __init clk_register(struct clk *clk)
{
if (clk_is_peripheral(clk)) {
clk->parent = &mck;
clk->mode = pmc_periph_mode;
list_add_tail(&clk->node, &clocks);
}
#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
else if (clk_is_programmable(clk)) {
clk->mode = pmc_sys_mode;
init_programmable_clock(clk);
list_add_tail(&clk->node, &clocks);
}
#endif
return 0;
}
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg) static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg)
...@@ -640,20 +518,17 @@ static unsigned __init at91_pll_calc(unsigned main_freq, unsigned out_freq) ...@@ -640,20 +518,17 @@ static unsigned __init at91_pll_calc(unsigned main_freq, unsigned out_freq)
return 0; return 0;
} }
/* /*
* Several unused clocks may be active. Turn them off. * Several unused clocks may be active. Turn them off.
*/ */
static void at91_periphclk_reset(void) static void __init at91_periphclk_reset(void)
{ {
unsigned long reg; unsigned long reg;
int i; struct clk *clk;
reg = at91_sys_read(AT91_PMC_PCSR); reg = at91_sys_read(AT91_PMC_PCSR);
for (i = 0; i < ARRAY_SIZE(clock_list); i++) { list_for_each_entry(clk, &clocks, node) {
struct clk *clk = clock_list[i];
if (clk->mode != pmc_periph_mode) if (clk->mode != pmc_periph_mode)
continue; continue;
...@@ -664,11 +539,25 @@ static void at91_periphclk_reset(void) ...@@ -664,11 +539,25 @@ static void at91_periphclk_reset(void)
at91_sys_write(AT91_PMC_PCDR, reg); at91_sys_write(AT91_PMC_PCDR, reg);
} }
static struct clk *const standard_pmc_clocks[] __initdata = {
/* four primary clocks */
&clk32k,
&main_clk,
&plla,
&pllb,
/* PLLB children (USB) */
&udpck,
&uhpck,
/* MCK */
&mck
};
int __init at91_clock_init(unsigned long main_clock) int __init at91_clock_init(unsigned long main_clock)
{ {
unsigned tmp, freq, mckr; unsigned tmp, freq, mckr;
int i;
spin_lock_init(&clk_lock);
/* /*
* When the bootloader initialized the main oscillator correctly, * When the bootloader initialized the main oscillator correctly,
...@@ -709,11 +598,15 @@ int __init at91_clock_init(unsigned long main_clock) ...@@ -709,11 +598,15 @@ int __init at91_clock_init(unsigned long main_clock)
* For now, assume this parentage won't change. * For now, assume this parentage won't change.
*/ */
mckr = at91_sys_read(AT91_PMC_MCKR); mckr = at91_sys_read(AT91_PMC_MCKR);
mck.parent = clock_list[mckr & AT91_PMC_CSS]; mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
freq = mck.parent->rate_hz; freq = mck.parent->rate_hz;
freq /= (1 << ((mckr >> 2) & 3)); /* prescale */ freq /= (1 << ((mckr >> 2) & 3)); /* prescale */
mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */ mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */
/* Register the PMC's standard clocks */
for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
list_add_tail(&standard_pmc_clocks[i]->node, &clocks);
/* MCK and CPU clock are "always on" */ /* MCK and CPU clock are "always on" */
clk_enable(&mck); clk_enable(&mck);
...@@ -722,35 +615,8 @@ int __init at91_clock_init(unsigned long main_clock) ...@@ -722,35 +615,8 @@ int __init at91_clock_init(unsigned long main_clock)
(unsigned) main_clock / 1000000, (unsigned) main_clock / 1000000,
((unsigned) main_clock % 1000000) / 1000); ((unsigned) main_clock % 1000000) / 1000);
#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
/* establish PCK0..PCK3 parentage */
for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) {
struct clk *clk = clock_list[tmp], *parent;
u32 pckr;
if (!clk->programmable)
continue;
pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
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 all programmable clocks */ /* disable all programmable clocks */
at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3);
#endif
/* 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 */ /* disable all other unused peripheral clocks */
at91_periphclk_reset(); at91_periphclk_reset();
......
/*
* linux/arch/arm/mach-at91rm9200/clock.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#define CLK_TYPE_PRIMARY 0x1
#define CLK_TYPE_PLL 0x2
#define CLK_TYPE_PROGRAMMABLE 0x4
#define CLK_TYPE_PERIPHERAL 0x8
struct clk {
struct list_head node;
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;
void (*mode)(struct clk *, int);
unsigned id:2; /* PCK0..3, or 32k/main/a/b */
unsigned type; /* clock type */
u16 users;
};
extern int __init clk_register(struct clk *clk);
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
/* Processors */
extern void __init at91rm9200_initialize(unsigned long main_clock);
/* Interrupts */ /* Interrupts */
extern void __init at91rm9200_init_irq(unsigned int priority[]); extern void __init at91rm9200_init_irq(unsigned int priority[]);
extern void __init at91_aic_init(unsigned int priority[]); extern void __init at91_aic_init(unsigned int priority[]);
...@@ -17,9 +20,6 @@ extern void __init at91_gpio_irq_setup(unsigned banks); ...@@ -17,9 +20,6 @@ extern void __init at91_gpio_irq_setup(unsigned banks);
struct sys_timer; struct sys_timer;
extern struct sys_timer at91rm9200_timer; extern struct sys_timer at91rm9200_timer;
/* Memory Map */
extern void __init at91rm9200_map_io(void);
/* Clocks */ /* Clocks */
extern int __init at91_clock_init(unsigned long main_clock); extern int __init at91_clock_init(unsigned long main_clock);
struct device; struct device;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment