1518fb721SGraeme Gregory /* 2518fb721SGraeme Gregory * tps65910.c -- TI tps65910 3518fb721SGraeme Gregory * 4518fb721SGraeme Gregory * Copyright 2010 Texas Instruments Inc. 5518fb721SGraeme Gregory * 6518fb721SGraeme Gregory * Author: Graeme Gregory <gg@slimlogic.co.uk> 7518fb721SGraeme Gregory * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk> 8518fb721SGraeme Gregory * 9518fb721SGraeme Gregory * This program is free software; you can redistribute it and/or modify it 10518fb721SGraeme Gregory * under the terms of the GNU General Public License as published by the 11518fb721SGraeme Gregory * Free Software Foundation; either version 2 of the License, or (at your 12518fb721SGraeme Gregory * option) any later version. 13518fb721SGraeme Gregory * 14518fb721SGraeme Gregory */ 15518fb721SGraeme Gregory 16518fb721SGraeme Gregory #include <linux/kernel.h> 17518fb721SGraeme Gregory #include <linux/module.h> 18518fb721SGraeme Gregory #include <linux/init.h> 19518fb721SGraeme Gregory #include <linux/err.h> 20518fb721SGraeme Gregory #include <linux/platform_device.h> 21518fb721SGraeme Gregory #include <linux/regulator/driver.h> 22518fb721SGraeme Gregory #include <linux/regulator/machine.h> 23518fb721SGraeme Gregory #include <linux/delay.h> 24518fb721SGraeme Gregory #include <linux/slab.h> 25518fb721SGraeme Gregory #include <linux/gpio.h> 26518fb721SGraeme Gregory #include <linux/mfd/tps65910.h> 27518fb721SGraeme Gregory 28518fb721SGraeme Gregory #define TPS65910_REG_VRTC 0 29518fb721SGraeme Gregory #define TPS65910_REG_VIO 1 30518fb721SGraeme Gregory #define TPS65910_REG_VDD1 2 31518fb721SGraeme Gregory #define TPS65910_REG_VDD2 3 32518fb721SGraeme Gregory #define TPS65910_REG_VDD3 4 33518fb721SGraeme Gregory #define TPS65910_REG_VDIG1 5 34518fb721SGraeme Gregory #define TPS65910_REG_VDIG2 6 35518fb721SGraeme Gregory #define TPS65910_REG_VPLL 7 36518fb721SGraeme Gregory #define TPS65910_REG_VDAC 8 37518fb721SGraeme Gregory #define TPS65910_REG_VAUX1 9 38518fb721SGraeme Gregory #define TPS65910_REG_VAUX2 10 39518fb721SGraeme Gregory #define TPS65910_REG_VAUX33 11 40518fb721SGraeme Gregory #define TPS65910_REG_VMMC 12 41518fb721SGraeme Gregory 42518fb721SGraeme Gregory #define TPS65910_NUM_REGULATOR 13 43518fb721SGraeme Gregory 44518fb721SGraeme Gregory #define TPS65910_SUPPLY_STATE_ENABLED 0x1 45518fb721SGraeme Gregory 46518fb721SGraeme Gregory /* supported VIO voltages in milivolts */ 47518fb721SGraeme Gregory static const u16 VIO_VSEL_table[] = { 48518fb721SGraeme Gregory 1500, 1800, 2500, 3300, 49518fb721SGraeme Gregory }; 50518fb721SGraeme Gregory 51518fb721SGraeme Gregory /* supported VIO voltages in milivolts */ 52518fb721SGraeme Gregory static const u16 VDD3_VSEL_table[] = { 53518fb721SGraeme Gregory 5000, 54518fb721SGraeme Gregory }; 55518fb721SGraeme Gregory 56518fb721SGraeme Gregory /* supported VDIG1 voltages in milivolts */ 57518fb721SGraeme Gregory static const u16 VDIG1_VSEL_table[] = { 58518fb721SGraeme Gregory 1200, 1500, 1800, 2700, 59518fb721SGraeme Gregory }; 60518fb721SGraeme Gregory 61518fb721SGraeme Gregory /* supported VDIG2 voltages in milivolts */ 62518fb721SGraeme Gregory static const u16 VDIG2_VSEL_table[] = { 63518fb721SGraeme Gregory 1000, 1100, 1200, 1800, 64518fb721SGraeme Gregory }; 65518fb721SGraeme Gregory 66518fb721SGraeme Gregory /* supported VPLL voltages in milivolts */ 67518fb721SGraeme Gregory static const u16 VPLL_VSEL_table[] = { 68518fb721SGraeme Gregory 1000, 1100, 1800, 2500, 69518fb721SGraeme Gregory }; 70518fb721SGraeme Gregory 71518fb721SGraeme Gregory /* supported VDAC voltages in milivolts */ 72518fb721SGraeme Gregory static const u16 VDAC_VSEL_table[] = { 73518fb721SGraeme Gregory 1800, 2600, 2800, 2850, 74518fb721SGraeme Gregory }; 75518fb721SGraeme Gregory 76518fb721SGraeme Gregory /* supported VAUX1 voltages in milivolts */ 77518fb721SGraeme Gregory static const u16 VAUX1_VSEL_table[] = { 78518fb721SGraeme Gregory 1800, 2500, 2800, 2850, 79518fb721SGraeme Gregory }; 80518fb721SGraeme Gregory 81518fb721SGraeme Gregory /* supported VAUX2 voltages in milivolts */ 82518fb721SGraeme Gregory static const u16 VAUX2_VSEL_table[] = { 83518fb721SGraeme Gregory 1800, 2800, 2900, 3300, 84518fb721SGraeme Gregory }; 85518fb721SGraeme Gregory 86518fb721SGraeme Gregory /* supported VAUX33 voltages in milivolts */ 87518fb721SGraeme Gregory static const u16 VAUX33_VSEL_table[] = { 88518fb721SGraeme Gregory 1800, 2000, 2800, 3300, 89518fb721SGraeme Gregory }; 90518fb721SGraeme Gregory 91518fb721SGraeme Gregory /* supported VMMC voltages in milivolts */ 92518fb721SGraeme Gregory static const u16 VMMC_VSEL_table[] = { 93518fb721SGraeme Gregory 1800, 2800, 3000, 3300, 94518fb721SGraeme Gregory }; 95518fb721SGraeme Gregory 96518fb721SGraeme Gregory struct tps_info { 97518fb721SGraeme Gregory const char *name; 98518fb721SGraeme Gregory unsigned min_uV; 99518fb721SGraeme Gregory unsigned max_uV; 100518fb721SGraeme Gregory u8 table_len; 101518fb721SGraeme Gregory const u16 *table; 102518fb721SGraeme Gregory }; 103518fb721SGraeme Gregory 104518fb721SGraeme Gregory static struct tps_info tps65910_regs[] = { 105518fb721SGraeme Gregory { 106518fb721SGraeme Gregory .name = "VRTC", 107518fb721SGraeme Gregory }, 108518fb721SGraeme Gregory { 109518fb721SGraeme Gregory .name = "VIO", 110518fb721SGraeme Gregory .min_uV = 1500000, 111518fb721SGraeme Gregory .max_uV = 3300000, 112518fb721SGraeme Gregory .table_len = ARRAY_SIZE(VIO_VSEL_table), 113518fb721SGraeme Gregory .table = VIO_VSEL_table, 114518fb721SGraeme Gregory }, 115518fb721SGraeme Gregory { 116518fb721SGraeme Gregory .name = "VDD1", 117518fb721SGraeme Gregory .min_uV = 600000, 118518fb721SGraeme Gregory .max_uV = 4500000, 119518fb721SGraeme Gregory }, 120518fb721SGraeme Gregory { 121518fb721SGraeme Gregory .name = "VDD2", 122518fb721SGraeme Gregory .min_uV = 600000, 123518fb721SGraeme Gregory .max_uV = 4500000, 124518fb721SGraeme Gregory }, 125518fb721SGraeme Gregory { 126518fb721SGraeme Gregory .name = "VDD3", 127518fb721SGraeme Gregory .min_uV = 5000000, 128518fb721SGraeme Gregory .max_uV = 5000000, 129518fb721SGraeme Gregory .table_len = ARRAY_SIZE(VDD3_VSEL_table), 130518fb721SGraeme Gregory .table = VDD3_VSEL_table, 131518fb721SGraeme Gregory }, 132518fb721SGraeme Gregory { 133518fb721SGraeme Gregory .name = "VDIG1", 134518fb721SGraeme Gregory .min_uV = 1200000, 135518fb721SGraeme Gregory .max_uV = 2700000, 136518fb721SGraeme Gregory .table_len = ARRAY_SIZE(VDIG1_VSEL_table), 137518fb721SGraeme Gregory .table = VDIG1_VSEL_table, 138518fb721SGraeme Gregory }, 139518fb721SGraeme Gregory { 140518fb721SGraeme Gregory .name = "VDIG2", 141518fb721SGraeme Gregory .min_uV = 1000000, 142518fb721SGraeme Gregory .max_uV = 1800000, 143518fb721SGraeme Gregory .table_len = ARRAY_SIZE(VDIG2_VSEL_table), 144518fb721SGraeme Gregory .table = VDIG2_VSEL_table, 145518fb721SGraeme Gregory }, 146518fb721SGraeme Gregory { 147518fb721SGraeme Gregory .name = "VPLL", 148518fb721SGraeme Gregory .min_uV = 1000000, 149518fb721SGraeme Gregory .max_uV = 2500000, 150518fb721SGraeme Gregory .table_len = ARRAY_SIZE(VPLL_VSEL_table), 151518fb721SGraeme Gregory .table = VPLL_VSEL_table, 152518fb721SGraeme Gregory }, 153518fb721SGraeme Gregory { 154518fb721SGraeme Gregory .name = "VDAC", 155518fb721SGraeme Gregory .min_uV = 1800000, 156518fb721SGraeme Gregory .max_uV = 2850000, 157518fb721SGraeme Gregory .table_len = ARRAY_SIZE(VDAC_VSEL_table), 158518fb721SGraeme Gregory .table = VDAC_VSEL_table, 159518fb721SGraeme Gregory }, 160518fb721SGraeme Gregory { 161518fb721SGraeme Gregory .name = "VAUX1", 162518fb721SGraeme Gregory .min_uV = 1800000, 163518fb721SGraeme Gregory .max_uV = 2850000, 164518fb721SGraeme Gregory .table_len = ARRAY_SIZE(VAUX1_VSEL_table), 165518fb721SGraeme Gregory .table = VAUX1_VSEL_table, 166518fb721SGraeme Gregory }, 167518fb721SGraeme Gregory { 168518fb721SGraeme Gregory .name = "VAUX2", 169518fb721SGraeme Gregory .min_uV = 1800000, 170518fb721SGraeme Gregory .max_uV = 3300000, 171518fb721SGraeme Gregory .table_len = ARRAY_SIZE(VAUX2_VSEL_table), 172518fb721SGraeme Gregory .table = VAUX2_VSEL_table, 173518fb721SGraeme Gregory }, 174518fb721SGraeme Gregory { 175518fb721SGraeme Gregory .name = "VAUX33", 176518fb721SGraeme Gregory .min_uV = 1800000, 177518fb721SGraeme Gregory .max_uV = 3300000, 178518fb721SGraeme Gregory .table_len = ARRAY_SIZE(VAUX33_VSEL_table), 179518fb721SGraeme Gregory .table = VAUX33_VSEL_table, 180518fb721SGraeme Gregory }, 181518fb721SGraeme Gregory { 182518fb721SGraeme Gregory .name = "VMMC", 183518fb721SGraeme Gregory .min_uV = 1800000, 184518fb721SGraeme Gregory .max_uV = 3300000, 185518fb721SGraeme Gregory .table_len = ARRAY_SIZE(VMMC_VSEL_table), 186518fb721SGraeme Gregory .table = VMMC_VSEL_table, 187518fb721SGraeme Gregory }, 188518fb721SGraeme Gregory }; 189518fb721SGraeme Gregory 190518fb721SGraeme Gregory struct tps65910_reg { 191518fb721SGraeme Gregory struct regulator_desc desc[TPS65910_NUM_REGULATOR]; 192518fb721SGraeme Gregory struct tps65910 *mfd; 193518fb721SGraeme Gregory struct regulator_dev *rdev[TPS65910_NUM_REGULATOR]; 194518fb721SGraeme Gregory struct tps_info *info[TPS65910_NUM_REGULATOR]; 195518fb721SGraeme Gregory struct mutex mutex; 196518fb721SGraeme Gregory int mode; 197518fb721SGraeme Gregory }; 198518fb721SGraeme Gregory 199518fb721SGraeme Gregory static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg) 200518fb721SGraeme Gregory { 201518fb721SGraeme Gregory u8 val; 202518fb721SGraeme Gregory int err; 203518fb721SGraeme Gregory 204518fb721SGraeme Gregory err = pmic->mfd->read(pmic->mfd, reg, 1, &val); 205518fb721SGraeme Gregory if (err) 206518fb721SGraeme Gregory return err; 207518fb721SGraeme Gregory 208518fb721SGraeme Gregory return val; 209518fb721SGraeme Gregory } 210518fb721SGraeme Gregory 211518fb721SGraeme Gregory static inline int tps65910_write(struct tps65910_reg *pmic, u8 reg, u8 val) 212518fb721SGraeme Gregory { 213518fb721SGraeme Gregory return pmic->mfd->write(pmic->mfd, reg, 1, &val); 214518fb721SGraeme Gregory } 215518fb721SGraeme Gregory 216518fb721SGraeme Gregory static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg, 217518fb721SGraeme Gregory u8 set_mask, u8 clear_mask) 218518fb721SGraeme Gregory { 219518fb721SGraeme Gregory int err, data; 220518fb721SGraeme Gregory 221518fb721SGraeme Gregory mutex_lock(&pmic->mutex); 222518fb721SGraeme Gregory 223518fb721SGraeme Gregory data = tps65910_read(pmic, reg); 224518fb721SGraeme Gregory if (data < 0) { 225518fb721SGraeme Gregory dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg); 226518fb721SGraeme Gregory err = data; 227518fb721SGraeme Gregory goto out; 228518fb721SGraeme Gregory } 229518fb721SGraeme Gregory 230518fb721SGraeme Gregory data &= ~clear_mask; 231518fb721SGraeme Gregory data |= set_mask; 232518fb721SGraeme Gregory err = tps65910_write(pmic, reg, data); 233518fb721SGraeme Gregory if (err) 234518fb721SGraeme Gregory dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg); 235518fb721SGraeme Gregory 236518fb721SGraeme Gregory out: 237518fb721SGraeme Gregory mutex_unlock(&pmic->mutex); 238518fb721SGraeme Gregory return err; 239518fb721SGraeme Gregory } 240518fb721SGraeme Gregory 241518fb721SGraeme Gregory static int tps65910_reg_read(struct tps65910_reg *pmic, u8 reg) 242518fb721SGraeme Gregory { 243518fb721SGraeme Gregory int data; 244518fb721SGraeme Gregory 245518fb721SGraeme Gregory mutex_lock(&pmic->mutex); 246518fb721SGraeme Gregory 247518fb721SGraeme Gregory data = tps65910_read(pmic, reg); 248518fb721SGraeme Gregory if (data < 0) 249518fb721SGraeme Gregory dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg); 250518fb721SGraeme Gregory 251518fb721SGraeme Gregory mutex_unlock(&pmic->mutex); 252518fb721SGraeme Gregory return data; 253518fb721SGraeme Gregory } 254518fb721SGraeme Gregory 255518fb721SGraeme Gregory static int tps65910_reg_write(struct tps65910_reg *pmic, u8 reg, u8 val) 256518fb721SGraeme Gregory { 257518fb721SGraeme Gregory int err; 258518fb721SGraeme Gregory 259518fb721SGraeme Gregory mutex_lock(&pmic->mutex); 260518fb721SGraeme Gregory 261518fb721SGraeme Gregory err = tps65910_write(pmic, reg, val); 262518fb721SGraeme Gregory if (err < 0) 263518fb721SGraeme Gregory dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg); 264518fb721SGraeme Gregory 265518fb721SGraeme Gregory mutex_unlock(&pmic->mutex); 266518fb721SGraeme Gregory return err; 267518fb721SGraeme Gregory } 268518fb721SGraeme Gregory 269518fb721SGraeme Gregory static int tps65910_get_ctrl_register(int id) 270518fb721SGraeme Gregory { 271518fb721SGraeme Gregory switch (id) { 272518fb721SGraeme Gregory case TPS65910_REG_VRTC: 273518fb721SGraeme Gregory return TPS65910_VRTC; 274518fb721SGraeme Gregory case TPS65910_REG_VIO: 275518fb721SGraeme Gregory return TPS65910_VIO; 276518fb721SGraeme Gregory case TPS65910_REG_VDD1: 277518fb721SGraeme Gregory return TPS65910_VDD1; 278518fb721SGraeme Gregory case TPS65910_REG_VDD2: 279518fb721SGraeme Gregory return TPS65910_VDD2; 280518fb721SGraeme Gregory case TPS65910_REG_VDD3: 281518fb721SGraeme Gregory return TPS65910_VDD3; 282518fb721SGraeme Gregory case TPS65910_REG_VDIG1: 283518fb721SGraeme Gregory return TPS65910_VDIG1; 284518fb721SGraeme Gregory case TPS65910_REG_VDIG2: 285518fb721SGraeme Gregory return TPS65910_VDIG2; 286518fb721SGraeme Gregory case TPS65910_REG_VPLL: 287518fb721SGraeme Gregory return TPS65910_VPLL; 288518fb721SGraeme Gregory case TPS65910_REG_VDAC: 289518fb721SGraeme Gregory return TPS65910_VDAC; 290518fb721SGraeme Gregory case TPS65910_REG_VAUX1: 291518fb721SGraeme Gregory return TPS65910_VAUX1; 292518fb721SGraeme Gregory case TPS65910_REG_VAUX2: 293518fb721SGraeme Gregory return TPS65910_VAUX2; 294518fb721SGraeme Gregory case TPS65910_REG_VAUX33: 295518fb721SGraeme Gregory return TPS65910_VAUX33; 296518fb721SGraeme Gregory case TPS65910_REG_VMMC: 297518fb721SGraeme Gregory return TPS65910_VMMC; 298518fb721SGraeme Gregory default: 299518fb721SGraeme Gregory return -EINVAL; 300518fb721SGraeme Gregory } 301518fb721SGraeme Gregory } 302518fb721SGraeme Gregory 303518fb721SGraeme Gregory static int tps65910_is_enabled(struct regulator_dev *dev) 304518fb721SGraeme Gregory { 305518fb721SGraeme Gregory struct tps65910_reg *pmic = rdev_get_drvdata(dev); 306518fb721SGraeme Gregory int reg, value, id = rdev_get_id(dev); 307518fb721SGraeme Gregory 308518fb721SGraeme Gregory reg = tps65910_get_ctrl_register(id); 309518fb721SGraeme Gregory if (reg < 0) 310518fb721SGraeme Gregory return reg; 311518fb721SGraeme Gregory 312518fb721SGraeme Gregory value = tps65910_reg_read(pmic, reg); 313518fb721SGraeme Gregory if (value < 0) 314518fb721SGraeme Gregory return value; 315518fb721SGraeme Gregory 316518fb721SGraeme Gregory return value & TPS65910_SUPPLY_STATE_ENABLED; 317518fb721SGraeme Gregory } 318518fb721SGraeme Gregory 319518fb721SGraeme Gregory static int tps65910_enable(struct regulator_dev *dev) 320518fb721SGraeme Gregory { 321518fb721SGraeme Gregory struct tps65910_reg *pmic = rdev_get_drvdata(dev); 322518fb721SGraeme Gregory struct tps65910 *mfd = pmic->mfd; 323518fb721SGraeme Gregory int reg, id = rdev_get_id(dev); 324518fb721SGraeme Gregory 325518fb721SGraeme Gregory reg = tps65910_get_ctrl_register(id); 326518fb721SGraeme Gregory if (reg < 0) 327518fb721SGraeme Gregory return reg; 328518fb721SGraeme Gregory 329518fb721SGraeme Gregory return tps65910_set_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); 330518fb721SGraeme Gregory } 331518fb721SGraeme Gregory 332518fb721SGraeme Gregory static int tps65910_disable(struct regulator_dev *dev) 333518fb721SGraeme Gregory { 334518fb721SGraeme Gregory struct tps65910_reg *pmic = rdev_get_drvdata(dev); 335518fb721SGraeme Gregory struct tps65910 *mfd = pmic->mfd; 336518fb721SGraeme Gregory int reg, id = rdev_get_id(dev); 337518fb721SGraeme Gregory 338518fb721SGraeme Gregory reg = tps65910_get_ctrl_register(id); 339518fb721SGraeme Gregory if (reg < 0) 340518fb721SGraeme Gregory return reg; 341518fb721SGraeme Gregory 342518fb721SGraeme Gregory return tps65910_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); 343518fb721SGraeme Gregory } 344518fb721SGraeme Gregory 345518fb721SGraeme Gregory 346518fb721SGraeme Gregory static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) 347518fb721SGraeme Gregory { 348518fb721SGraeme Gregory struct tps65910_reg *pmic = rdev_get_drvdata(dev); 349518fb721SGraeme Gregory struct tps65910 *mfd = pmic->mfd; 350518fb721SGraeme Gregory int reg, value, id = rdev_get_id(dev); 351518fb721SGraeme Gregory reg = tps65910_get_ctrl_register(id); 352518fb721SGraeme Gregory if (reg < 0) 353518fb721SGraeme Gregory return reg; 354518fb721SGraeme Gregory 355518fb721SGraeme Gregory switch (mode) { 356518fb721SGraeme Gregory case REGULATOR_MODE_NORMAL: 357518fb721SGraeme Gregory return tps65910_modify_bits(pmic, reg, LDO_ST_ON_BIT, 358518fb721SGraeme Gregory LDO_ST_MODE_BIT); 359518fb721SGraeme Gregory case REGULATOR_MODE_IDLE: 360518fb721SGraeme Gregory value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT; 361518fb721SGraeme Gregory return tps65910_set_bits(mfd, reg, value); 362518fb721SGraeme Gregory case REGULATOR_MODE_STANDBY: 363518fb721SGraeme Gregory return tps65910_clear_bits(mfd, reg, LDO_ST_ON_BIT); 364518fb721SGraeme Gregory } 365518fb721SGraeme Gregory 366518fb721SGraeme Gregory return -EINVAL; 367518fb721SGraeme Gregory } 368518fb721SGraeme Gregory 369518fb721SGraeme Gregory static unsigned int tps65910_get_mode(struct regulator_dev *dev) 370518fb721SGraeme Gregory { 371518fb721SGraeme Gregory struct tps65910_reg *pmic = rdev_get_drvdata(dev); 372518fb721SGraeme Gregory int reg, value, id = rdev_get_id(dev); 373518fb721SGraeme Gregory 374518fb721SGraeme Gregory reg = tps65910_get_ctrl_register(id); 375518fb721SGraeme Gregory if (reg < 0) 376518fb721SGraeme Gregory return reg; 377518fb721SGraeme Gregory 378518fb721SGraeme Gregory value = tps65910_reg_read(pmic, reg); 379518fb721SGraeme Gregory if (value < 0) 380518fb721SGraeme Gregory return value; 381518fb721SGraeme Gregory 382518fb721SGraeme Gregory if (value & LDO_ST_ON_BIT) 383518fb721SGraeme Gregory return REGULATOR_MODE_STANDBY; 384518fb721SGraeme Gregory else if (value & LDO_ST_MODE_BIT) 385518fb721SGraeme Gregory return REGULATOR_MODE_IDLE; 386518fb721SGraeme Gregory else 387518fb721SGraeme Gregory return REGULATOR_MODE_NORMAL; 388518fb721SGraeme Gregory } 389518fb721SGraeme Gregory 390518fb721SGraeme Gregory static int tps65910_get_voltage_dcdc(struct regulator_dev *dev) 391518fb721SGraeme Gregory { 392518fb721SGraeme Gregory struct tps65910_reg *pmic = rdev_get_drvdata(dev); 393518fb721SGraeme Gregory int id = rdev_get_id(dev), voltage = 0; 394518fb721SGraeme Gregory int opvsel = 0, srvsel = 0, mult = 0, sr = 0; 395518fb721SGraeme Gregory 396518fb721SGraeme Gregory switch (id) { 397518fb721SGraeme Gregory case TPS65910_REG_VDD1: 398518fb721SGraeme Gregory opvsel = tps65910_reg_read(pmic, TPS65910_VDD1_OP); 399518fb721SGraeme Gregory mult = tps65910_reg_read(pmic, TPS65910_VDD1); 400518fb721SGraeme Gregory mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT; 401518fb721SGraeme Gregory srvsel = tps65910_reg_read(pmic, TPS65910_VDD1_SR); 402518fb721SGraeme Gregory sr = opvsel & VDD1_OP_CMD_MASK; 403518fb721SGraeme Gregory opvsel &= VDD1_OP_SEL_MASK; 404518fb721SGraeme Gregory srvsel &= VDD1_SR_SEL_MASK; 405518fb721SGraeme Gregory break; 406518fb721SGraeme Gregory case TPS65910_REG_VDD2: 407518fb721SGraeme Gregory opvsel = tps65910_reg_read(pmic, TPS65910_VDD2_OP); 408518fb721SGraeme Gregory mult = tps65910_reg_read(pmic, TPS65910_VDD2); 409518fb721SGraeme Gregory mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT; 410518fb721SGraeme Gregory srvsel = tps65910_reg_read(pmic, TPS65910_VDD2_SR); 411518fb721SGraeme Gregory sr = opvsel & VDD2_OP_CMD_MASK; 412518fb721SGraeme Gregory opvsel &= VDD2_OP_SEL_MASK; 413518fb721SGraeme Gregory srvsel &= VDD2_SR_SEL_MASK; 414518fb721SGraeme Gregory break; 415518fb721SGraeme Gregory } 416518fb721SGraeme Gregory 417518fb721SGraeme Gregory /* multiplier 0 == 1 but 2,3 normal */ 418518fb721SGraeme Gregory if (!mult) 419518fb721SGraeme Gregory mult=1; 420518fb721SGraeme Gregory 421518fb721SGraeme Gregory if (sr) { 422518fb721SGraeme Gregory /* Valid range is 3-75 so normalise */ 423518fb721SGraeme Gregory if (srvsel < 3) srvsel = 3; 424518fb721SGraeme Gregory if (srvsel > 75) srvsel = 75; 425518fb721SGraeme Gregory srvsel -= 3; 426518fb721SGraeme Gregory 427518fb721SGraeme Gregory voltage = (srvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100; 428518fb721SGraeme Gregory } else { 429518fb721SGraeme Gregory 430518fb721SGraeme Gregory /* Valid range is 3-75 so normalise */ 431518fb721SGraeme Gregory if (opvsel < 3) opvsel = 3; 432518fb721SGraeme Gregory if (opvsel > 75) opvsel = 75; 433518fb721SGraeme Gregory opvsel -= 3; 434518fb721SGraeme Gregory 435518fb721SGraeme Gregory voltage = (opvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100; 436518fb721SGraeme Gregory } 437518fb721SGraeme Gregory 438518fb721SGraeme Gregory voltage *= mult; 439518fb721SGraeme Gregory 440518fb721SGraeme Gregory return voltage; 441518fb721SGraeme Gregory } 442518fb721SGraeme Gregory 443518fb721SGraeme Gregory static int tps65910_get_voltage(struct regulator_dev *dev) 444518fb721SGraeme Gregory { 445518fb721SGraeme Gregory struct tps65910_reg *pmic = rdev_get_drvdata(dev); 446518fb721SGraeme Gregory int reg, value, id = rdev_get_id(dev), voltage = 0; 447518fb721SGraeme Gregory 448518fb721SGraeme Gregory reg = tps65910_get_ctrl_register(id); 449518fb721SGraeme Gregory if (reg < 0) 450518fb721SGraeme Gregory return reg; 451518fb721SGraeme Gregory 452518fb721SGraeme Gregory value = tps65910_reg_read(pmic, reg); 453518fb721SGraeme Gregory if (value < 0) 454518fb721SGraeme Gregory return value; 455518fb721SGraeme Gregory 456518fb721SGraeme Gregory switch (id) { 457518fb721SGraeme Gregory case TPS65910_REG_VIO: 458518fb721SGraeme Gregory case TPS65910_REG_VDIG1: 459518fb721SGraeme Gregory case TPS65910_REG_VDIG2: 460518fb721SGraeme Gregory case TPS65910_REG_VPLL: 461518fb721SGraeme Gregory case TPS65910_REG_VDAC: 462518fb721SGraeme Gregory case TPS65910_REG_VAUX1: 463518fb721SGraeme Gregory case TPS65910_REG_VAUX2: 464518fb721SGraeme Gregory case TPS65910_REG_VAUX33: 465518fb721SGraeme Gregory case TPS65910_REG_VMMC: 466518fb721SGraeme Gregory value &= LDO_SEL_MASK; 467518fb721SGraeme Gregory value >>= LDO_SEL_SHIFT; 468518fb721SGraeme Gregory break; 469518fb721SGraeme Gregory default: 470518fb721SGraeme Gregory return -EINVAL; 471518fb721SGraeme Gregory } 472518fb721SGraeme Gregory 473518fb721SGraeme Gregory voltage = pmic->info[id]->table[value] * 1000; 474518fb721SGraeme Gregory 475518fb721SGraeme Gregory return voltage; 476518fb721SGraeme Gregory } 477518fb721SGraeme Gregory 478518fb721SGraeme Gregory static int tps65910_get_voltage_vdd3(struct regulator_dev *dev) 479518fb721SGraeme Gregory { 480518fb721SGraeme Gregory return 5 * 1000 * 1000; 481518fb721SGraeme Gregory } 482518fb721SGraeme Gregory 483518fb721SGraeme Gregory static int tps65910_set_voltage_dcdc(struct regulator_dev *dev, 484518fb721SGraeme Gregory unsigned selector) 485518fb721SGraeme Gregory { 486518fb721SGraeme Gregory struct tps65910_reg *pmic = rdev_get_drvdata(dev); 487518fb721SGraeme Gregory int id = rdev_get_id(dev), vsel; 488518fb721SGraeme Gregory int dcdc_mult; 489518fb721SGraeme Gregory 490518fb721SGraeme Gregory /* Split vsel into appropriate registers */ 491518fb721SGraeme Gregory dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1; 492518fb721SGraeme Gregory if (dcdc_mult == 1) dcdc_mult--; 493518fb721SGraeme Gregory 494518fb721SGraeme Gregory vsel = (selector % VDD1_2_NUM_VOLTS) + 3; 495518fb721SGraeme Gregory 496518fb721SGraeme Gregory if (id == TPS65910_REG_VDD1) { 497518fb721SGraeme Gregory tps65910_modify_bits(pmic, TPS65910_VDD1, 498518fb721SGraeme Gregory (dcdc_mult << VDD1_VGAIN_SEL_SHIFT), 499518fb721SGraeme Gregory VDD1_VGAIN_SEL_MASK); 500518fb721SGraeme Gregory tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel); 501518fb721SGraeme Gregory } else { 502518fb721SGraeme Gregory tps65910_modify_bits(pmic, TPS65910_VDD2, 503518fb721SGraeme Gregory (dcdc_mult << VDD2_VGAIN_SEL_SHIFT), 504518fb721SGraeme Gregory VDD1_VGAIN_SEL_MASK); 505518fb721SGraeme Gregory tps65910_reg_write(pmic, TPS65910_VDD2_OP, vsel); 506518fb721SGraeme Gregory } 507518fb721SGraeme Gregory 508518fb721SGraeme Gregory return 0; 509518fb721SGraeme Gregory } 510518fb721SGraeme Gregory 511518fb721SGraeme Gregory static int tps65910_set_voltage(struct regulator_dev *dev, unsigned selector) 512518fb721SGraeme Gregory { 513518fb721SGraeme Gregory struct tps65910_reg *pmic = rdev_get_drvdata(dev); 514518fb721SGraeme Gregory int reg, id = rdev_get_id(dev); 515518fb721SGraeme Gregory 516518fb721SGraeme Gregory reg = tps65910_get_ctrl_register(id); 517518fb721SGraeme Gregory if (reg < 0) 518518fb721SGraeme Gregory return reg; 519518fb721SGraeme Gregory 520518fb721SGraeme Gregory switch (id) { 521518fb721SGraeme Gregory case TPS65910_REG_VIO: 522518fb721SGraeme Gregory case TPS65910_REG_VDIG1: 523518fb721SGraeme Gregory case TPS65910_REG_VDIG2: 524518fb721SGraeme Gregory case TPS65910_REG_VPLL: 525518fb721SGraeme Gregory case TPS65910_REG_VDAC: 526518fb721SGraeme Gregory case TPS65910_REG_VAUX1: 527518fb721SGraeme Gregory case TPS65910_REG_VAUX2: 528518fb721SGraeme Gregory case TPS65910_REG_VAUX33: 529518fb721SGraeme Gregory case TPS65910_REG_VMMC: 530518fb721SGraeme Gregory return tps65910_modify_bits(pmic, reg, 531518fb721SGraeme Gregory (selector << LDO_SEL_SHIFT), LDO_SEL_MASK); 532518fb721SGraeme Gregory } 533518fb721SGraeme Gregory 534518fb721SGraeme Gregory return -EINVAL; 535518fb721SGraeme Gregory } 536518fb721SGraeme Gregory 537518fb721SGraeme Gregory static int tps65910_list_voltage_dcdc(struct regulator_dev *dev, 538518fb721SGraeme Gregory unsigned selector) 539518fb721SGraeme Gregory { 540518fb721SGraeme Gregory int mult, volt; 541518fb721SGraeme Gregory 542518fb721SGraeme Gregory mult = (selector / VDD1_2_NUM_VOLTS) + 1; 543518fb721SGraeme Gregory 544518fb721SGraeme Gregory volt = VDD1_2_MIN_VOLT + (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET; 545518fb721SGraeme Gregory 546518fb721SGraeme Gregory return volt * 100 * mult; 547518fb721SGraeme Gregory } 548518fb721SGraeme Gregory 549518fb721SGraeme Gregory static int tps65910_list_voltage(struct regulator_dev *dev, 550518fb721SGraeme Gregory unsigned selector) 551518fb721SGraeme Gregory { 552518fb721SGraeme Gregory struct tps65910_reg *pmic = rdev_get_drvdata(dev); 553518fb721SGraeme Gregory int id = rdev_get_id(dev), voltage; 554518fb721SGraeme Gregory 555518fb721SGraeme Gregory if (id < TPS65910_REG_VIO || id > TPS65910_REG_VMMC) 556518fb721SGraeme Gregory return -EINVAL; 557518fb721SGraeme Gregory 558518fb721SGraeme Gregory if (selector >= pmic->info[id]->table_len) 559518fb721SGraeme Gregory return -EINVAL; 560518fb721SGraeme Gregory else 561518fb721SGraeme Gregory voltage = pmic->info[id]->table[selector] * 1000; 562518fb721SGraeme Gregory 563518fb721SGraeme Gregory return voltage; 564518fb721SGraeme Gregory } 565518fb721SGraeme Gregory 566518fb721SGraeme Gregory /* Regulator ops (except VRTC) */ 567518fb721SGraeme Gregory static struct regulator_ops tps65910_ops_dcdc = { 568518fb721SGraeme Gregory .is_enabled = tps65910_is_enabled, 569518fb721SGraeme Gregory .enable = tps65910_enable, 570518fb721SGraeme Gregory .disable = tps65910_disable, 571518fb721SGraeme Gregory .set_mode = tps65910_set_mode, 572518fb721SGraeme Gregory .get_mode = tps65910_get_mode, 573518fb721SGraeme Gregory .get_voltage = tps65910_get_voltage_dcdc, 574518fb721SGraeme Gregory .set_voltage_sel = tps65910_set_voltage_dcdc, 575518fb721SGraeme Gregory .list_voltage = tps65910_list_voltage_dcdc, 576518fb721SGraeme Gregory }; 577518fb721SGraeme Gregory 578518fb721SGraeme Gregory static struct regulator_ops tps65910_ops_vdd3 = { 579518fb721SGraeme Gregory .is_enabled = tps65910_is_enabled, 580518fb721SGraeme Gregory .enable = tps65910_enable, 581518fb721SGraeme Gregory .disable = tps65910_disable, 582518fb721SGraeme Gregory .set_mode = tps65910_set_mode, 583518fb721SGraeme Gregory .get_mode = tps65910_get_mode, 584518fb721SGraeme Gregory .get_voltage = tps65910_get_voltage_vdd3, 585518fb721SGraeme Gregory .list_voltage = tps65910_list_voltage, 586518fb721SGraeme Gregory }; 587518fb721SGraeme Gregory 588518fb721SGraeme Gregory static struct regulator_ops tps65910_ops = { 589518fb721SGraeme Gregory .is_enabled = tps65910_is_enabled, 590518fb721SGraeme Gregory .enable = tps65910_enable, 591518fb721SGraeme Gregory .disable = tps65910_disable, 592518fb721SGraeme Gregory .set_mode = tps65910_set_mode, 593518fb721SGraeme Gregory .get_mode = tps65910_get_mode, 594518fb721SGraeme Gregory .get_voltage = tps65910_get_voltage, 595518fb721SGraeme Gregory .set_voltage_sel = tps65910_set_voltage, 596518fb721SGraeme Gregory .list_voltage = tps65910_list_voltage, 597518fb721SGraeme Gregory }; 598518fb721SGraeme Gregory 599518fb721SGraeme Gregory static __devinit int tps65910_probe(struct platform_device *pdev) 600518fb721SGraeme Gregory { 601518fb721SGraeme Gregory struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); 602518fb721SGraeme Gregory struct tps_info *info = tps65910_regs; 603518fb721SGraeme Gregory struct regulator_init_data *reg_data; 604518fb721SGraeme Gregory struct regulator_dev *rdev; 605518fb721SGraeme Gregory struct tps65910_reg *pmic; 606518fb721SGraeme Gregory struct tps65910_board *pmic_plat_data; 607518fb721SGraeme Gregory int i, err; 608518fb721SGraeme Gregory 609518fb721SGraeme Gregory pmic_plat_data = dev_get_platdata(tps65910->dev); 610518fb721SGraeme Gregory if (!pmic_plat_data) 611518fb721SGraeme Gregory return -EINVAL; 612518fb721SGraeme Gregory 613518fb721SGraeme Gregory reg_data = pmic_plat_data->tps65910_pmic_init_data; 614518fb721SGraeme Gregory 615518fb721SGraeme Gregory pmic = kzalloc(sizeof(*pmic), GFP_KERNEL); 616518fb721SGraeme Gregory if (!pmic) 617518fb721SGraeme Gregory return -ENOMEM; 618518fb721SGraeme Gregory 619518fb721SGraeme Gregory mutex_init(&pmic->mutex); 620518fb721SGraeme Gregory pmic->mfd = tps65910; 621518fb721SGraeme Gregory platform_set_drvdata(pdev, pmic); 622518fb721SGraeme Gregory 623518fb721SGraeme Gregory /* Give control of all register to control port */ 624518fb721SGraeme Gregory tps65910_set_bits(pmic->mfd, TPS65910_DEVCTRL, 625518fb721SGraeme Gregory DEVCTRL_SR_CTL_I2C_SEL_MASK); 626518fb721SGraeme Gregory 627518fb721SGraeme Gregory for (i = 0; i < TPS65910_NUM_REGULATOR; i++, info++, reg_data++) { 628518fb721SGraeme Gregory /* Register the regulators */ 629518fb721SGraeme Gregory pmic->info[i] = info; 630518fb721SGraeme Gregory 631518fb721SGraeme Gregory pmic->desc[i].name = info->name; 63277fa44d0SAxel Lin pmic->desc[i].id = i; 633518fb721SGraeme Gregory pmic->desc[i].n_voltages = info->table_len; 634518fb721SGraeme Gregory 635518fb721SGraeme Gregory if ((i == TPS65910_REG_VDD1) || (i == TPS65910_REG_VDD2)) 636518fb721SGraeme Gregory pmic->desc[i].ops = &tps65910_ops_dcdc; 637518fb721SGraeme Gregory else if (i == TPS65910_REG_VDD3) 638518fb721SGraeme Gregory pmic->desc[i].ops = &tps65910_ops_vdd3; 639518fb721SGraeme Gregory else 640518fb721SGraeme Gregory pmic->desc[i].ops = &tps65910_ops; 641518fb721SGraeme Gregory 642518fb721SGraeme Gregory pmic->desc[i].type = REGULATOR_VOLTAGE; 643518fb721SGraeme Gregory pmic->desc[i].owner = THIS_MODULE; 644518fb721SGraeme Gregory 645518fb721SGraeme Gregory rdev = regulator_register(&pmic->desc[i], 646518fb721SGraeme Gregory tps65910->dev, reg_data, pmic); 647518fb721SGraeme Gregory if (IS_ERR(rdev)) { 648518fb721SGraeme Gregory dev_err(tps65910->dev, 649518fb721SGraeme Gregory "failed to register %s regulator\n", 650518fb721SGraeme Gregory pdev->name); 651518fb721SGraeme Gregory err = PTR_ERR(rdev); 652518fb721SGraeme Gregory goto err; 653518fb721SGraeme Gregory } 654518fb721SGraeme Gregory 655518fb721SGraeme Gregory /* Save regulator for cleanup */ 656518fb721SGraeme Gregory pmic->rdev[i] = rdev; 657518fb721SGraeme Gregory } 658518fb721SGraeme Gregory return 0; 659518fb721SGraeme Gregory 660518fb721SGraeme Gregory err: 661518fb721SGraeme Gregory while (--i >= 0) 662518fb721SGraeme Gregory regulator_unregister(pmic->rdev[i]); 663518fb721SGraeme Gregory 664518fb721SGraeme Gregory kfree(pmic); 665518fb721SGraeme Gregory return err; 666518fb721SGraeme Gregory } 667518fb721SGraeme Gregory 668518fb721SGraeme Gregory static int __devexit tps65910_remove(struct platform_device *pdev) 669518fb721SGraeme Gregory { 670518fb721SGraeme Gregory struct tps65910_reg *tps65910_reg = platform_get_drvdata(pdev); 671518fb721SGraeme Gregory int i; 672518fb721SGraeme Gregory 673518fb721SGraeme Gregory for (i = 0; i < TPS65910_NUM_REGULATOR; i++) 674518fb721SGraeme Gregory regulator_unregister(tps65910_reg->rdev[i]); 675518fb721SGraeme Gregory 676518fb721SGraeme Gregory kfree(tps65910_reg); 677518fb721SGraeme Gregory return 0; 678518fb721SGraeme Gregory } 679518fb721SGraeme Gregory 680518fb721SGraeme Gregory static struct platform_driver tps65910_driver = { 681518fb721SGraeme Gregory .driver = { 682518fb721SGraeme Gregory .name = "tps65910-pmic", 683518fb721SGraeme Gregory .owner = THIS_MODULE, 684518fb721SGraeme Gregory }, 685518fb721SGraeme Gregory .probe = tps65910_probe, 686518fb721SGraeme Gregory .remove = __devexit_p(tps65910_remove), 687518fb721SGraeme Gregory }; 688518fb721SGraeme Gregory 689518fb721SGraeme Gregory static int __init tps65910_init(void) 690518fb721SGraeme Gregory { 691518fb721SGraeme Gregory return platform_driver_register(&tps65910_driver); 692518fb721SGraeme Gregory } 693518fb721SGraeme Gregory subsys_initcall(tps65910_init); 694518fb721SGraeme Gregory 695518fb721SGraeme Gregory static void __exit tps65910_cleanup(void) 696518fb721SGraeme Gregory { 697518fb721SGraeme Gregory platform_driver_unregister(&tps65910_driver); 698518fb721SGraeme Gregory } 699518fb721SGraeme Gregory module_exit(tps65910_cleanup); 700518fb721SGraeme Gregory 701518fb721SGraeme Gregory MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); 702518fb721SGraeme Gregory MODULE_DESCRIPTION("TPS6507x voltage regulator driver"); 703518fb721SGraeme Gregory MODULE_LICENSE("GPL v2"); 704518fb721SGraeme Gregory MODULE_ALIAS("platform:tps65910-pmic"); 705