mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
ARM: 32-bit SoC platform updates
Most of the SoC updates in this cycle are cleanups and moves to more
modern infrastructure:
- Davinci was moved to common clock framework
- OMAP1-based Amstrad E3 "Superphone" saw a bunch of cleanups to the
keyboard interface (bitbanged AT keyboard via GPIO).
- Removal of some stale code for Renesas platforms
- Power management improvements for i.MX6LL
-----BEGIN PGP SIGNATURE-----
iQJDBAABCAAtFiEElf+HevZ4QCAJmMQ+jBrnPN6EHHcFAlt+Lh0PHG9sb2ZAbGl4
b20ubmV0AAoJEIwa5zzehBx3Y+YP/2QVT1T1/Fz3WsuLg7BYa6r51BDxvr/pSQKh
eqLhZCcI5RpOlW4noWgJXWqnX2AlR1vX6xe0W0ebj177ttUHmidUQUJCpwP39AGE
LrVC2+mlFb3uPx0HlpHsx3zFZdNFfrhl5mN3JbZfnLv0fUibVEhR+K8ii7MV1/Fk
Lbo9sVPT8GIJuU6uyTTUnsCufwCkARMhrYbO6cbtS0FCO77a5aHp7btvHZ2ykxwh
hG9CI3FhfAP3Tkpm+IbHkC5jYQNRewQoqthzJ4WJbRrcdA/vaArBTOUoZG4NFMOM
M3B4jd1x26llmQhUqH4kGeOZiQ714GPrKcGS+8w7Twj5sIRGDxpif2Ac0kKL2B8X
Ps6UTM0cb63W9I+TphjLysKSarNjR2lVVhNVoJ8P47MSyDGIRpSR7+IWvlJ7U8vz
1yMWCguwrwZH3DnQb8UINTfI1Y1RstmtO5v8paSqfJyFX5r64x6VfYso1fRzxyFE
4r2TS0HRv117aKkHwY8smjielZ0CpGnyEDQgq9Z72V4FueIqsJQrA3oGYXgTArFl
mLL+fJUdwPv00nWuAZ8q0wIj1NvJvksJy+cObZXL6HK9m3cSdYwOHipdG86k20S5
6/KMPmgrMbV9YO3lVtfJZjdu2QTBiYVBPGfsiSo5lVL5Q5rDYV9QBijnE+9W9/yT
tJ038MhK
=ACVk
-----END PGP SIGNATURE-----
Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM 32-bit SoC platform updates from Olof Johansson:
"Most of the SoC updates in this cycle are cleanups and moves to more
modern infrastructure:
- Davinci was moved to common clock framework
- OMAP1-based Amstrad E3 "Superphone" saw a bunch of cleanups to the
keyboard interface (bitbanged AT keyboard via GPIO).
- Removal of some stale code for Renesas platforms
- Power management improvements for i.MX6LL"
* tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (112 commits)
ARM: uniphier: select RESET_CONTROLLER
arm64: uniphier: select RESET_CONTROLLER
ARM: uniphier: remove empty Makefile
ARM: exynos: Clear global variable on init error path
ARM: exynos: Remove outdated maintainer information
ARM: shmobile: Always enable ARCH_TIMER on SoCs with A7 and/or A15
ARM: shmobile: r8a7779: hide unused r8a7779_platform_cpu_kill
soc: r9a06g032: don't build SMP files for non-SMP config
ARM: shmobile: Add the R9A06G032 SMP enabler driver
ARM: at91: pm: configure wakeup sources for ULP1 mode
ARM: at91: pm: add PMC fast startup registers defines
ARM: at91: pm: Add ULP1 mode support
ARM: at91: pm: Use ULP0 naming instead of slow clock
ARM: hisi: handle of_iomap and fix missing of_node_put
ARM: hisi: check of_iomap and fix missing of_node_put
ARM: hisi: fix error handling and missing of_node_put
ARM: mx5: Set the DBGEN bit in ARM_GPC register
ARM: imx51: Configure M4IF to avoid visual artifacts
ARM: imx: call imx6sx_cpuidle_init() conditionally for 6sll
ARM: imx: fix i.MX6SLL build
...
This commit is contained in:
commit
9e259f9352
133 changed files with 2432 additions and 5307 deletions
|
|
@ -18,6 +18,9 @@ obj-$(CONFIG_SYSC_R8A77970) += r8a77970-sysc.o
|
|||
obj-$(CONFIG_SYSC_R8A77980) += r8a77980-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A77990) += r8a77990-sysc.o
|
||||
obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o
|
||||
ifdef CONFIG_SMP
|
||||
obj-$(CONFIG_ARCH_R9A06G032) += r9a06g032-smp.o
|
||||
endif
|
||||
|
||||
# Family
|
||||
obj-$(CONFIG_RST_RCAR) += rcar-rst.o
|
||||
|
|
|
|||
96
drivers/soc/renesas/r9a06g032-smp.c
Normal file
96
drivers/soc/renesas/r9a06g032-smp.c
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* R9A06G032 Second CA7 enabler.
|
||||
*
|
||||
* Copyright (C) 2018 Renesas Electronics Europe Limited
|
||||
*
|
||||
* Michel Pollet <michel.pollet@bp.renesas.com>, <buserror@gmail.com>
|
||||
* Derived from actions,s500-smp
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
/*
|
||||
* The second CPU is parked in ROM at boot time. It requires waking it after
|
||||
* writing an address into the BOOTADDR register of sysctrl.
|
||||
*
|
||||
* So the default value of the "cpu-release-addr" corresponds to BOOTADDR...
|
||||
*
|
||||
* *However* the BOOTADDR register is not available when the kernel
|
||||
* starts in NONSEC mode.
|
||||
*
|
||||
* So for NONSEC mode, the bootloader re-parks the second CPU into a pen
|
||||
* in SRAM, and changes the "cpu-release-addr" of linux's DT to a SRAM address,
|
||||
* which is not restricted.
|
||||
*/
|
||||
|
||||
static void __iomem *cpu_bootaddr;
|
||||
|
||||
static DEFINE_SPINLOCK(cpu_lock);
|
||||
|
||||
static int
|
||||
r9a06g032_smp_boot_secondary(unsigned int cpu,
|
||||
struct task_struct *idle)
|
||||
{
|
||||
if (!cpu_bootaddr)
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock(&cpu_lock);
|
||||
|
||||
writel(__pa_symbol(secondary_startup), cpu_bootaddr);
|
||||
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
|
||||
|
||||
spin_unlock(&cpu_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init r9a06g032_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
struct device_node *dn;
|
||||
int ret = -EINVAL, dns;
|
||||
u32 bootaddr;
|
||||
|
||||
dn = of_get_cpu_node(1, NULL);
|
||||
if (!dn) {
|
||||
pr_err("CPU#1: missing device tree node\n");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Determine the address from which the CPU is polling.
|
||||
* The bootloader *does* change this property.
|
||||
* Note: The property can be either 64 or 32 bits, so handle both cases
|
||||
*/
|
||||
if (of_find_property(dn, "cpu-release-addr", &dns)) {
|
||||
if (dns == sizeof(u64)) {
|
||||
u64 temp;
|
||||
|
||||
ret = of_property_read_u64(dn,
|
||||
"cpu-release-addr", &temp);
|
||||
bootaddr = temp;
|
||||
} else {
|
||||
ret = of_property_read_u32(dn,
|
||||
"cpu-release-addr",
|
||||
&bootaddr);
|
||||
}
|
||||
}
|
||||
of_node_put(dn);
|
||||
if (ret) {
|
||||
pr_err("CPU#1: invalid cpu-release-addr property\n");
|
||||
return;
|
||||
}
|
||||
pr_info("CPU#1: cpu-release-addr %08x\n", bootaddr);
|
||||
|
||||
cpu_bootaddr = ioremap(bootaddr, sizeof(bootaddr));
|
||||
}
|
||||
|
||||
static const struct smp_operations r9a06g032_smp_ops __initconst = {
|
||||
.smp_prepare_cpus = r9a06g032_smp_prepare_cpus,
|
||||
.smp_boot_secondary = r9a06g032_smp_boot_secondary,
|
||||
};
|
||||
|
||||
CPU_METHOD_OF_DECLARE(r9a06g032_smp,
|
||||
"renesas,r9a06g032-smp", &r9a06g032_smp_ops);
|
||||
|
|
@ -58,6 +58,12 @@
|
|||
|
||||
#define RCAR_PD_ALWAYS_ON 32 /* Always-on power area */
|
||||
|
||||
struct rcar_sysc_ch {
|
||||
u16 chan_offs;
|
||||
u8 chan_bit;
|
||||
u8 isr_bit;
|
||||
};
|
||||
|
||||
static void __iomem *rcar_sysc_base;
|
||||
static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
|
||||
|
||||
|
|
@ -143,12 +149,12 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
|
||||
static int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
|
||||
{
|
||||
return rcar_sysc_power(sysc_ch, false);
|
||||
}
|
||||
|
||||
int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
|
||||
static int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
|
||||
{
|
||||
return rcar_sysc_power(sysc_ch, true);
|
||||
}
|
||||
|
|
@ -315,6 +321,8 @@ struct rcar_pm_domains {
|
|||
struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1];
|
||||
};
|
||||
|
||||
static struct genpd_onecell_data *rcar_sysc_onecell_data;
|
||||
|
||||
static int __init rcar_sysc_pd_init(void)
|
||||
{
|
||||
const struct rcar_sysc_info *info;
|
||||
|
|
@ -326,9 +334,6 @@ static int __init rcar_sysc_pd_init(void)
|
|||
unsigned int i;
|
||||
int error;
|
||||
|
||||
if (rcar_sysc_base)
|
||||
return 0;
|
||||
|
||||
np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
|
@ -361,6 +366,7 @@ static int __init rcar_sysc_pd_init(void)
|
|||
|
||||
domains->onecell_data.domains = domains->domains;
|
||||
domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
|
||||
rcar_sysc_onecell_data = &domains->onecell_data;
|
||||
|
||||
for (i = 0, syscier = 0; i < info->num_areas; i++)
|
||||
syscier |= BIT(info->areas[i].isr_bit);
|
||||
|
|
@ -448,27 +454,39 @@ void __init rcar_sysc_nullify(struct rcar_sysc_area *areas,
|
|||
}
|
||||
}
|
||||
|
||||
void __init rcar_sysc_init(phys_addr_t base, u32 syscier)
|
||||
#ifdef CONFIG_ARCH_R8A7779
|
||||
static int rcar_sysc_power_cpu(unsigned int idx, bool on)
|
||||
{
|
||||
u32 syscimr;
|
||||
struct generic_pm_domain *genpd;
|
||||
struct rcar_sysc_pd *pd;
|
||||
unsigned int i;
|
||||
|
||||
if (!rcar_sysc_pd_init())
|
||||
return;
|
||||
if (!rcar_sysc_onecell_data)
|
||||
return -ENODEV;
|
||||
|
||||
rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
|
||||
for (i = 0; i < rcar_sysc_onecell_data->num_domains; i++) {
|
||||
genpd = rcar_sysc_onecell_data->domains[i];
|
||||
if (!genpd)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Mask all interrupt sources to prevent the CPU from receiving them.
|
||||
* Make sure not to clear reserved bits that were set before.
|
||||
*/
|
||||
syscimr = ioread32(rcar_sysc_base + SYSCIMR);
|
||||
syscimr |= syscier;
|
||||
pr_debug("%s: syscimr = 0x%08x\n", __func__, syscimr);
|
||||
iowrite32(syscimr, rcar_sysc_base + SYSCIMR);
|
||||
pd = to_rcar_pd(genpd);
|
||||
if (!(pd->flags & PD_CPU) || pd->ch.chan_bit != idx)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* SYSC needs all interrupt sources enabled to control power.
|
||||
*/
|
||||
pr_debug("%s: syscier = 0x%08x\n", __func__, syscier);
|
||||
iowrite32(syscier, rcar_sysc_base + SYSCIER);
|
||||
return on ? rcar_sysc_power_up(&pd->ch)
|
||||
: rcar_sysc_power_down(&pd->ch);
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int rcar_sysc_power_down_cpu(unsigned int cpu)
|
||||
{
|
||||
return rcar_sysc_power_cpu(cpu, false);
|
||||
}
|
||||
|
||||
int rcar_sysc_power_up_cpu(unsigned int cpu)
|
||||
{
|
||||
return rcar_sysc_power_cpu(cpu, true);
|
||||
}
|
||||
#endif /* CONFIG_ARCH_R8A7779 */
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ static struct am33xx_pm_sram_addr *pm_sram;
|
|||
static struct device *pm33xx_dev;
|
||||
static struct wkup_m3_ipc *m3_ipc;
|
||||
|
||||
static unsigned long suspend_wfi_flags;
|
||||
|
||||
static u32 sram_suspend_address(unsigned long addr)
|
||||
{
|
||||
return ((unsigned long)am33xx_do_wfi_sram +
|
||||
|
|
@ -53,7 +55,7 @@ static int am33xx_pm_suspend(suspend_state_t suspend_state)
|
|||
int i, ret = 0;
|
||||
|
||||
ret = pm_ops->soc_suspend((unsigned long)suspend_state,
|
||||
am33xx_do_wfi_sram);
|
||||
am33xx_do_wfi_sram, suspend_wfi_flags);
|
||||
|
||||
if (ret) {
|
||||
dev_err(pm33xx_dev, "PM: Kernel suspend failure\n");
|
||||
|
|
@ -227,6 +229,7 @@ static int am33xx_push_sram_idle(void)
|
|||
ro_sram_data.amx3_pm_sram_data_virt = ocmcram_location_data;
|
||||
ro_sram_data.amx3_pm_sram_data_phys =
|
||||
gen_pool_virt_to_phys(sram_pool_data, ocmcram_location_data);
|
||||
ro_sram_data.rtc_base_virt = pm_ops->get_rtc_base_addr();
|
||||
|
||||
/* Save physical address to calculate resume offset during pm init */
|
||||
am33xx_do_wfi_sram_phys = gen_pool_virt_to_phys(sram_pool,
|
||||
|
|
@ -310,6 +313,17 @@ static int am33xx_pm_probe(struct platform_device *pdev)
|
|||
suspend_set_ops(&am33xx_pm_ops);
|
||||
#endif /* CONFIG_SUSPEND */
|
||||
|
||||
/*
|
||||
* For a system suspend we must flush the caches, we want
|
||||
* the DDR in self-refresh, we want to save the context
|
||||
* of the EMIF, and we want the wkup_m3 to handle low-power
|
||||
* transition.
|
||||
*/
|
||||
suspend_wfi_flags |= WFI_FLAG_FLUSH_CACHE;
|
||||
suspend_wfi_flags |= WFI_FLAG_SELF_REFRESH;
|
||||
suspend_wfi_flags |= WFI_FLAG_SAVE_EMIF;
|
||||
suspend_wfi_flags |= WFI_FLAG_WAKE_M3;
|
||||
|
||||
ret = pm_ops->init();
|
||||
if (ret) {
|
||||
dev_err(dev, "Unable to call core pm init!\n");
|
||||
|
|
|
|||
Loading…
Reference in a new issue