aboutsummaryrefslogtreecommitdiff
path: root/drivers/sh/pfc/core.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2012-12-15 23:50:47 +0100
committerSimon Horman <horms+renesas@verge.net.au>2013-01-25 09:24:21 +0900
commitc6193eacda6d50c405b0d484f5f2577ff9068a13 (patch)
treed736dd1e72bd85664698e7dcecc461fd1d991bef /drivers/sh/pfc/core.c
parent6f6a4a683be97837f3baae443aacd2b0e6162b10 (diff)
sh-pfc: Move platform device and driver to the core
The pinctrl module registers both a platform device and a platform driver. The only purpose of this awkward construction is to have a device to pass to the pinctrl registration function. As a first step to get rid of this hack, move the platform device and driver from the pinctrl module to the core. The platform device will then be moved to arch code. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Acked-by: Paul Mundt <lethal@linux-sh.org> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Diffstat (limited to 'drivers/sh/pfc/core.c')
-rw-r--r--drivers/sh/pfc/core.c101
1 files changed, 83 insertions, 18 deletions
diff --git a/drivers/sh/pfc/core.c b/drivers/sh/pfc/core.c
index 541099613a2..6d162e694e6 100644
--- a/drivers/sh/pfc/core.c
+++ b/drivers/sh/pfc/core.c
@@ -8,6 +8,8 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
+
+#define DRV_NAME "sh-pfc"
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/errno.h>
@@ -20,11 +22,10 @@
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/pinctrl/machine.h>
+#include <linux/platform_device.h>
#include "core.h"
-static struct sh_pfc sh_pfc __read_mostly;
-
static void pfc_iounmap(struct sh_pfc *pfc)
{
int k;
@@ -494,8 +495,10 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
return -1;
}
-int register_sh_pfc(struct sh_pfc_platform_data *pdata)
+static int sh_pfc_probe(struct platform_device *pdev)
{
+ struct sh_pfc_platform_data *pdata = pdev->dev.platform_data;
+ struct sh_pfc *pfc;
int ret;
/*
@@ -503,26 +506,29 @@ int register_sh_pfc(struct sh_pfc_platform_data *pdata)
*/
BUILD_BUG_ON(PINMUX_FLAG_TYPE > ((1 << PINMUX_FLAG_DBIT_SHIFT) - 1));
- if (sh_pfc.pdata)
- return -EBUSY;
+ if (pdata == NULL)
+ return -ENODEV;
- sh_pfc.pdata = pdata;
+ pfc = devm_kzalloc(&pdev->dev, sizeof(pfc), GFP_KERNEL);
+ if (pfc == NULL)
+ return -ENOMEM;
- ret = pfc_ioremap(&sh_pfc);
- if (unlikely(ret < 0)) {
- sh_pfc.pdata = NULL;
+ pfc->pdata = pdata;
+ pfc->dev = &pdev->dev;
+
+ ret = pfc_ioremap(pfc);
+ if (unlikely(ret < 0))
return ret;
- }
- spin_lock_init(&sh_pfc.lock);
+ spin_lock_init(&pfc->lock);
pinctrl_provide_dummies();
- setup_data_regs(&sh_pfc);
+ setup_data_regs(pfc);
/*
* Initialize pinctrl bindings first
*/
- ret = sh_pfc_register_pinctrl(&sh_pfc);
+ ret = sh_pfc_register_pinctrl(pfc);
if (unlikely(ret != 0))
goto err;
@@ -530,7 +536,7 @@ int register_sh_pfc(struct sh_pfc_platform_data *pdata)
/*
* Then the GPIO chip
*/
- ret = sh_pfc_register_gpiochip(&sh_pfc);
+ ret = sh_pfc_register_gpiochip(pfc);
if (unlikely(ret != 0)) {
/*
* If the GPIO chip fails to come up we still leave the
@@ -541,17 +547,76 @@ int register_sh_pfc(struct sh_pfc_platform_data *pdata)
}
#endif
- pr_info("%s support registered\n", sh_pfc.pdata->name);
+ platform_set_drvdata(pdev, pfc);
+
+ pr_info("%s support registered\n", pdata->name);
return 0;
err:
- pfc_iounmap(&sh_pfc);
- sh_pfc.pdata = NULL;
-
+ pfc_iounmap(pfc);
return ret;
}
+static int sh_pfc_remove(struct platform_device *pdev)
+{
+ struct sh_pfc *pfc = platform_get_drvdata(pdev);
+
+#ifdef CONFIG_GPIO_SH_PFC
+ sh_pfc_unregister_gpiochip(pfc);
+#endif
+ sh_pfc_unregister_pinctrl(pfc);
+
+ pfc_iounmap(pfc);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static const struct platform_device_id sh_pfc_id_table[] = {
+ { "sh-pfc", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, sh_pfc_id_table);
+
+static struct platform_driver sh_pfc_driver = {
+ .probe = sh_pfc_probe,
+ .remove = sh_pfc_remove,
+ .id_table = sh_pfc_id_table,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static struct platform_device sh_pfc_device = {
+ .name = DRV_NAME,
+ .id = -1,
+};
+
+int __init register_sh_pfc(struct sh_pfc_platform_data *pdata)
+{
+ int rc;
+
+ sh_pfc_device.dev.platform_data = pdata;
+
+ rc = platform_driver_register(&sh_pfc_driver);
+ if (likely(!rc)) {
+ rc = platform_device_register(&sh_pfc_device);
+ if (unlikely(rc))
+ platform_driver_unregister(&sh_pfc_driver);
+ }
+
+ return rc;
+}
+
+static void __exit sh_pfc_exit(void)
+{
+ platform_driver_unregister(&sh_pfc_driver);
+}
+module_exit(sh_pfc_exit);
+
MODULE_AUTHOR("Magnus Damm, Paul Mundt, Laurent Pinchart");
MODULE_DESCRIPTION("Pin Control and GPIO driver for SuperH pin function controller");
MODULE_LICENSE("GPL v2");