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