mfp.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * linux/arch/arm/mach-pxa/mfp.c
  3. *
  4. * PXA3xx Multi-Function Pin Support
  5. *
  6. * Copyright (C) 2007 Marvell Internation Ltd.
  7. *
  8. * 2007-08-21: eric miao <eric.y.miao@gmail.com>
  9. * initial version
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License version 2 as
  13. * published by the Free Software Foundation.
  14. */
  15. #include <linux/module.h>
  16. #include <linux/kernel.h>
  17. #include <linux/init.h>
  18. #include <linux/io.h>
  19. #include <asm/hardware.h>
  20. #include <asm/arch/mfp.h>
  21. /* mfp_spin_lock is used to ensure that MFP register configuration
  22. * (most likely a read-modify-write operation) is atomic, and that
  23. * mfp_table[] is consistent
  24. */
  25. static DEFINE_SPINLOCK(mfp_spin_lock);
  26. static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
  27. static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];
  28. #define mfpr_readl(off) \
  29. __raw_readl(mfpr_mmio_base + (off))
  30. #define mfpr_writel(off, val) \
  31. __raw_writel(val, mfpr_mmio_base + (off))
  32. /*
  33. * perform a read-back of any MFPR register to make sure the
  34. * previous writings are finished
  35. */
  36. #define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0)
  37. static inline void __mfp_config(int pin, unsigned long val)
  38. {
  39. unsigned long off = mfp_table[pin].mfpr_off;
  40. mfp_table[pin].mfpr_val = val;
  41. mfpr_writel(off, val);
  42. }
  43. void pxa3xx_mfp_config(mfp_cfg_t *mfp_cfgs, int num)
  44. {
  45. int i, pin;
  46. unsigned long val, flags;
  47. mfp_cfg_t *mfp_cfg = mfp_cfgs;
  48. spin_lock_irqsave(&mfp_spin_lock, flags);
  49. for (i = 0; i < num; i++, mfp_cfg++) {
  50. pin = MFP_CFG_PIN(*mfp_cfg);
  51. val = MFP_CFG_VAL(*mfp_cfg);
  52. BUG_ON(pin >= MFP_PIN_MAX);
  53. __mfp_config(pin, val);
  54. }
  55. mfpr_sync();
  56. spin_unlock_irqrestore(&mfp_spin_lock, flags);
  57. }
  58. unsigned long pxa3xx_mfp_read(int mfp)
  59. {
  60. unsigned long val, flags;
  61. BUG_ON(mfp >= MFP_PIN_MAX);
  62. spin_lock_irqsave(&mfp_spin_lock, flags);
  63. val = mfpr_readl(mfp_table[mfp].mfpr_off);
  64. spin_unlock_irqrestore(&mfp_spin_lock, flags);
  65. return val;
  66. }
  67. void pxa3xx_mfp_write(int mfp, unsigned long val)
  68. {
  69. unsigned long flags;
  70. BUG_ON(mfp >= MFP_PIN_MAX);
  71. spin_lock_irqsave(&mfp_spin_lock, flags);
  72. mfpr_writel(mfp_table[mfp].mfpr_off, val);
  73. mfpr_sync();
  74. spin_unlock_irqrestore(&mfp_spin_lock, flags);
  75. }
  76. void pxa3xx_mfp_set_afds(int mfp, int af, int ds)
  77. {
  78. uint32_t mfpr_off, mfpr_val;
  79. unsigned long flags;
  80. BUG_ON(mfp >= MFP_PIN_MAX);
  81. spin_lock_irqsave(&mfp_spin_lock, flags);
  82. mfpr_off = mfp_table[mfp].mfpr_off;
  83. mfpr_val = mfpr_readl(mfpr_off);
  84. mfpr_val &= ~(MFPR_AF_MASK | MFPR_DRV_MASK);
  85. mfpr_val |= (((af & 0x7) << MFPR_ALT_OFFSET) |
  86. ((ds & 0x7) << MFPR_DRV_OFFSET));
  87. mfpr_writel(mfpr_off, mfpr_val);
  88. mfpr_sync();
  89. spin_unlock_irqrestore(&mfp_spin_lock, flags);
  90. }
  91. void pxa3xx_mfp_set_rdh(int mfp, int rdh)
  92. {
  93. uint32_t mfpr_off, mfpr_val;
  94. unsigned long flags;
  95. BUG_ON(mfp >= MFP_PIN_MAX);
  96. spin_lock_irqsave(&mfp_spin_lock, flags);
  97. mfpr_off = mfp_table[mfp].mfpr_off;
  98. mfpr_val = mfpr_readl(mfpr_off);
  99. mfpr_val &= ~MFPR_RDH_MASK;
  100. if (likely(rdh))
  101. mfpr_val |= (1u << MFPR_SS_OFFSET);
  102. mfpr_writel(mfpr_off, mfpr_val);
  103. mfpr_sync();
  104. spin_unlock_irqrestore(&mfp_spin_lock, flags);
  105. }
  106. void pxa3xx_mfp_set_lpm(int mfp, int lpm)
  107. {
  108. uint32_t mfpr_off, mfpr_val;
  109. unsigned long flags;
  110. BUG_ON(mfp >= MFP_PIN_MAX);
  111. spin_lock_irqsave(&mfp_spin_lock, flags);
  112. mfpr_off = mfp_table[mfp].mfpr_off;
  113. mfpr_val = mfpr_readl(mfpr_off);
  114. mfpr_val &= ~MFPR_LPM_MASK;
  115. if (lpm & 0x1) mfpr_val |= 1u << MFPR_SON_OFFSET;
  116. if (lpm & 0x2) mfpr_val |= 1u << MFPR_SD_OFFSET;
  117. if (lpm & 0x4) mfpr_val |= 1u << MFPR_PU_OFFSET;
  118. if (lpm & 0x8) mfpr_val |= 1u << MFPR_PD_OFFSET;
  119. if (lpm &0x10) mfpr_val |= 1u << MFPR_PS_OFFSET;
  120. mfpr_writel(mfpr_off, mfpr_val);
  121. mfpr_sync();
  122. spin_unlock_irqrestore(&mfp_spin_lock, flags);
  123. }
  124. void pxa3xx_mfp_set_pull(int mfp, int pull)
  125. {
  126. uint32_t mfpr_off, mfpr_val;
  127. unsigned long flags;
  128. BUG_ON(mfp >= MFP_PIN_MAX);
  129. spin_lock_irqsave(&mfp_spin_lock, flags);
  130. mfpr_off = mfp_table[mfp].mfpr_off;
  131. mfpr_val = mfpr_readl(mfpr_off);
  132. mfpr_val &= ~MFPR_PULL_MASK;
  133. mfpr_val |= ((pull & 0x7u) << MFPR_PD_OFFSET);
  134. mfpr_writel(mfpr_off, mfpr_val);
  135. mfpr_sync();
  136. spin_unlock_irqrestore(&mfp_spin_lock, flags);
  137. }
  138. void pxa3xx_mfp_set_edge(int mfp, int edge)
  139. {
  140. uint32_t mfpr_off, mfpr_val;
  141. unsigned long flags;
  142. BUG_ON(mfp >= MFP_PIN_MAX);
  143. spin_lock_irqsave(&mfp_spin_lock, flags);
  144. mfpr_off = mfp_table[mfp].mfpr_off;
  145. mfpr_val = mfpr_readl(mfpr_off);
  146. mfpr_val &= ~MFPR_EDGE_MASK;
  147. mfpr_val |= (edge & 0x3u) << MFPR_ERE_OFFSET;
  148. mfpr_val |= (!edge & 0x1) << MFPR_EC_OFFSET;
  149. mfpr_writel(mfpr_off, mfpr_val);
  150. mfpr_sync();
  151. spin_unlock_irqrestore(&mfp_spin_lock, flags);
  152. }
  153. void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map)
  154. {
  155. struct pxa3xx_mfp_addr_map *p;
  156. unsigned long offset, flags;
  157. int i;
  158. spin_lock_irqsave(&mfp_spin_lock, flags);
  159. for (p = map; p->start != MFP_PIN_INVALID; p++) {
  160. offset = p->offset;
  161. i = p->start;
  162. do {
  163. mfp_table[i].mfpr_off = offset;
  164. mfp_table[i].mfpr_val = 0;
  165. offset += 4; i++;
  166. } while ((i <= p->end) && (p->end != -1));
  167. }
  168. spin_unlock_irqrestore(&mfp_spin_lock, flags);
  169. }
  170. void __init pxa3xx_init_mfp(void)
  171. {
  172. memset(mfp_table, 0, sizeof(mfp_table));
  173. }