aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2019-02-15 12:00:42 -0500
committerArnd Bergmann <arnd@arndb.de>2019-02-15 12:01:17 -0500
commit187b4ac7dfeb74cf6e6043f82aeab4ddc2a4c44a (patch)
treed1a3e4b49183d0bd2841a9d45463f79bbbe5fe6b
parent405bcfff172db863b7c4b63e0e0ef8508966c90a (diff)
parent50de64947f40f869dc5b9306891b750f317135ef (diff)
Merge tag 'arm-soc/for-5.1/drivers' of https://github.com/Broadcom/stblinux into arm/drivers
This pull request contains Broadcom ARM/ARM64/MIPS based SoCs changes for 5.1, please pull the following: - Stefan updates the BCM2835 SoC driver with downstream properties and uses that to implement a reboot notifier to tell the VC4 firmware when Linux on the ARM CPU is rebooting - Eric adds a proper power domain driver for the BCM283x SoCs and updates a bunch of drivers to have a better and clearer Device Tree definition to support power domains/breaking up of functionality. This requires converting the existing watchdog driver into a MFD and then breaking up the functionality into separate drivers and finally updating the DTS files to leverage the power domains information. - Wei provides a fix for making a symbol static * tag 'arm-soc/for-5.1/drivers' of https://github.com/Broadcom/stblinux: ARM: bcm283x: Switch V3D over to using the PM driver instead of firmware. ARM: bcm283x: Extend the WDT DT node out to cover the whole PM block. (v4) soc: bcm: bcm2835-pm: Make local symbol static soc: bcm: Make PM driver default for BCM2835 soc: bcm: bcm2835-pm: Add support for power domains under a new binding. bcm2835-pm: Move bcm2835-watchdog's DT probe to an MFD. dt-bindings: soc: Add a new binding for the BCM2835 PM node. (v4) firmware: raspberrypi: notify VC4 firmware of a reboot soc: bcm2835: sync firmware properties with downstream Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--Documentation/devicetree/bindings/soc/bcm/brcm,bcm2835-pm.txt46
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi.dtsi4
-rw-r--r--arch/arm/boot/dts/bcm283x.dtsi17
-rw-r--r--arch/arm/mach-bcm/Kconfig1
-rw-r--r--drivers/firmware/raspberrypi.c11
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/bcm2835-pm.c92
-rw-r--r--drivers/soc/bcm/Kconfig12
-rw-r--r--drivers/soc/bcm/Makefile1
-rw-r--r--drivers/soc/bcm/bcm2835-power.c661
-rw-r--r--drivers/watchdog/bcm2835_wdt.c26
-rw-r--r--include/dt-bindings/soc/bcm2835-pm.h28
-rw-r--r--include/linux/mfd/bcm2835-pm.h14
-rw-r--r--include/soc/bcm2835/raspberrypi-firmware.h4
14 files changed, 894 insertions, 24 deletions
diff --git a/Documentation/devicetree/bindings/soc/bcm/brcm,bcm2835-pm.txt b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm2835-pm.txt
new file mode 100644
index 000000000000..3b7d32956391
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm2835-pm.txt
@@ -0,0 +1,46 @@
1BCM2835 PM (Power domains, watchdog)
2
3The PM block controls power domains and some reset lines, and includes
4a watchdog timer. This binding supersedes the brcm,bcm2835-pm-wdt
5binding which covered some of PM's register range and functionality.
6
7Required properties:
8
9- compatible: Should be "brcm,bcm2835-pm"
10- reg: Specifies base physical address and size of the two
11 register ranges ("PM" and "ASYNC_BRIDGE" in that
12 order)
13- clocks: a) v3d: The V3D clock from CPRMAN
14 b) peri_image: The PERI_IMAGE clock from CPRMAN
15 c) h264: The H264 clock from CPRMAN
16 d) isp: The ISP clock from CPRMAN
17- #reset-cells: Should be 1. This property follows the reset controller
18 bindings[1].
19- #power-domain-cells: Should be 1. This property follows the power domain
20 bindings[2].
21
22Optional properties:
23
24- timeout-sec: Contains the watchdog timeout in seconds
25- system-power-controller: Whether the watchdog is controlling the
26 system power. This node follows the power controller bindings[3].
27
28[1] Documentation/devicetree/bindings/reset/reset.txt
29[2] Documentation/devicetree/bindings/power/power_domain.txt
30[3] Documentation/devicetree/bindings/power/power-controller.txt
31
32Example:
33
34pm {
35 compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
36 #power-domain-cells = <1>;
37 #reset-cells = <1>;
38 reg = <0x7e100000 0x114>,
39 <0x7e00a000 0x24>;
40 clocks = <&clocks BCM2835_CLOCK_V3D>,
41 <&clocks BCM2835_CLOCK_PERI_IMAGE>,
42 <&clocks BCM2835_CLOCK_H264>,
43 <&clocks BCM2835_CLOCK_ISP>;
44 clock-names = "v3d", "peri_image", "h264", "isp";
45 system-power-controller;
46};
diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi
index 29f970f864dc..c6e2b2320abc 100644
--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
@@ -87,10 +87,6 @@
87 power-domains = <&power RPI_POWER_DOMAIN_USB>; 87 power-domains = <&power RPI_POWER_DOMAIN_USB>;
88}; 88};
89 89
90&v3d {
91 power-domains = <&power RPI_POWER_DOMAIN_V3D>;
92};
93
94&hdmi { 90&hdmi {
95 power-domains = <&power RPI_POWER_DOMAIN_HDMI>; 91 power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
96 status = "okay"; 92 status = "okay";
diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index 31b29646b14c..9777644c6c2b 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
+++ b/arch/arm/boot/dts/bcm283x.dtsi
@@ -3,6 +3,7 @@
3#include <dt-bindings/clock/bcm2835-aux.h> 3#include <dt-bindings/clock/bcm2835-aux.h>
4#include <dt-bindings/gpio/gpio.h> 4#include <dt-bindings/gpio/gpio.h>
5#include <dt-bindings/interrupt-controller/irq.h> 5#include <dt-bindings/interrupt-controller/irq.h>
6#include <dt-bindings/soc/bcm2835-pm.h>
6 7
7/* firmware-provided startup stubs live here, where the secondary CPUs are 8/* firmware-provided startup stubs live here, where the secondary CPUs are
8 * spinning. 9 * spinning.
@@ -120,9 +121,18 @@
120 #interrupt-cells = <2>; 121 #interrupt-cells = <2>;
121 }; 122 };
122 123
123 watchdog@7e100000 { 124 pm: watchdog@7e100000 {
124 compatible = "brcm,bcm2835-pm-wdt"; 125 compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
125 reg = <0x7e100000 0x28>; 126 #power-domain-cells = <1>;
127 #reset-cells = <1>;
128 reg = <0x7e100000 0x114>,
129 <0x7e00a000 0x24>;
130 clocks = <&clocks BCM2835_CLOCK_V3D>,
131 <&clocks BCM2835_CLOCK_PERI_IMAGE>,
132 <&clocks BCM2835_CLOCK_H264>,
133 <&clocks BCM2835_CLOCK_ISP>;
134 clock-names = "v3d", "peri_image", "h264", "isp";
135 system-power-controller;
126 }; 136 };
127 137
128 clocks: cprman@7e101000 { 138 clocks: cprman@7e101000 {
@@ -629,6 +639,7 @@
629 compatible = "brcm,bcm2835-v3d"; 639 compatible = "brcm,bcm2835-v3d";
630 reg = <0x7ec00000 0x1000>; 640 reg = <0x7ec00000 0x1000>;
631 interrupts = <1 10>; 641 interrupts = <1 10>;
642 power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>;
632 }; 643 };
633 644
634 vc4: gpu { 645 vc4: gpu {
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index a067adf9f1ee..4ef1e55f4a0b 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -167,6 +167,7 @@ config ARCH_BCM2835
167 select BCM2835_TIMER 167 select BCM2835_TIMER
168 select PINCTRL 168 select PINCTRL
169 select PINCTRL_BCM2835 169 select PINCTRL_BCM2835
170 select MFD_CORE
170 help 171 help
171 This enables support for the Broadcom BCM2835 and BCM2836 SoCs. 172 This enables support for the Broadcom BCM2835 and BCM2836 SoCs.
172 This SoC is used in the Raspberry Pi and Roku 2 devices. 173 This SoC is used in the Raspberry Pi and Roku 2 devices.
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index a13558154ac3..61be15d9df7d 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -238,6 +238,16 @@ static int rpi_firmware_probe(struct platform_device *pdev)
238 return 0; 238 return 0;
239} 239}
240 240
241static void rpi_firmware_shutdown(struct platform_device *pdev)
242{
243 struct rpi_firmware *fw = platform_get_drvdata(pdev);
244
245 if (!fw)
246 return;
247
248 rpi_firmware_property(fw, RPI_FIRMWARE_NOTIFY_REBOOT, NULL, 0);
249}
250
241static int rpi_firmware_remove(struct platform_device *pdev) 251static int rpi_firmware_remove(struct platform_device *pdev)
242{ 252{
243 struct rpi_firmware *fw = platform_get_drvdata(pdev); 253 struct rpi_firmware *fw = platform_get_drvdata(pdev);
@@ -278,6 +288,7 @@ static struct platform_driver rpi_firmware_driver = {
278 .of_match_table = rpi_firmware_of_match, 288 .of_match_table = rpi_firmware_of_match,
279 }, 289 },
280 .probe = rpi_firmware_probe, 290 .probe = rpi_firmware_probe,
291 .shutdown = rpi_firmware_shutdown,
281 .remove = rpi_firmware_remove, 292 .remove = rpi_firmware_remove,
282}; 293};
283module_platform_driver(rpi_firmware_driver); 294module_platform_driver(rpi_firmware_driver);
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 12980a4ad460..ee6fb6af655e 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o
10obj-$(CONFIG_MFD_ACT8945A) += act8945a.o 10obj-$(CONFIG_MFD_ACT8945A) += act8945a.o
11obj-$(CONFIG_MFD_SM501) += sm501.o 11obj-$(CONFIG_MFD_SM501) += sm501.o
12obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o 12obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
13obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
13obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o 14obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
14obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o 15obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
15cros_ec_core-objs := cros_ec.o 16cros_ec_core-objs := cros_ec.o
diff --git a/drivers/mfd/bcm2835-pm.c b/drivers/mfd/bcm2835-pm.c
new file mode 100644
index 000000000000..42fe67f1538e
--- /dev/null
+++ b/drivers/mfd/bcm2835-pm.c
@@ -0,0 +1,92 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * PM MFD driver for Broadcom BCM2835
4 *
5 * This driver binds to the PM block and creates the MFD device for
6 * the WDT and power drivers.
7 */
8
9#include <linux/delay.h>
10#include <linux/io.h>
11#include <linux/mfd/bcm2835-pm.h>
12#include <linux/mfd/core.h>
13#include <linux/module.h>
14#include <linux/of_address.h>
15#include <linux/of_platform.h>
16#include <linux/platform_device.h>
17#include <linux/types.h>
18#include <linux/watchdog.h>
19
20static const struct mfd_cell bcm2835_pm_devs[] = {
21 { .name = "bcm2835-wdt" },
22};
23
24static const struct mfd_cell bcm2835_power_devs[] = {
25 { .name = "bcm2835-power" },
26};
27
28static int bcm2835_pm_probe(struct platform_device *pdev)
29{
30 struct resource *res;
31 struct device *dev = &pdev->dev;
32 struct bcm2835_pm *pm;
33 int ret;
34
35 pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
36 if (!pm)
37 return -ENOMEM;
38 platform_set_drvdata(pdev, pm);
39
40 pm->dev = dev;
41
42 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
43 pm->base = devm_ioremap_resource(dev, res);
44 if (IS_ERR(pm->base))
45 return PTR_ERR(pm->base);
46
47 ret = devm_mfd_add_devices(dev, -1,
48 bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),
49 NULL, 0, NULL);
50 if (ret)
51 return ret;
52
53 /* We'll use the presence of the AXI ASB regs in the
54 * bcm2835-pm binding as the key for whether we can reference
55 * the full PM register range and support power domains.
56 */
57 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
58 if (res) {
59 pm->asb = devm_ioremap_resource(dev, res);
60 if (IS_ERR(pm->asb))
61 return PTR_ERR(pm->asb);
62
63 ret = devm_mfd_add_devices(dev, -1,
64 bcm2835_power_devs,
65 ARRAY_SIZE(bcm2835_power_devs),
66 NULL, 0, NULL);
67 if (ret)
68 return ret;
69 }
70
71 return 0;
72}
73
74static const struct of_device_id bcm2835_pm_of_match[] = {
75 { .compatible = "brcm,bcm2835-pm-wdt", },
76 { .compatible = "brcm,bcm2835-pm", },
77 {},
78};
79MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
80
81static struct platform_driver bcm2835_pm_driver = {
82 .probe = bcm2835_pm_probe,
83 .driver = {
84 .name = "bcm2835-pm",
85 .of_match_table = bcm2835_pm_of_match,
86 },
87};
88module_platform_driver(bcm2835_pm_driver);
89
90MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
91MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM MFD");
92MODULE_LICENSE("GPL");
diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig
index 055a845ed979..03fa91fbe2da 100644
--- a/drivers/soc/bcm/Kconfig
+++ b/drivers/soc/bcm/Kconfig
@@ -1,5 +1,17 @@
1menu "Broadcom SoC drivers" 1menu "Broadcom SoC drivers"
2 2
3config BCM2835_POWER
4 bool "BCM2835 power domain driver"
5 depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
6 default y if ARCH_BCM2835
7 select PM_GENERIC_DOMAINS if PM
8 select RESET_CONTROLLER
9 help
10 This enables support for the BCM2835 power domains and reset
11 controller. Any usage of power domains by the Raspberry Pi
12 firmware means that Linux usage of the same power domain
13 must be accessed using the RASPBERRYPI_POWER driver
14
3config RASPBERRYPI_POWER 15config RASPBERRYPI_POWER
4 bool "Raspberry Pi power domain driver" 16 bool "Raspberry Pi power domain driver"
5 depends on ARCH_BCM2835 || (COMPILE_TEST && OF) 17 depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
diff --git a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile
index dc4fced72d21..c81df4b2403c 100644
--- a/drivers/soc/bcm/Makefile
+++ b/drivers/soc/bcm/Makefile
@@ -1,2 +1,3 @@
1obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o
1obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o 2obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o
2obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/ 3obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
diff --git a/drivers/soc/bcm/bcm2835-power.c b/drivers/soc/bcm/bcm2835-power.c
new file mode 100644
index 000000000000..9351349cf0a9
--- /dev/null
+++ b/drivers/soc/bcm/bcm2835-power.c
@@ -0,0 +1,661 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Power domain driver for Broadcom BCM2835
4 *
5 * Copyright (C) 2018 Broadcom
6 */
7
8#include <dt-bindings/soc/bcm2835-pm.h>
9#include <linux/clk.h>
10#include <linux/delay.h>
11#include <linux/io.h>
12#include <linux/mfd/bcm2835-pm.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/pm_domain.h>
16#include <linux/reset-controller.h>
17#include <linux/types.h>
18
19#define PM_GNRIC 0x00
20#define PM_AUDIO 0x04
21#define PM_STATUS 0x18
22#define PM_RSTC 0x1c
23#define PM_RSTS 0x20
24#define PM_WDOG 0x24
25#define PM_PADS0 0x28
26#define PM_PADS2 0x2c
27#define PM_PADS3 0x30
28#define PM_PADS4 0x34
29#define PM_PADS5 0x38
30#define PM_PADS6 0x3c
31#define PM_CAM0 0x44
32#define PM_CAM0_LDOHPEN BIT(2)
33#define PM_CAM0_LDOLPEN BIT(1)
34#define PM_CAM0_CTRLEN BIT(0)
35
36#define PM_CAM1 0x48
37#define PM_CAM1_LDOHPEN BIT(2)
38#define PM_CAM1_LDOLPEN BIT(1)
39#define PM_CAM1_CTRLEN BIT(0)
40
41#define PM_CCP2TX 0x4c
42#define PM_CCP2TX_LDOEN BIT(1)
43#define PM_CCP2TX_CTRLEN BIT(0)
44
45#define PM_DSI0 0x50
46#define PM_DSI0_LDOHPEN BIT(2)
47#define PM_DSI0_LDOLPEN BIT(1)
48#define PM_DSI0_CTRLEN BIT(0)
49
50#define PM_DSI1 0x54
51#define PM_DSI1_LDOHPEN BIT(2)
52#define PM_DSI1_LDOLPEN BIT(1)
53#define PM_DSI1_CTRLEN BIT(0)
54
55#define PM_HDMI 0x58
56#define PM_HDMI_RSTDR BIT(19)
57#define PM_HDMI_LDOPD BIT(1)
58#define PM_HDMI_CTRLEN BIT(0)
59
60#define PM_USB 0x5c
61/* The power gates must be enabled with this bit before enabling the LDO in the
62 * USB block.
63 */
64#define PM_USB_CTRLEN BIT(0)
65
66#define PM_PXLDO 0x60
67#define PM_PXBG 0x64
68#define PM_DFT 0x68
69#define PM_SMPS 0x6c
70#define PM_XOSC 0x70
71#define PM_SPAREW 0x74
72#define PM_SPARER 0x78
73#define PM_AVS_RSTDR 0x7c
74#define PM_AVS_STAT 0x80
75#define PM_AVS_EVENT 0x84
76#define PM_AVS_INTEN 0x88
77#define PM_DUMMY 0xfc
78
79#define PM_IMAGE 0x108
80#define PM_GRAFX 0x10c
81#define PM_PROC 0x110
82#define PM_ENAB BIT(12)
83#define PM_ISPRSTN BIT(8)
84#define PM_H264RSTN BIT(7)
85#define PM_PERIRSTN BIT(6)
86#define PM_V3DRSTN BIT(6)
87#define PM_ISFUNC BIT(5)
88#define PM_MRDONE BIT(4)
89#define PM_MEMREP BIT(3)
90#define PM_ISPOW BIT(2)
91#define PM_POWOK BIT(1)
92#define PM_POWUP BIT(0)
93#define PM_INRUSH_SHIFT 13
94#define PM_INRUSH_3_5_MA 0
95#define PM_INRUSH_5_MA 1
96#define PM_INRUSH_10_MA 2
97#define PM_INRUSH_20_MA 3
98#define PM_INRUSH_MASK (3 << PM_INRUSH_SHIFT)
99
100#define PM_PASSWORD 0x5a000000
101
102#define PM_WDOG_TIME_SET 0x000fffff
103#define PM_RSTC_WRCFG_CLR 0xffffffcf
104#define PM_RSTS_HADWRH_SET 0x00000040
105#define PM_RSTC_WRCFG_SET 0x00000030
106#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
107#define PM_RSTC_RESET 0x00000102
108
109#define PM_READ(reg) readl(power->base + (reg))
110#define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg))
111
112#define ASB_BRDG_VERSION 0x00
113#define ASB_CPR_CTRL 0x04
114
115#define ASB_V3D_S_CTRL 0x08
116#define ASB_V3D_M_CTRL 0x0c
117#define ASB_ISP_S_CTRL 0x10
118#define ASB_ISP_M_CTRL 0x14
119#define ASB_H264_S_CTRL 0x18
120#define ASB_H264_M_CTRL 0x1c
121
122#define ASB_REQ_STOP BIT(0)
123#define ASB_ACK BIT(1)
124#define ASB_EMPTY BIT(2)
125#define ASB_FULL BIT(3)
126
127#define ASB_AXI_BRDG_ID 0x20
128
129#define ASB_READ(reg) readl(power->asb + (reg))
130#define ASB_WRITE(reg, val) writel(PM_PASSWORD | (val), power->asb + (reg))
131
132struct bcm2835_power_domain {
133 struct generic_pm_domain base;
134 struct bcm2835_power *power;
135 u32 domain;
136 struct clk *clk;
137};
138
139struct bcm2835_power {
140 struct device *dev;
141 /* PM registers. */
142 void __iomem *base;
143 /* AXI Async bridge registers. */
144 void __iomem *asb;
145
146 struct genpd_onecell_data pd_xlate;
147 struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
148 struct reset_controller_dev reset;
149};
150
151static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
152{
153 u64 start = ktime_get_ns();
154
155 /* Enable the module's async AXI bridges. */
156 ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
157 while (ASB_READ(reg) & ASB_ACK) {
158 cpu_relax();
159 if (ktime_get_ns() - start >= 1000)
160 return -ETIMEDOUT;
161 }
162
163 return 0;
164}
165
166static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
167{
168 u64 start = ktime_get_ns();
169
170 /* Enable the module's async AXI bridges. */
171 ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
172 while (!(ASB_READ(reg) & ASB_ACK)) {
173 cpu_relax();
174 if (ktime_get_ns() - start >= 1000)
175 return -ETIMEDOUT;
176 }
177
178 return 0;
179}
180
181static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
182{
183 struct bcm2835_power *power = pd->power;
184
185 /* Enable functional isolation */
186 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
187
188 /* Enable electrical isolation */
189 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
190
191 /* Open the power switches. */
192 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);
193
194 return 0;
195}
196
197static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
198{
199 struct bcm2835_power *power = pd->power;
200 struct device *dev = power->dev;
201 u64 start;
202 int ret;
203 int inrush;
204 bool powok;
205
206 /* If it was already powered on by the fw, leave it that way. */
207 if (PM_READ(pm_reg) & PM_POWUP)
208 return 0;
209
210 /* Enable power. Allowing too much current at once may result
211 * in POWOK never getting set, so start low and ramp it up as
212 * necessary to succeed.
213 */
214 powok = false;
215 for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) {
216 PM_WRITE(pm_reg,
217 (PM_READ(pm_reg) & ~PM_INRUSH_MASK) |
218 (inrush << PM_INRUSH_SHIFT) |
219 PM_POWUP);
220
221 start = ktime_get_ns();
222 while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) {
223 cpu_relax();
224 if (ktime_get_ns() - start >= 3000)
225 break;
226 }
227 }
228 if (!powok) {
229 dev_err(dev, "Timeout waiting for %s power OK\n",
230 pd->base.name);
231 ret = -ETIMEDOUT;
232 goto err_disable_powup;
233 }
234
235 /* Disable electrical isolation */
236 PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW);
237
238 /* Repair memory */
239 PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP);
240 start = ktime_get_ns();
241 while (!(PM_READ(pm_reg) & PM_MRDONE)) {
242 cpu_relax();
243 if (ktime_get_ns() - start >= 1000) {
244 dev_err(dev, "Timeout waiting for %s memory repair\n",
245 pd->base.name);
246 ret = -ETIMEDOUT;
247 goto err_disable_ispow;
248 }
249 }
250
251 /* Disable functional isolation */
252 PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC);
253
254 return 0;
255
256err_disable_ispow:
257 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
258err_disable_powup:
259 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
260 return ret;
261}
262
263static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd,
264 u32 pm_reg,
265 u32 asb_m_reg,
266 u32 asb_s_reg,
267 u32 reset_flags)
268{
269 struct bcm2835_power *power = pd->power;
270 int ret;
271
272 ret = clk_prepare_enable(pd->clk);
273 if (ret) {
274 dev_err(power->dev, "Failed to enable clock for %s\n",
275 pd->base.name);
276 return ret;
277 }
278
279 /* Wait 32 clocks for reset to propagate, 1 us will be enough */
280 udelay(1);
281
282 clk_disable_unprepare(pd->clk);
283
284 /* Deassert the resets. */
285 PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags);
286
287 ret = clk_prepare_enable(pd->clk);
288 if (ret) {
289 dev_err(power->dev, "Failed to enable clock for %s\n",
290 pd->base.name);
291 goto err_enable_resets;
292 }
293
294 ret = bcm2835_asb_enable(power, asb_m_reg);
295 if (ret) {
296 dev_err(power->dev, "Failed to enable ASB master for %s\n",
297 pd->base.name);
298 goto err_disable_clk;
299 }
300 ret = bcm2835_asb_enable(power, asb_s_reg);
301 if (ret) {
302 dev_err(power->dev, "Failed to enable ASB slave for %s\n",
303 pd->base.name);
304 goto err_disable_asb_master;
305 }
306
307 return 0;
308
309err_disable_asb_master:
310 bcm2835_asb_disable(power, asb_m_reg);
311err_disable_clk:
312 clk_disable_unprepare(pd->clk);
313err_enable_resets:
314 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
315 return ret;
316}
317
318static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd,
319 u32 pm_reg,
320 u32 asb_m_reg,
321 u32 asb_s_reg,
322 u32 reset_flags)
323{
324 struct bcm2835_power *power = pd->power;
325 int ret;
326
327 ret = bcm2835_asb_disable(power, asb_s_reg);
328 if (ret) {
329 dev_warn(power->dev, "Failed to disable ASB slave for %s\n",
330 pd->base.name);
331 return ret;
332 }
333 ret = bcm2835_asb_disable(power, asb_m_reg);
334 if (ret) {
335 dev_warn(power->dev, "Failed to disable ASB master for %s\n",
336 pd->base.name);
337 bcm2835_asb_enable(power, asb_s_reg);
338 return ret;
339 }
340
341 clk_disable_unprepare(pd->clk);
342
343 /* Assert the resets. */
344 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
345
346 return 0;
347}
348
349static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain)
350{
351 struct bcm2835_power_domain *pd =
352 container_of(domain, struct bcm2835_power_domain, base);
353 struct bcm2835_power *power = pd->power;
354
355 switch (pd->domain) {
356 case BCM2835_POWER_DOMAIN_GRAFX:
357 return bcm2835_power_power_on(pd, PM_GRAFX);
358
359 case BCM2835_POWER_DOMAIN_GRAFX_V3D:
360 return bcm2835_asb_power_on(pd, PM_GRAFX,
361 ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
362 PM_V3DRSTN);
363
364 case BCM2835_POWER_DOMAIN_IMAGE:
365 return bcm2835_power_power_on(pd, PM_IMAGE);
366
367 case BCM2835_POWER_DOMAIN_IMAGE_PERI:
368 return bcm2835_asb_power_on(pd, PM_IMAGE,
369 0, 0,
370 PM_PERIRSTN);
371
372 case BCM2835_POWER_DOMAIN_IMAGE_ISP:
373 return bcm2835_asb_power_on(pd, PM_IMAGE,
374 ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
375 PM_ISPRSTN);
376
377 case BCM2835_POWER_DOMAIN_IMAGE_H264:
378 return bcm2835_asb_power_on(pd, PM_IMAGE,
379 ASB_H264_M_CTRL, ASB_H264_S_CTRL,
380 PM_H264RSTN);
381
382 case BCM2835_POWER_DOMAIN_USB:
383 PM_WRITE(PM_USB, PM_USB_CTRLEN);
384 return 0;
385
386 case BCM2835_POWER_DOMAIN_DSI0:
387 PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
388 PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN);
389 return 0;
390
391 case BCM2835_POWER_DOMAIN_DSI1:
392 PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
393 PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN);
394 return 0;
395
396 case BCM2835_POWER_DOMAIN_CCP2TX:
397 PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
398 PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN);
399 return 0;
400
401 case BCM2835_POWER_DOMAIN_HDMI:
402 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR);
403 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN);
404 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD);
405 usleep_range(100, 200);
406 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR);
407 return 0;
408
409 default:
410 dev_err(power->dev, "Invalid domain %d\n", pd->domain);
411 return -EINVAL;
412 }
413}
414
415static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain)
416{
417 struct bcm2835_power_domain *pd =
418 container_of(domain, struct bcm2835_power_domain, base);
419 struct bcm2835_power *power = pd->power;
420
421 switch (pd->domain) {
422 case BCM2835_POWER_DOMAIN_GRAFX:
423 return bcm2835_power_power_off(pd, PM_GRAFX);
424
425 case BCM2835_POWER_DOMAIN_GRAFX_V3D:
426 return bcm2835_asb_power_off(pd, PM_GRAFX,
427 ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
428 PM_V3DRSTN);
429
430 case BCM2835_POWER_DOMAIN_IMAGE:
431 return bcm2835_power_power_off(pd, PM_IMAGE);
432
433 case BCM2835_POWER_DOMAIN_IMAGE_PERI:
434 return bcm2835_asb_power_off(pd, PM_IMAGE,
435 0, 0,
436 PM_PERIRSTN);
437
438 case BCM2835_POWER_DOMAIN_IMAGE_ISP:
439 return bcm2835_asb_power_off(pd, PM_IMAGE,
440 ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
441 PM_ISPRSTN);
442
443 case BCM2835_POWER_DOMAIN_IMAGE_H264:
444 return bcm2835_asb_power_off(pd, PM_IMAGE,
445 ASB_H264_M_CTRL, ASB_H264_S_CTRL,
446 PM_H264RSTN);
447
448 case BCM2835_POWER_DOMAIN_USB:
449 PM_WRITE(PM_USB, 0);
450 return 0;
451
452 case BCM2835_POWER_DOMAIN_DSI0:
453 PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
454 PM_WRITE(PM_DSI0, 0);
455 return 0;
456
457 case BCM2835_POWER_DOMAIN_DSI1:
458 PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
459 PM_WRITE(PM_DSI1, 0);
460 return 0;
461
462 case BCM2835_POWER_DOMAIN_CCP2TX:
463 PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
464 PM_WRITE(PM_CCP2TX, 0);
465 return 0;
466
467 case BCM2835_POWER_DOMAIN_HDMI:
468 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD);
469 PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN);
470 return 0;
471
472 default:
473 dev_err(power->dev, "Invalid domain %d\n", pd->domain);
474 return -EINVAL;
475 }
476}
477
478static void
479bcm2835_init_power_domain(struct bcm2835_power *power,
480 int pd_xlate_index, const char *name)
481{
482 struct device *dev = power->dev;
483 struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
484
485 dom->clk = devm_clk_get(dev->parent, name);
486
487 dom->base.name = name;
488 dom->base.power_on = bcm2835_power_pd_power_on;
489 dom->base.power_off = bcm2835_power_pd_power_off;
490
491 dom->domain = pd_xlate_index;
492 dom->power = power;
493
494 /* XXX: on/off at boot? */
495 pm_genpd_init(&dom->base, NULL, true);
496
497 power->pd_xlate.domains[pd_xlate_index] = &dom->base;
498}
499
500/** bcm2835_reset_reset - Resets a block that has a reset line in the
501 * PM block.
502 *
503 * The consumer of the reset controller must have the power domain up
504 * -- there's no reset ability with the power domain down. To reset
505 * the sub-block, we just disable its access to memory through the
506 * ASB, reset, and re-enable.
507 */
508static int bcm2835_reset_reset(struct reset_controller_dev *rcdev,
509 unsigned long id)
510{
511 struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
512 reset);
513 struct bcm2835_power_domain *pd;
514 int ret;
515
516 switch (id) {
517 case BCM2835_RESET_V3D:
518 pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D];
519 break;
520 case BCM2835_RESET_H264:
521 pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264];
522 break;
523 case BCM2835_RESET_ISP:
524 pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP];
525 break;
526 default:
527 dev_err(power->dev, "Bad reset id %ld\n", id);
528 return -EINVAL;
529 }
530
531 ret = bcm2835_power_pd_power_off(&pd->base);
532 if (ret)
533 return ret;
534
535 return bcm2835_power_pd_power_on(&pd->base);
536}
537
538static int bcm2835_reset_status(struct reset_controller_dev *rcdev,
539 unsigned long id)
540{
541 struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
542 reset);
543
544 switch (id) {
545 case BCM2835_RESET_V3D:
546 return !PM_READ(PM_GRAFX & PM_V3DRSTN);
547 case BCM2835_RESET_H264:
548 return !PM_READ(PM_IMAGE & PM_H264RSTN);
549 case BCM2835_RESET_ISP:
550 return !PM_READ(PM_IMAGE & PM_ISPRSTN);
551 default:
552 return -EINVAL;
553 }
554}
555
556static const struct reset_control_ops bcm2835_reset_ops = {
557 .reset = bcm2835_reset_reset,
558 .status = bcm2835_reset_status,
559};
560
561static const char *const power_domain_names[] = {
562 [BCM2835_POWER_DOMAIN_GRAFX] = "grafx",
563 [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d",
564
565 [BCM2835_POWER_DOMAIN_IMAGE] = "image",
566 [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image",
567 [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264",
568 [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp",
569
570 [BCM2835_POWER_DOMAIN_USB] = "usb",
571 [BCM2835_POWER_DOMAIN_DSI0] = "dsi0",
572 [BCM2835_POWER_DOMAIN_DSI1] = "dsi1",
573 [BCM2835_POWER_DOMAIN_CAM0] = "cam0",
574 [BCM2835_POWER_DOMAIN_CAM1] = "cam1",
575 [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx",
576 [BCM2835_POWER_DOMAIN_HDMI] = "hdmi",
577};
578
579static int bcm2835_power_probe(struct platform_device *pdev)
580{
581 struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
582 struct device *dev = &pdev->dev;
583 struct bcm2835_power *power;
584 static const struct {
585 int parent, child;
586 } domain_deps[] = {
587 { BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D },
588 { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI },
589 { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 },
590 { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP },
591 { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB },
592 { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
593 { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
594 };
595 int ret, i;
596 u32 id;
597
598 power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
599 if (!power)
600 return -ENOMEM;
601 platform_set_drvdata(pdev, power);
602
603 power->dev = dev;
604 power->base = pm->base;
605 power->asb = pm->asb;
606
607 id = ASB_READ(ASB_AXI_BRDG_ID);
608 if (id != 0x62726467 /* "BRDG" */) {
609 dev_err(dev, "ASB register ID returned 0x%08x\n", id);
610 return -ENODEV;
611 }
612
613 power->pd_xlate.domains = devm_kcalloc(dev,
614 ARRAY_SIZE(power_domain_names),
615 sizeof(*power->pd_xlate.domains),
616 GFP_KERNEL);
617 if (!power->pd_xlate.domains)
618 return -ENOMEM;
619
620 power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
621
622 for (i = 0; i < ARRAY_SIZE(power_domain_names); i++)
623 bcm2835_init_power_domain(power, i, power_domain_names[i]);
624
625 for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
626 pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
627 &power->domains[domain_deps[i].child].base);
628 }
629
630 power->reset.owner = THIS_MODULE;
631 power->reset.nr_resets = BCM2835_RESET_COUNT;
632 power->reset.ops = &bcm2835_reset_ops;
633 power->reset.of_node = dev->parent->of_node;
634
635 ret = devm_reset_controller_register(dev, &power->reset);
636 if (ret)
637 return ret;
638
639 of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
640
641 dev_info(dev, "Broadcom BCM2835 power domains driver");
642 return 0;
643}
644
645static int bcm2835_power_remove(struct platform_device *pdev)
646{
647 return 0;
648}
649
650static struct platform_driver bcm2835_power_driver = {
651 .probe = bcm2835_power_probe,
652 .remove = bcm2835_power_remove,
653 .driver = {
654 .name = "bcm2835-power",
655 },
656};
657module_platform_driver(bcm2835_power_driver);
658
659MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
660MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
661MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c
index ed05514cc2dc..1834524ae373 100644
--- a/drivers/watchdog/bcm2835_wdt.c
+++ b/drivers/watchdog/bcm2835_wdt.c
@@ -12,6 +12,7 @@
12 12
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/types.h> 14#include <linux/types.h>
15#include <linux/mfd/bcm2835-pm.h>
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/io.h> 17#include <linux/io.h>
17#include <linux/watchdog.h> 18#include <linux/watchdog.h>
@@ -47,6 +48,8 @@ struct bcm2835_wdt {
47 spinlock_t lock; 48 spinlock_t lock;
48}; 49};
49 50
51static struct bcm2835_wdt *bcm2835_power_off_wdt;
52
50static unsigned int heartbeat; 53static unsigned int heartbeat;
51static bool nowayout = WATCHDOG_NOWAYOUT; 54static bool nowayout = WATCHDOG_NOWAYOUT;
52 55
@@ -148,10 +151,7 @@ static struct watchdog_device bcm2835_wdt_wdd = {
148 */ 151 */
149static void bcm2835_power_off(void) 152static void bcm2835_power_off(void)
150{ 153{
151 struct device_node *np = 154 struct bcm2835_wdt *wdt = bcm2835_power_off_wdt;
152 of_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm-wdt");
153 struct platform_device *pdev = of_find_device_by_node(np);
154 struct bcm2835_wdt *wdt = platform_get_drvdata(pdev);
155 u32 val; 155 u32 val;
156 156
157 /* 157 /*
@@ -169,7 +169,7 @@ static void bcm2835_power_off(void)
169 169
170static int bcm2835_wdt_probe(struct platform_device *pdev) 170static int bcm2835_wdt_probe(struct platform_device *pdev)
171{ 171{
172 struct resource *res; 172 struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
173 struct device *dev = &pdev->dev; 173 struct device *dev = &pdev->dev;
174 struct bcm2835_wdt *wdt; 174 struct bcm2835_wdt *wdt;
175 int err; 175 int err;
@@ -181,10 +181,7 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
181 181
182 spin_lock_init(&wdt->lock); 182 spin_lock_init(&wdt->lock);
183 183
184 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 184 wdt->base = pm->base;
185 wdt->base = devm_ioremap_resource(dev, res);
186 if (IS_ERR(wdt->base))
187 return PTR_ERR(wdt->base);
188 185
189 watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt); 186 watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt);
190 watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev); 187 watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev);
@@ -211,8 +208,10 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
211 return err; 208 return err;
212 } 209 }
213 210
214 if (pm_power_off == NULL) 211 if (pm_power_off == NULL) {
215 pm_power_off = bcm2835_power_off; 212 pm_power_off = bcm2835_power_off;
213 bcm2835_power_off_wdt = wdt;
214 }
216 215
217 dev_info(dev, "Broadcom BCM2835 watchdog timer"); 216 dev_info(dev, "Broadcom BCM2835 watchdog timer");
218 return 0; 217 return 0;
@@ -226,18 +225,11 @@ static int bcm2835_wdt_remove(struct platform_device *pdev)
226 return 0; 225 return 0;
227} 226}
228 227
229static const struct of_device_id bcm2835_wdt_of_match[] = {
230 { .compatible = "brcm,bcm2835-pm-wdt", },
231 {},
232};
233MODULE_DEVICE_TABLE(of, bcm2835_wdt_of_match);
234
235static struct platform_driver bcm2835_wdt_driver = { 228static struct platform_driver bcm2835_wdt_driver = {
236 .probe = bcm2835_wdt_probe, 229 .probe = bcm2835_wdt_probe,
237 .remove = bcm2835_wdt_remove, 230 .remove = bcm2835_wdt_remove,
238 .driver = { 231 .driver = {
239 .name = "bcm2835-wdt", 232 .name = "bcm2835-wdt",
240 .of_match_table = bcm2835_wdt_of_match,
241 }, 233 },
242}; 234};
243module_platform_driver(bcm2835_wdt_driver); 235module_platform_driver(bcm2835_wdt_driver);
diff --git a/include/dt-bindings/soc/bcm2835-pm.h b/include/dt-bindings/soc/bcm2835-pm.h
new file mode 100644
index 000000000000..153d75b8d99f
--- /dev/null
+++ b/include/dt-bindings/soc/bcm2835-pm.h
@@ -0,0 +1,28 @@
1/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
2
3#ifndef _DT_BINDINGS_ARM_BCM2835_PM_H
4#define _DT_BINDINGS_ARM_BCM2835_PM_H
5
6#define BCM2835_POWER_DOMAIN_GRAFX 0
7#define BCM2835_POWER_DOMAIN_GRAFX_V3D 1
8#define BCM2835_POWER_DOMAIN_IMAGE 2
9#define BCM2835_POWER_DOMAIN_IMAGE_PERI 3
10#define BCM2835_POWER_DOMAIN_IMAGE_ISP 4
11#define BCM2835_POWER_DOMAIN_IMAGE_H264 5
12#define BCM2835_POWER_DOMAIN_USB 6
13#define BCM2835_POWER_DOMAIN_DSI0 7
14#define BCM2835_POWER_DOMAIN_DSI1 8
15#define BCM2835_POWER_DOMAIN_CAM0 9
16#define BCM2835_POWER_DOMAIN_CAM1 10
17#define BCM2835_POWER_DOMAIN_CCP2TX 11
18#define BCM2835_POWER_DOMAIN_HDMI 12
19
20#define BCM2835_POWER_DOMAIN_COUNT 13
21
22#define BCM2835_RESET_V3D 0
23#define BCM2835_RESET_ISP 1
24#define BCM2835_RESET_H264 2
25
26#define BCM2835_RESET_COUNT 3
27
28#endif /* _DT_BINDINGS_ARM_BCM2835_PM_H */
diff --git a/include/linux/mfd/bcm2835-pm.h b/include/linux/mfd/bcm2835-pm.h
new file mode 100644
index 000000000000..ed37dc40e82a
--- /dev/null
+++ b/include/linux/mfd/bcm2835-pm.h
@@ -0,0 +1,14 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2
3#ifndef BCM2835_MFD_PM_H
4#define BCM2835_MFD_PM_H
5
6#include <linux/regmap.h>
7
8struct bcm2835_pm {
9 struct device *dev;
10 void __iomem *base;
11 void __iomem *asb;
12};
13
14#endif /* BCM2835_MFD_PM_H */
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index 4be1aa4435ae..7800e12ee042 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -73,6 +73,8 @@ enum rpi_firmware_property_tag {
73 RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021, 73 RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021,
74 RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030, 74 RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030,
75 RPI_FIRMWARE_GET_THROTTLED = 0x00030046, 75 RPI_FIRMWARE_GET_THROTTLED = 0x00030046,
76 RPI_FIRMWARE_GET_CLOCK_MEASURED = 0x00030047,
77 RPI_FIRMWARE_NOTIFY_REBOOT = 0x00030048,
76 RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001, 78 RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001,
77 RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002, 79 RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002,
78 RPI_FIRMWARE_SET_VOLTAGE = 0x00038003, 80 RPI_FIRMWARE_SET_VOLTAGE = 0x00038003,
@@ -86,6 +88,8 @@ enum rpi_firmware_property_tag {
86 RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043, 88 RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043,
87 RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045, 89 RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045,
88 RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045, 90 RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045,
91 RPI_FIRMWARE_GET_POE_HAT_VAL = 0x00030049,
92 RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00030050,
89 93
90 94
91 /* Dispmanx TAGS */ 95 /* Dispmanx TAGS */