• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2018 Marty E. Plummer <hanetzer@startmail.com> */
3 /* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
4 
5 #include <linux/clk.h>
6 #include <linux/reset.h>
7 #include <linux/platform_device.h>
8 #include <linux/pm_domain.h>
9 #include <linux/regulator/consumer.h>
10 
11 #include "panfrost_device.h"
12 #include "panfrost_devfreq.h"
13 #include "panfrost_features.h"
14 #include "panfrost_gpu.h"
15 #include "panfrost_job.h"
16 #include "panfrost_mmu.h"
17 #include "panfrost_perfcnt.h"
18 
19 #define PRCM_REG_BASE 0x07010000
20 #define GPU_POWEROFF_GATING_REG (PRCM_REG_BASE + 0x0254)
21 #define AW_GPU_CLK_RATE 600000000
22 
aw_power_gating(struct panfrost_device * pfdev,bool gate)23 static int aw_power_gating(struct panfrost_device *pfdev, bool gate)
24 {
25 	void __iomem *ioaddr;
26 	u32 val;
27 
28 	ioaddr = ioremap(GPU_POWEROFF_GATING_REG, 4);
29 	if (!ioaddr) {
30 		dev_err(pfdev->dev, "can't ioremap aw_power_gating\n");
31 		return -ENOMEM;
32 	}
33 	val = readl(ioaddr);
34 
35 	if (gate)
36 		val |= gate;
37 	else
38 		val &= 0xfffffffe;
39 
40 	writel(val, ioaddr);
41 	iounmap(ioaddr);
42 	return 0;
43 }
44 
panfrost_reset_init(struct panfrost_device * pfdev)45 static int panfrost_reset_init(struct panfrost_device *pfdev)
46 {
47 	int err;
48 
49 	pfdev->rstc = devm_reset_control_array_get(pfdev->dev, false, true);
50 	if (IS_ERR(pfdev->rstc)) {
51 		dev_err(pfdev->dev, "get reset failed %ld\n", PTR_ERR(pfdev->rstc));
52 		return PTR_ERR(pfdev->rstc);
53 	}
54 
55 	err = reset_control_deassert(pfdev->rstc);
56 	if (err)
57 		return err;
58 
59 	return 0;
60 }
61 
panfrost_reset_fini(struct panfrost_device * pfdev)62 static void panfrost_reset_fini(struct panfrost_device *pfdev)
63 {
64 	reset_control_assert(pfdev->rstc);
65 }
66 
panfrost_clk_init(struct panfrost_device * pfdev)67 static int panfrost_clk_init(struct panfrost_device *pfdev)
68 {
69 	int err;
70 	unsigned long rate;
71 #ifdef CONFIG_ARCH_SUN50IW9
72 	rate = AW_GPU_CLK_RATE;
73 	aw_power_gating(pfdev, false);
74 
75 	pfdev->parent_clock = of_clk_get_by_name(pfdev->dev->of_node, "clk_parent");
76 	if (!IS_ERR_OR_NULL(pfdev->parent_clock)) {
77 		clk_set_rate(pfdev->parent_clock, rate);
78 		err = clk_prepare_enable(pfdev->parent_clock);
79 		if (err)
80 			return err;
81 	} else {
82 		dev_err(pfdev->dev, "get clk_parent failed %ld\n", PTR_ERR(pfdev->parent_clock));
83 		return PTR_ERR(pfdev->parent_clock);
84 	}
85 
86 	pfdev->clock = of_clk_get_by_name(pfdev->dev->of_node, "clk_mali");
87 	if (!IS_ERR_OR_NULL(pfdev->clock)) {
88 		clk_set_rate(pfdev->clock, rate);
89 		err = clk_prepare_enable(pfdev->clock);
90 	if (err)
91 		return err;
92 
93 	} else {
94 		dev_err(pfdev->dev, "get clk_mali failed %ld\n", PTR_ERR(pfdev->parent_clock));
95 		return PTR_ERR(pfdev->clock);
96 	}
97 
98 	pfdev->bus_clock = of_clk_get_by_name(pfdev->dev->of_node, "clk_bus");
99 	if (!IS_ERR_OR_NULL(pfdev->bus_clock)) {
100 		err = clk_prepare_enable(pfdev->bus_clock);
101 		if (err)
102 			goto disable_clock;
103 	} else {
104 		dev_err(pfdev->dev, "get clk_bus failed %ld\n", PTR_ERR(pfdev->bus_clock));
105 	}
106 
107 	pfdev->bak_clock = of_clk_get_by_name(pfdev->dev->of_node, "clk_bak");
108 	if (!IS_ERR_OR_NULL(pfdev->bak_clock)) {
109 		clk_set_rate(pfdev->bak_clock, AW_GPU_CLK_RATE);
110 		err = clk_prepare_enable(pfdev->bak_clock);
111 	if (err)
112 		goto disable_clock;
113 	} else {
114 		dev_err(pfdev->dev, "get clk_bak failed %ld\n", PTR_ERR(pfdev->bak_clock));
115 	}
116 
117 #else
118 	pfdev->clock = devm_clk_get(pfdev->dev, NULL);
119 	if (IS_ERR(pfdev->clock)) {
120 		dev_err(pfdev->dev, "get clock failed %ld\n", PTR_ERR(pfdev->clock));
121 		return PTR_ERR(pfdev->clock);
122 	}
123 
124 	rate = clk_get_rate(pfdev->clock);
125 	dev_info(pfdev->dev, "clock rate = %lu\n", rate);
126 
127 	err = clk_prepare_enable(pfdev->clock);
128 	if (err)
129 		return err;
130 
131 	pfdev->bus_clock = devm_clk_get_optional(pfdev->dev, "bus");
132 	if (IS_ERR(pfdev->bus_clock)) {
133 		dev_err(pfdev->dev, "get bus_clock failed %ld\n",
134 			PTR_ERR(pfdev->bus_clock));
135 		err = PTR_ERR(pfdev->bus_clock);
136 		goto disable_clock;
137 	}
138 
139 	if (pfdev->bus_clock) {
140 		rate = clk_get_rate(pfdev->bus_clock);
141 		dev_info(pfdev->dev, "bus_clock rate = %lu\n", rate);
142 
143 		err = clk_prepare_enable(pfdev->bus_clock);
144 		if (err)
145 			goto disable_clock;
146 	}
147 #endif
148 
149 	return 0;
150 
151 disable_clock:
152 	clk_disable_unprepare(pfdev->clock);
153 
154 	return err;
155 }
156 
panfrost_clk_fini(struct panfrost_device * pfdev)157 static void panfrost_clk_fini(struct panfrost_device *pfdev)
158 {
159 	clk_disable_unprepare(pfdev->bus_clock);
160 	clk_disable_unprepare(pfdev->clock);
161 }
162 
panfrost_regulator_init(struct panfrost_device * pfdev)163 static int panfrost_regulator_init(struct panfrost_device *pfdev)
164 {
165 	int ret, i;
166 
167 	pfdev->regulators = devm_kcalloc(pfdev->dev, pfdev->comp->num_supplies,
168 					 sizeof(*pfdev->regulators),
169 					 GFP_KERNEL);
170 	if (!pfdev->regulators)
171 		return -ENOMEM;
172 
173 	for (i = 0; i < pfdev->comp->num_supplies; i++)
174 		pfdev->regulators[i].supply = pfdev->comp->supply_names[i];
175 
176 	ret = devm_regulator_bulk_get(pfdev->dev,
177 				      pfdev->comp->num_supplies,
178 				      pfdev->regulators);
179 	if (ret < 0) {
180 		if (ret != -EPROBE_DEFER)
181 			dev_err(pfdev->dev, "failed to get regulators: %d\n",
182 				ret);
183 		return ret;
184 	}
185 
186 	ret = regulator_bulk_enable(pfdev->comp->num_supplies,
187 				    pfdev->regulators);
188 	if (ret < 0) {
189 		dev_err(pfdev->dev, "failed to enable regulators: %d\n", ret);
190 		return ret;
191 	}
192 
193 	return 0;
194 }
195 
panfrost_regulator_fini(struct panfrost_device * pfdev)196 static void panfrost_regulator_fini(struct panfrost_device *pfdev)
197 {
198 	if (!pfdev->regulators)
199 		return;
200 
201 	regulator_bulk_disable(pfdev->comp->num_supplies, pfdev->regulators);
202 }
203 
panfrost_pm_domain_fini(struct panfrost_device * pfdev)204 static void panfrost_pm_domain_fini(struct panfrost_device *pfdev)
205 {
206 	int i;
207 
208 	for (i = 0; i < ARRAY_SIZE(pfdev->pm_domain_devs); i++) {
209 		if (!pfdev->pm_domain_devs[i])
210 			break;
211 
212 		if (pfdev->pm_domain_links[i])
213 			device_link_del(pfdev->pm_domain_links[i]);
214 
215 		dev_pm_domain_detach(pfdev->pm_domain_devs[i], true);
216 	}
217 }
218 
panfrost_pm_domain_init(struct panfrost_device * pfdev)219 static int panfrost_pm_domain_init(struct panfrost_device *pfdev)
220 {
221 	int err;
222 	int i, num_domains;
223 
224 	num_domains = of_count_phandle_with_args(pfdev->dev->of_node,
225 						 "power-domains",
226 						 "#power-domain-cells");
227 
228 	/*
229 	 * Single domain is handled by the core, and, if only a single power
230 	 * the power domain is requested, the property is optional.
231 	 */
232 	if (num_domains < 2 && pfdev->comp->num_pm_domains < 2)
233 		return 0;
234 
235 	if (num_domains != pfdev->comp->num_pm_domains) {
236 		dev_err(pfdev->dev,
237 			"Incorrect number of power domains: %d provided, %d needed\n",
238 			num_domains, pfdev->comp->num_pm_domains);
239 		return -EINVAL;
240 	}
241 
242 	if (WARN(num_domains > ARRAY_SIZE(pfdev->pm_domain_devs),
243 			"Too many supplies in compatible structure.\n"))
244 		return -EINVAL;
245 
246 	for (i = 0; i < num_domains; i++) {
247 		pfdev->pm_domain_devs[i] =
248 			dev_pm_domain_attach_by_name(pfdev->dev,
249 					pfdev->comp->pm_domain_names[i]);
250 		if (IS_ERR_OR_NULL(pfdev->pm_domain_devs[i])) {
251 			err = PTR_ERR(pfdev->pm_domain_devs[i]) ? : -ENODATA;
252 			pfdev->pm_domain_devs[i] = NULL;
253 			dev_err(pfdev->dev,
254 				"failed to get pm-domain %s(%d): %d\n",
255 				pfdev->comp->pm_domain_names[i], i, err);
256 			goto err;
257 		}
258 
259 		pfdev->pm_domain_links[i] = device_link_add(pfdev->dev,
260 				pfdev->pm_domain_devs[i], DL_FLAG_PM_RUNTIME |
261 				DL_FLAG_STATELESS | DL_FLAG_RPM_ACTIVE);
262 		if (!pfdev->pm_domain_links[i]) {
263 			dev_err(pfdev->pm_domain_devs[i],
264 				"adding device link failed!\n");
265 			err = -ENODEV;
266 			goto err;
267 		}
268 	}
269 
270 	return 0;
271 
272 err:
273 	panfrost_pm_domain_fini(pfdev);
274 	return err;
275 }
276 
panfrost_device_init(struct panfrost_device * pfdev)277 int panfrost_device_init(struct panfrost_device *pfdev)
278 {
279 	int err;
280 	struct resource *res;
281 
282 	mutex_init(&pfdev->sched_lock);
283 	INIT_LIST_HEAD(&pfdev->scheduled_jobs);
284 	INIT_LIST_HEAD(&pfdev->as_lru_list);
285 
286 	spin_lock_init(&pfdev->as_lock);
287 
288 	err = panfrost_clk_init(pfdev);
289 	if (err) {
290 		dev_err(pfdev->dev, "clk init failed %d\n", err);
291 		return err;
292 	}
293 
294 #ifndef CONFIG_ARCH_SUN50IW9
295 	err = panfrost_devfreq_init(pfdev);
296 	if (err) {
297 		if (err != -EPROBE_DEFER)
298 			dev_err(pfdev->dev, "devfreq init failed %d\n", err);
299 		goto out_clk;
300 	}
301 #endif
302 
303 	/* OPP will handle regulators */
304 	if (!pfdev->pfdevfreq.opp_of_table_added) {
305 		err = panfrost_regulator_init(pfdev);
306 		if (err)
307 			goto out_devfreq;
308 	}
309 
310 	err = panfrost_reset_init(pfdev);
311 	if (err) {
312 		dev_err(pfdev->dev, "reset init failed %d\n", err);
313 		goto out_regulator;
314 	}
315 
316 	err = panfrost_pm_domain_init(pfdev);
317 	if (err)
318 		goto out_reset;
319 
320 	res = platform_get_resource(pfdev->pdev, IORESOURCE_MEM, 0);
321 	pfdev->iomem = devm_ioremap_resource(pfdev->dev, res);
322 	if (IS_ERR(pfdev->iomem)) {
323 		dev_err(pfdev->dev, "failed to ioremap iomem\n");
324 		err = PTR_ERR(pfdev->iomem);
325 		goto out_pm_domain;
326 	}
327 
328 	err = panfrost_gpu_init(pfdev);
329 	if (err)
330 		goto out_pm_domain;
331 
332 	err = panfrost_mmu_init(pfdev);
333 	if (err)
334 		goto out_gpu;
335 
336 	err = panfrost_job_init(pfdev);
337 	if (err)
338 		goto out_mmu;
339 
340 	err = panfrost_perfcnt_init(pfdev);
341 	if (err)
342 		goto out_job;
343 
344 	return 0;
345 out_job:
346 	panfrost_job_fini(pfdev);
347 out_mmu:
348 	panfrost_mmu_fini(pfdev);
349 out_gpu:
350 	panfrost_gpu_fini(pfdev);
351 out_pm_domain:
352 	panfrost_pm_domain_fini(pfdev);
353 out_reset:
354 	panfrost_reset_fini(pfdev);
355 out_regulator:
356 	panfrost_regulator_fini(pfdev);
357 out_devfreq:
358 	panfrost_devfreq_fini(pfdev);
359 out_clk:
360 	panfrost_clk_fini(pfdev);
361 	return err;
362 }
363 
panfrost_device_fini(struct panfrost_device * pfdev)364 void panfrost_device_fini(struct panfrost_device *pfdev)
365 {
366 	panfrost_perfcnt_fini(pfdev);
367 	panfrost_job_fini(pfdev);
368 	panfrost_mmu_fini(pfdev);
369 	panfrost_gpu_fini(pfdev);
370 	panfrost_pm_domain_fini(pfdev);
371 	panfrost_reset_fini(pfdev);
372 	panfrost_devfreq_fini(pfdev);
373 	panfrost_regulator_fini(pfdev);
374 	panfrost_clk_fini(pfdev);
375 }
376 
panfrost_exception_name(struct panfrost_device * pfdev,u32 exception_code)377 const char *panfrost_exception_name(struct panfrost_device *pfdev, u32 exception_code)
378 {
379 	switch (exception_code) {
380 		/* Non-Fault Status code */
381 	case 0x00: return "NOT_STARTED/IDLE/OK";
382 	case 0x01: return "DONE";
383 	case 0x02: return "INTERRUPTED";
384 	case 0x03: return "STOPPED";
385 	case 0x04: return "TERMINATED";
386 	case 0x08: return "ACTIVE";
387 		/* Job exceptions */
388 	case 0x40: return "JOB_CONFIG_FAULT";
389 	case 0x41: return "JOB_POWER_FAULT";
390 	case 0x42: return "JOB_READ_FAULT";
391 	case 0x43: return "JOB_WRITE_FAULT";
392 	case 0x44: return "JOB_AFFINITY_FAULT";
393 	case 0x48: return "JOB_BUS_FAULT";
394 	case 0x50: return "INSTR_INVALID_PC";
395 	case 0x51: return "INSTR_INVALID_ENC";
396 	case 0x52: return "INSTR_TYPE_MISMATCH";
397 	case 0x53: return "INSTR_OPERAND_FAULT";
398 	case 0x54: return "INSTR_TLS_FAULT";
399 	case 0x55: return "INSTR_BARRIER_FAULT";
400 	case 0x56: return "INSTR_ALIGN_FAULT";
401 	case 0x58: return "DATA_INVALID_FAULT";
402 	case 0x59: return "TILE_RANGE_FAULT";
403 	case 0x5A: return "ADDR_RANGE_FAULT";
404 	case 0x60: return "OUT_OF_MEMORY";
405 		/* GPU exceptions */
406 	case 0x80: return "DELAYED_BUS_FAULT";
407 	case 0x88: return "SHAREABILITY_FAULT";
408 		/* MMU exceptions */
409 	case 0xC1: return "TRANSLATION_FAULT_LEVEL1";
410 	case 0xC2: return "TRANSLATION_FAULT_LEVEL2";
411 	case 0xC3: return "TRANSLATION_FAULT_LEVEL3";
412 	case 0xC4: return "TRANSLATION_FAULT_LEVEL4";
413 	case 0xC8: return "PERMISSION_FAULT";
414 	case 0xC9 ... 0xCF: return "PERMISSION_FAULT";
415 	case 0xD1: return "TRANSTAB_BUS_FAULT_LEVEL1";
416 	case 0xD2: return "TRANSTAB_BUS_FAULT_LEVEL2";
417 	case 0xD3: return "TRANSTAB_BUS_FAULT_LEVEL3";
418 	case 0xD4: return "TRANSTAB_BUS_FAULT_LEVEL4";
419 	case 0xD8: return "ACCESS_FLAG";
420 	case 0xD9 ... 0xDF: return "ACCESS_FLAG";
421 	case 0xE0 ... 0xE7: return "ADDRESS_SIZE_FAULT";
422 	case 0xE8 ... 0xEF: return "MEMORY_ATTRIBUTES_FAULT";
423 	}
424 
425 	return "UNKNOWN";
426 }
427 
panfrost_device_reset(struct panfrost_device * pfdev)428 void panfrost_device_reset(struct panfrost_device *pfdev)
429 {
430 	panfrost_gpu_soft_reset(pfdev);
431 
432 	panfrost_gpu_power_on(pfdev);
433 	panfrost_mmu_reset(pfdev);
434 	panfrost_job_enable_interrupts(pfdev);
435 }
436 
437 #ifdef CONFIG_PM
panfrost_device_resume(struct device * dev)438 int panfrost_device_resume(struct device *dev)
439 {
440 	struct platform_device *pdev = to_platform_device(dev);
441 	struct panfrost_device *pfdev = platform_get_drvdata(pdev);
442 
443 	panfrost_device_reset(pfdev);
444 	panfrost_devfreq_resume(pfdev);
445 
446 	return 0;
447 }
448 
panfrost_device_suspend(struct device * dev)449 int panfrost_device_suspend(struct device *dev)
450 {
451 	struct platform_device *pdev = to_platform_device(dev);
452 	struct panfrost_device *pfdev = platform_get_drvdata(pdev);
453 
454 	if (!panfrost_job_is_idle(pfdev))
455 		return -EBUSY;
456 
457 	panfrost_devfreq_suspend(pfdev);
458 	panfrost_gpu_power_off(pfdev);
459 
460 	return 0;
461 }
462 #endif
463