Hi,

I am working on TPS65023 PMIC 
(http://focus.ti.com/docs/prod/folders/print/tps65023.html) regulator driver. 
It supports 3 step-down converters and 2 LDOs, all connected to the same I2C 
device. I am facing some design related issues and need your opinion on the 
same.

Since all the five regulators can be controlled using a single i2c device, I 
made a single i2c_board_info structure in my platform specific file and put all 
the regulator_init_data information there:

<<<<<code starts>>>>
/* MPU voltage regulator of DCDC type */
struct regulator_consumer_supply tps65023_mpu_consumers = {
        .supply = "vdd1",
};

/* MMC voltage regulator of LDO type */
struct regulator_consumer_supply tps65023_mmc_consumers = {
        .supply = "mmc",
};

struct regulator_init_data tps_regulator_data[] = {
        {
                .constraints = {
                        .min_uV = 800000,
                        .max_uV = 1600000,
                        .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE |
                                REGULATOR_CHANGE_STATUS),
                },
                .num_consumer_supplies  = 1,
                .consumer_supplies      = &tps65023_mpu_consumers,
        },
        .
        .
        .
        {
                .constraints = {
                        .min_uV = 1050000,
                        .max_uV = 3300000,
                        .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE |
                                REGULATOR_CHANGE_STATUS),
                },
                .num_consumer_supplies  = 1,
                .consumer_supplies      = &tps65023_mmc_consumers,
        },
};

static struct i2c_board_info __initdata tps_65023_i2c_board_info[] = {
        {
                I2C_BOARD_INFO("tps65023", 0x48),
                .flags = I2C_CLIENT_WAKE,
                .platform_data = &tps_regulator_data[0],
        },
};

static int __init omap3_evm_i2c_init(void)
{
        omap_register_i2c_bus(1, 400, tps_65023_i2c_board_info,
                ARRAY_SIZE(tps_65023_i2c_board_info));
        .
        .
}
<<<<<code ends>>>>

Now, in my regulator driver code, I am creating an array of the available 
regulators, passing that array as driver_data in my i2c_device_id structure and 
registering my i2c_driver using i2c_add_driver() during initialization, as 
shown below:

<<<<<code starts>>>>
#define TPS65023_NUM_DCDC               3
#define TPS65023_NUM_LDO                2
#define TPS65023_NUM_REGULATOR  (TPS65023_NUM_DCDC + TPS65023_NUM_LDO)

struct tps_info {
        const char      *name;
        unsigned                min_uV;
        unsigned                max_uV;
        bool                    fixed;
        u8                      table_len;
        const u16               *table;
};

struct tps {
        struct regulator_desc   desc[TPS65023_NUM_REGULATOR];
        struct i2c_client               *client;
        struct regulator_dev    *rdev[TPS65023_NUM_REGULATOR];
        const struct tps_info   *info[TPS65023_NUM_REGULATOR];
};

static const struct tps_info tps65023_regs[] = {
        {
        .name = "VDCDC1",
        .min_uV         =  800000,
        .max_uV         = 1600000,
        .fixed = 0,
        .table_len = ARRAY_SIZE(VDCDC1_VSEL_table),
        .table = VDCDC1_VSEL_table,
        },
        .       
        .
        .
        {
        .name = "LDO2",
        .min_uV         = 1000000,
        .max_uV         = 3150000,
        .fixed = 0,
        .table_len = ARRAY_SIZE(LDO2_VSEL_table),
        .table = LDO2_VSEL_table,
        },
};

static const struct i2c_device_id tps_65023_id = {
        .name = "tps65023",
        .driver_data = (unsigned long) &tps65023_regs[0],
};

MODULE_DEVICE_TABLE(i2c, tps_65023_id);

static struct i2c_driver tps_65023_i2c_driver = {
        .driver = {
                .name   =       "tps_65023_pwr",
                .owner  =       THIS_MODULE,
        },
        .probe          = tps_65023_probe,
        .remove = __devexit_p(tps_65023_remove),
        .id_table       = &tps_65023_id,
};

/**
 * tps_65023_init
 *
 * Module init function
 */
static int __init tps_65023_init(void)
{
        return i2c_add_driver(&tps_65023_i2c_driver);
}
late_initcall(tps_65023_init);
<<<<<code ends>>>>

Now, the problem is in the tps_65023_probe function. Since it will be called 
only once as there is only one i2c device, I have to register all the 
regulators in that only. But I am not able to communicate the same to the 
regulator core layer. Inside the regulator_register(), variable init_data, 
which equals to dev->platform_data, is always pointing to the first array 
member, which is coming from the evm specific file. And it fails to register my 
second regulator instance, set_consumer_device_supply() specifically failing 
for the second iteration. Because of this, the probe function fails.

How should I handle this scenario? Am I missing something in my implementation?

Regards,
Anuj Aggarwal
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to