aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds2017-05-09 12:01:15 -0500
committerLinus Torvalds2017-05-09 12:01:15 -0500
commit0160e00ae8e987be8822745fb166aa76451c9bcc (patch)
treedeca2d09a729155ed0cb631f2bc8f557e634ab06
parentc81ee18e97e4e3162169a749eb7f2b79b3510c7a (diff)
parentb6942b68f85ed3161c91741791ec6f1779574919 (diff)
downloadkernel-0160e00ae8e987be8822745fb166aa76451c9bcc.tar.gz
kernel-0160e00ae8e987be8822745fb166aa76451c9bcc.tar.xz
kernel-0160e00ae8e987be8822745fb166aa76451c9bcc.zip
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
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 ...
-rw-r--r--Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt34
-rw-r--r--Documentation/devicetree/bindings/power/fsl,imx-gpc.txt85
-rw-r--r--Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt71
-rw-r--r--Documentation/devicetree/bindings/reset/fsl,imx7-src.txt47
-rw-r--r--Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt57
-rw-r--r--MAINTAINERS6
-rw-r--r--arch/arm/common/Kconfig3
-rw-r--r--arch/arm/common/Makefile1
-rw-r--r--arch/arm/mach-imx/gpc.c217
-rw-r--r--arch/arm/mach-keystone/Kconfig1
-rw-r--r--arch/arm/mach-keystone/pm_domain.c4
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra20.c3
-rw-r--r--arch/arm/mach-tegra/platsmp.c2
-rw-r--r--arch/arm/mach-tegra/pm.c2
-rw-r--r--arch/arm/mach-tegra/reset-handler.S2
-rw-r--r--arch/arm/mach-tegra/sleep-tegra20.S3
-rw-r--r--arch/arm/mach-tegra/sleep-tegra30.S2
-rw-r--r--arch/arm/mach-tegra/sleep.S2
-rw-r--r--arch/arm/mach-tegra/tegra.c2
-rw-r--r--arch/arm/plat-versatile/include/plat/clock.h15
-rw-r--r--drivers/ata/Kconfig9
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/ata/pata_bk3710.c382
-rw-r--r--drivers/base/power/domain.c2
-rw-r--r--drivers/base/soc.c52
-rw-r--r--drivers/clk/versatile/Kconfig3
-rw-r--r--drivers/clk/versatile/Makefile2
-rw-r--r--drivers/clk/versatile/clk-icst.c1
-rw-r--r--drivers/clk/versatile/clk-icst.h2
-rw-r--r--drivers/clk/versatile/clk-impd1.c1
-rw-r--r--drivers/clk/versatile/clk-realview.c1
-rw-r--r--drivers/clk/versatile/clk-versatile.c1
-rw-r--r--drivers/clk/versatile/icst.c (renamed from arch/arm/common/icst.c)2
-rw-r--r--drivers/clk/versatile/icst.h (renamed from arch/arm/include/asm/hardware/icst.h)6
-rw-r--r--drivers/firmware/arm_scpi.c7
-rw-r--r--drivers/firmware/meson/meson_sm.c20
-rw-r--r--drivers/firmware/qcom_scm-32.c18
-rw-r--r--drivers/firmware/qcom_scm-64.c58
-rw-r--r--drivers/firmware/qcom_scm.c18
-rw-r--r--drivers/firmware/qcom_scm.h11
-rw-r--r--drivers/nvmem/meson-efuse.c2
-rw-r--r--drivers/reset/Kconfig14
-rw-r--r--drivers/reset/Makefile3
-rw-r--r--drivers/reset/reset-a10sr.c138
-rw-r--r--drivers/reset/reset-ath79.c27
-rw-r--r--drivers/reset/reset-imx7.c158
-rw-r--r--drivers/reset/reset-meson.c12
-rw-r--r--drivers/reset/reset-oxnas.c6
-rw-r--r--drivers/reset/reset-pistachio.c9
-rw-r--r--drivers/reset/reset-socfpga.c13
-rw-r--r--drivers/reset/reset-sunxi.c18
-rw-r--r--drivers/reset/reset-uniphier.c37
-rw-r--r--drivers/soc/Kconfig1
-rw-r--r--drivers/soc/Makefile1
-rw-r--r--drivers/soc/bcm/brcmstb/common.c9
-rw-r--r--drivers/soc/imx/Kconfig9
-rw-r--r--drivers/soc/imx/Makefile2
-rw-r--r--drivers/soc/imx/gpc.c489
-rw-r--r--drivers/soc/imx/gpcv2.c363
-rw-r--r--drivers/soc/renesas/r8a7795-sysc.c26
-rw-r--r--drivers/soc/renesas/rcar-sysc.c25
-rw-r--r--drivers/soc/renesas/rcar-sysc.h10
-rw-r--r--drivers/soc/renesas/renesas-soc.c18
-rw-r--r--drivers/soc/samsung/Kconfig8
-rw-r--r--drivers/soc/samsung/Makefile4
-rw-r--r--drivers/soc/samsung/exynos-pmu.c22
-rw-r--r--drivers/soc/samsung/exynos-pmu.h3
-rw-r--r--drivers/soc/tegra/Kconfig22
-rw-r--r--drivers/soc/tegra/Makefile4
-rw-r--r--drivers/soc/tegra/flowctrl.c (renamed from arch/arm/mach-tegra/flowctrl.c)87
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra.c4
-rw-r--r--drivers/soc/tegra/pmc-tegra186.c169
-rw-r--r--drivers/soc/ti/Kconfig12
-rw-r--r--drivers/soc/ti/Makefile1
-rw-r--r--drivers/soc/ti/ti_sci_pm_domains.c202
-rw-r--r--drivers/soc/zte/zx296718_pm_domains.c1
-rw-r--r--drivers/soc/zte/zx2967_pm_domains.c4
-rw-r--r--include/dt-bindings/genpd/k2g.h90
-rw-r--r--include/dt-bindings/power/imx7-power.h16
-rw-r--r--include/dt-bindings/power/r8a7795-sysc.h2
-rw-r--r--include/dt-bindings/reset/altr,rst-mgr-a10sr.h33
-rw-r--r--include/dt-bindings/reset/imx7-reset.h62
-rw-r--r--include/linux/firmware/meson/meson_sm.h4
-rw-r--r--include/linux/pm_domain.h1
-rw-r--r--include/linux/qcom_scm.h6
-rw-r--r--include/soc/tegra/flowctrl.h (renamed from arch/arm/mach-tegra/flowctrl.h)32
-rw-r--r--include/soc/tegra/pmc.h29
88 files changed, 2937 insertions, 428 deletions
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
index 000000000000..078a58b0302f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
@@ -0,0 +1,34 @@
1NVIDIA Tegra Power Management Controller (PMC)
2
3Required properties:
4- compatible: Should contain one of the following:
5 - "nvidia,tegra186-pmc": for Tegra186
6- reg: Must contain an (offset, length) pair of the register set for each
7 entry in reg-names.
8- reg-names: Must include the following entries:
9 - "pmc"
10 - "wake"
11 - "aotag"
12 - "scratch"
13
14Optional properties:
15- nvidia,invert-interrupt: If present, inverts the PMU interrupt signal.
16
17Example:
18
19SoC DTSI:
20
21 pmc@c3600000 {
22 compatible = "nvidia,tegra186-pmc";
23 reg = <0 0x0c360000 0 0x10000>,
24 <0 0x0c370000 0 0x10000>,
25 <0 0x0c380000 0 0x10000>,
26 <0 0x0c390000 0 0x10000>;
27 reg-names = "pmc", "wake", "aotag", "scratch";
28 };
29
30Board DTS:
31
32 pmc@c360000 {
33 nvidia,invert-interrupt;
34 };
diff --git a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
index 65cc0345747d..6c1498958d48 100644
--- a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
+++ b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
@@ -1,22 +1,42 @@
1Freescale i.MX General Power Controller 1Freescale i.MX General Power Controller
2======================================= 2=======================================
3 3
4The i.MX6Q General Power Control (GPC) block contains DVFS load tracking 4The i.MX6 General Power Control (GPC) block contains DVFS load tracking
5counters and Power Gating Control (PGC) for the CPU and PU (GPU/VPU) power 5counters and Power Gating Control (PGC).
6domains.
7 6
8Required properties: 7Required properties:
9- compatible: Should be "fsl,imx6q-gpc" or "fsl,imx6sl-gpc" 8- compatible: Should be one of the following:
9 - fsl,imx6q-gpc
10 - fsl,imx6qp-gpc
11 - fsl,imx6sl-gpc
10- reg: should be register base and length as documented in the 12- reg: should be register base and length as documented in the
11 datasheet 13 datasheet
12- interrupts: Should contain GPC interrupt request 1 14- interrupts: Should contain one interrupt specifier for the GPC interrupt
13- pu-supply: Link to the LDO regulator powering the PU power domain 15- clocks: Must contain an entry for each entry in clock-names.
14- clocks: Clock phandles to devices in the PU power domain that need 16 See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
15 to be enabled during domain power-up for reset propagation. 17- clock-names: Must include the following entries:
16- #power-domain-cells: Should be 1, see below: 18 - ipg
17 19
18The gpc node is a power-controller as documented by the generic power domain 20The power domains are generic power domain providers as documented in
19bindings in Documentation/devicetree/bindings/power/power_domain.txt. 21Documentation/devicetree/bindings/power/power_domain.txt. They are described as
22subnodes of the power gating controller 'pgc' node of the GPC and should
23contain the following:
24
25Required properties:
26- reg: Must contain the DOMAIN_INDEX of this power domain
27 The following DOMAIN_INDEX values are valid for i.MX6Q:
28 ARM_DOMAIN 0
29 PU_DOMAIN 1
30 The following additional DOMAIN_INDEX value is valid for i.MX6SL:
31 DISPLAY_DOMAIN 2
32
33- #power-domain-cells: Should be 0
34
35Optional properties:
36- clocks: a number of phandles to clocks that need to be enabled during domain
37 power-up sequencing to ensure reset propagation into devices located inside
38 this power domain
39- power-supply: a phandle to the regulator powering this domain
20 40
21Example: 41Example:
22 42
@@ -25,14 +45,30 @@ Example:
25 reg = <0x020dc000 0x4000>; 45 reg = <0x020dc000 0x4000>;
26 interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>, 46 interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
27 <0 90 IRQ_TYPE_LEVEL_HIGH>; 47 <0 90 IRQ_TYPE_LEVEL_HIGH>;
28 pu-supply = <&reg_pu>; 48 clocks = <&clks IMX6QDL_CLK_IPG>;
29 clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>, 49 clock-names = "ipg";
30 <&clks IMX6QDL_CLK_GPU3D_SHADER>, 50
31 <&clks IMX6QDL_CLK_GPU2D_CORE>, 51 pgc {
32 <&clks IMX6QDL_CLK_GPU2D_AXI>, 52 #address-cells = <1>;
33 <&clks IMX6QDL_CLK_OPENVG_AXI>, 53 #size-cells = <0>;
34 <&clks IMX6QDL_CLK_VPU_AXI>; 54
35 #power-domain-cells = <1>; 55 power-domain@0 {
56 reg = <0>;
57 #power-domain-cells = <0>;
58 };
59
60 pd_pu: power-domain@1 {
61 reg = <1>;
62 #power-domain-cells = <0>;
63 power-supply = <&reg_pu>;
64 clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>,
65 <&clks IMX6QDL_CLK_GPU3D_SHADER>,
66 <&clks IMX6QDL_CLK_GPU2D_CORE>,
67 <&clks IMX6QDL_CLK_GPU2D_AXI>,
68 <&clks IMX6QDL_CLK_OPENVG_AXI>,
69 <&clks IMX6QDL_CLK_VPU_AXI>;
70 };
71 };
36 }; 72 };
37 73
38 74
@@ -40,20 +76,13 @@ Specifying power domain for IP modules
40====================================== 76======================================
41 77
42IP cores belonging to a power domain should contain a 'power-domains' property 78IP cores belonging to a power domain should contain a 'power-domains' property
43that is a phandle pointing to the gpc device node and a DOMAIN_INDEX specifying 79that is a phandle pointing to the power domain the device belongs to.
44the power domain the device belongs to.
45 80
46Example of a device that is part of the PU power domain: 81Example of a device that is part of the PU power domain:
47 82
48 vpu: vpu@02040000 { 83 vpu: vpu@02040000 {
49 reg = <0x02040000 0x3c000>; 84 reg = <0x02040000 0x3c000>;
50 /* ... */ 85 /* ... */
51 power-domains = <&gpc 1>; 86 power-domains = <&pd_pu>;
52 /* ... */ 87 /* ... */
53 }; 88 };
54
55The following DOMAIN_INDEX values are valid for i.MX6Q:
56ARM_DOMAIN 0
57PU_DOMAIN 1
58The following additional DOMAIN_INDEX value is valid for i.MX6SL:
59DISPLAY_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
index 000000000000..02f45c65fd87
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt
@@ -0,0 +1,71 @@
1Freescale i.MX General Power Controller v2
2==========================================
3
4The i.MX7S/D General Power Control (GPC) block contains Power Gating
5Control (PGC) for various power domains.
6
7Required properties:
8
9- compatible: Should be "fsl,imx7d-gpc"
10
11- reg: should be register base and length as documented in the
12 datasheet
13
14- interrupts: Should contain GPC interrupt request 1
15
16Power domains contained within GPC node are generic power domain
17providers, documented in
18Documentation/devicetree/bindings/power/power_domain.txt, which are
19described as subnodes of the power gating controller 'pgc' node,
20which, in turn, is expected to contain the following:
21
22Required properties:
23
24- reg: Power domain index. Valid values are defined in
25 include/dt-bindings/power/imx7-power.h
26
27- #power-domain-cells: Should be 0
28
29Optional properties:
30
31- power-supply: Power supply used to power the domain
32
33Example:
34
35 gpc: gpc@303a0000 {
36 compatible = "fsl,imx7d-gpc";
37 reg = <0x303a0000 0x1000>;
38 interrupt-controller;
39 interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
40 #interrupt-cells = <3>;
41 interrupt-parent = <&intc>;
42
43 pgc {
44 #address-cells = <1>;
45 #size-cells = <0>;
46
47 pgc_pcie_phy: power-domain@3 {
48 #power-domain-cells = <0>;
49
50 reg = <IMX7_POWER_DOMAIN_PCIE_PHY>;
51 power-supply = <&reg_1p0d>;
52 };
53 };
54 };
55
56
57Specifying power domain for IP modules
58======================================
59
60IP cores belonging to a power domain should contain a 'power-domains'
61property that is a phandle for PGC node representing the domain.
62
63Example of a device that is part of the PCIE_PHY power domain:
64
65 pcie: pcie@33800000 {
66 reg = <0x33800000 0x4000>,
67 <0x4ff00000 0x80000>;
68 /* ... */
69 power-domains = <&pgc_pcie_phy>;
70 /* ... */
71 };
diff --git a/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
new file mode 100644
index 000000000000..5e1afc3d8480
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
@@ -0,0 +1,47 @@
1Freescale i.MX7 System Reset Controller
2======================================
3
4Please also refer to reset.txt in this directory for common reset
5controller binding usage.
6
7Required properties:
8- compatible: Should be "fsl,imx7-src", "syscon"
9- reg: should be register base and length as documented in the
10 datasheet
11- interrupts: Should contain SRC interrupt
12- #reset-cells: 1, see below
13
14example:
15
16src: reset-controller@30390000 {
17 compatible = "fsl,imx7d-src", "syscon";
18 reg = <0x30390000 0x2000>;
19 interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
20 #reset-cells = <1>;
21};
22
23
24Specifying reset lines connected to IP modules
25==============================================
26
27The system reset controller can be used to reset various set of
28peripherals. Device nodes that need access to reset lines should
29specify them as a reset phandle in their corresponding node as
30specified in reset.txt.
31
32Example:
33
34 pcie: pcie@33800000 {
35
36 ...
37
38 resets = <&src IMX7_RESET_PCIEPHY>,
39 <&src IMX7_RESET_PCIE_CTRL_APPS_EN>;
40 reset-names = "pciephy", "apps";
41
42 ...
43 };
44
45
46For list of all valid reset indicies see
47<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
index 000000000000..c705db07d820
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
@@ -0,0 +1,57 @@
1Texas Instruments TI-SCI Generic Power Domain
2---------------------------------------------
3
4Some TI SoCs contain a system controller (like the PMMC, etc...) that is
5responsible for controlling the state of the IPs that are present.
6Communication between the host processor running an OS and the system
7controller happens through a protocol known as TI-SCI [1].
8
9[1] Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
10
11PM Domain Node
12==============
13The PM domain node represents the global PM domain managed by the PMMC, which
14in this case is the implementation as documented by the generic PM domain
15bindings in Documentation/devicetree/bindings/power/power_domain.txt. Because
16this relies on the TI SCI protocol to communicate with the PMMC it must be a
17child of the pmmc node.
18
19Required Properties:
20--------------------
21- compatible: should be "ti,sci-pm-domain"
22- #power-domain-cells: Must be 1 so that an id can be provided in each
23 device node.
24
25Example (K2G):
26-------------
27 pmmc: pmmc {
28 compatible = "ti,k2g-sci";
29 ...
30
31 k2g_pds: power-controller {
32 compatible = "ti,sci-pm-domain";
33 #power-domain-cells = <1>;
34 };
35 };
36
37PM Domain Consumers
38===================
39Hardware blocks belonging to a PM domain should contain a "power-domains"
40property that is a phandle pointing to the corresponding PM domain node
41along with an index representing the device id to be passed to the PMMC
42for device control.
43
44Required Properties:
45--------------------
46- power-domains: phandle pointing to the corresponding PM domain node
47 and an ID representing the device.
48
49See dt-bindings/genpd/k2g.h for the list of valid identifiers for k2g.
50
51Example (K2G):
52--------------------
53 uart0: serial@02530c00 {
54 compatible = "ns16550a";
55 ...
56 power-domains = <&k2g_pds K2G_DEV_UART0>;
57 };
diff --git a/MAINTAINERS b/MAINTAINERS
index 9d58e9f18705..41590d3a665a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -653,7 +653,9 @@ M: Thor Thayer <thor.thayer@linux.intel.com>
653S: Maintained 653S: Maintained
654F: drivers/gpio/gpio-altera-a10sr.c 654F: drivers/gpio/gpio-altera-a10sr.c
655F: drivers/mfd/altera-a10sr.c 655F: drivers/mfd/altera-a10sr.c
656F: drivers/reset/reset-a10sr.c
656F: include/linux/mfd/altera-a10sr.h 657F: include/linux/mfd/altera-a10sr.h
658F: include/dt-bindings/reset/altr,rst-mgr-a10sr.h
657 659
658ALTERA TRIPLE SPEED ETHERNET DRIVER 660ALTERA TRIPLE SPEED ETHERNET DRIVER
659M: Vince Bridgers <vbridger@opensource.altera.com> 661M: Vince Bridgers <vbridger@opensource.altera.com>
@@ -1282,6 +1284,7 @@ F: arch/arm/mach-mxs/
1282F: arch/arm/boot/dts/imx* 1284F: arch/arm/boot/dts/imx*
1283F: arch/arm/configs/imx*_defconfig 1285F: arch/arm/configs/imx*_defconfig
1284F: drivers/clk/imx/ 1286F: drivers/clk/imx/
1287F: drivers/soc/imx/
1285F: include/soc/imx/ 1288F: include/soc/imx/
1286 1289
1287ARM/FREESCALE VYBRID ARM ARCHITECTURE 1290ARM/FREESCALE VYBRID ARM ARCHITECTURE
@@ -12604,6 +12607,9 @@ S: Maintained
12604F: Documentation/devicetree/bindings/arm/keystone/ti,sci.txt 12607F: Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
12605F: drivers/firmware/ti_sci* 12608F: drivers/firmware/ti_sci*
12606F: include/linux/soc/ti/ti_sci_protocol.h 12609F: include/linux/soc/ti/ti_sci_protocol.h
12610F: Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
12611F: include/dt-bindings/genpd/k2g.h
12612F: drivers/soc/ti/ti_sci_pm_domains.c
12607 12613
12608THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER 12614THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
12609M: Hans Verkuil <hverkuil@xs4all.nl> 12615M: Hans Verkuil <hverkuil@xs4all.nl>
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 9353184d730d..1181053e3ade 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -1,6 +1,3 @@
1config ICST
2 bool
3
4config SA1111 1config SA1111
5 bool 2 bool
6 select DMABOUNCE if !ARCH_PXA 3 select DMABOUNCE if !ARCH_PXA
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 27f23b15b1ea..29fdf6a3601d 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -4,7 +4,6 @@
4 4
5obj-y += firmware.o 5obj-y += firmware.o
6 6
7obj-$(CONFIG_ICST) += icst.o
8obj-$(CONFIG_SA1111) += sa1111.o 7obj-$(CONFIG_SA1111) += sa1111.o
9obj-$(CONFIG_DMABOUNCE) += dmabounce.o 8obj-$(CONFIG_DMABOUNCE) += dmabounce.o
10obj-$(CONFIG_SHARP_LOCOMO) += locomo.o 9obj-$(CONFIG_SHARP_LOCOMO) += locomo.o
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 1dc2a34b9dbd..93f584ba0130 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -10,26 +10,17 @@
10 * http://www.gnu.org/copyleft/gpl.html 10 * http://www.gnu.org/copyleft/gpl.html
11 */ 11 */
12 12
13#include <linux/clk.h>
14#include <linux/delay.h>
15#include <linux/io.h> 13#include <linux/io.h>
16#include <linux/irq.h> 14#include <linux/irq.h>
17#include <linux/irqchip.h> 15#include <linux/irqchip.h>
18#include <linux/of.h> 16#include <linux/of.h>
19#include <linux/of_address.h> 17#include <linux/of_address.h>
20#include <linux/of_irq.h> 18#include <linux/of_irq.h>
21#include <linux/platform_device.h>
22#include <linux/pm_domain.h>
23#include <linux/regulator/consumer.h>
24#include <linux/irqchip/arm-gic.h> 19#include <linux/irqchip/arm-gic.h>
25#include "common.h" 20#include "common.h"
26#include "hardware.h" 21#include "hardware.h"
27 22
28#define GPC_CNTR 0x000
29#define GPC_IMR1 0x008 23#define GPC_IMR1 0x008
30#define GPC_PGC_GPU_PDN 0x260
31#define GPC_PGC_GPU_PUPSCR 0x264
32#define GPC_PGC_GPU_PDNSCR 0x268
33#define GPC_PGC_CPU_PDN 0x2a0 24#define GPC_PGC_CPU_PDN 0x2a0
34#define GPC_PGC_CPU_PUPSCR 0x2a4 25#define GPC_PGC_CPU_PUPSCR 0x2a4
35#define GPC_PGC_CPU_PDNSCR 0x2a8 26#define GPC_PGC_CPU_PDNSCR 0x2a8
@@ -39,18 +30,6 @@
39#define IMR_NUM 4 30#define IMR_NUM 4
40#define GPC_MAX_IRQS (IMR_NUM * 32) 31#define GPC_MAX_IRQS (IMR_NUM * 32)
41 32
42#define GPU_VPU_PUP_REQ BIT(1)
43#define GPU_VPU_PDN_REQ BIT(0)
44
45#define GPC_CLK_MAX 6
46
47struct pu_domain {
48 struct generic_pm_domain base;
49 struct regulator *reg;
50 struct clk *clk[GPC_CLK_MAX];
51 int num_clks;
52};
53
54static void __iomem *gpc_base; 33static void __iomem *gpc_base;
55static u32 gpc_wake_irqs[IMR_NUM]; 34static u32 gpc_wake_irqs[IMR_NUM];
56static u32 gpc_saved_imrs[IMR_NUM]; 35static u32 gpc_saved_imrs[IMR_NUM];
@@ -296,199 +275,3 @@ void __init imx_gpc_check_dt(void)
296 gpc_base = of_iomap(np, 0); 275 gpc_base = of_iomap(np, 0);
297 } 276 }
298} 277}
299
300static void _imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
301{
302 int iso, iso2sw;
303 u32 val;
304
305 /* Read ISO and ISO2SW power down delays */
306 val = readl_relaxed(gpc_base + GPC_PGC_GPU_PDNSCR);
307 iso = val & 0x3f;
308 iso2sw = (val >> 8) & 0x3f;
309
310 /* Gate off PU domain when GPU/VPU when powered down */
311 writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
312
313 /* Request GPC to power down GPU/VPU */
314 val = readl_relaxed(gpc_base + GPC_CNTR);
315 val |= GPU_VPU_PDN_REQ;
316 writel_relaxed(val, gpc_base + GPC_CNTR);
317
318 /* Wait ISO + ISO2SW IPG clock cycles */
319 ndelay((iso + iso2sw) * 1000 / 66);
320}
321
322static int imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
323{
324 struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
325
326 _imx6q_pm_pu_power_off(genpd);
327
328 if (pu->reg)
329 regulator_disable(pu->reg);
330
331 return 0;
332}
333
334static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd)
335{
336 struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
337 int i, ret, sw, sw2iso;
338 u32 val;
339
340 if (pu->reg)
341 ret = regulator_enable(pu->reg);
342 if (pu->reg && ret) {
343 pr_err("%s: failed to enable regulator: %d\n", __func__, ret);
344 return ret;
345 }
346
347 /* Enable reset clocks for all devices in the PU domain */
348 for (i = 0; i < pu->num_clks; i++)
349 clk_prepare_enable(pu->clk[i]);
350
351 /* Gate off PU domain when GPU/VPU when powered down */
352 writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
353
354 /* Read ISO and ISO2SW power down delays */
355 val = readl_relaxed(gpc_base + GPC_PGC_GPU_PUPSCR);
356 sw = val & 0x3f;
357 sw2iso = (val >> 8) & 0x3f;
358
359 /* Request GPC to power up GPU/VPU */
360 val = readl_relaxed(gpc_base + GPC_CNTR);
361 val |= GPU_VPU_PUP_REQ;
362 writel_relaxed(val, gpc_base + GPC_CNTR);
363
364 /* Wait ISO + ISO2SW IPG clock cycles */
365 ndelay((sw + sw2iso) * 1000 / 66);
366
367 /* Disable reset clocks for all devices in the PU domain */
368 for (i = 0; i < pu->num_clks; i++)
369 clk_disable_unprepare(pu->clk[i]);
370
371 return 0;
372}
373
374static struct generic_pm_domain imx6q_arm_domain = {
375 .name = "ARM",
376};
377
378static struct pu_domain imx6q_pu_domain = {
379 .base = {
380 .name = "PU",
381 .power_off = imx6q_pm_pu_power_off,
382 .power_on = imx6q_pm_pu_power_on,
383 },
384};
385
386static struct generic_pm_domain imx6sl_display_domain = {
387 .name = "DISPLAY",
388};
389
390static struct generic_pm_domain *imx_gpc_domains[] = {
391 &imx6q_arm_domain,
392 &imx6q_pu_domain.base,
393 &imx6sl_display_domain,
394};
395
396static struct genpd_onecell_data imx_gpc_onecell_data = {
397 .domains = imx_gpc_domains,
398 .num_domains = ARRAY_SIZE(imx_gpc_domains),
399};
400
401static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
402{
403 struct clk *clk;
404 int i, ret;
405
406 imx6q_pu_domain.reg = pu_reg;
407
408 for (i = 0; ; i++) {
409 clk = of_clk_get(dev->of_node, i);
410 if (IS_ERR(clk))
411 break;
412 if (i >= GPC_CLK_MAX) {
413 dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
414 goto clk_err;
415 }
416 imx6q_pu_domain.clk[i] = clk;
417 }
418 imx6q_pu_domain.num_clks = i;
419
420 /* Enable power always in case bootloader disabled it. */
421 imx6q_pm_pu_power_on(&imx6q_pu_domain.base);
422
423 if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
424 return 0;
425
426 imx6q_pu_domain.base.states = devm_kzalloc(dev,
427 sizeof(*imx6q_pu_domain.base.states),
428 GFP_KERNEL);
429 if (!imx6q_pu_domain.base.states)
430 return -ENOMEM;
431
432 imx6q_pu_domain.base.states[0].power_off_latency_ns = 25000;
433 imx6q_pu_domain.base.states[0].power_on_latency_ns = 2000000;
434 imx6q_pu_domain.base.state_count = 1;
435
436 for (i = 0; i < ARRAY_SIZE(imx_gpc_domains); i++)
437 pm_genpd_init(imx_gpc_domains[i], NULL, false);
438
439 ret = of_genpd_add_provider_onecell(dev->of_node,
440 &imx_gpc_onecell_data);
441 if (ret)
442 goto power_off;
443
444 return 0;
445
446power_off:
447 imx6q_pm_pu_power_off(&imx6q_pu_domain.base);
448clk_err:
449 while (i--)
450 clk_put(imx6q_pu_domain.clk[i]);
451 imx6q_pu_domain.reg = NULL;
452 return -EINVAL;
453}
454
455static int imx_gpc_probe(struct platform_device *pdev)
456{
457 struct regulator *pu_reg;
458 int ret;
459
460 /* bail out if DT too old and doesn't provide the necessary info */
461 if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells"))
462 return 0;
463
464 pu_reg = devm_regulator_get_optional(&pdev->dev, "pu");
465 if (PTR_ERR(pu_reg) == -ENODEV)
466 pu_reg = NULL;
467 if (IS_ERR(pu_reg)) {
468 ret = PTR_ERR(pu_reg);
469 dev_err(&pdev->dev, "failed to get pu regulator: %d\n", ret);
470 return ret;
471 }
472
473 return imx_gpc_genpd_init(&pdev->dev, pu_reg);
474}
475
476static const struct of_device_id imx_gpc_dt_ids[] = {
477 { .compatible = "fsl,imx6q-gpc" },
478 { .compatible = "fsl,imx6sl-gpc" },
479 { }
480};
481
482static struct platform_driver imx_gpc_driver = {
483 .driver = {
484 .name = "imx-gpc",
485 .of_match_table = imx_gpc_dt_ids,
486 },
487 .probe = imx_gpc_probe,
488};
489
490static int __init imx_pgc_init(void)
491{
492 return platform_driver_register(&imx_gpc_driver);
493}
494subsys_initcall(imx_pgc_init);
diff --git a/arch/arm/mach-keystone/Kconfig b/arch/arm/mach-keystone/Kconfig
index 554357035f30..db122356b410 100644
--- a/arch/arm/mach-keystone/Kconfig
+++ b/arch/arm/mach-keystone/Kconfig
@@ -10,6 +10,7 @@ config ARCH_KEYSTONE
10 select ARCH_SUPPORTS_BIG_ENDIAN 10 select ARCH_SUPPORTS_BIG_ENDIAN
11 select ZONE_DMA if ARM_LPAE 11 select ZONE_DMA if ARM_LPAE
12 select PINCTRL 12 select PINCTRL
13 select PM_GENERIC_DOMAINS if PM
13 help 14 help
14 Support for boards based on the Texas Instruments Keystone family of 15 Support for boards based on the Texas Instruments Keystone family of
15 SoCs. 16 SoCs.
diff --git a/arch/arm/mach-keystone/pm_domain.c b/arch/arm/mach-keystone/pm_domain.c
index 8cbb35765a19..fe57e2692629 100644
--- a/arch/arm/mach-keystone/pm_domain.c
+++ b/arch/arm/mach-keystone/pm_domain.c
@@ -32,7 +32,9 @@ static struct pm_clk_notifier_block platform_domain_notifier = {
32}; 32};
33 33
34static const struct of_device_id of_keystone_table[] = { 34static const struct of_device_id of_keystone_table[] = {
35 {.compatible = "ti,keystone"}, 35 {.compatible = "ti,k2hk"},
36 {.compatible = "ti,k2e"},
37 {.compatible = "ti,k2l"},
36 { /* end of list */ }, 38 { /* end of list */ },
37}; 39};
38 40
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index fffad2426ee4..3b33f0bb78ae 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -2,7 +2,6 @@ asflags-y += -march=armv7-a
2 2
3obj-y += io.o 3obj-y += io.o
4obj-y += irq.o 4obj-y += irq.o
5obj-y += flowctrl.o
6obj-y += pm.o 5obj-y += pm.o
7obj-y += reset.o 6obj-y += reset.o
8obj-y += reset-handler.o 7obj-y += reset-handler.o
diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c
index afcee04f2616..76e4c83cd5c8 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra20.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra20.c
@@ -26,12 +26,13 @@
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/module.h> 27#include <linux/module.h>
28 28
29#include <soc/tegra/flowctrl.h>
30
29#include <asm/cpuidle.h> 31#include <asm/cpuidle.h>
30#include <asm/smp_plat.h> 32#include <asm/smp_plat.h>
31#include <asm/suspend.h> 33#include <asm/suspend.h>
32 34
33#include "cpuidle.h" 35#include "cpuidle.h"
34#include "flowctrl.h"
35#include "iomap.h" 36#include "iomap.h"
36#include "irq.h" 37#include "irq.h"
37#include "pm.h" 38#include "pm.h"
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 75620ae73913..b5a2afe99101 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -21,6 +21,7 @@
21#include <linux/jiffies.h> 21#include <linux/jiffies.h>
22#include <linux/smp.h> 22#include <linux/smp.h>
23 23
24#include <soc/tegra/flowctrl.h>
24#include <soc/tegra/fuse.h> 25#include <soc/tegra/fuse.h>
25#include <soc/tegra/pmc.h> 26#include <soc/tegra/pmc.h>
26 27
@@ -30,7 +31,6 @@
30#include <asm/smp_scu.h> 31#include <asm/smp_scu.h>
31 32
32#include "common.h" 33#include "common.h"
33#include "flowctrl.h"
34#include "iomap.h" 34#include "iomap.h"
35#include "reset.h" 35#include "reset.h"
36 36
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index b0f48a3946fa..1ad5719779b0 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -27,6 +27,7 @@
27#include <linux/spinlock.h> 27#include <linux/spinlock.h>
28#include <linux/suspend.h> 28#include <linux/suspend.h>
29 29
30#include <soc/tegra/flowctrl.h>
30#include <soc/tegra/fuse.h> 31#include <soc/tegra/fuse.h>
31#include <soc/tegra/pm.h> 32#include <soc/tegra/pm.h>
32#include <soc/tegra/pmc.h> 33#include <soc/tegra/pmc.h>
@@ -38,7 +39,6 @@
38#include <asm/suspend.h> 39#include <asm/suspend.h>
39#include <asm/tlbflush.h> 40#include <asm/tlbflush.h>
40 41
41#include "flowctrl.h"
42#include "iomap.h" 42#include "iomap.h"
43#include "pm.h" 43#include "pm.h"
44#include "reset.h" 44#include "reset.h"
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index e3070fdab80b..805f306fa6f7 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -17,12 +17,12 @@
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/linkage.h> 18#include <linux/linkage.h>
19 19
20#include <soc/tegra/flowctrl.h>
20#include <soc/tegra/fuse.h> 21#include <soc/tegra/fuse.h>
21 22
22#include <asm/asm-offsets.h> 23#include <asm/asm-offsets.h>
23#include <asm/cache.h> 24#include <asm/cache.h>
24 25
25#include "flowctrl.h"
26#include "iomap.h" 26#include "iomap.h"
27#include "reset.h" 27#include "reset.h"
28#include "sleep.h" 28#include "sleep.h"
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index f5d19667484e..5c8e638ee51a 100644
--- a/arch/arm/mach-tegra/sleep-tegra20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -20,6 +20,8 @@
20 20
21#include <linux/linkage.h> 21#include <linux/linkage.h>
22 22
23#include <soc/tegra/flowctrl.h>
24
23#include <asm/assembler.h> 25#include <asm/assembler.h>
24#include <asm/proc-fns.h> 26#include <asm/proc-fns.h>
25#include <asm/cp15.h> 27#include <asm/cp15.h>
@@ -27,7 +29,6 @@
27 29
28#include "irammap.h" 30#include "irammap.h"
29#include "sleep.h" 31#include "sleep.h"
30#include "flowctrl.h"
31 32
32#define EMC_CFG 0xc 33#define EMC_CFG 0xc
33#define EMC_ADR_CFG 0x10 34#define EMC_ADR_CFG 0x10
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index 16e5ff03383c..dd4a67dabd91 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -16,13 +16,13 @@
16 16
17#include <linux/linkage.h> 17#include <linux/linkage.h>
18 18
19#include <soc/tegra/flowctrl.h>
19#include <soc/tegra/fuse.h> 20#include <soc/tegra/fuse.h>
20 21
21#include <asm/asm-offsets.h> 22#include <asm/asm-offsets.h>
22#include <asm/assembler.h> 23#include <asm/assembler.h>
23#include <asm/cache.h> 24#include <asm/cache.h>
24 25
25#include "flowctrl.h"
26#include "irammap.h" 26#include "irammap.h"
27#include "sleep.h" 27#include "sleep.h"
28 28
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index f024a5109e8e..5e3496753df1 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -30,8 +30,6 @@
30#include <asm/hardware/cache-l2x0.h> 30#include <asm/hardware/cache-l2x0.h>
31 31
32#include "iomap.h" 32#include "iomap.h"
33
34#include "flowctrl.h"
35#include "sleep.h" 33#include "sleep.h"
36 34
37#define CLK_RESET_CCLK_BURST 0x20 35#define CLK_RESET_CCLK_BURST 0x20
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index e01cbca196b5..649e9e8c7bcc 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -48,7 +48,6 @@
48#include "board.h" 48#include "board.h"
49#include "common.h" 49#include "common.h"
50#include "cpuidle.h" 50#include "cpuidle.h"
51#include "flowctrl.h"
52#include "iomap.h" 51#include "iomap.h"
53#include "irq.h" 52#include "irq.h"
54#include "pm.h" 53#include "pm.h"
@@ -75,7 +74,6 @@ static void __init tegra_init_early(void)
75{ 74{
76 of_register_trusted_foundations(); 75 of_register_trusted_foundations();
77 tegra_cpu_reset_handler_init(); 76 tegra_cpu_reset_handler_init();
78 tegra_flowctrl_init();
79} 77}
80 78
81static void __init tegra_dt_init_irq(void) 79static 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
index 3cfb024ccd70..000000000000
--- a/arch/arm/plat-versatile/include/plat/clock.h
+++ /dev/null
@@ -1,15 +0,0 @@
1#ifndef PLAT_CLOCK_H
2#define PLAT_CLOCK_H
3
4#include <asm/hardware/icst.h>
5
6struct clk_ops {
7 long (*round)(struct clk *, unsigned long);
8 int (*set)(struct clk *, unsigned long);
9 void (*setvco)(struct clk *, struct icst_vco);
10};
11
12int icst_clk_set(struct clk *, unsigned long);
13long icst_clk_round(struct clk *, unsigned long);
14
15#endif
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index ff6cb9e4c381..de3eaf051697 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -518,6 +518,15 @@ config PATA_BF54X
518 518
519 If unsure, say N. 519 If unsure, say N.
520 520
521config PATA_BK3710
522 tristate "Palmchip BK3710 PATA support"
523 depends on ARCH_DAVINCI
524 help
525 This option enables support for the integrated IDE controller on
526 the TI DaVinci SoC.
527
528 If unsure, say N.
529
521config PATA_CMD64X 530config PATA_CMD64X
522 tristate "CMD64x PATA support" 531 tristate "CMD64x PATA support"
523 depends on PCI 532 depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 3048cc100a46..cd931a5eba92 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_PATA_ARTOP) += pata_artop.o
51obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o 51obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o
52obj-$(CONFIG_PATA_ATP867X) += pata_atp867x.o 52obj-$(CONFIG_PATA_ATP867X) += pata_atp867x.o
53obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o 53obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o
54obj-$(CONFIG_PATA_BK3710) += pata_bk3710.o
54obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o 55obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o
55obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o 56obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o
56obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o 57obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o
diff --git a/drivers/ata/pata_bk3710.c b/drivers/ata/pata_bk3710.c
new file mode 100644
index 000000000000..6c3bd5fae3e4
--- /dev/null
+++ b/drivers/ata/pata_bk3710.c
@@ -0,0 +1,382 @@
1/*
2 * Palmchip BK3710 PATA controller driver
3 *
4 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 *
7 * Based on palm_bk3710.c:
8 *
9 * Copyright (C) 2006 Texas Instruments.
10 * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
11 *
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file "COPYING" in the main directory of this archive
14 * for more details.
15 */
16
17#include <linux/ata.h>
18#include <linux/clk.h>
19#include <linux/delay.h>
20#include <linux/init.h>
21#include <linux/ioport.h>
22#include <linux/kernel.h>
23#include <linux/libata.h>
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/types.h>
27
28#define DRV_NAME "pata_bk3710"
29
30#define BK3710_TF_OFFSET 0x1F0
31#define BK3710_CTL_OFFSET 0x3F6
32
33#define BK3710_BMISP 0x02
34#define BK3710_IDETIMP 0x40
35#define BK3710_UDMACTL 0x48
36#define BK3710_MISCCTL 0x50
37#define BK3710_REGSTB 0x54
38#define BK3710_REGRCVR 0x58
39#define BK3710_DATSTB 0x5C
40#define BK3710_DATRCVR 0x60
41#define BK3710_DMASTB 0x64
42#define BK3710_DMARCVR 0x68
43#define BK3710_UDMASTB 0x6C
44#define BK3710_UDMATRP 0x70
45#define BK3710_UDMAENV 0x74
46#define BK3710_IORDYTMP 0x78
47
48static struct scsi_host_template pata_bk3710_sht = {
49 ATA_BMDMA_SHT(DRV_NAME),
50};
51
52static unsigned int ideclk_period; /* in nanoseconds */
53
54struct pata_bk3710_udmatiming {
55 unsigned int rptime; /* tRP -- Ready to pause time (nsec) */
56 unsigned int cycletime; /* tCYCTYP2/2 -- avg Cycle Time (nsec) */
57 /* tENV is always a minimum of 20 nsec */
58};
59
60static const struct pata_bk3710_udmatiming pata_bk3710_udmatimings[6] = {
61 { 160, 240 / 2 }, /* UDMA Mode 0 */
62 { 125, 160 / 2 }, /* UDMA Mode 1 */
63 { 100, 120 / 2 }, /* UDMA Mode 2 */
64 { 100, 90 / 2 }, /* UDMA Mode 3 */
65 { 100, 60 / 2 }, /* UDMA Mode 4 */
66 { 85, 40 / 2 }, /* UDMA Mode 5 */
67};
68
69static void pata_bk3710_setudmamode(void __iomem *base, unsigned int dev,
70 unsigned int mode)
71{
72 u32 val32;
73 u16 val16;
74 u8 tenv, trp, t0;
75
76 /* DMA Data Setup */
77 t0 = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].cycletime,
78 ideclk_period) - 1;
79 tenv = DIV_ROUND_UP(20, ideclk_period) - 1;
80 trp = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].rptime,
81 ideclk_period) - 1;
82
83 /* udmastb Ultra DMA Access Strobe Width */
84 val32 = ioread32(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
85 val32 |= t0 << (dev ? 8 : 0);
86 iowrite32(val32, base + BK3710_UDMASTB);
87
88 /* udmatrp Ultra DMA Ready to Pause Time */
89 val32 = ioread32(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
90 val32 |= trp << (dev ? 8 : 0);
91 iowrite32(val32, base + BK3710_UDMATRP);
92
93 /* udmaenv Ultra DMA envelop Time */
94 val32 = ioread32(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
95 val32 |= tenv << (dev ? 8 : 0);
96 iowrite32(val32, base + BK3710_UDMAENV);
97
98 /* Enable UDMA for Device */
99 val16 = ioread16(base + BK3710_UDMACTL) | (1 << dev);
100 iowrite16(val16, base + BK3710_UDMACTL);
101}
102
103static void pata_bk3710_setmwdmamode(void __iomem *base, unsigned int dev,
104 unsigned short min_cycle,
105 unsigned int mode)
106{
107 const struct ata_timing *t;
108 int cycletime;
109 u32 val32;
110 u16 val16;
111 u8 td, tkw, t0;
112
113 t = ata_timing_find_mode(mode);
114 cycletime = max_t(int, t->cycle, min_cycle);
115
116 /* DMA Data Setup */
117 t0 = DIV_ROUND_UP(cycletime, ideclk_period);
118 td = DIV_ROUND_UP(t->active, ideclk_period);
119 tkw = t0 - td - 1;
120 td--;
121
122 val32 = ioread32(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
123 val32 |= td << (dev ? 8 : 0);
124 iowrite32(val32, base + BK3710_DMASTB);
125
126 val32 = ioread32(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
127 val32 |= tkw << (dev ? 8 : 0);
128 iowrite32(val32, base + BK3710_DMARCVR);
129
130 /* Disable UDMA for Device */
131 val16 = ioread16(base + BK3710_UDMACTL) & ~(1 << dev);
132 iowrite16(val16, base + BK3710_UDMACTL);
133}
134
135static void pata_bk3710_set_dmamode(struct ata_port *ap,
136 struct ata_device *adev)
137{
138 void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
139 int is_slave = adev->devno;
140 const u8 xferspeed = adev->dma_mode;
141
142 if (xferspeed >= XFER_UDMA_0)
143 pata_bk3710_setudmamode(base, is_slave,
144 xferspeed - XFER_UDMA_0);
145 else
146 pata_bk3710_setmwdmamode(base, is_slave,
147 adev->id[ATA_ID_EIDE_DMA_MIN],
148 xferspeed);
149}
150
151static void pata_bk3710_setpiomode(void __iomem *base, struct ata_device *pair,
152 unsigned int dev, unsigned int cycletime,
153 unsigned int mode)
154{
155 const struct ata_timing *t;
156 u32 val32;
157 u8 t2, t2i, t0;
158
159 t = ata_timing_find_mode(XFER_PIO_0 + mode);
160
161 /* PIO Data Setup */
162 t0 = DIV_ROUND_UP(cycletime, ideclk_period);
163 t2 = DIV_ROUND_UP(t->active, ideclk_period);
164
165 t2i = t0 - t2 - 1;
166 t2--;
167
168 val32 = ioread32(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
169 val32 |= t2 << (dev ? 8 : 0);
170 iowrite32(val32, base + BK3710_DATSTB);
171
172 val32 = ioread32(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
173 val32 |= t2i << (dev ? 8 : 0);
174 iowrite32(val32, base + BK3710_DATRCVR);
175
176 /* FIXME: this is broken also in the old driver */
177 if (pair) {
178 u8 mode2 = pair->pio_mode - XFER_PIO_0;
179
180 if (mode2 < mode)
181 mode = mode2;
182 }
183
184 /* TASKFILE Setup */
185 t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
186 t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
187
188 t2i = t0 - t2 - 1;
189 t2--;
190
191 val32 = ioread32(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
192 val32 |= t2 << (dev ? 8 : 0);
193 iowrite32(val32, base + BK3710_REGSTB);
194
195 val32 = ioread32(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
196 val32 |= t2i << (dev ? 8 : 0);
197 iowrite32(val32, base + BK3710_REGRCVR);
198}
199
200static void pata_bk3710_set_piomode(struct ata_port *ap,
201 struct ata_device *adev)
202{
203 void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
204 struct ata_device *pair = ata_dev_pair(adev);
205 const struct ata_timing *t = ata_timing_find_mode(adev->pio_mode);
206 const u16 *id = adev->id;
207 unsigned int cycle_time = 0;
208 int is_slave = adev->devno;
209 const u8 pio = adev->pio_mode - XFER_PIO_0;
210
211 if (id[ATA_ID_FIELD_VALID] & 2) {
212 if (ata_id_has_iordy(id))
213 cycle_time = id[ATA_ID_EIDE_PIO_IORDY];
214 else
215 cycle_time = id[ATA_ID_EIDE_PIO];
216
217 /* conservative "downgrade" for all pre-ATA2 drives */
218 if (pio < 3 && cycle_time < t->cycle)
219 cycle_time = 0; /* use standard timing */
220 }
221
222 if (!cycle_time)
223 cycle_time = t->cycle;
224
225 pata_bk3710_setpiomode(base, pair, is_slave, cycle_time, pio);
226}
227
228static void pata_bk3710_chipinit(void __iomem *base)
229{
230 /*
231 * REVISIT: the ATA reset signal needs to be managed through a
232 * GPIO, which means it should come from platform_data. Until
233 * we get and use such information, we have to trust that things
234 * have been reset before we get here.
235 */
236
237 /*
238 * Program the IDETIMP Register Value based on the following assumptions
239 *
240 * (ATA_IDETIMP_IDEEN , ENABLE ) |
241 * (ATA_IDETIMP_PREPOST1 , DISABLE) |
242 * (ATA_IDETIMP_PREPOST0 , DISABLE) |
243 *
244 * DM6446 silicon rev 2.1 and earlier have no observed net benefit
245 * from enabling prefetch/postwrite.
246 */
247 iowrite16(BIT(15), base + BK3710_IDETIMP);
248
249 /*
250 * UDMACTL Ultra-ATA DMA Control
251 * (ATA_UDMACTL_UDMAP1 , 0 ) |
252 * (ATA_UDMACTL_UDMAP0 , 0 )
253 *
254 */
255 iowrite16(0, base + BK3710_UDMACTL);
256
257 /*
258 * MISCCTL Miscellaneous Conrol Register
259 * (ATA_MISCCTL_HWNHLD1P , 1 cycle)
260 * (ATA_MISCCTL_HWNHLD0P , 1 cycle)
261 * (ATA_MISCCTL_TIMORIDE , 1)
262 */
263 iowrite32(0x001, base + BK3710_MISCCTL);
264
265 /*
266 * IORDYTMP IORDY Timer for Primary Register
267 * (ATA_IORDYTMP_IORDYTMP , DISABLE)
268 */
269 iowrite32(0, base + BK3710_IORDYTMP);
270
271 /*
272 * Configure BMISP Register
273 * (ATA_BMISP_DMAEN1 , DISABLE ) |
274 * (ATA_BMISP_DMAEN0 , DISABLE ) |
275 * (ATA_BMISP_IORDYINT , CLEAR) |
276 * (ATA_BMISP_INTRSTAT , CLEAR) |
277 * (ATA_BMISP_DMAERROR , CLEAR)
278 */
279 iowrite16(0xE, base + BK3710_BMISP);
280
281 pata_bk3710_setpiomode(base, NULL, 0, 600, 0);
282 pata_bk3710_setpiomode(base, NULL, 1, 600, 0);
283}
284
285static struct ata_port_operations pata_bk3710_ports_ops = {
286 .inherits = &ata_bmdma_port_ops,
287 .cable_detect = ata_cable_80wire,
288
289 .set_piomode = pata_bk3710_set_piomode,
290 .set_dmamode = pata_bk3710_set_dmamode,
291};
292
293static int __init pata_bk3710_probe(struct platform_device *pdev)
294{
295 struct clk *clk;
296 struct resource *mem;
297 struct ata_host *host;
298 struct ata_port *ap;
299 void __iomem *base;
300 unsigned long rate;
301 int irq;
302
303 clk = devm_clk_get(&pdev->dev, NULL);
304 if (IS_ERR(clk))
305 return -ENODEV;
306
307 clk_enable(clk);
308 rate = clk_get_rate(clk);
309 if (!rate)
310 return -EINVAL;
311
312 /* NOTE: round *down* to meet minimum timings; we count in clocks */
313 ideclk_period = 1000000000UL / rate;
314
315 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
316
317 irq = platform_get_irq(pdev, 0);
318 if (irq < 0) {
319 pr_err(DRV_NAME ": failed to get IRQ resource\n");
320 return irq;
321 }
322
323 base = devm_ioremap_resource(&pdev->dev, mem);
324 if (IS_ERR(base))
325 return PTR_ERR(base);
326
327 /* configure the Palmchip controller */
328 pata_bk3710_chipinit(base);
329
330 /* allocate host */
331 host = ata_host_alloc(&pdev->dev, 1);
332 if (!host)
333 return -ENOMEM;
334 ap = host->ports[0];
335
336 ap->ops = &pata_bk3710_ports_ops;
337 ap->pio_mask = ATA_PIO4;
338 ap->mwdma_mask = ATA_MWDMA2;
339 ap->udma_mask = rate < 100000000 ? ATA_UDMA4 : ATA_UDMA5;
340 ap->flags |= ATA_FLAG_SLAVE_POSS;
341
342 ap->ioaddr.data_addr = base + BK3710_TF_OFFSET;
343 ap->ioaddr.error_addr = base + BK3710_TF_OFFSET + 1;
344 ap->ioaddr.feature_addr = base + BK3710_TF_OFFSET + 1;
345 ap->ioaddr.nsect_addr = base + BK3710_TF_OFFSET + 2;
346 ap->ioaddr.lbal_addr = base + BK3710_TF_OFFSET + 3;
347 ap->ioaddr.lbam_addr = base + BK3710_TF_OFFSET + 4;
348 ap->ioaddr.lbah_addr = base + BK3710_TF_OFFSET + 5;
349 ap->ioaddr.device_addr = base + BK3710_TF_OFFSET + 6;
350 ap->ioaddr.status_addr = base + BK3710_TF_OFFSET + 7;
351 ap->ioaddr.command_addr = base + BK3710_TF_OFFSET + 7;
352
353 ap->ioaddr.altstatus_addr = base + BK3710_CTL_OFFSET;
354 ap->ioaddr.ctl_addr = base + BK3710_CTL_OFFSET;
355
356 ap->ioaddr.bmdma_addr = base;
357
358 ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx",
359 (unsigned long)base + BK3710_TF_OFFSET,
360 (unsigned long)base + BK3710_CTL_OFFSET);
361
362 /* activate */
363 return ata_host_activate(host, irq, ata_sff_interrupt, 0,
364 &pata_bk3710_sht);
365}
366
367/* work with hotplug and coldplug */
368MODULE_ALIAS("platform:palm_bk3710");
369
370static struct platform_driver pata_bk3710_driver = {
371 .driver = {
372 .name = "palm_bk3710",
373 },
374};
375
376static int __init pata_bk3710_init(void)
377{
378 return platform_driver_probe(&pata_bk3710_driver, pata_bk3710_probe);
379}
380
381module_init(pata_bk3710_init);
382MODULE_LICENSE("GPL");
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index ad196427b4f2..da49a8383dc3 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1636,8 +1636,6 @@ static struct generic_pm_domain *genpd_xlate_simple(
1636 struct of_phandle_args *genpdspec, 1636 struct of_phandle_args *genpdspec,
1637 void *data) 1637 void *data)
1638{ 1638{
1639 if (genpdspec->args_count != 0)
1640 return ERR_PTR(-EINVAL);
1641 return data; 1639 return data;
1642} 1640}
1643 1641
diff --git a/drivers/base/soc.c b/drivers/base/soc.c
index dc26e5949a32..909dedae4c4e 100644
--- a/drivers/base/soc.c
+++ b/drivers/base/soc.c
@@ -109,15 +109,18 @@ static void soc_release(struct device *dev)
109 kfree(soc_dev); 109 kfree(soc_dev);
110} 110}
111 111
112static struct soc_device_attribute *early_soc_dev_attr;
113
112struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr) 114struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr)
113{ 115{
114 struct soc_device *soc_dev; 116 struct soc_device *soc_dev;
115 int ret; 117 int ret;
116 118
117 if (!soc_bus_type.p) { 119 if (!soc_bus_type.p) {
118 ret = bus_register(&soc_bus_type); 120 if (early_soc_dev_attr)
119 if (ret) 121 return ERR_PTR(-EBUSY);
120 goto out1; 122 early_soc_dev_attr = soc_dev_attr;
123 return NULL;
121 } 124 }
122 125
123 soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL); 126 soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
@@ -159,45 +162,53 @@ void soc_device_unregister(struct soc_device *soc_dev)
159 ida_simple_remove(&soc_ida, soc_dev->soc_dev_num); 162 ida_simple_remove(&soc_ida, soc_dev->soc_dev_num);
160 163
161 device_unregister(&soc_dev->dev); 164 device_unregister(&soc_dev->dev);
165 early_soc_dev_attr = NULL;
162} 166}
163 167
164static int __init soc_bus_register(void) 168static int __init soc_bus_register(void)
165{ 169{
166 if (soc_bus_type.p) 170 int ret;
167 return 0;
168 171
169 return bus_register(&soc_bus_type); 172 ret = bus_register(&soc_bus_type);
173 if (ret)
174 return ret;
175
176 if (early_soc_dev_attr)
177 return PTR_ERR(soc_device_register(early_soc_dev_attr));
178
179 return 0;
170} 180}
171core_initcall(soc_bus_register); 181core_initcall(soc_bus_register);
172 182
173static int soc_device_match_one(struct device *dev, void *arg) 183static int soc_device_match_attr(const struct soc_device_attribute *attr,
184 const struct soc_device_attribute *match)
174{ 185{
175 struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
176 const struct soc_device_attribute *match = arg;
177
178 if (match->machine && 186 if (match->machine &&
179 (!soc_dev->attr->machine || 187 (!attr->machine || !glob_match(match->machine, attr->machine)))
180 !glob_match(match->machine, soc_dev->attr->machine)))
181 return 0; 188 return 0;
182 189
183 if (match->family && 190 if (match->family &&
184 (!soc_dev->attr->family || 191 (!attr->family || !glob_match(match->family, attr->family)))
185 !glob_match(match->family, soc_dev->attr->family)))
186 return 0; 192 return 0;
187 193
188 if (match->revision && 194 if (match->revision &&
189 (!soc_dev->attr->revision || 195 (!attr->revision || !glob_match(match->revision, attr->revision)))
190 !glob_match(match->revision, soc_dev->attr->revision)))
191 return 0; 196 return 0;
192 197
193 if (match->soc_id && 198 if (match->soc_id &&
194 (!soc_dev->attr->soc_id || 199 (!attr->soc_id || !glob_match(match->soc_id, attr->soc_id)))
195 !glob_match(match->soc_id, soc_dev->attr->soc_id)))
196 return 0; 200 return 0;
197 201
198 return 1; 202 return 1;
199} 203}
200 204
205static int soc_device_match_one(struct device *dev, void *arg)
206{
207 struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
208
209 return soc_device_match_attr(soc_dev->attr, arg);
210}
211
201/* 212/*
202 * soc_device_match - identify the SoC in the machine 213 * soc_device_match - identify the SoC in the machine
203 * @matches: zero-terminated array of possible matches 214 * @matches: zero-terminated array of possible matches
@@ -230,6 +241,11 @@ const struct soc_device_attribute *soc_device_match(
230 break; 241 break;
231 ret = bus_for_each_dev(&soc_bus_type, NULL, (void *)matches, 242 ret = bus_for_each_dev(&soc_bus_type, NULL, (void *)matches,
232 soc_device_match_one); 243 soc_device_match_one);
244 if (ret < 0 && early_soc_dev_attr)
245 ret = soc_device_match_attr(early_soc_dev_attr,
246 matches);
247 if (ret < 0)
248 return NULL;
233 if (!ret) 249 if (!ret)
234 matches++; 250 matches++;
235 else 251 else
diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig
index a6da2aa09f83..8aa875f25239 100644
--- a/drivers/clk/versatile/Kconfig
+++ b/drivers/clk/versatile/Kconfig
@@ -1,3 +1,6 @@
1config ICST
2 bool
3
1config COMMON_CLK_VERSATILE 4config COMMON_CLK_VERSATILE
2 bool "Clock driver for ARM Reference designs" 5 bool "Clock driver for ARM Reference designs"
3 depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \ 6 depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
index 8ff03744fe98..794130402c8d 100644
--- a/drivers/clk/versatile/Makefile
+++ b/drivers/clk/versatile/Makefile
@@ -1,5 +1,5 @@
1# Makefile for Versatile-specific clocks 1# Makefile for Versatile-specific clocks
2obj-$(CONFIG_ICST) += clk-icst.o clk-versatile.o 2obj-$(CONFIG_ICST) += icst.o clk-icst.o clk-versatile.o
3obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o 3obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
4obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o 4obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o
5obj-$(CONFIG_CLK_SP810) += clk-sp810.o 5obj-$(CONFIG_CLK_SP810) += clk-sp810.o
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
index 4faa94440779..09fbe66f1f11 100644
--- a/drivers/clk/versatile/clk-icst.c
+++ b/drivers/clk/versatile/clk-icst.c
@@ -22,6 +22,7 @@
22#include <linux/regmap.h> 22#include <linux/regmap.h>
23#include <linux/mfd/syscon.h> 23#include <linux/mfd/syscon.h>
24 24
25#include "icst.h"
25#include "clk-icst.h" 26#include "clk-icst.h"
26 27
27/* Magic unlocking token used on all Versatile boards */ 28/* Magic unlocking token used on all Versatile boards */
diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h
index 04e6f0aef588..5add02ebec5d 100644
--- a/drivers/clk/versatile/clk-icst.h
+++ b/drivers/clk/versatile/clk-icst.h
@@ -1,5 +1,3 @@
1#include <asm/hardware/icst.h>
2
3/** 1/**
4 * struct clk_icst_desc - descriptor for the ICST VCO 2 * struct clk_icst_desc - descriptor for the ICST VCO
5 * @params: ICST parameters 3 * @params: ICST parameters
diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c
index 74c3216dbb00..401558bfc409 100644
--- a/drivers/clk/versatile/clk-impd1.c
+++ b/drivers/clk/versatile/clk-impd1.c
@@ -12,6 +12,7 @@
12#include <linux/io.h> 12#include <linux/io.h>
13#include <linux/platform_data/clk-integrator.h> 13#include <linux/platform_data/clk-integrator.h>
14 14
15#include "icst.h"
15#include "clk-icst.h" 16#include "clk-icst.h"
16 17
17#define IMPD1_OSC1 0x00 18#define IMPD1_OSC1 0x00
diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c
index c56efc70ac16..6fdfee3232f4 100644
--- a/drivers/clk/versatile/clk-realview.c
+++ b/drivers/clk/versatile/clk-realview.c
@@ -11,6 +11,7 @@
11#include <linux/io.h> 11#include <linux/io.h>
12#include <linux/clk-provider.h> 12#include <linux/clk-provider.h>
13 13
14#include "icst.h"
14#include "clk-icst.h" 15#include "clk-icst.h"
15 16
16#define REALVIEW_SYS_OSC0_OFFSET 0x0C 17#define REALVIEW_SYS_OSC0_OFFSET 0x0C
diff --git a/drivers/clk/versatile/clk-versatile.c b/drivers/clk/versatile/clk-versatile.c
index a89a927567e0..d6960de64d4a 100644
--- a/drivers/clk/versatile/clk-versatile.c
+++ b/drivers/clk/versatile/clk-versatile.c
@@ -12,6 +12,7 @@
12#include <linux/of.h> 12#include <linux/of.h>
13#include <linux/of_address.h> 13#include <linux/of_address.h>
14 14
15#include "icst.h"
15#include "clk-icst.h" 16#include "clk-icst.h"
16 17
17#define INTEGRATOR_HDR_LOCK_OFFSET 0x14 18#define INTEGRATOR_HDR_LOCK_OFFSET 0x14
diff --git a/arch/arm/common/icst.c b/drivers/clk/versatile/icst.c
index d7ed252708c5..de2af63a3aad 100644
--- a/arch/arm/common/icst.c
+++ b/drivers/clk/versatile/icst.c
@@ -17,7 +17,7 @@
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <asm/div64.h> 19#include <asm/div64.h>
20#include <asm/hardware/icst.h> 20#include "icst.h"
21 21
22/* 22/*
23 * Divisors for each OD setting. 23 * Divisors for each OD setting.
diff --git a/arch/arm/include/asm/hardware/icst.h b/drivers/clk/versatile/icst.h
index 794220b087d2..7519bba03b04 100644
--- a/arch/arm/include/asm/hardware/icst.h
+++ b/drivers/clk/versatile/icst.h
@@ -1,6 +1,4 @@
1/* 1/*
2 * arch/arm/include/asm/hardware/icst.h
3 *
4 * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. 2 * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
5 * 3 *
6 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
@@ -11,8 +9,8 @@
11 * clock generators. See http://www.idt.com/ for more information 9 * clock generators. See http://www.idt.com/ for more information
12 * on these devices. 10 * on these devices.
13 */ 11 */
14#ifndef ASMARM_HARDWARE_ICST_H 12#ifndef ICST_H
15#define ASMARM_HARDWARE_ICST_H 13#define ICST_H
16 14
17struct icst_params { 15struct icst_params {
18 unsigned long ref; 16 unsigned long ref;
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 9ad0b1934be9..f6cfc31d34c7 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -538,7 +538,7 @@ static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len,
538 msg->tx_len = tx_len; 538 msg->tx_len = tx_len;
539 msg->rx_buf = rx_buf; 539 msg->rx_buf = rx_buf;
540 msg->rx_len = rx_len; 540 msg->rx_len = rx_len;
541 init_completion(&msg->done); 541 reinit_completion(&msg->done);
542 542
543 ret = mbox_send_message(scpi_chan->chan, msg); 543 ret = mbox_send_message(scpi_chan->chan, msg);
544 if (ret < 0 || !rx_buf) 544 if (ret < 0 || !rx_buf)
@@ -872,8 +872,11 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
872 return -ENOMEM; 872 return -ENOMEM;
873 873
874 ch->xfers = xfers; 874 ch->xfers = xfers;
875 for (i = 0; i < MAX_SCPI_XFERS; i++, xfers++) 875 for (i = 0; i < MAX_SCPI_XFERS; i++, xfers++) {
876 init_completion(&xfers->done);
876 list_add_tail(&xfers->node, &ch->xfers_list); 877 list_add_tail(&xfers->node, &ch->xfers_list);
878 }
879
877 return 0; 880 return 0;
878} 881}
879 882
diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
index b0d254930ed3..ff204421117b 100644
--- a/drivers/firmware/meson/meson_sm.c
+++ b/drivers/firmware/meson/meson_sm.c
@@ -127,6 +127,7 @@ EXPORT_SYMBOL(meson_sm_call);
127 * meson_sm_call_read - retrieve data from secure-monitor 127 * meson_sm_call_read - retrieve data from secure-monitor
128 * 128 *
129 * @buffer: Buffer to store the retrieved data 129 * @buffer: Buffer to store the retrieved data
130 * @bsize: Size of the buffer
130 * @cmd_index: Index of the SMC32 function ID 131 * @cmd_index: Index of the SMC32 function ID
131 * @arg0: SMC32 Argument 0 132 * @arg0: SMC32 Argument 0
132 * @arg1: SMC32 Argument 1 133 * @arg1: SMC32 Argument 1
@@ -135,11 +136,14 @@ EXPORT_SYMBOL(meson_sm_call);
135 * @arg4: SMC32 Argument 4 136 * @arg4: SMC32 Argument 4
136 * 137 *
137 * Return: size of read data on success, a negative value on error 138 * Return: size of read data on success, a negative value on error
139 * When 0 is returned there is no guarantee about the amount of
140 * data read and bsize bytes are copied in buffer.
138 */ 141 */
139int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0, 142int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
140 u32 arg1, u32 arg2, u32 arg3, u32 arg4) 143 u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
141{ 144{
142 u32 size; 145 u32 size;
146 int ret;
143 147
144 if (!fw.chip) 148 if (!fw.chip)
145 return -ENOENT; 149 return -ENOENT;
@@ -147,16 +151,24 @@ int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0,
147 if (!fw.chip->cmd_shmem_out_base) 151 if (!fw.chip->cmd_shmem_out_base)
148 return -EINVAL; 152 return -EINVAL;
149 153
154 if (bsize > fw.chip->shmem_size)
155 return -EINVAL;
156
150 if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0) 157 if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
151 return -EINVAL; 158 return -EINVAL;
152 159
153 if (!size || size > fw.chip->shmem_size) 160 if (size > bsize)
154 return -EINVAL; 161 return -EINVAL;
155 162
163 ret = size;
164
165 if (!size)
166 size = bsize;
167
156 if (buffer) 168 if (buffer)
157 memcpy(buffer, fw.sm_shmem_out_base, size); 169 memcpy(buffer, fw.sm_shmem_out_base, size);
158 170
159 return size; 171 return ret;
160} 172}
161EXPORT_SYMBOL(meson_sm_call_read); 173EXPORT_SYMBOL(meson_sm_call_read);
162 174
diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 8ad226c60374..93e3b96b6dfa 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -578,3 +578,21 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
578 578
579 return ret ? : le32_to_cpu(scm_ret); 579 return ret ? : le32_to_cpu(scm_ret);
580} 580}
581
582int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id,
583 u32 spare)
584{
585 return -ENODEV;
586}
587
588int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
589 size_t *size)
590{
591 return -ENODEV;
592}
593
594int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
595 u32 spare)
596{
597 return -ENODEV;
598}
diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c
index c9332590e8c6..6e6d561708e2 100644
--- a/drivers/firmware/qcom_scm-64.c
+++ b/drivers/firmware/qcom_scm-64.c
@@ -381,3 +381,61 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
381 381
382 return ret ? : res.a1; 382 return ret ? : res.a1;
383} 383}
384
385int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare)
386{
387 struct qcom_scm_desc desc = {0};
388 struct arm_smccc_res res;
389 int ret;
390
391 desc.args[0] = device_id;
392 desc.args[1] = spare;
393 desc.arginfo = QCOM_SCM_ARGS(2);
394
395 ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, QCOM_SCM_RESTORE_SEC_CFG,
396 &desc, &res);
397
398 return ret ? : res.a1;
399}
400
401int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
402 size_t *size)
403{
404 struct qcom_scm_desc desc = {0};
405 struct arm_smccc_res res;
406 int ret;
407
408 desc.args[0] = spare;
409 desc.arginfo = QCOM_SCM_ARGS(1);
410
411 ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
412 QCOM_SCM_IOMMU_SECURE_PTBL_SIZE, &desc, &res);
413
414 if (size)
415 *size = res.a1;
416
417 return ret ? : res.a2;
418}
419
420int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
421 u32 spare)
422{
423 struct qcom_scm_desc desc = {0};
424 struct arm_smccc_res res;
425 int ret;
426
427 desc.args[0] = addr;
428 desc.args[1] = size;
429 desc.args[2] = spare;
430 desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL,
431 QCOM_SCM_VAL);
432
433 ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
434 QCOM_SCM_IOMMU_SECURE_PTBL_INIT, &desc, &res);
435
436 /* the pg table has been initialized already, ignore the error */
437 if (ret == -EPERM)
438 ret = 0;
439
440 return ret;
441}
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index d987bcc7489d..bb16510d75ba 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -315,6 +315,24 @@ static const struct reset_control_ops qcom_scm_pas_reset_ops = {
315 .deassert = qcom_scm_pas_reset_deassert, 315 .deassert = qcom_scm_pas_reset_deassert,
316}; 316};
317 317
318int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
319{
320 return __qcom_scm_restore_sec_cfg(__scm->dev, device_id, spare);
321}
322EXPORT_SYMBOL(qcom_scm_restore_sec_cfg);
323
324int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size)
325{
326 return __qcom_scm_iommu_secure_ptbl_size(__scm->dev, spare, size);
327}
328EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_size);
329
330int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
331{
332 return __qcom_scm_iommu_secure_ptbl_init(__scm->dev, addr, size, spare);
333}
334EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init);
335
318/** 336/**
319 * qcom_scm_is_available() - Checks if SCM is available 337 * qcom_scm_is_available() - Checks if SCM is available
320 */ 338 */
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index 6a0f15469344..9bea691f30fb 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -85,4 +85,15 @@ static inline int qcom_scm_remap_error(int err)
85 return -EINVAL; 85 return -EINVAL;
86} 86}
87 87
88#define QCOM_SCM_SVC_MP 0xc
89#define QCOM_SCM_RESTORE_SEC_CFG 2
90extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id,
91 u32 spare);
92#define QCOM_SCM_IOMMU_SECURE_PTBL_SIZE 3
93#define QCOM_SCM_IOMMU_SECURE_PTBL_INIT 4
94extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
95 size_t *size);
96extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr,
97 u32 size, u32 spare);
98
88#endif 99#endif
diff --git a/drivers/nvmem/meson-efuse.c b/drivers/nvmem/meson-efuse.c
index f207c3b10482..70bfc9839bb2 100644
--- a/drivers/nvmem/meson-efuse.c
+++ b/drivers/nvmem/meson-efuse.c
@@ -27,7 +27,7 @@ static int meson_efuse_read(void *context, unsigned int offset,
27 u8 *buf = val; 27 u8 *buf = val;
28 int ret; 28 int ret;
29 29
30 ret = meson_sm_call_read(buf, SM_EFUSE_READ, offset, 30 ret = meson_sm_call_read(buf, bytes, SM_EFUSE_READ, offset,
31 bytes, 0, 0, 0); 31 bytes, 0, 0, 0);
32 if (ret < 0) 32 if (ret < 0)
33 return ret; 33 return ret;
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index f4cdfe94b9ec..d21c07ccc94e 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -14,6 +14,13 @@ menuconfig RESET_CONTROLLER
14 14
15if RESET_CONTROLLER 15if RESET_CONTROLLER
16 16
17config RESET_A10SR
18 tristate "Altera Arria10 System Resource Reset"
19 depends on MFD_ALTERA_A10SR
20 help
21 This option enables support for the external reset functions for
22 peripheral PHYs on the Altera Arria10 System Resource Chip.
23
17config RESET_ATH79 24config RESET_ATH79
18 bool "AR71xx Reset Driver" if COMPILE_TEST 25 bool "AR71xx Reset Driver" if COMPILE_TEST
19 default ATH79 26 default ATH79
@@ -27,6 +34,13 @@ config RESET_BERLIN
27 help 34 help
28 This enables the reset controller driver for Marvell Berlin SoCs. 35 This enables the reset controller driver for Marvell Berlin SoCs.
29 36
37config RESET_IMX7
38 bool "i.MX7 Reset Driver" if COMPILE_TEST
39 default SOC_IMX7D
40 select MFD_SYSCON
41 help
42 This enables the reset controller driver for i.MX7 SoCs.
43
30config RESET_LPC18XX 44config RESET_LPC18XX
31 bool "LPC18xx/43xx Reset Driver" if COMPILE_TEST 45 bool "LPC18xx/43xx Reset Driver" if COMPILE_TEST
32 default ARCH_LPC18XX 46 default ARCH_LPC18XX
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 2cd3f6c45165..02a74db94339 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -2,8 +2,10 @@ obj-y += core.o
2obj-y += hisilicon/ 2obj-y += hisilicon/
3obj-$(CONFIG_ARCH_STI) += sti/ 3obj-$(CONFIG_ARCH_STI) += sti/
4obj-$(CONFIG_ARCH_TEGRA) += tegra/ 4obj-$(CONFIG_ARCH_TEGRA) += tegra/
5obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
5obj-$(CONFIG_RESET_ATH79) += reset-ath79.o 6obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
6obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o 7obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
8obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
7obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o 9obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
8obj-$(CONFIG_RESET_MESON) += reset-meson.o 10obj-$(CONFIG_RESET_MESON) += reset-meson.o
9obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o 11obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
@@ -15,3 +17,4 @@ obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
15obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o 17obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
16obj-$(CONFIG_RESET_ZX2967) += reset-zx2967.o 18obj-$(CONFIG_RESET_ZX2967) += reset-zx2967.o
17obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o 19obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
20
diff --git a/drivers/reset/reset-a10sr.c b/drivers/reset/reset-a10sr.c
new file mode 100644
index 000000000000..37496bd27fa2
--- /dev/null
+++ b/drivers/reset/reset-a10sr.c
@@ -0,0 +1,138 @@
1/*
2 * Copyright Intel Corporation (C) 2017. All Rights Reserved
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Reset driver for Altera Arria10 MAX5 System Resource Chip
17 *
18 * Adapted from reset-socfpga.c
19 */
20
21#include <linux/err.h>
22#include <linux/mfd/altera-a10sr.h>
23#include <linux/module.h>
24#include <linux/of.h>
25#include <linux/platform_device.h>
26#include <linux/reset-controller.h>
27
28#include <dt-bindings/reset/altr,rst-mgr-a10sr.h>
29
30struct a10sr_reset {
31 struct reset_controller_dev rcdev;
32 struct regmap *regmap;
33};
34
35static inline struct a10sr_reset *to_a10sr_rst(struct reset_controller_dev *rc)
36{
37 return container_of(rc, struct a10sr_reset, rcdev);
38}
39
40static inline int a10sr_reset_shift(unsigned long id)
41{
42 switch (id) {
43 case A10SR_RESET_ENET_HPS:
44 return 1;
45 case A10SR_RESET_PCIE:
46 case A10SR_RESET_FILE:
47 case A10SR_RESET_BQSPI:
48 case A10SR_RESET_USB:
49 return id + 11;
50 default:
51 return -EINVAL;
52 }
53}
54
55static int a10sr_reset_update(struct reset_controller_dev *rcdev,
56 unsigned long id, bool assert)
57{
58 struct a10sr_reset *a10r = to_a10sr_rst(rcdev);
59 int offset = a10sr_reset_shift(id);
60 u8 mask = ALTR_A10SR_REG_BIT_MASK(offset);
61 int index = ALTR_A10SR_HPS_RST_REG + ALTR_A10SR_REG_OFFSET(offset);
62
63 return regmap_update_bits(a10r->regmap, index, mask, assert ? 0 : mask);
64}
65
66static int a10sr_reset_assert(struct reset_controller_dev *rcdev,
67 unsigned long id)
68{
69 return a10sr_reset_update(rcdev, id, true);
70}
71
72static int a10sr_reset_deassert(struct reset_controller_dev *rcdev,
73 unsigned long id)
74{
75 return a10sr_reset_update(rcdev, id, false);
76}
77
78static int a10sr_reset_status(struct reset_controller_dev *rcdev,
79 unsigned long id)
80{
81 int ret;
82 struct a10sr_reset *a10r = to_a10sr_rst(rcdev);
83 int offset = a10sr_reset_shift(id);
84 u8 mask = ALTR_A10SR_REG_BIT_MASK(offset);
85 int index = ALTR_A10SR_HPS_RST_REG + ALTR_A10SR_REG_OFFSET(offset);
86 unsigned int value;
87
88 ret = regmap_read(a10r->regmap, index, &value);
89 if (ret < 0)
90 return ret;
91
92 return !!(value & mask);
93}
94
95static const struct reset_control_ops a10sr_reset_ops = {
96 .assert = a10sr_reset_assert,
97 .deassert = a10sr_reset_deassert,
98 .status = a10sr_reset_status,
99};
100
101static int a10sr_reset_probe(struct platform_device *pdev)
102{
103 struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent);
104 struct a10sr_reset *a10r;
105
106 a10r = devm_kzalloc(&pdev->dev, sizeof(struct a10sr_reset),
107 GFP_KERNEL);
108 if (!a10r)
109 return -ENOMEM;
110
111 a10r->rcdev.owner = THIS_MODULE;
112 a10r->rcdev.nr_resets = A10SR_RESET_NUM;
113 a10r->rcdev.ops = &a10sr_reset_ops;
114 a10r->rcdev.of_node = pdev->dev.of_node;
115 a10r->regmap = a10sr->regmap;
116
117 platform_set_drvdata(pdev, a10r);
118
119 return devm_reset_controller_register(&pdev->dev, &a10r->rcdev);
120}
121
122static const struct of_device_id a10sr_reset_of_match[] = {
123 { .compatible = "altr,a10sr-reset" },
124 { },
125};
126MODULE_DEVICE_TABLE(of, a10sr_reset_of_match);
127
128static struct platform_driver a10sr_reset_driver = {
129 .probe = a10sr_reset_probe,
130 .driver = {
131 .name = "altr_a10sr_reset",
132 },
133};
134module_platform_driver(a10sr_reset_driver);
135
136MODULE_AUTHOR("Thor Thayer <thor.thayer@linux.intel.com>");
137MODULE_DESCRIPTION("Altera Arria10 System Resource Reset Controller Driver");
138MODULE_LICENSE("GPL v2");
diff --git a/drivers/reset/reset-ath79.c b/drivers/reset/reset-ath79.c
index 6b97631f5489..2674880e5492 100644
--- a/drivers/reset/reset-ath79.c
+++ b/drivers/reset/reset-ath79.c
@@ -1,4 +1,7 @@
1/* 1/*
2 * AR71xx Reset Controller Driver
3 * Author: Alban Bedel
4 *
2 * Copyright (C) 2015 Alban Bedel <albeu@free.fr> 5 * Copyright (C) 2015 Alban Bedel <albeu@free.fr>
3 * 6 *
4 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -13,7 +16,7 @@
13 */ 16 */
14 17
15#include <linux/io.h> 18#include <linux/io.h>
16#include <linux/module.h> 19#include <linux/init.h>
17#include <linux/platform_device.h> 20#include <linux/platform_device.h>
18#include <linux/reset-controller.h> 21#include <linux/reset-controller.h>
19#include <linux/reboot.h> 22#include <linux/reboot.h>
@@ -127,31 +130,17 @@ static int ath79_reset_probe(struct platform_device *pdev)
127 return 0; 130 return 0;
128} 131}
129 132
130static int ath79_reset_remove(struct platform_device *pdev)
131{
132 struct ath79_reset *ath79_reset = platform_get_drvdata(pdev);
133
134 unregister_restart_handler(&ath79_reset->restart_nb);
135
136 return 0;
137}
138
139static const struct of_device_id ath79_reset_dt_ids[] = { 133static const struct of_device_id ath79_reset_dt_ids[] = {
140 { .compatible = "qca,ar7100-reset", }, 134 { .compatible = "qca,ar7100-reset", },
141 { }, 135 { },
142}; 136};
143MODULE_DEVICE_TABLE(of, ath79_reset_dt_ids);
144 137
145static struct platform_driver ath79_reset_driver = { 138static struct platform_driver ath79_reset_driver = {
146 .probe = ath79_reset_probe, 139 .probe = ath79_reset_probe,
147 .remove = ath79_reset_remove,
148 .driver = { 140 .driver = {
149 .name = "ath79-reset", 141 .name = "ath79-reset",
150 .of_match_table = ath79_reset_dt_ids, 142 .of_match_table = ath79_reset_dt_ids,
143 .suppress_bind_attrs = true,
151 }, 144 },
152}; 145};
153module_platform_driver(ath79_reset_driver); 146builtin_platform_driver(ath79_reset_driver);
154
155MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
156MODULE_DESCRIPTION("AR71xx Reset Controller Driver");
157MODULE_LICENSE("GPL");
diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c
new file mode 100644
index 000000000000..4db177bc89bc
--- /dev/null
+++ b/drivers/reset/reset-imx7.c
@@ -0,0 +1,158 @@
1/*
2 * Copyright (c) 2017, Impinj, Inc.
3 *
4 * i.MX7 System Reset Controller (SRC) driver
5 *
6 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/mfd/syscon.h>
19#include <linux/platform_device.h>
20#include <linux/reset-controller.h>
21#include <linux/regmap.h>
22#include <dt-bindings/reset/imx7-reset.h>
23
24struct imx7_src {
25 struct reset_controller_dev rcdev;
26 struct regmap *regmap;
27};
28
29enum imx7_src_registers {
30 SRC_A7RCR0 = 0x0004,
31 SRC_M4RCR = 0x000c,
32 SRC_ERCR = 0x0014,
33 SRC_HSICPHY_RCR = 0x001c,
34 SRC_USBOPHY1_RCR = 0x0020,
35 SRC_USBOPHY2_RCR = 0x0024,
36 SRC_MIPIPHY_RCR = 0x0028,
37 SRC_PCIEPHY_RCR = 0x002c,
38 SRC_DDRC_RCR = 0x1000,
39};
40
41struct imx7_src_signal {
42 unsigned int offset, bit;
43};
44
45static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = {
46 [IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) },
47 [IMX7_RESET_A7_CORE_POR_RESET1] = { SRC_A7RCR0, BIT(1) },
48 [IMX7_RESET_A7_CORE_RESET0] = { SRC_A7RCR0, BIT(4) },
49 [IMX7_RESET_A7_CORE_RESET1] = { SRC_A7RCR0, BIT(5) },
50 [IMX7_RESET_A7_DBG_RESET0] = { SRC_A7RCR0, BIT(8) },
51 [IMX7_RESET_A7_DBG_RESET1] = { SRC_A7RCR0, BIT(9) },
52 [IMX7_RESET_A7_ETM_RESET0] = { SRC_A7RCR0, BIT(12) },
53 [IMX7_RESET_A7_ETM_RESET1] = { SRC_A7RCR0, BIT(13) },
54 [IMX7_RESET_A7_SOC_DBG_RESET] = { SRC_A7RCR0, BIT(20) },
55 [IMX7_RESET_A7_L2RESET] = { SRC_A7RCR0, BIT(21) },
56 [IMX7_RESET_SW_M4C_RST] = { SRC_M4RCR, BIT(1) },
57 [IMX7_RESET_SW_M4P_RST] = { SRC_M4RCR, BIT(2) },
58 [IMX7_RESET_EIM_RST] = { SRC_ERCR, BIT(0) },
59 [IMX7_RESET_HSICPHY_PORT_RST] = { SRC_HSICPHY_RCR, BIT(1) },
60 [IMX7_RESET_USBPHY1_POR] = { SRC_USBOPHY1_RCR, BIT(0) },
61 [IMX7_RESET_USBPHY1_PORT_RST] = { SRC_USBOPHY1_RCR, BIT(1) },
62 [IMX7_RESET_USBPHY2_POR] = { SRC_USBOPHY2_RCR, BIT(0) },
63 [IMX7_RESET_USBPHY2_PORT_RST] = { SRC_USBOPHY2_RCR, BIT(1) },
64 [IMX7_RESET_MIPI_PHY_MRST] = { SRC_MIPIPHY_RCR, BIT(1) },
65 [IMX7_RESET_MIPI_PHY_SRST] = { SRC_MIPIPHY_RCR, BIT(2) },
66 [IMX7_RESET_PCIEPHY] = { SRC_PCIEPHY_RCR, BIT(2) | BIT(1) },
67 [IMX7_RESET_PCIEPHY_PERST] = { SRC_PCIEPHY_RCR, BIT(3) },
68 [IMX7_RESET_PCIE_CTRL_APPS_EN] = { SRC_PCIEPHY_RCR, BIT(6) },
69 [IMX7_RESET_DDRC_PRST] = { SRC_DDRC_RCR, BIT(0) },
70 [IMX7_RESET_DDRC_CORE_RST] = { SRC_DDRC_RCR, BIT(1) },
71};
72
73static struct imx7_src *to_imx7_src(struct reset_controller_dev *rcdev)
74{
75 return container_of(rcdev, struct imx7_src, rcdev);
76}
77
78static int imx7_reset_set(struct reset_controller_dev *rcdev,
79 unsigned long id, bool assert)
80{
81 struct imx7_src *imx7src = to_imx7_src(rcdev);
82 const struct imx7_src_signal *signal = &imx7_src_signals[id];
83 unsigned int value = 0;
84
85 switch (id) {
86 case IMX7_RESET_PCIEPHY:
87 /*
88 * wait for more than 10us to release phy g_rst and
89 * btnrst
90 */
91 if (!assert)
92 udelay(10);
93 break;
94
95 case IMX7_RESET_PCIE_CTRL_APPS_EN:
96 value = (assert) ? 0 : signal->bit;
97 break;
98 }
99
100 return regmap_update_bits(imx7src->regmap,
101 signal->offset, signal->bit, value);
102}
103
104static int imx7_reset_assert(struct reset_controller_dev *rcdev,
105 unsigned long id)
106{
107 return imx7_reset_set(rcdev, id, true);
108}
109
110static int imx7_reset_deassert(struct reset_controller_dev *rcdev,
111 unsigned long id)
112{
113 return imx7_reset_set(rcdev, id, false);
114}
115
116static const struct reset_control_ops imx7_reset_ops = {
117 .assert = imx7_reset_assert,
118 .deassert = imx7_reset_deassert,
119};
120
121static int imx7_reset_probe(struct platform_device *pdev)
122{
123 struct imx7_src *imx7src;
124 struct device *dev = &pdev->dev;
125 struct regmap_config config = { .name = "src" };
126
127 imx7src = devm_kzalloc(dev, sizeof(*imx7src), GFP_KERNEL);
128 if (!imx7src)
129 return -ENOMEM;
130
131 imx7src->regmap = syscon_node_to_regmap(dev->of_node);
132 if (IS_ERR(imx7src->regmap)) {
133 dev_err(dev, "Unable to get imx7-src regmap");
134 return PTR_ERR(imx7src->regmap);
135 }
136 regmap_attach_dev(dev, imx7src->regmap, &config);
137
138 imx7src->rcdev.owner = THIS_MODULE;
139 imx7src->rcdev.nr_resets = IMX7_RESET_NUM;
140 imx7src->rcdev.ops = &imx7_reset_ops;
141 imx7src->rcdev.of_node = dev->of_node;
142
143 return devm_reset_controller_register(dev, &imx7src->rcdev);
144}
145
146static const struct of_device_id imx7_reset_dt_ids[] = {
147 { .compatible = "fsl,imx7d-src", },
148 { /* sentinel */ },
149};
150
151static struct platform_driver imx7_reset_driver = {
152 .probe = imx7_reset_probe,
153 .driver = {
154 .name = KBUILD_MODNAME,
155 .of_match_table = imx7_reset_dt_ids,
156 },
157};
158builtin_platform_driver(imx7_reset_driver);
diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
index c32f11a30c5f..a8b915eb8b58 100644
--- a/drivers/reset/reset-meson.c
+++ b/drivers/reset/reset-meson.c
@@ -1,4 +1,6 @@
1/* 1/*
2 * Amlogic Meson Reset Controller driver
3 *
2 * This file is provided under a dual BSD/GPLv2 license. When using or 4 * This file is provided under a dual BSD/GPLv2 license. When using or
3 * redistributing this file, you may do so under either license. 5 * redistributing this file, you may do so under either license.
4 * 6 *
@@ -53,7 +55,7 @@
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 */ 56 */
55#include <linux/err.h> 57#include <linux/err.h>
56#include <linux/module.h> 58#include <linux/init.h>
57#include <linux/io.h> 59#include <linux/io.h>
58#include <linux/of.h> 60#include <linux/of.h>
59#include <linux/platform_device.h> 61#include <linux/platform_device.h>
@@ -95,7 +97,6 @@ static const struct of_device_id meson_reset_dt_ids[] = {
95 { .compatible = "amlogic,meson-gxbb-reset", }, 97 { .compatible = "amlogic,meson-gxbb-reset", },
96 { /* sentinel */ }, 98 { /* sentinel */ },
97}; 99};
98MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
99 100
100static int meson_reset_probe(struct platform_device *pdev) 101static int meson_reset_probe(struct platform_device *pdev)
101{ 102{
@@ -128,9 +129,4 @@ static struct platform_driver meson_reset_driver = {
128 .of_match_table = meson_reset_dt_ids, 129 .of_match_table = meson_reset_dt_ids,
129 }, 130 },
130}; 131};
131 132builtin_platform_driver(meson_reset_driver);
132module_platform_driver(meson_reset_driver);
133
134MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
135MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver");
136MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c
index 0d9036dea010..cf5b9742b86e 100644
--- a/drivers/reset/reset-oxnas.c
+++ b/drivers/reset/reset-oxnas.c
@@ -18,7 +18,7 @@
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */ 19 */
20#include <linux/err.h> 20#include <linux/err.h>
21#include <linux/module.h> 21#include <linux/init.h>
22#include <linux/of.h> 22#include <linux/of.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/reset-controller.h> 24#include <linux/reset-controller.h>
@@ -83,7 +83,6 @@ static const struct of_device_id oxnas_reset_dt_ids[] = {
83 { .compatible = "oxsemi,ox820-reset", }, 83 { .compatible = "oxsemi,ox820-reset", },
84 { /* sentinel */ }, 84 { /* sentinel */ },
85}; 85};
86MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
87 86
88static int oxnas_reset_probe(struct platform_device *pdev) 87static int oxnas_reset_probe(struct platform_device *pdev)
89{ 88{
@@ -123,5 +122,4 @@ static struct platform_driver oxnas_reset_driver = {
123 .of_match_table = oxnas_reset_dt_ids, 122 .of_match_table = oxnas_reset_dt_ids,
124 }, 123 },
125}; 124};
126 125builtin_platform_driver(oxnas_reset_driver);
127module_platform_driver(oxnas_reset_driver);
diff --git a/drivers/reset/reset-pistachio.c b/drivers/reset/reset-pistachio.c
index bbc4c06dd33b..11d651b44e81 100644
--- a/drivers/reset/reset-pistachio.c
+++ b/drivers/reset/reset-pistachio.c
@@ -10,7 +10,7 @@
10 * version 2, as published by the Free Software Foundation. 10 * version 2, as published by the Free Software Foundation.
11 */ 11 */
12 12
13#include <linux/module.h> 13#include <linux/init.h>
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/platform_device.h> 15#include <linux/platform_device.h>
16#include <linux/regmap.h> 16#include <linux/regmap.h>
@@ -128,7 +128,6 @@ static const struct of_device_id pistachio_reset_dt_ids[] = {
128 { .compatible = "img,pistachio-reset", }, 128 { .compatible = "img,pistachio-reset", },
129 { /* sentinel */ }, 129 { /* sentinel */ },
130}; 130};
131MODULE_DEVICE_TABLE(of, pistachio_reset_dt_ids);
132 131
133static struct platform_driver pistachio_reset_driver = { 132static struct platform_driver pistachio_reset_driver = {
134 .probe = pistachio_reset_probe, 133 .probe = pistachio_reset_probe,
@@ -137,8 +136,4 @@ static struct platform_driver pistachio_reset_driver = {
137 .of_match_table = pistachio_reset_dt_ids, 136 .of_match_table = pistachio_reset_dt_ids,
138 }, 137 },
139}; 138};
140module_platform_driver(pistachio_reset_driver); 139builtin_platform_driver(pistachio_reset_driver);
141
142MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
143MODULE_DESCRIPTION("Pistacho Reset Controller Driver");
144MODULE_LICENSE("GPL v2");
diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
index 43e4a9f39b9b..07224c019892 100644
--- a/drivers/reset/reset-socfpga.c
+++ b/drivers/reset/reset-socfpga.c
@@ -25,7 +25,8 @@
25#include <linux/spinlock.h> 25#include <linux/spinlock.h>
26#include <linux/types.h> 26#include <linux/types.h>
27 27
28#define NR_BANKS 4 28#define BANK_INCREMENT 4
29#define NR_BANKS 8
29 30
30struct socfpga_reset_data { 31struct socfpga_reset_data {
31 spinlock_t lock; 32 spinlock_t lock;
@@ -46,8 +47,8 @@ static int socfpga_reset_assert(struct reset_controller_dev *rcdev,
46 47
47 spin_lock_irqsave(&data->lock, flags); 48 spin_lock_irqsave(&data->lock, flags);
48 49
49 reg = readl(data->membase + (bank * NR_BANKS)); 50 reg = readl(data->membase + (bank * BANK_INCREMENT));
50 writel(reg | BIT(offset), data->membase + (bank * NR_BANKS)); 51 writel(reg | BIT(offset), data->membase + (bank * BANK_INCREMENT));
51 spin_unlock_irqrestore(&data->lock, flags); 52 spin_unlock_irqrestore(&data->lock, flags);
52 53
53 return 0; 54 return 0;
@@ -67,8 +68,8 @@ static int socfpga_reset_deassert(struct reset_controller_dev *rcdev,
67 68
68 spin_lock_irqsave(&data->lock, flags); 69 spin_lock_irqsave(&data->lock, flags);
69 70
70 reg = readl(data->membase + (bank * NR_BANKS)); 71 reg = readl(data->membase + (bank * BANK_INCREMENT));
71 writel(reg & ~BIT(offset), data->membase + (bank * NR_BANKS)); 72 writel(reg & ~BIT(offset), data->membase + (bank * BANK_INCREMENT));
72 73
73 spin_unlock_irqrestore(&data->lock, flags); 74 spin_unlock_irqrestore(&data->lock, flags);
74 75
@@ -84,7 +85,7 @@ static int socfpga_reset_status(struct reset_controller_dev *rcdev,
84 int offset = id % BITS_PER_LONG; 85 int offset = id % BITS_PER_LONG;
85 u32 reg; 86 u32 reg;
86 87
87 reg = readl(data->membase + (bank * NR_BANKS)); 88 reg = readl(data->membase + (bank * BANK_INCREMENT));
88 89
89 return !(reg & BIT(offset)); 90 return !(reg & BIT(offset));
90} 91}
diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
index b44f6b5f87b6..cd585cd2f04d 100644
--- a/drivers/reset/reset-sunxi.c
+++ b/drivers/reset/reset-sunxi.c
@@ -34,15 +34,16 @@ static int sunxi_reset_assert(struct reset_controller_dev *rcdev,
34 struct sunxi_reset_data *data = container_of(rcdev, 34 struct sunxi_reset_data *data = container_of(rcdev,
35 struct sunxi_reset_data, 35 struct sunxi_reset_data,
36 rcdev); 36 rcdev);
37 int bank = id / BITS_PER_LONG; 37 int reg_width = sizeof(u32);
38 int offset = id % BITS_PER_LONG; 38 int bank = id / (reg_width * BITS_PER_BYTE);
39 int offset = id % (reg_width * BITS_PER_BYTE);
39 unsigned long flags; 40 unsigned long flags;
40 u32 reg; 41 u32 reg;
41 42
42 spin_lock_irqsave(&data->lock, flags); 43 spin_lock_irqsave(&data->lock, flags);
43 44
44 reg = readl(data->membase + (bank * 4)); 45 reg = readl(data->membase + (bank * reg_width));
45 writel(reg & ~BIT(offset), data->membase + (bank * 4)); 46 writel(reg & ~BIT(offset), data->membase + (bank * reg_width));
46 47
47 spin_unlock_irqrestore(&data->lock, flags); 48 spin_unlock_irqrestore(&data->lock, flags);
48 49
@@ -55,15 +56,16 @@ static int sunxi_reset_deassert(struct reset_controller_dev *rcdev,
55 struct sunxi_reset_data *data = container_of(rcdev, 56 struct sunxi_reset_data *data = container_of(rcdev,
56 struct sunxi_reset_data, 57 struct sunxi_reset_data,
57 rcdev); 58 rcdev);
58 int bank = id / BITS_PER_LONG; 59 int reg_width = sizeof(u32);
59 int offset = id % BITS_PER_LONG; 60 int bank = id / (reg_width * BITS_PER_BYTE);
61 int offset = id % (reg_width * BITS_PER_BYTE);
60 unsigned long flags; 62 unsigned long flags;
61 u32 reg; 63 u32 reg;
62 64
63 spin_lock_irqsave(&data->lock, flags); 65 spin_lock_irqsave(&data->lock, flags);
64 66
65 reg = readl(data->membase + (bank * 4)); 67 reg = readl(data->membase + (bank * reg_width));
66 writel(reg | BIT(offset), data->membase + (bank * 4)); 68 writel(reg | BIT(offset), data->membase + (bank * reg_width));
67 69
68 spin_unlock_irqrestore(&data->lock, flags); 70 spin_unlock_irqrestore(&data->lock, flags);
69 71
diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c
index 9c11be3d3450..c4ba89832796 100644
--- a/drivers/reset/reset-uniphier.c
+++ b/drivers/reset/reset-uniphier.c
@@ -50,6 +50,15 @@ struct uniphier_reset_data {
50 } 50 }
51 51
52/* System reset data */ 52/* System reset data */
53#define UNIPHIER_SLD3_SYS_RESET_NAND(id) \
54 UNIPHIER_RESETX((id), 0x2004, 2)
55
56#define UNIPHIER_LD11_SYS_RESET_NAND(id) \
57 UNIPHIER_RESETX((id), 0x200c, 0)
58
59#define UNIPHIER_LD11_SYS_RESET_EMMC(id) \
60 UNIPHIER_RESETX((id), 0x200c, 2)
61
53#define UNIPHIER_SLD3_SYS_RESET_STDMAC(id) \ 62#define UNIPHIER_SLD3_SYS_RESET_STDMAC(id) \
54 UNIPHIER_RESETX((id), 0x2000, 10) 63 UNIPHIER_RESETX((id), 0x2000, 10)
55 64
@@ -65,12 +74,14 @@ struct uniphier_reset_data {
65#define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch) \ 74#define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch) \
66 UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17) 75 UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17)
67 76
68const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = { 77static const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = {
78 UNIPHIER_SLD3_SYS_RESET_NAND(2),
69 UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* Ether, HSC, MIO */ 79 UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* Ether, HSC, MIO */
70 UNIPHIER_RESET_END, 80 UNIPHIER_RESET_END,
71}; 81};
72 82
73const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = { 83static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
84 UNIPHIER_SLD3_SYS_RESET_NAND(2),
74 UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, MIO, RLE */ 85 UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, MIO, RLE */
75 UNIPHIER_PRO4_SYS_RESET_GIO(12), /* Ether, SATA, USB3 */ 86 UNIPHIER_PRO4_SYS_RESET_GIO(12), /* Ether, SATA, USB3 */
76 UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), 87 UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
@@ -78,7 +89,8 @@ const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
78 UNIPHIER_RESET_END, 89 UNIPHIER_RESET_END,
79}; 90};
80 91
81const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = { 92static const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
93 UNIPHIER_SLD3_SYS_RESET_NAND(2),
82 UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC */ 94 UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC */
83 UNIPHIER_PRO4_SYS_RESET_GIO(12), /* PCIe, USB3 */ 95 UNIPHIER_PRO4_SYS_RESET_GIO(12), /* PCIe, USB3 */
84 UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), 96 UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
@@ -86,7 +98,8 @@ const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
86 UNIPHIER_RESET_END, 98 UNIPHIER_RESET_END,
87}; 99};
88 100
89const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = { 101static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
102 UNIPHIER_SLD3_SYS_RESET_NAND(2),
90 UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, RLE */ 103 UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, RLE */
91 UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), 104 UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
92 UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), 105 UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
@@ -100,12 +113,16 @@ const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
100 UNIPHIER_RESET_END, 113 UNIPHIER_RESET_END,
101}; 114};
102 115
103const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = { 116static const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
117 UNIPHIER_LD11_SYS_RESET_NAND(2),
118 UNIPHIER_LD11_SYS_RESET_EMMC(4),
104 UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC, MIO */ 119 UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC, MIO */
105 UNIPHIER_RESET_END, 120 UNIPHIER_RESET_END,
106}; 121};
107 122
108const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = { 123static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
124 UNIPHIER_LD11_SYS_RESET_NAND(2),
125 UNIPHIER_LD11_SYS_RESET_EMMC(4),
109 UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC */ 126 UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC */
110 UNIPHIER_LD20_SYS_RESET_GIO(12), /* PCIe, USB3 */ 127 UNIPHIER_LD20_SYS_RESET_GIO(12), /* PCIe, USB3 */
111 UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */ 128 UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */
@@ -134,7 +151,7 @@ const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
134#define UNIPHIER_MIO_RESET_DMAC(id) \ 151#define UNIPHIER_MIO_RESET_DMAC(id) \
135 UNIPHIER_RESETX((id), 0x110, 17) 152 UNIPHIER_RESETX((id), 0x110, 17)
136 153
137const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = { 154static const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
138 UNIPHIER_MIO_RESET_SD(0, 0), 155 UNIPHIER_MIO_RESET_SD(0, 0),
139 UNIPHIER_MIO_RESET_SD(1, 1), 156 UNIPHIER_MIO_RESET_SD(1, 1),
140 UNIPHIER_MIO_RESET_SD(2, 2), 157 UNIPHIER_MIO_RESET_SD(2, 2),
@@ -154,7 +171,7 @@ const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
154 UNIPHIER_RESET_END, 171 UNIPHIER_RESET_END,
155}; 172};
156 173
157const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = { 174static const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
158 UNIPHIER_MIO_RESET_SD(0, 0), 175 UNIPHIER_MIO_RESET_SD(0, 0),
159 UNIPHIER_MIO_RESET_SD(1, 1), 176 UNIPHIER_MIO_RESET_SD(1, 1),
160 UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1), 177 UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1),
@@ -171,7 +188,7 @@ const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
171#define UNIPHIER_PERI_RESET_FI2C(id, ch) \ 188#define UNIPHIER_PERI_RESET_FI2C(id, ch) \
172 UNIPHIER_RESETX((id), 0x114, 24 + (ch)) 189 UNIPHIER_RESETX((id), 0x114, 24 + (ch))
173 190
174const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = { 191static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
175 UNIPHIER_PERI_RESET_UART(0, 0), 192 UNIPHIER_PERI_RESET_UART(0, 0),
176 UNIPHIER_PERI_RESET_UART(1, 1), 193 UNIPHIER_PERI_RESET_UART(1, 1),
177 UNIPHIER_PERI_RESET_UART(2, 2), 194 UNIPHIER_PERI_RESET_UART(2, 2),
@@ -184,7 +201,7 @@ const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
184 UNIPHIER_RESET_END, 201 UNIPHIER_RESET_END,
185}; 202};
186 203
187const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = { 204static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
188 UNIPHIER_PERI_RESET_UART(0, 0), 205 UNIPHIER_PERI_RESET_UART(0, 0),
189 UNIPHIER_PERI_RESET_UART(1, 1), 206 UNIPHIER_PERI_RESET_UART(1, 1),
190 UNIPHIER_PERI_RESET_UART(2, 2), 207 UNIPHIER_PERI_RESET_UART(2, 2),
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 45e5b13a3c02..309643fe35f9 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -3,6 +3,7 @@ menu "SOC (System On Chip) specific Drivers"
3source "drivers/soc/atmel/Kconfig" 3source "drivers/soc/atmel/Kconfig"
4source "drivers/soc/bcm/Kconfig" 4source "drivers/soc/bcm/Kconfig"
5source "drivers/soc/fsl/Kconfig" 5source "drivers/soc/fsl/Kconfig"
6source "drivers/soc/imx/Kconfig"
6source "drivers/soc/mediatek/Kconfig" 7source "drivers/soc/mediatek/Kconfig"
7source "drivers/soc/qcom/Kconfig" 8source "drivers/soc/qcom/Kconfig"
8source "drivers/soc/rockchip/Kconfig" 9source "drivers/soc/rockchip/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 3467de7d3890..824b44281efa 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -7,6 +7,7 @@ obj-y += bcm/
7obj-$(CONFIG_ARCH_DOVE) += dove/ 7obj-$(CONFIG_ARCH_DOVE) += dove/
8obj-$(CONFIG_MACH_DOVE) += dove/ 8obj-$(CONFIG_MACH_DOVE) += dove/
9obj-y += fsl/ 9obj-y += fsl/
10obj-$(CONFIG_ARCH_MXC) += imx/
10obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ 11obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
11obj-$(CONFIG_ARCH_QCOM) += qcom/ 12obj-$(CONFIG_ARCH_QCOM) += qcom/
12obj-$(CONFIG_ARCH_RENESAS) += renesas/ 13obj-$(CONFIG_ARCH_RENESAS) += renesas/
diff --git a/drivers/soc/bcm/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c
index 94e7335553f4..b6195fdf0d00 100644
--- a/drivers/soc/bcm/brcmstb/common.c
+++ b/drivers/soc/bcm/brcmstb/common.c
@@ -41,6 +41,15 @@ bool soc_is_brcmstb(void)
41} 41}
42 42
43static const struct of_device_id sun_top_ctrl_match[] = { 43static const struct of_device_id sun_top_ctrl_match[] = {
44 { .compatible = "brcm,bcm7125-sun-top-ctrl", },
45 { .compatible = "brcm,bcm7346-sun-top-ctrl", },
46 { .compatible = "brcm,bcm7358-sun-top-ctrl", },
47 { .compatible = "brcm,bcm7360-sun-top-ctrl", },
48 { .compatible = "brcm,bcm7362-sun-top-ctrl", },
49 { .compatible = "brcm,bcm7420-sun-top-ctrl", },
50 { .compatible = "brcm,bcm7425-sun-top-ctrl", },
51 { .compatible = "brcm,bcm7429-sun-top-ctrl", },
52 { .compatible = "brcm,bcm7425-sun-top-ctrl", },
44 { .compatible = "brcm,brcmstb-sun-top-ctrl", }, 53 { .compatible = "brcm,brcmstb-sun-top-ctrl", },
45 { } 54 { }
46}; 55};
diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
new file mode 100644
index 000000000000..357a5d8f8da0
--- /dev/null
+++ b/drivers/soc/imx/Kconfig
@@ -0,0 +1,9 @@
1menu "i.MX SoC drivers"
2
3config IMX7_PM_DOMAINS
4 bool "i.MX7 PM domains"
5 select PM_GENERIC_DOMAINS
6 depends on SOC_IMX7D || (COMPILE_TEST && OF)
7 default y if SOC_IMX7D
8
9endmenu
diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile
new file mode 100644
index 000000000000..5b6e396c1121
--- /dev/null
+++ b/drivers/soc/imx/Makefile
@@ -0,0 +1,2 @@
1obj-y += gpc.o
2obj-$(CONFIG_IMX7_PM_DOMAINS) += gpcv2.o
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
new file mode 100644
index 000000000000..47e7aa963dbb
--- /dev/null
+++ b/drivers/soc/imx/gpc.c
@@ -0,0 +1,489 @@
1/*
2 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
3 * Copyright 2011-2013 Freescale Semiconductor, Inc.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/clk.h>
14#include <linux/delay.h>
15#include <linux/io.h>
16#include <linux/of_device.h>
17#include <linux/platform_device.h>
18#include <linux/pm_domain.h>
19#include <linux/regmap.h>
20#include <linux/regulator/consumer.h>
21
22#define GPC_CNTR 0x000
23
24#define GPC_PGC_CTRL_OFFS 0x0
25#define GPC_PGC_PUPSCR_OFFS 0x4
26#define GPC_PGC_PDNSCR_OFFS 0x8
27#define GPC_PGC_SW2ISO_SHIFT 0x8
28#define GPC_PGC_SW_SHIFT 0x0
29
30#define GPC_PGC_GPU_PDN 0x260
31#define GPC_PGC_GPU_PUPSCR 0x264
32#define GPC_PGC_GPU_PDNSCR 0x268
33
34#define GPU_VPU_PUP_REQ BIT(1)
35#define GPU_VPU_PDN_REQ BIT(0)
36
37#define GPC_CLK_MAX 6
38
39#define PGC_DOMAIN_FLAG_NO_PD BIT(0)
40
41struct imx_pm_domain {
42 struct generic_pm_domain base;
43 struct regmap *regmap;
44 struct regulator *supply;
45 struct clk *clk[GPC_CLK_MAX];
46 int num_clks;
47 unsigned int reg_offs;
48 signed char cntr_pdn_bit;
49 unsigned int ipg_rate_mhz;
50 unsigned int flags;
51};
52
53static inline struct imx_pm_domain *
54to_imx_pm_domain(struct generic_pm_domain *genpd)
55{
56 return container_of(genpd, struct imx_pm_domain, base);
57}
58
59static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
60{
61 struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
62 int iso, iso2sw;
63 u32 val;
64
65 if (pd->flags & PGC_DOMAIN_FLAG_NO_PD)
66 return -EBUSY;
67
68 /* Read ISO and ISO2SW power down delays */
69 regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
70 iso = val & 0x3f;
71 iso2sw = (val >> 8) & 0x3f;
72
73 /* Gate off domain when powered down */
74 regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
75 0x1, 0x1);
76
77 /* Request GPC to power down domain */
78 val = BIT(pd->cntr_pdn_bit);
79 regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
80
81 /* Wait ISO + ISO2SW IPG clock cycles */
82 udelay(DIV_ROUND_UP(iso + iso2sw, pd->ipg_rate_mhz));
83
84 if (pd->supply)
85 regulator_disable(pd->supply);
86
87 return 0;
88}
89
90static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
91{
92 struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
93 int i, ret, sw, sw2iso;
94 u32 val;
95
96 if (pd->supply) {
97 ret = regulator_enable(pd->supply);
98 if (ret) {
99 pr_err("%s: failed to enable regulator: %d\n",
100 __func__, ret);
101 return ret;
102 }
103 }
104
105 /* Enable reset clocks for all devices in the domain */
106 for (i = 0; i < pd->num_clks; i++)
107 clk_prepare_enable(pd->clk[i]);
108
109 /* Gate off domain when powered down */
110 regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
111 0x1, 0x1);
112
113 /* Read ISO and ISO2SW power up delays */
114 regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
115 sw = val & 0x3f;
116 sw2iso = (val >> 8) & 0x3f;
117
118 /* Request GPC to power up domain */
119 val = BIT(pd->cntr_pdn_bit + 1);
120 regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
121
122 /* Wait ISO + ISO2SW IPG clock cycles */
123 udelay(DIV_ROUND_UP(sw + sw2iso, pd->ipg_rate_mhz));
124
125 /* Disable reset clocks for all devices in the domain */
126 for (i = 0; i < pd->num_clks; i++)
127 clk_disable_unprepare(pd->clk[i]);
128
129 return 0;
130}
131
132static int imx_pgc_get_clocks(struct device *dev, struct imx_pm_domain *domain)
133{
134 int i, ret;
135
136 for (i = 0; ; i++) {
137 struct clk *clk = of_clk_get(dev->of_node, i);
138 if (IS_ERR(clk))
139 break;
140 if (i >= GPC_CLK_MAX) {
141 dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
142 ret = -EINVAL;
143 goto clk_err;
144 }
145 domain->clk[i] = clk;
146 }
147 domain->num_clks = i;
148
149 return 0;
150
151clk_err:
152 while (i--)
153 clk_put(domain->clk[i]);
154
155 return ret;
156}
157
158static void imx_pgc_put_clocks(struct imx_pm_domain *domain)
159{
160 int i;
161
162 for (i = domain->num_clks - 1; i >= 0; i--)
163 clk_put(domain->clk[i]);
164}
165
166static int imx_pgc_parse_dt(struct device *dev, struct imx_pm_domain *domain)
167{
168 /* try to get the domain supply regulator */
169 domain->supply = devm_regulator_get_optional(dev, "power");
170 if (IS_ERR(domain->supply)) {
171 if (PTR_ERR(domain->supply) == -ENODEV)
172 domain->supply = NULL;
173 else
174 return PTR_ERR(domain->supply);
175 }
176
177 /* try to get all clocks needed for reset propagation */
178 return imx_pgc_get_clocks(dev, domain);
179}
180
181static int imx_pgc_power_domain_probe(struct platform_device *pdev)
182{
183 struct imx_pm_domain *domain = pdev->dev.platform_data;
184 struct device *dev = &pdev->dev;
185 int ret;
186
187 /* if this PD is associated with a DT node try to parse it */
188 if (dev->of_node) {
189 ret = imx_pgc_parse_dt(dev, domain);
190 if (ret)
191 return ret;
192 }
193
194 /* initially power on the domain */
195 if (domain->base.power_on)
196 domain->base.power_on(&domain->base);
197
198 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
199 pm_genpd_init(&domain->base, NULL, false);
200 ret = of_genpd_add_provider_simple(dev->of_node, &domain->base);
201 if (ret)
202 goto genpd_err;
203 }
204
205 device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE);
206
207 return 0;
208
209genpd_err:
210 pm_genpd_remove(&domain->base);
211 imx_pgc_put_clocks(domain);
212
213 return ret;
214}
215
216static int imx_pgc_power_domain_remove(struct platform_device *pdev)
217{
218 struct imx_pm_domain *domain = pdev->dev.platform_data;
219
220 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
221 of_genpd_del_provider(pdev->dev.of_node);
222 pm_genpd_remove(&domain->base);
223 imx_pgc_put_clocks(domain);
224 }
225
226 return 0;
227}
228
229static const struct platform_device_id imx_pgc_power_domain_id[] = {
230 { "imx-pgc-power-domain"},
231 { },
232};
233
234static struct platform_driver imx_pgc_power_domain_driver = {
235 .driver = {
236 .name = "imx-pgc-pd",
237 },
238 .probe = imx_pgc_power_domain_probe,
239 .remove = imx_pgc_power_domain_remove,
240 .id_table = imx_pgc_power_domain_id,
241};
242builtin_platform_driver(imx_pgc_power_domain_driver)
243
244#define GPC_PGC_DOMAIN_ARM 0
245#define GPC_PGC_DOMAIN_PU 1
246#define GPC_PGC_DOMAIN_DISPLAY 2
247
248static struct genpd_power_state imx6_pm_domain_pu_state = {
249 .power_off_latency_ns = 25000,
250 .power_on_latency_ns = 2000000,
251};
252
253static struct imx_pm_domain imx_gpc_domains[] = {
254 {
255 .base = {
256 .name = "ARM",
257 },
258 }, {
259 .base = {
260 .name = "PU",
261 .power_off = imx6_pm_domain_power_off,
262 .power_on = imx6_pm_domain_power_on,
263 .states = &imx6_pm_domain_pu_state,
264 .state_count = 1,
265 },
266 .reg_offs = 0x260,
267 .cntr_pdn_bit = 0,
268 }, {
269 .base = {
270 .name = "DISPLAY",
271 .power_off = imx6_pm_domain_power_off,
272 .power_on = imx6_pm_domain_power_on,
273 },
274 .reg_offs = 0x240,
275 .cntr_pdn_bit = 4,
276 }
277};
278
279struct imx_gpc_dt_data {
280 int num_domains;
281 bool err009619_present;
282};
283
284static const struct imx_gpc_dt_data imx6q_dt_data = {
285 .num_domains = 2,
286 .err009619_present = false,
287};
288
289static const struct imx_gpc_dt_data imx6qp_dt_data = {
290 .num_domains = 2,
291 .err009619_present = true,
292};
293
294static const struct imx_gpc_dt_data imx6sl_dt_data = {
295 .num_domains = 3,
296 .err009619_present = false,
297};
298
299static const struct of_device_id imx_gpc_dt_ids[] = {
300 { .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data },
301 { .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data },
302 { .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data },
303 { }
304};
305
306static const struct regmap_config imx_gpc_regmap_config = {
307 .reg_bits = 32,
308 .val_bits = 32,
309 .reg_stride = 4,
310 .max_register = 0x2ac,
311};
312
313static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
314 &imx_gpc_domains[0].base,
315 &imx_gpc_domains[1].base,
316};
317
318static struct genpd_onecell_data imx_gpc_onecell_data = {
319 .domains = imx_gpc_onecell_domains,
320 .num_domains = 2,
321};
322
323static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap,
324 unsigned int num_domains)
325{
326 struct imx_pm_domain *domain;
327 int i, ret;
328
329 for (i = 0; i < num_domains; i++) {
330 domain = &imx_gpc_domains[i];
331 domain->regmap = regmap;
332 domain->ipg_rate_mhz = 66;
333
334 if (i == 1) {
335 domain->supply = devm_regulator_get(dev, "pu");
336 if (IS_ERR(domain->supply))
337 return PTR_ERR(domain->supply);;
338
339 ret = imx_pgc_get_clocks(dev, domain);
340 if (ret)
341 goto clk_err;
342
343 domain->base.power_on(&domain->base);
344 }
345 }
346
347 for (i = 0; i < num_domains; i++)
348 pm_genpd_init(&imx_gpc_domains[i].base, NULL, false);
349
350 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
351 ret = of_genpd_add_provider_onecell(dev->of_node,
352 &imx_gpc_onecell_data);
353 if (ret)
354 goto genpd_err;
355 }
356
357 return 0;
358
359genpd_err:
360 for (i = 0; i < num_domains; i++)
361 pm_genpd_remove(&imx_gpc_domains[i].base);
362 imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
363clk_err:
364 return ret;
365}
366
367static int imx_gpc_probe(struct platform_device *pdev)
368{
369 const struct of_device_id *of_id =
370 of_match_device(imx_gpc_dt_ids, &pdev->dev);
371 const struct imx_gpc_dt_data *of_id_data = of_id->data;
372 struct device_node *pgc_node;
373 struct regmap *regmap;
374 struct resource *res;
375 void __iomem *base;
376 int ret;
377
378 pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
379
380 /* bail out if DT too old and doesn't provide the necessary info */
381 if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
382 !pgc_node)
383 return 0;
384
385 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
386 base = devm_ioremap_resource(&pdev->dev, res);
387 if (IS_ERR(base))
388 return PTR_ERR(base);
389
390 regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
391 &imx_gpc_regmap_config);
392 if (IS_ERR(regmap)) {
393 ret = PTR_ERR(regmap);
394 dev_err(&pdev->dev, "failed to init regmap: %d\n",
395 ret);
396 return ret;
397 }
398
399 /* Disable PU power down in normal operation if ERR009619 is present */
400 if (of_id_data->err009619_present)
401 imx_gpc_domains[GPC_PGC_DOMAIN_PU].flags |=
402 PGC_DOMAIN_FLAG_NO_PD;
403
404 if (!pgc_node) {
405 ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
406 of_id_data->num_domains);
407 if (ret)
408 return ret;
409 } else {
410 struct imx_pm_domain *domain;
411 struct platform_device *pd_pdev;
412 struct device_node *np;
413 struct clk *ipg_clk;
414 unsigned int ipg_rate_mhz;
415 int domain_index;
416
417 ipg_clk = devm_clk_get(&pdev->dev, "ipg");
418 if (IS_ERR(ipg_clk))
419 return PTR_ERR(ipg_clk);
420 ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000;
421
422 for_each_child_of_node(pgc_node, np) {
423 ret = of_property_read_u32(np, "reg", &domain_index);
424 if (ret) {
425 of_node_put(np);
426 return ret;
427 }
428 if (domain_index >= of_id_data->num_domains)
429 continue;
430
431 domain = &imx_gpc_domains[domain_index];
432 domain->regmap = regmap;
433 domain->ipg_rate_mhz = ipg_rate_mhz;
434
435 pd_pdev = platform_device_alloc("imx-pgc-power-domain",
436 domain_index);
437 if (!pd_pdev) {
438 of_node_put(np);
439 return -ENOMEM;
440 }
441 pd_pdev->dev.platform_data = domain;
442 pd_pdev->dev.parent = &pdev->dev;
443 pd_pdev->dev.of_node = np;
444
445 ret = platform_device_add(pd_pdev);
446 if (ret) {
447 platform_device_put(pd_pdev);
448 of_node_put(np);
449 return ret;
450 }
451 }
452 }
453
454 return 0;
455}
456
457static int imx_gpc_remove(struct platform_device *pdev)
458{
459 int ret;
460
461 /*
462 * If the old DT binding is used the toplevel driver needs to
463 * de-register the power domains
464 */
465 if (!of_get_child_by_name(pdev->dev.of_node, "pgc")) {
466 of_genpd_del_provider(pdev->dev.of_node);
467
468 ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base);
469 if (ret)
470 return ret;
471 imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
472
473 ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base);
474 if (ret)
475 return ret;
476 }
477
478 return 0;
479}
480
481static struct platform_driver imx_gpc_driver = {
482 .driver = {
483 .name = "imx-gpc",
484 .of_match_table = imx_gpc_dt_ids,
485 },
486 .probe = imx_gpc_probe,
487 .remove = imx_gpc_remove,
488};
489builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
new file mode 100644
index 000000000000..3039072911a5
--- /dev/null
+++ b/drivers/soc/imx/gpcv2.c
@@ -0,0 +1,363 @@
1/*
2 * Copyright 2017 Impinj, Inc
3 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
4 *
5 * Based on the code of analogus driver:
6 *
7 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
8 *
9 * The code contained herein is licensed under the GNU General Public
10 * License. You may obtain a copy of the GNU General Public License
11 * Version 2 or later at the following locations:
12 *
13 * http://www.opensource.org/licenses/gpl-license.html
14 * http://www.gnu.org/copyleft/gpl.html
15 */
16
17#include <linux/platform_device.h>
18#include <linux/pm_domain.h>
19#include <linux/regmap.h>
20#include <linux/regulator/consumer.h>
21#include <dt-bindings/power/imx7-power.h>
22
23#define GPC_LPCR_A7_BSC 0x000
24
25#define GPC_PGC_CPU_MAPPING 0x0ec
26#define USB_HSIC_PHY_A7_DOMAIN BIT(6)
27#define USB_OTG2_PHY_A7_DOMAIN BIT(5)
28#define USB_OTG1_PHY_A7_DOMAIN BIT(4)
29#define PCIE_PHY_A7_DOMAIN BIT(3)
30#define MIPI_PHY_A7_DOMAIN BIT(2)
31
32#define GPC_PU_PGC_SW_PUP_REQ 0x0f8
33#define GPC_PU_PGC_SW_PDN_REQ 0x104
34#define USB_HSIC_PHY_SW_Pxx_REQ BIT(4)
35#define USB_OTG2_PHY_SW_Pxx_REQ BIT(3)
36#define USB_OTG1_PHY_SW_Pxx_REQ BIT(2)
37#define PCIE_PHY_SW_Pxx_REQ BIT(1)
38#define MIPI_PHY_SW_Pxx_REQ BIT(0)
39
40#define GPC_M4_PU_PDN_FLG 0x1bc
41
42
43#define PGC_MIPI 4
44#define PGC_PCIE 5
45#define PGC_USB_HSIC 8
46#define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40)
47#define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc)
48
49#define GPC_PGC_CTRL_PCR BIT(0)
50
51struct imx7_pgc_domain {
52 struct generic_pm_domain genpd;
53 struct regmap *regmap;
54 struct regulator *regulator;
55
56 unsigned int pgc;
57
58 const struct {
59 u32 pxx;
60 u32 map;
61 } bits;
62
63 const int voltage;
64 struct device *dev;
65};
66
67static int imx7_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
68 bool on)
69{
70 struct imx7_pgc_domain *domain = container_of(genpd,
71 struct imx7_pgc_domain,
72 genpd);
73 unsigned int offset = on ?
74 GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ;
75 const bool enable_power_control = !on;
76 const bool has_regulator = !IS_ERR(domain->regulator);
77 unsigned long deadline;
78 int ret = 0;
79
80 regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
81 domain->bits.map, domain->bits.map);
82
83 if (has_regulator && on) {
84 ret = regulator_enable(domain->regulator);
85 if (ret) {
86 dev_err(domain->dev, "failed to enable regulator\n");
87 goto unmap;
88 }
89 }
90
91 if (enable_power_control)
92 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
93 GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
94
95 regmap_update_bits(domain->regmap, offset,
96 domain->bits.pxx, domain->bits.pxx);
97
98 /*
99 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
100 * for PUP_REQ/PDN_REQ bit to be cleared
101 */
102 deadline = jiffies + msecs_to_jiffies(1);
103 while (true) {
104 u32 pxx_req;
105
106 regmap_read(domain->regmap, offset, &pxx_req);
107
108 if (!(pxx_req & domain->bits.pxx))
109 break;
110
111 if (time_after(jiffies, deadline)) {
112 dev_err(domain->dev, "falied to command PGC\n");
113 ret = -ETIMEDOUT;
114 /*
115 * If we were in a process of enabling a
116 * domain and failed we might as well disable
117 * the regulator we just enabled. And if it
118 * was the opposite situation and we failed to
119 * power down -- keep the regulator on
120 */
121 on = !on;
122 break;
123 }
124
125 cpu_relax();
126 }
127
128 if (enable_power_control)
129 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
130 GPC_PGC_CTRL_PCR, 0);
131
132 if (has_regulator && !on) {
133 int err;
134
135 err = regulator_disable(domain->regulator);
136 if (err)
137 dev_err(domain->dev,
138 "failed to disable regulator: %d\n", ret);
139 /* Preserve earlier error code */
140 ret = ret ?: err;
141 }
142unmap:
143 regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
144 domain->bits.map, 0);
145 return ret;
146}
147
148static int imx7_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd)
149{
150 return imx7_gpc_pu_pgc_sw_pxx_req(genpd, true);
151}
152
153static int imx7_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd)
154{
155 return imx7_gpc_pu_pgc_sw_pxx_req(genpd, false);
156}
157
158static struct imx7_pgc_domain imx7_pgc_domains[] = {
159 [IMX7_POWER_DOMAIN_MIPI_PHY] = {
160 .genpd = {
161 .name = "mipi-phy",
162 },
163 .bits = {
164 .pxx = MIPI_PHY_SW_Pxx_REQ,
165 .map = MIPI_PHY_A7_DOMAIN,
166 },
167 .voltage = 1000000,
168 .pgc = PGC_MIPI,
169 },
170
171 [IMX7_POWER_DOMAIN_PCIE_PHY] = {
172 .genpd = {
173 .name = "pcie-phy",
174 },
175 .bits = {
176 .pxx = PCIE_PHY_SW_Pxx_REQ,
177 .map = PCIE_PHY_A7_DOMAIN,
178 },
179 .voltage = 1000000,
180 .pgc = PGC_PCIE,
181 },
182
183 [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
184 .genpd = {
185 .name = "usb-hsic-phy",
186 },
187 .bits = {
188 .pxx = USB_HSIC_PHY_SW_Pxx_REQ,
189 .map = USB_HSIC_PHY_A7_DOMAIN,
190 },
191 .voltage = 1200000,
192 .pgc = PGC_USB_HSIC,
193 },
194};
195
196static int imx7_pgc_domain_probe(struct platform_device *pdev)
197{
198 struct imx7_pgc_domain *domain = pdev->dev.platform_data;
199 int ret;
200
201 domain->dev = &pdev->dev;
202
203 ret = pm_genpd_init(&domain->genpd, NULL, true);
204 if (ret) {
205 dev_err(domain->dev, "Failed to init power domain\n");
206 return ret;
207 }
208
209 domain->regulator = devm_regulator_get_optional(domain->dev, "power");
210 if (IS_ERR(domain->regulator)) {
211 if (PTR_ERR(domain->regulator) != -ENODEV) {
212 dev_err(domain->dev, "Failed to get domain's regulator\n");
213 return PTR_ERR(domain->regulator);
214 }
215 } else {
216 regulator_set_voltage(domain->regulator,
217 domain->voltage, domain->voltage);
218 }
219
220 ret = of_genpd_add_provider_simple(domain->dev->of_node,
221 &domain->genpd);
222 if (ret) {
223 dev_err(domain->dev, "Failed to add genpd provider\n");
224 pm_genpd_remove(&domain->genpd);
225 }
226
227 return ret;
228}
229
230static int imx7_pgc_domain_remove(struct platform_device *pdev)
231{
232 struct imx7_pgc_domain *domain = pdev->dev.platform_data;
233
234 of_genpd_del_provider(domain->dev->of_node);
235 pm_genpd_remove(&domain->genpd);
236
237 return 0;
238}
239
240static const struct platform_device_id imx7_pgc_domain_id[] = {
241 { "imx7-pgc-domain", },
242 { },
243};
244
245static struct platform_driver imx7_pgc_domain_driver = {
246 .driver = {
247 .name = "imx7-pgc",
248 },
249 .probe = imx7_pgc_domain_probe,
250 .remove = imx7_pgc_domain_remove,
251 .id_table = imx7_pgc_domain_id,
252};
253builtin_platform_driver(imx7_pgc_domain_driver)
254
255static int imx_gpcv2_probe(struct platform_device *pdev)
256{
257 static const struct regmap_range yes_ranges[] = {
258 regmap_reg_range(GPC_LPCR_A7_BSC,
259 GPC_M4_PU_PDN_FLG),
260 regmap_reg_range(GPC_PGC_CTRL(PGC_MIPI),
261 GPC_PGC_SR(PGC_MIPI)),
262 regmap_reg_range(GPC_PGC_CTRL(PGC_PCIE),
263 GPC_PGC_SR(PGC_PCIE)),
264 regmap_reg_range(GPC_PGC_CTRL(PGC_USB_HSIC),
265 GPC_PGC_SR(PGC_USB_HSIC)),
266 };
267 static const struct regmap_access_table access_table = {
268 .yes_ranges = yes_ranges,
269 .n_yes_ranges = ARRAY_SIZE(yes_ranges),
270 };
271 static const struct regmap_config regmap_config = {
272 .reg_bits = 32,
273 .val_bits = 32,
274 .reg_stride = 4,
275 .rd_table = &access_table,
276 .wr_table = &access_table,
277 .max_register = SZ_4K,
278 };
279 struct device *dev = &pdev->dev;
280 struct device_node *pgc_np, *np;
281 struct regmap *regmap;
282 struct resource *res;
283 void __iomem *base;
284 int ret;
285
286 pgc_np = of_get_child_by_name(dev->of_node, "pgc");
287 if (!pgc_np) {
288 dev_err(dev, "No power domains specified in DT\n");
289 return -EINVAL;
290 }
291
292 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
293 base = devm_ioremap_resource(dev, res);
294 if (IS_ERR(base))
295 return PTR_ERR(base);
296
297 regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
298 if (IS_ERR(regmap)) {
299 ret = PTR_ERR(regmap);
300 dev_err(dev, "failed to init regmap (%d)\n", ret);
301 return ret;
302 }
303
304 for_each_child_of_node(pgc_np, np) {
305 struct platform_device *pd_pdev;
306 struct imx7_pgc_domain *domain;
307 u32 domain_index;
308
309 ret = of_property_read_u32(np, "reg", &domain_index);
310 if (ret) {
311 dev_err(dev, "Failed to read 'reg' property\n");
312 of_node_put(np);
313 return ret;
314 }
315
316 if (domain_index >= ARRAY_SIZE(imx7_pgc_domains)) {
317 dev_warn(dev,
318 "Domain index %d is out of bounds\n",
319 domain_index);
320 continue;
321 }
322
323 domain = &imx7_pgc_domains[domain_index];
324 domain->regmap = regmap;
325 domain->genpd.power_on = imx7_gpc_pu_pgc_sw_pup_req;
326 domain->genpd.power_off = imx7_gpc_pu_pgc_sw_pdn_req;
327
328 pd_pdev = platform_device_alloc("imx7-pgc-domain",
329 domain_index);
330 if (!pd_pdev) {
331 dev_err(dev, "Failed to allocate platform device\n");
332 of_node_put(np);
333 return -ENOMEM;
334 }
335
336 pd_pdev->dev.platform_data = domain;
337 pd_pdev->dev.parent = dev;
338 pd_pdev->dev.of_node = np;
339
340 ret = platform_device_add(pd_pdev);
341 if (ret) {
342 platform_device_put(pd_pdev);
343 of_node_put(np);
344 return ret;
345 }
346 }
347
348 return 0;
349}
350
351static const struct of_device_id imx_gpcv2_dt_ids[] = {
352 { .compatible = "fsl,imx7d-gpc" },
353 { }
354};
355
356static struct platform_driver imx_gpc_driver = {
357 .driver = {
358 .name = "imx-gpcv2",
359 .of_match_table = imx_gpcv2_dt_ids,
360 },
361 .probe = imx_gpcv2_probe,
362};
363builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/soc/renesas/r8a7795-sysc.c b/drivers/soc/renesas/r8a7795-sysc.c
index 5e7537c96f7b..7412666187b3 100644
--- a/drivers/soc/renesas/r8a7795-sysc.c
+++ b/drivers/soc/renesas/r8a7795-sysc.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Renesas R-Car H3 System Controller 2 * Renesas R-Car H3 System Controller
3 * 3 *
4 * Copyright (C) 2016 Glider bvba 4 * Copyright (C) 2016-2017 Glider bvba
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -10,12 +10,13 @@
10 10
11#include <linux/bug.h> 11#include <linux/bug.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/sys_soc.h>
13 14
14#include <dt-bindings/power/r8a7795-sysc.h> 15#include <dt-bindings/power/r8a7795-sysc.h>
15 16
16#include "rcar-sysc.h" 17#include "rcar-sysc.h"
17 18
18static const struct rcar_sysc_area r8a7795_areas[] __initconst = { 19static struct rcar_sysc_area r8a7795_areas[] __initdata = {
19 { "always-on", 0, 0, R8A7795_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, 20 { "always-on", 0, 0, R8A7795_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
20 { "ca57-scu", 0x1c0, 0, R8A7795_PD_CA57_SCU, R8A7795_PD_ALWAYS_ON, 21 { "ca57-scu", 0x1c0, 0, R8A7795_PD_CA57_SCU, R8A7795_PD_ALWAYS_ON,
21 PD_SCU }, 22 PD_SCU },
@@ -40,6 +41,7 @@ static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
40 { "a3vp", 0x340, 0, R8A7795_PD_A3VP, R8A7795_PD_ALWAYS_ON }, 41 { "a3vp", 0x340, 0, R8A7795_PD_A3VP, R8A7795_PD_ALWAYS_ON },
41 { "cr7", 0x240, 0, R8A7795_PD_CR7, R8A7795_PD_ALWAYS_ON }, 42 { "cr7", 0x240, 0, R8A7795_PD_CR7, R8A7795_PD_ALWAYS_ON },
42 { "a3vc", 0x380, 0, R8A7795_PD_A3VC, R8A7795_PD_ALWAYS_ON }, 43 { "a3vc", 0x380, 0, R8A7795_PD_A3VC, R8A7795_PD_ALWAYS_ON },
44 /* A2VC0 exists on ES1.x only */
43 { "a2vc0", 0x3c0, 0, R8A7795_PD_A2VC0, R8A7795_PD_A3VC }, 45 { "a2vc0", 0x3c0, 0, R8A7795_PD_A2VC0, R8A7795_PD_A3VC },
44 { "a2vc1", 0x3c0, 1, R8A7795_PD_A2VC1, R8A7795_PD_A3VC }, 46 { "a2vc1", 0x3c0, 1, R8A7795_PD_A2VC1, R8A7795_PD_A3VC },
45 { "3dg-a", 0x100, 0, R8A7795_PD_3DG_A, R8A7795_PD_ALWAYS_ON }, 47 { "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 = {
50 { "a3ir", 0x180, 0, R8A7795_PD_A3IR, R8A7795_PD_ALWAYS_ON }, 52 { "a3ir", 0x180, 0, R8A7795_PD_A3IR, R8A7795_PD_ALWAYS_ON },
51}; 53};
52 54
55
56 /*
57 * Fixups for R-Car H3 revisions after ES1.x
58 */
59
60static const struct soc_device_attribute r8a7795es1[] __initconst = {
61 { .soc_id = "r8a7795", .revision = "ES1.*" },
62 { /* sentinel */ }
63};
64
65static int __init r8a7795_sysc_init(void)
66{
67 if (!soc_device_match(r8a7795es1))
68 rcar_sysc_nullify(r8a7795_areas, ARRAY_SIZE(r8a7795_areas),
69 R8A7795_PD_A2VC0);
70
71 return 0;
72}
73
53const struct rcar_sysc_info r8a7795_sysc_info __initconst = { 74const struct rcar_sysc_info r8a7795_sysc_info __initconst = {
75 .init = r8a7795_sysc_init,
54 .areas = r8a7795_areas, 76 .areas = r8a7795_areas,
55 .num_areas = ARRAY_SIZE(r8a7795_areas), 77 .num_areas = ARRAY_SIZE(r8a7795_areas),
56}; 78};
diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c
index 225c35c79d9a..528a13742aeb 100644
--- a/drivers/soc/renesas/rcar-sysc.c
+++ b/drivers/soc/renesas/rcar-sysc.c
@@ -2,7 +2,7 @@
2 * R-Car SYSC Power management support 2 * R-Car SYSC Power management support
3 * 3 *
4 * Copyright (C) 2014 Magnus Damm 4 * Copyright (C) 2014 Magnus Damm
5 * Copyright (C) 2015-2016 Glider bvba 5 * Copyright (C) 2015-2017 Glider bvba
6 * 6 *
7 * This file is subject to the terms and conditions of the GNU General Public 7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive 8 * License. See the file "COPYING" in the main directory of this archive
@@ -334,6 +334,12 @@ static int __init rcar_sysc_pd_init(void)
334 334
335 info = match->data; 335 info = match->data;
336 336
337 if (info->init) {
338 error = info->init();
339 if (error)
340 return error;
341 }
342
337 has_cpg_mstp = of_find_compatible_node(NULL, NULL, 343 has_cpg_mstp = of_find_compatible_node(NULL, NULL,
338 "renesas,cpg-mstp-clocks"); 344 "renesas,cpg-mstp-clocks");
339 345
@@ -377,6 +383,11 @@ static int __init rcar_sysc_pd_init(void)
377 const struct rcar_sysc_area *area = &info->areas[i]; 383 const struct rcar_sysc_area *area = &info->areas[i];
378 struct rcar_sysc_pd *pd; 384 struct rcar_sysc_pd *pd;
379 385
386 if (!area->name) {
387 /* Skip NULLified area */
388 continue;
389 }
390
380 pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL); 391 pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL);
381 if (!pd) { 392 if (!pd) {
382 error = -ENOMEM; 393 error = -ENOMEM;
@@ -406,6 +417,18 @@ out_put:
406} 417}
407early_initcall(rcar_sysc_pd_init); 418early_initcall(rcar_sysc_pd_init);
408 419
420void __init rcar_sysc_nullify(struct rcar_sysc_area *areas,
421 unsigned int num_areas, u8 id)
422{
423 unsigned int i;
424
425 for (i = 0; i < num_areas; i++)
426 if (areas[i].isr_bit == id) {
427 areas[i].name = NULL;
428 return;
429 }
430}
431
409void __init rcar_sysc_init(phys_addr_t base, u32 syscier) 432void __init rcar_sysc_init(phys_addr_t base, u32 syscier)
410{ 433{
411 u32 syscimr; 434 u32 syscimr;
diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h
index f6e842e2976e..07edb049a401 100644
--- a/drivers/soc/renesas/rcar-sysc.h
+++ b/drivers/soc/renesas/rcar-sysc.h
@@ -46,6 +46,7 @@ struct rcar_sysc_area {
46 */ 46 */
47 47
48struct rcar_sysc_info { 48struct rcar_sysc_info {
49 int (*init)(void); /* Optional */
49 const struct rcar_sysc_area *areas; 50 const struct rcar_sysc_area *areas;
50 unsigned int num_areas; 51 unsigned int num_areas;
51}; 52};
@@ -59,4 +60,13 @@ extern const struct rcar_sysc_info r8a7792_sysc_info;
59extern const struct rcar_sysc_info r8a7794_sysc_info; 60extern const struct rcar_sysc_info r8a7794_sysc_info;
60extern const struct rcar_sysc_info r8a7795_sysc_info; 61extern const struct rcar_sysc_info r8a7795_sysc_info;
61extern const struct rcar_sysc_info r8a7796_sysc_info; 62extern const struct rcar_sysc_info r8a7796_sysc_info;
63
64
65 /*
66 * Helpers for fixing up power area tables depending on SoC revision
67 */
68
69extern void rcar_sysc_nullify(struct rcar_sysc_area *areas,
70 unsigned int num_areas, u8 id);
71
62#endif /* __SOC_RENESAS_RCAR_SYSC_H__ */ 72#endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c
index 330960312296..ca26f13d399c 100644
--- a/drivers/soc/renesas/renesas-soc.c
+++ b/drivers/soc/renesas/renesas-soc.c
@@ -80,11 +80,21 @@ static const struct renesas_soc soc_rmobile_a1 __initconst __maybe_unused = {
80 .id = 0x40, 80 .id = 0x40,
81}; 81};
82 82
83static const struct renesas_soc soc_rz_g1h __initconst __maybe_unused = {
84 .family = &fam_rzg,
85 .id = 0x45,
86};
87
83static const struct renesas_soc soc_rz_g1m __initconst __maybe_unused = { 88static const struct renesas_soc soc_rz_g1m __initconst __maybe_unused = {
84 .family = &fam_rzg, 89 .family = &fam_rzg,
85 .id = 0x47, 90 .id = 0x47,
86}; 91};
87 92
93static const struct renesas_soc soc_rz_g1n __initconst __maybe_unused = {
94 .family = &fam_rzg,
95 .id = 0x4b,
96};
97
88static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = { 98static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = {
89 .family = &fam_rzg, 99 .family = &fam_rzg,
90 .id = 0x4c, 100 .id = 0x4c,
@@ -150,9 +160,15 @@ static const struct of_device_id renesas_socs[] __initconst = {
150#ifdef CONFIG_ARCH_R8A7740 160#ifdef CONFIG_ARCH_R8A7740
151 { .compatible = "renesas,r8a7740", .data = &soc_rmobile_a1 }, 161 { .compatible = "renesas,r8a7740", .data = &soc_rmobile_a1 },
152#endif 162#endif
163#ifdef CONFIG_ARCH_R8A7742
164 { .compatible = "renesas,r8a7742", .data = &soc_rz_g1h },
165#endif
153#ifdef CONFIG_ARCH_R8A7743 166#ifdef CONFIG_ARCH_R8A7743
154 { .compatible = "renesas,r8a7743", .data = &soc_rz_g1m }, 167 { .compatible = "renesas,r8a7743", .data = &soc_rz_g1m },
155#endif 168#endif
169#ifdef CONFIG_ARCH_R8A7744
170 { .compatible = "renesas,r8a7744", .data = &soc_rz_g1n },
171#endif
156#ifdef CONFIG_ARCH_R8A7745 172#ifdef CONFIG_ARCH_R8A7745
157 { .compatible = "renesas,r8a7745", .data = &soc_rz_g1e }, 173 { .compatible = "renesas,r8a7745", .data = &soc_rz_g1e },
158#endif 174#endif
@@ -254,4 +270,4 @@ static int __init renesas_soc_init(void)
254 270
255 return 0; 271 return 0;
256} 272}
257core_initcall(renesas_soc_init); 273early_initcall(renesas_soc_init);
diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
index 245533907d1b..8b25bd55e648 100644
--- a/drivers/soc/samsung/Kconfig
+++ b/drivers/soc/samsung/Kconfig
@@ -8,7 +8,13 @@ if SOC_SAMSUNG
8 8
9config EXYNOS_PMU 9config EXYNOS_PMU
10 bool "Exynos PMU controller driver" if COMPILE_TEST 10 bool "Exynos PMU controller driver" if COMPILE_TEST
11 depends on (ARM && ARCH_EXYNOS) || ((ARM || ARM64) && COMPILE_TEST) 11 depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)
12 select EXYNOS_PMU_ARM_DRIVERS if ARM && ARCH_EXYNOS
13
14# There is no need to enable these drivers for ARMv8
15config EXYNOS_PMU_ARM_DRIVERS
16 bool "Exynos PMU ARMv7-specific driver extensions" if COMPILE_TEST
17 depends on EXYNOS_PMU
12 18
13config EXYNOS_PM_DOMAINS 19config EXYNOS_PM_DOMAINS
14 bool "Exynos PM domains" if COMPILE_TEST 20 bool "Exynos PM domains" if COMPILE_TEST
diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
index 3619f2ecddaa..4d7694a4e7a4 100644
--- a/drivers/soc/samsung/Makefile
+++ b/drivers/soc/samsung/Makefile
@@ -1,3 +1,5 @@
1obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o exynos3250-pmu.o exynos4-pmu.o \ 1obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o
2
3obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \
2 exynos5250-pmu.o exynos5420-pmu.o 4 exynos5250-pmu.o exynos5420-pmu.o
3obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o 5obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index 56d9244ff981..bd4a76f27bc2 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -69,27 +69,37 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
69} 69}
70 70
71/* 71/*
72 * Split the data between ARM architectures because it is relatively big
73 * and useless on other arch.
74 */
75#ifdef CONFIG_EXYNOS_PMU_ARM_DRIVERS
76#define exynos_pmu_data_arm_ptr(data) (&data)
77#else
78#define exynos_pmu_data_arm_ptr(data) NULL
79#endif
80
81/*
72 * PMU platform driver and devicetree bindings. 82 * PMU platform driver and devicetree bindings.
73 */ 83 */
74static const struct of_device_id exynos_pmu_of_device_ids[] = { 84static const struct of_device_id exynos_pmu_of_device_ids[] = {
75 { 85 {
76 .compatible = "samsung,exynos3250-pmu", 86 .compatible = "samsung,exynos3250-pmu",
77 .data = &exynos3250_pmu_data, 87 .data = exynos_pmu_data_arm_ptr(exynos3250_pmu_data),
78 }, { 88 }, {
79 .compatible = "samsung,exynos4210-pmu", 89 .compatible = "samsung,exynos4210-pmu",
80 .data = &exynos4210_pmu_data, 90 .data = exynos_pmu_data_arm_ptr(exynos4210_pmu_data),
81 }, { 91 }, {
82 .compatible = "samsung,exynos4212-pmu", 92 .compatible = "samsung,exynos4212-pmu",
83 .data = &exynos4212_pmu_data, 93 .data = exynos_pmu_data_arm_ptr(exynos4212_pmu_data),
84 }, { 94 }, {
85 .compatible = "samsung,exynos4412-pmu", 95 .compatible = "samsung,exynos4412-pmu",
86 .data = &exynos4412_pmu_data, 96 .data = exynos_pmu_data_arm_ptr(exynos4412_pmu_data),
87 }, { 97 }, {
88 .compatible = "samsung,exynos5250-pmu", 98 .compatible = "samsung,exynos5250-pmu",
89 .data = &exynos5250_pmu_data, 99 .data = exynos_pmu_data_arm_ptr(exynos5250_pmu_data),
90 }, { 100 }, {
91 .compatible = "samsung,exynos5420-pmu", 101 .compatible = "samsung,exynos5420-pmu",
92 .data = &exynos5420_pmu_data, 102 .data = exynos_pmu_data_arm_ptr(exynos5420_pmu_data),
93 }, { 103 }, {
94 .compatible = "samsung,exynos5433-pmu", 104 .compatible = "samsung,exynos5433-pmu",
95 }, 105 },
diff --git a/drivers/soc/samsung/exynos-pmu.h b/drivers/soc/samsung/exynos-pmu.h
index a469e366fead..40d4229abfb5 100644
--- a/drivers/soc/samsung/exynos-pmu.h
+++ b/drivers/soc/samsung/exynos-pmu.h
@@ -31,6 +31,8 @@ struct exynos_pmu_data {
31}; 31};
32 32
33extern void __iomem *pmu_base_addr; 33extern void __iomem *pmu_base_addr;
34
35#ifdef CONFIG_EXYNOS_PMU_ARM_DRIVERS
34/* list of all exported SoC specific data */ 36/* list of all exported SoC specific data */
35extern const struct exynos_pmu_data exynos3250_pmu_data; 37extern const struct exynos_pmu_data exynos3250_pmu_data;
36extern const struct exynos_pmu_data exynos4210_pmu_data; 38extern const struct exynos_pmu_data exynos4210_pmu_data;
@@ -38,6 +40,7 @@ extern const struct exynos_pmu_data exynos4212_pmu_data;
38extern const struct exynos_pmu_data exynos4412_pmu_data; 40extern const struct exynos_pmu_data exynos4412_pmu_data;
39extern const struct exynos_pmu_data exynos5250_pmu_data;