max8649.c (6910B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Regulators driver for Maxim max8649 4 * 5 * Copyright (C) 2009-2010 Marvell International Ltd. 6 * Haojian Zhuang <haojian.zhuang@marvell.com> 7 */ 8#include <linux/kernel.h> 9#include <linux/module.h> 10#include <linux/err.h> 11#include <linux/i2c.h> 12#include <linux/platform_device.h> 13#include <linux/regulator/driver.h> 14#include <linux/slab.h> 15#include <linux/regulator/max8649.h> 16#include <linux/regmap.h> 17 18#define MAX8649_DCDC_VMIN 750000 /* uV */ 19#define MAX8649_DCDC_VMAX 1380000 /* uV */ 20#define MAX8649_DCDC_STEP 10000 /* uV */ 21#define MAX8649_VOL_MASK 0x3f 22 23/* Registers */ 24#define MAX8649_MODE0 0x00 25#define MAX8649_MODE1 0x01 26#define MAX8649_MODE2 0x02 27#define MAX8649_MODE3 0x03 28#define MAX8649_CONTROL 0x04 29#define MAX8649_SYNC 0x05 30#define MAX8649_RAMP 0x06 31#define MAX8649_CHIP_ID1 0x08 32#define MAX8649_CHIP_ID2 0x09 33 34/* Bits */ 35#define MAX8649_EN_PD (1 << 7) 36#define MAX8649_VID0_PD (1 << 6) 37#define MAX8649_VID1_PD (1 << 5) 38#define MAX8649_VID_MASK (3 << 5) 39 40#define MAX8649_FORCE_PWM (1 << 7) 41#define MAX8649_SYNC_EXTCLK (1 << 6) 42 43#define MAX8649_EXT_MASK (3 << 6) 44 45#define MAX8649_RAMP_MASK (7 << 5) 46#define MAX8649_RAMP_DOWN (1 << 1) 47 48struct max8649_regulator_info { 49 struct device *dev; 50 struct regmap *regmap; 51 52 unsigned mode:2; /* bit[1:0] = VID1, VID0 */ 53 unsigned extclk_freq:2; 54 unsigned extclk:1; 55 unsigned ramp_timing:3; 56 unsigned ramp_down:1; 57}; 58 59static int max8649_enable_time(struct regulator_dev *rdev) 60{ 61 struct max8649_regulator_info *info = rdev_get_drvdata(rdev); 62 int voltage, rate, ret; 63 unsigned int val; 64 65 /* get voltage */ 66 ret = regmap_read(info->regmap, rdev->desc->vsel_reg, &val); 67 if (ret != 0) 68 return ret; 69 val &= MAX8649_VOL_MASK; 70 voltage = regulator_list_voltage_linear(rdev, (unsigned char)val); 71 72 /* get rate */ 73 ret = regmap_read(info->regmap, MAX8649_RAMP, &val); 74 if (ret != 0) 75 return ret; 76 ret = (val & MAX8649_RAMP_MASK) >> 5; 77 rate = (32 * 1000) >> ret; /* uV/uS */ 78 79 return DIV_ROUND_UP(voltage, rate); 80} 81 82static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode) 83{ 84 struct max8649_regulator_info *info = rdev_get_drvdata(rdev); 85 86 switch (mode) { 87 case REGULATOR_MODE_FAST: 88 regmap_update_bits(info->regmap, rdev->desc->vsel_reg, 89 MAX8649_FORCE_PWM, MAX8649_FORCE_PWM); 90 break; 91 case REGULATOR_MODE_NORMAL: 92 regmap_update_bits(info->regmap, rdev->desc->vsel_reg, 93 MAX8649_FORCE_PWM, 0); 94 break; 95 default: 96 return -EINVAL; 97 } 98 return 0; 99} 100 101static unsigned int max8649_get_mode(struct regulator_dev *rdev) 102{ 103 struct max8649_regulator_info *info = rdev_get_drvdata(rdev); 104 unsigned int val; 105 int ret; 106 107 ret = regmap_read(info->regmap, rdev->desc->vsel_reg, &val); 108 if (ret != 0) 109 return ret; 110 if (val & MAX8649_FORCE_PWM) 111 return REGULATOR_MODE_FAST; 112 return REGULATOR_MODE_NORMAL; 113} 114 115static const struct regulator_ops max8649_dcdc_ops = { 116 .set_voltage_sel = regulator_set_voltage_sel_regmap, 117 .get_voltage_sel = regulator_get_voltage_sel_regmap, 118 .list_voltage = regulator_list_voltage_linear, 119 .map_voltage = regulator_map_voltage_linear, 120 .enable = regulator_enable_regmap, 121 .disable = regulator_disable_regmap, 122 .is_enabled = regulator_is_enabled_regmap, 123 .enable_time = max8649_enable_time, 124 .set_mode = max8649_set_mode, 125 .get_mode = max8649_get_mode, 126 127}; 128 129static struct regulator_desc dcdc_desc = { 130 .name = "max8649", 131 .ops = &max8649_dcdc_ops, 132 .type = REGULATOR_VOLTAGE, 133 .n_voltages = 1 << 6, 134 .owner = THIS_MODULE, 135 .vsel_mask = MAX8649_VOL_MASK, 136 .min_uV = MAX8649_DCDC_VMIN, 137 .uV_step = MAX8649_DCDC_STEP, 138 .enable_reg = MAX8649_CONTROL, 139 .enable_mask = MAX8649_EN_PD, 140 .enable_is_inverted = true, 141}; 142 143static const struct regmap_config max8649_regmap_config = { 144 .reg_bits = 8, 145 .val_bits = 8, 146}; 147 148static int max8649_regulator_probe(struct i2c_client *client, 149 const struct i2c_device_id *id) 150{ 151 struct max8649_platform_data *pdata = dev_get_platdata(&client->dev); 152 struct max8649_regulator_info *info = NULL; 153 struct regulator_dev *regulator; 154 struct regulator_config config = { }; 155 unsigned int val; 156 unsigned char data; 157 int ret; 158 159 info = devm_kzalloc(&client->dev, sizeof(struct max8649_regulator_info), 160 GFP_KERNEL); 161 if (!info) 162 return -ENOMEM; 163 164 info->regmap = devm_regmap_init_i2c(client, &max8649_regmap_config); 165 if (IS_ERR(info->regmap)) { 166 ret = PTR_ERR(info->regmap); 167 dev_err(&client->dev, "Failed to allocate register map: %d\n", ret); 168 return ret; 169 } 170 171 info->dev = &client->dev; 172 i2c_set_clientdata(client, info); 173 174 info->mode = pdata->mode; 175 switch (info->mode) { 176 case 0: 177 dcdc_desc.vsel_reg = MAX8649_MODE0; 178 break; 179 case 1: 180 dcdc_desc.vsel_reg = MAX8649_MODE1; 181 break; 182 case 2: 183 dcdc_desc.vsel_reg = MAX8649_MODE2; 184 break; 185 case 3: 186 dcdc_desc.vsel_reg = MAX8649_MODE3; 187 break; 188 default: 189 break; 190 } 191 192 ret = regmap_read(info->regmap, MAX8649_CHIP_ID1, &val); 193 if (ret != 0) { 194 dev_err(info->dev, "Failed to detect ID of MAX8649:%d\n", 195 ret); 196 return ret; 197 } 198 dev_info(info->dev, "Detected MAX8649 (ID:%x)\n", val); 199 200 /* enable VID0 & VID1 */ 201 regmap_update_bits(info->regmap, MAX8649_CONTROL, MAX8649_VID_MASK, 0); 202 203 /* enable/disable external clock synchronization */ 204 info->extclk = pdata->extclk; 205 data = (info->extclk) ? MAX8649_SYNC_EXTCLK : 0; 206 regmap_update_bits(info->regmap, dcdc_desc.vsel_reg, 207 MAX8649_SYNC_EXTCLK, data); 208 if (info->extclk) { 209 /* set external clock frequency */ 210 info->extclk_freq = pdata->extclk_freq; 211 regmap_update_bits(info->regmap, MAX8649_SYNC, MAX8649_EXT_MASK, 212 info->extclk_freq << 6); 213 } 214 215 if (pdata->ramp_timing) { 216 info->ramp_timing = pdata->ramp_timing; 217 regmap_update_bits(info->regmap, MAX8649_RAMP, MAX8649_RAMP_MASK, 218 info->ramp_timing << 5); 219 } 220 221 info->ramp_down = pdata->ramp_down; 222 if (info->ramp_down) { 223 regmap_update_bits(info->regmap, MAX8649_RAMP, MAX8649_RAMP_DOWN, 224 MAX8649_RAMP_DOWN); 225 } 226 227 config.dev = &client->dev; 228 config.init_data = pdata->regulator; 229 config.driver_data = info; 230 config.regmap = info->regmap; 231 232 regulator = devm_regulator_register(&client->dev, &dcdc_desc, 233 &config); 234 if (IS_ERR(regulator)) { 235 dev_err(info->dev, "failed to register regulator %s\n", 236 dcdc_desc.name); 237 return PTR_ERR(regulator); 238 } 239 240 return 0; 241} 242 243static const struct i2c_device_id max8649_id[] = { 244 { "max8649", 0 }, 245 { } 246}; 247MODULE_DEVICE_TABLE(i2c, max8649_id); 248 249static struct i2c_driver max8649_driver = { 250 .probe = max8649_regulator_probe, 251 .driver = { 252 .name = "max8649", 253 }, 254 .id_table = max8649_id, 255}; 256 257static int __init max8649_init(void) 258{ 259 return i2c_add_driver(&max8649_driver); 260} 261subsys_initcall(max8649_init); 262 263static void __exit max8649_exit(void) 264{ 265 i2c_del_driver(&max8649_driver); 266} 267module_exit(max8649_exit); 268 269/* Module information */ 270MODULE_DESCRIPTION("MAXIM 8649 voltage regulator driver"); 271MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 272MODULE_LICENSE("GPL");