gpio-amd8111.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * GPIO driver for AMD 8111 south bridges
  4. *
  5. * Copyright (c) 2012 Dmitry Eremin-Solenikov
  6. *
  7. * Based on the AMD RNG driver:
  8. * Copyright 2005 (c) MontaVista Software, Inc.
  9. * with the majority of the code coming from:
  10. *
  11. * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
  12. * (c) Copyright 2003 Red Hat Inc <[email protected]>
  13. *
  14. * derived from
  15. *
  16. * Hardware driver for the AMD 768 Random Number Generator (RNG)
  17. * (c) Copyright 2001 Red Hat Inc
  18. *
  19. * derived from
  20. *
  21. * Hardware driver for Intel i810 Random Number Generator (RNG)
  22. * Copyright 2000,2001 Jeff Garzik <[email protected]>
  23. * Copyright 2000,2001 Philipp Rumpf <[email protected]>
  24. */
  25. #include <linux/ioport.h>
  26. #include <linux/module.h>
  27. #include <linux/kernel.h>
  28. #include <linux/gpio/driver.h>
  29. #include <linux/pci.h>
  30. #include <linux/spinlock.h>
  31. #define PMBASE_OFFSET 0xb0
  32. #define PMBASE_SIZE 0x30
  33. #define AMD_REG_GPIO(i) (0x10 + (i))
  34. #define AMD_GPIO_LTCH_STS 0x40 /* Latch status, w1 */
  35. #define AMD_GPIO_RTIN 0x20 /* Real Time in, ro */
  36. #define AMD_GPIO_DEBOUNCE 0x10 /* Debounce, rw */
  37. #define AMD_GPIO_MODE_MASK 0x0c /* Pin Mode Select, rw */
  38. #define AMD_GPIO_MODE_IN 0x00
  39. #define AMD_GPIO_MODE_OUT 0x04
  40. /* Enable alternative (e.g. clkout, IRQ, etc) function of the pin */
  41. #define AMD_GPIO_MODE_ALTFN 0x08 /* Or 0x09 */
  42. #define AMD_GPIO_X_MASK 0x03 /* In/Out specific, rw */
  43. #define AMD_GPIO_X_IN_ACTIVEHI 0x01 /* Active High */
  44. #define AMD_GPIO_X_IN_LATCH 0x02 /* Latched version is selected */
  45. #define AMD_GPIO_X_OUT_LOW 0x00
  46. #define AMD_GPIO_X_OUT_HI 0x01
  47. #define AMD_GPIO_X_OUT_CLK0 0x02
  48. #define AMD_GPIO_X_OUT_CLK1 0x03
  49. /*
  50. * Data for PCI driver interface
  51. *
  52. * This data only exists for exporting the supported
  53. * PCI ids via MODULE_DEVICE_TABLE. We do not actually
  54. * register a pci_driver, because someone else might one day
  55. * want to register another driver on the same PCI id.
  56. */
  57. static const struct pci_device_id pci_tbl[] = {
  58. { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), 0 },
  59. { 0, }, /* terminate list */
  60. };
  61. MODULE_DEVICE_TABLE(pci, pci_tbl);
  62. struct amd_gpio {
  63. struct gpio_chip chip;
  64. u32 pmbase;
  65. void __iomem *pm;
  66. struct pci_dev *pdev;
  67. spinlock_t lock; /* guards hw registers and orig table */
  68. u8 orig[32];
  69. };
  70. static int amd_gpio_request(struct gpio_chip *chip, unsigned offset)
  71. {
  72. struct amd_gpio *agp = gpiochip_get_data(chip);
  73. agp->orig[offset] = ioread8(agp->pm + AMD_REG_GPIO(offset)) &
  74. (AMD_GPIO_DEBOUNCE | AMD_GPIO_MODE_MASK | AMD_GPIO_X_MASK);
  75. dev_dbg(&agp->pdev->dev, "Requested gpio %d, data %x\n", offset, agp->orig[offset]);
  76. return 0;
  77. }
  78. static void amd_gpio_free(struct gpio_chip *chip, unsigned offset)
  79. {
  80. struct amd_gpio *agp = gpiochip_get_data(chip);
  81. dev_dbg(&agp->pdev->dev, "Freed gpio %d, data %x\n", offset, agp->orig[offset]);
  82. iowrite8(agp->orig[offset], agp->pm + AMD_REG_GPIO(offset));
  83. }
  84. static void amd_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
  85. {
  86. struct amd_gpio *agp = gpiochip_get_data(chip);
  87. u8 temp;
  88. unsigned long flags;
  89. spin_lock_irqsave(&agp->lock, flags);
  90. temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
  91. temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_OUT | (value ? AMD_GPIO_X_OUT_HI : AMD_GPIO_X_OUT_LOW);
  92. iowrite8(temp, agp->pm + AMD_REG_GPIO(offset));
  93. spin_unlock_irqrestore(&agp->lock, flags);
  94. dev_dbg(&agp->pdev->dev, "Setting gpio %d, value %d, reg=%02x\n", offset, !!value, temp);
  95. }
  96. static int amd_gpio_get(struct gpio_chip *chip, unsigned offset)
  97. {
  98. struct amd_gpio *agp = gpiochip_get_data(chip);
  99. u8 temp;
  100. temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
  101. dev_dbg(&agp->pdev->dev, "Getting gpio %d, reg=%02x\n", offset, temp);
  102. return (temp & AMD_GPIO_RTIN) ? 1 : 0;
  103. }
  104. static int amd_gpio_dirout(struct gpio_chip *chip, unsigned offset, int value)
  105. {
  106. struct amd_gpio *agp = gpiochip_get_data(chip);
  107. u8 temp;
  108. unsigned long flags;
  109. spin_lock_irqsave(&agp->lock, flags);
  110. temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
  111. temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_OUT | (value ? AMD_GPIO_X_OUT_HI : AMD_GPIO_X_OUT_LOW);
  112. iowrite8(temp, agp->pm + AMD_REG_GPIO(offset));
  113. spin_unlock_irqrestore(&agp->lock, flags);
  114. dev_dbg(&agp->pdev->dev, "Dirout gpio %d, value %d, reg=%02x\n", offset, !!value, temp);
  115. return 0;
  116. }
  117. static int amd_gpio_dirin(struct gpio_chip *chip, unsigned offset)
  118. {
  119. struct amd_gpio *agp = gpiochip_get_data(chip);
  120. u8 temp;
  121. unsigned long flags;
  122. spin_lock_irqsave(&agp->lock, flags);
  123. temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
  124. temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_IN;
  125. iowrite8(temp, agp->pm + AMD_REG_GPIO(offset));
  126. spin_unlock_irqrestore(&agp->lock, flags);
  127. dev_dbg(&agp->pdev->dev, "Dirin gpio %d, reg=%02x\n", offset, temp);
  128. return 0;
  129. }
  130. static struct amd_gpio gp = {
  131. .chip = {
  132. .label = "AMD GPIO",
  133. .owner = THIS_MODULE,
  134. .base = -1,
  135. .ngpio = 32,
  136. .request = amd_gpio_request,
  137. .free = amd_gpio_free,
  138. .set = amd_gpio_set,
  139. .get = amd_gpio_get,
  140. .direction_output = amd_gpio_dirout,
  141. .direction_input = amd_gpio_dirin,
  142. },
  143. };
  144. static int __init amd_gpio_init(void)
  145. {
  146. int err = -ENODEV;
  147. struct pci_dev *pdev = NULL;
  148. const struct pci_device_id *ent;
  149. /* We look for our device - AMD South Bridge
  150. * I don't know about a system with two such bridges,
  151. * so we can assume that there is max. one device.
  152. *
  153. * We can't use plain pci_driver mechanism,
  154. * as the device is really a multiple function device,
  155. * main driver that binds to the pci_device is an smbus
  156. * driver and have to find & bind to the device this way.
  157. */
  158. for_each_pci_dev(pdev) {
  159. ent = pci_match_id(pci_tbl, pdev);
  160. if (ent)
  161. goto found;
  162. }
  163. /* Device not found. */
  164. goto out;
  165. found:
  166. err = pci_read_config_dword(pdev, 0x58, &gp.pmbase);
  167. if (err)
  168. goto out;
  169. err = -EIO;
  170. gp.pmbase &= 0x0000FF00;
  171. if (gp.pmbase == 0)
  172. goto out;
  173. if (!devm_request_region(&pdev->dev, gp.pmbase + PMBASE_OFFSET,
  174. PMBASE_SIZE, "AMD GPIO")) {
  175. dev_err(&pdev->dev, "AMD GPIO region 0x%x already in use!\n",
  176. gp.pmbase + PMBASE_OFFSET);
  177. err = -EBUSY;
  178. goto out;
  179. }
  180. gp.pm = ioport_map(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
  181. if (!gp.pm) {
  182. dev_err(&pdev->dev, "Couldn't map io port into io memory\n");
  183. err = -ENOMEM;
  184. goto out;
  185. }
  186. gp.pdev = pdev;
  187. gp.chip.parent = &pdev->dev;
  188. spin_lock_init(&gp.lock);
  189. dev_info(&pdev->dev, "AMD-8111 GPIO detected\n");
  190. err = gpiochip_add_data(&gp.chip, &gp);
  191. if (err) {
  192. dev_err(&pdev->dev, "GPIO registering failed (%d)\n", err);
  193. ioport_unmap(gp.pm);
  194. goto out;
  195. }
  196. return 0;
  197. out:
  198. pci_dev_put(pdev);
  199. return err;
  200. }
  201. static void __exit amd_gpio_exit(void)
  202. {
  203. gpiochip_remove(&gp.chip);
  204. ioport_unmap(gp.pm);
  205. pci_dev_put(gp.pdev);
  206. }
  207. module_init(amd_gpio_init);
  208. module_exit(amd_gpio_exit);
  209. MODULE_AUTHOR("The Linux Kernel team");
  210. MODULE_DESCRIPTION("GPIO driver for AMD chipsets");
  211. MODULE_LICENSE("GPL");