drivers/power/supply/ab8500_charger.c

Source file repositories/reference/linux-study-clean/drivers/power/supply/ab8500_charger.c

File Facts

System
Linux kernel
Corpus path
drivers/power/supply/ab8500_charger.c
Extension
.c
Size
105215 bytes
Lines
3754
Domain
Driver Families
Bucket
drivers/power
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct device_driver *drv = &ab8500_charger_component_drivers[i]->driver;
		struct device *p = NULL, *d;

		while ((d = platform_find_device_by_driver(p, drv))) {
			put_device(p);
			component_match_add(dev, &match, component_compare_dev, d);
			p = d;
		}
		put_device(p);
	}
	if (!match) {
		dev_err(dev, "no matching components\n");
		ret = -ENODEV;
		goto remove_ab8500_bm;
	}
	if (IS_ERR(match)) {
		dev_err(dev, "could not create component match\n");
		ret = PTR_ERR(match);
		goto remove_ab8500_bm;
	}

	di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
	if (IS_ERR_OR_NULL(di->usb_phy)) {
		dev_err(dev, "failed to get usb transceiver\n");
		ret = -EINVAL;
		goto remove_ab8500_bm;
	}
	di->nb.notifier_call = ab8500_charger_usb_notifier_call;
	ret = usb_register_notifier(di->usb_phy, &di->nb);
	if (ret) {
		dev_err(dev, "failed to register usb notifier\n");
		goto put_usb_phy;
	}

	ret = component_master_add_with_match(&pdev->dev,
					      &ab8500_charger_comp_ops,
					      match);
	if (ret) {
		dev_err(dev, "failed to add component master\n");
		goto free_notifier;
	}

	return 0;

free_notifier:
	usb_unregister_notifier(di->usb_phy, &di->nb);
put_usb_phy:
	usb_put_phy(di->usb_phy);
remove_ab8500_bm:
	ab8500_bm_of_remove(di->usb_chg.psy, di->bm);
	return ret;
}

static void ab8500_charger_remove(struct platform_device *pdev)
{
	struct ab8500_charger *di = platform_get_drvdata(pdev);

	component_master_del(&pdev->dev, &ab8500_charger_comp_ops);

	usb_unregister_notifier(di->usb_phy, &di->nb);
	ab8500_bm_of_remove(di->usb_chg.psy, di->bm);
	usb_put_phy(di->usb_phy);
}

static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume);

static const struct of_device_id ab8500_charger_match[] = {
	{ .compatible = "stericsson,ab8500-charger", },
	{ },
};
MODULE_DEVICE_TABLE(of, ab8500_charger_match);

static struct platform_driver ab8500_charger_driver = {
	.probe = ab8500_charger_probe,
	.remove = ab8500_charger_remove,
	.driver = {
		.name = "ab8500-charger",
		.of_match_table = ab8500_charger_match,
		.pm = &ab8500_charger_pm_ops,
	},
};

static int __init ab8500_charger_init(void)
{
	int ret;

	ret = platform_register_drivers(ab8500_charger_component_drivers,
			ARRAY_SIZE(ab8500_charger_component_drivers));
	if (ret)
		return ret;

Annotation

Implementation Notes