Skip to content

Commit

Permalink
nomadik-gpio: allow sleep mode dir/pull to differ from normal mode
Browse files Browse the repository at this point in the history
In the nomadik GPIO pin configuration, allow the sleep mode direction
and pull configurations to differ from the ones for the normal state.
PIN_SLPM_PULL_*, PIN_SLPM_INPUT, PIN_SLPM_OUTPUT* macros are provided
for this.

Since the hardware does not allow seperate configurations for sleep mode
and normal mode, this is implemented by having software remux the
configurations as necessary.

Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
  • Loading branch information
Rabin Vincent authored and Linus Walleij committed Dec 8, 2010
1 parent edaa86a commit dacdc96
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 21 deletions.
50 changes: 44 additions & 6 deletions arch/arm/plat-nomadik/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
}

static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
pin_cfg_t cfg)
pin_cfg_t cfg, bool sleep)
{
static const char *afnames[] = {
[NMK_GPIO_ALT_GPIO] = "GPIO",
Expand All @@ -145,11 +145,34 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
int output = PIN_DIR(cfg);
int val = PIN_VAL(cfg);

dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s (%s%s)\n",
pin, afnames[af], pullnames[pull], slpmnames[slpm],
dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n",
pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm],
output ? "output " : "input",
output ? (val ? "high" : "low") : "");

if (sleep) {
int slpm_pull = PIN_SLPM_PULL(cfg);
int slpm_output = PIN_SLPM_DIR(cfg);
int slpm_val = PIN_SLPM_VAL(cfg);

/*
* The SLPM_* values are normal values + 1 to allow zero to
* mean "same as normal".
*/
if (slpm_pull)
pull = slpm_pull - 1;
if (slpm_output)
output = slpm_output - 1;
if (slpm_val)
val = slpm_val - 1;

dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n",
pin,
slpm_pull ? pullnames[pull] : "same",
slpm_output ? (output ? "output" : "input") : "same",
slpm_val ? (val ? "high" : "low") : "same");
}

if (output)
__nmk_gpio_make_output(nmk_chip, offset, val);
else {
Expand All @@ -175,7 +198,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
* side-effects. The gpio can be manipulated later using standard GPIO API
* calls.
*/
int nmk_config_pin(pin_cfg_t cfg)
int nmk_config_pin(pin_cfg_t cfg, bool sleep)
{
struct nmk_gpio_chip *nmk_chip;
int gpio = PIN_NUM(cfg);
Expand All @@ -186,7 +209,7 @@ int nmk_config_pin(pin_cfg_t cfg)
return -EINVAL;

spin_lock_irqsave(&nmk_chip->lock, flags);
__nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg);
__nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg, sleep);
spin_unlock_irqrestore(&nmk_chip->lock, flags);

return 0;
Expand All @@ -207,7 +230,7 @@ int nmk_config_pins(pin_cfg_t *cfgs, int num)
int i;

for (i = 0; i < num; i++) {
int ret = nmk_config_pin(cfgs[i]);
ret = nmk_config_pin(cfgs[i], false);
if (ret)
break;
}
Expand All @@ -216,6 +239,21 @@ int nmk_config_pins(pin_cfg_t *cfgs, int num)
}
EXPORT_SYMBOL(nmk_config_pins);

int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num)
{
int ret = 0;
int i;

for (i = 0; i < num; i++) {
ret = nmk_config_pin(cfgs[i], true);
if (ret)
break;
}

return ret;
}
EXPORT_SYMBOL(nmk_config_pins_sleep);

/**
* nmk_gpio_set_slpm() - configure the sleep mode of a pin
* @gpio: pin number
Expand Down
70 changes: 55 additions & 15 deletions arch/arm/plat-nomadik/include/plat/pincfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,22 @@
* bit 9..10 - Alternate Function Selection
* bit 11..12 - Pull up/down state
* bit 13 - Sleep mode behaviour
* bit 14 - (sleep mode) Direction
* bit 15 - (sleep mode) Value (if output)
* bit 14 - Direction
* bit 15 - Value (if output)
* bit 16..18 - SLPM pull up/down state
* bit 19..20 - SLPM direction
* bit 21..22 - SLPM Value (if output)
*
* to facilitate the definition, the following macros are provided
*
* PIN_CFG_DEFAULT - default config (0):
* pull up/down = disabled
* sleep mode = input/wakeup
* (sleep mode) direction = input
* (sleep mode) value = low
* direction = input
* value = low
* SLPM direction = same as normal
* SLPM pull = same as normal
* SLPM value = same as normal
*
* PIN_CFG - default config with alternate function
* PIN_CFG_PULL - default config with alternate function and pull up/down
Expand Down Expand Up @@ -75,30 +81,64 @@ typedef unsigned long pin_cfg_t;
#define PIN_VAL_LOW (0 << PIN_VAL_SHIFT)
#define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT)

/* Shortcuts. Use these instead of separate DIR and VAL. */
#define PIN_INPUT PIN_DIR_INPUT
#define PIN_SLPM_PULL_SHIFT 16
#define PIN_SLPM_PULL_MASK (0x7 << PIN_SLPM_PULL_SHIFT)
#define PIN_SLPM_PULL(x) \
(((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
#define PIN_SLPM_PULL_NONE \
((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
#define PIN_SLPM_PULL_UP \
((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
#define PIN_SLPM_PULL_DOWN \
((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)

#define PIN_SLPM_DIR_SHIFT 19
#define PIN_SLPM_DIR_MASK (0x3 << PIN_SLPM_DIR_SHIFT)
#define PIN_SLPM_DIR(x) \
(((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
#define PIN_SLPM_DIR_INPUT ((1 + 0) << PIN_SLPM_DIR_SHIFT)
#define PIN_SLPM_DIR_OUTPUT ((1 + 1) << PIN_SLPM_DIR_SHIFT)

#define PIN_SLPM_VAL_SHIFT 21
#define PIN_SLPM_VAL_MASK (0x3 << PIN_SLPM_VAL_SHIFT)
#define PIN_SLPM_VAL(x) \
(((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
#define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT)
#define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT)

/* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */
#define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN)
#define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP)
#define PIN_INPUT_NOPULL (PIN_DIR_INPUT | PIN_PULL_NONE)
#define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW)
#define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH)

/*
* These are the same as the ones above, but should make more sense to the
* reader when seen along with a setting a pin to AF mode.
*/
#define PIN_SLPM_INPUT PIN_INPUT
#define PIN_SLPM_OUTPUT_LOW PIN_OUTPUT_LOW
#define PIN_SLPM_OUTPUT_HIGH PIN_OUTPUT_HIGH
#define PIN_SLPM_INPUT_PULLDOWN (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
#define PIN_SLPM_INPUT_PULLUP (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
#define PIN_SLPM_INPUT_NOPULL (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
#define PIN_SLPM_OUTPUT_LOW (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
#define PIN_SLPM_OUTPUT_HIGH (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)

#define PIN_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT)
#define PIN_CFG_DEFAULT (0)

#define PIN_CFG(num, alt) \
(PIN_CFG_DEFAULT |\
(PIN_NUM(num) | PIN_##alt))

#define PIN_CFG_INPUT(num, alt, pull) \
(PIN_CFG_DEFAULT |\
(PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))

#define PIN_CFG_OUTPUT(num, alt, val) \
(PIN_CFG_DEFAULT |\
(PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))

#define PIN_CFG_PULL(num, alt, pull) \
((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\
(PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull))

extern int nmk_config_pin(pin_cfg_t cfg);
extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);

#endif

0 comments on commit dacdc96

Please sign in to comment.