1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * SY8824C/SY8824E regulator driver 4 * 5 * Copyright (C) 2019 Synaptics Incorporated 6 * 7 * Author: Jisheng Zhang <jszhang@kernel.org> 8 */ 9 10 #include <linux/module.h> 11 #include <linux/i2c.h> 12 #include <linux/of_device.h> 13 #include <linux/regmap.h> 14 #include <linux/regulator/driver.h> 15 #include <linux/regulator/of_regulator.h> 16 17 #define BUCK_EN (1 << 7) 18 #define MODE (1 << 6) 19 20 struct sy8824_config { 21 /* registers */ 22 unsigned int vol_reg; 23 unsigned int mode_reg; 24 unsigned int enable_reg; 25 /* Voltage range and step(linear) */ 26 unsigned int vsel_min; 27 unsigned int vsel_step; 28 unsigned int vsel_count; 29 }; 30 31 struct sy8824_device_info { 32 struct device *dev; 33 struct regulator_desc desc; 34 struct regulator_init_data *regulator; 35 const struct sy8824_config *cfg; 36 }; 37 38 static int sy8824_set_mode(struct regulator_dev *rdev, unsigned int mode) 39 { 40 struct sy8824_device_info *di = rdev_get_drvdata(rdev); 41 const struct sy8824_config *cfg = di->cfg; 42 43 switch (mode) { 44 case REGULATOR_MODE_FAST: 45 regmap_update_bits(rdev->regmap, cfg->mode_reg, MODE, MODE); 46 break; 47 case REGULATOR_MODE_NORMAL: 48 regmap_update_bits(rdev->regmap, cfg->mode_reg, MODE, 0); 49 break; 50 default: 51 return -EINVAL; 52 } 53 return 0; 54 } 55 56 static unsigned int sy8824_get_mode(struct regulator_dev *rdev) 57 { 58 struct sy8824_device_info *di = rdev_get_drvdata(rdev); 59 const struct sy8824_config *cfg = di->cfg; 60 u32 val; 61 int ret = 0; 62 63 ret = regmap_read(rdev->regmap, cfg->mode_reg, &val); 64 if (ret < 0) 65 return ret; 66 if (val & MODE) 67 return REGULATOR_MODE_FAST; 68 else 69 return REGULATOR_MODE_NORMAL; 70 } 71 72 static const struct regulator_ops sy8824_regulator_ops = { 73 .set_voltage_sel = regulator_set_voltage_sel_regmap, 74 .get_voltage_sel = regulator_get_voltage_sel_regmap, 75 .set_voltage_time_sel = regulator_set_voltage_time_sel, 76 .map_voltage = regulator_map_voltage_linear, 77 .list_voltage = regulator_list_voltage_linear, 78 .enable = regulator_enable_regmap, 79 .disable = regulator_disable_regmap, 80 .is_enabled = regulator_is_enabled_regmap, 81 .set_mode = sy8824_set_mode, 82 .get_mode = sy8824_get_mode, 83 }; 84 85 static int sy8824_regulator_register(struct sy8824_device_info *di, 86 struct regulator_config *config) 87 { 88 struct regulator_desc *rdesc = &di->desc; 89 const struct sy8824_config *cfg = di->cfg; 90 struct regulator_dev *rdev; 91 92 rdesc->name = "sy8824-reg"; 93 rdesc->supply_name = "vin"; 94 rdesc->ops = &sy8824_regulator_ops; 95 rdesc->type = REGULATOR_VOLTAGE; 96 rdesc->n_voltages = cfg->vsel_count; 97 rdesc->enable_reg = cfg->enable_reg; 98 rdesc->enable_mask = BUCK_EN; 99 rdesc->min_uV = cfg->vsel_min; 100 rdesc->uV_step = cfg->vsel_step; 101 rdesc->vsel_reg = cfg->vol_reg; 102 rdesc->vsel_mask = cfg->vsel_count - 1; 103 rdesc->owner = THIS_MODULE; 104 105 rdev = devm_regulator_register(di->dev, &di->desc, config); 106 return PTR_ERR_OR_ZERO(rdev); 107 } 108 109 static const struct regmap_config sy8824_regmap_config = { 110 .reg_bits = 8, 111 .val_bits = 8, 112 }; 113 114 static int sy8824_i2c_probe(struct i2c_client *client, 115 const struct i2c_device_id *id) 116 { 117 struct device *dev = &client->dev; 118 struct device_node *np = dev->of_node; 119 struct sy8824_device_info *di; 120 struct regulator_config config = { }; 121 struct regmap *regmap; 122 int ret; 123 124 di = devm_kzalloc(dev, sizeof(struct sy8824_device_info), GFP_KERNEL); 125 if (!di) 126 return -ENOMEM; 127 128 di->regulator = of_get_regulator_init_data(dev, np, &di->desc); 129 if (!di->regulator) { 130 dev_err(dev, "Platform data not found!\n"); 131 return -EINVAL; 132 } 133 134 di->dev = dev; 135 di->cfg = of_device_get_match_data(dev); 136 137 regmap = devm_regmap_init_i2c(client, &sy8824_regmap_config); 138 if (IS_ERR(regmap)) { 139 dev_err(dev, "Failed to allocate regmap!\n"); 140 return PTR_ERR(regmap); 141 } 142 i2c_set_clientdata(client, di); 143 144 config.dev = di->dev; 145 config.init_data = di->regulator; 146 config.regmap = regmap; 147 config.driver_data = di; 148 config.of_node = np; 149 150 ret = sy8824_regulator_register(di, &config); 151 if (ret < 0) 152 dev_err(dev, "Failed to register regulator!\n"); 153 return ret; 154 } 155 156 static const struct sy8824_config sy8824c_cfg = { 157 .vol_reg = 0x00, 158 .mode_reg = 0x00, 159 .enable_reg = 0x00, 160 .vsel_min = 762500, 161 .vsel_step = 12500, 162 .vsel_count = 64, 163 }; 164 165 static const struct sy8824_config sy8824e_cfg = { 166 .vol_reg = 0x00, 167 .mode_reg = 0x00, 168 .enable_reg = 0x00, 169 .vsel_min = 700000, 170 .vsel_step = 12500, 171 .vsel_count = 64, 172 }; 173 174 static const struct sy8824_config sy20276_cfg = { 175 .vol_reg = 0x00, 176 .mode_reg = 0x01, 177 .enable_reg = 0x01, 178 .vsel_min = 600000, 179 .vsel_step = 10000, 180 .vsel_count = 128, 181 }; 182 183 static const struct of_device_id sy8824_dt_ids[] = { 184 { 185 .compatible = "silergy,sy8824c", 186 .data = &sy8824c_cfg 187 }, 188 { 189 .compatible = "silergy,sy8824e", 190 .data = &sy8824e_cfg 191 }, 192 { 193 .compatible = "silergy,sy20276", 194 .data = &sy20276_cfg 195 }, 196 { } 197 }; 198 MODULE_DEVICE_TABLE(of, sy8824_dt_ids); 199 200 static const struct i2c_device_id sy8824_id[] = { 201 { "sy8824", }, 202 { }, 203 }; 204 MODULE_DEVICE_TABLE(i2c, sy8824_id); 205 206 static struct i2c_driver sy8824_regulator_driver = { 207 .driver = { 208 .name = "sy8824-regulator", 209 .of_match_table = of_match_ptr(sy8824_dt_ids), 210 }, 211 .probe = sy8824_i2c_probe, 212 .id_table = sy8824_id, 213 }; 214 module_i2c_driver(sy8824_regulator_driver); 215 216 MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>"); 217 MODULE_DESCRIPTION("SY8824C/SY8824E regulator driver"); 218 MODULE_LICENSE("GPL v2"); 219