padmux.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. *
  3. * arch/arm/mach-u300/padmux.c
  4. *
  5. *
  6. * Copyright (C) 2009 ST-Ericsson AB
  7. * License terms: GNU General Public License (GPL) version 2
  8. * U300 PADMUX functions
  9. * Author: Martin Persson <martin.persson@stericsson.com>
  10. */
  11. #include <linux/module.h>
  12. #include <linux/kernel.h>
  13. #include <linux/device.h>
  14. #include <linux/err.h>
  15. #include <linux/errno.h>
  16. #include <linux/io.h>
  17. #include <linux/mutex.h>
  18. #include <linux/string.h>
  19. #include <linux/bug.h>
  20. #include <linux/debugfs.h>
  21. #include <linux/seq_file.h>
  22. #include <mach/u300-regs.h>
  23. #include <mach/syscon.h>
  24. #include "padmux.h"
  25. static DEFINE_MUTEX(pmx_mutex);
  26. const u32 pmx_registers[] = {
  27. (U300_SYSCON_VBASE + U300_SYSCON_PMC1LR),
  28. (U300_SYSCON_VBASE + U300_SYSCON_PMC1HR),
  29. (U300_SYSCON_VBASE + U300_SYSCON_PMC2R),
  30. (U300_SYSCON_VBASE + U300_SYSCON_PMC3R),
  31. (U300_SYSCON_VBASE + U300_SYSCON_PMC4R)
  32. };
  33. /* High level functionality */
  34. /* Lazy dog:
  35. * onmask = {
  36. * {"PMC1LR" mask, "PMC1LR" value},
  37. * {"PMC1HR" mask, "PMC1HR" value},
  38. * {"PMC2R" mask, "PMC2R" value},
  39. * {"PMC3R" mask, "PMC3R" value},
  40. * {"PMC4R" mask, "PMC4R" value}
  41. * }
  42. */
  43. static struct pmx mmc_setting = {
  44. .setting = U300_APP_PMX_MMC_SETTING,
  45. .default_on = false,
  46. .activated = false,
  47. .name = "MMC",
  48. .onmask = {
  49. {U300_SYSCON_PMC1LR_MMCSD_MASK,
  50. U300_SYSCON_PMC1LR_MMCSD_MMCSD},
  51. {0, 0},
  52. {0, 0},
  53. {0, 0},
  54. {U300_SYSCON_PMC4R_APP_MISC_12_MASK,
  55. U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO}
  56. },
  57. };
  58. static struct pmx spi_setting = {
  59. .setting = U300_APP_PMX_SPI_SETTING,
  60. .default_on = false,
  61. .activated = false,
  62. .name = "SPI",
  63. .onmask = {{0, 0},
  64. {U300_SYSCON_PMC1HR_APP_SPI_2_MASK |
  65. U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK |
  66. U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK,
  67. U300_SYSCON_PMC1HR_APP_SPI_2_SPI |
  68. U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI |
  69. U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI},
  70. {0, 0},
  71. {0, 0},
  72. {0, 0}
  73. },
  74. };
  75. /* Available padmux settings */
  76. static struct pmx *pmx_settings[] = {
  77. &mmc_setting,
  78. &spi_setting,
  79. };
  80. static void update_registers(struct pmx *pmx, bool activate)
  81. {
  82. u16 regval, val, mask;
  83. int i;
  84. for (i = 0; i < ARRAY_SIZE(pmx_registers); i++) {
  85. if (activate)
  86. val = pmx->onmask[i].val;
  87. else
  88. val = 0;
  89. mask = pmx->onmask[i].mask;
  90. if (mask != 0) {
  91. regval = readw(pmx_registers[i]);
  92. regval &= ~mask;
  93. regval |= val;
  94. writew(regval, pmx_registers[i]);
  95. }
  96. }
  97. }
  98. struct pmx *pmx_get(struct device *dev, enum pmx_settings setting)
  99. {
  100. int i;
  101. struct pmx *pmx = ERR_PTR(-ENOENT);
  102. if (dev == NULL)
  103. return ERR_PTR(-EINVAL);
  104. mutex_lock(&pmx_mutex);
  105. for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
  106. if (setting == pmx_settings[i]->setting) {
  107. if (pmx_settings[i]->dev != NULL) {
  108. WARN(1, "padmux: required setting "
  109. "in use by another consumer\n");
  110. } else {
  111. pmx = pmx_settings[i];
  112. pmx->dev = dev;
  113. dev_dbg(dev, "padmux: setting nr %d is now "
  114. "bound to %s and ready to use\n",
  115. setting, dev_name(dev));
  116. break;
  117. }
  118. }
  119. }
  120. mutex_unlock(&pmx_mutex);
  121. return pmx;
  122. }
  123. EXPORT_SYMBOL(pmx_get);
  124. int pmx_put(struct device *dev, struct pmx *pmx)
  125. {
  126. int i;
  127. int ret = -ENOENT;
  128. if (pmx == NULL || dev == NULL)
  129. return -EINVAL;
  130. mutex_lock(&pmx_mutex);
  131. for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
  132. if (pmx->setting == pmx_settings[i]->setting) {
  133. if (dev != pmx->dev) {
  134. WARN(1, "padmux: cannot release handle as "
  135. "it is bound to another consumer\n");
  136. ret = -EINVAL;
  137. break;
  138. } else {
  139. pmx_settings[i]->dev = NULL;
  140. ret = 0;
  141. break;
  142. }
  143. }
  144. }
  145. mutex_unlock(&pmx_mutex);
  146. return ret;
  147. }
  148. EXPORT_SYMBOL(pmx_put);
  149. int pmx_activate(struct device *dev, struct pmx *pmx)
  150. {
  151. int i, j, ret;
  152. ret = 0;
  153. if (pmx == NULL || dev == NULL)
  154. return -EINVAL;
  155. mutex_lock(&pmx_mutex);
  156. /* Make sure the required bits are not used */
  157. for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
  158. if (pmx_settings[i]->dev == NULL || pmx_settings[i] == pmx)
  159. continue;
  160. for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) {
  161. if (pmx_settings[i]->onmask[j].mask & pmx->
  162. onmask[j].mask) {
  163. /* More than one entry on the same bits */
  164. WARN(1, "padmux: cannot activate "
  165. "setting. Bit conflict with "
  166. "an active setting\n");
  167. ret = -EUSERS;
  168. goto exit;
  169. }
  170. }
  171. }
  172. update_registers(pmx, true);
  173. pmx->activated = true;
  174. dev_dbg(dev, "padmux: setting nr %d is activated\n",
  175. pmx->setting);
  176. exit:
  177. mutex_unlock(&pmx_mutex);
  178. return ret;
  179. }
  180. EXPORT_SYMBOL(pmx_activate);
  181. int pmx_deactivate(struct device *dev, struct pmx *pmx)
  182. {
  183. int i;
  184. int ret = -ENOENT;
  185. if (pmx == NULL || dev == NULL)
  186. return -EINVAL;
  187. mutex_lock(&pmx_mutex);
  188. for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
  189. if (pmx_settings[i]->dev == NULL)
  190. continue;
  191. if (pmx->setting == pmx_settings[i]->setting) {
  192. if (dev != pmx->dev) {
  193. WARN(1, "padmux: cannot deactivate "
  194. "pmx setting as it was activated "
  195. "by another consumer\n");
  196. ret = -EBUSY;
  197. continue;
  198. } else {
  199. update_registers(pmx, false);
  200. pmx_settings[i]->dev = NULL;
  201. pmx->activated = false;
  202. ret = 0;
  203. dev_dbg(dev, "padmux: setting nr %d is deactivated",
  204. pmx->setting);
  205. break;
  206. }
  207. }
  208. }
  209. mutex_unlock(&pmx_mutex);
  210. return ret;
  211. }
  212. EXPORT_SYMBOL(pmx_deactivate);
  213. /*
  214. * For internal use only. If it is to be exported,
  215. * it should be reentrant. Notice that pmx_activate
  216. * (i.e. runtime settings) always override default settings.
  217. */
  218. static int pmx_set_default(void)
  219. {
  220. /* Used to identify several entries on the same bits */
  221. u16 modbits[ARRAY_SIZE(pmx_registers)];
  222. int i, j;
  223. memset(modbits, 0, ARRAY_SIZE(pmx_registers) * sizeof(u16));
  224. for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
  225. if (!pmx_settings[i]->default_on)
  226. continue;
  227. for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) {
  228. /* Make sure there is only one entry on the same bits */
  229. if (modbits[j] & pmx_settings[i]->onmask[j].mask) {
  230. BUG();
  231. return -EUSERS;
  232. }
  233. modbits[j] |= pmx_settings[i]->onmask[j].mask;
  234. }
  235. update_registers(pmx_settings[i], true);
  236. }
  237. return 0;
  238. }
  239. #if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG))
  240. static int pmx_show(struct seq_file *s, void *data)
  241. {
  242. int i;
  243. seq_printf(s, "-------------------------------------------------\n");
  244. seq_printf(s, "SETTING BOUND TO DEVICE STATE\n");
  245. seq_printf(s, "-------------------------------------------------\n");
  246. mutex_lock(&pmx_mutex);
  247. for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
  248. /* Format pmx and device name nicely */
  249. char cdp[33];
  250. int chars;
  251. chars = snprintf(&cdp[0], 17, "%s", pmx_settings[i]->name);
  252. while (chars < 16) {
  253. cdp[chars] = ' ';
  254. chars++;
  255. }
  256. chars = snprintf(&cdp[16], 17, "%s", pmx_settings[i]->dev ?
  257. dev_name(pmx_settings[i]->dev) : "N/A");
  258. while (chars < 16) {
  259. cdp[chars+16] = ' ';
  260. chars++;
  261. }
  262. cdp[32] = '\0';
  263. seq_printf(s,
  264. "%s\t%s\n",
  265. &cdp[0],
  266. pmx_settings[i]->activated ?
  267. "ACTIVATED" : "DEACTIVATED"
  268. );
  269. }
  270. mutex_unlock(&pmx_mutex);
  271. return 0;
  272. }
  273. static int pmx_open(struct inode *inode, struct file *file)
  274. {
  275. return single_open(file, pmx_show, NULL);
  276. }
  277. static const struct file_operations pmx_operations = {
  278. .owner = THIS_MODULE,
  279. .open = pmx_open,
  280. .read = seq_read,
  281. .llseek = seq_lseek,
  282. .release = single_release,
  283. };
  284. static int __init init_pmx_read_debugfs(void)
  285. {
  286. /* Expose a simple debugfs interface to view pmx settings */
  287. (void) debugfs_create_file("padmux", S_IFREG | S_IRUGO,
  288. NULL, NULL,
  289. &pmx_operations);
  290. return 0;
  291. }
  292. /*
  293. * This needs to come in after the core_initcall(),
  294. * because debugfs is not available until
  295. * the subsystems come up.
  296. */
  297. module_init(init_pmx_read_debugfs);
  298. #endif
  299. static int __init pmx_init(void)
  300. {
  301. int ret;
  302. ret = pmx_set_default();
  303. if (IS_ERR_VALUE(ret))
  304. pr_crit("padmux: default settings could not be set\n");
  305. return 0;
  306. }
  307. /* Should be initialized before consumers */
  308. core_initcall(pmx_init);