gpio-exar.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * GPIO driver for Exar XR17V35X chip
  3. *
  4. * Copyright (C) 2015 Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #include <linux/bitops.h>
  11. #include <linux/device.h>
  12. #include <linux/gpio/driver.h>
  13. #include <linux/init.h>
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/pci.h>
  17. #include <linux/platform_device.h>
  18. #define EXAR_OFFSET_MPIOLVL_LO 0x90
  19. #define EXAR_OFFSET_MPIOSEL_LO 0x93
  20. #define EXAR_OFFSET_MPIOLVL_HI 0x96
  21. #define EXAR_OFFSET_MPIOSEL_HI 0x99
  22. #define DRIVER_NAME "gpio_exar"
  23. static DEFINE_IDA(ida_index);
  24. struct exar_gpio_chip {
  25. struct gpio_chip gpio_chip;
  26. struct mutex lock;
  27. int index;
  28. void __iomem *regs;
  29. char name[20];
  30. };
  31. static void exar_update(struct gpio_chip *chip, unsigned int reg, int val,
  32. unsigned int offset)
  33. {
  34. struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
  35. int temp;
  36. mutex_lock(&exar_gpio->lock);
  37. temp = readb(exar_gpio->regs + reg);
  38. temp &= ~BIT(offset);
  39. if (val)
  40. temp |= BIT(offset);
  41. writeb(temp, exar_gpio->regs + reg);
  42. mutex_unlock(&exar_gpio->lock);
  43. }
  44. static int exar_set_direction(struct gpio_chip *chip, int direction,
  45. unsigned int offset)
  46. {
  47. unsigned int bank = offset / 8;
  48. unsigned int addr;
  49. addr = bank ? EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
  50. exar_update(chip, addr, direction, offset % 8);
  51. return 0;
  52. }
  53. static int exar_get(struct gpio_chip *chip, unsigned int reg)
  54. {
  55. struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
  56. int value;
  57. mutex_lock(&exar_gpio->lock);
  58. value = readb(exar_gpio->regs + reg);
  59. mutex_unlock(&exar_gpio->lock);
  60. return !!value;
  61. }
  62. static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
  63. {
  64. unsigned int bank = offset / 8;
  65. unsigned int addr;
  66. int val;
  67. addr = bank ? EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
  68. val = exar_get(chip, addr) >> (offset % 8);
  69. return !!val;
  70. }
  71. static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
  72. {
  73. unsigned int bank = offset / 8;
  74. unsigned int addr;
  75. int val;
  76. addr = bank ? EXAR_OFFSET_MPIOLVL_LO : EXAR_OFFSET_MPIOLVL_HI;
  77. val = exar_get(chip, addr) >> (offset % 8);
  78. return !!val;
  79. }
  80. static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
  81. int value)
  82. {
  83. unsigned int bank = offset / 8;
  84. unsigned int addr;
  85. addr = bank ? EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
  86. exar_update(chip, addr, value, offset % 8);
  87. }
  88. static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
  89. int value)
  90. {
  91. exar_set_value(chip, offset, value);
  92. return exar_set_direction(chip, 0, offset);
  93. }
  94. static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)
  95. {
  96. return exar_set_direction(chip, 1, offset);
  97. }
  98. static int gpio_exar_probe(struct platform_device *pdev)
  99. {
  100. struct pci_dev *pcidev = platform_get_drvdata(pdev);
  101. struct exar_gpio_chip *exar_gpio;
  102. void __iomem *p;
  103. int index, ret;
  104. if (pcidev->vendor != PCI_VENDOR_ID_EXAR)
  105. return -ENODEV;
  106. /*
  107. * Map the pci device to get the register addresses.
  108. * We will need to read and write those registers to control
  109. * the GPIO pins.
  110. * Using managed functions will save us from unmaping on exit.
  111. * As the device is enabled using managed functions by the
  112. * UART driver we can also use managed functions here.
  113. */
  114. p = pcim_iomap(pcidev, 0, 0);
  115. if (!p)
  116. return -ENOMEM;
  117. exar_gpio = devm_kzalloc(&pcidev->dev, sizeof(*exar_gpio), GFP_KERNEL);
  118. if (!exar_gpio)
  119. return -ENOMEM;
  120. mutex_init(&exar_gpio->lock);
  121. index = ida_simple_get(&ida_index, 0, 0, GFP_KERNEL);
  122. sprintf(exar_gpio->name, "exar_gpio%d", index);
  123. exar_gpio->gpio_chip.label = exar_gpio->name;
  124. exar_gpio->gpio_chip.parent = &pcidev->dev;
  125. exar_gpio->gpio_chip.direction_output = exar_direction_output;
  126. exar_gpio->gpio_chip.direction_input = exar_direction_input;
  127. exar_gpio->gpio_chip.get_direction = exar_get_direction;
  128. exar_gpio->gpio_chip.get = exar_get_value;
  129. exar_gpio->gpio_chip.set = exar_set_value;
  130. exar_gpio->gpio_chip.base = -1;
  131. exar_gpio->gpio_chip.ngpio = 16;
  132. exar_gpio->regs = p;
  133. exar_gpio->index = index;
  134. ret = devm_gpiochip_add_data(&pcidev->dev,
  135. &exar_gpio->gpio_chip, exar_gpio);
  136. if (ret)
  137. goto err_destroy;
  138. platform_set_drvdata(pdev, exar_gpio);
  139. return 0;
  140. err_destroy:
  141. ida_simple_remove(&ida_index, index);
  142. mutex_destroy(&exar_gpio->lock);
  143. return ret;
  144. }
  145. static int gpio_exar_remove(struct platform_device *pdev)
  146. {
  147. struct exar_gpio_chip *exar_gpio = platform_get_drvdata(pdev);
  148. ida_simple_remove(&ida_index, exar_gpio->index);
  149. mutex_destroy(&exar_gpio->lock);
  150. return 0;
  151. }
  152. static struct platform_driver gpio_exar_driver = {
  153. .probe = gpio_exar_probe,
  154. .remove = gpio_exar_remove,
  155. .driver = {
  156. .name = DRIVER_NAME,
  157. },
  158. };
  159. module_platform_driver(gpio_exar_driver);
  160. MODULE_ALIAS("platform:" DRIVER_NAME);
  161. MODULE_DESCRIPTION("Exar GPIO driver");
  162. MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>");
  163. MODULE_LICENSE("GPL");