dm: core: Require users of devres to include the header
[oweals/u-boot.git] / drivers / remoteproc / ti_k3_arm64_rproc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Texas Instruments' K3 ARM64 Remoteproc driver
4  *
5  * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
6  *      Lokesh Vutla <lokeshvutla@ti.com>
7  *
8  */
9
10 #include <common.h>
11 #include <dm.h>
12 #include <remoteproc.h>
13 #include <errno.h>
14 #include <clk.h>
15 #include <reset.h>
16 #include <asm/io.h>
17 #include <power-domain.h>
18 #include <linux/err.h>
19 #include <linux/soc/ti/ti_sci_protocol.h>
20 #include "ti_sci_proc.h"
21
22 #define INVALID_ID      0xffff
23
24 #define GTC_CNTCR_REG   0x0
25 #define GTC_CNTR_EN     0x3
26
27 /**
28  * struct k3_arm64_privdata - Structure representing Remote processor data.
29  * @rproc_pwrdmn:       rproc power domain data
30  * @rproc_rst:          rproc reset control data
31  * @sci:                Pointer to TISCI handle
32  * @tsp:                TISCI processor control helper structure
33  * @gtc_base:           Timer base address.
34  */
35 struct k3_arm64_privdata {
36         struct power_domain rproc_pwrdmn;
37         struct power_domain gtc_pwrdmn;
38         struct reset_ctl rproc_rst;
39         struct ti_sci_proc tsp;
40         void *gtc_base;
41 };
42
43 /**
44  * k3_arm64_load() - Load up the Remote processor image
45  * @dev:        rproc device pointer
46  * @addr:       Address at which image is available
47  * @size:       size of the image
48  *
49  * Return: 0 if all goes good, else appropriate error message.
50  */
51 static int k3_arm64_load(struct udevice *dev, ulong addr, ulong size)
52 {
53         struct k3_arm64_privdata *rproc = dev_get_priv(dev);
54         int ret;
55
56         dev_dbg(dev, "%s addr = 0x%lx, size = 0x%lx\n", __func__, addr, size);
57
58         /* request for the processor */
59         ret = ti_sci_proc_request(&rproc->tsp);
60         if (ret)
61                 return ret;
62
63         return ti_sci_proc_set_config(&rproc->tsp, addr, 0, 0);
64 }
65
66 /**
67  * k3_arm64_start() - Start the remote processor
68  * @dev:        rproc device pointer
69  *
70  * Return: 0 if all went ok, else return appropriate error
71  */
72 static int k3_arm64_start(struct udevice *dev)
73 {
74         struct k3_arm64_privdata *rproc = dev_get_priv(dev);
75         int ret;
76
77         dev_dbg(dev, "%s\n", __func__);
78
79         ret = power_domain_on(&rproc->gtc_pwrdmn);
80         if (ret) {
81                 dev_err(dev, "power_domain_on() failed: %d\n", ret);
82                 return ret;
83         }
84
85         /* Enable the timer before starting remote core */
86         writel(GTC_CNTR_EN, rproc->gtc_base + GTC_CNTCR_REG);
87
88         /*
89          * Setting the right clock frequency would have taken care by
90          * assigned-clock-rates during the device probe. So no need to
91          * set the frequency again here.
92          */
93         ret = power_domain_on(&rproc->rproc_pwrdmn);
94         if (ret) {
95                 dev_err(dev, "power_domain_on() failed: %d\n", ret);
96                 return ret;
97         }
98
99         return ti_sci_proc_release(&rproc->tsp);
100 }
101
102 /**
103  * k3_arm64_init() - Initialize the remote processor
104  * @dev:        rproc device pointer
105  *
106  * Return: 0 if all went ok, else return appropriate error
107  */
108 static int k3_arm64_init(struct udevice *dev)
109 {
110         dev_dbg(dev, "%s\n", __func__);
111
112         /* Enable the module */
113         dev_dbg(dev, "%s: rproc successfully initialized\n", __func__);
114
115         return 0;
116 }
117
118 static const struct dm_rproc_ops k3_arm64_ops = {
119         .init = k3_arm64_init,
120         .load = k3_arm64_load,
121         .start = k3_arm64_start,
122 };
123
124 static int ti_sci_proc_of_to_priv(struct udevice *dev, struct ti_sci_proc *tsp)
125 {
126         dev_dbg(dev, "%s\n", __func__);
127
128         tsp->sci = ti_sci_get_by_phandle(dev, "ti,sci");
129         if (IS_ERR(tsp->sci)) {
130                 dev_err(dev, "ti_sci get failed: %ld\n", PTR_ERR(tsp->sci));
131                 return PTR_ERR(tsp->sci);
132         }
133
134         tsp->proc_id = dev_read_u32_default(dev, "ti,sci-proc-id", INVALID_ID);
135         if (tsp->proc_id == INVALID_ID) {
136                 dev_err(dev, "proc id not populated\n");
137                 return -ENOENT;
138         }
139         tsp->host_id = dev_read_u32_default(dev, "ti,sci-host-id", INVALID_ID);
140         tsp->ops = &tsp->sci->ops.proc_ops;
141
142         return 0;
143 }
144
145 /**
146  * k3_of_to_priv() - generate private data from device tree
147  * @dev:        corresponding k3 remote processor device
148  * @priv:       pointer to driver specific private data
149  *
150  * Return: 0 if all goes good, else appropriate error message.
151  */
152 static int k3_arm64_of_to_priv(struct udevice *dev,
153                                struct k3_arm64_privdata *rproc)
154 {
155         int ret;
156
157         dev_dbg(dev, "%s\n", __func__);
158
159         ret = power_domain_get_by_index(dev, &rproc->rproc_pwrdmn, 1);
160         if (ret) {
161                 dev_err(dev, "power_domain_get() failed: %d\n", ret);
162                 return ret;
163         }
164
165         ret = power_domain_get_by_index(dev, &rproc->gtc_pwrdmn, 0);
166         if (ret) {
167                 dev_err(dev, "power_domain_get() failed: %d\n", ret);
168                 return ret;
169         }
170
171         ret = reset_get_by_index(dev, 0, &rproc->rproc_rst);
172         if (ret) {
173                 dev_err(dev, "reset_get() failed: %d\n", ret);
174                 return ret;
175         }
176
177         ret = ti_sci_proc_of_to_priv(dev, &rproc->tsp);
178         if (ret)
179                 return ret;
180
181         rproc->gtc_base = dev_read_addr_ptr(dev);
182         if (!rproc->gtc_base) {
183                 dev_err(dev, "Get address failed\n");
184                 return -ENODEV;
185         }
186
187         return 0;
188 }
189
190 /**
191  * k3_arm64_probe() - Basic probe
192  * @dev:        corresponding k3 remote processor device
193  *
194  * Return: 0 if all goes good, else appropriate error message.
195  */
196 static int k3_arm64_probe(struct udevice *dev)
197 {
198         struct k3_arm64_privdata *priv;
199         int ret;
200
201         dev_dbg(dev, "%s\n", __func__);
202
203         priv = dev_get_priv(dev);
204
205         ret = k3_arm64_of_to_priv(dev, priv);
206         if (ret) {
207                 dev_dbg(dev, "%s: Probe failed with error %d\n", __func__, ret);
208                 return ret;
209         }
210
211         dev_dbg(dev, "Remoteproc successfully probed\n");
212
213         return 0;
214 }
215
216 static const struct udevice_id k3_arm64_ids[] = {
217         { .compatible = "ti,am654-arm64"},
218         { .compatible = "ti,am654-rproc"},
219         {}
220 };
221
222 U_BOOT_DRIVER(k3_arm64) = {
223         .name = "k3_arm64",
224         .of_match = k3_arm64_ids,
225         .id = UCLASS_REMOTEPROC,
226         .ops = &k3_arm64_ops,
227         .probe = k3_arm64_probe,
228         .priv_auto_alloc_size = sizeof(struct k3_arm64_privdata),
229         .flags = DM_FLAG_DEFAULT_PD_CTRL_OFF,
230 };