Linux gpio驱动学习

蔚落 2022-04-25 03:56 760阅读 0赞

首先我们来看一下gpio驱动框架吧

  1. GPIO驱动的头文件为:include/linux/gpio.hinclude/asm-generic/gpio.h
  2. GPIO驱动框架的实现代码为:drivers/gpio/gpiolib.c
  3. gpio操作增删改查架构:
  4. /*
  5. * Add a new chip to the global chips list, keeping the list of chips sorted
  6. * by base order.
  7. *
  8. * Return -EBUSY if the new chip overlaps with some other chip's integer
  9. * space.
  10. */
  11. static int gpiochip_add_to_list(struct gpio_chip *chip)
  12. {
  13. struct list_head *pos;
  14. struct gpio_chip *_chip;
  15. int err = 0;
  16. /* find where to insert our chip */
  17. list_for_each(pos, &gpio_chips) {
  18. _chip = list_entry(pos, struct gpio_chip, list);
  19. /* shall we insert before _chip? */
  20. if (_chip->base >= chip->base + chip->ngpio)
  21. break;
  22. }
  23. /* are we stepping on the chip right before? */
  24. if (pos != &gpio_chips && pos->prev != &gpio_chips) {
  25. _chip = list_entry(pos->prev, struct gpio_chip, list);
  26. if (_chip->base + _chip->ngpio > chip->base) {
  27. dev_err(chip->dev,
  28. "GPIO integer space overlap, cannot add chip\n");
  29. err = -EBUSY;
  30. }
  31. }
  32. if (!err)
  33. list_add_tail(&chip->list, pos);
  34. return err;
  35. }
  36. int gpiochip_add(struct gpio_chip *chip)
  37. {
  38. unsigned long flags;
  39. int status = 0;
  40. unsigned id;
  41. int base = chip->base;
  42. struct gpio_desc *descs;
  43. descs = kcalloc(chip->ngpio, sizeof(descs[0]), GFP_KERNEL);
  44. if (!descs)
  45. return -ENOMEM;
  46. spin_lock_irqsave(&gpio_lock, flags);
  47. if (base < 0) {
  48. base = gpiochip_find_base(chip->ngpio);
  49. if (base < 0) {
  50. status = base;
  51. spin_unlock_irqrestore(&gpio_lock, flags);
  52. goto err_free_descs;
  53. }
  54. chip->base = base;
  55. }
  56. status = gpiochip_add_to_list(chip);
  57. if (status) {
  58. spin_unlock_irqrestore(&gpio_lock, flags);
  59. goto err_free_descs;
  60. }
  61. for (id = 0; id < chip->ngpio; id++) {
  62. struct gpio_desc *desc = &descs[id];
  63. desc->chip = chip;
  64. /* REVISIT: most hardware initializes GPIOs as inputs (often
  65. * with pullups enabled) so power usage is minimized. Linux
  66. * code should set the gpio direction first thing; but until
  67. * it does, and in case chip->get_direction is not set, we may
  68. * expose the wrong direction in sysfs.
  69. */
  70. desc->flags = !chip->direction_input ? (1 << FLAG_IS_OUT) : 0;
  71. }
  72. chip->desc = descs;
  73. spin_unlock_irqrestore(&gpio_lock, flags);
  74. #ifdef CONFIG_PINCTRL
  75. INIT_LIST_HEAD(&chip->pin_ranges);
  76. #endif
  77. if (!chip->owner && chip->dev && chip->dev->driver)
  78. chip->owner = chip->dev->driver->owner;
  79. status = gpiochip_set_desc_names(chip);
  80. if (status)
  81. goto err_remove_from_list;
  82. status = of_gpiochip_add(chip);
  83. if (status)
  84. goto err_remove_chip;
  85. acpi_gpiochip_add(chip);
  86. status = gpiochip_sysfs_register(chip);
  87. if (status)
  88. goto err_remove_chip;
  89. pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__,
  90. chip->base, chip->base + chip->ngpio - 1,
  91. chip->label ? : "generic");
  92. return 0;
  93. err_remove_chip:
  94. acpi_gpiochip_remove(chip);
  95. gpiochip_free_hogs(chip);
  96. of_gpiochip_remove(chip);
  97. err_remove_from_list:
  98. spin_lock_irqsave(&gpio_lock, flags);
  99. list_del(&chip->list);
  100. spin_unlock_irqrestore(&gpio_lock, flags);
  101. chip->desc = NULL;
  102. err_free_descs:
  103. kfree(descs);
  104. /* failures here can mean systems won't boot... */
  105. pr_err("%s: GPIOs %d..%d (%s) failed to register\n", __func__,
  106. chip->base, chip->base + chip->ngpio - 1,
  107. chip->label ? : "generic");
  108. return status;
  109. }
  110. EXPORT_SYMBOL_GPL(gpiochip_add);
  111. /**
  112. * gpiochip_remove() - unregister a gpio_chip
  113. * @chip: the chip to unregister
  114. *
  115. * A gpio_chip with any GPIOs still requested may not be removed.
  116. */
  117. void gpiochip_remove(struct gpio_chip *chip)
  118. {
  119. struct gpio_desc *desc;
  120. unsigned long flags;
  121. unsigned id;
  122. bool requested = false;
  123. gpiochip_sysfs_unregister(chip);
  124. gpiochip_irqchip_remove(chip);
  125. acpi_gpiochip_remove(chip);
  126. gpiochip_remove_pin_ranges(chip);
  127. gpiochip_free_hogs(chip);
  128. of_gpiochip_remove(chip);
  129. spin_lock_irqsave(&gpio_lock, flags);
  130. for (id = 0; id < chip->ngpio; id++) {
  131. desc = &chip->desc[id];
  132. desc->chip = NULL;
  133. if (test_bit(FLAG_REQUESTED, &desc->flags))
  134. requested = true;
  135. }
  136. list_del(&chip->list);
  137. spin_unlock_irqrestore(&gpio_lock, flags);
  138. if (requested)
  139. dev_crit(chip->dev, "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n");
  140. kfree(chip->desc);
  141. chip->desc = NULL;
  142. }
  143. EXPORT_SYMBOL_GPL(gpiochip_remove);
  144. /**
  145. * gpiochip_find() - iterator for locating a specific gpio_chip
  146. * @data: data to pass to match function
  147. * @callback: Callback function to check gpio_chip
  148. *
  149. * Similar to bus_find_device. It returns a reference to a gpio_chip as
  150. * determined by a user supplied @match callback. The callback should return
  151. * 0 if the device doesn't match and non-zero if it does. If the callback is
  152. * non-zero, this function will return to the caller and not iterate over any
  153. * more gpio_chips.
  154. */
  155. struct gpio_chip *gpiochip_find(void *data,
  156. int (*match)(struct gpio_chip *chip,
  157. void *data))
  158. {
  159. struct gpio_chip *chip;
  160. unsigned long flags;
  161. spin_lock_irqsave(&gpio_lock, flags);
  162. list_for_each_entry(chip, &gpio_chips, list)
  163. if (match(chip, data))
  164. break;
  165. /* No match? */
  166. if (&chip->list == &gpio_chips)
  167. chip = NULL;
  168. spin_unlock_irqrestore(&gpio_lock, flags);
  169. return chip;
  170. }
  171. EXPORT_SYMBOL_GPL(gpiochip_find);
  172. static int gpiochip_match_name(struct gpio_chip *chip, void *data)
  173. {
  174. const char *name = data;
  175. return !strcmp(chip->label, name);
  176. }
  177. static struct gpio_chip *find_chip_by_name(const char *name)
  178. {
  179. return gpiochip_find((void *)name, gpiochip_match_name);
  180. }

gpio驱动输入输出设置,高低电平设置:

  1. static int nx_alive_gpio_direction_input(struct udevice *dev, unsigned pin)
  2. {
  3. struct nx_gpio_platdata *plat = dev_get_platdata(dev);
  4. struct nx_alive_g+
  5. pio_regs *const regs = plat->regs;
  6. setbits_le32(&regs->outputenb_reset, 1 << pin);
  7. return 0;
  8. }
  9. static int nx_alive_gpio_direction_output(struct udevice *dev, unsigned pin,
  10. int val)
  11. {
  12. struct nx_gpio_platdata *plat = dev_get_platdata(dev);
  13. struct nx_alive_gpio_regs *const regs = plat->regs;
  14. if (val)
  15. setbits_le32(&regs->data, 1 << pin);
  16. else
  17. setbits_le32(&regs->pad_reset, 1 << pin);
  18. setbits_le32(&regs->outputenb, 1 << pin);
  19. return 0;
  20. }
  21. static int nx_alive_gpio_get_value(struct udevice *dev, unsigned pin)
  22. {
  23. struct nx_gpio_platdata *plat = dev_get_platdata(dev);
  24. struct nx_alive_gpio_regs *const regs = plat->regs;
  25. unsigned int mask = 1UL << pin;
  26. unsigned int value;
  27. value = (readl(&regs->pad_read) & mask) >> pin;
  28. return value;
  29. }
  30. static int nx_alive_gpio_set_value(struct udevice *dev, unsigned pin, int val)
  31. {
  32. struct nx_gpio_platdata *plat = dev_get_platdata(dev);
  33. struct nx_alive_gpio_regs *const regs = plat->regs;
  34. if (val)
  35. setbits_le32(&regs->data, 1 << pin);
  36. else
  37. clrbits_le32(&regs->pad_reset, 1 << pin);
  38. return 0;
  39. }
  40. static int nx_alive_gpio_get_function(struct udevice *dev, unsigned pin)
  41. {
  42. struct nx_gpio_platdata *plat = dev_get_platdata(dev);
  43. struct nx_alive_gpio_regs *const regs = plat->regs;
  44. unsigned int mask = (1UL << pin);
  45. unsigned int output;
  46. output = readl(&regs->outputenb_read) & mask;
  47. if (output)
  48. return GPIOF_OUTPUT;
  49. else
  50. return GPIOF_INPUT;
  51. }
  52. static int nx_gpio_direction_input(struct udevice *dev, unsigned pin)
  53. {
  54. struct nx_gpio_platdata *plat = dev_get_platdata(dev);
  55. struct nx_gpio_regs *const regs = plat->regs;
  56. if (nx_alive_gpio_is_check(dev))
  57. return nx_alive_gpio_direction_input(dev, pin);
  58. clrbits_le32(&regs->outputenb, 1 << pin);
  59. return 0;
  60. }
  61. static int nx_gpio_direction_output(struct udevice *dev, unsigned pin,
  62. int val)
  63. {
  64. struct nx_gpio_platdata *plat = dev_get_platdata(dev);
  65. struct nx_gpio_regs *const regs = plat->regs;
  66. if (nx_alive_gpio_is_check(dev))
  67. return nx_alive_gpio_direction_output(dev, pin, val);
  68. if (val)
  69. setbits_le32(&regs->data, 1 << pin);
  70. else
  71. clrbits_le32(&regs->data, 1 << pin);
  72. setbits_le32(&regs->outputenb, 1 << pin);
  73. return 0;
  74. }
  75. static int nx_gpio_get_value(struct udevice *dev, unsigned pin)
  76. {
  77. struct nx_gpio_platdata *plat = dev_get_platdata(dev);
  78. struct nx_gpio_regs *const regs = plat->regs;
  79. unsigned int mask = 1UL << pin;
  80. unsigned int value;
  81. if (nx_alive_gpio_is_check(dev))
  82. return nx_alive_gpio_get_value(dev, pin);
  83. value = (readl(&regs->pad) & mask) >> pin;
  84. return value;
  85. }
  86. static int nx_gpio_set_value(struct udevice *dev, unsigned pin, int val)
  87. {
  88. struct nx_gpio_platdata *plat = dev_get_platdata(dev);
  89. struct nx_gpio_regs *const regs = plat->regs;
  90. if (nx_alive_gpio_is_check(dev))
  91. return nx_alive_gpio_set_value(dev, pin, val);
  92. if (val)
  93. setbits_le32(&regs->data, 1 << pin);
  94. else
  95. clrbits_le32(&regs->data, 1 << pin);
  96. return 0;
  97. }
  98. static int nx_gpio_get_function(struct udevice *dev, unsigned pin)
  99. {
  100. struct nx_gpio_platdata *plat = dev_get_platdata(dev);
  101. struct nx_gpio_regs *const regs = plat->regs;
  102. unsigned int mask = (1UL << pin);
  103. unsigned int output;
  104. if (nx_alive_gpio_is_check(dev))
  105. return nx_alive_gpio_get_function(dev, pin);
  106. output = readl(&regs->outputenb) & mask;
  107. if (output)
  108. return GPIOF_OUTPUT;
  109. else
  110. return GPIOF_INPUT;
  111. }

发表评论

表情:
评论列表 (有 0 条评论,760人围观)

还没有评论,来说两句吧...

相关阅读