Add pvpanic_add/remove_device API. Follow-up patches will use them to add/remove specific drivers into framework.
Signed-off-by: Peng Hao <peng.h...@zte.com.cn> --- drivers/misc/pvpanic/pvpanic.c | 47 ++++++++++++++++++++++++++++++++++++++---- drivers/misc/pvpanic/pvpanic.h | 15 ++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 drivers/misc/pvpanic/pvpanic.h diff --git a/drivers/misc/pvpanic/pvpanic.c b/drivers/misc/pvpanic/pvpanic.c index f44a884..6225dfb 100644 --- a/drivers/misc/pvpanic/pvpanic.c +++ b/drivers/misc/pvpanic/pvpanic.c @@ -14,7 +14,11 @@ #include <linux/platform_device.h> #include <linux/types.h> -static void __iomem *base; +static struct { + struct platform_device *pdev; + void __iomem *base; + bool is_ioport; +} pvpanic_data; #define PVPANIC_PANICKED (1 << 0) @@ -25,7 +29,7 @@ static void pvpanic_send_event(unsigned int event) { - iowrite8(event, base); + iowrite8(event, pvpanic_data.base); } static int @@ -41,10 +45,43 @@ .priority = 1, /* let this called before broken drm_fb_helper */ }; +int pvpanic_add_device(struct device *dev, struct resource *res) +{ + struct platform_device *pdev; + int ret; + + pdev = platform_device_alloc("pvpanic", -1); + if (!pdev) + return -ENOMEM; + + pdev->dev.parent = dev; + + ret = platform_device_add_resources(pdev, res, 1); + if (ret) + goto err; + + ret = platform_device_add(pdev); + if (ret) + goto err; + pvpanic_data.pdev = pdev; + + return 0; +err: + platform_device_put(pdev); + return -1; +} + +void pvpanic_remove_device(void) +{ + platform_device_unregister(pvpanic_data.pdev); + pvpanic_data.pdev = NULL; +} + static int pvpanic_platform_probe (struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; + void __iomem *base; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res) { @@ -59,8 +96,10 @@ static int pvpanic_platform_probe (struct platform_device *pdev) base = ioport_map(res->start, resource_size(res)); if (!base) return -ENODEV; + pvpanic_data.is_ioport = true; } + pvpanic_data.base = base; atomic_notifier_chain_register(&panic_notifier_list, &pvpanic_panic_nb); @@ -71,8 +110,8 @@ static int pvpanic_platform_remove(struct platform_device *pdev) { atomic_notifier_chain_unregister(&panic_notifier_list, &pvpanic_panic_nb); - - iounmap(base); + if (pvpanic_data.is_ioport) + iounmap(pvpanic_data.base); return 0; } diff --git a/drivers/misc/pvpanic/pvpanic.h b/drivers/misc/pvpanic/pvpanic.h new file mode 100644 index 0000000..7fb6bb2 --- /dev/null +++ b/drivers/misc/pvpanic/pvpanic.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* pvpanic driver framework header file + * + * Copyright (C) 2019 ZTE Ltd. + * + * Author: Peng Hao <peng.h...@zte.com.cn> + */ + +#ifndef __DRIVERS_MISC_PVPANIC_H +#define __DRIVERS_MISC_PVPANIC_H + +extern int pvpanic_add_device(struct device *dev, struct resource *res); +extern void pvpanic_remove_device(void); + +#endif -- 1.8.3.1