Other Parts Discussed in Thread: TPS53819A, PCF8575
Hi,
I get a EIO which is thrown inside tps53819a_probe when trying to register a i2c regulator. It seems like the exception is because of lacking platform_data.
Basically what I did is casting the default gpio-regulator registration into the i2c regulator's, and add some driver support for the i2c regulator.
1. Add regulator specific data to the board file at "arch/arm/mach-omap2/board-dm8168z3.c":
#elif CONFIG_REGULATOR_TPS53819A
static struct regulator_consumer_supply ti816x_tps53819a_dcdc_supply[] = {
{
.supply = "tps53819a",
},
};
static struct regulator_init_data tps53819a_pmic_init_data = {
.constraints = {
.min_uV = 800000,
.max_uV = 1500000,
.valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS),
},
.num_consumer_supplies = ARRAY_SIZE(ti816x_tps53819a_dcdc_supply),
.consumer_supplies = ti816x_tps53819a_dcdc_supply,
};
/* TPS regulator platform data */
static struct tps53819a_reg_platform_data tps53819a_vr_init_data = {
.name = "tps53819a",
.pmic_init_data = &tps53819a_pmic_init_data,
};
/* VCORE for SR regulator init */
static struct platform_device ti816x_tps53819a_vr_device = {
.name = "tps53819a",
.id = -1,
.dev = {
.platform_data = &tps53819a_vr_init_data,
},
};
static void __init ti816x_tps53819a_vr_init(void)
{
if (platform_device_register(&ti816x_tps53819a_vr_device))
printk(KERN_ERR "failed to register ti816x_tps53819a_vr device\n");
else
printk(KERN_INFO "registered ti816x_tps53819a_vr device\n");
}
....
static struct i2c_board_info __initdata z3dm816x_i2c_boardinfo1[] = {
{
I2C_BOARD_INFO("tps53819a", 0x2a),
.platform_data = &tps53819a_vr_init_data,
},
};
...
#ifdef CONFIG_REGULATOR_TPS53819A
ti816x_tps53819a_vr_init();
2. Add SR platform specific data based on the chosen PMIC to the devices file at "arch/arm/mach-omap2/devices.c":
static struct ti816x_sr_platform_data ti816x_sr_pdata = {
.vd_name = "tps53819a",
.ip_type = 2,
.irq_delay = 2000,
.no_of_vds = 1,
.no_of_sens = ARRAY_SIZE(sr_sensor_data),
.vstep_size_uv = 49000,
.enable_on_init = true,
.sr_sdata = sr_sensor_data,
};
3. Add regulator driver support at "kernel/driver/regulator/tps53819a-regulator.c":
static int __devinit tps53819a_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
const struct tps_info *info = (void *)id->driver_data;
struct regulator_init_data *init_data;
struct regulator_dev *rdev;
struct tps_pmic *tps;
int error;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_err(&client->dev, "i2c_check_functionality failed!\n");
return -EIO;
}
init_data = client->dev.platform_data;
if (!init_data) {
dev_err(&client->dev, "platform_data is null!\n");
return -EIO;
}
tps = kzalloc(sizeof(*tps), GFP_KERNEL);
if (!tps)
return -ENOMEM;
mutex_init(&tps->io_lock);
/* common for all regulators */
tps->client = client;
tps->info = info;
tps->desc.name = info->name;
tps->desc.n_voltages = ARRAY_SIZE(VDCDC_VSEL_table);
tps->desc.ops = &tps53819a_dcdc_ops;
tps->desc.type = REGULATOR_VOLTAGE;
tps->desc.owner = THIS_MODULE;
/* Register the Regulator */
rdev = regulator_register(&tps->desc, &client->dev, init_data, tps);
if (IS_ERR(rdev)) {
dev_err(&client->dev, "failed to register %s\n", id->name);
error = PTR_ERR(rdev);
goto exit_devreg;
}
/* Save regulator for cleanup */
tps->rdev = rdev;
i2c_set_clientdata(client, tps);
return 0;
exit_devreg:
regulator_unregister(tps->rdev);
kfree(tps);
return error;
}
static const struct tps_info tps53819a_regs[] = {
{
.name = "TPS53819A_VDCDC",
.min_uV = TPS53819A_MIN_VOLTAGE,
.max_uV = TPS53819A_MAX_VOLTAGE,
.table_len = ARRAY_SIZE(VDCDC_VSEL_table),
.table = VDCDC_VSEL_table,
},
};
static const struct i2c_device_id tps53819a_id[] = {
{
.name = "tps53819a",
.driver_data = (unsigned long) tps53819a_regs,
},
};
MODULE_DEVICE_TABLE(i2c, tps53819a_id);
static struct i2c_driver tps53819a_i2c_driver = {
.driver = {
.name = "tps53819a",
.owner = THIS_MODULE,
},
.probe = tps53819a_probe,
.remove = __devexit_p(tps53819a_remove),
.id_table = tps53819a_id,
};
static int __init tps53819a_init(void)
{
printk(KERN_INFO "regulator: %s\n", __func__);
return i2c_add_driver(&tps53819a_i2c_driver);
}
module_init(tps53819a_init);
Thanks,
Guang
