xref: /linux/drivers/remoteproc/ti_k3_m4_remoteproc.c (revision e78f70bad29c5ae1e1076698b690b15794e9b81e)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * TI K3 Cortex-M4 Remote Processor(s) driver
4  *
5  * Copyright (C) 2021-2024 Texas Instruments Incorporated - https://www.ti.com/
6  *	Hari Nagalla <hnagalla@ti.com>
7  */
8 
9 #include <linux/io.h>
10 #include <linux/mailbox_client.h>
11 #include <linux/module.h>
12 #include <linux/of_address.h>
13 #include <linux/of_reserved_mem.h>
14 #include <linux/platform_device.h>
15 #include <linux/remoteproc.h>
16 #include <linux/reset.h>
17 #include <linux/slab.h>
18 
19 #include "omap_remoteproc.h"
20 #include "remoteproc_internal.h"
21 #include "ti_sci_proc.h"
22 #include "ti_k3_common.h"
23 
24 static const struct rproc_ops k3_m4_rproc_ops = {
25 	.prepare = k3_rproc_prepare,
26 	.unprepare = k3_rproc_unprepare,
27 	.start = k3_rproc_start,
28 	.stop = k3_rproc_stop,
29 	.attach = k3_rproc_attach,
30 	.detach = k3_rproc_detach,
31 	.kick = k3_rproc_kick,
32 	.da_to_va = k3_rproc_da_to_va,
33 	.get_loaded_rsc_table = k3_get_loaded_rsc_table,
34 };
35 
36 static int k3_m4_rproc_probe(struct platform_device *pdev)
37 {
38 	const struct k3_rproc_dev_data *data;
39 	struct device *dev = &pdev->dev;
40 	struct k3_rproc *kproc;
41 	struct rproc *rproc;
42 	const char *fw_name;
43 	bool r_state = false;
44 	bool p_state = false;
45 	int ret;
46 
47 	data = of_device_get_match_data(dev);
48 	if (!data)
49 		return -ENODEV;
50 
51 	ret = rproc_of_parse_firmware(dev, 0, &fw_name);
52 	if (ret)
53 		return dev_err_probe(dev, ret, "failed to parse firmware-name property\n");
54 
55 	rproc = devm_rproc_alloc(dev, dev_name(dev), &k3_m4_rproc_ops, fw_name,
56 				 sizeof(*kproc));
57 	if (!rproc)
58 		return -ENOMEM;
59 
60 	rproc->has_iommu = false;
61 	rproc->recovery_disabled = true;
62 	kproc = rproc->priv;
63 	kproc->dev = dev;
64 	kproc->rproc = rproc;
65 	kproc->data = data;
66 	platform_set_drvdata(pdev, rproc);
67 
68 	kproc->ti_sci = devm_ti_sci_get_by_phandle(dev, "ti,sci");
69 	if (IS_ERR(kproc->ti_sci))
70 		return dev_err_probe(dev, PTR_ERR(kproc->ti_sci),
71 				     "failed to get ti-sci handle\n");
72 
73 	ret = of_property_read_u32(dev->of_node, "ti,sci-dev-id", &kproc->ti_sci_id);
74 	if (ret)
75 		return dev_err_probe(dev, ret, "missing 'ti,sci-dev-id' property\n");
76 
77 	kproc->reset = devm_reset_control_get_exclusive(dev, NULL);
78 	if (IS_ERR(kproc->reset))
79 		return dev_err_probe(dev, PTR_ERR(kproc->reset), "failed to get reset\n");
80 
81 	kproc->tsp = ti_sci_proc_of_get_tsp(dev, kproc->ti_sci);
82 	if (IS_ERR(kproc->tsp))
83 		return dev_err_probe(dev, PTR_ERR(kproc->tsp),
84 				     "failed to construct ti-sci proc control\n");
85 
86 	ret = ti_sci_proc_request(kproc->tsp);
87 	if (ret < 0)
88 		return dev_err_probe(dev, ret, "ti_sci_proc_request failed\n");
89 	ret = devm_add_action_or_reset(dev, k3_release_tsp, kproc->tsp);
90 	if (ret)
91 		return ret;
92 
93 	ret = k3_rproc_of_get_memories(pdev, kproc);
94 	if (ret)
95 		return ret;
96 
97 	ret = k3_reserved_mem_init(kproc);
98 	if (ret)
99 		return dev_err_probe(dev, ret, "reserved memory init failed\n");
100 
101 	ret = kproc->ti_sci->ops.dev_ops.is_on(kproc->ti_sci, kproc->ti_sci_id,
102 					       &r_state, &p_state);
103 	if (ret)
104 		return dev_err_probe(dev, ret,
105 				     "failed to get initial state, mode cannot be determined\n");
106 
107 	/* configure devices for either remoteproc or IPC-only mode */
108 	if (p_state) {
109 		rproc->state = RPROC_DETACHED;
110 		dev_info(dev, "configured M4F for IPC-only mode\n");
111 	} else {
112 		dev_info(dev, "configured M4F for remoteproc mode\n");
113 	}
114 
115 	ret = k3_rproc_request_mbox(rproc);
116 	if (ret)
117 		return ret;
118 
119 	ret = devm_rproc_add(dev, rproc);
120 	if (ret)
121 		return dev_err_probe(dev, ret,
122 				     "failed to register device with remoteproc core\n");
123 
124 	return 0;
125 }
126 
127 static const struct k3_rproc_mem_data am64_m4_mems[] = {
128 	{ .name = "iram", .dev_addr = 0x0 },
129 	{ .name = "dram", .dev_addr = 0x30000 },
130 };
131 
132 static const struct k3_rproc_dev_data am64_m4_data = {
133 	.mems = am64_m4_mems,
134 	.num_mems = ARRAY_SIZE(am64_m4_mems),
135 	.boot_align_addr = SZ_1K,
136 	.uses_lreset = true,
137 };
138 
139 static const struct of_device_id k3_m4_of_match[] = {
140 	{ .compatible = "ti,am64-m4fss", .data = &am64_m4_data, },
141 	{ /* sentinel */ },
142 };
143 MODULE_DEVICE_TABLE(of, k3_m4_of_match);
144 
145 static struct platform_driver k3_m4_rproc_driver = {
146 	.probe	= k3_m4_rproc_probe,
147 	.driver	= {
148 		.name = "k3-m4-rproc",
149 		.of_match_table = k3_m4_of_match,
150 	},
151 };
152 module_platform_driver(k3_m4_rproc_driver);
153 
154 MODULE_AUTHOR("Hari Nagalla <hnagalla@ti.com>");
155 MODULE_DESCRIPTION("TI K3 M4 Remoteproc driver");
156 MODULE_LICENSE("GPL");
157