static int max8903_ac_detect_handle(void* dev, int ac_handle) { struct S10_std_charger_device* charger = (struct S10_std_charger_device*)dev; struct max8903_dev_info *dev_info = charger ? (struct max8903_dev_info *)charger->charger_private_info : NULL; struct max8903_platform_data *pdata = dev_info ? dev_info->pdata : NULL; int ret = 0; power_debug(HW_POWER_CHARGER_IC_DUG, "%s:ac_handle=%d\n", __func__,ac_handle); if( ac_handle != AC_STATUS_DETECT && ac_handle != AC_IRQ_REQUEST && ac_handle != AC_IRQ_FREE) { return -EINVAL; //参数非法,返回 } switch(ac_handle){ case AC_STATUS_DETECT: if (pdata->dok && gpio_is_valid(pdata->dok)) { ret = gpio_get_value(pdata->dok) ? 0 : 1; } else { dev_err(dev, "When DC is wired, DOK should be wired." "as well.\n"); ret = -EIO; return ret; } break; case AC_IRQ_REQUEST: if (pdata->dc_valid) { ret = request_threaded_irq(gpio_to_irq(pdata->dok), NULL, max8903_dc_in, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "MAX8903 DC IN", charger); if (ret) { dev_err(dev, "Cannot request irq %d for DC (%d)\n", gpio_to_irq(pdata->dok), ret); return ret; } } break; case AC_IRQ_FREE: if (pdata->dc_valid) { free_irq(gpio_to_irq(pdata->dok), charger); } break; default: break; } return ret; }
static int max8903_report_get_property_usb(struct power_supply * psy, enum power_supply_property psp, union power_supply_propval *val) { struct S10_std_charger_device* charger = charger_max8903; int charger_type_usb = 0; if (IS_ERR_OR_NULL(charger)) { return -EINVAL; } switch (psp) { case POWER_SUPPLY_PROP_STATUS: val->intval = charger->charger_report_info.charging_status; break; case POWER_SUPPLY_PROP_ONLINE: charger_type_usb = ((POWER_SUPPLY_TYPE_USB == charger->charger_report_info.charger_type) || (POWER_SUPPLY_TYPE_USB_CDP == charger->charger_report_info.charger_type) || (POWER_SUPPLY_TYPE_UPS == charger->charger_report_info.charger_type)); if (charger_type_usb) { val->intval = charger->charger_report_info.charger_online; break; } else { val->intval = 0; break; } case POWER_SUPPLY_PROP_TYPE: val->intval = charger->charger_report_info.charger_type; break; case POWER_SUPPLY_PROP_HEALTH: val->intval = charger->charger_report_info.charger_health; break; default: break; } power_debug(HW_POWER_CHARGER_IC_DUG, "[Power Dug: %s, %s, %d,%d]: psp = %d \n", __FILE__, __func__, __LINE__, psp, val->intval); return 0; }
static int dev_cfg( INI *dev) { int ret = 0; config_debug("(dev_cfg): start\n"); ret = lead_amp_load_cfg(dev); if( ret < 0) { config_debug( "(head_amp_load_cfg) : return err! dev = %x\n", (unsigned int)dev); } ret = peripheral_load_cfg(dev); if( ret < 0) { config_debug("(peripheral_load_cfg): return err! ret=%d, dev=%x\n",ret, (unsigned int)dev); } ret = caller_load_cfg(dev); if( ret < 0) { config_debug("(caller_load_cfg): return err! ret=%d, dev=%x\n",ret, (unsigned int)dev); } ret = select_amp_load_cfg(dev); if( ret < 0) { config_debug("(select_amp_load_cfg): return err! ret=%d, dev=%x\n",ret, (unsigned int)dev); } ret = matrix_load_cfg(dev); if(ret <0){ config_debug("(matrix_load_cfg): return err! ret = %d, dev= %x\n", ret, ( unsigned int )dev); } ret = power_load_cfg(dev); if(ret <0){ power_debug("(power_load_cfg): return err! ret = %d, dev= %x\n", ret, ( unsigned int )dev); } ret = sound_load_cfg(dev); if(ret < 0) { config_debug("(sound_load_cfg): err!, ret = %d, dev = %x\n", ret, (unsigned int) dev); } return ret; }
static __devinit int max8903_charger_probe(struct platform_device *pdev) { struct S10_std_charger_device* charger; struct max8903_dev_info* dev_info; struct device *dev = &pdev->dev; struct max8903_platform_data *pdata = pdev->dev.platform_data; int ret = 0; struct S10_psy_monitor_dev_info* monitordev_info = NULL; //#ifdef RECOGNISE_CHARGER_TYPE_BY_EXTRAL_IC // struct notifier_block nb; //#endif printk("%s\n", __func__); charger = kzalloc(sizeof(struct S10_std_charger_device), GFP_KERNEL); if (charger == NULL) { dev_err(dev, "Cannot allocate memory.\n"); return -ENOMEM; } //分配充电器私有数据空间 dev_info = kzalloc(sizeof(struct max8903_dev_info), GFP_KERNEL); if (dev_info == NULL) { dev_err(dev, "Cannot allocate memory.\n"); return -ENOMEM; } dev_info->pdata = pdata; charger->dev = dev; charger->charger_private_info = (void*)dev_info; platform_set_drvdata(pdev, dev_info); //初始化充电相关的IO,供后面的代码使用 if (pdata->io_mux_block_init(pdata)) { ret = -EINVAL; goto err_iomux_init; } //if (pdata->gpio_block_init(pdata)) //{ // ret = -EINVAL; // goto err_gpio_init; // } //判断MAX8903芯片的各个管脚是否可用 //DC与USB充电器须可用 if ((pdata->dc_valid == false) && (pdata->usb_valid == false)) { dev_err(dev, "No valid power sources.\n"); ret = -EINVAL; goto err_config_charger; } //使能MAX8903,后续不再操作CEN管脚(MAX8903芯片有bug,使系统的电压跌落0.8v左右导致死机) //printk("LEON>>1\n"); if (pdata->cen) { if (gpio_is_valid(pdata->cen)) { //printk("LEON>>2\n"); gpio_set_value(pdata->cen, 0); } else { dev_err(dev, "Invalid pin: cen.\n"); ret = -EINVAL; goto err_config_charger; } } if (pdata->chg) { if (!gpio_is_valid(pdata->chg)) { dev_err(dev, "Invalid pin: chg.\n"); ret = -EINVAL; goto err_config_charger; } } if (pdata->flt) { //充电异常处理IO,必须可使用 if (!gpio_is_valid(pdata->flt)) { dev_err(dev, "Invalid pin: flt.\n"); ret = -EINVAL; goto err_config_charger; } //printk("LEON>>3\n"); ret = request_threaded_irq(gpio_to_irq(pdata->flt), NULL, max8903_fault, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "MAX8903 Fault", charger); if (ret) { dev_err(dev, "Cannot request irq %d for Fault (%d)\n", gpio_to_irq(pdata->flt), ret); goto err_config_charger; } } if (pdata->usus) { if (!gpio_is_valid(pdata->usus)) { dev_err(dev, "Invalid pin: usus.\n"); // ret = -EINVAL; // goto err_config_charger; } } //检查充电器是否已在位,如果已在位,则设置相应充电电流 //此处不检测,fsa880驱动后于此驱动加载且fsa880会主动检测充电器是否在位 //如果在位,则发送notifier消息来通知Max8903驱动 #ifdef RECOGNISE_CHARGER_TYPE_BY_EXTRAL_IC dev_info->nb.notifier_call = max8903_charger_plug_event; ret = blocking_notifier_chain_register(¬ifier_list_psy, &(dev_info->nb)); if (ret) { goto err_notifier_register; } #endif //填充S10_std_charger_device结构并向监控模块注册 strcpy(charger->name, AC_CHARGER); charger->charger_report_get_property = max8903_get_property; charger->charging_done_flag = 1; //充电是否截止标志 charger->psy_type = POWER_SUPPLY_TYPE_MAINS;/* 注册type为AC的电量上报节点 */ //此处不再判断充电器在位与否,也不再更新power_supply设备通知上层 #if 0 charger->charger_online = dev_info.ac_in || dev_info.usb_in ? 1 : 0; if (dev_info.ac_in) { charger->charger_type = POWER_SUPPLY_TYPE_USB; } else if (dev_info.usb_in) { charger->charger_type = POWER_SUPPLY_TYPE_USB_ACA; } else { charger->charger_type = POWER_SUPPLY_TYPE_MAINS; } #endif charger->S10_charger_support_props = max8903_charger_props; charger->num_properties = ARRAY_SIZE(max8903_charger_props); charger->ops = &max8903_private_ops; charger_max8903 = charger; monitordev_info = S10_power_get_monitor_devinfo(); if (monitordev_info->usb_charging_support) { charger->charger_report_get_property_usb = max8903_report_get_property_usb; } else { charger->charger_report_get_property_usb = NULL; } ret = charger2monitor_register(charger); if (ret) { power_debug(HW_POWER_CHARGER_IC_ERR, "[Power ERR: %s, %s, %d]\n", __FILE__, __func__, __LINE__); goto err_register2monitor; } return 0; err_register2monitor: charger_max8903 = NULL; #ifdef RECOGNISE_CHARGER_TYPE_BY_EXTRAL_IC blocking_notifier_chain_unregister(¬ifier_list_psy, &(dev_info->nb)); err_notifier_register: if (pdata->flt) { free_irq(gpio_to_irq(pdata->flt), charger); } #endif err_config_charger: // pdata->gpio_block_exit(pdata); err_gpio_init: pdata->io_mux_block_exit(pdata); err_iomux_init: kfree(charger); kfree(dev_info); return ret; }
static int max8903_charger_plug_event(struct notifier_block *nb, unsigned long event, void *_data) { //unsigned long report_event; struct S10_std_charger_device* charger = charger_max8903; struct max8903_dev_info *dev_info = charger ? (struct max8903_dev_info *)charger->charger_private_info : NULL; int dock_charger_online = 0; if (IS_ERR_OR_NULL(charger) || IS_ERR_OR_NULL(dev_info)) { return -EINVAL; } power_debug(HW_POWER_CHARGER_IC_DUG, "%s:event=%d\n", __func__,event); switch (event) { case CHG_USB_CDP_PULGIN_EVENT: dev_info->usb_in = true; charger->charger_online = 1; charger->charger_type = POWER_SUPPLY_TYPE_USB_CDP; break; case CHG_USB_DCP_PULGIN_EVENT: dev_info->usb_in = true; charger->charger_online = 1; charger->charger_type = POWER_SUPPLY_TYPE_USB_DCP; break; case CHG_USB_SDP_PULGIN_EVENT: dev_info->usb_in = true; charger->charger_online = 1; charger->charger_type = POWER_SUPPLY_TYPE_USB; break; case CHG_DOCK_PULGIN_EVENT: dev_info->dock_in = true; //DOCK口状态有变化,检测是否有充电器已插入 dock_charger_online = max8903_ac_detect_handle(charger, AC_STATUS_DETECT); power_debug(HW_POWER_CHARGER_IC_DUG, "%s:dock_charger_online=%d\n", __func__,dock_charger_online); if(dock_charger_online) { dev_info->ac_in = true; charger->charger_online = 1; charger->charger_type = POWER_SUPPLY_TYPE_USB_ACA; } //注册一个DOK中断信号 max8903_ac_detect_handle(charger, AC_IRQ_REQUEST); break; case CHG_AC_PULGIN_EVENT: dev_info->ac_in = true; charger->charger_online = 1; charger->charger_type = POWER_SUPPLY_TYPE_USB_ACA; break; case CHG_CHARGER_PULGOUT_EVENT: if(dev_info->dock_in){ //释放DOK中断信号 max8903_ac_detect_handle(charger, AC_IRQ_FREE); dev_info->dock_in = false; } dev_info->ac_in = false; dev_info->usb_in = false; charger->charger_online = 0; charger->charger_type = POWER_SUPPLY_TYPE_MAINS; break; case PSY_INFO_CHANGE_EVENT: break; default: break; } #if 0 //注释原因:CEN常开 if (dev_info->pdata->cen) { gpio_set_value(dev_info->pdata->cen, dev_info->ac_in || dev_info->usb_in ? 0 : 1); } #endif //充电器拨出,设定默认输入电流为500mA if(!charger->charger_online){ charger->charger_type = POWER_SUPPLY_TYPE_USB; } max8903_max_input_current_set(charger, 0);//设定输入电流 //通知Monitor监控模块充电器状态的变化 S10_power_monitor_notifier_call_chain(event, NULL); power_debug(HW_POWER_CHARGER_IC_DUG, "%s:End!\n", __func__); }