#include <linux/idr.h>
#include <linux/slab.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/gpio.h>
/* Optional implementation infrastructure for GPIO interfaces.
*
return chip;
}
+EXPORT_SYMBOL_GPL(gpiochip_find);
/* These "optional" allocation calls help prevent drivers from stomping
* on each other, and help provide better diagnostics in debugfs.
spin_unlock_irqrestore(&gpio_lock, flags);
return status;
}
-EXPORT_SYMBOL_GPL(gpio_request);
+EXPORT_SYMBOL(gpio_request);//EXPORT_SYMBOL_GPL(gpio_request);
void gpio_free(unsigned gpio)
{
spin_unlock_irqrestore(&gpio_lock, flags);
}
-EXPORT_SYMBOL_GPL(gpio_free);
+//EXPORT_SYMBOL_GPL(gpio_free);
+EXPORT_SYMBOL(gpio_free);
+
/**
* gpio_request_one - request a single GPIO with initial configuration
* @array: array of the 'struct gpio'
* @num: how many GPIOs in the array
*/
-int gpio_request_array(struct gpio *array, size_t num)
+int gpio_request_array(const struct gpio *array, size_t num)
{
int i, err;
* @array: array of the 'struct gpio'
* @num: how many GPIOs in the array
*/
-void gpio_free_array(struct gpio *array, size_t num)
+void gpio_free_array(const struct gpio *array, size_t num)
{
while (num--)
gpio_free((array++)->gpio);
status = chip->direction_input(chip, gpio);
if (status == 0)
clear_bit(FLAG_IS_OUT, &desc->flags);
+
+ trace_gpio_direction(chip->base + gpio, 1, status);
lose:
return status;
fail:
__func__, gpio, status);
return status;
}
-EXPORT_SYMBOL_GPL(gpio_direction_input);
+//EXPORT_SYMBOL_GPL(gpio_direction_input);
+EXPORT_SYMBOL(gpio_direction_input);
+
int gpio_direction_output(unsigned gpio, int value)
{
spin_lock_irqsave(&gpio_lock, flags);
+ if (value !=0 && value !=1)
+ goto fail;
if (!gpio_is_valid(gpio))
goto fail;
chip = desc->chip;
status = chip->direction_output(chip, gpio, value);
if (status == 0)
set_bit(FLAG_IS_OUT, &desc->flags);
+ trace_gpio_value(chip->base + gpio, 0, value);
+ trace_gpio_direction(chip->base + gpio, 0, status);
+lose:
+ return status;
+fail:
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ if (status)
+ pr_debug("%s: gpio-%d status %d\n",
+ __func__, gpio, status);
+ return status;
+}
+//EXPORT_SYMBOL_GPL(gpio_direction_output);
+EXPORT_SYMBOL(gpio_direction_output);
+
+/*
+gpio pull up or pull down
+value = 0, normal
+value = 1, pull up
+value = 2, pull down
+*/
+int gpio_pull_updown(unsigned gpio, unsigned value)
+{
+ unsigned long flags;
+ struct gpio_chip *chip;
+ struct gpio_desc *desc = &gpio_desc[gpio];
+ int status = -EINVAL;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ if (value >3)
+ goto fail;
+ if (!gpio_is_valid(gpio))
+ goto fail;
+ chip = desc->chip;
+ if (!chip || !chip->get || !chip->pull_updown)
+ goto fail;
+ gpio -= chip->base;
+ if (gpio >= chip->ngpio)
+ goto fail;
+ status = gpio_ensure_requested(desc, gpio);
+ if (status < 0)
+ goto fail;
+
+ /* now we know the gpio is valid and chip won't vanish */
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ might_sleep_if(extra_checks && chip->can_sleep);
+
+ if (status) {
+ status = chip->request(chip, gpio);
+ if (status < 0) {
+ pr_debug("GPIO-%d: chip request fail, %d\n",
+ chip->base + gpio, status);
+ /* and it's not available to anyone else ...
+ * gpio_request() is the fully clean solution.
+ */
+ goto lose;
+ }
+ }
+ status = chip->pull_updown(chip, gpio,value);
+ if (status == 0)
+ clear_bit(FLAG_IS_OUT, &desc->flags);
+
lose:
return status;
fail:
__func__, gpio, status);
return status;
}
-EXPORT_SYMBOL_GPL(gpio_direction_output);
+//EXPORT_SYMBOL_GPL(gpio_pull_updown);
+EXPORT_SYMBOL(gpio_pull_updown);
/**
* gpio_set_debounce - sets @debounce time for a @gpio
int __gpio_get_value(unsigned gpio)
{
struct gpio_chip *chip;
+ int value;
+ if (!gpio_is_valid(gpio))
+ return -1;
chip = gpio_to_chip(gpio);
WARN_ON(chip->can_sleep);
- return chip->get ? chip->get(chip, gpio - chip->base) : 0;
+ value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
+ trace_gpio_value(gpio, 1, value);
+ return value;
}
-EXPORT_SYMBOL_GPL(__gpio_get_value);
+//EXPORT_SYMBOL_GPL(__gpio_get_value);
+EXPORT_SYMBOL(__gpio_get_value);
+
/**
* __gpio_set_value() - assign a gpio's value
{
struct gpio_chip *chip;
+ if(value !=0 && value !=1)
+ return;
+ if (!gpio_is_valid(gpio))
+ return;
chip = gpio_to_chip(gpio);
WARN_ON(chip->can_sleep);
+ trace_gpio_value(gpio, 0, value);
chip->set(chip, gpio - chip->base, value);
}
-EXPORT_SYMBOL_GPL(__gpio_set_value);
+//EXPORT_SYMBOL_GPL(__gpio_set_value);
+EXPORT_SYMBOL(__gpio_set_value);
/**
* __gpio_cansleep() - report whether gpio value access will sleep
int __gpio_to_irq(unsigned gpio)
{
struct gpio_chip *chip;
-
+
+ if (!gpio_is_valid(gpio))
+ return -1;
+
chip = gpio_to_chip(gpio);
- return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO;
+
+ return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -1;
}
EXPORT_SYMBOL_GPL(__gpio_to_irq);
int gpio_get_value_cansleep(unsigned gpio)
{
struct gpio_chip *chip;
+ int value;
might_sleep_if(extra_checks);
chip = gpio_to_chip(gpio);
- return chip->get ? chip->get(chip, gpio - chip->base) : 0;
+ value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
+ trace_gpio_value(gpio, 1, value);
+ return value;
}
EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
might_sleep_if(extra_checks);
chip = gpio_to_chip(gpio);
+ trace_gpio_value(gpio, 0, value);
chip->set(chip, gpio - chip->base, value);
}
EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);