Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Power domain driver for Broadcom BCM2835
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2018 Broadcom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <dt-bindings/soc/bcm2835-pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/mfd/bcm2835-pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/pm_domain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/reset-controller.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #define PM_GNRIC                        0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define PM_AUDIO                        0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define PM_STATUS                       0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define PM_RSTC				0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define PM_RSTS				0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define PM_WDOG				0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define PM_PADS0			0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define PM_PADS2			0x2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define PM_PADS3			0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define PM_PADS4			0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define PM_PADS5			0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define PM_PADS6			0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define PM_CAM0				0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define PM_CAM0_LDOHPEN			BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define PM_CAM0_LDOLPEN			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define PM_CAM0_CTRLEN			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define PM_CAM1				0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define PM_CAM1_LDOHPEN			BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define PM_CAM1_LDOLPEN			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define PM_CAM1_CTRLEN			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define PM_CCP2TX			0x4c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define PM_CCP2TX_LDOEN			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define PM_CCP2TX_CTRLEN		BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define PM_DSI0				0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define PM_DSI0_LDOHPEN			BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define PM_DSI0_LDOLPEN			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define PM_DSI0_CTRLEN			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) #define PM_DSI1				0x54
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define PM_DSI1_LDOHPEN			BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #define PM_DSI1_LDOLPEN			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) #define PM_DSI1_CTRLEN			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) #define PM_HDMI				0x58
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) #define PM_HDMI_RSTDR			BIT(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #define PM_HDMI_LDOPD			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) #define PM_HDMI_CTRLEN			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) #define PM_USB				0x5c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) /* The power gates must be enabled with this bit before enabling the LDO in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * USB block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) #define PM_USB_CTRLEN			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) #define PM_PXLDO			0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) #define PM_PXBG				0x64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) #define PM_DFT				0x68
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) #define PM_SMPS				0x6c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) #define PM_XOSC				0x70
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) #define PM_SPAREW			0x74
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) #define PM_SPARER			0x78
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) #define PM_AVS_RSTDR			0x7c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) #define PM_AVS_STAT			0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) #define PM_AVS_EVENT			0x84
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) #define PM_AVS_INTEN			0x88
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) #define PM_DUMMY			0xfc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) #define PM_IMAGE			0x108
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) #define PM_GRAFX			0x10c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) #define PM_PROC				0x110
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) #define PM_ENAB				BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) #define PM_ISPRSTN			BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) #define PM_H264RSTN			BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) #define PM_PERIRSTN			BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) #define PM_V3DRSTN			BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) #define PM_ISFUNC			BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) #define PM_MRDONE			BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) #define PM_MEMREP			BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) #define PM_ISPOW			BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) #define PM_POWOK			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) #define PM_POWUP			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) #define PM_INRUSH_SHIFT			13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) #define PM_INRUSH_3_5_MA		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) #define PM_INRUSH_5_MA			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) #define PM_INRUSH_10_MA			2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) #define PM_INRUSH_20_MA			3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) #define PM_INRUSH_MASK			(3 << PM_INRUSH_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define PM_PASSWORD			0x5a000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define PM_WDOG_TIME_SET		0x000fffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define PM_RSTC_WRCFG_CLR		0xffffffcf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define PM_RSTS_HADWRH_SET		0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define PM_RSTC_WRCFG_SET		0x00000030
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define PM_RSTC_WRCFG_FULL_RESET	0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define PM_RSTC_RESET			0x00000102
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define PM_READ(reg) readl(power->base + (reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define ASB_BRDG_VERSION                0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define ASB_CPR_CTRL                    0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define ASB_V3D_S_CTRL			0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define ASB_V3D_M_CTRL			0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define ASB_ISP_S_CTRL			0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define ASB_ISP_M_CTRL			0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define ASB_H264_S_CTRL			0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define ASB_H264_M_CTRL			0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define ASB_REQ_STOP                    BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define ASB_ACK                         BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define ASB_EMPTY                       BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define ASB_FULL                        BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define ASB_AXI_BRDG_ID			0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define ASB_READ(reg) readl(power->asb + (reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define ASB_WRITE(reg, val) writel(PM_PASSWORD | (val), power->asb + (reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct bcm2835_power_domain {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	struct generic_pm_domain base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	struct bcm2835_power *power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	u32 domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct bcm2835_power {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	struct device		*dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	/* PM registers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	void __iomem		*base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	/* AXI Async bridge registers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	void __iomem		*asb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	struct genpd_onecell_data pd_xlate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	struct reset_controller_dev reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	u64 start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	if (!reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	start = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	/* Enable the module's async AXI bridges. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	while (ASB_READ(reg) & ASB_ACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		if (ktime_get_ns() - start >= 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	u64 start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	if (!reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	start = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	/* Enable the module's async AXI bridges. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	while (!(ASB_READ(reg) & ASB_ACK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		if (ktime_get_ns() - start >= 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	struct bcm2835_power *power = pd->power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	/* Enable functional isolation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	/* Enable electrical isolation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	/* Open the power switches. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	struct bcm2835_power *power = pd->power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	struct device *dev = power->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	u64 start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	int inrush;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	bool powok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	/* If it was already powered on by the fw, leave it that way. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	if (PM_READ(pm_reg) & PM_POWUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	/* Enable power.  Allowing too much current at once may result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	 * in POWOK never getting set, so start low and ramp it up as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	 * necessary to succeed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	powok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		PM_WRITE(pm_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			 (PM_READ(pm_reg) & ~PM_INRUSH_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 			 (inrush << PM_INRUSH_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 			 PM_POWUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		start = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 			cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			if (ktime_get_ns() - start >= 3000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	if (!powok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		dev_err(dev, "Timeout waiting for %s power OK\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 			pd->base.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		goto err_disable_powup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	/* Disable electrical isolation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	/* Repair memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	start = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	while (!(PM_READ(pm_reg) & PM_MRDONE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		if (ktime_get_ns() - start >= 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 			dev_err(dev, "Timeout waiting for %s memory repair\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 				pd->base.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 			ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 			goto err_disable_ispow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	/* Disable functional isolation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) err_disable_ispow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) err_disable_powup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 				u32 pm_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 				u32 asb_m_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 				u32 asb_s_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 				u32 reset_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	struct bcm2835_power *power = pd->power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	ret = clk_prepare_enable(pd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		dev_err(power->dev, "Failed to enable clock for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 			pd->base.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	/* Wait 32 clocks for reset to propagate, 1 us will be enough */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	clk_disable_unprepare(pd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	/* Deassert the resets. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	ret = clk_prepare_enable(pd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		dev_err(power->dev, "Failed to enable clock for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 			pd->base.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		goto err_enable_resets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	ret = bcm2835_asb_enable(power, asb_m_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		dev_err(power->dev, "Failed to enable ASB master for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 			pd->base.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		goto err_disable_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	ret = bcm2835_asb_enable(power, asb_s_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		dev_err(power->dev, "Failed to enable ASB slave for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 			pd->base.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		goto err_disable_asb_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) err_disable_asb_master:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	bcm2835_asb_disable(power, asb_m_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) err_disable_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	clk_disable_unprepare(pd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) err_enable_resets:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 				 u32 pm_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 				 u32 asb_m_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 				 u32 asb_s_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 				 u32 reset_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	struct bcm2835_power *power = pd->power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	ret = bcm2835_asb_disable(power, asb_s_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		dev_warn(power->dev, "Failed to disable ASB slave for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 			 pd->base.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	ret = bcm2835_asb_disable(power, asb_m_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		dev_warn(power->dev, "Failed to disable ASB master for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 			 pd->base.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		bcm2835_asb_enable(power, asb_s_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	clk_disable_unprepare(pd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	/* Assert the resets. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	struct bcm2835_power_domain *pd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		container_of(domain, struct bcm2835_power_domain, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	struct bcm2835_power *power = pd->power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	switch (pd->domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	case BCM2835_POWER_DOMAIN_GRAFX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		return bcm2835_power_power_on(pd, PM_GRAFX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	case BCM2835_POWER_DOMAIN_GRAFX_V3D:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 		return bcm2835_asb_power_on(pd, PM_GRAFX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 					    ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 					    PM_V3DRSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	case BCM2835_POWER_DOMAIN_IMAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		return bcm2835_power_power_on(pd, PM_IMAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	case BCM2835_POWER_DOMAIN_IMAGE_PERI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 		return bcm2835_asb_power_on(pd, PM_IMAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 					    0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 					    PM_PERIRSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	case BCM2835_POWER_DOMAIN_IMAGE_ISP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		return bcm2835_asb_power_on(pd, PM_IMAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 					    ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 					    PM_ISPRSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	case BCM2835_POWER_DOMAIN_IMAGE_H264:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		return bcm2835_asb_power_on(pd, PM_IMAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 					    ASB_H264_M_CTRL, ASB_H264_S_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 					    PM_H264RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	case BCM2835_POWER_DOMAIN_USB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 		PM_WRITE(PM_USB, PM_USB_CTRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	case BCM2835_POWER_DOMAIN_DSI0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 		PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	case BCM2835_POWER_DOMAIN_DSI1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 		PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	case BCM2835_POWER_DOMAIN_CCP2TX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	case BCM2835_POWER_DOMAIN_HDMI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		usleep_range(100, 200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		dev_err(power->dev, "Invalid domain %d\n", pd->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	struct bcm2835_power_domain *pd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		container_of(domain, struct bcm2835_power_domain, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	struct bcm2835_power *power = pd->power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	switch (pd->domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	case BCM2835_POWER_DOMAIN_GRAFX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		return bcm2835_power_power_off(pd, PM_GRAFX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	case BCM2835_POWER_DOMAIN_GRAFX_V3D:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		return bcm2835_asb_power_off(pd, PM_GRAFX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 					     ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 					     PM_V3DRSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	case BCM2835_POWER_DOMAIN_IMAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		return bcm2835_power_power_off(pd, PM_IMAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	case BCM2835_POWER_DOMAIN_IMAGE_PERI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 		return bcm2835_asb_power_off(pd, PM_IMAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 					     0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 					     PM_PERIRSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	case BCM2835_POWER_DOMAIN_IMAGE_ISP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		return bcm2835_asb_power_off(pd, PM_IMAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 					     ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 					     PM_ISPRSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	case BCM2835_POWER_DOMAIN_IMAGE_H264:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		return bcm2835_asb_power_off(pd, PM_IMAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 					     ASB_H264_M_CTRL, ASB_H264_S_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 					     PM_H264RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	case BCM2835_POWER_DOMAIN_USB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		PM_WRITE(PM_USB, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	case BCM2835_POWER_DOMAIN_DSI0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		PM_WRITE(PM_DSI0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	case BCM2835_POWER_DOMAIN_DSI1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		PM_WRITE(PM_DSI1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	case BCM2835_POWER_DOMAIN_CCP2TX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		PM_WRITE(PM_CCP2TX, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	case BCM2835_POWER_DOMAIN_HDMI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		dev_err(power->dev, "Invalid domain %d\n", pd->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) bcm2835_init_power_domain(struct bcm2835_power *power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 			  int pd_xlate_index, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	struct device *dev = power->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	dom->clk = devm_clk_get(dev->parent, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	if (IS_ERR(dom->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		int ret = PTR_ERR(dom->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		if (ret == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		/* Some domains don't have a clk, so make sure that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		 * don't deref an error pointer later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		dom->clk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	dom->base.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	dom->base.power_on = bcm2835_power_pd_power_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	dom->base.power_off = bcm2835_power_pd_power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	dom->domain = pd_xlate_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	dom->power = power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	/* XXX: on/off at boot? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	pm_genpd_init(&dom->base, NULL, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	power->pd_xlate.domains[pd_xlate_index] = &dom->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /** bcm2835_reset_reset - Resets a block that has a reset line in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)  * PM block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)  * The consumer of the reset controller must have the power domain up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)  * -- there's no reset ability with the power domain down.  To reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)  * the sub-block, we just disable its access to memory through the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)  * ASB, reset, and re-enable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static int bcm2835_reset_reset(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 			       unsigned long id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 						   reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	struct bcm2835_power_domain *pd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	switch (id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	case BCM2835_RESET_V3D:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	case BCM2835_RESET_H264:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	case BCM2835_RESET_ISP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		dev_err(power->dev, "Bad reset id %ld\n", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	ret = bcm2835_power_pd_power_off(&pd->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	return bcm2835_power_pd_power_on(&pd->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static int bcm2835_reset_status(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 				unsigned long id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 						   reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	switch (id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	case BCM2835_RESET_V3D:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		return !PM_READ(PM_GRAFX & PM_V3DRSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	case BCM2835_RESET_H264:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 		return !PM_READ(PM_IMAGE & PM_H264RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	case BCM2835_RESET_ISP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 		return !PM_READ(PM_IMAGE & PM_ISPRSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) static const struct reset_control_ops bcm2835_reset_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	.reset = bcm2835_reset_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	.status = bcm2835_reset_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static const char *const power_domain_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	[BCM2835_POWER_DOMAIN_GRAFX] = "grafx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	[BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	[BCM2835_POWER_DOMAIN_IMAGE] = "image",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	[BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	[BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	[BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	[BCM2835_POWER_DOMAIN_USB] = "usb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	[BCM2835_POWER_DOMAIN_DSI0] = "dsi0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	[BCM2835_POWER_DOMAIN_DSI1] = "dsi1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	[BCM2835_POWER_DOMAIN_CAM0] = "cam0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	[BCM2835_POWER_DOMAIN_CAM1] = "cam1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	[BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	[BCM2835_POWER_DOMAIN_HDMI] = "hdmi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static int bcm2835_power_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	struct bcm2835_power *power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 		int parent, child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	} domain_deps[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 		{ BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 		{ BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 		{ BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 		{ BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 		{ BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 		{ BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		{ BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	int ret = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	if (!power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	platform_set_drvdata(pdev, power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	power->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	power->base = pm->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	power->asb = pm->asb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	id = ASB_READ(ASB_AXI_BRDG_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	if (id != 0x62726467 /* "BRDG" */) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 		dev_err(dev, "ASB register ID returned 0x%08x\n", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	power->pd_xlate.domains = devm_kcalloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 					       ARRAY_SIZE(power_domain_names),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 					       sizeof(*power->pd_xlate.domains),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 					       GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	if (!power->pd_xlate.domains)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 		ret = bcm2835_init_power_domain(power, i, power_domain_names[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 		pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 				       &power->domains[domain_deps[i].child].base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	power->reset.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	power->reset.nr_resets = BCM2835_RESET_COUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 	power->reset.ops = &bcm2835_reset_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	power->reset.of_node = dev->parent->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	ret = devm_reset_controller_register(dev, &power->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 	of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	dev_info(dev, "Broadcom BCM2835 power domains driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 		struct generic_pm_domain *dom = &power->domains[i].base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 		if (dom->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 			pm_genpd_remove(dom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) static int bcm2835_power_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static struct platform_driver bcm2835_power_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 	.probe		= bcm2835_power_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	.remove		= bcm2835_power_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 		.name =	"bcm2835-power",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) module_platform_driver(bcm2835_power_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) MODULE_LICENSE("GPL");