From 24a0f5c539f944248cbb2e3502830dcb7fd2a96e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 27 Sep 2016 12:29:50 +0200 Subject: [PATCH 01/11] ARM: at91: pm: Add sama5d2 backup mode The sama5d2 has a mode were it is possible to cut power to the SoC while keeping the RAM in self refresh. Resuming from that mode needs support in the firmware/bootloader. Signed-off-by: Alexandre Belloni Acked-by: Wenyou Yang --- arch/arm/mach-at91/generic.h | 2 + arch/arm/mach-at91/pm.c | 109 ++++++++++++++++++++++++++- arch/arm/mach-at91/pm.h | 4 + arch/arm/mach-at91/pm_data-offsets.c | 3 + arch/arm/mach-at91/pm_suspend.S | 73 +++++++++++++----- arch/arm/mach-at91/sama5.c | 19 ++++- 6 files changed, 187 insertions(+), 23 deletions(-) diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index f1ead0f13c19..e2bd17237964 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -15,10 +15,12 @@ extern void __init at91rm9200_pm_init(void); extern void __init at91sam9_pm_init(void); extern void __init sama5_pm_init(void); +extern void __init sama5d2_pm_init(void); #else static inline void __init at91rm9200_pm_init(void) { } static inline void __init at91sam9_pm_init(void) { } static inline void __init sama5_pm_init(void) { } +static inline void __init sama5d2_pm_init(void) { } #endif #endif /* _AT91_GENERIC_H */ diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 2cd27c830ab6..d138d19fa9f0 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "generic.h" #include "pm.h" @@ -58,6 +59,14 @@ static int at91_pm_valid_state(suspend_state_t state) } } +static int canary = 0xA5A5A5A5; + +static struct at91_pm_bu { + int suspended; + unsigned long reserved; + phys_addr_t canary; + phys_addr_t resume; +} *pm_bu; static suspend_state_t target_state; @@ -123,15 +132,39 @@ 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) +static int at91_suspend_finish(unsigned long val) { - pm_data.mode = (state == PM_SUSPEND_MEM) ? AT91_PM_SLOW_CLOCK : 0; - flush_cache_all(); outer_disable(); at91_suspend_sram_fn(&pm_data); + return 0; +} + +static void at91_pm_suspend(suspend_state_t state) +{ + if (pm_data.deepest_state == AT91_PM_BACKUP) + if (state == PM_SUSPEND_MEM) + pm_data.mode = AT91_PM_BACKUP; + else + pm_data.mode = AT91_PM_SLOW_CLOCK; + else + pm_data.mode = (state == PM_SUSPEND_MEM) ? AT91_PM_SLOW_CLOCK : 0; + + if (pm_data.mode == AT91_PM_BACKUP) { + pm_bu->suspended = 1; + + cpu_suspend(0, at91_suspend_finish); + + /* The SRAM is lost between suspend cycles */ + at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn, + &at91_pm_suspend_in_sram, + at91_pm_suspend_in_sram_sz); + } else { + at91_suspend_finish(0); + } + outer_resume(); } @@ -436,6 +469,70 @@ static void __init at91_pm_sram_init(void) &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz); } +static void __init at91_pm_backup_init(void) +{ + struct gen_pool *sram_pool; + struct device_node *np; + struct platform_device *pdev = NULL; + + pm_bu = NULL; + + np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc"); + if (!np) { + pr_warn("%s: failed to find shdwc!\n", __func__); + return; + } + + pm_data.shdwc = of_iomap(np, 0); + of_node_put(np); + + np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu"); + if (!np) { + pr_warn("%s: failed to find sfrbu!\n", __func__); + goto sfrbu_fail; + } + + pm_data.sfrbu = of_iomap(np, 0); + of_node_put(np); + pm_bu = NULL; + + np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam"); + if (!np) + goto securam_fail; + + pdev = of_find_device_by_node(np); + of_node_put(np); + if (!pdev) { + pr_warn("%s: failed to find securam device!\n", __func__); + goto securam_fail; + } + + sram_pool = gen_pool_get(&pdev->dev, NULL); + if (!sram_pool) { + pr_warn("%s: securam pool unavailable!\n", __func__); + goto securam_fail; + } + + pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu)); + if (!pm_bu) { + pr_warn("%s: unable to alloc securam!\n", __func__); + goto securam_fail; + } + + pm_bu->suspended = 0; + pm_bu->canary = virt_to_phys(&canary); + pm_bu->resume = virt_to_phys(cpu_resume); + + return; + +sfrbu_fail: + iounmap(pm_data.shdwc); + pm_data.shdwc = NULL; +securam_fail: + iounmap(pm_data.sfrbu); + pm_data.sfrbu = NULL; +} + struct pmc_info { unsigned long uhp_udp_mask; }; @@ -510,3 +607,9 @@ void __init sama5_pm_init(void) at91_dt_ramc(); at91_pm_init(NULL); } + +void __init sama5d2_pm_init(void) +{ + at91_pm_backup_init(); + sama5_pm_init(); +} diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index fc0f7d048187..d9c6612ef62f 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -22,6 +22,7 @@ #define AT91_MEMCTRL_DDRSDR 2 #define AT91_PM_SLOW_CLOCK 0x01 +#define AT91_PM_BACKUP 0x02 #ifndef __ASSEMBLY__ struct at91_pm_data { @@ -30,6 +31,9 @@ struct at91_pm_data { unsigned long uhp_udp_mask; unsigned int memctrl; unsigned int mode; + void __iomem *shdwc; + void __iomem *sfrbu; + unsigned int deepest_state; }; #endif diff --git a/arch/arm/mach-at91/pm_data-offsets.c b/arch/arm/mach-at91/pm_data-offsets.c index 30302cb16df0..c0a73e62b725 100644 --- a/arch/arm/mach-at91/pm_data-offsets.c +++ b/arch/arm/mach-at91/pm_data-offsets.c @@ -9,5 +9,8 @@ int main(void) 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)); + DEFINE(PM_DATA_SHDWC, offsetof(struct at91_pm_data, shdwc)); + DEFINE(PM_DATA_SFRBU, offsetof(struct at91_pm_data, sfrbu)); + return 0; } diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index 96781daa671a..daca91feea6a 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -97,15 +97,61 @@ ENTRY(at91_pm_suspend_in_sram) str tmp1, .memtype ldr tmp1, [r0, #PM_DATA_MODE] str tmp1, .pm_mode + /* Both ldrne below are here to preload their address in the TLB */ + ldr tmp1, [r0, #PM_DATA_SHDWC] + str tmp1, .shdwc + cmp tmp1, #0 + ldrne tmp2, [tmp1, #0] + ldr tmp1, [r0, #PM_DATA_SFRBU] + str tmp1, .sfr + cmp tmp1, #0 + ldrne tmp2, [tmp1, #0x10] /* Active the self-refresh mode */ mov r0, #SRAMC_SELF_FRESH_ACTIVE bl at91_sramc_self_refresh ldr r0, .pm_mode - tst r0, #AT91_PM_SLOW_CLOCK - beq skip_disable_main_clock + cmp r0, #AT91_PM_SLOW_CLOCK + beq slow_clock + cmp r0, #AT91_PM_BACKUP + beq backup_mode + /* Wait for interrupt */ + ldr pmc, .pmc_base + at91_cpu_idle + b exit_suspend + +slow_clock: + bl at91_slowck_mode + b exit_suspend +backup_mode: + bl at91_backup_mode + b exit_suspend + +exit_suspend: + /* Exit the self-refresh mode */ + mov r0, #SRAMC_SELF_FRESH_EXIT + bl at91_sramc_self_refresh + + /* Restore registers, and return */ + ldmfd sp!, {r4 - r12, pc} +ENDPROC(at91_pm_suspend_in_sram) + +ENTRY(at91_backup_mode) + /*BUMEN*/ + ldr r0, .sfr + mov tmp1, #0x1 + str tmp1, [r0, #0x10] + + /* Shutdown */ + ldr r0, .shdwc + mov tmp1, #0xA5000000 + add tmp1, tmp1, #0x1 + str tmp1, [r0, #0] +ENDPROC(at91_backup_mode) + +ENTRY(at91_slowck_mode) ldr pmc, .pmc_base /* Save Master clock setting */ @@ -134,18 +180,9 @@ ENTRY(at91_pm_suspend_in_sram) orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] -skip_disable_main_clock: - ldr pmc, .pmc_base - /* Wait for interrupt */ at91_cpu_idle - ldr r0, .pm_mode - tst r0, #AT91_PM_SLOW_CLOCK - beq skip_enable_main_clock - - ldr pmc, .pmc_base - /* Turn on the main oscillator */ ldr tmp1, [pmc, #AT91_CKGR_MOR] orr tmp1, tmp1, #AT91_PMC_MOSCEN @@ -174,14 +211,8 @@ skip_disable_main_clock: wait_mckrdy -skip_enable_main_clock: - /* Exit the self-refresh mode */ - mov r0, #SRAMC_SELF_FRESH_EXIT - bl at91_sramc_self_refresh - - /* Restore registers, and return */ - ldmfd sp!, {r4 - r12, pc} -ENDPROC(at91_pm_suspend_in_sram) + mov pc, lr +ENDPROC(at91_slowck_mode) /* * void at91_sramc_self_refresh(unsigned int is_active) @@ -314,6 +345,10 @@ ENDPROC(at91_sramc_self_refresh) .word 0 .sramc1_base: .word 0 +.shdwc: + .word 0 +.sfr: + .word 0 .memtype: .word 0 .pm_mode: diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c index 6d157d0ead8e..3d0bf95a56ae 100644 --- a/arch/arm/mach-at91/sama5.c +++ b/arch/arm/mach-at91/sama5.c @@ -34,7 +34,6 @@ DT_MACHINE_START(sama5_dt, "Atmel SAMA5") MACHINE_END static const char *const sama5_alt_dt_board_compat[] __initconst = { - "atmel,sama5d2", "atmel,sama5d4", NULL }; @@ -45,3 +44,21 @@ DT_MACHINE_START(sama5_alt_dt, "Atmel SAMA5") .dt_compat = sama5_alt_dt_board_compat, .l2c_aux_mask = ~0UL, MACHINE_END + +static void __init sama5d2_init(void) +{ + of_platform_default_populate(NULL, NULL, NULL); + sama5d2_pm_init(); +} + +static const char *const sama5d2_compat[] __initconst = { + "atmel,sama5d2", + NULL +}; + +DT_MACHINE_START(sama5d2, "Atmel SAMA5") + /* Maintainer: Atmel */ + .init_machine = sama5d2_init, + .dt_compat = sama5d2_compat, + .l2c_aux_mask = ~0UL, +MACHINE_END From 7693e18e8c2e2f3188f69bd572ff77dac481da6e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 26 Apr 2017 16:31:03 +0200 Subject: [PATCH 02/11] ARM: at91: pm: allow selecting standby and suspend modes While we can only select between "standby" and "mem" states for power management, the atmel platforms can actually support more modes. For both standby and mem, allow selecting which mode will be used using the atmel.pm_modes kernel parameter. By default, keep the current modes. Signed-off-by: Alexandre Belloni Acked-by: Wenyou Yang --- arch/arm/mach-at91/pm.c | 110 +++++++++++++++++++++++++++------------- arch/arm/mach-at91/pm.h | 3 +- 2 files changed, 78 insertions(+), 35 deletions(-) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index d138d19fa9f0..ef9c1d29cc67 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -38,7 +39,17 @@ extern void at91_pinctrl_gpio_suspend(void); extern void at91_pinctrl_gpio_resume(void); #endif -static struct at91_pm_data pm_data; +static const match_table_t pm_modes __initconst = { + { 0, "standby" }, + { AT91_PM_SLOW_CLOCK, "ulp0" }, + { AT91_PM_BACKUP, "backup" }, + { -1, NULL }, +}; + +static struct at91_pm_data pm_data = { + .standby_mode = 0, + .suspend_mode = AT91_PM_SLOW_CLOCK, +}; #define at91_ramc_read(id, field) \ __raw_readl(pm_data.ramc[id] + field) @@ -68,14 +79,24 @@ static struct at91_pm_bu { phys_addr_t resume; } *pm_bu; -static suspend_state_t target_state; - /* * Called after processes are frozen, but before we shutdown devices. */ static int at91_pm_begin(suspend_state_t state) { - target_state = state; + switch (state) { + case PM_SUSPEND_MEM: + pm_data.mode = pm_data.suspend_mode; + break; + + case PM_SUSPEND_STANDBY: + pm_data.mode = pm_data.standby_mode; + break; + + default: + pm_data.mode = -1; + } + return 0; } @@ -124,7 +145,7 @@ static int at91_pm_verify_clocks(void) */ int at91_suspend_entering_slow_clock(void) { - return (target_state == PM_SUSPEND_MEM); + return (pm_data.mode >= AT91_PM_SLOW_CLOCK); } EXPORT_SYMBOL(at91_suspend_entering_slow_clock); @@ -144,14 +165,6 @@ static int at91_suspend_finish(unsigned long val) static void at91_pm_suspend(suspend_state_t state) { - if (pm_data.deepest_state == AT91_PM_BACKUP) - if (state == PM_SUSPEND_MEM) - pm_data.mode = AT91_PM_BACKUP; - else - pm_data.mode = AT91_PM_SLOW_CLOCK; - else - pm_data.mode = (state == PM_SUSPEND_MEM) ? AT91_PM_SLOW_CLOCK : 0; - if (pm_data.mode == AT91_PM_BACKUP) { pm_bu->suspended = 1; @@ -168,38 +181,37 @@ static void at91_pm_suspend(suspend_state_t state) outer_resume(); } +/* + * STANDBY mode has *all* drivers suspended; ignores irqs not marked as 'wakeup' + * event sources; and reduces DRAM power. But otherwise it's identical to + * PM_SUSPEND_ON: cpu idle, and nothing fancy done with main or cpu clocks. + * + * AT91_PM_SLOW_CLOCK is like STANDBY plus slow clock mode, so drivers must + * suspend more deeply, the master clock switches to the clk32k and turns off + * the main oscillator + * + * AT91_PM_BACKUP turns off the whole SoC after placing the DDR in self refresh + */ static int at91_pm_enter(suspend_state_t state) { #ifdef CONFIG_PINCTRL_AT91 at91_pinctrl_gpio_suspend(); #endif + switch (state) { - /* - * Suspend-to-RAM is like STANDBY plus slow clock mode, so - * drivers must suspend more deeply, the master clock switches - * to the clk32k and turns off the main oscillator - */ case PM_SUSPEND_MEM: + case PM_SUSPEND_STANDBY: /* * Ensure that clocks are in a valid state. */ - if (!at91_pm_verify_clocks()) + if ((pm_data.mode >= AT91_PM_SLOW_CLOCK) && + !at91_pm_verify_clocks()) goto error; at91_pm_suspend(state); break; - /* - * STANDBY mode has *all* drivers suspended; ignores irqs not - * marked as 'wakeup' event sources; and reduces DRAM power. - * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and - * nothing fancy done with main or cpu clocks. - */ - case PM_SUSPEND_STANDBY: - at91_pm_suspend(state); - break; - case PM_SUSPEND_ON: cpu_do_idle(); break; @@ -210,8 +222,6 @@ static int at91_pm_enter(suspend_state_t state) } error: - target_state = PM_SUSPEND_ON; - #ifdef CONFIG_PINCTRL_AT91 at91_pinctrl_gpio_resume(); #endif @@ -223,7 +233,6 @@ error: */ static void at91_pm_end(void) { - target_state = PM_SUSPEND_ON; } @@ -475,6 +484,10 @@ static void __init at91_pm_backup_init(void) struct device_node *np; struct platform_device *pdev = NULL; + if ((pm_data.standby_mode != AT91_PM_BACKUP) && + (pm_data.suspend_mode != AT91_PM_BACKUP)) + return; + pm_bu = NULL; np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc"); @@ -578,10 +591,14 @@ static void __init at91_pm_init(void (*pm_idle)(void)) at91_pm_sram_init(); - if (at91_suspend_sram_fn) + if (at91_suspend_sram_fn) { suspend_set_ops(&at91_pm_ops); - else + pr_info("AT91: PM: standby: %s, suspend: %s\n", + pm_modes[pm_data.standby_mode].pattern, + pm_modes[pm_data.suspend_mode].pattern); + } else { pr_info("AT91: PM not supported, due to no SRAM allocated\n"); + } } void __init at91rm9200_pm_init(void) @@ -613,3 +630,28 @@ void __init sama5d2_pm_init(void) at91_pm_backup_init(); sama5_pm_init(); } + +static int __init at91_pm_modes_select(char *str) +{ + char *s; + substring_t args[MAX_OPT_ARGS]; + int standby, suspend; + + if (!str) + return 0; + + s = strsep(&str, ","); + standby = match_token(s, pm_modes, args); + if (standby < 0) + return 0; + + suspend = match_token(str, pm_modes, args); + if (suspend < 0) + return 0; + + pm_data.standby_mode = standby; + pm_data.suspend_mode = suspend; + + return 0; +} +early_param("atmel.pm_modes", at91_pm_modes_select); diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index d9c6612ef62f..f95d31496f08 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -33,7 +33,8 @@ struct at91_pm_data { unsigned int mode; void __iomem *shdwc; void __iomem *sfrbu; - unsigned int deepest_state; + unsigned int standby_mode; + unsigned int suspend_mode; }; #endif From 287322386d303891e9cdc81313137054da9d5467 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 26 Apr 2017 16:34:24 +0200 Subject: [PATCH 03/11] ARM: at91: pm: fallback to slowclock when backup mode fails If the backup sram allocation fails, ensure we can suspend by falling back to the usual slow clock mode. Signed-off-by: Alexandre Belloni Acked-by: Wenyou Yang --- arch/arm/mach-at91/pm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index ef9c1d29cc67..fc4026478579 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -544,6 +544,11 @@ sfrbu_fail: securam_fail: iounmap(pm_data.sfrbu); pm_data.sfrbu = NULL; + + if (pm_data.standby_mode == AT91_PM_BACKUP) + pm_data.standby_mode = AT91_PM_SLOW_CLOCK; + if (pm_data.suspend_mode == AT91_PM_BACKUP) + pm_data.suspend_mode = AT91_PM_SLOW_CLOCK; } struct pmc_info { From f0979987c91debc7146fbe1509c2466b44cb9796 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 31 May 2017 03:06:19 +0200 Subject: [PATCH 04/11] ARM: at91: Documentation: add armv7m families The Atmel sams70, samv70 and samv71 are Cortex-M7 based MCUs that can run Linux (without MMU). Acked-by: Nicolas Ferre Signed-off-by: Alexandre Belloni --- Documentation/arm/Atmel/README | 38 +++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/Documentation/arm/Atmel/README b/Documentation/arm/Atmel/README index 6ca78f818dbf..afb13c15389d 100644 --- a/Documentation/arm/Atmel/README +++ b/Documentation/arm/Atmel/README @@ -16,7 +16,7 @@ git branches/tags and email subject always contain this "at91" sub-string. AT91 SoCs --------- -Documentation and detailled datasheet for each product are available on +Documentation and detailed datasheet for each product are available on the Atmel website: http://www.atmel.com. Flavors: @@ -101,6 +101,42 @@ the Atmel website: http://www.atmel.com. + Datasheet http://www.atmel.com/Images/Atmel-11267-32-bit-Cortex-A5-Microcontroller-SAMA5D2_Datasheet.pdf + * ARM Cortex-M7 MCUs + - sams70 family + - sams70j19 + - sams70j20 + - sams70j21 + - sams70n19 + - sams70n20 + - sams70n21 + - sams70q19 + - sams70q20 + - sams70q21 + + Datasheet + http://www.atmel.com/Images/Atmel-11242-32-bit-Cortex-M7-Microcontroller-SAM-S70Q-SAM-S70N-SAM-S70J_Datasheet.pdf + + - samv70 family + - samv70j19 + - samv70j20 + - samv70n19 + - samv70n20 + - samv70q19 + - samv70q20 + + Datasheet + http://www.atmel.com/Images/Atmel-11297-32-bit-Cortex-M7-Microcontroller-SAM-V70Q-SAM-V70N-SAM-V70J_Datasheet.pdf + + - samv71 family + - samv71j19 + - samv71j20 + - samv71j21 + - samv71n19 + - samv71n20 + - samv71n21 + - samv71q19 + - samv71q20 + - samv71q21 + + Datasheet + http://www.atmel.com/Images/Atmel-44003-32-bit-Cortex-M7-Microcontroller-SAM-V71Q-SAM-V71N-SAM-V71J_Datasheet.pdf Linux kernel information ------------------------ From 8a9d600a8e119373fe17555219948d8d235a62d5 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 31 May 2017 03:06:20 +0200 Subject: [PATCH 05/11] ARM: at91: Document armv7m compatibles Introduce necessary compatibles to describe the armv7m based SoCs. Acked-by: Nicolas Ferre Signed-off-by: Alexandre Belloni --- .../devicetree/bindings/arm/atmel-at91.txt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index 799af90dd75b..91cb8e4f2a4f 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -41,6 +41,36 @@ compatible: must be one of: - "atmel,sama5d43" - "atmel,sama5d44" + * "atmel,samv7" for MCUs using a Cortex-M7, shall be extended with the specific + SoC family: + o "atmel,sams70" shall be extended with the specific MCU compatible: + - "atmel,sams70j19" + - "atmel,sams70j20" + - "atmel,sams70j21" + - "atmel,sams70n19" + - "atmel,sams70n20" + - "atmel,sams70n21" + - "atmel,sams70q19" + - "atmel,sams70q20" + - "atmel,sams70q21" + o "atmel,samv70" shall be extended with the specific MCU compatible: + - "atmel,samv70j19" + - "atmel,samv70j20" + - "atmel,samv70n19" + - "atmel,samv70n20" + - "atmel,samv70q19" + - "atmel,samv70q20" + o "atmel,samv71" shall be extended with the specific MCU compatible: + - "atmel,samv71j19" + - "atmel,samv71j20" + - "atmel,samv71j21" + - "atmel,samv71n19" + - "atmel,samv71n20" + - "atmel,samv71n21" + - "atmel,samv71q19" + - "atmel,samv71q20" + - "atmel,samv71q21" + Chipid required properties: - compatible: Should be "atmel,sama5d2-chipid" - reg : Should contain registers location and length From 2d4c44e979eaa846dfa63717c4f4818e11161c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szemz=C5=91=20Andr=C3=A1s?= Date: Wed, 31 May 2017 03:06:21 +0200 Subject: [PATCH 06/11] ARM: at91: Add armv7m support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Atmel SAME70/SAMS70/SAMV71 SoC support. Signed-off-by: Szemző András Acked-by: Nicolas Ferre Signed-off-by: Alexandre Belloni --- arch/arm/mach-at91/Kconfig | 10 +++++++++- arch/arm/mach-at91/Makefile | 1 + arch/arm/mach-at91/Makefile.boot | 3 +++ arch/arm/mach-at91/samv7.c | 25 +++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-at91/Makefile.boot create mode 100644 arch/arm/mach-at91/samv7.c diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 841e924143f9..2594b6a412f0 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -1,12 +1,20 @@ menuconfig ARCH_AT91 bool "Atmel SoCs" - depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V7 + depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V7 || ARM_SINGLE_ARMV7M select COMMON_CLK_AT91 select GPIOLIB select PINCTRL select SOC_BUS if ARCH_AT91 +config SOC_SAMV7 + bool "SAM Cortex-M7 family" if ARM_SINGLE_ARMV7M + select COMMON_CLK_AT91 + select PINCTRL_AT91 + help + Select this if you are using an SoC from Atmel's SAME7, SAMS7 or SAMV7 + families. + config SOC_SAMA5D2 bool "SAMA5D2 family" depends on ARCH_MULTI_V7 diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index cfd8f60a9268..a189081dccc0 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o obj-$(CONFIG_SOC_AT91SAM9) += at91sam9.o obj-$(CONFIG_SOC_SAMA5) += sama5.o +obj-$(CONFIG_SOC_SAMV7) += samv7.o # Power Management obj-$(CONFIG_PM) += pm.o diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot new file mode 100644 index 000000000000..eacfc3f5c33e --- /dev/null +++ b/arch/arm/mach-at91/Makefile.boot @@ -0,0 +1,3 @@ +# Empty file waiting for deletion once Makefile.boot isn't needed any more. +# Patch waits for application at +# http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=7889/1 . diff --git a/arch/arm/mach-at91/samv7.c b/arch/arm/mach-at91/samv7.c new file mode 100644 index 000000000000..11386f190c83 --- /dev/null +++ b/arch/arm/mach-at91/samv7.c @@ -0,0 +1,25 @@ +/* + * Setup code for SAMv7x + * + * Copyright (C) 2013 Atmel, + * 2016 Andras Szemzo + * + * Licensed under GPLv2 or later. + */ +#include +#include +#include +#include +#include +#include +#include +#include "generic.h" + +static const char *const samv7_dt_board_compat[] __initconst = { + "atmel,samv7", + NULL +}; + +DT_MACHINE_START(samv7_dt, "Atmel SAMV7") + .dt_compat = samv7_dt_board_compat, +MACHINE_END From b2f06274337074a64ad42550f336b9f279eb835a Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 31 May 2017 03:06:22 +0200 Subject: [PATCH 07/11] ARM: at91: handle CONFIG_PM for armv7m configurations There is currently no PM support for samx7 but the symbol can still be selected. This avoids compilation issues. Acked-by: Nicolas Ferre Signed-off-by: Alexandre Belloni --- arch/arm/mach-at91/Kconfig | 6 ++++++ arch/arm/mach-at91/Makefile | 3 +-- arch/arm/mach-at91/samv7.c | 9 +++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 2594b6a412f0..7497a28a79d1 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -60,6 +60,7 @@ config SOC_AT91RM9200 bool "AT91RM9200" depends on ARCH_MULTI_V4T select ATMEL_AIC_IRQ + select ATMEL_PM if PM select ATMEL_ST select CPU_ARM920T select HAVE_AT91_USB_CLK @@ -73,6 +74,7 @@ config SOC_AT91SAM9 bool "AT91SAM9" depends on ARCH_MULTI_V5 select ATMEL_AIC_IRQ + select ATMEL_PM if PM select ATMEL_SDRAMC select CPU_ARM926T select HAVE_AT91_SMD @@ -131,9 +133,13 @@ config SOC_SAM_V7 config SOC_SAMA5 bool select ATMEL_AIC5_IRQ + select ATMEL_PM if PM select ATMEL_SDRAMC select MEMORY select SOC_SAM_V7 select SRAM if PM +config ATMEL_PM + bool + endif diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index a189081dccc0..ee34aa34cc51 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -9,8 +9,7 @@ obj-$(CONFIG_SOC_SAMA5) += sama5.o obj-$(CONFIG_SOC_SAMV7) += samv7.o # Power Management -obj-$(CONFIG_PM) += pm.o -obj-$(CONFIG_PM) += pm_suspend.o +obj-$(CONFIG_ATMEL_PM) += pm.o pm_suspend.o ifeq ($(CONFIG_CPU_V7),y) AFLAGS_pm_suspend.o := -march=armv7-a diff --git a/arch/arm/mach-at91/samv7.c b/arch/arm/mach-at91/samv7.c index 11386f190c83..910f0c68db62 100644 --- a/arch/arm/mach-at91/samv7.c +++ b/arch/arm/mach-at91/samv7.c @@ -15,6 +15,15 @@ #include #include "generic.h" +#ifdef CONFIG_PM +/* This function has to be defined for various drivers that are using it */ +int at91_suspend_entering_slow_clock(void) +{ + return 0; +} +EXPORT_SYMBOL(at91_suspend_entering_slow_clock); +#endif + static const char *const samv7_dt_board_compat[] __initconst = { "atmel,samv7", NULL From 82208e7568c29aa687fd93b6702106b21a780b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szemz=C5=91=20Andr=C3=A1s?= Date: Wed, 31 May 2017 03:06:23 +0200 Subject: [PATCH 08/11] ARM: at91: add armv7m SoC detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add SAME70/V71/S70/V70 chip-ids to SoC detection. Signed-off-by: Szemző András Acked-by: Nicolas Ferre Signed-off-by: Alexandre Belloni --- drivers/soc/atmel/soc.c | 24 ++++++++++++++++++++++++ drivers/soc/atmel/soc.h | 26 ++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c index 4790094b498e..c1363c83c352 100644 --- a/drivers/soc/atmel/soc.c +++ b/drivers/soc/atmel/soc.c @@ -106,6 +106,30 @@ static const struct at91_soc __initconst socs[] = { "sama5d43", "sama5d4"), AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH, "sama5d44", "sama5d4"), +#endif +#ifdef CONFIG_SOC_SAMV7 + AT91_SOC(SAME70Q21_CIDR_MATCH, SAME70Q21_EXID_MATCH, + "same70q21", "same7"), + AT91_SOC(SAME70Q20_CIDR_MATCH, SAME70Q20_EXID_MATCH, + "same70q20", "same7"), + AT91_SOC(SAME70Q19_CIDR_MATCH, SAME70Q19_EXID_MATCH, + "same70q19", "same7"), + AT91_SOC(SAMS70Q21_CIDR_MATCH, SAMS70Q21_EXID_MATCH, + "sams70q21", "sams7"), + AT91_SOC(SAMS70Q20_CIDR_MATCH, SAMS70Q20_EXID_MATCH, + "sams70q20", "sams7"), + AT91_SOC(SAMS70Q19_CIDR_MATCH, SAMS70Q19_EXID_MATCH, + "sams70q19", "sams7"), + AT91_SOC(SAMV71Q21_CIDR_MATCH, SAMV71Q21_EXID_MATCH, + "samv71q21", "samv7"), + AT91_SOC(SAMV71Q20_CIDR_MATCH, SAMV71Q20_EXID_MATCH, + "samv71q20", "samv7"), + AT91_SOC(SAMV71Q19_CIDR_MATCH, SAMV71Q19_EXID_MATCH, + "samv71q19", "samv7"), + AT91_SOC(SAMV70Q20_CIDR_MATCH, SAMV70Q20_EXID_MATCH, + "samv70q20", "samv7"), + AT91_SOC(SAMV70Q19_CIDR_MATCH, SAMV70Q19_EXID_MATCH, + "samv70q19", "samv7"), #endif { /* sentinel */ }, }; diff --git a/drivers/soc/atmel/soc.h b/drivers/soc/atmel/soc.h index 228efded5085..a90bd5b0ef8f 100644 --- a/drivers/soc/atmel/soc.h +++ b/drivers/soc/atmel/soc.h @@ -88,4 +88,30 @@ at91_soc_init(const struct at91_soc *socs); #define SAMA5D43_EXID_MATCH 0x00000003 #define SAMA5D44_EXID_MATCH 0x00000004 +#define SAME70Q21_CIDR_MATCH 0x21020e00 +#define SAME70Q21_EXID_MATCH 0x00000002 +#define SAME70Q20_CIDR_MATCH 0x21020c00 +#define SAME70Q20_EXID_MATCH 0x00000002 +#define SAME70Q19_CIDR_MATCH 0x210d0a00 +#define SAME70Q19_EXID_MATCH 0x00000002 + +#define SAMS70Q21_CIDR_MATCH 0x21120e00 +#define SAMS70Q21_EXID_MATCH 0x00000002 +#define SAMS70Q20_CIDR_MATCH 0x21120c00 +#define SAMS70Q20_EXID_MATCH 0x00000002 +#define SAMS70Q19_CIDR_MATCH 0x211d0a00 +#define SAMS70Q19_EXID_MATCH 0x00000002 + +#define SAMV71Q21_CIDR_MATCH 0x21220e00 +#define SAMV71Q21_EXID_MATCH 0x00000002 +#define SAMV71Q20_CIDR_MATCH 0x21220c00 +#define SAMV71Q20_EXID_MATCH 0x00000002 +#define SAMV71Q19_CIDR_MATCH 0x212d0a00 +#define SAMV71Q19_EXID_MATCH 0x00000002 + +#define SAMV70Q20_CIDR_MATCH 0x21320c00 +#define SAMV70Q20_EXID_MATCH 0x00000002 +#define SAMV70Q19_CIDR_MATCH 0x213d0a00 +#define SAMV70Q19_EXID_MATCH 0x00000002 + #endif /* __AT91_SOC_H */ From 63e07c0fdc41d7d585dad72ed01856c68ce52bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szemz=C5=91=20Andr=C3=A1s?= Date: Wed, 31 May 2017 03:06:24 +0200 Subject: [PATCH 09/11] ARM: at91: debug: add samv7x support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for low level debugging on Atmel samv7x. Signed-off-by: Szemző András Acked-by: Nicolas Ferre Signed-off-by: Alexandre Belloni --- arch/arm/Kconfig.debug | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 426d2716f55d..e10fb1842b1d 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -145,6 +145,15 @@ choice Say Y here if you want kernel low-level debugging support on the USART3 port of sama5d4. + config DEBUG_AT91_SAMV7_USART1 + bool "Kernel low-level debugging via SAMV7 USART1" + select DEBUG_AT91_UART + depends on SOC_SAMV7 + help + Say Y here if you want the debug print routines to direct + their output to the USART1 port on SAMV7 based + machines. + config DEBUG_BCM2835 bool "Kernel low-level debugging on BCM2835 PL011 UART" depends on ARCH_BCM2835 && ARCH_MULTI_V6 @@ -1481,6 +1490,7 @@ config DEBUG_UART_PHYS default 0x3f201000 if DEBUG_BCM2836 default 0x3e000000 if DEBUG_BCM_KONA_UART default 0x4000e400 if DEBUG_LL_UART_EFM32 + default 0x40028000 if DEBUG_AT91_SAMV7_USART1 default 0x40081000 if DEBUG_LPC18XX_UART0 default 0x40090000 if DEBUG_LPC32XX default 0x40100000 if DEBUG_PXA_UART1 From be36e000bc2d28512721c6e09c3df920b1bfad5e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Jun 2017 12:18:02 +0200 Subject: [PATCH 10/11] ARM: at91: fix at91_suspend_entering_slow_clock link error When CONFIG_ARCH_AT91 is enabled, but none of the specific SoC support is in use, some at91 specific drivers fail to link: drivers/tty/serial/atmel_serial.o: In function `atmel_serial_suspend': atmel_serial.c:(.text.atmel_serial_suspend+0x1e): undefined reference to `at91_suspend_entering_slow_clock' drivers/usb/host/ohci-at91.o: In function `ohci_hcd_at91_drv_suspend': ohci-at91.c:(.text.ohci_hcd_at91_drv_suspend+0x12): undefined reference to `at91_suspend_entering_slow_clock' drivers/usb/gadget/udc/at91_udc.o: In function `at91udc_suspend': at91_udc.c:(.text.at91udc_suspend+0x26): undefined reference to `at91_suspend_entering_slow_clock' This changes the at91_suspend_entering_slow_clock hack once more, adding an alternative inline implementation that is used exactly in those cases that don't provide the normal implementation. Fixes: c1892c2379d2 ("ARM: at91: handle CONFIG_PM for armv7m configurations") Signed-off-by: Arnd Bergmann Signed-off-by: Alexandre Belloni --- arch/arm/mach-at91/samv7.c | 9 --------- include/linux/platform_data/atmel.h | 7 +++++++ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-at91/samv7.c b/arch/arm/mach-at91/samv7.c index 910f0c68db62..11386f190c83 100644 --- a/arch/arm/mach-at91/samv7.c +++ b/arch/arm/mach-at91/samv7.c @@ -15,15 +15,6 @@ #include #include "generic.h" -#ifdef CONFIG_PM -/* This function has to be defined for various drivers that are using it */ -int at91_suspend_entering_slow_clock(void) -{ - return 0; -} -EXPORT_SYMBOL(at91_suspend_entering_slow_clock); -#endif - static const char *const samv7_dt_board_compat[] __initconst = { "atmel,samv7", NULL diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h index 3c8825b67298..7b6dce7d6d33 100644 --- a/include/linux/platform_data/atmel.h +++ b/include/linux/platform_data/atmel.h @@ -52,6 +52,13 @@ struct atmel_uart_data { }; /* FIXME: this needs a better location, but gets stuff building again */ +#ifdef CONFIG_ATMEL_PM extern int at91_suspend_entering_slow_clock(void); +#else +static inline int at91_suspend_entering_slow_clock(void) +{ + return 0; +} +#endif #endif /* __ATMEL_H__ */ From 8a3d809373c6790b3958f74fa5640aedd4e804dd Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 13 Jun 2017 14:51:07 +0200 Subject: [PATCH 11/11] ARM: at91: remove atmel_nand_data Since AVR32 is gone and the driver rework, struct atmel_nand_data is not used anywhere. Acked-by: Boris Brezillon Signed-off-by: Alexandre Belloni --- include/linux/platform_data/atmel.h | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h index 7b6dce7d6d33..70c5c766628e 100644 --- a/include/linux/platform_data/atmel.h +++ b/include/linux/platform_data/atmel.h @@ -7,8 +7,6 @@ #ifndef __ATMEL_H__ #define __ATMEL_H__ -#include -#include #include /* Compact Flash */ @@ -23,25 +21,6 @@ struct at91_cf_data { #define AT91_IDE_SWAP_A0_A2 0x02 }; - /* NAND / SmartMedia */ -struct atmel_nand_data { - int enable_pin; /* chip enable */ - int det_pin; /* card detect */ - int rdy_pin; /* ready/busy */ - u8 rdy_pin_active_low; /* rdy_pin value is inverted */ - u8 ale; /* address line number connected to ALE */ - u8 cle; /* address line number connected to CLE */ - u8 bus_width_16; /* buswidth is 16 bit */ - u8 ecc_mode; /* ecc mode */ - u8 on_flash_bbt; /* bbt on flash */ - struct mtd_partition *parts; - unsigned int num_parts; - bool has_dma; /* support dma transfer */ - - /* default is false, only for at32ap7000 chip is true */ - bool need_reset_workaround; -}; - /* Serial */ struct atmel_uart_data { int num; /* port num */