forked from mirrors/linux
		
	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: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: Grant 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
This commit is contained in:
		
							parent
							
								
									594fa265e0
								
							
						
					
					
						commit
						391c970c0d
					
				
					 13 changed files with 34 additions and 26 deletions
				
			
		| 
						 | 
					@ -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,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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)
 | 
				
			||||||
	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)
 | 
				
			||||||
	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)
 | 
				
			||||||
	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)
 | 
				
			||||||
	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)
 | 
				
			||||||
	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)
 | 
				
			||||||
	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)
 | 
				
			||||||
		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)
 | 
				
			||||||
		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)
 | 
				
			||||||
	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 @@
 | 
				
			||||||
#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)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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,7 +125,7 @@ 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;
 | 
				
			||||||
| 
						 | 
					@ -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,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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,
 | 
				
			||||||
	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,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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)
 | 
				
			||||||
	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 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue