Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 355341
b: refs/heads/master
c: c6193ea
h: refs/heads/master
i:
  355339: 777be7c
v: v3
  • Loading branch information
Laurent Pinchart authored and Simon Horman committed Jan 25, 2013
1 parent 3b22b1d commit 4226420
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 95 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6f6a4a683be97837f3baae443aacd2b0e6162b10
refs/heads/master: c6193eacda6d50c405b0d484f5f2577ff9068a13
101 changes: 83 additions & 18 deletions trunk/drivers/sh/pfc/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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;
Expand Down Expand Up @@ -494,43 +495,48 @@ 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;

/*
* Ensure that the type encoding fits
*/
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;

#ifdef CONFIG_GPIO_SH_PFC
/*
* 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
Expand All @@ -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");
4 changes: 4 additions & 0 deletions trunk/drivers/sh/pfc/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,23 @@ struct pfc_window {
};

struct sh_pfc_chip;
struct sh_pfc_pinctrl;

struct sh_pfc {
struct device *dev;
struct sh_pfc_platform_data *pdata;
spinlock_t lock;

struct pfc_window *window;
struct sh_pfc_chip *gpio;
struct sh_pfc_pinctrl *pinctrl;
};

int sh_pfc_register_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_unregister_pinctrl(struct sh_pfc *pfc);

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,
Expand Down
3 changes: 2 additions & 1 deletion trunk/drivers/sh/pfc/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
* License. See the file "COPYING" in the main directory of this archive
* 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/gpio.h>
Expand Down
100 changes: 25 additions & 75 deletions trunk/drivers/sh/pfc/pinctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#define DRV_NAME "pinctrl-sh_pfc"

#define DRV_NAME "sh-pfc"
#define pr_fmt(fmt) KBUILD_MODNAME " pinctrl: " fmt

#include <linux/init.h>
Expand All @@ -17,7 +17,6 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf.h>
Expand All @@ -39,8 +38,6 @@ struct sh_pfc_pinctrl {
spinlock_t lock;
};

static struct sh_pfc_pinctrl *sh_pfc_pmx;

static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
Expand Down Expand Up @@ -421,28 +418,31 @@ static int sh_pfc_map_functions(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
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;

if (unlikely(!sh_pfc_pmx))
return -ENODEV;
pmx = kzalloc(sizeof(struct sh_pfc_pinctrl), GFP_KERNEL);
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))
return ret;

ret = sh_pfc_map_functions(pfc, sh_pfc_pmx);
ret = sh_pfc_map_functions(pfc, pmx);
if (unlikely(ret != 0))
goto free_pads;

sh_pfc_pmx->pctl = pinctrl_register(&sh_pfc_pinctrl_desc, &pdev->dev,
sh_pfc_pmx);
if (IS_ERR(sh_pfc_pmx->pctl)) {
ret = PTR_ERR(sh_pfc_pmx->pctl);
pmx->pctl = pinctrl_register(&sh_pfc_pinctrl_desc, pfc->dev, pmx);
if (IS_ERR(pmx->pctl)) {
ret = PTR_ERR(pmx->pctl);
goto free_functions;
}

Expand All @@ -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.pin_base = pfc->pdata->first_gpio;

pinctrl_add_gpio_range(sh_pfc_pmx->pctl, &sh_pfc_gpio_range);

platform_set_drvdata(pdev, sh_pfc_pmx);
pinctrl_add_gpio_range(pmx->pctl, &sh_pfc_gpio_range);

return 0;

free_functions:
kfree(sh_pfc_pmx->functions);
kfree(pmx->functions);
free_pads:
kfree(sh_pfc_pmx->pads);
kfree(sh_pfc_pmx);
kfree(pmx->pads);
kfree(pmx);

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);

platform_set_drvdata(pdev, NULL);

kfree(sh_pfc_pmx->functions);
kfree(sh_pfc_pmx->pads);
kfree(sh_pfc_pmx);
kfree(pmx->functions);
kfree(pmx->pads);
kfree(pmx);

pfc->pinctrl = NULL;
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);

0 comments on commit 4226420

Please sign in to comment.