Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2018, 2020-2021 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> */ #include <linux/interconnect.h> #include <linux/io.h> #include "msm_drv.h" /* * Util/helpers: */ struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count, const char *name) { int i; char n[32]; snprintf(n, sizeof(n), "%s_clk", name); for (i = 0; bulk && i < count; i++) { if (!strcmp(bulk[i].id, name) || !strcmp(bulk[i].id, n)) return bulk[i].clk; } return NULL; } struct clk *msm_clk_get(struct platform_device *pdev, const char *name) { struct clk *clk; char name2[32]; clk = devm_clk_get(&pdev->dev, name); if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER) return clk; snprintf(name2, sizeof(name2), "%s_clk", name); clk = devm_clk_get(&pdev->dev, name2); if (!IS_ERR(clk)) dev_warn(&pdev->dev, "Using legacy clk name binding. Use " "\"%s\" instead of \"%s\"\n", name, name2); return clk; } void __iomem *msm_ioremap_mdss(struct platform_device *mdss_pdev, struct platform_device *pdev, const char *name) { struct resource *res; res = platform_get_resource_byname(mdss_pdev, IORESOURCE_MEM, name); if (!res) return ERR_PTR(-EINVAL); return devm_ioremap_resource(&pdev->dev, res); } static void __iomem *_msm_ioremap(struct platform_device *pdev, const char *name, bool quiet, phys_addr_t *psize) { struct resource *res; unsigned long size; void __iomem *ptr; if (name) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); else res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { if (!quiet) DRM_DEV_ERROR(&pdev->dev, "failed to get memory resource: %s\n", name); return ERR_PTR(-EINVAL); } size = resource_size(res); ptr = devm_ioremap(&pdev->dev, res->start, size); if (!ptr) { if (!quiet) DRM_DEV_ERROR(&pdev->dev, "failed to ioremap: %s\n", name); return ERR_PTR(-ENOMEM); } if (psize) *psize = size; return ptr; } void __iomem *msm_ioremap(struct platform_device *pdev, const char *name) { return _msm_ioremap(pdev, name, false, NULL); } void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name) { return _msm_ioremap(pdev, name, true, NULL); } void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name, phys_addr_t *psize) { return _msm_ioremap(pdev, name, false, psize); } static enum hrtimer_restart msm_hrtimer_worktimer(struct hrtimer *t) { struct msm_hrtimer_work *work = container_of(t, struct msm_hrtimer_work, timer); kthread_queue_work(work->worker, &work->work); return HRTIMER_NORESTART; } void msm_hrtimer_queue_work(struct msm_hrtimer_work *work, ktime_t wakeup_time, enum hrtimer_mode mode) { hrtimer_start(&work->timer, wakeup_time, mode); } void msm_hrtimer_work_init(struct msm_hrtimer_work *work, struct kthread_worker *worker, kthread_work_func_t fn, clockid_t clock_id, enum hrtimer_mode mode) { hrtimer_init(&work->timer, clock_id, mode); work->timer.function = msm_hrtimer_worktimer; work->worker = worker; kthread_init_work(&work->work, fn); } struct icc_path *msm_icc_get(struct device *dev, const char *name) { struct device *mdss_dev = dev->parent; struct icc_path *path; path = of_icc_get(dev, name); if (path) return path; /* * If there are no interconnects attached to the corresponding device * node, of_icc_get() will return NULL. * * If the MDP5/DPU device node doesn't have interconnects, lookup the * path in the parent (MDSS) device. */ return of_icc_get(mdss_dev, name); } |