xref: /openbmc/linux/drivers/gpu/drm/msm/msm_io_utils.c (revision ba936421)
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 }
127