- add new SoC based on a Cortex-A7 core: the SAMA7G5 family
   - mach-at91 entry, Kconfig and header files
   - Power Management Controller (PMC) code and associated power management
     changes. Support for suspend/resume, Ultra Low Power modes and
     Backup with Memory in Self-Refresh mode.
   - Power management association with DDR controller and
     shutdown controller for addressing this variety of modes.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQQ5TRCVIBiyi/S+BG4fOrpwrNPNDAUCYQpPnQAKCRAfOrpwrNPN
 DJyeAQDvS538E7jFPdsmUn3iZhMhV4zCZVsPk9fox9ptV8ewEAD/QuWFZg78YkZE
 vGe/AXlxjA4V/TMiGElf0/nbZ8xLiw4=
 =YucO
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmEKnQEACgkQmmx57+YA
 GNnU8g/+OZx39NCFnyUcUUmdFHEl/tn6Vkcirs9abdkpjSSylXLJnIVuimHZy0d5
 oxDc3H83dIhCxLO5my27y8QH5e41dhCD7gVIxf+MF/RCYzGt+BjXiImt6YTOvrK9
 hEFzO49XkiBSTtXpNER6hk5BWuIVAg4b1bFnzrhH9ajGxMCboubsxuRMlRP7t4ad
 Vg8Rgf4TOY1AgMm6P5zVjjMAij4C3uKcOO8WLZA9zVGFlKdftdDCvYBfojitctho
 O97Hg4tSYb4N+l8UPcD+dIie0L7Pp8QtgNjV2MiT/Nyuhewdf1DyH14cFSNxIrmA
 laVeRU5WPXJwxNdnEYukb1yI6TEKFQDHTksGWkHr0cQkxalHhuegNUczVwHgZaEZ
 j6pk1yskhRtqmwMyt/810lrEB/o01aPX2TldGda3h3XUxe4q/mw4QR7j9fIFDzjY
 06S5LH/kL36kJ7QAV6ppQLFjBJ5+UJFHymHSXnsCNnaeD6mSZxncaLDoNt+O90kE
 IdALvvwq1ggbKDTQVgpIyU1XfYaNdXcbX1hACXP2LO5/MQejgQ2KJNtS1Qk1aLCC
 T161nfyi/YW5o7h70JGpNK9go5lj/60MgGtocQ5d+zxzyUKNCARaiYRjy0xP7/KR
 1eftv0qgk+J+3+NYOGroLaixVbfLWlIjD9hyaMDnGKzYB857nSY=
 =+KcA
 -----END PGP SIGNATURE-----

Merge tag 'at91-soc-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux into arm/soc

AT91 soc for 5.15:

- add new SoC based on a Cortex-A7 core: the SAMA7G5 family
  - mach-at91 entry, Kconfig and header files
  - Power Management Controller (PMC) code and associated power management
    changes. Support for suspend/resume, Ultra Low Power modes and
    Backup with Memory in Self-Refresh mode.
  - Power management association with DDR controller and
    shutdown controller for addressing this variety of modes.

* tag 'at91-soc-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux: (26 commits)
  ARM: at91: pm: add sama7g5 shdwc
  ARM: at91: pm: add pm support for SAMA7G5
  ARM: at91: sama7: introduce sama7 SoC family
  ARM: at91: pm: add sama7g5's pmc
  ARM: at91: pm: add backup mode support for SAMA7G5
  ARM: at91: pm: save ddr phy calibration data to securam
  ARM: at91: pm: add sama7g5 ddr phy controller
  ARM: at91: pm: add sama7g5 ddr controller
  ARM: at91: pm: wait for ddr power mode off
  ARM: at91: pm: add support for 2.5V LDO regulator control
  ARM: at91: pm: add support for MCK1..4 save/restore for ulp modes
  ARM: at91: pm: add self-refresh support for sama7g5
  ARM: at91: ddr: add registers definitions for sama7g5's ddr
  ARM: at91: sfrbu: add sfrbu registers definitions for sama7g5
  ARM: at91: pm: add support for waiting MCK1..4
  ARM: at91: pm: s/CONFIG_SOC_SAM9X60/CONFIG_HAVE_AT91_SAM9X60_PLL/g
  ARM: at91: pm: avoid push and pop on stack while memory is in self-refersh
  ARM: at91: pm: use r7 instead of tmp1
  ARM: at91: pm: do not initialize pdev
  ARM: at91: pm: check for different controllers in at91_pm_modes_init()
  ...

Link: https://lore.kernel.org/r/20210804084316.12641-1-nicolas.ferre@microchip.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2021-08-04 15:58:24 +02:00
Родитель 12c3dca25d ad9bc2e35c
Коммит 318845985f
12 изменённых файлов: 1094 добавлений и 293 удалений

Просмотреть файл

@ -193,6 +193,14 @@ choice
their output to the USART1 port on SAMV7 based
machines.
config DEBUG_AT91_SAMA7G5_FLEXCOM3
bool "Kernel low-level debugging on SAMA7G5 FLEXCOM3"
select DEBUG_AT91_UART
depends on SOC_SAMA7G5
help
Say Y here if you want kernel low-level debugging support
on the FLEXCOM3 port of SAMA7G5.
config DEBUG_BCM2835
bool "Kernel low-level debugging on BCM2835 PL011 UART"
depends on ARCH_BCM2835 && ARCH_MULTI_V6
@ -1668,6 +1676,7 @@ config DEBUG_UART_PHYS
default 0xd4017000 if DEBUG_MMP_UART2
default 0xd4018000 if DEBUG_MMP_UART3
default 0xe0000000 if DEBUG_SPEAR13XX
default 0xe1824200 if DEBUG_AT91_SAMA7G5_FLEXCOM3
default 0xe4007000 if DEBUG_HIP04_UART
default 0xe6c40000 if DEBUG_RMOBILE_SCIFA0
default 0xe6c50000 if DEBUG_RMOBILE_SCIFA1
@ -1729,6 +1738,7 @@ config DEBUG_UART_VIRT
default 0xc8821000 if DEBUG_RV1108_UART1
default 0xc8912000 if DEBUG_RV1108_UART0
default 0xe0010fe0 if ARCH_RPC
default 0xe0824200 if DEBUG_AT91_SAMA7G5_FLEXCOM3
default 0xf0010000 if DEBUG_ASM9260_UART
default 0xf0100000 if DEBUG_DIGICOLOR_UA0
default 0xf01fb000 if DEBUG_NOMADIK_UART

Просмотреть файл

@ -57,6 +57,16 @@ config SOC_SAMA5D4
help
Select this if you are using one of Microchip's SAMA5D4 family SoC.
config SOC_SAMA7G5
bool "SAMA7G5 family"
depends on ARCH_MULTI_V7
select HAVE_AT91_GENERATED_CLK
select HAVE_AT91_SAM9X60_PLL
select HAVE_AT91_UTMI
select SOC_SAMA7
help
Select this if you are using one of Microchip's SAMA7G5 family SoC.
config SOC_AT91RM9200
bool "AT91RM9200"
depends on ARCH_MULTI_V4T
@ -191,4 +201,12 @@ config SOC_SAMA5
config ATMEL_PM
bool
config SOC_SAMA7
bool
select ARM_GIC
select ATMEL_PM if PM
select ATMEL_SDRAMC
select MEMORY
select SOC_SAM_V7
select SRAM if PM
endif

Просмотреть файл

@ -8,6 +8,7 @@ obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o
obj-$(CONFIG_SOC_AT91SAM9) += at91sam9.o
obj-$(CONFIG_SOC_SAM9X60) += sam9x60.o
obj-$(CONFIG_SOC_SAMA5) += sama5.o
obj-$(CONFIG_SOC_SAMA7) += sama7.o
obj-$(CONFIG_SOC_SAMV7) += samv7.o
# Power Management

Просмотреть файл

@ -14,12 +14,14 @@ extern void __init at91sam9_pm_init(void);
extern void __init sam9x60_pm_init(void);
extern void __init sama5_pm_init(void);
extern void __init sama5d2_pm_init(void);
extern void __init sama7_pm_init(void);
#else
static inline void __init at91rm9200_pm_init(void) { }
static inline void __init at91sam9_pm_init(void) { }
static inline void __init sam9x60_pm_init(void) { }
static inline void __init sama5_pm_init(void) { }
static inline void __init sama5d2_pm_init(void) { }
static inline void __init sama7_pm_init(void) { }
#endif
#endif /* _AT91_GENERIC_H */

Просмотреть файл

@ -10,6 +10,7 @@
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <linux/parser.h>
#include <linux/suspend.h>
@ -27,13 +28,55 @@
#include "generic.h"
#include "pm.h"
#define BACKUP_DDR_PHY_CALIBRATION (9)
/**
* struct at91_pm_bu - AT91 power management backup unit data structure
* @suspended: true if suspended to backup mode
* @reserved: reserved
* @canary: canary data for memory checking after exit from backup mode
* @resume: resume API
* @ddr_phy_calibration: DDR PHY calibration data: ZQ0CR0, first 8 words
* of the memory
*/
struct at91_pm_bu {
int suspended;
unsigned long reserved;
phys_addr_t canary;
phys_addr_t resume;
unsigned long ddr_phy_calibration[BACKUP_DDR_PHY_CALIBRATION];
};
/**
* struct at91_soc_pm - AT91 SoC power management data structure
* @config_shdwc_ws: wakeup sources configuration function for SHDWC
* @config_pmc_ws: wakeup srouces configuration function for PMC
* @ws_ids: wakup sources of_device_id array
* @data: PM data to be used on last phase of suspend
* @bu: backup unit mapped data (for backup mode)
* @memcs: memory chip select
*/
struct at91_soc_pm {
int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity);
const struct of_device_id *ws_ids;
struct at91_pm_bu *bu;
struct at91_pm_data data;
void *memcs;
};
/**
* enum at91_pm_iomaps: IOs that needs to be mapped for different PM modes
* @AT91_PM_IOMAP_SHDWC: SHDWC controller
* @AT91_PM_IOMAP_SFRBU: SFRBU controller
*/
enum at91_pm_iomaps {
AT91_PM_IOMAP_SHDWC,
AT91_PM_IOMAP_SFRBU,
};
#define AT91_PM_IOMAP(name) BIT(AT91_PM_IOMAP_##name)
static struct at91_soc_pm soc_pm = {
.data = {
.standby_mode = AT91_PM_STANDBY,
@ -71,13 +114,6 @@ 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;
struct wakeup_source_info {
unsigned int pmc_fsmr_bit;
unsigned int shdwc_mr_bit;
@ -116,6 +152,17 @@ static const struct of_device_id sam9x60_ws_ids[] = {
{ /* sentinel */ }
};
static const struct of_device_id sama7g5_ws_ids[] = {
{ .compatible = "atmel,at91sam9x5-rtc", .data = &ws_info[1] },
{ .compatible = "microchip,sama7g5-ohci", .data = &ws_info[2] },
{ .compatible = "usb-ohci", .data = &ws_info[2] },
{ .compatible = "atmel,at91sam9g45-ehci", .data = &ws_info[2] },
{ .compatible = "usb-ehci", .data = &ws_info[2] },
{ .compatible = "microchip,sama7g5-sdhci", .data = &ws_info[3] },
{ .compatible = "atmel,at91sam9260-rtt", .data = &ws_info[4] },
{ /* sentinel */ }
};
static int at91_pm_config_ws(unsigned int pm_mode, bool set)
{
const struct wakeup_source_info *wsi;
@ -206,6 +253,8 @@ static int at91_sam9x60_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity)
*/
static int at91_pm_begin(suspend_state_t state)
{
int ret;
switch (state) {
case PM_SUSPEND_MEM:
soc_pm.data.mode = soc_pm.data.suspend_mode;
@ -219,7 +268,16 @@ static int at91_pm_begin(suspend_state_t state)
soc_pm.data.mode = -1;
}
return at91_pm_config_ws(soc_pm.data.mode, true);
ret = at91_pm_config_ws(soc_pm.data.mode, true);
if (ret)
return ret;
if (soc_pm.data.mode == AT91_PM_BACKUP)
soc_pm.bu->suspended = 1;
else if (soc_pm.bu)
soc_pm.bu->suspended = 0;
return 0;
}
/*
@ -277,6 +335,19 @@ extern u32 at91_pm_suspend_in_sram_sz;
static int at91_suspend_finish(unsigned long val)
{
int i;
if (soc_pm.data.mode == AT91_PM_BACKUP && soc_pm.data.ramc_phy) {
/*
* The 1st 8 words of memory might get corrupted in the process
* of DDR PHY recalibration; it is saved here in securam and it
* will be restored later, after recalibration, by bootloader
*/
for (i = 1; i < BACKUP_DDR_PHY_CALIBRATION; i++)
soc_pm.bu->ddr_phy_calibration[i] =
*((unsigned int *)soc_pm.memcs + (i - 1));
}
flush_cache_all();
outer_disable();
@ -288,8 +359,6 @@ static int at91_suspend_finish(unsigned long val)
static void at91_pm_suspend(suspend_state_t state)
{
if (soc_pm.data.mode == AT91_PM_BACKUP) {
pm_bu->suspended = 1;
cpu_suspend(0, at91_suspend_finish);
/* The SRAM is lost between suspend cycles */
@ -511,10 +580,16 @@ static const struct of_device_id ramc_ids[] __initconst = {
{ .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] },
{ .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] },
{ .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[3] },
{ .compatible = "microchip,sama7g5-uddrc", },
{ /*sentinel*/ }
};
static __init void at91_dt_ramc(void)
static const struct of_device_id ramc_phy_ids[] __initconst = {
{ .compatible = "microchip,sama7g5-ddr3phy", },
{ /* Sentinel. */ },
};
static __init void at91_dt_ramc(bool phy_mandatory)
{
struct device_node *np;
const struct of_device_id *of_id;
@ -528,9 +603,11 @@ static __init void at91_dt_ramc(void)
panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx);
ramc = of_id->data;
if (!standby)
standby = ramc->idle;
soc_pm.data.memctrl = ramc->memctrl;
if (ramc) {
if (!standby)
standby = ramc->idle;
soc_pm.data.memctrl = ramc->memctrl;
}
idx++;
}
@ -538,6 +615,16 @@ static __init void at91_dt_ramc(void)
if (!idx)
panic(pr_fmt("unable to find compatible ram controller node in dtb\n"));
/* Lookup for DDR PHY node, if any. */
for_each_matching_node_and_match(np, ramc_phy_ids, &of_id) {
soc_pm.data.ramc_phy = of_iomap(np, 0);
if (!soc_pm.data.ramc_phy)
panic(pr_fmt("unable to map ramc phy cpu registers\n"));
}
if (phy_mandatory && !soc_pm.data.ramc_phy)
panic(pr_fmt("DDR PHY is mandatory!\n"));
if (!standby) {
pr_warn("ramc no standby function available\n");
return;
@ -618,37 +705,57 @@ static bool __init at91_is_pm_mode_active(int pm_mode)
soc_pm.data.suspend_mode == pm_mode);
}
static int __init at91_pm_backup_scan_memcs(unsigned long node,
const char *uname, int depth,
void *data)
{
const char *type;
const __be32 *reg;
int *located = data;
int size;
/* Memory node already located. */
if (*located)
return 0;
type = of_get_flat_dt_prop(node, "device_type", NULL);
/* We are scanning "memory" nodes only. */
if (!type || strcmp(type, "memory"))
return 0;
reg = of_get_flat_dt_prop(node, "reg", &size);
if (reg) {
soc_pm.memcs = __va((phys_addr_t)be32_to_cpu(*reg));
*located = 1;
}
return 0;
}
static int __init at91_pm_backup_init(void)
{
struct gen_pool *sram_pool;
struct device_node *np;
struct platform_device *pdev = NULL;
int ret = -ENODEV;
struct platform_device *pdev;
int ret = -ENODEV, located = 0;
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2) &&
!IS_ENABLED(CONFIG_SOC_SAMA7G5))
return -EPERM;
if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
return 0;
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
if (!np) {
pr_warn("%s: failed to find sfrbu!\n", __func__);
return ret;
}
soc_pm.data.sfrbu = of_iomap(np, 0);
of_node_put(np);
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
if (!np)
goto securam_fail_no_ref_dev;
return ret;
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_no_ref_dev;
return ret;
}
sram_pool = gen_pool_get(&pdev->dev, NULL);
@ -657,79 +764,117 @@ static int __init at91_pm_backup_init(void)
goto securam_fail;
}
pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
if (!pm_bu) {
soc_pm.bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
if (!soc_pm.bu) {
pr_warn("%s: unable to alloc securam!\n", __func__);
ret = -ENOMEM;
goto securam_fail;
}
pm_bu->suspended = 0;
pm_bu->canary = __pa_symbol(&canary);
pm_bu->resume = __pa_symbol(cpu_resume);
soc_pm.bu->suspended = 0;
soc_pm.bu->canary = __pa_symbol(&canary);
soc_pm.bu->resume = __pa_symbol(cpu_resume);
if (soc_pm.data.ramc_phy) {
of_scan_flat_dt(at91_pm_backup_scan_memcs, &located);
if (!located)
goto securam_fail;
/* DDR3PHY_ZQ0SR0 */
soc_pm.bu->ddr_phy_calibration[0] = readl(soc_pm.data.ramc_phy +
0x188);
}
return 0;
securam_fail:
put_device(&pdev->dev);
securam_fail_no_ref_dev:
iounmap(soc_pm.data.sfrbu);
soc_pm.data.sfrbu = NULL;
return ret;
}
static void __init at91_pm_use_default_mode(int pm_mode)
{
if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
return;
if (soc_pm.data.standby_mode == pm_mode)
soc_pm.data.standby_mode = AT91_PM_ULP0;
if (soc_pm.data.suspend_mode == pm_mode)
soc_pm.data.suspend_mode = AT91_PM_ULP0;
}
static const struct of_device_id atmel_shdwc_ids[] = {
{ .compatible = "atmel,sama5d2-shdwc" },
{ .compatible = "microchip,sam9x60-shdwc" },
{ .compatible = "microchip,sama7g5-shdwc" },
{ /* sentinel. */ }
};
static void __init at91_pm_modes_init(void)
static void __init at91_pm_modes_init(const u32 *maps, int len)
{
struct device_node *np;
int ret;
if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
!at91_is_pm_mode_active(AT91_PM_ULP1))
return;
np = of_find_matching_node(NULL, atmel_shdwc_ids);
if (!np) {
pr_warn("%s: failed to find shdwc!\n", __func__);
goto ulp1_default;
}
soc_pm.data.shdwc = of_iomap(np, 0);
of_node_put(np);
int ret, mode;
ret = at91_pm_backup_init();
if (ret) {
if (!at91_is_pm_mode_active(AT91_PM_ULP1))
goto unmap;
else
goto backup_default;
if (soc_pm.data.standby_mode == AT91_PM_BACKUP)
soc_pm.data.standby_mode = AT91_PM_ULP0;
if (soc_pm.data.suspend_mode == AT91_PM_BACKUP)
soc_pm.data.suspend_mode = AT91_PM_ULP0;
}
if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC) ||
maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC)) {
np = of_find_matching_node(NULL, atmel_shdwc_ids);
if (!np) {
pr_warn("%s: failed to find shdwc!\n", __func__);
/* Use ULP0 if it doesn't needs SHDWC.*/
if (!(maps[AT91_PM_ULP0] & AT91_PM_IOMAP(SHDWC)))
mode = AT91_PM_ULP0;
else
mode = AT91_PM_STANDBY;
if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC))
soc_pm.data.standby_mode = mode;
if (maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC))
soc_pm.data.suspend_mode = mode;
} else {
soc_pm.data.shdwc = of_iomap(np, 0);
of_node_put(np);
}
}
if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU) ||
maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU)) {
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
if (!np) {
pr_warn("%s: failed to find sfrbu!\n", __func__);
/*
* Use ULP0 if it doesn't need SHDWC or if SHDWC
* was already located.
*/
if (!(maps[AT91_PM_ULP0] & AT91_PM_IOMAP(SHDWC)) ||
soc_pm.data.shdwc)
mode = AT91_PM_ULP0;
else
mode = AT91_PM_STANDBY;
if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU))
soc_pm.data.standby_mode = mode;
if (maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU))
soc_pm.data.suspend_mode = mode;
} else {
soc_pm.data.sfrbu = of_iomap(np, 0);
of_node_put(np);
}
}
/* Unmap all unnecessary. */
if (soc_pm.data.shdwc &&
!(maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC) ||
maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC))) {
iounmap(soc_pm.data.shdwc);
soc_pm.data.shdwc = NULL;
}
if (soc_pm.data.sfrbu &&
!(maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU) ||
maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU))) {
iounmap(soc_pm.data.sfrbu);
soc_pm.data.sfrbu = NULL;
}
return;
unmap:
iounmap(soc_pm.data.shdwc);
soc_pm.data.shdwc = NULL;
ulp1_default:
at91_pm_use_default_mode(AT91_PM_ULP1);
backup_default:
at91_pm_use_default_mode(AT91_PM_BACKUP);
}
struct pmc_info {
@ -764,6 +909,11 @@ static const struct pmc_info pmc_infos[] __initconst = {
.mckr = 0x28,
.version = AT91_PMC_V2,
},
{
.mckr = 0x28,
.version = AT91_PMC_V2,
},
};
static const struct of_device_id atmel_pmc_ids[] __initconst = {
@ -779,6 +929,7 @@ static const struct of_device_id atmel_pmc_ids[] __initconst = {
{ .compatible = "atmel,sama5d4-pmc", .data = &pmc_infos[1] },
{ .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] },
{ .compatible = "microchip,sam9x60-pmc", .data = &pmc_infos[4] },
{ .compatible = "microchip,sama7g5-pmc", .data = &pmc_infos[5] },
{ /* sentinel */ },
};
@ -877,7 +1028,7 @@ void __init at91rm9200_pm_init(void)
soc_pm.data.standby_mode = AT91_PM_STANDBY;
soc_pm.data.suspend_mode = AT91_PM_ULP0;
at91_dt_ramc();
at91_dt_ramc(false);
/*
* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh.
@ -892,13 +1043,16 @@ void __init sam9x60_pm_init(void)
static const int modes[] __initconst = {
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
};
static const int iomaps[] __initconst = {
[AT91_PM_ULP1] = AT91_PM_IOMAP(SHDWC),
};
if (!IS_ENABLED(CONFIG_SOC_SAM9X60))
return;
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_pm_modes_init();
at91_dt_ramc();
at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
at91_dt_ramc(false);
at91_pm_init(NULL);
soc_pm.ws_ids = sam9x60_ws_ids;
@ -918,7 +1072,7 @@ void __init at91sam9_pm_init(void)
soc_pm.data.standby_mode = AT91_PM_STANDBY;
soc_pm.data.suspend_mode = AT91_PM_ULP0;
at91_dt_ramc();
at91_dt_ramc(false);
at91_pm_init(at91sam9_idle);
}
@ -932,7 +1086,7 @@ void __init sama5_pm_init(void)
return;
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_dt_ramc();
at91_dt_ramc(false);
at91_pm_init(NULL);
}
@ -942,13 +1096,18 @@ void __init sama5d2_pm_init(void)
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
AT91_PM_BACKUP,
};
static const u32 iomaps[] __initconst = {
[AT91_PM_ULP1] = AT91_PM_IOMAP(SHDWC),
[AT91_PM_BACKUP] = AT91_PM_IOMAP(SHDWC) |
AT91_PM_IOMAP(SFRBU),
};
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
return;
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_pm_modes_init();
at91_dt_ramc();
at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
at91_dt_ramc(false);
at91_pm_init(NULL);
soc_pm.ws_ids = sama5d2_ws_ids;
@ -956,6 +1115,32 @@ void __init sama5d2_pm_init(void)
soc_pm.config_pmc_ws = at91_sama5d2_config_pmc_ws;
}
void __init sama7_pm_init(void)
{
static const int modes[] __initconst = {
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP1, AT91_PM_BACKUP,
};
static const u32 iomaps[] __initconst = {
[AT91_PM_ULP0] = AT91_PM_IOMAP(SFRBU),
[AT91_PM_ULP1] = AT91_PM_IOMAP(SFRBU) |
AT91_PM_IOMAP(SHDWC),
[AT91_PM_BACKUP] = AT91_PM_IOMAP(SFRBU) |
AT91_PM_IOMAP(SHDWC),
};
if (!IS_ENABLED(CONFIG_SOC_SAMA7))
return;
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_dt_ramc(true);
at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
at91_pm_init(NULL);
soc_pm.ws_ids = sama7g5_ws_ids;
soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
}
static int __init at91_pm_modes_select(char *str)
{
char *s;

Просмотреть файл

@ -12,6 +12,8 @@
#include <linux/mfd/syscon/atmel-mc.h>
#include <soc/at91/at91sam9_ddrsdr.h>
#include <soc/at91/at91sam9_sdramc.h>
#include <soc/at91/sama7-ddr.h>
#include <soc/at91/sama7-sfrbu.h>
#define AT91_MEMCTRL_MC 0
#define AT91_MEMCTRL_SDRAMC 1
@ -27,6 +29,7 @@
struct at91_pm_data {
void __iomem *pmc;
void __iomem *ramc[2];
void __iomem *ramc_phy;
unsigned long uhp_udp_mask;
unsigned int memctrl;
unsigned int mode;

Просмотреть файл

@ -8,6 +8,8 @@ int main(void)
DEFINE(PM_DATA_PMC, offsetof(struct at91_pm_data, pmc));
DEFINE(PM_DATA_RAMC0, offsetof(struct at91_pm_data, ramc[0]));
DEFINE(PM_DATA_RAMC1, offsetof(struct at91_pm_data, ramc[1]));
DEFINE(PM_DATA_RAMC_PHY, offsetof(struct at91_pm_data,
ramc_phy));
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));

Просмотреть файл

@ -22,39 +22,57 @@ tmp3 .req r6
/*
* Wait until master clock is ready (after switching master clock source)
*
* @r_mckid: register holding master clock identifier
*
* Side effects: overwrites r7, r8
*/
.macro wait_mckrdy
1: ldr tmp1, [pmc, #AT91_PMC_SR]
tst tmp1, #AT91_PMC_MCKRDY
beq 1b
.macro wait_mckrdy r_mckid
#ifdef CONFIG_SOC_SAMA7
cmp \r_mckid, #0
beq 1f
mov r7, #AT91_PMC_MCKXRDY
b 2f
#endif
1: mov r7, #AT91_PMC_MCKRDY
2: ldr r8, [pmc, #AT91_PMC_SR]
and r8, r7
cmp r8, r7
bne 2b
.endm
/*
* Wait until master oscillator has stabilized.
*
* Side effects: overwrites r7
*/
.macro wait_moscrdy
1: ldr tmp1, [pmc, #AT91_PMC_SR]
tst tmp1, #AT91_PMC_MOSCS
1: ldr r7, [pmc, #AT91_PMC_SR]
tst r7, #AT91_PMC_MOSCS
beq 1b
.endm
/*
* Wait for main oscillator selection is done
*
* Side effects: overwrites r7
*/
.macro wait_moscsels
1: ldr tmp1, [pmc, #AT91_PMC_SR]
tst tmp1, #AT91_PMC_MOSCSELS
1: ldr r7, [pmc, #AT91_PMC_SR]
tst r7, #AT91_PMC_MOSCSELS
beq 1b
.endm
/*
* Put the processor to enter the idle state
*
* Side effects: overwrites r7
*/
.macro at91_cpu_idle
#if defined(CONFIG_CPU_V7)
mov tmp1, #AT91_PMC_PCK
str tmp1, [pmc, #AT91_PMC_SCDR]
mov r7, #AT91_PMC_PCK
str r7, [pmc, #AT91_PMC_SCDR]
dsb
@ -65,102 +83,375 @@ tmp3 .req r6
.endm
/**
* Set state for 2.5V low power regulator
* @ena: 0 - disable regulator
* 1 - enable regulator
*
* Side effects: overwrites r7, r8, r9, r10
*/
.macro at91_2_5V_reg_set_low_power ena
#ifdef CONFIG_SOC_SAMA7
ldr r7, .sfrbu
mov r8, #\ena
ldr r9, [r7, #AT91_SFRBU_25LDOCR]
orr r9, r9, #AT91_SFRBU_25LDOCR_LP
cmp r8, #1
beq lp_done_\ena
bic r9, r9, #AT91_SFRBU_25LDOCR_LP
lp_done_\ena:
ldr r10, =AT91_SFRBU_25LDOCR_LDOANAKEY
orr r9, r9, r10
str r9, [r7, #AT91_SFRBU_25LDOCR]
#endif
.endm
.macro at91_backup_set_lpm reg
#ifdef CONFIG_SOC_SAMA7
orr \reg, \reg, #0x200000
#endif
.endm
.text
.arm
/*
* void at91_suspend_sram_fn(struct at91_pm_data*)
* @input param:
* @r0: base address of struct at91_pm_data
#ifdef CONFIG_SOC_SAMA7
/**
* Enable self-refresh
*
* Side effects: overwrites r2, r3, tmp1, tmp2, tmp3, r7
*/
/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
.align 3
ENTRY(at91_pm_suspend_in_sram)
/* Save registers on stack */
stmfd sp!, {r4 - r12, lr}
.macro at91_sramc_self_refresh_ena
ldr r2, .sramc_base
ldr r3, .sramc_phy_base
ldr r7, .pm_mode
/* Drain write buffer */
dsb
/* Disable all AXI ports. */
ldr tmp1, [r2, #UDDRC_PCTRL_0]
bic tmp1, tmp1, #0x1
str tmp1, [r2, #UDDRC_PCTRL_0]
ldr tmp1, [r2, #UDDRC_PCTRL_1]
bic tmp1, tmp1, #0x1
str tmp1, [r2, #UDDRC_PCTRL_1]
ldr tmp1, [r2, #UDDRC_PCTRL_2]
bic tmp1, tmp1, #0x1
str tmp1, [r2, #UDDRC_PCTRL_2]
ldr tmp1, [r2, #UDDRC_PCTRL_3]
bic tmp1, tmp1, #0x1
str tmp1, [r2, #UDDRC_PCTRL_3]
ldr tmp1, [r2, #UDDRC_PCTRL_4]
bic tmp1, tmp1, #0x1
str tmp1, [r2, #UDDRC_PCTRL_4]
sr_ena_1:
/* Wait for all ports to disable. */
ldr tmp1, [r2, #UDDRC_PSTAT]
ldr tmp2, =UDDRC_PSTAT_ALL_PORTS
tst tmp1, tmp2
bne sr_ena_1
/* Switch to self-refresh. */
ldr tmp1, [r2, #UDDRC_PWRCTL]
orr tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW
str tmp1, [r2, #UDDRC_PWRCTL]
sr_ena_2:
/* Wait for self-refresh enter. */
ldr tmp1, [r2, #UDDRC_STAT]
bic tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK
cmp tmp1, #UDDRC_STAT_SELFREF_TYPE_SW
bne sr_ena_2
/* Put DDR PHY's DLL in bypass mode for non-backup modes. */
cmp r7, #AT91_PM_BACKUP
beq sr_ena_3
ldr tmp1, [r3, #DDR3PHY_PIR]
orr tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
str tmp1, [r3, #DDR3PHY_PIR]
sr_ena_3:
/* Power down DDR PHY data receivers. */
ldr tmp1, [r3, #DDR3PHY_DXCCR]
orr tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
str tmp1, [r3, #DDR3PHY_DXCCR]
/* Power down ADDR/CMD IO. */
ldr tmp1, [r3, #DDR3PHY_ACIOCR]
orr tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
orr tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
orr tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
str tmp1, [r3, #DDR3PHY_ACIOCR]
/* Power down ODT. */
ldr tmp1, [r3, #DDR3PHY_DSGCR]
orr tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
str tmp1, [r3, #DDR3PHY_DSGCR]
.endm
/**
* Disable self-refresh
*
* Side effects: overwrites r2, r3, tmp1, tmp2, tmp3
*/
.macro at91_sramc_self_refresh_dis
ldr r2, .sramc_base
ldr r3, .sramc_phy_base
/* Power up DDR PHY data receivers. */
ldr tmp1, [r3, #DDR3PHY_DXCCR]
bic tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
str tmp1, [r3, #DDR3PHY_DXCCR]
/* Power up the output of CK and CS pins. */
ldr tmp1, [r3, #DDR3PHY_ACIOCR]
bic tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
bic tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
bic tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
str tmp1, [r3, #DDR3PHY_ACIOCR]
/* Power up ODT. */
ldr tmp1, [r3, #DDR3PHY_DSGCR]
bic tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
str tmp1, [r3, #DDR3PHY_DSGCR]
/* Take DDR PHY's DLL out of bypass mode. */
ldr tmp1, [r3, #DDR3PHY_PIR]
bic tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
str tmp1, [r3, #DDR3PHY_PIR]
/* Enable quasi-dynamic programming. */
mov tmp1, #0
mcr p15, 0, tmp1, c7, c10, 4
str tmp1, [r2, #UDDRC_SWCTRL]
ldr tmp1, [r0, #PM_DATA_PMC]
str tmp1, .pmc_base
ldr tmp1, [r0, #PM_DATA_RAMC0]
str tmp1, .sramc_base
ldr tmp1, [r0, #PM_DATA_RAMC1]
str tmp1, .sramc1_base
ldr tmp1, [r0, #PM_DATA_MEMCTRL]
str tmp1, .memtype
ldr tmp1, [r0, #PM_DATA_MODE]
str tmp1, .pm_mode
ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET]
str tmp1, .mckr_offset
ldr tmp1, [r0, #PM_DATA_PMC_VERSION]
str tmp1, .pmc_version
/* 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, .sfrbu
cmp tmp1, #0
ldrne tmp2, [tmp1, #0x10]
/* De-assert SDRAM initialization. */
ldr tmp1, [r2, #UDDRC_DFIMISC]
bic tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
str tmp1, [r2, #UDDRC_DFIMISC]
/* Active the self-refresh mode */
mov r0, #SRAMC_SELF_FRESH_ACTIVE
bl at91_sramc_self_refresh
/* Quasi-dynamic programming done. */
mov tmp1, #UDDRC_SWCTRL_SW_DONE
str tmp1, [r2, #UDDRC_SWCTRL]
ldr r0, .pm_mode
cmp r0, #AT91_PM_STANDBY
beq standby
cmp r0, #AT91_PM_BACKUP
beq backup_mode
sr_dis_1:
ldr tmp1, [r2, #UDDRC_SWSTAT]
tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
beq sr_dis_1
bl at91_ulp_mode
b exit_suspend
/* DLL soft-reset + DLL lock wait + ITM reset */
mov tmp1, #(DDR3PHY_PIR_INIT | DDR3PHY_PIR_DLLSRST | \
DDR3PHY_PIR_DLLLOCK | DDR3PHY_PIR_ITMSRST)
str tmp1, [r3, #DDR3PHY_PIR]
standby:
/* Wait for interrupt */
ldr pmc, .pmc_base
at91_cpu_idle
b exit_suspend
sr_dis_4:
/* Wait for it. */
ldr tmp1, [r3, #DDR3PHY_PGSR]
tst tmp1, #DDR3PHY_PGSR_IDONE
beq sr_dis_4
backup_mode:
bl at91_backup_mode
b exit_suspend
/* Enable quasi-dynamic programming. */
mov tmp1, #0
str tmp1, [r2, #UDDRC_SWCTRL]
exit_suspend:
/* Exit the self-refresh mode */
mov r0, #SRAMC_SELF_FRESH_EXIT
bl at91_sramc_self_refresh
/* Assert PHY init complete enable signal. */
ldr tmp1, [r2, #UDDRC_DFIMISC]
orr tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
str tmp1, [r2, #UDDRC_DFIMISC]
/* Restore registers, and return */
ldmfd sp!, {r4 - r12, pc}
ENDPROC(at91_pm_suspend_in_sram)
/* Programming is done. Set sw_done. */
mov tmp1, #UDDRC_SWCTRL_SW_DONE
str tmp1, [r2, #UDDRC_SWCTRL]
ENTRY(at91_backup_mode)
/* Switch the master clock source to slow clock. */
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
ldr tmp1, [pmc, tmp2]
bic tmp1, tmp1, #AT91_PMC_CSS
str tmp1, [pmc, tmp2]
sr_dis_5:
/* Wait for it. */
ldr tmp1, [r2, #UDDRC_SWSTAT]
tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
beq sr_dis_5
wait_mckrdy
/* Trigger self-refresh exit. */
ldr tmp1, [r2, #UDDRC_PWRCTL]
bic tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW
str tmp1, [r2, #UDDRC_PWRCTL]
/*BUMEN*/
ldr r0, .sfrbu
mov tmp1, #0x1
str tmp1, [r0, #0x10]
sr_dis_6:
/* Wait for self-refresh exit done. */
ldr tmp1, [r2, #UDDRC_STAT]
bic tmp1, tmp1, #~UDDRC_STAT_OPMODE_MSK
cmp tmp1, #UDDRC_STAT_OPMODE_NORMAL
bne sr_dis_6
/* Shutdown */
ldr r0, .shdwc
mov tmp1, #0xA5000000
add tmp1, tmp1, #0x1
str tmp1, [r0, #0]
ENDPROC(at91_backup_mode)
/* Enable all AXI ports. */
ldr tmp1, [r2, #UDDRC_PCTRL_0]
orr tmp1, tmp1, #0x1
str tmp1, [r2, #UDDRC_PCTRL_0]
ldr tmp1, [r2, #UDDRC_PCTRL_1]
orr tmp1, tmp1, #0x1
str tmp1, [r2, #UDDRC_PCTRL_1]
ldr tmp1, [r2, #UDDRC_PCTRL_2]
orr tmp1, tmp1, #0x1
str tmp1, [r2, #UDDRC_PCTRL_2]
ldr tmp1, [r2, #UDDRC_PCTRL_3]
orr tmp1, tmp1, #0x1
str tmp1, [r2, #UDDRC_PCTRL_3]
ldr tmp1, [r2, #UDDRC_PCTRL_4]
orr tmp1, tmp1, #0x1
str tmp1, [r2, #UDDRC_PCTRL_4]
dsb
.endm
#else
/**
* Enable self-refresh
*
* register usage:
* @r1: memory type
* @r2: base address of the sram controller
* @r3: temporary
*/
.macro at91_sramc_self_refresh_ena
ldr r1, .memtype
ldr r2, .sramc_base
cmp r1, #AT91_MEMCTRL_MC
bne sr_ena_ddrc_sf
/* Active SDRAM self-refresh mode */
mov r3, #1
str r3, [r2, #AT91_MC_SDRAMC_SRR]
b sr_ena_exit
sr_ena_ddrc_sf:
cmp r1, #AT91_MEMCTRL_DDRSDR
bne sr_ena_sdramc_sf
/*
* DDR Memory controller
*/
/* LPDDR1 --> force DDR2 mode during self-refresh */
ldr r3, [r2, #AT91_DDRSDRC_MDR]
str r3, .saved_sam9_mdr
bic r3, r3, #~AT91_DDRSDRC_MD
cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
ldreq r3, [r2, #AT91_DDRSDRC_MDR]
biceq r3, r3, #AT91_DDRSDRC_MD
orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
streq r3, [r2, #AT91_DDRSDRC_MDR]
/* Active DDRC self-refresh mode */
ldr r3, [r2, #AT91_DDRSDRC_LPR]
str r3, .saved_sam9_lpr
bic r3, r3, #AT91_DDRSDRC_LPCB
orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
str r3, [r2, #AT91_DDRSDRC_LPR]
/* If using the 2nd ddr controller */
ldr r2, .sramc1_base
cmp r2, #0
beq sr_ena_no_2nd_ddrc
ldr r3, [r2, #AT91_DDRSDRC_MDR]
str r3, .saved_sam9_mdr1
bic r3, r3, #~AT91_DDRSDRC_MD
cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
ldreq r3, [r2, #AT91_DDRSDRC_MDR]
biceq r3, r3, #AT91_DDRSDRC_MD
orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
streq r3, [r2, #AT91_DDRSDRC_MDR]
/* Active DDRC self-refresh mode */
ldr r3, [r2, #AT91_DDRSDRC_LPR]
str r3, .saved_sam9_lpr1
bic r3, r3, #AT91_DDRSDRC_LPCB
orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
str r3, [r2, #AT91_DDRSDRC_LPR]
sr_ena_no_2nd_ddrc:
b sr_ena_exit
/*
* SDRAMC Memory controller
*/
sr_ena_sdramc_sf:
/* Active SDRAMC self-refresh mode */
ldr r3, [r2, #AT91_SDRAMC_LPR]
str r3, .saved_sam9_lpr
bic r3, r3, #AT91_SDRAMC_LPCB
orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
str r3, [r2, #AT91_SDRAMC_LPR]
ldr r3, .saved_sam9_lpr
str r3, [r2, #AT91_SDRAMC_LPR]
sr_ena_exit:
.endm
/**
* Disable self-refresh
*
* register usage:
* @r1: memory type
* @r2: base address of the sram controller
* @r3: temporary
*/
.macro at91_sramc_self_refresh_dis
ldr r1, .memtype
ldr r2, .sramc_base
cmp r1, #AT91_MEMCTRL_MC
bne sr_dis_ddrc_exit_sf
/*
* at91rm9200 Memory controller
*/
/*
* For exiting the self-refresh mode, do nothing,
* automatically exit the self-refresh mode.
*/
b sr_dis_exit
sr_dis_ddrc_exit_sf:
cmp r1, #AT91_MEMCTRL_DDRSDR
bne sdramc_exit_sf
/* DDR Memory controller */
/* Restore MDR in case of LPDDR1 */
ldr r3, .saved_sam9_mdr
str r3, [r2, #AT91_DDRSDRC_MDR]
/* Restore LPR on AT91 with DDRAM */
ldr r3, .saved_sam9_lpr
str r3, [r2, #AT91_DDRSDRC_LPR]
/* If using the 2nd ddr controller */
ldr r2, .sramc1_base
cmp r2, #0
ldrne r3, .saved_sam9_mdr1
strne r3, [r2, #AT91_DDRSDRC_MDR]
ldrne r3, .saved_sam9_lpr1
strne r3, [r2, #AT91_DDRSDRC_LPR]
b sr_dis_exit
sdramc_exit_sf:
/* SDRAMC Memory controller */
ldr r3, .saved_sam9_lpr
str r3, [r2, #AT91_SDRAMC_LPR]
sr_dis_exit:
.endm
#endif
.macro at91_pm_ulp0_mode
ldr pmc, .pmc_base
@ -176,7 +467,9 @@ ENDPROC(at91_backup_mode)
bic tmp1, tmp1, #AT91_PMC_PRES
orr tmp1, tmp1, #AT91_PMC_PRES_64
str tmp1, [pmc, tmp3]
wait_mckrdy
mov tmp3, #0
wait_mckrdy tmp3
b 1f
0:
@ -212,10 +505,13 @@ ENDPROC(at91_backup_mode)
bne 5f
/* Set lowest prescaler for fast resume. */
ldr tmp3, .mckr_offset
ldr tmp1, [pmc, tmp3]
bic tmp1, tmp1, #AT91_PMC_PRES
str tmp1, [pmc, tmp3]
wait_mckrdy
mov tmp3, #0
wait_mckrdy tmp3
b 6f
5: /* Restore RC oscillator state */
@ -252,6 +548,7 @@ ENDPROC(at91_backup_mode)
.macro at91_pm_ulp1_mode
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
mov tmp3, #0
/* Save RC oscillator state and check if it is enabled. */
ldr tmp1, [pmc, #AT91_PMC_SR]
@ -293,7 +590,7 @@ ENDPROC(at91_backup_mode)
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
str tmp1, [pmc, tmp2]
wait_mckrdy
wait_mckrdy tmp3
/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@ -306,7 +603,7 @@ ENDPROC(at91_backup_mode)
nop
nop
wait_mckrdy
wait_mckrdy tmp3
/* Enable the crystal oscillator */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@ -322,7 +619,7 @@ ENDPROC(at91_backup_mode)
bic tmp1, tmp1, #AT91_PMC_CSS
str tmp1, [pmc, tmp2]
wait_mckrdy
wait_mckrdy tmp3
/* Switch main clock source to crystal oscillator */
ldr tmp1, [pmc, #AT91_CKGR_MOR]
@ -339,7 +636,7 @@ ENDPROC(at91_backup_mode)
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
str tmp1, [pmc, tmp2]
wait_mckrdy
wait_mckrdy tmp3
/* Restore RC oscillator state */
ldr tmp1, .saved_osc_status
@ -367,7 +664,7 @@ ENDPROC(at91_backup_mode)
cmp tmp1, #AT91_PMC_V1
beq 1f
#ifdef CONFIG_SOC_SAM9X60
#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL
/* Save PLLA settings. */
ldr tmp2, [pmc, #AT91_PMC_PLL_UPDT]
bic tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID
@ -434,7 +731,7 @@ ENDPROC(at91_backup_mode)
cmp tmp3, #AT91_PMC_V1
beq 4f
#ifdef CONFIG_SOC_SAM9X60
#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL
/* step 1. */
ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT]
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
@ -497,7 +794,122 @@ ENDPROC(at91_backup_mode)
2:
.endm
ENTRY(at91_ulp_mode)
/**
* at91_mckx_ps_enable: save MCK1..4 settings and switch it to main clock
*
* Side effects: overwrites tmp1, tmp2
*/
.macro at91_mckx_ps_enable
#ifdef CONFIG_SOC_SAMA7
ldr pmc, .pmc_base
/* There are 4 MCKs we need to handle: MCK1..4 */
mov tmp1, #1
e_loop: cmp tmp1, #5
beq e_done
/* Write MCK ID to retrieve the settings. */
str tmp1, [pmc, #AT91_PMC_MCR_V2]
ldr tmp2, [pmc, #AT91_PMC_MCR_V2]
e_save_mck1:
cmp tmp1, #1
bne e_save_mck2
str tmp2, .saved_mck1
b e_ps
e_save_mck2:
cmp tmp1, #2
bne e_save_mck3
str tmp2, .saved_mck2
b e_ps
e_save_mck3:
cmp tmp1, #3
bne e_save_mck4
str tmp2, .saved_mck3
b e_ps
e_save_mck4:
str tmp2, .saved_mck4
e_ps:
/* Use CSS=MAINCK and DIV=1. */
bic tmp2, tmp2, #AT91_PMC_MCR_V2_CSS
bic tmp2, tmp2, #AT91_PMC_MCR_V2_DIV
orr tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MAINCK
orr tmp2, tmp2, #AT91_PMC_MCR_V2_DIV1
str tmp2, [pmc, #AT91_PMC_MCR_V2]
wait_mckrdy tmp1
add tmp1, tmp1, #1
b e_loop
e_done:
#endif
.endm
/**
* at91_mckx_ps_restore: restore MCK1..4 settings
*
* Side effects: overwrites tmp1, tmp2
*/
.macro at91_mckx_ps_restore
#ifdef CONFIG_SOC_SAMA7
ldr pmc, .pmc_base
/* There are 4 MCKs we need to handle: MCK1..4 */
mov tmp1, #1
r_loop: cmp tmp1, #5
beq r_done
r_save_mck1:
cmp tmp1, #1
bne r_save_mck2
ldr tmp2, .saved_mck1
b r_ps
r_save_mck2:
cmp tmp1, #2
bne r_save_mck3
ldr tmp2, .saved_mck2
b r_ps
r_save_mck3:
cmp tmp1, #3
bne r_save_mck4
ldr tmp2, .saved_mck3
b r_ps
r_save_mck4:
ldr tmp2, .saved_mck4
r_ps:
/* Write MCK ID to retrieve the settings. */
str tmp1, [pmc, #AT91_PMC_MCR_V2]
ldr tmp3, [pmc, #AT91_PMC_MCR_V2]
/* We need to restore CSS and DIV. */
bic tmp3, tmp3, #AT91_PMC_MCR_V2_CSS
bic tmp3, tmp3, #AT91_PMC_MCR_V2_DIV
orr tmp3, tmp3, tmp2
bic tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MSK
orr tmp3, tmp3, tmp1
orr tmp3, tmp3, #AT91_PMC_MCR_V2_CMD
str tmp2, [pmc, #AT91_PMC_MCR_V2]
wait_mckrdy tmp1
add tmp1, tmp1, #1
b r_loop
r_done:
#endif
.endm
.macro at91_ulp_mode
at91_mckx_ps_enable
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
ldr tmp3, .pm_mode
@ -518,10 +930,15 @@ ENTRY(at91_ulp_mode)
save_mck:
str tmp1, [pmc, tmp2]
wait_mckrdy
mov tmp3, #0
wait_mckrdy tmp3
at91_plla_disable
/* Enable low power mode for 2.5V regulator. */
at91_2_5V_reg_set_low_power 1
ldr tmp3, .pm_mode
cmp tmp3, #AT91_PM_ULP1
beq ulp1_mode
@ -533,6 +950,9 @@ ulp1_mode:
b ulp_exit
ulp_exit:
/* Disable low power mode for 2.5V regulator. */
at91_2_5V_reg_set_low_power 0
ldr pmc, .pmc_base
at91_plla_enable
@ -544,135 +964,110 @@ ulp_exit:
ldr tmp2, .saved_mckr
str tmp2, [pmc, tmp1]
wait_mckrdy
mov tmp3, #0
wait_mckrdy tmp3
mov pc, lr
ENDPROC(at91_ulp_mode)
at91_mckx_ps_restore
.endm
.macro at91_backup_mode
/* Switch the master clock source to slow clock. */
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
ldr tmp1, [pmc, tmp2]
bic tmp1, tmp1, #AT91_PMC_CSS
str tmp1, [pmc, tmp2]
mov tmp3, #0
wait_mckrdy tmp3
/*BUMEN*/
ldr r0, .sfrbu
mov tmp1, #0x1
str tmp1, [r0, #0x10]
/* Wait for it. */
1: ldr tmp1, [r0, #0x10]
tst tmp1, #0x1
beq 1b
/* Shutdown */
ldr r0, .shdwc
mov tmp1, #0xA5000000
add tmp1, tmp1, #0x1
at91_backup_set_lpm tmp1
str tmp1, [r0, #0]
.endm
/*
* void at91_sramc_self_refresh(unsigned int is_active)
*
* void at91_suspend_sram_fn(struct at91_pm_data*)
* @input param:
* @r0: 1 - active self-refresh mode
* 0 - exit self-refresh mode
* register usage:
* @r1: memory type
* @r2: base address of the sram controller
* @r0: base address of struct at91_pm_data
*/
/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
.align 3
ENTRY(at91_pm_suspend_in_sram)
/* Save registers on stack */
stmfd sp!, {r4 - r12, lr}
ENTRY(at91_sramc_self_refresh)
ldr r1, .memtype
ldr r2, .sramc_base
/* Drain write buffer */
mov tmp1, #0
mcr p15, 0, tmp1, c7, c10, 4
cmp r1, #AT91_MEMCTRL_MC
bne ddrc_sf
ldr tmp1, [r0, #PM_DATA_PMC]
str tmp1, .pmc_base
ldr tmp1, [r0, #PM_DATA_RAMC0]
str tmp1, .sramc_base
ldr tmp1, [r0, #PM_DATA_RAMC1]
str tmp1, .sramc1_base
ldr tmp1, [r0, #PM_DATA_RAMC_PHY]
str tmp1, .sramc_phy_base
ldr tmp1, [r0, #PM_DATA_MEMCTRL]
str tmp1, .memtype
ldr tmp1, [r0, #PM_DATA_MODE]
str tmp1, .pm_mode
ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET]
str tmp1, .mckr_offset
ldr tmp1, [r0, #PM_DATA_PMC_VERSION]
str tmp1, .pmc_version
/* 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, .sfrbu
cmp tmp1, #0
ldrne tmp2, [tmp1, #0x10]
/*
* at91rm9200 Memory controller
*/
/* Active the self-refresh mode */
at91_sramc_self_refresh_ena
/*
* For exiting the self-refresh mode, do nothing,
* automatically exit the self-refresh mode.
*/
tst r0, #SRAMC_SELF_FRESH_ACTIVE
beq exit_sramc_sf
ldr r0, .pm_mode
cmp r0, #AT91_PM_STANDBY
beq standby
cmp r0, #AT91_PM_BACKUP
beq backup_mode
/* Active SDRAM self-refresh mode */
mov r3, #1
str r3, [r2, #AT91_MC_SDRAMC_SRR]
b exit_sramc_sf
at91_ulp_mode
b exit_suspend
ddrc_sf:
cmp r1, #AT91_MEMCTRL_DDRSDR
bne sdramc_sf
standby:
/* Wait for interrupt */
ldr pmc, .pmc_base
at91_cpu_idle
b exit_suspend
/*
* DDR Memory controller
*/
tst r0, #SRAMC_SELF_FRESH_ACTIVE
beq ddrc_exit_sf
backup_mode:
at91_backup_mode
/* LPDDR1 --> force DDR2 mode during self-refresh */
ldr r3, [r2, #AT91_DDRSDRC_MDR]
str r3, .saved_sam9_mdr
bic r3, r3, #~AT91_DDRSDRC_MD
cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
ldreq r3, [r2, #AT91_DDRSDRC_MDR]
biceq r3, r3, #AT91_DDRSDRC_MD
orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
streq r3, [r2, #AT91_DDRSDRC_MDR]
exit_suspend:
/* Exit the self-refresh mode */
at91_sramc_self_refresh_dis
/* Active DDRC self-refresh mode */
ldr r3, [r2, #AT91_DDRSDRC_LPR]
str r3, .saved_sam9_lpr
bic r3, r3, #AT91_DDRSDRC_LPCB
orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
str r3, [r2, #AT91_DDRSDRC_LPR]
/* If using the 2nd ddr controller */
ldr r2, .sramc1_base
cmp r2, #0
beq no_2nd_ddrc
ldr r3, [r2, #AT91_DDRSDRC_MDR]
str r3, .saved_sam9_mdr1
bic r3, r3, #~AT91_DDRSDRC_MD
cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
ldreq r3, [r2, #AT91_DDRSDRC_MDR]
biceq r3, r3, #AT91_DDRSDRC_MD
orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
streq r3, [r2, #AT91_DDRSDRC_MDR]
/* Active DDRC self-refresh mode */
ldr r3, [r2, #AT91_DDRSDRC_LPR]
str r3, .saved_sam9_lpr1
bic r3, r3, #AT91_DDRSDRC_LPCB
orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
str r3, [r2, #AT91_DDRSDRC_LPR]
no_2nd_ddrc:
b exit_sramc_sf
ddrc_exit_sf:
/* Restore MDR in case of LPDDR1 */
ldr r3, .saved_sam9_mdr
str r3, [r2, #AT91_DDRSDRC_MDR]
/* Restore LPR on AT91 with DDRAM */
ldr r3, .saved_sam9_lpr
str r3, [r2, #AT91_DDRSDRC_LPR]
/* If using the 2nd ddr controller */
ldr r2, .sramc1_base
cmp r2, #0
ldrne r3, .saved_sam9_mdr1
strne r3, [r2, #AT91_DDRSDRC_MDR]
ldrne r3, .saved_sam9_lpr1
strne r3, [r2, #AT91_DDRSDRC_LPR]
b exit_sramc_sf
/*
* SDRAMC Memory controller
*/
sdramc_sf:
tst r0, #SRAMC_SELF_FRESH_ACTIVE
beq sdramc_exit_sf
/* Active SDRAMC self-refresh mode */
ldr r3, [r2, #AT91_SDRAMC_LPR]
str r3, .saved_sam9_lpr
bic r3, r3, #AT91_SDRAMC_LPCB
orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
str r3, [r2, #AT91_SDRAMC_LPR]
sdramc_exit_sf:
ldr r3, .saved_sam9_lpr
str r3, [r2, #AT91_SDRAMC_LPR]
exit_sramc_sf:
mov pc, lr
ENDPROC(at91_sramc_self_refresh)
/* Restore registers, and return */
ldmfd sp!, {r4 - r12, pc}
ENDPROC(at91_pm_suspend_in_sram)
.pmc_base:
.word 0
@ -680,6 +1075,8 @@ ENDPROC(at91_sramc_self_refresh)
.word 0
.sramc1_base:
.word 0
.sramc_phy_base:
.word 0
.shdwc:
.word 0
.sfrbu:
@ -706,6 +1103,16 @@ ENDPROC(at91_sramc_self_refresh)
.word 0
.saved_osc_status:
.word 0
#ifdef CONFIG_SOC_SAMA7
.saved_mck1:
.word 0
.saved_mck2:
.word 0
.saved_mck3:
.word 0
.saved_mck4:
.word 0
#endif
ENTRY(at91_pm_suspend_in_sram_sz)
.word .-at91_pm_suspend_in_sram

Просмотреть файл

@ -0,0 +1,33 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Setup code for SAMA7
*
* Copyright (C) 2021 Microchip Technology, Inc. and its subsidiaries
*
*/
#include <linux/of.h>
#include <linux/of_platform.h>
#include <asm/mach/arch.h>
#include <asm/system_misc.h>
#include "generic.h"
static void __init sama7_dt_device_init(void)
{
of_platform_default_populate(NULL, NULL, NULL);
sama7_pm_init();
}
static const char *const sama7_dt_board_compat[] __initconst = {
"microchip,sama7",
NULL
};
DT_MACHINE_START(sama7_dt, "Microchip SAMA7")
/* Maintainer: Microchip */
.init_machine = sama7_dt_device_init,
.dt_compat = sama7_dt_board_compat,
MACHINE_END

Просмотреть файл

@ -137,6 +137,32 @@
#define AT91_PMC_PLLADIV2_ON (1 << 12)
#define AT91_PMC_H32MXDIV BIT(24)
#define AT91_PMC_MCR_V2 0x30 /* Master Clock Register [SAMA7G5 only] */
#define AT91_PMC_MCR_V2_ID_MSK (0xF)
#define AT91_PMC_MCR_V2_ID(_id) ((_id) & AT91_PMC_MCR_V2_ID_MSK)
#define AT91_PMC_MCR_V2_CMD (1 << 7)
#define AT91_PMC_MCR_V2_DIV (7 << 8)
#define AT91_PMC_MCR_V2_DIV1 (0 << 8)
#define AT91_PMC_MCR_V2_DIV2 (1 << 8)
#define AT91_PMC_MCR_V2_DIV4 (2 << 8)
#define AT91_PMC_MCR_V2_DIV8 (3 << 8)
#define AT91_PMC_MCR_V2_DIV16 (4 << 8)
#define AT91_PMC_MCR_V2_DIV32 (5 << 8)
#define AT91_PMC_MCR_V2_DIV64 (6 << 8)
#define AT91_PMC_MCR_V2_DIV3 (7 << 8)
#define AT91_PMC_MCR_V2_CSS (0x1F << 16)
#define AT91_PMC_MCR_V2_CSS_MD_SLCK (0 << 16)
#define AT91_PMC_MCR_V2_CSS_TD_SLCK (1 << 16)
#define AT91_PMC_MCR_V2_CSS_MAINCK (2 << 16)
#define AT91_PMC_MCR_V2_CSS_MCK0 (3 << 16)
#define AT91_PMC_MCR_V2_CSS_SYSPLL (5 << 16)
#define AT91_PMC_MCR_V2_CSS_DDRPLL (6 << 16)
#define AT91_PMC_MCR_V2_CSS_IMGPLL (7 << 16)
#define AT91_PMC_MCR_V2_CSS_BAUDPLL (8 << 16)
#define AT91_PMC_MCR_V2_CSS_AUDIOPLL (9 << 16)
#define AT91_PMC_MCR_V2_CSS_ETHPLL (10 << 16)
#define AT91_PMC_MCR_V2_EN (1 << 28)
#define AT91_PMC_XTALF 0x34 /* Main XTAL Frequency Register [SAMA7G5 only] */
#define AT91_PMC_USB 0x38 /* USB Clock Register [some SAM9 only] */

Просмотреть файл

@ -0,0 +1,80 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Microchip SAMA7 UDDR Controller and DDR3 PHY Controller registers offsets
* and bit definitions.
*
* Copyright (C) [2020] Microchip Technology Inc. and its subsidiaries
*
* Author: Claudu Beznea <claudiu.beznea@microchip.com>
*/
#ifndef __SAMA7_DDR_H__
#define __SAMA7_DDR_H__
#ifdef CONFIG_SOC_SAMA7
/* DDR3PHY */
#define DDR3PHY_PIR (0x04) /* DDR3PHY PHY Initialization Register */
#define DDR3PHY_PIR_DLLBYP (1 << 17) /* DLL Bypass */
#define DDR3PHY_PIR_ITMSRST (1 << 4) /* Interface Timing Module Soft Reset */
#define DDR3PHY_PIR_DLLLOCK (1 << 2) /* DLL Lock */
#define DDR3PHY_PIR_DLLSRST (1 << 1) /* DLL Soft Rest */
#define DDR3PHY_PIR_INIT (1 << 0) /* Initialization Trigger */
#define DDR3PHY_PGCR (0x08) /* DDR3PHY PHY General Configuration Register */
#define DDR3PHY_PGCR_CKDV1 (1 << 13) /* CK# Disable Value */
#define DDR3PHY_PGCR_CKDV0 (1 << 12) /* CK Disable Value */
#define DDR3PHY_PGSR (0x0C) /* DDR3PHY PHY General Status Register */
#define DDR3PHY_PGSR_IDONE (1 << 0) /* Initialization Done */
#define DDR3PHY_ACIOCR (0x24) /* DDR3PHY AC I/O Configuration Register */
#define DDR3PHY_ACIOCR_CSPDD_CS0 (1 << 18) /* CS#[0] Power Down Driver */
#define DDR3PHY_ACIOCR_CKPDD_CK0 (1 << 8) /* CK[0] Power Down Driver */
#define DDR3PHY_ACIORC_ACPDD (1 << 3) /* AC Power Down Driver */
#define DDR3PHY_DXCCR (0x28) /* DDR3PHY DATX8 Common Configuration Register */
#define DDR3PHY_DXCCR_DXPDR (1 << 3) /* Data Power Down Receiver */
#define DDR3PHY_DSGCR (0x2C) /* DDR3PHY DDR System General Configuration Register */
#define DDR3PHY_DSGCR_ODTPDD_ODT0 (1 << 20) /* ODT[0] Power Down Driver */
#define DDR3PHY_ZQ0SR0 (0x188) /* ZQ status register 0 */
/* UDDRC */
#define UDDRC_STAT (0x04) /* UDDRC Operating Mode Status Register */
#define UDDRC_STAT_SELFREF_TYPE_DIS (0x0 << 4) /* SDRAM is not in Self-refresh */
#define UDDRC_STAT_SELFREF_TYPE_PHY (0x1 << 4) /* SDRAM is in Self-refresh, which was caused by PHY Master Request */
#define UDDRC_STAT_SELFREF_TYPE_SW (0x2 << 4) /* SDRAM is in Self-refresh, which was not caused solely under Automatic Self-refresh control */
#define UDDRC_STAT_SELFREF_TYPE_AUTO (0x3 << 4) /* SDRAM is in Self-refresh, which was caused by Automatic Self-refresh only */
#define UDDRC_STAT_SELFREF_TYPE_MSK (0x3 << 4) /* Self-refresh type mask */
#define UDDRC_STAT_OPMODE_INIT (0x0 << 0) /* Init */
#define UDDRC_STAT_OPMODE_NORMAL (0x1 << 0) /* Normal */
#define UDDRC_STAT_OPMODE_PWRDOWN (0x2 << 0) /* Power-down */
#define UDDRC_STAT_OPMODE_SELF_REFRESH (0x3 << 0) /* Self-refresh */
#define UDDRC_STAT_OPMODE_MSK (0x7 << 0) /* Operating mode mask */
#define UDDRC_PWRCTL (0x30) /* UDDRC Low Power Control Register */
#define UDDRC_PWRCTRL_SELFREF_SW (1 << 5) /* Software self-refresh */
#define UDDRC_DFIMISC (0x1B0) /* UDDRC DFI Miscellaneous Control Register */
#define UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN (1 << 0) /* PHY initialization complete enable signal */
#define UDDRC_SWCTRL (0x320) /* UDDRC Software Register Programming Control Enable */
#define UDDRC_SWCTRL_SW_DONE (1 << 0) /* Enable quasi-dynamic register programming outside reset */
#define UDDRC_SWSTAT (0x324) /* UDDRC Software Register Programming Control Status */
#define UDDRC_SWSTAT_SW_DONE_ACK (1 << 0) /* Register programming done */
#define UDDRC_PSTAT (0x3FC) /* UDDRC Port Status Register */
#define UDDRC_PSTAT_ALL_PORTS (0x1F001F) /* Read + writes outstanding transactions on all ports */
#define UDDRC_PCTRL_0 (0x490) /* UDDRC Port 0 Control Register */
#define UDDRC_PCTRL_1 (0x540) /* UDDRC Port 1 Control Register */
#define UDDRC_PCTRL_2 (0x5F0) /* UDDRC Port 2 Control Register */
#define UDDRC_PCTRL_3 (0x6A0) /* UDDRC Port 3 Control Register */
#define UDDRC_PCTRL_4 (0x750) /* UDDRC Port 4 Control Register */
#endif /* CONFIG_SOC_SAMA7 */
#endif /* __SAMA7_DDR_H__ */

Просмотреть файл

@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Microchip SAMA7 SFRBU registers offsets and bit definitions.
*
* Copyright (C) [2020] Microchip Technology Inc. and its subsidiaries
*
* Author: Claudu Beznea <claudiu.beznea@microchip.com>
*/
#ifndef __SAMA7_SFRBU_H__
#define __SAMA7_SFRBU_H__
#ifdef CONFIG_SOC_SAMA7
#define AT91_SFRBU_PSWBU (0x00) /* SFRBU Power Switch BU Control Register */
#define AT91_SFRBU_PSWBU_PSWKEY (0x4BD20C << 8) /* Specific value mandatory to allow writing of other register bits */
#define AT91_SFRBU_PSWBU_STATE (1 << 2) /* Power switch BU state */
#define AT91_SFRBU_PSWBU_SOFTSWITCH (1 << 1) /* Power switch BU source selection */
#define AT91_SFRBU_PSWBU_CTRL (1 << 0) /* Power switch BU control */
#define AT91_SFRBU_25LDOCR (0x0C) /* SFRBU 2.5V LDO Control Register */
#define AT91_SFRBU_25LDOCR_LDOANAKEY (0x3B6E18 << 8) /* Specific value mandatory to allow writing of other register bits. */
#define AT91_SFRBU_25LDOCR_STATE (1 << 3) /* LDOANA Switch On/Off Control */
#define AT91_SFRBU_25LDOCR_LP (1 << 2) /* LDOANA Low-Power Mode Control */
#define AT91_SFRBU_PD_VALUE_MSK (0x3)
#define AT91_SFRBU_25LDOCR_PD_VALUE(v) ((v) & AT91_SFRBU_PD_VALUE_MSK) /* LDOANA Pull-down value */
#define AT91_FRBU_DDRPWR (0x10) /* SFRBU DDR Power Control Register */
#define AT91_FRBU_DDRPWR_STATE (1 << 0) /* DDR Power Mode State */
#endif /* CONFIG_SOC_SAMA7 */
#endif /* __SAMA7_SFRBU_H__ */