10c47e1a8SKancyJoe // SPDX-License-Identifier: GPL-2.0-only 20c47e1a8SKancyJoe // 30c47e1a8SKancyJoe // SGMicro SGM3804 regulator Driver 40c47e1a8SKancyJoe // 50c47e1a8SKancyJoe // Copyright (C) 2025 Kancy Joe <kancy2333@outlook.com> 60c47e1a8SKancyJoe // Copyright (C) 2026 Linaro Limited 70c47e1a8SKancyJoe // Author: Neil Armstrong <neil.armstrong@linaro.org> 80c47e1a8SKancyJoe 90c47e1a8SKancyJoe #include <linux/err.h> 100c47e1a8SKancyJoe #include <linux/i2c.h> 110c47e1a8SKancyJoe #include <linux/module.h> 120c47e1a8SKancyJoe #include <linux/regmap.h> 130c47e1a8SKancyJoe #include <linux/regulator/driver.h> 140c47e1a8SKancyJoe #include <linux/regulator/of_regulator.h> 150c47e1a8SKancyJoe #include <linux/gpio/consumer.h> 160c47e1a8SKancyJoe 170c47e1a8SKancyJoe #define SGM3804_POS_RAIL_VOLTAGE_REG 0x0 180c47e1a8SKancyJoe #define SGM3804_NEG_RAIL_VOLTAGE_REG 0x1 190c47e1a8SKancyJoe #define SGM3804_RAIL_DISCHARGE_REG 0x3 200c47e1a8SKancyJoe 210c47e1a8SKancyJoe #define RAIL_VOLTAGE_MASK GENMASK(5, 0) 220c47e1a8SKancyJoe 230c47e1a8SKancyJoe #define POS_RAIL_DISCHARGE_EN BIT(1) 240c47e1a8SKancyJoe #define NEG_RAIL_DISCHARGE_EN BIT(0) 250c47e1a8SKancyJoe 260c47e1a8SKancyJoe #define RAIL_VOLTAGE_INVALID RAIL_VOLTAGE_MASK 270c47e1a8SKancyJoe #define RAIL_DISCHARGE_REG_DEFAULT (POS_RAIL_DISCHARGE_EN | NEG_RAIL_DISCHARGE_EN) 280c47e1a8SKancyJoe 290c47e1a8SKancyJoe #define SGM3804_VOLTAGES_MAX_SELECTOR 0x2f 300c47e1a8SKancyJoe 310c47e1a8SKancyJoe enum { 320c47e1a8SKancyJoe SGM3804_POS_RAIL = 0, 330c47e1a8SKancyJoe SGM3804_NEG_RAIL, 340c47e1a8SKancyJoe SGM3804_RAIL_COUNT, 350c47e1a8SKancyJoe }; 360c47e1a8SKancyJoe 370c47e1a8SKancyJoe /* 380c47e1a8SKancyJoe * The registers are only writable when the gpio is enabled, so 390c47e1a8SKancyJoe * we need to use the cache for read operations and set the regmap 400c47e1a8SKancyJoe * as cache_only when both GPIOs are down. 410c47e1a8SKancyJoe */ 420c47e1a8SKancyJoe struct sgm3804_data { 430c47e1a8SKancyJoe struct regmap *regmap; 440c47e1a8SKancyJoe /* Protects the regcache state update */ 450c47e1a8SKancyJoe struct mutex lock; 460c47e1a8SKancyJoe struct gpio_desc *gpios[SGM3804_RAIL_COUNT]; 470c47e1a8SKancyJoe }; 480c47e1a8SKancyJoe 490c47e1a8SKancyJoe static const struct linear_range sgm3804_voltages[] = { 500c47e1a8SKancyJoe REGULATOR_LINEAR_RANGE(2400000, 0x20, 0x2f, 100000), 510c47e1a8SKancyJoe REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x17, 100000), 520c47e1a8SKancyJoe }; 530c47e1a8SKancyJoe 540c47e1a8SKancyJoe /* 550c47e1a8SKancyJoe * The cache is populated with those hardware default values 560c47e1a8SKancyJoe * so the regmap_update_bits operation will use the cached 570c47e1a8SKancyJoe * value to build a new register value and write it when GPIOs 580c47e1a8SKancyJoe * are enabled. 590c47e1a8SKancyJoe */ 600c47e1a8SKancyJoe static const struct reg_default sgm3804_reg_defaults[] = { 610c47e1a8SKancyJoe { SGM3804_POS_RAIL_VOLTAGE_REG, RAIL_VOLTAGE_INVALID }, 620c47e1a8SKancyJoe { SGM3804_NEG_RAIL_VOLTAGE_REG, RAIL_VOLTAGE_INVALID }, 630c47e1a8SKancyJoe { SGM3804_RAIL_DISCHARGE_REG, RAIL_DISCHARGE_REG_DEFAULT }, 640c47e1a8SKancyJoe }; 650c47e1a8SKancyJoe 660c47e1a8SKancyJoe /* Registers are only writable */ 670c47e1a8SKancyJoe static bool sgm3804_writeable_reg(struct device *dev, unsigned int reg) 680c47e1a8SKancyJoe { 690c47e1a8SKancyJoe switch (reg) { 700c47e1a8SKancyJoe case SGM3804_POS_RAIL_VOLTAGE_REG: 710c47e1a8SKancyJoe case SGM3804_NEG_RAIL_VOLTAGE_REG: 720c47e1a8SKancyJoe case SGM3804_RAIL_DISCHARGE_REG: 730c47e1a8SKancyJoe return true; 740c47e1a8SKancyJoe default: 750c47e1a8SKancyJoe return false; 760c47e1a8SKancyJoe } 770c47e1a8SKancyJoe } 780c47e1a8SKancyJoe 790c47e1a8SKancyJoe /* 800c47e1a8SKancyJoe * Since all registers are only writeable, regmap will only read from the cache data. 810c47e1a8SKancyJoe */ 820c47e1a8SKancyJoe static bool sgm3804_readable_reg(struct device *dev, unsigned int reg) 830c47e1a8SKancyJoe { 840c47e1a8SKancyJoe return false; 850c47e1a8SKancyJoe } 860c47e1a8SKancyJoe 870c47e1a8SKancyJoe static const struct regmap_config sgm3804_regmap_config = { 880c47e1a8SKancyJoe .reg_bits = 8, 890c47e1a8SKancyJoe .val_bits = 8, 900c47e1a8SKancyJoe .max_register = 0x03, 910c47e1a8SKancyJoe .writeable_reg = sgm3804_writeable_reg, 920c47e1a8SKancyJoe .readable_reg = sgm3804_readable_reg, 930c47e1a8SKancyJoe .cache_type = REGCACHE_MAPLE, 940c47e1a8SKancyJoe .reg_defaults = sgm3804_reg_defaults, 950c47e1a8SKancyJoe .num_reg_defaults = ARRAY_SIZE(sgm3804_reg_defaults), 960c47e1a8SKancyJoe }; 970c47e1a8SKancyJoe 980c47e1a8SKancyJoe static int sgm3804_sync_regcache_state(struct sgm3804_data *ctx) 990c47e1a8SKancyJoe { 1000c47e1a8SKancyJoe guard(mutex)(&ctx->lock); 1010c47e1a8SKancyJoe 1020c47e1a8SKancyJoe /* If both GPIOs are down, IC is powered down and I2C writes will fail */ 1030c47e1a8SKancyJoe if (!gpiod_get_value_cansleep(ctx->gpios[SGM3804_POS_RAIL]) && 1040c47e1a8SKancyJoe !gpiod_get_value_cansleep(ctx->gpios[SGM3804_NEG_RAIL])) { 1050c47e1a8SKancyJoe regcache_cache_only(ctx->regmap, true); 1060c47e1a8SKancyJoe regcache_mark_dirty(ctx->regmap); 1070c47e1a8SKancyJoe } else { 1080c47e1a8SKancyJoe int ret; 1090c47e1a8SKancyJoe 1100c47e1a8SKancyJoe /* At least a GPIO is up, we can write registers */ 1110c47e1a8SKancyJoe regcache_cache_only(ctx->regmap, false); 1120c47e1a8SKancyJoe ret = regcache_sync(ctx->regmap); 1130c47e1a8SKancyJoe if (ret) { 1140c47e1a8SKancyJoe regcache_cache_only(ctx->regmap, true); 1150c47e1a8SKancyJoe return ret; 1160c47e1a8SKancyJoe } 1170c47e1a8SKancyJoe } 1180c47e1a8SKancyJoe 1190c47e1a8SKancyJoe return 0; 1200c47e1a8SKancyJoe } 1210c47e1a8SKancyJoe 1220c47e1a8SKancyJoe static int sgm3804_get_voltage_sel(struct regulator_dev *rdev) 1230c47e1a8SKancyJoe { 1240c47e1a8SKancyJoe int ret; 1250c47e1a8SKancyJoe 1260c47e1a8SKancyJoe ret = regulator_get_voltage_sel_regmap(rdev); 1270c47e1a8SKancyJoe if (ret < 0) 1280c47e1a8SKancyJoe return ret; 1290c47e1a8SKancyJoe 1300c47e1a8SKancyJoe /* Force setting a voltage on probe */ 1310c47e1a8SKancyJoe if (ret == RAIL_VOLTAGE_INVALID) 1320c47e1a8SKancyJoe return -ENOTRECOVERABLE; 1330c47e1a8SKancyJoe 1340c47e1a8SKancyJoe return ret; 1350c47e1a8SKancyJoe } 1360c47e1a8SKancyJoe 1370c47e1a8SKancyJoe static int sgm3804_enable(struct regulator_dev *rdev) 1380c47e1a8SKancyJoe { 1390c47e1a8SKancyJoe struct sgm3804_data *ctx = rdev->reg_data; 1400c47e1a8SKancyJoe int ret; 1410c47e1a8SKancyJoe 1420c47e1a8SKancyJoe ret = gpiod_set_value_cansleep(ctx->gpios[rdev_get_id(rdev)], 1); 1430c47e1a8SKancyJoe if (ret) 1440c47e1a8SKancyJoe return ret; 1450c47e1a8SKancyJoe 1460c47e1a8SKancyJoe ret = sgm3804_sync_regcache_state(ctx); 1470c47e1a8SKancyJoe if (ret) 1480c47e1a8SKancyJoe goto err; 1490c47e1a8SKancyJoe 1500c47e1a8SKancyJoe return 0; 1510c47e1a8SKancyJoe 1520c47e1a8SKancyJoe err: 1530c47e1a8SKancyJoe gpiod_set_value_cansleep(ctx->gpios[rdev_get_id(rdev)], 0); 1540c47e1a8SKancyJoe return ret; 1550c47e1a8SKancyJoe } 1560c47e1a8SKancyJoe 1570c47e1a8SKancyJoe static int sgm3804_disable(struct regulator_dev *rdev) 1580c47e1a8SKancyJoe { 1590c47e1a8SKancyJoe struct sgm3804_data *ctx = rdev->reg_data; 1600c47e1a8SKancyJoe int ret; 1610c47e1a8SKancyJoe 1620c47e1a8SKancyJoe ret = gpiod_set_value_cansleep(ctx->gpios[rdev_get_id(rdev)], 0); 1630c47e1a8SKancyJoe if (ret) 1640c47e1a8SKancyJoe return ret; 1650c47e1a8SKancyJoe 1660c47e1a8SKancyJoe return sgm3804_sync_regcache_state(ctx); 1670c47e1a8SKancyJoe } 1680c47e1a8SKancyJoe 1690c47e1a8SKancyJoe static int sgm3804_is_enabled(struct regulator_dev *rdev) 1700c47e1a8SKancyJoe { 1710c47e1a8SKancyJoe struct sgm3804_data *ctx = rdev->reg_data; 1720c47e1a8SKancyJoe 1730c47e1a8SKancyJoe return gpiod_get_value_cansleep(ctx->gpios[rdev_get_id(rdev)]); 1740c47e1a8SKancyJoe } 1750c47e1a8SKancyJoe 1760c47e1a8SKancyJoe static const struct regulator_ops sgm3804_ops = { 1770c47e1a8SKancyJoe .list_voltage = regulator_list_voltage_linear_range, 1780c47e1a8SKancyJoe .map_voltage = regulator_map_voltage_linear_range, 1790c47e1a8SKancyJoe .set_voltage_sel = regulator_set_voltage_sel_regmap, 1800c47e1a8SKancyJoe .get_voltage_sel = sgm3804_get_voltage_sel, 1810c47e1a8SKancyJoe .set_active_discharge = regulator_set_active_discharge_regmap, 1820c47e1a8SKancyJoe .enable = sgm3804_enable, 1830c47e1a8SKancyJoe .disable = sgm3804_disable, 1840c47e1a8SKancyJoe .is_enabled = sgm3804_is_enabled, 1850c47e1a8SKancyJoe }; 1860c47e1a8SKancyJoe 1870c47e1a8SKancyJoe static const struct regulator_desc sgm3804_regulator_desc[] = { 1880c47e1a8SKancyJoe /* Positive Output */ 1890c47e1a8SKancyJoe { 1900c47e1a8SKancyJoe .name = "pos", 1910c47e1a8SKancyJoe .of_match = "pos", 1920c47e1a8SKancyJoe .supply_name = "vin", 1930c47e1a8SKancyJoe .id = SGM3804_POS_RAIL, 1940c47e1a8SKancyJoe .ops = &sgm3804_ops, 1950c47e1a8SKancyJoe .type = REGULATOR_VOLTAGE, 1960c47e1a8SKancyJoe .linear_ranges = sgm3804_voltages, 1970c47e1a8SKancyJoe .n_linear_ranges = ARRAY_SIZE(sgm3804_voltages), 1980c47e1a8SKancyJoe .n_voltages = SGM3804_VOLTAGES_MAX_SELECTOR + 1, 1990c47e1a8SKancyJoe .vsel_reg = SGM3804_POS_RAIL_VOLTAGE_REG, 2000c47e1a8SKancyJoe .vsel_mask = RAIL_VOLTAGE_MASK, 2010c47e1a8SKancyJoe .active_discharge_on = POS_RAIL_DISCHARGE_EN, 2020c47e1a8SKancyJoe .active_discharge_mask = POS_RAIL_DISCHARGE_EN, 2030c47e1a8SKancyJoe .active_discharge_reg = SGM3804_RAIL_DISCHARGE_REG, 2040c47e1a8SKancyJoe .enable_time = 40000, 2050c47e1a8SKancyJoe .owner = THIS_MODULE, 2060c47e1a8SKancyJoe }, 2070c47e1a8SKancyJoe /* Negative Output */ 2080c47e1a8SKancyJoe { 2090c47e1a8SKancyJoe .name = "neg", 2100c47e1a8SKancyJoe .of_match = "neg", 2110c47e1a8SKancyJoe .supply_name = "vin", 2120c47e1a8SKancyJoe .id = SGM3804_NEG_RAIL, 2130c47e1a8SKancyJoe .ops = &sgm3804_ops, 2140c47e1a8SKancyJoe .type = REGULATOR_VOLTAGE, 2150c47e1a8SKancyJoe .linear_ranges = sgm3804_voltages, 2160c47e1a8SKancyJoe .n_linear_ranges = ARRAY_SIZE(sgm3804_voltages), 2170c47e1a8SKancyJoe .n_voltages = SGM3804_VOLTAGES_MAX_SELECTOR + 1, 2180c47e1a8SKancyJoe .vsel_reg = SGM3804_NEG_RAIL_VOLTAGE_REG, 2190c47e1a8SKancyJoe .vsel_mask = RAIL_VOLTAGE_MASK, 2200c47e1a8SKancyJoe .active_discharge_on = NEG_RAIL_DISCHARGE_EN, 2210c47e1a8SKancyJoe .active_discharge_mask = NEG_RAIL_DISCHARGE_EN, 2220c47e1a8SKancyJoe .active_discharge_reg = SGM3804_RAIL_DISCHARGE_REG, 2230c47e1a8SKancyJoe .enable_time = 40000, 2240c47e1a8SKancyJoe .owner = THIS_MODULE, 2250c47e1a8SKancyJoe }, 2260c47e1a8SKancyJoe }; 2270c47e1a8SKancyJoe 2280c47e1a8SKancyJoe static int sgm3804_probe(struct i2c_client *i2c) 2290c47e1a8SKancyJoe { 2300c47e1a8SKancyJoe struct device *dev = &i2c->dev; 2310c47e1a8SKancyJoe struct sgm3804_data *ctx; 2320c47e1a8SKancyJoe int ret, i; 2330c47e1a8SKancyJoe 2340c47e1a8SKancyJoe ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 2350c47e1a8SKancyJoe if (!ctx) 2360c47e1a8SKancyJoe return -ENOMEM; 2370c47e1a8SKancyJoe 2380c47e1a8SKancyJoe mutex_init(&ctx->lock); 2390c47e1a8SKancyJoe 2400c47e1a8SKancyJoe ctx->regmap = devm_regmap_init_i2c(i2c, &sgm3804_regmap_config); 2410c47e1a8SKancyJoe if (IS_ERR(ctx->regmap)) 2420c47e1a8SKancyJoe return dev_err_probe(dev, PTR_ERR(ctx->regmap), 2430c47e1a8SKancyJoe "failed to init regmap\n"); 2440c47e1a8SKancyJoe 2450c47e1a8SKancyJoe /* Get enable GPIOs */ 2460c47e1a8SKancyJoe for (i = 0; i < ARRAY_SIZE(sgm3804_regulator_desc); i++) { 2470c47e1a8SKancyJoe const struct regulator_desc *reg = &sgm3804_regulator_desc[i]; 2480c47e1a8SKancyJoe struct fwnode_handle *child; 2490c47e1a8SKancyJoe 2500c47e1a8SKancyJoe child = device_get_named_child_node(dev, reg->of_match); 2510c47e1a8SKancyJoe if (!child) { 2520c47e1a8SKancyJoe dev_err(dev, "missing child '%s'\n", reg->of_match); 2530c47e1a8SKancyJoe return -EINVAL; 2540c47e1a8SKancyJoe } 2550c47e1a8SKancyJoe 2560c47e1a8SKancyJoe ctx->gpios[i] = devm_fwnode_gpiod_get(dev, child, "enable", 2570c47e1a8SKancyJoe GPIOD_ASIS, reg->name); 2580c47e1a8SKancyJoe fwnode_handle_put(child); 2590c47e1a8SKancyJoe if (IS_ERR(ctx->gpios[i])) 2600c47e1a8SKancyJoe return dev_err_probe(dev, PTR_ERR(ctx->gpios[i]), 2610c47e1a8SKancyJoe "failed to get '%s' enable GPIO\n", 2620c47e1a8SKancyJoe reg->name); 2630c47e1a8SKancyJoe } 2640c47e1a8SKancyJoe 2650c47e1a8SKancyJoe ret = sgm3804_sync_regcache_state(ctx); 2660c47e1a8SKancyJoe if (ret) 2670c47e1a8SKancyJoe return ret; 2680c47e1a8SKancyJoe 2690c47e1a8SKancyJoe for (i = 0; i < ARRAY_SIZE(sgm3804_regulator_desc); i++) { 2700c47e1a8SKancyJoe struct regulator_config config = { }; 2710c47e1a8SKancyJoe struct regulator_dev *rdev; 2720c47e1a8SKancyJoe 2730c47e1a8SKancyJoe config.dev = dev; 2740c47e1a8SKancyJoe config.regmap = ctx->regmap; 2750c47e1a8SKancyJoe config.of_node = dev_of_node(dev); 2760c47e1a8SKancyJoe config.driver_data = ctx; 2770c47e1a8SKancyJoe rdev = devm_regulator_register(dev, &sgm3804_regulator_desc[i], 2780c47e1a8SKancyJoe &config); 2790c47e1a8SKancyJoe if (IS_ERR(rdev)) 2800c47e1a8SKancyJoe return dev_err_probe(dev, PTR_ERR(rdev), 2810c47e1a8SKancyJoe "failed to register regulator %d\n", i); 2820c47e1a8SKancyJoe } 2830c47e1a8SKancyJoe 2840c47e1a8SKancyJoe return 0; 2850c47e1a8SKancyJoe } 2860c47e1a8SKancyJoe 2870c47e1a8SKancyJoe static const struct i2c_device_id sgm3804_id[] = { 288*8e74b2dbSUwe Kleine-König (The Capable Hub) { .name = "sgm3804" }, 2890c47e1a8SKancyJoe { } 2900c47e1a8SKancyJoe }; 2910c47e1a8SKancyJoe MODULE_DEVICE_TABLE(i2c, sgm3804_id); 2920c47e1a8SKancyJoe 2930c47e1a8SKancyJoe static const struct of_device_id sgm3804_of_match[] = { 2940c47e1a8SKancyJoe { .compatible = "sgmicro,sgm3804" }, 2950c47e1a8SKancyJoe { } 2960c47e1a8SKancyJoe }; 2970c47e1a8SKancyJoe MODULE_DEVICE_TABLE(of, sgm3804_of_match); 2980c47e1a8SKancyJoe 2990c47e1a8SKancyJoe static struct i2c_driver sgm3804_regulator_driver = { 3000c47e1a8SKancyJoe .driver = { 3010c47e1a8SKancyJoe .name = "sgm3804", 3020c47e1a8SKancyJoe .probe_type = PROBE_PREFER_ASYNCHRONOUS, 3030c47e1a8SKancyJoe .of_match_table = sgm3804_of_match, 3040c47e1a8SKancyJoe }, 3050c47e1a8SKancyJoe .probe = sgm3804_probe, 3060c47e1a8SKancyJoe .id_table = sgm3804_id, 3070c47e1a8SKancyJoe }; 3080c47e1a8SKancyJoe 3090c47e1a8SKancyJoe module_i2c_driver(sgm3804_regulator_driver); 3100c47e1a8SKancyJoe 3110c47e1a8SKancyJoe MODULE_DESCRIPTION("SGMicro SGM3804 regulator Driver"); 3120c47e1a8SKancyJoe MODULE_AUTHOR("Kancy Joe <kancy2333@outlook.com>"); 3130c47e1a8SKancyJoe MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>"); 3140c47e1a8SKancyJoe MODULE_LICENSE("GPL"); 315