Received: by 10.223.185.116 with SMTP id b49csp174102wrg; Mon, 19 Feb 2018 19:34:30 -0800 (PST) X-Google-Smtp-Source: AH8x225jTcbmSJyz/weQg8vgEdpOOkk3uuBc5nghDYRsOAv0R+yBZr2TrS18gGLW+b3MjXuKaVi5 X-Received: by 2002:a17:902:981:: with SMTP id 1-v6mr16363349pln.345.1519097670507; Mon, 19 Feb 2018 19:34:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519097670; cv=none; d=google.com; s=arc-20160816; b=Naa//aJ96P2cxBHMYCtjteLp2KLQBVUC80UpB6x2o5dQu/2zNdLWMNOuVmPebL8Co7 NhAtAd9rLGyhEyqi3jLIRgXKR2UdTHt0jS2xah2QiaDlhQm+doVkoxvEW8ftclS56UoD Q4xGyIifV7GnDhyZCAvrD7EhMUAnbzVIjZYXfoJRD7hI/JGgZxCMTyOVjtiHzqjghqT5 QPtSc1Di4sogc1oqhvBxQqb/SSC9/Ozfxi16D3cjCqpf7WUyTCEplY7/NyLWpWlpQISh iQOVGncWYarlRq2ScxKFwcvOcpRPyTDBL1yAEz450VTUUMExFOFpmmLMoMMsNqtQt2XG LPvQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:cc:to:subject :message-id:date:from:references:in-reply-to:mime-version :arc-authentication-results; bh=IzCCcI9Ksx+pByHm1+ScUBn+RNq6b63QM/e40okWxtE=; b=KiUNhFlceJMaVWevT/KX6CVzjsV39V+E2YIl0abfxG6YQ4dHyxTg274vLEPKAXhjyc 8Pk4K8EpiPhEwKGFoBLy42caa1uoqZy5x3oEBRQ6zj5LiYtk4QTQ+9shDO/J+m8iuZTo 06anNW7CAQQSZrGKenlHz47ahb2WEBtQsYvGzF3tGeY3xj/ljlWKgG389QwM65Ul75Zt FqB6x6O40oEIYmE0axc6j+Qzq/1i1FaaUXPUaaA9K1bk7Lbo4FkJJnaYZ98p5AvPNMzL qEeMI2RjAoGD/zr65RUEEkNAHvJuaS8B1mavYrtGx7aZDhdBA701BP2dEmYqi22AaY/w NPOQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r62si673467pfe.400.2018.02.19.19.34.16; Mon, 19 Feb 2018 19:34:30 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932437AbeBTDc3 convert rfc822-to-8bit (ORCPT + 99 others); Mon, 19 Feb 2018 22:32:29 -0500 Received: from mail-wm0-f65.google.com ([74.125.82.65]:38716 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932389AbeBTDc1 (ORCPT ); Mon, 19 Feb 2018 22:32:27 -0500 Received: by mail-wm0-f65.google.com with SMTP id z9so13249659wmb.3; Mon, 19 Feb 2018 19:32:26 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=edIjeuR35HMHFVd/WAnjwCTjsX+aEFZIqYratzU42pQ=; b=ls4J8rFS5hjKQIfJnIfg4I3MebzDvGHs8RB6iEttrykzBEuFRom4Va1f4Q7/LYTCp1 36E0zN3bfo5j9JaWR1OdNlSyKE4reV1t9W3dAhj6S76KIF4TTDxDQbMbrLy+kwrVUCxa J0dMirc5IwnK0oNCX50gbYMPJc2ulXmuWHu51xoAGU2Di0vNdRB6liinQ0t0b7yceVB0 N83nB9YPxYuedSltzQHXok8xyPKVhvEGztVR4WJspStkBvSdNDqMP45hJ5pzQo3c5O/N Rw6Z2HBOgCT3QwyJ2Snv7eJ3brCWbqqZ0pjyuTzPtEa5/S17kJMqoO4ql7ObJuj3rOG8 ZfDg== X-Gm-Message-State: APf1xPC2nmpBgf0qF+ok7aH2L890L2xQVa1KqRJIWJm2xnK9W40wRIKB rPc31JVV56HyFfAsya0oY7Fa3SUA X-Received: by 10.80.158.235 with SMTP id a98mr22628806edf.188.1519097545878; Mon, 19 Feb 2018 19:32:25 -0800 (PST) Received: from mail-wr0-f176.google.com (mail-wr0-f176.google.com. [209.85.128.176]) by smtp.gmail.com with ESMTPSA id c58sm11484089edb.33.2018.02.19.19.32.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 19 Feb 2018 19:32:25 -0800 (PST) Received: by mail-wr0-f176.google.com with SMTP id u15so11637605wrg.3; Mon, 19 Feb 2018 19:32:24 -0800 (PST) X-Received: by 10.223.162.152 with SMTP id s24mr7710891wra.148.1519097544375; Mon, 19 Feb 2018 19:32:24 -0800 (PST) MIME-Version: 1.0 Received: by 10.223.134.148 with HTTP; Mon, 19 Feb 2018 19:32:03 -0800 (PST) In-Reply-To: <20180219081837.15482-2-mylene.josserand@bootlin.com> References: <20180219081837.15482-1-mylene.josserand@bootlin.com> <20180219081837.15482-2-mylene.josserand@bootlin.com> From: Chen-Yu Tsai Date: Tue, 20 Feb 2018 11:32:03 +0800 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [PATCH v3 1/7] ARM: sun8i: smp: Add support for A83T To: =?UTF-8?Q?Myl=C3=A8ne_Josserand?= Cc: Maxime Ripard , Russell King , Rob Herring , Mark Rutland , devicetree , linux-arm-kernel , linux-kernel , LABBE Corentin , thomas.petazzoni@bootlin.com, quentin.schulz@bootlin.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8BIT Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, Feb 19, 2018 at 4:18 PM, Mylène Josserand wrote: > Add the support for A83T. > > A83T SoC has an additional register than A80 to handle CPU configurations: > R_CPUS_CFG. Information about the register comes from Allwinner's BSP > driver. > An important difference is the Power Off Gating register for clusters > which is BIT(4) in case of SUN9I-A80 and BIT(0) in case of SUN8I-A83T. > > Signed-off-by: Mylène Josserand > --- > arch/arm/mach-sunxi/Kconfig | 2 +- > arch/arm/mach-sunxi/mc_smp.c | 239 +++++++++++++++++++++++++++++++++++-------- The same high-level comments as Maxime. Splitting the patch will make this much easier to understand. > 2 files changed, 198 insertions(+), 43 deletions(-) > > diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig > index ce53ceaf4cc5..a0ad35c41c02 100644 > --- a/arch/arm/mach-sunxi/Kconfig > +++ b/arch/arm/mach-sunxi/Kconfig > @@ -51,7 +51,7 @@ config MACH_SUN9I > config ARCH_SUNXI_MC_SMP > bool > depends on SMP > - default MACH_SUN9I > + default y if MACH_SUN9I || MACH_SUN8I > select ARM_CCI400_PORT_CTRL > select ARM_CPU_SUSPEND > > diff --git a/arch/arm/mach-sunxi/mc_smp.c b/arch/arm/mach-sunxi/mc_smp.c > index 11e46c6efb90..fec592bf68b4 100644 > --- a/arch/arm/mach-sunxi/mc_smp.c > +++ b/arch/arm/mach-sunxi/mc_smp.c > @@ -55,20 +55,29 @@ > #define CPUCFG_CX_RST_CTRL_L2_RST BIT(8) > #define CPUCFG_CX_RST_CTRL_CX_RST(n) BIT(4 + (n)) > #define CPUCFG_CX_RST_CTRL_CORE_RST(n) BIT(n) > +#define CPUCFG_CX_RST_CTRL_CORE_RST_ALL (0xf << 0) > > #define PRCM_CPU_PO_RST_CTRL(c) (0x4 + 0x4 * (c)) > #define PRCM_CPU_PO_RST_CTRL_CORE(n) BIT(n) > #define PRCM_CPU_PO_RST_CTRL_CORE_ALL 0xf > #define PRCM_PWROFF_GATING_REG(c) (0x100 + 0x4 * (c)) > -#define PRCM_PWROFF_GATING_REG_CLUSTER BIT(4) > +/* The power off register for clusters are different from SUN9I and SUN8I */ > +#define PRCM_PWROFF_GATING_REG_CLUSTER_SUN8I BIT(0) > +#define PRCM_PWROFF_GATING_REG_CLUSTER_SUN9I BIT(4) > #define PRCM_PWROFF_GATING_REG_CORE(n) BIT(n) > #define PRCM_PWR_SWITCH_REG(c, cpu) (0x140 + 0x10 * (c) + 0x4 * (cpu)) > #define PRCM_CPU_SOFT_ENTRY_REG 0x164 > > +/* R_CPUCFG registers, specific to SUN8I */ > +#define R_CPUCFG_CLUSTER_PO_RST_CTRL(c) (0x30 + (c) * 0x4) > +#define R_CPUCFG_CLUSTER_PO_RST_CTRL_CORE(n) BIT(n) > +#define R_CPUCFG_CPU_SOFT_ENTRY_REG 0x01a4 > + > #define CPU0_SUPPORT_HOTPLUG_MAGIC0 0xFA50392F > #define CPU0_SUPPORT_HOTPLUG_MAGIC1 0x790DCA3A > > static void __iomem *cpucfg_base; > +static void __iomem *r_cpucfg_base; > static void __iomem *prcm_base; > static void __iomem *sram_b_smp_base; > > @@ -157,6 +166,16 @@ static int sunxi_cpu_powerup(unsigned int cpu, unsigned int cluster) > reg &= ~PRCM_CPU_PO_RST_CTRL_CORE(cpu); > writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster)); > > + if (r_cpucfg_base) { > + /* assert cpu power-on reset */ > + reg = readl(r_cpucfg_base + > + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); > + reg &= ~(R_CPUCFG_CLUSTER_PO_RST_CTRL_CORE(cpu)); > + writel(reg, r_cpucfg_base + > + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); > + udelay(10); > + } > + > /* Cortex-A7: hold L1 reset disable signal low */ > if (!sunxi_core_is_cortex_a15(cpu, cluster)) { > reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG0(cluster)); > @@ -180,17 +199,37 @@ static int sunxi_cpu_powerup(unsigned int cpu, unsigned int cluster) > /* open power switch */ > sunxi_cpu_power_switch_set(cpu, cluster, true); > > + /* Handle A83T bit swap */ > + if (of_machine_is_compatible("allwinner,sun8i-a83t")) { > + if (cpu == 0) > + cpu = 4; > + } > + > /* clear processor power gate */ > reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster)); > reg &= ~PRCM_PWROFF_GATING_REG_CORE(cpu); > writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster)); > udelay(20); > > + if (of_machine_is_compatible("allwinner,sun8i-a83t")) { > + if (cpu == 4) > + cpu = 0; > + } > + > /* de-assert processor power-on reset */ > reg = readl(prcm_base + PRCM_CPU_PO_RST_CTRL(cluster)); > reg |= PRCM_CPU_PO_RST_CTRL_CORE(cpu); > writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster)); > > + if (r_cpucfg_base) { > + reg = readl(r_cpucfg_base + > + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); > + reg |= R_CPUCFG_CLUSTER_PO_RST_CTRL_CORE(cpu); > + writel(reg, r_cpucfg_base + > + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); > + udelay(10); > + } > + > /* de-assert all processor resets */ > reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster)); > reg |= CPUCFG_CX_RST_CTRL_DBG_RST(cpu); > @@ -212,6 +251,14 @@ static int sunxi_cluster_powerup(unsigned int cluster) > if (cluster >= SUNXI_NR_CLUSTERS) > return -EINVAL; > > + /* For A83T, assert cluster cores resets */ > + if (of_machine_is_compatible("allwinner,sun8i-a83t")) { > + reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster)); > + reg &= ~CPUCFG_CX_RST_CTRL_CORE_RST_ALL; /* Core Reset */ > + writel(reg, cpucfg_base + CPUCFG_CX_RST_CTRL(cluster)); > + udelay(10); > + } > + > /* assert ACINACTM */ > reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG1(cluster)); > reg |= CPUCFG_CX_CTRL_REG1_ACINACTM; > @@ -222,6 +269,16 @@ static int sunxi_cluster_powerup(unsigned int cluster) > reg &= ~PRCM_CPU_PO_RST_CTRL_CORE_ALL; > writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster)); > > + /* assert cluster cores resets */ > + if (r_cpucfg_base) { > + reg = readl(r_cpucfg_base + > + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); > + reg &= ~CPUCFG_CX_RST_CTRL_CORE_RST_ALL; > + writel(reg, r_cpucfg_base + > + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); > + udelay(10); > + } > + > /* assert cluster resets */ > reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster)); > reg &= ~CPUCFG_CX_RST_CTRL_DBG_SOC_RST; > @@ -252,7 +309,10 @@ static int sunxi_cluster_powerup(unsigned int cluster) > > /* clear cluster power gate */ > reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster)); > - reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER; > + if (of_machine_is_compatible("allwinner,sun8i-a83t")) > + reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER_SUN8I; > + else > + reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER_SUN9I; > writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster)); > udelay(20); > > @@ -516,7 +576,10 @@ static int sunxi_cluster_powerdown(unsigned int cluster) > /* gate cluster power */ > pr_debug("%s: gate cluster power\n", __func__); > reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster)); > - reg |= PRCM_PWROFF_GATING_REG_CLUSTER; > + if (of_machine_is_compatible("allwinner,sun8i-a83t")) > + reg |= PRCM_PWROFF_GATING_REG_CLUSTER_SUN8I; > + else > + reg |= PRCM_PWROFF_GATING_REG_CLUSTER_SUN9I; > writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster)); > udelay(20); > > @@ -684,37 +747,25 @@ static int __init sunxi_mc_smp_lookback(void) > return ret; > } > > -static int __init sunxi_mc_smp_init(void) > +static int sun9i_dt_parsing(struct resource res) > { > - struct device_node *cpucfg_node, *sram_node, *node; > - struct resource res; > + struct device_node *prcm_node, *cpucfg_node, *sram_node; > int ret; > > - if (!of_machine_is_compatible("allwinner,sun9i-a80")) > - return -ENODEV; > - > - if (!sunxi_mc_smp_cpu_table_init()) > - return -EINVAL; > - > - if (!cci_probed()) { > - pr_err("%s: CCI-400 not available\n", __func__); > - return -ENODEV; > - } > - > - node = of_find_compatible_node(NULL, NULL, "allwinner,sun9i-a80-prcm"); > - if (!node) { > - pr_err("%s: PRCM not available\n", __func__); > + prcm_node = of_find_compatible_node(NULL, NULL, > + "allwinner,sun9i-a80-prcm"); > + if (!prcm_node) > return -ENODEV; > - } > > /* > * Unfortunately we can not request the I/O region for the PRCM. > * It is shared with the PRCM clock. > */ > - prcm_base = of_iomap(node, 0); > - of_node_put(node); > + prcm_base = of_iomap(prcm_node, 0); > + of_node_put(prcm_node); > if (!prcm_base) { > pr_err("%s: failed to map PRCM registers\n", __func__); > + iounmap(prcm_base); Why are you trying to unmap the pointer that you already failed to map? > return -ENOMEM; > } > > @@ -748,35 +799,88 @@ static int __init sunxi_mc_smp_init(void) > goto err_put_sram_node; > } > > - /* Configure CCI-400 for boot cluster */ > - ret = sunxi_mc_smp_lookback(); > - if (ret) { > - pr_err("%s: failed to configure boot cluster: %d\n", > - __func__, ret); > - goto err_unmap_release_secure_sram; > - } > + r_cpucfg_base = NULL; This is not needed. Global static variables without initial values are always initialized to 0. > > /* We don't need the CPUCFG and SRAM device nodes anymore */ > of_node_put(cpucfg_node); > of_node_put(sram_node); > > - /* Set the hardware entry point address */ > - writel(__pa_symbol(sunxi_mc_smp_secondary_startup), > - prcm_base + PRCM_CPU_SOFT_ENTRY_REG); > - > - /* Actually enable multi cluster SMP */ > - smp_set_ops(&sunxi_mc_smp_smp_ops); > - > - pr_info("sunxi multi cluster SMP support installed\n"); > - > return 0; > > -err_unmap_release_secure_sram: > - iounmap(sram_b_smp_base); > - of_address_to_resource(sram_node, 0, &res); > +err_unmap_release_cpucfg: > + iounmap(cpucfg_base); > + of_address_to_resource(cpucfg_node, 0, &res); > release_mem_region(res.start, resource_size(&res)); > err_put_sram_node: > of_node_put(sram_node); > +err_put_cpucfg_node: > + of_node_put(cpucfg_node); > +err_unmap_prcm: > + iounmap(prcm_base); > + > + return ret; > +} > + > +static int sun8i_dt_parsing(struct resource res) > +{ > + struct device_node *node, *cpucfg_node; > + int ret; > + > + node = of_find_compatible_node(NULL, NULL, > + "allwinner,sun8i-a83t-prcm"); > + if (!node) > + return -ENODEV; > + > + /* > + * Unfortunately we can not request the I/O region for the PRCM. > + * It is shared with the PRCM clock. > + */ > + prcm_base = of_iomap(node, 0); > + of_node_put(node); > + if (!prcm_base) { > + pr_err("%s: failed to map PRCM registers\n", __func__); > + iounmap(prcm_base); > + return -ENOMEM; > + } > + > + cpucfg_node = of_find_compatible_node(NULL, NULL, > + "allwinner,sun8i-a83t-cpucfg"); > + if (!cpucfg_node) { > + ret = -ENODEV; > + pr_err("%s: CPUCFG not available\n", __func__); > + goto err_unmap_prcm; > + } > + > + cpucfg_base = of_io_request_and_map(cpucfg_node, 0, "sunxi-mc-smp"); > + if (IS_ERR(cpucfg_base)) { > + ret = PTR_ERR(cpucfg_base); > + pr_err("%s: failed to map CPUCFG registers: %d\n", > + __func__, ret); > + goto err_put_cpucfg_node; > + } > + > + node = of_find_compatible_node(NULL, NULL, > + "allwinner,sun8i-a83t-r-cpucfg"); > + if (!node) { > + ret = -ENODEV; > + goto err_unmap_release_cpucfg; > + } > + > + r_cpucfg_base = of_iomap(node, 0); > + if (!r_cpucfg_base) { > + pr_err("%s: failed to map R-CPUCFG registers\n", > + __func__); > + ret = -ENOMEM; > + goto err_put_node; > + } > + > + /* We don't need the CPUCFG device node anymore */ > + of_node_put(cpucfg_node); > + of_node_put(node); > + > + return 0; > +err_put_node: > + of_node_put(node); > err_unmap_release_cpucfg: > iounmap(cpucfg_base); > of_address_to_resource(cpucfg_node, 0, &res); > @@ -785,6 +889,57 @@ static int __init sunxi_mc_smp_init(void) > of_node_put(cpucfg_node); > err_unmap_prcm: > iounmap(prcm_base); > + > + return ret; > +} > + > +static int __init sunxi_mc_smp_init(void) > +{ > + struct resource res; > + int ret; > + > + if (!of_machine_is_compatible("allwinner,sun9i-a80") && > + !of_machine_is_compatible("allwinner,sun8i-a83t")) > + return -ENODEV; > + > + if (!sunxi_mc_smp_cpu_table_init()) > + return -EINVAL; > + > + if (!cci_probed()) { > + pr_err("%s: CCI-400 not available\n", __func__); > + return -ENODEV; > + } > + > + if (of_machine_is_compatible("allwinner,sun9i-a80")) > + ret = sun9i_dt_parsing(res); > + else > + ret = sun8i_dt_parsing(res); > + if (ret) { > + pr_err("%s: failed to parse DT: %d\n", __func__, ret); > + return ret; > + } > + > + /* Configure CCI-400 for boot cluster */ > + ret = sunxi_mc_smp_lookback(); > + if (ret) { > + pr_err("%s: failed to configure boot cluster: %d\n", > + __func__, ret); > + return ret; /* MYMY: Need to handle this error case */ Please add functions to release the resources. They will need to be platform specific, since it requires you to find the device node to get the resource that you want to release (for CPUCFG / R-CPUCFG). For sun9i do it in the refactor patch. For A83T do it in the patch you add support. Thanks ChenYu > + } > + > + /* Set the hardware entry point address */ > + if (of_machine_is_compatible("allwinner,sun9i-a80")) > + writel(__pa_symbol(sunxi_mc_smp_secondary_startup), > + prcm_base + PRCM_CPU_SOFT_ENTRY_REG); > + else > + writel(__pa_symbol(sunxi_mc_smp_secondary_startup), > + r_cpucfg_base + R_CPUCFG_CPU_SOFT_ENTRY_REG); > + > + /* Actually enable multi cluster SMP */ > + smp_set_ops(&sunxi_mc_smp_smp_ops); > + > + pr_info("sunxi multi cluster SMP support installed\n"); > + > return ret; > } > > -- > 2.11.0 >