]> git.karo-electronics.de Git - karo-tx-linux.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>
1  2 
arch/arm/Kconfig.debug
arch/arm/mach-at91/pm.c

diff --combined arch/arm/Kconfig.debug
index fa5eabbbbfcd7f17dd2132b8bf717075906d1e9d,e10fb1842b1d98a229731bdf0236d2089df16b52..447629d89884fd1ed600227a676b339fd9c256e1
@@@ -145,6 -145,15 +145,15 @@@ choic
                  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
                  ARCH      DEBUG_UART_PHYS   DEBUG_UART_VIRT
                  APQ8064   0x16640000        0xf0040000
                  APQ8084   0xf995e000        0xfa75e000
 +                IPQ4019   0x078af000        0xf78af000
                  MSM8X60   0x19c40000        0xf0040000
                  MSM8960   0x16440000        0xf0040000
                  MSM8974   0xf991e000        0xfa71e000
                  their output to the standard serial port on the RealView
                  PB1176 platform.
  
 +      config DEBUG_RV1108_UART0
 +              bool "Kernel low-level debugging messages via Rockchip RV1108 UART0"
 +              depends on ARCH_ROCKCHIP
 +              select DEBUG_UART_8250
 +              help
 +                Say Y here if you want kernel low-level debugging support
 +                  on Rockchip RV1108 based platforms.
 +
 +      config DEBUG_RV1108_UART1
 +              bool "Kernel low-level debugging messages via Rockchip RV1108 UART1"
 +              depends on ARCH_ROCKCHIP
 +              select DEBUG_UART_8250
 +              help
 +                Say Y here if you want kernel low-level debugging support
 +                on Rockchip RV1108 based platforms.
 +
 +      config DEBUG_RV1108_UART2
 +              bool "Kernel low-level debugging messages via Rockchip RV1108 UART2"
 +              depends on ARCH_ROCKCHIP
 +              select DEBUG_UART_8250
 +              help
 +                Say Y here if you want kernel low-level debugging support
 +                on Rockchip RV1108 based platforms.
 +
        config DEBUG_RK29_UART0
                bool "Kernel low-level debugging messages via Rockchip RK29 UART0"
                depends on ARCH_ROCKCHIP
@@@ -1490,9 -1474,6 +1499,9 @@@ config DEBUG_UART_PHY
        default 0x10126000 if DEBUG_RK3X_UART1
        default 0x101f1000 if DEBUG_VERSATILE
        default 0x101fb000 if DEBUG_NOMADIK_UART
 +      default 0x10210000 if DEBUG_RV1108_UART2
 +      default 0x10220000 if DEBUG_RV1108_UART1
 +      default 0x10230000 if DEBUG_RV1108_UART0
        default 0x11002000 if DEBUG_MT8127_UART0
        default 0x11006000 if DEBUG_MT6589_UART0
        default 0x11009000 if DEBUG_MT8135_UART3
        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
  
  config DEBUG_UART_VIRT
        hex "Virtual base address of debug UART"
 +      default 0xc881f000 if DEBUG_RV1108_UART2
 +      default 0xc8821000 if DEBUG_RV1108_UART1
 +      default 0xc8912000 if DEBUG_RV1108_UART0
        default 0xe0000a00 if DEBUG_NETX_UART
        default 0xe0010fe0 if ARCH_RPC
        default 0xf0000be0 if ARCH_EBSA110
diff --combined arch/arm/mach-at91/pm.c
index 283e79ab587de91405e0b579fb16d202ca5072b7,fc4026478579dce9259a6a130415c08c805d666f..667fddac38561eff3f25788ccbf9e05ac8214d84
@@@ -15,6 -15,7 +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 +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 +39,17 @@@ extern void at91_pinctrl_gpio_suspend(v
  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 +70,33 @@@ static int at91_pm_valid_state(suspend_
        }
  }
  
+ 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 +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 +153,65 @@@ static void (*at91_suspend_sram_fn)(str
  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;
        }
  
  error:
-       target_state = PM_SUSPEND_ON;
  #ifdef CONFIG_PINCTRL_AT91
        at91_pinctrl_gpio_resume();
  #endif
   */
  static void at91_pm_end(void)
  {
-       target_state = PM_SUSPEND_ON;
  }
  
  
@@@ -335,7 -377,7 +377,7 @@@ static const struct ramc_info ramc_info
        { .idle = sama5d3_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
  };
  
 -static const struct of_device_id const ramc_ids[] __initconst = {
 +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] },
@@@ -436,6 -478,79 +478,79 @@@ static void __init at91_pm_sram_init(vo
                        &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 +596,14 @@@ static void __init at91_pm_init(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 +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);