110 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* arch/arm/mach-msm/generic_gpio.c
 | |
|  *
 | |
|  * Copyright (C) 2007 Google, Inc.
 | |
|  *
 | |
|  * This software is licensed under the terms of the GNU General Public
 | |
|  * License version 2, as published by the Free Software Foundation, and
 | |
|  * may be copied, distributed, and modified under those terms.
 | |
|  *
 | |
|  * This program is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  * GNU General Public License for more details.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <linux/kernel.h>
 | |
| #include <linux/module.h>
 | |
| #include <linux/errno.h>
 | |
| #include <linux/slab.h>
 | |
| #include <linux/spinlock.h>
 | |
| #include <asm/gpio.h>
 | |
| #include "gpio_chip.h"
 | |
| 
 | |
| #undef gpio_chip
 | |
| static int gpio_chip_direction_input(struct gpio_chip *chip, unsigned offset)
 | |
| {
 | |
| 	struct old_gpio_chip *old_chip;
 | |
| 	unsigned long irq_flags;
 | |
| 	int ret = -ENOTSUPP;
 | |
| 
 | |
| 	old_chip = container_of(chip, struct old_gpio_chip, gpio_chip);
 | |
| 	spin_lock_irqsave(&old_chip->lock, irq_flags);
 | |
| 	ret = old_chip->configure(old_chip, chip->base + offset, GPIOF_INPUT);
 | |
| 	spin_unlock_irqrestore(&old_chip->lock, irq_flags);
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| static int gpio_chip_get(struct gpio_chip *chip, unsigned offset)
 | |
| {
 | |
| 	struct old_gpio_chip *old_chip;
 | |
| 	unsigned long irq_flags;
 | |
| 	int ret = -ENOTSUPP;
 | |
| 
 | |
| 	old_chip = container_of(chip, struct old_gpio_chip, gpio_chip);
 | |
| 	spin_lock_irqsave(&old_chip->lock, irq_flags);
 | |
| 	if (old_chip->read)
 | |
| 		ret = old_chip->read(old_chip, chip->base + offset);
 | |
| 	spin_unlock_irqrestore(&old_chip->lock, irq_flags);
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| static int
 | |
| gpio_chip_direction_output(struct gpio_chip *chip, unsigned offset, int value)
 | |
| {
 | |
| 	struct old_gpio_chip *old_chip;
 | |
| 	unsigned long irq_flags;
 | |
| 	int ret = -ENOTSUPP;
 | |
| 
 | |
| 	old_chip = container_of(chip, struct old_gpio_chip, gpio_chip);
 | |
| 	spin_lock_irqsave(&old_chip->lock, irq_flags);
 | |
| 	if (old_chip->write)
 | |
| 		old_chip->write(old_chip, chip->base + offset, value);
 | |
| 	ret = old_chip->configure(old_chip, chip->base + offset, GPIOF_DRIVE_OUTPUT);
 | |
| 	spin_unlock_irqrestore(&old_chip->lock, irq_flags);
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| static void gpio_chip_set(struct gpio_chip *chip, unsigned offset, int value)
 | |
| {
 | |
| 	struct old_gpio_chip *old_chip;
 | |
| 	unsigned long irq_flags;
 | |
| 
 | |
| 	old_chip = container_of(chip, struct old_gpio_chip, gpio_chip);
 | |
| 	spin_lock_irqsave(&old_chip->lock, irq_flags);
 | |
| 	if (old_chip->write)
 | |
| 		old_chip->write(old_chip, chip->base + offset, value);
 | |
| 	spin_unlock_irqrestore(&old_chip->lock, irq_flags);
 | |
| }
 | |
| 
 | |
| static int gpio_chip_to_irq(struct gpio_chip *chip, unsigned offset)
 | |
| {
 | |
| 	struct old_gpio_chip *old_chip;
 | |
| 	unsigned long irq_flags;
 | |
| 	int ret = -ENOTSUPP;
 | |
| 	int irq;
 | |
| 
 | |
| 	old_chip = container_of(chip, struct old_gpio_chip, gpio_chip);
 | |
| 	spin_lock_irqsave(&old_chip->lock, irq_flags);
 | |
| 	if (old_chip->get_irq_num)
 | |
| 		ret = old_chip->get_irq_num(old_chip, chip->base + offset, &irq, NULL);
 | |
| 	spin_unlock_irqrestore(&old_chip->lock, irq_flags);
 | |
| 	if (ret)
 | |
| 		return ret;
 | |
| 	return irq;
 | |
| }
 | |
| 
 | |
| int register_gpio_chip(struct old_gpio_chip *new_gpio_chip)
 | |
| {
 | |
| 	spin_lock_init(&new_gpio_chip->lock);
 | |
| 	new_gpio_chip->gpio_chip.direction_input = gpio_chip_direction_input;
 | |
| 	new_gpio_chip->gpio_chip.get = gpio_chip_get;
 | |
| 	new_gpio_chip->gpio_chip.direction_output = gpio_chip_direction_output;
 | |
| 	new_gpio_chip->gpio_chip.set = gpio_chip_set;
 | |
| 	new_gpio_chip->gpio_chip.to_irq = gpio_chip_to_irq;
 | |
| 	new_gpio_chip->gpio_chip.base = new_gpio_chip->start;
 | |
| 	new_gpio_chip->gpio_chip.ngpio = new_gpio_chip->end - new_gpio_chip->start + 1;
 | |
| 
 | |
| 	return gpiochip_add(&new_gpio_chip->gpio_chip);
 | |
| }
 |