diff options
Diffstat (limited to 'arch/arm/mach-at91')
-rw-r--r-- | arch/arm/mach-at91/Makefile | 34 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91rm9200.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9.c | 91 | ||||
-rw-r--r-- | arch/arm/mach-at91/generic.h | 8 | ||||
-rw-r--r-- | arch/arm/mach-at91/pm.c | 201 | ||||
-rw-r--r-- | arch/arm/mach-at91/pm.h | 24 | ||||
-rw-r--r-- | arch/arm/mach-at91/pm_data-offsets.c | 13 | ||||
-rw-r--r-- | arch/arm/mach-at91/pm_suspend.S | 31 | ||||
-rw-r--r-- | arch/arm/mach-at91/sama5.c | 52 | ||||
-rw-r--r-- | arch/arm/mach-at91/soc.c | 142 | ||||
-rw-r--r-- | arch/arm/mach-at91/soc.h | 91 |
11 files changed, 176 insertions, 526 deletions
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index c5bbf8bb8c0f..cfd8f60a9268 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -1,7 +1,6 @@ # # Makefile for the linux kernel. # -obj-y := soc.o # CPU-specific support obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o @@ -18,3 +17,36 @@ endif ifeq ($(CONFIG_PM_DEBUG),y) CFLAGS_pm.o += -DDEBUG endif + +# Default sed regexp - multiline due to syntax constraints +define sed-y + "/^->/{s:->#\(.*\):/* \1 */:; \ + s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ + s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ + s:->::; p;}" +endef + +# Use filechk to avoid rebuilds when a header changes, but the resulting file +# does not +define filechk_offsets + (set -e; \ + echo "#ifndef $2"; \ + echo "#define $2"; \ + echo "/*"; \ + echo " * DO NOT MODIFY."; \ + echo " *"; \ + echo " * This file was generated by Kbuild"; \ + echo " */"; \ + echo ""; \ + sed -ne $(sed-y); \ + echo ""; \ + echo "#endif" ) +endef + +arch/arm/mach-at91/pm_data-offsets.s: arch/arm/mach-at91/pm_data-offsets.c + $(call if_changed_dep,cc_s_c) + +include/generated/at91_pm_data-offsets.h: arch/arm/mach-at91/pm_data-offsets.s FORCE + $(call filechk,offsets,__PM_DATA_OFFSETS_H__) + +arch/arm/mach-at91/pm_suspend.o: include/generated/at91_pm_data-offsets.h diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index d068ec3cd1f6..656ad409a253 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -14,23 +14,10 @@ #include <asm/mach/arch.h> #include "generic.h" -#include "soc.h" - -static const struct at91_soc rm9200_socs[] = { - AT91_SOC(AT91RM9200_CIDR_MATCH, 0, "at91rm9200 BGA", "at91rm9200"), - { /* sentinel */ }, -}; static void __init at91rm9200_dt_device_init(void) { - struct soc_device *soc; - struct device *soc_dev = NULL; - - soc = at91_soc_init(rm9200_socs); - if (soc != NULL) - soc_dev = soc_device_to_device(soc); - - of_platform_default_populate(NULL, NULL, soc_dev); + of_platform_default_populate(NULL, NULL, NULL); at91rm9200_pm_init(); } diff --git a/arch/arm/mach-at91/at91sam9.c b/arch/arm/mach-at91/at91sam9.c index ba28e9cc584d..3dbdef4d3cbf 100644 --- a/arch/arm/mach-at91/at91sam9.c +++ b/arch/arm/mach-at91/at91sam9.c @@ -14,60 +14,12 @@ #include <asm/system_misc.h> #include "generic.h" -#include "soc.h" -static const struct at91_soc at91sam9_socs[] = { - AT91_SOC(AT91SAM9260_CIDR_MATCH, 0, "at91sam9260", NULL), - AT91_SOC(AT91SAM9261_CIDR_MATCH, 0, "at91sam9261", NULL), - AT91_SOC(AT91SAM9263_CIDR_MATCH, 0, "at91sam9263", NULL), - AT91_SOC(AT91SAM9G20_CIDR_MATCH, 0, "at91sam9g20", NULL), - AT91_SOC(AT91SAM9RL64_CIDR_MATCH, 0, "at91sam9rl64", NULL), - AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M11_EXID_MATCH, - "at91sam9m11", "at91sam9g45"), - AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M10_EXID_MATCH, - "at91sam9m10", "at91sam9g45"), - AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G46_EXID_MATCH, - "at91sam9g46", "at91sam9g45"), - AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G45_EXID_MATCH, - "at91sam9g45", "at91sam9g45"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G15_EXID_MATCH, - "at91sam9g15", "at91sam9x5"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G35_EXID_MATCH, - "at91sam9g35", "at91sam9x5"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X35_EXID_MATCH, - "at91sam9x35", "at91sam9x5"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G25_EXID_MATCH, - "at91sam9g25", "at91sam9x5"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X25_EXID_MATCH, - "at91sam9x25", "at91sam9x5"), - AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN12_EXID_MATCH, - "at91sam9cn12", "at91sam9n12"), - AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9N12_EXID_MATCH, - "at91sam9n12", "at91sam9n12"), - AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN11_EXID_MATCH, - "at91sam9cn11", "at91sam9n12"), - AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"), - AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"), - AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"), - { /* sentinel */ }, -}; - -static void __init at91sam9_common_init(void) +static void __init at91sam9_init(void) { - struct soc_device *soc; - struct device *soc_dev = NULL; - - soc = at91_soc_init(at91sam9_socs); - if (soc != NULL) - soc_dev = soc_device_to_device(soc); + of_platform_default_populate(NULL, NULL, NULL); - of_platform_default_populate(NULL, NULL, soc_dev); -} - -static void __init at91sam9_dt_device_init(void) -{ - at91sam9_common_init(); - at91sam9260_pm_init(); + at91sam9_pm_init(); } static const char *const at91_dt_board_compat[] __initconst = { @@ -77,41 +29,6 @@ static const char *const at91_dt_board_compat[] __initconst = { DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM9") /* Maintainer: Atmel */ - .init_machine = at91sam9_dt_device_init, + .init_machine = at91sam9_init, .dt_compat = at91_dt_board_compat, MACHINE_END - -static void __init at91sam9g45_dt_device_init(void) -{ - at91sam9_common_init(); - at91sam9g45_pm_init(); -} - -static const char *const at91sam9g45_board_compat[] __initconst = { - "atmel,at91sam9g45", - NULL -}; - -DT_MACHINE_START(at91sam9g45_dt, "Atmel AT91SAM9G45") - /* Maintainer: Atmel */ - .init_machine = at91sam9g45_dt_device_init, - .dt_compat = at91sam9g45_board_compat, -MACHINE_END - -static void __init at91sam9x5_dt_device_init(void) -{ - at91sam9_common_init(); - at91sam9x5_pm_init(); -} - -static const char *const at91sam9x5_board_compat[] __initconst = { - "atmel,at91sam9x5", - "atmel,at91sam9n12", - NULL -}; - -DT_MACHINE_START(at91sam9x5_dt, "Atmel AT91SAM9") - /* Maintainer: Atmel */ - .init_machine = at91sam9x5_dt_device_init, - .dt_compat = at91sam9x5_board_compat, -MACHINE_END diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 28ca57a2060f..f1ead0f13c19 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -13,15 +13,11 @@ #ifdef CONFIG_PM extern void __init at91rm9200_pm_init(void); -extern void __init at91sam9260_pm_init(void); -extern void __init at91sam9g45_pm_init(void); -extern void __init at91sam9x5_pm_init(void); +extern void __init at91sam9_pm_init(void); extern void __init sama5_pm_init(void); #else static inline void __init at91rm9200_pm_init(void) { } -static inline void __init at91sam9260_pm_init(void) { } -static inline void __init at91sam9g45_pm_init(void) { } -static inline void __init at91sam9x5_pm_init(void) { } +static inline void __init at91sam9_pm_init(void) { } static inline void __init sama5_pm_init(void) { } #endif diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index a277981f414d..283e79ab587d 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -10,35 +10,22 @@ * (at your option) any later version. */ -#include <linux/gpio.h> -#include <linux/suspend.h> -#include <linux/sched.h> -#include <linux/proc_fs.h> #include <linux/genalloc.h> -#include <linux/interrupt.h> -#include <linux/sysfs.h> -#include <linux/module.h> +#include <linux/io.h> +#include <linux/of_address.h> #include <linux/of.h> #include <linux/of_platform.h> -#include <linux/of_address.h> -#include <linux/platform_device.h> -#include <linux/platform_data/atmel.h> -#include <linux/io.h> +#include <linux/suspend.h> + #include <linux/clk/at91_pmc.h> -#include <asm/irq.h> -#include <linux/atomic.h> -#include <asm/mach/time.h> -#include <asm/mach/irq.h> -#include <asm/fncpy.h> #include <asm/cacheflush.h> +#include <asm/fncpy.h> #include <asm/system_misc.h> #include "generic.h" #include "pm.h" -static void __iomem *pmc; - /* * FIXME: this is needed to communicate between the pinctrl driver and * the PM implementation in the machine. Possibly part of the PM @@ -50,12 +37,13 @@ extern void at91_pinctrl_gpio_suspend(void); extern void at91_pinctrl_gpio_resume(void); #endif -static struct { - unsigned long uhp_udp_mask; - int memctrl; -} at91_pm_data; +static struct at91_pm_data pm_data; -static void __iomem *at91_ramc_base[2]; +#define at91_ramc_read(id, field) \ + __raw_readl(pm_data.ramc[id] + field) + +#define at91_ramc_write(id, field, value) \ + __raw_writel(value, pm_data.ramc[id] + field) static int at91_pm_valid_state(suspend_state_t state) { @@ -91,10 +79,10 @@ static int at91_pm_verify_clocks(void) unsigned long scsr; int i; - scsr = readl(pmc + AT91_PMC_SCSR); + scsr = readl(pm_data.pmc + AT91_PMC_SCSR); /* USB must not be using PLLB */ - if ((scsr & at91_pm_data.uhp_udp_mask) != 0) { + if ((scsr & pm_data.uhp_udp_mask) != 0) { pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); return 0; } @@ -105,7 +93,7 @@ static int at91_pm_verify_clocks(void) if ((scsr & (AT91_PMC_PCK0 << i)) == 0) continue; - css = readl(pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS; + css = readl(pm_data.pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS; if (css != AT91_PMC_CSS_SLOW) { pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); return 0; @@ -131,25 +119,18 @@ int at91_suspend_entering_slow_clock(void) } EXPORT_SYMBOL(at91_suspend_entering_slow_clock); -static void (*at91_suspend_sram_fn)(void __iomem *pmc, void __iomem *ramc0, - void __iomem *ramc1, int memctrl); - -extern void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *ramc0, - void __iomem *ramc1, int memctrl); +static void (*at91_suspend_sram_fn)(struct at91_pm_data *); +extern void at91_pm_suspend_in_sram(struct at91_pm_data *pm_data); extern u32 at91_pm_suspend_in_sram_sz; static void at91_pm_suspend(suspend_state_t state) { - unsigned int pm_data = at91_pm_data.memctrl; - - pm_data |= (state == PM_SUSPEND_MEM) ? - AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0; + pm_data.mode = (state == PM_SUSPEND_MEM) ? AT91_PM_SLOW_CLOCK : 0; flush_cache_all(); outer_disable(); - at91_suspend_sram_fn(pmc, at91_ramc_base[0], - at91_ramc_base[1], pm_data); + at91_suspend_sram_fn(&pm_data); outer_resume(); } @@ -224,12 +205,6 @@ static struct platform_device at91_cpuidle_device = { .name = "cpuidle-at91", }; -static void at91_pm_set_standby(void (*at91_standby)(void)) -{ - if (at91_standby) - at91_cpuidle_device.dev.platform_data = at91_standby; -} - /* * The AT91RM9200 goes into self-refresh mode with this command, and will * terminate self-refresh automatically on the next SDRAM access. @@ -241,20 +216,15 @@ static void at91_pm_set_standby(void (*at91_standby)(void)) */ static void at91rm9200_standby(void) { - u32 lpr = at91_ramc_read(0, AT91_MC_SDRAMC_LPR); - asm volatile( "b 1f\n\t" ".align 5\n\t" "1: mcr p15, 0, %0, c7, c10, 4\n\t" - " str %0, [%1, %2]\n\t" - " str %3, [%1, %4]\n\t" + " str %2, [%1, %3]\n\t" " mcr p15, 0, %0, c7, c0, 4\n\t" - " str %5, [%1, %2]" : - : "r" (0), "r" (at91_ramc_base[0]), "r" (AT91_MC_SDRAMC_LPR), - "r" (1), "r" (AT91_MC_SDRAMC_SRR), - "r" (lpr)); + : "r" (0), "r" (pm_data.ramc[0]), + "r" (1), "r" (AT91_MC_SDRAMC_SRR)); } /* We manage both DDRAM/SDRAM controllers, we need more than one value to @@ -265,12 +235,27 @@ static void at91_ddr_standby(void) /* Those two values allow us to delay self-refresh activation * to the maximum. */ u32 lpr0, lpr1 = 0; + u32 mdr, saved_mdr0, saved_mdr1 = 0; u32 saved_lpr0, saved_lpr1 = 0; - if (at91_ramc_base[1]) { + /* LPDDR1 --> force DDR2 mode during self-refresh */ + saved_mdr0 = at91_ramc_read(0, AT91_DDRSDRC_MDR); + if ((saved_mdr0 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) { + mdr = saved_mdr0 & ~AT91_DDRSDRC_MD; + mdr |= AT91_DDRSDRC_MD_DDR2; + at91_ramc_write(0, AT91_DDRSDRC_MDR, mdr); + } + + if (pm_data.ramc[1]) { saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR); lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB; lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH; + saved_mdr1 = at91_ramc_read(1, AT91_DDRSDRC_MDR); + if ((saved_mdr1 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) { + mdr = saved_mdr1 & ~AT91_DDRSDRC_MD; + mdr |= AT91_DDRSDRC_MD_DDR2; + at91_ramc_write(1, AT91_DDRSDRC_MDR, mdr); + } } saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR); @@ -279,14 +264,17 @@ static void at91_ddr_standby(void) /* self-refresh mode now */ at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0); - if (at91_ramc_base[1]) + if (pm_data.ramc[1]) at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1); cpu_do_idle(); + at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr0); at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0); - if (at91_ramc_base[1]) + if (pm_data.ramc[1]) { + at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr1); at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); + } } static void sama5d3_ddr_standby(void) @@ -313,7 +301,7 @@ static void at91sam9_sdram_standby(void) u32 lpr0, lpr1 = 0; u32 saved_lpr0, saved_lpr1 = 0; - if (at91_ramc_base[1]) { + if (pm_data.ramc[1]) { saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR); lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB; lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH; @@ -325,21 +313,33 @@ static void at91sam9_sdram_standby(void) /* self-refresh mode now */ at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0); - if (at91_ramc_base[1]) + if (pm_data.ramc[1]) at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1); cpu_do_idle(); at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0); - if (at91_ramc_base[1]) + if (pm_data.ramc[1]) at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); } -static const struct of_device_id const ramc_ids[] __initconst = { - { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby }, - { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby }, - { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby }, - { .compatible = "atmel,sama5d3-ddramc", .data = sama5d3_ddr_standby }, +struct ramc_info { + void (*idle)(void); + unsigned int memctrl; +}; + +static const struct ramc_info ramc_infos[] __initconst = { + { .idle = at91rm9200_standby, .memctrl = AT91_MEMCTRL_MC}, + { .idle = at91sam9_sdram_standby, .memctrl = AT91_MEMCTRL_SDRAMC}, + { .idle = at91_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR}, + { .idle = sama5d3_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR}, +}; + +static const struct of_device_id ramc_ids[] __initconst = { + { .compatible = "atmel,at91rm9200-sdramc", .data = &ramc_infos[0] }, + { .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] }, + { .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] }, + { .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[3] }, { /*sentinel*/ } }; @@ -348,15 +348,18 @@ static __init void at91_dt_ramc(void) struct device_node *np; const struct of_device_id *of_id; int idx = 0; - const void *standby = NULL; + void *standby = NULL; + const struct ramc_info *ramc; for_each_matching_node_and_match(np, ramc_ids, &of_id) { - at91_ramc_base[idx] = of_iomap(np, 0); - if (!at91_ramc_base[idx]) + pm_data.ramc[idx] = of_iomap(np, 0); + if (!pm_data.ramc[idx]) panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx); + ramc = of_id->data; if (!standby) - standby = of_id->data; + standby = ramc->idle; + pm_data.memctrl = ramc->memctrl; idx++; } @@ -369,7 +372,7 @@ static __init void at91_dt_ramc(void) return; } - at91_pm_set_standby(standby); + at91_cpuidle_device.dev.platform_data = standby; } static void at91rm9200_idle(void) @@ -378,12 +381,12 @@ static void at91rm9200_idle(void) * Disable the processor clock. The processor will be automatically * re-enabled by an interrupt or by a reset. */ - writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR); + writel(AT91_PMC_PCK, pm_data.pmc + AT91_PMC_SCDR); } static void at91sam9_idle(void) { - writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR); + writel(AT91_PMC_PCK, pm_data.pmc + AT91_PMC_SCDR); cpu_do_idle(); } @@ -433,31 +436,46 @@ static void __init at91_pm_sram_init(void) &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz); } +struct pmc_info { + unsigned long uhp_udp_mask; +}; + +static const struct pmc_info pmc_infos[] __initconst = { + { .uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP }, + { .uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP }, + { .uhp_udp_mask = AT91SAM926x_PMC_UHP }, +}; + static const struct of_device_id atmel_pmc_ids[] __initconst = { - { .compatible = "atmel,at91rm9200-pmc" }, - { .compatible = "atmel,at91sam9260-pmc" }, - { .compatible = "atmel,at91sam9g45-pmc" }, - { .compatible = "atmel,at91sam9n12-pmc" }, - { .compatible = "atmel,at91sam9x5-pmc" }, - { .compatible = "atmel,sama5d3-pmc" }, - { .compatible = "atmel,sama5d2-pmc" }, + { .compatible = "atmel,at91rm9200-pmc", .data = &pmc_infos[0] }, + { .compatible = "atmel,at91sam9260-pmc", .data = &pmc_infos[1] }, + { .compatible = "atmel,at91sam9g45-pmc", .data = &pmc_infos[2] }, + { .compatible = "atmel,at91sam9n12-pmc", .data = &pmc_infos[1] }, + { .compatible = "atmel,at91sam9x5-pmc", .data = &pmc_infos[1] }, + { .compatible = "atmel,sama5d3-pmc", .data = &pmc_infos[1] }, + { .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] }, { /* sentinel */ }, }; static void __init at91_pm_init(void (*pm_idle)(void)) { struct device_node *pmc_np; + const struct of_device_id *of_id; + const struct pmc_info *pmc; if (at91_cpuidle_device.dev.platform_data) platform_device_register(&at91_cpuidle_device); - pmc_np = of_find_matching_node(NULL, atmel_pmc_ids); - pmc = of_iomap(pmc_np, 0); - if (!pmc) { + pmc_np = of_find_matching_node_and_match(NULL, atmel_pmc_ids, &of_id); + pm_data.pmc = of_iomap(pmc_np, 0); + if (!pm_data.pmc) { pr_err("AT91: PM not supported, PMC not found\n"); return; } + pmc = of_id->data; + pm_data.uhp_udp_mask = pmc->uhp_udp_mask; + if (pm_idle) arm_pm_idle = pm_idle; @@ -478,40 +496,17 @@ void __init at91rm9200_pm_init(void) */ at91_ramc_write(0, AT91_MC_SDRAMC_LPR, 0); - at91_pm_data.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP; - at91_pm_data.memctrl = AT91_MEMCTRL_MC; - at91_pm_init(at91rm9200_idle); } -void __init at91sam9260_pm_init(void) -{ - at91_dt_ramc(); - at91_pm_data.memctrl = AT91_MEMCTRL_SDRAMC; - at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; - at91_pm_init(at91sam9_idle); -} - -void __init at91sam9g45_pm_init(void) -{ - at91_dt_ramc(); - at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP; - at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; - at91_pm_init(at91sam9_idle); -} - -void __init at91sam9x5_pm_init(void) +void __init at91sam9_pm_init(void) { at91_dt_ramc(); - at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; - at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; at91_pm_init(at91sam9_idle); } void __init sama5_pm_init(void) { at91_dt_ramc(); - at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; - at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; at91_pm_init(NULL); } diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index bf980c6ef294..fc0f7d048187 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -17,24 +17,20 @@ #include <soc/at91/at91sam9_ddrsdr.h> #include <soc/at91/at91sam9_sdramc.h> -#ifndef __ASSEMBLY__ -#define at91_ramc_read(id, field) \ - __raw_readl(at91_ramc_base[id] + field) - -#define at91_ramc_write(id, field, value) \ - __raw_writel(value, at91_ramc_base[id] + field) -#endif - #define AT91_MEMCTRL_MC 0 #define AT91_MEMCTRL_SDRAMC 1 #define AT91_MEMCTRL_DDRSDR 2 -#define AT91_PM_MEMTYPE_MASK 0x0f - -#define AT91_PM_MODE_OFFSET 4 -#define AT91_PM_MODE_MASK 0x01 -#define AT91_PM_MODE(x) (((x) & AT91_PM_MODE_MASK) << AT91_PM_MODE_OFFSET) - #define AT91_PM_SLOW_CLOCK 0x01 +#ifndef __ASSEMBLY__ +struct at91_pm_data { + void __iomem *pmc; + void __iomem *ramc[2]; + unsigned long uhp_udp_mask; + unsigned int memctrl; + unsigned int mode; +}; +#endif + #endif diff --git a/arch/arm/mach-at91/pm_data-offsets.c b/arch/arm/mach-at91/pm_data-offsets.c new file mode 100644 index 000000000000..30302cb16df0 --- /dev/null +++ b/arch/arm/mach-at91/pm_data-offsets.c @@ -0,0 +1,13 @@ +#include <linux/stddef.h> +#include <linux/kbuild.h> +#include "pm.h" + +int main(void) +{ + DEFINE(PM_DATA_PMC, offsetof(struct at91_pm_data, pmc)); + DEFINE(PM_DATA_RAMC0, offsetof(struct at91_pm_data, ramc[0])); + DEFINE(PM_DATA_RAMC1, offsetof(struct at91_pm_data, ramc[1])); + DEFINE(PM_DATA_MEMCTRL, offsetof(struct at91_pm_data, memctrl)); + DEFINE(PM_DATA_MODE, offsetof(struct at91_pm_data, mode)); + return 0; +} diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index a25defda3d22..96781daa671a 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -4,7 +4,7 @@ * Copyright (C) 2006 Savin Zlobec * * AT91SAM9 support: - * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee + * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee> * * 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 @@ -14,6 +14,7 @@ #include <linux/linkage.h> #include <linux/clk/at91_pmc.h> #include "pm.h" +#include "generated/at91_pm_data-offsets.h" #define SRAMC_SELF_FRESH_ACTIVE 0x01 #define SRAMC_SELF_FRESH_EXIT 0x00 @@ -72,13 +73,9 @@ tmp2 .req r5 .arm /* - * void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc, - * void __iomem *ramc1, int memctrl) + * void at91_suspend_sram_fn(struct at91_pm_data*) * @input param: - * @r0: base address of AT91_PMC - * @r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS) - * @r2: base address of second SDRAM Controller or 0 if not present - * @r3: pm information + * @r0: base address of struct at91_pm_data */ /* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */ .align 3 @@ -90,16 +87,16 @@ ENTRY(at91_pm_suspend_in_sram) mov tmp1, #0 mcr p15, 0, tmp1, c7, c10, 4 - str r0, .pmc_base - str r1, .sramc_base - str r2, .sramc1_base - - and r0, r3, #AT91_PM_MEMTYPE_MASK - str r0, .memtype - - lsr r0, r3, #AT91_PM_MODE_OFFSET - and r0, r0, #AT91_PM_MODE_MASK - str r0, .pm_mode + ldr tmp1, [r0, #PM_DATA_PMC] + str tmp1, .pmc_base + ldr tmp1, [r0, #PM_DATA_RAMC0] + str tmp1, .sramc_base + ldr tmp1, [r0, #PM_DATA_RAMC1] + str tmp1, .sramc1_base + ldr tmp1, [r0, #PM_DATA_MEMCTRL] + str tmp1, .memtype + ldr tmp1, [r0, #PM_DATA_MODE] + str tmp1, .pm_mode /* Active the self-refresh mode */ mov r0, #SRAMC_SELF_FRESH_ACTIVE diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c index b272c45b400f..6d157d0ead8e 100644 --- a/arch/arm/mach-at91/sama5.c +++ b/arch/arm/mach-at91/sama5.c @@ -15,60 +15,10 @@ #include <asm/system_misc.h> #include "generic.h" -#include "soc.h" - -static const struct at91_soc sama5_socs[] = { - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH, - "sama5d21", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D22CU_EXID_MATCH, - "sama5d22", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D23CU_EXID_MATCH, - "sama5d23", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CX_EXID_MATCH, - "sama5d24", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CU_EXID_MATCH, - "sama5d24", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D26CU_EXID_MATCH, - "sama5d26", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CU_EXID_MATCH, - "sama5d27", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CN_EXID_MATCH, - "sama5d27", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH, - "sama5d28", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH, - "sama5d28", "sama5d2"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH, - "sama5d31", "sama5d3"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH, - "sama5d33", "sama5d3"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D34_EXID_MATCH, - "sama5d34", "sama5d3"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D35_EXID_MATCH, - "sama5d35", "sama5d3"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D36_EXID_MATCH, - "sama5d36", "sama5d3"), - AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D41_EXID_MATCH, - "sama5d41", "sama5d4"), - AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D42_EXID_MATCH, - "sama5d42", "sama5d4"), - AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D43_EXID_MATCH, - "sama5d43", "sama5d4"), - AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH, - "sama5d44", "sama5d4"), - { /* sentinel */ }, -}; static void __init sama5_dt_device_init(void) { - struct soc_device *soc; - struct device *soc_dev = NULL; - - soc = at91_soc_init(sama5_socs); - if (soc != NULL) - soc_dev = soc_device_to_device(soc); - - of_platform_default_populate(NULL, NULL, soc_dev); + of_platform_default_populate(NULL, NULL, NULL); sama5_pm_init(); } diff --git a/arch/arm/mach-at91/soc.c b/arch/arm/mach-at91/soc.c deleted file mode 100644 index c6fda75ddb89..000000000000 --- a/arch/arm/mach-at91/soc.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2015 Atmel - * - * Alexandre Belloni <alexandre.belloni@free-electrons.com - * Boris Brezillon <boris.brezillon@free-electrons.com - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - */ - -#define pr_fmt(fmt) "AT91: " fmt - -#include <linux/io.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_platform.h> -#include <linux/slab.h> -#include <linux/sys_soc.h> - -#include "soc.h" - -#define AT91_DBGU_CIDR 0x40 -#define AT91_DBGU_EXID 0x44 -#define AT91_CHIPID_CIDR 0x00 -#define AT91_CHIPID_EXID 0x04 -#define AT91_CIDR_VERSION(x) ((x) & 0x1f) -#define AT91_CIDR_EXT BIT(31) -#define AT91_CIDR_MATCH_MASK 0x7fffffe0 - -static int __init at91_get_cidr_exid_from_dbgu(u32 *cidr, u32 *exid) -{ - struct device_node *np; - void __iomem *regs; - - np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-dbgu"); - if (!np) - np = of_find_compatible_node(NULL, NULL, - "atmel,at91sam9260-dbgu"); - if (!np) - return -ENODEV; - - regs = of_iomap(np, 0); - of_node_put(np); - - if (!regs) { - pr_warn("Could not map DBGU iomem range"); - return -ENXIO; - } - - *cidr = readl(regs + AT91_DBGU_CIDR); - *exid = readl(regs + AT91_DBGU_EXID); - - iounmap(regs); - - return 0; -} - -static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid) -{ - struct device_node *np; - void __iomem *regs; - - np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-chipid"); - if (!np) - return -ENODEV; - - regs = of_iomap(np, 0); - of_node_put(np); - - if (!regs) { - pr_warn("Could not map DBGU iomem range"); - return -ENXIO; - } - - *cidr = readl(regs + AT91_CHIPID_CIDR); - *exid = readl(regs + AT91_CHIPID_EXID); - - iounmap(regs); - - return 0; -} - -struct soc_device * __init at91_soc_init(const struct at91_soc *socs) -{ - struct soc_device_attribute *soc_dev_attr; - const struct at91_soc *soc; - struct soc_device *soc_dev; - u32 cidr, exid; - int ret; - - /* - * With SAMA5D2 and later SoCs, CIDR and EXID registers are no more - * in the dbgu device but in the chipid device whose purpose is only - * to expose these two registers. - */ - ret = at91_get_cidr_exid_from_dbgu(&cidr, &exid); - if (ret) - ret = at91_get_cidr_exid_from_chipid(&cidr, &exid); - if (ret) { - if (ret == -ENODEV) - pr_warn("Could not find identification node"); - return NULL; - } - - for (soc = socs; soc->name; soc++) { - if (soc->cidr_match != (cidr & AT91_CIDR_MATCH_MASK)) - continue; - - if (!(cidr & AT91_CIDR_EXT) || soc->exid_match == exid) - break; - } - - if (!soc->name) { - pr_warn("Could not find matching SoC description\n"); - return NULL; - } - - soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); - if (!soc_dev_attr) - return NULL; - - soc_dev_attr->family = soc->family; - soc_dev_attr->soc_id = soc->name; - soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X", - AT91_CIDR_VERSION(cidr)); - soc_dev = soc_device_register(soc_dev_attr); - if (IS_ERR(soc_dev)) { - kfree(soc_dev_attr->revision); - kfree(soc_dev_attr); - pr_warn("Could not register SoC device\n"); - return NULL; - } - - if (soc->family) - pr_info("Detected SoC family: %s\n", soc->family); - pr_info("Detected SoC: %s, revision %X\n", soc->name, - AT91_CIDR_VERSION(cidr)); - - return soc_dev; -} diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h deleted file mode 100644 index 228efded5085..000000000000 --- a/arch/arm/mach-at91/soc.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2015 Atmel - * - * Boris Brezillon <boris.brezillon@free-electrons.com - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - */ - -#ifndef __AT91_SOC_H -#define __AT91_SOC_H - -#include <linux/sys_soc.h> - -struct at91_soc { - u32 cidr_match; - u32 exid_match; - const char *name; - const char *family; -}; - -#define AT91_SOC(__cidr, __exid, __name, __family) \ - { \ - .cidr_match = (__cidr), \ - .exid_match = (__exid), \ - .name = (__name), \ - .family = (__family), \ - } - -struct soc_device * __init -at91_soc_init(const struct at91_soc *socs); - -#define AT91RM9200_CIDR_MATCH 0x09290780 - -#define AT91SAM9260_CIDR_MATCH 0x019803a0 -#define AT91SAM9261_CIDR_MATCH 0x019703a0 -#define AT91SAM9263_CIDR_MATCH 0x019607a0 -#define AT91SAM9G20_CIDR_MATCH 0x019905a0 -#define AT91SAM9RL64_CIDR_MATCH 0x019b03a0 -#define AT91SAM9G45_CIDR_MATCH 0x019b05a0 -#define AT91SAM9X5_CIDR_MATCH 0x019a05a0 -#define AT91SAM9N12_CIDR_MATCH 0x019a07a0 - -#define AT91SAM9M11_EXID_MATCH 0x00000001 -#define AT91SAM9M10_EXID_MATCH 0x00000002 -#define AT91SAM9G46_EXID_MATCH 0x00000003 -#define AT91SAM9G45_EXID_MATCH 0x00000004 - -#define AT91SAM9G15_EXID_MATCH 0x00000000 -#define AT91SAM9G35_EXID_MATCH 0x00000001 -#define AT91SAM9X35_EXID_MATCH 0x00000002 -#define AT91SAM9G25_EXID_MATCH 0x00000003 -#define AT91SAM9X25_EXID_MATCH 0x00000004 - -#define AT91SAM9CN12_EXID_MATCH 0x00000005 -#define AT91SAM9N12_EXID_MATCH 0x00000006 -#define AT91SAM9CN11_EXID_MATCH 0x00000009 - -#define AT91SAM9XE128_CIDR_MATCH 0x329973a0 -#define AT91SAM9XE256_CIDR_MATCH 0x329a93a0 -#define AT91SAM9XE512_CIDR_MATCH 0x329aa3a0 - -#define SAMA5D2_CIDR_MATCH 0x0a5c08c0 -#define SAMA5D21CU_EXID_MATCH 0x0000005a -#define SAMA5D22CU_EXID_MATCH 0x00000059 -#define SAMA5D22CN_EXID_MATCH 0x00000069 -#define SAMA5D23CU_EXID_MATCH 0x00000058 -#define SAMA5D24CX_EXID_MATCH 0x00000004 -#define SAMA5D24CU_EXID_MATCH 0x00000014 -#define SAMA5D26CU_EXID_MATCH 0x00000012 -#define SAMA5D27CU_EXID_MATCH 0x00000011 -#define SAMA5D27CN_EXID_MATCH 0x00000021 -#define SAMA5D28CU_EXID_MATCH 0x00000010 -#define SAMA5D28CN_EXID_MATCH 0x00000020 - -#define SAMA5D3_CIDR_MATCH 0x0a5c07c0 -#define SAMA5D31_EXID_MATCH 0x00444300 -#define SAMA5D33_EXID_MATCH 0x00414300 -#define SAMA5D34_EXID_MATCH 0x00414301 -#define SAMA5D35_EXID_MATCH 0x00584300 -#define SAMA5D36_EXID_MATCH 0x00004301 - -#define SAMA5D4_CIDR_MATCH 0x0a5c07c0 -#define SAMA5D41_EXID_MATCH 0x00000001 -#define SAMA5D42_EXID_MATCH 0x00000002 -#define SAMA5D43_EXID_MATCH 0x00000003 -#define SAMA5D44_EXID_MATCH 0x00000004 - -#endif /* __AT91_SOC_H */ |