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