Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 May 2017 17:01:15 +0000 (10:01 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 May 2017 17:01:15 +0000 (10:01 -0700)
Pull ARM SoC driver updates from Olof Johansson:
 "Driver updates for ARM SoCs:

  Reset subsystem, merged through arm-soc by tradition:
   - Make bool drivers explicitly non-modular
   - New support for i.MX7 and Arria10 reset controllers

  PATA driver for Palmchip BK371 (acked by Tejun)

  Power domain drivers for i.MX (GPC, GPCv2)
   - Moved out of mach-imx for GPC
   - Bunch of tweaks, fixes, etc

  PMC support for Tegra186

  SoC detection support for Renesas RZ/G1H and RZ/G1N

  Move Tegra flow controller driver from mach directory to drivers/soc
   - (Power management / CPU power driver)

  Misc smaller tweaks for other platforms"

* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (60 commits)
  soc: pm-domain: Fix the mangled urls
  soc: renesas: rcar-sysc: Add support for R-Car H3 ES2.0
  soc: renesas: rcar-sysc: Add support for fixing up power area tables
  soc: renesas: Register SoC device early
  soc: imx: gpc: add workaround for i.MX6QP to the GPC PD driver
  dt-bindings: imx-gpc: add i.MX6 QuadPlus compatible
  soc: imx: gpc: add defines for domain index
  soc: imx: Add GPCv2 power gating driver
  dt-bindings: Add GPCv2 power gating driver
  ARM/clk: move the ICST library to drivers/clk
  ARM: plat-versatile: remove stale clock header
  ARM: keystone: Drop PM domain support for k2g
  soc: ti: Add ti_sci_pm_domains driver
  dt-bindings: Add TI SCI PM Domains
  PM / Domains: Do not check if simple providers have phandle cells
  PM / Domains: Add generic data pointer to genpd data struct
  soc/tegra: Add initial flowctrl support for Tegra132/210
  soc/tegra: flowctrl: Add basic platform driver
  soc/tegra: Move Tegra flowctrl driver
  ARM: tegra: Remove unnecessary inclusion of flowctrl header
  ...

88 files changed:
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt [new file with mode: 0644]
Documentation/devicetree/bindings/reset/fsl,imx7-src.txt [new file with mode: 0644]
Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt [new file with mode: 0644]
MAINTAINERS
arch/arm/common/Kconfig
arch/arm/common/Makefile
arch/arm/mach-imx/gpc.c
arch/arm/mach-keystone/Kconfig
arch/arm/mach-keystone/pm_domain.c
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/cpuidle-tegra20.c
arch/arm/mach-tegra/platsmp.c
arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/reset-handler.S
arch/arm/mach-tegra/sleep-tegra20.S
arch/arm/mach-tegra/sleep-tegra30.S
arch/arm/mach-tegra/sleep.S
arch/arm/mach-tegra/tegra.c
arch/arm/plat-versatile/include/plat/clock.h [deleted file]
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/pata_bk3710.c [new file with mode: 0644]
drivers/base/power/domain.c
drivers/base/soc.c
drivers/clk/versatile/Kconfig
drivers/clk/versatile/Makefile
drivers/clk/versatile/clk-icst.c
drivers/clk/versatile/clk-icst.h
drivers/clk/versatile/clk-impd1.c
drivers/clk/versatile/clk-realview.c
drivers/clk/versatile/clk-versatile.c
drivers/clk/versatile/icst.c [moved from arch/arm/common/icst.c with 98% similarity]
drivers/clk/versatile/icst.h [moved from arch/arm/include/asm/hardware/icst.h with 94% similarity]
drivers/firmware/arm_scpi.c
drivers/firmware/meson/meson_sm.c
drivers/firmware/qcom_scm-32.c
drivers/firmware/qcom_scm-64.c
drivers/firmware/qcom_scm.c
drivers/firmware/qcom_scm.h
drivers/nvmem/meson-efuse.c
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/reset-a10sr.c [new file with mode: 0644]
drivers/reset/reset-ath79.c
drivers/reset/reset-imx7.c [new file with mode: 0644]
drivers/reset/reset-meson.c
drivers/reset/reset-oxnas.c
drivers/reset/reset-pistachio.c
drivers/reset/reset-socfpga.c
drivers/reset/reset-sunxi.c
drivers/reset/reset-uniphier.c
drivers/soc/Kconfig
drivers/soc/Makefile
drivers/soc/bcm/brcmstb/common.c
drivers/soc/imx/Kconfig [new file with mode: 0644]
drivers/soc/imx/Makefile [new file with mode: 0644]
drivers/soc/imx/gpc.c [new file with mode: 0644]
drivers/soc/imx/gpcv2.c [new file with mode: 0644]
drivers/soc/renesas/r8a7795-sysc.c
drivers/soc/renesas/rcar-sysc.c
drivers/soc/renesas/rcar-sysc.h
drivers/soc/renesas/renesas-soc.c
drivers/soc/samsung/Kconfig
drivers/soc/samsung/Makefile
drivers/soc/samsung/exynos-pmu.c
drivers/soc/samsung/exynos-pmu.h
drivers/soc/tegra/Kconfig
drivers/soc/tegra/Makefile
drivers/soc/tegra/flowctrl.c [moved from arch/arm/mach-tegra/flowctrl.c with 67% similarity]
drivers/soc/tegra/fuse/fuse-tegra.c
drivers/soc/tegra/pmc-tegra186.c [new file with mode: 0644]
drivers/soc/ti/Kconfig
drivers/soc/ti/Makefile
drivers/soc/ti/ti_sci_pm_domains.c [new file with mode: 0644]
drivers/soc/zte/zx296718_pm_domains.c
drivers/soc/zte/zx2967_pm_domains.c
include/dt-bindings/genpd/k2g.h [new file with mode: 0644]
include/dt-bindings/power/imx7-power.h [new file with mode: 0644]
include/dt-bindings/power/r8a7795-sysc.h
include/dt-bindings/reset/altr,rst-mgr-a10sr.h [new file with mode: 0644]
include/dt-bindings/reset/imx7-reset.h [new file with mode: 0644]
include/linux/firmware/meson/meson_sm.h
include/linux/pm_domain.h
include/linux/qcom_scm.h
include/soc/tegra/flowctrl.h [moved from arch/arm/mach-tegra/flowctrl.h with 77% similarity]
include/soc/tegra/pmc.h

diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
new file mode 100644 (file)
index 0000000..078a58b
--- /dev/null
@@ -0,0 +1,34 @@
+NVIDIA Tegra Power Management Controller (PMC)
+
+Required properties:
+- compatible: Should contain one of the following:
+  - "nvidia,tegra186-pmc": for Tegra186
+- reg: Must contain an (offset, length) pair of the register set for each
+  entry in reg-names.
+- reg-names: Must include the following entries:
+  - "pmc"
+  - "wake"
+  - "aotag"
+  - "scratch"
+
+Optional properties:
+- nvidia,invert-interrupt: If present, inverts the PMU interrupt signal.
+
+Example:
+
+SoC DTSI:
+
+       pmc@c3600000 {
+               compatible = "nvidia,tegra186-pmc";
+               reg = <0 0x0c360000 0 0x10000>,
+                     <0 0x0c370000 0 0x10000>,
+                     <0 0x0c380000 0 0x10000>,
+                     <0 0x0c390000 0 0x10000>;
+               reg-names = "pmc", "wake", "aotag", "scratch";
+       };
+
+Board DTS:
+
+       pmc@c360000 {
+               nvidia,invert-interrupt;
+       };
index 65cc0345747d73f540d6c5a4e8b18acc1618953b..6c1498958d48c0221ff2d7731051f5f82ea5fe85 100644 (file)
@@ -1,22 +1,42 @@
 Freescale i.MX General Power Controller
 =======================================
 
-The i.MX6Q General Power Control (GPC) block contains DVFS load tracking
-counters and Power Gating Control (PGC) for the CPU and PU (GPU/VPU) power
-domains.
+The i.MX6 General Power Control (GPC) block contains DVFS load tracking
+counters and Power Gating Control (PGC).
 
 Required properties:
-- compatible: Should be "fsl,imx6q-gpc" or "fsl,imx6sl-gpc"
+- compatible: Should be one of the following:
+  - fsl,imx6q-gpc
+  - fsl,imx6qp-gpc
+  - fsl,imx6sl-gpc
 - reg: should be register base and length as documented in the
   datasheet
-- interrupts: Should contain GPC interrupt request 1
-- pu-supply: Link to the LDO regulator powering the PU power domain
-- clocks: Clock phandles to devices in the PU power domain that need
-         to be enabled during domain power-up for reset propagation.
-- #power-domain-cells: Should be 1, see below:
+- interrupts: Should contain one interrupt specifier for the GPC interrupt
+- clocks: Must contain an entry for each entry in clock-names.
+  See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - ipg
 
-The gpc node is a power-controller as documented by the generic power domain
-bindings in Documentation/devicetree/bindings/power/power_domain.txt.
+The power domains are generic power domain providers as documented in
+Documentation/devicetree/bindings/power/power_domain.txt. They are described as
+subnodes of the power gating controller 'pgc' node of the GPC and should
+contain the following:
+
+Required properties:
+- reg: Must contain the DOMAIN_INDEX of this power domain
+  The following DOMAIN_INDEX values are valid for i.MX6Q:
+  ARM_DOMAIN     0
+  PU_DOMAIN      1
+  The following additional DOMAIN_INDEX value is valid for i.MX6SL:
+  DISPLAY_DOMAIN 2
+
+- #power-domain-cells: Should be 0
+
+Optional properties:
+- clocks: a number of phandles to clocks that need to be enabled during domain
+  power-up sequencing to ensure reset propagation into devices located inside
+  this power domain
+- power-supply: a phandle to the regulator powering this domain
 
 Example:
 
@@ -25,14 +45,30 @@ Example:
                reg = <0x020dc000 0x4000>;
                interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
                             <0 90 IRQ_TYPE_LEVEL_HIGH>;
-               pu-supply = <&reg_pu>;
-               clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>,
-                        <&clks IMX6QDL_CLK_GPU3D_SHADER>,
-                        <&clks IMX6QDL_CLK_GPU2D_CORE>,
-                        <&clks IMX6QDL_CLK_GPU2D_AXI>,
-                        <&clks IMX6QDL_CLK_OPENVG_AXI>,
-                        <&clks IMX6QDL_CLK_VPU_AXI>;
-               #power-domain-cells = <1>;
+               clocks = <&clks IMX6QDL_CLK_IPG>;
+               clock-names = "ipg";
+
+               pgc {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       power-domain@0 {
+                               reg = <0>;
+                               #power-domain-cells = <0>;
+                       };
+
+                       pd_pu: power-domain@1 {
+                               reg = <1>;
+                               #power-domain-cells = <0>;
+                               power-supply = <&reg_pu>;
+                               clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>,
+                                        <&clks IMX6QDL_CLK_GPU3D_SHADER>,
+                                        <&clks IMX6QDL_CLK_GPU2D_CORE>,
+                                        <&clks IMX6QDL_CLK_GPU2D_AXI>,
+                                        <&clks IMX6QDL_CLK_OPENVG_AXI>,
+                                        <&clks IMX6QDL_CLK_VPU_AXI>;
+                       };
+               };
        };
 
 
@@ -40,20 +76,13 @@ Specifying power domain for IP modules
 ======================================
 
 IP cores belonging to a power domain should contain a 'power-domains' property
-that is a phandle pointing to the gpc device node and a DOMAIN_INDEX specifying
-the power domain the device belongs to.
+that is a phandle pointing to the power domain the device belongs to.
 
 Example of a device that is part of the PU power domain:
 
        vpu: vpu@02040000 {
                reg = <0x02040000 0x3c000>;
                /* ... */
-               power-domains = <&gpc 1>;
+               power-domains = <&pd_pu>;
                /* ... */
        };
-
-The following DOMAIN_INDEX values are valid for i.MX6Q:
-ARM_DOMAIN     0
-PU_DOMAIN      1
-The following additional DOMAIN_INDEX value is valid for i.MX6SL:
-DISPLAY_DOMAIN 2
diff --git a/Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt b/Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt
new file mode 100644 (file)
index 0000000..02f45c6
--- /dev/null
@@ -0,0 +1,71 @@
+Freescale i.MX General Power Controller v2
+==========================================
+
+The i.MX7S/D General Power Control (GPC) block contains Power Gating
+Control (PGC) for various power domains.
+
+Required properties:
+
+- compatible: Should be "fsl,imx7d-gpc"
+
+- reg: should be register base and length as documented in the
+  datasheet
+
+- interrupts: Should contain GPC interrupt request 1
+
+Power domains contained within GPC node are generic power domain
+providers, documented in
+Documentation/devicetree/bindings/power/power_domain.txt, which are
+described as subnodes of the power gating controller 'pgc' node,
+which, in turn, is expected to contain the following:
+
+Required properties:
+
+- reg: Power domain index. Valid values are defined in
+  include/dt-bindings/power/imx7-power.h
+
+- #power-domain-cells: Should be 0
+
+Optional properties:
+
+- power-supply: Power supply used to power the domain
+
+Example:
+
+       gpc: gpc@303a0000 {
+               compatible = "fsl,imx7d-gpc";
+               reg = <0x303a0000 0x1000>;
+               interrupt-controller;
+               interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+               #interrupt-cells = <3>;
+               interrupt-parent = <&intc>;
+
+               pgc {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       pgc_pcie_phy: power-domain@3 {
+                               #power-domain-cells = <0>;
+
+                               reg = <IMX7_POWER_DOMAIN_PCIE_PHY>;
+                               power-supply = <&reg_1p0d>;
+                       };
+               };
+       };
+
+
+Specifying power domain for IP modules
+======================================
+
+IP cores belonging to a power domain should contain a 'power-domains'
+property that is a phandle for PGC node representing the domain.
+
+Example of a device that is part of the PCIE_PHY power domain:
+
+       pcie: pcie@33800000 {
+             reg = <0x33800000 0x4000>,
+                   <0x4ff00000 0x80000>;
+               /* ... */
+               power-domains = <&pgc_pcie_phy>;
+               /* ... */
+       };
diff --git a/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
new file mode 100644 (file)
index 0000000..5e1afc3
--- /dev/null
@@ -0,0 +1,47 @@
+Freescale i.MX7 System Reset Controller
+======================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "fsl,imx7-src", "syscon"
+- reg: should be register base and length as documented in the
+  datasheet
+- interrupts: Should contain SRC interrupt
+- #reset-cells: 1, see below
+
+example:
+
+src: reset-controller@30390000 {
+     compatible = "fsl,imx7d-src", "syscon";
+     reg = <0x30390000 0x2000>;
+     interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+     #reset-cells = <1>;
+};
+
+
+Specifying reset lines connected to IP modules
+==============================================
+
+The system reset controller can be used to reset various set of
+peripherals. Device nodes that need access to reset lines should
+specify them as a reset phandle in their corresponding node as
+specified in reset.txt.
+
+Example:
+
+       pcie: pcie@33800000 {
+
+               ...
+
+               resets = <&src IMX7_RESET_PCIEPHY>,
+                        <&src IMX7_RESET_PCIE_CTRL_APPS_EN>;
+               reset-names = "pciephy", "apps";
+
+               ...
+        };
+
+
+For list of all valid reset indicies see
+<dt-bindings/reset/imx7-reset.h>
diff --git a/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
new file mode 100644 (file)
index 0000000..c705db0
--- /dev/null
@@ -0,0 +1,57 @@
+Texas Instruments TI-SCI Generic Power Domain
+---------------------------------------------
+
+Some TI SoCs contain a system controller (like the PMMC, etc...) that is
+responsible for controlling the state of the IPs that are present.
+Communication between the host processor running an OS and the system
+controller happens through a protocol known as TI-SCI [1].
+
+[1] Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
+
+PM Domain Node
+==============
+The PM domain node represents the global PM domain managed by the PMMC, which
+in this case is the implementation as documented by the generic PM domain
+bindings in Documentation/devicetree/bindings/power/power_domain.txt.  Because
+this relies on the TI SCI protocol to communicate with the PMMC it must be a
+child of the pmmc node.
+
+Required Properties:
+--------------------
+- compatible: should be "ti,sci-pm-domain"
+- #power-domain-cells: Must be 1 so that an id can be provided in each
+                      device node.
+
+Example (K2G):
+-------------
+       pmmc: pmmc {
+               compatible = "ti,k2g-sci";
+               ...
+
+               k2g_pds: power-controller {
+                       compatible = "ti,sci-pm-domain";
+                       #power-domain-cells = <1>;
+               };
+       };
+
+PM Domain Consumers
+===================
+Hardware blocks belonging to a PM domain should contain a "power-domains"
+property that is a phandle pointing to the corresponding PM domain node
+along with an index representing the device id to be passed to the PMMC
+for device control.
+
+Required Properties:
+--------------------
+- power-domains: phandle pointing to the corresponding PM domain node
+                and an ID representing the device.
+
+See dt-bindings/genpd/k2g.h for the list of valid identifiers for k2g.
+
+Example (K2G):
+--------------------
+       uart0: serial@02530c00 {
+               compatible = "ns16550a";
+               ...
+               power-domains = <&k2g_pds K2G_DEV_UART0>;
+       };
index 9d58e9f18705bd904461b6c796afb279b634b554..41590d3a665a60f8ee5a7b158cb13c0f01b5e45c 100644 (file)
@@ -653,7 +653,9 @@ M:  Thor Thayer <thor.thayer@linux.intel.com>
 S:     Maintained
 F:     drivers/gpio/gpio-altera-a10sr.c
 F:     drivers/mfd/altera-a10sr.c
+F:     drivers/reset/reset-a10sr.c
 F:     include/linux/mfd/altera-a10sr.h
+F:     include/dt-bindings/reset/altr,rst-mgr-a10sr.h
 
 ALTERA TRIPLE SPEED ETHERNET DRIVER
 M:     Vince Bridgers <vbridger@opensource.altera.com>
@@ -1282,6 +1284,7 @@ F:        arch/arm/mach-mxs/
 F:     arch/arm/boot/dts/imx*
 F:     arch/arm/configs/imx*_defconfig
 F:     drivers/clk/imx/
+F:     drivers/soc/imx/
 F:     include/soc/imx/
 
 ARM/FREESCALE VYBRID ARM ARCHITECTURE
@@ -12604,6 +12607,9 @@ S:      Maintained
 F:     Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
 F:     drivers/firmware/ti_sci*
 F:     include/linux/soc/ti/ti_sci_protocol.h
+F:     Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
+F:     include/dt-bindings/genpd/k2g.h
+F:     drivers/soc/ti/ti_sci_pm_domains.c
 
 THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
 M:     Hans Verkuil <hverkuil@xs4all.nl>
index 9353184d730dfda864c85ec180b906b9ed575681..1181053e3ade766fd0ad5364831920b97d5632a5 100644 (file)
@@ -1,6 +1,3 @@
-config ICST
-       bool
-
 config SA1111
        bool
        select DMABOUNCE if !ARCH_PXA
index 27f23b15b1ea272a227fa431c12a0266de7061fe..29fdf6a3601dcbdf4abfaaa224cc9b75c6bfc932 100644 (file)
@@ -4,7 +4,6 @@
 
 obj-y                          += firmware.o
 
-obj-$(CONFIG_ICST)             += icst.o
 obj-$(CONFIG_SA1111)           += sa1111.o
 obj-$(CONFIG_DMABOUNCE)                += dmabounce.o
 obj-$(CONFIG_SHARP_LOCOMO)     += locomo.o
index 1dc2a34b9dbd452531479d0766187c8547cb13fd..93f584ba0130eb480b001d98946d9981da19d34c 100644 (file)
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
-#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/regulator/consumer.h>
 #include <linux/irqchip/arm-gic.h>
 #include "common.h"
 #include "hardware.h"
 
-#define GPC_CNTR               0x000
 #define GPC_IMR1               0x008
-#define GPC_PGC_GPU_PDN                0x260
-#define GPC_PGC_GPU_PUPSCR     0x264
-#define GPC_PGC_GPU_PDNSCR     0x268
 #define GPC_PGC_CPU_PDN                0x2a0
 #define GPC_PGC_CPU_PUPSCR     0x2a4
 #define GPC_PGC_CPU_PDNSCR     0x2a8
 #define IMR_NUM                        4
 #define GPC_MAX_IRQS           (IMR_NUM * 32)
 
-#define GPU_VPU_PUP_REQ                BIT(1)
-#define GPU_VPU_PDN_REQ                BIT(0)
-
-#define GPC_CLK_MAX            6
-
-struct pu_domain {
-       struct generic_pm_domain base;
-       struct regulator *reg;
-       struct clk *clk[GPC_CLK_MAX];
-       int num_clks;
-};
-
 static void __iomem *gpc_base;
 static u32 gpc_wake_irqs[IMR_NUM];
 static u32 gpc_saved_imrs[IMR_NUM];
@@ -296,199 +275,3 @@ void __init imx_gpc_check_dt(void)
                gpc_base = of_iomap(np, 0);
        }
 }
-
-static void _imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
-{
-       int iso, iso2sw;
-       u32 val;
-
-       /* Read ISO and ISO2SW power down delays */
-       val = readl_relaxed(gpc_base + GPC_PGC_GPU_PDNSCR);
-       iso = val & 0x3f;
-       iso2sw = (val >> 8) & 0x3f;
-
-       /* Gate off PU domain when GPU/VPU when powered down */
-       writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
-
-       /* Request GPC to power down GPU/VPU */
-       val = readl_relaxed(gpc_base + GPC_CNTR);
-       val |= GPU_VPU_PDN_REQ;
-       writel_relaxed(val, gpc_base + GPC_CNTR);
-
-       /* Wait ISO + ISO2SW IPG clock cycles */
-       ndelay((iso + iso2sw) * 1000 / 66);
-}
-
-static int imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
-{
-       struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
-
-       _imx6q_pm_pu_power_off(genpd);
-
-       if (pu->reg)
-               regulator_disable(pu->reg);
-
-       return 0;
-}
-
-static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd)
-{
-       struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
-       int i, ret, sw, sw2iso;
-       u32 val;
-
-       if (pu->reg)
-               ret = regulator_enable(pu->reg);
-       if (pu->reg && ret) {
-               pr_err("%s: failed to enable regulator: %d\n", __func__, ret);
-               return ret;
-       }
-
-       /* Enable reset clocks for all devices in the PU domain */
-       for (i = 0; i < pu->num_clks; i++)
-               clk_prepare_enable(pu->clk[i]);
-
-       /* Gate off PU domain when GPU/VPU when powered down */
-       writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
-
-       /* Read ISO and ISO2SW power down delays */
-       val = readl_relaxed(gpc_base + GPC_PGC_GPU_PUPSCR);
-       sw = val & 0x3f;
-       sw2iso = (val >> 8) & 0x3f;
-
-       /* Request GPC to power up GPU/VPU */
-       val = readl_relaxed(gpc_base + GPC_CNTR);
-       val |= GPU_VPU_PUP_REQ;
-       writel_relaxed(val, gpc_base + GPC_CNTR);
-
-       /* Wait ISO + ISO2SW IPG clock cycles */
-       ndelay((sw + sw2iso) * 1000 / 66);
-
-       /* Disable reset clocks for all devices in the PU domain */
-       for (i = 0; i < pu->num_clks; i++)
-               clk_disable_unprepare(pu->clk[i]);
-
-       return 0;
-}
-
-static struct generic_pm_domain imx6q_arm_domain = {
-       .name = "ARM",
-};
-
-static struct pu_domain imx6q_pu_domain = {
-       .base = {
-               .name = "PU",
-               .power_off = imx6q_pm_pu_power_off,
-               .power_on = imx6q_pm_pu_power_on,
-       },
-};
-
-static struct generic_pm_domain imx6sl_display_domain = {
-       .name = "DISPLAY",
-};
-
-static struct generic_pm_domain *imx_gpc_domains[] = {
-       &imx6q_arm_domain,
-       &imx6q_pu_domain.base,
-       &imx6sl_display_domain,
-};
-
-static struct genpd_onecell_data imx_gpc_onecell_data = {
-       .domains = imx_gpc_domains,
-       .num_domains = ARRAY_SIZE(imx_gpc_domains),
-};
-
-static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
-{
-       struct clk *clk;
-       int i, ret;
-
-       imx6q_pu_domain.reg = pu_reg;
-
-       for (i = 0; ; i++) {
-               clk = of_clk_get(dev->of_node, i);
-               if (IS_ERR(clk))
-                       break;
-               if (i >= GPC_CLK_MAX) {
-                       dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
-                       goto clk_err;
-               }
-               imx6q_pu_domain.clk[i] = clk;
-       }
-       imx6q_pu_domain.num_clks = i;
-
-       /* Enable power always in case bootloader disabled it. */
-       imx6q_pm_pu_power_on(&imx6q_pu_domain.base);
-
-       if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
-               return 0;
-
-       imx6q_pu_domain.base.states = devm_kzalloc(dev,
-                                       sizeof(*imx6q_pu_domain.base.states),
-                                       GFP_KERNEL);
-       if (!imx6q_pu_domain.base.states)
-               return -ENOMEM;
-
-       imx6q_pu_domain.base.states[0].power_off_latency_ns = 25000;
-       imx6q_pu_domain.base.states[0].power_on_latency_ns = 2000000;
-       imx6q_pu_domain.base.state_count = 1;
-
-       for (i = 0; i < ARRAY_SIZE(imx_gpc_domains); i++)
-               pm_genpd_init(imx_gpc_domains[i], NULL, false);
-
-       ret =  of_genpd_add_provider_onecell(dev->of_node,
-                                            &imx_gpc_onecell_data);
-       if (ret)
-               goto power_off;
-
-       return 0;
-
-power_off:
-       imx6q_pm_pu_power_off(&imx6q_pu_domain.base);
-clk_err:
-       while (i--)
-               clk_put(imx6q_pu_domain.clk[i]);
-       imx6q_pu_domain.reg = NULL;
-       return -EINVAL;
-}
-
-static int imx_gpc_probe(struct platform_device *pdev)
-{
-       struct regulator *pu_reg;
-       int ret;
-
-       /* bail out if DT too old and doesn't provide the necessary info */
-       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells"))
-               return 0;
-
-       pu_reg = devm_regulator_get_optional(&pdev->dev, "pu");
-       if (PTR_ERR(pu_reg) == -ENODEV)
-               pu_reg = NULL;
-       if (IS_ERR(pu_reg)) {
-               ret = PTR_ERR(pu_reg);
-               dev_err(&pdev->dev, "failed to get pu regulator: %d\n", ret);
-               return ret;
-       }
-
-       return imx_gpc_genpd_init(&pdev->dev, pu_reg);
-}
-
-static const struct of_device_id imx_gpc_dt_ids[] = {
-       { .compatible = "fsl,imx6q-gpc" },
-       { .compatible = "fsl,imx6sl-gpc" },
-       { }
-};
-
-static struct platform_driver imx_gpc_driver = {
-       .driver = {
-               .name = "imx-gpc",
-               .of_match_table = imx_gpc_dt_ids,
-       },
-       .probe = imx_gpc_probe,
-};
-
-static int __init imx_pgc_init(void)
-{
-       return platform_driver_register(&imx_gpc_driver);
-}
-subsys_initcall(imx_pgc_init);
index 554357035f3037f37b31dcb868df3c6e90b5d324..db122356b410f6e2e1dadefa7ecea749e4fd9087 100644 (file)
@@ -10,6 +10,7 @@ config ARCH_KEYSTONE
        select ARCH_SUPPORTS_BIG_ENDIAN
        select ZONE_DMA if ARM_LPAE
        select PINCTRL
+       select PM_GENERIC_DOMAINS if PM
        help
          Support for boards based on the Texas Instruments Keystone family of
          SoCs.
index 8cbb35765a19f359d1cf854e7fbae8bf64621d48..fe57e26926292fe3dccc1adaf7d6c5e8552fd055 100644 (file)
@@ -32,7 +32,9 @@ static struct pm_clk_notifier_block platform_domain_notifier = {
 };
 
 static const struct of_device_id of_keystone_table[] = {
-       {.compatible = "ti,keystone"},
+       {.compatible = "ti,k2hk"},
+       {.compatible = "ti,k2e"},
+       {.compatible = "ti,k2l"},
        { /* end of list */ },
 };
 
index fffad2426ee4bc0ea1689b0de9e760db41713a0f..3b33f0bb78ae4bd9da4f1b1c810cdd3f740a75ba 100644 (file)
@@ -2,7 +2,6 @@ asflags-y                               += -march=armv7-a
 
 obj-y                                   += io.o
 obj-y                                   += irq.o
-obj-y                                  += flowctrl.o
 obj-y                                  += pm.o
 obj-y                                  += reset.o
 obj-y                                  += reset-handler.o
index afcee04f2616aa5c8c1e443b2feaa4f3465c1fea..76e4c83cd5c8dd54e1f644618beef62087e0b0b2 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 
+#include <soc/tegra/flowctrl.h>
+
 #include <asm/cpuidle.h>
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
 
 #include "cpuidle.h"
-#include "flowctrl.h"
 #include "iomap.h"
 #include "irq.h"
 #include "pm.h"
index 75620ae73913a18d92fd4521b7ae06aea397e1e1..b5a2afe99101f9008a34510a9bf3dbd17e2d5cf1 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/jiffies.h>
 #include <linux/smp.h>
 
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/pmc.h>
 
@@ -30,7 +31,6 @@
 #include <asm/smp_scu.h>
 
 #include "common.h"
-#include "flowctrl.h"
 #include "iomap.h"
 #include "reset.h"
 
index b0f48a3946fae27277dd8ca49f9432896e89cfb0..1ad5719779b00ab1fa4ea5d6a1c2d944e5b7e0f0 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/spinlock.h>
 #include <linux/suspend.h>
 
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/pm.h>
 #include <soc/tegra/pmc.h>
@@ -38,7 +39,6 @@
 #include <asm/suspend.h>
 #include <asm/tlbflush.h>
 
-#include "flowctrl.h"
 #include "iomap.h"
 #include "pm.h"
 #include "reset.h"
index e3070fdab80b8b7481c0527e2d649ae7d664dc58..805f306fa6f707f055878a31f00a2f412a89f9c5 100644 (file)
 #include <linux/init.h>
 #include <linux/linkage.h>
 
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
 
-#include "flowctrl.h"
 #include "iomap.h"
 #include "reset.h"
 #include "sleep.h"
index f5d19667484edd38e65bb1aa1d1a4413a036bfbf..5c8e638ee51a3b590cc8274a3edb22e5a93dd996 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <linux/linkage.h>
 
+#include <soc/tegra/flowctrl.h>
+
 #include <asm/assembler.h>
 #include <asm/proc-fns.h>
 #include <asm/cp15.h>
@@ -27,7 +29,6 @@
 
 #include "irammap.h"
 #include "sleep.h"
-#include "flowctrl.h"
 
 #define EMC_CFG                                0xc
 #define EMC_ADR_CFG                    0x10
index 16e5ff03383cad5b709eb42b24340b033f86a2c7..dd4a67dabd91692dffae18fd07245c372770840f 100644 (file)
 
 #include <linux/linkage.h>
 
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 
 #include <asm/asm-offsets.h>
 #include <asm/assembler.h>
 #include <asm/cache.h>
 
-#include "flowctrl.h"
 #include "irammap.h"
 #include "sleep.h"
 
index f024a5109e8e7c91ec8427f060748c7c47990462..5e3496753df184a556f0143cfc357e58224d7803 100644 (file)
@@ -30,8 +30,6 @@
 #include <asm/hardware/cache-l2x0.h>
 
 #include "iomap.h"
-
-#include "flowctrl.h"
 #include "sleep.h"
 
 #define CLK_RESET_CCLK_BURST   0x20
index e01cbca196b544f57e95ffb1e21e831b93adec03..649e9e8c7bccdf2e566ec0ad05c52c8a85a4fc04 100644 (file)
@@ -48,7 +48,6 @@
 #include "board.h"
 #include "common.h"
 #include "cpuidle.h"
-#include "flowctrl.h"
 #include "iomap.h"
 #include "irq.h"
 #include "pm.h"
@@ -75,7 +74,6 @@ static void __init tegra_init_early(void)
 {
        of_register_trusted_foundations();
        tegra_cpu_reset_handler_init();
-       tegra_flowctrl_init();
 }
 
 static void __init tegra_dt_init_irq(void)
diff --git a/arch/arm/plat-versatile/include/plat/clock.h b/arch/arm/plat-versatile/include/plat/clock.h
deleted file mode 100644 (file)
index 3cfb024..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef PLAT_CLOCK_H
-#define PLAT_CLOCK_H
-
-#include <asm/hardware/icst.h>
-
-struct clk_ops {
-       long    (*round)(struct clk *, unsigned long);
-       int     (*set)(struct clk *, unsigned long);
-       void    (*setvco)(struct clk *, struct icst_vco);
-};
-
-int icst_clk_set(struct clk *, unsigned long);
-long icst_clk_round(struct clk *, unsigned long);
-
-#endif
index ff6cb9e4c3811c9a34bcf14beb395faacc552a15..de3eaf051697601a641440d12687e88258ebc394 100644 (file)
@@ -518,6 +518,15 @@ config PATA_BF54X
 
          If unsure, say N.
 
+config PATA_BK3710
+       tristate "Palmchip BK3710 PATA support"
+       depends on ARCH_DAVINCI
+       help
+         This option enables support for the integrated IDE controller on
+         the TI DaVinci SoC.
+
+         If unsure, say N.
+
 config PATA_CMD64X
        tristate "CMD64x PATA support"
        depends on PCI
index 3048cc100a46691c3c3d581213fdc1073d499e65..cd931a5eba922267e0307a833f0b4e1f9f8cec17 100644 (file)
@@ -51,6 +51,7 @@ obj-$(CONFIG_PATA_ARTOP)      += pata_artop.o
 obj-$(CONFIG_PATA_ATIIXP)      += pata_atiixp.o
 obj-$(CONFIG_PATA_ATP867X)     += pata_atp867x.o
 obj-$(CONFIG_PATA_BF54X)       += pata_bf54x.o
+obj-$(CONFIG_PATA_BK3710)      += pata_bk3710.o
 obj-$(CONFIG_PATA_CMD64X)      += pata_cmd64x.o
 obj-$(CONFIG_PATA_CS5520)      += pata_cs5520.o
 obj-$(CONFIG_PATA_CS5530)      += pata_cs5530.o
diff --git a/drivers/ata/pata_bk3710.c b/drivers/ata/pata_bk3710.c
new file mode 100644 (file)
index 0000000..6c3bd5f
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * Palmchip BK3710 PATA controller driver
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Based on palm_bk3710.c:
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/ata.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/libata.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#define DRV_NAME "pata_bk3710"
+
+#define BK3710_TF_OFFSET       0x1F0
+#define BK3710_CTL_OFFSET      0x3F6
+
+#define BK3710_BMISP           0x02
+#define BK3710_IDETIMP         0x40
+#define BK3710_UDMACTL         0x48
+#define BK3710_MISCCTL         0x50
+#define BK3710_REGSTB          0x54
+#define BK3710_REGRCVR         0x58
+#define BK3710_DATSTB          0x5C
+#define BK3710_DATRCVR         0x60
+#define BK3710_DMASTB          0x64
+#define BK3710_DMARCVR         0x68
+#define BK3710_UDMASTB         0x6C
+#define BK3710_UDMATRP         0x70
+#define BK3710_UDMAENV         0x74
+#define BK3710_IORDYTMP                0x78
+
+static struct scsi_host_template pata_bk3710_sht = {
+       ATA_BMDMA_SHT(DRV_NAME),
+};
+
+static unsigned int ideclk_period; /* in nanoseconds */
+
+struct pata_bk3710_udmatiming {
+       unsigned int rptime;    /* tRP -- Ready to pause time (nsec) */
+       unsigned int cycletime; /* tCYCTYP2/2 -- avg Cycle Time (nsec) */
+                               /* tENV is always a minimum of 20 nsec */
+};
+
+static const struct pata_bk3710_udmatiming pata_bk3710_udmatimings[6] = {
+       { 160, 240 / 2 },       /* UDMA Mode 0 */
+       { 125, 160 / 2 },       /* UDMA Mode 1 */
+       { 100, 120 / 2 },       /* UDMA Mode 2 */
+       { 100,  90 / 2 },       /* UDMA Mode 3 */
+       { 100,  60 / 2 },       /* UDMA Mode 4 */
+       {  85,  40 / 2 },       /* UDMA Mode 5 */
+};
+
+static void pata_bk3710_setudmamode(void __iomem *base, unsigned int dev,
+                                   unsigned int mode)
+{
+       u32 val32;
+       u16 val16;
+       u8 tenv, trp, t0;
+
+       /* DMA Data Setup */
+       t0 = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].cycletime,
+                         ideclk_period) - 1;
+       tenv = DIV_ROUND_UP(20, ideclk_period) - 1;
+       trp = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].rptime,
+                          ideclk_period) - 1;
+
+       /* udmastb Ultra DMA Access Strobe Width */
+       val32 = ioread32(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
+       val32 |= t0 << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_UDMASTB);
+
+       /* udmatrp Ultra DMA Ready to Pause Time */
+       val32 = ioread32(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
+       val32 |= trp << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_UDMATRP);
+
+       /* udmaenv Ultra DMA envelop Time */
+       val32 = ioread32(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
+       val32 |= tenv << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_UDMAENV);
+
+       /* Enable UDMA for Device */
+       val16 = ioread16(base + BK3710_UDMACTL) | (1 << dev);
+       iowrite16(val16, base + BK3710_UDMACTL);
+}
+
+static void pata_bk3710_setmwdmamode(void __iomem *base, unsigned int dev,
+                                    unsigned short min_cycle,
+                                    unsigned int mode)
+{
+       const struct ata_timing *t;
+       int cycletime;
+       u32 val32;
+       u16 val16;
+       u8 td, tkw, t0;
+
+       t = ata_timing_find_mode(mode);
+       cycletime = max_t(int, t->cycle, min_cycle);
+
+       /* DMA Data Setup */
+       t0 = DIV_ROUND_UP(cycletime, ideclk_period);
+       td = DIV_ROUND_UP(t->active, ideclk_period);
+       tkw = t0 - td - 1;
+       td--;
+
+       val32 = ioread32(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
+       val32 |= td << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_DMASTB);
+
+       val32 = ioread32(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
+       val32 |= tkw << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_DMARCVR);
+
+       /* Disable UDMA for Device */
+       val16 = ioread16(base + BK3710_UDMACTL) & ~(1 << dev);
+       iowrite16(val16, base + BK3710_UDMACTL);
+}
+
+static void pata_bk3710_set_dmamode(struct ata_port *ap,
+                                   struct ata_device *adev)
+{
+       void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
+       int is_slave = adev->devno;
+       const u8 xferspeed = adev->dma_mode;
+
+       if (xferspeed >= XFER_UDMA_0)
+               pata_bk3710_setudmamode(base, is_slave,
+                                       xferspeed - XFER_UDMA_0);
+       else
+               pata_bk3710_setmwdmamode(base, is_slave,
+                                        adev->id[ATA_ID_EIDE_DMA_MIN],
+                                        xferspeed);
+}
+
+static void pata_bk3710_setpiomode(void __iomem *base, struct ata_device *pair,
+                                  unsigned int dev, unsigned int cycletime,
+                                  unsigned int mode)
+{
+       const struct ata_timing *t;
+       u32 val32;
+       u8 t2, t2i, t0;
+
+       t = ata_timing_find_mode(XFER_PIO_0 + mode);
+
+       /* PIO Data Setup */
+       t0 = DIV_ROUND_UP(cycletime, ideclk_period);
+       t2 = DIV_ROUND_UP(t->active, ideclk_period);
+
+       t2i = t0 - t2 - 1;
+       t2--;
+
+       val32 = ioread32(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
+       val32 |= t2 << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_DATSTB);
+
+       val32 = ioread32(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
+       val32 |= t2i << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_DATRCVR);
+
+       /* FIXME: this is broken also in the old driver */
+       if (pair) {
+               u8 mode2 = pair->pio_mode - XFER_PIO_0;
+
+               if (mode2 < mode)
+                       mode = mode2;
+       }
+
+       /* TASKFILE Setup */
+       t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
+       t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
+
+       t2i = t0 - t2 - 1;
+       t2--;
+
+       val32 = ioread32(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
+       val32 |= t2 << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_REGSTB);
+
+       val32 = ioread32(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
+       val32 |= t2i << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_REGRCVR);
+}
+
+static void pata_bk3710_set_piomode(struct ata_port *ap,
+                                   struct ata_device *adev)
+{
+       void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
+       struct ata_device *pair = ata_dev_pair(adev);
+       const struct ata_timing *t = ata_timing_find_mode(adev->pio_mode);
+       const u16 *id = adev->id;
+       unsigned int cycle_time = 0;
+       int is_slave = adev->devno;
+       const u8 pio = adev->pio_mode - XFER_PIO_0;
+
+       if (id[ATA_ID_FIELD_VALID] & 2) {
+               if (ata_id_has_iordy(id))
+                       cycle_time = id[ATA_ID_EIDE_PIO_IORDY];
+               else
+                       cycle_time = id[ATA_ID_EIDE_PIO];
+
+               /* conservative "downgrade" for all pre-ATA2 drives */
+               if (pio < 3 && cycle_time < t->cycle)
+                       cycle_time = 0; /* use standard timing */
+       }
+
+       if (!cycle_time)
+               cycle_time = t->cycle;
+
+       pata_bk3710_setpiomode(base, pair, is_slave, cycle_time, pio);
+}
+
+static void pata_bk3710_chipinit(void __iomem *base)
+{
+       /*
+        * REVISIT:  the ATA reset signal needs to be managed through a
+        * GPIO, which means it should come from platform_data.  Until
+        * we get and use such information, we have to trust that things
+        * have been reset before we get here.
+        */
+
+       /*
+        * Program the IDETIMP Register Value based on the following assumptions
+        *
+        * (ATA_IDETIMP_IDEEN           , ENABLE ) |
+        * (ATA_IDETIMP_PREPOST1        , DISABLE) |
+        * (ATA_IDETIMP_PREPOST0        , DISABLE) |
+        *
+        * DM6446 silicon rev 2.1 and earlier have no observed net benefit
+        * from enabling prefetch/postwrite.
+        */
+       iowrite16(BIT(15), base + BK3710_IDETIMP);
+
+       /*
+        * UDMACTL Ultra-ATA DMA Control
+        * (ATA_UDMACTL_UDMAP1  , 0 ) |
+        * (ATA_UDMACTL_UDMAP0  , 0 )
+        *
+        */
+       iowrite16(0, base + BK3710_UDMACTL);
+
+       /*
+        * MISCCTL Miscellaneous Conrol Register
+        * (ATA_MISCCTL_HWNHLD1P        , 1 cycle)
+        * (ATA_MISCCTL_HWNHLD0P        , 1 cycle)
+        * (ATA_MISCCTL_TIMORIDE        , 1)
+        */
+       iowrite32(0x001, base + BK3710_MISCCTL);
+
+       /*
+        * IORDYTMP IORDY Timer for Primary Register
+        * (ATA_IORDYTMP_IORDYTMP       , DISABLE)
+        */
+       iowrite32(0, base + BK3710_IORDYTMP);
+
+       /*
+        * Configure BMISP Register
+        * (ATA_BMISP_DMAEN1    , DISABLE )     |
+        * (ATA_BMISP_DMAEN0    , DISABLE )     |
+        * (ATA_BMISP_IORDYINT  , CLEAR)        |
+        * (ATA_BMISP_INTRSTAT  , CLEAR)        |
+        * (ATA_BMISP_DMAERROR  , CLEAR)
+        */
+       iowrite16(0xE, base + BK3710_BMISP);
+
+       pata_bk3710_setpiomode(base, NULL, 0, 600, 0);
+       pata_bk3710_setpiomode(base, NULL, 1, 600, 0);
+}
+
+static struct ata_port_operations pata_bk3710_ports_ops = {
+       .inherits               = &ata_bmdma_port_ops,
+       .cable_detect           = ata_cable_80wire,
+
+       .set_piomode            = pata_bk3710_set_piomode,
+       .set_dmamode            = pata_bk3710_set_dmamode,
+};
+
+static int __init pata_bk3710_probe(struct platform_device *pdev)
+{
+       struct clk *clk;
+       struct resource *mem;
+       struct ata_host *host;
+       struct ata_port *ap;
+       void __iomem *base;
+       unsigned long rate;
+       int irq;
+
+       clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(clk))
+               return -ENODEV;
+
+       clk_enable(clk);
+       rate = clk_get_rate(clk);
+       if (!rate)
+               return -EINVAL;
+
+       /* NOTE:  round *down* to meet minimum timings; we count in clocks */
+       ideclk_period = 1000000000UL / rate;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               pr_err(DRV_NAME ": failed to get IRQ resource\n");
+               return irq;
+       }
+
+       base = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       /* configure the Palmchip controller */
+       pata_bk3710_chipinit(base);
+
+       /* allocate host */
+       host = ata_host_alloc(&pdev->dev, 1);
+       if (!host)
+               return -ENOMEM;
+       ap = host->ports[0];
+
+       ap->ops = &pata_bk3710_ports_ops;
+       ap->pio_mask = ATA_PIO4;
+       ap->mwdma_mask = ATA_MWDMA2;
+       ap->udma_mask = rate < 100000000 ? ATA_UDMA4 : ATA_UDMA5;
+       ap->flags |= ATA_FLAG_SLAVE_POSS;
+
+       ap->ioaddr.data_addr            = base + BK3710_TF_OFFSET;
+       ap->ioaddr.error_addr           = base + BK3710_TF_OFFSET + 1;
+       ap->ioaddr.feature_addr         = base + BK3710_TF_OFFSET + 1;
+       ap->ioaddr.nsect_addr           = base + BK3710_TF_OFFSET + 2;
+       ap->ioaddr.lbal_addr            = base + BK3710_TF_OFFSET + 3;
+       ap->ioaddr.lbam_addr            = base + BK3710_TF_OFFSET + 4;
+       ap->ioaddr.lbah_addr            = base + BK3710_TF_OFFSET + 5;
+       ap->ioaddr.device_addr          = base + BK3710_TF_OFFSET + 6;
+       ap->ioaddr.status_addr          = base + BK3710_TF_OFFSET + 7;
+       ap->ioaddr.command_addr         = base + BK3710_TF_OFFSET + 7;
+
+       ap->ioaddr.altstatus_addr       = base + BK3710_CTL_OFFSET;
+       ap->ioaddr.ctl_addr             = base + BK3710_CTL_OFFSET;
+
+       ap->ioaddr.bmdma_addr           = base;
+
+       ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx",
+                     (unsigned long)base + BK3710_TF_OFFSET,
+                     (unsigned long)base + BK3710_CTL_OFFSET);
+
+       /* activate */
+       return ata_host_activate(host, irq, ata_sff_interrupt, 0,
+                                &pata_bk3710_sht);
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:palm_bk3710");
+
+static struct platform_driver pata_bk3710_driver = {
+       .driver = {
+               .name = "palm_bk3710",
+       },
+};
+
+static int __init pata_bk3710_init(void)
+{
+       return platform_driver_probe(&pata_bk3710_driver, pata_bk3710_probe);
+}
+
+module_init(pata_bk3710_init);
+MODULE_LICENSE("GPL");
index ad196427b4f2a1c07f80e3a457d72b746c873eed..da49a8383dc30b074d28463e3b2771cd2ebd8adb 100644 (file)
@@ -1636,8 +1636,6 @@ static struct generic_pm_domain *genpd_xlate_simple(
                                        struct of_phandle_args *genpdspec,
                                        void *data)
 {
-       if (genpdspec->args_count != 0)
-               return ERR_PTR(-EINVAL);
        return data;
 }
 
index dc26e5949a3202233ddbeecd6921cd3f1488120b..909dedae4c4e1d4802542e5f33e464da4be0e21d 100644 (file)
@@ -109,15 +109,18 @@ static void soc_release(struct device *dev)
        kfree(soc_dev);
 }
 
+static struct soc_device_attribute *early_soc_dev_attr;
+
 struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr)
 {
        struct soc_device *soc_dev;
        int ret;
 
        if (!soc_bus_type.p) {
-               ret = bus_register(&soc_bus_type);
-               if (ret)
-                       goto out1;
+               if (early_soc_dev_attr)
+                       return ERR_PTR(-EBUSY);
+               early_soc_dev_attr = soc_dev_attr;
+               return NULL;
        }
 
        soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
@@ -159,45 +162,53 @@ void soc_device_unregister(struct soc_device *soc_dev)
        ida_simple_remove(&soc_ida, soc_dev->soc_dev_num);
 
        device_unregister(&soc_dev->dev);
+       early_soc_dev_attr = NULL;
 }
 
 static int __init soc_bus_register(void)
 {
-       if (soc_bus_type.p)
-               return 0;
+       int ret;
 
-       return bus_register(&soc_bus_type);
+       ret = bus_register(&soc_bus_type);
+       if (ret)
+               return ret;
+
+       if (early_soc_dev_attr)
+               return PTR_ERR(soc_device_register(early_soc_dev_attr));
+
+       return 0;
 }
 core_initcall(soc_bus_register);
 
-static int soc_device_match_one(struct device *dev, void *arg)
+static int soc_device_match_attr(const struct soc_device_attribute *attr,
+                                const struct soc_device_attribute *match)
 {
-       struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
-       const struct soc_device_attribute *match = arg;
-
        if (match->machine &&
-           (!soc_dev->attr->machine ||
-            !glob_match(match->machine, soc_dev->attr->machine)))
+           (!attr->machine || !glob_match(match->machine, attr->machine)))
                return 0;
 
        if (match->family &&
-           (!soc_dev->attr->family ||
-            !glob_match(match->family, soc_dev->attr->family)))
+           (!attr->family || !glob_match(match->family, attr->family)))
                return 0;
 
        if (match->revision &&
-           (!soc_dev->attr->revision ||
-            !glob_match(match->revision, soc_dev->attr->revision)))
+           (!attr->revision || !glob_match(match->revision, attr->revision)))
                return 0;
 
        if (match->soc_id &&
-           (!soc_dev->attr->soc_id ||
-            !glob_match(match->soc_id, soc_dev->attr->soc_id)))
+           (!attr->soc_id || !glob_match(match->soc_id, attr->soc_id)))
                return 0;
 
        return 1;
 }
 
+static int soc_device_match_one(struct device *dev, void *arg)
+{
+       struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
+
+       return soc_device_match_attr(soc_dev->attr, arg);
+}
+
 /*
  * soc_device_match - identify the SoC in the machine
  * @matches: zero-terminated array of possible matches
@@ -230,6 +241,11 @@ const struct soc_device_attribute *soc_device_match(
                        break;
                ret = bus_for_each_dev(&soc_bus_type, NULL, (void *)matches,
                                       soc_device_match_one);
+               if (ret < 0 && early_soc_dev_attr)
+                       ret = soc_device_match_attr(early_soc_dev_attr,
+                                                   matches);
+               if (ret < 0)
+                       return NULL;
                if (!ret)
                        matches++;
                else
index a6da2aa09f831ff512a11b0253d45588f3bee614..8aa875f252391907d0a00ad66840975f4f02a021 100644 (file)
@@ -1,3 +1,6 @@
+config ICST
+       bool
+
 config COMMON_CLK_VERSATILE
        bool "Clock driver for ARM Reference designs"
        depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \
index 8ff03744fe9890e1ec9069c31ac37dc2d4a329f4..794130402c8dca01985d9142fdeea2be2a1f013a 100644 (file)
@@ -1,5 +1,5 @@
 # Makefile for Versatile-specific clocks
-obj-$(CONFIG_ICST)             += clk-icst.o clk-versatile.o
+obj-$(CONFIG_ICST)             += icst.o clk-icst.o clk-versatile.o
 obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
 obj-$(CONFIG_ARCH_REALVIEW)    += clk-realview.o
 obj-$(CONFIG_CLK_SP810)                += clk-sp810.o
index 4faa94440779bcfadd11f75dc78ae7f416c2df39..09fbe66f1f11cb41507f104a7458ed38d83e75cd 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/regmap.h>
 #include <linux/mfd/syscon.h>
 
+#include "icst.h"
 #include "clk-icst.h"
 
 /* Magic unlocking token used on all Versatile boards */
index 04e6f0aef5889ad260aaced2b427f7487240dd37..5add02ebec5d0af809b1a6c5c2eae4481217d634 100644 (file)
@@ -1,5 +1,3 @@
-#include <asm/hardware/icst.h>
-
 /**
  * struct clk_icst_desc - descriptor for the ICST VCO
  * @params: ICST parameters
index 74c3216dbb0045273cc40793caa88bc78e9d4c8e..401558bfc409c01c59582df9c6d3e8ed6fc24aff 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/clk-integrator.h>
 
+#include "icst.h"
 #include "clk-icst.h"
 
 #define IMPD1_OSC1     0x00
index c56efc70ac16c40502aeccb0e5bf459d40659682..6fdfee3232f445f5eda439e78e58a2f3967fe8c0 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 #include <linux/clk-provider.h>
 
+#include "icst.h"
 #include "clk-icst.h"
 
 #define REALVIEW_SYS_OSC0_OFFSET             0x0C
index a89a927567e0cfae45df95b8aed7cc2218509fc3..d6960de64d4a08dbae5cdcd2bb9a27b16803b2e3 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 
+#include "icst.h"
 #include "clk-icst.h"
 
 #define INTEGRATOR_HDR_LOCK_OFFSET     0x14
similarity index 98%
rename from arch/arm/common/icst.c
rename to drivers/clk/versatile/icst.c
index d7ed252708c57fa86cff5d51887bd756b53b48e7..de2af63a3aad52e740228e8b6ef7b8346f5e7770 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <asm/div64.h>
-#include <asm/hardware/icst.h>
+#include "icst.h"
 
 /*
  * Divisors for each OD setting.
similarity index 94%
rename from arch/arm/include/asm/hardware/icst.h
rename to drivers/clk/versatile/icst.h
index 794220b087d2392ce3807b61f5103f8429f55364..7519bba03b04574b20558ff827757389ad7bf32c 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  arch/arm/include/asm/hardware/icst.h
- *
  *  Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -11,8 +9,8 @@
  *  clock generators.  See http://www.idt.com/ for more information
  *  on these devices.
  */
-#ifndef ASMARM_HARDWARE_ICST_H
-#define ASMARM_HARDWARE_ICST_H
+#ifndef ICST_H
+#define ICST_H
 
 struct icst_params {
        unsigned long   ref;
index 9ad0b1934be9a31173ede1ed6c1c3705cc0c1e05..f6cfc31d34c71578623258bbe7443e4023b8a485 100644 (file)
@@ -538,7 +538,7 @@ static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len,
        msg->tx_len = tx_len;
        msg->rx_buf = rx_buf;
        msg->rx_len = rx_len;
-       init_completion(&msg->done);
+       reinit_completion(&msg->done);
 
        ret = mbox_send_message(scpi_chan->chan, msg);
        if (ret < 0 || !rx_buf)
@@ -872,8 +872,11 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
                return -ENOMEM;
 
        ch->xfers = xfers;
-       for (i = 0; i < MAX_SCPI_XFERS; i++, xfers++)
+       for (i = 0; i < MAX_SCPI_XFERS; i++, xfers++) {
+               init_completion(&xfers->done);
                list_add_tail(&xfers->node, &ch->xfers_list);
+       }
+
        return 0;
 }
 
index b0d254930ed35cd86efa782d631582bcabda22b4..ff204421117b8bd9c836a41e6f439f592f21c565 100644 (file)
@@ -127,6 +127,7 @@ EXPORT_SYMBOL(meson_sm_call);
  * meson_sm_call_read - retrieve data from secure-monitor
  *
  * @buffer:    Buffer to store the retrieved data
+ * @bsize:     Size of the buffer
  * @cmd_index: Index of the SMC32 function ID
  * @arg0:      SMC32 Argument 0
  * @arg1:      SMC32 Argument 1
@@ -135,11 +136,14 @@ EXPORT_SYMBOL(meson_sm_call);
  * @arg4:      SMC32 Argument 4
  *
  * Return:     size of read data on success, a negative value on error
+ *             When 0 is returned there is no guarantee about the amount of
+ *             data read and bsize bytes are copied in buffer.
  */
-int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0,
-                      u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
+                      u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
 {
        u32 size;
+       int ret;
 
        if (!fw.chip)
                return -ENOENT;
@@ -147,16 +151,24 @@ int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0,
        if (!fw.chip->cmd_shmem_out_base)
                return -EINVAL;
 
+       if (bsize > fw.chip->shmem_size)
+               return -EINVAL;
+
        if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
                return -EINVAL;
 
-       if (!size || size > fw.chip->shmem_size)
+       if (size > bsize)
                return -EINVAL;
 
+       ret = size;
+
+       if (!size)
+               size = bsize;
+
        if (buffer)
                memcpy(buffer, fw.sm_shmem_out_base, size);
 
-       return size;
+       return ret;
 }
 EXPORT_SYMBOL(meson_sm_call_read);
 
index 8ad226c60374cd9a2697268c4137212d63673f7f..93e3b96b6dfafa181db0a2910f29ed493777c06f 100644 (file)
@@ -578,3 +578,21 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
 
        return ret ? : le32_to_cpu(scm_ret);
 }
+
+int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id,
+                              u32 spare)
+{
+       return -ENODEV;
+}
+
+int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
+                                     size_t *size)
+{
+       return -ENODEV;
+}
+
+int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
+                                     u32 spare)
+{
+       return -ENODEV;
+}
index c9332590e8c662d3ed79c7986ab759fd0a0a7699..6e6d561708e28c5da0fd6f7f95eb3b39f5e609e6 100644 (file)
@@ -381,3 +381,61 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
 
        return ret ? : res.a1;
 }
+
+int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare)
+{
+       struct qcom_scm_desc desc = {0};
+       struct arm_smccc_res res;
+       int ret;
+
+       desc.args[0] = device_id;
+       desc.args[1] = spare;
+       desc.arginfo = QCOM_SCM_ARGS(2);
+
+       ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, QCOM_SCM_RESTORE_SEC_CFG,
+                           &desc, &res);
+
+       return ret ? : res.a1;
+}
+
+int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
+                                     size_t *size)
+{
+       struct qcom_scm_desc desc = {0};
+       struct arm_smccc_res res;
+       int ret;
+
+       desc.args[0] = spare;
+       desc.arginfo = QCOM_SCM_ARGS(1);
+
+       ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
+                           QCOM_SCM_IOMMU_SECURE_PTBL_SIZE, &desc, &res);
+
+       if (size)
+               *size = res.a1;
+
+       return ret ? : res.a2;
+}
+
+int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
+                                     u32 spare)
+{
+       struct qcom_scm_desc desc = {0};
+       struct arm_smccc_res res;
+       int ret;
+
+       desc.args[0] = addr;
+       desc.args[1] = size;
+       desc.args[2] = spare;
+       desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL,
+                                    QCOM_SCM_VAL);
+
+       ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
+                           QCOM_SCM_IOMMU_SECURE_PTBL_INIT, &desc, &res);
+
+       /* the pg table has been initialized already, ignore the error */
+       if (ret == -EPERM)
+               ret = 0;
+
+       return ret;
+}
index d987bcc7489d981ee4b9784a6293fa6fd6ce175a..bb16510d75baa94f84f8e2a7993fe9bccde258dd 100644 (file)
@@ -315,6 +315,24 @@ static const struct reset_control_ops qcom_scm_pas_reset_ops = {
        .deassert = qcom_scm_pas_reset_deassert,
 };
 
+int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
+{
+       return __qcom_scm_restore_sec_cfg(__scm->dev, device_id, spare);
+}
+EXPORT_SYMBOL(qcom_scm_restore_sec_cfg);
+
+int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size)
+{
+       return __qcom_scm_iommu_secure_ptbl_size(__scm->dev, spare, size);
+}
+EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_size);
+
+int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
+{
+       return __qcom_scm_iommu_secure_ptbl_init(__scm->dev, addr, size, spare);
+}
+EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init);
+
 /**
  * qcom_scm_is_available() - Checks if SCM is available
  */
index 6a0f15469344e0b960747a3d06f4236467da942f..9bea691f30fb8dd3a7906035a62af8e2c8766a93 100644 (file)
@@ -85,4 +85,15 @@ static inline int qcom_scm_remap_error(int err)
        return -EINVAL;
 }
 
+#define QCOM_SCM_SVC_MP                        0xc
+#define QCOM_SCM_RESTORE_SEC_CFG       2
+extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id,
+                                     u32 spare);
+#define QCOM_SCM_IOMMU_SECURE_PTBL_SIZE        3
+#define QCOM_SCM_IOMMU_SECURE_PTBL_INIT        4
+extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
+                                            size_t *size);
+extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr,
+                                            u32 size, u32 spare);
+
 #endif
index f207c3b1048200d6a37586de7acaf5071a9bf2c0..70bfc9839bb2fede6ec424f23d933805ba3f4812 100644 (file)
@@ -27,7 +27,7 @@ static int meson_efuse_read(void *context, unsigned int offset,
        u8 *buf = val;
        int ret;
 
-       ret = meson_sm_call_read(buf, SM_EFUSE_READ, offset,
+       ret = meson_sm_call_read(buf, bytes, SM_EFUSE_READ, offset,
                                 bytes, 0, 0, 0);
        if (ret < 0)
                return ret;
index f4cdfe94b9ec0b4124b3f9680b23c283d546f867..d21c07ccc94e501ff44206c151a8bc5c48db513e 100644 (file)
@@ -14,6 +14,13 @@ menuconfig RESET_CONTROLLER
 
 if RESET_CONTROLLER
 
+config RESET_A10SR
+       tristate "Altera Arria10 System Resource Reset"
+       depends on MFD_ALTERA_A10SR
+       help
+         This option enables support for the external reset functions for
+         peripheral PHYs on the Altera Arria10 System Resource Chip.
+
 config RESET_ATH79
        bool "AR71xx Reset Driver" if COMPILE_TEST
        default ATH79
@@ -27,6 +34,13 @@ config RESET_BERLIN
        help
          This enables the reset controller driver for Marvell Berlin SoCs.
 
+config RESET_IMX7
+       bool "i.MX7 Reset Driver" if COMPILE_TEST
+       default SOC_IMX7D
+       select MFD_SYSCON
+       help
+         This enables the reset controller driver for i.MX7 SoCs.
+
 config RESET_LPC18XX
        bool "LPC18xx/43xx Reset Driver" if COMPILE_TEST
        default ARCH_LPC18XX
index 2cd3f6c45165a8f4a3a1e5c31c92e7f2fa69a8f8..02a74db94339750d4bb57b2450f24d29caed4128 100644 (file)
@@ -2,8 +2,10 @@ obj-y += core.o
 obj-y += hisilicon/
 obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_TEGRA) += tegra/
+obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
 obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
 obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
+obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
 obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
 obj-$(CONFIG_RESET_MESON) += reset-meson.o
 obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
@@ -15,3 +17,4 @@ obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
 obj-$(CONFIG_RESET_ZX2967) += reset-zx2967.o
 obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
+
diff --git a/drivers/reset/reset-a10sr.c b/drivers/reset/reset-a10sr.c
new file mode 100644 (file)
index 0000000..37496bd
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ *  Copyright Intel Corporation (C) 2017. All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Reset driver for Altera Arria10 MAX5 System Resource Chip
+ *
+ * Adapted from reset-socfpga.c
+ */
+
+#include <linux/err.h>
+#include <linux/mfd/altera-a10sr.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/reset/altr,rst-mgr-a10sr.h>
+
+struct a10sr_reset {
+       struct reset_controller_dev     rcdev;
+       struct regmap *regmap;
+};
+
+static inline struct a10sr_reset *to_a10sr_rst(struct reset_controller_dev *rc)
+{
+       return container_of(rc, struct a10sr_reset, rcdev);
+}
+
+static inline int a10sr_reset_shift(unsigned long id)
+{
+       switch (id) {
+       case A10SR_RESET_ENET_HPS:
+               return 1;
+       case A10SR_RESET_PCIE:
+       case A10SR_RESET_FILE:
+       case A10SR_RESET_BQSPI:
+       case A10SR_RESET_USB:
+               return id + 11;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int a10sr_reset_update(struct reset_controller_dev *rcdev,
+                             unsigned long id, bool assert)
+{
+       struct a10sr_reset *a10r = to_a10sr_rst(rcdev);
+       int offset = a10sr_reset_shift(id);
+       u8 mask = ALTR_A10SR_REG_BIT_MASK(offset);
+       int index = ALTR_A10SR_HPS_RST_REG + ALTR_A10SR_REG_OFFSET(offset);
+
+       return regmap_update_bits(a10r->regmap, index, mask, assert ? 0 : mask);
+}
+
+static int a10sr_reset_assert(struct reset_controller_dev *rcdev,
+                             unsigned long id)
+{
+       return a10sr_reset_update(rcdev, id, true);
+}
+
+static int a10sr_reset_deassert(struct reset_controller_dev *rcdev,
+                               unsigned long id)
+{
+       return a10sr_reset_update(rcdev, id, false);
+}
+
+static int a10sr_reset_status(struct reset_controller_dev *rcdev,
+                             unsigned long id)
+{
+       int ret;
+       struct a10sr_reset *a10r = to_a10sr_rst(rcdev);
+       int offset = a10sr_reset_shift(id);
+       u8 mask = ALTR_A10SR_REG_BIT_MASK(offset);
+       int index = ALTR_A10SR_HPS_RST_REG + ALTR_A10SR_REG_OFFSET(offset);
+       unsigned int value;
+
+       ret = regmap_read(a10r->regmap, index, &value);
+       if (ret < 0)
+               return ret;
+
+       return !!(value & mask);
+}
+
+static const struct reset_control_ops a10sr_reset_ops = {
+       .assert         = a10sr_reset_assert,
+       .deassert       = a10sr_reset_deassert,
+       .status         = a10sr_reset_status,
+};
+
+static int a10sr_reset_probe(struct platform_device *pdev)
+{
+       struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent);
+       struct a10sr_reset *a10r;
+
+       a10r = devm_kzalloc(&pdev->dev, sizeof(struct a10sr_reset),
+                           GFP_KERNEL);
+       if (!a10r)
+               return -ENOMEM;
+
+       a10r->rcdev.owner = THIS_MODULE;
+       a10r->rcdev.nr_resets = A10SR_RESET_NUM;
+       a10r->rcdev.ops = &a10sr_reset_ops;
+       a10r->rcdev.of_node = pdev->dev.of_node;
+       a10r->regmap = a10sr->regmap;
+
+       platform_set_drvdata(pdev, a10r);
+
+       return devm_reset_controller_register(&pdev->dev, &a10r->rcdev);
+}
+
+static const struct of_device_id a10sr_reset_of_match[] = {
+       { .compatible = "altr,a10sr-reset" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, a10sr_reset_of_match);
+
+static struct platform_driver a10sr_reset_driver = {
+       .probe  = a10sr_reset_probe,
+       .driver = {
+               .name           = "altr_a10sr_reset",
+       },
+};
+module_platform_driver(a10sr_reset_driver);
+
+MODULE_AUTHOR("Thor Thayer <thor.thayer@linux.intel.com>");
+MODULE_DESCRIPTION("Altera Arria10 System Resource Reset Controller Driver");
+MODULE_LICENSE("GPL v2");
index 6b97631f548932158e7e84b29fdc5cc63f5e2049..2674880e5492be7be62b7053abe776961ba013ef 100644 (file)
@@ -1,4 +1,7 @@
 /*
+ * AR71xx Reset Controller Driver
+ * Author: Alban Bedel
+ *
  * Copyright (C) 2015 Alban Bedel <albeu@free.fr>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -13,7 +16,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/reset-controller.h>
 #include <linux/reboot.h>
@@ -127,31 +130,17 @@ static int ath79_reset_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int ath79_reset_remove(struct platform_device *pdev)
-{
-       struct ath79_reset *ath79_reset = platform_get_drvdata(pdev);
-
-       unregister_restart_handler(&ath79_reset->restart_nb);
-
-       return 0;
-}
-
 static const struct of_device_id ath79_reset_dt_ids[] = {
        { .compatible = "qca,ar7100-reset", },
        { },
 };
-MODULE_DEVICE_TABLE(of, ath79_reset_dt_ids);
 
 static struct platform_driver ath79_reset_driver = {
        .probe  = ath79_reset_probe,
-       .remove = ath79_reset_remove,
        .driver = {
-               .name           = "ath79-reset",
-               .of_match_table = ath79_reset_dt_ids,
+               .name                   = "ath79-reset",
+               .of_match_table         = ath79_reset_dt_ids,
+               .suppress_bind_attrs    = true,
        },
 };
-module_platform_driver(ath79_reset_driver);
-
-MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
-MODULE_DESCRIPTION("AR71xx Reset Controller Driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(ath79_reset_driver);
diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c
new file mode 100644 (file)
index 0000000..4db177b
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 System Reset Controller (SRC) driver
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/regmap.h>
+#include <dt-bindings/reset/imx7-reset.h>
+
+struct imx7_src {
+       struct reset_controller_dev rcdev;
+       struct regmap *regmap;
+};
+
+enum imx7_src_registers {
+       SRC_A7RCR0              = 0x0004,
+       SRC_M4RCR               = 0x000c,
+       SRC_ERCR                = 0x0014,
+       SRC_HSICPHY_RCR         = 0x001c,
+       SRC_USBOPHY1_RCR        = 0x0020,
+       SRC_USBOPHY2_RCR        = 0x0024,
+       SRC_MIPIPHY_RCR         = 0x0028,
+       SRC_PCIEPHY_RCR         = 0x002c,
+       SRC_DDRC_RCR            = 0x1000,
+};
+
+struct imx7_src_signal {
+       unsigned int offset, bit;
+};
+
+static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = {
+       [IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) },
+       [IMX7_RESET_A7_CORE_POR_RESET1] = { SRC_A7RCR0, BIT(1) },
+       [IMX7_RESET_A7_CORE_RESET0]     = { SRC_A7RCR0, BIT(4) },
+       [IMX7_RESET_A7_CORE_RESET1]     = { SRC_A7RCR0, BIT(5) },
+       [IMX7_RESET_A7_DBG_RESET0]      = { SRC_A7RCR0, BIT(8) },
+       [IMX7_RESET_A7_DBG_RESET1]      = { SRC_A7RCR0, BIT(9) },
+       [IMX7_RESET_A7_ETM_RESET0]      = { SRC_A7RCR0, BIT(12) },
+       [IMX7_RESET_A7_ETM_RESET1]      = { SRC_A7RCR0, BIT(13) },
+       [IMX7_RESET_A7_SOC_DBG_RESET]   = { SRC_A7RCR0, BIT(20) },
+       [IMX7_RESET_A7_L2RESET]         = { SRC_A7RCR0, BIT(21) },
+       [IMX7_RESET_SW_M4C_RST]         = { SRC_M4RCR, BIT(1) },
+       [IMX7_RESET_SW_M4P_RST]         = { SRC_M4RCR, BIT(2) },
+       [IMX7_RESET_EIM_RST]            = { SRC_ERCR, BIT(0) },
+       [IMX7_RESET_HSICPHY_PORT_RST]   = { SRC_HSICPHY_RCR, BIT(1) },
+       [IMX7_RESET_USBPHY1_POR]        = { SRC_USBOPHY1_RCR, BIT(0) },
+       [IMX7_RESET_USBPHY1_PORT_RST]   = { SRC_USBOPHY1_RCR, BIT(1) },
+       [IMX7_RESET_USBPHY2_POR]        = { SRC_USBOPHY2_RCR, BIT(0) },
+       [IMX7_RESET_USBPHY2_PORT_RST]   = { SRC_USBOPHY2_RCR, BIT(1) },
+       [IMX7_RESET_MIPI_PHY_MRST]      = { SRC_MIPIPHY_RCR, BIT(1) },
+       [IMX7_RESET_MIPI_PHY_SRST]      = { SRC_MIPIPHY_RCR, BIT(2) },
+       [IMX7_RESET_PCIEPHY]            = { SRC_PCIEPHY_RCR, BIT(2) | BIT(1) },
+       [IMX7_RESET_PCIEPHY_PERST]      = { SRC_PCIEPHY_RCR, BIT(3) },
+       [IMX7_RESET_PCIE_CTRL_APPS_EN]  = { SRC_PCIEPHY_RCR, BIT(6) },
+       [IMX7_RESET_DDRC_PRST]          = { SRC_DDRC_RCR, BIT(0) },
+       [IMX7_RESET_DDRC_CORE_RST]      = { SRC_DDRC_RCR, BIT(1) },
+};
+
+static struct imx7_src *to_imx7_src(struct reset_controller_dev *rcdev)
+{
+       return container_of(rcdev, struct imx7_src, rcdev);
+}
+
+static int imx7_reset_set(struct reset_controller_dev *rcdev,
+                         unsigned long id, bool assert)
+{
+       struct imx7_src *imx7src = to_imx7_src(rcdev);
+       const struct imx7_src_signal *signal = &imx7_src_signals[id];
+       unsigned int value = 0;
+
+       switch (id) {
+       case IMX7_RESET_PCIEPHY:
+               /*
+                * wait for more than 10us to release phy g_rst and
+                * btnrst
+                */
+               if (!assert)
+                       udelay(10);
+               break;
+
+       case IMX7_RESET_PCIE_CTRL_APPS_EN:
+               value = (assert) ? 0 : signal->bit;
+               break;
+       }
+
+       return regmap_update_bits(imx7src->regmap,
+                                 signal->offset, signal->bit, value);
+}
+
+static int imx7_reset_assert(struct reset_controller_dev *rcdev,
+                            unsigned long id)
+{
+       return imx7_reset_set(rcdev, id, true);
+}
+
+static int imx7_reset_deassert(struct reset_controller_dev *rcdev,
+                              unsigned long id)
+{
+       return imx7_reset_set(rcdev, id, false);
+}
+
+static const struct reset_control_ops imx7_reset_ops = {
+       .assert         = imx7_reset_assert,
+       .deassert       = imx7_reset_deassert,
+};
+
+static int imx7_reset_probe(struct platform_device *pdev)
+{
+       struct imx7_src *imx7src;
+       struct device *dev = &pdev->dev;
+       struct regmap_config config = { .name = "src" };
+
+       imx7src = devm_kzalloc(dev, sizeof(*imx7src), GFP_KERNEL);
+       if (!imx7src)
+               return -ENOMEM;
+
+       imx7src->regmap = syscon_node_to_regmap(dev->of_node);
+       if (IS_ERR(imx7src->regmap)) {
+               dev_err(dev, "Unable to get imx7-src regmap");
+               return PTR_ERR(imx7src->regmap);
+       }
+       regmap_attach_dev(dev, imx7src->regmap, &config);
+
+       imx7src->rcdev.owner     = THIS_MODULE;
+       imx7src->rcdev.nr_resets = IMX7_RESET_NUM;
+       imx7src->rcdev.ops       = &imx7_reset_ops;
+       imx7src->rcdev.of_node   = dev->of_node;
+
+       return devm_reset_controller_register(dev, &imx7src->rcdev);
+}
+
+static const struct of_device_id imx7_reset_dt_ids[] = {
+       { .compatible = "fsl,imx7d-src", },
+       { /* sentinel */ },
+};
+
+static struct platform_driver imx7_reset_driver = {
+       .probe  = imx7_reset_probe,
+       .driver = {
+               .name           = KBUILD_MODNAME,
+               .of_match_table = imx7_reset_dt_ids,
+       },
+};
+builtin_platform_driver(imx7_reset_driver);
index c32f11a30c5f3f732e2e80d11e88a394cf0fe425..a8b915eb8b581e4e9086d5cb0d2df11ff800b814 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * Amlogic Meson Reset Controller driver
+ *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
  *
@@ -53,7 +55,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -95,7 +97,6 @@ static const struct of_device_id meson_reset_dt_ids[] = {
         { .compatible = "amlogic,meson-gxbb-reset", },
         { /* sentinel */ },
 };
-MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
 
 static int meson_reset_probe(struct platform_device *pdev)
 {
@@ -128,9 +129,4 @@ static struct platform_driver meson_reset_driver = {
                .of_match_table = meson_reset_dt_ids,
        },
 };
-
-module_platform_driver(meson_reset_driver);
-
-MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
-MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver");
-MODULE_LICENSE("Dual BSD/GPL");
+builtin_platform_driver(meson_reset_driver);
index 0d9036dea010d1274e4a79b536368adad543f0a0..cf5b9742b86ecf4ebc8aa8f53fd5ffb3f607d6b1 100644 (file)
@@ -18,7 +18,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/reset-controller.h>
@@ -83,7 +83,6 @@ static const struct of_device_id oxnas_reset_dt_ids[] = {
         { .compatible = "oxsemi,ox820-reset", },
         { /* sentinel */ },
 };
-MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
 
 static int oxnas_reset_probe(struct platform_device *pdev)
 {
@@ -123,5 +122,4 @@ static struct platform_driver oxnas_reset_driver = {
                .of_match_table = oxnas_reset_dt_ids,
        },
 };
-
-module_platform_driver(oxnas_reset_driver);
+builtin_platform_driver(oxnas_reset_driver);
index bbc4c06dd33b7542b1b1478e46201e9024237682..11d651b44e814ba922e1f7151c6214666cf7c057 100644 (file)
@@ -10,7 +10,7 @@
  * version 2, as published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
@@ -128,7 +128,6 @@ static const struct of_device_id pistachio_reset_dt_ids[] = {
         { .compatible = "img,pistachio-reset", },
         { /* sentinel */ },
 };
-MODULE_DEVICE_TABLE(of, pistachio_reset_dt_ids);
 
 static struct platform_driver pistachio_reset_driver = {
        .probe  = pistachio_reset_probe,
@@ -137,8 +136,4 @@ static struct platform_driver pistachio_reset_driver = {
                .of_match_table = pistachio_reset_dt_ids,
        },
 };
-module_platform_driver(pistachio_reset_driver);
-
-MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
-MODULE_DESCRIPTION("Pistacho Reset Controller Driver");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(pistachio_reset_driver);
index 43e4a9f39b9b8f9be75a52695c9adec73a981667..07224c019892006248a98fe58343d2a0f6c4fe36 100644 (file)
@@ -25,7 +25,8 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
-#define NR_BANKS               4
+#define BANK_INCREMENT         4
+#define NR_BANKS               8
 
 struct socfpga_reset_data {
        spinlock_t                      lock;
@@ -46,8 +47,8 @@ static int socfpga_reset_assert(struct reset_controller_dev *rcdev,
 
        spin_lock_irqsave(&data->lock, flags);
 
-       reg = readl(data->membase + (bank * NR_BANKS));
-       writel(reg | BIT(offset), data->membase + (bank * NR_BANKS));
+       reg = readl(data->membase + (bank * BANK_INCREMENT));
+       writel(reg | BIT(offset), data->membase + (bank * BANK_INCREMENT));
        spin_unlock_irqrestore(&data->lock, flags);
 
        return 0;
@@ -67,8 +68,8 @@ static int socfpga_reset_deassert(struct reset_controller_dev *rcdev,
 
        spin_lock_irqsave(&data->lock, flags);
 
-       reg = readl(data->membase + (bank * NR_BANKS));
-       writel(reg & ~BIT(offset), data->membase + (bank * NR_BANKS));
+       reg = readl(data->membase + (bank * BANK_INCREMENT));
+       writel(reg & ~BIT(offset), data->membase + (bank * BANK_INCREMENT));
 
        spin_unlock_irqrestore(&data->lock, flags);
 
@@ -84,7 +85,7 @@ static int socfpga_reset_status(struct reset_controller_dev *rcdev,
        int offset = id % BITS_PER_LONG;
        u32 reg;
 
-       reg = readl(data->membase + (bank * NR_BANKS));
+       reg = readl(data->membase + (bank * BANK_INCREMENT));
 
        return !(reg & BIT(offset));
 }
index b44f6b5f87b6389a7f983ff794c746a77fbe9b7a..cd585cd2f04dd1b2677fa8c2cf5ac95200792b70 100644 (file)
@@ -34,15 +34,16 @@ static int sunxi_reset_assert(struct reset_controller_dev *rcdev,
        struct sunxi_reset_data *data = container_of(rcdev,
                                                     struct sunxi_reset_data,
                                                     rcdev);
-       int bank = id / BITS_PER_LONG;
-       int offset = id % BITS_PER_LONG;
+       int reg_width = sizeof(u32);
+       int bank = id / (reg_width * BITS_PER_BYTE);
+       int offset = id % (reg_width * BITS_PER_BYTE);
        unsigned long flags;
        u32 reg;
 
        spin_lock_irqsave(&data->lock, flags);
 
-       reg = readl(data->membase + (bank * 4));
-       writel(reg & ~BIT(offset), data->membase + (bank * 4));
+       reg = readl(data->membase + (bank * reg_width));
+       writel(reg & ~BIT(offset), data->membase + (bank * reg_width));
 
        spin_unlock_irqrestore(&data->lock, flags);
 
@@ -55,15 +56,16 @@ static int sunxi_reset_deassert(struct reset_controller_dev *rcdev,
        struct sunxi_reset_data *data = container_of(rcdev,
                                                     struct sunxi_reset_data,
                                                     rcdev);
-       int bank = id / BITS_PER_LONG;
-       int offset = id % BITS_PER_LONG;
+       int reg_width = sizeof(u32);
+       int bank = id / (reg_width * BITS_PER_BYTE);
+       int offset = id % (reg_width * BITS_PER_BYTE);
        unsigned long flags;
        u32 reg;
 
        spin_lock_irqsave(&data->lock, flags);
 
-       reg = readl(data->membase + (bank * 4));
-       writel(reg | BIT(offset), data->membase + (bank * 4));
+       reg = readl(data->membase + (bank * reg_width));
+       writel(reg | BIT(offset), data->membase + (bank * reg_width));
 
        spin_unlock_irqrestore(&data->lock, flags);
 
index 9c11be3d3450f804d1ae90470a3950ac79c5bef0..c4ba89832796b767debc204d41513dc563c96c81 100644 (file)
@@ -50,6 +50,15 @@ struct uniphier_reset_data {
        }
 
 /* System reset data */
+#define UNIPHIER_SLD3_SYS_RESET_NAND(id)               \
+       UNIPHIER_RESETX((id), 0x2004, 2)
+
+#define UNIPHIER_LD11_SYS_RESET_NAND(id)               \
+       UNIPHIER_RESETX((id), 0x200c, 0)
+
+#define UNIPHIER_LD11_SYS_RESET_EMMC(id)               \
+       UNIPHIER_RESETX((id), 0x200c, 2)
+
 #define UNIPHIER_SLD3_SYS_RESET_STDMAC(id)             \
        UNIPHIER_RESETX((id), 0x2000, 10)
 
@@ -65,12 +74,14 @@ struct uniphier_reset_data {
 #define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch)           \
        UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17)
 
-const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = {
+static const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = {
+       UNIPHIER_SLD3_SYS_RESET_NAND(2),
        UNIPHIER_SLD3_SYS_RESET_STDMAC(8),      /* Ether, HSC, MIO */
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
+static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
+       UNIPHIER_SLD3_SYS_RESET_NAND(2),
        UNIPHIER_SLD3_SYS_RESET_STDMAC(8),      /* HSC, MIO, RLE */
        UNIPHIER_PRO4_SYS_RESET_GIO(12),        /* Ether, SATA, USB3 */
        UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
@@ -78,7 +89,8 @@ const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
+static const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
+       UNIPHIER_SLD3_SYS_RESET_NAND(2),
        UNIPHIER_SLD3_SYS_RESET_STDMAC(8),      /* HSC */
        UNIPHIER_PRO4_SYS_RESET_GIO(12),        /* PCIe, USB3 */
        UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
@@ -86,7 +98,8 @@ const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
+static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
+       UNIPHIER_SLD3_SYS_RESET_NAND(2),
        UNIPHIER_SLD3_SYS_RESET_STDMAC(8),      /* HSC, RLE */
        UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
        UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
@@ -100,12 +113,16 @@ const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
+static const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
+       UNIPHIER_LD11_SYS_RESET_NAND(2),
+       UNIPHIER_LD11_SYS_RESET_EMMC(4),
        UNIPHIER_LD11_SYS_RESET_STDMAC(8),      /* HSC, MIO */
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
+static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
+       UNIPHIER_LD11_SYS_RESET_NAND(2),
+       UNIPHIER_LD11_SYS_RESET_EMMC(4),
        UNIPHIER_LD11_SYS_RESET_STDMAC(8),      /* HSC */
        UNIPHIER_LD20_SYS_RESET_GIO(12),        /* PCIe, USB3 */
        UNIPHIER_RESETX(16, 0x200c, 12),        /* USB30-PHY0 */
@@ -134,7 +151,7 @@ const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
 #define UNIPHIER_MIO_RESET_DMAC(id)                    \
        UNIPHIER_RESETX((id), 0x110, 17)
 
-const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
+static const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
        UNIPHIER_MIO_RESET_SD(0, 0),
        UNIPHIER_MIO_RESET_SD(1, 1),
        UNIPHIER_MIO_RESET_SD(2, 2),
@@ -154,7 +171,7 @@ const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
+static const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
        UNIPHIER_MIO_RESET_SD(0, 0),
        UNIPHIER_MIO_RESET_SD(1, 1),
        UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1),
@@ -171,7 +188,7 @@ const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
 #define UNIPHIER_PERI_RESET_FI2C(id, ch)               \
        UNIPHIER_RESETX((id), 0x114, 24 + (ch))
 
-const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
+static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
        UNIPHIER_PERI_RESET_UART(0, 0),
        UNIPHIER_PERI_RESET_UART(1, 1),
        UNIPHIER_PERI_RESET_UART(2, 2),
@@ -184,7 +201,7 @@ const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
+static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
        UNIPHIER_PERI_RESET_UART(0, 0),
        UNIPHIER_PERI_RESET_UART(1, 1),
        UNIPHIER_PERI_RESET_UART(2, 2),
index 45e5b13a3c02ba3e4373ff685985191bccc2873a..309643fe35f9e68eb8e542d5ef48c5d81b904fad 100644 (file)
@@ -3,6 +3,7 @@ menu "SOC (System On Chip) specific Drivers"
 source "drivers/soc/atmel/Kconfig"
 source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/fsl/Kconfig"
+source "drivers/soc/imx/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/rockchip/Kconfig"
index 3467de7d3890d7d7c27eb7182334c6d18f68ba66..824b44281efa5e115b829b345ed0ea5c73af569b 100644 (file)
@@ -7,6 +7,7 @@ obj-y                           += bcm/
 obj-$(CONFIG_ARCH_DOVE)                += dove/
 obj-$(CONFIG_MACH_DOVE)                += dove/
 obj-y                          += fsl/
+obj-$(CONFIG_ARCH_MXC)         += imx/
 obj-$(CONFIG_ARCH_MEDIATEK)    += mediatek/
 obj-$(CONFIG_ARCH_QCOM)                += qcom/
 obj-$(CONFIG_ARCH_RENESAS)     += renesas/
index 94e7335553f437f43d614a50e2bf2381c1fae330..b6195fdf0d0033c7ec24afb9cff100cd5dcf0978 100644 (file)
@@ -41,6 +41,15 @@ bool soc_is_brcmstb(void)
 }
 
 static const struct of_device_id sun_top_ctrl_match[] = {
+       { .compatible = "brcm,bcm7125-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7346-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7358-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7360-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7362-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7420-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7425-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7429-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7425-sun-top-ctrl", },
        { .compatible = "brcm,brcmstb-sun-top-ctrl", },
        { }
 };
diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
new file mode 100644 (file)
index 0000000..357a5d8
--- /dev/null
@@ -0,0 +1,9 @@
+menu "i.MX SoC drivers"
+
+config IMX7_PM_DOMAINS
+       bool "i.MX7 PM domains"
+       select PM_GENERIC_DOMAINS
+       depends on SOC_IMX7D || (COMPILE_TEST && OF)
+       default y if SOC_IMX7D
+
+endmenu
diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile
new file mode 100644 (file)
index 0000000..5b6e396
--- /dev/null
@@ -0,0 +1,2 @@
+obj-y += gpc.o
+obj-$(CONFIG_IMX7_PM_DOMAINS) += gpcv2.o
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
new file mode 100644 (file)
index 0000000..47e7aa9
--- /dev/null
@@ -0,0 +1,489 @@
+/*
+ * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ * Copyright 2011-2013 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define GPC_CNTR               0x000
+
+#define GPC_PGC_CTRL_OFFS      0x0
+#define GPC_PGC_PUPSCR_OFFS    0x4
+#define GPC_PGC_PDNSCR_OFFS    0x8
+#define GPC_PGC_SW2ISO_SHIFT   0x8
+#define GPC_PGC_SW_SHIFT       0x0
+
+#define GPC_PGC_GPU_PDN                0x260
+#define GPC_PGC_GPU_PUPSCR     0x264
+#define GPC_PGC_GPU_PDNSCR     0x268
+
+#define GPU_VPU_PUP_REQ                BIT(1)
+#define GPU_VPU_PDN_REQ                BIT(0)
+
+#define GPC_CLK_MAX            6
+
+#define PGC_DOMAIN_FLAG_NO_PD          BIT(0)
+
+struct imx_pm_domain {
+       struct generic_pm_domain base;
+       struct regmap *regmap;
+       struct regulator *supply;
+       struct clk *clk[GPC_CLK_MAX];
+       int num_clks;
+       unsigned int reg_offs;
+       signed char cntr_pdn_bit;
+       unsigned int ipg_rate_mhz;
+       unsigned int flags;
+};
+
+static inline struct imx_pm_domain *
+to_imx_pm_domain(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx_pm_domain, base);
+}
+
+static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
+{
+       struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
+       int iso, iso2sw;
+       u32 val;
+
+       if (pd->flags & PGC_DOMAIN_FLAG_NO_PD)
+               return -EBUSY;
+
+       /* Read ISO and ISO2SW power down delays */
+       regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
+       iso = val & 0x3f;
+       iso2sw = (val >> 8) & 0x3f;
+
+       /* Gate off domain when powered down */
+       regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
+                          0x1, 0x1);
+
+       /* Request GPC to power down domain */
+       val = BIT(pd->cntr_pdn_bit);
+       regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
+
+       /* Wait ISO + ISO2SW IPG clock cycles */
+       udelay(DIV_ROUND_UP(iso + iso2sw, pd->ipg_rate_mhz));
+
+       if (pd->supply)
+               regulator_disable(pd->supply);
+
+       return 0;
+}
+
+static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
+{
+       struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
+       int i, ret, sw, sw2iso;
+       u32 val;
+
+       if (pd->supply) {
+               ret = regulator_enable(pd->supply);
+               if (ret) {
+                       pr_err("%s: failed to enable regulator: %d\n",
+                              __func__, ret);
+                       return ret;
+               }
+       }
+
+       /* Enable reset clocks for all devices in the domain */
+       for (i = 0; i < pd->num_clks; i++)
+               clk_prepare_enable(pd->clk[i]);
+
+       /* Gate off domain when powered down */
+       regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
+                          0x1, 0x1);
+
+       /* Read ISO and ISO2SW power up delays */
+       regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
+       sw = val & 0x3f;
+       sw2iso = (val >> 8) & 0x3f;
+
+       /* Request GPC to power up domain */
+       val = BIT(pd->cntr_pdn_bit + 1);
+       regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
+
+       /* Wait ISO + ISO2SW IPG clock cycles */
+       udelay(DIV_ROUND_UP(sw + sw2iso, pd->ipg_rate_mhz));
+
+       /* Disable reset clocks for all devices in the domain */
+       for (i = 0; i < pd->num_clks; i++)
+               clk_disable_unprepare(pd->clk[i]);
+
+       return 0;
+}
+
+static int imx_pgc_get_clocks(struct device *dev, struct imx_pm_domain *domain)
+{
+       int i, ret;
+
+       for (i = 0; ; i++) {
+               struct clk *clk = of_clk_get(dev->of_node, i);
+               if (IS_ERR(clk))
+                       break;
+               if (i >= GPC_CLK_MAX) {
+                       dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
+                       ret = -EINVAL;
+                       goto clk_err;
+               }
+               domain->clk[i] = clk;
+       }
+       domain->num_clks = i;
+
+       return 0;
+
+clk_err:
+       while (i--)
+               clk_put(domain->clk[i]);
+
+       return ret;
+}
+
+static void imx_pgc_put_clocks(struct imx_pm_domain *domain)
+{
+       int i;
+
+       for (i = domain->num_clks - 1; i >= 0; i--)
+               clk_put(domain->clk[i]);
+}
+
+static int imx_pgc_parse_dt(struct device *dev, struct imx_pm_domain *domain)
+{
+       /* try to get the domain supply regulator */
+       domain->supply = devm_regulator_get_optional(dev, "power");
+       if (IS_ERR(domain->supply)) {
+               if (PTR_ERR(domain->supply) == -ENODEV)
+                       domain->supply = NULL;
+               else
+                       return PTR_ERR(domain->supply);
+       }
+
+       /* try to get all clocks needed for reset propagation */
+       return imx_pgc_get_clocks(dev, domain);
+}
+
+static int imx_pgc_power_domain_probe(struct platform_device *pdev)
+{
+       struct imx_pm_domain *domain = pdev->dev.platform_data;
+       struct device *dev = &pdev->dev;
+       int ret;
+
+       /* if this PD is associated with a DT node try to parse it */
+       if (dev->of_node) {
+               ret = imx_pgc_parse_dt(dev, domain);
+               if (ret)
+                       return ret;
+       }
+
+       /* initially power on the domain */
+       if (domain->base.power_on)
+               domain->base.power_on(&domain->base);
+
+       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
+               pm_genpd_init(&domain->base, NULL, false);
+               ret = of_genpd_add_provider_simple(dev->of_node, &domain->base);
+               if (ret)
+                       goto genpd_err;
+       }
+
+       device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE);
+
+       return 0;
+
+genpd_err:
+       pm_genpd_remove(&domain->base);
+       imx_pgc_put_clocks(domain);
+
+       return ret;
+}
+
+static int imx_pgc_power_domain_remove(struct platform_device *pdev)
+{
+       struct imx_pm_domain *domain = pdev->dev.platform_data;
+
+       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
+               of_genpd_del_provider(pdev->dev.of_node);
+               pm_genpd_remove(&domain->base);
+               imx_pgc_put_clocks(domain);
+       }
+
+       return 0;
+}
+
+static const struct platform_device_id imx_pgc_power_domain_id[] = {
+       { "imx-pgc-power-domain"},
+       { },
+};
+
+static struct platform_driver imx_pgc_power_domain_driver = {
+       .driver = {
+               .name = "imx-pgc-pd",
+       },
+       .probe = imx_pgc_power_domain_probe,
+       .remove = imx_pgc_power_domain_remove,
+       .id_table = imx_pgc_power_domain_id,
+};
+builtin_platform_driver(imx_pgc_power_domain_driver)
+
+#define GPC_PGC_DOMAIN_ARM     0
+#define GPC_PGC_DOMAIN_PU      1
+#define GPC_PGC_DOMAIN_DISPLAY 2
+
+static struct genpd_power_state imx6_pm_domain_pu_state = {
+       .power_off_latency_ns = 25000,
+       .power_on_latency_ns = 2000000,
+};
+
+static struct imx_pm_domain imx_gpc_domains[] = {
+       {
+               .base = {
+                       .name = "ARM",
+               },
+       }, {
+               .base = {
+                       .name = "PU",
+                       .power_off = imx6_pm_domain_power_off,
+                       .power_on = imx6_pm_domain_power_on,
+                       .states = &imx6_pm_domain_pu_state,
+                       .state_count = 1,
+               },
+               .reg_offs = 0x260,
+               .cntr_pdn_bit = 0,
+       }, {
+               .base = {
+                       .name = "DISPLAY",
+                       .power_off = imx6_pm_domain_power_off,
+                       .power_on = imx6_pm_domain_power_on,
+               },
+               .reg_offs = 0x240,
+               .cntr_pdn_bit = 4,
+       }
+};
+
+struct imx_gpc_dt_data {
+       int num_domains;
+       bool err009619_present;
+};
+
+static const struct imx_gpc_dt_data imx6q_dt_data = {
+       .num_domains = 2,
+       .err009619_present = false,
+};
+
+static const struct imx_gpc_dt_data imx6qp_dt_data = {
+       .num_domains = 2,
+       .err009619_present = true,
+};
+
+static const struct imx_gpc_dt_data imx6sl_dt_data = {
+       .num_domains = 3,
+       .err009619_present = false,
+};
+
+static const struct of_device_id imx_gpc_dt_ids[] = {
+       { .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data },
+       { .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data },
+       { .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data },
+       { }
+};
+
+static const struct regmap_config imx_gpc_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+       .max_register = 0x2ac,
+};
+
+static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
+       &imx_gpc_domains[0].base,
+       &imx_gpc_domains[1].base,
+};
+
+static struct genpd_onecell_data imx_gpc_onecell_data = {
+       .domains = imx_gpc_onecell_domains,
+       .num_domains = 2,
+};
+
+static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap,
+                              unsigned int num_domains)
+{
+       struct imx_pm_domain *domain;
+       int i, ret;
+
+       for (i = 0; i < num_domains; i++) {
+               domain = &imx_gpc_domains[i];
+               domain->regmap = regmap;
+               domain->ipg_rate_mhz = 66;
+
+               if (i == 1) {
+                       domain->supply = devm_regulator_get(dev, "pu");
+                       if (IS_ERR(domain->supply))
+                               return PTR_ERR(domain->supply);;
+
+                       ret = imx_pgc_get_clocks(dev, domain);
+                       if (ret)
+                               goto clk_err;
+
+                       domain->base.power_on(&domain->base);
+               }
+       }
+
+       for (i = 0; i < num_domains; i++)
+               pm_genpd_init(&imx_gpc_domains[i].base, NULL, false);
+
+       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
+               ret = of_genpd_add_provider_onecell(dev->of_node,
+                                                   &imx_gpc_onecell_data);
+               if (ret)
+                       goto genpd_err;
+       }
+
+       return 0;
+
+genpd_err:
+       for (i = 0; i < num_domains; i++)
+               pm_genpd_remove(&imx_gpc_domains[i].base);
+       imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
+clk_err:
+       return ret;
+}
+
+static int imx_gpc_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *of_id =
+                       of_match_device(imx_gpc_dt_ids, &pdev->dev);
+       const struct imx_gpc_dt_data *of_id_data = of_id->data;
+       struct device_node *pgc_node;
+       struct regmap *regmap;
+       struct resource *res;
+       void __iomem *base;
+       int ret;
+
+       pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
+
+       /* bail out if DT too old and doesn't provide the necessary info */
+       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
+           !pgc_node)
+               return 0;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
+                                          &imx_gpc_regmap_config);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(&pdev->dev, "failed to init regmap: %d\n",
+                       ret);
+               return ret;
+       }
+
+       /* Disable PU power down in normal operation if ERR009619 is present */
+       if (of_id_data->err009619_present)
+               imx_gpc_domains[GPC_PGC_DOMAIN_PU].flags |=
+                               PGC_DOMAIN_FLAG_NO_PD;
+
+       if (!pgc_node) {
+               ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
+                                         of_id_data->num_domains);
+               if (ret)
+                       return ret;
+       } else {
+               struct imx_pm_domain *domain;
+               struct platform_device *pd_pdev;
+               struct device_node *np;
+               struct clk *ipg_clk;
+               unsigned int ipg_rate_mhz;
+               int domain_index;
+
+               ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+               if (IS_ERR(ipg_clk))
+                       return PTR_ERR(ipg_clk);
+               ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000;
+
+               for_each_child_of_node(pgc_node, np) {
+                       ret = of_property_read_u32(np, "reg", &domain_index);
+                       if (ret) {
+                               of_node_put(np);
+                               return ret;
+                       }
+                       if (domain_index >= of_id_data->num_domains)
+                               continue;
+
+                       domain = &imx_gpc_domains[domain_index];
+                       domain->regmap = regmap;
+                       domain->ipg_rate_mhz = ipg_rate_mhz;
+
+                       pd_pdev = platform_device_alloc("imx-pgc-power-domain",
+                                                       domain_index);
+                       if (!pd_pdev) {
+                               of_node_put(np);
+                               return -ENOMEM;
+                       }
+                       pd_pdev->dev.platform_data = domain;
+                       pd_pdev->dev.parent = &pdev->dev;
+                       pd_pdev->dev.of_node = np;
+
+                       ret = platform_device_add(pd_pdev);
+                       if (ret) {
+                               platform_device_put(pd_pdev);
+                               of_node_put(np);
+                               return ret;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int imx_gpc_remove(struct platform_device *pdev)
+{
+       int ret;
+
+       /*
+        * If the old DT binding is used the toplevel driver needs to
+        * de-register the power domains
+        */
+       if (!of_get_child_by_name(pdev->dev.of_node, "pgc")) {
+               of_genpd_del_provider(pdev->dev.of_node);
+
+               ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base);
+               if (ret)
+                       return ret;
+               imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
+
+               ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static struct platform_driver imx_gpc_driver = {
+       .driver = {
+               .name = "imx-gpc",
+               .of_match_table = imx_gpc_dt_ids,
+       },
+       .probe = imx_gpc_probe,
+       .remove = imx_gpc_remove,
+};
+builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
new file mode 100644 (file)
index 0000000..3039072
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2017 Impinj, Inc
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * Based on the code of analogus driver:
+ *
+ * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <dt-bindings/power/imx7-power.h>
+
+#define GPC_LPCR_A7_BSC                        0x000
+
+#define GPC_PGC_CPU_MAPPING            0x0ec
+#define USB_HSIC_PHY_A7_DOMAIN         BIT(6)
+#define USB_OTG2_PHY_A7_DOMAIN         BIT(5)
+#define USB_OTG1_PHY_A7_DOMAIN         BIT(4)
+#define PCIE_PHY_A7_DOMAIN             BIT(3)
+#define MIPI_PHY_A7_DOMAIN             BIT(2)
+
+#define GPC_PU_PGC_SW_PUP_REQ          0x0f8
+#define GPC_PU_PGC_SW_PDN_REQ          0x104
+#define USB_HSIC_PHY_SW_Pxx_REQ                BIT(4)
+#define USB_OTG2_PHY_SW_Pxx_REQ                BIT(3)
+#define USB_OTG1_PHY_SW_Pxx_REQ                BIT(2)
+#define PCIE_PHY_SW_Pxx_REQ            BIT(1)
+#define MIPI_PHY_SW_Pxx_REQ            BIT(0)
+
+#define GPC_M4_PU_PDN_FLG              0x1bc
+
+
+#define PGC_MIPI                       4
+#define PGC_PCIE                       5
+#define PGC_USB_HSIC                   8
+#define GPC_PGC_CTRL(n)                        (0x800 + (n) * 0x40)
+#define GPC_PGC_SR(n)                  (GPC_PGC_CTRL(n) + 0xc)
+
+#define GPC_PGC_CTRL_PCR               BIT(0)
+
+struct imx7_pgc_domain {
+       struct generic_pm_domain genpd;
+       struct regmap *regmap;
+       struct regulator *regulator;
+
+       unsigned int pgc;
+
+       const struct {
+               u32 pxx;
+               u32 map;
+       } bits;
+
+       const int voltage;
+       struct device *dev;
+};
+
+static int imx7_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
+                                     bool on)
+{
+       struct imx7_pgc_domain *domain = container_of(genpd,
+                                                     struct imx7_pgc_domain,
+                                                     genpd);
+       unsigned int offset = on ?
+               GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ;
+       const bool enable_power_control = !on;
+       const bool has_regulator = !IS_ERR(domain->regulator);
+       unsigned long deadline;
+       int ret = 0;
+
+       regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
+                          domain->bits.map, domain->bits.map);
+
+       if (has_regulator && on) {
+               ret = regulator_enable(domain->regulator);
+               if (ret) {
+                       dev_err(domain->dev, "failed to enable regulator\n");
+                       goto unmap;
+               }
+       }
+
+       if (enable_power_control)
+               regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
+                                  GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
+
+       regmap_update_bits(domain->regmap, offset,
+                          domain->bits.pxx, domain->bits.pxx);
+
+       /*
+        * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
+        * for PUP_REQ/PDN_REQ bit to be cleared
+        */
+       deadline = jiffies + msecs_to_jiffies(1);
+       while (true) {
+               u32 pxx_req;
+
+               regmap_read(domain->regmap, offset, &pxx_req);
+
+               if (!(pxx_req & domain->bits.pxx))
+                       break;
+
+               if (time_after(jiffies, deadline)) {
+                       dev_err(domain->dev, "falied to command PGC\n");
+                       ret = -ETIMEDOUT;
+                       /*
+                        * If we were in a process of enabling a
+                        * domain and failed we might as well disable
+                        * the regulator we just enabled. And if it
+                        * was the opposite situation and we failed to
+                        * power down -- keep the regulator on
+                        */
+                       on = !on;
+                       break;
+               }
+
+               cpu_relax();
+       }
+
+       if (enable_power_control)
+               regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
+                                  GPC_PGC_CTRL_PCR, 0);
+
+       if (has_regulator && !on) {
+               int err;
+
+               err = regulator_disable(domain->regulator);
+               if (err)
+                       dev_err(domain->dev,
+                               "failed to disable regulator: %d\n", ret);
+               /* Preserve earlier error code */
+               ret = ret ?: err;
+       }
+unmap:
+       regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
+                          domain->bits.map, 0);
+       return ret;
+}
+
+static int imx7_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd)
+{
+       return imx7_gpc_pu_pgc_sw_pxx_req(genpd, true);
+}
+
+static int imx7_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd)
+{
+       return imx7_gpc_pu_pgc_sw_pxx_req(genpd, false);
+}
+
+static struct imx7_pgc_domain imx7_pgc_domains[] = {
+       [IMX7_POWER_DOMAIN_MIPI_PHY] = {
+               .genpd = {
+                       .name      = "mipi-phy",
+               },
+               .bits  = {
+                       .pxx = MIPI_PHY_SW_Pxx_REQ,
+                       .map = MIPI_PHY_A7_DOMAIN,
+               },
+               .voltage   = 1000000,
+               .pgc       = PGC_MIPI,
+       },
+
+       [IMX7_POWER_DOMAIN_PCIE_PHY] = {
+               .genpd = {
+                       .name      = "pcie-phy",
+               },
+               .bits  = {
+                       .pxx = PCIE_PHY_SW_Pxx_REQ,
+                       .map = PCIE_PHY_A7_DOMAIN,
+               },
+               .voltage   = 1000000,
+               .pgc       = PGC_PCIE,
+       },
+
+       [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
+               .genpd = {
+                       .name      = "usb-hsic-phy",
+               },
+               .bits  = {
+                       .pxx = USB_HSIC_PHY_SW_Pxx_REQ,
+                       .map = USB_HSIC_PHY_A7_DOMAIN,
+               },
+               .voltage   = 1200000,
+               .pgc       = PGC_USB_HSIC,
+       },
+};
+
+static int imx7_pgc_domain_probe(struct platform_device *pdev)
+{
+       struct imx7_pgc_domain *domain = pdev->dev.platform_data;
+       int ret;
+
+       domain->dev = &pdev->dev;
+
+       ret = pm_genpd_init(&domain->genpd, NULL, true);
+       if (ret) {
+               dev_err(domain->dev, "Failed to init power domain\n");
+               return ret;
+       }
+
+       domain->regulator = devm_regulator_get_optional(domain->dev, "power");
+       if (IS_ERR(domain->regulator)) {
+               if (PTR_ERR(domain->regulator) != -ENODEV) {
+                       dev_err(domain->dev, "Failed to get domain's regulator\n");
+                       return PTR_ERR(domain->regulator);
+               }
+       } else {
+               regulator_set_voltage(domain->regulator,
+                                     domain->voltage, domain->voltage);
+       }
+
+       ret = of_genpd_add_provider_simple(domain->dev->of_node,
+                                          &domain->genpd);
+       if (ret) {
+               dev_err(domain->dev, "Failed to add genpd provider\n");
+               pm_genpd_remove(&domain->genpd);
+       }
+
+       return ret;
+}
+
+static int imx7_pgc_domain_remove(struct platform_device *pdev)
+{
+       struct imx7_pgc_domain *domain = pdev->dev.platform_data;
+
+       of_genpd_del_provider(domain->dev->of_node);
+       pm_genpd_remove(&domain->genpd);
+
+       return 0;
+}
+
+static const struct platform_device_id imx7_pgc_domain_id[] = {
+       { "imx7-pgc-domain", },
+       { },
+};
+
+static struct platform_driver imx7_pgc_domain_driver = {
+       .driver = {
+               .name = "imx7-pgc",
+       },
+       .probe    = imx7_pgc_domain_probe,
+       .remove   = imx7_pgc_domain_remove,
+       .id_table = imx7_pgc_domain_id,
+};
+builtin_platform_driver(imx7_pgc_domain_driver)
+
+static int imx_gpcv2_probe(struct platform_device *pdev)
+{
+       static const struct regmap_range yes_ranges[] = {
+               regmap_reg_range(GPC_LPCR_A7_BSC,
+                                GPC_M4_PU_PDN_FLG),
+               regmap_reg_range(GPC_PGC_CTRL(PGC_MIPI),
+                                GPC_PGC_SR(PGC_MIPI)),
+               regmap_reg_range(GPC_PGC_CTRL(PGC_PCIE),
+                                GPC_PGC_SR(PGC_PCIE)),
+               regmap_reg_range(GPC_PGC_CTRL(PGC_USB_HSIC),
+                                GPC_PGC_SR(PGC_USB_HSIC)),
+       };
+       static const struct regmap_access_table access_table = {
+               .yes_ranges     = yes_ranges,
+               .n_yes_ranges   = ARRAY_SIZE(yes_ranges),
+       };
+       static const struct regmap_config regmap_config = {
+               .reg_bits       = 32,
+               .val_bits       = 32,
+               .reg_stride     = 4,
+               .rd_table       = &access_table,
+               .wr_table       = &access_table,
+               .max_register   = SZ_4K,
+       };
+       struct device *dev = &pdev->dev;
+       struct device_node *pgc_np, *np;
+       struct regmap *regmap;
+       struct resource *res;
+       void __iomem *base;
+       int ret;
+
+       pgc_np = of_get_child_by_name(dev->of_node, "pgc");
+       if (!pgc_np) {
+               dev_err(dev, "No power domains specified in DT\n");
+               return -EINVAL;
+       }
+
+       res  = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(dev, "failed to init regmap (%d)\n", ret);
+               return ret;
+       }
+
+       for_each_child_of_node(pgc_np, np) {
+               struct platform_device *pd_pdev;
+               struct imx7_pgc_domain *domain;
+               u32 domain_index;
+
+               ret = of_property_read_u32(np, "reg", &domain_index);
+               if (ret) {
+                       dev_err(dev, "Failed to read 'reg' property\n");
+                       of_node_put(np);
+                       return ret;
+               }
+
+               if (domain_index >= ARRAY_SIZE(imx7_pgc_domains)) {
+                       dev_warn(dev,
+                                "Domain index %d is out of bounds\n",
+                                domain_index);
+                       continue;
+               }
+
+               domain = &imx7_pgc_domains[domain_index];
+               domain->regmap = regmap;
+               domain->genpd.power_on  = imx7_gpc_pu_pgc_sw_pup_req;
+               domain->genpd.power_off = imx7_gpc_pu_pgc_sw_pdn_req;
+
+               pd_pdev = platform_device_alloc("imx7-pgc-domain",
+                                               domain_index);
+               if (!pd_pdev) {
+                       dev_err(dev, "Failed to allocate platform device\n");
+                       of_node_put(np);
+                       return -ENOMEM;
+               }
+
+               pd_pdev->dev.platform_data = domain;
+               pd_pdev->dev.parent = dev;
+               pd_pdev->dev.of_node = np;
+
+               ret = platform_device_add(pd_pdev);
+               if (ret) {
+                       platform_device_put(pd_pdev);
+                       of_node_put(np);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static const struct of_device_id imx_gpcv2_dt_ids[] = {
+       { .compatible = "fsl,imx7d-gpc" },
+       { }
+};
+
+static struct platform_driver imx_gpc_driver = {
+       .driver = {
+               .name = "imx-gpcv2",
+               .of_match_table = imx_gpcv2_dt_ids,
+       },
+       .probe = imx_gpcv2_probe,
+};
+builtin_platform_driver(imx_gpc_driver)
index 5e7537c96f7bbbcd2470a15ff1bdaaa13d8a6a13..7412666187b30420235e1ef10d64ce7926c5e7f7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Renesas R-Car H3 System Controller
  *
- * Copyright (C) 2016 Glider bvba
+ * Copyright (C) 2016-2017 Glider bvba
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include <linux/bug.h>
 #include <linux/kernel.h>
+#include <linux/sys_soc.h>
 
 #include <dt-bindings/power/r8a7795-sysc.h>
 
 #include "rcar-sysc.h"
 
-static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
+static struct rcar_sysc_area r8a7795_areas[] __initdata = {
        { "always-on",      0, 0, R8A7795_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
        { "ca57-scu",   0x1c0, 0, R8A7795_PD_CA57_SCU,  R8A7795_PD_ALWAYS_ON,
          PD_SCU },
@@ -40,6 +41,7 @@ static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
        { "a3vp",       0x340, 0, R8A7795_PD_A3VP,      R8A7795_PD_ALWAYS_ON },
        { "cr7",        0x240, 0, R8A7795_PD_CR7,       R8A7795_PD_ALWAYS_ON },
        { "a3vc",       0x380, 0, R8A7795_PD_A3VC,      R8A7795_PD_ALWAYS_ON },
+       /* A2VC0 exists on ES1.x only */
        { "a2vc0",      0x3c0, 0, R8A7795_PD_A2VC0,     R8A7795_PD_A3VC },
        { "a2vc1",      0x3c0, 1, R8A7795_PD_A2VC1,     R8A7795_PD_A3VC },
        { "3dg-a",      0x100, 0, R8A7795_PD_3DG_A,     R8A7795_PD_ALWAYS_ON },
@@ -50,7 +52,27 @@ static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
        { "a3ir",       0x180, 0, R8A7795_PD_A3IR,      R8A7795_PD_ALWAYS_ON },
 };
 
+
+       /*
+        * Fixups for R-Car H3 revisions after ES1.x
+        */
+
+static const struct soc_device_attribute r8a7795es1[] __initconst = {
+       { .soc_id = "r8a7795", .revision = "ES1.*" },
+       { /* sentinel */ }
+};
+
+static int __init r8a7795_sysc_init(void)
+{
+       if (!soc_device_match(r8a7795es1))
+               rcar_sysc_nullify(r8a7795_areas, ARRAY_SIZE(r8a7795_areas),
+                                 R8A7795_PD_A2VC0);
+
+       return 0;
+}
+
 const struct rcar_sysc_info r8a7795_sysc_info __initconst = {
+       .init = r8a7795_sysc_init,
        .areas = r8a7795_areas,
        .num_areas = ARRAY_SIZE(r8a7795_areas),
 };
index 225c35c79d9abad07308d2226f99448ba0d93531..528a13742aeb98d8035c7a998e5e2a037ccffe2c 100644 (file)
@@ -2,7 +2,7 @@
  * R-Car SYSC Power management support
  *
  * Copyright (C) 2014  Magnus Damm
- * Copyright (C) 2015-2016 Glider bvba
+ * Copyright (C) 2015-2017 Glider bvba
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -334,6 +334,12 @@ static int __init rcar_sysc_pd_init(void)
 
        info = match->data;
 
+       if (info->init) {
+               error = info->init();
+               if (error)
+                       return error;
+       }
+
        has_cpg_mstp = of_find_compatible_node(NULL, NULL,
                                               "renesas,cpg-mstp-clocks");
 
@@ -377,6 +383,11 @@ static int __init rcar_sysc_pd_init(void)
                const struct rcar_sysc_area *area = &info->areas[i];
                struct rcar_sysc_pd *pd;
 
+               if (!area->name) {
+                       /* Skip NULLified area */
+                       continue;
+               }
+
                pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL);
                if (!pd) {
                        error = -ENOMEM;
@@ -406,6 +417,18 @@ out_put:
 }
 early_initcall(rcar_sysc_pd_init);
 
+void __init rcar_sysc_nullify(struct rcar_sysc_area *areas,
+                             unsigned int num_areas, u8 id)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_areas; i++)
+               if (areas[i].isr_bit == id) {
+                       areas[i].name = NULL;
+                       return;
+               }
+}
+
 void __init rcar_sysc_init(phys_addr_t base, u32 syscier)
 {
        u32 syscimr;
index f6e842e2976ebe326ca2439dfb58a4b14f6464bc..07edb049a401196c7a6cd8903d37d310a96d09c0 100644 (file)
@@ -46,6 +46,7 @@ struct rcar_sysc_area {
  */
 
 struct rcar_sysc_info {
+       int (*init)(void);      /* Optional */
        const struct rcar_sysc_area *areas;
        unsigned int num_areas;
 };
@@ -59,4 +60,13 @@ extern const struct rcar_sysc_info r8a7792_sysc_info;
 extern const struct rcar_sysc_info r8a7794_sysc_info;
 extern const struct rcar_sysc_info r8a7795_sysc_info;
 extern const struct rcar_sysc_info r8a7796_sysc_info;
+
+
+    /*
+     * Helpers for fixing up power area tables depending on SoC revision
+     */
+
+extern void rcar_sysc_nullify(struct rcar_sysc_area *areas,
+                             unsigned int num_areas, u8 id);
+
 #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
index 330960312296f603075fbcd0296f2693df8889aa..ca26f13d399cf4c12bb2a8e92b2ab526cdee049c 100644 (file)
@@ -80,11 +80,21 @@ static const struct renesas_soc soc_rmobile_a1 __initconst __maybe_unused = {
        .id     = 0x40,
 };
 
+static const struct renesas_soc soc_rz_g1h __initconst __maybe_unused = {
+       .family = &fam_rzg,
+       .id     = 0x45,
+};
+
 static const struct renesas_soc soc_rz_g1m __initconst __maybe_unused = {
        .family = &fam_rzg,
        .id     = 0x47,
 };
 
+static const struct renesas_soc soc_rz_g1n __initconst __maybe_unused = {
+       .family = &fam_rzg,
+       .id     = 0x4b,
+};
+
 static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = {
        .family = &fam_rzg,
        .id     = 0x4c,
@@ -150,9 +160,15 @@ static const struct of_device_id renesas_socs[] __initconst = {
 #ifdef CONFIG_ARCH_R8A7740
        { .compatible = "renesas,r8a7740",      .data = &soc_rmobile_a1 },
 #endif
+#ifdef CONFIG_ARCH_R8A7742
+       { .compatible = "renesas,r8a7742",      .data = &soc_rz_g1h },
+#endif
 #ifdef CONFIG_ARCH_R8A7743
        { .compatible = "renesas,r8a7743",      .data = &soc_rz_g1m },
 #endif
+#ifdef CONFIG_ARCH_R8A7744
+       { .compatible = "renesas,r8a7744",      .data = &soc_rz_g1n },
+#endif
 #ifdef CONFIG_ARCH_R8A7745
        { .compatible = "renesas,r8a7745",      .data = &soc_rz_g1e },
 #endif
@@ -254,4 +270,4 @@ static int __init renesas_soc_init(void)
 
        return 0;
 }
-core_initcall(renesas_soc_init);
+early_initcall(renesas_soc_init);
index 245533907d1ba51d59e784d644303db88076e582..8b25bd55e64803aa528aa97dabf6090641d619ab 100644 (file)
@@ -8,7 +8,13 @@ if SOC_SAMSUNG
 
 config EXYNOS_PMU
        bool "Exynos PMU controller driver" if COMPILE_TEST
-       depends on (ARM && ARCH_EXYNOS) || ((ARM || ARM64) && COMPILE_TEST)
+       depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)
+       select EXYNOS_PMU_ARM_DRIVERS if ARM && ARCH_EXYNOS
+
+# There is no need to enable these drivers for ARMv8
+config EXYNOS_PMU_ARM_DRIVERS
+       bool "Exynos PMU ARMv7-specific driver extensions" if COMPILE_TEST
+       depends on EXYNOS_PMU
 
 config EXYNOS_PM_DOMAINS
        bool "Exynos PM domains" if COMPILE_TEST
index 3619f2ecddaa787da3bd19f86c3cc35b0a39c50e..4d7694a4e7a4916db6892cf036fbf872ef31d58b 100644 (file)
@@ -1,3 +1,5 @@
-obj-$(CONFIG_EXYNOS_PMU)       += exynos-pmu.o exynos3250-pmu.o exynos4-pmu.o \
+obj-$(CONFIG_EXYNOS_PMU)       += exynos-pmu.o
+
+obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS)   += exynos3250-pmu.o exynos4-pmu.o \
                                        exynos5250-pmu.o exynos5420-pmu.o
 obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o
index 56d9244ff98147d056fc094fb6dcee6ad7f6830e..bd4a76f27bc20521a214c26888f1e7a27b8cc9ff 100644 (file)
@@ -68,28 +68,38 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
        }
 }
 
+/*
+ * Split the data between ARM architectures because it is relatively big
+ * and useless on other arch.
+ */
+#ifdef CONFIG_EXYNOS_PMU_ARM_DRIVERS
+#define exynos_pmu_data_arm_ptr(data)  (&data)
+#else
+#define exynos_pmu_data_arm_ptr(data)  NULL
+#endif
+
 /*
  * PMU platform driver and devicetree bindings.
  */
 static const struct of_device_id exynos_pmu_of_device_ids[] = {
        {
                .compatible = "samsung,exynos3250-pmu",
-               .data = &exynos3250_pmu_data,
+               .data = exynos_pmu_data_arm_ptr(exynos3250_pmu_data),
        }, {
                .compatible = "samsung,exynos4210-pmu",
-               .data = &exynos4210_pmu_data,
+               .data = exynos_pmu_data_arm_ptr(exynos4210_pmu_data),
        }, {
                .compatible = "samsung,exynos4212-pmu",
-               .data = &exynos4212_pmu_data,
+               .data = exynos_pmu_data_arm_ptr(exynos4212_pmu_data),
        }, {
                .compatible = "samsung,exynos4412-pmu",
-               .data = &exynos4412_pmu_data,
+               .data = exynos_pmu_data_arm_ptr(exynos4412_pmu_data),
        }, {
                .compatible = "samsung,exynos5250-pmu",
-               .data = &exynos5250_pmu_data,
+               .data = exynos_pmu_data_arm_ptr(exynos5250_pmu_data),
        }, {
                .compatible = "samsung,exynos5420-pmu",
-               .data = &exynos5420_pmu_data,
+               .data = exynos_pmu_data_arm_ptr(exynos5420_pmu_data),
        }, {
                .compatible = "samsung,exynos5433-pmu",
        },
index a469e366fead456671b53bc7f1512751fe03c5c6..40d4229abfb5670b3da22df5e3a9d2e5baa5cbd1 100644 (file)
@@ -31,6 +31,8 @@ struct exynos_pmu_data {
 };
 
 extern void __iomem *pmu_base_addr;
+
+#ifdef CONFIG_EXYNOS_PMU_ARM_DRIVERS
 /* list of all exported SoC specific data */
 extern const struct exynos_pmu_data exynos3250_pmu_data;
 extern const struct exynos_pmu_data exynos4210_pmu_data;
@@ -38,6 +40,7 @@ extern const struct exynos_pmu_data exynos4212_pmu_data;
 extern const struct exynos_pmu_data exynos4412_pmu_data;
 extern const struct exynos_pmu_data exynos5250_pmu_data;
 extern const struct exynos_pmu_data exynos5420_pmu_data;
+#endif
 
 extern void pmu_raw_writel(u32 val, u32 offset);
 extern u32 pmu_raw_readl(u32 offset);
index e5e124c07066b8a0e202cfe2fd17fb71f979e71e..dcf088db40b664502e9c4dacba81e5487a811f46 100644 (file)
@@ -12,6 +12,8 @@ config ARCH_TEGRA_2x_SOC
        select PINCTRL_TEGRA20
        select PL310_ERRATA_727915 if CACHE_L2X0
        select PL310_ERRATA_769419 if CACHE_L2X0
+       select SOC_TEGRA_FLOWCTRL
+       select SOC_TEGRA_PMC
        select TEGRA_TIMER
        help
          Support for NVIDIA Tegra AP20 and T20 processors, based on the
@@ -23,6 +25,8 @@ config ARCH_TEGRA_3x_SOC
        select ARM_ERRATA_764369 if SMP
        select PINCTRL_TEGRA30
        select PL310_ERRATA_769419 if CACHE_L2X0
+       select SOC_TEGRA_FLOWCTRL
+       select SOC_TEGRA_PMC
        select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T30 processor family, based on the
@@ -33,6 +37,8 @@ config ARCH_TEGRA_114_SOC
        select ARM_ERRATA_798181 if SMP
        select HAVE_ARM_ARCH_TIMER
        select PINCTRL_TEGRA114
+       select SOC_TEGRA_FLOWCTRL
+       select SOC_TEGRA_PMC
        select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T114 processor family, based on the
@@ -42,6 +48,8 @@ config ARCH_TEGRA_124_SOC
        bool "Enable support for Tegra124 family"
        select HAVE_ARM_ARCH_TIMER
        select PINCTRL_TEGRA124
+       select SOC_TEGRA_FLOWCTRL
+       select SOC_TEGRA_PMC
        select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T124 processor family, based on the
@@ -55,6 +63,8 @@ if ARM64
 config ARCH_TEGRA_132_SOC
        bool "NVIDIA Tegra132 SoC"
        select PINCTRL_TEGRA124
+       select SOC_TEGRA_FLOWCTRL
+       select SOC_TEGRA_PMC
        help
          Enable support for NVIDIA Tegra132 SoC, based on the Denver
          ARMv8 CPU.  The Tegra132 SoC is similar to the Tegra124 SoC,
@@ -64,6 +74,8 @@ config ARCH_TEGRA_132_SOC
 config ARCH_TEGRA_210_SOC
        bool "NVIDIA Tegra210 SoC"
        select PINCTRL_TEGRA210
+       select SOC_TEGRA_FLOWCTRL
+       select SOC_TEGRA_PMC
        help
          Enable support for the NVIDIA Tegra210 SoC. Also known as Tegra X1,
          the Tegra210 has four Cortex-A57 cores paired with four Cortex-A53
@@ -83,6 +95,7 @@ config ARCH_TEGRA_186_SOC
        select TEGRA_BPMP
        select TEGRA_HSP_MBOX
        select TEGRA_IVC
+       select SOC_TEGRA_PMC_TEGRA186
        help
          Enable support for the NVIDIA Tegar186 SoC. The Tegra186 features a
          combination of Denver and Cortex-A57 CPU cores and a GPU based on
@@ -93,3 +106,12 @@ config ARCH_TEGRA_186_SOC
 
 endif
 endif
+
+config SOC_TEGRA_FLOWCTRL
+       bool
+
+config SOC_TEGRA_PMC
+       bool
+
+config SOC_TEGRA_PMC_TEGRA186
+       bool
index ae857ff7d53d99c772d3a4c5809b618a17957fdb..4f81dd55e5d1c46443724ef34e90d03e9d15796c 100644 (file)
@@ -1,4 +1,6 @@
 obj-y += fuse/
 
 obj-y += common.o
-obj-y += pmc.o
+obj-$(CONFIG_SOC_TEGRA_FLOWCTRL) += flowctrl.o
+obj-$(CONFIG_SOC_TEGRA_PMC) += pmc.o
+obj-$(CONFIG_SOC_TEGRA_PMC_TEGRA186) += pmc-tegra186.o
similarity index 67%
rename from arch/arm/mach-tegra/flowctrl.c
rename to drivers/soc/tegra/flowctrl.c
index 475e783992fd284dbeb613ba8928262811c1809a..0e345c05fc6529faefe7f991c5f98845e6db07a5 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * arch/arm/mach-tegra/flowctrl.c
+ * drivers/soc/tegra/flowctrl.c
  *
- * functions and macros to control the flowcontroller
+ * Functions and macros to control the flowcontroller
  *
  * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
  *
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/platform_device.h>
 
+#include <soc/tegra/common.h>
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 
-#include "flowctrl.h"
-
 static u8 flowctrl_offset_halt_cpu[] = {
        FLOW_CTRL_HALT_CPU0_EVENTS,
        FLOW_CTRL_HALT_CPU1_EVENTS,
@@ -47,6 +48,10 @@ static void __iomem *tegra_flowctrl_base;
 
 static void flowctrl_update(u8 offset, u32 value)
 {
+       if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base),
+                     "Tegra flowctrl not initialised!\n"))
+               return;
+
        writel(value, tegra_flowctrl_base + offset);
 
        /* ensure the update has reached the flow controller */
@@ -58,6 +63,10 @@ u32 flowctrl_read_cpu_csr(unsigned int cpuid)
 {
        u8 offset = flowctrl_offset_cpu_csr[cpuid];
 
+       if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base),
+                     "Tegra flowctrl not initialised!\n"))
+               return 0;
+
        return readl(tegra_flowctrl_base + offset);
 }
 
@@ -140,7 +149,23 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid)
        flowctrl_write_cpu_csr(cpuid, reg);
 }
 
-static const struct of_device_id matches[] __initconst = {
+static int tegra_flowctrl_probe(struct platform_device *pdev)
+{
+       void __iomem *base = tegra_flowctrl_base;
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       tegra_flowctrl_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(tegra_flowctrl_base))
+               return PTR_ERR(base);
+
+       iounmap(base);
+
+       return 0;
+}
+
+static const struct of_device_id tegra_flowctrl_match[] = {
+       { .compatible = "nvidia,tegra210-flowctrl" },
        { .compatible = "nvidia,tegra124-flowctrl" },
        { .compatible = "nvidia,tegra114-flowctrl" },
        { .compatible = "nvidia,tegra30-flowctrl" },
@@ -148,24 +173,52 @@ static const struct of_device_id matches[] __initconst = {
        { }
 };
 
-void __init tegra_flowctrl_init(void)
+static struct platform_driver tegra_flowctrl_driver = {
+       .driver = {
+               .name = "tegra-flowctrl",
+               .suppress_bind_attrs = true,
+               .of_match_table = tegra_flowctrl_match,
+       },
+       .probe = tegra_flowctrl_probe,
+};
+builtin_platform_driver(tegra_flowctrl_driver);
+
+static int __init tegra_flowctrl_init(void)
 {
-       /* hardcoded fallback if device tree node is missing */
-       unsigned long base = 0x60007000;
-       unsigned long size = SZ_4K;
+       struct resource res;
        struct device_node *np;
 
-       np = of_find_matching_node(NULL, matches);
-       if (np) {
-               struct resource res;
+       if (!soc_is_tegra())
+               return 0;
 
-               if (of_address_to_resource(np, 0, &res) == 0) {
-                       size = resource_size(&res);
-                       base = res.start;
+       np = of_find_matching_node(NULL, tegra_flowctrl_match);
+       if (np) {
+               if (of_address_to_resource(np, 0, &res) < 0) {
+                       pr_err("failed to get flowctrl register\n");
+                       return -ENXIO;
                }
-
                of_node_put(np);
+       } else if (IS_ENABLED(CONFIG_ARM)) {
+               /*
+                * Hardcoded fallback for 32-bit Tegra
+                * devices if device tree node is missing.
+                */
+               res.start = 0x60007000;
+               res.end = 0x60007fff;
+               res.flags = IORESOURCE_MEM;
+       } else {
+               /*
+                * At this point we're running on a Tegra,
+                * that doesn't support the flow controller
+                * (eg. Tegra186), so just return.
+                */
+               return 0;
        }
 
-       tegra_flowctrl_base = ioremap_nocache(base, size);
+       tegra_flowctrl_base = ioremap_nocache(res.start, resource_size(&res));
+       if (!tegra_flowctrl_base)
+               return -ENXIO;
+
+       return 0;
 }
+early_initcall(tegra_flowctrl_init);
index de2c1bfe28b5f6297f6c51dc570951556d064f34..7413f60fa855d7f128efe604a972ee361fdfea4b 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/kobject.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -168,7 +168,7 @@ static struct platform_driver tegra_fuse_driver = {
        },
        .probe = tegra_fuse_probe,
 };
-module_platform_driver(tegra_fuse_driver);
+builtin_platform_driver(tegra_fuse_driver);
 
 bool __init tegra_fuse_read_spare(unsigned int spare)
 {
diff --git a/drivers/soc/tegra/pmc-tegra186.c b/drivers/soc/tegra/pmc-tegra186.c
new file mode 100644 (file)
index 0000000..6f5c6f9
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#define pr_fmt(fmt) "tegra-pmc: " fmt
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+#include <asm/system_misc.h>
+
+#define PMC_CNTRL 0x000
+#define  PMC_CNTRL_MAIN_RST BIT(4)
+
+#define PMC_RST_STATUS 0x070
+
+#define WAKE_AOWAKE_CTRL 0x4f4
+#define  WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
+
+#define SCRATCH_SCRATCH0 0x2000
+#define  SCRATCH_SCRATCH0_MODE_RECOVERY BIT(31)
+#define  SCRATCH_SCRATCH0_MODE_BOOTLOADER BIT(30)
+#define  SCRATCH_SCRATCH0_MODE_RCM BIT(1)
+#define  SCRATCH_SCRATCH0_MODE_MASK (SCRATCH_SCRATCH0_MODE_RECOVERY | \
+                                    SCRATCH_SCRATCH0_MODE_BOOTLOADER | \
+                                    SCRATCH_SCRATCH0_MODE_RCM)
+
+struct tegra_pmc {
+       struct device *dev;
+       void __iomem *regs;
+       void __iomem *wake;
+       void __iomem *aotag;
+       void __iomem *scratch;
+
+       void (*system_restart)(enum reboot_mode mode, const char *cmd);
+       struct notifier_block restart;
+};
+
+static int tegra186_pmc_restart_notify(struct notifier_block *nb,
+                                      unsigned long action,
+                                      void *data)
+{
+       struct tegra_pmc *pmc = container_of(nb, struct tegra_pmc, restart);
+       const char *cmd = data;
+       u32 value;
+
+       value = readl(pmc->scratch + SCRATCH_SCRATCH0);
+       value &= ~SCRATCH_SCRATCH0_MODE_MASK;
+
+       if (cmd) {
+               if (strcmp(cmd, "recovery") == 0)
+                       value |= SCRATCH_SCRATCH0_MODE_RECOVERY;
+
+               if (strcmp(cmd, "bootloader") == 0)
+                       value |= SCRATCH_SCRATCH0_MODE_BOOTLOADER;
+
+               if (strcmp(cmd, "forced-recovery") == 0)
+                       value |= SCRATCH_SCRATCH0_MODE_RCM;
+       }
+
+       writel(value, pmc->scratch + SCRATCH_SCRATCH0);
+
+       /*
+        * If available, call the system restart implementation that was
+        * registered earlier (typically PSCI).
+        */
+       if (pmc->system_restart) {
+               pmc->system_restart(reboot_mode, cmd);
+               return NOTIFY_DONE;
+       }
+
+       /* reset everything but SCRATCH0_SCRATCH0 and PMC_RST_STATUS */
+       value = readl(pmc->regs + PMC_CNTRL);
+       value |= PMC_CNTRL_MAIN_RST;
+       writel(value, pmc->regs + PMC_CNTRL);
+
+       return NOTIFY_DONE;
+}
+
+static int tegra186_pmc_setup(struct tegra_pmc *pmc)
+{
+       struct device_node *np = pmc->dev->of_node;
+       bool invert;
+       u32 value;
+
+       invert = of_property_read_bool(np, "nvidia,invert-interrupt");
+
+       value = readl(pmc->wake + WAKE_AOWAKE_CTRL);
+
+       if (invert)
+               value |= WAKE_AOWAKE_CTRL_INTR_POLARITY;
+       else
+               value &= ~WAKE_AOWAKE_CTRL_INTR_POLARITY;
+
+       writel(value, pmc->wake + WAKE_AOWAKE_CTRL);
+
+       /*
+        * We need to hook any system restart implementation registered
+        * previously so we can write SCRATCH_SCRATCH0 before reset.
+        */
+       pmc->system_restart = arm_pm_restart;
+       arm_pm_restart = NULL;
+
+       pmc->restart.notifier_call = tegra186_pmc_restart_notify;
+       pmc->restart.priority = 128;
+
+       return register_restart_handler(&pmc->restart);
+}
+
+static int tegra186_pmc_probe(struct platform_device *pdev)
+{
+       struct tegra_pmc *pmc;
+       struct resource *res;
+
+       pmc = devm_kzalloc(&pdev->dev, sizeof(*pmc), GFP_KERNEL);
+       if (!pmc)
+               return -ENOMEM;
+
+       pmc->dev = &pdev->dev;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pmc");
+       pmc->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pmc->regs))
+               return PTR_ERR(pmc->regs);
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wake");
+       pmc->wake = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pmc->wake))
+               return PTR_ERR(pmc->wake);
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aotag");
+       pmc->aotag = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pmc->aotag))
+               return PTR_ERR(pmc->aotag);
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "scratch");
+       pmc->scratch = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pmc->scratch))
+               return PTR_ERR(pmc->scratch);
+
+       return tegra186_pmc_setup(pmc);
+}
+
+static const struct of_device_id tegra186_pmc_of_match[] = {
+       { .compatible = "nvidia,tegra186-pmc" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, tegra186_pmc_of_match);
+
+static struct platform_driver tegra186_pmc_driver = {
+       .driver = {
+               .name = "tegra186-pmc",
+               .of_match_table = tegra186_pmc_of_match,
+       },
+       .probe = tegra186_pmc_probe,
+};
+builtin_platform_driver(tegra186_pmc_driver);
index 3557c5e32a931098e9386e97db82da6efeeb2632..39e152abe6b901cfb6fabd0e1f379740a86de2ab 100644 (file)
@@ -38,4 +38,16 @@ config WKUP_M3_IPC
          to communicate and use the Wakeup M3 for PM features like suspend
          resume and boots it using wkup_m3_rproc driver.
 
+config TI_SCI_PM_DOMAINS
+       tristate "TI SCI PM Domains Driver"
+       depends on TI_SCI_PROTOCOL
+       depends on PM_GENERIC_DOMAINS
+       help
+         Generic power domain implementation for TI device implementing
+         the TI SCI protocol.
+
+         To compile this as a module, choose M here. The module will be
+         called ti_sci_pm_domains. Note this is needed early in boot before
+         rootfs may be available.
+
 endif # SOC_TI
index 48ff3a79634fb2d7bbeca91f6a638e417e5557bb..7d572736c86ec8507f1d80d45479d99001446202 100644 (file)
@@ -5,3 +5,4 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS)   += knav_qmss.o
 knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o
 obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA)   += knav_dma.o
 obj-$(CONFIG_WKUP_M3_IPC)              += wkup_m3_ipc.o
+obj-$(CONFIG_TI_SCI_PM_DOMAINS)                += ti_sci_pm_domains.o
diff --git a/drivers/soc/ti/ti_sci_pm_domains.c b/drivers/soc/ti/ti_sci_pm_domains.c
new file mode 100644 (file)
index 0000000..b0b2838
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * TI SCI Generic Power Domain Driver
+ *
+ * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
+ *     J Keerthy <j-keerthy@ti.com>
+ *     Dave Gerlach <d-gerlach@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+
+/**
+ * struct ti_sci_genpd_dev_data: holds data needed for every device attached
+ *                              to this genpd
+ * @idx: index of the device that identifies it with the system
+ *      control processor.
+ */
+struct ti_sci_genpd_dev_data {
+       int idx;
+};
+
+/**
+ * struct ti_sci_pm_domain: TI specific data needed for power domain
+ * @ti_sci: handle to TI SCI protocol driver that provides ops to
+ *         communicate with system control processor.
+ * @dev: pointer to dev for the driver for devm allocs
+ * @pd: generic_pm_domain for use with the genpd framework
+ */
+struct ti_sci_pm_domain {
+       const struct ti_sci_handle *ti_sci;
+       struct device *dev;
+       struct generic_pm_domain pd;
+};
+
+#define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd)
+
+/**
+ * ti_sci_dev_id(): get prepopulated ti_sci id from struct dev
+ * @dev: pointer to device associated with this genpd
+ *
+ * Returns device_id stored from ti,sci_id property
+ */
+static int ti_sci_dev_id(struct device *dev)
+{
+       struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
+       struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
+
+       return sci_dev_data->idx;
+}
+
+/**
+ * ti_sci_dev_to_sci_handle(): get pointer to ti_sci_handle
+ * @dev: pointer to device associated with this genpd
+ *
+ * Returns ti_sci_handle to be used to communicate with system
+ *        control processor.
+ */
+static const struct ti_sci_handle *ti_sci_dev_to_sci_handle(struct device *dev)
+{
+       struct generic_pm_domain *pd = pd_to_genpd(dev->pm_domain);
+       struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(pd);
+
+       return ti_sci_genpd->ti_sci;
+}
+
+/**
+ * ti_sci_dev_start(): genpd device start hook called to turn device on
+ * @dev: pointer to device associated with this genpd to be powered on
+ */
+static int ti_sci_dev_start(struct device *dev)
+{
+       const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
+       int idx = ti_sci_dev_id(dev);
+
+       return ti_sci->ops.dev_ops.get_device(ti_sci, idx);
+}
+
+/**
+ * ti_sci_dev_stop(): genpd device stop hook called to turn device off
+ * @dev: pointer to device associated with this genpd to be powered off
+ */
+static int ti_sci_dev_stop(struct device *dev)
+{
+       const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
+       int idx = ti_sci_dev_id(dev);
+
+       return ti_sci->ops.dev_ops.put_device(ti_sci, idx);
+}
+
+static int ti_sci_pd_attach_dev(struct generic_pm_domain *domain,
+                               struct device *dev)
+{
+       struct device_node *np = dev->of_node;
+       struct of_phandle_args pd_args;
+       struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(domain);
+       const struct ti_sci_handle *ti_sci = ti_sci_genpd->ti_sci;
+       struct ti_sci_genpd_dev_data *sci_dev_data;
+       struct generic_pm_domain_data *genpd_data;
+       int idx, ret = 0;
+
+       ret = of_parse_phandle_with_args(np, "power-domains",
+                                        "#power-domain-cells", 0, &pd_args);
+       if (ret < 0)
+               return ret;
+
+       if (pd_args.args_count != 1)
+               return -EINVAL;
+
+       idx = pd_args.args[0];
+
+       /*
+        * Check the validity of the requested idx, if the index is not valid
+        * the PMMC will return a NAK here and we will not allocate it.
+        */
+       ret = ti_sci->ops.dev_ops.is_valid(ti_sci, idx);
+       if (ret)
+               return -EINVAL;
+
+       sci_dev_data = kzalloc(sizeof(*sci_dev_data), GFP_KERNEL);
+       if (!sci_dev_data)
+               return -ENOMEM;
+
+       sci_dev_data->idx = idx;
+
+       genpd_data = dev_gpd_data(dev);
+       genpd_data->data = sci_dev_data;
+
+       return 0;
+}
+
+static void ti_sci_pd_detach_dev(struct generic_pm_domain *domain,
+                                struct device *dev)
+{
+       struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
+       struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
+
+       kfree(sci_dev_data);
+       genpd_data->data = NULL;
+}
+
+static const struct of_device_id ti_sci_pm_domain_matches[] = {
+       { .compatible = "ti,sci-pm-domain", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, ti_sci_pm_domain_matches);
+
+static int ti_sci_pm_domain_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct ti_sci_pm_domain *ti_sci_pd;
+       int ret;
+
+       ti_sci_pd = devm_kzalloc(dev, sizeof(*ti_sci_pd), GFP_KERNEL);
+       if (!ti_sci_pd)
+               return -ENOMEM;
+
+       ti_sci_pd->ti_sci = devm_ti_sci_get_handle(dev);
+       if (IS_ERR(ti_sci_pd->ti_sci))
+               return PTR_ERR(ti_sci_pd->ti_sci);
+
+       ti_sci_pd->dev = dev;
+
+       ti_sci_pd->pd.attach_dev = ti_sci_pd_attach_dev;
+       ti_sci_pd->pd.detach_dev = ti_sci_pd_detach_dev;
+
+       ti_sci_pd->pd.dev_ops.start = ti_sci_dev_start;
+       ti_sci_pd->pd.dev_ops.stop = ti_sci_dev_stop;
+
+       pm_genpd_init(&ti_sci_pd->pd, NULL, true);
+
+       ret = of_genpd_add_provider_simple(np, &ti_sci_pd->pd);
+
+       return ret;
+}
+
+static struct platform_driver ti_sci_pm_domains_driver = {
+       .probe = ti_sci_pm_domain_probe,
+       .driver = {
+               .name = "ti_sci_pm_domains",
+               .of_match_table = ti_sci_pm_domain_matches,
+       },
+};
+module_platform_driver(ti_sci_pm_domains_driver);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI System Control Interface (SCI) Power Domain driver");
+MODULE_AUTHOR("Dave Gerlach");
index 5ed924fee855c8b21b82c5dc26844604ff639d34..4dc5d62ee81b1674088a8df2da3600310c0cd7a0 100644 (file)
@@ -169,7 +169,6 @@ static const struct of_device_id zx296718_pm_domain_matches[] = {
 static struct platform_driver zx296718_pd_driver = {
        .driver = {
                .name = "zx296718-powerdomain",
-               .owner = THIS_MODULE,
                .of_match_table = zx296718_pm_domain_matches,
        },
        .probe = zx296718_pd_probe,
index 61c8d84bf31560725439904c0d4e1fc8dbe8775f..c42aeaaa34bab184e1e64008abd2c58ae0bce45e 100644 (file)
@@ -125,10 +125,8 @@ int zx2967_pd_probe(struct platform_device *pdev,
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        pcubase = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(pcubase)) {
-               dev_err(&pdev->dev, "ioremap fail.\n");
+       if (IS_ERR(pcubase))
                return PTR_ERR(pcubase);
-       }
 
        for (i = 0; i < domain_num; ++i) {
                zx_pm_domains[i]->power_on = zx2967_power_on;
diff --git a/include/dt-bindings/genpd/k2g.h b/include/dt-bindings/genpd/k2g.h
new file mode 100644 (file)
index 0000000..1f31f17
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * TI K2G SoC Device definitions
+ *
+ * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_GENPD_K2G_H
+#define _DT_BINDINGS_GENPD_K2G_H
+
+/* Documented in http://processors.wiki.ti.com/index.php/TISCI */
+
+#define K2G_DEV_PMMC0                  0x0000
+#define K2G_DEV_MLB0                   0x0001
+#define K2G_DEV_DSS0                   0x0002
+#define K2G_DEV_MCBSP0                 0x0003
+#define K2G_DEV_MCASP0                 0x0004
+#define K2G_DEV_MCASP1                 0x0005
+#define K2G_DEV_MCASP2                 0x0006
+#define K2G_DEV_DCAN0                  0x0008
+#define K2G_DEV_DCAN1                  0x0009
+#define K2G_DEV_EMIF0                  0x000a
+#define K2G_DEV_MMCHS0                 0x000b
+#define K2G_DEV_MMCHS1                 0x000c
+#define K2G_DEV_GPMC0                  0x000d
+#define K2G_DEV_ELM0                   0x000e
+#define K2G_DEV_SPI0                   0x0010
+#define K2G_DEV_SPI1                   0x0011
+#define K2G_DEV_SPI2                   0x0012
+#define K2G_DEV_SPI3                   0x0013
+#define K2G_DEV_ICSS0                  0x0014
+#define K2G_DEV_ICSS1                  0x0015
+#define K2G_DEV_USB0                   0x0016
+#define K2G_DEV_USB1                   0x0017
+#define K2G_DEV_NSS0                   0x0018
+#define K2G_DEV_PCIE0                  0x0019
+#define K2G_DEV_GPIO0                  0x001b
+#define K2G_DEV_GPIO1                  0x001c
+#define K2G_DEV_TIMER64_0              0x001d
+#define K2G_DEV_TIMER64_1              0x001e
+#define K2G_DEV_TIMER64_2              0x001f
+#define K2G_DEV_TIMER64_3              0x0020
+#define K2G_DEV_TIMER64_4              0x0021
+#define K2G_DEV_TIMER64_5              0x0022
+#define K2G_DEV_TIMER64_6              0x0023
+#define K2G_DEV_MSGMGR0                        0x0025
+#define K2G_DEV_BOOTCFG0               0x0026
+#define K2G_DEV_ARM_BOOTROM0           0x0027
+#define K2G_DEV_DSP_BOOTROM0           0x0029
+#define K2G_DEV_DEBUGSS0               0x002b
+#define K2G_DEV_UART0                  0x002c
+#define K2G_DEV_UART1                  0x002d
+#define K2G_DEV_UART2                  0x002e
+#define K2G_DEV_EHRPWM0                        0x002f
+#define K2G_DEV_EHRPWM1                        0x0030
+#define K2G_DEV_EHRPWM2                        0x0031
+#define K2G_DEV_EHRPWM3                        0x0032
+#define K2G_DEV_EHRPWM4                        0x0033
+#define K2G_DEV_EHRPWM5                        0x0034
+#define K2G_DEV_EQEP0                  0x0035
+#define K2G_DEV_EQEP1                  0x0036
+#define K2G_DEV_EQEP2                  0x0037
+#define K2G_DEV_ECAP0                  0x0038
+#define K2G_DEV_ECAP1                  0x0039
+#define K2G_DEV_I2C0                   0x003a
+#define K2G_DEV_I2C1                   0x003b
+#define K2G_DEV_I2C2                   0x003c
+#define K2G_DEV_EDMA0                  0x003f
+#define K2G_DEV_SEMAPHORE0             0x0040
+#define K2G_DEV_INTC0                  0x0041
+#define K2G_DEV_GIC0                   0x0042
+#define K2G_DEV_QSPI0                  0x0043
+#define K2G_DEV_ARM_64B_COUNTER0       0x0044
+#define K2G_DEV_TETRIS0                        0x0045
+#define K2G_DEV_CGEM0                  0x0046
+#define K2G_DEV_MSMC0                  0x0047
+#define K2G_DEV_CBASS0                 0x0049
+#define K2G_DEV_BOARD0                 0x004c
+#define K2G_DEV_EDMA1                  0x004f
+
+#endif
diff --git a/include/dt-bindings/power/imx7-power.h b/include/dt-bindings/power/imx7-power.h
new file mode 100644 (file)
index 0000000..3a181e4
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  Copyright (C) 2017 Impinj
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DT_BINDINGS_IMX7_POWER_H__
+#define __DT_BINDINGS_IMX7_POWER_H__
+
+#define IMX7_POWER_DOMAIN_MIPI_PHY             0
+#define IMX7_POWER_DOMAIN_PCIE_PHY             1
+#define IMX7_POWER_DOMAIN_USB_HSIC_PHY         2
+
+#endif
index ee2e26ba605ef9a37801d1b2858506f8d17864cb..ad679eeda1370a9dec9dd21c0fae84c1cb53a150 100644 (file)
@@ -33,7 +33,7 @@
 #define R8A7795_PD_CA53_SCU            21
 #define R8A7795_PD_3DG_E               22
 #define R8A7795_PD_A3IR                        24
-#define R8A7795_PD_A2VC0               25
+#define R8A7795_PD_A2VC0               25      /* ES1.x only */
 #define R8A7795_PD_A2VC1               26
 
 /* Always-on power area */
diff --git a/include/dt-bindings/reset/altr,rst-mgr-a10sr.h b/include/dt-bindings/reset/altr,rst-mgr-a10sr.h
new file mode 100644 (file)
index 0000000..9855925
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  Copyright Intel Corporation (C) 2017. All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Reset binding definitions for Altera Arria10 MAX5 System Resource Chip
+ *
+ * Adapted from altr,rst-mgr-a10.h
+ */
+
+#ifndef _DT_BINDINGS_RESET_ALTR_RST_MGR_A10SR_H
+#define _DT_BINDINGS_RESET_ALTR_RST_MGR_A10SR_H
+
+/* Peripheral PHY resets */
+#define A10SR_RESET_ENET_HPS   0
+#define A10SR_RESET_PCIE       1
+#define A10SR_RESET_FILE       2
+#define A10SR_RESET_BQSPI      3
+#define A10SR_RESET_USB                4
+
+#define A10SR_RESET_NUM                5
+
+#endif
diff --git a/include/dt-bindings/reset/imx7-reset.h b/include/dt-bindings/reset/imx7-reset.h
new file mode 100644 (file)
index 0000000..6394817
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 Impinj, Inc.
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DT_BINDING_RESET_IMX7_H
+#define DT_BINDING_RESET_IMX7_H
+
+#define IMX7_RESET_A7_CORE_POR_RESET0  0
+#define IMX7_RESET_A7_CORE_POR_RESET1  1
+#define IMX7_RESET_A7_CORE_RESET0      2
+#define IMX7_RESET_A7_CORE_RESET1      3
+#define IMX7_RESET_A7_DBG_RESET0       4
+#define IMX7_RESET_A7_DBG_RESET1       5
+#define IMX7_RESET_A7_ETM_RESET0       6
+#define IMX7_RESET_A7_ETM_RESET1       7
+#define IMX7_RESET_A7_SOC_DBG_RESET    8
+#define IMX7_RESET_A7_L2RESET          9
+#define IMX7_RESET_SW_M4C_RST          10
+#define IMX7_RESET_SW_M4P_RST          11
+#define IMX7_RESET_EIM_RST             12
+#define IMX7_RESET_HSICPHY_PORT_RST    13
+#define IMX7_RESET_USBPHY1_POR         14
+#define IMX7_RESET_USBPHY1_PORT_RST    15
+#define IMX7_RESET_USBPHY2_POR         16
+#define IMX7_RESET_USBPHY2_PORT_RST    17
+#define IMX7_RESET_MIPI_PHY_MRST       18
+#define IMX7_RESET_MIPI_PHY_SRST       19
+
+/*
+ * IMX7_RESET_PCIEPHY is a logical reset line combining PCIEPHY_BTN
+ * and PCIEPHY_G_RST
+ */
+#define IMX7_RESET_PCIEPHY             20
+#define IMX7_RESET_PCIEPHY_PERST       21
+
+/*
+ * IMX7_RESET_PCIE_CTRL_APPS_EN is not strictly a reset line, but it
+ * can be used to inhibit PCIe LTTSM, so, in a way, it can be thoguht
+ * of as one
+ */
+#define IMX7_RESET_PCIE_CTRL_APPS_EN   22
+#define IMX7_RESET_DDRC_PRST           23
+#define IMX7_RESET_DDRC_CORE_RST       24
+
+#define IMX7_RESET_NUM                 25
+
+#endif
+
index 8e953c6f394ae58ef5902c2ae4fd44fd5f3c1173..37a5eaea69dde299a18855ffc99b1227513b25da 100644 (file)
@@ -25,7 +25,7 @@ int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0, u32 arg1,
                  u32 arg2, u32 arg3, u32 arg4);
 int meson_sm_call_write(void *buffer, unsigned int b_size, unsigned int cmd_index,
                        u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
-int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0, u32 arg1,
-                      u32 arg2, u32 arg3, u32 arg4);
+int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
+                      u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
 
 #endif /* _MESON_SM_FW_H_ */
index 9b6abe6325875ce91a353d64fa2f53a52a77f583..b7803a251044a0eb89142b7a32452bef61f2594b 100644 (file)
@@ -118,6 +118,7 @@ struct generic_pm_domain_data {
        struct pm_domain_data base;
        struct gpd_timing_data td;
        struct notifier_block nb;
+       void *data;
 };
 
 #ifdef CONFIG_PM_GENERIC_DOMAINS
index d32f6f1a5225f38de2ff8456a09b236028eb1de5..e5380471c2cd2a42edb8d0bbeb231d8b7320ddf0 100644 (file)
@@ -40,6 +40,9 @@ extern int qcom_scm_pas_shutdown(u32 peripheral);
 extern void qcom_scm_cpu_power_down(u32 flags);
 extern u32 qcom_scm_get_version(void);
 extern int qcom_scm_set_remote_state(u32 state, u32 id);
+extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare);
+extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size);
+extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare);
 #else
 static inline
 int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
@@ -67,5 +70,8 @@ static inline void qcom_scm_cpu_power_down(u32 flags) {}
 static inline u32 qcom_scm_get_version(void) { return 0; }
 static inline u32
 qcom_scm_set_remote_state(u32 state,u32 id) { return -ENODEV; }
+static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) { return -ENODEV; }
+static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { return -ENODEV; }
+static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; }
 #endif
 #endif
similarity index 77%
rename from arch/arm/mach-tegra/flowctrl.h
rename to include/soc/tegra/flowctrl.h
index 73a9c5016c1ab1ae9414887eb3fdfa16a1b32293..8f86aea4024b2f41ad9f28b9cbf39d397940dbac 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * arch/arm/mach-tegra/flowctrl.h
- *
- * functions and macros to control the flowcontroller
+ * Functions and macros to control the flowcontroller
  *
  * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
  *
@@ -18,8 +16,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __MACH_TEGRA_FLOWCTRL_H
-#define __MACH_TEGRA_FLOWCTRL_H
+#ifndef __SOC_TEGRA_FLOWCTRL_H__
+#define __SOC_TEGRA_FLOWCTRL_H__
 
 #define FLOW_CTRL_HALT_CPU0_EVENTS     0x0
 #define FLOW_CTRL_WAITEVENT            (2 << 29)
 #define TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP       (0xF << 8)
 
 #ifndef __ASSEMBLY__
+#ifdef CONFIG_SOC_TEGRA_FLOWCTRL
 u32 flowctrl_read_cpu_csr(unsigned int cpuid);
 void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value);
 void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value);
 
 void flowctrl_cpu_suspend_enter(unsigned int cpuid);
 void flowctrl_cpu_suspend_exit(unsigned int cpuid);
+#else
+static inline u32 flowctrl_read_cpu_csr(unsigned int cpuid)
+{
+       return 0;
+}
+
+static inline void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value)
+{
+}
+
+static inline void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value) {}
 
-void tegra_flowctrl_init(void);
-#endif
+static inline void flowctrl_cpu_suspend_enter(unsigned int cpuid)
+{
+}
 
-#endif
+static inline void flowctrl_cpu_suspend_exit(unsigned int cpuid)
+{
+}
+#endif /* CONFIG_SOC_TEGRA_FLOWCTRL */
+#endif /* __ASSEMBLY */
+#endif /* __SOC_TEGRA_FLOWCTRL_H__ */
index 2f271d1b9cea6fdc9bb1678077eab3222ea3bf92..1c3982bc558fb1d98ec3c90f6663c1a8189dca8e 100644 (file)
 struct clk;
 struct reset_control;
 
-#ifdef CONFIG_PM_SLEEP
-enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
-void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
-void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
-#endif /* CONFIG_PM_SLEEP */
-
 #ifdef CONFIG_SMP
 bool tegra_pmc_cpu_is_powered(unsigned int cpuid);
 int tegra_pmc_cpu_power_on(unsigned int cpuid);
@@ -144,7 +138,7 @@ enum tegra_io_pad_voltage {
        TEGRA_IO_PAD_3300000UV,
 };
 
-#ifdef CONFIG_ARCH_TEGRA
+#ifdef CONFIG_SOC_TEGRA_PMC
 int tegra_powergate_is_powered(unsigned int id);
 int tegra_powergate_power_on(unsigned int id);
 int tegra_powergate_power_off(unsigned int id);
@@ -163,6 +157,11 @@ int tegra_io_pad_get_voltage(enum tegra_io_pad id);
 /* deprecated, use tegra_io_pad_power_{enable,disable}() instead */
 int tegra_io_rail_power_on(unsigned int id);
 int tegra_io_rail_power_off(unsigned int id);
+
+enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
+void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
+void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
+
 #else
 static inline int tegra_powergate_is_powered(unsigned int id)
 {
@@ -221,6 +220,20 @@ static inline int tegra_io_rail_power_off(unsigned int id)
 {
        return -ENOSYS;
 }
-#endif /* CONFIG_ARCH_TEGRA */
+
+static inline enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
+{
+       return TEGRA_SUSPEND_NONE;
+}
+
+static inline void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
+{
+}
+
+static inline void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
+{
+}
+
+#endif /* CONFIG_SOC_TEGRA_PMC */
 
 #endif /* __SOC_TEGRA_PMC_H__ */