gpiomux.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program; if not, write to the Free Software
  14. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. * 02110-1301, USA.
  16. */
  17. #include <linux/module.h>
  18. #include <linux/spinlock.h>
  19. #include "gpiomux.h"
  20. static DEFINE_SPINLOCK(gpiomux_lock);
  21. int msm_gpiomux_write(unsigned gpio,
  22. gpiomux_config_t active,
  23. gpiomux_config_t suspended)
  24. {
  25. struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
  26. unsigned long irq_flags;
  27. gpiomux_config_t setting;
  28. if (gpio >= GPIOMUX_NGPIOS)
  29. return -EINVAL;
  30. spin_lock_irqsave(&gpiomux_lock, irq_flags);
  31. if (active & GPIOMUX_VALID)
  32. cfg->active = active;
  33. if (suspended & GPIOMUX_VALID)
  34. cfg->suspended = suspended;
  35. setting = cfg->ref ? active : suspended;
  36. if (setting & GPIOMUX_VALID)
  37. __msm_gpiomux_write(gpio, setting);
  38. spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
  39. return 0;
  40. }
  41. EXPORT_SYMBOL(msm_gpiomux_write);
  42. int msm_gpiomux_get(unsigned gpio)
  43. {
  44. struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
  45. unsigned long irq_flags;
  46. if (gpio >= GPIOMUX_NGPIOS)
  47. return -EINVAL;
  48. spin_lock_irqsave(&gpiomux_lock, irq_flags);
  49. if (cfg->ref++ == 0 && cfg->active & GPIOMUX_VALID)
  50. __msm_gpiomux_write(gpio, cfg->active);
  51. spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
  52. return 0;
  53. }
  54. EXPORT_SYMBOL(msm_gpiomux_get);
  55. int msm_gpiomux_put(unsigned gpio)
  56. {
  57. struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
  58. unsigned long irq_flags;
  59. if (gpio >= GPIOMUX_NGPIOS)
  60. return -EINVAL;
  61. spin_lock_irqsave(&gpiomux_lock, irq_flags);
  62. BUG_ON(cfg->ref == 0);
  63. if (--cfg->ref == 0 && cfg->suspended & GPIOMUX_VALID)
  64. __msm_gpiomux_write(gpio, cfg->suspended);
  65. spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
  66. return 0;
  67. }
  68. EXPORT_SYMBOL(msm_gpiomux_put);
  69. static int __init gpiomux_init(void)
  70. {
  71. unsigned n;
  72. for (n = 0; n < GPIOMUX_NGPIOS; ++n) {
  73. msm_gpiomux_configs[n].ref = 0;
  74. if (!(msm_gpiomux_configs[n].suspended & GPIOMUX_VALID))
  75. continue;
  76. __msm_gpiomux_write(n, msm_gpiomux_configs[n].suspended);
  77. }
  78. return 0;
  79. }
  80. postcore_initcall(gpiomux_init);