/* * drivers/power/supply/axp/axp20x/axp20x-virtual.c * (C) Copyright 2010-2016 * Allwinner Technology Co., Ltd. * caiyongheng * * virtual regulator driver of axp20x * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * */ #include #include #include #include #include #include #include "../axp-virtual.h" struct axp_virtual_dev_mapping axp20x_mapping[] = { {"reg-20-cs-dcdc2", "axp20x_dcdc2"}, {"reg-20-cs-dcdc3", "axp20x_dcdc3"}, {"reg-20-cs-rtc", "axp20x_rtc"}, {"reg-20-cs-ldo2", "axp20x_ldo2"}, {"reg-20-cs-ldo3", "axp20x_ldo3"}, {"reg-20-cs-ldo4", "axp20x_ldo4"}, {"reg-20-cs-ldoio0", "axp20x_ldoio0"}, }; static struct platform_device axp20x_vr_pdev[ARRAY_SIZE(axp20x_mapping)]; static struct platform_driver axp20x_vr_pdrv[ARRAY_SIZE(axp20x_mapping)]; static int axp20x_vrd_probe(struct platform_device *pdev) { char *reg_id = pdev->dev.platform_data; struct virtual_consumer_data *drvdata; int ret, i; const char *pmu_name; for (i = 0; i < AXP_ONLINE_SUM; i++) { pmu_name = get_pmu_cur_name(i); if (pmu_name == NULL) continue; if (!strncmp("axp20", pmu_name, 5) || !strncmp("axp209", pmu_name, 6)) break; else continue; } if (i == AXP_ONLINE_SUM) return 0; drvdata = kzalloc(sizeof(struct virtual_consumer_data), GFP_KERNEL); if (drvdata == NULL) { ret = -ENOMEM; goto err; } mutex_init(&drvdata->lock); sprintf(drvdata->regu_name, reg_id); for (i = 0; i < ARRAY_SIZE(attributes_virtual); i++) { ret = device_create_file(&pdev->dev, attributes_virtual[i]); if (ret != 0) goto err; } platform_set_drvdata(pdev, drvdata); return 0; err: for (i = 0; i < ARRAY_SIZE(attributes_virtual); i++) device_remove_file(&pdev->dev, attributes_virtual[i]); kfree(drvdata); return ret; } static int axp20x_vrd_remove(struct platform_device *pdev) { struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev); int i; for (i = 0; i < ARRAY_SIZE(attributes_virtual); i++) device_remove_file(&pdev->dev, attributes_virtual[i]); kfree(drvdata); return 0; } static int __init axp20x_virtual_regulator_pdrv_init(void) { int j, ret; ret = axp_add_virtual_regulator_devices(axp20x_vr_pdev, ARRAY_SIZE(axp20x_mapping), axp20x_mapping); if (ret) { pr_err("%s: add virtual devices failed\n", __func__); return -EINVAL; } axp_init_virtual_regulator_drivers(axp20x_vr_pdrv, ARRAY_SIZE(axp20x_mapping), axp20x_mapping, axp20x_vrd_probe, axp20x_vrd_remove); for (j = 0; j < ARRAY_SIZE(axp20x_mapping); j++) { ret = platform_driver_register(&axp20x_vr_pdrv[j]); if (ret) goto creat_drivers_failed; } return ret; creat_drivers_failed: while (j--) platform_driver_unregister( &axp20x_vr_pdrv[j]); return ret; } module_init(axp20x_virtual_regulator_pdrv_init); static void __exit axp20x_virtual_regulator_pdrv_exit(void) { int j; for (j = ARRAY_SIZE(axp20x_mapping) - 1; j >= 0; j--) platform_driver_unregister(&axp20x_vr_pdrv[j]); for (j = 0; j < ARRAY_SIZE(axp20x_mapping); j++) platform_device_unregister(&axp20x_vr_pdev[j]); } module_exit(axp20x_virtual_regulator_pdrv_exit); MODULE_DESCRIPTION("Virtual regulator driver of axp20x"); MODULE_AUTHOR("caiyongheng"); MODULE_LICENSE("GPL");