diff options
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/52xx/Kconfig | 41 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/efika.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/lite5200.c | 28 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/lite5200_pm.c | 9 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/mpc5200_simple.c | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/mpc52xx_common.c | 117 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/mpc52xx_pci.c | 10 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/mpc52xx_pic.c | 16 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/mpc52xx_pm.c | 9 |
9 files changed, 170 insertions, 69 deletions
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig index 733a806..515f244 100644 --- a/arch/powerpc/platforms/52xx/Kconfig +++ b/arch/powerpc/platforms/52xx/Kconfig @@ -1,31 +1,14 @@ config PPC_MPC52xx - bool + bool "52xx-based boards" + depends on PPC_MULTIPLATFORM && PPC32 select FSL_SOC select PPC_CLOCK - default n - -config PPC_MPC5200 - bool - select PPC_MPC52xx - default n - -config PPC_MPC5200_BUGFIX - bool "MPC5200 (L25R) bugfix support" - depends on PPC_MPC5200 - default n - help - Enable workarounds for original MPC5200 errata. This is not required - for MPC5200B based boards. - - It is safe to say 'Y' here config PPC_MPC5200_SIMPLE bool "Generic support for simple MPC5200 based boards" - depends on PPC_MULTIPLATFORM && PPC32 - select PPC_MPC5200 + depends on PPC_MPC52xx select DEFAULT_UIMAGE select WANT_DEVICE_TREE - default n help This option enables support for a simple MPC52xx based boards which do not need a custom platform specific setup. Such boards are @@ -43,17 +26,23 @@ config PPC_MPC5200_SIMPLE config PPC_EFIKA bool "bPlan Efika 5k2. MPC5200B based computer" - depends on PPC_MULTIPLATFORM && PPC32 + depends on PPC_MPC52xx select PPC_RTAS select RTAS_PROC - select PPC_MPC52xx select PPC_NATIVE - default n config PPC_LITE5200 bool "Freescale Lite5200 Eval Board" - depends on PPC_MULTIPLATFORM && PPC32 - select PPC_MPC5200 + depends on PPC_MPC52xx select DEFAULT_UIMAGE select WANT_DEVICE_TREE - default n + +config PPC_MPC5200_BUGFIX + bool "MPC5200 (L25R) bugfix support" + depends on PPC_MPC52xx + help + Enable workarounds for original MPC5200 errata. This is not required + for MPC5200B based boards. + + It is safe to say 'Y' here + diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index a0da70c..a2068fa 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c @@ -180,6 +180,9 @@ static void __init efika_setup_arch(void) { rtas_initialize(); + /* Map important registers from the internal memory map */ + mpc52xx_map_common_devices(); + efika_pcisetup(); #ifdef CONFIG_PM diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c index 5a8d190..956f459 100644 --- a/arch/powerpc/platforms/52xx/lite5200.c +++ b/arch/powerpc/platforms/52xx/lite5200.c @@ -32,6 +32,19 @@ * */ +/* mpc5200 device tree match tables */ +static struct of_device_id mpc5200_cdm_ids[] __initdata = { + { .compatible = "fsl,mpc5200-cdm", }, + { .compatible = "mpc5200-cdm", }, + {} +}; + +static struct of_device_id mpc5200_gpio_ids[] __initdata = { + { .compatible = "fsl,mpc5200-gpio", }, + { .compatible = "mpc5200-gpio", }, + {} +}; + /* * Fix clock configuration. * @@ -44,9 +57,8 @@ lite5200_fix_clock_config(void) { struct device_node *np; struct mpc52xx_cdm __iomem *cdm; - /* Map zones */ - np = of_find_compatible_node(NULL, NULL, "mpc5200-cdm"); + np = of_find_matching_node(NULL, mpc5200_cdm_ids); cdm = of_iomap(np, 0); of_node_put(np); if (!cdm) { @@ -81,7 +93,7 @@ lite5200_fix_port_config(void) struct mpc52xx_gpio __iomem *gpio; u32 port_config; - np = of_find_compatible_node(NULL, NULL, "mpc5200-gpio"); + np = of_find_matching_node(NULL, mpc5200_gpio_ids); gpio = of_iomap(np, 0); of_node_put(np); if (!gpio) { @@ -140,15 +152,15 @@ static void __init lite5200_setup_arch(void) if (ppc_md.progress) ppc_md.progress("lite5200_setup_arch()", 0); - /* Fix things that firmware should have done. */ - lite5200_fix_clock_config(); - lite5200_fix_port_config(); + /* Map important registers from the internal memory map */ + mpc52xx_map_common_devices(); /* Some mpc5200 & mpc5200b related configuration */ mpc5200_setup_xlb_arbiter(); - /* Map wdt for mpc52xx_restart() */ - mpc52xx_map_wdt(); + /* Fix things that firmware should have done. */ + lite5200_fix_clock_config(); + lite5200_fix_port_config(); #ifdef CONFIG_PM mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare; diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c index c3ada1e..c0f13e8 100644 --- a/arch/powerpc/platforms/52xx/lite5200_pm.c +++ b/arch/powerpc/platforms/52xx/lite5200_pm.c @@ -43,6 +43,13 @@ static int lite5200_pm_set_target(suspend_state_t state) static int lite5200_pm_prepare(void) { struct device_node *np; + const struct of_device_id immr_ids[] = { + { .compatible = "fsl,mpc5200-immr", }, + { .compatible = "fsl,mpc5200b-immr", }, + { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */ + { .type = "builtin", .compatible = "mpc5200", }, /* efika */ + {} + }; /* deep sleep? let mpc52xx code handle that */ if (lite5200_pm_target_state == PM_SUSPEND_STANDBY) @@ -52,7 +59,7 @@ static int lite5200_pm_prepare(void) return -EINVAL; /* map registers */ - np = of_find_compatible_node(NULL, NULL, "mpc5200"); + np = of_find_matching_node(NULL, immr_ids); mbar = of_iomap(np, 0); of_node_put(np); if (!mbar) { diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c index 754aa93..c48b82b 100644 --- a/arch/powerpc/platforms/52xx/mpc5200_simple.c +++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c @@ -39,12 +39,12 @@ static void __init mpc5200_simple_setup_arch(void) if (ppc_md.progress) ppc_md.progress("mpc5200_simple_setup_arch()", 0); + /* Map important registers from the internal memory map */ + mpc52xx_map_common_devices(); + /* Some mpc5200 & mpc5200b related configuration */ mpc5200_setup_xlb_arbiter(); - /* Map wdt for mpc52xx_restart() */ - mpc52xx_map_wdt(); - mpc52xx_setup_pci(); } diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index 6695593..9aa4425 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -13,18 +13,38 @@ #undef DEBUG #include <linux/kernel.h> +#include <linux/spinlock.h> #include <linux/of_platform.h> #include <asm/io.h> #include <asm/prom.h> #include <asm/mpc52xx.h> +/* MPC5200 device tree match tables */ +static struct of_device_id mpc52xx_xlb_ids[] __initdata = { + { .compatible = "fsl,mpc5200-xlb", }, + { .compatible = "mpc5200-xlb", }, + {} +}; +static struct of_device_id mpc52xx_bus_ids[] __initdata = { + { .compatible = "fsl,mpc5200-immr", }, + { .compatible = "fsl,mpc5200b-immr", }, + { .compatible = "fsl,lpb", }, + + /* depreciated matches; shouldn't be used in new device trees */ + { .type = "builtin", .compatible = "mpc5200", }, /* efika */ + { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */ + {} +}; + /* * This variable is mapped in mpc52xx_map_wdt() and used in mpc52xx_restart(). * Permanent mapping is required because mpc52xx_restart() can be called * from interrupt context while node mapping (which calls ioremap()) * cannot be used at such point. */ -static volatile struct mpc52xx_gpt *mpc52xx_wdt = NULL; +static spinlock_t mpc52xx_lock = SPIN_LOCK_UNLOCKED; +static struct mpc52xx_gpt __iomem *mpc52xx_wdt; +static struct mpc52xx_cdm __iomem *mpc52xx_cdm; /** * mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device @@ -65,7 +85,7 @@ mpc5200_setup_xlb_arbiter(void) struct device_node *np; struct mpc52xx_xlb __iomem *xlb; - np = of_find_compatible_node(NULL, NULL, "mpc5200-xlb"); + np = of_find_matching_node(NULL, mpc52xx_xlb_ids); xlb = of_iomap(np, 0); of_node_put(np); if (!xlb) { @@ -88,16 +108,11 @@ mpc5200_setup_xlb_arbiter(void) iounmap(xlb); } -static struct of_device_id mpc52xx_bus_ids[] __initdata= { - { .compatible = "fsl,mpc5200-immr", }, - { .compatible = "fsl,lpb", }, - - /* depreciated matches; shouldn't be used in new device trees */ - { .type = "builtin", .compatible = "mpc5200", }, /* efika */ - { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */ - {}, -}; - +/** + * mpc52xx_declare_of_platform_devices: register internal devices and children + * of the localplus bus to the of_platform + * bus. + */ void __init mpc52xx_declare_of_platform_devices(void) { @@ -107,35 +122,87 @@ mpc52xx_declare_of_platform_devices(void) "Error while probing of_platform bus\n"); } +/* + * match tables used by mpc52xx_map_common_devices() + */ +static struct of_device_id mpc52xx_gpt_ids[] __initdata = { + { .compatible = "fsl,mpc5200-gpt", }, + { .compatible = "mpc5200-gpt", }, /* old */ + {} +}; +static struct of_device_id mpc52xx_cdm_ids[] __initdata = { + { .compatible = "fsl,mpc5200-cdm", }, + { .compatible = "mpc5200-cdm", }, /* old */ + {} +}; + +/** + * mpc52xx_map_common_devices: iomap devices required by common code + */ void __init -mpc52xx_map_wdt(void) +mpc52xx_map_common_devices(void) { - const void *has_wdt; struct device_node *np; /* mpc52xx_wdt is mapped here and used in mpc52xx_restart, * possibly from a interrupt context. wdt is only implement * on a gpt0, so check has-wdt property before mapping. */ - for_each_compatible_node(np, NULL, "fsl,mpc5200-gpt") { - has_wdt = of_get_property(np, "fsl,has-wdt", NULL); - if (has_wdt) { + for_each_matching_node(np, mpc52xx_gpt_ids) { + if (of_get_property(np, "fsl,has-wdt", NULL) || + of_get_property(np, "has-wdt", NULL)) { mpc52xx_wdt = of_iomap(np, 0); of_node_put(np); - return; + break; } } - for_each_compatible_node(np, NULL, "mpc5200-gpt") { - has_wdt = of_get_property(np, "has-wdt", NULL); - if (has_wdt) { - mpc52xx_wdt = of_iomap(np, 0); - of_node_put(np); - return; - } + /* Clock Distribution Module, used by PSC clock setting function */ + np = of_find_matching_node(NULL, mpc52xx_cdm_ids); + mpc52xx_cdm = of_iomap(np, 0); + of_node_put(np); +} + +/** + * mpc52xx_set_psc_clkdiv: Set clock divider in the CDM for PSC ports + * + * @psc_id: id of psc port; must be 1,2,3 or 6 + * @clkdiv: clock divider value to put into CDM PSC register. + */ +int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv) +{ + unsigned long flags; + u16 __iomem *reg; + u32 val; + u32 mask; + u32 mclken_div; + + if (!mpc52xx_cdm) + return -ENODEV; + + mclken_div = 0x8000 | (clkdiv & 0x1FF); + switch (psc_id) { + case 1: reg = &mpc52xx_cdm->mclken_div_psc1; mask = 0x20; break; + case 2: reg = &mpc52xx_cdm->mclken_div_psc2; mask = 0x40; break; + case 3: reg = &mpc52xx_cdm->mclken_div_psc3; mask = 0x80; break; + case 6: reg = &mpc52xx_cdm->mclken_div_psc6; mask = 0x10; break; + default: + return -ENODEV; } + + /* Set the rate and enable the clock */ + spin_lock_irqsave(&mpc52xx_lock, flags); + out_be16(reg, mclken_div); + val = in_be32(&mpc52xx_cdm->clk_enables); + out_be32(&mpc52xx_cdm->clk_enables, val | mask); + spin_unlock_irqrestore(&mpc52xx_lock, flags); + + return 0; } +/** + * mpc52xx_restart: ppc_md->restart hook for mpc5200 using the watchdog timer + */ void mpc52xx_restart(char *cmd) { diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c index 4b79398..e3428dd 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c @@ -99,6 +99,12 @@ struct mpc52xx_pci { u8 reserved6[4]; /* PCI + 0xFC */ }; +/* MPC5200 device tree match tables */ +const struct of_device_id mpc52xx_pci_ids[] __initdata = { + { .type = "pci", .compatible = "fsl,mpc5200-pci", }, + { .type = "pci", .compatible = "mpc5200-pci", }, + {} +}; /* ======================================================================== */ /* PCI configuration acess */ @@ -411,9 +417,7 @@ void __init mpc52xx_setup_pci(void) { struct device_node *pci; - pci = of_find_compatible_node(NULL, NULL, "fsl,mpc5200-pci"); - if (!pci) - pci = of_find_compatible_node(NULL, NULL, "mpc5200-pci"); + pci = of_find_matching_node(NULL, mpc52xx_pci_ids); if (!pci) return; diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 07e8987..d0dead8 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -29,6 +29,18 @@ * */ +/* MPC5200 device tree match tables */ +static struct of_device_id mpc52xx_pic_ids[] __initdata = { + { .compatible = "fsl,mpc5200-pic", }, + { .compatible = "mpc5200-pic", }, + {} +}; +static struct of_device_id mpc52xx_sdma_ids[] __initdata = { + { .compatible = "fsl,mpc5200-bestcomm", }, + { .compatible = "mpc5200-bestcomm", }, + {} +}; + static struct mpc52xx_intr __iomem *intr; static struct mpc52xx_sdma __iomem *sdma; static struct irq_host *mpc52xx_irqhost = NULL; @@ -367,13 +379,13 @@ void __init mpc52xx_init_irq(void) struct device_node *np; /* Remap the necessary zones */ - picnode = of_find_compatible_node(NULL, NULL, "mpc5200-pic"); + picnode = of_find_matching_node(NULL, mpc52xx_pic_ids); intr = of_iomap(picnode, 0); if (!intr) panic(__FILE__ ": find_and_map failed on 'mpc5200-pic'. " "Check node !"); - np = of_find_compatible_node(NULL, NULL, "mpc5200-bestcomm"); + np = of_find_matching_node(NULL, mpc52xx_sdma_ids); sdma = of_iomap(np, 0); of_node_put(np); if (!sdma) diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c index 52f0277..c72d330 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c @@ -60,9 +60,16 @@ int mpc52xx_set_wakeup_gpio(u8 pin, u8 level) int mpc52xx_pm_prepare(void) { struct device_node *np; + const struct of_device_id immr_ids[] = { + { .compatible = "fsl,mpc5200-immr", }, + { .compatible = "fsl,mpc5200b-immr", }, + { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */ + { .type = "builtin", .compatible = "mpc5200", }, /* efika */ + {} + }; /* map the whole register space */ - np = of_find_compatible_node(NULL, NULL, "mpc5200"); + np = of_find_matching_node(NULL, immr_ids); mbar = of_iomap(np, 0); of_node_put(np); if (!mbar) { |