static int twlreg_disable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; int ret; grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; /* For 6030, set the off state for all grps enabled */ if (twl_class_is_6030()) { ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, (grp & (P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030)) << TWL6030_CFG_STATE_GRP_SHIFT | TWL6030_CFG_STATE_OFF); if (ret) return ret; } if (twl_class_is_4030()) grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030); else grp &= ~(P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030); ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); /* Next, associate cleared grp in state register */ if (!ret && twl_class_is_6030()) ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, grp << TWL6030_CFG_STATE_GRP_SHIFT | TWL6030_CFG_STATE_OFF); return ret; }
static int twlreg_enable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; int ret; grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; if (twl_class_is_4030()) grp |= P1_GRP_4030; else grp |= P1_GRP_6030; ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); if (!ret && twl_class_is_6030()) ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, grp << TWL6030_CFG_STATE_GRP_SHIFT | TWL6030_CFG_STATE_ON); udelay(info->delay); return ret; }
int twlreg_refresh(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); u16 delay=1000; int stat; int grp; int backup_stat; int backup_grp; int ret=0; grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; backup_grp = grp; grp |= 0x07; ret=twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); if (ret < 0) return ret; stat = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE); if (stat < 0) return stat; backup_stat = stat; stat = 0xE0; ret=twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, stat); if (ret < 0) { twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, backup_grp); return ret; } udelay(delay); grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); grp |= 0x07; ret=twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); stat = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE); stat = 0xE1; ret=twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, stat); udelay(delay/2); ret=twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, backup_grp); if (ret < 0) { twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, backup_stat); return ret; } ret=twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, backup_stat); if (ret < 0) return ret; return ret; }
static int twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel; for (vsel = 0; vsel < info->table_len; vsel++) { int mV = info->table[vsel]; int uV; if (IS_UNSUP(mV)) continue; uV = LDO_MV(mV) * 1000; /* REVISIT for VAUX2, first match may not be best/lowest */ /* use the first in-range value */ if (min_uV <= uV && uV <= max_uV){ printk("%s : %s uV=%d\n",__func__,rdev->desc->name,uV); return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel); } } return -EDOM; }
static int twl6030reg_enable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp = 0; int ret; if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, grp << TWL6030_CFG_STATE_GRP_SHIFT | TWL6030_CFG_STATE_ON); /* * Ensure it stays in Auto mode when we enter suspend state. * (TWL6030 in sleep mode). */ if (!ret) ret = twl6030reg_set_trans_state(rdev, TWL6030_CFG_TRANS_SLEEP_SHIFT, TWL6030_CFG_TRANS_STATE_AUTO); udelay(info->delay); return ret; }
static int twl6030reg_set_trans_state(struct regulator_dev *rdev, u8 shift, u8 val) { struct twlreg_info *info = rdev_get_drvdata(rdev); int rval; u8 mask; /* Read CFG_TRANS register of TWL6030 */ rval = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_TRANS); if (rval < 0) return rval; mask = TWL6030_CFG_TRANS_STATE_MASK << shift; val = (val << shift) & mask; /* If value is already set, no need to write to reg */ if (val == (rval & mask)) return 0; rval &= ~mask; rval |= val; return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_TRANS, rval); }
static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp = 0; int val; if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) grp = twlreg_grp(rdev); if (grp < 0) return grp; /* Compose the state register settings */ val = grp << TWL6030_CFG_STATE_GRP_SHIFT; /* We can only set the mode through state machine commands... */ switch (mode) { case REGULATOR_MODE_NORMAL: val |= TWL6030_CFG_STATE_ON; break; case REGULATOR_MODE_STANDBY: val |= TWL6030_CFG_STATE_SLEEP; break; default: return -EINVAL; } return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, val); }
static int twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel; for (vsel = 0; vsel < info->table_len; vsel++) { int mV = info->table[vsel]; int uV; if (IS_UNSUP(mV)) continue; uV = LDO_MV(mV) * 1000; if (min_uV <= uV && uV <= max_uV) { *selector = vsel; return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel); } } return -EDOM; }
static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp = 0; int val; if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; val = grp << TWL6030_CFG_STATE_GRP_SHIFT; switch (mode) { case REGULATOR_MODE_NORMAL: val |= TWL6030_CFG_STATE_ON; break; case REGULATOR_MODE_STANDBY: val |= TWL6030_CFG_STATE_SLEEP; break; default: return -EINVAL; } return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, val); }
static int twl6030smps_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector) { struct twlreg_info *info = rdev_get_drvdata(rdev); return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS, selector); }
static int twl4030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel = DIV_ROUND_UP(min_uV - 600000, 12500); twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS_4030, vsel); return 0; }
static int twl6030_enable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int state; int ret; state = twlreg_read(info, TWL_MODULE_PM_RECEIVER, 2); state |= 1; ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, 2 , state); state = twlreg_read(info, TWL_MODULE_PM_RECEIVER, 2); printk("%s: %s state=0x%x\n",__func__,rdev->desc->name,state); udelay(info->delay); return ret; }
static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; int val = 0; int trans_val = 0; grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; trans_val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_TRANS); /* For ACT map to ACT and SLEEP map to AMS */ trans_val |= (0x1 << TWL6030_CFG_TRANS_SLEEP) | (0x3 << TWL6030_CFG_TRANS_ACT); trans_val = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_TRANS, trans_val); if (trans_val < 0) return trans_val; /* Compose the state register settings */ val = grp << TWL6030_CFG_STATE_GRP_SHIFT; /* We can only set the mode through state machine commands... */ switch (mode) { case REGULATOR_MODE_NORMAL: val |= TWL6030_CFG_STATE_ON; break; case REGULATOR_MODE_STANDBY: val |= TWL6030_CFG_STATE_SLEEP; break; default: return -EINVAL; } return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, val); }
static int twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel; if ((min_uV/1000 < info->min_mV) || (max_uV/1000 > info->max_mV)) return -EDOM; vsel = (min_uV/1000 - 1000)/100 + 1; *selector = vsel; return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel); }
static int twl6030_disable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int state; int ret; state = twlreg_read(info, TWL_MODULE_PM_RECEIVER, 2); // if (state < 0) // return state; //state &= ~ 3; state=0; printk("%s: %s state=0x%x\n",__func__,rdev->desc->name,state); ret= twlreg_write(info, TWL_MODULE_PM_RECEIVER, 2, 0); return ret; }
static int twlreg_disable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; if (twl_class_is_4030()) grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030); else grp &= ~(P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030); return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); }
static int twl4030reg_disable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; int ret; grp = twlreg_grp(rdev); if (grp < 0) return grp; grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030); ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); return ret; }
static int twl6030reg_disable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp = 0; int ret; if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030; /* For 6030, set the off state for all grps enabled */ ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, (grp) << TWL6030_CFG_STATE_GRP_SHIFT | TWL6030_CFG_STATE_OFF); return ret; }
static int twl6030reg_enable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp = 0; int ret; if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) grp = twlreg_grp(rdev); if (grp < 0) return grp; ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, grp << TWL6030_CFG_STATE_GRP_SHIFT | TWL6030_CFG_STATE_ON); return ret; }
static int twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel; if ((min_uV/1000 < info->min_mV) || (max_uV/1000 > info->max_mV)) return -EDOM; /* * Use the below formula to calculate vsel * mV = 1000mv + 100mv * (vsel - 1) */ vsel = (min_uV/1000 - 1000)/100 + 1; return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel); }
static int twlreg_disable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; int ret; grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; if (twl_class_is_4030()) grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030); else grp &= ~(P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030); ret= twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); printk("%s : %s info->base=0x%x grp=0x%x \n",__func__,rdev->desc->name,info->base , grp); return ret; }
static int twl4030reg_enable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; int ret; grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; grp |= P1_GRP_4030; ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); udelay(info->delay); return ret; }
static int twl6030reg_disable(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); int grp = 0; int ret; if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030; /* For 6030, set the off state for all grps enabled */ ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, (grp) << TWL6030_CFG_STATE_GRP_SHIFT | TWL6030_CFG_STATE_OFF); /* Ensure it remains OFF when we enter suspend (TWL6030 in sleep). */ if (!ret) ret = twl6030reg_set_trans_state(rdev, TWL6030_CFG_TRANS_SLEEP_SHIFT, TWL6030_CFG_TRANS_STATE_OFF); return ret; }
static int twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel; if ((min_uV/1000 < info->min_mV) || (max_uV/1000 > info->max_mV)) return -EDOM; /* * Use the below formula to calculate vsel * mV = 1000mv + 100mv * (vsel - 1) */ vsel = (min_uV/1000 - 1000)/100 + 1; *selector = vsel; #ifdef CONFIG_JET_V2 if(info->base == 0x68) // LDO5 vsel |= TWL6030_CFG_VOLTAGE_WR_S_BIT; // WR_S Keep the voltage configuration settings, same VSEL [5:0] value justbefore the warm reset event. #endif return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel); }
static int __devinit twlreg_probe(struct platform_device *pdev) { int i; struct twlreg_info *info; struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; int ret; for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) { if (twl_regs[i].desc.id != pdev->id) continue; info = twl_regs + i; break; } if (!info) return -ENODEV; initdata = pdev->dev.platform_data; if (!initdata) return -EINVAL; /* copy the features into regulator data */ info->features = (unsigned long)initdata->driver_data; /* Constrain board-specific capabilities according to what * this driver and the chip itself can actually do. */ c = &initdata->constraints; c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY; c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS; switch (pdev->id) { case TWL4030_REG_VIO: case TWL4030_REG_VDD1: case TWL4030_REG_VDD2: case TWL4030_REG_VPLL1: case TWL4030_REG_VINTANA1: case TWL4030_REG_VINTANA2: case TWL4030_REG_VINTDIG: c->always_on = true; break; case TWL6030_REG_VUSB: /* Program CFG_LDO_PD2 register and set VUSB bit */ ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, 0x1, TWL6030_CFG_LDO_PD2); if (ret < 0) return ret; /* Program MISC2 register and set bit VUSB_IN_VBAT */ ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, 0x10, TWL6030_MISC2); if (ret < 0) return ret; break; default: break; } switch (pdev->id) { case TWL6032_REG_SMPS3: if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3) info->flags |= SMPS_OFFSET_EN; break; case TWL6032_REG_SMPS4: if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4) info->flags |= SMPS_OFFSET_EN; break; case TWL6032_REG_VIO: if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO) info->flags |= SMPS_OFFSET_EN; break; } rdev = regulator_register(&info->desc, &pdev->dev, initdata, info); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "can't register %s, %ld\n", info->desc.name, PTR_ERR(rdev)); return PTR_ERR(rdev); } platform_set_drvdata(pdev, rdev); if (twl_class_is_4030()) twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP, info->remap); /* NOTE: many regulators support short-circuit IRQs (presentable * as REGULATOR_OVER_CURRENT notifications?) configured via: * - SC_CONFIG * - SC_DETECT1 (vintana2, vmmc1/2, vaux1/2/3/4) * - SC_DETECT2 (vusb, vdac, vio, vdd1/2, vpll2) * - IT_CONFIG */ return 0; }
static int __devinit twlreg_probe(struct platform_device *pdev) { int i, id; struct twlreg_info *info; struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; struct twl_regulator_driver_data *drvdata; const struct of_device_id *match; u32 twl_errata = 0; match = of_match_device(twl_of_match, &pdev->dev); if (match) { info = match->data; id = info->desc.id; initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); drvdata = NULL; } else { id = pdev->id; initdata = pdev->dev.platform_data; for (i = 0, info = NULL; i < ARRAY_SIZE(twl_of_match); i++) { info = twl_of_match[i].data; if (!info || info->desc.id != id) continue; break; } drvdata = initdata->driver_data; if (!drvdata) return -EINVAL; } if (!info) return -ENODEV; if (!initdata) return -EINVAL; if (drvdata) { /* copy the driver data into regulator data */ info->features = drvdata->features; twl_errata = drvdata->errata; info->data = drvdata->data; info->set_voltage = drvdata->set_voltage; info->get_voltage = drvdata->get_voltage; } /* Constrain board-specific capabilities according to what * this driver and the chip itself can actually do. */ c = &initdata->constraints; c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY; c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS; switch (id) { case TWL4030_REG_VIO: case TWL4030_REG_VDD1: case TWL4030_REG_VDD2: case TWL4030_REG_VPLL1: case TWL4030_REG_VINTANA1: case TWL4030_REG_VINTANA2: case TWL4030_REG_VINTDIG: c->always_on = true; break; default: break; } switch (id) { case TWL6032_REG_SMPS3: if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3) info->flags |= SMPS_OFFSET_EN; break; case TWL6032_REG_SMPS4: if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4) info->flags |= SMPS_OFFSET_EN; break; case TWL6032_REG_VIO: if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO) info->flags |= SMPS_OFFSET_EN; break; case TWL6030_REG_SYSEN: case TWL6032_REG_LDO6: case TWL6032_REG_LDOLN: if (twl_errata & TWL6032_ERRATA_LDO_MUST_BE_ALWAYS_ON) { c->state_mem.enabled = true; c->state_mem.disabled = false; } break; } rdev = regulator_register(&info->desc, &pdev->dev, initdata, info, pdev->dev.of_node); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "can't register %s, %ld\n", info->desc.name, PTR_ERR(rdev)); return PTR_ERR(rdev); } platform_set_drvdata(pdev, rdev); if (twl_class_is_4030()) twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP, info->remap); /* NOTE: many regulators support short-circuit IRQs (presentable * as REGULATOR_OVER_CURRENT notifications?) configured via: * - SC_CONFIG * - SC_DETECT1 (vintana2, vmmc1/2, vaux1/2/3/4) * - SC_DETECT2 (vusb, vdac, vio, vdd1/2, vpll2) * - IT_CONFIG */ return 0; }
static int __devinit twlreg_probe(struct platform_device *pdev) { int i; struct twlreg_info *info; struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) { if (twl_regs[i].desc.id != pdev->id) continue; info = twl_regs + i; break; } if (!info) return -ENODEV; initdata = pdev->dev.platform_data; if (!initdata) return -EINVAL; /* Constrain board-specific capabilities according to what * this driver and the chip itself can actually do. */ c = &initdata->constraints; c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY; c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS; switch (pdev->id) { case TWL4030_REG_VIO: case TWL4030_REG_VDD1: case TWL4030_REG_VDD2: case TWL4030_REG_VPLL1: case TWL4030_REG_VINTANA1: case TWL4030_REG_VINTANA2: case TWL4030_REG_VINTDIG: c->always_on = true; break; /* * TODO: This is needed for a Phoenix ES1.0 Errata. * Once, ES check for Phoenix is implemented. Make * this conditional only for ES1. */ case TWL6030_REG_VAUX3_6030: /* Set duty-cycle to 100% */ twl_i2c_write_u8(TWL6030_MODULE_ID1, 0, TWL6030_VIBCTRL); /* Enable the Vibrator driver */ twl_i2c_write_u8(TWL6030_MODULE_ID1, 128, TWL6030_TOGGLE2); break; default: break; } rdev = regulator_register(&info->desc, &pdev->dev, initdata, info); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "can't register %s, %ld\n", info->desc.name, PTR_ERR(rdev)); return PTR_ERR(rdev); } platform_set_drvdata(pdev, rdev); if (twl_class_is_4030()) twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP, info->remap); /* NOTE: many regulators support short-circuit IRQs (presentable * as REGULATOR_OVER_CURRENT notifications?) configured via: * - SC_CONFIG * - SC_DETECT1 (vintana2, vmmc1/2, vaux1/2/3/4) * - SC_DETECT2 (vusb, vdac, vio, vdd1/2, vpll2) * - IT_CONFIG */ return 0; }
static int twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned int *selector) { struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel = 0; switch (info->flags) { case 0: if (min_uV == 0) vsel = 0; else if ((min_uV >= 600000) && (min_uV <= 1300000)) { int calc_uV; vsel = (min_uV - 600000) / 125; if (vsel % 100) vsel += 100; vsel /= 100; vsel++; calc_uV = twl6030smps_list_voltage(rdev, vsel); if (calc_uV > max_uV) return -EINVAL; } /* Values 1..57 for vsel are linear and can be calculated * values 58..62 are non linear. */ else if ((min_uV > 1900000) && (max_uV >= 2100000)) vsel = 62; else if ((min_uV > 1800000) && (max_uV >= 1900000)) vsel = 61; else if ((min_uV > 1500000) && (max_uV >= 1800000)) vsel = 60; else if ((min_uV > 1350000) && (max_uV >= 1500000)) vsel = 59; else if ((min_uV > 1300000) && (max_uV >= 1350000)) vsel = 58; else return -EINVAL; break; case SMPS_OFFSET_EN: if (min_uV == 0) vsel = 0; else if ((min_uV >= 700000) && (min_uV <= 1420000)) { int calc_uV; vsel = (min_uV - 700000) / 125; if (vsel % 100) vsel += 100; vsel /= 100; vsel++; calc_uV = twl6030smps_list_voltage(rdev, vsel); if (calc_uV > max_uV) return -EINVAL; } /* Values 1..57 for vsel are linear and can be calculated * values 58..62 are non linear. */ else if ((min_uV > 1900000) && (max_uV >= 2100000)) vsel = 62; else if ((min_uV > 1800000) && (max_uV >= 1900000)) vsel = 61; else if ((min_uV > 1350000) && (max_uV >= 1800000)) vsel = 60; else if ((min_uV > 1350000) && (max_uV >= 1500000)) vsel = 59; else if ((min_uV > 1300000) && (max_uV >= 1350000)) vsel = 58; else return -EINVAL; break; case SMPS_EXTENDED_EN: if (min_uV == 0) vsel = 0; else if ((min_uV >= 1852000) && (max_uV <= 4013600)) { vsel = (min_uV - 1852000) / 386; if (vsel % 100) vsel += 100; vsel /= 100; vsel++; } break; case SMPS_OFFSET_EN|SMPS_EXTENDED_EN: if (min_uV == 0) vsel = 0; else if ((min_uV >= 2161000) && (max_uV <= 4321000)) { vsel = (min_uV - 2161000) / 386; if (vsel % 100) vsel += 100; vsel /= 100; vsel++; } break; } *selector = vsel; return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS, vsel); }
static int __devinit twlreg_probe(struct platform_device *pdev) { int i; struct twlreg_info *info; struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) { if (twl_regs[i].desc.id != pdev->id) continue; info = twl_regs + i; break; } if (!info) return -ENODEV; initdata = pdev->dev.platform_data; if (!initdata) return -EINVAL; /* Constrain board-specific capabilities according to what * this driver and the chip itself can actually do. */ c = &initdata->constraints; c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY; c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS; switch (pdev->id) { case TWL4030_REG_VIO: case TWL4030_REG_VDD1: case TWL4030_REG_VDD2: case TWL4030_REG_VPLL1: case TWL4030_REG_VINTANA1: case TWL4030_REG_VINTANA2: case TWL4030_REG_VINTDIG: c->always_on = true; break; default: break; } rdev = regulator_register(&info->desc, &pdev->dev, initdata, info); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "can't register %s, %ld\n", info->desc.name, PTR_ERR(rdev)); return PTR_ERR(rdev); } platform_set_drvdata(pdev, rdev); twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP, info->remap); /* NOTE: many regulators support short-circuit IRQs (presentable * as REGULATOR_OVER_CURRENT notifications?) configured via: * - SC_CONFIG * - SC_DETECT1 (vintana2, vmmc1/2, vaux1/2/3/4) * - SC_DETECT2 (vusb, vdac, vio, vdd1/2, vpll2) * - IT_CONFIG */ return 0; }
static int __devinit twlreg_probe(struct platform_device *pdev) { int i, id; struct twlreg_info *info; struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; struct twl_regulator_driver_data *drvdata; const struct of_device_id *match; match = of_match_device(twl_of_match, &pdev->dev); if (match) { info = match->data; id = info->desc.id; initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); drvdata = NULL; } else { id = pdev->id; initdata = pdev->dev.platform_data; for (i = 0, info = NULL; i < ARRAY_SIZE(twl_of_match); i++) { info = twl_of_match[i].data; if (!info || info->desc.id != id) continue; break; } drvdata = initdata->driver_data; if (!drvdata) return -EINVAL; } if (!info) return -ENODEV; if (!initdata) return -EINVAL; if (drvdata) { info->features = drvdata->features; info->data = drvdata->data; info->set_voltage = drvdata->set_voltage; info->get_voltage = drvdata->get_voltage; } c = &initdata->constraints; c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY; c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS; switch (id) { case TWL4030_REG_VIO: case TWL4030_REG_VDD1: case TWL4030_REG_VDD2: case TWL4030_REG_VPLL1: case TWL4030_REG_VINTANA1: case TWL4030_REG_VINTANA2: case TWL4030_REG_VINTDIG: c->always_on = true; break; default: break; } switch (id) { case TWL6025_REG_SMPS3: if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3) info->flags |= SMPS_OFFSET_EN; break; case TWL6025_REG_SMPS4: if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4) info->flags |= SMPS_OFFSET_EN; break; case TWL6025_REG_VIO: if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO) info->flags |= SMPS_OFFSET_EN; break; } rdev = regulator_register(&info->desc, &pdev->dev, initdata, info, pdev->dev.of_node); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "can't register %s, %ld\n", info->desc.name, PTR_ERR(rdev)); return PTR_ERR(rdev); } platform_set_drvdata(pdev, rdev); if (twl_class_is_4030()) twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP, info->remap); return 0; }