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