ab8500_charger.c (942baad211336efefb93a8369478888ab845c450) | ab8500_charger.c (1c1f13a006ed0d71bb5664c8b7e3e77a28da3beb) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) ST-Ericsson SA 2012 4 * 5 * Charger driver for AB8500 6 * 7 * Author: 8 * Johan Palsson <johan.palsson@stericsson.com> 9 * Karl Komierowski <karl.komierowski@stericsson.com> 10 * Arun R Murthy <arun.murthy@stericsson.com> 11 */ 12 13#include <linux/init.h> 14#include <linux/module.h> 15#include <linux/device.h> | 1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) ST-Ericsson SA 2012 4 * 5 * Charger driver for AB8500 6 * 7 * Author: 8 * Johan Palsson <johan.palsson@stericsson.com> 9 * Karl Komierowski <karl.komierowski@stericsson.com> 10 * Arun R Murthy <arun.murthy@stericsson.com> 11 */ 12 13#include <linux/init.h> 14#include <linux/module.h> 15#include <linux/device.h> |
16#include <linux/component.h> |
|
16#include <linux/interrupt.h> 17#include <linux/delay.h> 18#include <linux/notifier.h> 19#include <linux/slab.h> 20#include <linux/platform_device.h> 21#include <linux/power_supply.h> 22#include <linux/completion.h> 23#include <linux/regulator/consumer.h> --- 3247 unchanged lines hidden (view full) --- 3271 3272 return 0; 3273} 3274 3275static struct notifier_block charger_nb = { 3276 .notifier_call = ab8500_external_charger_prepare, 3277}; 3278 | 17#include <linux/interrupt.h> 18#include <linux/delay.h> 19#include <linux/notifier.h> 20#include <linux/slab.h> 21#include <linux/platform_device.h> 22#include <linux/power_supply.h> 23#include <linux/completion.h> 24#include <linux/regulator/consumer.h> --- 3247 unchanged lines hidden (view full) --- 3272 3273 return 0; 3274} 3275 3276static struct notifier_block charger_nb = { 3277 .notifier_call = ab8500_external_charger_prepare, 3278}; 3279 |
3279static int ab8500_charger_remove(struct platform_device *pdev) | 3280static char *supply_interface[] = { 3281 "ab8500_chargalg", 3282 "ab8500_fg", 3283 "ab8500_btemp", 3284}; 3285 3286static const struct power_supply_desc ab8500_ac_chg_desc = { 3287 .name = "ab8500_ac", 3288 .type = POWER_SUPPLY_TYPE_MAINS, 3289 .properties = ab8500_charger_ac_props, 3290 .num_properties = ARRAY_SIZE(ab8500_charger_ac_props), 3291 .get_property = ab8500_charger_ac_get_property, 3292}; 3293 3294static const struct power_supply_desc ab8500_usb_chg_desc = { 3295 .name = "ab8500_usb", 3296 .type = POWER_SUPPLY_TYPE_USB, 3297 .properties = ab8500_charger_usb_props, 3298 .num_properties = ARRAY_SIZE(ab8500_charger_usb_props), 3299 .get_property = ab8500_charger_usb_get_property, 3300}; 3301 3302static int ab8500_charger_bind(struct device *dev) |
3280{ | 3303{ |
3281 struct ab8500_charger *di = platform_get_drvdata(pdev); 3282 int i, irq, ret; | 3304 struct ab8500_charger *di = dev_get_drvdata(dev); 3305 int ch_stat; 3306 int ret; |
3283 | 3307 |
3308 /* Create a work queue for the charger */ 3309 di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq", 3310 WQ_MEM_RECLAIM); 3311 if (di->charger_wq == NULL) { 3312 dev_err(dev, "failed to create work queue\n"); 3313 return -ENOMEM; 3314 } 3315 3316 ch_stat = ab8500_charger_detect_chargers(di, false); 3317 3318 if (ch_stat & AC_PW_CONN) { 3319 if (is_ab8500(di->parent)) 3320 queue_delayed_work(di->charger_wq, 3321 &di->ac_charger_attached_work, 3322 HZ); 3323 } 3324 if (ch_stat & USB_PW_CONN) { 3325 if (is_ab8500(di->parent)) 3326 queue_delayed_work(di->charger_wq, 3327 &di->usb_charger_attached_work, 3328 HZ); 3329 di->vbus_detected = true; 3330 di->vbus_detected_start = true; 3331 queue_work(di->charger_wq, 3332 &di->detect_usb_type_work); 3333 } 3334 3335 ret = component_bind_all(dev, di); 3336 if (ret) { 3337 dev_err(dev, "can't bind component devices\n"); 3338 return ret; 3339 } 3340 3341 return 0; 3342} 3343 3344static void ab8500_charger_unbind(struct device *dev) 3345{ 3346 struct ab8500_charger *di = dev_get_drvdata(dev); 3347 int ret; 3348 |
|
3284 /* Disable AC charging */ 3285 ab8500_charger_ac_en(&di->ac_chg, false, 0, 0); 3286 3287 /* Disable USB charging */ 3288 ab8500_charger_usb_en(&di->usb_chg, false, 0, 0); 3289 | 3349 /* Disable AC charging */ 3350 ab8500_charger_ac_en(&di->ac_chg, false, 0, 0); 3351 3352 /* Disable USB charging */ 3353 ab8500_charger_usb_en(&di->usb_chg, false, 0, 0); 3354 |
3290 /* Disable interrupts */ 3291 for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { 3292 irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 3293 free_irq(irq, di); 3294 } 3295 | |
3296 /* Backup battery voltage and current disable */ 3297 ret = abx500_mask_and_set_register_interruptible(di->dev, 3298 AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0); 3299 if (ret < 0) 3300 dev_err(di->dev, "%s mask and set failed\n", __func__); 3301 | 3355 /* Backup battery voltage and current disable */ 3356 ret = abx500_mask_and_set_register_interruptible(di->dev, 3357 AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0); 3358 if (ret < 0) 3359 dev_err(di->dev, "%s mask and set failed\n", __func__); 3360 |
3302 usb_unregister_notifier(di->usb_phy, &di->nb); 3303 usb_put_phy(di->usb_phy); 3304 | |
3305 /* Delete the work queue */ 3306 destroy_workqueue(di->charger_wq); 3307 | 3361 /* Delete the work queue */ 3362 destroy_workqueue(di->charger_wq); 3363 |
3308 /* Unregister external charger enable notifier */ 3309 if (!di->ac_chg.enabled) 3310 blocking_notifier_chain_unregister( 3311 &charger_notifier_list, &charger_nb); 3312 | |
3313 flush_scheduled_work(); | 3364 flush_scheduled_work(); |
3314 if (di->usb_chg.enabled) 3315 power_supply_unregister(di->usb_chg.psy); | |
3316 | 3365 |
3317 if (di->ac_chg.enabled && !di->ac_chg.external) 3318 power_supply_unregister(di->ac_chg.psy); 3319 3320 return 0; | 3366 /* Unbind fg, btemp, algorithm */ 3367 component_unbind_all(dev, di); |
3321} 3322 | 3368} 3369 |
3323static char *supply_interface[] = { 3324 "ab8500_chargalg", 3325 "ab8500_fg", 3326 "ab8500_btemp", | 3370static const struct component_master_ops ab8500_charger_comp_ops = { 3371 .bind = ab8500_charger_bind, 3372 .unbind = ab8500_charger_unbind, |
3327}; 3328 | 3373}; 3374 |
3329static const struct power_supply_desc ab8500_ac_chg_desc = { 3330 .name = "ab8500_ac", 3331 .type = POWER_SUPPLY_TYPE_MAINS, 3332 .properties = ab8500_charger_ac_props, 3333 .num_properties = ARRAY_SIZE(ab8500_charger_ac_props), 3334 .get_property = ab8500_charger_ac_get_property, | 3375static struct platform_driver *const ab8500_charger_component_drivers[] = { 3376 &ab8500_fg_driver, 3377 &ab8500_btemp_driver, 3378 &abx500_chargalg_driver, |
3335}; 3336 | 3379}; 3380 |
3337static const struct power_supply_desc ab8500_usb_chg_desc = { 3338 .name = "ab8500_usb", 3339 .type = POWER_SUPPLY_TYPE_USB, 3340 .properties = ab8500_charger_usb_props, 3341 .num_properties = ARRAY_SIZE(ab8500_charger_usb_props), 3342 .get_property = ab8500_charger_usb_get_property, 3343}; | 3381static int ab8500_charger_compare_dev(struct device *dev, void *data) 3382{ 3383 return dev == data; 3384} |
3344 3345static int ab8500_charger_probe(struct platform_device *pdev) 3346{ | 3385 3386static int ab8500_charger_probe(struct platform_device *pdev) 3387{ |
3347 struct device_node *np = pdev->dev.of_node; | 3388 struct device *dev = &pdev->dev; 3389 struct device_node *np = dev->of_node; 3390 struct component_match *match = NULL; |
3348 struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {}; 3349 struct ab8500_charger *di; | 3391 struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {}; 3392 struct ab8500_charger *di; |
3350 int irq, i, charger_status, ret = 0, ch_stat; 3351 struct device *dev = &pdev->dev; | 3393 int charger_status; 3394 int i, irq; 3395 int ret; |
3352 3353 di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); 3354 if (!di) 3355 return -ENOMEM; 3356 3357 di->bm = &ab8500_bm_data; 3358 3359 ret = ab8500_bm_of_probe(dev, np, di->bm); --- 28 unchanged lines hidden (view full) --- 3388 } 3389 di->adc_usb_charger_c = devm_iio_channel_get(dev, "usb_charger_c"); 3390 if (IS_ERR(di->adc_usb_charger_c)) { 3391 ret = dev_err_probe(dev, PTR_ERR(di->adc_usb_charger_c), 3392 "failed to get ADC USB charger current\n"); 3393 return ret; 3394 } 3395 | 3396 3397 di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); 3398 if (!di) 3399 return -ENOMEM; 3400 3401 di->bm = &ab8500_bm_data; 3402 3403 ret = ab8500_bm_of_probe(dev, np, di->bm); --- 28 unchanged lines hidden (view full) --- 3432 } 3433 di->adc_usb_charger_c = devm_iio_channel_get(dev, "usb_charger_c"); 3434 if (IS_ERR(di->adc_usb_charger_c)) { 3435 ret = dev_err_probe(dev, PTR_ERR(di->adc_usb_charger_c), 3436 "failed to get ADC USB charger current\n"); 3437 return ret; 3438 } 3439 |
3440 /* 3441 * VDD ADC supply needs to be enabled from this driver when there 3442 * is a charger connected to avoid erroneous BTEMP_HIGH/LOW 3443 * interrupts during charging 3444 */ 3445 di->regu = devm_regulator_get(dev, "vddadc"); 3446 if (IS_ERR(di->regu)) { 3447 ret = PTR_ERR(di->regu); 3448 dev_err(dev, "failed to get vddadc regulator\n"); 3449 return ret; 3450 } 3451 3452 /* Request interrupts */ 3453 for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { 3454 irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 3455 if (irq < 0) 3456 return irq; 3457 3458 ret = devm_request_threaded_irq(dev, 3459 irq, NULL, ab8500_charger_irq[i].isr, 3460 IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, 3461 ab8500_charger_irq[i].name, di); 3462 3463 if (ret != 0) { 3464 dev_err(dev, "failed to request %s IRQ %d: %d\n" 3465 , ab8500_charger_irq[i].name, irq, ret); 3466 return ret; 3467 } 3468 dev_dbg(dev, "Requested %s IRQ %d: %d\n", 3469 ab8500_charger_irq[i].name, irq, ret); 3470 } 3471 |
|
3396 /* initialize lock */ 3397 spin_lock_init(&di->usb_state.usb_lock); 3398 mutex_init(&di->usb_ipt_crnt_lock); 3399 3400 di->autopower = false; 3401 di->invalid_charger_detect_state = 0; 3402 3403 /* AC and USB supply config */ --- 13 unchanged lines hidden (view full) --- 3417 di->ac_chg.max_out_volt = ab8500_charger_voltage_map[ 3418 ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 3419 di->ac_chg.max_out_curr = 3420 di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1]; 3421 di->ac_chg.wdt_refresh = CHG_WD_INTERVAL; 3422 di->ac_chg.enabled = di->bm->ac_enabled; 3423 di->ac_chg.external = false; 3424 | 3472 /* initialize lock */ 3473 spin_lock_init(&di->usb_state.usb_lock); 3474 mutex_init(&di->usb_ipt_crnt_lock); 3475 3476 di->autopower = false; 3477 di->invalid_charger_detect_state = 0; 3478 3479 /* AC and USB supply config */ --- 13 unchanged lines hidden (view full) --- 3493 di->ac_chg.max_out_volt = ab8500_charger_voltage_map[ 3494 ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 3495 di->ac_chg.max_out_curr = 3496 di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1]; 3497 di->ac_chg.wdt_refresh = CHG_WD_INTERVAL; 3498 di->ac_chg.enabled = di->bm->ac_enabled; 3499 di->ac_chg.external = false; 3500 |
3425 /*notifier for external charger enabling*/ 3426 if (!di->ac_chg.enabled) 3427 blocking_notifier_chain_register( 3428 &charger_notifier_list, &charger_nb); 3429 | |
3430 /* USB supply */ 3431 /* ux500_charger sub-class */ 3432 di->usb_chg.ops.enable = &ab8500_charger_usb_en; 3433 di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable; 3434 di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; 3435 di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current; 3436 di->usb_chg.max_out_volt = ab8500_charger_voltage_map[ 3437 ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 3438 di->usb_chg.max_out_curr = 3439 di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1]; 3440 di->usb_chg.wdt_refresh = CHG_WD_INTERVAL; 3441 di->usb_chg.enabled = di->bm->usb_enabled; 3442 di->usb_chg.external = false; 3443 di->usb_state.usb_current = -1; 3444 | 3501 /* USB supply */ 3502 /* ux500_charger sub-class */ 3503 di->usb_chg.ops.enable = &ab8500_charger_usb_en; 3504 di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable; 3505 di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; 3506 di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current; 3507 di->usb_chg.max_out_volt = ab8500_charger_voltage_map[ 3508 ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 3509 di->usb_chg.max_out_curr = 3510 di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1]; 3511 di->usb_chg.wdt_refresh = CHG_WD_INTERVAL; 3512 di->usb_chg.enabled = di->bm->usb_enabled; 3513 di->usb_chg.external = false; 3514 di->usb_state.usb_current = -1; 3515 |
3445 /* Create a work queue for the charger */ 3446 di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq", 3447 WQ_MEM_RECLAIM); 3448 if (di->charger_wq == NULL) { 3449 dev_err(dev, "failed to create work queue\n"); 3450 return -ENOMEM; 3451 } 3452 | |
3453 mutex_init(&di->charger_attached_mutex); 3454 3455 /* Init work for HW failure check */ 3456 INIT_DEFERRABLE_WORK(&di->check_hw_failure_work, 3457 ab8500_charger_check_hw_failure_work); 3458 INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work, 3459 ab8500_charger_check_usbchargernotok_work); 3460 --- 34 unchanged lines hidden (view full) --- 3495 ab8500_charger_detect_usb_type_work); 3496 3497 /* Init work for checking HW status */ 3498 INIT_WORK(&di->check_main_thermal_prot_work, 3499 ab8500_charger_check_main_thermal_prot_work); 3500 INIT_WORK(&di->check_usb_thermal_prot_work, 3501 ab8500_charger_check_usb_thermal_prot_work); 3502 | 3516 mutex_init(&di->charger_attached_mutex); 3517 3518 /* Init work for HW failure check */ 3519 INIT_DEFERRABLE_WORK(&di->check_hw_failure_work, 3520 ab8500_charger_check_hw_failure_work); 3521 INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work, 3522 ab8500_charger_check_usbchargernotok_work); 3523 --- 34 unchanged lines hidden (view full) --- 3558 ab8500_charger_detect_usb_type_work); 3559 3560 /* Init work for checking HW status */ 3561 INIT_WORK(&di->check_main_thermal_prot_work, 3562 ab8500_charger_check_main_thermal_prot_work); 3563 INIT_WORK(&di->check_usb_thermal_prot_work, 3564 ab8500_charger_check_usb_thermal_prot_work); 3565 |
3503 /* 3504 * VDD ADC supply needs to be enabled from this driver when there 3505 * is a charger connected to avoid erroneous BTEMP_HIGH/LOW 3506 * interrupts during charging 3507 */ 3508 di->regu = devm_regulator_get(dev, "vddadc"); 3509 if (IS_ERR(di->regu)) { 3510 ret = PTR_ERR(di->regu); 3511 dev_err(dev, "failed to get vddadc regulator\n"); 3512 goto free_charger_wq; 3513 } | |
3514 | 3566 |
3515 | |
3516 /* Initialize OVV, and other registers */ 3517 ret = ab8500_charger_init_hw_registers(di); 3518 if (ret) { 3519 dev_err(dev, "failed to initialize ABB registers\n"); | 3567 /* Initialize OVV, and other registers */ 3568 ret = ab8500_charger_init_hw_registers(di); 3569 if (ret) { 3570 dev_err(dev, "failed to initialize ABB registers\n"); |
3520 goto free_charger_wq; | 3571 return ret; |
3521 } 3522 3523 /* Register AC charger class */ 3524 if (di->ac_chg.enabled) { | 3572 } 3573 3574 /* Register AC charger class */ 3575 if (di->ac_chg.enabled) { |
3525 di->ac_chg.psy = power_supply_register(dev, | 3576 di->ac_chg.psy = devm_power_supply_register(dev, |
3526 &ab8500_ac_chg_desc, 3527 &ac_psy_cfg); 3528 if (IS_ERR(di->ac_chg.psy)) { 3529 dev_err(dev, "failed to register AC charger\n"); | 3577 &ab8500_ac_chg_desc, 3578 &ac_psy_cfg); 3579 if (IS_ERR(di->ac_chg.psy)) { 3580 dev_err(dev, "failed to register AC charger\n"); |
3530 ret = PTR_ERR(di->ac_chg.psy); 3531 goto free_charger_wq; | 3581 return PTR_ERR(di->ac_chg.psy); |
3532 } 3533 } 3534 3535 /* Register USB charger class */ 3536 if (di->usb_chg.enabled) { | 3582 } 3583 } 3584 3585 /* Register USB charger class */ 3586 if (di->usb_chg.enabled) { |
3537 di->usb_chg.psy = power_supply_register(dev, | 3587 di->usb_chg.psy = devm_power_supply_register(dev, |
3538 &ab8500_usb_chg_desc, 3539 &usb_psy_cfg); 3540 if (IS_ERR(di->usb_chg.psy)) { 3541 dev_err(dev, "failed to register USB charger\n"); | 3588 &ab8500_usb_chg_desc, 3589 &usb_psy_cfg); 3590 if (IS_ERR(di->usb_chg.psy)) { 3591 dev_err(dev, "failed to register USB charger\n"); |
3542 ret = PTR_ERR(di->usb_chg.psy); 3543 goto free_ac; | 3592 return PTR_ERR(di->usb_chg.psy); |
3544 } 3545 } 3546 | 3593 } 3594 } 3595 |
3547 di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); 3548 if (IS_ERR_OR_NULL(di->usb_phy)) { 3549 dev_err(dev, "failed to get usb transceiver\n"); 3550 ret = -EINVAL; 3551 goto free_usb; 3552 } 3553 di->nb.notifier_call = ab8500_charger_usb_notifier_call; 3554 ret = usb_register_notifier(di->usb_phy, &di->nb); 3555 if (ret) { 3556 dev_err(dev, "failed to register usb notifier\n"); 3557 goto put_usb_phy; 3558 } 3559 | |
3560 /* Identify the connected charger types during startup */ 3561 charger_status = ab8500_charger_detect_chargers(di, true); 3562 if (charger_status & AC_PW_CONN) { 3563 di->ac.charger_connected = 1; 3564 di->ac_conn = true; 3565 ab8500_power_supply_changed(di, di->ac_chg.psy); 3566 sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present"); 3567 } 3568 | 3596 /* Identify the connected charger types during startup */ 3597 charger_status = ab8500_charger_detect_chargers(di, true); 3598 if (charger_status & AC_PW_CONN) { 3599 di->ac.charger_connected = 1; 3600 di->ac_conn = true; 3601 ab8500_power_supply_changed(di, di->ac_chg.psy); 3602 sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present"); 3603 } 3604 |
3569 if (charger_status & USB_PW_CONN) { 3570 di->vbus_detected = true; 3571 di->vbus_detected_start = true; 3572 queue_work(di->charger_wq, 3573 &di->detect_usb_type_work); 3574 } | 3605 platform_set_drvdata(pdev, di); |
3575 | 3606 |
3576 /* Register interrupts */ 3577 for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { 3578 irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 3579 if (irq < 0) { 3580 ret = irq; 3581 goto free_irq; 3582 } | 3607 /* Create something that will match the subdrivers when we bind */ 3608 for (i = 0; i < ARRAY_SIZE(ab8500_charger_component_drivers); i++) { 3609 struct device_driver *drv = &ab8500_charger_component_drivers[i]->driver; 3610 struct device *p = NULL, *d; |
3583 | 3611 |
3584 ret = request_threaded_irq(irq, NULL, ab8500_charger_irq[i].isr, 3585 IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, 3586 ab8500_charger_irq[i].name, di); 3587 3588 if (ret != 0) { 3589 dev_err(dev, "failed to request %s IRQ %d: %d\n" 3590 , ab8500_charger_irq[i].name, irq, ret); 3591 goto free_irq; | 3612 while ((d = platform_find_device_by_driver(p, drv))) { 3613 put_device(p); 3614 component_match_add(dev, &match, 3615 ab8500_charger_compare_dev, d); 3616 p = d; |
3592 } | 3617 } |
3593 dev_dbg(dev, "Requested %s IRQ %d: %d\n", 3594 ab8500_charger_irq[i].name, irq, ret); | 3618 put_device(p); |
3595 } | 3619 } |
3620 if (!match) { 3621 dev_err(dev, "no matching components\n"); 3622 return -ENODEV; 3623 } 3624 if (IS_ERR(match)) { 3625 dev_err(dev, "could not create component match\n"); 3626 return PTR_ERR(match); 3627 } |
|
3596 | 3628 |
3597 platform_set_drvdata(pdev, di); | 3629 /* Notifier for external charger enabling */ 3630 if (!di->ac_chg.enabled) 3631 blocking_notifier_chain_register( 3632 &charger_notifier_list, &charger_nb); |
3598 | 3633 |
3599 mutex_lock(&di->charger_attached_mutex); | |
3600 | 3634 |
3601 ch_stat = ab8500_charger_detect_chargers(di, false); 3602 3603 if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) { 3604 if (is_ab8500(di->parent)) 3605 queue_delayed_work(di->charger_wq, 3606 &di->ac_charger_attached_work, 3607 HZ); | 3635 di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); 3636 if (IS_ERR_OR_NULL(di->usb_phy)) { 3637 dev_err(dev, "failed to get usb transceiver\n"); 3638 ret = -EINVAL; 3639 goto out_charger_notifier; |
3608 } | 3640 } |
3609 if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) { 3610 if (is_ab8500(di->parent)) 3611 queue_delayed_work(di->charger_wq, 3612 &di->usb_charger_attached_work, 3613 HZ); | 3641 di->nb.notifier_call = ab8500_charger_usb_notifier_call; 3642 ret = usb_register_notifier(di->usb_phy, &di->nb); 3643 if (ret) { 3644 dev_err(dev, "failed to register usb notifier\n"); 3645 goto put_usb_phy; |
3614 } 3615 | 3646 } 3647 |
3616 mutex_unlock(&di->charger_attached_mutex); | |
3617 | 3648 |
3618 return ret; | 3649 ret = component_master_add_with_match(&pdev->dev, 3650 &ab8500_charger_comp_ops, 3651 match); 3652 if (ret) { 3653 dev_err(dev, "failed to add component master\n"); 3654 goto free_notifier; 3655 } |
3619 | 3656 |
3620free_irq: 3621 usb_unregister_notifier(di->usb_phy, &di->nb); | 3657 return 0; |
3622 | 3658 |
3623 /* We also have to free all successfully registered irqs */ 3624 for (i = i - 1; i >= 0; i--) { 3625 irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); 3626 free_irq(irq, di); 3627 } | 3659free_notifier: 3660 usb_unregister_notifier(di->usb_phy, &di->nb); |
3628put_usb_phy: 3629 usb_put_phy(di->usb_phy); | 3661put_usb_phy: 3662 usb_put_phy(di->usb_phy); |
3630free_usb: 3631 if (di->usb_chg.enabled) 3632 power_supply_unregister(di->usb_chg.psy); 3633free_ac: 3634 if (di->ac_chg.enabled) 3635 power_supply_unregister(di->ac_chg.psy); 3636free_charger_wq: 3637 destroy_workqueue(di->charger_wq); | 3663out_charger_notifier: 3664 if (!di->ac_chg.enabled) 3665 blocking_notifier_chain_unregister( 3666 &charger_notifier_list, &charger_nb); |
3638 return ret; 3639} 3640 | 3667 return ret; 3668} 3669 |
3670static int ab8500_charger_remove(struct platform_device *pdev) 3671{ 3672 struct ab8500_charger *di = platform_get_drvdata(pdev); 3673 3674 component_master_del(&pdev->dev, &ab8500_charger_comp_ops); 3675 3676 usb_unregister_notifier(di->usb_phy, &di->nb); 3677 usb_put_phy(di->usb_phy); 3678 if (!di->ac_chg.enabled) 3679 blocking_notifier_chain_unregister( 3680 &charger_notifier_list, &charger_nb); 3681 3682 return 0; 3683} 3684 |
|
3641static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume); 3642 3643static const struct of_device_id ab8500_charger_match[] = { 3644 { .compatible = "stericsson,ab8500-charger", }, 3645 { }, 3646}; 3647 3648static struct platform_driver ab8500_charger_driver = { 3649 .probe = ab8500_charger_probe, 3650 .remove = ab8500_charger_remove, 3651 .driver = { 3652 .name = "ab8500-charger", 3653 .of_match_table = ab8500_charger_match, 3654 .pm = &ab8500_charger_pm_ops, 3655 }, 3656}; 3657 3658static int __init ab8500_charger_init(void) 3659{ | 3685static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume); 3686 3687static const struct of_device_id ab8500_charger_match[] = { 3688 { .compatible = "stericsson,ab8500-charger", }, 3689 { }, 3690}; 3691 3692static struct platform_driver ab8500_charger_driver = { 3693 .probe = ab8500_charger_probe, 3694 .remove = ab8500_charger_remove, 3695 .driver = { 3696 .name = "ab8500-charger", 3697 .of_match_table = ab8500_charger_match, 3698 .pm = &ab8500_charger_pm_ops, 3699 }, 3700}; 3701 3702static int __init ab8500_charger_init(void) 3703{ |
3704 int ret; 3705 3706 ret = platform_register_drivers(ab8500_charger_component_drivers, 3707 ARRAY_SIZE(ab8500_charger_component_drivers)); 3708 if (ret) 3709 return ret; 3710 |
|
3660 return platform_driver_register(&ab8500_charger_driver); 3661} 3662 3663static void __exit ab8500_charger_exit(void) 3664{ | 3711 return platform_driver_register(&ab8500_charger_driver); 3712} 3713 3714static void __exit ab8500_charger_exit(void) 3715{ |
3716 platform_unregister_drivers(ab8500_charger_component_drivers, 3717 ARRAY_SIZE(ab8500_charger_component_drivers)); |
|
3665 platform_driver_unregister(&ab8500_charger_driver); 3666} 3667 | 3718 platform_driver_unregister(&ab8500_charger_driver); 3719} 3720 |
3668subsys_initcall_sync(ab8500_charger_init); | 3721module_init(ab8500_charger_init); |
3669module_exit(ab8500_charger_exit); 3670 3671MODULE_LICENSE("GPL v2"); 3672MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy"); 3673MODULE_ALIAS("platform:ab8500-charger"); 3674MODULE_DESCRIPTION("AB8500 charger management driver"); | 3722module_exit(ab8500_charger_exit); 3723 3724MODULE_LICENSE("GPL v2"); 3725MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy"); 3726MODULE_ALIAS("platform:ab8500-charger"); 3727MODULE_DESCRIPTION("AB8500 charger management driver"); |