summaryrefslogtreecommitdiffstats
path: root/drivers/soc
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2023-07-05 00:36:24 +0200
committerUlf Hansson <ulf.hansson@linaro.org>2023-07-11 15:30:09 +0200
commitaded002384c13a473af7d519e38ff59bf6056289 (patch)
tree83af7b64abbd0b191450b7a0e6dce064219dff07 /drivers/soc
parentsoc: apple: Move power-domain driver to the genpd dir (diff)
downloadlinux-aded002384c13a473af7d519e38ff59bf6056289.tar.xz
linux-aded002384c13a473af7d519e38ff59bf6056289.zip
soc: bcm: Move power-domain drivers to the genpd dir
To simplify with maintenance let's move the bcm power-domain drivers to the new genpd directory. Going forward, patches are intended to be managed through a separate git tree, according to MAINTAINERS. While moving the drivers, we end up with a directory for bcm63xx that only contains a Kconfig file, which seems a bit silly. Let's therefore also move the Kconfig options into the Kconfig file a directory above, as it allows us to drop the directory too. Cc: Florian Fainelli <florian.fainelli@broadcom.com> Cc: Ray Jui <rjui@broadcom.com> Cc: Scott Branden <sbranden@broadcom.com> Cc: <linux-mips@vger.kernel.org> Cc: <linux-rpi-kernel@lists.infradead.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/bcm/Kconfig22
-rw-r--r--drivers/soc/bcm/Makefile3
-rw-r--r--drivers/soc/bcm/bcm2835-power.c713
-rw-r--r--drivers/soc/bcm/bcm63xx/Kconfig21
-rw-r--r--drivers/soc/bcm/bcm63xx/Makefile3
-rw-r--r--drivers/soc/bcm/bcm63xx/bcm-pmb.c364
-rw-r--r--drivers/soc/bcm/bcm63xx/bcm63xx-power.c376
-rw-r--r--drivers/soc/bcm/raspberrypi-power.c245
8 files changed, 21 insertions, 1726 deletions
diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig
index 24f92a6e882a..f96906795fa6 100644
--- a/drivers/soc/bcm/Kconfig
+++ b/drivers/soc/bcm/Kconfig
@@ -42,7 +42,27 @@ config SOC_BRCMSTB
If unsure, say N.
-source "drivers/soc/bcm/bcm63xx/Kconfig"
+config BCM_PMB
+ bool "Broadcom PMB (Power Management Bus) driver"
+ depends on ARCH_BCMBCA || (COMPILE_TEST && OF)
+ default ARCH_BCMBCA
+ select PM_GENERIC_DOMAINS if PM
+ help
+ This enables support for the Broadcom's PMB (Power Management Bus) that
+ is used for disabling and enabling SoC devices.
+
+if SOC_BCM63XX
+
+config BCM63XX_POWER
+ bool "BCM63xx power domain driver"
+ depends on BMIPS_GENERIC || (COMPILE_TEST && OF)
+ select PM_GENERIC_DOMAINS if PM
+ help
+ This enables support for the BCM63xx power domains controller on
+ BCM6318, BCM6328, BCM6362 and BCM63268 SoCs.
+
+endif # SOC_BCM63XX
+
source "drivers/soc/bcm/brcmstb/Kconfig"
endmenu
diff --git a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile
index 0f0efa28d92b..32424b1032c7 100644
--- a/drivers/soc/bcm/Makefile
+++ b/drivers/soc/bcm/Makefile
@@ -1,5 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o
-obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o
-obj-y += bcm63xx/
obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
diff --git a/drivers/soc/bcm/bcm2835-power.c b/drivers/soc/bcm/bcm2835-power.c
deleted file mode 100644
index 1a179d4e011c..000000000000
--- a/drivers/soc/bcm/bcm2835-power.c
+++ /dev/null
@@ -1,713 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Power domain driver for Broadcom BCM2835
- *
- * Copyright (C) 2018 Broadcom
- */
-
-#include <dt-bindings/soc/bcm2835-pm.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/mfd/bcm2835-pm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/reset-controller.h>
-#include <linux/types.h>
-
-#define PM_GNRIC 0x00
-#define PM_AUDIO 0x04
-#define PM_STATUS 0x18
-#define PM_RSTC 0x1c
-#define PM_RSTS 0x20
-#define PM_WDOG 0x24
-#define PM_PADS0 0x28
-#define PM_PADS2 0x2c
-#define PM_PADS3 0x30
-#define PM_PADS4 0x34
-#define PM_PADS5 0x38
-#define PM_PADS6 0x3c
-#define PM_CAM0 0x44
-#define PM_CAM0_LDOHPEN BIT(2)
-#define PM_CAM0_LDOLPEN BIT(1)
-#define PM_CAM0_CTRLEN BIT(0)
-
-#define PM_CAM1 0x48
-#define PM_CAM1_LDOHPEN BIT(2)
-#define PM_CAM1_LDOLPEN BIT(1)
-#define PM_CAM1_CTRLEN BIT(0)
-
-#define PM_CCP2TX 0x4c
-#define PM_CCP2TX_LDOEN BIT(1)
-#define PM_CCP2TX_CTRLEN BIT(0)
-
-#define PM_DSI0 0x50
-#define PM_DSI0_LDOHPEN BIT(2)
-#define PM_DSI0_LDOLPEN BIT(1)
-#define PM_DSI0_CTRLEN BIT(0)
-
-#define PM_DSI1 0x54
-#define PM_DSI1_LDOHPEN BIT(2)
-#define PM_DSI1_LDOLPEN BIT(1)
-#define PM_DSI1_CTRLEN BIT(0)
-
-#define PM_HDMI 0x58
-#define PM_HDMI_RSTDR BIT(19)
-#define PM_HDMI_LDOPD BIT(1)
-#define PM_HDMI_CTRLEN BIT(0)
-
-#define PM_USB 0x5c
-/* The power gates must be enabled with this bit before enabling the LDO in the
- * USB block.
- */
-#define PM_USB_CTRLEN BIT(0)
-
-#define PM_PXLDO 0x60
-#define PM_PXBG 0x64
-#define PM_DFT 0x68
-#define PM_SMPS 0x6c
-#define PM_XOSC 0x70
-#define PM_SPAREW 0x74
-#define PM_SPARER 0x78
-#define PM_AVS_RSTDR 0x7c
-#define PM_AVS_STAT 0x80
-#define PM_AVS_EVENT 0x84
-#define PM_AVS_INTEN 0x88
-#define PM_DUMMY 0xfc
-
-#define PM_IMAGE 0x108
-#define PM_GRAFX 0x10c
-#define PM_PROC 0x110
-#define PM_ENAB BIT(12)
-#define PM_ISPRSTN BIT(8)
-#define PM_H264RSTN BIT(7)
-#define PM_PERIRSTN BIT(6)
-#define PM_V3DRSTN BIT(6)
-#define PM_ISFUNC BIT(5)
-#define PM_MRDONE BIT(4)
-#define PM_MEMREP BIT(3)
-#define PM_ISPOW BIT(2)
-#define PM_POWOK BIT(1)
-#define PM_POWUP BIT(0)
-#define PM_INRUSH_SHIFT 13
-#define PM_INRUSH_3_5_MA 0
-#define PM_INRUSH_5_MA 1
-#define PM_INRUSH_10_MA 2
-#define PM_INRUSH_20_MA 3
-#define PM_INRUSH_MASK (3 << PM_INRUSH_SHIFT)
-
-#define PM_PASSWORD 0x5a000000
-
-#define PM_WDOG_TIME_SET 0x000fffff
-#define PM_RSTC_WRCFG_CLR 0xffffffcf
-#define PM_RSTS_HADWRH_SET 0x00000040
-#define PM_RSTC_WRCFG_SET 0x00000030
-#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
-#define PM_RSTC_RESET 0x00000102
-
-#define PM_READ(reg) readl(power->base + (reg))
-#define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg))
-
-#define ASB_BRDG_VERSION 0x00
-#define ASB_CPR_CTRL 0x04
-
-#define ASB_V3D_S_CTRL 0x08
-#define ASB_V3D_M_CTRL 0x0c
-#define ASB_ISP_S_CTRL 0x10
-#define ASB_ISP_M_CTRL 0x14
-#define ASB_H264_S_CTRL 0x18
-#define ASB_H264_M_CTRL 0x1c
-
-#define ASB_REQ_STOP BIT(0)
-#define ASB_ACK BIT(1)
-#define ASB_EMPTY BIT(2)
-#define ASB_FULL BIT(3)
-
-#define ASB_AXI_BRDG_ID 0x20
-
-#define BCM2835_BRDG_ID 0x62726467
-
-struct bcm2835_power_domain {
- struct generic_pm_domain base;
- struct bcm2835_power *power;
- u32 domain;
- struct clk *clk;
-};
-
-struct bcm2835_power {
- struct device *dev;
- /* PM registers. */
- void __iomem *base;
- /* AXI Async bridge registers. */
- void __iomem *asb;
- /* RPiVid bridge registers. */
- void __iomem *rpivid_asb;
-
- struct genpd_onecell_data pd_xlate;
- struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
- struct reset_controller_dev reset;
-};
-
-static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable)
-{
- void __iomem *base = power->asb;
- u64 start;
- u32 val;
-
- switch (reg) {
- case 0:
- return 0;
- case ASB_V3D_S_CTRL:
- case ASB_V3D_M_CTRL:
- if (power->rpivid_asb)
- base = power->rpivid_asb;
- break;
- }
-
- start = ktime_get_ns();
-
- /* Enable the module's async AXI bridges. */
- if (enable) {
- val = readl(base + reg) & ~ASB_REQ_STOP;
- } else {
- val = readl(base + reg) | ASB_REQ_STOP;
- }
- writel(PM_PASSWORD | val, base + reg);
-
- while (readl(base + reg) & ASB_ACK) {
- cpu_relax();
- if (ktime_get_ns() - start >= 1000)
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
-{
- return bcm2835_asb_control(power, reg, true);
-}
-
-static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
-{
- return bcm2835_asb_control(power, reg, false);
-}
-
-static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
-{
- struct bcm2835_power *power = pd->power;
-
- /* We don't run this on BCM2711 */
- if (power->rpivid_asb)
- return 0;
-
- /* Enable functional isolation */
- PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
-
- /* Enable electrical isolation */
- PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
-
- /* Open the power switches. */
- PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);
-
- return 0;
-}
-
-static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
-{
- struct bcm2835_power *power = pd->power;
- struct device *dev = power->dev;
- u64 start;
- int ret;
- int inrush;
- bool powok;
-
- /* We don't run this on BCM2711 */
- if (power->rpivid_asb)
- return 0;
-
- /* If it was already powered on by the fw, leave it that way. */
- if (PM_READ(pm_reg) & PM_POWUP)
- return 0;
-
- /* Enable power. Allowing too much current at once may result
- * in POWOK never getting set, so start low and ramp it up as
- * necessary to succeed.
- */
- powok = false;
- for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) {
- PM_WRITE(pm_reg,
- (PM_READ(pm_reg) & ~PM_INRUSH_MASK) |
- (inrush << PM_INRUSH_SHIFT) |
- PM_POWUP);
-
- start = ktime_get_ns();
- while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) {
- cpu_relax();
- if (ktime_get_ns() - start >= 3000)
- break;
- }
- }
- if (!powok) {
- dev_err(dev, "Timeout waiting for %s power OK\n",
- pd->base.name);
- ret = -ETIMEDOUT;
- goto err_disable_powup;
- }
-
- /* Disable electrical isolation */
- PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW);
-
- /* Repair memory */
- PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP);
- start = ktime_get_ns();
- while (!(PM_READ(pm_reg) & PM_MRDONE)) {
- cpu_relax();
- if (ktime_get_ns() - start >= 1000) {
- dev_err(dev, "Timeout waiting for %s memory repair\n",
- pd->base.name);
- ret = -ETIMEDOUT;
- goto err_disable_ispow;
- }
- }
-
- /* Disable functional isolation */
- PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC);
-
- return 0;
-
-err_disable_ispow:
- PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
-err_disable_powup:
- PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
- return ret;
-}
-
-static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd,
- u32 pm_reg,
- u32 asb_m_reg,
- u32 asb_s_reg,
- u32 reset_flags)
-{
- struct bcm2835_power *power = pd->power;
- int ret;
-
- ret = clk_prepare_enable(pd->clk);
- if (ret) {
- dev_err(power->dev, "Failed to enable clock for %s\n",
- pd->base.name);
- return ret;
- }
-
- /* Wait 32 clocks for reset to propagate, 1 us will be enough */
- udelay(1);
-
- clk_disable_unprepare(pd->clk);
-
- /* Deassert the resets. */
- PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags);
-
- ret = clk_prepare_enable(pd->clk);
- if (ret) {
- dev_err(power->dev, "Failed to enable clock for %s\n",
- pd->base.name);
- goto err_enable_resets;
- }
-
- ret = bcm2835_asb_enable(power, asb_m_reg);
- if (ret) {
- dev_err(power->dev, "Failed to enable ASB master for %s\n",
- pd->base.name);
- goto err_disable_clk;
- }
- ret = bcm2835_asb_enable(power, asb_s_reg);
- if (ret) {
- dev_err(power->dev, "Failed to enable ASB slave for %s\n",
- pd->base.name);
- goto err_disable_asb_master;
- }
-
- return 0;
-
-err_disable_asb_master:
- bcm2835_asb_disable(power, asb_m_reg);
-err_disable_clk:
- clk_disable_unprepare(pd->clk);
-err_enable_resets:
- PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
- return ret;
-}
-
-static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd,
- u32 pm_reg,
- u32 asb_m_reg,
- u32 asb_s_reg,
- u32 reset_flags)
-{
- struct bcm2835_power *power = pd->power;
- int ret;
-
- ret = bcm2835_asb_disable(power, asb_s_reg);
- if (ret) {
- dev_warn(power->dev, "Failed to disable ASB slave for %s\n",
- pd->base.name);
- return ret;
- }
- ret = bcm2835_asb_disable(power, asb_m_reg);
- if (ret) {
- dev_warn(power->dev, "Failed to disable ASB master for %s\n",
- pd->base.name);
- bcm2835_asb_enable(power, asb_s_reg);
- return ret;
- }
-
- clk_disable_unprepare(pd->clk);
-
- /* Assert the resets. */
- PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
-
- return 0;
-}
-
-static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain)
-{
- struct bcm2835_power_domain *pd =
- container_of(domain, struct bcm2835_power_domain, base);
- struct bcm2835_power *power = pd->power;
-
- switch (pd->domain) {
- case BCM2835_POWER_DOMAIN_GRAFX:
- return bcm2835_power_power_on(pd, PM_GRAFX);
-
- case BCM2835_POWER_DOMAIN_GRAFX_V3D:
- return bcm2835_asb_power_on(pd, PM_GRAFX,
- ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
- PM_V3DRSTN);
-
- case BCM2835_POWER_DOMAIN_IMAGE:
- return bcm2835_power_power_on(pd, PM_IMAGE);
-
- case BCM2835_POWER_DOMAIN_IMAGE_PERI:
- return bcm2835_asb_power_on(pd, PM_IMAGE,
- 0, 0,
- PM_PERIRSTN);
-
- case BCM2835_POWER_DOMAIN_IMAGE_ISP:
- return bcm2835_asb_power_on(pd, PM_IMAGE,
- ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
- PM_ISPRSTN);
-
- case BCM2835_POWER_DOMAIN_IMAGE_H264:
- return bcm2835_asb_power_on(pd, PM_IMAGE,
- ASB_H264_M_CTRL, ASB_H264_S_CTRL,
- PM_H264RSTN);
-
- case BCM2835_POWER_DOMAIN_USB:
- PM_WRITE(PM_USB, PM_USB_CTRLEN);
- return 0;
-
- case BCM2835_POWER_DOMAIN_DSI0:
- PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
- PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN);
- return 0;
-
- case BCM2835_POWER_DOMAIN_DSI1:
- PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
- PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN);
- return 0;
-
- case BCM2835_POWER_DOMAIN_CCP2TX:
- PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
- PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN);
- return 0;
-
- case BCM2835_POWER_DOMAIN_HDMI:
- PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR);
- PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN);
- PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD);
- usleep_range(100, 200);
- PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR);
- return 0;
-
- default:
- dev_err(power->dev, "Invalid domain %d\n", pd->domain);
- return -EINVAL;
- }
-}
-
-static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain)
-{
- struct bcm2835_power_domain *pd =
- container_of(domain, struct bcm2835_power_domain, base);
- struct bcm2835_power *power = pd->power;
-
- switch (pd->domain) {
- case BCM2835_POWER_DOMAIN_GRAFX:
- return bcm2835_power_power_off(pd, PM_GRAFX);
-
- case BCM2835_POWER_DOMAIN_GRAFX_V3D:
- return bcm2835_asb_power_off(pd, PM_GRAFX,
- ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
- PM_V3DRSTN);
-
- case BCM2835_POWER_DOMAIN_IMAGE:
- return bcm2835_power_power_off(pd, PM_IMAGE);
-
- case BCM2835_POWER_DOMAIN_IMAGE_PERI:
- return bcm2835_asb_power_off(pd, PM_IMAGE,
- 0, 0,
- PM_PERIRSTN);
-
- case BCM2835_POWER_DOMAIN_IMAGE_ISP:
- return bcm2835_asb_power_off(pd, PM_IMAGE,
- ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
- PM_ISPRSTN);
-
- case BCM2835_POWER_DOMAIN_IMAGE_H264:
- return bcm2835_asb_power_off(pd, PM_IMAGE,
- ASB_H264_M_CTRL, ASB_H264_S_CTRL,
- PM_H264RSTN);
-
- case BCM2835_POWER_DOMAIN_USB:
- PM_WRITE(PM_USB, 0);
- return 0;
-
- case BCM2835_POWER_DOMAIN_DSI0:
- PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
- PM_WRITE(PM_DSI0, 0);
- return 0;
-
- case BCM2835_POWER_DOMAIN_DSI1:
- PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
- PM_WRITE(PM_DSI1, 0);
- return 0;
-
- case BCM2835_POWER_DOMAIN_CCP2TX:
- PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
- PM_WRITE(PM_CCP2TX, 0);
- return 0;
-
- case BCM2835_POWER_DOMAIN_HDMI:
- PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD);
- PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN);
- return 0;
-
- default:
- dev_err(power->dev, "Invalid domain %d\n", pd->domain);
- return -EINVAL;
- }
-}
-
-static int
-bcm2835_init_power_domain(struct bcm2835_power *power,
- int pd_xlate_index, const char *name)
-{
- struct device *dev = power->dev;
- struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
-
- dom->clk = devm_clk_get(dev->parent, name);
- if (IS_ERR(dom->clk)) {
- int ret = PTR_ERR(dom->clk);
-
- if (ret == -EPROBE_DEFER)
- return ret;
-
- /* Some domains don't have a clk, so make sure that we
- * don't deref an error pointer later.
- */
- dom->clk = NULL;
- }
-
- dom->base.name = name;
- dom->base.power_on = bcm2835_power_pd_power_on;
- dom->base.power_off = bcm2835_power_pd_power_off;
-
- dom->domain = pd_xlate_index;
- dom->power = power;
-
- /* XXX: on/off at boot? */
- pm_genpd_init(&dom->base, NULL, true);
-
- power->pd_xlate.domains[pd_xlate_index] = &dom->base;
-
- return 0;
-}
-
-/** bcm2835_reset_reset - Resets a block that has a reset line in the
- * PM block.
- *
- * The consumer of the reset controller must have the power domain up
- * -- there's no reset ability with the power domain down. To reset
- * the sub-block, we just disable its access to memory through the
- * ASB, reset, and re-enable.
- */
-static int bcm2835_reset_reset(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
- reset);
- struct bcm2835_power_domain *pd;
- int ret;
-
- switch (id) {
- case BCM2835_RESET_V3D:
- pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D];
- break;
- case BCM2835_RESET_H264:
- pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264];
- break;
- case BCM2835_RESET_ISP:
- pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP];
- break;
- default:
- dev_err(power->dev, "Bad reset id %ld\n", id);
- return -EINVAL;
- }
-
- ret = bcm2835_power_pd_power_off(&pd->base);
- if (ret)
- return ret;
-
- return bcm2835_power_pd_power_on(&pd->base);
-}
-
-static int bcm2835_reset_status(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
- reset);
-
- switch (id) {
- case BCM2835_RESET_V3D:
- return !PM_READ(PM_GRAFX & PM_V3DRSTN);
- case BCM2835_RESET_H264:
- return !PM_READ(PM_IMAGE & PM_H264RSTN);
- case BCM2835_RESET_ISP:
- return !PM_READ(PM_IMAGE & PM_ISPRSTN);
- default:
- return -EINVAL;
- }
-}
-
-static const struct reset_control_ops bcm2835_reset_ops = {
- .reset = bcm2835_reset_reset,
- .status = bcm2835_reset_status,
-};
-
-static const char *const power_domain_names[] = {
- [BCM2835_POWER_DOMAIN_GRAFX] = "grafx",
- [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d",
-
- [BCM2835_POWER_DOMAIN_IMAGE] = "image",
- [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image",
- [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264",
- [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp",
-
- [BCM2835_POWER_DOMAIN_USB] = "usb",
- [BCM2835_POWER_DOMAIN_DSI0] = "dsi0",
- [BCM2835_POWER_DOMAIN_DSI1] = "dsi1",
- [BCM2835_POWER_DOMAIN_CAM0] = "cam0",
- [BCM2835_POWER_DOMAIN_CAM1] = "cam1",
- [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx",
- [BCM2835_POWER_DOMAIN_HDMI] = "hdmi",
-};
-
-static int bcm2835_power_probe(struct platform_device *pdev)
-{
- struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
- struct device *dev = &pdev->dev;
- struct bcm2835_power *power;
- static const struct {
- int parent, child;
- } domain_deps[] = {
- { BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D },
- { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI },
- { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 },
- { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP },
- { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB },
- { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
- { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
- };
- int ret = 0, i;
- u32 id;
-
- power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
- if (!power)
- return -ENOMEM;
- platform_set_drvdata(pdev, power);
-
- power->dev = dev;
- power->base = pm->base;
- power->asb = pm->asb;
- power->rpivid_asb = pm->rpivid_asb;
-
- id = readl(power->asb + ASB_AXI_BRDG_ID);
- if (id != BCM2835_BRDG_ID /* "BRDG" */) {
- dev_err(dev, "ASB register ID returned 0x%08x\n", id);
- return -ENODEV;
- }
-
- if (power->rpivid_asb) {
- id = readl(power->rpivid_asb + ASB_AXI_BRDG_ID);
- if (id != BCM2835_BRDG_ID /* "BRDG" */) {
- dev_err(dev, "RPiVid ASB register ID returned 0x%08x\n",
- id);
- return -ENODEV;
- }
- }
-
- power->pd_xlate.domains = devm_kcalloc(dev,
- ARRAY_SIZE(power_domain_names),
- sizeof(*power->pd_xlate.domains),
- GFP_KERNEL);
- if (!power->pd_xlate.domains)
- return -ENOMEM;
-
- power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
-
- for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
- ret = bcm2835_init_power_domain(power, i, power_domain_names[i]);
- if (ret)
- goto fail;
- }
-
- for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
- pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
- &power->domains[domain_deps[i].child].base);
- }
-
- power->reset.owner = THIS_MODULE;
- power->reset.nr_resets = BCM2835_RESET_COUNT;
- power->reset.ops = &bcm2835_reset_ops;
- power->reset.of_node = dev->parent->of_node;
-
- ret = devm_reset_controller_register(dev, &power->reset);
- if (ret)
- goto fail;
-
- of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
-
- dev_info(dev, "Broadcom BCM2835 power domains driver");
- return 0;
-
-fail:
- for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
- struct generic_pm_domain *dom = &power->domains[i].base;
-
- if (dom->name)
- pm_genpd_remove(dom);
- }
- return ret;
-}
-
-static struct platform_driver bcm2835_power_driver = {
- .probe = bcm2835_power_probe,
- .driver = {
- .name = "bcm2835-power",
- },
-};
-module_platform_driver(bcm2835_power_driver);
-
-MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
-MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
diff --git a/drivers/soc/bcm/bcm63xx/Kconfig b/drivers/soc/bcm/bcm63xx/Kconfig
deleted file mode 100644
index 355c34482076..000000000000
--- a/drivers/soc/bcm/bcm63xx/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-if SOC_BCM63XX
-
-config BCM63XX_POWER
- bool "BCM63xx power domain driver"
- depends on BMIPS_GENERIC || (COMPILE_TEST && OF)
- select PM_GENERIC_DOMAINS if PM
- help
- This enables support for the BCM63xx power domains controller on
- BCM6318, BCM6328, BCM6362 and BCM63268 SoCs.
-
-endif # SOC_BCM63XX
-
-config BCM_PMB
- bool "Broadcom PMB (Power Management Bus) driver"
- depends on ARCH_BCMBCA || (COMPILE_TEST && OF)
- default ARCH_BCMBCA
- select PM_GENERIC_DOMAINS if PM
- help
- This enables support for the Broadcom's PMB (Power Management Bus) that
- is used for disabling and enabling SoC devices.
diff --git a/drivers/soc/bcm/bcm63xx/Makefile b/drivers/soc/bcm/bcm63xx/Makefile
deleted file mode 100644
index 557eed3d67bd..000000000000
--- a/drivers/soc/bcm/bcm63xx/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_BCM63XX_POWER) += bcm63xx-power.o
-obj-$(CONFIG_BCM_PMB) += bcm-pmb.o
diff --git a/drivers/soc/bcm/bcm63xx/bcm-pmb.c b/drivers/soc/bcm/bcm63xx/bcm-pmb.c
deleted file mode 100644
index 9407cac47fdb..000000000000
--- a/drivers/soc/bcm/bcm63xx/bcm-pmb.c
+++ /dev/null
@@ -1,364 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) 2013 Broadcom
- * Copyright (C) 2020 Rafał Miłecki <rafal@milecki.pl>
- */
-
-#include <dt-bindings/soc/bcm-pmb.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/reset/bcm63xx_pmb.h>
-
-#define BPCM_ID_REG 0x00
-#define BPCM_CAPABILITIES 0x04
-#define BPCM_CAP_NUM_ZONES 0x000000ff
-#define BPCM_CAP_SR_REG_BITS 0x0000ff00
-#define BPCM_CAP_PLLTYPE 0x00030000
-#define BPCM_CAP_UBUS 0x00080000
-#define BPCM_CONTROL 0x08
-#define BPCM_STATUS 0x0c
-#define BPCM_ROSC_CONTROL 0x10
-#define BPCM_ROSC_THRESH_H 0x14
-#define BPCM_ROSC_THRESHOLD_BCM6838 0x14
-#define BPCM_ROSC_THRESH_S 0x18
-#define BPCM_ROSC_COUNT_BCM6838 0x18
-#define BPCM_ROSC_COUNT 0x1c
-#define BPCM_PWD_CONTROL_BCM6838 0x1c
-#define BPCM_PWD_CONTROL 0x20
-#define BPCM_SR_CONTROL_BCM6838 0x20
-#define BPCM_PWD_ACCUM_CONTROL 0x24
-#define BPCM_SR_CONTROL 0x28
-#define BPCM_GLOBAL_CONTROL 0x2c
-#define BPCM_MISC_CONTROL 0x30
-#define BPCM_MISC_CONTROL2 0x34
-#define BPCM_SGPHY_CNTL 0x38
-#define BPCM_SGPHY_STATUS 0x3c
-#define BPCM_ZONE0 0x40
-#define BPCM_ZONE_CONTROL 0x00
-#define BPCM_ZONE_CONTROL_MANUAL_CLK_EN 0x00000001
-#define BPCM_ZONE_CONTROL_MANUAL_RESET_CTL 0x00000002
-#define BPCM_ZONE_CONTROL_FREQ_SCALE_USED 0x00000004 /* R/O */
-#define BPCM_ZONE_CONTROL_DPG_CAPABLE 0x00000008 /* R/O */
-#define BPCM_ZONE_CONTROL_MANUAL_MEM_PWR 0x00000030
-#define BPCM_ZONE_CONTROL_MANUAL_ISO_CTL 0x00000040
-#define BPCM_ZONE_CONTROL_MANUAL_CTL 0x00000080
-#define BPCM_ZONE_CONTROL_DPG_CTL_EN 0x00000100
-#define BPCM_ZONE_CONTROL_PWR_DN_REQ 0x00000200
-#define BPCM_ZONE_CONTROL_PWR_UP_REQ 0x00000400
-#define BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN 0x00000800
-#define BPCM_ZONE_CONTROL_BLK_RESET_ASSERT 0x00001000
-#define BPCM_ZONE_CONTROL_MEM_STBY 0x00002000
-#define BPCM_ZONE_CONTROL_RESERVED 0x0007c000
-#define BPCM_ZONE_CONTROL_PWR_CNTL_STATE 0x00f80000
-#define BPCM_ZONE_CONTROL_FREQ_SCALAR_DYN_SEL 0x01000000 /* R/O */
-#define BPCM_ZONE_CONTROL_PWR_OFF_STATE 0x02000000 /* R/O */
-#define BPCM_ZONE_CONTROL_PWR_ON_STATE 0x04000000 /* R/O */
-#define BPCM_ZONE_CONTROL_PWR_GOOD 0x08000000 /* R/O */
-#define BPCM_ZONE_CONTROL_DPG_PWR_STATE 0x10000000 /* R/O */
-#define BPCM_ZONE_CONTROL_MEM_PWR_STATE 0x20000000 /* R/O */
-#define BPCM_ZONE_CONTROL_ISO_STATE 0x40000000 /* R/O */
-#define BPCM_ZONE_CONTROL_RESET_STATE 0x80000000 /* R/O */
-#define BPCM_ZONE_CONFIG1 0x04
-#define BPCM_ZONE_CONFIG2 0x08
-#define BPCM_ZONE_FREQ_SCALAR_CONTROL 0x0c
-#define BPCM_ZONE_SIZE 0x10
-
-struct bcm_pmb {
- struct device *dev;
- void __iomem *base;
- spinlock_t lock;
- bool little_endian;
- struct genpd_onecell_data genpd_onecell_data;
-};
-
-struct bcm_pmb_pd_data {
- const char * const name;
- int id;
- u8 bus;
- u8 device;
-};
-
-struct bcm_pmb_pm_domain {
- struct bcm_pmb *pmb;
- const struct bcm_pmb_pd_data *data;
- struct generic_pm_domain genpd;
-};
-
-static int bcm_pmb_bpcm_read(struct bcm_pmb *pmb, int bus, u8 device,
- int offset, u32 *val)
-{
- void __iomem *base = pmb->base + bus * 0x20;
- unsigned long flags;
- int err;
-
- spin_lock_irqsave(&pmb->lock, flags);
- err = bpcm_rd(base, device, offset, val);
- spin_unlock_irqrestore(&pmb->lock, flags);
-
- if (!err)
- *val = pmb->little_endian ? le32_to_cpu(*val) : be32_to_cpu(*val);
-
- return err;
-}
-
-static int bcm_pmb_bpcm_write(struct bcm_pmb *pmb, int bus, u8 device,
- int offset, u32 val)
-{
- void __iomem *base = pmb->base + bus * 0x20;
- unsigned long flags;
- int err;
-
- val = pmb->little_endian ? cpu_to_le32(val) : cpu_to_be32(val);
-
- spin_lock_irqsave(&pmb->lock, flags);
- err = bpcm_wr(base, device, offset, val);
- spin_unlock_irqrestore(&pmb->lock, flags);
-
- return err;
-}
-
-static int bcm_pmb_power_off_zone(struct bcm_pmb *pmb, int bus, u8 device,
- int zone)
-{
- int offset;
- u32 val;
- int err;
-
- offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL;
-
- err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val);
- if (err)
- return err;
-
- val |= BPCM_ZONE_CONTROL_PWR_DN_REQ;
- val &= ~BPCM_ZONE_CONTROL_PWR_UP_REQ;
-
- err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val);
-
- return err;
-}
-
-static int bcm_pmb_power_on_zone(struct bcm_pmb *pmb, int bus, u8 device,
- int zone)
-{
- int offset;
- u32 val;
- int err;
-
- offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL;
-
- err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val);
- if (err)
- return err;
-
- if (!(val & BPCM_ZONE_CONTROL_PWR_ON_STATE)) {
- val &= ~BPCM_ZONE_CONTROL_PWR_DN_REQ;
- val |= BPCM_ZONE_CONTROL_DPG_CTL_EN;
- val |= BPCM_ZONE_CONTROL_PWR_UP_REQ;
- val |= BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN;
- val |= BPCM_ZONE_CONTROL_BLK_RESET_ASSERT;
-
- err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val);
- }
-
- return err;
-}
-
-static int bcm_pmb_power_off_device(struct bcm_pmb *pmb, int bus, u8 device)
-{
- int offset;
- u32 val;
- int err;
-
- /* Entire device can be powered off by powering off the 0th zone */
- offset = BPCM_ZONE0 + BPCM_ZONE_CONTROL;
-
- err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val);
- if (err)
- return err;
-
- if (!(val & BPCM_ZONE_CONTROL_PWR_OFF_STATE)) {
- val = BPCM_ZONE_CONTROL_PWR_DN_REQ;
-
- err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val);
- }
-
- return err;
-}
-
-static int bcm_pmb_power_on_device(struct bcm_pmb *pmb, int bus, u8 device)
-{
- u32 val;
- int err;
- int i;
-
- err = bcm_pmb_bpcm_read(pmb, bus, device, BPCM_CAPABILITIES, &val);
- if (err)
- return err;
-
- for (i = 0; i < (val & BPCM_CAP_NUM_ZONES); i++) {
- err = bcm_pmb_power_on_zone(pmb, bus, device, i);
- if (err)
- return err;
- }
-
- return err;
-}
-
-static int bcm_pmb_power_on_sata(struct bcm_pmb *pmb, int bus, u8 device)
-{
- int err;
-
- err = bcm_pmb_power_on_zone(pmb, bus, device, 0);
- if (err)
- return err;
-
- /* Does not apply to the BCM963158 */
- err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_MISC_CONTROL, 0);
- if (err)
- return err;
-
- err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_SR_CONTROL, 0xffffffff);
- if (err)
- return err;
-
- err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_SR_CONTROL, 0);
-
- return err;
-}
-
-static int bcm_pmb_power_on(struct generic_pm_domain *genpd)
-{
- struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd);
- const struct bcm_pmb_pd_data *data = pd->data;
- struct bcm_pmb *pmb = pd->pmb;
-
- switch (data->id) {
- case BCM_PMB_PCIE0:
- case BCM_PMB_PCIE1:
- case BCM_PMB_PCIE2:
- return bcm_pmb_power_on_zone(pmb, data->bus, data->device, 0);
- case BCM_PMB_HOST_USB:
- return bcm_pmb_power_on_device(pmb, data->bus, data->device);
- case BCM_PMB_SATA:
- return bcm_pmb_power_on_sata(pmb, data->bus, data->device);
- default:
- dev_err(pmb->dev, "unsupported device id: %d\n", data->id);
- return -EINVAL;
- }
-}
-
-static int bcm_pmb_power_off(struct generic_pm_domain *genpd)
-{
- struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd);
- const struct bcm_pmb_pd_data *data = pd->data;
- struct bcm_pmb *pmb = pd->pmb;
-
- switch (data->id) {
- case BCM_PMB_PCIE0:
- case BCM_PMB_PCIE1:
- case BCM_PMB_PCIE2:
- return bcm_pmb_power_off_zone(pmb, data->bus, data->device, 0);
- case BCM_PMB_HOST_USB:
- return bcm_pmb_power_off_device(pmb, data->bus, data->device);
- default:
- dev_err(pmb->dev, "unsupported device id: %d\n", data->id);
- return -EINVAL;
- }
-}
-
-static int bcm_pmb_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- const struct bcm_pmb_pd_data *table;
- const struct bcm_pmb_pd_data *e;
- struct bcm_pmb *pmb;
- int max_id;
- int err;
-
- pmb = devm_kzalloc(dev, sizeof(*pmb), GFP_KERNEL);
- if (!pmb)
- return -ENOMEM;
-
- pmb->dev = dev;
-
- pmb->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(pmb->base))
- return PTR_ERR(pmb->base);
-
- spin_lock_init(&pmb->lock);
-
- pmb->little_endian = !of_device_is_big_endian(dev->of_node);
-
- table = of_device_get_match_data(dev);
- if (!table)
- return -EINVAL;
-
- max_id = 0;
- for (e = table; e->name; e++)
- max_id = max(max_id, e->id);
-
- pmb->genpd_onecell_data.num_domains = max_id + 1;
- pmb->genpd_onecell_data.domains =
- devm_kcalloc(dev, pmb->genpd_onecell_data.num_domains,
- sizeof(struct generic_pm_domain *), GFP_KERNEL);
- if (!pmb->genpd_onecell_data.domains)
- return -ENOMEM;
-
- for (e = table; e->name; e++) {
- struct bcm_pmb_pm_domain *pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-
- if (!pd)
- return -ENOMEM;
-
- pd->pmb = pmb;
- pd->data = e;
- pd->genpd.name = e->name;
- pd->genpd.power_on = bcm_pmb_power_on;
- pd->genpd.power_off = bcm_pmb_power_off;
-
- pm_genpd_init(&pd->genpd, NULL, true);
- pmb->genpd_onecell_data.domains[e->id] = &pd->genpd;
- }
-
- err = of_genpd_add_provider_onecell(dev->of_node, &pmb->genpd_onecell_data);
- if (err) {
- dev_err(dev, "failed to add genpd provider: %d\n", err);
- return err;
- }
-
- return 0;
-}
-
-static const struct bcm_pmb_pd_data bcm_pmb_bcm4908_data[] = {
- { .name = "pcie2", .id = BCM_PMB_PCIE2, .bus = 0, .device = 2, },
- { .name = "pcie0", .id = BCM_PMB_PCIE0, .bus = 1, .device = 14, },
- { .name = "pcie1", .id = BCM_PMB_PCIE1, .bus = 1, .device = 15, },
- { .name = "usb", .id = BCM_PMB_HOST_USB, .bus = 1, .device = 17, },
- { },
-};
-
-static const struct bcm_pmb_pd_data bcm_pmb_bcm63138_data[] = {
- { .name = "sata", .id = BCM_PMB_SATA, .bus = 0, .device = 3, },
- { },
-};
-
-static const struct of_device_id bcm_pmb_of_match[] = {
- { .compatible = "brcm,bcm4908-pmb", .data = &bcm_pmb_bcm4908_data, },
- { .compatible = "brcm,bcm63138-pmb", .data = &bcm_pmb_bcm63138_data, },
- { },
-};
-
-static struct platform_driver bcm_pmb_driver = {
- .driver = {
- .name = "bcm-pmb",
- .of_match_table = bcm_pmb_of_match,
- },
- .probe = bcm_pmb_probe,
-};
-
-builtin_platform_driver(bcm_pmb_driver);
diff --git a/drivers/soc/bcm/bcm63xx/bcm63xx-power.c b/drivers/soc/bcm/bcm63xx/bcm63xx-power.c
deleted file mode 100644
index aa72e13d5d0e..000000000000
--- a/drivers/soc/bcm/bcm63xx/bcm63xx-power.c
+++ /dev/null
@@ -1,376 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * BCM63xx Power Domain Controller Driver
- *
- * Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
- */
-
-#include <dt-bindings/soc/bcm6318-pm.h>
-#include <dt-bindings/soc/bcm6328-pm.h>
-#include <dt-bindings/soc/bcm6362-pm.h>
-#include <dt-bindings/soc/bcm63268-pm.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-
-struct bcm63xx_power_dev {
- struct generic_pm_domain genpd;
- struct bcm63xx_power *power;
- uint32_t mask;
-};
-
-struct bcm63xx_power {
- void __iomem *base;
- spinlock_t lock;
- struct bcm63xx_power_dev *dev;
- struct genpd_onecell_data genpd_data;
- struct generic_pm_domain **genpd;
-};
-
-struct bcm63xx_power_data {
- const char * const name;
- uint8_t bit;
- unsigned int flags;
-};
-
-static int bcm63xx_power_get_state(struct bcm63xx_power_dev *pmd, bool *is_on)
-{
- struct bcm63xx_power *power = pmd->power;
-
- if (!pmd->mask) {
- *is_on = false;
- return -EINVAL;
- }
-
- *is_on = !(__raw_readl(power->base) & pmd->mask);
-
- return 0;
-}
-
-static int bcm63xx_power_set_state(struct bcm63xx_power_dev *pmd, bool on)
-{
- struct bcm63xx_power *power = pmd->power;
- unsigned long flags;
- uint32_t val;
-
- if (!pmd->mask)
- return -EINVAL;
-
- spin_lock_irqsave(&power->lock, flags);
- val = __raw_readl(power->base);
- if (on)
- val &= ~pmd->mask;
- else
- val |= pmd->mask;
- __raw_writel(val, power->base);
- spin_unlock_irqrestore(&power->lock, flags);
-
- return 0;
-}
-
-static int bcm63xx_power_on(struct generic_pm_domain *genpd)
-{
- struct bcm63xx_power_dev *pmd = container_of(genpd,
- struct bcm63xx_power_dev, genpd);
-
- return bcm63xx_power_set_state(pmd, true);
-}
-
-static int bcm63xx_power_off(struct generic_pm_domain *genpd)
-{
- struct bcm63xx_power_dev *pmd = container_of(genpd,
- struct bcm63xx_power_dev, genpd);
-
- return bcm63xx_power_set_state(pmd, false);
-}
-
-static int bcm63xx_power_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
- const struct bcm63xx_power_data *entry, *table;
- struct bcm63xx_power *power;
- unsigned int ndom;
- uint8_t max_bit = 0;
- int ret;
-
- power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
- if (!power)
- return -ENOMEM;
-
- power->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(power->base))
- return PTR_ERR(power->base);
-
- table = of_device_get_match_data(dev);
- if (!table)
- return -EINVAL;
-
- power->genpd_data.num_domains = 0;
- ndom = 0;
- for (entry = table; entry->name; entry++) {
- max_bit = max(max_bit, entry->bit);
- ndom++;
- }
-
- if (!ndom)
- return -ENODEV;
-
- power->genpd_data.num_domains = max_bit + 1;
-
- power->dev = devm_kcalloc(dev, power->genpd_data.num_domains,
- sizeof(struct bcm63xx_power_dev),
- GFP_KERNEL);
- if (!power->dev)
- return -ENOMEM;
-
- power->genpd = devm_kcalloc(dev, power->genpd_data.num_domains,
- sizeof(struct generic_pm_domain *),
- GFP_KERNEL);
- if (!power->genpd)
- return -ENOMEM;
-
- power->genpd_data.domains = power->genpd;
-
- ndom = 0;
- for (entry = table; entry->name; entry++) {
- struct bcm63xx_power_dev *pmd = &power->dev[ndom];
- bool is_on;
-
- pmd->power = power;
- pmd->mask = BIT(entry->bit);
- pmd->genpd.name = entry->name;
- pmd->genpd.flags = entry->flags;
-
- ret = bcm63xx_power_get_state(pmd, &is_on);
- if (ret)
- dev_warn(dev, "unable to get current state for %s\n",
- pmd->genpd.name);
-
- pmd->genpd.power_on = bcm63xx_power_on;
- pmd->genpd.power_off = bcm63xx_power_off;
-
- pm_genpd_init(&pmd->genpd, NULL, !is_on);
- power->genpd[entry->bit] = &pmd->genpd;
-
- ndom++;
- }
-
- spin_lock_init(&power->lock);
-
- ret = of_genpd_add_provider_onecell(np, &power->genpd_data);
- if (ret) {
- dev_err(dev, "failed to register genpd driver: %d\n", ret);
- return ret;
- }
-
- dev_info(dev, "registered %u power domains\n", ndom);
-
- return 0;
-}
-
-static const struct bcm63xx_power_data bcm6318_power_domains[] = {
- {
- .name = "pcie",
- .bit = BCM6318_POWER_DOMAIN_PCIE,
- }, {
- .name = "usb",
- .bit = BCM6318_POWER_DOMAIN_USB,
- }, {
- .name = "ephy0",
- .bit = BCM6318_POWER_DOMAIN_EPHY0,
- }, {
- .name = "ephy1",
- .bit = BCM6318_POWER_DOMAIN_EPHY1,
- }, {
- .name = "ephy2",
- .bit = BCM6318_POWER_DOMAIN_EPHY2,
- }, {
- .name = "ephy3",
- .bit = BCM6318_POWER_DOMAIN_EPHY3,
- }, {
- .name = "ldo2p5",
- .bit = BCM6318_POWER_DOMAIN_LDO2P5,
- .flags = GENPD_FLAG_ALWAYS_ON,
- }, {
- .name = "ldo2p9",
- .bit = BCM6318_POWER_DOMAIN_LDO2P9,
- .flags = GENPD_FLAG_ALWAYS_ON,
- }, {
- .name = "sw1p0",
- .bit = BCM6318_POWER_DOMAIN_SW1P0,
- .flags = GENPD_FLAG_ALWAYS_ON,
- }, {
- .name = "pad",
- .bit = BCM6318_POWER_DOMAIN_PAD,
- .flags = GENPD_FLAG_ALWAYS_ON,
- }, {
- /* sentinel */
- },
-};
-
-static const struct bcm63xx_power_data bcm6328_power_domains[] = {
- {
- .name = "adsl2-mips",
- .bit = BCM6328_POWER_DOMAIN_ADSL2_MIPS,
- }, {
- .name = "adsl2-phy",
- .bit = BCM6328_POWER_DOMAIN_ADSL2_PHY,
- }, {
- .name = "adsl2-afe",
- .bit = BCM6328_POWER_DOMAIN_ADSL2_AFE,
- }, {
- .name = "sar",
- .bit = BCM6328_POWER_DOMAIN_SAR,
- }, {
- .name = "pcm",
- .bit = BCM6328_POWER_DOMAIN_PCM,
- }, {
- .name = "usbd",
- .bit = BCM6328_POWER_DOMAIN_USBD,
- }, {
- .name = "usbh",
- .bit = BCM6328_POWER_DOMAIN_USBH,
- }, {
- .name = "pcie",
- .bit = BCM6328_POWER_DOMAIN_PCIE,
- }, {
- .name = "robosw",
- .bit = BCM6328_POWER_DOMAIN_ROBOSW,
- }, {
- .name = "ephy",
- .bit = BCM6328_POWER_DOMAIN_EPHY,
- }, {
- /* sentinel */
- },
-};
-
-static const struct bcm63xx_power_data bcm6362_power_domains[] = {
- {
- .name = "sar",
- .bit = BCM6362_POWER_DOMAIN_SAR,
- }, {
- .name = "ipsec",
- .bit = BCM6362_POWER_DOMAIN_IPSEC,
- }, {
- .name = "mips",
- .bit = BCM6362_POWER_DOMAIN_MIPS,
- .flags = GENPD_FLAG_ALWAYS_ON,
- }, {
- .name = "dect",
- .bit = BCM6362_POWER_DOMAIN_DECT,
- }, {
- .name = "usbh",
- .bit = BCM6362_POWER_DOMAIN_USBH,
- }, {
- .name = "usbd",
- .bit = BCM6362_POWER_DOMAIN_USBD,
- }, {
- .name = "robosw",
- .bit = BCM6362_POWER_DOMAIN_ROBOSW,
- }, {
- .name = "pcm",
- .bit = BCM6362_POWER_DOMAIN_PCM,
- }, {
- .name = "periph",
- .bit = BCM6362_POWER_DOMAIN_PERIPH,
- .flags = GENPD_FLAG_ALWAYS_ON,
- }, {
- .name = "adsl-phy",
- .bit = BCM6362_POWER_DOMAIN_ADSL_PHY,
- }, {
- .name = "gmii-pads",
- .bit = BCM6362_POWER_DOMAIN_GMII_PADS,
- }, {
- .name = "fap",
- .bit = BCM6362_POWER_DOMAIN_FAP,
- }, {
- .name = "pcie",
- .bit = BCM6362_POWER_DOMAIN_PCIE,
- }, {
- .name = "wlan-pads",
- .bit = BCM6362_POWER_DOMAIN_WLAN_PADS,
- }, {
- /* sentinel */
- },
-};
-
-static const struct bcm63xx_power_data bcm63268_power_domains[] = {
- {
- .name = "sar",
- .bit = BCM63268_POWER_DOMAIN_SAR,
- }, {
- .name = "ipsec",
- .bit = BCM63268_POWER_DOMAIN_IPSEC,
- }, {
- .name = "mips",
- .bit = BCM63268_POWER_DOMAIN_MIPS,
- .flags = GENPD_FLAG_ALWAYS_ON,
- }, {
- .name = "dect",
- .bit = BCM63268_POWER_DOMAIN_DECT,
- }, {
- .name = "usbh",
- .bit = BCM63268_POWER_DOMAIN_USBH,
- }, {
- .name = "usbd",
- .bit = BCM63268_POWER_DOMAIN_USBD,
- }, {
- .name = "robosw",
- .bit = BCM63268_POWER_DOMAIN_ROBOSW,
- }, {
- .name = "pcm",
- .bit = BCM63268_POWER_DOMAIN_PCM,
- }, {
- .name = "periph",
- .bit = BCM63268_POWER_DOMAIN_PERIPH,
- .flags = GENPD_FLAG_ALWAYS_ON,
- }, {
- .name = "vdsl-phy",
- .bit = BCM63268_POWER_DOMAIN_VDSL_PHY,
- }, {
- .name = "vdsl-mips",
- .bit = BCM63268_POWER_DOMAIN_VDSL_MIPS,
- }, {
- .name = "fap",
- .bit = BCM63268_POWER_DOMAIN_FAP,
- }, {
- .name = "pcie",
- .bit = BCM63268_POWER_DOMAIN_PCIE,
- }, {
- .name = "wlan-pads",
- .bit = BCM63268_POWER_DOMAIN_WLAN_PADS,
- }, {
- /* sentinel */
- },
-};
-
-static const struct of_device_id bcm63xx_power_of_match[] = {
- {
- .compatible = "brcm,bcm6318-power-controller",
- .data = &bcm6318_power_domains,
- }, {
- .compatible = "brcm,bcm6328-power-controller",
- .data = &bcm6328_power_domains,
- }, {
- .compatible = "brcm,bcm6362-power-controller",
- .data = &bcm6362_power_domains,
- }, {
- .compatible = "brcm,bcm63268-power-controller",
- .data = &bcm63268_power_domains,
- }, {
- /* sentinel */
- }
-};
-
-static struct platform_driver bcm63xx_power_driver = {
- .driver = {
- .name = "bcm63xx-power-controller",
- .of_match_table = bcm63xx_power_of_match,
- },
- .probe = bcm63xx_power_probe,
-};
-builtin_platform_driver(bcm63xx_power_driver);
diff --git a/drivers/soc/bcm/raspberrypi-power.c b/drivers/soc/bcm/raspberrypi-power.c
deleted file mode 100644
index 58175af982a0..000000000000
--- a/drivers/soc/bcm/raspberrypi-power.c
+++ /dev/null
@@ -1,245 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de>
- *
- * Authors:
- * Alexander Aring <aar@pengutronix.de>
- * Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/module.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <dt-bindings/power/raspberrypi-power.h>
-#include <soc/bcm2835/raspberrypi-firmware.h>
-
-/*
- * Firmware indices for the old power domains interface. Only a few
- * of them were actually implemented.
- */
-#define RPI_OLD_POWER_DOMAIN_USB 3
-#define RPI_OLD_POWER_DOMAIN_V3D 10
-
-struct rpi_power_domain {
- u32 domain;
- bool enabled;
- bool old_interface;
- struct generic_pm_domain base;
- struct rpi_firmware *fw;
-};
-
-struct rpi_power_domains {
- bool has_new_interface;
- struct genpd_onecell_data xlate;
- struct rpi_firmware *fw;
- struct rpi_power_domain domains[RPI_POWER_DOMAIN_COUNT];
-};
-
-/*
- * Packet definition used by RPI_FIRMWARE_SET_POWER_STATE and
- * RPI_FIRMWARE_SET_DOMAIN_STATE
- */
-struct rpi_power_domain_packet {
- u32 domain;
- u32 on;
-};
-
-/*
- * Asks the firmware to enable or disable power on a specific power
- * domain.
- */
-static int rpi_firmware_set_power(struct rpi_power_domain *rpi_domain, bool on)
-{
- struct rpi_power_domain_packet packet;
-
- packet.domain = rpi_domain->domain;
- packet.on = on;
- return rpi_firmware_property(rpi_domain->fw,
- rpi_domain->old_interface ?
- RPI_FIRMWARE_SET_POWER_STATE :
- RPI_FIRMWARE_SET_DOMAIN_STATE,
- &packet, sizeof(packet));
-}
-
-static int rpi_domain_off(struct generic_pm_domain *domain)
-{
- struct rpi_power_domain *rpi_domain =
- container_of(domain, struct rpi_power_domain, base);
-
- return rpi_firmware_set_power(rpi_domain, false);
-}
-
-static int rpi_domain_on(struct generic_pm_domain *domain)
-{
- struct rpi_power_domain *rpi_domain =
- container_of(domain, struct rpi_power_domain, base);
-
- return rpi_firmware_set_power(rpi_domain, true);
-}
-
-static void rpi_common_init_power_domain(struct rpi_power_domains *rpi_domains,
- int xlate_index, const char *name)
-{
- struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index];
-
- dom->fw = rpi_domains->fw;
-
- dom->base.name = name;
- dom->base.power_on = rpi_domain_on;
- dom->base.power_off = rpi_domain_off;
-
- /*
- * Treat all power domains as off at boot.
- *
- * The firmware itself may be keeping some domains on, but
- * from Linux's perspective all we control is the refcounts
- * that we give to the firmware, and we can't ask the firmware
- * to turn off something that we haven't ourselves turned on.
- */
- pm_genpd_init(&dom->base, NULL, true);
-
- rpi_domains->xlate.domains[xlate_index] = &dom->base;
-}
-
-static void rpi_init_power_domain(struct rpi_power_domains *rpi_domains,
- int xlate_index, const char *name)
-{
- struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index];
-
- if (!rpi_domains->has_new_interface)
- return;
-
- /* The DT binding index is the firmware's domain index minus one. */
- dom->domain = xlate_index + 1;
-
- rpi_common_init_power_domain(rpi_domains, xlate_index, name);
-}
-
-static void rpi_init_old_power_domain(struct rpi_power_domains *rpi_domains,
- int xlate_index, int domain,
- const char *name)
-{
- struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index];
-
- dom->old_interface = true;
- dom->domain = domain;
-
- rpi_common_init_power_domain(rpi_domains, xlate_index, name);
-}
-
-/*
- * Detects whether the firmware supports the new power domains interface.
- *
- * The firmware doesn't actually return an error on an unknown tag,
- * and just skips over it, so we do the detection by putting an
- * unexpected value in the return field and checking if it was
- * unchanged.
- */
-static bool
-rpi_has_new_domain_support(struct rpi_power_domains *rpi_domains)
-{
- struct rpi_power_domain_packet packet;
- int ret;
-
- packet.domain = RPI_POWER_DOMAIN_ARM;
- packet.on = ~0;
-
- ret = rpi_firmware_property(rpi_domains->fw,
- RPI_FIRMWARE_GET_DOMAIN_STATE,
- &packet, sizeof(packet));
-
- return ret == 0 && packet.on != ~0;
-}
-
-static int rpi_power_probe(struct platform_device *pdev)
-{
- struct device_node *fw_np;
- struct device *dev = &pdev->dev;
- struct rpi_power_domains *rpi_domains;
-
- rpi_domains = devm_kzalloc(dev, sizeof(*rpi_domains), GFP_KERNEL);
- if (!rpi_domains)
- return -ENOMEM;
-
- rpi_domains->xlate.domains =
- devm_kcalloc(dev,
- RPI_POWER_DOMAIN_COUNT,
- sizeof(*rpi_domains->xlate.domains),
- GFP_KERNEL);
- if (!rpi_domains->xlate.domains)
- return -ENOMEM;
-
- rpi_domains->xlate.num_domains = RPI_POWER_DOMAIN_COUNT;
-
- fw_np = of_parse_phandle(pdev->dev.of_node, "firmware", 0);
- if (!fw_np) {
- dev_err(&pdev->dev, "no firmware node\n");
- return -ENODEV;
- }
-
- rpi_domains->fw = devm_rpi_firmware_get(&pdev->dev, fw_np);
- of_node_put(fw_np);
- if (!rpi_domains->fw)
- return -EPROBE_DEFER;
-
- rpi_domains->has_new_interface =
- rpi_has_new_domain_support(rpi_domains);
-
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C0, "I2C0");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C1, "I2C1");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C2, "I2C2");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VIDEO_SCALER,
- "VIDEO_SCALER");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VPU1, "VPU1");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_HDMI, "HDMI");
-
- /*
- * Use the old firmware interface for USB power, so that we
- * can turn it on even if the firmware hasn't been updated.
- */
- rpi_init_old_power_domain(rpi_domains, RPI_POWER_DOMAIN_USB,
- RPI_OLD_POWER_DOMAIN_USB, "USB");
-
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VEC, "VEC");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_JPEG, "JPEG");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_H264, "H264");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_V3D, "V3D");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_ISP, "ISP");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_UNICAM0, "UNICAM0");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_UNICAM1, "UNICAM1");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CCP2RX, "CCP2RX");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CSI2, "CSI2");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CPI, "CPI");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_DSI0, "DSI0");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_DSI1, "DSI1");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_TRANSPOSER,
- "TRANSPOSER");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CCP2TX, "CCP2TX");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CDP, "CDP");
- rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_ARM, "ARM");
-
- of_genpd_add_provider_onecell(dev->of_node, &rpi_domains->xlate);
-
- platform_set_drvdata(pdev, rpi_domains);
-
- return 0;
-}
-
-static const struct of_device_id rpi_power_of_match[] = {
- { .compatible = "raspberrypi,bcm2835-power", },
- {},
-};
-MODULE_DEVICE_TABLE(of, rpi_power_of_match);
-
-static struct platform_driver rpi_power_driver = {
- .driver = {
- .name = "raspberrypi-power",
- .of_match_table = rpi_power_of_match,
- },
- .probe = rpi_power_probe,
-};
-builtin_platform_driver(rpi_power_driver);
-
-MODULE_AUTHOR("Alexander Aring <aar@pengutronix.de>");
-MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
-MODULE_DESCRIPTION("Raspberry Pi power domain driver");