db5500-prcmu.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. /*
  2. * Copyright (C) ST-Ericsson SA 2010
  3. *
  4. * License Terms: GNU General Public License v2
  5. * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
  6. *
  7. * U5500 PRCM Unit interface driver
  8. */
  9. #include <linux/module.h>
  10. #include <linux/kernel.h>
  11. #include <linux/delay.h>
  12. #include <linux/errno.h>
  13. #include <linux/err.h>
  14. #include <linux/spinlock.h>
  15. #include <linux/io.h>
  16. #include <linux/slab.h>
  17. #include <linux/mutex.h>
  18. #include <linux/completion.h>
  19. #include <linux/irq.h>
  20. #include <linux/jiffies.h>
  21. #include <linux/bitops.h>
  22. #include <linux/interrupt.h>
  23. #include <linux/mfd/dbx500-prcmu.h>
  24. #include <mach/hardware.h>
  25. #include <mach/irqs.h>
  26. #include <mach/db5500-regs.h>
  27. #include "dbx500-prcmu-regs.h"
  28. #define _PRCM_MB_HEADER (tcdm_base + 0xFE8)
  29. #define PRCM_REQ_MB0_HEADER (_PRCM_MB_HEADER + 0x0)
  30. #define PRCM_REQ_MB1_HEADER (_PRCM_MB_HEADER + 0x1)
  31. #define PRCM_REQ_MB2_HEADER (_PRCM_MB_HEADER + 0x2)
  32. #define PRCM_REQ_MB3_HEADER (_PRCM_MB_HEADER + 0x3)
  33. #define PRCM_REQ_MB4_HEADER (_PRCM_MB_HEADER + 0x4)
  34. #define PRCM_REQ_MB5_HEADER (_PRCM_MB_HEADER + 0x5)
  35. #define PRCM_REQ_MB6_HEADER (_PRCM_MB_HEADER + 0x6)
  36. #define PRCM_REQ_MB7_HEADER (_PRCM_MB_HEADER + 0x7)
  37. #define PRCM_ACK_MB0_HEADER (_PRCM_MB_HEADER + 0x8)
  38. #define PRCM_ACK_MB1_HEADER (_PRCM_MB_HEADER + 0x9)
  39. #define PRCM_ACK_MB2_HEADER (_PRCM_MB_HEADER + 0xa)
  40. #define PRCM_ACK_MB3_HEADER (_PRCM_MB_HEADER + 0xb)
  41. #define PRCM_ACK_MB4_HEADER (_PRCM_MB_HEADER + 0xc)
  42. #define PRCM_ACK_MB5_HEADER (_PRCM_MB_HEADER + 0xd)
  43. #define PRCM_ACK_MB6_HEADER (_PRCM_MB_HEADER + 0xe)
  44. #define PRCM_ACK_MB7_HEADER (_PRCM_MB_HEADER + 0xf)
  45. /* Req Mailboxes */
  46. #define PRCM_REQ_MB0 (tcdm_base + 0xFD8)
  47. #define PRCM_REQ_MB1 (tcdm_base + 0xFCC)
  48. #define PRCM_REQ_MB2 (tcdm_base + 0xFC4)
  49. #define PRCM_REQ_MB3 (tcdm_base + 0xFC0)
  50. #define PRCM_REQ_MB4 (tcdm_base + 0xF98)
  51. #define PRCM_REQ_MB5 (tcdm_base + 0xF90)
  52. #define PRCM_REQ_MB6 (tcdm_base + 0xF8C)
  53. #define PRCM_REQ_MB7 (tcdm_base + 0xF84)
  54. /* Ack Mailboxes */
  55. #define PRCM_ACK_MB0 (tcdm_base + 0xF38)
  56. #define PRCM_ACK_MB1 (tcdm_base + 0xF30)
  57. #define PRCM_ACK_MB2 (tcdm_base + 0xF24)
  58. #define PRCM_ACK_MB3 (tcdm_base + 0xF20)
  59. #define PRCM_ACK_MB4 (tcdm_base + 0xF1C)
  60. #define PRCM_ACK_MB5 (tcdm_base + 0xF14)
  61. #define PRCM_ACK_MB6 (tcdm_base + 0xF0C)
  62. #define PRCM_ACK_MB7 (tcdm_base + 0xF08)
  63. enum mb_return_code {
  64. RC_SUCCESS,
  65. RC_FAIL,
  66. };
  67. /* Mailbox 0 headers. */
  68. enum mb0_header {
  69. /* request */
  70. RMB0H_PWR_STATE_TRANS = 1,
  71. RMB0H_WAKE_UP_CFG,
  72. RMB0H_RD_WAKE_UP_ACK,
  73. /* acknowledge */
  74. AMB0H_WAKE_UP = 1,
  75. };
  76. /* Mailbox 5 headers. */
  77. enum mb5_header {
  78. MB5H_I2C_WRITE = 1,
  79. MB5H_I2C_READ,
  80. };
  81. /* Request mailbox 5 fields. */
  82. #define PRCM_REQ_MB5_I2C_SLAVE (PRCM_REQ_MB5 + 0)
  83. #define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 1)
  84. #define PRCM_REQ_MB5_I2C_SIZE (PRCM_REQ_MB5 + 2)
  85. #define PRCM_REQ_MB5_I2C_DATA (PRCM_REQ_MB5 + 4)
  86. /* Acknowledge mailbox 5 fields. */
  87. #define PRCM_ACK_MB5_RETURN_CODE (PRCM_ACK_MB5 + 0)
  88. #define PRCM_ACK_MB5_I2C_DATA (PRCM_ACK_MB5 + 4)
  89. #define NUM_MB 8
  90. #define MBOX_BIT BIT
  91. #define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1)
  92. /*
  93. * Used by MCDE to setup all necessary PRCMU registers
  94. */
  95. #define PRCMU_RESET_DSIPLL 0x00004000
  96. #define PRCMU_UNCLAMP_DSIPLL 0x00400800
  97. /* HDMI CLK MGT PLLSW=001 (PLLSOC0), PLLDIV=0x8, = 50 Mhz*/
  98. #define PRCMU_DSI_CLOCK_SETTING 0x00000128
  99. /* TVCLK_MGT PLLSW=001 (PLLSOC0) PLLDIV=0x13, = 19.05 MHZ */
  100. #define PRCMU_DSI_LP_CLOCK_SETTING 0x00000135
  101. #define PRCMU_PLLDSI_FREQ_SETTING 0x00020121
  102. #define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000002
  103. #define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x03000201
  104. #define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00000101
  105. #define PRCMU_ENABLE_PLLDSI 0x00000001
  106. #define PRCMU_DISABLE_PLLDSI 0x00000000
  107. #define PRCMU_DSI_RESET_SW 0x00000003
  108. #define PRCMU_RESOUTN0_PIN 0x00000001
  109. #define PRCMU_RESOUTN1_PIN 0x00000002
  110. #define PRCMU_RESOUTN2_PIN 0x00000004
  111. #define PRCMU_PLLDSI_LOCKP_LOCKED 0x3
  112. /*
  113. * mb0_transfer - state needed for mailbox 0 communication.
  114. * @lock: The transaction lock.
  115. */
  116. static struct {
  117. spinlock_t lock;
  118. } mb0_transfer;
  119. /*
  120. * mb5_transfer - state needed for mailbox 5 communication.
  121. * @lock: The transaction lock.
  122. * @work: The transaction completion structure.
  123. * @ack: Reply ("acknowledge") data.
  124. */
  125. static struct {
  126. struct mutex lock;
  127. struct completion work;
  128. struct {
  129. u8 header;
  130. u8 status;
  131. u8 value[4];
  132. } ack;
  133. } mb5_transfer;
  134. /* PRCMU TCDM base IO address. */
  135. static __iomem void *tcdm_base;
  136. /**
  137. * db5500_prcmu_abb_read() - Read register value(s) from the ABB.
  138. * @slave: The I2C slave address.
  139. * @reg: The (start) register address.
  140. * @value: The read out value(s).
  141. * @size: The number of registers to read.
  142. *
  143. * Reads register value(s) from the ABB.
  144. * @size has to be <= 4.
  145. */
  146. int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
  147. {
  148. int r;
  149. if ((size < 1) || (4 < size))
  150. return -EINVAL;
  151. mutex_lock(&mb5_transfer.lock);
  152. while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
  153. cpu_relax();
  154. writeb(slave, PRCM_REQ_MB5_I2C_SLAVE);
  155. writeb(reg, PRCM_REQ_MB5_I2C_REG);
  156. writeb(size, PRCM_REQ_MB5_I2C_SIZE);
  157. writeb(MB5H_I2C_READ, PRCM_REQ_MB5_HEADER);
  158. writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
  159. wait_for_completion(&mb5_transfer.work);
  160. r = 0;
  161. if ((mb5_transfer.ack.header == MB5H_I2C_READ) &&
  162. (mb5_transfer.ack.status == RC_SUCCESS))
  163. memcpy(value, mb5_transfer.ack.value, (size_t)size);
  164. else
  165. r = -EIO;
  166. mutex_unlock(&mb5_transfer.lock);
  167. return r;
  168. }
  169. /**
  170. * db5500_prcmu_abb_write() - Write register value(s) to the ABB.
  171. * @slave: The I2C slave address.
  172. * @reg: The (start) register address.
  173. * @value: The value(s) to write.
  174. * @size: The number of registers to write.
  175. *
  176. * Writes register value(s) to the ABB.
  177. * @size has to be <= 4.
  178. */
  179. int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
  180. {
  181. int r;
  182. if ((size < 1) || (4 < size))
  183. return -EINVAL;
  184. mutex_lock(&mb5_transfer.lock);
  185. while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
  186. cpu_relax();
  187. writeb(slave, PRCM_REQ_MB5_I2C_SLAVE);
  188. writeb(reg, PRCM_REQ_MB5_I2C_REG);
  189. writeb(size, PRCM_REQ_MB5_I2C_SIZE);
  190. memcpy_toio(PRCM_REQ_MB5_I2C_DATA, value, size);
  191. writeb(MB5H_I2C_WRITE, PRCM_REQ_MB5_HEADER);
  192. writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
  193. wait_for_completion(&mb5_transfer.work);
  194. if ((mb5_transfer.ack.header == MB5H_I2C_WRITE) &&
  195. (mb5_transfer.ack.status == RC_SUCCESS))
  196. r = 0;
  197. else
  198. r = -EIO;
  199. mutex_unlock(&mb5_transfer.lock);
  200. return r;
  201. }
  202. int db5500_prcmu_enable_dsipll(void)
  203. {
  204. int i;
  205. /* Enable DSIPLL_RESETN resets */
  206. writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR);
  207. /* Unclamp DSIPLL in/out */
  208. writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR);
  209. /* Set DSI PLL FREQ */
  210. writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ);
  211. writel(PRCMU_DSI_PLLOUT_SEL_SETTING,
  212. PRCM_DSI_PLLOUT_SEL);
  213. /* Enable Escape clocks */
  214. writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
  215. /* Start DSI PLL */
  216. writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
  217. /* Reset DSI PLL */
  218. writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET);
  219. for (i = 0; i < 10; i++) {
  220. if ((readl(PRCM_PLLDSI_LOCKP) &
  221. PRCMU_PLLDSI_LOCKP_LOCKED) == PRCMU_PLLDSI_LOCKP_LOCKED)
  222. break;
  223. udelay(100);
  224. }
  225. /* Release DSIPLL_RESETN */
  226. writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_SET);
  227. return 0;
  228. }
  229. int db5500_prcmu_disable_dsipll(void)
  230. {
  231. /* Disable dsi pll */
  232. writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
  233. /* Disable escapeclock */
  234. writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
  235. return 0;
  236. }
  237. int db5500_prcmu_set_display_clocks(void)
  238. {
  239. /* HDMI and TVCLK Should be handled somewhere else */
  240. /* PLLDIV=8, PLLSW=2, CLKEN=1 */
  241. writel(PRCMU_DSI_CLOCK_SETTING, PRCM_HDMICLK_MGT);
  242. /* PLLDIV=14, PLLSW=2, CLKEN=1 */
  243. writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT);
  244. return 0;
  245. }
  246. static void ack_dbb_wakeup(void)
  247. {
  248. unsigned long flags;
  249. spin_lock_irqsave(&mb0_transfer.lock, flags);
  250. while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
  251. cpu_relax();
  252. writeb(RMB0H_RD_WAKE_UP_ACK, PRCM_REQ_MB0_HEADER);
  253. writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
  254. spin_unlock_irqrestore(&mb0_transfer.lock, flags);
  255. }
  256. static inline void print_unknown_header_warning(u8 n, u8 header)
  257. {
  258. pr_warning("prcmu: Unknown message header (%d) in mailbox %d.\n",
  259. header, n);
  260. }
  261. static bool read_mailbox_0(void)
  262. {
  263. bool r;
  264. u8 header;
  265. header = readb(PRCM_ACK_MB0_HEADER);
  266. switch (header) {
  267. case AMB0H_WAKE_UP:
  268. r = true;
  269. break;
  270. default:
  271. print_unknown_header_warning(0, header);
  272. r = false;
  273. break;
  274. }
  275. writel(MBOX_BIT(0), PRCM_ARM_IT1_CLR);
  276. return r;
  277. }
  278. static bool read_mailbox_1(void)
  279. {
  280. writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR);
  281. return false;
  282. }
  283. static bool read_mailbox_2(void)
  284. {
  285. writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR);
  286. return false;
  287. }
  288. static bool read_mailbox_3(void)
  289. {
  290. writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR);
  291. return false;
  292. }
  293. static bool read_mailbox_4(void)
  294. {
  295. writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR);
  296. return false;
  297. }
  298. static bool read_mailbox_5(void)
  299. {
  300. u8 header;
  301. header = readb(PRCM_ACK_MB5_HEADER);
  302. switch (header) {
  303. case MB5H_I2C_READ:
  304. memcpy_fromio(mb5_transfer.ack.value, PRCM_ACK_MB5_I2C_DATA, 4);
  305. case MB5H_I2C_WRITE:
  306. mb5_transfer.ack.header = header;
  307. mb5_transfer.ack.status = readb(PRCM_ACK_MB5_RETURN_CODE);
  308. complete(&mb5_transfer.work);
  309. break;
  310. default:
  311. print_unknown_header_warning(5, header);
  312. break;
  313. }
  314. writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR);
  315. return false;
  316. }
  317. static bool read_mailbox_6(void)
  318. {
  319. writel(MBOX_BIT(6), PRCM_ARM_IT1_CLR);
  320. return false;
  321. }
  322. static bool read_mailbox_7(void)
  323. {
  324. writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR);
  325. return false;
  326. }
  327. static bool (* const read_mailbox[NUM_MB])(void) = {
  328. read_mailbox_0,
  329. read_mailbox_1,
  330. read_mailbox_2,
  331. read_mailbox_3,
  332. read_mailbox_4,
  333. read_mailbox_5,
  334. read_mailbox_6,
  335. read_mailbox_7
  336. };
  337. static irqreturn_t prcmu_irq_handler(int irq, void *data)
  338. {
  339. u32 bits;
  340. u8 n;
  341. irqreturn_t r;
  342. bits = (readl(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
  343. if (unlikely(!bits))
  344. return IRQ_NONE;
  345. r = IRQ_HANDLED;
  346. for (n = 0; bits; n++) {
  347. if (bits & MBOX_BIT(n)) {
  348. bits -= MBOX_BIT(n);
  349. if (read_mailbox[n]())
  350. r = IRQ_WAKE_THREAD;
  351. }
  352. }
  353. return r;
  354. }
  355. static irqreturn_t prcmu_irq_thread_fn(int irq, void *data)
  356. {
  357. ack_dbb_wakeup();
  358. return IRQ_HANDLED;
  359. }
  360. void __init db5500_prcmu_early_init(void)
  361. {
  362. tcdm_base = __io_address(U5500_PRCMU_TCDM_BASE);
  363. spin_lock_init(&mb0_transfer.lock);
  364. mutex_init(&mb5_transfer.lock);
  365. init_completion(&mb5_transfer.work);
  366. }
  367. /**
  368. * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
  369. *
  370. */
  371. int __init db5500_prcmu_init(void)
  372. {
  373. int r = 0;
  374. if (ux500_is_svp() || !cpu_is_u5500())
  375. return -ENODEV;
  376. /* Clean up the mailbox interrupts after pre-kernel code. */
  377. writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
  378. r = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler,
  379. prcmu_irq_thread_fn, 0, "prcmu", NULL);
  380. if (r < 0) {
  381. pr_err("prcmu: Failed to allocate IRQ_DB5500_PRCMU1.\n");
  382. return -EBUSY;
  383. }
  384. return 0;
  385. }
  386. arch_initcall(db5500_prcmu_init);