1
2
3
4
5#define pr_fmt(fmt) "%s: " fmt, __func__
6#include <common.h>
7#include <dm.h>
8#include <errno.h>
9#include <fdtdec.h>
10#include <log.h>
11#include <remoteproc.h>
12#include <reset.h>
13#include <asm/io.h>
14#include <dm/device_compat.h>
15#include <linux/err.h>
16
17
18
19
20
21
22
23struct stm32_copro_privdata {
24 struct reset_ctl reset_ctl;
25 struct reset_ctl hold_boot;
26 ulong rsc_table_addr;
27};
28
29
30
31
32
33
34static int stm32_copro_probe(struct udevice *dev)
35{
36 struct stm32_copro_privdata *priv;
37 int ret;
38
39 priv = dev_get_priv(dev);
40
41 ret = reset_get_by_name(dev, "mcu_rst", &priv->reset_ctl);
42 if (ret) {
43 dev_err(dev, "failed to get reset (%d)\n", ret);
44 return ret;
45 }
46
47 ret = reset_get_by_name(dev, "hold_boot", &priv->hold_boot);
48 if (ret) {
49 dev_err(dev, "failed to get hold boot (%d)\n", ret);
50 return ret;
51 }
52
53 dev_dbg(dev, "probed\n");
54
55 return 0;
56}
57
58
59
60
61
62
63
64
65static void *stm32_copro_device_to_virt(struct udevice *dev, ulong da,
66 ulong size)
67{
68 fdt32_t in_addr = cpu_to_be32(da), end_addr;
69 u64 paddr;
70
71 paddr = dev_translate_dma_address(dev, &in_addr);
72 if (paddr == OF_BAD_ADDR) {
73 dev_err(dev, "Unable to convert address %ld\n", da);
74 return NULL;
75 }
76
77 end_addr = cpu_to_be32(da + size - 1);
78 if (dev_translate_dma_address(dev, &end_addr) == OF_BAD_ADDR) {
79 dev_err(dev, "Unable to convert address %ld\n", da + size - 1);
80 return NULL;
81 }
82
83 return phys_to_virt(paddr);
84}
85
86
87
88
89
90
91
92
93static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size)
94{
95 struct stm32_copro_privdata *priv;
96 ulong rsc_table_size;
97 int ret;
98
99 priv = dev_get_priv(dev);
100
101 ret = reset_assert(&priv->hold_boot);
102 if (ret) {
103 dev_err(dev, "Unable to assert hold boot (ret=%d)\n", ret);
104 return ret;
105 }
106
107 ret = reset_assert(&priv->reset_ctl);
108 if (ret) {
109 dev_err(dev, "Unable to assert reset line (ret=%d)\n", ret);
110 return ret;
111 }
112
113 if (rproc_elf32_load_rsc_table(dev, addr, size, &priv->rsc_table_addr,
114 &rsc_table_size)) {
115 priv->rsc_table_addr = 0;
116 dev_warn(dev, "No valid resource table for this firmware\n");
117 }
118
119 return rproc_elf32_load_image(dev, addr, size);
120}
121
122
123
124
125
126
127static int stm32_copro_start(struct udevice *dev)
128{
129 struct stm32_copro_privdata *priv;
130 int ret;
131
132 priv = dev_get_priv(dev);
133
134 ret = reset_deassert(&priv->hold_boot);
135 if (ret) {
136 dev_err(dev, "Unable to deassert hold boot (ret=%d)\n", ret);
137 return ret;
138 }
139
140
141
142
143
144 ret = reset_assert(&priv->hold_boot);
145 if (ret)
146 dev_err(dev, "Unable to assert hold boot (ret=%d)\n", ret);
147
148
149 writel(TAMP_COPRO_STATE_CRUN, TAMP_COPRO_STATE);
150
151 writel(priv->rsc_table_addr, TAMP_COPRO_RSC_TBL_ADDRESS);
152
153 return 0;
154}
155
156
157
158
159
160
161static int stm32_copro_reset(struct udevice *dev)
162{
163 struct stm32_copro_privdata *priv;
164 int ret;
165
166 priv = dev_get_priv(dev);
167
168 ret = reset_assert(&priv->hold_boot);
169 if (ret) {
170 dev_err(dev, "Unable to assert hold boot (ret=%d)\n", ret);
171 return ret;
172 }
173
174 ret = reset_assert(&priv->reset_ctl);
175 if (ret) {
176 dev_err(dev, "Unable to assert reset line (ret=%d)\n", ret);
177 return ret;
178 }
179
180 writel(TAMP_COPRO_STATE_OFF, TAMP_COPRO_STATE);
181
182 return 0;
183}
184
185
186
187
188
189
190static int stm32_copro_stop(struct udevice *dev)
191{
192 return stm32_copro_reset(dev);
193}
194
195
196
197
198
199
200static int stm32_copro_is_running(struct udevice *dev)
201{
202 return (readl(TAMP_COPRO_STATE) == TAMP_COPRO_STATE_OFF);
203}
204
205static const struct dm_rproc_ops stm32_copro_ops = {
206 .load = stm32_copro_load,
207 .start = stm32_copro_start,
208 .stop = stm32_copro_stop,
209 .reset = stm32_copro_reset,
210 .is_running = stm32_copro_is_running,
211 .device_to_virt = stm32_copro_device_to_virt,
212};
213
214static const struct udevice_id stm32_copro_ids[] = {
215 {.compatible = "st,stm32mp1-m4"},
216 {}
217};
218
219U_BOOT_DRIVER(stm32_copro) = {
220 .name = "stm32_m4_proc",
221 .of_match = stm32_copro_ids,
222 .id = UCLASS_REMOTEPROC,
223 .ops = &stm32_copro_ops,
224 .probe = stm32_copro_probe,
225 .priv_auto_alloc_size = sizeof(struct stm32_copro_privdata),
226};
227