Commit 391c970c authored by Anton Vorontsov's avatar Anton Vorontsov Committed by Grant Likely

of/gpio: add default of_xlate function if device has a node pointer

Implement generic OF gpio hooks and thus make device-enabled GPIO chips
(i.e.  the ones that have gpio_chip->dev specified) automatically attach
to the OpenFirmware subsystem.  Which means that now we can handle I2C and
SPI GPIO chips almost* transparently.

* "Almost" because some chips still require platform data, and for these
  chips OF-glue is still needed, though with this change the glue will
  be much smaller.
Signed-off-by: default avatarAnton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Bill Gatliff <bgat@billgatliff.com>
Cc: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
CC: linux-kernel@vger.kernel.org
CC: devicetree-discuss@lists.ozlabs.org
parent 594fa265
...@@ -161,7 +161,6 @@ static int __devinit mpc52xx_wkup_gpiochip_probe(struct of_device *ofdev, ...@@ -161,7 +161,6 @@ static int __devinit mpc52xx_wkup_gpiochip_probe(struct of_device *ofdev,
gc = &chip->mmchip.gc; gc = &chip->mmchip.gc;
gc->of_gpio_n_cells = 2;
gc->ngpio = 8; gc->ngpio = 8;
gc->direction_input = mpc52xx_wkup_gpio_dir_in; gc->direction_input = mpc52xx_wkup_gpio_dir_in;
gc->direction_output = mpc52xx_wkup_gpio_dir_out; gc->direction_output = mpc52xx_wkup_gpio_dir_out;
...@@ -325,7 +324,6 @@ static int __devinit mpc52xx_simple_gpiochip_probe(struct of_device *ofdev, ...@@ -325,7 +324,6 @@ static int __devinit mpc52xx_simple_gpiochip_probe(struct of_device *ofdev,
gc = &chip->mmchip.gc; gc = &chip->mmchip.gc;
gc->of_gpio_n_cells = 2;
gc->ngpio = 32; gc->ngpio = 32;
gc->direction_input = mpc52xx_simple_gpio_dir_in; gc->direction_input = mpc52xx_simple_gpio_dir_in;
gc->direction_output = mpc52xx_simple_gpio_dir_out; gc->direction_output = mpc52xx_simple_gpio_dir_out;
......
...@@ -348,10 +348,7 @@ mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node) ...@@ -348,10 +348,7 @@ mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node)
gpt->gc.get = mpc52xx_gpt_gpio_get; gpt->gc.get = mpc52xx_gpt_gpio_get;
gpt->gc.set = mpc52xx_gpt_gpio_set; gpt->gc.set = mpc52xx_gpt_gpio_set;
gpt->gc.base = -1; gpt->gc.base = -1;
gpt->gc.of_gpio_n_cells = 2;
gpt->gc.of_xlate = of_gpio_simple_xlate;
gpt->gc.of_node = node; gpt->gc.of_node = node;
of_node_get(node);
/* Setup external pin in GPIO mode */ /* Setup external pin in GPIO mode */
clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_MS_MASK, clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_MS_MASK,
......
...@@ -90,8 +90,6 @@ static int mcu_gpiochip_add(struct mcu *mcu) ...@@ -90,8 +90,6 @@ static int mcu_gpiochip_add(struct mcu *mcu)
gc->base = -1; gc->base = -1;
gc->set = mcu_gpio_set; gc->set = mcu_gpio_set;
gc->direction_output = mcu_gpio_dir_out; gc->direction_output = mcu_gpio_dir_out;
gc->of_gpio_n_cells = 2;
gc->of_xlate = of_gpio_simple_xlate;
gc->of_node = np; gc->of_node = np;
return gpiochip_add(gc); return gpiochip_add(gc);
......
...@@ -633,7 +633,6 @@ int cpm1_gpiochip_add16(struct device_node *np) ...@@ -633,7 +633,6 @@ int cpm1_gpiochip_add16(struct device_node *np)
gc = &mm_gc->gc; gc = &mm_gc->gc;
mm_gc->save_regs = cpm1_gpio16_save_regs; mm_gc->save_regs = cpm1_gpio16_save_regs;
gc->of_gpio_n_cells = 2;
gc->ngpio = 16; gc->ngpio = 16;
gc->direction_input = cpm1_gpio16_dir_in; gc->direction_input = cpm1_gpio16_dir_in;
gc->direction_output = cpm1_gpio16_dir_out; gc->direction_output = cpm1_gpio16_dir_out;
...@@ -755,7 +754,6 @@ int cpm1_gpiochip_add32(struct device_node *np) ...@@ -755,7 +754,6 @@ int cpm1_gpiochip_add32(struct device_node *np)
gc = &mm_gc->gc; gc = &mm_gc->gc;
mm_gc->save_regs = cpm1_gpio32_save_regs; mm_gc->save_regs = cpm1_gpio32_save_regs;
gc->of_gpio_n_cells = 2;
gc->ngpio = 32; gc->ngpio = 32;
gc->direction_input = cpm1_gpio32_dir_in; gc->direction_input = cpm1_gpio32_dir_in;
gc->direction_output = cpm1_gpio32_dir_out; gc->direction_output = cpm1_gpio32_dir_out;
......
...@@ -337,7 +337,6 @@ int cpm2_gpiochip_add32(struct device_node *np) ...@@ -337,7 +337,6 @@ int cpm2_gpiochip_add32(struct device_node *np)
gc = &mm_gc->gc; gc = &mm_gc->gc;
mm_gc->save_regs = cpm2_gpio32_save_regs; mm_gc->save_regs = cpm2_gpio32_save_regs;
gc->of_gpio_n_cells = 2;
gc->ngpio = 32; gc->ngpio = 32;
gc->direction_input = cpm2_gpio32_dir_in; gc->direction_input = cpm2_gpio32_dir_in;
gc->direction_output = cpm2_gpio32_dir_out; gc->direction_output = cpm2_gpio32_dir_out;
......
...@@ -273,7 +273,6 @@ static void __init mpc8xxx_add_controller(struct device_node *np) ...@@ -273,7 +273,6 @@ static void __init mpc8xxx_add_controller(struct device_node *np)
gc = &mm_gc->gc; gc = &mm_gc->gc;
mm_gc->save_regs = mpc8xxx_gpio_save_regs; mm_gc->save_regs = mpc8xxx_gpio_save_regs;
gc->of_gpio_n_cells = 2;
gc->ngpio = MPC8XXX_GPIO_PINS; gc->ngpio = MPC8XXX_GPIO_PINS;
gc->direction_input = mpc8xxx_gpio_dir_in; gc->direction_input = mpc8xxx_gpio_dir_in;
gc->direction_output = mpc8xxx_gpio_dir_out; gc->direction_output = mpc8xxx_gpio_dir_out;
......
...@@ -194,7 +194,6 @@ static int __init ppc4xx_add_gpiochips(void) ...@@ -194,7 +194,6 @@ static int __init ppc4xx_add_gpiochips(void)
mm_gc = &ppc4xx_gc->mm_gc; mm_gc = &ppc4xx_gc->mm_gc;
gc = &mm_gc->gc; gc = &mm_gc->gc;
gc->of_gpio_n_cells = 2;
gc->ngpio = 32; gc->ngpio = 32;
gc->direction_input = ppc4xx_gpio_dir_in; gc->direction_input = ppc4xx_gpio_dir_in;
gc->direction_output = ppc4xx_gpio_dir_out; gc->direction_output = ppc4xx_gpio_dir_out;
......
...@@ -321,7 +321,6 @@ static int __init qe_add_gpiochips(void) ...@@ -321,7 +321,6 @@ static int __init qe_add_gpiochips(void)
gc = &mm_gc->gc; gc = &mm_gc->gc;
mm_gc->save_regs = qe_gpio_save_regs; mm_gc->save_regs = qe_gpio_save_regs;
gc->of_gpio_n_cells = 2;
gc->ngpio = QE_PIO_PINS; gc->ngpio = QE_PIO_PINS;
gc->direction_input = qe_gpio_dir_in; gc->direction_input = qe_gpio_dir_in;
gc->direction_output = qe_gpio_dir_out; gc->direction_output = qe_gpio_dir_out;
......
...@@ -103,7 +103,6 @@ static int __init u8_simple_gpiochip_add(struct device_node *np) ...@@ -103,7 +103,6 @@ static int __init u8_simple_gpiochip_add(struct device_node *np)
gc = &mm_gc->gc; gc = &mm_gc->gc;
mm_gc->save_regs = u8_gpio_save_regs; mm_gc->save_regs = u8_gpio_save_regs;
gc->of_gpio_n_cells = 2;
gc->ngpio = 8; gc->ngpio = 8;
gc->direction_input = u8_gpio_dir_in; gc->direction_input = u8_gpio_dir_in;
gc->direction_output = u8_gpio_dir_out; gc->direction_output = u8_gpio_dir_out;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -1099,6 +1100,8 @@ int gpiochip_add(struct gpio_chip *chip) ...@@ -1099,6 +1100,8 @@ int gpiochip_add(struct gpio_chip *chip)
} }
} }
of_gpiochip_add(chip);
unlock: unlock:
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
...@@ -1133,6 +1136,8 @@ int gpiochip_remove(struct gpio_chip *chip) ...@@ -1133,6 +1136,8 @@ int gpiochip_remove(struct gpio_chip *chip)
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
of_gpiochip_remove(chip);
for (id = chip->base; id < chip->base + chip->ngpio; id++) { for (id = chip->base; id < chip->base + chip->ngpio; id++) {
if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) { if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) {
status = -EBUSY; status = -EBUSY;
......
...@@ -190,7 +190,6 @@ static int __devinit xgpio_of_probe(struct device_node *np) ...@@ -190,7 +190,6 @@ static int __devinit xgpio_of_probe(struct device_node *np)
spin_lock_init(&chip->gpio_lock); spin_lock_init(&chip->gpio_lock);
chip->mmchip.gc.of_gpio_n_cells = 2;
chip->mmchip.gc.direction_input = xgpio_dir_in; chip->mmchip.gc.direction_input = xgpio_dir_in;
chip->mmchip.gc.direction_output = xgpio_dir_out; chip->mmchip.gc.direction_output = xgpio_dir_out;
chip->mmchip.gc.get = xgpio_get; chip->mmchip.gc.get = xgpio_get;
......
...@@ -125,8 +125,8 @@ EXPORT_SYMBOL(of_gpio_count); ...@@ -125,8 +125,8 @@ EXPORT_SYMBOL(of_gpio_count);
* gpio chips. This function performs only one sanity check: whether gpio * gpio chips. This function performs only one sanity check: whether gpio
* is less than ngpios (that is specified in the gpio_chip). * is less than ngpios (that is specified in the gpio_chip).
*/ */
int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np, static int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
const void *gpio_spec, u32 *flags) const void *gpio_spec, u32 *flags)
{ {
const __be32 *gpio = gpio_spec; const __be32 *gpio = gpio_spec;
const u32 n = be32_to_cpup(gpio); const u32 n = be32_to_cpup(gpio);
...@@ -150,7 +150,6 @@ int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np, ...@@ -150,7 +150,6 @@ int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
return n; return n;
} }
EXPORT_SYMBOL(of_gpio_simple_xlate);
/** /**
* of_mm_gpiochip_add - Add memory mapped GPIO chip (bank) * of_mm_gpiochip_add - Add memory mapped GPIO chip (bank)
...@@ -187,9 +186,6 @@ int of_mm_gpiochip_add(struct device_node *np, ...@@ -187,9 +186,6 @@ int of_mm_gpiochip_add(struct device_node *np,
gc->base = -1; gc->base = -1;
if (!gc->of_xlate)
gc->of_xlate = of_gpio_simple_xlate;
if (mm_gc->save_regs) if (mm_gc->save_regs)
mm_gc->save_regs(mm_gc); mm_gc->save_regs(mm_gc);
...@@ -199,9 +195,6 @@ int of_mm_gpiochip_add(struct device_node *np, ...@@ -199,9 +195,6 @@ int of_mm_gpiochip_add(struct device_node *np,
if (ret) if (ret)
goto err2; goto err2;
/* We don't want to lose the node and its ->data */
of_node_get(np);
pr_debug("%s: registered as generic GPIO chip, base is %d\n", pr_debug("%s: registered as generic GPIO chip, base is %d\n",
np->full_name, gc->base); np->full_name, gc->base);
return 0; return 0;
...@@ -216,6 +209,28 @@ int of_mm_gpiochip_add(struct device_node *np, ...@@ -216,6 +209,28 @@ int of_mm_gpiochip_add(struct device_node *np,
} }
EXPORT_SYMBOL(of_mm_gpiochip_add); EXPORT_SYMBOL(of_mm_gpiochip_add);
void of_gpiochip_add(struct gpio_chip *chip)
{
if ((!chip->of_node) && (chip->dev))
chip->of_node = chip->dev->of_node;
if (!chip->of_node)
return;
if (!chip->of_xlate) {
chip->of_gpio_n_cells = 2;
chip->of_xlate = of_gpio_simple_xlate;
}
of_node_get(chip->of_node);
}
void of_gpiochip_remove(struct gpio_chip *chip)
{
if (chip->of_node)
of_node_put(chip->of_node);
}
/* Private function for resolving node pointer to gpio_chip */ /* Private function for resolving node pointer to gpio_chip */
static int of_gpiochip_is_match(struct gpio_chip *chip, void *data) static int of_gpiochip_is_match(struct gpio_chip *chip, void *data)
{ {
......
...@@ -52,9 +52,9 @@ extern unsigned int of_gpio_count(struct device_node *np); ...@@ -52,9 +52,9 @@ extern unsigned int of_gpio_count(struct device_node *np);
extern int of_mm_gpiochip_add(struct device_node *np, extern int of_mm_gpiochip_add(struct device_node *np,
struct of_mm_gpio_chip *mm_gc); struct of_mm_gpio_chip *mm_gc);
extern int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
const void *gpio_spec, u32 *flags);
extern void of_gpiochip_add(struct gpio_chip *gc);
extern void of_gpiochip_remove(struct gpio_chip *gc);
extern struct gpio_chip *of_node_to_gpiochip(struct device_node *np); extern struct gpio_chip *of_node_to_gpiochip(struct device_node *np);
#else /* CONFIG_OF_GPIO */ #else /* CONFIG_OF_GPIO */
...@@ -71,6 +71,9 @@ static inline unsigned int of_gpio_count(struct device_node *np) ...@@ -71,6 +71,9 @@ static inline unsigned int of_gpio_count(struct device_node *np)
return 0; return 0;
} }
static inline void of_gpiochip_add(struct gpio_chip *gc) { }
static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
#endif /* CONFIG_OF_GPIO */ #endif /* CONFIG_OF_GPIO */
/** /**
......
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