1 /*
2 * SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018, The Linux Foundation
4 */
5
6 #include "dpu_kms.h"
7
8 #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
9
10 #define HW_INTR_STATUS 0x0010
11
12 struct dpu_mdss {
13 struct msm_mdss base;
14 void __iomem *mmio;
15 unsigned long mmio_len;
16 u32 hwversion;
17 struct dss_module_power mp;
18 struct dpu_irq_controller irq_controller;
19 };
20
dpu_mdss_irq(int irq,void * arg)21 static irqreturn_t dpu_mdss_irq(int irq, void *arg)
22 {
23 struct dpu_mdss *dpu_mdss = arg;
24 u32 interrupts;
25
26 interrupts = readl_relaxed(dpu_mdss->mmio + HW_INTR_STATUS);
27
28 while (interrupts) {
29 irq_hw_number_t hwirq = fls(interrupts) - 1;
30 unsigned int mapping;
31 int rc;
32
33 mapping = irq_find_mapping(dpu_mdss->irq_controller.domain,
34 hwirq);
35 if (mapping == 0) {
36 DRM_ERROR("couldn't find irq mapping for %lu\n", hwirq);
37 return IRQ_NONE;
38 }
39
40 rc = generic_handle_irq(mapping);
41 if (rc < 0) {
42 DRM_ERROR("handle irq fail: irq=%lu mapping=%u rc=%d\n",
43 hwirq, mapping, rc);
44 return IRQ_NONE;
45 }
46
47 interrupts &= ~(1 << hwirq);
48 }
49
50 return IRQ_HANDLED;
51 }
52
dpu_mdss_irq_mask(struct irq_data * irqd)53 static void dpu_mdss_irq_mask(struct irq_data *irqd)
54 {
55 struct dpu_mdss *dpu_mdss = irq_data_get_irq_chip_data(irqd);
56
57 /* memory barrier */
58 smp_mb__before_atomic();
59 clear_bit(irqd->hwirq, &dpu_mdss->irq_controller.enabled_mask);
60 /* memory barrier */
61 smp_mb__after_atomic();
62 }
63
dpu_mdss_irq_unmask(struct irq_data * irqd)64 static void dpu_mdss_irq_unmask(struct irq_data *irqd)
65 {
66 struct dpu_mdss *dpu_mdss = irq_data_get_irq_chip_data(irqd);
67
68 /* memory barrier */
69 smp_mb__before_atomic();
70 set_bit(irqd->hwirq, &dpu_mdss->irq_controller.enabled_mask);
71 /* memory barrier */
72 smp_mb__after_atomic();
73 }
74
75 static struct irq_chip dpu_mdss_irq_chip = {
76 .name = "dpu_mdss",
77 .irq_mask = dpu_mdss_irq_mask,
78 .irq_unmask = dpu_mdss_irq_unmask,
79 };
80
dpu_mdss_irqdomain_map(struct irq_domain * domain,unsigned int irq,irq_hw_number_t hwirq)81 static int dpu_mdss_irqdomain_map(struct irq_domain *domain,
82 unsigned int irq, irq_hw_number_t hwirq)
83 {
84 struct dpu_mdss *dpu_mdss = domain->host_data;
85 int ret;
86
87 irq_set_chip_and_handler(irq, &dpu_mdss_irq_chip, handle_level_irq);
88 ret = irq_set_chip_data(irq, dpu_mdss);
89
90 return ret;
91 }
92
93 static const struct irq_domain_ops dpu_mdss_irqdomain_ops = {
94 .map = dpu_mdss_irqdomain_map,
95 .xlate = irq_domain_xlate_onecell,
96 };
97
_dpu_mdss_irq_domain_add(struct dpu_mdss * dpu_mdss)98 static int _dpu_mdss_irq_domain_add(struct dpu_mdss *dpu_mdss)
99 {
100 struct device *dev;
101 struct irq_domain *domain;
102
103 dev = dpu_mdss->base.dev->dev;
104
105 domain = irq_domain_add_linear(dev->of_node, 32,
106 &dpu_mdss_irqdomain_ops, dpu_mdss);
107 if (!domain) {
108 DPU_ERROR("failed to add irq_domain\n");
109 return -EINVAL;
110 }
111
112 dpu_mdss->irq_controller.enabled_mask = 0;
113 dpu_mdss->irq_controller.domain = domain;
114
115 return 0;
116 }
117
_dpu_mdss_irq_domain_fini(struct dpu_mdss * dpu_mdss)118 static int _dpu_mdss_irq_domain_fini(struct dpu_mdss *dpu_mdss)
119 {
120 if (dpu_mdss->irq_controller.domain) {
121 irq_domain_remove(dpu_mdss->irq_controller.domain);
122 dpu_mdss->irq_controller.domain = NULL;
123 }
124 return 0;
125 }
dpu_mdss_enable(struct msm_mdss * mdss)126 static int dpu_mdss_enable(struct msm_mdss *mdss)
127 {
128 struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
129 struct dss_module_power *mp = &dpu_mdss->mp;
130 int ret;
131
132 ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
133 if (ret)
134 DPU_ERROR("clock enable failed, ret:%d\n", ret);
135
136 return ret;
137 }
138
dpu_mdss_disable(struct msm_mdss * mdss)139 static int dpu_mdss_disable(struct msm_mdss *mdss)
140 {
141 struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
142 struct dss_module_power *mp = &dpu_mdss->mp;
143 int ret;
144
145 ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false);
146 if (ret)
147 DPU_ERROR("clock disable failed, ret:%d\n", ret);
148
149 return ret;
150 }
151
dpu_mdss_destroy(struct drm_device * dev)152 static void dpu_mdss_destroy(struct drm_device *dev)
153 {
154 struct platform_device *pdev = to_platform_device(dev->dev);
155 struct msm_drm_private *priv = dev->dev_private;
156 struct dpu_mdss *dpu_mdss = to_dpu_mdss(priv->mdss);
157 struct dss_module_power *mp = &dpu_mdss->mp;
158
159 _dpu_mdss_irq_domain_fini(dpu_mdss);
160
161 msm_dss_put_clk(mp->clk_config, mp->num_clk);
162 devm_kfree(&pdev->dev, mp->clk_config);
163
164 if (dpu_mdss->mmio)
165 devm_iounmap(&pdev->dev, dpu_mdss->mmio);
166 dpu_mdss->mmio = NULL;
167
168 pm_runtime_disable(dev->dev);
169 priv->mdss = NULL;
170 }
171
172 static const struct msm_mdss_funcs mdss_funcs = {
173 .enable = dpu_mdss_enable,
174 .disable = dpu_mdss_disable,
175 .destroy = dpu_mdss_destroy,
176 };
177
dpu_mdss_init(struct drm_device * dev)178 int dpu_mdss_init(struct drm_device *dev)
179 {
180 struct platform_device *pdev = to_platform_device(dev->dev);
181 struct msm_drm_private *priv = dev->dev_private;
182 struct resource *res;
183 struct dpu_mdss *dpu_mdss;
184 struct dss_module_power *mp;
185 int ret = 0;
186
187 dpu_mdss = devm_kzalloc(dev->dev, sizeof(*dpu_mdss), GFP_KERNEL);
188 if (!dpu_mdss)
189 return -ENOMEM;
190
191 dpu_mdss->mmio = msm_ioremap(pdev, "mdss", "mdss");
192 if (IS_ERR(dpu_mdss->mmio))
193 return PTR_ERR(dpu_mdss->mmio);
194
195 DRM_DEBUG("mapped mdss address space @%pK\n", dpu_mdss->mmio);
196
197 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdss");
198 if (!res) {
199 DRM_ERROR("failed to get memory resource for mdss\n");
200 return -ENOMEM;
201 }
202 dpu_mdss->mmio_len = resource_size(res);
203
204 mp = &dpu_mdss->mp;
205 ret = msm_dss_parse_clock(pdev, mp);
206 if (ret) {
207 DPU_ERROR("failed to parse clocks, ret=%d\n", ret);
208 goto clk_parse_err;
209 }
210
211 dpu_mdss->base.dev = dev;
212 dpu_mdss->base.funcs = &mdss_funcs;
213
214 ret = _dpu_mdss_irq_domain_add(dpu_mdss);
215 if (ret)
216 goto irq_domain_error;
217
218 ret = devm_request_irq(dev->dev, platform_get_irq(pdev, 0),
219 dpu_mdss_irq, 0, "dpu_mdss_isr", dpu_mdss);
220 if (ret) {
221 DPU_ERROR("failed to init irq: %d\n", ret);
222 goto irq_error;
223 }
224
225 pm_runtime_enable(dev->dev);
226
227 pm_runtime_get_sync(dev->dev);
228 dpu_mdss->hwversion = readl_relaxed(dpu_mdss->mmio);
229 pm_runtime_put_sync(dev->dev);
230
231 priv->mdss = &dpu_mdss->base;
232
233 return ret;
234
235 irq_error:
236 _dpu_mdss_irq_domain_fini(dpu_mdss);
237 irq_domain_error:
238 msm_dss_put_clk(mp->clk_config, mp->num_clk);
239 clk_parse_err:
240 devm_kfree(&pdev->dev, mp->clk_config);
241 if (dpu_mdss->mmio)
242 devm_iounmap(&pdev->dev, dpu_mdss->mmio);
243 dpu_mdss->mmio = NULL;
244 return ret;
245 }
246