From 6c795c895781e5c57125e9329683ffccd7d3e3a7 Mon Sep 17 00:00:00 2001 From: Jin Park Date: Tue, 2 Aug 2011 16:35:58 +0900 Subject: regulator: max77663: Add MAX77663 regulator driver Add regulator driver for Maxim PMU MAX77663. Bug 849360 Bug 854414 Signed-off-by: Jin Park Original-Change-Id: I740f484ee1f39deefa8e5b9669426d6e6bafb42d Reviewed-on: http://git-master/r/44484 Reviewed-by: Laxman Dewangan Reviewed-by: Bharat Nihalani Rebase-Id: Re303620c5dcae6f56d1f219484d659525005eaa7 --- drivers/regulator/Kconfig | 8 + drivers/regulator/Makefile | 1 + drivers/regulator/max77663-regulator.c | 673 +++++++++++++++++++++++++++ include/linux/regulator/max77663-regulator.h | 110 +++++ 4 files changed, 792 insertions(+) create mode 100644 drivers/regulator/max77663-regulator.c create mode 100644 include/linux/regulator/max77663-regulator.h diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 2f5c27d52140..91cd8f1d059b 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -133,6 +133,14 @@ config REGULATOR_MAX8907C via I2C bus. The provided regulator is suitable for Tegra chip to control Step-Down DC-DC and LDOs. +config REGULATOR_MAX77663 + tristate "Maxim 77663 voltage regulator" + depends on MFD_MAX77663 + help + This driver controls a Maxim 77663 voltage output regulator + via I2C bus. The provided regulator is suitable for Tegra + chip to control Step-Down DC-DC and LDOs. + config REGULATOR_TWL4030 bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC" depends on TWL4030_CORE diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index c5f242c06332..5bf68b93f955 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o obj-$(CONFIG_REGULATOR_MAX8907C) += max8907c-regulator.o +obj-$(CONFIG_REGULATOR_MAX77663) += max77663-regulator.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o diff --git a/drivers/regulator/max77663-regulator.c b/drivers/regulator/max77663-regulator.c new file mode 100644 index 000000000000..17551266673f --- /dev/null +++ b/drivers/regulator/max77663-regulator.c @@ -0,0 +1,673 @@ +/* + * drivers/regulator/max77663-regulator.c + * Maxim LDO and Buck regulators driver + * + * Copyright 2011 Maxim Integrated Products, Inc. + * Copyright (C) 2011 NVIDIA Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Regulator types */ +#define REGULATOR_TYPE_SD 0 +#define REGULATOR_TYPE_LDO 1 + +/* SD and LDO Registers */ +#define MAX77663_REG_SD0 0x16 +#define MAX77663_REG_SD1 0x17 +#define MAX77663_REG_SD2 0x18 +#define MAX77663_REG_SD3 0x19 +#define MAX77663_REG_SD4 0x1A +#define MAX77663_REG_DVSSD0 0x1B +#define MAX77663_REG_DVSSD1 0x1C +#define MAX77663_REG_SD0_CFG 0x1D +#define MAX77663_REG_DVSSD0_CFG MAX77663_REG_SD0_CFG +#define MAX77663_REG_SD1_CFG 0x1E +#define MAX77663_REG_DVSSD1_CFG MAX77663_REG_SD1_CFG +#define MAX77663_REG_SD2_CFG 0x1F +#define MAX77663_REG_SD3_CFG 0x20 +#define MAX77663_REG_SD4_CFG 0x21 +#define MAX77663_REG_LDO0_CFG 0x23 +#define MAX77663_REG_LDO0_CFG2 0x24 +#define MAX77663_REG_LDO1_CFG 0x25 +#define MAX77663_REG_LDO1_CFG2 0x26 +#define MAX77663_REG_LDO2_CFG 0x27 +#define MAX77663_REG_LDO2_CFG2 0x28 +#define MAX77663_REG_LDO3_CFG 0x29 +#define MAX77663_REG_LDO3_CFG2 0x2A +#define MAX77663_REG_LDO4_CFG 0x2B +#define MAX77663_REG_LDO4_CFG2 0x2C +#define MAX77663_REG_LDO5_CFG 0x2D +#define MAX77663_REG_LDO5_CFG2 0x2E +#define MAX77663_REG_LDO6_CFG 0x2F +#define MAX77663_REG_LDO6_CFG2 0x30 +#define MAX77663_REG_LDO7_CFG 0x31 +#define MAX77663_REG_LDO7_CFG2 0x32 +#define MAX77663_REG_LDO8_CFG 0x33 +#define MAX77663_REG_LDO8_CFG2 0x34 + +#define POWER_MODE_NORMAL 3 +#define POWER_MODE_LPM 2 +#define POWER_MODE_GLPM 1 +#define POWER_MODE_DISABLE 0 + +#define SD_POWER_MODE_MASK 0x30 +#define SD_POWER_MODE_SHIFT 4 +#define LDO_POWER_MODE_MASK 0xC0 +#define LDO_POWER_MODE_SHIFT 6 + +#define SDX_VOLT_MASK 0xFF +#define SD1_VOLT_MASK 0x3F +#define LDO_VOLT_MASK 0x3F + +/* FPS Registers */ +#define MAX77663_REG_FPS_CFG0 0x43 +#define MAX77663_REG_FPS_CFG1 0x44 +#define MAX77663_REG_FPS_CFG2 0x45 +#define MAX77663_REG_FPS_LDO0 0x46 +#define MAX77663_REG_FPS_LDO1 0x47 +#define MAX77663_REG_FPS_LDO2 0x48 +#define MAX77663_REG_FPS_LDO3 0x49 +#define MAX77663_REG_FPS_LDO4 0x4A +#define MAX77663_REG_FPS_LDO5 0x4B +#define MAX77663_REG_FPS_LDO6 0x4C +#define MAX77663_REG_FPS_LDO7 0x4D +#define MAX77663_REG_FPS_LDO8 0x4E +#define MAX77663_REG_FPS_SD0 0x4F +#define MAX77663_REG_FPS_SD1 0x50 +#define MAX77663_REG_FPS_SD2 0x51 +#define MAX77663_REG_FPS_SD3 0x52 +#define MAX77663_REG_FPS_SD4 0x53 +#define MAX77663_REG_FPS_NONE 0 + +#define FPS_TIME_PERIOD_MASK 0x38 +#define FPS_TIME_PERIOD_SHIFT 3 +#define FPS_EN_SRC_MASK 0x06 +#define FPS_EN_SRC_SHIFT 1 +#define FPS_SW_EN_MASK 0x01 +#define FPS_SW_EN_SHIFT 0 +#define FPS_SRC_MASK 0xC0 +#define FPS_SRC_SHIFT 6 +#define FPS_PU_PERIOD_MASK 0x38 +#define FPS_PU_PERIOD_SHIFT 3 +#define FPS_PD_PERIOD_MASK 0x07 +#define FPS_PD_PERIOD_SHIFT 0 + +struct max77663_regulator { + struct regulator_dev *rdev; + struct device *dev; + + u8 id; + u8 type; + u32 min_uV; + u32 max_uV; + u32 step_uV; + u32 regulator_mode; + + u8 volt_reg; + u8 cfg_reg; + u8 fps_reg; + + int fps_src; + + u8 volt_mask; + + u8 power_mode; + u8 power_mode_mask; + u8 power_mode_shift; +}; + +#define fps_src_name(fps_src) \ + (fps_src == FPS_SRC_0 ? "FPS_SRC_0" : \ + fps_src == FPS_SRC_1 ? "FPS_SRC_1" : \ + fps_src == FPS_SRC_2 ? "FPS_SRC_2" : "FPS_SRC_NONE") + +static int fps_cfg_init; +static u8 fps_cfg_reg[] = { + MAX77663_REG_FPS_CFG0, + MAX77663_REG_FPS_CFG1, + MAX77663_REG_FPS_CFG2 +}; + +static inline struct max77663_regulator_platform_data +*_to_pdata(struct max77663_regulator *reg) +{ + return reg->dev->platform_data; +} + +static inline struct device *_to_parent(struct max77663_regulator *reg) +{ + return reg->dev->parent; +} + +static int max77663_regulator_set_fps_src(struct max77663_regulator *reg, + int fps_src) +{ + struct device *parent = _to_parent(reg); + int ret; + + if (reg->fps_reg == MAX77663_REG_FPS_NONE) + return 0; + + switch (fps_src) { + case FPS_SRC_0: + case FPS_SRC_1: + case FPS_SRC_2: + case FPS_SRC_NONE: + break; + case FPS_SRC_DEF: + return 0; + default: + return -EINVAL; + } + + ret = max77663_set_bits(parent, reg->fps_reg, FPS_SRC_MASK, + fps_src << FPS_SRC_SHIFT, 0); + if (ret < 0) + return ret; + + reg->fps_src = fps_src; + return 0; +} + +static int max77663_regulator_set_fps(struct max77663_regulator *reg) +{ + struct max77663_regulator_platform_data *pdata = _to_pdata(reg); + struct device *parent = _to_parent(reg); + u8 fps_val = 0, fps_mask = 0; + int ret = 0; + + if (reg->fps_reg == MAX77663_REG_FPS_NONE) + return 0; + + if (reg->fps_src == FPS_SRC_NONE) + return 0; + + /* FPS power up period setting */ + if (pdata->fps_pu_period != FPS_POWER_PERIOD_DEF) { + fps_val |= (pdata->fps_pu_period << FPS_PU_PERIOD_SHIFT); + fps_mask |= FPS_PU_PERIOD_MASK; + } + + /* FPS power down period setting */ + if (pdata->fps_pd_period != FPS_POWER_PERIOD_DEF) { + fps_val |= (pdata->fps_pd_period << FPS_PD_PERIOD_SHIFT); + fps_mask |= FPS_PD_PERIOD_MASK; + } + + if (fps_val) + ret = max77663_set_bits(parent, reg->fps_reg, fps_mask, + fps_val, 0); + + return ret; +} + +static int max77663_regulator_set_fps_cfg(struct max77663_regulator *reg) +{ + struct max77663_regulator_platform_data *pdata = _to_pdata(reg); + struct device *parent = _to_parent(reg); + int i; + int ret = 0; + + if (fps_cfg_init) + return 0; + + for (i = FPS_SRC_0; i <= FPS_SRC_2; i++) { + struct max77663_regulator_fps_cfg *fps_cfg; + u8 fps_cfg_val = 0, fps_cfg_mask = 0; + + fps_cfg = &pdata->fps_cfg[i]; + + /* FPS enable source setting */ + fps_cfg_val = (fps_cfg->en_src << FPS_EN_SRC_SHIFT); + fps_cfg_mask = FPS_EN_SRC_MASK; + + /* FPS time period setting */ + if (fps_cfg->time_period != FPS_TIME_PERIOD_DEF) { + fps_cfg_val |= (fps_cfg->time_period + << FPS_TIME_PERIOD_SHIFT); + fps_cfg_mask |= FPS_TIME_PERIOD_MASK; + } + + ret = max77663_set_bits(parent, fps_cfg_reg[i], fps_cfg_mask, + fps_cfg_val, 0); + if (ret < 0) + goto out; + } + + fps_cfg_init = 1; +out: + return ret; +} + +static int +max77663_regulator_set_power_mode(struct max77663_regulator *reg, u8 power_mode) +{ + struct device *parent = _to_parent(reg); + u8 addr; + u8 mask = reg->power_mode_mask; + u8 shift = reg->power_mode_shift; + int ret; + + if (reg->type == REGULATOR_TYPE_SD) + addr = reg->cfg_reg; + else + addr = reg->volt_reg; + + ret = max77663_set_bits(parent, addr, mask, power_mode << shift, 0); + if (ret < 0) + return ret; + + reg->power_mode = power_mode; + return ret; +} + +static u8 max77663_regulator_get_power_mode(struct max77663_regulator *reg) +{ + struct device *parent = _to_parent(reg); + u8 addr, val; + u8 mask = reg->power_mode_mask; + u8 shift = reg->power_mode_shift; + int ret; + + if (reg->type == REGULATOR_TYPE_SD) + addr = reg->cfg_reg; + else + addr = reg->volt_reg; + + ret = max77663_read(parent, addr, &val, 1, 0); + if (ret < 0) + return ret; + + reg->power_mode = (val & mask) >> shift; + return reg->power_mode; +} + +static int max77663_regulator_do_set_voltage(struct max77663_regulator *reg, + int min_uV, int max_uV) +{ + struct device *parent = _to_parent(reg); + u8 val; + + if (min_uV < reg->min_uV || max_uV > reg->max_uV) + return -EDOM; + + val = (min_uV - reg->min_uV) / reg->step_uV; + return max77663_set_bits(parent, reg->volt_reg, reg->volt_mask, val, 0); +} + +static int max77663_regulator_set_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + struct max77663_regulator *reg = rdev_get_drvdata(rdev); + + dev_dbg(&rdev->dev, "set_voltage: name=%s, min_uV=%d, max_uV=%d\n", + rdev->desc->name, min_uV, max_uV); + return max77663_regulator_do_set_voltage(reg, min_uV, max_uV); +} + +static int max77663_regulator_get_voltage(struct regulator_dev *rdev) +{ + struct max77663_regulator *reg = rdev_get_drvdata(rdev); + struct device *parent = _to_parent(reg); + u8 val; + int volt; + int ret; + + ret = max77663_read(parent, reg->volt_reg, &val, 1, 0); + if (ret < 0) + return ret; + + volt = (val & reg->volt_mask) * reg->step_uV + reg->min_uV; + + dev_dbg(&rdev->dev, "get_voltage: name=%s, volt=%d, val=0x%02x\n", + rdev->desc->name, volt, val); + return volt; +} + +static int max77663_regulator_enable(struct regulator_dev *rdev) +{ + struct max77663_regulator *reg = rdev_get_drvdata(rdev); + int power_mode = POWER_MODE_NORMAL; + + if (reg->fps_src != FPS_SRC_NONE) { + dev_warn(&rdev->dev, "enable: Regulator %s using %s\n", + rdev->desc->name, fps_src_name(reg->fps_src)); + return 0; + } + + if (reg->regulator_mode == REGULATOR_MODE_STANDBY) + power_mode = POWER_MODE_LPM; + + return max77663_regulator_set_power_mode(reg, power_mode); +} + +static int max77663_regulator_disable(struct regulator_dev *rdev) +{ + struct max77663_regulator *reg = rdev_get_drvdata(rdev); + int power_mode = POWER_MODE_DISABLE; + + if (reg->fps_src != FPS_SRC_NONE) { + dev_warn(&rdev->dev, "disable: Regulator %s using %s\n", + rdev->desc->name, fps_src_name(reg->fps_src)); + return 0; + } + + return max77663_regulator_set_power_mode(reg, power_mode);; +} + +static int max77663_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct max77663_regulator *reg = rdev_get_drvdata(rdev); + int power_mode = max77663_regulator_get_power_mode(reg); + int ret = 1; + + if (reg->fps_src != FPS_SRC_NONE) { + dev_warn(&rdev->dev, "is_enable: Regulator %s using %s\n", + rdev->desc->name, fps_src_name(reg->fps_src)); + return 1; + } + + if (power_mode == POWER_MODE_DISABLE) + ret = 0; + + return ret; +} + +static int max77663_regulator_set_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + struct max77663_regulator *reg = rdev_get_drvdata(rdev); + u8 power_mode; + int ret; + + if (mode == REGULATOR_MODE_NORMAL) + power_mode = POWER_MODE_NORMAL; + else if (mode == REGULATOR_MODE_STANDBY) + power_mode = POWER_MODE_LPM; + else + return -EINVAL; + + ret = max77663_regulator_set_power_mode(reg, power_mode); + if (!ret) + reg->regulator_mode = mode; + + return ret; +} + +static unsigned int max77663_regulator_get_mode(struct regulator_dev *rdev) +{ + struct max77663_regulator *reg = rdev_get_drvdata(rdev); + + return reg->regulator_mode; +} + +static struct regulator_ops max77663_ldo_ops = { + .set_voltage = max77663_regulator_set_voltage, + .get_voltage = max77663_regulator_get_voltage, + .enable = max77663_regulator_enable, + .disable = max77663_regulator_disable, + .is_enabled = max77663_regulator_is_enabled, + .set_mode = max77663_regulator_set_mode, + .get_mode = max77663_regulator_get_mode, +}; + +static int max77663_regulator_preinit(struct max77663_regulator *reg) +{ + struct max77663_regulator_platform_data *pdata = _to_pdata(reg); + struct device *parent = _to_parent(reg); + u8 val; + int ret; + + /* Update FPS source */ + if (reg->fps_reg == MAX77663_REG_FPS_NONE) + reg->fps_src = FPS_SRC_NONE; + else { + ret = max77663_read(parent, reg->fps_reg, &val, 1, 0); + if (ret < 0) { + dev_err(reg->dev, + "preinit: Failed to get FPS source\n"); + return ret; + } + reg->fps_src = (val & FPS_SRC_MASK) >> FPS_SRC_SHIFT; + } + + /* Set initial state */ + if (!pdata->init_apply) + goto set_fps_cfg; + + if (pdata->init_uV >= 0) { + ret = max77663_regulator_do_set_voltage(reg, pdata->init_uV, + pdata->init_uV); + if (ret < 0) { + dev_err(reg->dev, "preinit: Failed to set voltage to " + "%d\n", pdata->init_uV); + return ret; + } + } + + if (pdata->init_enable) + val = POWER_MODE_NORMAL; + else + val = POWER_MODE_DISABLE; + + ret = max77663_regulator_set_power_mode(reg, val); + if (ret < 0) { + dev_err(reg->dev, + "preinit: Failed to set power mode to %d\n", val); + return ret; + } + + if ((reg->id == MAX77663_REGULATOR_ID_SD0) + && (pdata->flags & EN2_CTRL_SD0)) { + val = POWER_MODE_DISABLE; + ret = max77663_regulator_set_power_mode(reg, val); + if (ret < 0) { + dev_err(reg->dev, "preinit: Failed to set power mode to" + "%d for EN2_CTRL_SD0\n", val); + return ret; + } + + if (reg->fps_src == FPS_SRC_NONE) + return 0; + + ret = max77663_regulator_set_fps_src(reg, FPS_SRC_NONE); + if (ret < 0) { + dev_err(reg->dev, "preinit: Failed to set FPSSRC to " + "FPS_SRC_NONE for EN2_CTRL_SD0\n"); + return ret; + } + } + +set_fps_cfg: + ret = max77663_regulator_set_fps_cfg(reg); + if (ret < 0) { + dev_err(reg->dev, "preinit: Failed to set FPSCFG\n"); + return ret; + } + + ret = max77663_regulator_set_fps_src(reg, pdata->fps_src); + if (ret < 0) { + dev_err(reg->dev, "preinit: Failed to set FPSSRC to %d\n", + pdata->fps_src); + return ret; + } + + ret = max77663_regulator_set_fps(reg); + if (ret < 0) { + dev_err(reg->dev, "preinit: Failed to set FPS\n"); + return ret; + } + + return 0; +} + +#define REGULATOR_SD(_id, _volt_mask, _fps_reg, _min_uV, _max_uV, _step_uV) \ + [MAX77663_REGULATOR_ID_##_id] = { \ + .id = MAX77663_REGULATOR_ID_##_id, \ + .type = REGULATOR_TYPE_SD, \ + .volt_reg = MAX77663_REG_##_id, \ + .volt_mask = _volt_mask##_VOLT_MASK, \ + .cfg_reg = MAX77663_REG_##_id##_CFG, \ + .fps_reg = MAX77663_REG_FPS_##_fps_reg, \ + .min_uV = _min_uV, \ + .max_uV = _max_uV, \ + .step_uV = _step_uV, \ + .regulator_mode = REGULATOR_MODE_NORMAL, \ + .power_mode = POWER_MODE_NORMAL, \ + .power_mode_mask = SD_POWER_MODE_MASK, \ + .power_mode_shift = SD_POWER_MODE_SHIFT, \ + } + +#define REGULATOR_LDO(_id, _min_uV, _max_uV, _step_uV) \ + [MAX77663_REGULATOR_ID_##_id] = { \ + .id = MAX77663_REGULATOR_ID_##_id, \ + .type = REGULATOR_TYPE_LDO, \ + .volt_reg = MAX77663_REG_##_id##_CFG, \ + .volt_mask = LDO_VOLT_MASK, \ + .cfg_reg = MAX77663_REG_##_id##_CFG2, \ + .fps_reg = MAX77663_REG_FPS_##_id, \ + .min_uV = _min_uV, \ + .max_uV = _max_uV, \ + .step_uV = _step_uV, \ + .regulator_mode = REGULATOR_MODE_NORMAL, \ + .power_mode = POWER_MODE_NORMAL, \ + .power_mode_mask = LDO_POWER_MODE_MASK, \ + .power_mode_shift = LDO_POWER_MODE_SHIFT, \ + } + +static struct max77663_regulator max77663_regs[MAX77663_REGULATOR_ID_NR] = { + REGULATOR_SD(SD0, SDX, SD0, 600000, 3387500, 12500), + REGULATOR_SD(DVSSD0, SDX, NONE, 600000, 3387500, 12500), + REGULATOR_SD(SD1, SD1, SD1, 800000, 1587500, 12500), + REGULATOR_SD(DVSSD1, SD1, NONE, 800000, 1587500, 12500), + REGULATOR_SD(SD2, SDX, SD2, 600000, 3387500, 12500), + REGULATOR_SD(SD3, SDX, SD3, 600000, 3387500, 12500), + REGULATOR_SD(SD4, SDX, SD4, 600000, 3387500, 12500), + + REGULATOR_LDO(LDO0, 800000, 2350000, 25000), + REGULATOR_LDO(LDO1, 800000, 2350000, 25000), + REGULATOR_LDO(LDO2, 800000, 3950000, 50000), + REGULATOR_LDO(LDO3, 800000, 3950000, 50000), + REGULATOR_LDO(LDO4, 800000, 1587500, 12500), + REGULATOR_LDO(LDO5, 800000, 3950000, 50000), + REGULATOR_LDO(LDO6, 800000, 3950000, 50000), + REGULATOR_LDO(LDO7, 800000, 3950000, 50000), + REGULATOR_LDO(LDO8, 800000, 3950000, 50000), +}; + +#define REGULATOR_DESC(_id, _name) \ + [MAX77663_REGULATOR_ID_##_id] = { \ + .name = max77663_rails(_name), \ + .id = MAX77663_REGULATOR_ID_##_id, \ + .ops = &max77663_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } + +static struct regulator_desc max77663_rdesc[MAX77663_REGULATOR_ID_NR] = { + REGULATOR_DESC(SD0, sd0), + REGULATOR_DESC(DVSSD0, dvssd0), + REGULATOR_DESC(SD1, sd1), + REGULATOR_DESC(DVSSD1, dvssd1), + REGULATOR_DESC(SD2, sd2), + REGULATOR_DESC(SD3, sd3), + REGULATOR_DESC(SD4, sd4), + REGULATOR_DESC(LDO0, ldo0), + REGULATOR_DESC(LDO1, ldo1), + REGULATOR_DESC(LDO2, ldo2), + REGULATOR_DESC(LDO3, ldo3), + REGULATOR_DESC(LDO4, ldo4), + REGULATOR_DESC(LDO5, ldo5), + REGULATOR_DESC(LDO6, ldo6), + REGULATOR_DESC(LDO7, ldo7), + REGULATOR_DESC(LDO8, ldo8), +}; + +static int max77663_regulator_probe(struct platform_device *pdev) +{ + struct regulator_desc *rdesc; + struct max77663_regulator *reg; + struct max77663_regulator_platform_data *pdata; + int ret = 0; + + if ((pdev->id < 0) || (pdev->id >= MAX77663_REGULATOR_ID_NR)) { + dev_err(&pdev->dev, "Invalid device id %d\n", pdev->id); + return -ENODEV; + } + + rdesc = &max77663_rdesc[pdev->id]; + reg = &max77663_regs[pdev->id]; + reg->dev = &pdev->dev; + pdata = reg->dev->platform_data; + + dev_dbg(&pdev->dev, "probe: name=%s\n", rdesc->name); + + ret = max77663_regulator_preinit(reg); + if (ret) { + dev_err(&pdev->dev, "probe: Failed to preinit regulator %s\n", + rdesc->name); + return ret; + } + + reg->rdev = regulator_register(rdesc, &pdev->dev, &pdata->init_data, + reg); + if (IS_ERR(reg->rdev)) { + dev_err(&pdev->dev, "probe: Failed to register regulator %s\n", + rdesc->name); + return PTR_ERR(reg->rdev); + } + + return 0; +} + +static int max77663_regulator_remove(struct platform_device *pdev) +{ + struct regulator_dev *rdev = platform_get_drvdata(pdev); + + regulator_unregister(rdev); + return 0; +} + +static struct platform_driver max77663_regulator_driver = { + .probe = max77663_regulator_probe, + .remove = __devexit_p(max77663_regulator_remove), + .driver = { + .name = "max77663-regulator", + .owner = THIS_MODULE, + }, +}; + +static int __init max77663_regulator_init(void) +{ + return platform_driver_register(&max77663_regulator_driver); +} +subsys_initcall(max77663_regulator_init); + +static void __exit max77663_reg_exit(void) +{ + platform_driver_unregister(&max77663_regulator_driver); +} +module_exit(max77663_reg_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("max77663 regulator driver"); +MODULE_VERSION("1.0"); diff --git a/include/linux/regulator/max77663-regulator.h b/include/linux/regulator/max77663-regulator.h new file mode 100644 index 000000000000..8cf8c5852538 --- /dev/null +++ b/include/linux/regulator/max77663-regulator.h @@ -0,0 +1,110 @@ +/* + * include/linux/regulator/max77663-regulator.h + * Maxim LDO and Buck regulators driver + * + * Copyright 2011 Maxim Integrated Products, Inc. + * Copyright (C) 2011 NVIDIA Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + */ + +#ifndef __LINUX_REGULATOR_MAX77663_REGULATOR_H__ +#define __LINUX_REGULATOR_MAX77663_REGULATOR_H__ + +#include + +#define max77663_rails(_name) "max77663_"#_name + +enum max77663_regulator_id { + MAX77663_REGULATOR_ID_SD0, + MAX77663_REGULATOR_ID_DVSSD0, + MAX77663_REGULATOR_ID_SD1, + MAX77663_REGULATOR_ID_DVSSD1, + MAX77663_REGULATOR_ID_SD2, + MAX77663_REGULATOR_ID_SD3, + MAX77663_REGULATOR_ID_SD4, + MAX77663_REGULATOR_ID_LDO0, + MAX77663_REGULATOR_ID_LDO1, + MAX77663_REGULATOR_ID_LDO2, + MAX77663_REGULATOR_ID_LDO3, + MAX77663_REGULATOR_ID_LDO4, + MAX77663_REGULATOR_ID_LDO5, + MAX77663_REGULATOR_ID_LDO6, + MAX77663_REGULATOR_ID_LDO7, + MAX77663_REGULATOR_ID_LDO8, + MAX77663_REGULATOR_ID_NR, +}; + +/* FPS Power Up/Down Period */ +enum max77663_regulator_fps_power_period { + FPS_POWER_PERIOD_0, + FPS_POWER_PERIOD_1, + FPS_POWER_PERIOD_2, + FPS_POWER_PERIOD_3, + FPS_POWER_PERIOD_4, + FPS_POWER_PERIOD_5, + FPS_POWER_PERIOD_6, + FPS_POWER_PERIOD_7, + FPS_POWER_PERIOD_DEF = -1, +}; + +/* FPS Time Period */ +enum max77663_regulator_fps_time_period { + FPS_TIME_PERIOD_20US, + FPS_TIME_PERIOD_40US, + FPS_TIME_PERIOD_80US, + FPS_TIME_PERIOD_160US, + FPS_TIME_PERIOD_320US, + FPS_TIME_PERIOD_640US, + FPS_TIME_PERIOD_1280US, + FPS_TIME_PERIOD_2560US, + FPS_TIME_PERIOD_DEF = -1, +}; + +/* FPS Enable Source */ +enum max77663_regulator_fps_en_src { + FPS_EN_SRC_EN0, + FPS_EN_SRC_EN1, + FPS_EN_SRC_SW, + FPS_EN_SRC_RSVD, +}; + +/* FPS Source */ +enum max77663_regulator_fps_src { + FPS_SRC_0, + FPS_SRC_1, + FPS_SRC_2, + FPS_SRC_NONE, + FPS_SRC_DEF = -1, +}; + +/* + * Flags + */ +/* SD0 is controlled by EN2 input. */ +#define EN2_CTRL_SD0 0x01 + +struct max77663_regulator_fps_cfg { + int en_src; + int time_period; +}; + +struct max77663_regulator_platform_data { + struct regulator_init_data init_data; + bool init_apply; + bool init_enable; + int init_uV; + + int fps_src; + int fps_pu_period; + int fps_pd_period; + struct max77663_regulator_fps_cfg *fps_cfg; + + unsigned int flags; +}; + +#endif /* __LINUX_REGULATOR_MAX77663_REGULATOR_H__ */ -- cgit v1.2.3