]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge tag 'at91-ab-4.13-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/abellon...
authorOlof Johansson <olof@lixom.net>
Mon, 19 Jun 2017 05:53:20 +0000 (22:53 -0700)
committerOlof Johansson <olof@lixom.net>
Mon, 19 Jun 2017 05:53:20 +0000 (22:53 -0700)
SoC for 4.13:

 - New suspend/resume mode for sama5d2
 - Initial support for armv7m based SoCs

* tag 'at91-ab-4.13-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux:
  ARM: at91: remove atmel_nand_data
  ARM: at91: fix at91_suspend_entering_slow_clock link error
  ARM: at91: debug: add samv7x support
  ARM: at91: add armv7m SoC detection
  ARM: at91: handle CONFIG_PM for armv7m configurations
  ARM: at91: Add armv7m support
  ARM: at91: Document armv7m compatibles
  ARM: at91: Documentation: add armv7m families
  ARM: at91: pm: fallback to slowclock when backup mode fails
  ARM: at91: pm: allow selecting standby and suspend modes
  ARM: at91: pm: Add sama5d2 backup mode

Signed-off-by: Olof Johansson <olof@lixom.net>
16 files changed:
Documentation/arm/Atmel/README
Documentation/devicetree/bindings/arm/atmel-at91.txt
arch/arm/Kconfig.debug
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/Makefile.boot [new file with mode: 0644]
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm.h
arch/arm/mach-at91/pm_data-offsets.c
arch/arm/mach-at91/pm_suspend.S
arch/arm/mach-at91/sama5.c
arch/arm/mach-at91/samv7.c [new file with mode: 0644]
drivers/soc/atmel/soc.c
drivers/soc/atmel/soc.h
include/linux/platform_data/atmel.h

index 6ca78f818dbf03be4120da8ff3284b9534664a1c..afb13c15389de1bb7a38c47a80f10d4a2d136cc2 100644 (file)
@@ -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
 ------------------------
index 799af90dd75b09b4c28e85bbcf36db0604d63bd2..91cb8e4f2a4f3cec3bb9231b3ea1f7cb4cfd1169 100644 (file)
@@ -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
index fa5eabbbbfcd7f17dd2132b8bf717075906d1e9d..447629d89884fd1ed600227a676b339fd9c256e1 100644 (file)
@@ -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
@@ -1509,6 +1518,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
index 841e924143f90e089bae9269acacdff65ab597f9..7497a28a79d12cbd88c53f05ce9b45743c6855df 100644 (file)
@@ -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
@@ -52,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
@@ -65,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
@@ -123,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
index cfd8f60a9268f85f30048e92949c0d13051e71d8..ee34aa34cc51ec284ae2de38376d97f179c414c6 100644 (file)
@@ -6,10 +6,10 @@
 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
-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/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
new file mode 100644 (file)
index 0000000..eacfc3f
--- /dev/null
@@ -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 .
index f1ead0f13c19e053a1ffaddd9c031b6f9c9fb978..e2bd172379648548d35e942ad705cf56cb09655d 100644 (file)
 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 */
index 283e79ab587de91405e0b579fb16d202ca5072b7..667fddac38561eff3f25788ccbf9e05ac8214d84 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of_address.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/parser.h>
 #include <linux/suspend.h>
 
 #include <linux/clk/at91_pmc.h>
@@ -22,6 +23,7 @@
 #include <asm/cacheflush.h>
 #include <asm/fncpy.h>
 #include <asm/system_misc.h>
+#include <asm/suspend.h>
 
 #include "generic.h"
 #include "pm.h"
@@ -37,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)
@@ -58,15 +70,33 @@ static int at91_pm_valid_state(suspend_state_t state)
        }
 }
 
+static int canary = 0xA5A5A5A5;
 
-static suspend_state_t target_state;
+static struct at91_pm_bu {
+       int suspended;
+       unsigned long reserved;
+       phys_addr_t canary;
+       phys_addr_t resume;
+} *pm_bu;
 
 /*
  * 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;
 }
 
@@ -115,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);
 
@@ -123,50 +153,65 @@ 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.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();
 }
 
+/*
+ * 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;
@@ -177,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
@@ -190,7 +233,6 @@ error:
  */
 static void at91_pm_end(void)
 {
-       target_state = PM_SUSPEND_ON;
 }
 
 
@@ -436,6 +478,79 @@ 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;
+
+       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");
+       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;
+
+       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 {
        unsigned long uhp_udp_mask;
 };
@@ -481,10 +596,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)
@@ -510,3 +629,34 @@ 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();
+}
+
+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);
index fc0f7d048187b68a7e2e504fb143f1d6046ddca6..f95d31496f08f496242798b7d26911b1098ef363 100644 (file)
@@ -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,10 @@ struct at91_pm_data {
        unsigned long uhp_udp_mask;
        unsigned int memctrl;
        unsigned int mode;
+       void __iomem *shdwc;
+       void __iomem *sfrbu;
+       unsigned int standby_mode;
+       unsigned int suspend_mode;
 };
 #endif
 
index 30302cb16df0656f2bf8a61021edd44cf907678f..c0a73e62b7256b244c687e1755272a823c9f7319 100644 (file)
@@ -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;
 }
index 96781daa671a33f15d8939da690eeeed3d44f9f4..daca91feea6a2603bf45822684adfcd5cf3e9c83 100644 (file)
@@ -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:
index 6d157d0ead8e3d61b474212d538c7a2de86a3b70..3d0bf95a56ae3a5b73e96be21bd0edba2c05b61a 100644 (file)
@@ -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
diff --git a/arch/arm/mach-at91/samv7.c b/arch/arm/mach-at91/samv7.c
new file mode 100644 (file)
index 0000000..11386f1
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  Setup code for SAMv7x
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2016 Andras Szemzo <szemzo.andras@gmail.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/system_misc.h>
+#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
index 4790094b498e07ed5095c6afe76625f46472974e..c1363c83c352a269a0c604816fcf18a34cbd9cc7 100644 (file)
@@ -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 */ },
 };
index 228efded5085da6f93947788164daa67f7f03195..a90bd5b0ef8f52aab099270183ddc8b280d7d932 100644 (file)
@@ -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 */
index 3c8825b67298fafe60f22c803206f9f0789fc8f7..70c5c766628e17957620651eb6822dcbcb8b7e6e 100644 (file)
@@ -7,8 +7,6 @@
 #ifndef __ATMEL_H__
 #define __ATMEL_H__
 
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
 #include <linux/serial.h>
 
  /* 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 */
@@ -52,6 +31,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__ */