1*3b15ccacSCristian Ciocaltea // SPDX-License-Identifier: GPL-2.0+ 2*3b15ccacSCristian Ciocaltea // 3*3b15ccacSCristian Ciocaltea // Regulator driver for ATC260x PMICs 4*3b15ccacSCristian Ciocaltea // 5*3b15ccacSCristian Ciocaltea // Copyright (C) 2019 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> 6*3b15ccacSCristian Ciocaltea // Copyright (C) 2020 Cristian Ciocaltea <cristian.ciocaltea@gmail.com> 7*3b15ccacSCristian Ciocaltea 8*3b15ccacSCristian Ciocaltea #include <linux/mfd/atc260x/core.h> 9*3b15ccacSCristian Ciocaltea #include <linux/module.h> 10*3b15ccacSCristian Ciocaltea #include <linux/of_device.h> 11*3b15ccacSCristian Ciocaltea #include <linux/regmap.h> 12*3b15ccacSCristian Ciocaltea #include <linux/regulator/driver.h> 13*3b15ccacSCristian Ciocaltea 14*3b15ccacSCristian Ciocaltea struct atc260x_regulator_data { 15*3b15ccacSCristian Ciocaltea int voltage_time_dcdc; 16*3b15ccacSCristian Ciocaltea int voltage_time_ldo; 17*3b15ccacSCristian Ciocaltea }; 18*3b15ccacSCristian Ciocaltea 19*3b15ccacSCristian Ciocaltea static const struct linear_range atc2603c_dcdc_voltage_ranges[] = { 20*3b15ccacSCristian Ciocaltea REGULATOR_LINEAR_RANGE(1300000, 0, 13, 50000), 21*3b15ccacSCristian Ciocaltea REGULATOR_LINEAR_RANGE(1950000, 14, 15, 100000), 22*3b15ccacSCristian Ciocaltea }; 23*3b15ccacSCristian Ciocaltea 24*3b15ccacSCristian Ciocaltea static const struct linear_range atc2609a_dcdc_voltage_ranges[] = { 25*3b15ccacSCristian Ciocaltea REGULATOR_LINEAR_RANGE(600000, 0, 127, 6250), 26*3b15ccacSCristian Ciocaltea REGULATOR_LINEAR_RANGE(1400000, 128, 232, 25000), 27*3b15ccacSCristian Ciocaltea }; 28*3b15ccacSCristian Ciocaltea 29*3b15ccacSCristian Ciocaltea static const struct linear_range atc2609a_ldo_voltage_ranges0[] = { 30*3b15ccacSCristian Ciocaltea REGULATOR_LINEAR_RANGE(700000, 0, 15, 100000), 31*3b15ccacSCristian Ciocaltea REGULATOR_LINEAR_RANGE(2100000, 16, 28, 100000), 32*3b15ccacSCristian Ciocaltea }; 33*3b15ccacSCristian Ciocaltea 34*3b15ccacSCristian Ciocaltea static const struct linear_range atc2609a_ldo_voltage_ranges1[] = { 35*3b15ccacSCristian Ciocaltea REGULATOR_LINEAR_RANGE(850000, 0, 15, 100000), 36*3b15ccacSCristian Ciocaltea REGULATOR_LINEAR_RANGE(2100000, 16, 27, 100000), 37*3b15ccacSCristian Ciocaltea }; 38*3b15ccacSCristian Ciocaltea 39*3b15ccacSCristian Ciocaltea static const unsigned int atc260x_ldo_voltage_range_sel[] = { 40*3b15ccacSCristian Ciocaltea 0x0, 0x1, 41*3b15ccacSCristian Ciocaltea }; 42*3b15ccacSCristian Ciocaltea 43*3b15ccacSCristian Ciocaltea static int atc260x_dcdc_set_voltage_time_sel(struct regulator_dev *rdev, 44*3b15ccacSCristian Ciocaltea unsigned int old_selector, 45*3b15ccacSCristian Ciocaltea unsigned int new_selector) 46*3b15ccacSCristian Ciocaltea { 47*3b15ccacSCristian Ciocaltea struct atc260x_regulator_data *data = rdev_get_drvdata(rdev); 48*3b15ccacSCristian Ciocaltea 49*3b15ccacSCristian Ciocaltea if (new_selector > old_selector) 50*3b15ccacSCristian Ciocaltea return data->voltage_time_dcdc; 51*3b15ccacSCristian Ciocaltea 52*3b15ccacSCristian Ciocaltea return 0; 53*3b15ccacSCristian Ciocaltea } 54*3b15ccacSCristian Ciocaltea 55*3b15ccacSCristian Ciocaltea static int atc260x_ldo_set_voltage_time_sel(struct regulator_dev *rdev, 56*3b15ccacSCristian Ciocaltea unsigned int old_selector, 57*3b15ccacSCristian Ciocaltea unsigned int new_selector) 58*3b15ccacSCristian Ciocaltea { 59*3b15ccacSCristian Ciocaltea struct atc260x_regulator_data *data = rdev_get_drvdata(rdev); 60*3b15ccacSCristian Ciocaltea 61*3b15ccacSCristian Ciocaltea if (new_selector > old_selector) 62*3b15ccacSCristian Ciocaltea return data->voltage_time_ldo; 63*3b15ccacSCristian Ciocaltea 64*3b15ccacSCristian Ciocaltea return 0; 65*3b15ccacSCristian Ciocaltea } 66*3b15ccacSCristian Ciocaltea 67*3b15ccacSCristian Ciocaltea static const struct regulator_ops atc260x_dcdc_ops = { 68*3b15ccacSCristian Ciocaltea .enable = regulator_enable_regmap, 69*3b15ccacSCristian Ciocaltea .disable = regulator_disable_regmap, 70*3b15ccacSCristian Ciocaltea .is_enabled = regulator_is_enabled_regmap, 71*3b15ccacSCristian Ciocaltea .list_voltage = regulator_list_voltage_linear, 72*3b15ccacSCristian Ciocaltea .set_voltage_sel = regulator_set_voltage_sel_regmap, 73*3b15ccacSCristian Ciocaltea .get_voltage_sel = regulator_get_voltage_sel_regmap, 74*3b15ccacSCristian Ciocaltea .set_voltage_time_sel = atc260x_dcdc_set_voltage_time_sel, 75*3b15ccacSCristian Ciocaltea }; 76*3b15ccacSCristian Ciocaltea 77*3b15ccacSCristian Ciocaltea static const struct regulator_ops atc260x_ldo_ops = { 78*3b15ccacSCristian Ciocaltea .enable = regulator_enable_regmap, 79*3b15ccacSCristian Ciocaltea .disable = regulator_disable_regmap, 80*3b15ccacSCristian Ciocaltea .is_enabled = regulator_is_enabled_regmap, 81*3b15ccacSCristian Ciocaltea .list_voltage = regulator_list_voltage_linear, 82*3b15ccacSCristian Ciocaltea .set_voltage_sel = regulator_set_voltage_sel_regmap, 83*3b15ccacSCristian Ciocaltea .get_voltage_sel = regulator_get_voltage_sel_regmap, 84*3b15ccacSCristian Ciocaltea .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel, 85*3b15ccacSCristian Ciocaltea }; 86*3b15ccacSCristian Ciocaltea 87*3b15ccacSCristian Ciocaltea static const struct regulator_ops atc260x_ldo_bypass_ops = { 88*3b15ccacSCristian Ciocaltea .enable = regulator_enable_regmap, 89*3b15ccacSCristian Ciocaltea .disable = regulator_disable_regmap, 90*3b15ccacSCristian Ciocaltea .is_enabled = regulator_is_enabled_regmap, 91*3b15ccacSCristian Ciocaltea .list_voltage = regulator_list_voltage_linear, 92*3b15ccacSCristian Ciocaltea .set_voltage_sel = regulator_set_voltage_sel_regmap, 93*3b15ccacSCristian Ciocaltea .get_voltage_sel = regulator_get_voltage_sel_regmap, 94*3b15ccacSCristian Ciocaltea .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel, 95*3b15ccacSCristian Ciocaltea .set_bypass = regulator_set_bypass_regmap, 96*3b15ccacSCristian Ciocaltea .get_bypass = regulator_get_bypass_regmap, 97*3b15ccacSCristian Ciocaltea }; 98*3b15ccacSCristian Ciocaltea 99*3b15ccacSCristian Ciocaltea static const struct regulator_ops atc260x_ldo_bypass_discharge_ops = { 100*3b15ccacSCristian Ciocaltea .enable = regulator_enable_regmap, 101*3b15ccacSCristian Ciocaltea .disable = regulator_disable_regmap, 102*3b15ccacSCristian Ciocaltea .is_enabled = regulator_is_enabled_regmap, 103*3b15ccacSCristian Ciocaltea .list_voltage = regulator_list_voltage_linear, 104*3b15ccacSCristian Ciocaltea .set_voltage_sel = regulator_set_voltage_sel_regmap, 105*3b15ccacSCristian Ciocaltea .get_voltage_sel = regulator_get_voltage_sel_regmap, 106*3b15ccacSCristian Ciocaltea .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel, 107*3b15ccacSCristian Ciocaltea .set_bypass = regulator_set_bypass_regmap, 108*3b15ccacSCristian Ciocaltea .get_bypass = regulator_get_bypass_regmap, 109*3b15ccacSCristian Ciocaltea .set_active_discharge = regulator_set_active_discharge_regmap, 110*3b15ccacSCristian Ciocaltea }; 111*3b15ccacSCristian Ciocaltea 112*3b15ccacSCristian Ciocaltea static const struct regulator_ops atc260x_dcdc_range_ops = { 113*3b15ccacSCristian Ciocaltea .enable = regulator_enable_regmap, 114*3b15ccacSCristian Ciocaltea .disable = regulator_disable_regmap, 115*3b15ccacSCristian Ciocaltea .is_enabled = regulator_is_enabled_regmap, 116*3b15ccacSCristian Ciocaltea .list_voltage = regulator_list_voltage_linear_range, 117*3b15ccacSCristian Ciocaltea .set_voltage_sel = regulator_set_voltage_sel_regmap, 118*3b15ccacSCristian Ciocaltea .get_voltage_sel = regulator_get_voltage_sel_regmap, 119*3b15ccacSCristian Ciocaltea .set_voltage_time_sel = atc260x_dcdc_set_voltage_time_sel, 120*3b15ccacSCristian Ciocaltea }; 121*3b15ccacSCristian Ciocaltea 122*3b15ccacSCristian Ciocaltea static const struct regulator_ops atc260x_ldo_range_pick_ops = { 123*3b15ccacSCristian Ciocaltea .enable = regulator_enable_regmap, 124*3b15ccacSCristian Ciocaltea .disable = regulator_disable_regmap, 125*3b15ccacSCristian Ciocaltea .is_enabled = regulator_is_enabled_regmap, 126*3b15ccacSCristian Ciocaltea .list_voltage = regulator_list_voltage_pickable_linear_range, 127*3b15ccacSCristian Ciocaltea .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap, 128*3b15ccacSCristian Ciocaltea .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, 129*3b15ccacSCristian Ciocaltea .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel, 130*3b15ccacSCristian Ciocaltea }; 131*3b15ccacSCristian Ciocaltea 132*3b15ccacSCristian Ciocaltea static const struct regulator_ops atc260x_dcdc_fixed_ops = { 133*3b15ccacSCristian Ciocaltea .list_voltage = regulator_list_voltage_linear, 134*3b15ccacSCristian Ciocaltea .set_voltage_sel = regulator_set_voltage_sel_regmap, 135*3b15ccacSCristian Ciocaltea .get_voltage_sel = regulator_get_voltage_sel_regmap, 136*3b15ccacSCristian Ciocaltea .set_voltage_time_sel = atc260x_dcdc_set_voltage_time_sel, 137*3b15ccacSCristian Ciocaltea }; 138*3b15ccacSCristian Ciocaltea 139*3b15ccacSCristian Ciocaltea static const struct regulator_ops atc260x_ldo_fixed_ops = { 140*3b15ccacSCristian Ciocaltea .list_voltage = regulator_list_voltage_linear, 141*3b15ccacSCristian Ciocaltea .set_voltage_sel = regulator_set_voltage_sel_regmap, 142*3b15ccacSCristian Ciocaltea .get_voltage_sel = regulator_get_voltage_sel_regmap, 143*3b15ccacSCristian Ciocaltea .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel, 144*3b15ccacSCristian Ciocaltea }; 145*3b15ccacSCristian Ciocaltea 146*3b15ccacSCristian Ciocaltea static const struct regulator_ops atc260x_no_ops = { 147*3b15ccacSCristian Ciocaltea }; 148*3b15ccacSCristian Ciocaltea 149*3b15ccacSCristian Ciocaltea /* 150*3b15ccacSCristian Ciocaltea * Note LDO8 is not documented in datasheet (v2.4), but supported 151*3b15ccacSCristian Ciocaltea * in the vendor's driver implementation (xapp-le-kernel). 152*3b15ccacSCristian Ciocaltea */ 153*3b15ccacSCristian Ciocaltea enum atc2603c_reg_ids { 154*3b15ccacSCristian Ciocaltea ATC2603C_ID_DCDC1, 155*3b15ccacSCristian Ciocaltea ATC2603C_ID_DCDC2, 156*3b15ccacSCristian Ciocaltea ATC2603C_ID_DCDC3, 157*3b15ccacSCristian Ciocaltea ATC2603C_ID_LDO1, 158*3b15ccacSCristian Ciocaltea ATC2603C_ID_LDO2, 159*3b15ccacSCristian Ciocaltea ATC2603C_ID_LDO3, 160*3b15ccacSCristian Ciocaltea ATC2603C_ID_LDO5, 161*3b15ccacSCristian Ciocaltea ATC2603C_ID_LDO6, 162*3b15ccacSCristian Ciocaltea ATC2603C_ID_LDO7, 163*3b15ccacSCristian Ciocaltea ATC2603C_ID_LDO8, 164*3b15ccacSCristian Ciocaltea ATC2603C_ID_LDO11, 165*3b15ccacSCristian Ciocaltea ATC2603C_ID_LDO12, 166*3b15ccacSCristian Ciocaltea ATC2603C_ID_SWITCHLDO1, 167*3b15ccacSCristian Ciocaltea ATC2603C_ID_MAX, 168*3b15ccacSCristian Ciocaltea }; 169*3b15ccacSCristian Ciocaltea 170*3b15ccacSCristian Ciocaltea #define atc2603c_reg_desc_dcdc(num, min, step, n_volt, vsel_h, vsel_l) { \ 171*3b15ccacSCristian Ciocaltea .name = "DCDC"#num, \ 172*3b15ccacSCristian Ciocaltea .supply_name = "dcdc"#num, \ 173*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("dcdc"#num), \ 174*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 175*3b15ccacSCristian Ciocaltea .id = ATC2603C_ID_DCDC##num, \ 176*3b15ccacSCristian Ciocaltea .ops = &atc260x_dcdc_ops, \ 177*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 178*3b15ccacSCristian Ciocaltea .min_uV = min, \ 179*3b15ccacSCristian Ciocaltea .uV_step = step, \ 180*3b15ccacSCristian Ciocaltea .n_voltages = n_volt, \ 181*3b15ccacSCristian Ciocaltea .vsel_reg = ATC2603C_PMU_DC##num##_CTL0, \ 182*3b15ccacSCristian Ciocaltea .vsel_mask = GENMASK(vsel_h, vsel_l), \ 183*3b15ccacSCristian Ciocaltea .enable_reg = ATC2603C_PMU_DC##num##_CTL0, \ 184*3b15ccacSCristian Ciocaltea .enable_mask = BIT(15), \ 185*3b15ccacSCristian Ciocaltea .enable_time = 800, \ 186*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 187*3b15ccacSCristian Ciocaltea } 188*3b15ccacSCristian Ciocaltea 189*3b15ccacSCristian Ciocaltea #define atc2603c_reg_desc_dcdc_range(num, vsel_h, vsel_l) { \ 190*3b15ccacSCristian Ciocaltea .name = "DCDC"#num, \ 191*3b15ccacSCristian Ciocaltea .supply_name = "dcdc"#num, \ 192*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("dcdc"#num), \ 193*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 194*3b15ccacSCristian Ciocaltea .id = ATC2603C_ID_DCDC##num, \ 195*3b15ccacSCristian Ciocaltea .ops = &atc260x_dcdc_range_ops, \ 196*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 197*3b15ccacSCristian Ciocaltea .n_voltages = 16, \ 198*3b15ccacSCristian Ciocaltea .linear_ranges = atc2603c_dcdc_voltage_ranges, \ 199*3b15ccacSCristian Ciocaltea .n_linear_ranges = ARRAY_SIZE(atc2603c_dcdc_voltage_ranges), \ 200*3b15ccacSCristian Ciocaltea .vsel_reg = ATC2603C_PMU_DC##num##_CTL0, \ 201*3b15ccacSCristian Ciocaltea .vsel_mask = GENMASK(vsel_h, vsel_l), \ 202*3b15ccacSCristian Ciocaltea .enable_reg = ATC2603C_PMU_DC##num##_CTL0, \ 203*3b15ccacSCristian Ciocaltea .enable_mask = BIT(15), \ 204*3b15ccacSCristian Ciocaltea .enable_time = 800, \ 205*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 206*3b15ccacSCristian Ciocaltea } 207*3b15ccacSCristian Ciocaltea 208*3b15ccacSCristian Ciocaltea #define atc2603c_reg_desc_dcdc_fixed(num, min, step, n_volt, vsel_h, vsel_l) { \ 209*3b15ccacSCristian Ciocaltea .name = "DCDC"#num, \ 210*3b15ccacSCristian Ciocaltea .supply_name = "dcdc"#num, \ 211*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("dcdc"#num), \ 212*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 213*3b15ccacSCristian Ciocaltea .id = ATC2603C_ID_DCDC##num, \ 214*3b15ccacSCristian Ciocaltea .ops = &atc260x_dcdc_fixed_ops, \ 215*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 216*3b15ccacSCristian Ciocaltea .min_uV = min, \ 217*3b15ccacSCristian Ciocaltea .uV_step = step, \ 218*3b15ccacSCristian Ciocaltea .n_voltages = n_volt, \ 219*3b15ccacSCristian Ciocaltea .vsel_reg = ATC2603C_PMU_DC##num##_CTL0, \ 220*3b15ccacSCristian Ciocaltea .vsel_mask = GENMASK(vsel_h, vsel_l), \ 221*3b15ccacSCristian Ciocaltea .enable_time = 800, \ 222*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 223*3b15ccacSCristian Ciocaltea } 224*3b15ccacSCristian Ciocaltea 225*3b15ccacSCristian Ciocaltea #define atc2603c_reg_desc_ldo(num, min, step, n_volt, vsel_h, vsel_l) { \ 226*3b15ccacSCristian Ciocaltea .name = "LDO"#num, \ 227*3b15ccacSCristian Ciocaltea .supply_name = "ldo"#num, \ 228*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("ldo"#num), \ 229*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 230*3b15ccacSCristian Ciocaltea .id = ATC2603C_ID_LDO##num, \ 231*3b15ccacSCristian Ciocaltea .ops = &atc260x_ldo_ops, \ 232*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 233*3b15ccacSCristian Ciocaltea .min_uV = min, \ 234*3b15ccacSCristian Ciocaltea .uV_step = step, \ 235*3b15ccacSCristian Ciocaltea .n_voltages = n_volt, \ 236*3b15ccacSCristian Ciocaltea .vsel_reg = ATC2603C_PMU_LDO##num##_CTL, \ 237*3b15ccacSCristian Ciocaltea .vsel_mask = GENMASK(vsel_h, vsel_l), \ 238*3b15ccacSCristian Ciocaltea .enable_reg = ATC2603C_PMU_LDO##num##_CTL, \ 239*3b15ccacSCristian Ciocaltea .enable_mask = BIT(0), \ 240*3b15ccacSCristian Ciocaltea .enable_time = 2000, \ 241*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 242*3b15ccacSCristian Ciocaltea } 243*3b15ccacSCristian Ciocaltea 244*3b15ccacSCristian Ciocaltea #define atc2603c_reg_desc_ldo_fixed(num, min, step, n_volt, vsel_h, vsel_l) { \ 245*3b15ccacSCristian Ciocaltea .name = "LDO"#num, \ 246*3b15ccacSCristian Ciocaltea .supply_name = "ldo"#num, \ 247*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("ldo"#num), \ 248*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 249*3b15ccacSCristian Ciocaltea .id = ATC2603C_ID_LDO##num, \ 250*3b15ccacSCristian Ciocaltea .ops = &atc260x_ldo_fixed_ops, \ 251*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 252*3b15ccacSCristian Ciocaltea .min_uV = min, \ 253*3b15ccacSCristian Ciocaltea .uV_step = step, \ 254*3b15ccacSCristian Ciocaltea .n_voltages = n_volt, \ 255*3b15ccacSCristian Ciocaltea .vsel_reg = ATC2603C_PMU_LDO##num##_CTL, \ 256*3b15ccacSCristian Ciocaltea .vsel_mask = GENMASK(vsel_h, vsel_l), \ 257*3b15ccacSCristian Ciocaltea .enable_time = 2000, \ 258*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 259*3b15ccacSCristian Ciocaltea } 260*3b15ccacSCristian Ciocaltea 261*3b15ccacSCristian Ciocaltea #define atc2603c_reg_desc_ldo_noops(num, vfixed) { \ 262*3b15ccacSCristian Ciocaltea .name = "LDO"#num, \ 263*3b15ccacSCristian Ciocaltea .supply_name = "ldo"#num, \ 264*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("ldo"#num), \ 265*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 266*3b15ccacSCristian Ciocaltea .id = ATC2603C_ID_LDO##num, \ 267*3b15ccacSCristian Ciocaltea .ops = &atc260x_no_ops, \ 268*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 269*3b15ccacSCristian Ciocaltea .fixed_uV = vfixed, \ 270*3b15ccacSCristian Ciocaltea .n_voltages = 1, \ 271*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 272*3b15ccacSCristian Ciocaltea } 273*3b15ccacSCristian Ciocaltea 274*3b15ccacSCristian Ciocaltea #define atc2603c_reg_desc_ldo_switch(num, min, step, n_volt, vsel_h, vsel_l) { \ 275*3b15ccacSCristian Ciocaltea .name = "SWITCHLDO"#num, \ 276*3b15ccacSCristian Ciocaltea .supply_name = "switchldo"#num, \ 277*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("switchldo"#num), \ 278*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 279*3b15ccacSCristian Ciocaltea .id = ATC2603C_ID_SWITCHLDO##num, \ 280*3b15ccacSCristian Ciocaltea .ops = &atc260x_ldo_bypass_discharge_ops, \ 281*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 282*3b15ccacSCristian Ciocaltea .min_uV = min, \ 283*3b15ccacSCristian Ciocaltea .uV_step = step, \ 284*3b15ccacSCristian Ciocaltea .n_voltages = n_volt, \ 285*3b15ccacSCristian Ciocaltea .vsel_reg = ATC2603C_PMU_SWITCH_CTL, \ 286*3b15ccacSCristian Ciocaltea .vsel_mask = GENMASK(vsel_h, vsel_l), \ 287*3b15ccacSCristian Ciocaltea .enable_reg = ATC2603C_PMU_SWITCH_CTL, \ 288*3b15ccacSCristian Ciocaltea .enable_mask = BIT(15), \ 289*3b15ccacSCristian Ciocaltea .enable_is_inverted = true, \ 290*3b15ccacSCristian Ciocaltea .enable_time = 2000, \ 291*3b15ccacSCristian Ciocaltea .bypass_reg = ATC2603C_PMU_SWITCH_CTL, \ 292*3b15ccacSCristian Ciocaltea .bypass_mask = BIT(5), \ 293*3b15ccacSCristian Ciocaltea .active_discharge_reg = ATC2603C_PMU_SWITCH_CTL, \ 294*3b15ccacSCristian Ciocaltea .active_discharge_mask = BIT(1), \ 295*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 296*3b15ccacSCristian Ciocaltea } 297*3b15ccacSCristian Ciocaltea 298*3b15ccacSCristian Ciocaltea static const struct regulator_desc atc2603c_reg[] = { 299*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_dcdc_fixed(1, 700000, 25000, 29, 11, 7), 300*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_dcdc_range(2, 12, 8), 301*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_dcdc_fixed(3, 2600000, 100000, 8, 11, 9), 302*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_ldo_fixed(1, 2600000, 100000, 8, 15, 13), 303*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_ldo_fixed(2, 2600000, 100000, 8, 15, 13), 304*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_ldo_fixed(3, 1500000, 100000, 6, 15, 13), 305*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_ldo(5, 2600000, 100000, 8, 15, 13), 306*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_ldo_fixed(6, 700000, 25000, 29, 15, 11), 307*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_ldo(7, 1500000, 100000, 6, 15, 13), 308*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_ldo(8, 2300000, 100000, 11, 15, 12), 309*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_ldo_fixed(11, 2600000, 100000, 8, 15, 13), 310*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_ldo_noops(12, 1800000), 311*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_ldo_switch(1, 3000000, 100000, 4, 4, 3), 312*3b15ccacSCristian Ciocaltea }; 313*3b15ccacSCristian Ciocaltea 314*3b15ccacSCristian Ciocaltea static const struct regulator_desc atc2603c_reg_dcdc2_ver_b = 315*3b15ccacSCristian Ciocaltea atc2603c_reg_desc_dcdc(2, 1000000, 50000, 18, 12, 8); 316*3b15ccacSCristian Ciocaltea 317*3b15ccacSCristian Ciocaltea enum atc2609a_reg_ids { 318*3b15ccacSCristian Ciocaltea ATC2609A_ID_DCDC0, 319*3b15ccacSCristian Ciocaltea ATC2609A_ID_DCDC1, 320*3b15ccacSCristian Ciocaltea ATC2609A_ID_DCDC2, 321*3b15ccacSCristian Ciocaltea ATC2609A_ID_DCDC3, 322*3b15ccacSCristian Ciocaltea ATC2609A_ID_DCDC4, 323*3b15ccacSCristian Ciocaltea ATC2609A_ID_LDO0, 324*3b15ccacSCristian Ciocaltea ATC2609A_ID_LDO1, 325*3b15ccacSCristian Ciocaltea ATC2609A_ID_LDO2, 326*3b15ccacSCristian Ciocaltea ATC2609A_ID_LDO3, 327*3b15ccacSCristian Ciocaltea ATC2609A_ID_LDO4, 328*3b15ccacSCristian Ciocaltea ATC2609A_ID_LDO5, 329*3b15ccacSCristian Ciocaltea ATC2609A_ID_LDO6, 330*3b15ccacSCristian Ciocaltea ATC2609A_ID_LDO7, 331*3b15ccacSCristian Ciocaltea ATC2609A_ID_LDO8, 332*3b15ccacSCristian Ciocaltea ATC2609A_ID_LDO9, 333*3b15ccacSCristian Ciocaltea ATC2609A_ID_MAX, 334*3b15ccacSCristian Ciocaltea }; 335*3b15ccacSCristian Ciocaltea 336*3b15ccacSCristian Ciocaltea #define atc2609a_reg_desc_dcdc(num, en_bit) { \ 337*3b15ccacSCristian Ciocaltea .name = "DCDC"#num, \ 338*3b15ccacSCristian Ciocaltea .supply_name = "dcdc"#num, \ 339*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("dcdc"#num), \ 340*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 341*3b15ccacSCristian Ciocaltea .id = ATC2609A_ID_DCDC##num, \ 342*3b15ccacSCristian Ciocaltea .ops = &atc260x_dcdc_ops, \ 343*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 344*3b15ccacSCristian Ciocaltea .min_uV = 600000, \ 345*3b15ccacSCristian Ciocaltea .uV_step = 6250, \ 346*3b15ccacSCristian Ciocaltea .n_voltages = 256, \ 347*3b15ccacSCristian Ciocaltea .vsel_reg = ATC2609A_PMU_DC##num##_CTL0, \ 348*3b15ccacSCristian Ciocaltea .vsel_mask = GENMASK(15, 8), \ 349*3b15ccacSCristian Ciocaltea .enable_reg = ATC2609A_PMU_DC_OSC, \ 350*3b15ccacSCristian Ciocaltea .enable_mask = BIT(en_bit), \ 351*3b15ccacSCristian Ciocaltea .enable_time = 800, \ 352*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 353*3b15ccacSCristian Ciocaltea } 354*3b15ccacSCristian Ciocaltea 355*3b15ccacSCristian Ciocaltea #define atc2609a_reg_desc_dcdc_range(num, en_bit) { \ 356*3b15ccacSCristian Ciocaltea .name = "DCDC"#num, \ 357*3b15ccacSCristian Ciocaltea .supply_name = "dcdc"#num, \ 358*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("dcdc"#num), \ 359*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 360*3b15ccacSCristian Ciocaltea .id = ATC2609A_ID_DCDC##num, \ 361*3b15ccacSCristian Ciocaltea .ops = &atc260x_dcdc_range_ops, \ 362*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 363*3b15ccacSCristian Ciocaltea .n_voltages = 233, \ 364*3b15ccacSCristian Ciocaltea .linear_ranges = atc2609a_dcdc_voltage_ranges, \ 365*3b15ccacSCristian Ciocaltea .n_linear_ranges = ARRAY_SIZE(atc2609a_dcdc_voltage_ranges), \ 366*3b15ccacSCristian Ciocaltea .vsel_reg = ATC2609A_PMU_DC##num##_CTL0, \ 367*3b15ccacSCristian Ciocaltea .vsel_mask = GENMASK(15, 8), \ 368*3b15ccacSCristian Ciocaltea .enable_reg = ATC2609A_PMU_DC_OSC, \ 369*3b15ccacSCristian Ciocaltea .enable_mask = BIT(en_bit), \ 370*3b15ccacSCristian Ciocaltea .enable_time = 800, \ 371*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 372*3b15ccacSCristian Ciocaltea } 373*3b15ccacSCristian Ciocaltea 374*3b15ccacSCristian Ciocaltea #define atc2609a_reg_desc_ldo(num) { \ 375*3b15ccacSCristian Ciocaltea .name = "LDO"#num, \ 376*3b15ccacSCristian Ciocaltea .supply_name = "ldo"#num, \ 377*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("ldo"#num), \ 378*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 379*3b15ccacSCristian Ciocaltea .id = ATC2609A_ID_LDO##num, \ 380*3b15ccacSCristian Ciocaltea .ops = &atc260x_ldo_ops, \ 381*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 382*3b15ccacSCristian Ciocaltea .min_uV = 700000, \ 383*3b15ccacSCristian Ciocaltea .uV_step = 100000, \ 384*3b15ccacSCristian Ciocaltea .n_voltages = 16, \ 385*3b15ccacSCristian Ciocaltea .vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 386*3b15ccacSCristian Ciocaltea .vsel_mask = GENMASK(4, 1), \ 387*3b15ccacSCristian Ciocaltea .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 388*3b15ccacSCristian Ciocaltea .enable_mask = BIT(0), \ 389*3b15ccacSCristian Ciocaltea .enable_time = 2000, \ 390*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 391*3b15ccacSCristian Ciocaltea } 392*3b15ccacSCristian Ciocaltea 393*3b15ccacSCristian Ciocaltea #define atc2609a_reg_desc_ldo_bypass(num) { \ 394*3b15ccacSCristian Ciocaltea .name = "LDO"#num, \ 395*3b15ccacSCristian Ciocaltea .supply_name = "ldo"#num, \ 396*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("ldo"#num), \ 397*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 398*3b15ccacSCristian Ciocaltea .id = ATC2609A_ID_LDO##num, \ 399*3b15ccacSCristian Ciocaltea .ops = &atc260x_ldo_bypass_ops, \ 400*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 401*3b15ccacSCristian Ciocaltea .min_uV = 2300000, \ 402*3b15ccacSCristian Ciocaltea .uV_step = 100000, \ 403*3b15ccacSCristian Ciocaltea .n_voltages = 12, \ 404*3b15ccacSCristian Ciocaltea .vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 405*3b15ccacSCristian Ciocaltea .vsel_mask = GENMASK(5, 2), \ 406*3b15ccacSCristian Ciocaltea .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 407*3b15ccacSCristian Ciocaltea .enable_mask = BIT(0), \ 408*3b15ccacSCristian Ciocaltea .enable_time = 2000, \ 409*3b15ccacSCristian Ciocaltea .bypass_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 410*3b15ccacSCristian Ciocaltea .bypass_mask = BIT(1), \ 411*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 412*3b15ccacSCristian Ciocaltea } 413*3b15ccacSCristian Ciocaltea 414*3b15ccacSCristian Ciocaltea #define atc2609a_reg_desc_ldo_range_pick(num, n_range) { \ 415*3b15ccacSCristian Ciocaltea .name = "LDO"#num, \ 416*3b15ccacSCristian Ciocaltea .supply_name = "ldo"#num, \ 417*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("ldo"#num), \ 418*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 419*3b15ccacSCristian Ciocaltea .id = ATC2609A_ID_LDO##num, \ 420*3b15ccacSCristian Ciocaltea .ops = &atc260x_ldo_range_pick_ops, \ 421*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 422*3b15ccacSCristian Ciocaltea .linear_ranges = atc2609a_ldo_voltage_ranges##n_range, \ 423*3b15ccacSCristian Ciocaltea .n_linear_ranges = ARRAY_SIZE(atc2609a_ldo_voltage_ranges##n_range), \ 424*3b15ccacSCristian Ciocaltea .vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 425*3b15ccacSCristian Ciocaltea .vsel_mask = GENMASK(4, 1), \ 426*3b15ccacSCristian Ciocaltea .vsel_range_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 427*3b15ccacSCristian Ciocaltea .vsel_range_mask = BIT(5), \ 428*3b15ccacSCristian Ciocaltea .linear_range_selectors = atc260x_ldo_voltage_range_sel, \ 429*3b15ccacSCristian Ciocaltea .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 430*3b15ccacSCristian Ciocaltea .enable_mask = BIT(0), \ 431*3b15ccacSCristian Ciocaltea .enable_time = 2000, \ 432*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 433*3b15ccacSCristian Ciocaltea } 434*3b15ccacSCristian Ciocaltea 435*3b15ccacSCristian Ciocaltea #define atc2609a_reg_desc_ldo_fixed(num) { \ 436*3b15ccacSCristian Ciocaltea .name = "LDO"#num, \ 437*3b15ccacSCristian Ciocaltea .supply_name = "ldo"#num, \ 438*3b15ccacSCristian Ciocaltea .of_match = of_match_ptr("ldo"#num), \ 439*3b15ccacSCristian Ciocaltea .regulators_node = of_match_ptr("regulators"), \ 440*3b15ccacSCristian Ciocaltea .id = ATC2609A_ID_LDO##num, \ 441*3b15ccacSCristian Ciocaltea .ops = &atc260x_ldo_fixed_ops, \ 442*3b15ccacSCristian Ciocaltea .type = REGULATOR_VOLTAGE, \ 443*3b15ccacSCristian Ciocaltea .min_uV = 2600000, \ 444*3b15ccacSCristian Ciocaltea .uV_step = 100000, \ 445*3b15ccacSCristian Ciocaltea .n_voltages = 8, \ 446*3b15ccacSCristian Ciocaltea .vsel_reg = ATC2609A_PMU_LDO##num##_CTL, \ 447*3b15ccacSCristian Ciocaltea .vsel_mask = GENMASK(15, 13), \ 448*3b15ccacSCristian Ciocaltea .enable_time = 2000, \ 449*3b15ccacSCristian Ciocaltea .owner = THIS_MODULE, \ 450*3b15ccacSCristian Ciocaltea } 451*3b15ccacSCristian Ciocaltea 452*3b15ccacSCristian Ciocaltea static const struct regulator_desc atc2609a_reg[] = { 453*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_dcdc(0, 4), 454*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_dcdc(1, 5), 455*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_dcdc(2, 6), 456*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_dcdc_range(3, 7), 457*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_dcdc(4, 8), 458*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_ldo_bypass(0), 459*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_ldo_bypass(1), 460*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_ldo_bypass(2), 461*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_ldo_range_pick(3, 0), 462*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_ldo_range_pick(4, 0), 463*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_ldo(5), 464*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_ldo_range_pick(6, 1), 465*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_ldo_range_pick(7, 0), 466*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_ldo_range_pick(8, 0), 467*3b15ccacSCristian Ciocaltea atc2609a_reg_desc_ldo_fixed(9), 468*3b15ccacSCristian Ciocaltea }; 469*3b15ccacSCristian Ciocaltea 470*3b15ccacSCristian Ciocaltea static int atc260x_regulator_probe(struct platform_device *pdev) 471*3b15ccacSCristian Ciocaltea { 472*3b15ccacSCristian Ciocaltea struct atc260x *atc260x = dev_get_drvdata(pdev->dev.parent); 473*3b15ccacSCristian Ciocaltea struct device *dev = atc260x->dev; 474*3b15ccacSCristian Ciocaltea struct atc260x_regulator_data *atc260x_data; 475*3b15ccacSCristian Ciocaltea struct regulator_config config = {}; 476*3b15ccacSCristian Ciocaltea struct regulator_dev *atc260x_rdev; 477*3b15ccacSCristian Ciocaltea const struct regulator_desc *regulators; 478*3b15ccacSCristian Ciocaltea bool atc2603c_ver_b = false; 479*3b15ccacSCristian Ciocaltea int i, nregulators; 480*3b15ccacSCristian Ciocaltea 481*3b15ccacSCristian Ciocaltea atc260x_data = devm_kzalloc(&pdev->dev, sizeof(*atc260x_data), GFP_KERNEL); 482*3b15ccacSCristian Ciocaltea if (!atc260x_data) 483*3b15ccacSCristian Ciocaltea return -ENOMEM; 484*3b15ccacSCristian Ciocaltea 485*3b15ccacSCristian Ciocaltea atc260x_data->voltage_time_dcdc = 350; 486*3b15ccacSCristian Ciocaltea atc260x_data->voltage_time_ldo = 800; 487*3b15ccacSCristian Ciocaltea 488*3b15ccacSCristian Ciocaltea switch (atc260x->ic_type) { 489*3b15ccacSCristian Ciocaltea case ATC2603C: 490*3b15ccacSCristian Ciocaltea regulators = atc2603c_reg; 491*3b15ccacSCristian Ciocaltea nregulators = ATC2603C_ID_MAX; 492*3b15ccacSCristian Ciocaltea atc2603c_ver_b = atc260x->ic_ver == ATC260X_B; 493*3b15ccacSCristian Ciocaltea break; 494*3b15ccacSCristian Ciocaltea case ATC2609A: 495*3b15ccacSCristian Ciocaltea atc260x_data->voltage_time_dcdc = 250; 496*3b15ccacSCristian Ciocaltea regulators = atc2609a_reg; 497*3b15ccacSCristian Ciocaltea nregulators = ATC2609A_ID_MAX; 498*3b15ccacSCristian Ciocaltea break; 499*3b15ccacSCristian Ciocaltea default: 500*3b15ccacSCristian Ciocaltea dev_err(dev, "unsupported ATC260X ID %d\n", atc260x->ic_type); 501*3b15ccacSCristian Ciocaltea return -EINVAL; 502*3b15ccacSCristian Ciocaltea } 503*3b15ccacSCristian Ciocaltea 504*3b15ccacSCristian Ciocaltea config.dev = dev; 505*3b15ccacSCristian Ciocaltea config.regmap = atc260x->regmap; 506*3b15ccacSCristian Ciocaltea config.driver_data = atc260x_data; 507*3b15ccacSCristian Ciocaltea 508*3b15ccacSCristian Ciocaltea /* Instantiate the regulators */ 509*3b15ccacSCristian Ciocaltea for (i = 0; i < nregulators; i++) { 510*3b15ccacSCristian Ciocaltea if (atc2603c_ver_b && regulators[i].id == ATC2603C_ID_DCDC2) 511*3b15ccacSCristian Ciocaltea atc260x_rdev = devm_regulator_register(&pdev->dev, 512*3b15ccacSCristian Ciocaltea &atc2603c_reg_dcdc2_ver_b, 513*3b15ccacSCristian Ciocaltea &config); 514*3b15ccacSCristian Ciocaltea else 515*3b15ccacSCristian Ciocaltea atc260x_rdev = devm_regulator_register(&pdev->dev, 516*3b15ccacSCristian Ciocaltea ®ulators[i], 517*3b15ccacSCristian Ciocaltea &config); 518*3b15ccacSCristian Ciocaltea if (IS_ERR(atc260x_rdev)) { 519*3b15ccacSCristian Ciocaltea dev_err(dev, "failed to register regulator: %d\n", i); 520*3b15ccacSCristian Ciocaltea return PTR_ERR(atc260x_rdev); 521*3b15ccacSCristian Ciocaltea } 522*3b15ccacSCristian Ciocaltea } 523*3b15ccacSCristian Ciocaltea 524*3b15ccacSCristian Ciocaltea return 0; 525*3b15ccacSCristian Ciocaltea } 526*3b15ccacSCristian Ciocaltea 527*3b15ccacSCristian Ciocaltea static struct platform_driver atc260x_regulator_driver = { 528*3b15ccacSCristian Ciocaltea .probe = atc260x_regulator_probe, 529*3b15ccacSCristian Ciocaltea .driver = { 530*3b15ccacSCristian Ciocaltea .name = "atc260x-regulator", 531*3b15ccacSCristian Ciocaltea }, 532*3b15ccacSCristian Ciocaltea }; 533*3b15ccacSCristian Ciocaltea 534*3b15ccacSCristian Ciocaltea module_platform_driver(atc260x_regulator_driver); 535*3b15ccacSCristian Ciocaltea 536*3b15ccacSCristian Ciocaltea MODULE_DESCRIPTION("Regulator driver for ATC260x PMICs"); 537*3b15ccacSCristian Ciocaltea MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>"); 538*3b15ccacSCristian Ciocaltea MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@gmail.com>"); 539*3b15ccacSCristian Ciocaltea MODULE_LICENSE("GPL"); 540