^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Broadcom BCM590xx regulator driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2014 Linaro Limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Matt Porter <mporter@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.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/mfd/bcm590xx.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/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/regulator/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/regulator/machine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/regulator/of_regulator.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* I2C slave 0 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define BCM590XX_RFLDOPMCTRL1 0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define BCM590XX_IOSR1PMCTRL1 0x7a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define BCM590XX_IOSR2PMCTRL1 0x7c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define BCM590XX_CSRPMCTRL1 0x7e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define BCM590XX_SDSR1PMCTRL1 0x82
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define BCM590XX_SDSR2PMCTRL1 0x86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define BCM590XX_MSRPMCTRL1 0x8a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define BCM590XX_VSRPMCTRL1 0x8e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define BCM590XX_RFLDOCTRL 0x96
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define BCM590XX_CSRVOUT1 0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* I2C slave 1 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define BCM590XX_GPLDO5PMCTRL1 0x16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define BCM590XX_GPLDO6PMCTRL1 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define BCM590XX_GPLDO1CTRL 0x1a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define BCM590XX_GPLDO2CTRL 0x1b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define BCM590XX_GPLDO3CTRL 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define BCM590XX_GPLDO4CTRL 0x1d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define BCM590XX_GPLDO5CTRL 0x1e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define BCM590XX_GPLDO6CTRL 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define BCM590XX_OTG_CTRL 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define BCM590XX_GPLDO1PMCTRL1 0x57
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define BCM590XX_GPLDO2PMCTRL1 0x59
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define BCM590XX_GPLDO3PMCTRL1 0x5b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define BCM590XX_GPLDO4PMCTRL1 0x5d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define BCM590XX_REG_ENABLE BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define BCM590XX_VBUS_ENABLE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define BCM590XX_LDO_VSEL_MASK GENMASK(5, 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define BCM590XX_SR_VSEL_MASK GENMASK(5, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * RFLDO to VSR regulators are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * accessed via I2C slave 0
^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) /* LDO regulator IDs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define BCM590XX_REG_RFLDO 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define BCM590XX_REG_CAMLDO1 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define BCM590XX_REG_CAMLDO2 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define BCM590XX_REG_SIMLDO1 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define BCM590XX_REG_SIMLDO2 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define BCM590XX_REG_SDLDO 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define BCM590XX_REG_SDXLDO 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define BCM590XX_REG_MMCLDO1 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define BCM590XX_REG_MMCLDO2 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define BCM590XX_REG_AUDLDO 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define BCM590XX_REG_MICLDO 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define BCM590XX_REG_USBLDO 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define BCM590XX_REG_VIBLDO 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* DCDC regulator IDs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define BCM590XX_REG_CSR 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define BCM590XX_REG_IOSR1 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define BCM590XX_REG_IOSR2 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define BCM590XX_REG_MSR 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define BCM590XX_REG_SDSR1 17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define BCM590XX_REG_SDSR2 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define BCM590XX_REG_VSR 19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * GPLDO1 to VBUS regulators are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * accessed via I2C slave 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define BCM590XX_REG_GPLDO1 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define BCM590XX_REG_GPLDO2 21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define BCM590XX_REG_GPLDO3 22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define BCM590XX_REG_GPLDO4 23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define BCM590XX_REG_GPLDO5 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define BCM590XX_REG_GPLDO6 25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define BCM590XX_REG_VBUS 26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define BCM590XX_NUM_REGS 27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define BCM590XX_REG_IS_LDO(n) (n < BCM590XX_REG_CSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define BCM590XX_REG_IS_GPLDO(n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) ((n > BCM590XX_REG_VSR) && (n < BCM590XX_REG_VBUS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define BCM590XX_REG_IS_VBUS(n) (n == BCM590XX_REG_VBUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* LDO group A: supported voltages in microvolts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static const unsigned int ldo_a_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 1200000, 1800000, 2500000, 2700000, 2800000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 2900000, 3000000, 3300000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* LDO group C: supported voltages in microvolts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static const unsigned int ldo_c_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 3100000, 1800000, 2500000, 2700000, 2800000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 2900000, 3000000, 3300000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static const unsigned int ldo_vbus[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 5000000,
^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) /* DCDC group CSR: supported voltages in microvolts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static const struct linear_range dcdc_csr_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) REGULATOR_LINEAR_RANGE(1360000, 51, 55, 20000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) REGULATOR_LINEAR_RANGE(900000, 56, 63, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* DCDC group IOSR1: supported voltages in microvolts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static const struct linear_range dcdc_iosr1_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) REGULATOR_LINEAR_RANGE(860000, 2, 51, 10000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) REGULATOR_LINEAR_RANGE(1500000, 52, 52, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) REGULATOR_LINEAR_RANGE(1800000, 53, 53, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) REGULATOR_LINEAR_RANGE(900000, 54, 63, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* DCDC group SDSR1: supported voltages in microvolts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static const struct linear_range dcdc_sdsr1_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) REGULATOR_LINEAR_RANGE(1340000, 51, 51, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) REGULATOR_LINEAR_RANGE(900000, 52, 63, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct bcm590xx_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) const char *vin_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) u8 n_voltages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) const unsigned int *volt_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u8 n_linear_ranges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) const struct linear_range *linear_ranges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define BCM590XX_REG_TABLE(_name, _table) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .name = #_name, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .n_voltages = ARRAY_SIZE(_table), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .volt_table = _table, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define BCM590XX_REG_RANGES(_name, _ranges) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .name = #_name, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .n_voltages = 64, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .n_linear_ranges = ARRAY_SIZE(_ranges), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .linear_ranges = _ranges, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static struct bcm590xx_info bcm590xx_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) BCM590XX_REG_TABLE(rfldo, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) BCM590XX_REG_TABLE(camldo1, ldo_c_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) BCM590XX_REG_TABLE(camldo2, ldo_c_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) BCM590XX_REG_TABLE(simldo1, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) BCM590XX_REG_TABLE(simldo2, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) BCM590XX_REG_TABLE(sdldo, ldo_c_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) BCM590XX_REG_TABLE(sdxldo, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) BCM590XX_REG_TABLE(mmcldo1, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) BCM590XX_REG_TABLE(mmcldo2, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) BCM590XX_REG_TABLE(audldo, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) BCM590XX_REG_TABLE(micldo, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) BCM590XX_REG_TABLE(usbldo, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) BCM590XX_REG_TABLE(vibldo, ldo_c_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) BCM590XX_REG_RANGES(csr, dcdc_csr_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) BCM590XX_REG_RANGES(iosr1, dcdc_iosr1_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) BCM590XX_REG_RANGES(iosr2, dcdc_iosr1_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) BCM590XX_REG_RANGES(msr, dcdc_iosr1_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) BCM590XX_REG_RANGES(sdsr1, dcdc_sdsr1_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) BCM590XX_REG_RANGES(sdsr2, dcdc_iosr1_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) BCM590XX_REG_RANGES(vsr, dcdc_iosr1_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) BCM590XX_REG_TABLE(gpldo1, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) BCM590XX_REG_TABLE(gpldo2, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) BCM590XX_REG_TABLE(gpldo3, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) BCM590XX_REG_TABLE(gpldo4, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) BCM590XX_REG_TABLE(gpldo5, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) BCM590XX_REG_TABLE(gpldo6, ldo_a_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) BCM590XX_REG_TABLE(vbus, ldo_vbus),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct bcm590xx_reg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct regulator_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct bcm590xx *mfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static int bcm590xx_get_vsel_register(int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (BCM590XX_REG_IS_LDO(id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return BCM590XX_RFLDOCTRL + id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) else if (BCM590XX_REG_IS_GPLDO(id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return BCM590XX_GPLDO1CTRL + id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return BCM590XX_CSRVOUT1 + (id - BCM590XX_REG_CSR) * 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int bcm590xx_get_enable_register(int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int reg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (BCM590XX_REG_IS_LDO(id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) reg = BCM590XX_RFLDOPMCTRL1 + id * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) else if (BCM590XX_REG_IS_GPLDO(id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) reg = BCM590XX_GPLDO1PMCTRL1 + id * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) switch (id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case BCM590XX_REG_CSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) reg = BCM590XX_CSRPMCTRL1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) case BCM590XX_REG_IOSR1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) reg = BCM590XX_IOSR1PMCTRL1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) case BCM590XX_REG_IOSR2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) reg = BCM590XX_IOSR2PMCTRL1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) case BCM590XX_REG_MSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) reg = BCM590XX_MSRPMCTRL1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case BCM590XX_REG_SDSR1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) reg = BCM590XX_SDSR1PMCTRL1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) case BCM590XX_REG_SDSR2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) reg = BCM590XX_SDSR2PMCTRL1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) case BCM590XX_REG_VSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) reg = BCM590XX_VSRPMCTRL1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) case BCM590XX_REG_VBUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) reg = BCM590XX_OTG_CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) break;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static const struct regulator_ops bcm590xx_ops_ldo = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) .is_enabled = regulator_is_enabled_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .enable = regulator_enable_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .disable = regulator_disable_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .get_voltage_sel = regulator_get_voltage_sel_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .set_voltage_sel = regulator_set_voltage_sel_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .list_voltage = regulator_list_voltage_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .map_voltage = regulator_map_voltage_iterate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static const struct regulator_ops bcm590xx_ops_dcdc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .is_enabled = regulator_is_enabled_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .enable = regulator_enable_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .disable = regulator_disable_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .get_voltage_sel = regulator_get_voltage_sel_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .set_voltage_sel = regulator_set_voltage_sel_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .list_voltage = regulator_list_voltage_linear_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .map_voltage = regulator_map_voltage_linear_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static const struct regulator_ops bcm590xx_ops_vbus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .is_enabled = regulator_is_enabled_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .enable = regulator_enable_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) .disable = regulator_disable_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static int bcm590xx_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct bcm590xx *bcm590xx = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct bcm590xx_reg *pmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct regulator_config config = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct bcm590xx_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct regulator_dev *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!pmu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) pmu->mfd = bcm590xx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) platform_set_drvdata(pdev, pmu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) pmu->desc = devm_kcalloc(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) BCM590XX_NUM_REGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) sizeof(struct regulator_desc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (!pmu->desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) info = bcm590xx_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) for (i = 0; i < BCM590XX_NUM_REGS; i++, info++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) /* Register the regulators */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) pmu->desc[i].name = info->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) pmu->desc[i].of_match = of_match_ptr(info->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) pmu->desc[i].regulators_node = of_match_ptr("regulators");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) pmu->desc[i].supply_name = info->vin_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) pmu->desc[i].id = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) pmu->desc[i].volt_table = info->volt_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) pmu->desc[i].n_voltages = info->n_voltages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) pmu->desc[i].linear_ranges = info->linear_ranges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) pmu->desc[i].n_linear_ranges = info->n_linear_ranges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if ((BCM590XX_REG_IS_LDO(i)) || (BCM590XX_REG_IS_GPLDO(i))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) pmu->desc[i].ops = &bcm590xx_ops_ldo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) pmu->desc[i].vsel_mask = BCM590XX_LDO_VSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) } else if (BCM590XX_REG_IS_VBUS(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) pmu->desc[i].ops = &bcm590xx_ops_vbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) pmu->desc[i].ops = &bcm590xx_ops_dcdc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) pmu->desc[i].vsel_mask = BCM590XX_SR_VSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (BCM590XX_REG_IS_VBUS(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) pmu->desc[i].enable_mask = BCM590XX_VBUS_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) pmu->desc[i].vsel_reg = bcm590xx_get_vsel_register(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) pmu->desc[i].enable_is_inverted = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) pmu->desc[i].enable_mask = BCM590XX_REG_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) pmu->desc[i].enable_reg = bcm590xx_get_enable_register(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) pmu->desc[i].type = REGULATOR_VOLTAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) pmu->desc[i].owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) config.dev = bcm590xx->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) config.driver_data = pmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (BCM590XX_REG_IS_GPLDO(i) || BCM590XX_REG_IS_VBUS(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) config.regmap = bcm590xx->regmap_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) config.regmap = bcm590xx->regmap_pri;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) rdev = devm_regulator_register(&pdev->dev, &pmu->desc[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) &config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (IS_ERR(rdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) dev_err(bcm590xx->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) "failed to register %s regulator\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) pdev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return PTR_ERR(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static struct platform_driver bcm590xx_regulator_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) .name = "bcm590xx-vregs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) .probe = bcm590xx_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) module_platform_driver(bcm590xx_regulator_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) MODULE_DESCRIPTION("BCM590xx voltage regulator driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) MODULE_ALIAS("platform:bcm590xx-vregs");