panfrost_device.c (10726B)
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 19static int panfrost_reset_init(struct panfrost_device *pfdev) 20{ 21 pfdev->rstc = devm_reset_control_array_get_optional_exclusive(pfdev->dev); 22 if (IS_ERR(pfdev->rstc)) { 23 dev_err(pfdev->dev, "get reset failed %ld\n", PTR_ERR(pfdev->rstc)); 24 return PTR_ERR(pfdev->rstc); 25 } 26 27 return reset_control_deassert(pfdev->rstc); 28} 29 30static void panfrost_reset_fini(struct panfrost_device *pfdev) 31{ 32 reset_control_assert(pfdev->rstc); 33} 34 35static int panfrost_clk_init(struct panfrost_device *pfdev) 36{ 37 int err; 38 unsigned long rate; 39 40 pfdev->clock = devm_clk_get(pfdev->dev, NULL); 41 if (IS_ERR(pfdev->clock)) { 42 dev_err(pfdev->dev, "get clock failed %ld\n", PTR_ERR(pfdev->clock)); 43 return PTR_ERR(pfdev->clock); 44 } 45 46 rate = clk_get_rate(pfdev->clock); 47 dev_info(pfdev->dev, "clock rate = %lu\n", rate); 48 49 err = clk_prepare_enable(pfdev->clock); 50 if (err) 51 return err; 52 53 pfdev->bus_clock = devm_clk_get_optional(pfdev->dev, "bus"); 54 if (IS_ERR(pfdev->bus_clock)) { 55 dev_err(pfdev->dev, "get bus_clock failed %ld\n", 56 PTR_ERR(pfdev->bus_clock)); 57 err = PTR_ERR(pfdev->bus_clock); 58 goto disable_clock; 59 } 60 61 if (pfdev->bus_clock) { 62 rate = clk_get_rate(pfdev->bus_clock); 63 dev_info(pfdev->dev, "bus_clock rate = %lu\n", rate); 64 65 err = clk_prepare_enable(pfdev->bus_clock); 66 if (err) 67 goto disable_clock; 68 } 69 70 return 0; 71 72disable_clock: 73 clk_disable_unprepare(pfdev->clock); 74 75 return err; 76} 77 78static void panfrost_clk_fini(struct panfrost_device *pfdev) 79{ 80 clk_disable_unprepare(pfdev->bus_clock); 81 clk_disable_unprepare(pfdev->clock); 82} 83 84static int panfrost_regulator_init(struct panfrost_device *pfdev) 85{ 86 int ret, i; 87 88 pfdev->regulators = devm_kcalloc(pfdev->dev, pfdev->comp->num_supplies, 89 sizeof(*pfdev->regulators), 90 GFP_KERNEL); 91 if (!pfdev->regulators) 92 return -ENOMEM; 93 94 for (i = 0; i < pfdev->comp->num_supplies; i++) 95 pfdev->regulators[i].supply = pfdev->comp->supply_names[i]; 96 97 ret = devm_regulator_bulk_get(pfdev->dev, 98 pfdev->comp->num_supplies, 99 pfdev->regulators); 100 if (ret < 0) { 101 if (ret != -EPROBE_DEFER) 102 dev_err(pfdev->dev, "failed to get regulators: %d\n", 103 ret); 104 return ret; 105 } 106 107 ret = regulator_bulk_enable(pfdev->comp->num_supplies, 108 pfdev->regulators); 109 if (ret < 0) { 110 dev_err(pfdev->dev, "failed to enable regulators: %d\n", ret); 111 return ret; 112 } 113 114 return 0; 115} 116 117static void panfrost_regulator_fini(struct panfrost_device *pfdev) 118{ 119 if (!pfdev->regulators) 120 return; 121 122 regulator_bulk_disable(pfdev->comp->num_supplies, pfdev->regulators); 123} 124 125static void panfrost_pm_domain_fini(struct panfrost_device *pfdev) 126{ 127 int i; 128 129 for (i = 0; i < ARRAY_SIZE(pfdev->pm_domain_devs); i++) { 130 if (!pfdev->pm_domain_devs[i]) 131 break; 132 133 if (pfdev->pm_domain_links[i]) 134 device_link_del(pfdev->pm_domain_links[i]); 135 136 dev_pm_domain_detach(pfdev->pm_domain_devs[i], true); 137 } 138} 139 140static int panfrost_pm_domain_init(struct panfrost_device *pfdev) 141{ 142 int err; 143 int i, num_domains; 144 145 num_domains = of_count_phandle_with_args(pfdev->dev->of_node, 146 "power-domains", 147 "#power-domain-cells"); 148 149 /* 150 * Single domain is handled by the core, and, if only a single power 151 * the power domain is requested, the property is optional. 152 */ 153 if (num_domains < 2 && pfdev->comp->num_pm_domains < 2) 154 return 0; 155 156 if (num_domains != pfdev->comp->num_pm_domains) { 157 dev_err(pfdev->dev, 158 "Incorrect number of power domains: %d provided, %d needed\n", 159 num_domains, pfdev->comp->num_pm_domains); 160 return -EINVAL; 161 } 162 163 if (WARN(num_domains > ARRAY_SIZE(pfdev->pm_domain_devs), 164 "Too many supplies in compatible structure.\n")) 165 return -EINVAL; 166 167 for (i = 0; i < num_domains; i++) { 168 pfdev->pm_domain_devs[i] = 169 dev_pm_domain_attach_by_name(pfdev->dev, 170 pfdev->comp->pm_domain_names[i]); 171 if (IS_ERR_OR_NULL(pfdev->pm_domain_devs[i])) { 172 err = PTR_ERR(pfdev->pm_domain_devs[i]) ? : -ENODATA; 173 pfdev->pm_domain_devs[i] = NULL; 174 dev_err(pfdev->dev, 175 "failed to get pm-domain %s(%d): %d\n", 176 pfdev->comp->pm_domain_names[i], i, err); 177 goto err; 178 } 179 180 pfdev->pm_domain_links[i] = device_link_add(pfdev->dev, 181 pfdev->pm_domain_devs[i], DL_FLAG_PM_RUNTIME | 182 DL_FLAG_STATELESS | DL_FLAG_RPM_ACTIVE); 183 if (!pfdev->pm_domain_links[i]) { 184 dev_err(pfdev->pm_domain_devs[i], 185 "adding device link failed!\n"); 186 err = -ENODEV; 187 goto err; 188 } 189 } 190 191 return 0; 192 193err: 194 panfrost_pm_domain_fini(pfdev); 195 return err; 196} 197 198int panfrost_device_init(struct panfrost_device *pfdev) 199{ 200 int err; 201 202 mutex_init(&pfdev->sched_lock); 203 INIT_LIST_HEAD(&pfdev->scheduled_jobs); 204 INIT_LIST_HEAD(&pfdev->as_lru_list); 205 206 spin_lock_init(&pfdev->as_lock); 207 208 err = panfrost_clk_init(pfdev); 209 if (err) { 210 dev_err(pfdev->dev, "clk init failed %d\n", err); 211 return err; 212 } 213 214 err = panfrost_devfreq_init(pfdev); 215 if (err) { 216 if (err != -EPROBE_DEFER) 217 dev_err(pfdev->dev, "devfreq init failed %d\n", err); 218 goto out_clk; 219 } 220 221 /* OPP will handle regulators */ 222 if (!pfdev->pfdevfreq.opp_of_table_added) { 223 err = panfrost_regulator_init(pfdev); 224 if (err) 225 goto out_devfreq; 226 } 227 228 err = panfrost_reset_init(pfdev); 229 if (err) { 230 dev_err(pfdev->dev, "reset init failed %d\n", err); 231 goto out_regulator; 232 } 233 234 err = panfrost_pm_domain_init(pfdev); 235 if (err) 236 goto out_reset; 237 238 pfdev->iomem = devm_platform_ioremap_resource(pfdev->pdev, 0); 239 if (IS_ERR(pfdev->iomem)) { 240 err = PTR_ERR(pfdev->iomem); 241 goto out_pm_domain; 242 } 243 244 err = panfrost_gpu_init(pfdev); 245 if (err) 246 goto out_pm_domain; 247 248 err = panfrost_mmu_init(pfdev); 249 if (err) 250 goto out_gpu; 251 252 err = panfrost_job_init(pfdev); 253 if (err) 254 goto out_mmu; 255 256 err = panfrost_perfcnt_init(pfdev); 257 if (err) 258 goto out_job; 259 260 return 0; 261out_job: 262 panfrost_job_fini(pfdev); 263out_mmu: 264 panfrost_mmu_fini(pfdev); 265out_gpu: 266 panfrost_gpu_fini(pfdev); 267out_pm_domain: 268 panfrost_pm_domain_fini(pfdev); 269out_reset: 270 panfrost_reset_fini(pfdev); 271out_regulator: 272 panfrost_regulator_fini(pfdev); 273out_devfreq: 274 panfrost_devfreq_fini(pfdev); 275out_clk: 276 panfrost_clk_fini(pfdev); 277 return err; 278} 279 280void panfrost_device_fini(struct panfrost_device *pfdev) 281{ 282 panfrost_perfcnt_fini(pfdev); 283 panfrost_job_fini(pfdev); 284 panfrost_mmu_fini(pfdev); 285 panfrost_gpu_fini(pfdev); 286 panfrost_pm_domain_fini(pfdev); 287 panfrost_reset_fini(pfdev); 288 panfrost_devfreq_fini(pfdev); 289 panfrost_regulator_fini(pfdev); 290 panfrost_clk_fini(pfdev); 291} 292 293#define PANFROST_EXCEPTION(id) \ 294 [DRM_PANFROST_EXCEPTION_ ## id] = { \ 295 .name = #id, \ 296 } 297 298struct panfrost_exception_info { 299 const char *name; 300}; 301 302static const struct panfrost_exception_info panfrost_exception_infos[] = { 303 PANFROST_EXCEPTION(OK), 304 PANFROST_EXCEPTION(DONE), 305 PANFROST_EXCEPTION(INTERRUPTED), 306 PANFROST_EXCEPTION(STOPPED), 307 PANFROST_EXCEPTION(TERMINATED), 308 PANFROST_EXCEPTION(KABOOM), 309 PANFROST_EXCEPTION(EUREKA), 310 PANFROST_EXCEPTION(ACTIVE), 311 PANFROST_EXCEPTION(JOB_CONFIG_FAULT), 312 PANFROST_EXCEPTION(JOB_POWER_FAULT), 313 PANFROST_EXCEPTION(JOB_READ_FAULT), 314 PANFROST_EXCEPTION(JOB_WRITE_FAULT), 315 PANFROST_EXCEPTION(JOB_AFFINITY_FAULT), 316 PANFROST_EXCEPTION(JOB_BUS_FAULT), 317 PANFROST_EXCEPTION(INSTR_INVALID_PC), 318 PANFROST_EXCEPTION(INSTR_INVALID_ENC), 319 PANFROST_EXCEPTION(INSTR_TYPE_MISMATCH), 320 PANFROST_EXCEPTION(INSTR_OPERAND_FAULT), 321 PANFROST_EXCEPTION(INSTR_TLS_FAULT), 322 PANFROST_EXCEPTION(INSTR_BARRIER_FAULT), 323 PANFROST_EXCEPTION(INSTR_ALIGN_FAULT), 324 PANFROST_EXCEPTION(DATA_INVALID_FAULT), 325 PANFROST_EXCEPTION(TILE_RANGE_FAULT), 326 PANFROST_EXCEPTION(ADDR_RANGE_FAULT), 327 PANFROST_EXCEPTION(IMPRECISE_FAULT), 328 PANFROST_EXCEPTION(OOM), 329 PANFROST_EXCEPTION(OOM_AFBC), 330 PANFROST_EXCEPTION(UNKNOWN), 331 PANFROST_EXCEPTION(DELAYED_BUS_FAULT), 332 PANFROST_EXCEPTION(GPU_SHAREABILITY_FAULT), 333 PANFROST_EXCEPTION(SYS_SHAREABILITY_FAULT), 334 PANFROST_EXCEPTION(GPU_CACHEABILITY_FAULT), 335 PANFROST_EXCEPTION(TRANSLATION_FAULT_0), 336 PANFROST_EXCEPTION(TRANSLATION_FAULT_1), 337 PANFROST_EXCEPTION(TRANSLATION_FAULT_2), 338 PANFROST_EXCEPTION(TRANSLATION_FAULT_3), 339 PANFROST_EXCEPTION(TRANSLATION_FAULT_4), 340 PANFROST_EXCEPTION(TRANSLATION_FAULT_IDENTITY), 341 PANFROST_EXCEPTION(PERM_FAULT_0), 342 PANFROST_EXCEPTION(PERM_FAULT_1), 343 PANFROST_EXCEPTION(PERM_FAULT_2), 344 PANFROST_EXCEPTION(PERM_FAULT_3), 345 PANFROST_EXCEPTION(TRANSTAB_BUS_FAULT_0), 346 PANFROST_EXCEPTION(TRANSTAB_BUS_FAULT_1), 347 PANFROST_EXCEPTION(TRANSTAB_BUS_FAULT_2), 348 PANFROST_EXCEPTION(TRANSTAB_BUS_FAULT_3), 349 PANFROST_EXCEPTION(ACCESS_FLAG_0), 350 PANFROST_EXCEPTION(ACCESS_FLAG_1), 351 PANFROST_EXCEPTION(ACCESS_FLAG_2), 352 PANFROST_EXCEPTION(ACCESS_FLAG_3), 353 PANFROST_EXCEPTION(ADDR_SIZE_FAULT_IN0), 354 PANFROST_EXCEPTION(ADDR_SIZE_FAULT_IN1), 355 PANFROST_EXCEPTION(ADDR_SIZE_FAULT_IN2), 356 PANFROST_EXCEPTION(ADDR_SIZE_FAULT_IN3), 357 PANFROST_EXCEPTION(ADDR_SIZE_FAULT_OUT0), 358 PANFROST_EXCEPTION(ADDR_SIZE_FAULT_OUT1), 359 PANFROST_EXCEPTION(ADDR_SIZE_FAULT_OUT2), 360 PANFROST_EXCEPTION(ADDR_SIZE_FAULT_OUT3), 361 PANFROST_EXCEPTION(MEM_ATTR_FAULT_0), 362 PANFROST_EXCEPTION(MEM_ATTR_FAULT_1), 363 PANFROST_EXCEPTION(MEM_ATTR_FAULT_2), 364 PANFROST_EXCEPTION(MEM_ATTR_FAULT_3), 365 PANFROST_EXCEPTION(MEM_ATTR_NONCACHE_0), 366 PANFROST_EXCEPTION(MEM_ATTR_NONCACHE_1), 367 PANFROST_EXCEPTION(MEM_ATTR_NONCACHE_2), 368 PANFROST_EXCEPTION(MEM_ATTR_NONCACHE_3), 369}; 370 371const char *panfrost_exception_name(u32 exception_code) 372{ 373 if (WARN_ON(exception_code >= ARRAY_SIZE(panfrost_exception_infos) || 374 !panfrost_exception_infos[exception_code].name)) 375 return "Unknown exception type"; 376 377 return panfrost_exception_infos[exception_code].name; 378} 379 380bool panfrost_exception_needs_reset(const struct panfrost_device *pfdev, 381 u32 exception_code) 382{ 383 /* Right now, none of the GPU we support need a reset, but this 384 * might change. 385 */ 386 return false; 387} 388 389void panfrost_device_reset(struct panfrost_device *pfdev) 390{ 391 panfrost_gpu_soft_reset(pfdev); 392 393 panfrost_gpu_power_on(pfdev); 394 panfrost_mmu_reset(pfdev); 395 panfrost_job_enable_interrupts(pfdev); 396} 397 398#ifdef CONFIG_PM 399int panfrost_device_resume(struct device *dev) 400{ 401 struct panfrost_device *pfdev = dev_get_drvdata(dev); 402 403 panfrost_device_reset(pfdev); 404 panfrost_devfreq_resume(pfdev); 405 406 return 0; 407} 408 409int panfrost_device_suspend(struct device *dev) 410{ 411 struct panfrost_device *pfdev = dev_get_drvdata(dev); 412 413 if (!panfrost_job_is_idle(pfdev)) 414 return -EBUSY; 415 416 panfrost_devfreq_suspend(pfdev); 417 panfrost_gpu_power_off(pfdev); 418 419 return 0; 420} 421#endif