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-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (c) 2015, 2017-2018, 2022, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/ktime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/pm_domain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/regulator/consumer.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/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include "gdsc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define PWR_ON_MASK		BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define EN_REST_WAIT_MASK	GENMASK_ULL(23, 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define EN_FEW_WAIT_MASK	GENMASK_ULL(19, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define CLK_DIS_WAIT_MASK	GENMASK_ULL(15, 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define SW_OVERRIDE_MASK	BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define HW_CONTROL_MASK		BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define SW_COLLAPSE_MASK	BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define GMEM_CLAMP_IO_MASK	BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define GMEM_RESET_MASK		BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) /* CFG_GDSCR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define GDSC_POWER_UP_COMPLETE		BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define GDSC_POWER_DOWN_COMPLETE	BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define GDSC_RETAIN_FF_ENABLE		BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define CFG_GDSCR_OFFSET		0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) /* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define EN_REST_WAIT_VAL	0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define EN_FEW_WAIT_VAL		0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define CLK_DIS_WAIT_VAL	0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) /* Transition delay shifts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define EN_REST_WAIT_SHIFT	20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define EN_FEW_WAIT_SHIFT	16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define CLK_DIS_WAIT_SHIFT	12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define RETAIN_MEM		BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define RETAIN_PERIPH		BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) #define TIMEOUT_US		500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define domain_to_gdsc(domain) container_of(domain, struct gdsc, pd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) enum gdsc_status {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	GDSC_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	GDSC_ON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) /* Returns 1 if GDSC status is status, 0 if not, and < 0 on error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) static int gdsc_check_status(struct gdsc *sc, enum gdsc_status status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	if (sc->flags & POLL_CFG_GDSCR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		reg = sc->gdscr + CFG_GDSCR_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	else if (sc->gds_hw_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		reg = sc->gds_hw_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		reg = sc->gdscr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	ret = regmap_read(sc->regmap, reg, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	if (sc->flags & POLL_CFG_GDSCR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		switch (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		case GDSC_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 			return !!(val & GDSC_POWER_UP_COMPLETE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		case GDSC_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 			return !!(val & GDSC_POWER_DOWN_COMPLETE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	switch (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	case GDSC_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		return !!(val & PWR_ON_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	case GDSC_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		return !(val & PWR_ON_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) static int gdsc_hwctrl(struct gdsc *sc, bool en)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	u32 val = en ? HW_CONTROL_MASK : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	return regmap_update_bits(sc->regmap, sc->gdscr, HW_CONTROL_MASK, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int gdsc_poll_status(struct gdsc *sc, enum gdsc_status status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	ktime_t start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	start = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		if (gdsc_check_status(sc, status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	} while (ktime_us_delta(ktime_get(), start) < TIMEOUT_US);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	if (gdsc_check_status(sc, status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	u32 val = (status == GDSC_ON) ? 0 : SW_COLLAPSE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	if (status == GDSC_ON && sc->rsupply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		ret = regulator_enable(sc->rsupply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	ret = regmap_update_bits(sc->regmap, sc->gdscr, SW_COLLAPSE_MASK, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	/* If disabling votable gdscs, don't poll on status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	if ((sc->flags & VOTABLE) && status == GDSC_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		 * Add a short delay here to ensure that an enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		 * right after it was disabled does not put it in an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		 * unknown state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		udelay(TIMEOUT_US);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	if (sc->gds_hw_ctrl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		 * The gds hw controller asserts/de-asserts the status bit soon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		 * after it receives a power on/off request from a master.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		 * The controller then takes around 8 xo cycles to start its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		 * internal state machine and update the status bit. During
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		 * this time, the status bit does not reflect the true status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		 * of the core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		 * Add a delay of 1 us between writing to the SW_COLLAPSE bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		 * and polling the status bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	ret = gdsc_poll_status(sc, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	WARN(ret, "%s status stuck at 'o%s'", sc->pd.name, status ? "ff" : "n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	if (!ret && status == GDSC_OFF && sc->rsupply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		ret = regulator_disable(sc->rsupply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static inline int gdsc_deassert_reset(struct gdsc *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	for (i = 0; i < sc->reset_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		sc->rcdev->ops->deassert(sc->rcdev, sc->resets[i]);
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static inline int gdsc_assert_reset(struct gdsc *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	for (i = 0; i < sc->reset_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		sc->rcdev->ops->assert(sc->rcdev, sc->resets[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	return 0;
^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) static inline void gdsc_force_mem_on(struct gdsc *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	u32 mask = RETAIN_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	if (!(sc->flags & NO_RET_PERIPH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		mask |= RETAIN_PERIPH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	for (i = 0; i < sc->cxc_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		regmap_update_bits(sc->regmap, sc->cxcs[i], mask, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static inline void gdsc_clear_mem_on(struct gdsc *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	u32 mask = RETAIN_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	if (!(sc->flags & NO_RET_PERIPH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		mask |= RETAIN_PERIPH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	for (i = 0; i < sc->cxc_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		regmap_update_bits(sc->regmap, sc->cxcs[i], mask, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static inline void gdsc_deassert_clamp_io(struct gdsc *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	regmap_update_bits(sc->regmap, sc->clamp_io_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 			   GMEM_CLAMP_IO_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static inline void gdsc_assert_clamp_io(struct gdsc *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	regmap_update_bits(sc->regmap, sc->clamp_io_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 			   GMEM_CLAMP_IO_MASK, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static inline void gdsc_assert_reset_aon(struct gdsc *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	regmap_update_bits(sc->regmap, sc->clamp_io_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			   GMEM_RESET_MASK, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	regmap_update_bits(sc->regmap, sc->clamp_io_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 			   GMEM_RESET_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static void gdsc_retain_ff_on(struct gdsc *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	u32 mask = GDSC_RETAIN_FF_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	regmap_update_bits(sc->regmap, sc->gdscr, mask, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static int gdsc_enable(struct generic_pm_domain *domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	struct gdsc *sc = domain_to_gdsc(domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	if (sc->pwrsts == PWRSTS_ON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		return gdsc_deassert_reset(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	if (sc->flags & SW_RESET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		gdsc_assert_reset(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		gdsc_deassert_reset(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	if (sc->flags & CLAMP_IO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		if (sc->flags & AON_RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 			gdsc_assert_reset_aon(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		gdsc_deassert_clamp_io(sc);
^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) 	ret = gdsc_toggle_logic(sc, GDSC_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	if (sc->pwrsts & PWRSTS_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		gdsc_force_mem_on(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	 * If clocks to this power domain were already on, they will take an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	 * additional 4 clock cycles to re-enable after the power domain is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	 * enabled. Delay to account for this. A delay is also needed to ensure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	 * clocks are not enabled within 400ns of enabling power to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	 * memories.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	/* Turn on HW trigger mode if supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	if (sc->flags & HW_CTRL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		ret = gdsc_hwctrl(sc, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		 * Wait for the GDSC to go through a power down and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		 * up cycle.  In case a firmware ends up polling status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		 * bits for the gdsc, it might read an 'on' status before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		 * the GDSC can finish the power cycle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		 * We wait 1us before returning to ensure the firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		 * can't immediately poll the status bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	if (sc->flags & RETAIN_FF_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		gdsc_retain_ff_on(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static int gdsc_disable(struct generic_pm_domain *domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	struct gdsc *sc = domain_to_gdsc(domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	if (sc->pwrsts == PWRSTS_ON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		return gdsc_assert_reset(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	/* Turn off HW trigger mode if supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	if (sc->flags & HW_CTRL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		ret = gdsc_hwctrl(sc, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		 * Wait for the GDSC to go through a power down and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		 * up cycle.  In case we end up polling status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		 * bits for the gdsc before the power cycle is completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		 * it might read an 'on' status wrongly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		ret = gdsc_poll_status(sc, GDSC_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	if (sc->pwrsts & PWRSTS_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		gdsc_clear_mem_on(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	ret = gdsc_toggle_logic(sc, GDSC_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	if (sc->flags & CLAMP_IO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		gdsc_assert_clamp_io(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static int gdsc_init(struct gdsc *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	u32 mask, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	int on, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	 * Disable HW trigger: collapse/restore occur based on registers writes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	 * Disable SW override: Use hardware state-machine for sequencing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	 * Configure wait time between states.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	mask = HW_CONTROL_MASK | SW_OVERRIDE_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	       EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	if (!sc->en_rest_wait_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		sc->en_rest_wait_val = EN_REST_WAIT_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	if (!sc->en_few_wait_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		sc->en_few_wait_val = EN_FEW_WAIT_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	if (!sc->clk_dis_wait_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		sc->clk_dis_wait_val = CLK_DIS_WAIT_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	val = sc->en_rest_wait_val << EN_REST_WAIT_SHIFT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		sc->en_few_wait_val << EN_FEW_WAIT_SHIFT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		sc->clk_dis_wait_val << CLK_DIS_WAIT_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	ret = regmap_update_bits(sc->regmap, sc->gdscr, mask, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	/* Force gdsc ON if only ON state is supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	if (sc->pwrsts == PWRSTS_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		ret = gdsc_toggle_logic(sc, GDSC_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	on = gdsc_check_status(sc, GDSC_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	if (on < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		return on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		/* The regulator must be on, sync the kernel state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 		if (sc->rsupply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 			ret = regulator_enable(sc->rsupply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 			if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		 * Votable GDSCs can be ON due to Vote from other masters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		 * If a Votable GDSC is ON, make sure we have a Vote.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		if (sc->flags & VOTABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 			ret = regmap_update_bits(sc->regmap, sc->gdscr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 						 SW_COLLAPSE_MASK, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 		/* Turn on HW trigger mode if supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		if (sc->flags & HW_CTRL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 			ret = gdsc_hwctrl(sc, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 			if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 		 * Make sure the retain bit is set if the GDSC is already on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		 * otherwise we end up turning off the GDSC and destroying all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		 * the register contents that we thought we were saving.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		if (sc->flags & RETAIN_FF_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 			gdsc_retain_ff_on(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	} else if (sc->flags & ALWAYS_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		/* If ALWAYS_ON GDSCs are not ON, turn them ON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		gdsc_enable(&sc->pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		on = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	if (on || (sc->pwrsts & PWRSTS_RET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		gdsc_force_mem_on(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		gdsc_clear_mem_on(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	if (sc->flags & ALWAYS_ON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		sc->pd.flags |= GENPD_FLAG_ALWAYS_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	if (!sc->pd.power_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 		sc->pd.power_off = gdsc_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	if (!sc->pd.power_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		sc->pd.power_on = gdsc_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	pm_genpd_init(&sc->pd, NULL, !on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) int gdsc_register(struct gdsc_desc *desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		  struct reset_controller_dev *rcdev, struct regmap *regmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	struct genpd_onecell_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	struct device *dev = desc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	struct gdsc **scs = desc->scs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	size_t num = desc->num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	data->domains = devm_kcalloc(dev, num, sizeof(*data->domains),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 				     GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	if (!data->domains)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		if (!scs[i] || !scs[i]->supply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		scs[i]->rsupply = devm_regulator_get(dev, scs[i]->supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		if (IS_ERR(scs[i]->rsupply))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 			return PTR_ERR(scs[i]->rsupply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	data->num_domains = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		if (!scs[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		scs[i]->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		scs[i]->rcdev = rcdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		ret = gdsc_init(scs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		data->domains[i] = &scs[i]->pd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	/* Add subdomains */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		if (!scs[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		if (scs[i]->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 			pm_genpd_add_subdomain(scs[i]->parent, &scs[i]->pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	return of_genpd_add_provider_onecell(dev->of_node, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) void gdsc_unregister(struct gdsc_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	struct device *dev = desc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	struct gdsc **scs = desc->scs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	size_t num = desc->num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	/* Remove subdomains */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		if (!scs[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		if (scs[i]->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 			pm_genpd_remove_subdomain(scs[i]->parent, &scs[i]->pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	of_genpd_del_provider(dev->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)  * On SDM845+ the GPU GX domain is *almost* entirely controlled by the GMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)  * running in the CX domain so the CPU doesn't need to know anything about the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)  * GX domain EXCEPT....
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)  * Hardware constraints dictate that the GX be powered down before the CX. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)  * the GMU crashes it could leave the GX on. In order to successfully bring back
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)  * the device the CPU needs to disable the GX headswitch. There being no sane
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)  * way to reach in and touch that register from deep inside the GPU driver we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)  * need to set up the infrastructure to be able to ensure that the GPU can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)  * ensure that the GX is off during this super special case. We do this by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)  * defining a GX gdsc with a dummy enable function and a "default" disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)  * function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)  * This allows us to attach with genpd_dev_pm_attach_by_name() in the GPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)  * driver. During power up, nothing will happen from the CPU (and the GMU will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)  * power up normally but during power down this will ensure that the GX domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)  * is *really* off - this gives us a semi standard way of doing what we need.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	/* Do nothing but give genpd the impression that we were successful */
^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) EXPORT_SYMBOL_GPL(gdsc_gx_do_nothing_enable);