diff options
Diffstat (limited to 'drivers/regulator/max1586.c')
| -rw-r--r-- | drivers/regulator/max1586.c | 186 |
1 files changed, 77 insertions, 109 deletions
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 559cfa271a4..d23d0577754 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -44,10 +44,19 @@ struct max1586_data { unsigned int min_uV; unsigned int max_uV; - struct regulator_dev *rdev[0]; + unsigned int v3_curr_sel; + unsigned int v6_curr_sel; }; /* + * V6 voltage + * On I2C bus, sending a "x" byte to the max1586 means : + * set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3) + * As regulator framework doesn't accept voltages to be 0V, we use 1uV. + */ +static const unsigned int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 }; + +/* * V3 voltage * On I2C bus, sending a "x" byte to the max1586 means : * set V3 to 0.700V + (x & 0x1f) * 0.025V @@ -55,96 +64,60 @@ struct max1586_data { * R24 and R25=100kOhm as described in the data sheet. * The gain is approximately: 1 + R24/R25 + R24/185.5kOhm */ -static int max1586_v3_calc_voltage(struct max1586_data *max1586, - unsigned selector) +static int max1586_v3_get_voltage_sel(struct regulator_dev *rdev) { - unsigned range_uV = max1586->max_uV - max1586->min_uV; + struct max1586_data *max1586 = rdev_get_drvdata(rdev); - return max1586->min_uV + (selector * range_uV / MAX1586_V3_MAX_VSEL); + return max1586->v3_curr_sel; } -static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV) +static int max1586_v3_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) { struct max1586_data *max1586 = rdev_get_drvdata(rdev); struct i2c_client *client = max1586->client; - unsigned range_uV = max1586->max_uV - max1586->min_uV; - unsigned selector; + int ret; u8 v3_prog; - if (min_uV > max1586->max_uV || max_uV < max1586->min_uV) - return -EINVAL; - if (min_uV < max1586->min_uV) - min_uV = max1586->min_uV; - - selector = ((min_uV - max1586->min_uV) * MAX1586_V3_MAX_VSEL + - range_uV - 1) / range_uV; - if (max1586_v3_calc_voltage(max1586, selector) > max_uV) - return -EINVAL; - dev_dbg(&client->dev, "changing voltage v3 to %dmv\n", - max1586_v3_calc_voltage(max1586, selector) / 1000); + regulator_list_voltage_linear(rdev, selector) / 1000); v3_prog = I2C_V3_SELECT | (u8) selector; - return i2c_smbus_write_byte(client, v3_prog); -} + ret = i2c_smbus_write_byte(client, v3_prog); + if (ret) + return ret; -static int max1586_v3_list(struct regulator_dev *rdev, unsigned selector) -{ - struct max1586_data *max1586 = rdev_get_drvdata(rdev); + max1586->v3_curr_sel = selector; - if (selector > MAX1586_V3_MAX_VSEL) - return -EINVAL; - return max1586_v3_calc_voltage(max1586, selector); + return 0; } -/* - * V6 voltage - * On I2C bus, sending a "x" byte to the max1586 means : - * set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3) - * As regulator framework doesn't accept voltages to be 0V, we use 1uV. - */ -static int max1586_v6_calc_voltage(unsigned selector) +static int max1586_v6_get_voltage_sel(struct regulator_dev *rdev) { - static int voltages_uv[] = { 1, 1800000, 2500000, 3000000 }; + struct max1586_data *max1586 = rdev_get_drvdata(rdev); - return voltages_uv[selector]; + return max1586->v6_curr_sel; } -static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV) +static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) { - struct i2c_client *client = rdev_get_drvdata(rdev); - unsigned selector; + struct max1586_data *max1586 = rdev_get_drvdata(rdev); + struct i2c_client *client = max1586->client; u8 v6_prog; - - if (min_uV < MAX1586_V6_MIN_UV || min_uV > MAX1586_V6_MAX_UV) - return -EINVAL; - if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV) - return -EINVAL; - - if (min_uV < 1800000) - selector = 0; - else if (min_uV < 2500000) - selector = 1; - else if (min_uV < 3000000) - selector = 2; - else if (min_uV >= 3000000) - selector = 3; - - if (max1586_v6_calc_voltage(selector) > max_uV) - return -EINVAL; + int ret; dev_dbg(&client->dev, "changing voltage v6 to %dmv\n", - max1586_v6_calc_voltage(selector) / 1000); + rdev->desc->volt_table[selector] / 1000); v6_prog = I2C_V6_SELECT | (u8) selector; - return i2c_smbus_write_byte(client, v6_prog); -} + ret = i2c_smbus_write_byte(client, v6_prog); + if (ret) + return ret; -static int max1586_v6_list(struct regulator_dev *rdev, unsigned selector) -{ - if (selector > MAX1586_V6_MAX_VSEL) - return -EINVAL; - return max1586_v6_calc_voltage(selector); + max1586->v6_curr_sel = selector; + + return 0; } /* @@ -152,13 +125,16 @@ static int max1586_v6_list(struct regulator_dev *rdev, unsigned selector) * the set up value. */ static struct regulator_ops max1586_v3_ops = { - .set_voltage = max1586_v3_set, - .list_voltage = max1586_v3_list, + .get_voltage_sel = max1586_v3_get_voltage_sel, + .set_voltage_sel = max1586_v3_set_voltage_sel, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, }; static struct regulator_ops max1586_v6_ops = { - .set_voltage = max1586_v6_set, - .list_voltage = max1586_v6_list, + .get_voltage_sel = max1586_v6_get_voltage_sel, + .set_voltage_sel = max1586_v6_set_voltage_sel, + .list_voltage = regulator_list_voltage_table, }; static struct regulator_desc max1586_reg[] = { @@ -176,77 +152,70 @@ static struct regulator_desc max1586_reg[] = { .ops = &max1586_v6_ops, .type = REGULATOR_VOLTAGE, .n_voltages = MAX1586_V6_MAX_VSEL + 1, + .volt_table = v6_voltages_uv, .owner = THIS_MODULE, }, }; -static int __devinit max1586_pmic_probe(struct i2c_client *client, +static int max1586_pmic_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { - struct regulator_dev **rdev; - struct max1586_platform_data *pdata = client->dev.platform_data; + struct max1586_platform_data *pdata = dev_get_platdata(&client->dev); + struct regulator_config config = { }; struct max1586_data *max1586; - int i, id, ret = -ENOMEM; + int i, id; - max1586 = kzalloc(sizeof(struct max1586_data) + - sizeof(struct regulator_dev *) * (MAX1586_V6 + 1), + max1586 = devm_kzalloc(&client->dev, sizeof(struct max1586_data), GFP_KERNEL); if (!max1586) - goto out; + return -ENOMEM; max1586->client = client; - if (!pdata->v3_gain) { - ret = -EINVAL; - goto out_unmap; - } + if (!pdata->v3_gain) + return -EINVAL; + max1586->min_uV = MAX1586_V3_MIN_UV / 1000 * pdata->v3_gain / 1000; max1586->max_uV = MAX1586_V3_MAX_UV / 1000 * pdata->v3_gain / 1000; - rdev = max1586->rdev; + /* Set curr_sel to default voltage on power-up */ + max1586->v3_curr_sel = 24; /* 1.3V */ + max1586->v6_curr_sel = 0; + for (i = 0; i < pdata->num_subdevs && i <= MAX1586_V6; i++) { + struct regulator_dev *rdev; + id = pdata->subdevs[i].id; if (!pdata->subdevs[i].platform_data) continue; if (id < MAX1586_V3 || id > MAX1586_V6) { dev_err(&client->dev, "invalid regulator id %d\n", id); - goto err; + return -EINVAL; + } + + if (id == MAX1586_V3) { + max1586_reg[id].min_uV = max1586->min_uV; + max1586_reg[id].uV_step = + (max1586->max_uV - max1586->min_uV) / + MAX1586_V3_MAX_VSEL; } - rdev[i] = regulator_register(&max1586_reg[id], &client->dev, - pdata->subdevs[i].platform_data, - max1586); - if (IS_ERR(rdev[i])) { - ret = PTR_ERR(rdev[i]); + + config.dev = &client->dev; + config.init_data = pdata->subdevs[i].platform_data; + config.driver_data = max1586; + + rdev = devm_regulator_register(&client->dev, + &max1586_reg[id], &config); + if (IS_ERR(rdev)) { dev_err(&client->dev, "failed to register %s\n", max1586_reg[id].name); - goto err; + return PTR_ERR(rdev); } } i2c_set_clientdata(client, max1586); dev_info(&client->dev, "Maxim 1586 regulator driver loaded\n"); return 0; - -err: - while (--i >= 0) - regulator_unregister(rdev[i]); -out_unmap: - kfree(max1586); -out: - return ret; -} - -static int __devexit max1586_pmic_remove(struct i2c_client *client) -{ - struct max1586_data *max1586 = i2c_get_clientdata(client); - int i; - - for (i = 0; i <= MAX1586_V6; i++) - if (max1586->rdev[i]) - regulator_unregister(max1586->rdev[i]); - kfree(max1586); - - return 0; } static const struct i2c_device_id max1586_id[] = { @@ -257,7 +226,6 @@ MODULE_DEVICE_TABLE(i2c, max1586_id); static struct i2c_driver max1586_pmic_driver = { .probe = max1586_pmic_probe, - .remove = __devexit_p(max1586_pmic_remove), .driver = { .name = "max1586", .owner = THIS_MODULE, |
