gpio.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /* linux/arch/arm/plat-s3c/gpio.c
  2. *
  3. * Copyright 2008 Simtec Electronics
  4. * Ben Dooks <ben@simtec.co.uk>
  5. * http://armlinux.simtec.co.uk/
  6. *
  7. * S3C series GPIO core
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/init.h>
  15. #include <linux/io.h>
  16. #include <linux/gpio.h>
  17. #include <linux/spinlock.h>
  18. #include <plat/gpio-core.h>
  19. #ifdef CONFIG_S3C_GPIO_TRACK
  20. struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
  21. static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip)
  22. {
  23. unsigned int gpn;
  24. int i;
  25. gpn = chip->chip.base;
  26. for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
  27. BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
  28. s3c_gpios[gpn] = chip;
  29. }
  30. }
  31. #endif /* CONFIG_S3C_GPIO_TRACK */
  32. /* Default routines for controlling GPIO, based on the original S3C24XX
  33. * GPIO functions which deal with the case where each gpio bank of the
  34. * chip is as following:
  35. *
  36. * base + 0x00: Control register, 2 bits per gpio
  37. * gpio n: 2 bits starting at (2*n)
  38. * 00 = input, 01 = output, others mean special-function
  39. * base + 0x04: Data register, 1 bit per gpio
  40. * bit n: data bit n
  41. */
  42. static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
  43. {
  44. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  45. void __iomem *base = ourchip->base;
  46. unsigned long flags;
  47. unsigned long con;
  48. s3c_gpio_lock(ourchip, flags);
  49. con = __raw_readl(base + 0x00);
  50. con &= ~(3 << (offset * 2));
  51. __raw_writel(con, base + 0x00);
  52. s3c_gpio_unlock(ourchip, flags);
  53. return 0;
  54. }
  55. static int s3c_gpiolib_output(struct gpio_chip *chip,
  56. unsigned offset, int value)
  57. {
  58. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  59. void __iomem *base = ourchip->base;
  60. unsigned long flags;
  61. unsigned long dat;
  62. unsigned long con;
  63. s3c_gpio_lock(ourchip, flags);
  64. dat = __raw_readl(base + 0x04);
  65. dat &= ~(1 << offset);
  66. if (value)
  67. dat |= 1 << offset;
  68. __raw_writel(dat, base + 0x04);
  69. con = __raw_readl(base + 0x00);
  70. con &= ~(3 << (offset * 2));
  71. con |= 1 << (offset * 2);
  72. __raw_writel(con, base + 0x00);
  73. __raw_writel(dat, base + 0x04);
  74. s3c_gpio_unlock(ourchip, flags);
  75. return 0;
  76. }
  77. static void s3c_gpiolib_set(struct gpio_chip *chip,
  78. unsigned offset, int value)
  79. {
  80. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  81. void __iomem *base = ourchip->base;
  82. unsigned long flags;
  83. unsigned long dat;
  84. s3c_gpio_lock(ourchip, flags);
  85. dat = __raw_readl(base + 0x04);
  86. dat &= ~(1 << offset);
  87. if (value)
  88. dat |= 1 << offset;
  89. __raw_writel(dat, base + 0x04);
  90. s3c_gpio_unlock(ourchip, flags);
  91. }
  92. static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
  93. {
  94. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  95. unsigned long val;
  96. val = __raw_readl(ourchip->base + 0x04);
  97. val >>= offset;
  98. val &= 1;
  99. return val;
  100. }
  101. __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
  102. {
  103. struct gpio_chip *gc = &chip->chip;
  104. int ret;
  105. BUG_ON(!chip->base);
  106. BUG_ON(!gc->label);
  107. BUG_ON(!gc->ngpio);
  108. spin_lock_init(&chip->lock);
  109. if (!gc->direction_input)
  110. gc->direction_input = s3c_gpiolib_input;
  111. if (!gc->direction_output)
  112. gc->direction_output = s3c_gpiolib_output;
  113. if (!gc->set)
  114. gc->set = s3c_gpiolib_set;
  115. if (!gc->get)
  116. gc->get = s3c_gpiolib_get;
  117. #ifdef CONFIG_PM
  118. if (chip->pm != NULL) {
  119. if (!chip->pm->save || !chip->pm->resume)
  120. printk(KERN_ERR "gpio: %s has missing PM functions\n",
  121. gc->label);
  122. } else
  123. printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
  124. #endif
  125. /* gpiochip_add() prints own failure message on error. */
  126. ret = gpiochip_add(gc);
  127. if (ret >= 0)
  128. s3c_gpiolib_track(chip);
  129. }
  130. int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
  131. {
  132. struct s3c_gpio_chip *s3c_chip = container_of(chip,
  133. struct s3c_gpio_chip, chip);
  134. return s3c_chip->irq_base + offset;
  135. }