gpio-exar.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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_direction_output(struct gpio_chip *chip, unsigned int offset,
  54. int value)
  55. {
  56. return exar_set_direction(chip, 0, offset);
  57. }
  58. static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)
  59. {
  60. return exar_set_direction(chip, 1, offset);
  61. }
  62. static int exar_get(struct gpio_chip *chip, unsigned int reg)
  63. {
  64. struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
  65. int value;
  66. mutex_lock(&exar_gpio->lock);
  67. value = readb(exar_gpio->regs + reg);
  68. mutex_unlock(&exar_gpio->lock);
  69. return !!value;
  70. }
  71. static int exar_get_direction(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_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
  77. val = exar_get(chip, addr) >> (offset % 8);
  78. return !!val;
  79. }
  80. static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
  81. {
  82. unsigned int bank = offset / 8;
  83. unsigned int addr;
  84. int val;
  85. addr = bank ? EXAR_OFFSET_MPIOLVL_LO : EXAR_OFFSET_MPIOLVL_HI;
  86. val = exar_get(chip, addr) >> (offset % 8);
  87. return !!val;
  88. }
  89. static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
  90. int value)
  91. {
  92. unsigned int bank = offset / 8;
  93. unsigned int addr;
  94. addr = bank ? EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
  95. exar_update(chip, addr, value, offset % 8);
  96. }
  97. static int gpio_exar_probe(struct platform_device *pdev)
  98. {
  99. struct pci_dev *pcidev = platform_get_drvdata(pdev);
  100. struct exar_gpio_chip *exar_gpio;
  101. void __iomem *p;
  102. int index, ret;
  103. if (pcidev->vendor != PCI_VENDOR_ID_EXAR)
  104. return -ENODEV;
  105. /*
  106. * Map the pci device to get the register addresses.
  107. * We will need to read and write those registers to control
  108. * the GPIO pins.
  109. * Using managed functions will save us from unmaping on exit.
  110. * As the device is enabled using managed functions by the
  111. * UART driver we can also use managed functions here.
  112. */
  113. p = pcim_iomap(pcidev, 0, 0);
  114. if (!p)
  115. return -ENOMEM;
  116. exar_gpio = devm_kzalloc(&pcidev->dev, sizeof(*exar_gpio), GFP_KERNEL);
  117. if (!exar_gpio)
  118. return -ENOMEM;
  119. mutex_init(&exar_gpio->lock);
  120. index = ida_simple_get(&ida_index, 0, 0, GFP_KERNEL);
  121. sprintf(exar_gpio->name, "exar_gpio%d", index);
  122. exar_gpio->gpio_chip.label = exar_gpio->name;
  123. exar_gpio->gpio_chip.parent = &pcidev->dev;
  124. exar_gpio->gpio_chip.direction_output = exar_direction_output;
  125. exar_gpio->gpio_chip.direction_input = exar_direction_input;
  126. exar_gpio->gpio_chip.get_direction = exar_get_direction;
  127. exar_gpio->gpio_chip.get = exar_get_value;
  128. exar_gpio->gpio_chip.set = exar_set_value;
  129. exar_gpio->gpio_chip.base = -1;
  130. exar_gpio->gpio_chip.ngpio = 16;
  131. exar_gpio->regs = p;
  132. exar_gpio->index = index;
  133. ret = devm_gpiochip_add_data(&pcidev->dev,
  134. &exar_gpio->gpio_chip, exar_gpio);
  135. if (ret)
  136. goto err_destroy;
  137. platform_set_drvdata(pdev, exar_gpio);
  138. return 0;
  139. err_destroy:
  140. ida_simple_remove(&ida_index, index);
  141. mutex_destroy(&exar_gpio->lock);
  142. return ret;
  143. }
  144. static int gpio_exar_remove(struct platform_device *pdev)
  145. {
  146. struct exar_gpio_chip *exar_gpio = platform_get_drvdata(pdev);
  147. ida_simple_remove(&ida_index, exar_gpio->index);
  148. mutex_destroy(&exar_gpio->lock);
  149. return 0;
  150. }
  151. static struct platform_driver gpio_exar_driver = {
  152. .probe = gpio_exar_probe,
  153. .remove = gpio_exar_remove,
  154. .driver = {
  155. .name = DRIVER_NAME,
  156. },
  157. };
  158. module_platform_driver(gpio_exar_driver);
  159. MODULE_ALIAS("platform:" DRIVER_NAME);
  160. MODULE_DESCRIPTION("Exar GPIO driver");
  161. MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>");
  162. MODULE_LICENSE("GPL");