struct twlreg_info { /* start of regulator's PM_RECEIVER control register bank */
u8 base;
/* twl resource ID, for resource control state machine */
u8 id;
u8 flags;
/* used by regulator core */ struct regulator_desc desc;
/* chip specific features */ unsignedlong features;
/* data passed from board for external get/set voltage */ void *data;
};
/* LDO control registers ... offset is from the base of its register bank. * The first three registers of all power resource banks help hardware to * manage the various resource groups.
*/ /* Common offset in TWL4030/6030 */ #define VREG_GRP 0 /* TWL6030 register offsets */ #define VREG_TRANS 1 #define VREG_STATE 2 #define VREG_VOLTAGE 3 #define VREG_VOLTAGE_SMPS 4 /* TWL6030 Misc register offsets */ #define VREG_BC_ALL 1 #define VREG_BC_REF 2 #define VREG_BC_PROC 3 #define VREG_BC_CLK_RST 4
/* generic power resource operations, which work on all regulators */ staticint twlreg_grp(struct regulator_dev *rdev)
{ return twlreg_read(rdev_get_drvdata(rdev), TWL_MODULE_PM_RECEIVER,
VREG_GRP);
}
/* * Enable/disable regulators by joining/leaving the P1 (processor) group. * We assume nobody else is updating the DEV_GRP registers.
*/ /* definition for 6030 family */ #define P3_GRP_6030 BIT(2) /* secondary processor, modem, etc */ #define P2_GRP_6030 BIT(1) /* "peripherals" */ #define P1_GRP_6030 BIT(0) /* CPU/Linux */
/* 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);
val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
if (info->features & TWL6032_SUBCLASS)
val &= TWL6030_CFG_STATE_MASK; else
val = TWL6030_CFG_STATE_APP(val);
switch (val) { case TWL6030_CFG_STATE_ON: return REGULATOR_STATUS_NORMAL;
case TWL6030_CFG_STATE_SLEEP: return REGULATOR_STATUS_STANDBY;
case TWL6030_CFG_STATE_OFF: case TWL6030_CFG_STATE_OFF2: default: break;
}
return REGULATOR_STATUS_OFF;
}
staticint 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 & TWL6032_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;
switch (info->flags) { case SMPS_OFFSET_EN:
voltage = 100000;
fallthrough; case 0: switch (index) { case 0:
voltage = 0; break; case 58:
voltage = 1350 * 1000; break; case 59:
voltage = 1500 * 1000; break; case 60:
voltage = 1800 * 1000; break; case 61:
voltage = 1900 * 1000; break; case 62:
voltage = 2100 * 1000; break; default:
voltage += (600000 + (12500 * (index - 1)));
} break; case SMPS_EXTENDED_EN: switch (index) { case 0:
voltage = 0; break; case 58:
voltage = 2084 * 1000; break; case 59:
voltage = 2315 * 1000; break; case 60:
voltage = 2778 * 1000; break; case 61:
voltage = 2932 * 1000; break; case 62:
voltage = 3241 * 1000; break; default:
voltage = (1852000 + (38600 * (index - 1)));
} break; case SMPS_OFFSET_EN | SMPS_EXTENDED_EN: switch (index) { case 0:
voltage = 0; break; case 58:
voltage = 4167 * 1000; break; case 59:
voltage = 2315 * 1000; break; case 60:
voltage = 2778 * 1000; break; case 61:
voltage = 2932 * 1000; break; case 62:
voltage = 3241 * 1000; break; default:
voltage = (2161000 + (38600 * (index - 1)));
} break;
}
return voltage;
}
staticint twl6030smps_map_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
{ struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel = 0;
template = of_device_get_match_data(&pdev->dev); if (!template) return -ENODEV;
id = template->desc.id;
initdata = of_get_regulator_init_data(&pdev->dev, np, &template->desc); if (!initdata) return -EINVAL;
info = devm_kmemdup(&pdev->dev, template, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM;
/* 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 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;
}
if (of_property_read_bool(np, "ti,retain-on-reset"))
info->flags |= TWL_6030_WARM_RESET;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.