mux.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. /*
  2. * linux/arch/arm/mach-omap2/mux.c
  3. *
  4. * OMAP2, OMAP3 and OMAP4 pin multiplexing configurations
  5. *
  6. * Copyright (C) 2004 - 2010 Texas Instruments Inc.
  7. * Copyright (C) 2003 - 2008 Nokia Corporation
  8. *
  9. * Written by Tony Lindgren
  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 as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  24. *
  25. */
  26. #include <linux/kernel.h>
  27. #include <linux/init.h>
  28. #include <linux/io.h>
  29. #include <linux/list.h>
  30. #include <linux/slab.h>
  31. #include <linux/ctype.h>
  32. #include <linux/debugfs.h>
  33. #include <linux/seq_file.h>
  34. #include <linux/uaccess.h>
  35. #include <asm/system.h>
  36. #include "control.h"
  37. #include "mux.h"
  38. #define OMAP_MUX_BASE_OFFSET 0x30 /* Offset from CTRL_BASE */
  39. #define OMAP_MUX_BASE_SZ 0x5ca
  40. struct omap_mux_entry {
  41. struct omap_mux mux;
  42. struct list_head node;
  43. };
  44. static LIST_HEAD(mux_partitions);
  45. static DEFINE_MUTEX(muxmode_mutex);
  46. struct omap_mux_partition *omap_mux_get(const char *name)
  47. {
  48. struct omap_mux_partition *partition;
  49. list_for_each_entry(partition, &mux_partitions, node) {
  50. if (!strcmp(name, partition->name))
  51. return partition;
  52. }
  53. return NULL;
  54. }
  55. u16 omap_mux_read(struct omap_mux_partition *partition, u16 reg)
  56. {
  57. if (partition->flags & OMAP_MUX_REG_8BIT)
  58. return __raw_readb(partition->base + reg);
  59. else
  60. return __raw_readw(partition->base + reg);
  61. }
  62. void omap_mux_write(struct omap_mux_partition *partition, u16 val,
  63. u16 reg)
  64. {
  65. if (partition->flags & OMAP_MUX_REG_8BIT)
  66. __raw_writeb(val, partition->base + reg);
  67. else
  68. __raw_writew(val, partition->base + reg);
  69. }
  70. void omap_mux_write_array(struct omap_mux_partition *partition,
  71. struct omap_board_mux *board_mux)
  72. {
  73. while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) {
  74. omap_mux_write(partition, board_mux->value,
  75. board_mux->reg_offset);
  76. board_mux++;
  77. }
  78. }
  79. #ifdef CONFIG_OMAP_MUX
  80. static char *omap_mux_options;
  81. static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
  82. int gpio, int val)
  83. {
  84. struct omap_mux_entry *e;
  85. struct omap_mux *gpio_mux = NULL;
  86. u16 old_mode;
  87. u16 mux_mode;
  88. int found = 0;
  89. struct list_head *muxmodes = &partition->muxmodes;
  90. if (!gpio)
  91. return -EINVAL;
  92. list_for_each_entry(e, muxmodes, node) {
  93. struct omap_mux *m = &e->mux;
  94. if (gpio == m->gpio) {
  95. gpio_mux = m;
  96. found++;
  97. }
  98. }
  99. if (found == 0) {
  100. pr_err("%s: Could not set gpio%i\n", __func__, gpio);
  101. return -ENODEV;
  102. }
  103. if (found > 1) {
  104. pr_info("%s: Multiple gpio paths (%d) for gpio%i\n", __func__,
  105. found, gpio);
  106. return -EINVAL;
  107. }
  108. old_mode = omap_mux_read(partition, gpio_mux->reg_offset);
  109. mux_mode = val & ~(OMAP_MUX_NR_MODES - 1);
  110. if (partition->flags & OMAP_MUX_GPIO_IN_MODE3)
  111. mux_mode |= OMAP_MUX_MODE3;
  112. else
  113. mux_mode |= OMAP_MUX_MODE4;
  114. pr_debug("%s: Setting signal %s.gpio%i 0x%04x -> 0x%04x\n", __func__,
  115. gpio_mux->muxnames[0], gpio, old_mode, mux_mode);
  116. omap_mux_write(partition, mux_mode, gpio_mux->reg_offset);
  117. return 0;
  118. }
  119. int __init omap_mux_init_gpio(int gpio, int val)
  120. {
  121. struct omap_mux_partition *partition;
  122. int ret;
  123. list_for_each_entry(partition, &mux_partitions, node) {
  124. ret = _omap_mux_init_gpio(partition, gpio, val);
  125. if (!ret)
  126. return ret;
  127. }
  128. return -ENODEV;
  129. }
  130. static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
  131. const char *muxname,
  132. struct omap_mux **found_mux)
  133. {
  134. struct omap_mux *mux = NULL;
  135. struct omap_mux_entry *e;
  136. const char *mode_name;
  137. int found = 0, found_mode, mode0_len = 0;
  138. struct list_head *muxmodes = &partition->muxmodes;
  139. mode_name = strchr(muxname, '.');
  140. if (mode_name) {
  141. mode0_len = strlen(muxname) - strlen(mode_name);
  142. mode_name++;
  143. } else {
  144. mode_name = muxname;
  145. }
  146. list_for_each_entry(e, muxmodes, node) {
  147. char *m0_entry;
  148. int i;
  149. mux = &e->mux;
  150. m0_entry = mux->muxnames[0];
  151. /* First check for full name in mode0.muxmode format */
  152. if (mode0_len && strncmp(muxname, m0_entry, mode0_len))
  153. continue;
  154. /* Then check for muxmode only */
  155. for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
  156. char *mode_cur = mux->muxnames[i];
  157. if (!mode_cur)
  158. continue;
  159. if (!strcmp(mode_name, mode_cur)) {
  160. *found_mux = mux;
  161. found++;
  162. found_mode = i;
  163. }
  164. }
  165. }
  166. if (found == 1) {
  167. return found_mode;
  168. }
  169. if (found > 1) {
  170. pr_err("%s: Multiple signal paths (%i) for %s\n", __func__,
  171. found, muxname);
  172. return -EINVAL;
  173. }
  174. pr_err("%s: Could not find signal %s\n", __func__, muxname);
  175. return -ENODEV;
  176. }
  177. static int __init
  178. omap_mux_get_by_name(const char *muxname,
  179. struct omap_mux_partition **found_partition,
  180. struct omap_mux **found_mux)
  181. {
  182. struct omap_mux_partition *partition;
  183. list_for_each_entry(partition, &mux_partitions, node) {
  184. struct omap_mux *mux = NULL;
  185. int mux_mode = _omap_mux_get_by_name(partition, muxname, &mux);
  186. if (mux_mode < 0)
  187. continue;
  188. *found_partition = partition;
  189. *found_mux = mux;
  190. return mux_mode;
  191. }
  192. return -ENODEV;
  193. }
  194. int __init omap_mux_init_signal(const char *muxname, int val)
  195. {
  196. struct omap_mux_partition *partition = NULL;
  197. struct omap_mux *mux = NULL;
  198. u16 old_mode;
  199. int mux_mode;
  200. mux_mode = omap_mux_get_by_name(muxname, &partition, &mux);
  201. if (mux_mode < 0)
  202. return mux_mode;
  203. old_mode = omap_mux_read(partition, mux->reg_offset);
  204. mux_mode |= val;
  205. pr_debug("%s: Setting signal %s 0x%04x -> 0x%04x\n",
  206. __func__, muxname, old_mode, mux_mode);
  207. omap_mux_write(partition, mux_mode, mux->reg_offset);
  208. return 0;
  209. }
  210. #ifdef CONFIG_DEBUG_FS
  211. #define OMAP_MUX_MAX_NR_FLAGS 10
  212. #define OMAP_MUX_TEST_FLAG(val, mask) \
  213. if (((val) & (mask)) == (mask)) { \
  214. i++; \
  215. flags[i] = #mask; \
  216. }
  217. /* REVISIT: Add checking for non-optimal mux settings */
  218. static inline void omap_mux_decode(struct seq_file *s, u16 val)
  219. {
  220. char *flags[OMAP_MUX_MAX_NR_FLAGS];
  221. char mode[sizeof("OMAP_MUX_MODE") + 1];
  222. int i = -1;
  223. sprintf(mode, "OMAP_MUX_MODE%d", val & 0x7);
  224. i++;
  225. flags[i] = mode;
  226. OMAP_MUX_TEST_FLAG(val, OMAP_PIN_OFF_WAKEUPENABLE);
  227. if (val & OMAP_OFF_EN) {
  228. if (!(val & OMAP_OFFOUT_EN)) {
  229. if (!(val & OMAP_OFF_PULL_UP)) {
  230. OMAP_MUX_TEST_FLAG(val,
  231. OMAP_PIN_OFF_INPUT_PULLDOWN);
  232. } else {
  233. OMAP_MUX_TEST_FLAG(val,
  234. OMAP_PIN_OFF_INPUT_PULLUP);
  235. }
  236. } else {
  237. if (!(val & OMAP_OFFOUT_VAL)) {
  238. OMAP_MUX_TEST_FLAG(val,
  239. OMAP_PIN_OFF_OUTPUT_LOW);
  240. } else {
  241. OMAP_MUX_TEST_FLAG(val,
  242. OMAP_PIN_OFF_OUTPUT_HIGH);
  243. }
  244. }
  245. }
  246. if (val & OMAP_INPUT_EN) {
  247. if (val & OMAP_PULL_ENA) {
  248. if (!(val & OMAP_PULL_UP)) {
  249. OMAP_MUX_TEST_FLAG(val,
  250. OMAP_PIN_INPUT_PULLDOWN);
  251. } else {
  252. OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT_PULLUP);
  253. }
  254. } else {
  255. OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT);
  256. }
  257. } else {
  258. i++;
  259. flags[i] = "OMAP_PIN_OUTPUT";
  260. }
  261. do {
  262. seq_printf(s, "%s", flags[i]);
  263. if (i > 0)
  264. seq_printf(s, " | ");
  265. } while (i-- > 0);
  266. }
  267. #define OMAP_MUX_DEFNAME_LEN 32
  268. static int omap_mux_dbg_board_show(struct seq_file *s, void *unused)
  269. {
  270. struct omap_mux_partition *partition = s->private;
  271. struct omap_mux_entry *e;
  272. u8 omap_gen = omap_rev() >> 28;
  273. list_for_each_entry(e, &partition->muxmodes, node) {
  274. struct omap_mux *m = &e->mux;
  275. char m0_def[OMAP_MUX_DEFNAME_LEN];
  276. char *m0_name = m->muxnames[0];
  277. u16 val;
  278. int i, mode;
  279. if (!m0_name)
  280. continue;
  281. /* REVISIT: Needs to be updated if mode0 names get longer */
  282. for (i = 0; i < OMAP_MUX_DEFNAME_LEN; i++) {
  283. if (m0_name[i] == '\0') {
  284. m0_def[i] = m0_name[i];
  285. break;
  286. }
  287. m0_def[i] = toupper(m0_name[i]);
  288. }
  289. val = omap_mux_read(partition, m->reg_offset);
  290. mode = val & OMAP_MUX_MODE7;
  291. if (mode != 0)
  292. seq_printf(s, "/* %s */\n", m->muxnames[mode]);
  293. /*
  294. * XXX: Might be revisited to support differences accross
  295. * same OMAP generation.
  296. */
  297. seq_printf(s, "OMAP%d_MUX(%s, ", omap_gen, m0_def);
  298. omap_mux_decode(s, val);
  299. seq_printf(s, "),\n");
  300. }
  301. return 0;
  302. }
  303. static int omap_mux_dbg_board_open(struct inode *inode, struct file *file)
  304. {
  305. return single_open(file, omap_mux_dbg_board_show, inode->i_private);
  306. }
  307. static const struct file_operations omap_mux_dbg_board_fops = {
  308. .open = omap_mux_dbg_board_open,
  309. .read = seq_read,
  310. .llseek = seq_lseek,
  311. .release = single_release,
  312. };
  313. static struct omap_mux_partition *omap_mux_get_partition(struct omap_mux *mux)
  314. {
  315. struct omap_mux_partition *partition;
  316. list_for_each_entry(partition, &mux_partitions, node) {
  317. struct list_head *muxmodes = &partition->muxmodes;
  318. struct omap_mux_entry *e;
  319. list_for_each_entry(e, muxmodes, node) {
  320. struct omap_mux *m = &e->mux;
  321. if (m == mux)
  322. return partition;
  323. }
  324. }
  325. return NULL;
  326. }
  327. static int omap_mux_dbg_signal_show(struct seq_file *s, void *unused)
  328. {
  329. struct omap_mux *m = s->private;
  330. struct omap_mux_partition *partition;
  331. const char *none = "NA";
  332. u16 val;
  333. int mode;
  334. partition = omap_mux_get_partition(m);
  335. if (!partition)
  336. return 0;
  337. val = omap_mux_read(partition, m->reg_offset);
  338. mode = val & OMAP_MUX_MODE7;
  339. seq_printf(s, "name: %s.%s (0x%08x/0x%03x = 0x%04x), b %s, t %s\n",
  340. m->muxnames[0], m->muxnames[mode],
  341. partition->phys + m->reg_offset, m->reg_offset, val,
  342. m->balls[0] ? m->balls[0] : none,
  343. m->balls[1] ? m->balls[1] : none);
  344. seq_printf(s, "mode: ");
  345. omap_mux_decode(s, val);
  346. seq_printf(s, "\n");
  347. seq_printf(s, "signals: %s | %s | %s | %s | %s | %s | %s | %s\n",
  348. m->muxnames[0] ? m->muxnames[0] : none,
  349. m->muxnames[1] ? m->muxnames[1] : none,
  350. m->muxnames[2] ? m->muxnames[2] : none,
  351. m->muxnames[3] ? m->muxnames[3] : none,
  352. m->muxnames[4] ? m->muxnames[4] : none,
  353. m->muxnames[5] ? m->muxnames[5] : none,
  354. m->muxnames[6] ? m->muxnames[6] : none,
  355. m->muxnames[7] ? m->muxnames[7] : none);
  356. return 0;
  357. }
  358. #define OMAP_MUX_MAX_ARG_CHAR 7
  359. static ssize_t omap_mux_dbg_signal_write(struct file *file,
  360. const char __user *user_buf,
  361. size_t count, loff_t *ppos)
  362. {
  363. char buf[OMAP_MUX_MAX_ARG_CHAR];
  364. struct seq_file *seqf;
  365. struct omap_mux *m;
  366. unsigned long val;
  367. int buf_size, ret;
  368. struct omap_mux_partition *partition;
  369. if (count > OMAP_MUX_MAX_ARG_CHAR)
  370. return -EINVAL;
  371. memset(buf, 0, sizeof(buf));
  372. buf_size = min(count, sizeof(buf) - 1);
  373. if (copy_from_user(buf, user_buf, buf_size))
  374. return -EFAULT;
  375. ret = strict_strtoul(buf, 0x10, &val);
  376. if (ret < 0)
  377. return ret;
  378. if (val > 0xffff)
  379. return -EINVAL;
  380. seqf = file->private_data;
  381. m = seqf->private;
  382. partition = omap_mux_get_partition(m);
  383. if (!partition)
  384. return -ENODEV;
  385. omap_mux_write(partition, (u16)val, m->reg_offset);
  386. *ppos += count;
  387. return count;
  388. }
  389. static int omap_mux_dbg_signal_open(struct inode *inode, struct file *file)
  390. {
  391. return single_open(file, omap_mux_dbg_signal_show, inode->i_private);
  392. }
  393. static const struct file_operations omap_mux_dbg_signal_fops = {
  394. .open = omap_mux_dbg_signal_open,
  395. .read = seq_read,
  396. .write = omap_mux_dbg_signal_write,
  397. .llseek = seq_lseek,
  398. .release = single_release,
  399. };
  400. static struct dentry *mux_dbg_dir;
  401. static void __init omap_mux_dbg_create_entry(
  402. struct omap_mux_partition *partition,
  403. struct dentry *mux_dbg_dir)
  404. {
  405. struct omap_mux_entry *e;
  406. list_for_each_entry(e, &partition->muxmodes, node) {
  407. struct omap_mux *m = &e->mux;
  408. (void)debugfs_create_file(m->muxnames[0], S_IWUGO, mux_dbg_dir,
  409. m, &omap_mux_dbg_signal_fops);
  410. }
  411. }
  412. static void __init omap_mux_dbg_init(void)
  413. {
  414. struct omap_mux_partition *partition;
  415. static struct dentry *mux_dbg_board_dir;
  416. mux_dbg_dir = debugfs_create_dir("omap_mux", NULL);
  417. if (!mux_dbg_dir)
  418. return;
  419. mux_dbg_board_dir = debugfs_create_dir("board", mux_dbg_dir);
  420. if (!mux_dbg_board_dir)
  421. return;
  422. list_for_each_entry(partition, &mux_partitions, node) {
  423. omap_mux_dbg_create_entry(partition, mux_dbg_dir);
  424. (void)debugfs_create_file(partition->name, S_IRUGO,
  425. mux_dbg_board_dir, partition,
  426. &omap_mux_dbg_board_fops);
  427. }
  428. }
  429. #else
  430. static inline void omap_mux_dbg_init(void)
  431. {
  432. }
  433. #endif /* CONFIG_DEBUG_FS */
  434. static void __init omap_mux_free_names(struct omap_mux *m)
  435. {
  436. int i;
  437. for (i = 0; i < OMAP_MUX_NR_MODES; i++)
  438. kfree(m->muxnames[i]);
  439. #ifdef CONFIG_DEBUG_FS
  440. for (i = 0; i < OMAP_MUX_NR_SIDES; i++)
  441. kfree(m->balls[i]);
  442. #endif
  443. }
  444. /* Free all data except for GPIO pins unless CONFIG_DEBUG_FS is set */
  445. static int __init omap_mux_late_init(void)
  446. {
  447. struct omap_mux_partition *partition;
  448. list_for_each_entry(partition, &mux_partitions, node) {
  449. struct omap_mux_entry *e, *tmp;
  450. list_for_each_entry_safe(e, tmp, &partition->muxmodes, node) {
  451. struct omap_mux *m = &e->mux;
  452. u16 mode = omap_mux_read(partition, m->reg_offset);
  453. if (OMAP_MODE_GPIO(mode))
  454. continue;
  455. #ifndef CONFIG_DEBUG_FS
  456. mutex_lock(&muxmode_mutex);
  457. list_del(&e->node);
  458. mutex_unlock(&muxmode_mutex);
  459. omap_mux_free_names(m);
  460. kfree(m);
  461. #endif
  462. }
  463. }
  464. omap_mux_dbg_init();
  465. return 0;
  466. }
  467. late_initcall(omap_mux_late_init);
  468. static void __init omap_mux_package_fixup(struct omap_mux *p,
  469. struct omap_mux *superset)
  470. {
  471. while (p->reg_offset != OMAP_MUX_TERMINATOR) {
  472. struct omap_mux *s = superset;
  473. int found = 0;
  474. while (s->reg_offset != OMAP_MUX_TERMINATOR) {
  475. if (s->reg_offset == p->reg_offset) {
  476. *s = *p;
  477. found++;
  478. break;
  479. }
  480. s++;
  481. }
  482. if (!found)
  483. pr_err("%s: Unknown entry offset 0x%x\n", __func__,
  484. p->reg_offset);
  485. p++;
  486. }
  487. }
  488. #ifdef CONFIG_DEBUG_FS
  489. static void __init omap_mux_package_init_balls(struct omap_ball *b,
  490. struct omap_mux *superset)
  491. {
  492. while (b->reg_offset != OMAP_MUX_TERMINATOR) {
  493. struct omap_mux *s = superset;
  494. int found = 0;
  495. while (s->reg_offset != OMAP_MUX_TERMINATOR) {
  496. if (s->reg_offset == b->reg_offset) {
  497. s->balls[0] = b->balls[0];
  498. s->balls[1] = b->balls[1];
  499. found++;
  500. break;
  501. }
  502. s++;
  503. }
  504. if (!found)
  505. pr_err("%s: Unknown ball offset 0x%x\n", __func__,
  506. b->reg_offset);
  507. b++;
  508. }
  509. }
  510. #else /* CONFIG_DEBUG_FS */
  511. static inline void omap_mux_package_init_balls(struct omap_ball *b,
  512. struct omap_mux *superset)
  513. {
  514. }
  515. #endif /* CONFIG_DEBUG_FS */
  516. static int __init omap_mux_setup(char *options)
  517. {
  518. if (!options)
  519. return 0;
  520. omap_mux_options = options;
  521. return 1;
  522. }
  523. __setup("omap_mux=", omap_mux_setup);
  524. /*
  525. * Note that the omap_mux=some.signal1=0x1234,some.signal2=0x1234
  526. * cmdline options only override the bootloader values.
  527. * During development, please enable CONFIG_DEBUG_FS, and use the
  528. * signal specific entries under debugfs.
  529. */
  530. static void __init omap_mux_set_cmdline_signals(void)
  531. {
  532. char *options, *next_opt, *token;
  533. if (!omap_mux_options)
  534. return;
  535. options = kmalloc(strlen(omap_mux_options) + 1, GFP_KERNEL);
  536. if (!options)
  537. return;
  538. strcpy(options, omap_mux_options);
  539. next_opt = options;
  540. while ((token = strsep(&next_opt, ",")) != NULL) {
  541. char *keyval, *name;
  542. unsigned long val;
  543. keyval = token;
  544. name = strsep(&keyval, "=");
  545. if (name) {
  546. int res;
  547. res = strict_strtoul(keyval, 0x10, &val);
  548. if (res < 0)
  549. continue;
  550. omap_mux_init_signal(name, (u16)val);
  551. }
  552. }
  553. kfree(options);
  554. }
  555. static int __init omap_mux_copy_names(struct omap_mux *src,
  556. struct omap_mux *dst)
  557. {
  558. int i;
  559. for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
  560. if (src->muxnames[i]) {
  561. dst->muxnames[i] =
  562. kmalloc(strlen(src->muxnames[i]) + 1,
  563. GFP_KERNEL);
  564. if (!dst->muxnames[i])
  565. goto free;
  566. strcpy(dst->muxnames[i], src->muxnames[i]);
  567. }
  568. }
  569. #ifdef CONFIG_DEBUG_FS
  570. for (i = 0; i < OMAP_MUX_NR_SIDES; i++) {
  571. if (src->balls[i]) {
  572. dst->balls[i] =
  573. kmalloc(strlen(src->balls[i]) + 1,
  574. GFP_KERNEL);
  575. if (!dst->balls[i])
  576. goto free;
  577. strcpy(dst->balls[i], src->balls[i]);
  578. }
  579. }
  580. #endif
  581. return 0;
  582. free:
  583. omap_mux_free_names(dst);
  584. return -ENOMEM;
  585. }
  586. #endif /* CONFIG_OMAP_MUX */
  587. static struct omap_mux *omap_mux_get_by_gpio(
  588. struct omap_mux_partition *partition,
  589. int gpio)
  590. {
  591. struct omap_mux_entry *e;
  592. struct omap_mux *ret = NULL;
  593. list_for_each_entry(e, &partition->muxmodes, node) {
  594. struct omap_mux *m = &e->mux;
  595. if (m->gpio == gpio) {
  596. ret = m;
  597. break;
  598. }
  599. }
  600. return ret;
  601. }
  602. /* Needed for dynamic muxing of GPIO pins for off-idle */
  603. u16 omap_mux_get_gpio(int gpio)
  604. {
  605. struct omap_mux_partition *partition;
  606. struct omap_mux *m;
  607. list_for_each_entry(partition, &mux_partitions, node) {
  608. m = omap_mux_get_by_gpio(partition, gpio);
  609. if (m)
  610. return omap_mux_read(partition, m->reg_offset);
  611. }
  612. if (!m || m->reg_offset == OMAP_MUX_TERMINATOR)
  613. pr_err("%s: Could not get gpio%i\n", __func__, gpio);
  614. return OMAP_MUX_TERMINATOR;
  615. }
  616. /* Needed for dynamic muxing of GPIO pins for off-idle */
  617. void omap_mux_set_gpio(u16 val, int gpio)
  618. {
  619. struct omap_mux_partition *partition;
  620. struct omap_mux *m = NULL;
  621. list_for_each_entry(partition, &mux_partitions, node) {
  622. m = omap_mux_get_by_gpio(partition, gpio);
  623. if (m) {
  624. omap_mux_write(partition, val, m->reg_offset);
  625. return;
  626. }
  627. }
  628. if (!m || m->reg_offset == OMAP_MUX_TERMINATOR)
  629. pr_err("%s: Could not set gpio%i\n", __func__, gpio);
  630. }
  631. static struct omap_mux * __init omap_mux_list_add(
  632. struct omap_mux_partition *partition,
  633. struct omap_mux *src)
  634. {
  635. struct omap_mux_entry *entry;
  636. struct omap_mux *m;
  637. entry = kzalloc(sizeof(struct omap_mux_entry), GFP_KERNEL);
  638. if (!entry)
  639. return NULL;
  640. m = &entry->mux;
  641. memcpy(m, src, sizeof(struct omap_mux_entry));
  642. #ifdef CONFIG_OMAP_MUX
  643. if (omap_mux_copy_names(src, m)) {
  644. kfree(entry);
  645. return NULL;
  646. }
  647. #endif
  648. mutex_lock(&muxmode_mutex);
  649. list_add_tail(&entry->node, &partition->muxmodes);
  650. mutex_unlock(&muxmode_mutex);
  651. return m;
  652. }
  653. /*
  654. * Note if CONFIG_OMAP_MUX is not selected, we will only initialize
  655. * the GPIO to mux offset mapping that is needed for dynamic muxing
  656. * of GPIO pins for off-idle.
  657. */
  658. static void __init omap_mux_init_list(struct omap_mux_partition *partition,
  659. struct omap_mux *superset)
  660. {
  661. while (superset->reg_offset != OMAP_MUX_TERMINATOR) {
  662. struct omap_mux *entry;
  663. #ifdef CONFIG_OMAP_MUX
  664. if (!superset->muxnames || !superset->muxnames[0]) {
  665. superset++;
  666. continue;
  667. }
  668. #else
  669. /* Skip pins that are not muxed as GPIO by bootloader */
  670. if (!OMAP_MODE_GPIO(omap_mux_read(partition,
  671. superset->reg_offset))) {
  672. superset++;
  673. continue;
  674. }
  675. #endif
  676. entry = omap_mux_list_add(partition, superset);
  677. if (!entry) {
  678. pr_err("%s: Could not add entry\n", __func__);
  679. return;
  680. }
  681. superset++;
  682. }
  683. }
  684. #ifdef CONFIG_OMAP_MUX
  685. static void omap_mux_init_package(struct omap_mux *superset,
  686. struct omap_mux *package_subset,
  687. struct omap_ball *package_balls)
  688. {
  689. if (package_subset)
  690. omap_mux_package_fixup(package_subset, superset);
  691. if (package_balls)
  692. omap_mux_package_init_balls(package_balls, superset);
  693. }
  694. static void omap_mux_init_signals(struct omap_mux_partition *partition,
  695. struct omap_board_mux *board_mux)
  696. {
  697. omap_mux_set_cmdline_signals();
  698. omap_mux_write_array(partition, board_mux);
  699. }
  700. #else
  701. static void omap_mux_init_package(struct omap_mux *superset,
  702. struct omap_mux *package_subset,
  703. struct omap_ball *package_balls)
  704. {
  705. }
  706. static void omap_mux_init_signals(struct omap_mux_partition *partition,
  707. struct omap_board_mux *board_mux)
  708. {
  709. }
  710. #endif
  711. static u32 mux_partitions_cnt;
  712. int __init omap_mux_init(const char *name, u32 flags,
  713. u32 mux_pbase, u32 mux_size,
  714. struct omap_mux *superset,
  715. struct omap_mux *package_subset,
  716. struct omap_board_mux *board_mux,
  717. struct omap_ball *package_balls)
  718. {
  719. struct omap_mux_partition *partition;
  720. partition = kzalloc(sizeof(struct omap_mux_partition), GFP_KERNEL);
  721. if (!partition)
  722. return -ENOMEM;
  723. partition->name = name;
  724. partition->flags = flags;
  725. partition->size = mux_size;
  726. partition->phys = mux_pbase;
  727. partition->base = ioremap(mux_pbase, mux_size);
  728. if (!partition->base) {
  729. pr_err("%s: Could not ioremap mux partition at 0x%08x\n",
  730. __func__, partition->phys);
  731. return -ENODEV;
  732. }
  733. INIT_LIST_HEAD(&partition->muxmodes);
  734. list_add_tail(&partition->node, &mux_partitions);
  735. mux_partitions_cnt++;
  736. pr_info("%s: Add partition: #%d: %s, flags: %x\n", __func__,
  737. mux_partitions_cnt, partition->name, partition->flags);
  738. omap_mux_init_package(superset, package_subset, package_balls);
  739. omap_mux_init_list(partition, superset);
  740. omap_mux_init_signals(partition, board_mux);
  741. return 0;
  742. }