^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) // Regulator support for WM8400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright 2008 Wolfson Microelectronics PLC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) // Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/err.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/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/regulator/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mfd/wm8400-private.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static const struct linear_range wm8400_ldo_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static const struct regulator_ops wm8400_ldo_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) .is_enabled = regulator_is_enabled_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) .enable = regulator_enable_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) .disable = regulator_disable_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) .list_voltage = regulator_list_voltage_linear_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) .get_voltage_sel = regulator_get_voltage_sel_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) .set_voltage_sel = regulator_set_voltage_sel_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) .map_voltage = regulator_map_voltage_linear_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct regmap *rmap = rdev_get_regmap(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) u16 data[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) ret = regmap_bulk_read(rmap, WM8400_DCDC1_CONTROL_1 + offset, data, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* Datasheet: hibernate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (data[0] & WM8400_DC1_SLEEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return REGULATOR_MODE_STANDBY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* Datasheet: standby */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (!(data[0] & WM8400_DC1_ACTIVE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return REGULATOR_MODE_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* Datasheet: active with or without force PWM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (data[1] & WM8400_DC1_FRC_PWM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return REGULATOR_MODE_FAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return REGULATOR_MODE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static int wm8400_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct regmap *rmap = rdev_get_regmap(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case REGULATOR_MODE_FAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* Datasheet: active with force PWM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) ret = regmap_update_bits(rmap, WM8400_DCDC1_CONTROL_2 + offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) WM8400_DC1_FRC_PWM, WM8400_DC1_FRC_PWM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return regmap_update_bits(rmap, WM8400_DCDC1_CONTROL_1 + offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) WM8400_DC1_ACTIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) case REGULATOR_MODE_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* Datasheet: active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ret = regmap_update_bits(rmap, WM8400_DCDC1_CONTROL_2 + offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) WM8400_DC1_FRC_PWM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return regmap_update_bits(rmap, WM8400_DCDC1_CONTROL_1 + offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) WM8400_DC1_ACTIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) case REGULATOR_MODE_IDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* Datasheet: standby */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return regmap_update_bits(rmap, WM8400_DCDC1_CONTROL_1 + offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^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 unsigned int wm8400_dcdc_get_optimum_mode(struct regulator_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int input_uV, int output_uV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int load_uA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return REGULATOR_MODE_NORMAL;
^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 const struct regulator_ops wm8400_dcdc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .is_enabled = regulator_is_enabled_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .enable = regulator_enable_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .disable = regulator_disable_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .list_voltage = regulator_list_voltage_linear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .map_voltage = regulator_map_voltage_linear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .get_voltage_sel = regulator_get_voltage_sel_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .set_voltage_sel = regulator_set_voltage_sel_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .get_mode = wm8400_dcdc_get_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .set_mode = wm8400_dcdc_set_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .get_optimum_mode = wm8400_dcdc_get_optimum_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static struct regulator_desc regulators[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .name = "LDO1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .id = WM8400_LDO1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .ops = &wm8400_ldo_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .enable_reg = WM8400_LDO1_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .enable_mask = WM8400_LDO1_ENA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .n_voltages = WM8400_LDO1_VSEL_MASK + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .linear_ranges = wm8400_ldo_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .vsel_reg = WM8400_LDO1_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .vsel_mask = WM8400_LDO1_VSEL_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .type = REGULATOR_VOLTAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .name = "LDO2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .id = WM8400_LDO2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .ops = &wm8400_ldo_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .enable_reg = WM8400_LDO2_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .enable_mask = WM8400_LDO2_ENA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .n_voltages = WM8400_LDO2_VSEL_MASK + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .linear_ranges = wm8400_ldo_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .type = REGULATOR_VOLTAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .vsel_reg = WM8400_LDO2_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .vsel_mask = WM8400_LDO2_VSEL_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .name = "LDO3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .id = WM8400_LDO3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .ops = &wm8400_ldo_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .enable_reg = WM8400_LDO3_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .enable_mask = WM8400_LDO3_ENA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .n_voltages = WM8400_LDO3_VSEL_MASK + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .linear_ranges = wm8400_ldo_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .vsel_reg = WM8400_LDO3_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .vsel_mask = WM8400_LDO3_VSEL_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .type = REGULATOR_VOLTAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .name = "LDO4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .id = WM8400_LDO4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .ops = &wm8400_ldo_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .enable_reg = WM8400_LDO4_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .enable_mask = WM8400_LDO4_ENA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .n_voltages = WM8400_LDO4_VSEL_MASK + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .linear_ranges = wm8400_ldo_ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .vsel_reg = WM8400_LDO4_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .vsel_mask = WM8400_LDO4_VSEL_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .type = REGULATOR_VOLTAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .name = "DCDC1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .id = WM8400_DCDC1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .ops = &wm8400_dcdc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .enable_reg = WM8400_DCDC1_CONTROL_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .enable_mask = WM8400_DC1_ENA_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .n_voltages = WM8400_DC1_VSEL_MASK + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .vsel_reg = WM8400_DCDC1_CONTROL_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .vsel_mask = WM8400_DC1_VSEL_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .min_uV = 850000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .uV_step = 25000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .type = REGULATOR_VOLTAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .name = "DCDC2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .id = WM8400_DCDC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .ops = &wm8400_dcdc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .enable_reg = WM8400_DCDC2_CONTROL_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .enable_mask = WM8400_DC2_ENA_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .n_voltages = WM8400_DC2_VSEL_MASK + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .vsel_reg = WM8400_DCDC2_CONTROL_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .vsel_mask = WM8400_DC2_VSEL_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .min_uV = 850000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .uV_step = 25000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .type = REGULATOR_VOLTAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static int wm8400_regulator_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct regulator_config config = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct regulator_dev *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) config.dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) config.init_data = dev_get_platdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) config.driver_data = wm8400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) config.regmap = wm8400->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) rdev = devm_regulator_register(&pdev->dev, ®ulators[pdev->id],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) &config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (IS_ERR(rdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return PTR_ERR(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) platform_set_drvdata(pdev, rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static struct platform_driver wm8400_regulator_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .name = "wm8400-regulator",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .probe = wm8400_regulator_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * wm8400_register_regulator - enable software control of a WM8400 regulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * This function enables software control of a WM8400 regulator via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * the regulator API. It is intended to be called from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * platform_init() callback of the WM8400 MFD driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * @dev: The WM8400 device to operate on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * @reg: The regulator to control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * @initdata: Regulator initdata for the regulator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int wm8400_register_regulator(struct device *dev, int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct regulator_init_data *initdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct wm8400 *wm8400 = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (wm8400->regulators[reg].name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) initdata->driver_data = wm8400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) wm8400->regulators[reg].name = "wm8400-regulator";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) wm8400->regulators[reg].id = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) wm8400->regulators[reg].dev.parent = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) wm8400->regulators[reg].dev.platform_data = initdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return platform_device_register(&wm8400->regulators[reg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) EXPORT_SYMBOL_GPL(wm8400_register_regulator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static int __init wm8400_regulator_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return platform_driver_register(&wm8400_regulator_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) subsys_initcall(wm8400_regulator_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static void __exit wm8400_regulator_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) platform_driver_unregister(&wm8400_regulator_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) module_exit(wm8400_regulator_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) MODULE_DESCRIPTION("WM8400 regulator driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) MODULE_ALIAS("platform:wm8400-regulator");