pmic芯片lp3925驱动_i2c接口

1. init/exit

    static int __init lp3925_init(void)
    {
        int ret = 0;
        ret = i2c_add_driver(&lp3925_driver);   //添加lp3925 i2c驱动.
        if (ret) {
            printk(KERN_WARNING "lp3925: Driver registration failed, \
                        module not inserted.\n");
            return ret;
        }
        return ret;
    }
    static void __exit lp3925_exit(void)
    {
        i2c_del_driver(&lp3925_driver);
    }
    subsys_initcall(lp3925_init);
    module_exit(lp3925_exit);
2. lp3925_driver

    static struct i2c_driver lp3925_driver = {
        .driver = {
             .name = "lp3925",
        },
        .probe        = lp3925_probe,    //i2c_add_driver() 注册完成,就会自动运行这个probe函数.
        .remove     = __devexit_p(lp3925_remove),
        .id_table    = lp3925_id,
    };
lp3925_id
    static const struct i2c_device_id lp3925_id[] = {
        { "lp3925", 0 },  // "lp3925" , 这个名字必须与 i2c_board_info 中的设备名字一样,系统会进行名字匹配,匹配上了才能i2c_add_driver成功。
        { },
    };
3. lp3925_probe()
    static int __devinit lp3925_probe(struct i2c_client *client,
                     const struct i2c_device_id *id)
    {
        struct lp3925_platform_data *pdata;
        struct lp3925_data *data;
        int err = 0;
        pdata = client->dev.platform_data;   //这个platform_data, 就是i2c_board_info中的 *platform_data, 在board.c中进行初始化。
        if (pdata == NULL) {
            dev_dbg(&client->dev, "No platform data\n");
            return -EINVAL;
        }
        if ((pdata->buck1_dvs > LP3925_BUCK_DVS_MAX)
            || (pdata->buck2_dvs > LP3925_BUCK_DVS_MAX)) {
            dev_dbg(&client->dev, "Invalid platform data\n");
            return -EINVAL;
        }
        if (!(data = kzalloc(sizeof(struct lp3925_data), GFP_KERNEL)))
            return -ENOMEM;
        lp3925_client = client;
        /* Init real i2c_client */
        data->pdata = pdata;
        data->irq_mask = 0xffffffff;
        data->irq_gpio = pdata->irq_gpio;
        data->irq = gpio_to_irq(pdata->irq_gpio);  //irq_gpio就是下面platform_data中的.irq_gpio = mfp_to_gpio(LP3925_INT_PIN),
        i2c_set_clientdata(client, data);          //设置i2c client data.标准I2C操作。
        mutex_init(&data->power_lock);
        mutex_init(&data->adc_lock);
        mutex_init(&data->reg_lock);
        /* Initialize LP3925 hardware. */
        if ((err = lp3925_hw_init(data)) != 0)     //硬件初始化
            goto exit;
        /* Set PMIC ops. */
        pmic_ops_set(&lp3925_pmic_ops);            //lp3925芯片驱动的各种操作
        return 0;
    exit:
        kfree(data);
        return err;
    }
4. 解析 pdata = client->dev.platform_data; 这里的platform_data 在board.c中初始化:
    #if defined(CONFIG_COMIP_LP3925)
        /* LP3925. */
        {LP3925_INT_PIN,        MFP_PIN_MODE_GPIO},
    #endif

    #if defined(CONFIG_COMIP_LP3925)
    static struct lp3925_ldo_ctrl_map comip_lp3925_ldo_ctrl_map[] = {   //因为是个PMIC 芯片,所以肯定会出现个种可调节LDO。
        {LP3925_LDO_1,        LP3925_LDO_CTRL_ALWAYS_ON,    LP3925_LDO_CTRL_GPIO_ID_NONE,    2850},
        {LP3925_LDO_2,        LP3925_LDO_CTRL_REG21,        LP3925_LDO_CTRL_GPIO_ID_NONE,    1800},
        {LP3925_LDO_3,        LP3925_LDO_CTRL_REG00,        LP3925_LDO_CTRL_GPIO_ID_NONE,    2200},
        {LP3925_LDO_5,        LP3925_LDO_CTRL_GPIO4,        LP3925_LDO_CTRL_GPIO_ID_NONE,    1800},
        {LP3925_LDO_6,        LP3925_LDO_CTRL_REG00,        LP3925_LDO_CTRL_GPIO_ID_NONE,    3000},
        {LP3925_LDO_7,        LP3925_LDO_CTRL_REG01,         LP3925_LDO_CTRL_GPIO_ID_NONE,    1800},
        {LP3925_LDO_11,     LP3925_LDO_CTRL_REG10,        LP3925_LDO_CTRL_GPIO_ID_NONE,    2850},
        {LP3925_LDO_12,     LP3925_LDO_CTRL_REG10,        LP3925_LDO_CTRL_GPIO_ID_NONE,    3000},
        {LP3925_LDO_13,     LP3925_LDO_CTRL_REG11,        LP3925_LDO_CTRL_GPIO_ID_NONE,    2850},
        {LP3925_REFOUT,     LP3925_LDO_CTRL_GPIO3,        LP3925_LDO_CTRL_GPIO_ID_NONE,    2500},
    };
    static struct lp3925_ldo_module_map comip_lp3925_ldo_module_map[] = {
        {LP3925_LDO_2,        PMIC_POWER_CAMERA_DIGITAL,    1,                0},
        {LP3925_LDO_3,        PMIC_POWER_SWITCH,        0,                0},
        {LP3925_LDO_7,        PMIC_POWER_CMMB_BB_CORE,    0,                0},
        {LP3925_LDO_6,        PMIC_POWER_USIM,        0,                0},
        {LP3925_LDO_8,         PMIC_POWER_RF_GSM_CORE,        0,                1},
        {LP3925_LDO_9,         PMIC_POWER_RF_GSM_IO,         0,                1},
        {LP3925_LDO_10,     PMIC_POWER_RF_TDD_CORE,     0,                1},
        {LP3925_LDO_11,     PMIC_POWER_CMMB_IO,         0,                0},
        {LP3925_LDO_12,     PMIC_POWER_SDIO,        0,                0},
        {LP3925_LDO_13,     PMIC_POWER_CAMERA_IO,        1,                0},
        {LP3925_LDO_13,     PMIC_POWER_CAMERA_CORE,        0,                0},
        {LP3925_LDO_13,     PMIC_POWER_LCD_CORE,        0,                0},
        {LP3925_LDO_EXT_1,    PMIC_POWER_LED,            0,                0},
        {LP3925_LDO_EXT_2,    PMIC_POWER_VIBRATOR,         0,                0},
    };
    static struct lp3925_pin_map comip_lp3925_pin_map[] = {
        {LP3925_PIN_INP1,    LP3925_PIN_INP_1000MV},
        {LP3925_PIN_INP2,    LP3925_PIN_INP_1000MV},
        {LP3925_PIN_SINK1,    LP3925_PIN_SINK1_125MA},
        {LP3925_PIN_SINK2,    LP3925_PIN_SINK2_3_100MA},
    };
    static struct lp3925_platform_data comip_i2c_lp3925_info = { 
        .irq_gpio = mfp_to_gpio(LP3925_INT_PIN),
        .ctrl_map = comip_lp3925_ldo_ctrl_map,
        .ctrl_map_num = ARRAY_SIZE(comip_lp3925_ldo_ctrl_map),
        .module_map = comip_lp3925_ldo_module_map,
        .module_map_num = ARRAY_SIZE(comip_lp3925_ldo_module_map),
        .pin_map = comip_lp3925_pin_map,
        .pin_map_num = ARRAY_SIZE(comip_lp3925_pin_map),
        .buck1_dvs = 1,
        .buck2_dvs = 3,
    };
    #endif
最后是i2c0_board_info中添加的I2C数据项:
    #if defined(CONFIG_COMIP_LP3925)
        {
            .type = "lp3925",      // 这个名字就必须与上面的 id 同一个名字,以便进行匹配。
            .addr = 0x7e,    //i2c slave 地址
            .platform_data    = &comip_i2c_lp3925_info,  //这就是platform_data
        },
    #endif


一个LP3925重要的数据结构,表达了该芯片的各种属性,细节就不跟了,得跟datasheet联系:
    /* Platform data for the LP3925 driver */
    struct lp3925_platform_data {
        int irq_gpio;
        struct lp3925_pin_map* pin_map;
        int pin_map_num;
        struct lp3925_ldo_timing* ldo_timing;
        int ldo_timing_num;
        struct lp3925_ldo_pull_down* ldo_pull_down;
        int ldo_pull_down_num;
        struct lp3925_ldo_ctrl_map* ctrl_map;
        int ctrl_map_num;
        struct lp3925_ldo_module_map* module_map;
        int module_map_num;
        /* BUCK DVS selectors. */
        u8 buck1_dvs;
        u8 buck2_dvs;
    };
5. lp3925_hw_init()硬件初始化,芯片的各种初始化流程。
    static int lp3925_hw_init(struct lp3925_data *data)
    {
        int i;
        int ret;
        /* Mask all interrupts. */
        lp3925_reg_write(LP3925_REG_INT_MASK0, 0xff);
        lp3925_reg_write(LP3925_REG_INT_MASK1, 0xff);
        /* Read version id. */
        lp3925_reg_read(LP3925_REG_SILICON_ID, &data->silicon_id);
        lp3925_reg_read(LP3925_REG_EEPROM_VERSION_ID, &data->version_id);
        /* Read enable registers. */
        for (i = 0; i < LP3925_REG_ENABLE_NUM; i++)
            lp3925_reg_read(LP3925_REG_ENABLE_BASE + i, &data->enable_reg[i]);
        /* Initialize LP3925 reboot. */
        lp3925_reboot_init(data);
        /* Initialize LP3925 RTC. */
        lp3925_rtc_init(data);
        /* Initialize LP3925 pin. */
        lp3925_pin_init(data);
        /* Initialize LP3925 power. */
        lp3925_power_init(data);
        /* Initialize LP3925 irq. */
        ret = lp3925_irq_init(data);
        if (ret)
            goto exit;
        return 0;
    exit:
        return ret;
    }
6. pmic_ops_set(&lp3925_pmic_ops),这个函数在arch/arm/mach-xxx/xxx-pmic.c中。这里就有点设计PM模块了。
    int pmic_ops_set(struct pmic_ops *ops)
    {
        if (g_pmic_ops != NULL) {
            printk(KERN_ERR "set pmic_ops when pmic_ops is not NULL\n");
            return -EFAULT;
        }
        g_pmic_ops = ops;
        INIT_LIST_HEAD(&g_pmic_ops->list);
        spin_lock_init(&g_pmic_ops->cb_lock);
        return 0;
    }
    EXPORT_SYMBOL(pmic_ops_set);
pmic_ops
    /* PMIC ops. */
    struct pmic_ops {
        /* Registers. */
        int (*reg_write)(u16 reg, u16 val);
        int (*reg_read)(u16 reg, u16 *pval);
        /* Event. */
        int (*event_mask)(int event);
        int (*event_unmask)(int event);
        /* Power. */
        int (*voltage_get)(u8 module, u8 param, int *pmv);
        int (*voltage_set)(u8 module, u8 param, int mv);
        /* RTC. */
        int (*rtc_time_get)(struct rtc_time *tm);
        int (*rtc_time_set)(struct rtc_time *tm);
        int (*rtc_alarm_get)(u8 id, struct rtc_wkalrm *alrm);
        int (*rtc_alarm_set)(u8 id, struct rtc_wkalrm *alrm);
        /* Comparator. */
        int (*comp_state_get)(u8 id);
        /* Power on type. */
        int (*power_on_type_get)(void);
        /* Power key. */
        int (*power_key_state_get)(void);
        /* Callback list. */
        struct list_head list;
        /* Spinlock for callback list. */
        spinlock_t cb_lock;
    };
7. lp3925_pmic_ops, LP3925具体的pmic_ops.
    static struct pmic_ops lp3925_pmic_ops = {
        .reg_read        = lp3925_pmu_reg_read,
        .reg_write        = lp3925_pmu_reg_write,
        .event_mask        = lp3925_event_mask,
        .event_unmask        = lp3925_event_unmask,
        .voltage_get        = lp3925_voltage_get,
        .voltage_set        = lp3925_voltage_set,
        .rtc_time_get        = lp3925_rtc_time_get,
        .rtc_time_set        = lp3925_rtc_time_set,
        .rtc_alarm_get        = lp3925_rtc_alarm_get,
        .rtc_alarm_set        = lp3925_rtc_alarm_set,
        .comp_state_get        = lp3925_comp_state_get,
        .power_key_state_get    = lp3925_power_key_state_get,
        .power_on_type_get    = lp3925_power_on_type_get,
    };



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值