mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
SoC for 4.13:
- New suspend/resume mode for sama5d2 - Initial support for armv7m based SoCs -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEXx9Viay1+e7J/aM4AyWl4gNJNJIFAllEBAgACgkQAyWl4gNJ NJI+xA//S3Wkndjt/XXl1LMbl0iakv4qkLNBg7VPAO9NHZp5sLPf4MFbqvJMSiv4 mq+nCVKyQetj6tQnVTyp/vXu4alK8GmYqgKbnr4taoapM/9/6whiDwEMU+/F6BVy q9iGAsqDpgjnTsc7VZoUt0+N45dCiAP68zgSVSxdttEDDKIFOvEq0TK9oRW2YZZa pd39C9Jly+0JSik4t9Fuk7/E40sOLQ4QAQT6z82B8XfIdN1s9hdflgAn1JMvDGRh BgEg4wKGf7LZEP2fhJhX+dhXnhImnebOXXGCXOUdSGKBkLplHe30w9SJ8TodL/7L 2QC18NObx40R04GpV5a55Ln/gAWfOJpcXYAMNrJ+J080Vc7YRHvVY6LJsKxP5+yV +FmC5+jB1w5ndfPr2Rz+26S9C0PvfrCYTk2liXohvfKdj1kRjPMds7nYtW0ADAPX E4Ba8TG90h68sC5ojyC4gsnWYnLWPf8rBfYfaPpxWniaIuCzncOPAkRFvJjrDorD u5shFW1EFiIjNPmQOenXJ4sIh2DO75T7aRSztsmrVsxiHzQ8wMW/dVCiHYfOgn/m yccN91ljv4/69nwsxoqEULdWkXV9vrdzc3iLKE0lZGpFForiW/gtmd2EXq/WqbJ9 SGQMEURwvVyiAOmlAtJuCSkPIrs1yOPtSCb465oUverkOpaBp/8= =JHP9 -----END PGP SIGNATURE----- Merge tag 'at91-ab-4.13-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux into next/soc 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>
This commit is contained in:
commit
5a55029f46
@ -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
|
||||
------------------------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
3
arch/arm/mach-at91/Makefile.boot
Normal file
3
arch/arm/mach-at91/Makefile.boot
Normal file
@ -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 .
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
25
arch/arm/mach-at91/samv7.c
Normal file
25
arch/arm/mach-at91/samv7.c
Normal file
@ -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
|
@ -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 */ },
|
||||
};
|
||||
|
@ -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 */
|
||||
|
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user