Skip to content

Commit

Permalink
Merge tag 'at91-fixes-5.15' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/at91/linux into arm/fixes

AT91 fixes #1 for 5.15:

- Fixes for newly introduced SAMA7G5 and its Power Management code.
  Associated core peripherals need to be instantiated in DT for
  benefiting from best PM support like Backup mode with DDR in
  Self-Refresh.
- Add chip ID for SAMA7G5 for easing the kernel log identification.
- Avoid Camera Sensor probe error on sama5d27 som1 ek board.

* tag 'at91-fixes-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux:
  ARM: dts: at91: sama5d2_som1_ek: disable ISC node by default
  ARM: at91: pm: switch backup area to vbat in backup mode
  ARM: dts: at91: sama7g5: add chipid
  ARM: dts: at91: sama7g5: add shdwc node
  ARM: dts: at91: sama7g5: add securam node
  ARM: dts: at91: sama7g5: add ram controllers
  ARM: at91: pm: do not panic if ram controllers are not enabled

Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Arnd Bergmann <[email protected]>
  • Loading branch information
arndb committed Sep 14, 2021
2 parents 3f1c260 + 4348cc1 commit d0c624c
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 17 deletions.
1 change: 0 additions & 1 deletion arch/arm/boot/dts/at91-sama5d27_som1_ek.dts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
isc: isc@f0008000 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_isc_base &pinctrl_isc_data_8bit &pinctrl_isc_data_9_10 &pinctrl_isc_data_11_12>;
status = "okay";
};

qspi1: spi@f0024000 {
Expand Down
9 changes: 9 additions & 0 deletions arch/arm/boot/dts/at91-sama7g5ek.dts
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,15 @@
pinctrl-0 = <&pinctrl_sdmmc2_default>;
};

&shdwc {
atmel,shdwc-debouncer = <976>;
status = "okay";

input@0 {
reg = <0>;
};
};

&spdifrx {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spdifrx_default>;
Expand Down
39 changes: 39 additions & 0 deletions arch/arm/boot/dts/sama7g5.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@
#size-cells = <1>;
ranges;

securam: securam@e0000000 {
compatible = "microchip,sama7g5-securam", "atmel,sama5d2-securam", "mmio-sram";
reg = <0xe0000000 0x4000>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 18>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0xe0000000 0x4000>;
no-memory-wc;
status = "okay";
};

secumod: secumod@e0004000 {
compatible = "microchip,sama7g5-secumod", "atmel,sama5d2-secumod", "syscon";
reg = <0xe0004000 0x4000>;
Expand Down Expand Up @@ -111,6 +122,17 @@
clock-names = "td_slck", "md_slck", "main_xtal";
};

shdwc: shdwc@e001d010 {
compatible = "microchip,sama7g5-shdwc", "syscon";
reg = <0xe001d010 0x10>;
clocks = <&clk32k 0>;
#address-cells = <1>;
#size-cells = <0>;
atmel,wakeup-rtc-timer;
atmel,wakeup-rtt-timer;
status = "disabled";
};

rtt: rtt@e001d020 {
compatible = "microchip,sama7g5-rtt", "microchip,sam9x60-rtt", "atmel,at91sam9260-rtt";
reg = <0xe001d020 0x30>;
Expand All @@ -137,6 +159,11 @@
clocks = <&clk32k 0>;
};

chipid@e0020000 {
compatible = "microchip,sama7g5-chipid";
reg = <0xe0020000 0x8>;
};

sdmmc0: mmc@e1204000 {
compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci";
reg = <0xe1204000 0x4000>;
Expand Down Expand Up @@ -515,6 +542,18 @@
};
};

uddrc: uddrc@e3800000 {
compatible = "microchip,sama7g5-uddrc";
reg = <0xe3800000 0x4000>;
status = "okay";
};

ddr3phy: ddr3phy@e3804000 {
compatible = "microchip,sama7g5-ddr3phy";
reg = <0xe3804000 0x1000>;
status = "okay";
};

gic: interrupt-controller@e8c11000 {
compatible = "arm,cortex-a7-gic";
#interrupt-cells = <3>;
Expand Down
130 changes: 114 additions & 16 deletions arch/arm/mach-at91/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,26 @@ struct at91_pm_bu {
unsigned long ddr_phy_calibration[BACKUP_DDR_PHY_CALIBRATION];
};

/*
* struct at91_pm_sfrbu_offsets: registers mapping for SFRBU
* @pswbu: power switch BU control registers
*/
struct at91_pm_sfrbu_regs {
struct {
u32 key;
u32 ctrl;
u32 state;
u32 softsw;
} pswbu;
};

/**
* 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
* @sfrbu_regs: SFRBU registers mapping
* @bu: backup unit mapped data (for backup mode)
* @memcs: memory chip select
*/
Expand All @@ -62,6 +76,7 @@ struct at91_soc_pm {
const struct of_device_id *ws_ids;
struct at91_pm_bu *bu;
struct at91_pm_data data;
struct at91_pm_sfrbu_regs sfrbu_regs;
void *memcs;
};

Expand Down Expand Up @@ -356,9 +371,36 @@ static int at91_suspend_finish(unsigned long val)
return 0;
}

static void at91_pm_switch_ba_to_vbat(void)
{
unsigned int offset = offsetof(struct at91_pm_sfrbu_regs, pswbu);
unsigned int val;

/* Just for safety. */
if (!soc_pm.data.sfrbu)
return;

val = readl(soc_pm.data.sfrbu + offset);

/* Already on VBAT. */
if (!(val & soc_pm.sfrbu_regs.pswbu.state))
return;

val &= ~soc_pm.sfrbu_regs.pswbu.softsw;
val |= soc_pm.sfrbu_regs.pswbu.key | soc_pm.sfrbu_regs.pswbu.ctrl;
writel(val, soc_pm.data.sfrbu + offset);

/* Wait for update. */
val = readl(soc_pm.data.sfrbu + offset);
while (val & soc_pm.sfrbu_regs.pswbu.state)
val = readl(soc_pm.data.sfrbu + offset);
}

static void at91_pm_suspend(suspend_state_t state)
{
if (soc_pm.data.mode == AT91_PM_BACKUP) {
at91_pm_switch_ba_to_vbat();

cpu_suspend(0, at91_suspend_finish);

/* The SRAM is lost between suspend cycles */
Expand Down Expand Up @@ -589,18 +631,22 @@ static const struct of_device_id ramc_phy_ids[] __initconst = {
{ /* Sentinel. */ },
};

static __init void at91_dt_ramc(bool phy_mandatory)
static __init int at91_dt_ramc(bool phy_mandatory)
{
struct device_node *np;
const struct of_device_id *of_id;
int idx = 0;
void *standby = NULL;
const struct ramc_info *ramc;
int ret;

for_each_matching_node_and_match(np, ramc_ids, &of_id) {
soc_pm.data.ramc[idx] = of_iomap(np, 0);
if (!soc_pm.data.ramc[idx])
panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx);
if (!soc_pm.data.ramc[idx]) {
pr_err("unable to map ramc[%d] cpu registers\n", idx);
ret = -ENOMEM;
goto unmap_ramc;
}

ramc = of_id->data;
if (ramc) {
Expand All @@ -612,25 +658,42 @@ static __init void at91_dt_ramc(bool phy_mandatory)
idx++;
}

if (!idx)
panic(pr_fmt("unable to find compatible ram controller node in dtb\n"));
if (!idx) {
pr_err("unable to find compatible ram controller node in dtb\n");
ret = -ENODEV;
goto unmap_ramc;
}

/* 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 (!soc_pm.data.ramc_phy) {
pr_err("unable to map ramc phy cpu registers\n");
ret = -ENOMEM;
goto unmap_ramc;
}
}

if (phy_mandatory && !soc_pm.data.ramc_phy)
panic(pr_fmt("DDR PHY is mandatory!\n"));
if (phy_mandatory && !soc_pm.data.ramc_phy) {
pr_err("DDR PHY is mandatory!\n");
ret = -ENODEV;
goto unmap_ramc;
}

if (!standby) {
pr_warn("ramc no standby function available\n");
return;
return 0;
}

at91_cpuidle_device.dev.platform_data = standby;

return 0;

unmap_ramc:
while (idx)
iounmap(soc_pm.data.ramc[--idx]);

return ret;
}

static void at91rm9200_idle(void)
Expand Down Expand Up @@ -1017,6 +1080,8 @@ static void __init at91_pm_init(void (*pm_idle)(void))

void __init at91rm9200_pm_init(void)
{
int ret;

if (!IS_ENABLED(CONFIG_SOC_AT91RM9200))
return;

Expand All @@ -1028,7 +1093,9 @@ 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(false);
ret = at91_dt_ramc(false);
if (ret)
return;

/*
* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh.
Expand All @@ -1046,13 +1113,17 @@ void __init sam9x60_pm_init(void)
static const int iomaps[] __initconst = {
[AT91_PM_ULP1] = AT91_PM_IOMAP(SHDWC),
};
int ret;

if (!IS_ENABLED(CONFIG_SOC_SAM9X60))
return;

at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
at91_dt_ramc(false);
ret = at91_dt_ramc(false);
if (ret)
return;

at91_pm_init(NULL);

soc_pm.ws_ids = sam9x60_ws_ids;
Expand All @@ -1061,6 +1132,8 @@ void __init sam9x60_pm_init(void)

void __init at91sam9_pm_init(void)
{
int ret;

if (!IS_ENABLED(CONFIG_SOC_AT91SAM9))
return;

Expand All @@ -1072,7 +1145,10 @@ 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(false);
ret = at91_dt_ramc(false);
if (ret)
return;

at91_pm_init(at91sam9_idle);
}

Expand All @@ -1081,12 +1157,16 @@ void __init sama5_pm_init(void)
static const int modes[] __initconst = {
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST,
};
int ret;

if (!IS_ENABLED(CONFIG_SOC_SAMA5))
return;

at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_dt_ramc(false);
ret = at91_dt_ramc(false);
if (ret)
return;

at91_pm_init(NULL);
}

Expand All @@ -1101,18 +1181,27 @@ void __init sama5d2_pm_init(void)
[AT91_PM_BACKUP] = AT91_PM_IOMAP(SHDWC) |
AT91_PM_IOMAP(SFRBU),
};
int ret;

if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
return;

at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
at91_dt_ramc(false);
ret = at91_dt_ramc(false);
if (ret)
return;

at91_pm_init(NULL);

soc_pm.ws_ids = sama5d2_ws_ids;
soc_pm.config_shdwc_ws = at91_sama5d2_config_shdwc_ws;
soc_pm.config_pmc_ws = at91_sama5d2_config_pmc_ws;

soc_pm.sfrbu_regs.pswbu.key = (0x4BD20C << 8);
soc_pm.sfrbu_regs.pswbu.ctrl = BIT(0);
soc_pm.sfrbu_regs.pswbu.softsw = BIT(1);
soc_pm.sfrbu_regs.pswbu.state = BIT(3);
}

void __init sama7_pm_init(void)
Expand All @@ -1127,18 +1216,27 @@ void __init sama7_pm_init(void)
[AT91_PM_BACKUP] = AT91_PM_IOMAP(SFRBU) |
AT91_PM_IOMAP(SHDWC),
};
int ret;

if (!IS_ENABLED(CONFIG_SOC_SAMA7))
return;

at91_pm_modes_validate(modes, ARRAY_SIZE(modes));

at91_dt_ramc(true);
ret = at91_dt_ramc(true);
if (ret)
return;

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;

soc_pm.sfrbu_regs.pswbu.key = (0x4BD20C << 8);
soc_pm.sfrbu_regs.pswbu.ctrl = BIT(0);
soc_pm.sfrbu_regs.pswbu.softsw = BIT(1);
soc_pm.sfrbu_regs.pswbu.state = BIT(2);
}

static int __init at91_pm_modes_select(char *str)
Expand Down

0 comments on commit d0c624c

Please sign in to comment.