Commit 57d459e2 authored by Olof Johansson's avatar Olof Johansson

Merge tag 'imx-soc-5.14' of...

Merge tag 'imx-soc-5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into arm/soc

i.MX SoC changes for 5.14:

- Add SMP support for i.MX7D, as there are i.MX7D devices running in
  field with U-Boot that doesn't support PSCI.
- Fix imx5_cpu_suspend_info reference in i.MX5 PM code comments.
- Add SoC ID initialization for i.MX50.
- Drop unnecessary of_platform_default_populate() call from i.MX6Q
  .init_machine hook.
- A series from Oleksij Rempel to remove most of the i.MX6/7 board
  specific PHY fixups.

* tag 'imx-soc-5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux:
  ARM: imx: add smp support for imx7d
  ARM: imx6q: drop of_platform_default_populate() from init_machine
  ARM: imx7d: remove Atheros AR8031 PHY fixup
  ARM: imx6sx: remove Atheros AR8031 PHY fixup
  ARM: imx6q: remove Atheros AR8035 SmartEEE fixup
  ARM: imx6q: remove clk-out fixup for the Atheros AR8031 and AR8035 PHYs
  ARM: imx6q: remove BMCR_PDOWN handler in ar8035_phy_fixup()
  ARM: imx6q: remove part of ar8031_phy_fixup()
  ARM: imx6q: remove PHY fixup for KSZ9031
  ARM: imx: Initialize SoC ID on i.MX50
  ARM: imx: pm-imx5: Fix references to imx5_cpu_suspend_info

Link: https://lore.kernel.org/r/20210613082544.16067-2-shawnguo@kernel.orgSigned-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 2f80e8b4 e34645f4
......@@ -35,7 +35,7 @@ obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_IMX7D_CA7)$(CONFIG_SOC_LS1021A),)
AFLAGS_headsmp.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
......
......@@ -68,11 +68,13 @@ void imx_set_cpu_arg(int cpu, u32 arg);
void v7_secondary_startup(void);
void imx_scu_map_io(void);
void imx_smp_prepare(void);
void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn);
#else
static inline void imx_scu_map_io(void) {}
static inline void imx_smp_prepare(void) {}
#endif
void imx_src_init(void);
void imx7_src_init(void);
void imx_gpc_pre_suspend(bool arm_power_off);
void imx_gpc_post_resume(void);
void imx_gpc_mask_all(void);
......@@ -131,6 +133,7 @@ static inline void imx_init_l2cache(void) {}
#endif
extern const struct smp_operations imx_smp_ops;
extern const struct smp_operations imx7_smp_ops;
extern const struct smp_operations ls1021a_smp_ops;
#endif
......@@ -21,6 +21,15 @@ diag_reg_offset:
ENTRY(v7_secondary_startup)
ARM_BE8(setend be) @ go BE8 if entered LE
mrc p15, 0, r0, c0, c0, 0
lsl r0, r0, #16
lsr r0, r0, #20
/* 0xc07 is cortex A7's ID */
mov r1, #0xc00
orr r1, #0x7
cmp r0, r1
beq secondary_startup
set_diag_reg
b secondary_startup
ENDPROC(v7_secondary_startup)
......@@ -11,6 +11,7 @@
#include <asm/proc-fns.h>
#include "common.h"
#include "hardware.h"
/*
* platform-specific code to shutdown a CPU
......@@ -40,5 +41,7 @@ int imx_cpu_kill(unsigned int cpu)
return 0;
imx_enable_cpu(cpu, false);
imx_set_cpu_arg(cpu, 0);
if (cpu_is_imx7d())
imx_gpcv2_set_core1_pdn_pup_by_software(true);
return 1;
}
......@@ -9,6 +9,12 @@
#include <asm/mach/arch.h>
#include "common.h"
#include "hardware.h"
static void __init imx50_init_early(void)
{
mxc_set_cpu_type(MXC_CPU_MX50);
}
static const char * const imx50_dt_board_compat[] __initconst = {
"fsl,imx50",
......@@ -16,5 +22,6 @@ static const char * const imx50_dt_board_compat[] __initconst = {
};
DT_MACHINE_START(IMX50_DT, "Freescale i.MX50 (Device Tree Support)")
.init_early = imx50_init_early,
.dt_compat = imx50_dt_board_compat,
MACHINE_END
......@@ -40,27 +40,6 @@ static int ksz9021rn_phy_fixup(struct phy_device *phydev)
return 0;
}
static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val)
{
phy_write(dev, 0x0d, device);
phy_write(dev, 0x0e, reg);
phy_write(dev, 0x0d, (1 << 14) | device);
phy_write(dev, 0x0e, val);
}
static int ksz9031rn_phy_fixup(struct phy_device *dev)
{
/*
* min rx data delay, max rx/tx clock delay,
* min rx/tx control delay
*/
mmd_write_reg(dev, 2, 4, 0);
mmd_write_reg(dev, 2, 5, 0);
mmd_write_reg(dev, 2, 8, 0x003ff);
return 0;
}
/*
* fixup for PLX PEX8909 bridge to configure GPIO1-7 as output High
* as they are used for slots1-7 PERST#
......@@ -89,75 +68,11 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8609, ventana_pciesw_early_fixup);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8606, ventana_pciesw_early_fixup);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8604, ventana_pciesw_early_fixup);
static int ar8031_phy_fixup(struct phy_device *dev)
{
u16 val;
/* To enable AR8031 output a 125MHz clk from CLK_25M */
phy_write(dev, 0xd, 0x7);
phy_write(dev, 0xe, 0x8016);
phy_write(dev, 0xd, 0x4007);
val = phy_read(dev, 0xe);
val &= 0xffe3;
val |= 0x18;
phy_write(dev, 0xe, val);
/* introduce tx clock delay */
phy_write(dev, 0x1d, 0x5);
val = phy_read(dev, 0x1e);
val |= 0x0100;
phy_write(dev, 0x1e, val);
return 0;
}
#define PHY_ID_AR8031 0x004dd074
static int ar8035_phy_fixup(struct phy_device *dev)
{
u16 val;
/* Ar803x phy SmartEEE feature cause link status generates glitch,
* which cause ethernet link down/up issue, so disable SmartEEE
*/
phy_write(dev, 0xd, 0x3);
phy_write(dev, 0xe, 0x805d);
phy_write(dev, 0xd, 0x4003);
val = phy_read(dev, 0xe);
phy_write(dev, 0xe, val & ~(1 << 8));
/*
* Enable 125MHz clock from CLK_25M on the AR8031. This
* is fed in to the IMX6 on the ENET_REF_CLK (V22) pad.
* Also, introduce a tx clock delay.
*
* This is the same as is the AR8031 fixup.
*/
ar8031_phy_fixup(dev);
/*check phy power*/
val = phy_read(dev, 0x0);
if (val & BMCR_PDOWN)
phy_write(dev, 0x0, val & ~BMCR_PDOWN);
return 0;
}
#define PHY_ID_AR8035 0x004dd072
static void __init imx6q_enet_phy_init(void)
{
if (IS_BUILTIN(CONFIG_PHYLIB)) {
phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
ksz9021rn_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
ksz9031rn_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffef,
ar8031_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_AR8035, 0xffffffef,
ar8035_phy_fixup);
}
}
......@@ -257,9 +172,6 @@ static void __init imx6q_init_machine(void)
imx_get_soc_revision());
imx6q_enet_phy_init();
of_platform_default_populate(NULL, NULL, NULL);
imx_anatop_init();
cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init();
imx6q_1588_init();
......
......@@ -15,31 +15,6 @@
#include "common.h"
#include "cpuidle.h"
static int ar8031_phy_fixup(struct phy_device *dev)
{
u16 val;
/* Set RGMII IO voltage to 1.8V */
phy_write(dev, 0x1d, 0x1f);
phy_write(dev, 0x1e, 0x8);
/* introduce tx clock delay */
phy_write(dev, 0x1d, 0x5);
val = phy_read(dev, 0x1e);
val |= 0x0100;
phy_write(dev, 0x1e, val);
return 0;
}
#define PHY_ID_AR8031 0x004dd074
static void __init imx6sx_enet_phy_init(void)
{
if (IS_BUILTIN(CONFIG_PHYLIB))
phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
ar8031_phy_fixup);
}
static void __init imx6sx_enet_clk_sel(void)
{
struct regmap *gpr;
......@@ -57,7 +32,6 @@ static void __init imx6sx_enet_clk_sel(void)
static inline void imx6sx_enet_init(void)
{
imx6sx_enet_phy_init();
imx6sx_enet_clk_sel();
}
......
......@@ -14,25 +14,6 @@
#include "common.h"
static int ar8031_phy_fixup(struct phy_device *dev)
{
u16 val;
/* Set RGMII IO voltage to 1.8V */
phy_write(dev, 0x1d, 0x1f);
phy_write(dev, 0x1e, 0x8);
/* disable phy AR8031 SmartEEE function. */
phy_write(dev, 0xd, 0x3);
phy_write(dev, 0xe, 0x805d);
phy_write(dev, 0xd, 0x4003);
val = phy_read(dev, 0xe);
val &= ~(0x1 << 8);
phy_write(dev, 0xe, val);
return 0;
}
static int bcm54220_phy_fixup(struct phy_device *dev)
{
/* enable RXC skew select RGMII copper mode */
......@@ -44,14 +25,11 @@ static int bcm54220_phy_fixup(struct phy_device *dev)
return 0;
}
#define PHY_ID_AR8031 0x004dd074
#define PHY_ID_BCM54220 0x600d8589
static void __init imx7d_enet_phy_init(void)
{
if (IS_BUILTIN(CONFIG_PHYLIB)) {
phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
ar8031_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_BCM54220, 0xffffffff,
bcm54220_phy_fixup);
}
......@@ -91,7 +69,7 @@ static void __init imx7d_init_late(void)
static void __init imx7d_init_irq(void)
{
imx_init_revision_from_anatop();
imx_src_init();
imx7_src_init();
irqchip_init();
}
......@@ -102,6 +80,7 @@ static const char *const imx7d_dt_compat[] __initconst = {
};
DT_MACHINE_START(IMX7D, "Freescale i.MX7 Dual (Device Tree)")
.smp = smp_ops(imx7_smp_ops),
.init_irq = imx7d_init_irq,
.init_machine = imx7d_init_machine,
.init_late = imx7d_init_late,
......
......@@ -92,6 +92,32 @@ const struct smp_operations imx_smp_ops __initconst = {
#endif
};
/*
* Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system.
*/
static void __init imx7_smp_init_cpus(void)
{
struct device_node *np;
int i, ncores = 0;
/* The iMX7D SCU does not report core count, get it from DT */
for_each_of_cpu_node(np)
ncores++;
for (i = ncores; i < NR_CPUS; i++)
set_cpu_possible(i, false);
}
const struct smp_operations imx7_smp_ops __initconst = {
.smp_init_cpus = imx7_smp_init_cpus,
.smp_boot_secondary = imx_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = imx_cpu_die,
.cpu_kill = imx_cpu_kill,
#endif
};
#define DCFG_CCSR_SCRATCHRW1 0x200
static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle)
......
......@@ -6,15 +6,19 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/reset-controller.h>
#include <linux/smp.h>
#include <asm/smp_plat.h>
#include "common.h"
#include "hardware.h"
#define SRC_SCR 0x000
#define SRC_GPR1 0x020
#define SRC_GPR1_V1 0x020
#define SRC_GPR1_V2 0x074
#define SRC_GPR1(gpr_v2) ((gpr_v2) ? SRC_GPR1_V2 : SRC_GPR1_V1)
#define BP_SRC_SCR_WARM_RESET_ENABLE 0
#define BP_SRC_SCR_SW_GPU_RST 1
#define BP_SRC_SCR_SW_VPU_RST 2
......@@ -23,9 +27,18 @@
#define BP_SRC_SCR_SW_IPU2_RST 12
#define BP_SRC_SCR_CORE1_RST 14
#define BP_SRC_SCR_CORE1_ENABLE 22
/* below is for i.MX7D */
#define SRC_A7RCR1 0x008
#define BP_SRC_A7RCR1_A7_CORE1_ENABLE 1
#define GPC_CPU_PGC_SW_PUP_REQ 0xf0
#define GPC_CPU_PGC_SW_PDN_REQ 0xfc
#define GPC_PGC_C1 0x840
#define BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7 0x2
static void __iomem *src_base;
static DEFINE_SPINLOCK(scr_lock);
static bool gpr_v2;
static void __iomem *gpc_base;
static const int sw_reset_bits[5] = {
BP_SRC_SCR_SW_GPU_RST,
......@@ -73,17 +86,64 @@ static struct reset_controller_dev imx_reset_controller = {
.nr_resets = ARRAY_SIZE(sw_reset_bits),
};
static void imx_gpcv2_set_m_core_pgc(bool enable, u32 offset)
{
writel_relaxed(enable, gpc_base + offset);
}
/*
* The motivation for bringing up the second i.MX7D core inside the kernel
* is that legacy vendor bootloaders usually do not implement PSCI support.
* This is a significant blocker for systems in the field that are running old
* bootloader versions to upgrade to a modern mainline kernel version, as only
* one CPU of the i.MX7D would be brought up.
* Bring up the second i.MX7D core inside the kernel to make the migration
* path to mainline kernel easier for the existing iMX7D users.
*/
void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn)
{
u32 reg = pdn ? GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ;
u32 val, pup;
int ret;
imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C1);
val = readl_relaxed(gpc_base + reg);
val |= BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
writel_relaxed(val, gpc_base + reg);
ret = readl_relaxed_poll_timeout_atomic(gpc_base + reg, pup,
!(pup & BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7),
5, 1000000);
if (ret < 0) {
pr_err("i.MX7D: CORE1_A7 power up timeout\n");
val &= ~BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
writel_relaxed(val, gpc_base + reg);
}
imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C1);
}
void imx_enable_cpu(int cpu, bool enable)
{
u32 mask, val;
cpu = cpu_logical_map(cpu);
mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
spin_lock(&scr_lock);
val = readl_relaxed(src_base + SRC_SCR);
val = enable ? val | mask : val & ~mask;
val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
writel_relaxed(val, src_base + SRC_SCR);
if (gpr_v2) {
if (enable)
imx_gpcv2_set_core1_pdn_pup_by_software(false);
mask = 1 << (BP_SRC_A7RCR1_A7_CORE1_ENABLE + cpu - 1);
val = readl_relaxed(src_base + SRC_A7RCR1);
val = enable ? val | mask : val & ~mask;
writel_relaxed(val, src_base + SRC_A7RCR1);
} else {
mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
val = readl_relaxed(src_base + SRC_SCR);
val = enable ? val | mask : val & ~mask;
val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
writel_relaxed(val, src_base + SRC_SCR);
}
spin_unlock(&scr_lock);
}
......@@ -91,19 +151,19 @@ void imx_set_cpu_jump(int cpu, void *jump_addr)
{
cpu = cpu_logical_map(cpu);
writel_relaxed(__pa_symbol(jump_addr),
src_base + SRC_GPR1 + cpu * 8);
src_base + SRC_GPR1(gpr_v2) + cpu * 8);
}
u32 imx_get_cpu_arg(int cpu)
{
cpu = cpu_logical_map(cpu);
return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
return readl_relaxed(src_base + SRC_GPR1(gpr_v2) + cpu * 8 + 4);
}
void imx_set_cpu_arg(int cpu, u32 arg)
{
cpu = cpu_logical_map(cpu);
writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
writel_relaxed(arg, src_base + SRC_GPR1(gpr_v2) + cpu * 8 + 4);
}
void __init imx_src_init(void)
......@@ -131,3 +191,26 @@ void __init imx_src_init(void)
writel_relaxed(val, src_base + SRC_SCR);
spin_unlock(&scr_lock);
}
void __init imx7_src_init(void)
{
struct device_node *np;
gpr_v2 = true;
np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-src");
if (!np)
return;
src_base = of_iomap(np, 0);
if (!src_base)
return;
np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-gpc");
if (!np)
return;
gpc_base = of_iomap(np, 0);
if (!gpc_base)
return;
}
......@@ -28,11 +28,11 @@
* ^
* ^
* imx53_suspend code
* PM_INFO structure(imx53_suspend_info)
* PM_INFO structure(imx5_cpu_suspend_info)
* ======================== low address =======================
*/
/* Offsets of members of struct imx53_suspend_info */
/* Offsets of members of struct imx5_cpu_suspend_info */
#define SUSPEND_INFO_MX53_M4IF_V_OFFSET 0x0
#define SUSPEND_INFO_MX53_IOMUXC_V_OFFSET 0x4
#define SUSPEND_INFO_MX53_IO_COUNT_OFFSET 0x8
......
......@@ -70,6 +70,9 @@ static int __init imx_soc_device_init(void)
case MXC_CPU_MX35:
soc_id = "i.MX35";
break;
case MXC_CPU_MX50:
soc_id = "i.MX50";
break;
case MXC_CPU_MX51:
ocotp_compat = "fsl,imx51-iim";
soc_id = "i.MX51";
......
......@@ -9,6 +9,7 @@
#define MXC_CPU_MX27 27
#define MXC_CPU_MX31 31
#define MXC_CPU_MX35 35
#define MXC_CPU_MX50 50
#define MXC_CPU_MX51 51
#define MXC_CPU_MX53 53
#define MXC_CPU_IMX6SL 0x60
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment