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