Commit c6193eac authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Simon Horman

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: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: default avatarPaul Mundt <lethal@linux-sh.org>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarSimon Horman <horms+renesas@verge.net.au>
parent 6f6a4a68
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
*/ */
#define DRV_NAME "sh-pfc"
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/errno.h> #include <linux/errno.h>
...@@ -20,11 +22,10 @@ ...@@ -20,11 +22,10 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/pinctrl/machine.h> #include <linux/pinctrl/machine.h>
#include <linux/platform_device.h>
#include "core.h" #include "core.h"
static struct sh_pfc sh_pfc __read_mostly;
static void pfc_iounmap(struct sh_pfc *pfc) static void pfc_iounmap(struct sh_pfc *pfc)
{ {
int k; int k;
...@@ -494,8 +495,10 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type, ...@@ -494,8 +495,10 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
return -1; 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; int ret;
/* /*
...@@ -503,26 +506,29 @@ int register_sh_pfc(struct sh_pfc_platform_data *pdata) ...@@ -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)); BUILD_BUG_ON(PINMUX_FLAG_TYPE > ((1 << PINMUX_FLAG_DBIT_SHIFT) - 1));
if (sh_pfc.pdata) if (pdata == NULL)
return -EBUSY; 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); pfc->pdata = pdata;
if (unlikely(ret < 0)) { pfc->dev = &pdev->dev;
sh_pfc.pdata = NULL;
ret = pfc_ioremap(pfc);
if (unlikely(ret < 0))
return ret; return ret;
}
spin_lock_init(&sh_pfc.lock); spin_lock_init(&pfc->lock);
pinctrl_provide_dummies(); pinctrl_provide_dummies();
setup_data_regs(&sh_pfc); setup_data_regs(pfc);
/* /*
* Initialize pinctrl bindings first * Initialize pinctrl bindings first
*/ */
ret = sh_pfc_register_pinctrl(&sh_pfc); ret = sh_pfc_register_pinctrl(pfc);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
goto err; goto err;
...@@ -530,7 +536,7 @@ int register_sh_pfc(struct sh_pfc_platform_data *pdata) ...@@ -530,7 +536,7 @@ int register_sh_pfc(struct sh_pfc_platform_data *pdata)
/* /*
* Then the GPIO chip * Then the GPIO chip
*/ */
ret = sh_pfc_register_gpiochip(&sh_pfc); ret = sh_pfc_register_gpiochip(pfc);
if (unlikely(ret != 0)) { if (unlikely(ret != 0)) {
/* /*
* If the GPIO chip fails to come up we still leave the * 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) ...@@ -541,17 +547,76 @@ int register_sh_pfc(struct sh_pfc_platform_data *pdata)
} }
#endif #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; return 0;
err: err:
pfc_iounmap(&sh_pfc); pfc_iounmap(pfc);
sh_pfc.pdata = NULL;
return ret; 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_AUTHOR("Magnus Damm, Paul Mundt, Laurent Pinchart");
MODULE_DESCRIPTION("Pin Control and GPIO driver for SuperH pin function controller"); MODULE_DESCRIPTION("Pin Control and GPIO driver for SuperH pin function controller");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -21,19 +21,23 @@ struct pfc_window { ...@@ -21,19 +21,23 @@ struct pfc_window {
}; };
struct sh_pfc_chip; struct sh_pfc_chip;
struct sh_pfc_pinctrl;
struct sh_pfc { struct sh_pfc {
struct device *dev;
struct sh_pfc_platform_data *pdata; struct sh_pfc_platform_data *pdata;
spinlock_t lock; spinlock_t lock;
struct pfc_window *window; struct pfc_window *window;
struct sh_pfc_chip *gpio; struct sh_pfc_chip *gpio;
struct sh_pfc_pinctrl *pinctrl;
}; };
int sh_pfc_register_gpiochip(struct sh_pfc *pfc); int sh_pfc_register_gpiochip(struct sh_pfc *pfc);
int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc); int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc);
int sh_pfc_register_pinctrl(struct sh_pfc *pfc); int sh_pfc_register_pinctrl(struct sh_pfc *pfc);
int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc);
int sh_pfc_read_bit(struct pinmux_data_reg *dr, unsigned long in_pos); int sh_pfc_read_bit(struct pinmux_data_reg *dr, unsigned long in_pos);
void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos, void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos,
......
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
*/ */
#define pr_fmt(fmt) "sh_pfc " KBUILD_MODNAME ": " fmt
#define pr_fmt(fmt) KBUILD_MODNAME " gpio: " fmt
#include <linux/init.h> #include <linux/init.h>
#include <linux/gpio.h> #include <linux/gpio.h>
......
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
*/ */
#define DRV_NAME "pinctrl-sh_pfc"
#define DRV_NAME "sh-pfc"
#define pr_fmt(fmt) KBUILD_MODNAME " pinctrl: " fmt #define pr_fmt(fmt) KBUILD_MODNAME " pinctrl: " fmt
#include <linux/init.h> #include <linux/init.h>
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinconf.h>
...@@ -39,8 +38,6 @@ struct sh_pfc_pinctrl { ...@@ -39,8 +38,6 @@ struct sh_pfc_pinctrl {
spinlock_t lock; spinlock_t lock;
}; };
static struct sh_pfc_pinctrl *sh_pfc_pmx;
static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev) static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev)
{ {
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
...@@ -421,28 +418,31 @@ static int sh_pfc_map_functions(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) ...@@ -421,28 +418,31 @@ static int sh_pfc_map_functions(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
return 0; return 0;
} }
static int sh_pfc_pinctrl_probe(struct platform_device *pdev) int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
{ {
struct sh_pfc *pfc; struct sh_pfc_pinctrl *pmx;
int ret; int ret;
if (unlikely(!sh_pfc_pmx)) pmx = kzalloc(sizeof(struct sh_pfc_pinctrl), GFP_KERNEL);
return -ENODEV; if (unlikely(!pmx))
return -ENOMEM;
spin_lock_init(&pmx->lock);
pfc = sh_pfc_pmx->pfc; pmx->pfc = pfc;
pfc->pinctrl = pmx;
ret = sh_pfc_map_gpios(pfc, sh_pfc_pmx); ret = sh_pfc_map_gpios(pfc, pmx);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
return ret; return ret;
ret = sh_pfc_map_functions(pfc, sh_pfc_pmx); ret = sh_pfc_map_functions(pfc, pmx);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
goto free_pads; goto free_pads;
sh_pfc_pmx->pctl = pinctrl_register(&sh_pfc_pinctrl_desc, &pdev->dev, pmx->pctl = pinctrl_register(&sh_pfc_pinctrl_desc, pfc->dev, pmx);
sh_pfc_pmx); if (IS_ERR(pmx->pctl)) {
if (IS_ERR(sh_pfc_pmx->pctl)) { ret = PTR_ERR(pmx->pctl);
ret = PTR_ERR(sh_pfc_pmx->pctl);
goto free_functions; goto free_functions;
} }
...@@ -451,79 +451,29 @@ static int sh_pfc_pinctrl_probe(struct platform_device *pdev) ...@@ -451,79 +451,29 @@ static int sh_pfc_pinctrl_probe(struct platform_device *pdev)
sh_pfc_gpio_range.base = pfc->pdata->first_gpio; sh_pfc_gpio_range.base = pfc->pdata->first_gpio;
sh_pfc_gpio_range.pin_base = pfc->pdata->first_gpio; sh_pfc_gpio_range.pin_base = pfc->pdata->first_gpio;
pinctrl_add_gpio_range(sh_pfc_pmx->pctl, &sh_pfc_gpio_range); pinctrl_add_gpio_range(pmx->pctl, &sh_pfc_gpio_range);
platform_set_drvdata(pdev, sh_pfc_pmx);
return 0; return 0;
free_functions: free_functions:
kfree(sh_pfc_pmx->functions); kfree(pmx->functions);
free_pads: free_pads:
kfree(sh_pfc_pmx->pads); kfree(pmx->pads);
kfree(sh_pfc_pmx); kfree(pmx);
return ret; return ret;
} }
static int sh_pfc_pinctrl_remove(struct platform_device *pdev) int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc)
{ {
struct sh_pfc_pinctrl *pmx = platform_get_drvdata(pdev); struct sh_pfc_pinctrl *pmx = pfc->pinctrl;
pinctrl_unregister(pmx->pctl); pinctrl_unregister(pmx->pctl);
platform_set_drvdata(pdev, NULL); kfree(pmx->functions);
kfree(pmx->pads);
kfree(sh_pfc_pmx->functions); kfree(pmx);
kfree(sh_pfc_pmx->pads);
kfree(sh_pfc_pmx);
pfc->pinctrl = NULL;
return 0; return 0;
} }
static struct platform_driver sh_pfc_pinctrl_driver = {
.probe = sh_pfc_pinctrl_probe,
.remove = sh_pfc_pinctrl_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
};
static struct platform_device sh_pfc_pinctrl_device = {
.name = DRV_NAME,
.id = -1,
};
static int sh_pfc_pinctrl_init(void)
{
int rc;
rc = platform_driver_register(&sh_pfc_pinctrl_driver);
if (likely(!rc)) {
rc = platform_device_register(&sh_pfc_pinctrl_device);
if (unlikely(rc))
platform_driver_unregister(&sh_pfc_pinctrl_driver);
}
return rc;
}
int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
{
sh_pfc_pmx = kzalloc(sizeof(struct sh_pfc_pinctrl), GFP_KERNEL);
if (unlikely(!sh_pfc_pmx))
return -ENOMEM;
spin_lock_init(&sh_pfc_pmx->lock);
sh_pfc_pmx->pfc = pfc;
return sh_pfc_pinctrl_init();
}
static void __exit sh_pfc_pinctrl_exit(void)
{
platform_driver_unregister(&sh_pfc_pinctrl_driver);
}
module_exit(sh_pfc_pinctrl_exit);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment