wkup_m3_ipc.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * AMx3 Wkup M3 IPC driver
  4. *
  5. * Copyright (C) 2015 Texas Instruments, Inc.
  6. *
  7. * Dave Gerlach <[email protected]>
  8. */
  9. #include <linux/debugfs.h>
  10. #include <linux/err.h>
  11. #include <linux/firmware.h>
  12. #include <linux/kernel.h>
  13. #include <linux/kthread.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/irq.h>
  16. #include <linux/module.h>
  17. #include <linux/of.h>
  18. #include <linux/omap-mailbox.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/remoteproc.h>
  21. #include <linux/suspend.h>
  22. #include <linux/wkup_m3_ipc.h>
  23. #define AM33XX_CTRL_IPC_REG_COUNT 0x8
  24. #define AM33XX_CTRL_IPC_REG_OFFSET(m) (0x4 + 4 * (m))
  25. /* AM33XX M3_TXEV_EOI register */
  26. #define AM33XX_CONTROL_M3_TXEV_EOI 0x00
  27. #define AM33XX_M3_TXEV_ACK (0x1 << 0)
  28. #define AM33XX_M3_TXEV_ENABLE (0x0 << 0)
  29. #define IPC_CMD_DS0 0x4
  30. #define IPC_CMD_STANDBY 0xc
  31. #define IPC_CMD_IDLE 0x10
  32. #define IPC_CMD_RESET 0xe
  33. #define DS_IPC_DEFAULT 0xffffffff
  34. #define M3_VERSION_UNKNOWN 0x0000ffff
  35. #define M3_BASELINE_VERSION 0x191
  36. #define M3_STATUS_RESP_MASK (0xffff << 16)
  37. #define M3_FW_VERSION_MASK 0xffff
  38. #define M3_WAKE_SRC_MASK 0xff
  39. #define IPC_MEM_TYPE_SHIFT (0x0)
  40. #define IPC_MEM_TYPE_MASK (0x7 << 0)
  41. #define IPC_VTT_STAT_SHIFT (0x3)
  42. #define IPC_VTT_STAT_MASK (0x1 << 3)
  43. #define IPC_VTT_GPIO_PIN_SHIFT (0x4)
  44. #define IPC_VTT_GPIO_PIN_MASK (0x3f << 4)
  45. #define IPC_IO_ISOLATION_STAT_SHIFT (10)
  46. #define IPC_IO_ISOLATION_STAT_MASK (0x1 << 10)
  47. #define IPC_DBG_HALT_SHIFT (11)
  48. #define IPC_DBG_HALT_MASK (0x1 << 11)
  49. #define M3_STATE_UNKNOWN 0
  50. #define M3_STATE_RESET 1
  51. #define M3_STATE_INITED 2
  52. #define M3_STATE_MSG_FOR_LP 3
  53. #define M3_STATE_MSG_FOR_RESET 4
  54. #define WKUP_M3_SD_FW_MAGIC 0x570C
  55. #define WKUP_M3_DMEM_START 0x80000
  56. #define WKUP_M3_AUXDATA_OFFSET 0x1000
  57. #define WKUP_M3_AUXDATA_SIZE 0xFF
  58. static struct wkup_m3_ipc *m3_ipc_state;
  59. static const struct wkup_m3_wakeup_src wakeups[] = {
  60. {.irq_nr = 16, .src = "PRCM"},
  61. {.irq_nr = 35, .src = "USB0_PHY"},
  62. {.irq_nr = 36, .src = "USB1_PHY"},
  63. {.irq_nr = 40, .src = "I2C0"},
  64. {.irq_nr = 41, .src = "RTC Timer"},
  65. {.irq_nr = 42, .src = "RTC Alarm"},
  66. {.irq_nr = 43, .src = "Timer0"},
  67. {.irq_nr = 44, .src = "Timer1"},
  68. {.irq_nr = 45, .src = "UART"},
  69. {.irq_nr = 46, .src = "GPIO0"},
  70. {.irq_nr = 48, .src = "MPU_WAKE"},
  71. {.irq_nr = 49, .src = "WDT0"},
  72. {.irq_nr = 50, .src = "WDT1"},
  73. {.irq_nr = 51, .src = "ADC_TSC"},
  74. {.irq_nr = 0, .src = "Unknown"},
  75. };
  76. /**
  77. * wkup_m3_copy_aux_data - Copy auxiliary data to special region of m3 dmem
  78. * @data - pointer to data
  79. * @sz - size of data to copy (limit 256 bytes)
  80. *
  81. * Copies any additional blob of data to the wkup_m3 dmem to be used by the
  82. * firmware
  83. */
  84. static unsigned long wkup_m3_copy_aux_data(struct wkup_m3_ipc *m3_ipc,
  85. const void *data, int sz)
  86. {
  87. unsigned long aux_data_dev_addr;
  88. void *aux_data_addr;
  89. aux_data_dev_addr = WKUP_M3_DMEM_START + WKUP_M3_AUXDATA_OFFSET;
  90. aux_data_addr = rproc_da_to_va(m3_ipc->rproc,
  91. aux_data_dev_addr,
  92. WKUP_M3_AUXDATA_SIZE,
  93. NULL);
  94. memcpy(aux_data_addr, data, sz);
  95. return WKUP_M3_AUXDATA_OFFSET;
  96. }
  97. static void wkup_m3_scale_data_fw_cb(const struct firmware *fw, void *context)
  98. {
  99. unsigned long val, aux_base;
  100. struct wkup_m3_scale_data_header hdr;
  101. struct wkup_m3_ipc *m3_ipc = context;
  102. struct device *dev = m3_ipc->dev;
  103. if (!fw) {
  104. dev_err(dev, "Voltage scale fw name given but file missing.\n");
  105. return;
  106. }
  107. memcpy(&hdr, fw->data, sizeof(hdr));
  108. if (hdr.magic != WKUP_M3_SD_FW_MAGIC) {
  109. dev_err(dev, "PM: Voltage Scale Data binary does not appear valid.\n");
  110. goto release_sd_fw;
  111. }
  112. aux_base = wkup_m3_copy_aux_data(m3_ipc, fw->data + sizeof(hdr),
  113. fw->size - sizeof(hdr));
  114. val = (aux_base + hdr.sleep_offset);
  115. val |= ((aux_base + hdr.wake_offset) << 16);
  116. m3_ipc->volt_scale_offsets = val;
  117. release_sd_fw:
  118. release_firmware(fw);
  119. };
  120. static int wkup_m3_init_scale_data(struct wkup_m3_ipc *m3_ipc,
  121. struct device *dev)
  122. {
  123. int ret = 0;
  124. /*
  125. * If no name is provided, user has already been warned, pm will
  126. * still work so return 0
  127. */
  128. if (!m3_ipc->sd_fw_name)
  129. return ret;
  130. ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
  131. m3_ipc->sd_fw_name, dev, GFP_ATOMIC,
  132. m3_ipc, wkup_m3_scale_data_fw_cb);
  133. return ret;
  134. }
  135. #ifdef CONFIG_DEBUG_FS
  136. static void wkup_m3_set_halt_late(bool enabled)
  137. {
  138. if (enabled)
  139. m3_ipc_state->halt = (1 << IPC_DBG_HALT_SHIFT);
  140. else
  141. m3_ipc_state->halt = 0;
  142. }
  143. static int option_get(void *data, u64 *val)
  144. {
  145. u32 *option = data;
  146. *val = *option;
  147. return 0;
  148. }
  149. static int option_set(void *data, u64 val)
  150. {
  151. u32 *option = data;
  152. *option = val;
  153. if (option == &m3_ipc_state->halt) {
  154. if (val)
  155. wkup_m3_set_halt_late(true);
  156. else
  157. wkup_m3_set_halt_late(false);
  158. }
  159. return 0;
  160. }
  161. DEFINE_SIMPLE_ATTRIBUTE(wkup_m3_ipc_option_fops, option_get, option_set,
  162. "%llu\n");
  163. static int wkup_m3_ipc_dbg_init(struct wkup_m3_ipc *m3_ipc)
  164. {
  165. m3_ipc->dbg_path = debugfs_create_dir("wkup_m3_ipc", NULL);
  166. if (!m3_ipc->dbg_path)
  167. return -EINVAL;
  168. (void)debugfs_create_file("enable_late_halt", 0644,
  169. m3_ipc->dbg_path,
  170. &m3_ipc->halt,
  171. &wkup_m3_ipc_option_fops);
  172. return 0;
  173. }
  174. static inline void wkup_m3_ipc_dbg_destroy(struct wkup_m3_ipc *m3_ipc)
  175. {
  176. debugfs_remove_recursive(m3_ipc->dbg_path);
  177. }
  178. #else
  179. static inline int wkup_m3_ipc_dbg_init(struct wkup_m3_ipc *m3_ipc)
  180. {
  181. return 0;
  182. }
  183. static inline void wkup_m3_ipc_dbg_destroy(struct wkup_m3_ipc *m3_ipc)
  184. {
  185. }
  186. #endif /* CONFIG_DEBUG_FS */
  187. static void am33xx_txev_eoi(struct wkup_m3_ipc *m3_ipc)
  188. {
  189. writel(AM33XX_M3_TXEV_ACK,
  190. m3_ipc->ipc_mem_base + AM33XX_CONTROL_M3_TXEV_EOI);
  191. }
  192. static void am33xx_txev_enable(struct wkup_m3_ipc *m3_ipc)
  193. {
  194. writel(AM33XX_M3_TXEV_ENABLE,
  195. m3_ipc->ipc_mem_base + AM33XX_CONTROL_M3_TXEV_EOI);
  196. }
  197. static void wkup_m3_ctrl_ipc_write(struct wkup_m3_ipc *m3_ipc,
  198. u32 val, int ipc_reg_num)
  199. {
  200. if (WARN(ipc_reg_num < 0 || ipc_reg_num > AM33XX_CTRL_IPC_REG_COUNT,
  201. "ipc register operation out of range"))
  202. return;
  203. writel(val, m3_ipc->ipc_mem_base +
  204. AM33XX_CTRL_IPC_REG_OFFSET(ipc_reg_num));
  205. }
  206. static unsigned int wkup_m3_ctrl_ipc_read(struct wkup_m3_ipc *m3_ipc,
  207. int ipc_reg_num)
  208. {
  209. if (WARN(ipc_reg_num < 0 || ipc_reg_num > AM33XX_CTRL_IPC_REG_COUNT,
  210. "ipc register operation out of range"))
  211. return 0;
  212. return readl(m3_ipc->ipc_mem_base +
  213. AM33XX_CTRL_IPC_REG_OFFSET(ipc_reg_num));
  214. }
  215. static int wkup_m3_fw_version_read(struct wkup_m3_ipc *m3_ipc)
  216. {
  217. int val;
  218. val = wkup_m3_ctrl_ipc_read(m3_ipc, 2);
  219. return val & M3_FW_VERSION_MASK;
  220. }
  221. static irqreturn_t wkup_m3_txev_handler(int irq, void *ipc_data)
  222. {
  223. struct wkup_m3_ipc *m3_ipc = ipc_data;
  224. struct device *dev = m3_ipc->dev;
  225. int ver = 0;
  226. am33xx_txev_eoi(m3_ipc);
  227. switch (m3_ipc->state) {
  228. case M3_STATE_RESET:
  229. ver = wkup_m3_fw_version_read(m3_ipc);
  230. if (ver == M3_VERSION_UNKNOWN ||
  231. ver < M3_BASELINE_VERSION) {
  232. dev_warn(dev, "CM3 Firmware Version %x not supported\n",
  233. ver);
  234. } else {
  235. dev_info(dev, "CM3 Firmware Version = 0x%x\n", ver);
  236. }
  237. m3_ipc->state = M3_STATE_INITED;
  238. wkup_m3_init_scale_data(m3_ipc, dev);
  239. complete(&m3_ipc->sync_complete);
  240. break;
  241. case M3_STATE_MSG_FOR_RESET:
  242. m3_ipc->state = M3_STATE_INITED;
  243. complete(&m3_ipc->sync_complete);
  244. break;
  245. case M3_STATE_MSG_FOR_LP:
  246. complete(&m3_ipc->sync_complete);
  247. break;
  248. case M3_STATE_UNKNOWN:
  249. dev_warn(dev, "Unknown CM3 State\n");
  250. }
  251. am33xx_txev_enable(m3_ipc);
  252. return IRQ_HANDLED;
  253. }
  254. static int wkup_m3_ping(struct wkup_m3_ipc *m3_ipc)
  255. {
  256. struct device *dev = m3_ipc->dev;
  257. mbox_msg_t dummy_msg = 0;
  258. int ret;
  259. if (!m3_ipc->mbox) {
  260. dev_err(dev,
  261. "No IPC channel to communicate with wkup_m3!\n");
  262. return -EIO;
  263. }
  264. /*
  265. * Write a dummy message to the mailbox in order to trigger the RX
  266. * interrupt to alert the M3 that data is available in the IPC
  267. * registers. We must enable the IRQ here and disable it after in
  268. * the RX callback to avoid multiple interrupts being received
  269. * by the CM3.
  270. */
  271. ret = mbox_send_message(m3_ipc->mbox, &dummy_msg);
  272. if (ret < 0) {
  273. dev_err(dev, "%s: mbox_send_message() failed: %d\n",
  274. __func__, ret);
  275. return ret;
  276. }
  277. ret = wait_for_completion_timeout(&m3_ipc->sync_complete,
  278. msecs_to_jiffies(500));
  279. if (!ret) {
  280. dev_err(dev, "MPU<->CM3 sync failure\n");
  281. m3_ipc->state = M3_STATE_UNKNOWN;
  282. return -EIO;
  283. }
  284. mbox_client_txdone(m3_ipc->mbox, 0);
  285. return 0;
  286. }
  287. static int wkup_m3_ping_noirq(struct wkup_m3_ipc *m3_ipc)
  288. {
  289. struct device *dev = m3_ipc->dev;
  290. mbox_msg_t dummy_msg = 0;
  291. int ret;
  292. if (!m3_ipc->mbox) {
  293. dev_err(dev,
  294. "No IPC channel to communicate with wkup_m3!\n");
  295. return -EIO;
  296. }
  297. ret = mbox_send_message(m3_ipc->mbox, &dummy_msg);
  298. if (ret < 0) {
  299. dev_err(dev, "%s: mbox_send_message() failed: %d\n",
  300. __func__, ret);
  301. return ret;
  302. }
  303. mbox_client_txdone(m3_ipc->mbox, 0);
  304. return 0;
  305. }
  306. static int wkup_m3_is_available(struct wkup_m3_ipc *m3_ipc)
  307. {
  308. return ((m3_ipc->state != M3_STATE_RESET) &&
  309. (m3_ipc->state != M3_STATE_UNKNOWN));
  310. }
  311. static void wkup_m3_set_vtt_gpio(struct wkup_m3_ipc *m3_ipc, int gpio)
  312. {
  313. m3_ipc->vtt_conf = (1 << IPC_VTT_STAT_SHIFT) |
  314. (gpio << IPC_VTT_GPIO_PIN_SHIFT);
  315. }
  316. static void wkup_m3_set_io_isolation(struct wkup_m3_ipc *m3_ipc)
  317. {
  318. m3_ipc->isolation_conf = (1 << IPC_IO_ISOLATION_STAT_SHIFT);
  319. }
  320. /* Public functions */
  321. /**
  322. * wkup_m3_set_mem_type - Pass wkup_m3 which type of memory is in use
  323. * @m3_ipc: Pointer to wkup_m3_ipc context
  324. * @mem_type: memory type value read directly from emif
  325. *
  326. * wkup_m3 must know what memory type is in use to properly suspend
  327. * and resume.
  328. */
  329. static void wkup_m3_set_mem_type(struct wkup_m3_ipc *m3_ipc, int mem_type)
  330. {
  331. m3_ipc->mem_type = mem_type;
  332. }
  333. /**
  334. * wkup_m3_set_resume_address - Pass wkup_m3 resume address
  335. * @m3_ipc: Pointer to wkup_m3_ipc context
  336. * @addr: Physical address from which resume code should execute
  337. */
  338. static void wkup_m3_set_resume_address(struct wkup_m3_ipc *m3_ipc, void *addr)
  339. {
  340. m3_ipc->resume_addr = (unsigned long)addr;
  341. }
  342. /**
  343. * wkup_m3_request_pm_status - Retrieve wkup_m3 status code after suspend
  344. * @m3_ipc: Pointer to wkup_m3_ipc context
  345. *
  346. * Returns code representing the status of a low power mode transition.
  347. * 0 - Successful transition
  348. * 1 - Failure to transition to low power state
  349. */
  350. static int wkup_m3_request_pm_status(struct wkup_m3_ipc *m3_ipc)
  351. {
  352. unsigned int i;
  353. int val;
  354. val = wkup_m3_ctrl_ipc_read(m3_ipc, 1);
  355. i = M3_STATUS_RESP_MASK & val;
  356. i >>= __ffs(M3_STATUS_RESP_MASK);
  357. return i;
  358. }
  359. /**
  360. * wkup_m3_prepare_low_power - Request preparation for transition to
  361. * low power state
  362. * @m3_ipc: Pointer to wkup_m3_ipc context
  363. * @state: A kernel suspend state to enter, either MEM or STANDBY
  364. *
  365. * Returns 0 if preparation was successful, otherwise returns error code
  366. */
  367. static int wkup_m3_prepare_low_power(struct wkup_m3_ipc *m3_ipc, int state)
  368. {
  369. struct device *dev = m3_ipc->dev;
  370. int m3_power_state;
  371. int ret = 0;
  372. if (!wkup_m3_is_available(m3_ipc))
  373. return -ENODEV;
  374. switch (state) {
  375. case WKUP_M3_DEEPSLEEP:
  376. m3_power_state = IPC_CMD_DS0;
  377. wkup_m3_ctrl_ipc_write(m3_ipc, m3_ipc->volt_scale_offsets, 5);
  378. break;
  379. case WKUP_M3_STANDBY:
  380. m3_power_state = IPC_CMD_STANDBY;
  381. wkup_m3_ctrl_ipc_write(m3_ipc, DS_IPC_DEFAULT, 5);
  382. break;
  383. case WKUP_M3_IDLE:
  384. m3_power_state = IPC_CMD_IDLE;
  385. wkup_m3_ctrl_ipc_write(m3_ipc, DS_IPC_DEFAULT, 5);
  386. break;
  387. default:
  388. return 1;
  389. }
  390. /* Program each required IPC register then write defaults to others */
  391. wkup_m3_ctrl_ipc_write(m3_ipc, m3_ipc->resume_addr, 0);
  392. wkup_m3_ctrl_ipc_write(m3_ipc, m3_power_state, 1);
  393. wkup_m3_ctrl_ipc_write(m3_ipc, m3_ipc->mem_type |
  394. m3_ipc->vtt_conf |
  395. m3_ipc->isolation_conf |
  396. m3_ipc->halt, 4);
  397. wkup_m3_ctrl_ipc_write(m3_ipc, DS_IPC_DEFAULT, 2);
  398. wkup_m3_ctrl_ipc_write(m3_ipc, DS_IPC_DEFAULT, 3);
  399. wkup_m3_ctrl_ipc_write(m3_ipc, DS_IPC_DEFAULT, 6);
  400. wkup_m3_ctrl_ipc_write(m3_ipc, DS_IPC_DEFAULT, 7);
  401. m3_ipc->state = M3_STATE_MSG_FOR_LP;
  402. if (state == WKUP_M3_IDLE)
  403. ret = wkup_m3_ping_noirq(m3_ipc);
  404. else
  405. ret = wkup_m3_ping(m3_ipc);
  406. if (ret) {
  407. dev_err(dev, "Unable to ping CM3\n");
  408. return ret;
  409. }
  410. return 0;
  411. }
  412. /**
  413. * wkup_m3_finish_low_power - Return m3 to reset state
  414. * @m3_ipc: Pointer to wkup_m3_ipc context
  415. *
  416. * Returns 0 if reset was successful, otherwise returns error code
  417. */
  418. static int wkup_m3_finish_low_power(struct wkup_m3_ipc *m3_ipc)
  419. {
  420. struct device *dev = m3_ipc->dev;
  421. int ret = 0;
  422. if (!wkup_m3_is_available(m3_ipc))
  423. return -ENODEV;
  424. wkup_m3_ctrl_ipc_write(m3_ipc, IPC_CMD_RESET, 1);
  425. wkup_m3_ctrl_ipc_write(m3_ipc, DS_IPC_DEFAULT, 2);
  426. m3_ipc->state = M3_STATE_MSG_FOR_RESET;
  427. ret = wkup_m3_ping(m3_ipc);
  428. if (ret) {
  429. dev_err(dev, "Unable to ping CM3\n");
  430. return ret;
  431. }
  432. return 0;
  433. }
  434. /**
  435. * wkup_m3_request_wake_src - Get the wakeup source info passed from wkup_m3
  436. * @m3_ipc: Pointer to wkup_m3_ipc context
  437. */
  438. static const char *wkup_m3_request_wake_src(struct wkup_m3_ipc *m3_ipc)
  439. {
  440. unsigned int wakeup_src_idx;
  441. int j, val;
  442. val = wkup_m3_ctrl_ipc_read(m3_ipc, 6);
  443. wakeup_src_idx = val & M3_WAKE_SRC_MASK;
  444. for (j = 0; j < ARRAY_SIZE(wakeups) - 1; j++) {
  445. if (wakeups[j].irq_nr == wakeup_src_idx)
  446. return wakeups[j].src;
  447. }
  448. return wakeups[j].src;
  449. }
  450. /**
  451. * wkup_m3_set_rtc_only - Set the rtc_only flag
  452. * @m3_ipc: Pointer to wkup_m3_ipc context
  453. */
  454. static void wkup_m3_set_rtc_only(struct wkup_m3_ipc *m3_ipc)
  455. {
  456. if (m3_ipc_state)
  457. m3_ipc_state->is_rtc_only = true;
  458. }
  459. static struct wkup_m3_ipc_ops ipc_ops = {
  460. .set_mem_type = wkup_m3_set_mem_type,
  461. .set_resume_address = wkup_m3_set_resume_address,
  462. .prepare_low_power = wkup_m3_prepare_low_power,
  463. .finish_low_power = wkup_m3_finish_low_power,
  464. .request_pm_status = wkup_m3_request_pm_status,
  465. .request_wake_src = wkup_m3_request_wake_src,
  466. .set_rtc_only = wkup_m3_set_rtc_only,
  467. };
  468. /**
  469. * wkup_m3_ipc_get - Return handle to wkup_m3_ipc
  470. *
  471. * Returns NULL if the wkup_m3 is not yet available, otherwise returns
  472. * pointer to wkup_m3_ipc struct.
  473. */
  474. struct wkup_m3_ipc *wkup_m3_ipc_get(void)
  475. {
  476. if (m3_ipc_state)
  477. get_device(m3_ipc_state->dev);
  478. else
  479. return NULL;
  480. return m3_ipc_state;
  481. }
  482. EXPORT_SYMBOL_GPL(wkup_m3_ipc_get);
  483. /**
  484. * wkup_m3_ipc_put - Free handle to wkup_m3_ipc returned from wkup_m3_ipc_get
  485. * @m3_ipc: A pointer to wkup_m3_ipc struct returned by wkup_m3_ipc_get
  486. */
  487. void wkup_m3_ipc_put(struct wkup_m3_ipc *m3_ipc)
  488. {
  489. if (m3_ipc_state)
  490. put_device(m3_ipc_state->dev);
  491. }
  492. EXPORT_SYMBOL_GPL(wkup_m3_ipc_put);
  493. static int wkup_m3_rproc_boot_thread(void *arg)
  494. {
  495. struct wkup_m3_ipc *m3_ipc = arg;
  496. struct device *dev = m3_ipc->dev;
  497. int ret;
  498. init_completion(&m3_ipc->sync_complete);
  499. ret = rproc_boot(m3_ipc->rproc);
  500. if (ret)
  501. dev_err(dev, "rproc_boot failed\n");
  502. else
  503. m3_ipc_state = m3_ipc;
  504. return 0;
  505. }
  506. static int wkup_m3_ipc_probe(struct platform_device *pdev)
  507. {
  508. struct device *dev = &pdev->dev;
  509. int irq, ret, temp;
  510. phandle rproc_phandle;
  511. struct rproc *m3_rproc;
  512. struct resource *res;
  513. struct task_struct *task;
  514. struct wkup_m3_ipc *m3_ipc;
  515. struct device_node *np = dev->of_node;
  516. m3_ipc = devm_kzalloc(dev, sizeof(*m3_ipc), GFP_KERNEL);
  517. if (!m3_ipc)
  518. return -ENOMEM;
  519. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  520. m3_ipc->ipc_mem_base = devm_ioremap_resource(dev, res);
  521. if (IS_ERR(m3_ipc->ipc_mem_base))
  522. return PTR_ERR(m3_ipc->ipc_mem_base);
  523. irq = platform_get_irq(pdev, 0);
  524. if (irq < 0)
  525. return irq;
  526. ret = devm_request_irq(dev, irq, wkup_m3_txev_handler,
  527. 0, "wkup_m3_txev", m3_ipc);
  528. if (ret) {
  529. dev_err(dev, "request_irq failed\n");
  530. return ret;
  531. }
  532. m3_ipc->mbox_client.dev = dev;
  533. m3_ipc->mbox_client.tx_done = NULL;
  534. m3_ipc->mbox_client.tx_prepare = NULL;
  535. m3_ipc->mbox_client.rx_callback = NULL;
  536. m3_ipc->mbox_client.tx_block = false;
  537. m3_ipc->mbox_client.knows_txdone = false;
  538. m3_ipc->mbox = mbox_request_channel(&m3_ipc->mbox_client, 0);
  539. if (IS_ERR(m3_ipc->mbox)) {
  540. dev_err(dev, "IPC Request for A8->M3 Channel failed! %ld\n",
  541. PTR_ERR(m3_ipc->mbox));
  542. return PTR_ERR(m3_ipc->mbox);
  543. }
  544. if (of_property_read_u32(dev->of_node, "ti,rproc", &rproc_phandle)) {
  545. dev_err(&pdev->dev, "could not get rproc phandle\n");
  546. ret = -ENODEV;
  547. goto err_free_mbox;
  548. }
  549. m3_rproc = rproc_get_by_phandle(rproc_phandle);
  550. if (!m3_rproc) {
  551. dev_err(&pdev->dev, "could not get rproc handle\n");
  552. ret = -EPROBE_DEFER;
  553. goto err_free_mbox;
  554. }
  555. m3_ipc->rproc = m3_rproc;
  556. m3_ipc->dev = dev;
  557. m3_ipc->state = M3_STATE_RESET;
  558. m3_ipc->ops = &ipc_ops;
  559. if (!of_property_read_u32(np, "ti,vtt-gpio-pin", &temp)) {
  560. if (temp >= 0 && temp <= 31)
  561. wkup_m3_set_vtt_gpio(m3_ipc, temp);
  562. else
  563. dev_warn(dev, "Invalid VTT GPIO(%d) pin\n", temp);
  564. }
  565. if (of_find_property(np, "ti,set-io-isolation", NULL))
  566. wkup_m3_set_io_isolation(m3_ipc);
  567. ret = of_property_read_string(np, "firmware-name",
  568. &m3_ipc->sd_fw_name);
  569. if (ret) {
  570. dev_dbg(dev, "Voltage scaling data blob not provided from DT.\n");
  571. }
  572. /*
  573. * Wait for firmware loading completion in a thread so we
  574. * can boot the wkup_m3 as soon as it's ready without holding
  575. * up kernel boot
  576. */
  577. task = kthread_run(wkup_m3_rproc_boot_thread, m3_ipc,
  578. "wkup_m3_rproc_loader");
  579. if (IS_ERR(task)) {
  580. dev_err(dev, "can't create rproc_boot thread\n");
  581. ret = PTR_ERR(task);
  582. goto err_put_rproc;
  583. }
  584. wkup_m3_ipc_dbg_init(m3_ipc);
  585. return 0;
  586. err_put_rproc:
  587. rproc_put(m3_rproc);
  588. err_free_mbox:
  589. mbox_free_channel(m3_ipc->mbox);
  590. return ret;
  591. }
  592. static int wkup_m3_ipc_remove(struct platform_device *pdev)
  593. {
  594. wkup_m3_ipc_dbg_destroy(m3_ipc_state);
  595. mbox_free_channel(m3_ipc_state->mbox);
  596. rproc_shutdown(m3_ipc_state->rproc);
  597. rproc_put(m3_ipc_state->rproc);
  598. m3_ipc_state = NULL;
  599. return 0;
  600. }
  601. static int __maybe_unused wkup_m3_ipc_suspend(struct device *dev)
  602. {
  603. /*
  604. * Nothing needs to be done on suspend even with rtc_only flag set
  605. */
  606. return 0;
  607. }
  608. static int __maybe_unused wkup_m3_ipc_resume(struct device *dev)
  609. {
  610. if (m3_ipc_state->is_rtc_only) {
  611. rproc_shutdown(m3_ipc_state->rproc);
  612. rproc_boot(m3_ipc_state->rproc);
  613. }
  614. m3_ipc_state->is_rtc_only = false;
  615. return 0;
  616. }
  617. static const struct dev_pm_ops wkup_m3_ipc_pm_ops = {
  618. SET_SYSTEM_SLEEP_PM_OPS(wkup_m3_ipc_suspend, wkup_m3_ipc_resume)
  619. };
  620. static const struct of_device_id wkup_m3_ipc_of_match[] = {
  621. { .compatible = "ti,am3352-wkup-m3-ipc", },
  622. { .compatible = "ti,am4372-wkup-m3-ipc", },
  623. {},
  624. };
  625. MODULE_DEVICE_TABLE(of, wkup_m3_ipc_of_match);
  626. static struct platform_driver wkup_m3_ipc_driver = {
  627. .probe = wkup_m3_ipc_probe,
  628. .remove = wkup_m3_ipc_remove,
  629. .driver = {
  630. .name = "wkup_m3_ipc",
  631. .of_match_table = wkup_m3_ipc_of_match,
  632. .pm = &wkup_m3_ipc_pm_ops,
  633. },
  634. };
  635. module_platform_driver(wkup_m3_ipc_driver);
  636. MODULE_LICENSE("GPL v2");
  637. MODULE_DESCRIPTION("wkup m3 remote processor ipc driver");
  638. MODULE_AUTHOR("Dave Gerlach <[email protected]>");