gpio-rdc321x.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * RDC321x GPIO driver
  4. *
  5. * Copyright (C) 2008, Volker Weiss <dev@tintuc.de>
  6. * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org>
  7. */
  8. #include <linux/module.h>
  9. #include <linux/kernel.h>
  10. #include <linux/init.h>
  11. #include <linux/spinlock.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/pci.h>
  14. #include <linux/gpio/driver.h>
  15. #include <linux/mfd/rdc321x.h>
  16. #include <linux/slab.h>
  17. struct rdc321x_gpio {
  18. spinlock_t lock;
  19. struct pci_dev *sb_pdev;
  20. u32 data_reg[2];
  21. int reg1_ctrl_base;
  22. int reg1_data_base;
  23. int reg2_ctrl_base;
  24. int reg2_data_base;
  25. struct gpio_chip chip;
  26. };
  27. /* read GPIO pin */
  28. static int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
  29. {
  30. struct rdc321x_gpio *gpch;
  31. u32 value = 0;
  32. int reg;
  33. gpch = gpiochip_get_data(chip);
  34. reg = gpio < 32 ? gpch->reg1_data_base : gpch->reg2_data_base;
  35. spin_lock(&gpch->lock);
  36. pci_write_config_dword(gpch->sb_pdev, reg,
  37. gpch->data_reg[gpio < 32 ? 0 : 1]);
  38. pci_read_config_dword(gpch->sb_pdev, reg, &value);
  39. spin_unlock(&gpch->lock);
  40. return (1 << (gpio & 0x1f)) & value ? 1 : 0;
  41. }
  42. static void rdc_gpio_set_value_impl(struct gpio_chip *chip,
  43. unsigned gpio, int value)
  44. {
  45. struct rdc321x_gpio *gpch;
  46. int reg = (gpio < 32) ? 0 : 1;
  47. gpch = gpiochip_get_data(chip);
  48. if (value)
  49. gpch->data_reg[reg] |= 1 << (gpio & 0x1f);
  50. else
  51. gpch->data_reg[reg] &= ~(1 << (gpio & 0x1f));
  52. pci_write_config_dword(gpch->sb_pdev,
  53. reg ? gpch->reg2_data_base : gpch->reg1_data_base,
  54. gpch->data_reg[reg]);
  55. }
  56. /* set GPIO pin to value */
  57. static void rdc_gpio_set_value(struct gpio_chip *chip,
  58. unsigned gpio, int value)
  59. {
  60. struct rdc321x_gpio *gpch;
  61. gpch = gpiochip_get_data(chip);
  62. spin_lock(&gpch->lock);
  63. rdc_gpio_set_value_impl(chip, gpio, value);
  64. spin_unlock(&gpch->lock);
  65. }
  66. static int rdc_gpio_config(struct gpio_chip *chip,
  67. unsigned gpio, int value)
  68. {
  69. struct rdc321x_gpio *gpch;
  70. int err;
  71. u32 reg;
  72. gpch = gpiochip_get_data(chip);
  73. spin_lock(&gpch->lock);
  74. err = pci_read_config_dword(gpch->sb_pdev, gpio < 32 ?
  75. gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, &reg);
  76. if (err)
  77. goto unlock;
  78. reg |= 1 << (gpio & 0x1f);
  79. err = pci_write_config_dword(gpch->sb_pdev, gpio < 32 ?
  80. gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, reg);
  81. if (err)
  82. goto unlock;
  83. rdc_gpio_set_value_impl(chip, gpio, value);
  84. unlock:
  85. spin_unlock(&gpch->lock);
  86. return err;
  87. }
  88. /* configure GPIO pin as input */
  89. static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
  90. {
  91. return rdc_gpio_config(chip, gpio, 1);
  92. }
  93. /*
  94. * Cache the initial value of both GPIO data registers
  95. */
  96. static int rdc321x_gpio_probe(struct platform_device *pdev)
  97. {
  98. int err;
  99. struct resource *r;
  100. struct rdc321x_gpio *rdc321x_gpio_dev;
  101. struct rdc321x_gpio_pdata *pdata;
  102. pdata = dev_get_platdata(&pdev->dev);
  103. if (!pdata) {
  104. dev_err(&pdev->dev, "no platform data supplied\n");
  105. return -ENODEV;
  106. }
  107. rdc321x_gpio_dev = devm_kzalloc(&pdev->dev, sizeof(struct rdc321x_gpio),
  108. GFP_KERNEL);
  109. if (!rdc321x_gpio_dev)
  110. return -ENOMEM;
  111. r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1");
  112. if (!r) {
  113. dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n");
  114. return -ENODEV;
  115. }
  116. spin_lock_init(&rdc321x_gpio_dev->lock);
  117. rdc321x_gpio_dev->sb_pdev = pdata->sb_pdev;
  118. rdc321x_gpio_dev->reg1_ctrl_base = r->start;
  119. rdc321x_gpio_dev->reg1_data_base = r->start + 0x4;
  120. r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2");
  121. if (!r) {
  122. dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n");
  123. return -ENODEV;
  124. }
  125. rdc321x_gpio_dev->reg2_ctrl_base = r->start;
  126. rdc321x_gpio_dev->reg2_data_base = r->start + 0x4;
  127. rdc321x_gpio_dev->chip.label = "rdc321x-gpio";
  128. rdc321x_gpio_dev->chip.owner = THIS_MODULE;
  129. rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input;
  130. rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config;
  131. rdc321x_gpio_dev->chip.get = rdc_gpio_get_value;
  132. rdc321x_gpio_dev->chip.set = rdc_gpio_set_value;
  133. rdc321x_gpio_dev->chip.base = 0;
  134. rdc321x_gpio_dev->chip.ngpio = pdata->max_gpios;
  135. platform_set_drvdata(pdev, rdc321x_gpio_dev);
  136. /* This might not be, what others (BIOS, bootloader, etc.)
  137. wrote to these registers before, but it's a good guess. Still
  138. better than just using 0xffffffff. */
  139. err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
  140. rdc321x_gpio_dev->reg1_data_base,
  141. &rdc321x_gpio_dev->data_reg[0]);
  142. if (err)
  143. return err;
  144. err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
  145. rdc321x_gpio_dev->reg2_data_base,
  146. &rdc321x_gpio_dev->data_reg[1]);
  147. if (err)
  148. return err;
  149. dev_info(&pdev->dev, "registering %d GPIOs\n",
  150. rdc321x_gpio_dev->chip.ngpio);
  151. return devm_gpiochip_add_data(&pdev->dev, &rdc321x_gpio_dev->chip,
  152. rdc321x_gpio_dev);
  153. }
  154. static struct platform_driver rdc321x_gpio_driver = {
  155. .driver.name = "rdc321x-gpio",
  156. .probe = rdc321x_gpio_probe,
  157. };
  158. module_platform_driver(rdc321x_gpio_driver);
  159. MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
  160. MODULE_DESCRIPTION("RDC321x GPIO driver");
  161. MODULE_LICENSE("GPL");
  162. MODULE_ALIAS("platform:rdc321x-gpio");