分享

[z]pmic芯片lp3925驱动

 techres 2012-07-28

1. init/exit

  1. static int __init lp3925_init(void)  
  2. {  
  3.     int ret = 0;  
  4.     ret = i2c_add_driver(&lp3925_driver);   //添加lp3925 i2c驱动.  
  5.     if (ret) {  
  6.         printk(KERN_WARNING "lp3925: Driver registration failed, \  
  7.                     module not inserted.\n");  
  8.         return ret;  
  9.     }  
  10.     return ret;  
  11. }  
  12. static void __exit lp3925_exit(void)  
  13. {  
  14.     i2c_del_driver(&lp3925_driver);  
  15. }  
  16. subsys_initcall(lp3925_init);  
  17. module_exit(lp3925_exit);  
2. lp3925_driver

  1. static struct i2c_driver lp3925_driver = {  
  2.     .driver = {  
  3.          .name = "lp3925",  
  4.     },  
  5.     .probe        = lp3925_probe,    //i2c_add_driver() 注册完成,就会自动运行这个probe函数.  
  6.     .remove     = __devexit_p(lp3925_remove),  
  7.     .id_table    = lp3925_id,  
  8. };  
lp3925_id
  1. static const struct i2c_device_id lp3925_id[] = {  
  2.     { "lp3925", 0 },  // "lp3925" , 这个名字必须与 i2c_board_info 中的设备名字一样,系统会进行名字匹配,匹配上了才能i2c_add_driver成功。  
  3.     { },  
  4. };  
3. lp3925_probe()
  1. static int __devinit lp3925_probe(struct i2c_client *client,  
  2.                  const struct i2c_device_id *id)  
  3. {  
  4.     struct lp3925_platform_data *pdata;  
  5.     struct lp3925_data *data;  
  6.     int err = 0;  
  7.     pdata = client->dev.platform_data;   //这个platform_data, 就是i2c_board_info中的 *platform_data, 在board.c中进行初始化。  
  8.     if (pdata == NULL) {  
  9.         dev_dbg(&client->dev, "No platform data\n");  
  10.         return -EINVAL;  
  11.     }  
  12.     if ((pdata->buck1_dvs > LP3925_BUCK_DVS_MAX)  
  13.         || (pdata->buck2_dvs > LP3925_BUCK_DVS_MAX)) {  
  14.         dev_dbg(&client->dev, "Invalid platform data\n");  
  15.         return -EINVAL;  
  16.     }  
  17.     if (!(data = kzalloc(sizeof(struct lp3925_data), GFP_KERNEL)))  
  18.         return -ENOMEM;  
  19.     lp3925_client = client;  
  20.     /* Init real i2c_client */  
  21.     data->pdata = pdata;  
  22.     data->irq_mask = 0xffffffff;  
  23.     data->irq_gpio = pdata->irq_gpio;  
  24.     data->irq = gpio_to_irq(pdata->irq_gpio);  //irq_gpio就是下面platform_data中的.irq_gpio = mfp_to_gpio(LP3925_INT_PIN),  
  25.     i2c_set_clientdata(client, data);          //设置i2c client data.标准I2C操作。  
  26.     mutex_init(&data->power_lock);  
  27.     mutex_init(&data->adc_lock);  
  28.     mutex_init(&data->reg_lock);  
  29.     /* Initialize LP3925 hardware. */  
  30.     if ((err = lp3925_hw_init(data)) != 0)     //硬件初始化  
  31.         goto exit;  
  32.     /* Set PMIC ops. */  
  33.     pmic_ops_set(&lp3925_pmic_ops);            //lp3925芯片驱动的各种操作  
  34.     return 0;  
  35. exit:  
  36.     kfree(data);  
  37.     return err;  
  38. }  
4. 解析 pdata = client->dev.platform_data; 这里的platform_data 在board.c中初始化:
  1. #if defined(CONFIG_COMIP_LP3925)  
  2.     /* LP3925. */  
  3.     {LP3925_INT_PIN,        MFP_PIN_MODE_GPIO},  
  4. #endif  
  5.   
  6. #if defined(CONFIG_COMIP_LP3925)  
  7. static struct lp3925_ldo_ctrl_map comip_lp3925_ldo_ctrl_map[] = {   //因为是个PMIC 芯片,所以肯定会出现个种可调节LDO。  
  8.     {LP3925_LDO_1,        LP3925_LDO_CTRL_ALWAYS_ON,    LP3925_LDO_CTRL_GPIO_ID_NONE,    2850},  
  9.     {LP3925_LDO_2,        LP3925_LDO_CTRL_REG21,        LP3925_LDO_CTRL_GPIO_ID_NONE,    1800},  
  10.     {LP3925_LDO_3,        LP3925_LDO_CTRL_REG00,        LP3925_LDO_CTRL_GPIO_ID_NONE,    2200},  
  11.     {LP3925_LDO_5,        LP3925_LDO_CTRL_GPIO4,        LP3925_LDO_CTRL_GPIO_ID_NONE,    1800},  
  12.     {LP3925_LDO_6,        LP3925_LDO_CTRL_REG00,        LP3925_LDO_CTRL_GPIO_ID_NONE,    3000},  
  13.     {LP3925_LDO_7,        LP3925_LDO_CTRL_REG01,         LP3925_LDO_CTRL_GPIO_ID_NONE,    1800},  
  14.     {LP3925_LDO_11,     LP3925_LDO_CTRL_REG10,        LP3925_LDO_CTRL_GPIO_ID_NONE,    2850},  
  15.     {LP3925_LDO_12,     LP3925_LDO_CTRL_REG10,        LP3925_LDO_CTRL_GPIO_ID_NONE,    3000},  
  16.     {LP3925_LDO_13,     LP3925_LDO_CTRL_REG11,        LP3925_LDO_CTRL_GPIO_ID_NONE,    2850},  
  17.     {LP3925_REFOUT,     LP3925_LDO_CTRL_GPIO3,        LP3925_LDO_CTRL_GPIO_ID_NONE,    2500},  
  18. };  
  19. static struct lp3925_ldo_module_map comip_lp3925_ldo_module_map[] = {  
  20.     {LP3925_LDO_2,        PMIC_POWER_CAMERA_DIGITAL,    1,                0},  
  21.     {LP3925_LDO_3,        PMIC_POWER_SWITCH,        0,                0},  
  22.     {LP3925_LDO_7,        PMIC_POWER_CMMB_BB_CORE,    0,                0},  
  23.     {LP3925_LDO_6,        PMIC_POWER_USIM,        0,                0},  
  24.     {LP3925_LDO_8,         PMIC_POWER_RF_GSM_CORE,        0,                1},  
  25.     {LP3925_LDO_9,         PMIC_POWER_RF_GSM_IO,         0,                1},  
  26.     {LP3925_LDO_10,     PMIC_POWER_RF_TDD_CORE,     0,                1},  
  27.     {LP3925_LDO_11,     PMIC_POWER_CMMB_IO,         0,                0},  
  28.     {LP3925_LDO_12,     PMIC_POWER_SDIO,        0,                0},  
  29.     {LP3925_LDO_13,     PMIC_POWER_CAMERA_IO,        1,                0},  
  30.     {LP3925_LDO_13,     PMIC_POWER_CAMERA_CORE,        0,                0},  
  31.     {LP3925_LDO_13,     PMIC_POWER_LCD_CORE,        0,                0},  
  32.     {LP3925_LDO_EXT_1,    PMIC_POWER_LED,            0,                0},  
  33.     {LP3925_LDO_EXT_2,    PMIC_POWER_VIBRATOR,         0,                0},  
  34. };  
  35. static struct lp3925_pin_map comip_lp3925_pin_map[] = {  
  36.     {LP3925_PIN_INP1,    LP3925_PIN_INP_1000MV},  
  37.     {LP3925_PIN_INP2,    LP3925_PIN_INP_1000MV},  
  38.     {LP3925_PIN_SINK1,    LP3925_PIN_SINK1_125MA},  
  39.     {LP3925_PIN_SINK2,    LP3925_PIN_SINK2_3_100MA},  
  40. };  
  41. static struct lp3925_platform_data comip_i2c_lp3925_info = {   
  42.     .irq_gpio = mfp_to_gpio(LP3925_INT_PIN),  
  43.     .ctrl_map = comip_lp3925_ldo_ctrl_map,  
  44.     .ctrl_map_num = ARRAY_SIZE(comip_lp3925_ldo_ctrl_map),  
  45.     .module_map = comip_lp3925_ldo_module_map,  
  46.     .module_map_num = ARRAY_SIZE(comip_lp3925_ldo_module_map),  
  47.     .pin_map = comip_lp3925_pin_map,  
  48.     .pin_map_num = ARRAY_SIZE(comip_lp3925_pin_map),  
  49.     .buck1_dvs = 1,  
  50.     .buck2_dvs = 3,  
  51. };  
  52. #endif  
最后是i2c0_board_info中添加的I2C数据项:
  1. #if defined(CONFIG_COMIP_LP3925)  
  2.     {  
  3.         .type = "lp3925",      // 这个名字就必须与上面的 id 同一个名字,以便进行匹配。  
  4.         .addr = 0x7e,    //i2c slave 地址  
  5.         .platform_data    = &comip_i2c_lp3925_info,  //这就是platform_data  
  6.     },  
  7. #endif  


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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多