GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / gpu / drm / msm / msm_io_utils.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2016-2018, 2020-2021 The Linux Foundation. All rights reserved.
4  * Copyright (C) 2013 Red Hat
5  * Author: Rob Clark <robdclark@gmail.com>
6  */
7
8 #include "msm_drv.h"
9
10 /*
11  * Util/helpers:
12  */
13
14 struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,
15                 const char *name)
16 {
17         int i;
18         char n[32];
19
20         snprintf(n, sizeof(n), "%s_clk", name);
21
22         for (i = 0; bulk && i < count; i++) {
23                 if (!strcmp(bulk[i].id, name) || !strcmp(bulk[i].id, n))
24                         return bulk[i].clk;
25         }
26
27
28         return NULL;
29 }
30
31 struct clk *msm_clk_get(struct platform_device *pdev, const char *name)
32 {
33         struct clk *clk;
34         char name2[32];
35
36         clk = devm_clk_get(&pdev->dev, name);
37         if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
38                 return clk;
39
40         snprintf(name2, sizeof(name2), "%s_clk", name);
41
42         clk = devm_clk_get(&pdev->dev, name2);
43         if (!IS_ERR(clk))
44                 dev_warn(&pdev->dev, "Using legacy clk name binding.  Use "
45                                 "\"%s\" instead of \"%s\"\n", name, name2);
46
47         return clk;
48 }
49
50 static void __iomem *_msm_ioremap(struct platform_device *pdev, const char *name,
51                                   bool quiet, phys_addr_t *psize)
52 {
53         struct resource *res;
54         unsigned long size;
55         void __iomem *ptr;
56
57         if (name)
58                 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
59         else
60                 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
61
62         if (!res) {
63                 if (!quiet)
64                         DRM_DEV_ERROR(&pdev->dev, "failed to get memory resource: %s\n", name);
65                 return ERR_PTR(-EINVAL);
66         }
67
68         size = resource_size(res);
69
70         ptr = devm_ioremap(&pdev->dev, res->start, size);
71         if (!ptr) {
72                 if (!quiet)
73                         DRM_DEV_ERROR(&pdev->dev, "failed to ioremap: %s\n", name);
74                 return ERR_PTR(-ENOMEM);
75         }
76
77         if (psize)
78                 *psize = size;
79
80         return ptr;
81 }
82
83 void __iomem *msm_ioremap(struct platform_device *pdev, const char *name)
84 {
85         return _msm_ioremap(pdev, name, false, NULL);
86 }
87
88 void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name)
89 {
90         return _msm_ioremap(pdev, name, true, NULL);
91 }
92
93 void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name,
94                           phys_addr_t *psize)
95 {
96         return _msm_ioremap(pdev, name, false, psize);
97 }
98
99 static enum hrtimer_restart msm_hrtimer_worktimer(struct hrtimer *t)
100 {
101         struct msm_hrtimer_work *work = container_of(t,
102                         struct msm_hrtimer_work, timer);
103
104         kthread_queue_work(work->worker, &work->work);
105
106         return HRTIMER_NORESTART;
107 }
108
109 void msm_hrtimer_queue_work(struct msm_hrtimer_work *work,
110                             ktime_t wakeup_time,
111                             enum hrtimer_mode mode)
112 {
113         hrtimer_start(&work->timer, wakeup_time, mode);
114 }
115
116 void msm_hrtimer_work_init(struct msm_hrtimer_work *work,
117                            struct kthread_worker *worker,
118                            kthread_work_func_t fn,
119                            clockid_t clock_id,
120                            enum hrtimer_mode mode)
121 {
122         hrtimer_init(&work->timer, clock_id, mode);
123         work->timer.function = msm_hrtimer_worktimer;
124         work->worker = worker;
125         kthread_init_work(&work->work, fn);
126 }