ARM: at91: add pmc DT support

Specified the main Oscillator via clock binding.
This will allow to do not hardcode it anymore in the DT board at 12MHz.

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Acked-by: Rob Herring <rob.herring@calxeda.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
This commit is contained in:
Jean-Christophe PLAGNIOL-VILLARD 2012-03-02 20:44:23 +08:00
parent 2b11ea5bf2
commit eb5e76ffd4
10 changed files with 112 additions and 7 deletions

View File

@ -0,0 +1,11 @@
* Power Management Controller (PMC)
Required properties:
- compatible: Should be "atmel,at91rm9200-pmc"
- reg: Should contain PMC registers location and length
Examples:
pmc: pmc@fffffc00 {
compatible = "atmel,at91rm9200-pmc";
reg = <0xfffffc00 0x100>;
};

View File

@ -59,6 +59,11 @@
reg = <0xfffff000 0x200>;
};
pmc: pmc@fffffc00 {
compatible = "atmel,at91rm9200-pmc";
reg = <0xfffffc00 0x100>;
};
pit: timer@fffffd30 {
compatible = "atmel,at91sam9260-pit";
reg = <0xfffffd30 0xf>;

View File

@ -60,6 +60,11 @@
reg = <0xfffff000 0x200>;
};
pmc: pmc@fffffc00 {
compatible = "atmel,at91rm9200-pmc";
reg = <0xfffffc00 0x100>;
};
pit: timer@fffffd30 {
compatible = "atmel,at91sam9260-pit";
reg = <0xfffffd30 0xf>;

View File

@ -21,6 +21,17 @@
reg = <0x70000000 0x4000000>;
};
clocks {
#address-cells = <1>;
#size-cells = <1>;
ranges;
main_clock: clock@0 {
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
};
ahb {
apb {
dbgu: serial@ffffee00 {

View File

@ -58,6 +58,11 @@
reg = <0xfffff000 0x200>;
};
pmc: pmc@fffffc00 {
compatible = "atmel,at91rm9200-pmc";
reg = <0xfffffc00 0x100>;
};
pit: timer@fffffe30 {
compatible = "atmel,at91sam9260-pit";
reg = <0xfffffe30 0xf>;

View File

@ -12,6 +12,17 @@
reg = <0x20000000 0x8000000>;
};
clocks {
#address-cells = <1>;
#size-cells = <1>;
ranges;
main_clock: clock@0 {
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
};
ahb {
nand0: nand@40000000 {
nand-bus-width = <8>;

View File

@ -20,6 +20,17 @@
reg = <0x20000000 0x4000000>;
};
clocks {
#address-cells = <1>;
#size-cells = <1>;
ranges;
main_clock: clock@0 {
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
};
ahb {
apb {
dbgu: serial@fffff200 {

View File

@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <mach/hardware.h>
#include <mach/at91_pmc.h>
@ -671,16 +672,12 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock)
uhpck.rate_hz /= 1 + ((at91_pmc_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8);
}
int __init at91_clock_init(unsigned long main_clock)
static int __init at91_pmc_init(unsigned long main_clock)
{
unsigned tmp, freq, mckr;
int i;
int pll_overclock = false;
at91_pmc_base = ioremap(AT91_PMC, 256);
if (!at91_pmc_base)
panic("Impossible to ioremap AT91_PMC 0x%x\n", AT91_PMC);
/*
* When the bootloader initialized the main oscillator correctly,
* there's no problem using the cycle counter. But if it didn't,
@ -802,6 +799,55 @@ int __init at91_clock_init(unsigned long main_clock)
return 0;
}
#if defined(CONFIG_OF)
static struct of_device_id pmc_ids[] = {
{ .compatible = "atmel,at91rm9200-pmc" },
{ /*sentinel*/ }
};
static struct of_device_id osc_ids[] = {
{ .compatible = "atmel,osc" },
{ /*sentinel*/ }
};
int __init at91_dt_clock_init(void)
{
struct device_node *np;
u32 main_clock = 0;
np = of_find_matching_node(NULL, pmc_ids);
if (!np)
panic("unable to find compatible pmc node in dtb\n");
at91_pmc_base = of_iomap(np, 0);
if (!at91_pmc_base)
panic("unable to map pmc cpu registers\n");
of_node_put(np);
/* retrieve the freqency of fixed clocks from device tree */
np = of_find_matching_node(NULL, osc_ids);
if (np) {
u32 rate;
if (!of_property_read_u32(np, "clock-frequency", &rate))
main_clock = rate;
}
of_node_put(np);
return at91_pmc_init(main_clock);
}
#endif
int __init at91_clock_init(unsigned long main_clock)
{
at91_pmc_base = ioremap(AT91_PMC, 256);
if (!at91_pmc_base)
panic("Impossible to ioremap AT91_PMC 0x%x\n", AT91_PMC);
return at91_pmc_init(main_clock);
}
/*
* Several unused clocks may be active. Turn them off.
*/

View File

@ -53,6 +53,7 @@ extern void __init at91sam9rl_set_console_clock(int id);
extern void __init at91sam9g45_set_console_clock(int id);
#ifdef CONFIG_AT91_PMC_UNIT
extern int __init at91_clock_init(unsigned long main_clock);
extern int __init at91_dt_clock_init(void);
#else
static int inline at91_clock_init(unsigned long main_clock) { return 0; }
#endif

View File

@ -292,9 +292,8 @@ void __init at91_dt_initialize(void)
/* temporary until have the ramc binding*/
at91_boot_soc.ioremap_registers();
/* temporary until have the pmc binding */
/* Init clock subsystem */
at91_clock_init(12000000);
at91_dt_clock_init();
/* Register the processor-specific clocks */
at91_boot_soc.register_clocks();