18171c93bSChiYuan Huang // SPDX-License-Identifier: GPL-2.0+ 28171c93bSChiYuan Huang 38171c93bSChiYuan Huang #include <linux/bits.h> 48171c93bSChiYuan Huang #include <linux/gpio/consumer.h> 58171c93bSChiYuan Huang #include <linux/interrupt.h> 68171c93bSChiYuan Huang #include <linux/kernel.h> 78171c93bSChiYuan Huang #include <linux/module.h> 88171c93bSChiYuan Huang #include <linux/of.h> 98171c93bSChiYuan Huang #include <linux/platform_device.h> 108171c93bSChiYuan Huang #include <linux/regmap.h> 118171c93bSChiYuan Huang #include <linux/regulator/driver.h> 128171c93bSChiYuan Huang #include <linux/regulator/machine.h> 138171c93bSChiYuan Huang 148171c93bSChiYuan Huang enum { 158171c93bSChiYuan Huang MT6370_IDX_DSVBOOST = 0, 168171c93bSChiYuan Huang MT6370_IDX_DSVPOS, 178171c93bSChiYuan Huang MT6370_IDX_DSVNEG, 188171c93bSChiYuan Huang MT6370_IDX_VIBLDO, 198171c93bSChiYuan Huang MT6370_MAX_IDX 208171c93bSChiYuan Huang }; 218171c93bSChiYuan Huang 228171c93bSChiYuan Huang #define MT6370_REG_LDO_CFG 0x180 238171c93bSChiYuan Huang #define MT6370_REG_LDO_VOUT 0x181 248171c93bSChiYuan Huang #define MT6370_REG_DB_CTRL1 0x1B0 258171c93bSChiYuan Huang #define MT6370_REG_DB_CTRL2 0x1B1 268171c93bSChiYuan Huang #define MT6370_REG_DB_VBST 0x1B2 278171c93bSChiYuan Huang #define MT6370_REG_DB_VPOS 0x1B3 288171c93bSChiYuan Huang #define MT6370_REG_DB_VNEG 0x1B4 298171c93bSChiYuan Huang #define MT6370_REG_LDO_STAT 0x1DC 308171c93bSChiYuan Huang #define MT6370_REG_DB_STAT 0x1DF 318171c93bSChiYuan Huang 328171c93bSChiYuan Huang #define MT6370_LDOOMS_MASK BIT(7) 338171c93bSChiYuan Huang #define MT6370_LDOEN_MASK BIT(7) 348171c93bSChiYuan Huang #define MT6370_LDOVOUT_MASK GENMASK(3, 0) 358171c93bSChiYuan Huang #define MT6370_DBPERD_MASK (BIT(7) | BIT(4)) 368171c93bSChiYuan Huang #define MT6370_DBEXTEN_MASK BIT(0) 378171c93bSChiYuan Huang #define MT6370_DBVPOSEN_MASK BIT(6) 388171c93bSChiYuan Huang #define MT6370_DBVPOSDISG_MASK BIT(5) 398171c93bSChiYuan Huang #define MT6370_DBVNEGEN_MASK BIT(3) 408171c93bSChiYuan Huang #define MT6370_DBVNEGDISG_MASK BIT(2) 418171c93bSChiYuan Huang #define MT6370_DBALLON_MASK (MT6370_DBVPOSEN_MASK | MT6370_DBVNEGEN_MASK) 428171c93bSChiYuan Huang #define MT6370_DBSLEW_MASK GENMASK(7, 6) 438171c93bSChiYuan Huang #define MT6370_DBVOUT_MASK GENMASK(5, 0) 448171c93bSChiYuan Huang #define MT6370_LDOOC_EVT_MASK BIT(7) 458171c93bSChiYuan Huang #define MT6370_POSSCP_EVT_MASK BIT(7) 468171c93bSChiYuan Huang #define MT6370_NEGSCP_EVT_MASK BIT(6) 478171c93bSChiYuan Huang #define MT6370_BSTOCP_EVT_MASK BIT(5) 488171c93bSChiYuan Huang #define MT6370_POSOCP_EVT_MASK BIT(4) 498171c93bSChiYuan Huang #define MT6370_NEGOCP_EVT_MASK BIT(3) 508171c93bSChiYuan Huang 518171c93bSChiYuan Huang #define MT6370_LDO_MINUV 1600000 528171c93bSChiYuan Huang #define MT6370_LDO_STPUV 200000 538171c93bSChiYuan Huang #define MT6370_LDO_N_VOLT 13 548171c93bSChiYuan Huang #define MT6370_DBVBOOST_MINUV 4000000 558171c93bSChiYuan Huang #define MT6370_DBVBOOST_STPUV 50000 568171c93bSChiYuan Huang #define MT6370_DBVBOOST_N_VOLT 45 578171c93bSChiYuan Huang #define MT6370_DBVOUT_MINUV 4000000 588171c93bSChiYuan Huang #define MT6370_DBVOUT_STPUV 50000 598171c93bSChiYuan Huang #define MT6370_DBVOUT_N_VOLT 41 608171c93bSChiYuan Huang 618171c93bSChiYuan Huang struct mt6370_priv { 628171c93bSChiYuan Huang struct device *dev; 638171c93bSChiYuan Huang struct regmap *regmap; 648171c93bSChiYuan Huang struct regulator_dev *rdev[MT6370_MAX_IDX]; 658171c93bSChiYuan Huang bool use_external_ctrl; 668171c93bSChiYuan Huang }; 678171c93bSChiYuan Huang 688171c93bSChiYuan Huang static const unsigned int mt6370_vpos_ramp_tbl[] = { 8540, 5840, 4830, 3000 }; 698171c93bSChiYuan Huang static const unsigned int mt6370_vneg_ramp_tbl[] = { 10090, 6310, 5050, 3150 }; 708171c93bSChiYuan Huang 718171c93bSChiYuan Huang static int mt6370_get_error_flags(struct regulator_dev *rdev, 728171c93bSChiYuan Huang unsigned int *flags) 738171c93bSChiYuan Huang { 748171c93bSChiYuan Huang struct regmap *regmap = rdev_get_regmap(rdev); 758171c93bSChiYuan Huang unsigned int stat_reg, stat, rpt_flags = 0; 768171c93bSChiYuan Huang int rid = rdev_get_id(rdev), ret; 778171c93bSChiYuan Huang 788171c93bSChiYuan Huang if (rid == MT6370_IDX_VIBLDO) 798171c93bSChiYuan Huang stat_reg = MT6370_REG_LDO_STAT; 808171c93bSChiYuan Huang else 818171c93bSChiYuan Huang stat_reg = MT6370_REG_DB_STAT; 828171c93bSChiYuan Huang 838171c93bSChiYuan Huang ret = regmap_read(regmap, stat_reg, &stat); 848171c93bSChiYuan Huang if (ret) 858171c93bSChiYuan Huang return ret; 868171c93bSChiYuan Huang 878171c93bSChiYuan Huang switch (rid) { 888171c93bSChiYuan Huang case MT6370_IDX_DSVBOOST: 898171c93bSChiYuan Huang if (stat & MT6370_BSTOCP_EVT_MASK) 908171c93bSChiYuan Huang rpt_flags |= REGULATOR_ERROR_OVER_CURRENT; 918171c93bSChiYuan Huang break; 928171c93bSChiYuan Huang case MT6370_IDX_DSVPOS: 938171c93bSChiYuan Huang if (stat & MT6370_POSSCP_EVT_MASK) 948171c93bSChiYuan Huang rpt_flags |= REGULATOR_ERROR_UNDER_VOLTAGE; 958171c93bSChiYuan Huang 968171c93bSChiYuan Huang if (stat & MT6370_POSOCP_EVT_MASK) 978171c93bSChiYuan Huang rpt_flags |= REGULATOR_ERROR_OVER_CURRENT; 988171c93bSChiYuan Huang break; 998171c93bSChiYuan Huang case MT6370_IDX_DSVNEG: 1008171c93bSChiYuan Huang if (stat & MT6370_NEGSCP_EVT_MASK) 1018171c93bSChiYuan Huang rpt_flags |= REGULATOR_ERROR_UNDER_VOLTAGE; 1028171c93bSChiYuan Huang 1038171c93bSChiYuan Huang if (stat & MT6370_NEGOCP_EVT_MASK) 1048171c93bSChiYuan Huang rpt_flags |= REGULATOR_ERROR_OVER_CURRENT; 1058171c93bSChiYuan Huang break; 1068171c93bSChiYuan Huang default: 1078171c93bSChiYuan Huang if (stat & MT6370_LDOOC_EVT_MASK) 1088171c93bSChiYuan Huang rpt_flags |= REGULATOR_ERROR_OVER_CURRENT; 1098171c93bSChiYuan Huang break; 1108171c93bSChiYuan Huang } 1118171c93bSChiYuan Huang 1128171c93bSChiYuan Huang *flags = rpt_flags; 1138171c93bSChiYuan Huang return 0; 1148171c93bSChiYuan Huang } 1158171c93bSChiYuan Huang 1168171c93bSChiYuan Huang static const struct regulator_ops mt6370_dbvboost_ops = { 1178171c93bSChiYuan Huang .get_voltage_sel = regulator_get_voltage_sel_regmap, 1188171c93bSChiYuan Huang .set_voltage_sel = regulator_set_voltage_sel_regmap, 1198171c93bSChiYuan Huang .list_voltage = regulator_list_voltage_linear, 1208171c93bSChiYuan Huang .get_bypass = regulator_get_bypass_regmap, 1218171c93bSChiYuan Huang .set_bypass = regulator_set_bypass_regmap, 1228171c93bSChiYuan Huang .get_error_flags = mt6370_get_error_flags, 1238171c93bSChiYuan Huang }; 1248171c93bSChiYuan Huang 1258171c93bSChiYuan Huang static const struct regulator_ops mt6370_dbvout_ops = { 1268171c93bSChiYuan Huang .get_voltage_sel = regulator_get_voltage_sel_regmap, 1278171c93bSChiYuan Huang .set_voltage_sel = regulator_set_voltage_sel_regmap, 1288171c93bSChiYuan Huang .list_voltage = regulator_list_voltage_linear, 1298171c93bSChiYuan Huang .is_enabled = regulator_is_enabled_regmap, 1308171c93bSChiYuan Huang .enable = regulator_enable_regmap, 1318171c93bSChiYuan Huang .disable = regulator_disable_regmap, 1328171c93bSChiYuan Huang .set_active_discharge = regulator_set_active_discharge_regmap, 1338171c93bSChiYuan Huang .set_ramp_delay = regulator_set_ramp_delay_regmap, 1348171c93bSChiYuan Huang .get_error_flags = mt6370_get_error_flags, 1358171c93bSChiYuan Huang }; 1368171c93bSChiYuan Huang 1378171c93bSChiYuan Huang static const struct regulator_ops mt6370_ldo_ops = { 1388171c93bSChiYuan Huang .get_voltage_sel = regulator_get_voltage_sel_regmap, 1398171c93bSChiYuan Huang .set_voltage_sel = regulator_set_voltage_sel_regmap, 1408171c93bSChiYuan Huang .list_voltage = regulator_list_voltage_linear, 1418171c93bSChiYuan Huang .is_enabled = regulator_is_enabled_regmap, 1428171c93bSChiYuan Huang .enable = regulator_enable_regmap, 1438171c93bSChiYuan Huang .disable = regulator_disable_regmap, 1448171c93bSChiYuan Huang .set_active_discharge = regulator_set_active_discharge_regmap, 1458171c93bSChiYuan Huang .get_error_flags = mt6370_get_error_flags, 1468171c93bSChiYuan Huang }; 1478171c93bSChiYuan Huang 1488171c93bSChiYuan Huang static int mt6370_of_parse_cb(struct device_node *np, 1498171c93bSChiYuan Huang const struct regulator_desc *desc, 1508171c93bSChiYuan Huang struct regulator_config *config) 1518171c93bSChiYuan Huang { 1528171c93bSChiYuan Huang struct mt6370_priv *priv = config->driver_data; 1538171c93bSChiYuan Huang struct gpio_desc *enable_gpio; 1548171c93bSChiYuan Huang int ret; 1558171c93bSChiYuan Huang 156*4806c991SChiYuan Huang enable_gpio = fwnode_gpiod_get_index(of_fwnode_handle(np), "enable", 0, 157*4806c991SChiYuan Huang GPIOD_OUT_HIGH | 1588171c93bSChiYuan Huang GPIOD_FLAGS_BIT_NONEXCLUSIVE, 1598171c93bSChiYuan Huang desc->name); 1608171c93bSChiYuan Huang if (IS_ERR(enable_gpio)) { 1618171c93bSChiYuan Huang config->ena_gpiod = NULL; 1628171c93bSChiYuan Huang return 0; 1638171c93bSChiYuan Huang } 1648171c93bSChiYuan Huang 1658171c93bSChiYuan Huang /* 1668171c93bSChiYuan Huang * RG control by default 1678171c93bSChiYuan Huang * Only if all are using external pin, change all by external control 1688171c93bSChiYuan Huang */ 1698171c93bSChiYuan Huang if (priv->use_external_ctrl) { 1708171c93bSChiYuan Huang ret = regmap_update_bits(priv->regmap, MT6370_REG_DB_CTRL1, 1718171c93bSChiYuan Huang MT6370_DBEXTEN_MASK, 1728171c93bSChiYuan Huang MT6370_DBEXTEN_MASK); 1738171c93bSChiYuan Huang if (ret) 1748171c93bSChiYuan Huang return ret; 1758171c93bSChiYuan Huang } 1768171c93bSChiYuan Huang 1778171c93bSChiYuan Huang config->ena_gpiod = enable_gpio; 1788171c93bSChiYuan Huang priv->use_external_ctrl = true; 1798171c93bSChiYuan Huang return 0; 1808171c93bSChiYuan Huang } 1818171c93bSChiYuan Huang 1828171c93bSChiYuan Huang static const struct regulator_desc mt6370_regulator_descs[] = { 1838171c93bSChiYuan Huang { 1848171c93bSChiYuan Huang .name = "mt6370-dsv-vbst", 1858171c93bSChiYuan Huang .of_match = of_match_ptr("dsvbst"), 1868171c93bSChiYuan Huang .regulators_node = of_match_ptr("regulators"), 1878171c93bSChiYuan Huang .id = MT6370_IDX_DSVBOOST, 1888171c93bSChiYuan Huang .type = REGULATOR_VOLTAGE, 1898171c93bSChiYuan Huang .owner = THIS_MODULE, 1908171c93bSChiYuan Huang .ops = &mt6370_dbvboost_ops, 1918171c93bSChiYuan Huang .min_uV = MT6370_DBVBOOST_MINUV, 1928171c93bSChiYuan Huang .uV_step = MT6370_DBVBOOST_STPUV, 1938171c93bSChiYuan Huang .n_voltages = MT6370_DBVBOOST_N_VOLT, 1948171c93bSChiYuan Huang .vsel_reg = MT6370_REG_DB_VBST, 1958171c93bSChiYuan Huang .vsel_mask = MT6370_DBVOUT_MASK, 1968171c93bSChiYuan Huang .bypass_reg = MT6370_REG_DB_CTRL1, 1978171c93bSChiYuan Huang .bypass_mask = MT6370_DBPERD_MASK, 1988171c93bSChiYuan Huang .bypass_val_on = MT6370_DBPERD_MASK, 1998171c93bSChiYuan Huang }, 2008171c93bSChiYuan Huang { 2018171c93bSChiYuan Huang .name = "mt6370-dsv-vpos", 2028171c93bSChiYuan Huang .of_match = of_match_ptr("dsvpos"), 2038171c93bSChiYuan Huang .regulators_node = of_match_ptr("regulators"), 2048171c93bSChiYuan Huang .id = MT6370_IDX_DSVPOS, 2058171c93bSChiYuan Huang .type = REGULATOR_VOLTAGE, 2068171c93bSChiYuan Huang .owner = THIS_MODULE, 2078171c93bSChiYuan Huang .of_parse_cb = mt6370_of_parse_cb, 2088171c93bSChiYuan Huang .ops = &mt6370_dbvout_ops, 2098171c93bSChiYuan Huang .min_uV = MT6370_DBVOUT_MINUV, 2108171c93bSChiYuan Huang .uV_step = MT6370_DBVOUT_STPUV, 2118171c93bSChiYuan Huang .n_voltages = MT6370_DBVOUT_N_VOLT, 2128171c93bSChiYuan Huang .vsel_reg = MT6370_REG_DB_VPOS, 2138171c93bSChiYuan Huang .vsel_mask = MT6370_DBVOUT_MASK, 2148171c93bSChiYuan Huang .enable_reg = MT6370_REG_DB_CTRL2, 2158171c93bSChiYuan Huang .enable_mask = MT6370_DBVPOSEN_MASK, 2168171c93bSChiYuan Huang .ramp_reg = MT6370_REG_DB_VPOS, 2178171c93bSChiYuan Huang .ramp_mask = MT6370_DBSLEW_MASK, 2188171c93bSChiYuan Huang .ramp_delay_table = mt6370_vpos_ramp_tbl, 2198171c93bSChiYuan Huang .n_ramp_values = ARRAY_SIZE(mt6370_vpos_ramp_tbl), 2208171c93bSChiYuan Huang .active_discharge_reg = MT6370_REG_DB_CTRL2, 2218171c93bSChiYuan Huang .active_discharge_mask = MT6370_DBVPOSDISG_MASK, 2228171c93bSChiYuan Huang .active_discharge_on = MT6370_DBVPOSDISG_MASK, 2238171c93bSChiYuan Huang }, 2248171c93bSChiYuan Huang { 2258171c93bSChiYuan Huang .name = "mt6370-dsv-vneg", 2268171c93bSChiYuan Huang .of_match = of_match_ptr("dsvneg"), 2278171c93bSChiYuan Huang .regulators_node = of_match_ptr("regulators"), 2288171c93bSChiYuan Huang .id = MT6370_IDX_DSVNEG, 2298171c93bSChiYuan Huang .type = REGULATOR_VOLTAGE, 2308171c93bSChiYuan Huang .owner = THIS_MODULE, 2318171c93bSChiYuan Huang .of_parse_cb = mt6370_of_parse_cb, 2328171c93bSChiYuan Huang .ops = &mt6370_dbvout_ops, 2338171c93bSChiYuan Huang .min_uV = MT6370_DBVOUT_MINUV, 2348171c93bSChiYuan Huang .uV_step = MT6370_DBVOUT_STPUV, 2358171c93bSChiYuan Huang .n_voltages = MT6370_DBVOUT_N_VOLT, 2368171c93bSChiYuan Huang .vsel_reg = MT6370_REG_DB_VNEG, 2378171c93bSChiYuan Huang .vsel_mask = MT6370_DBVOUT_MASK, 2388171c93bSChiYuan Huang .enable_reg = MT6370_REG_DB_CTRL2, 2398171c93bSChiYuan Huang .enable_mask = MT6370_DBVNEGEN_MASK, 2408171c93bSChiYuan Huang .ramp_reg = MT6370_REG_DB_VNEG, 2418171c93bSChiYuan Huang .ramp_mask = MT6370_DBSLEW_MASK, 2428171c93bSChiYuan Huang .ramp_delay_table = mt6370_vneg_ramp_tbl, 2438171c93bSChiYuan Huang .n_ramp_values = ARRAY_SIZE(mt6370_vneg_ramp_tbl), 2448171c93bSChiYuan Huang .active_discharge_reg = MT6370_REG_DB_CTRL2, 2458171c93bSChiYuan Huang .active_discharge_mask = MT6370_DBVNEGDISG_MASK, 2468171c93bSChiYuan Huang .active_discharge_on = MT6370_DBVNEGDISG_MASK, 2478171c93bSChiYuan Huang }, 2488171c93bSChiYuan Huang { 2498171c93bSChiYuan Huang .name = "mt6370-vib-ldo", 2508171c93bSChiYuan Huang .of_match = of_match_ptr("vibldo"), 2518171c93bSChiYuan Huang .regulators_node = of_match_ptr("regulators"), 2528171c93bSChiYuan Huang .id = MT6370_IDX_VIBLDO, 2538171c93bSChiYuan Huang .type = REGULATOR_VOLTAGE, 2548171c93bSChiYuan Huang .owner = THIS_MODULE, 2558171c93bSChiYuan Huang .ops = &mt6370_ldo_ops, 2568171c93bSChiYuan Huang .min_uV = MT6370_LDO_MINUV, 2578171c93bSChiYuan Huang .uV_step = MT6370_LDO_STPUV, 2588171c93bSChiYuan Huang .n_voltages = MT6370_LDO_N_VOLT, 2598171c93bSChiYuan Huang .vsel_reg = MT6370_REG_LDO_VOUT, 2608171c93bSChiYuan Huang .vsel_mask = MT6370_LDOVOUT_MASK, 2618171c93bSChiYuan Huang .enable_reg = MT6370_REG_LDO_VOUT, 2628171c93bSChiYuan Huang .enable_mask = MT6370_LDOEN_MASK, 2638171c93bSChiYuan Huang .active_discharge_reg = MT6370_REG_LDO_CFG, 2648171c93bSChiYuan Huang .active_discharge_mask = MT6370_LDOOMS_MASK, 2658171c93bSChiYuan Huang .active_discharge_on = MT6370_LDOOMS_MASK, 2668171c93bSChiYuan Huang } 2678171c93bSChiYuan Huang }; 2688171c93bSChiYuan Huang 2698171c93bSChiYuan Huang static irqreturn_t mt6370_scp_handler(int irq, void *data) 2708171c93bSChiYuan Huang { 2718171c93bSChiYuan Huang struct regulator_dev *rdev = data; 2728171c93bSChiYuan Huang 2738171c93bSChiYuan Huang regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE, 2748171c93bSChiYuan Huang NULL); 2758171c93bSChiYuan Huang return IRQ_HANDLED; 2768171c93bSChiYuan Huang } 2778171c93bSChiYuan Huang 2788171c93bSChiYuan Huang static irqreturn_t mt6370_ocp_handler(int irq, void *data) 2798171c93bSChiYuan Huang { 2808171c93bSChiYuan Huang struct regulator_dev *rdev = data; 2818171c93bSChiYuan Huang 2828171c93bSChiYuan Huang regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT, NULL); 2838171c93bSChiYuan Huang return IRQ_HANDLED; 2848171c93bSChiYuan Huang } 2858171c93bSChiYuan Huang 2868171c93bSChiYuan Huang static int mt6370_regulator_irq_register(struct mt6370_priv *priv) 2878171c93bSChiYuan Huang { 2888171c93bSChiYuan Huang struct platform_device *pdev = to_platform_device(priv->dev); 2898171c93bSChiYuan Huang static const struct { 2908171c93bSChiYuan Huang const char *name; 2918171c93bSChiYuan Huang int rid; 2928171c93bSChiYuan Huang irq_handler_t handler; 2938171c93bSChiYuan Huang } mt6370_irqs[] = { 2948171c93bSChiYuan Huang { "db_vpos_scp", MT6370_IDX_DSVPOS, mt6370_scp_handler }, 2958171c93bSChiYuan Huang { "db_vneg_scp", MT6370_IDX_DSVNEG, mt6370_scp_handler }, 2968171c93bSChiYuan Huang { "db_vbst_ocp", MT6370_IDX_DSVBOOST, mt6370_ocp_handler }, 2978171c93bSChiYuan Huang { "db_vpos_ocp", MT6370_IDX_DSVPOS, mt6370_ocp_handler }, 2988171c93bSChiYuan Huang { "db_vneg_ocp", MT6370_IDX_DSVNEG, mt6370_ocp_handler }, 2998171c93bSChiYuan Huang { "ldo_oc", MT6370_IDX_VIBLDO, mt6370_ocp_handler } 3008171c93bSChiYuan Huang }; 3018171c93bSChiYuan Huang struct regulator_dev *rdev; 3028171c93bSChiYuan Huang int i, irq, ret; 3038171c93bSChiYuan Huang 3048171c93bSChiYuan Huang for (i = 0; i < ARRAY_SIZE(mt6370_irqs); i++) { 3058171c93bSChiYuan Huang irq = platform_get_irq_byname(pdev, mt6370_irqs[i].name); 3068171c93bSChiYuan Huang 3078171c93bSChiYuan Huang rdev = priv->rdev[mt6370_irqs[i].rid]; 3088171c93bSChiYuan Huang 3098171c93bSChiYuan Huang ret = devm_request_threaded_irq(priv->dev, irq, NULL, 3108171c93bSChiYuan Huang mt6370_irqs[i].handler, 0, 3118171c93bSChiYuan Huang mt6370_irqs[i].name, rdev); 3128171c93bSChiYuan Huang if (ret) { 3138171c93bSChiYuan Huang dev_err(priv->dev, 3148171c93bSChiYuan Huang "Failed to register (%d) interrupt\n", i); 3158171c93bSChiYuan Huang return ret; 3168171c93bSChiYuan Huang } 3178171c93bSChiYuan Huang } 3188171c93bSChiYuan Huang 3198171c93bSChiYuan Huang return 0; 3208171c93bSChiYuan Huang } 3218171c93bSChiYuan Huang 3228171c93bSChiYuan Huang static int mt6370_regualtor_register(struct mt6370_priv *priv) 3238171c93bSChiYuan Huang { 3248171c93bSChiYuan Huang struct regulator_dev *rdev; 3258171c93bSChiYuan Huang struct regulator_config cfg = {}; 3268171c93bSChiYuan Huang struct device *parent = priv->dev->parent; 3278171c93bSChiYuan Huang int i; 3288171c93bSChiYuan Huang 3298171c93bSChiYuan Huang cfg.dev = parent; 3308171c93bSChiYuan Huang cfg.driver_data = priv; 3318171c93bSChiYuan Huang 3328171c93bSChiYuan Huang for (i = 0; i < MT6370_MAX_IDX; i++) { 3338171c93bSChiYuan Huang rdev = devm_regulator_register(priv->dev, 3348171c93bSChiYuan Huang mt6370_regulator_descs + i, 3358171c93bSChiYuan Huang &cfg); 3368171c93bSChiYuan Huang if (IS_ERR(rdev)) { 3378171c93bSChiYuan Huang dev_err(priv->dev, 3388171c93bSChiYuan Huang "Failed to register (%d) regulator\n", i); 3398171c93bSChiYuan Huang return PTR_ERR(rdev); 3408171c93bSChiYuan Huang } 3418171c93bSChiYuan Huang 3428171c93bSChiYuan Huang priv->rdev[i] = rdev; 3438171c93bSChiYuan Huang } 3448171c93bSChiYuan Huang 3458171c93bSChiYuan Huang return 0; 3468171c93bSChiYuan Huang } 3478171c93bSChiYuan Huang 3488171c93bSChiYuan Huang static int mt6370_regulator_probe(struct platform_device *pdev) 3498171c93bSChiYuan Huang { 3508171c93bSChiYuan Huang struct mt6370_priv *priv; 3518171c93bSChiYuan Huang int ret; 3528171c93bSChiYuan Huang 3538171c93bSChiYuan Huang priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 3548171c93bSChiYuan Huang if (!priv) 3558171c93bSChiYuan Huang return -ENOMEM; 3568171c93bSChiYuan Huang 3578171c93bSChiYuan Huang priv->dev = &pdev->dev; 3588171c93bSChiYuan Huang 3598171c93bSChiYuan Huang priv->regmap = dev_get_regmap(pdev->dev.parent, NULL); 3608171c93bSChiYuan Huang if (!priv->regmap) { 3618171c93bSChiYuan Huang dev_err(&pdev->dev, "Failed to init regmap\n"); 3628171c93bSChiYuan Huang return -ENODEV; 3638171c93bSChiYuan Huang } 3648171c93bSChiYuan Huang 3658171c93bSChiYuan Huang ret = mt6370_regualtor_register(priv); 3668171c93bSChiYuan Huang if (ret) 3678171c93bSChiYuan Huang return ret; 3688171c93bSChiYuan Huang 3698171c93bSChiYuan Huang return mt6370_regulator_irq_register(priv); 3708171c93bSChiYuan Huang } 3718171c93bSChiYuan Huang 3728171c93bSChiYuan Huang static const struct platform_device_id mt6370_devid_table[] = { 3738171c93bSChiYuan Huang { "mt6370-regulator", 0}, 3748171c93bSChiYuan Huang {} 3758171c93bSChiYuan Huang }; 3768171c93bSChiYuan Huang MODULE_DEVICE_TABLE(platform, mt6370_devid_table); 3778171c93bSChiYuan Huang 3788171c93bSChiYuan Huang static struct platform_driver mt6370_regulator_driver = { 3798171c93bSChiYuan Huang .driver = { 3808171c93bSChiYuan Huang .name = "mt6370-regulator", 3818171c93bSChiYuan Huang }, 3828171c93bSChiYuan Huang .id_table = mt6370_devid_table, 3838171c93bSChiYuan Huang .probe = mt6370_regulator_probe, 3848171c93bSChiYuan Huang }; 3858171c93bSChiYuan Huang module_platform_driver(mt6370_regulator_driver); 3868171c93bSChiYuan Huang 3878171c93bSChiYuan Huang MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); 3888171c93bSChiYuan Huang MODULE_DESCRIPTION("Mediatek MT6370 Regulator Driver"); 3898171c93bSChiYuan Huang MODULE_LICENSE("GPL v2"); 390