Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 313766
b: refs/heads/master
c: ca5481c
h: refs/heads/master
v: v3
  • Loading branch information
Paul Mundt committed Jul 10, 2012
1 parent 1e9b057 commit 2d92efd
Show file tree
Hide file tree
Showing 7 changed files with 441 additions and 134 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: 72c7afa10f272710028f244da65d35e571144085
refs/heads/master: ca5481c68e9fbcea62bb3c78ae6cccf99ca8fb73
13 changes: 13 additions & 0 deletions trunk/drivers/sh/pfc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,21 @@ config SH_PFC
# XXX move off the gpio dependency
depends on GENERIC_GPIO
select GPIO_SH_PFC if ARCH_REQUIRE_GPIOLIB
select PINCTRL_SH_PFC
def_bool y

#
# Placeholder for now, rehome to drivers/pinctrl once the PFC APIs
# have settled.
#
config PINCTRL_SH_PFC
tristate "SuperH PFC pin controller driver"
depends on SH_PFC
select PINCTRL
select PINMUX
select PINCONF
select GENERIC_PINCONF

config GPIO_SH_PFC
tristate "SuperH PFC GPIO support"
depends on SH_PFC && GPIOLIB
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/sh/pfc/Makefile
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
obj-y += core.o
obj-$(CONFIG_PINCTRL_SH_PFC) += pinctrl.o
obj-$(CONFIG_GPIO_SH_PFC) += gpio.o
81 changes: 36 additions & 45 deletions trunk/drivers/sh/pfc/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/pinctrl/machine.h>

static struct sh_pfc *sh_pfc __read_mostly;

Expand Down Expand Up @@ -501,49 +502,6 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
}
EXPORT_SYMBOL_GPL(sh_pfc_config_gpio);

int sh_pfc_set_direction(struct sh_pfc *pfc, unsigned gpio,
int new_pinmux_type)
{
int pinmux_type;
int ret = -EINVAL;

if (!pfc)
goto err_out;

pinmux_type = pfc->gpios[gpio].flags & PINMUX_FLAG_TYPE;

switch (pinmux_type) {
case PINMUX_TYPE_GPIO:
break;
case PINMUX_TYPE_OUTPUT:
case PINMUX_TYPE_INPUT:
case PINMUX_TYPE_INPUT_PULLUP:
case PINMUX_TYPE_INPUT_PULLDOWN:
sh_pfc_config_gpio(pfc, gpio, pinmux_type, GPIO_CFG_FREE);
break;
default:
goto err_out;
}

if (sh_pfc_config_gpio(pfc, gpio,
new_pinmux_type,
GPIO_CFG_DRYRUN) != 0)
goto err_out;

if (sh_pfc_config_gpio(pfc, gpio,
new_pinmux_type,
GPIO_CFG_REQ) != 0)
BUG();

pfc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
pfc->gpios[gpio].flags |= new_pinmux_type;

ret = 0;
err_out:
return ret;
}
EXPORT_SYMBOL_GPL(sh_pfc_set_direction);

int register_sh_pfc(struct sh_pfc *pfc)
{
int (*initroutine)(struct sh_pfc *) = NULL;
Expand All @@ -563,16 +521,49 @@ int register_sh_pfc(struct sh_pfc *pfc)

spin_lock_init(&pfc->lock);

pinctrl_provide_dummies();
setup_data_regs(pfc);

sh_pfc = pfc;
pr_info("%s support registered\n", pfc->name);

/*
* Initialize pinctrl bindings first
*/
initroutine = symbol_request(sh_pfc_register_pinctrl);
if (initroutine) {
ret = (*initroutine)(pfc);
symbol_put_addr(initroutine);

if (unlikely(ret != 0))
goto err;
}

/*
* Then the GPIO chip
*/
initroutine = symbol_request(sh_pfc_register_gpiochip);
if (initroutine) {
(*initroutine)(pfc);
ret = (*initroutine)(pfc);
symbol_put_addr(initroutine);

/*
* If the GPIO chip fails to come up we still leave the
* PFC state as it is, given that there are already
* extant users of it that have succeeded by this point.
*/
if (unlikely(ret != 0)) {
pr_notice("failed to init GPIO chip, ignoring...\n");
ret = 0;
}
}

pr_info("%s support registered\n", pfc->name);

return 0;

err:
pfc_iounmap(pfc);
sh_pfc = NULL;

return ret;
}
102 changes: 16 additions & 86 deletions trunk/drivers/sh/pfc/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h>

struct sh_pfc_chip {
struct sh_pfc *pfc;
Expand All @@ -34,80 +35,12 @@ static struct sh_pfc *gpio_to_pfc(struct gpio_chip *gc)

static int sh_gpio_request(struct gpio_chip *gc, unsigned offset)
{
struct sh_pfc *pfc = gpio_to_pfc(gc);
struct pinmux_data_reg *dummy;
unsigned long flags;
int i, ret, pinmux_type;

ret = -EINVAL;

if (!pfc)
goto err_out;

spin_lock_irqsave(&pfc->lock, flags);

if ((pfc->gpios[offset].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE)
goto err_unlock;

/* setup pin function here if no data is associated with pin */

if (sh_pfc_get_data_reg(pfc, offset, &dummy, &i) != 0)
pinmux_type = PINMUX_TYPE_FUNCTION;
else
pinmux_type = PINMUX_TYPE_GPIO;

if (pinmux_type == PINMUX_TYPE_FUNCTION) {
if (sh_pfc_config_gpio(pfc, offset,
pinmux_type,
GPIO_CFG_DRYRUN) != 0)
goto err_unlock;

if (sh_pfc_config_gpio(pfc, offset,
pinmux_type,
GPIO_CFG_REQ) != 0)
BUG();
}

pfc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
pfc->gpios[offset].flags |= pinmux_type;

ret = 0;
err_unlock:
spin_unlock_irqrestore(&pfc->lock, flags);
err_out:
return ret;
return pinctrl_request_gpio(offset);
}

static void sh_gpio_free(struct gpio_chip *gc, unsigned offset)
{
struct sh_pfc *pfc = gpio_to_pfc(gc);
unsigned long flags;
int pinmux_type;

if (!pfc)
return;

spin_lock_irqsave(&pfc->lock, flags);

pinmux_type = pfc->gpios[offset].flags & PINMUX_FLAG_TYPE;
sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE);
pfc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
pfc->gpios[offset].flags |= PINMUX_TYPE_NONE;

spin_unlock_irqrestore(&pfc->lock, flags);
}

static int sh_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct sh_pfc *pfc = gpio_to_pfc(gc);
unsigned long flags;
int ret;

spin_lock_irqsave(&pfc->lock, flags);
ret = sh_pfc_set_direction(pfc, offset, PINMUX_TYPE_INPUT);
spin_unlock_irqrestore(&pfc->lock, flags);

return ret;
pinctrl_free_gpio(offset);
}

static void sh_gpio_set_value(struct sh_pfc *pfc, unsigned gpio, int value)
Expand All @@ -121,22 +54,6 @@ static void sh_gpio_set_value(struct sh_pfc *pfc, unsigned gpio, int value)
sh_pfc_write_bit(dr, bit, value);
}

static int sh_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
int value)
{
struct sh_pfc *pfc = gpio_to_pfc(gc);
unsigned long flags;
int ret;

sh_gpio_set_value(pfc, offset, value);

spin_lock_irqsave(&pfc->lock, flags);
ret = sh_pfc_set_direction(pfc, offset, PINMUX_TYPE_OUTPUT);
spin_unlock_irqrestore(&pfc->lock, flags);

return ret;
}

static int sh_gpio_get_value(struct sh_pfc *pfc, unsigned gpio)
{
struct pinmux_data_reg *dr = NULL;
Expand All @@ -148,6 +65,19 @@ static int sh_gpio_get_value(struct sh_pfc *pfc, unsigned gpio)
return sh_pfc_read_bit(dr, bit);
}

static int sh_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
{
return pinctrl_gpio_direction_input(offset);
}

static int sh_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
int value)
{
sh_gpio_set_value(gpio_to_pfc(gc), offset, value);

return pinctrl_gpio_direction_output(offset);
}

static int sh_gpio_get(struct gpio_chip *gc, unsigned offset)
{
return sh_gpio_get_value(gpio_to_pfc(gc), offset);
Expand Down
Loading

0 comments on commit 2d92efd

Please sign in to comment.