/* * max15569-regulator.c -- max15569 regulator driver * * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include /* Register definitions */ #define MAX15569_VOUTMAX_REG 0x2 #define MAX15569_STATUS_REG 0x4 #define MAX15569_MASK_REG 0x5 #define MAX15569_SLEW_RATE_REG 0x6 #define MAX15569_SETVOUT_REG 0x7 #define MAX15569_IMON_REG 0x8 #define MAX15569_MAX_REG 0x9 #define MAX15569_MIN_VOLTAGE 500000 #define MAX15569_MAX_VOLTAGE 1520000 #define MAX15569_VOLTAGE_STEP 10000 #define MAX15569_MAX_SEL 0x7F #define MAX15569_MAX_SLEW_RATE 44 #define MAX15569_MIN_SLEW_RATE 1 #define MAX15569_STATUS_VRHOT 0x20 #define MAX15569_STATUS_UV 0x10 #define MAX15569_STATUS_OV 0x08 #define MAX15569_STATUS_OC 0x4 #define MAX15569_STATUS_VMERR 0x2 #define MAX15569_STATUS_INT 0x1 struct { unsigned char soft_start_slew_rate; unsigned char regular_slew_rate; } max15569_slewrate_table[] = { {-1, -1 }, { 9, 9}, { 9, 9}, { 9, 9}, { 9, 9}, { 0x19, 0x19}, { 0x19, 0x19}, { 0x23, 0x23}, { 3, 3}, { 3, 3}, { 0x17, 0x1e}, { 0x17, 0x1e}, { 0x20, 0x20}, { 0x20, 0x20}, { 0x20, 0x20}, { 0x20, 0x20}, { 0x20, 0x20}, { 0x0, 0x0}, { 0x0, 0x0}, { 0x0, 0x0}, { 0x0, 0x0}, { 0x10, 0x10}, { 0x10, 0x10}, { 0x10, 0x10}, { 0x10, 0x10}, { 0x25, 0x25}, { 0x25, 0x25}, { 0x25, 0x25}, { 0x25, 0x25}, { 0x25, 0x25}, { 0x25, 0x25}, { 0x25, 0x25}, { 0x25, 0x25}, { 0x5, 0x5}, { 0x5, 0x5}, { 0x5, 0x5}, { 0x5, 0x5}, { 0x5, 0x5}, { 0x5, 0x5}, { 0x5, 0x5}, { 0x5, 0x5}, { 0x15, 0x15}, { 0x15, 0x15}, { 0x15, 0x15}, { 0x15, 0x15}, }; /* MAX15569 chip information */ struct max15569_chip { struct device *dev; struct regulator_desc desc; struct regulator_dev *rdev; struct regmap *regmap; bool output_enabled; unsigned int change_mv_per_us; }; static int max15569_get_voltage_sel(struct regulator_dev *rdev) { struct max15569_chip *max = rdev_get_drvdata(rdev); unsigned int data; int ret; unsigned int reg = MAX15569_SETVOUT_REG; ret = regmap_read(max->regmap, reg, &data); if (ret < 0) { dev_err(max->dev, "reg read failed, err %d\n", ret); return ret; } return data; } static int max15569_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { struct max15569_chip *max = rdev_get_drvdata(rdev); unsigned int reg = MAX15569_SETVOUT_REG; int vsel; int ret; if ((max_uV < min_uV) || (max_uV < MAX15569_MIN_VOLTAGE) || (min_uV > MAX15569_MAX_VOLTAGE)) return -EINVAL; vsel = DIV_ROUND_UP(min_uV - MAX15569_MIN_VOLTAGE, MAX15569_VOLTAGE_STEP) + 0x1; if (selector) *selector = vsel; ret = regmap_write(max->regmap, reg, vsel); if (ret < 0) dev_err(max->dev, "reg write failed, err %d\n", ret); return ret; } static int max15569_list_voltage(struct regulator_dev *rdev, unsigned selector) { if (selector > MAX15569_MAX_SEL) return -EINVAL; return MAX15569_MIN_VOLTAGE + (selector - 0x1) * MAX15569_VOLTAGE_STEP; } static int max15569_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector, unsigned int new_selector) { struct max15569_chip *max = rdev_get_drvdata(rdev); int change_mv_per_us = max->change_mv_per_us; if (change_mv_per_us > MAX15569_MAX_SLEW_RATE) change_mv_per_us = MAX15569_MAX_SLEW_RATE; if (change_mv_per_us < MAX15569_MIN_SLEW_RATE) change_mv_per_us = MAX15569_MIN_SLEW_RATE; return max->output_enabled ? max15569_slewrate_table[max->change_mv_per_us].regular_slew_rate : max15569_slewrate_table[max->change_mv_per_us].soft_start_slew_rate; } static int max15569_set_control_mode(struct regulator_dev *rdev, unsigned int mode) { if (mode != REGULATOR_CONTROL_MODE_I2C) return -EINVAL; return 0; } static unsigned int max15569_get_control_mode(struct regulator_dev *rdev) { return REGULATOR_CONTROL_MODE_I2C; } static struct regulator_ops max15569_ops = { .get_voltage_sel = max15569_get_voltage_sel, .set_voltage = max15569_set_voltage, .list_voltage = max15569_list_voltage, .set_voltage_time_sel = max15569_set_voltage_time_sel, .set_control_mode = max15569_set_control_mode, .get_control_mode = max15569_get_control_mode, }; static int max15569_init(struct max15569_chip *max15569, struct max15569_regulator_platform_data *pdata) { int ret; int vsel; unsigned int status; max15569->output_enabled = true; /* Set slew rate */ /* max15569->change_mv_per_us = min(44,max(1, pdata->slew_rate_mv_per_us)); */ if (max15569->change_mv_per_us > 44) max15569->change_mv_per_us = 44; if (max15569->change_mv_per_us < 1) max15569->change_mv_per_us = 1; vsel = max15569_slewrate_table[max15569->change_mv_per_us].regular_slew_rate; ret = regmap_write(max15569->regmap, MAX15569_SLEW_RATE_REG, vsel); if (ret < 0) { dev_err(max15569->dev, "SLEW reg write failed, err %d\n", ret); return ret; } /* Set base voltage if passed from platform data*/ if (pdata->base_voltage_uV) { vsel = DIV_ROUND_UP(pdata->base_voltage_uV - MAX15569_MIN_VOLTAGE, MAX15569_VOLTAGE_STEP) + 0x1; dev_err(max15569->dev, "Setting rail to vsel %x\n", vsel); ret = regmap_write(max15569->regmap, MAX15569_SETVOUT_REG, vsel); if (ret < 0) { dev_err(max15569->dev, "BASE reg write failed, err %d\n", ret); return ret; } } /* setup max voltage */ if (pdata->max_voltage_uV) { vsel = DIV_ROUND_UP(pdata->max_voltage_uV - MAX15569_MIN_VOLTAGE, MAX15569_VOLTAGE_STEP) + 0x1; ret = regmap_write(max15569->regmap, MAX15569_VOUTMAX_REG, vsel); if (ret < 0) { dev_err(max15569->dev, "VMAX write failed, err %d\n", ret); return ret; } } ret = regmap_read(max15569->regmap, MAX15569_STATUS_REG, &status); if (ret < 0) { dev_err(max15569->dev, "STATUS reg read failed, err %d\n", ret); return ret; } if (status & MAX15569_STATUS_VRHOT) dev_err(max15569->dev, "VRHOT: regulator temperature beyond limit\n"); if (status & MAX15569_STATUS_UV) dev_err(max15569->dev, "UV: regulator under-voltage condition\n"); if (status & MAX15569_STATUS_OV) dev_err(max15569->dev, "UV: regulator over-voltage condition\n"); if (status & MAX15569_STATUS_OC) dev_err(max15569->dev, "UV: regulator over-current condition\n"); return 0; } static bool is_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { case MAX15569_IMON_REG: return true; default: return false; } } static bool is_read_reg(struct device *dev, unsigned int reg) { switch (reg) { case 0x02: case 0x4 ... 0x08: return true; default: return false; } } static bool is_write_reg(struct device *dev, unsigned int reg) { switch (reg) { case 0x02: case 0x5 ... 0x7: return true; default: return false; } } static const struct regmap_config max15569_regmap_config = { .reg_bits = 8, .val_bits = 8, .writeable_reg = is_write_reg, .readable_reg = is_read_reg, .volatile_reg = is_volatile_reg, .max_register = MAX15569_MAX_REG - 1, .cache_type = REGCACHE_RBTREE, }; static int max15569_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct max15569_regulator_platform_data *pdata; struct regulator_dev *rdev; struct max15569_chip *max; struct regulator_config rconfig = { }; int ret; pdata = client->dev.platform_data; if (!pdata) { dev_err(&client->dev, "No Platform data\n"); return -EINVAL; } max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL); if (!max) { dev_err(&client->dev, "Memory allocation failed\n"); return -ENOMEM; } max->dev = &client->dev; max->desc.name = id->name; max->desc.id = 0; max->desc.ops = &max15569_ops; max->desc.type = REGULATOR_VOLTAGE; max->desc.owner = THIS_MODULE; max->regmap = devm_regmap_init_i2c(client, &max15569_regmap_config); if (IS_ERR(max->regmap)) { ret = PTR_ERR(max->regmap); dev_err(&client->dev, "regmap init failed, err %d\n", ret); return ret; } i2c_set_clientdata(client, max); ret = max15569_init(max, pdata); if (ret < 0) { dev_err(max->dev, "Init failed, err = %d\n", ret); return ret; } /* Register the regulators */ rconfig.dev = &client->dev; rconfig.of_node = NULL; rconfig.init_data = pdata->reg_init_data; rconfig.driver_data = max; rdev = regulator_register(&max->desc, &rconfig); if (IS_ERR(rdev)) { dev_err(max->dev, "regulator register failed\n"); return PTR_ERR(rdev); } max->rdev = rdev; return 0; } static int max15569_remove(struct i2c_client *client) { struct max15569_chip *max = i2c_get_clientdata(client); regulator_unregister(max->rdev); return 0; } static const struct i2c_device_id max15569_id[] = { {.name = "max15569",}, {}, }; MODULE_DEVICE_TABLE(i2c, max15569_id); static struct i2c_driver max15569_i2c_driver = { .driver = { .name = "max15569", .owner = THIS_MODULE, }, .probe = max15569_probe, .remove = max15569_remove, .id_table = max15569_id, }; static int __init max15569_drv_init(void) { return i2c_add_driver(&max15569_i2c_driver); } subsys_initcall(max15569_drv_init); static void __exit max15569_drv_cleanup(void) { i2c_del_driver(&max15569_i2c_driver); } module_exit(max15569_drv_cleanup); MODULE_AUTHOR("NVIDIA Corporation"); MODULE_DESCRIPTION("MAX15569 voltage regulator driver"); MODULE_LICENSE("GPL v2");