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