diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-09 13:01:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-09 13:01:15 -0400 |
commit | 0160e00ae8e987be8822745fb166aa76451c9bcc (patch) | |
tree | deca2d09a729155ed0cb631f2bc8f557e634ab06 | |
parent | c81ee18e97e4e3162169a749eb7f2b79b3510c7a (diff) | |
parent | b6942b68f85ed3161c91741791ec6f1779574919 (diff) |
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
...
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 @@ | |||
1 | NVIDIA Tegra Power Management Controller (PMC) | ||
2 | |||
3 | Required 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 | |||
14 | Optional properties: | ||
15 | - nvidia,invert-interrupt: If present, inverts the PMU interrupt signal. | ||
16 | |||
17 | Example: | ||
18 | |||
19 | SoC 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 | |||
30 | Board 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 @@ | |||
1 | Freescale i.MX General Power Controller | 1 | Freescale i.MX General Power Controller |
2 | ======================================= | 2 | ======================================= |
3 | 3 | ||
4 | The i.MX6Q General Power Control (GPC) block contains DVFS load tracking | 4 | The i.MX6 General Power Control (GPC) block contains DVFS load tracking |
5 | counters and Power Gating Control (PGC) for the CPU and PU (GPU/VPU) power | 5 | counters and Power Gating Control (PGC). |
6 | domains. | ||
7 | 6 | ||
8 | Required properties: | 7 | Required 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 | ||
18 | The gpc node is a power-controller as documented by the generic power domain | 20 | The power domains are generic power domain providers as documented in |
19 | bindings in Documentation/devicetree/bindings/power/power_domain.txt. | 21 | Documentation/devicetree/bindings/power/power_domain.txt. They are described as |
22 | subnodes of the power gating controller 'pgc' node of the GPC and should | ||
23 | contain the following: | ||
24 | |||
25 | Required 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 | |||
35 | Optional 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 | ||
21 | Example: | 41 | Example: |
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 = <®_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 = <®_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 | ||
42 | IP cores belonging to a power domain should contain a 'power-domains' property | 78 | IP cores belonging to a power domain should contain a 'power-domains' property |
43 | that is a phandle pointing to the gpc device node and a DOMAIN_INDEX specifying | 79 | that is a phandle pointing to the power domain the device belongs to. |
44 | the power domain the device belongs to. | ||
45 | 80 | ||
46 | Example of a device that is part of the PU power domain: | 81 | Example 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 | |||
55 | The following DOMAIN_INDEX values are valid for i.MX6Q: | ||
56 | ARM_DOMAIN 0 | ||
57 | PU_DOMAIN 1 | ||
58 | The following additional DOMAIN_INDEX value is valid for i.MX6SL: | ||
59 | DISPLAY_DOMAIN 2 | ||
diff --git a/Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt b/Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt new file mode 100644 index 000000000000..02f45c65fd87 --- /dev/null +++ b/Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt | |||
@@ -0,0 +1,71 @@ | |||
1 | Freescale i.MX General Power Controller v2 | ||
2 | ========================================== | ||
3 | |||
4 | The i.MX7S/D General Power Control (GPC) block contains Power Gating | ||
5 | Control (PGC) for various power domains. | ||
6 | |||
7 | Required 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 | |||
16 | Power domains contained within GPC node are generic power domain | ||
17 | providers, documented in | ||
18 | Documentation/devicetree/bindings/power/power_domain.txt, which are | ||
19 | described as subnodes of the power gating controller 'pgc' node, | ||
20 | which, in turn, is expected to contain the following: | ||
21 | |||
22 | Required 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 | |||
29 | Optional properties: | ||
30 | |||
31 | - power-supply: Power supply used to power the domain | ||
32 | |||
33 | Example: | ||
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 = <®_1p0d>; | ||
52 | }; | ||
53 | }; | ||
54 | }; | ||
55 | |||
56 | |||
57 | Specifying power domain for IP modules | ||
58 | ====================================== | ||
59 | |||
60 | IP cores belonging to a power domain should contain a 'power-domains' | ||
61 | property that is a phandle for PGC node representing the domain. | ||
62 | |||
63 | Example 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 @@ | |||
1 | Freescale i.MX7 System Reset Controller | ||
2 | ====================================== | ||
3 | |||
4 | Please also refer to reset.txt in this directory for common reset | ||
5 | controller binding usage. | ||
6 | |||
7 | Required 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 | |||
14 | example: | ||
15 | |||
16 | src: 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 | |||
24 | Specifying reset lines connected to IP modules | ||
25 | ============================================== | ||
26 | |||
27 | The system reset controller can be used to reset various set of | ||
28 | peripherals. Device nodes that need access to reset lines should | ||
29 | specify them as a reset phandle in their corresponding node as | ||
30 | specified in reset.txt. | ||
31 | |||
32 | Example: | ||
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 | |||
46 | For 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 @@ | |||
1 | Texas Instruments TI-SCI Generic Power Domain | ||
2 | --------------------------------------------- | ||
3 | |||
4 | Some TI SoCs contain a system controller (like the PMMC, etc...) that is | ||
5 | responsible for controlling the state of the IPs that are present. | ||
6 | Communication between the host processor running an OS and the system | ||
7 | controller happens through a protocol known as TI-SCI [1]. | ||
8 | |||
9 | [1] Documentation/devicetree/bindings/arm/keystone/ti,sci.txt | ||
10 | |||
11 | PM Domain Node | ||
12 | ============== | ||
13 | The PM domain node represents the global PM domain managed by the PMMC, which | ||
14 | in this case is the implementation as documented by the generic PM domain | ||
15 | bindings in Documentation/devicetree/bindings/power/power_domain.txt. Because | ||
16 | this relies on the TI SCI protocol to communicate with the PMMC it must be a | ||
17 | child of the pmmc node. | ||
18 | |||
19 | Required 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 | |||
25 | Example (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 | |||
37 | PM Domain Consumers | ||
38 | =================== | ||
39 | Hardware blocks belonging to a PM domain should contain a "power-domains" | ||
40 | property that is a phandle pointing to the corresponding PM domain node | ||
41 | along with an index representing the device id to be passed to the PMMC | ||
42 | for device control. | ||
43 | |||
44 | Required Properties: | ||
45 | -------------------- | ||
46 | - power-domains: phandle pointing to the corresponding PM domain node | ||
47 | and an ID representing the device. | ||
48 | |||
49 | See dt-bindings/genpd/k2g.h for the list of valid identifiers for k2g. | ||
50 | |||
51 | Example (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> | |||
653 | S: Maintained | 653 | S: Maintained |
654 | F: drivers/gpio/gpio-altera-a10sr.c | 654 | F: drivers/gpio/gpio-altera-a10sr.c |
655 | F: drivers/mfd/altera-a10sr.c | 655 | F: drivers/mfd/altera-a10sr.c |
656 | F: drivers/reset/reset-a10sr.c | ||
656 | F: include/linux/mfd/altera-a10sr.h | 657 | F: include/linux/mfd/altera-a10sr.h |
658 | F: include/dt-bindings/reset/altr,rst-mgr-a10sr.h | ||
657 | 659 | ||
658 | ALTERA TRIPLE SPEED ETHERNET DRIVER | 660 | ALTERA TRIPLE SPEED ETHERNET DRIVER |
659 | M: Vince Bridgers <vbridger@opensource.altera.com> | 661 | M: Vince Bridgers <vbridger@opensource.altera.com> |
@@ -1282,6 +1284,7 @@ F: arch/arm/mach-mxs/ | |||
1282 | F: arch/arm/boot/dts/imx* | 1284 | F: arch/arm/boot/dts/imx* |
1283 | F: arch/arm/configs/imx*_defconfig | 1285 | F: arch/arm/configs/imx*_defconfig |
1284 | F: drivers/clk/imx/ | 1286 | F: drivers/clk/imx/ |
1287 | F: drivers/soc/imx/ | ||
1285 | F: include/soc/imx/ | 1288 | F: include/soc/imx/ |
1286 | 1289 | ||
1287 | ARM/FREESCALE VYBRID ARM ARCHITECTURE | 1290 | ARM/FREESCALE VYBRID ARM ARCHITECTURE |
@@ -12604,6 +12607,9 @@ S: Maintained | |||
12604 | F: Documentation/devicetree/bindings/arm/keystone/ti,sci.txt | 12607 | F: Documentation/devicetree/bindings/arm/keystone/ti,sci.txt |
12605 | F: drivers/firmware/ti_sci* | 12608 | F: drivers/firmware/ti_sci* |
12606 | F: include/linux/soc/ti/ti_sci_protocol.h | 12609 | F: include/linux/soc/ti/ti_sci_protocol.h |
12610 | F: Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt | ||
12611 | F: include/dt-bindings/genpd/k2g.h | ||
12612 | F: drivers/soc/ti/ti_sci_pm_domains.c | ||
12607 | 12613 | ||
12608 | THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER | 12614 | THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER |
12609 | M: Hans Verkuil <hverkuil@xs4all.nl> | 12615 | M: 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 @@ | |||
1 | config ICST | ||
2 | bool | ||
3 | |||
4 | config SA1111 | 1 | config 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 | ||
5 | obj-y += firmware.o | 5 | obj-y += firmware.o |
6 | 6 | ||
7 | obj-$(CONFIG_ICST) += icst.o | ||
8 | obj-$(CONFIG_SA1111) += sa1111.o | 7 | obj-$(CONFIG_SA1111) += sa1111.o |
9 | obj-$(CONFIG_DMABOUNCE) += dmabounce.o | 8 | obj-$(CONFIG_DMABOUNCE) += dmabounce.o |
10 | obj-$(CONFIG_SHARP_LOCOMO) += locomo.o | 9 | obj-$(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 | |||
47 | struct 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 | |||
54 | static void __iomem *gpc_base; | 33 | static void __iomem *gpc_base; |
55 | static u32 gpc_wake_irqs[IMR_NUM]; | 34 | static u32 gpc_wake_irqs[IMR_NUM]; |
56 | static u32 gpc_saved_imrs[IMR_NUM]; | 35 | static 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 | |||
300 | static 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 | |||
322 | static 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 | |||
334 | static 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 | |||
374 | static struct generic_pm_domain imx6q_arm_domain = { | ||
375 | .name = "ARM", | ||
376 | }; | ||
377 | |||
378 | static 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 | |||
386 | static struct generic_pm_domain imx6sl_display_domain = { | ||
387 | .name = "DISPLAY", | ||
388 | }; | ||
389 | |||
390 | static struct generic_pm_domain *imx_gpc_domains[] = { | ||
391 | &imx6q_arm_domain, | ||
392 | &imx6q_pu_domain.base, | ||
393 | &imx6sl_display_domain, | ||
394 | }; | ||
395 | |||
396 | static struct genpd_onecell_data imx_gpc_onecell_data = { | ||
397 | .domains = imx_gpc_domains, | ||
398 | .num_domains = ARRAY_SIZE(imx_gpc_domains), | ||
399 | }; | ||
400 | |||
401 | static 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 | |||
446 | power_off: | ||
447 | imx6q_pm_pu_power_off(&imx6q_pu_domain.base); | ||
448 | clk_err: | ||
449 | while (i--) | ||
450 | clk_put(imx6q_pu_domain.clk[i]); | ||
451 | imx6q_pu_domain.reg = NULL; | ||
452 | return -EINVAL; | ||
453 | } | ||
454 | |||
455 | static 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 | |||
476 | static const struct of_device_id imx_gpc_dt_ids[] = { | ||
477 | { .compatible = "fsl,imx6q-gpc" }, | ||
478 | { .compatible = "fsl,imx6sl-gpc" }, | ||
479 | { } | ||
480 | }; | ||
481 | |||
482 | static 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 | |||
490 | static int __init imx_pgc_init(void) | ||
491 | { | ||
492 | return platform_driver_register(&imx_gpc_driver); | ||
493 | } | ||
494 | subsys_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 | ||
34 | static const struct of_device_id of_keystone_table[] = { | 34 | static 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 | ||
3 | obj-y += io.o | 3 | obj-y += io.o |
4 | obj-y += irq.o | 4 | obj-y += irq.o |
5 | obj-y += flowctrl.o | ||
6 | obj-y += pm.o | 5 | obj-y += pm.o |
7 | obj-y += reset.o | 6 | obj-y += reset.o |
8 | obj-y += reset-handler.o | 7 | obj-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 | ||
81 | static void __init tegra_dt_init_irq(void) | 79 | static void __init tegra_dt_init_irq(void) |
diff --git a/arch/arm/plat-versatile/include/plat/clock.h b/arch/arm/plat-versatile/include/plat/clock.h deleted file mode 100644 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 | |||
6 | struct 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 | |||
12 | int icst_clk_set(struct clk *, unsigned long); | ||
13 | long 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 | ||
521 | config 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 | |||
521 | config PATA_CMD64X | 530 | config 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 | |||
51 | obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o | 51 | obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o |
52 | obj-$(CONFIG_PATA_ATP867X) += pata_atp867x.o | 52 | obj-$(CONFIG_PATA_ATP867X) += pata_atp867x.o |
53 | obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o | 53 | obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o |
54 | obj-$(CONFIG_PATA_BK3710) += pata_bk3710.o | ||
54 | obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o | 55 | obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o |
55 | obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o | 56 | obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o |
56 | obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o | 57 | obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o |
diff --git a/drivers/ata/pata_bk3710.c b/drivers/ata/pata_bk3710.c new file mode 100644 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 | |||
48 | static struct scsi_host_template pata_bk3710_sht = { | ||
49 | ATA_BMDMA_SHT(DRV_NAME), | ||
50 | }; | ||
51 | |||
52 | static unsigned int ideclk_period; /* in nanoseconds */ | ||
53 | |||
54 | struct 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 | |||
60 | static 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 | |||
69 | static 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 | |||
103 | static 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 | |||
135 | static 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 | |||
151 | static 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 | |||
200 | static 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 | |||
228 | static 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 | |||
285 | static 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 | |||
293 | static 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 */ | ||
368 | MODULE_ALIAS("platform:palm_bk3710"); | ||
369 | |||
370 | static struct platform_driver pata_bk3710_driver = { | ||
371 | .driver = { | ||
372 | .name = "palm_bk3710", | ||
373 | }, | ||
374 | }; | ||
375 | |||
376 | static int __init pata_bk3710_init(void) | ||
377 | { | ||
378 | return platform_driver_probe(&pata_bk3710_driver, pata_bk3710_probe); | ||
379 | } | ||
380 | |||
381 | module_init(pata_bk3710_init); | ||
382 | MODULE_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 | ||
112 | static struct soc_device_attribute *early_soc_dev_attr; | ||
113 | |||
112 | struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr) | 114 | struct 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 | ||
164 | static int __init soc_bus_register(void) | 168 | static 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 | } |
171 | core_initcall(soc_bus_register); | 181 | core_initcall(soc_bus_register); |
172 | 182 | ||
173 | static int soc_device_match_one(struct device *dev, void *arg) | 183 | static 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 | ||
205 | static 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 @@ | |||
1 | config ICST | ||
2 | bool | ||
3 | |||
1 | config COMMON_CLK_VERSATILE | 4 | config 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 |
2 | obj-$(CONFIG_ICST) += clk-icst.o clk-versatile.o | 2 | obj-$(CONFIG_ICST) += icst.o clk-icst.o clk-versatile.o |
3 | obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o | 3 | obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o |
4 | obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o | 4 | obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o |
5 | obj-$(CONFIG_CLK_SP810) += clk-sp810.o | 5 | obj-$(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 | ||
17 | struct icst_params { | 15 | struct 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 | */ |
139 | int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0, | 142 | int 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 | } |
161 | EXPORT_SYMBOL(meson_sm_call_read); | 173 | EXPORT_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 | |||
582 | int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, | ||
583 | u32 spare) | ||
584 | { | ||
585 | return -ENODEV; | ||
586 | } | ||
587 | |||
588 | int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, | ||
589 | size_t *size) | ||
590 | { | ||
591 | return -ENODEV; | ||
592 | } | ||
593 | |||
594 | int __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 | |||
385 | int __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 | |||
401 | int __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 | |||
420 | int __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 | ||
318 | int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) | ||
319 | { | ||
320 | return __qcom_scm_restore_sec_cfg(__scm->dev, device_id, spare); | ||
321 | } | ||
322 | EXPORT_SYMBOL(qcom_scm_restore_sec_cfg); | ||
323 | |||
324 | int 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 | } | ||
328 | EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_size); | ||
329 | |||
330 | int 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 | } | ||
334 | EXPORT_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 | ||
90 | extern 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 | ||
94 | extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, | ||
95 | size_t *size); | ||
96 | extern 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 | ||
15 | if RESET_CONTROLLER | 15 | if RESET_CONTROLLER |
16 | 16 | ||
17 | config 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 | |||
17 | config RESET_ATH79 | 24 | config 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 | ||
37 | config 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 | |||
30 | config RESET_LPC18XX | 44 | config 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 | |||
2 | obj-y += hisilicon/ | 2 | obj-y += hisilicon/ |
3 | obj-$(CONFIG_ARCH_STI) += sti/ | 3 | obj-$(CONFIG_ARCH_STI) += sti/ |
4 | obj-$(CONFIG_ARCH_TEGRA) += tegra/ | 4 | obj-$(CONFIG_ARCH_TEGRA) += tegra/ |
5 | obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o | ||
5 | obj-$(CONFIG_RESET_ATH79) += reset-ath79.o | 6 | obj-$(CONFIG_RESET_ATH79) += reset-ath79.o |
6 | obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o | 7 | obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o |
8 | obj-$(CONFIG_RESET_IMX7) += reset-imx7.o | ||
7 | obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o | 9 | obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o |
8 | obj-$(CONFIG_RESET_MESON) += reset-meson.o | 10 | obj-$(CONFIG_RESET_MESON) += reset-meson.o |
9 | obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o | 11 | obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o |
@@ -15,3 +17,4 @@ obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o | |||
15 | obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o | 17 | obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o |
16 | obj-$(CONFIG_RESET_ZX2967) += reset-zx2967.o | 18 | obj-$(CONFIG_RESET_ZX2967) += reset-zx2967.o |
17 | obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o | 19 | obj-$(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 | |||
30 | struct a10sr_reset { | ||
31 | struct reset_controller_dev rcdev; | ||
32 | struct regmap *regmap; | ||
33 | }; | ||
34 | |||
35 | static inline struct a10sr_reset *to_a10sr_rst(struct reset_controller_dev *rc) | ||
36 | { | ||
37 | return container_of(rc, struct a10sr_reset, rcdev); | ||
38 | } | ||
39 | |||
40 | static 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 | |||
55 | static 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 | |||
66 | static int a10sr_reset_assert(struct reset_controller_dev *rcdev, | ||
67 | unsigned long id) | ||
68 | { | ||
69 | return a10sr_reset_update(rcdev, id, true); | ||
70 | } | ||
71 | |||
72 | static int a10sr_reset_deassert(struct reset_controller_dev *rcdev, | ||
73 | unsigned long id) | ||
74 | { | ||
75 | return a10sr_reset_update(rcdev, id, false); | ||
76 | } | ||
77 | |||
78 | static 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 | |||
95 | static 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 | |||
101 | static 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 | |||
122 | static const struct of_device_id a10sr_reset_of_match[] = { | ||
123 | { .compatible = "altr,a10sr-reset" }, | ||
124 | { }, | ||
125 | }; | ||
126 | MODULE_DEVICE_TABLE(of, a10sr_reset_of_match); | ||
127 | |||
128 | static struct platform_driver a10sr_reset_driver = { | ||
129 | .probe = a10sr_reset_probe, | ||
130 | .driver = { | ||
131 | .name = "altr_a10sr_reset", | ||
132 | }, | ||
133 | }; | ||
134 | module_platform_driver(a10sr_reset_driver); | ||
135 | |||
136 | MODULE_AUTHOR("Thor Thayer <thor.thayer@linux.intel.com>"); | ||
137 | MODULE_DESCRIPTION("Altera Arria10 System Resource Reset Controller Driver"); | ||
138 | MODULE_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 | ||
130 | static 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 | |||
139 | static const struct of_device_id ath79_reset_dt_ids[] = { | 133 | static const struct of_device_id ath79_reset_dt_ids[] = { |
140 | { .compatible = "qca,ar7100-reset", }, | 134 | { .compatible = "qca,ar7100-reset", }, |
141 | { }, | 135 | { }, |
142 | }; | 136 | }; |
143 | MODULE_DEVICE_TABLE(of, ath79_reset_dt_ids); | ||
144 | 137 | ||
145 | static struct platform_driver ath79_reset_driver = { | 138 | static 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 | }; |
153 | module_platform_driver(ath79_reset_driver); | 146 | builtin_platform_driver(ath79_reset_driver); |
154 | |||
155 | MODULE_AUTHOR("Alban Bedel <albeu@free.fr>"); | ||
156 | MODULE_DESCRIPTION("AR71xx Reset Controller Driver"); | ||
157 | MODULE_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 | |||
24 | struct imx7_src { | ||
25 | struct reset_controller_dev rcdev; | ||
26 | struct regmap *regmap; | ||
27 | }; | ||
28 | |||
29 | enum 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 | |||
41 | struct imx7_src_signal { | ||
42 | unsigned int offset, bit; | ||
43 | }; | ||
44 | |||
45 | static 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 | |||
73 | static struct imx7_src *to_imx7_src(struct reset_controller_dev *rcdev) | ||
74 | { | ||
75 | return container_of(rcdev, struct imx7_src, rcdev); | ||
76 | } | ||
77 | |||
78 | static 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 | |||
104 | static int imx7_reset_assert(struct reset_controller_dev *rcdev, | ||
105 | unsigned long id) | ||
106 | { | ||
107 | return imx7_reset_set(rcdev, id, true); | ||
108 | } | ||
109 | |||
110 | static int imx7_reset_deassert(struct reset_controller_dev *rcdev, | ||
111 | unsigned long id) | ||
112 | { | ||
113 | return imx7_reset_set(rcdev, id, false); | ||
114 | } | ||
115 | |||
116 | static const struct reset_control_ops imx7_reset_ops = { | ||
117 | .assert = imx7_reset_assert, | ||
118 | .deassert = imx7_reset_deassert, | ||
119 | }; | ||
120 | |||
121 | static 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 | |||
146 | static const struct of_device_id imx7_reset_dt_ids[] = { | ||
147 | { .compatible = "fsl,imx7d-src", }, | ||
148 | { /* sentinel */ }, | ||
149 | }; | ||
150 | |||
151 | static 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 | }; | ||
158 | builtin_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 | }; |
98 | MODULE_DEVICE_TABLE(of, meson_reset_dt_ids); | ||
99 | 100 | ||
100 | static int meson_reset_probe(struct platform_device *pdev) | 101 | static 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 | 132 | builtin_platform_driver(meson_reset_driver); | |
132 | module_platform_driver(meson_reset_driver); | ||
133 | |||
134 | MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); | ||
135 | MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver"); | ||
136 | MODULE_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 | }; |
86 | MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids); | ||
87 | 86 | ||
88 | static int oxnas_reset_probe(struct platform_device *pdev) | 87 | static 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 | 125 | builtin_platform_driver(oxnas_reset_driver); | |
127 | module_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 | }; |
131 | MODULE_DEVICE_TABLE(of, pistachio_reset_dt_ids); | ||
132 | 131 | ||
133 | static struct platform_driver pistachio_reset_driver = { | 132 | static 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 | }; |
140 | module_platform_driver(pistachio_reset_driver); | 139 | builtin_platform_driver(pistachio_reset_driver); |
141 | |||
142 | MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>"); | ||
143 | MODULE_DESCRIPTION("Pistacho Reset Controller Driver"); | ||
144 | MODULE_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 | ||
30 | struct socfpga_reset_data { | 31 | struct 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 | ||
68 | const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = { | 77 | static 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 | ||
73 | const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = { | 83 | static 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 | ||
81 | const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = { | 92 | static 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 | ||
89 | const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = { | 101 | static 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 | ||
103 | const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = { | 116 | static 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 | ||
108 | const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = { | 123 | static 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 | ||
137 | const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = { | 154 | static 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 | ||
157 | const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = { | 174 | static 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 | ||
174 | const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = { | 191 | static 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 | ||
187 | const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = { | 204 | static 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" | |||
3 | source "drivers/soc/atmel/Kconfig" | 3 | source "drivers/soc/atmel/Kconfig" |
4 | source "drivers/soc/bcm/Kconfig" | 4 | source "drivers/soc/bcm/Kconfig" |
5 | source "drivers/soc/fsl/Kconfig" | 5 | source "drivers/soc/fsl/Kconfig" |
6 | source "drivers/soc/imx/Kconfig" | ||
6 | source "drivers/soc/mediatek/Kconfig" | 7 | source "drivers/soc/mediatek/Kconfig" |
7 | source "drivers/soc/qcom/Kconfig" | 8 | source "drivers/soc/qcom/Kconfig" |
8 | source "drivers/soc/rockchip/Kconfig" | 9 | source "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/ | |||
7 | obj-$(CONFIG_ARCH_DOVE) += dove/ | 7 | obj-$(CONFIG_ARCH_DOVE) += dove/ |
8 | obj-$(CONFIG_MACH_DOVE) += dove/ | 8 | obj-$(CONFIG_MACH_DOVE) += dove/ |
9 | obj-y += fsl/ | 9 | obj-y += fsl/ |
10 | obj-$(CONFIG_ARCH_MXC) += imx/ | ||
10 | obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ | 11 | obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ |
11 | obj-$(CONFIG_ARCH_QCOM) += qcom/ | 12 | obj-$(CONFIG_ARCH_QCOM) += qcom/ |
12 | obj-$(CONFIG_ARCH_RENESAS) += renesas/ | 13 | obj-$(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 | ||
43 | static const struct of_device_id sun_top_ctrl_match[] = { | 43 | static 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 @@ | |||
1 | menu "i.MX SoC drivers" | ||
2 | |||
3 | config 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 | |||
9 | endmenu | ||
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 @@ | |||
1 | obj-y += gpc.o | ||
2 | obj-$(CONFIG_IMX7_PM_DOMAINS) += gpcv2.o | ||
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c new file mode 100644 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 | |||
41 | struct 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 | |||
53 | static inline struct imx_pm_domain * | ||
54 | to_imx_pm_domain(struct generic_pm_domain *genpd) | ||
55 | { | ||
56 | return container_of(genpd, struct imx_pm_domain, base); | ||
57 | } | ||
58 | |||
59 | static 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 | |||
90 | static 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 | |||
132 | static 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 | |||
151 | clk_err: | ||
152 | while (i--) | ||
153 | clk_put(domain->clk[i]); | ||
154 | |||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | static 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 | |||
166 | static 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 | |||
181 | static 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 | |||
209 | genpd_err: | ||
210 | pm_genpd_remove(&domain->base); | ||
211 | imx_pgc_put_clocks(domain); | ||
212 | |||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | static 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 | |||
229 | static const struct platform_device_id imx_pgc_power_domain_id[] = { | ||
230 | { "imx-pgc-power-domain"}, | ||
231 | { }, | ||
232 | }; | ||
233 | |||
234 | static 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 | }; | ||
242 | builtin_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 | |||
248 | static struct genpd_power_state imx6_pm_domain_pu_state = { | ||
249 | .power_off_latency_ns = 25000, | ||
250 | .power_on_latency_ns = 2000000, | ||
251 | }; | ||
252 | |||
253 | static 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 | |||
279 | struct imx_gpc_dt_data { | ||
280 | int num_domains; | ||
281 | bool err009619_present; | ||
282 | }; | ||
283 | |||
284 | static const struct imx_gpc_dt_data imx6q_dt_data = { | ||
285 | .num_domains = 2, | ||
286 | .err009619_present = false, | ||
287 | }; | ||
288 | |||
289 | static const struct imx_gpc_dt_data imx6qp_dt_data = { | ||
290 | .num_domains = 2, | ||
291 | .err009619_present = true, | ||
292 | }; | ||
293 | |||
294 | static const struct imx_gpc_dt_data imx6sl_dt_data = { | ||
295 | .num_domains = 3, | ||
296 | .err009619_present = false, | ||
297 | }; | ||
298 | |||
299 | static 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 | |||
306 | static 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 | |||
313 | static struct generic_pm_domain *imx_gpc_onecell_domains[] = { | ||
314 | &imx_gpc_domains[0].base, | ||
315 | &imx_gpc_domains[1].base, | ||
316 | }; | ||
317 | |||
318 | static struct genpd_onecell_data imx_gpc_onecell_data = { | ||
319 | .domains = imx_gpc_onecell_domains, | ||
320 | .num_domains = 2, | ||
321 | }; | ||
322 | |||
323 | static 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 | |||
359 | genpd_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]); | ||
363 | clk_err: | ||
364 | return ret; | ||
365 | } | ||
366 | |||
367 | static 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 | |||
457 | static 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 | |||
481 | static 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 | }; | ||
489 | builtin_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 | |||
51 | struct 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 | |||
67 | static 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 | } | ||
142 | unmap: | ||
143 | regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING, | ||
144 | domain->bits.map, 0); | ||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | static 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 | |||
153 | static 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 | |||
158 | static 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 | |||
196 | static 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 | |||
230 | static 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 | |||
240 | static const struct platform_device_id imx7_pgc_domain_id[] = { | ||
241 | { "imx7-pgc-domain", }, | ||
242 | { }, | ||
243 | }; | ||
244 | |||
245 | static 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 | }; | ||
253 | builtin_platform_driver(imx7_pgc_domain_driver) | ||
254 | |||
255 | static 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, ®map_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 | |||
351 | static const struct of_device_id imx_gpcv2_dt_ids[] = { | ||
352 | { .compatible = "fsl,imx7d-gpc" }, | ||
353 | { } | ||
354 | }; | ||
355 | |||
356 | static 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 | }; | ||
363 | builtin_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 | ||
18 | static const struct rcar_sysc_area r8a7795_areas[] __initconst = { | 19 | static 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 | |||
60 | static const struct soc_device_attribute r8a7795es1[] __initconst = { | ||
61 | { .soc_id = "r8a7795", .revision = "ES1.*" }, | ||
62 | { /* sentinel */ } | ||
63 | }; | ||
64 | |||
65 | static 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 | |||
53 | const struct rcar_sysc_info r8a7795_sysc_info __initconst = { | 74 | const 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 | } |
407 | early_initcall(rcar_sysc_pd_init); | 418 | early_initcall(rcar_sysc_pd_init); |
408 | 419 | ||
420 | void __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 | |||
409 | void __init rcar_sysc_init(phys_addr_t base, u32 syscier) | 432 | void __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 | ||
48 | struct rcar_sysc_info { | 48 | struct 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; | |||
59 | extern const struct rcar_sysc_info r8a7794_sysc_info; | 60 | extern const struct rcar_sysc_info r8a7794_sysc_info; |
60 | extern const struct rcar_sysc_info r8a7795_sysc_info; | 61 | extern const struct rcar_sysc_info r8a7795_sysc_info; |
61 | extern const struct rcar_sysc_info r8a7796_sysc_info; | 62 | extern 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 | |||
69 | extern 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 | ||
83 | static const struct renesas_soc soc_rz_g1h __initconst __maybe_unused = { | ||
84 | .family = &fam_rzg, | ||
85 | .id = 0x45, | ||
86 | }; | ||
87 | |||
83 | static const struct renesas_soc soc_rz_g1m __initconst __maybe_unused = { | 88 | static 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 | ||
93 | static const struct renesas_soc soc_rz_g1n __initconst __maybe_unused = { | ||
94 | .family = &fam_rzg, | ||
95 | .id = 0x4b, | ||
96 | }; | ||
97 | |||
88 | static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = { | 98 | static 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 | } |
257 | core_initcall(renesas_soc_init); | 273 | early_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 | ||
9 | config EXYNOS_PMU | 9 | config 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 | ||
15 | config EXYNOS_PMU_ARM_DRIVERS | ||
16 | bool "Exynos PMU ARMv7-specific driver extensions" if COMPILE_TEST | ||
17 | depends on EXYNOS_PMU | ||
12 | 18 | ||
13 | config EXYNOS_PM_DOMAINS | 19 | config 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 @@ | |||
1 | obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o exynos3250-pmu.o exynos4-pmu.o \ | 1 | obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o |
2 | |||
3 | obj-$(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 |
3 | obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o | 5 | obj-$(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 | */ |
74 | static const struct of_device_id exynos_pmu_of_device_ids[] = { | 84 | static 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 | ||
33 | extern void __iomem *pmu_base_addr; | 33 | extern 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 */ |
35 | extern const struct exynos_pmu_data exynos3250_pmu_data; | 37 | extern const struct exynos_pmu_data exynos3250_pmu_data; |
36 | extern const struct exynos_pmu_data exynos4210_pmu_data; | 38 | extern const struct exynos_pmu_data exynos4210_pmu_data; |
@@ -38,6 +40,7 @@ extern const struct exynos_pmu_data exynos4212_pmu_data; | |||
38 | extern const struct exynos_pmu_data exynos4412_pmu_data; | 40 | extern const struct exynos_pmu_data exynos4412_pmu_data; |
39 | extern const struct exynos_pmu_data exynos5250_pmu_data; | 41 | extern const struct exynos_pmu_data exynos5250_pmu_data; |
40 | extern const struct exynos_pmu_data exynos5420_pmu_data; | 42 | extern const struct exynos_pmu_data exynos5420_pmu_data; |
43 | #endif | ||
41 | 44 | ||
42 | extern void pmu_raw_writel(u32 val, u32 offset); | 45 | extern void pmu_raw_writel(u32 val, u32 offset); |
43 | extern u32 pmu_raw_readl(u32 offset); | 46 | extern u32 pmu_raw_readl(u32 offset); |
diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index e5e124c07066..dcf088db40b6 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig | |||
@@ -12,6 +12,8 @@ config ARCH_TEGRA_2x_SOC | |||
12 | select PINCTRL_TEGRA20 | 12 | select PINCTRL_TEGRA20 |
13 | select PL310_ERRATA_727915 if CACHE_L2X0 | 13 | select PL310_ERRATA_727915 if CACHE_L2X0 |
14 | select PL310_ERRATA_769419 if CACHE_L2X0 | 14 | select PL310_ERRATA_769419 if CACHE_L2X0 |
15 | select SOC_TEGRA_FLOWCTRL | ||
16 | select SOC_TEGRA_PMC | ||
15 | select TEGRA_TIMER | 17 | select TEGRA_TIMER |
16 | help | 18 | help |
17 | Support for NVIDIA Tegra AP20 and T20 processors, based on the | 19 | Support for NVIDIA Tegra AP20 and T20 processors, based on the |
@@ -23,6 +25,8 @@ config ARCH_TEGRA_3x_SOC | |||
23 | select ARM_ERRATA_764369 if SMP | 25 | select ARM_ERRATA_764369 if SMP |
24 | select PINCTRL_TEGRA30 | 26 | select PINCTRL_TEGRA30 |
25 | select PL310_ERRATA_769419 if CACHE_L2X0 | 27 | select PL310_ERRATA_769419 if CACHE_L2X0 |
28 | select SOC_TEGRA_FLOWCTRL | ||
29 | select SOC_TEGRA_PMC | ||
26 | select TEGRA_TIMER | 30 | select TEGRA_TIMER |
27 | help | 31 | help |
28 | Support for NVIDIA Tegra T30 processor family, based on the | 32 | Support for NVIDIA Tegra T30 processor family, based on the |
@@ -33,6 +37,8 @@ config ARCH_TEGRA_114_SOC | |||
33 | select ARM_ERRATA_798181 if SMP | 37 | select ARM_ERRATA_798181 if SMP |
34 | select HAVE_ARM_ARCH_TIMER | 38 | select HAVE_ARM_ARCH_TIMER |
35 | select PINCTRL_TEGRA114 | 39 | select PINCTRL_TEGRA114 |
40 | select SOC_TEGRA_FLOWCTRL | ||
41 | select SOC_TEGRA_PMC | ||
36 | select TEGRA_TIMER | 42 | select TEGRA_TIMER |
37 | help | 43 | help |
38 | Support for NVIDIA Tegra T114 processor family, based on the | 44 | Support for NVIDIA Tegra T114 processor family, based on the |
@@ -42,6 +48,8 @@ config ARCH_TEGRA_124_SOC | |||
42 | bool "Enable support for Tegra124 family" | 48 | bool "Enable support for Tegra124 family" |
43 | select HAVE_ARM_ARCH_TIMER | 49 | select HAVE_ARM_ARCH_TIMER |
44 | select PINCTRL_TEGRA124 | 50 | select PINCTRL_TEGRA124 |
51 | select SOC_TEGRA_FLOWCTRL | ||
52 | select SOC_TEGRA_PMC | ||
45 | select TEGRA_TIMER | 53 | select TEGRA_TIMER |
46 | help | 54 | help |
47 | Support for NVIDIA Tegra T124 processor family, based on the | 55 | Support for NVIDIA Tegra T124 processor family, based on the |
@@ -55,6 +63,8 @@ if ARM64 | |||
55 | config ARCH_TEGRA_132_SOC | 63 | config ARCH_TEGRA_132_SOC |
56 | bool "NVIDIA Tegra132 SoC" | 64 | bool "NVIDIA Tegra132 SoC" |
57 | select PINCTRL_TEGRA124 | 65 | select PINCTRL_TEGRA124 |
66 | select SOC_TEGRA_FLOWCTRL | ||
67 | select SOC_TEGRA_PMC | ||
58 | help | 68 | help |
59 | Enable support for NVIDIA Tegra132 SoC, based on the Denver | 69 | Enable support for NVIDIA Tegra132 SoC, based on the Denver |
60 | ARMv8 CPU. The Tegra132 SoC is similar to the Tegra124 SoC, | 70 | ARMv8 CPU. The Tegra132 SoC is similar to the Tegra124 SoC, |
@@ -64,6 +74,8 @@ config ARCH_TEGRA_132_SOC | |||
64 | config ARCH_TEGRA_210_SOC | 74 | config ARCH_TEGRA_210_SOC |
65 | bool "NVIDIA Tegra210 SoC" | 75 | bool "NVIDIA Tegra210 SoC" |
66 | select PINCTRL_TEGRA210 | 76 | select PINCTRL_TEGRA210 |
77 | select SOC_TEGRA_FLOWCTRL | ||
78 | select SOC_TEGRA_PMC | ||
67 | help | 79 | help |
68 | Enable support for the NVIDIA Tegra210 SoC. Also known as Tegra X1, | 80 | Enable support for the NVIDIA Tegra210 SoC. Also known as Tegra X1, |
69 | the Tegra210 has four Cortex-A57 cores paired with four Cortex-A53 | 81 | the Tegra210 has four Cortex-A57 cores paired with four Cortex-A53 |
@@ -83,6 +95,7 @@ config ARCH_TEGRA_186_SOC | |||
83 | select TEGRA_BPMP | 95 | select TEGRA_BPMP |
84 | select TEGRA_HSP_MBOX | 96 | select TEGRA_HSP_MBOX |
85 | select TEGRA_IVC | 97 | select TEGRA_IVC |
98 | select SOC_TEGRA_PMC_TEGRA186 | ||
86 | help | 99 | help |
87 | Enable support for the NVIDIA Tegar186 SoC. The Tegra186 features a | 100 | Enable support for the NVIDIA Tegar186 SoC. The Tegra186 features a |
88 | combination of Denver and Cortex-A57 CPU cores and a GPU based on | 101 | combination of Denver and Cortex-A57 CPU cores and a GPU based on |
@@ -93,3 +106,12 @@ config ARCH_TEGRA_186_SOC | |||
93 | 106 | ||
94 | endif | 107 | endif |
95 | endif | 108 | endif |
109 | |||
110 | config SOC_TEGRA_FLOWCTRL | ||
111 | bool | ||
112 | |||
113 | config SOC_TEGRA_PMC | ||
114 | bool | ||
115 | |||
116 | config SOC_TEGRA_PMC_TEGRA186 | ||
117 | bool | ||
diff --git a/drivers/soc/tegra/Makefile b/drivers/soc/tegra/Makefile index ae857ff7d53d..4f81dd55e5d1 100644 --- a/drivers/soc/tegra/Makefile +++ b/drivers/soc/tegra/Makefile | |||
@@ -1,4 +1,6 @@ | |||
1 | obj-y += fuse/ | 1 | obj-y += fuse/ |
2 | 2 | ||
3 | obj-y += common.o | 3 | obj-y += common.o |
4 | obj-y += pmc.o | 4 | obj-$(CONFIG_SOC_TEGRA_FLOWCTRL) += flowctrl.o |
5 | obj-$(CONFIG_SOC_TEGRA_PMC) += pmc.o | ||
6 | obj-$(CONFIG_SOC_TEGRA_PMC_TEGRA186) += pmc-tegra186.o | ||
diff --git a/arch/arm/mach-tegra/flowctrl.c b/drivers/soc/tegra/flowctrl.c index 475e783992fd..0e345c05fc65 100644 --- a/arch/arm/mach-tegra/flowctrl.c +++ b/drivers/soc/tegra/flowctrl.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/mach-tegra/flowctrl.c | 2 | * drivers/soc/tegra/flowctrl.c |
3 | * | 3 | * |
4 | * functions and macros to control the flowcontroller | 4 | * Functions and macros to control the flowcontroller |
5 | * | 5 | * |
6 | * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. | 6 | * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. |
7 | * | 7 | * |
@@ -24,11 +24,12 @@ | |||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/of.h> | 25 | #include <linux/of.h> |
26 | #include <linux/of_address.h> | 26 | #include <linux/of_address.h> |
27 | #include <linux/platform_device.h> | ||
27 | 28 | ||
29 | #include <soc/tegra/common.h> | ||
30 | #include <soc/tegra/flowctrl.h> | ||
28 | #include <soc/tegra/fuse.h> | 31 | #include <soc/tegra/fuse.h> |
29 | 32 | ||
30 | #include "flowctrl.h" | ||
31 | |||
32 | static u8 flowctrl_offset_halt_cpu[] = { | 33 | static u8 flowctrl_offset_halt_cpu[] = { |
33 | FLOW_CTRL_HALT_CPU0_EVENTS, | 34 | FLOW_CTRL_HALT_CPU0_EVENTS, |
34 | FLOW_CTRL_HALT_CPU1_EVENTS, | 35 | FLOW_CTRL_HALT_CPU1_EVENTS, |
@@ -47,6 +48,10 @@ static void __iomem *tegra_flowctrl_base; | |||
47 | 48 | ||
48 | static void flowctrl_update(u8 offset, u32 value) | 49 | static void flowctrl_update(u8 offset, u32 value) |
49 | { | 50 | { |
51 | if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base), | ||
52 | "Tegra flowctrl not initialised!\n")) | ||
53 | return; | ||
54 | |||
50 | writel(value, tegra_flowctrl_base + offset); | 55 | writel(value, tegra_flowctrl_base + offset); |
51 | 56 | ||
52 | /* ensure the update has reached the flow controller */ | 57 | /* ensure the update has reached the flow controller */ |
@@ -58,6 +63,10 @@ u32 flowctrl_read_cpu_csr(unsigned int cpuid) | |||
58 | { | 63 | { |
59 | u8 offset = flowctrl_offset_cpu_csr[cpuid]; | 64 | u8 offset = flowctrl_offset_cpu_csr[cpuid]; |
60 | 65 | ||
66 | if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base), | ||
67 | "Tegra flowctrl not initialised!\n")) | ||
68 | return 0; | ||
69 | |||
61 | return readl(tegra_flowctrl_base + offset); | 70 | return readl(tegra_flowctrl_base + offset); |
62 | } | 71 | } |
63 | 72 | ||
@@ -140,7 +149,23 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid) | |||
140 | flowctrl_write_cpu_csr(cpuid, reg); | 149 | flowctrl_write_cpu_csr(cpuid, reg); |
141 | } | 150 | } |
142 | 151 | ||
143 | static const struct of_device_id matches[] __initconst = { | 152 | static int tegra_flowctrl_probe(struct platform_device *pdev) |
153 | { | ||
154 | void __iomem *base = tegra_flowctrl_base; | ||
155 | struct resource *res; | ||
156 | |||
157 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
158 | tegra_flowctrl_base = devm_ioremap_resource(&pdev->dev, res); | ||
159 | if (IS_ERR(tegra_flowctrl_base)) | ||
160 | return PTR_ERR(base); | ||
161 | |||
162 | iounmap(base); | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static const struct of_device_id tegra_flowctrl_match[] = { | ||
168 | { .compatible = "nvidia,tegra210-flowctrl" }, | ||
144 | { .compatible = "nvidia,tegra124-flowctrl" }, | 169 | { .compatible = "nvidia,tegra124-flowctrl" }, |
145 | { .compatible = "nvidia,tegra114-flowctrl" }, | 170 | { .compatible = "nvidia,tegra114-flowctrl" }, |
146 | { .compatible = "nvidia,tegra30-flowctrl" }, | 171 | { .compatible = "nvidia,tegra30-flowctrl" }, |
@@ -148,24 +173,52 @@ static const struct of_device_id matches[] __initconst = { | |||
148 | { } | 173 | { } |
149 | }; | 174 | }; |
150 | 175 | ||
151 | void __init tegra_flowctrl_init(void) | 176 | static struct platform_driver tegra_flowctrl_driver = { |
177 | .driver = { | ||
178 | .name = "tegra-flowctrl", | ||
179 | .suppress_bind_attrs = true, | ||
180 | .of_match_table = tegra_flowctrl_match, | ||
181 | }, | ||
182 | .probe = tegra_flowctrl_probe, | ||
183 | }; | ||
184 | builtin_platform_driver(tegra_flowctrl_driver); | ||
185 | |||
186 | static int __init tegra_flowctrl_init(void) | ||
152 | { | 187 | { |
153 | /* hardcoded fallback if device tree node is missing */ | 188 | struct resource res; |
154 | unsigned long base = 0x60007000; | ||
155 | unsigned long size = SZ_4K; | ||
156 | struct device_node *np; | 189 | struct device_node *np; |
157 | 190 | ||
158 | np = of_find_matching_node(NULL, matches); | 191 | if (!soc_is_tegra()) |
159 | if (np) { | 192 | return 0; |
160 | struct resource res; | ||
161 | 193 | ||
162 | if (of_address_to_resource(np, 0, &res) == 0) { | 194 | np = of_find_matching_node(NULL, tegra_flowctrl_match); |
163 | size = resource_size(&res); | 195 | if (np) { |
164 | base = res.start; | 196 | if (of_address_to_resource(np, 0, &res) < 0) { |
197 | pr_err("failed to get flowctrl register\n"); | ||
198 | return -ENXIO; | ||
165 | } | 199 | } |
166 | |||
167 | of_node_put(np); | 200 | of_node_put(np); |
201 | } else if (IS_ENABLED(CONFIG_ARM)) { | ||
202 | /* | ||
203 | * Hardcoded fallback for 32-bit Tegra | ||
204 | * devices if device tree node is missing. | ||
205 | */ | ||
206 | res.start = 0x60007000; | ||
207 | res.end = 0x60007fff; | ||
208 | res.flags = IORESOURCE_MEM; | ||
209 | } else { | ||
210 | /* | ||
211 | * At this point we're running on a Tegra, | ||
212 | * that doesn't support the flow controller | ||
213 | * (eg. Tegra186), so just return. | ||
214 | */ | ||
215 | return 0; | ||
168 | } | 216 | } |
169 | 217 | ||
170 | tegra_flowctrl_base = ioremap_nocache(base, size); | 218 | tegra_flowctrl_base = ioremap_nocache(res.start, resource_size(&res)); |
219 | if (!tegra_flowctrl_base) | ||
220 | return -ENXIO; | ||
221 | |||
222 | return 0; | ||
171 | } | 223 | } |
224 | early_initcall(tegra_flowctrl_init); | ||
diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index de2c1bfe28b5..7413f60fa855 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
20 | #include <linux/kobject.h> | 20 | #include <linux/kobject.h> |
21 | #include <linux/module.h> | 21 | #include <linux/init.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/of.h> | 23 | #include <linux/of.h> |
24 | #include <linux/of_address.h> | 24 | #include <linux/of_address.h> |
@@ -168,7 +168,7 @@ static struct platform_driver tegra_fuse_driver = { | |||
168 | }, | 168 | }, |
169 | .probe = tegra_fuse_probe, | 169 | .probe = tegra_fuse_probe, |
170 | }; | 170 | }; |
171 | module_platform_driver(tegra_fuse_driver); | 171 | builtin_platform_driver(tegra_fuse_driver); |
172 | 172 | ||
173 | bool __init tegra_fuse_read_spare(unsigned int spare) | 173 | bool __init tegra_fuse_read_spare(unsigned int spare) |
174 | { | 174 | { |
diff --git a/drivers/soc/tegra/pmc-tegra186.c b/drivers/soc/tegra/pmc-tegra186.c new file mode 100644 index 000000000000..6f5c6f98ba92 --- /dev/null +++ b/drivers/soc/tegra/pmc-tegra186.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016, NVIDIA CORPORATION. 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 | |||
14 | #define pr_fmt(fmt) "tegra-pmc: " fmt | ||
15 | |||
16 | #include <linux/io.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/reboot.h> | ||
21 | |||
22 | #include <asm/system_misc.h> | ||
23 | |||
24 | #define PMC_CNTRL 0x000 | ||
25 | #define PMC_CNTRL_MAIN_RST BIT(4) | ||
26 | |||
27 | #define PMC_RST_STATUS 0x070 | ||
28 | |||
29 | #define WAKE_AOWAKE_CTRL 0x4f4 | ||
30 | #define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0) | ||
31 | |||
32 | #define SCRATCH_SCRATCH0 0x2000 | ||
33 | #define SCRATCH_SCRATCH0_MODE_RECOVERY BIT(31) | ||
34 | #define SCRATCH_SCRATCH0_MODE_BOOTLOADER BIT(30) | ||
35 | #define SCRATCH_SCRATCH0_MODE_RCM BIT(1) | ||
36 | #define SCRATCH_SCRATCH0_MODE_MASK (SCRATCH_SCRATCH0_MODE_RECOVERY | \ | ||
37 | SCRATCH_SCRATCH0_MODE_BOOTLOADER | \ | ||
38 | SCRATCH_SCRATCH0_MODE_RCM) | ||
39 | |||
40 | struct tegra_pmc { | ||
41 | struct device *dev; | ||
42 | void __iomem *regs; | ||
43 | void __iomem *wake; | ||
44 | void __iomem *aotag; | ||
45 | void __iomem *scratch; | ||
46 | |||
47 | void (*system_restart)(enum reboot_mode mode, const char *cmd); | ||
48 | struct notifier_block restart; | ||
49 | }; | ||
50 | |||
51 | static int tegra186_pmc_restart_notify(struct notifier_block *nb, | ||
52 | unsigned long action, | ||
53 | void *data) | ||
54 | { | ||
55 | struct tegra_pmc *pmc = container_of(nb, struct tegra_pmc, restart); | ||
56 | const char *cmd = data; | ||
57 | u32 value; | ||
58 | |||
59 | value = readl(pmc->scratch + SCRATCH_SCRATCH0); | ||
60 | value &= ~SCRATCH_SCRATCH0_MODE_MASK; | ||
61 | |||
62 | if (cmd) { | ||
63 | if (strcmp(cmd, "recovery") == 0) | ||
64 | value |= SCRATCH_SCRATCH0_MODE_RECOVERY; | ||
65 | |||
66 | if (strcmp(cmd, "bootloader") == 0) | ||
67 | value |= SCRATCH_SCRATCH0_MODE_BOOTLOADER; | ||
68 | |||
69 | if (strcmp(cmd, "forced-recovery") == 0) | ||
70 | value |= SCRATCH_SCRATCH0_MODE_RCM; | ||
71 | } | ||
72 | |||
73 | writel(value, pmc->scratch + SCRATCH_SCRATCH0); | ||
74 | |||
75 | /* | ||
76 | * If available, call the system restart implementation that was | ||
77 | * registered earlier (typically PSCI). | ||
78 | */ | ||
79 | if (pmc->system_restart) { | ||
80 | pmc->system_restart(reboot_mode, cmd); | ||
81 | return NOTIFY_DONE; | ||
82 | } | ||
83 | |||
84 | /* reset everything but SCRATCH0_SCRATCH0 and PMC_RST_STATUS */ | ||
85 | value = readl(pmc->regs + PMC_CNTRL); | ||
86 | value |= PMC_CNTRL_MAIN_RST; | ||
87 | writel(value, pmc->regs + PMC_CNTRL); | ||
88 | |||
89 | return NOTIFY_DONE; | ||
90 | } | ||
91 | |||
92 | static int tegra186_pmc_setup(struct tegra_pmc *pmc) | ||
93 | { | ||
94 | struct device_node *np = pmc->dev->of_node; | ||
95 | bool invert; | ||
96 | u32 value; | ||
97 | |||
98 | invert = of_property_read_bool(np, "nvidia,invert-interrupt"); | ||
99 | |||
100 | value = readl(pmc->wake + WAKE_AOWAKE_CTRL); | ||
101 | |||
102 | if (invert) | ||
103 | value |= WAKE_AOWAKE_CTRL_INTR_POLARITY; | ||
104 | else | ||
105 | value &= ~WAKE_AOWAKE_CTRL_INTR_POLARITY; | ||
106 | |||
107 | writel(value, pmc->wake + WAKE_AOWAKE_CTRL); | ||
108 | |||
109 | /* | ||
110 | * We need to hook any system restart implementation registered | ||
111 | * previously so we can write SCRATCH_SCRATCH0 before reset. | ||
112 | */ | ||
113 | pmc->system_restart = arm_pm_restart; | ||
114 | arm_pm_restart = NULL; | ||
115 | |||
116 | pmc->restart.notifier_call = tegra186_pmc_restart_notify; | ||
117 | pmc->restart.priority = 128; | ||
118 | |||
119 | return register_restart_handler(&pmc->restart); | ||
120 | } | ||
121 | |||
122 | static int tegra186_pmc_probe(struct platform_device *pdev) | ||
123 | { | ||
124 | struct tegra_pmc *pmc; | ||
125 | struct resource *res; | ||
126 | |||
127 | pmc = devm_kzalloc(&pdev->dev, sizeof(*pmc), GFP_KERNEL); | ||
128 | if (!pmc) | ||
129 | return -ENOMEM; | ||
130 | |||
131 | pmc->dev = &pdev->dev; | ||
132 | |||
133 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pmc"); | ||
134 | pmc->regs = devm_ioremap_resource(&pdev->dev, res); | ||
135 | if (IS_ERR(pmc->regs)) | ||
136 | return PTR_ERR(pmc->regs); | ||
137 | |||
138 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wake"); | ||
139 | pmc->wake = devm_ioremap_resource(&pdev->dev, res); | ||
140 | if (IS_ERR(pmc->wake)) | ||
141 | return PTR_ERR(pmc->wake); | ||
142 | |||
143 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aotag"); | ||
144 | pmc->aotag = devm_ioremap_resource(&pdev->dev, res); | ||
145 | if (IS_ERR(pmc->aotag)) | ||
146 | return PTR_ERR(pmc->aotag); | ||
147 | |||
148 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "scratch"); | ||
149 | pmc->scratch = devm_ioremap_resource(&pdev->dev, res); | ||
150 | if (IS_ERR(pmc->scratch)) | ||
151 | return PTR_ERR(pmc->scratch); | ||
152 | |||
153 | return tegra186_pmc_setup(pmc); | ||
154 | } | ||
155 | |||
156 | static const struct of_device_id tegra186_pmc_of_match[] = { | ||
157 | { .compatible = "nvidia,tegra186-pmc" }, | ||
158 | { /* sentinel */ } | ||
159 | }; | ||
160 | MODULE_DEVICE_TABLE(of, tegra186_pmc_of_match); | ||
161 | |||
162 | static struct platform_driver tegra186_pmc_driver = { | ||
163 | .driver = { | ||
164 | .name = "tegra186-pmc", | ||
165 | .of_match_table = tegra186_pmc_of_match, | ||
166 | }, | ||
167 | .probe = tegra186_pmc_probe, | ||
168 | }; | ||
169 | builtin_platform_driver(tegra186_pmc_driver); | ||
diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index 3557c5e32a93..39e152abe6b9 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig | |||
@@ -38,4 +38,16 @@ config WKUP_M3_IPC | |||
38 | to communicate and use the Wakeup M3 for PM features like suspend | 38 | to communicate and use the Wakeup M3 for PM features like suspend |
39 | resume and boots it using wkup_m3_rproc driver. | 39 | resume and boots it using wkup_m3_rproc driver. |
40 | 40 | ||
41 | config TI_SCI_PM_DOMAINS | ||
42 | tristate "TI SCI PM Domains Driver" | ||
43 | depends on TI_SCI_PROTOCOL | ||
44 | depends on PM_GENERIC_DOMAINS | ||
45 | help | ||
46 | Generic power domain implementation for TI device implementing | ||
47 | the TI SCI protocol. | ||
48 | |||
49 | To compile this as a module, choose M here. The module will be | ||
50 | called ti_sci_pm_domains. Note this is needed early in boot before | ||
51 | rootfs may be available. | ||
52 | |||
41 | endif # SOC_TI | 53 | endif # SOC_TI |
diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile index 48ff3a79634f..7d572736c86e 100644 --- a/drivers/soc/ti/Makefile +++ b/drivers/soc/ti/Makefile | |||
@@ -5,3 +5,4 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS) += knav_qmss.o | |||
5 | knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o | 5 | knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o |
6 | obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o | 6 | obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o |
7 | obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o | 7 | obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o |
8 | obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o | ||
diff --git a/drivers/soc/ti/ti_sci_pm_domains.c b/drivers/soc/ti/ti_sci_pm_domains.c new file mode 100644 index 000000000000..b0b283810e72 --- /dev/null +++ b/drivers/soc/ti/ti_sci_pm_domains.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * TI SCI Generic Power Domain Driver | ||
3 | * | ||
4 | * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * J Keerthy <j-keerthy@ti.com> | ||
6 | * Dave Gerlach <d-gerlach@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
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/err.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/mutex.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/pm_domain.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/soc/ti/ti_sci_protocol.h> | ||
26 | |||
27 | /** | ||
28 | * struct ti_sci_genpd_dev_data: holds data needed for every device attached | ||
29 | * to this genpd | ||
30 | * @idx: index of the device that identifies it with the system | ||
31 | * control processor. | ||
32 | */ | ||
33 | struct ti_sci_genpd_dev_data { | ||
34 | int idx; | ||
35 | }; | ||
36 | |||
37 | /** | ||
38 | * struct ti_sci_pm_domain: TI specific data needed for power domain | ||
39 | * @ti_sci: handle to TI SCI protocol driver that provides ops to | ||
40 | * communicate with system control processor. | ||
41 | * @dev: pointer to dev for the driver for devm allocs | ||
42 | * @pd: generic_pm_domain for use with the genpd framework | ||
43 | */ | ||
44 | struct ti_sci_pm_domain { | ||
45 | const struct ti_sci_handle *ti_sci; | ||
46 | struct device *dev; | ||
47 | struct generic_pm_domain pd; | ||
48 | }; | ||
49 | |||
50 | #define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd) | ||
51 | |||
52 | /** | ||
53 | * ti_sci_dev_id(): get prepopulated ti_sci id from struct dev | ||
54 | * @dev: pointer to device associated with this genpd | ||
55 | * | ||
56 | * Returns device_id stored from ti,sci_id property | ||
57 | */ | ||
58 | static int ti_sci_dev_id(struct device *dev) | ||
59 | { | ||
60 | struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev); | ||
61 | struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data; | ||
62 | |||
63 | return sci_dev_data->idx; | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * ti_sci_dev_to_sci_handle(): get pointer to ti_sci_handle | ||
68 | * @dev: pointer to device associated with this genpd | ||
69 | * | ||
70 | * Returns ti_sci_handle to be used to communicate with system | ||
71 | * control processor. | ||
72 | */ | ||
73 | static const struct ti_sci_handle *ti_sci_dev_to_sci_handle(struct device *dev) | ||
74 | { | ||
75 | struct generic_pm_domain *pd = pd_to_genpd(dev->pm_domain); | ||
76 | struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(pd); | ||
77 | |||
78 | return ti_sci_genpd->ti_sci; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * ti_sci_dev_start(): genpd device start hook called to turn device on | ||
83 | * @dev: pointer to device associated with this genpd to be powered on | ||
84 | */ | ||
85 | static int ti_sci_dev_start(struct device *dev) | ||
86 | { | ||
87 | const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev); | ||
88 | int idx = ti_sci_dev_id(dev); | ||
89 | |||
90 | return ti_sci->ops.dev_ops.get_device(ti_sci, idx); | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * ti_sci_dev_stop(): genpd device stop hook called to turn device off | ||
95 | * @dev: pointer to device associated with this genpd to be powered off | ||
96 | */ | ||
97 | static int ti_sci_dev_stop(struct device *dev) | ||
98 | { | ||
99 | const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev); | ||
100 | int idx = ti_sci_dev_id(dev); | ||
101 | |||
102 | return ti_sci->ops.dev_ops.put_device(ti_sci, idx); | ||
103 | } | ||
104 | |||
105 | static int ti_sci_pd_attach_dev(struct generic_pm_domain *domain, | ||
106 | struct device *dev) | ||
107 | { | ||
108 | struct device_node *np = dev->of_node; | ||
109 | struct of_phandle_args pd_args; | ||
110 | struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(domain); | ||
111 | const struct ti_sci_handle *ti_sci = ti_sci_genpd->ti_sci; | ||
112 | struct ti_sci_genpd_dev_data *sci_dev_data; | ||
113 | struct generic_pm_domain_data *genpd_data; | ||
114 | int idx, ret = 0; | ||
115 | |||
116 | ret = of_parse_phandle_with_args(np, "power-domains", | ||
117 | "#power-domain-cells", 0, &pd_args); | ||
118 | if (ret < 0) | ||
119 | return ret; | ||
120 | |||
121 | if (pd_args.args_count != 1) | ||
122 | return -EINVAL; | ||
123 | |||
124 | idx = pd_args.args[0]; | ||
125 | |||
126 | /* | ||
127 | * Check the validity of the requested idx, if the index is not valid | ||
128 | * the PMMC will return a NAK here and we will not allocate it. | ||
129 | */ | ||
130 | ret = ti_sci->ops.dev_ops.is_valid(ti_sci, idx); | ||
131 | if (ret) | ||
132 | return -EINVAL; | ||
133 | |||
134 | sci_dev_data = kzalloc(sizeof(*sci_dev_data), GFP_KERNEL); | ||
135 | if (!sci_dev_data) | ||
136 | return -ENOMEM; | ||
137 | |||
138 | sci_dev_data->idx = idx; | ||
139 | |||
140 | genpd_data = dev_gpd_data(dev); | ||
141 | genpd_data->data = sci_dev_data; | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static void ti_sci_pd_detach_dev(struct generic_pm_domain *domain, | ||
147 | struct device *dev) | ||
148 | { | ||
149 | struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev); | ||
150 | struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data; | ||
151 | |||
152 | kfree(sci_dev_data); | ||
153 | genpd_data->data = NULL; | ||
154 | } | ||
155 | |||
156 | static const struct of_device_id ti_sci_pm_domain_matches[] = { | ||
157 | { .compatible = "ti,sci-pm-domain", }, | ||
158 | { }, | ||
159 | }; | ||
160 | MODULE_DEVICE_TABLE(of, ti_sci_pm_domain_matches); | ||
161 | |||
162 | static int ti_sci_pm_domain_probe(struct platform_device *pdev) | ||
163 | { | ||
164 | struct device *dev = &pdev->dev; | ||
165 | struct device_node *np = dev->of_node; | ||
166 | struct ti_sci_pm_domain *ti_sci_pd; | ||
167 | int ret; | ||
168 | |||
169 | ti_sci_pd = devm_kzalloc(dev, sizeof(*ti_sci_pd), GFP_KERNEL); | ||
170 | if (!ti_sci_pd) | ||
171 | return -ENOMEM; | ||
172 | |||
173 | ti_sci_pd->ti_sci = devm_ti_sci_get_handle(dev); | ||
174 | if (IS_ERR(ti_sci_pd->ti_sci)) | ||
175 | return PTR_ERR(ti_sci_pd->ti_sci); | ||
176 | |||
177 | ti_sci_pd->dev = dev; | ||
178 | |||
179 | ti_sci_pd->pd.attach_dev = ti_sci_pd_attach_dev; | ||
180 | ti_sci_pd->pd.detach_dev = ti_sci_pd_detach_dev; | ||
181 | |||
182 | ti_sci_pd->pd.dev_ops.start = ti_sci_dev_start; | ||
183 | ti_sci_pd->pd.dev_ops.stop = ti_sci_dev_stop; | ||
184 | |||
185 | pm_genpd_init(&ti_sci_pd->pd, NULL, true); | ||
186 | |||
187 | ret = of_genpd_add_provider_simple(np, &ti_sci_pd->pd); | ||
188 | |||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static struct platform_driver ti_sci_pm_domains_driver = { | ||
193 | .probe = ti_sci_pm_domain_probe, | ||
194 | .driver = { | ||
195 | .name = "ti_sci_pm_domains", | ||
196 | .of_match_table = ti_sci_pm_domain_matches, | ||
197 | }, | ||
198 | }; | ||
199 | module_platform_driver(ti_sci_pm_domains_driver); | ||
200 | MODULE_LICENSE("GPL v2"); | ||
201 | MODULE_DESCRIPTION("TI System Control Interface (SCI) Power Domain driver"); | ||
202 | MODULE_AUTHOR("Dave Gerlach"); | ||
diff --git a/drivers/soc/zte/zx296718_pm_domains.c b/drivers/soc/zte/zx296718_pm_domains.c index 5ed924fee855..4dc5d62ee81b 100644 --- a/drivers/soc/zte/zx296718_pm_domains.c +++ b/drivers/soc/zte/zx296718_pm_domains.c | |||
@@ -169,7 +169,6 @@ static const struct of_device_id zx296718_pm_domain_matches[] = { | |||
169 | static struct platform_driver zx296718_pd_driver = { | 169 | static struct platform_driver zx296718_pd_driver = { |
170 | .driver = { | 170 | .driver = { |
171 | .name = "zx296718-powerdomain", | 171 | .name = "zx296718-powerdomain", |
172 | .owner = THIS_MODULE, | ||
173 | .of_match_table = zx296718_pm_domain_matches, | 172 | .of_match_table = zx296718_pm_domain_matches, |
174 | }, | 173 | }, |
175 | .probe = zx296718_pd_probe, | 174 | .probe = zx296718_pd_probe, |
diff --git a/drivers/soc/zte/zx2967_pm_domains.c b/drivers/soc/zte/zx2967_pm_domains.c index 61c8d84bf315..c42aeaaa34ba 100644 --- a/drivers/soc/zte/zx2967_pm_domains.c +++ b/drivers/soc/zte/zx2967_pm_domains.c | |||
@@ -125,10 +125,8 @@ int zx2967_pd_probe(struct platform_device *pdev, | |||
125 | 125 | ||
126 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 126 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
127 | pcubase = devm_ioremap_resource(&pdev->dev, res); | 127 | pcubase = devm_ioremap_resource(&pdev->dev, res); |
128 | if (IS_ERR(pcubase)) { | 128 | if (IS_ERR(pcubase)) |
129 | dev_err(&pdev->dev, "ioremap fail.\n"); | ||
130 | return PTR_ERR(pcubase); | 129 | return PTR_ERR(pcubase); |
131 | } | ||
132 | 130 | ||
133 | for (i = 0; i < domain_num; ++i) { | 131 | for (i = 0; i < domain_num; ++i) { |
134 | zx_pm_domains[i]->power_on = zx2967_power_on; | 132 | zx_pm_domains[i]->power_on = zx2967_power_on; |
diff --git a/include/dt-bindings/genpd/k2g.h b/include/dt-bindings/genpd/k2g.h new file mode 100644 index 000000000000..1f31f17e19eb --- /dev/null +++ b/include/dt-bindings/genpd/k2g.h | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * TI K2G SoC Device definitions | ||
3 | * | ||
4 | * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * | ||
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 | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #ifndef _DT_BINDINGS_GENPD_K2G_H | ||
18 | #define _DT_BINDINGS_GENPD_K2G_H | ||
19 | |||
20 | /* Documented in http://processors.wiki.ti.com/index.php/TISCI */ | ||
21 | |||
22 | #define K2G_DEV_PMMC0 0x0000 | ||
23 | #define K2G_DEV_MLB0 0x0001 | ||
24 | #define K2G_DEV_DSS0 0x0002 | ||
25 | #define K2G_DEV_MCBSP0 0x0003 | ||
26 | #define K2G_DEV_MCASP0 0x0004 | ||
27 | #define K2G_DEV_MCASP1 0x0005 | ||
28 | #define K2G_DEV_MCASP2 0x0006 | ||
29 | #define K2G_DEV_DCAN0 0x0008 | ||
30 | #define K2G_DEV_DCAN1 0x0009 | ||
31 | #define K2G_DEV_EMIF0 0x000a | ||
32 | #define K2G_DEV_MMCHS0 0x000b | ||
33 | #define K2G_DEV_MMCHS1 0x000c | ||
34 | #define K2G_DEV_GPMC0 0x000d | ||
35 | #define K2G_DEV_ELM0 0x000e | ||
36 | #define K2G_DEV_SPI0 0x0010 | ||
37 | #define K2G_DEV_SPI1 0x0011 | ||
38 | #define K2G_DEV_SPI2 0x0012 | ||
39 | #define K2G_DEV_SPI3 0x0013 | ||
40 | #define K2G_DEV_ICSS0 0x0014 | ||
41 | #define K2G_DEV_ICSS1 0x0015 | ||
42 | #define K2G_DEV_USB0 0x0016 | ||
43 | #define K2G_DEV_USB1 0x0017 | ||
44 | #define K2G_DEV_NSS0 0x0018 | ||
45 | #define K2G_DEV_PCIE0 0x0019 | ||
46 | #define K2G_DEV_GPIO0 0x001b | ||
47 | #define K2G_DEV_GPIO1 0x001c | ||
48 | #define K2G_DEV_TIMER64_0 0x001d | ||
49 | #define K2G_DEV_TIMER64_1 0x001e | ||
50 | #define K2G_DEV_TIMER64_2 0x001f | ||
51 | #define K2G_DEV_TIMER64_3 0x0020 | ||
52 | #define K2G_DEV_TIMER64_4 0x0021 | ||
53 | #define K2G_DEV_TIMER64_5 0x0022 | ||
54 | #define K2G_DEV_TIMER64_6 0x0023 | ||
55 | #define K2G_DEV_MSGMGR0 0x0025 | ||
56 | #define K2G_DEV_BOOTCFG0 0x0026 | ||
57 | #define K2G_DEV_ARM_BOOTROM0 0x0027 | ||
58 | #define K2G_DEV_DSP_BOOTROM0 0x0029 | ||
59 | #define K2G_DEV_DEBUGSS0 0x002b | ||
60 | #define K2G_DEV_UART0 0x002c | ||
61 | #define K2G_DEV_UART1 0x002d | ||
62 | #define K2G_DEV_UART2 0x002e | ||
63 | #define K2G_DEV_EHRPWM0 0x002f | ||
64 | #define K2G_DEV_EHRPWM1 0x0030 | ||
65 | #define K2G_DEV_EHRPWM2 0x0031 | ||
66 | #define K2G_DEV_EHRPWM3 0x0032 | ||
67 | #define K2G_DEV_EHRPWM4 0x0033 | ||
68 | #define K2G_DEV_EHRPWM5 0x0034 | ||
69 | #define K2G_DEV_EQEP0 0x0035 | ||
70 | #define K2G_DEV_EQEP1 0x0036 | ||
71 | #define K2G_DEV_EQEP2 0x0037 | ||
72 | #define K2G_DEV_ECAP0 0x0038 | ||
73 | #define K2G_DEV_ECAP1 0x0039 | ||
74 | #define K2G_DEV_I2C0 0x003a | ||
75 | #define K2G_DEV_I2C1 0x003b | ||
76 | #define K2G_DEV_I2C2 0x003c | ||
77 | #define K2G_DEV_EDMA0 0x003f | ||
78 | #define K2G_DEV_SEMAPHORE0 0x0040 | ||
79 | #define K2G_DEV_INTC0 0x0041 | ||
80 | #define K2G_DEV_GIC0 0x0042 | ||
81 | #define K2G_DEV_QSPI0 0x0043 | ||
82 | #define K2G_DEV_ARM_64B_COUNTER0 0x0044 | ||
83 | #define K2G_DEV_TETRIS0 0x0045 | ||
84 | #define K2G_DEV_CGEM0 0x0046 | ||
85 | #define K2G_DEV_MSMC0 0x0047 | ||
86 | #define K2G_DEV_CBASS0 0x0049 | ||
87 | #define K2G_DEV_BOARD0 0x004c | ||
88 | #define K2G_DEV_EDMA1 0x004f | ||
89 | |||
90 | #endif | ||
diff --git a/include/dt-bindings/power/imx7-power.h b/include/dt-bindings/power/imx7-power.h new file mode 100644 index 000000000000..3a181e410517 --- /dev/null +++ b/include/dt-bindings/power/imx7-power.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Impinj | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef __DT_BINDINGS_IMX7_POWER_H__ | ||
10 | #define __DT_BINDINGS_IMX7_POWER_H__ | ||
11 | |||
12 | #define IMX7_POWER_DOMAIN_MIPI_PHY 0 | ||
13 | #define IMX7_POWER_DOMAIN_PCIE_PHY 1 | ||
14 | #define IMX7_POWER_DOMAIN_USB_HSIC_PHY 2 | ||
15 | |||
16 | #endif | ||
diff --git a/include/dt-bindings/power/r8a7795-sysc.h b/include/dt-bindings/power/r8a7795-sysc.h index ee2e26ba605e..ad679eeda137 100644 --- a/include/dt-bindings/power/r8a7795-sysc.h +++ b/include/dt-bindings/power/r8a7795-sysc.h | |||
@@ -33,7 +33,7 @@ | |||
33 | #define R8A7795_PD_CA53_SCU 21 | 33 | #define R8A7795_PD_CA53_SCU 21 |
34 | #define R8A7795_PD_3DG_E 22 | 34 | #define R8A7795_PD_3DG_E 22 |
35 | #define R8A7795_PD_A3IR 24 | 35 | #define R8A7795_PD_A3IR 24 |
36 | #define R8A7795_PD_A2VC0 25 | 36 | #define R8A7795_PD_A2VC0 25 /* ES1.x only */ |
37 | #define R8A7795_PD_A2VC1 26 | 37 | #define R8A7795_PD_A2VC1 26 |
38 | 38 | ||
39 | /* Always-on power area */ | 39 | /* Always-on power area */ |
diff --git a/include/dt-bindings/reset/altr,rst-mgr-a10sr.h b/include/dt-bindings/reset/altr,rst-mgr-a10sr.h new file mode 100644 index 000000000000..9855925e5256 --- /dev/null +++ b/include/dt-bindings/reset/altr,rst-mgr-a10sr.h | |||
@@ -0,0 +1,33 @@ | |||
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 binding definitions for Altera Arria10 MAX5 System Resource Chip | ||
17 | * | ||
18 | * Adapted from altr,rst-mgr-a10.h | ||
19 | */ | ||
20 | |||
21 | #ifndef _DT_BINDINGS_RESET_ALTR_RST_MGR_A10SR_H | ||
22 | #define _DT_BINDINGS_RESET_ALTR_RST_MGR_A10SR_H | ||
23 | |||
24 | /* Peripheral PHY resets */ | ||
25 | #define A10SR_RESET_ENET_HPS 0 | ||
26 | #define A10SR_RESET_PCIE 1 | ||
27 | #define A10SR_RESET_FILE 2 | ||
28 | #define A10SR_RESET_BQSPI 3 | ||
29 | #define A10SR_RESET_USB 4 | ||
30 | |||
31 | #define A10SR_RESET_NUM 5 | ||
32 | |||
33 | #endif | ||
diff --git a/include/dt-bindings/reset/imx7-reset.h b/include/dt-bindings/reset/imx7-reset.h new file mode 100644 index 000000000000..63948170c7b2 --- /dev/null +++ b/include/dt-bindings/reset/imx7-reset.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Impinj, Inc. | ||
3 | * | ||
4 | * Author: Andrey Smirnov <andrew.smirnov@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #ifndef DT_BINDING_RESET_IMX7_H | ||
20 | #define DT_BINDING_RESET_IMX7_H | ||
21 | |||
22 | #define IMX7_RESET_A7_CORE_POR_RESET0 0 | ||
23 | #define IMX7_RESET_A7_CORE_POR_RESET1 1 | ||
24 | #define IMX7_RESET_A7_CORE_RESET0 2 | ||
25 | #define IMX7_RESET_A7_CORE_RESET1 3 | ||
26 | #define IMX7_RESET_A7_DBG_RESET0 4 | ||
27 | #define IMX7_RESET_A7_DBG_RESET1 5 | ||
28 | #define IMX7_RESET_A7_ETM_RESET0 6 | ||
29 | #define IMX7_RESET_A7_ETM_RESET1 7 | ||
30 | #define IMX7_RESET_A7_SOC_DBG_RESET 8 | ||
31 | #define IMX7_RESET_A7_L2RESET 9 | ||
32 | #define IMX7_RESET_SW_M4C_RST 10 | ||
33 | #define IMX7_RESET_SW_M4P_RST 11 | ||
34 | #define IMX7_RESET_EIM_RST 12 | ||
35 | #define IMX7_RESET_HSICPHY_PORT_RST 13 | ||
36 | #define IMX7_RESET_USBPHY1_POR 14 | ||
37 | #define IMX7_RESET_USBPHY1_PORT_RST 15 | ||
38 | #define IMX7_RESET_USBPHY2_POR 16 | ||
39 | #define IMX7_RESET_USBPHY2_PORT_RST 17 | ||
40 | #define IMX7_RESET_MIPI_PHY_MRST 18 | ||
41 | #define IMX7_RESET_MIPI_PHY_SRST 19 | ||
42 | |||
43 | /* | ||
44 | * IMX7_RESET_PCIEPHY is a logical reset line combining PCIEPHY_BTN | ||
45 | * and PCIEPHY_G_RST | ||
46 | */ | ||
47 | #define IMX7_RESET_PCIEPHY 20 | ||
48 | #define IMX7_RESET_PCIEPHY_PERST 21 | ||
49 | |||
50 | /* | ||
51 | * IMX7_RESET_PCIE_CTRL_APPS_EN is not strictly a reset line, but it | ||
52 | * can be used to inhibit PCIe LTTSM, so, in a way, it can be thoguht | ||
53 | * of as one | ||
54 | */ | ||
55 | #define IMX7_RESET_PCIE_CTRL_APPS_EN 22 | ||
56 | #define IMX7_RESET_DDRC_PRST 23 | ||
57 | #define IMX7_RESET_DDRC_CORE_RST 24 | ||
58 | |||
59 | #define IMX7_RESET_NUM 25 | ||
60 | |||
61 | #endif | ||
62 | |||
diff --git a/include/linux/firmware/meson/meson_sm.h b/include/linux/firmware/meson/meson_sm.h index 8e953c6f394a..37a5eaea69dd 100644 --- a/include/linux/firmware/meson/meson_sm.h +++ b/include/linux/firmware/meson/meson_sm.h | |||
@@ -25,7 +25,7 @@ int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0, u32 arg1, | |||
25 | u32 arg2, u32 arg3, u32 arg4); | 25 | u32 arg2, u32 arg3, u32 arg4); |
26 | int meson_sm_call_write(void *buffer, unsigned int b_size, unsigned int cmd_index, | 26 | int meson_sm_call_write(void *buffer, unsigned int b_size, unsigned int cmd_index, |
27 | u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4); | 27 | u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4); |
28 | int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0, u32 arg1, | 28 | int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index, |
29 | u32 arg2, u32 arg3, u32 arg4); | 29 | u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4); |
30 | 30 | ||
31 | #endif /* _MESON_SM_FW_H_ */ | 31 | #endif /* _MESON_SM_FW_H_ */ |
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 9b6abe632587..b7803a251044 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h | |||
@@ -118,6 +118,7 @@ struct generic_pm_domain_data { | |||
118 | struct pm_domain_data base; | 118 | struct pm_domain_data base; |
119 | struct gpd_timing_data td; | 119 | struct gpd_timing_data td; |
120 | struct notifier_block nb; | 120 | struct notifier_block nb; |
121 | void *data; | ||
121 | }; | 122 | }; |
122 | 123 | ||
123 | #ifdef CONFIG_PM_GENERIC_DOMAINS | 124 | #ifdef CONFIG_PM_GENERIC_DOMAINS |
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index d32f6f1a5225..e5380471c2cd 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h | |||
@@ -40,6 +40,9 @@ extern int qcom_scm_pas_shutdown(u32 peripheral); | |||
40 | extern void qcom_scm_cpu_power_down(u32 flags); | 40 | extern void qcom_scm_cpu_power_down(u32 flags); |
41 | extern u32 qcom_scm_get_version(void); | 41 | extern u32 qcom_scm_get_version(void); |
42 | extern int qcom_scm_set_remote_state(u32 state, u32 id); | 42 | extern int qcom_scm_set_remote_state(u32 state, u32 id); |
43 | extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); | ||
44 | extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size); | ||
45 | extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); | ||
43 | #else | 46 | #else |
44 | static inline | 47 | static inline |
45 | int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) | 48 | int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) |
@@ -67,5 +70,8 @@ static inline void qcom_scm_cpu_power_down(u32 flags) {} | |||
67 | static inline u32 qcom_scm_get_version(void) { return 0; } | 70 | static inline u32 qcom_scm_get_version(void) { return 0; } |
68 | static inline u32 | 71 | static inline u32 |
69 | qcom_scm_set_remote_state(u32 state,u32 id) { return -ENODEV; } | 72 | qcom_scm_set_remote_state(u32 state,u32 id) { return -ENODEV; } |
73 | static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) { return -ENODEV; } | ||
74 | static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { return -ENODEV; } | ||
75 | static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; } | ||
70 | #endif | 76 | #endif |
71 | #endif | 77 | #endif |
diff --git a/arch/arm/mach-tegra/flowctrl.h b/include/soc/tegra/flowctrl.h index 73a9c5016c1a..8f86aea4024b 100644 --- a/arch/arm/mach-tegra/flowctrl.h +++ b/include/soc/tegra/flowctrl.h | |||
@@ -1,7 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/mach-tegra/flowctrl.h | 2 | * Functions and macros to control the flowcontroller |
3 | * | ||
4 | * functions and macros to control the flowcontroller | ||
5 | * | 3 | * |
6 | * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. | 4 | * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. |
7 | * | 5 | * |
@@ -18,8 +16,8 @@ | |||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | */ | 17 | */ |
20 | 18 | ||
21 | #ifndef __MACH_TEGRA_FLOWCTRL_H | 19 | #ifndef __SOC_TEGRA_FLOWCTRL_H__ |
22 | #define __MACH_TEGRA_FLOWCTRL_H | 20 | #define __SOC_TEGRA_FLOWCTRL_H__ |
23 | 21 | ||
24 | #define FLOW_CTRL_HALT_CPU0_EVENTS 0x0 | 22 | #define FLOW_CTRL_HALT_CPU0_EVENTS 0x0 |
25 | #define FLOW_CTRL_WAITEVENT (2 << 29) | 23 | #define FLOW_CTRL_WAITEVENT (2 << 29) |
@@ -53,14 +51,32 @@ | |||
53 | #define TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP (0xF << 8) | 51 | #define TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP (0xF << 8) |
54 | 52 | ||
55 | #ifndef __ASSEMBLY__ | 53 | #ifndef __ASSEMBLY__ |
54 | #ifdef CONFIG_SOC_TEGRA_FLOWCTRL | ||
56 | u32 flowctrl_read_cpu_csr(unsigned int cpuid); | 55 | u32 flowctrl_read_cpu_csr(unsigned int cpuid); |
57 | void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value); | 56 | void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value); |
58 | void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value); | 57 | void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value); |
59 | 58 | ||
60 | void flowctrl_cpu_suspend_enter(unsigned int cpuid); | 59 | void flowctrl_cpu_suspend_enter(unsigned int cpuid); |
61 | void flowctrl_cpu_suspend_exit(unsigned int cpuid); | 60 | void flowctrl_cpu_suspend_exit(unsigned int cpuid); |
61 | #else | ||
62 | static inline u32 flowctrl_read_cpu_csr(unsigned int cpuid) | ||
63 | { | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static inline void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value) | ||
68 | { | ||
69 | } | ||
70 | |||
71 | static inline void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value) {} | ||
62 | 72 | ||
63 | void tegra_flowctrl_init(void); | 73 | static inline void flowctrl_cpu_suspend_enter(unsigned int cpuid) |
64 | #endif | 74 | { |
75 | } | ||
65 | 76 | ||
66 | #endif | 77 | static inline void flowctrl_cpu_suspend_exit(unsigned int cpuid) |
78 | { | ||
79 | } | ||
80 | #endif /* CONFIG_SOC_TEGRA_FLOWCTRL */ | ||
81 | #endif /* __ASSEMBLY */ | ||
82 | #endif /* __SOC_TEGRA_FLOWCTRL_H__ */ | ||
diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h index 2f271d1b9cea..1c3982bc558f 100644 --- a/include/soc/tegra/pmc.h +++ b/include/soc/tegra/pmc.h | |||
@@ -26,12 +26,6 @@ | |||
26 | struct clk; | 26 | struct clk; |
27 | struct reset_control; | 27 | struct reset_control; |
28 | 28 | ||
29 | #ifdef CONFIG_PM_SLEEP | ||
30 | enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void); | ||
31 | void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode); | ||
32 | void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode); | ||
33 | #endif /* CONFIG_PM_SLEEP */ | ||
34 | |||
35 | #ifdef CONFIG_SMP | 29 | #ifdef CONFIG_SMP |
36 | bool tegra_pmc_cpu_is_powered(unsigned int cpuid); | 30 | bool tegra_pmc_cpu_is_powered(unsigned int cpuid); |
37 | int tegra_pmc_cpu_power_on(unsigned int cpuid); | 31 | int tegra_pmc_cpu_power_on(unsigned int cpuid); |
@@ -144,7 +138,7 @@ enum tegra_io_pad_voltage { | |||
144 | TEGRA_IO_PAD_3300000UV, | 138 | TEGRA_IO_PAD_3300000UV, |
145 | }; | 139 | }; |
146 | 140 | ||
147 | #ifdef CONFIG_ARCH_TEGRA | 141 | #ifdef CONFIG_SOC_TEGRA_PMC |
148 | int tegra_powergate_is_powered(unsigned int id); | 142 | int tegra_powergate_is_powered(unsigned int id); |
149 | int tegra_powergate_power_on(unsigned int id); | 143 | int tegra_powergate_power_on(unsigned int id); |
150 | int tegra_powergate_power_off(unsigned int id); | 144 | int tegra_powergate_power_off(unsigned int id); |
@@ -163,6 +157,11 @@ int tegra_io_pad_get_voltage(enum tegra_io_pad id); | |||
163 | /* deprecated, use tegra_io_pad_power_{enable,disable}() instead */ | 157 | /* deprecated, use tegra_io_pad_power_{enable,disable}() instead */ |
164 | int tegra_io_rail_power_on(unsigned int id); | 158 | int tegra_io_rail_power_on(unsigned int id); |
165 | int tegra_io_rail_power_off(unsigned int id); | 159 | int tegra_io_rail_power_off(unsigned int id); |
160 | |||
161 | enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void); | ||
162 | void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode); | ||
163 | void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode); | ||
164 | |||
166 | #else | 165 | #else |
167 | static inline int tegra_powergate_is_powered(unsigned int id) | 166 | static inline int tegra_powergate_is_powered(unsigned int id) |
168 | { | 167 | { |
@@ -221,6 +220,20 @@ static inline int tegra_io_rail_power_off(unsigned int id) | |||
221 | { | 220 | { |
222 | return -ENOSYS; | 221 | return -ENOSYS; |
223 | } | 222 | } |
224 | #endif /* CONFIG_ARCH_TEGRA */ | 223 | |
224 | static inline enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void) | ||
225 | { | ||
226 | return TEGRA_SUSPEND_NONE; | ||
227 | } | ||
228 | |||
229 | static inline void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode) | ||
230 | { | ||
231 | } | ||
232 | |||
233 | static inline void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode) | ||
234 | { | ||
235 | } | ||
236 | |||
237 | #endif /* CONFIG_SOC_TEGRA_PMC */ | ||
225 | 238 | ||
226 | #endif /* __SOC_TEGRA_PMC_H__ */ | 239 | #endif /* __SOC_TEGRA_PMC_H__ */ |