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