pinmux.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. /*
  2. * linux/arch/arm/mach-tegra/pinmux.c
  3. *
  4. * Copyright (C) 2010 Google, Inc.
  5. *
  6. * This software is licensed under the terms of the GNU General Public
  7. * License version 2, as published by the Free Software Foundation, and
  8. * may be copied, distributed, and modified under those terms.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. */
  16. #include <linux/init.h>
  17. #include <linux/module.h>
  18. #include <linux/kernel.h>
  19. #include <linux/errno.h>
  20. #include <linux/spinlock.h>
  21. #include <linux/io.h>
  22. #include <mach/iomap.h>
  23. #include <mach/pinmux.h>
  24. #define HSM_EN(reg) (((reg) >> 2) & 0x1)
  25. #define SCHMT_EN(reg) (((reg) >> 3) & 0x1)
  26. #define LPMD(reg) (((reg) >> 4) & 0x3)
  27. #define DRVDN(reg) (((reg) >> 12) & 0x1f)
  28. #define DRVUP(reg) (((reg) >> 20) & 0x1f)
  29. #define SLWR(reg) (((reg) >> 28) & 0x3)
  30. #define SLWF(reg) (((reg) >> 30) & 0x3)
  31. static const struct tegra_pingroup_desc *const pingroups = tegra_soc_pingroups;
  32. static const struct tegra_drive_pingroup_desc *const drive_pingroups = tegra_soc_drive_pingroups;
  33. static char *tegra_mux_names[TEGRA_MAX_MUX] = {
  34. [TEGRA_MUX_AHB_CLK] = "AHB_CLK",
  35. [TEGRA_MUX_APB_CLK] = "APB_CLK",
  36. [TEGRA_MUX_AUDIO_SYNC] = "AUDIO_SYNC",
  37. [TEGRA_MUX_CRT] = "CRT",
  38. [TEGRA_MUX_DAP1] = "DAP1",
  39. [TEGRA_MUX_DAP2] = "DAP2",
  40. [TEGRA_MUX_DAP3] = "DAP3",
  41. [TEGRA_MUX_DAP4] = "DAP4",
  42. [TEGRA_MUX_DAP5] = "DAP5",
  43. [TEGRA_MUX_DISPLAYA] = "DISPLAYA",
  44. [TEGRA_MUX_DISPLAYB] = "DISPLAYB",
  45. [TEGRA_MUX_EMC_TEST0_DLL] = "EMC_TEST0_DLL",
  46. [TEGRA_MUX_EMC_TEST1_DLL] = "EMC_TEST1_DLL",
  47. [TEGRA_MUX_GMI] = "GMI",
  48. [TEGRA_MUX_GMI_INT] = "GMI_INT",
  49. [TEGRA_MUX_HDMI] = "HDMI",
  50. [TEGRA_MUX_I2C] = "I2C",
  51. [TEGRA_MUX_I2C2] = "I2C2",
  52. [TEGRA_MUX_I2C3] = "I2C3",
  53. [TEGRA_MUX_IDE] = "IDE",
  54. [TEGRA_MUX_IRDA] = "IRDA",
  55. [TEGRA_MUX_KBC] = "KBC",
  56. [TEGRA_MUX_MIO] = "MIO",
  57. [TEGRA_MUX_MIPI_HS] = "MIPI_HS",
  58. [TEGRA_MUX_NAND] = "NAND",
  59. [TEGRA_MUX_OSC] = "OSC",
  60. [TEGRA_MUX_OWR] = "OWR",
  61. [TEGRA_MUX_PCIE] = "PCIE",
  62. [TEGRA_MUX_PLLA_OUT] = "PLLA_OUT",
  63. [TEGRA_MUX_PLLC_OUT1] = "PLLC_OUT1",
  64. [TEGRA_MUX_PLLM_OUT1] = "PLLM_OUT1",
  65. [TEGRA_MUX_PLLP_OUT2] = "PLLP_OUT2",
  66. [TEGRA_MUX_PLLP_OUT3] = "PLLP_OUT3",
  67. [TEGRA_MUX_PLLP_OUT4] = "PLLP_OUT4",
  68. [TEGRA_MUX_PWM] = "PWM",
  69. [TEGRA_MUX_PWR_INTR] = "PWR_INTR",
  70. [TEGRA_MUX_PWR_ON] = "PWR_ON",
  71. [TEGRA_MUX_RTCK] = "RTCK",
  72. [TEGRA_MUX_SDIO1] = "SDIO1",
  73. [TEGRA_MUX_SDIO2] = "SDIO2",
  74. [TEGRA_MUX_SDIO3] = "SDIO3",
  75. [TEGRA_MUX_SDIO4] = "SDIO4",
  76. [TEGRA_MUX_SFLASH] = "SFLASH",
  77. [TEGRA_MUX_SPDIF] = "SPDIF",
  78. [TEGRA_MUX_SPI1] = "SPI1",
  79. [TEGRA_MUX_SPI2] = "SPI2",
  80. [TEGRA_MUX_SPI2_ALT] = "SPI2_ALT",
  81. [TEGRA_MUX_SPI3] = "SPI3",
  82. [TEGRA_MUX_SPI4] = "SPI4",
  83. [TEGRA_MUX_TRACE] = "TRACE",
  84. [TEGRA_MUX_TWC] = "TWC",
  85. [TEGRA_MUX_UARTA] = "UARTA",
  86. [TEGRA_MUX_UARTB] = "UARTB",
  87. [TEGRA_MUX_UARTC] = "UARTC",
  88. [TEGRA_MUX_UARTD] = "UARTD",
  89. [TEGRA_MUX_UARTE] = "UARTE",
  90. [TEGRA_MUX_ULPI] = "ULPI",
  91. [TEGRA_MUX_VI] = "VI",
  92. [TEGRA_MUX_VI_SENSOR_CLK] = "VI_SENSOR_CLK",
  93. [TEGRA_MUX_XIO] = "XIO",
  94. [TEGRA_MUX_SAFE] = "<safe>",
  95. };
  96. static const char *tegra_drive_names[TEGRA_MAX_DRIVE] = {
  97. [TEGRA_DRIVE_DIV_8] = "DIV_8",
  98. [TEGRA_DRIVE_DIV_4] = "DIV_4",
  99. [TEGRA_DRIVE_DIV_2] = "DIV_2",
  100. [TEGRA_DRIVE_DIV_1] = "DIV_1",
  101. };
  102. static const char *tegra_slew_names[TEGRA_MAX_SLEW] = {
  103. [TEGRA_SLEW_FASTEST] = "FASTEST",
  104. [TEGRA_SLEW_FAST] = "FAST",
  105. [TEGRA_SLEW_SLOW] = "SLOW",
  106. [TEGRA_SLEW_SLOWEST] = "SLOWEST",
  107. };
  108. static DEFINE_SPINLOCK(mux_lock);
  109. static const char *pingroup_name(enum tegra_pingroup pg)
  110. {
  111. if (pg < 0 || pg >= TEGRA_MAX_PINGROUP)
  112. return "<UNKNOWN>";
  113. return pingroups[pg].name;
  114. }
  115. static const char *func_name(enum tegra_mux_func func)
  116. {
  117. if (func == TEGRA_MUX_RSVD1)
  118. return "RSVD1";
  119. if (func == TEGRA_MUX_RSVD2)
  120. return "RSVD2";
  121. if (func == TEGRA_MUX_RSVD3)
  122. return "RSVD3";
  123. if (func == TEGRA_MUX_RSVD4)
  124. return "RSVD4";
  125. if (func == TEGRA_MUX_NONE)
  126. return "NONE";
  127. if (func < 0 || func >= TEGRA_MAX_MUX)
  128. return "<UNKNOWN>";
  129. return tegra_mux_names[func];
  130. }
  131. static const char *tri_name(unsigned long val)
  132. {
  133. return val ? "TRISTATE" : "NORMAL";
  134. }
  135. static const char *pupd_name(unsigned long val)
  136. {
  137. switch (val) {
  138. case 0:
  139. return "NORMAL";
  140. case 1:
  141. return "PULL_DOWN";
  142. case 2:
  143. return "PULL_UP";
  144. default:
  145. return "RSVD";
  146. }
  147. }
  148. static inline unsigned long pg_readl(unsigned long offset)
  149. {
  150. return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
  151. }
  152. static inline void pg_writel(unsigned long value, unsigned long offset)
  153. {
  154. writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
  155. }
  156. static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
  157. {
  158. int mux = -1;
  159. int i;
  160. unsigned long reg;
  161. unsigned long flags;
  162. enum tegra_pingroup pg = config->pingroup;
  163. enum tegra_mux_func func = config->func;
  164. if (pg < 0 || pg >= TEGRA_MAX_PINGROUP)
  165. return -ERANGE;
  166. if (pingroups[pg].mux_reg < 0)
  167. return -EINVAL;
  168. if (func < 0)
  169. return -ERANGE;
  170. if (func == TEGRA_MUX_SAFE)
  171. func = pingroups[pg].func_safe;
  172. if (func & TEGRA_MUX_RSVD) {
  173. mux = func & 0x3;
  174. } else {
  175. for (i = 0; i < 4; i++) {
  176. if (pingroups[pg].funcs[i] == func) {
  177. mux = i;
  178. break;
  179. }
  180. }
  181. }
  182. if (mux < 0)
  183. return -EINVAL;
  184. spin_lock_irqsave(&mux_lock, flags);
  185. reg = pg_readl(pingroups[pg].mux_reg);
  186. reg &= ~(0x3 << pingroups[pg].mux_bit);
  187. reg |= mux << pingroups[pg].mux_bit;
  188. pg_writel(reg, pingroups[pg].mux_reg);
  189. spin_unlock_irqrestore(&mux_lock, flags);
  190. return 0;
  191. }
  192. int tegra_pinmux_set_tristate(enum tegra_pingroup pg,
  193. enum tegra_tristate tristate)
  194. {
  195. unsigned long reg;
  196. unsigned long flags;
  197. if (pg < 0 || pg >= TEGRA_MAX_PINGROUP)
  198. return -ERANGE;
  199. if (pingroups[pg].tri_reg < 0)
  200. return -EINVAL;
  201. spin_lock_irqsave(&mux_lock, flags);
  202. reg = pg_readl(pingroups[pg].tri_reg);
  203. reg &= ~(0x1 << pingroups[pg].tri_bit);
  204. if (tristate)
  205. reg |= 1 << pingroups[pg].tri_bit;
  206. pg_writel(reg, pingroups[pg].tri_reg);
  207. spin_unlock_irqrestore(&mux_lock, flags);
  208. return 0;
  209. }
  210. int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
  211. enum tegra_pullupdown pupd)
  212. {
  213. unsigned long reg;
  214. unsigned long flags;
  215. if (pg < 0 || pg >= TEGRA_MAX_PINGROUP)
  216. return -ERANGE;
  217. if (pingroups[pg].pupd_reg < 0)
  218. return -EINVAL;
  219. if (pupd != TEGRA_PUPD_NORMAL &&
  220. pupd != TEGRA_PUPD_PULL_DOWN &&
  221. pupd != TEGRA_PUPD_PULL_UP)
  222. return -EINVAL;
  223. spin_lock_irqsave(&mux_lock, flags);
  224. reg = pg_readl(pingroups[pg].pupd_reg);
  225. reg &= ~(0x3 << pingroups[pg].pupd_bit);
  226. reg |= pupd << pingroups[pg].pupd_bit;
  227. pg_writel(reg, pingroups[pg].pupd_reg);
  228. spin_unlock_irqrestore(&mux_lock, flags);
  229. return 0;
  230. }
  231. static void tegra_pinmux_config_pingroup(const struct tegra_pingroup_config *config)
  232. {
  233. enum tegra_pingroup pingroup = config->pingroup;
  234. enum tegra_mux_func func = config->func;
  235. enum tegra_pullupdown pupd = config->pupd;
  236. enum tegra_tristate tristate = config->tristate;
  237. int err;
  238. if (pingroups[pingroup].mux_reg >= 0) {
  239. err = tegra_pinmux_set_func(config);
  240. if (err < 0)
  241. pr_err("pinmux: can't set pingroup %s func to %s: %d\n",
  242. pingroup_name(pingroup), func_name(func), err);
  243. }
  244. if (pingroups[pingroup].pupd_reg >= 0) {
  245. err = tegra_pinmux_set_pullupdown(pingroup, pupd);
  246. if (err < 0)
  247. pr_err("pinmux: can't set pingroup %s pullupdown to %s: %d\n",
  248. pingroup_name(pingroup), pupd_name(pupd), err);
  249. }
  250. if (pingroups[pingroup].tri_reg >= 0) {
  251. err = tegra_pinmux_set_tristate(pingroup, tristate);
  252. if (err < 0)
  253. pr_err("pinmux: can't set pingroup %s tristate to %s: %d\n",
  254. pingroup_name(pingroup), tri_name(func), err);
  255. }
  256. }
  257. void tegra_pinmux_config_table(const struct tegra_pingroup_config *config, int len)
  258. {
  259. int i;
  260. for (i = 0; i < len; i++)
  261. tegra_pinmux_config_pingroup(&config[i]);
  262. }
  263. static const char *drive_pinmux_name(enum tegra_drive_pingroup pg)
  264. {
  265. if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP)
  266. return "<UNKNOWN>";
  267. return drive_pingroups[pg].name;
  268. }
  269. static const char *enable_name(unsigned long val)
  270. {
  271. return val ? "ENABLE" : "DISABLE";
  272. }
  273. static const char *drive_name(unsigned long val)
  274. {
  275. if (val >= TEGRA_MAX_DRIVE)
  276. return "<UNKNOWN>";
  277. return tegra_drive_names[val];
  278. }
  279. static const char *slew_name(unsigned long val)
  280. {
  281. if (val >= TEGRA_MAX_SLEW)
  282. return "<UNKNOWN>";
  283. return tegra_slew_names[val];
  284. }
  285. static int tegra_drive_pinmux_set_hsm(enum tegra_drive_pingroup pg,
  286. enum tegra_hsm hsm)
  287. {
  288. unsigned long flags;
  289. u32 reg;
  290. if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP)
  291. return -ERANGE;
  292. if (hsm != TEGRA_HSM_ENABLE && hsm != TEGRA_HSM_DISABLE)
  293. return -EINVAL;
  294. spin_lock_irqsave(&mux_lock, flags);
  295. reg = pg_readl(drive_pingroups[pg].reg);
  296. if (hsm == TEGRA_HSM_ENABLE)
  297. reg |= (1 << 2);
  298. else
  299. reg &= ~(1 << 2);
  300. pg_writel(reg, drive_pingroups[pg].reg);
  301. spin_unlock_irqrestore(&mux_lock, flags);
  302. return 0;
  303. }
  304. static int tegra_drive_pinmux_set_schmitt(enum tegra_drive_pingroup pg,
  305. enum tegra_schmitt schmitt)
  306. {
  307. unsigned long flags;
  308. u32 reg;
  309. if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP)
  310. return -ERANGE;
  311. if (schmitt != TEGRA_SCHMITT_ENABLE && schmitt != TEGRA_SCHMITT_DISABLE)
  312. return -EINVAL;
  313. spin_lock_irqsave(&mux_lock, flags);
  314. reg = pg_readl(drive_pingroups[pg].reg);
  315. if (schmitt == TEGRA_SCHMITT_ENABLE)
  316. reg |= (1 << 3);
  317. else
  318. reg &= ~(1 << 3);
  319. pg_writel(reg, drive_pingroups[pg].reg);
  320. spin_unlock_irqrestore(&mux_lock, flags);
  321. return 0;
  322. }
  323. static int tegra_drive_pinmux_set_drive(enum tegra_drive_pingroup pg,
  324. enum tegra_drive drive)
  325. {
  326. unsigned long flags;
  327. u32 reg;
  328. if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP)
  329. return -ERANGE;
  330. if (drive < 0 || drive >= TEGRA_MAX_DRIVE)
  331. return -EINVAL;
  332. spin_lock_irqsave(&mux_lock, flags);
  333. reg = pg_readl(drive_pingroups[pg].reg);
  334. reg &= ~(0x3 << 4);
  335. reg |= drive << 4;
  336. pg_writel(reg, drive_pingroups[pg].reg);
  337. spin_unlock_irqrestore(&mux_lock, flags);
  338. return 0;
  339. }
  340. static int tegra_drive_pinmux_set_pull_down(enum tegra_drive_pingroup pg,
  341. enum tegra_pull_strength pull_down)
  342. {
  343. unsigned long flags;
  344. u32 reg;
  345. if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP)
  346. return -ERANGE;
  347. if (pull_down < 0 || pull_down >= TEGRA_MAX_PULL)
  348. return -EINVAL;
  349. spin_lock_irqsave(&mux_lock, flags);
  350. reg = pg_readl(drive_pingroups[pg].reg);
  351. reg &= ~(0x1f << 12);
  352. reg |= pull_down << 12;
  353. pg_writel(reg, drive_pingroups[pg].reg);
  354. spin_unlock_irqrestore(&mux_lock, flags);
  355. return 0;
  356. }
  357. static int tegra_drive_pinmux_set_pull_up(enum tegra_drive_pingroup pg,
  358. enum tegra_pull_strength pull_up)
  359. {
  360. unsigned long flags;
  361. u32 reg;
  362. if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP)
  363. return -ERANGE;
  364. if (pull_up < 0 || pull_up >= TEGRA_MAX_PULL)
  365. return -EINVAL;
  366. spin_lock_irqsave(&mux_lock, flags);
  367. reg = pg_readl(drive_pingroups[pg].reg);
  368. reg &= ~(0x1f << 12);
  369. reg |= pull_up << 12;
  370. pg_writel(reg, drive_pingroups[pg].reg);
  371. spin_unlock_irqrestore(&mux_lock, flags);
  372. return 0;
  373. }
  374. static int tegra_drive_pinmux_set_slew_rising(enum tegra_drive_pingroup pg,
  375. enum tegra_slew slew_rising)
  376. {
  377. unsigned long flags;
  378. u32 reg;
  379. if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP)
  380. return -ERANGE;
  381. if (slew_rising < 0 || slew_rising >= TEGRA_MAX_SLEW)
  382. return -EINVAL;
  383. spin_lock_irqsave(&mux_lock, flags);
  384. reg = pg_readl(drive_pingroups[pg].reg);
  385. reg &= ~(0x3 << 28);
  386. reg |= slew_rising << 28;
  387. pg_writel(reg, drive_pingroups[pg].reg);
  388. spin_unlock_irqrestore(&mux_lock, flags);
  389. return 0;
  390. }
  391. static int tegra_drive_pinmux_set_slew_falling(enum tegra_drive_pingroup pg,
  392. enum tegra_slew slew_falling)
  393. {
  394. unsigned long flags;
  395. u32 reg;
  396. if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP)
  397. return -ERANGE;
  398. if (slew_falling < 0 || slew_falling >= TEGRA_MAX_SLEW)
  399. return -EINVAL;
  400. spin_lock_irqsave(&mux_lock, flags);
  401. reg = pg_readl(drive_pingroups[pg].reg);
  402. reg &= ~(0x3 << 30);
  403. reg |= slew_falling << 30;
  404. pg_writel(reg, drive_pingroups[pg].reg);
  405. spin_unlock_irqrestore(&mux_lock, flags);
  406. return 0;
  407. }
  408. static void tegra_drive_pinmux_config_pingroup(enum tegra_drive_pingroup pingroup,
  409. enum tegra_hsm hsm,
  410. enum tegra_schmitt schmitt,
  411. enum tegra_drive drive,
  412. enum tegra_pull_strength pull_down,
  413. enum tegra_pull_strength pull_up,
  414. enum tegra_slew slew_rising,
  415. enum tegra_slew slew_falling)
  416. {
  417. int err;
  418. err = tegra_drive_pinmux_set_hsm(pingroup, hsm);
  419. if (err < 0)
  420. pr_err("pinmux: can't set pingroup %s hsm to %s: %d\n",
  421. drive_pinmux_name(pingroup),
  422. enable_name(hsm), err);
  423. err = tegra_drive_pinmux_set_schmitt(pingroup, schmitt);
  424. if (err < 0)
  425. pr_err("pinmux: can't set pingroup %s schmitt to %s: %d\n",
  426. drive_pinmux_name(pingroup),
  427. enable_name(schmitt), err);
  428. err = tegra_drive_pinmux_set_drive(pingroup, drive);
  429. if (err < 0)
  430. pr_err("pinmux: can't set pingroup %s drive to %s: %d\n",
  431. drive_pinmux_name(pingroup),
  432. drive_name(drive), err);
  433. err = tegra_drive_pinmux_set_pull_down(pingroup, pull_down);
  434. if (err < 0)
  435. pr_err("pinmux: can't set pingroup %s pull down to %d: %d\n",
  436. drive_pinmux_name(pingroup),
  437. pull_down, err);
  438. err = tegra_drive_pinmux_set_pull_up(pingroup, pull_up);
  439. if (err < 0)
  440. pr_err("pinmux: can't set pingroup %s pull up to %d: %d\n",
  441. drive_pinmux_name(pingroup),
  442. pull_up, err);
  443. err = tegra_drive_pinmux_set_slew_rising(pingroup, slew_rising);
  444. if (err < 0)
  445. pr_err("pinmux: can't set pingroup %s rising slew to %s: %d\n",
  446. drive_pinmux_name(pingroup),
  447. slew_name(slew_rising), err);
  448. err = tegra_drive_pinmux_set_slew_falling(pingroup, slew_falling);
  449. if (err < 0)
  450. pr_err("pinmux: can't set pingroup %s falling slew to %s: %d\n",
  451. drive_pinmux_name(pingroup),
  452. slew_name(slew_falling), err);
  453. }
  454. void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config,
  455. int len)
  456. {
  457. int i;
  458. for (i = 0; i < len; i++)
  459. tegra_drive_pinmux_config_pingroup(config[i].pingroup,
  460. config[i].hsm,
  461. config[i].schmitt,
  462. config[i].drive,
  463. config[i].pull_down,
  464. config[i].pull_up,
  465. config[i].slew_rising,
  466. config[i].slew_falling);
  467. }
  468. void tegra_pinmux_set_safe_pinmux_table(const struct tegra_pingroup_config *config,
  469. int len)
  470. {
  471. int i;
  472. struct tegra_pingroup_config c;
  473. for (i = 0; i < len; i++) {
  474. int err;
  475. c = config[i];
  476. if (c.pingroup < 0 || c.pingroup >= TEGRA_MAX_PINGROUP) {
  477. WARN_ON(1);
  478. continue;
  479. }
  480. c.func = pingroups[c.pingroup].func_safe;
  481. err = tegra_pinmux_set_func(&c);
  482. if (err < 0)
  483. pr_err("%s: tegra_pinmux_set_func returned %d setting "
  484. "%s to %s\n", __func__, err,
  485. pingroup_name(c.pingroup), func_name(c.func));
  486. }
  487. }
  488. void tegra_pinmux_config_pinmux_table(const struct tegra_pingroup_config *config,
  489. int len)
  490. {
  491. int i;
  492. for (i = 0; i < len; i++) {
  493. int err;
  494. if (config[i].pingroup < 0 ||
  495. config[i].pingroup >= TEGRA_MAX_PINGROUP) {
  496. WARN_ON(1);
  497. continue;
  498. }
  499. err = tegra_pinmux_set_func(&config[i]);
  500. if (err < 0)
  501. pr_err("%s: tegra_pinmux_set_func returned %d setting "
  502. "%s to %s\n", __func__, err,
  503. pingroup_name(config[i].pingroup),
  504. func_name(config[i].func));
  505. }
  506. }
  507. void tegra_pinmux_config_tristate_table(const struct tegra_pingroup_config *config,
  508. int len, enum tegra_tristate tristate)
  509. {
  510. int i;
  511. int err;
  512. enum tegra_pingroup pingroup;
  513. for (i = 0; i < len; i++) {
  514. pingroup = config[i].pingroup;
  515. if (pingroups[pingroup].tri_reg >= 0) {
  516. err = tegra_pinmux_set_tristate(pingroup, tristate);
  517. if (err < 0)
  518. pr_err("pinmux: can't set pingroup %s tristate"
  519. " to %s: %d\n", pingroup_name(pingroup),
  520. tri_name(tristate), err);
  521. }
  522. }
  523. }
  524. void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *config,
  525. int len, enum tegra_pullupdown pupd)
  526. {
  527. int i;
  528. int err;
  529. enum tegra_pingroup pingroup;
  530. for (i = 0; i < len; i++) {
  531. pingroup = config[i].pingroup;
  532. if (pingroups[pingroup].pupd_reg >= 0) {
  533. err = tegra_pinmux_set_pullupdown(pingroup, pupd);
  534. if (err < 0)
  535. pr_err("pinmux: can't set pingroup %s pullupdown"
  536. " to %s: %d\n", pingroup_name(pingroup),
  537. pupd_name(pupd), err);
  538. }
  539. }
  540. }
  541. #ifdef CONFIG_DEBUG_FS
  542. #include <linux/debugfs.h>
  543. #include <linux/seq_file.h>
  544. static void dbg_pad_field(struct seq_file *s, int len)
  545. {
  546. seq_putc(s, ',');
  547. while (len-- > -1)
  548. seq_putc(s, ' ');
  549. }
  550. static int dbg_pinmux_show(struct seq_file *s, void *unused)
  551. {
  552. int i;
  553. int len;
  554. for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
  555. unsigned long tri;
  556. unsigned long mux;
  557. unsigned long pupd;
  558. seq_printf(s, "\t{TEGRA_PINGROUP_%s", pingroups[i].name);
  559. len = strlen(pingroups[i].name);
  560. dbg_pad_field(s, 5 - len);
  561. if (pingroups[i].mux_reg < 0) {
  562. seq_printf(s, "TEGRA_MUX_NONE");
  563. len = strlen("NONE");
  564. } else {
  565. mux = (pg_readl(pingroups[i].mux_reg) >>
  566. pingroups[i].mux_bit) & 0x3;
  567. if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
  568. seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
  569. len = 5;
  570. } else {
  571. seq_printf(s, "TEGRA_MUX_%s",
  572. tegra_mux_names[pingroups[i].funcs[mux]]);
  573. len = strlen(tegra_mux_names[pingroups[i].funcs[mux]]);
  574. }
  575. }
  576. dbg_pad_field(s, 13-len);
  577. if (pingroups[i].pupd_reg < 0) {
  578. seq_printf(s, "TEGRA_PUPD_NORMAL");
  579. len = strlen("NORMAL");
  580. } else {
  581. pupd = (pg_readl(pingroups[i].pupd_reg) >>
  582. pingroups[i].pupd_bit) & 0x3;
  583. seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
  584. len = strlen(pupd_name(pupd));
  585. }
  586. dbg_pad_field(s, 9 - len);
  587. if (pingroups[i].tri_reg < 0) {
  588. seq_printf(s, "TEGRA_TRI_NORMAL");
  589. } else {
  590. tri = (pg_readl(pingroups[i].tri_reg) >>
  591. pingroups[i].tri_bit) & 0x1;
  592. seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
  593. }
  594. seq_printf(s, "},\n");
  595. }
  596. return 0;
  597. }
  598. static int dbg_pinmux_open(struct inode *inode, struct file *file)
  599. {
  600. return single_open(file, dbg_pinmux_show, &inode->i_private);
  601. }
  602. static const struct file_operations debug_fops = {
  603. .open = dbg_pinmux_open,
  604. .read = seq_read,
  605. .llseek = seq_lseek,
  606. .release = single_release,
  607. };
  608. static int dbg_drive_pinmux_show(struct seq_file *s, void *unused)
  609. {
  610. int i;
  611. int len;
  612. for (i = 0; i < TEGRA_MAX_DRIVE_PINGROUP; i++) {
  613. u32 reg;
  614. seq_printf(s, "\t{TEGRA_DRIVE_PINGROUP_%s",
  615. drive_pingroups[i].name);
  616. len = strlen(drive_pingroups[i].name);
  617. dbg_pad_field(s, 7 - len);
  618. reg = pg_readl(drive_pingroups[i].reg);
  619. if (HSM_EN(reg)) {
  620. seq_printf(s, "TEGRA_HSM_ENABLE");
  621. len = 16;
  622. } else {
  623. seq_printf(s, "TEGRA_HSM_DISABLE");
  624. len = 17;
  625. }
  626. dbg_pad_field(s, 17 - len);
  627. if (SCHMT_EN(reg)) {
  628. seq_printf(s, "TEGRA_SCHMITT_ENABLE");
  629. len = 21;
  630. } else {
  631. seq_printf(s, "TEGRA_SCHMITT_DISABLE");
  632. len = 22;
  633. }
  634. dbg_pad_field(s, 22 - len);
  635. seq_printf(s, "TEGRA_DRIVE_%s", drive_name(LPMD(reg)));
  636. len = strlen(drive_name(LPMD(reg)));
  637. dbg_pad_field(s, 5 - len);
  638. seq_printf(s, "TEGRA_PULL_%d", DRVDN(reg));
  639. len = DRVDN(reg) < 10 ? 1 : 2;
  640. dbg_pad_field(s, 2 - len);
  641. seq_printf(s, "TEGRA_PULL_%d", DRVUP(reg));
  642. len = DRVUP(reg) < 10 ? 1 : 2;
  643. dbg_pad_field(s, 2 - len);
  644. seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWR(reg)));
  645. len = strlen(slew_name(SLWR(reg)));
  646. dbg_pad_field(s, 7 - len);
  647. seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWF(reg)));
  648. seq_printf(s, "},\n");
  649. }
  650. return 0;
  651. }
  652. static int dbg_drive_pinmux_open(struct inode *inode, struct file *file)
  653. {
  654. return single_open(file, dbg_drive_pinmux_show, &inode->i_private);
  655. }
  656. static const struct file_operations debug_drive_fops = {
  657. .open = dbg_drive_pinmux_open,
  658. .read = seq_read,
  659. .llseek = seq_lseek,
  660. .release = single_release,
  661. };
  662. static int __init tegra_pinmux_debuginit(void)
  663. {
  664. (void) debugfs_create_file("tegra_pinmux", S_IRUGO,
  665. NULL, NULL, &debug_fops);
  666. (void) debugfs_create_file("tegra_pinmux_drive", S_IRUGO,
  667. NULL, NULL, &debug_drive_fops);
  668. return 0;
  669. }
  670. late_initcall(tegra_pinmux_debuginit);
  671. #endif