/* * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under * "Recommended Operating Conditions" for "Digital GPIO". When the typical * is 3.3V the max is 3.6V. When the typical is 1.8V the max is 1.98V. * * They are used like this: * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the * SoC we're at 3.3. * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider * that to be an error.
*/ #define MAX_VOLTAGE_1_8 1980000 #define MAX_VOLTAGE_3_3 3600000
/* * According to Rockchip it's important to keep the SoC IO domain * higher than (or equal to) the external voltage. That means we need * to change it before external voltage changes happen in the case * of an increase. * * Note that in the "pre" change we pick the max possible voltage that * the regulator might end up at (the client requests a range and we * don't know for certain the exact voltage). Right now we rely on the * slop in MAX_VOLTAGE_1_8 and MAX_VOLTAGE_3_3 to save us if clients * request something like a max of 3.6V when they really want 3.3V. * We could attempt to come up with better rules if this fails.
*/ if (event & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) { struct pre_voltage_change_data *pvc_data = data;
if (uV > MAX_VOLTAGE_3_3) {
dev_err(supply->iod->dev, "Voltage too high: %d\n", uV);
if (event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) return NOTIFY_BAD;
}
ret = supply->iod->write(supply, uV); if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) return NOTIFY_BAD;
dev_dbg(supply->iod->dev, "Setting to %d done\n", uV); return NOTIFY_OK;
}
staticvoid px30_iodomain_init(struct rockchip_iodomain *iod)
{ int ret;
u32 val;
/* if no VCCIO6 supply we should leave things alone */ if (!iod->supplies[PX30_IO_VSEL_VCCIO6_SUPPLY_NUM].reg) return;
/* * set vccio6 iodomain to also use this framework * instead of a special gpio.
*/
val = PX30_IO_VSEL_VCCIO6_SRC | (PX30_IO_VSEL_VCCIO6_SRC << 16);
ret = regmap_write(iod->grf, PX30_IO_VSEL, val); if (ret < 0)
dev_warn(iod->dev, "couldn't update vccio6 ctrl\n");
}
staticvoid rk3288_iodomain_init(struct rockchip_iodomain *iod)
{ int ret;
u32 val;
/* if no flash supply we should leave things alone */ if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg) return;
/* * set flash0 iodomain to also use this framework * instead of a special gpio.
*/
val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16);
ret = regmap_write(iod->grf, RK3288_SOC_CON2, val); if (ret < 0)
dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
}
staticvoid rk3308_iodomain_init(struct rockchip_iodomain *iod)
{ int ret;
u32 val;
/* if no vccio3 supply we should leave things alone */ if (!iod->supplies[RK3308_SOC_VCCIO3_SUPPLY_NUM].reg) return;
/* * set vccio3 iodomain to also use this framework * instead of a special gpio.
*/
val = RK3308_SOC_CON0_VCCIO3 | (RK3308_SOC_CON0_VCCIO3 << 16);
ret = regmap_write(iod->grf, RK3308_SOC_CON0, val); if (ret < 0)
dev_warn(iod->dev, "couldn't update vccio3 vsel ctrl\n");
}
staticvoid rk3328_iodomain_init(struct rockchip_iodomain *iod)
{ int ret;
u32 val;
/* if no vccio2 supply we should leave things alone */ if (!iod->supplies[RK3328_SOC_VCCIO2_SUPPLY_NUM].reg) return;
/* * set vccio2 iodomain to also use this framework * instead of a special gpio.
*/
val = RK3328_SOC_CON4_VCCIO2 | (RK3328_SOC_CON4_VCCIO2 << 16);
ret = regmap_write(iod->grf, RK3328_SOC_CON4, val); if (ret < 0)
dev_warn(iod->dev, "couldn't update vccio2 vsel ctrl\n");
}
staticvoid rk3368_iodomain_init(struct rockchip_iodomain *iod)
{ int ret;
u32 val;
/* if no flash supply we should leave things alone */ if (!iod->supplies[RK3368_SOC_FLASH_SUPPLY_NUM].reg) return;
/* * set flash0 iodomain to also use this framework * instead of a special gpio.
*/
val = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16);
ret = regmap_write(iod->grf, RK3368_SOC_CON15, val); if (ret < 0)
dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
}
staticvoid rk3399_pmu_iodomain_init(struct rockchip_iodomain *iod)
{ int ret;
u32 val;
/* if no pmu io supply we should leave things alone */ if (!iod->supplies[RK3399_PMUGRF_VSEL_SUPPLY_NUM].reg) return;
/* * set pmu io iodomain to also use this framework * instead of a special gpio.
*/
val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16);
ret = regmap_write(iod->grf, RK3399_PMUGRF_CON0, val); if (ret < 0)
dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n");
}
/* * On the rk3188 the io-domains are handled by a shared register with the * lower 8 bits being still being continuing drive-strength settings.
*/ staticconststruct rockchip_iodomain_soc_data soc_data_rk3188 = {
.grf_offset = 0x104,
.supply_names = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL, "ap0", "ap1", "cif", "flash", "vccio0", "vccio1", "lcdc0", "lcdc1",
},
};
for (i = 0; i < MAX_SUPPLIES; i++) { constchar *supply_name = iod->soc_data->supply_names[i]; struct rockchip_iodomain_supply *supply = &iod->supplies[i]; struct regulator *reg; int uV;
if (!supply_name) continue;
reg = devm_regulator_get_optional(iod->dev, supply_name); if (IS_ERR(reg)) {
ret = PTR_ERR(reg);
/* If a supply wasn't specified, that's OK */ if (ret == -ENODEV) continue; elseif (ret != -EPROBE_DEFER)
dev_err(iod->dev, "couldn't get regulator %s\n",
supply_name); goto unreg_notify;
}
/* set initial correct value */
uV = regulator_get_voltage(reg);
/* must be a regulator we can get the voltage of */ if (uV < 0) {
dev_err(iod->dev, "Can't determine voltage: %s\n",
supply_name);
ret = uV; goto unreg_notify;
}
if (uV > MAX_VOLTAGE_3_3) {
dev_crit(iod->dev, "%d uV is too high. May damage SoC!\n",
uV);
ret = -EINVAL; goto unreg_notify;
}
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.