1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // SY8827N regulator driver 4 // 5 // Copyright (C) 2020 Synaptics Incorporated 6 // 7 // Author: Jisheng Zhang <jszhang@kernel.org> 8 9 #include <linux/gpio/consumer.h> 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 SY8827N_VSEL0 0 18 #define SY8827N_BUCK_EN (1 << 7) 19 #define SY8827N_MODE (1 << 6) 20 #define SY8827N_VSEL1 1 21 #define SY8827N_CTRL 2 22 #define SY8827N_ID1 3 23 #define SY8827N_ID2 4 24 #define SY8827N_PGOOD 5 25 #define SY8827N_MAX (SY8827N_PGOOD + 1) 26 27 #define SY8827N_NVOLTAGES 64 28 #define SY8827N_VSELMIN 600000 29 #define SY8827N_VSELSTEP 12500 30 31 struct sy8827n_device_info { 32 struct device *dev; 33 struct regulator_desc desc; 34 struct regulator_init_data *regulator; 35 struct gpio_desc *en_gpio; 36 unsigned int vsel_reg; 37 }; 38 39 static int sy8827n_set_mode(struct regulator_dev *rdev, unsigned int mode) 40 { 41 struct sy8827n_device_info *di = rdev_get_drvdata(rdev); 42 43 switch (mode) { 44 case REGULATOR_MODE_FAST: 45 regmap_update_bits(rdev->regmap, di->vsel_reg, 46 SY8827N_MODE, SY8827N_MODE); 47 break; 48 case REGULATOR_MODE_NORMAL: 49 regmap_update_bits(rdev->regmap, di->vsel_reg, 50 SY8827N_MODE, 0); 51 break; 52 default: 53 return -EINVAL; 54 } 55 return 0; 56 } 57 58 static unsigned int sy8827n_get_mode(struct regulator_dev *rdev) 59 { 60 struct sy8827n_device_info *di = rdev_get_drvdata(rdev); 61 u32 val; 62 int ret = 0; 63 64 ret = regmap_read(rdev->regmap, di->vsel_reg, &val); 65 if (ret < 0) 66 return ret; 67 if (val & SY8827N_MODE) 68 return REGULATOR_MODE_FAST; 69 else 70 return REGULATOR_MODE_NORMAL; 71 } 72 73 static const struct regulator_ops sy8827n_regulator_ops = { 74 .set_voltage_sel = regulator_set_voltage_sel_regmap, 75 .get_voltage_sel = regulator_get_voltage_sel_regmap, 76 .set_voltage_time_sel = regulator_set_voltage_time_sel, 77 .map_voltage = regulator_map_voltage_linear, 78 .list_voltage = regulator_list_voltage_linear, 79 .enable = regulator_enable_regmap, 80 .disable = regulator_disable_regmap, 81 .is_enabled = regulator_is_enabled_regmap, 82 .set_mode = sy8827n_set_mode, 83 .get_mode = sy8827n_get_mode, 84 }; 85 86 static int sy8827n_regulator_register(struct sy8827n_device_info *di, 87 struct regulator_config *config) 88 { 89 struct regulator_desc *rdesc = &di->desc; 90 struct regulator_dev *rdev; 91 92 rdesc->name = "sy8827n-reg"; 93 rdesc->supply_name = "vin"; 94 rdesc->ops = &sy8827n_regulator_ops; 95 rdesc->type = REGULATOR_VOLTAGE; 96 rdesc->n_voltages = SY8827N_NVOLTAGES; 97 rdesc->enable_reg = di->vsel_reg; 98 rdesc->enable_mask = SY8827N_BUCK_EN; 99 rdesc->min_uV = SY8827N_VSELMIN; 100 rdesc->uV_step = SY8827N_VSELSTEP; 101 rdesc->vsel_reg = di->vsel_reg; 102 rdesc->vsel_mask = rdesc->n_voltages - 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 bool sy8827n_volatile_reg(struct device *dev, unsigned int reg) 110 { 111 if (reg == SY8827N_PGOOD) 112 return true; 113 return false; 114 } 115 116 static const struct regmap_config sy8827n_regmap_config = { 117 .reg_bits = 8, 118 .val_bits = 8, 119 .volatile_reg = sy8827n_volatile_reg, 120 .num_reg_defaults_raw = SY8827N_MAX, 121 .cache_type = REGCACHE_FLAT, 122 }; 123 124 static int sy8827n_i2c_probe(struct i2c_client *client) 125 { 126 struct device *dev = &client->dev; 127 struct device_node *np = dev->of_node; 128 struct sy8827n_device_info *di; 129 struct regulator_config config = { }; 130 struct regmap *regmap; 131 int ret; 132 133 di = devm_kzalloc(dev, sizeof(struct sy8827n_device_info), GFP_KERNEL); 134 if (!di) 135 return -ENOMEM; 136 137 di->regulator = of_get_regulator_init_data(dev, np, &di->desc); 138 if (!di->regulator) { 139 dev_err(dev, "Platform data not found!\n"); 140 return -EINVAL; 141 } 142 143 di->en_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH); 144 if (IS_ERR(di->en_gpio)) 145 return PTR_ERR(di->en_gpio); 146 147 if (of_property_read_bool(np, "silergy,vsel-state-high")) 148 di->vsel_reg = SY8827N_VSEL1; 149 else 150 di->vsel_reg = SY8827N_VSEL0; 151 152 di->dev = dev; 153 154 regmap = devm_regmap_init_i2c(client, &sy8827n_regmap_config); 155 if (IS_ERR(regmap)) { 156 dev_err(dev, "Failed to allocate regmap!\n"); 157 return PTR_ERR(regmap); 158 } 159 i2c_set_clientdata(client, di); 160 161 config.dev = di->dev; 162 config.init_data = di->regulator; 163 config.regmap = regmap; 164 config.driver_data = di; 165 config.of_node = np; 166 167 ret = sy8827n_regulator_register(di, &config); 168 if (ret < 0) 169 dev_err(dev, "Failed to register regulator!\n"); 170 return ret; 171 } 172 173 static const struct of_device_id sy8827n_dt_ids[] = { 174 { 175 .compatible = "silergy,sy8827n", 176 }, 177 { } 178 }; 179 MODULE_DEVICE_TABLE(of, sy8827n_dt_ids); 180 181 static const struct i2c_device_id sy8827n_id[] = { 182 { "sy8827n", }, 183 { }, 184 }; 185 MODULE_DEVICE_TABLE(i2c, sy8827n_id); 186 187 static struct i2c_driver sy8827n_regulator_driver = { 188 .driver = { 189 .name = "sy8827n-regulator", 190 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 191 .of_match_table = sy8827n_dt_ids, 192 }, 193 .probe = sy8827n_i2c_probe, 194 .id_table = sy8827n_id, 195 }; 196 module_i2c_driver(sy8827n_regulator_driver); 197 198 MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>"); 199 MODULE_DESCRIPTION("SY8827N regulator driver"); 200 MODULE_LICENSE("GPL v2"); 201