gpio-loongson.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * Loongson-2F/3A/3B GPIO Support
  3. *
  4. * Copyright (c) 2008 Richard Liu, STMicroelectronics <richard.liu@st.com>
  5. * Copyright (c) 2008-2010 Arnaud Patard <apatard@mandriva.com>
  6. * Copyright (c) 2013 Hongbing Hu <huhb@lemote.com>
  7. * Copyright (c) 2014 Huacai Chen <chenhc@lemote.com>
  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 as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/init.h>
  16. #include <linux/module.h>
  17. #include <linux/spinlock.h>
  18. #include <linux/err.h>
  19. #include <asm/types.h>
  20. #include <loongson.h>
  21. #include <linux/gpio.h>
  22. #define STLS2F_N_GPIO 4
  23. #define STLS3A_N_GPIO 16
  24. #ifdef CONFIG_CPU_LOONGSON3
  25. #define LOONGSON_N_GPIO STLS3A_N_GPIO
  26. #else
  27. #define LOONGSON_N_GPIO STLS2F_N_GPIO
  28. #endif
  29. #define LOONGSON_GPIO_IN_OFFSET 16
  30. static DEFINE_SPINLOCK(gpio_lock);
  31. static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
  32. {
  33. u32 temp;
  34. u32 mask;
  35. spin_lock(&gpio_lock);
  36. mask = 1 << gpio;
  37. temp = LOONGSON_GPIOIE;
  38. temp |= mask;
  39. LOONGSON_GPIOIE = temp;
  40. spin_unlock(&gpio_lock);
  41. return 0;
  42. }
  43. static int loongson_gpio_direction_output(struct gpio_chip *chip,
  44. unsigned gpio, int level)
  45. {
  46. u32 temp;
  47. u32 mask;
  48. gpio_set_value(gpio, level);
  49. spin_lock(&gpio_lock);
  50. mask = 1 << gpio;
  51. temp = LOONGSON_GPIOIE;
  52. temp &= (~mask);
  53. LOONGSON_GPIOIE = temp;
  54. spin_unlock(&gpio_lock);
  55. return 0;
  56. }
  57. static int loongson_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
  58. {
  59. u32 val;
  60. u32 mask;
  61. mask = 1 << (gpio + LOONGSON_GPIO_IN_OFFSET);
  62. spin_lock(&gpio_lock);
  63. val = LOONGSON_GPIODATA;
  64. spin_unlock(&gpio_lock);
  65. return (val & mask) != 0;
  66. }
  67. static void loongson_gpio_set_value(struct gpio_chip *chip,
  68. unsigned gpio, int value)
  69. {
  70. u32 val;
  71. u32 mask;
  72. mask = 1 << gpio;
  73. spin_lock(&gpio_lock);
  74. val = LOONGSON_GPIODATA;
  75. if (value)
  76. val |= mask;
  77. else
  78. val &= (~mask);
  79. LOONGSON_GPIODATA = val;
  80. spin_unlock(&gpio_lock);
  81. }
  82. static struct gpio_chip loongson_chip = {
  83. .label = "Loongson-gpio-chip",
  84. .direction_input = loongson_gpio_direction_input,
  85. .get = loongson_gpio_get_value,
  86. .direction_output = loongson_gpio_direction_output,
  87. .set = loongson_gpio_set_value,
  88. .base = 0,
  89. .ngpio = LOONGSON_N_GPIO,
  90. .can_sleep = false,
  91. };
  92. static int __init loongson_gpio_setup(void)
  93. {
  94. return gpiochip_add_data(&loongson_chip, NULL);
  95. }
  96. postcore_initcall(loongson_gpio_setup);