1 // SPDX-License-Identifier: GPL-2.0
3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4 * Author: James.Qian.Wang <james.qian.wang@arm.com>
8 #include <linux/iommu.h>
9 #include <linux/of_device.h>
10 #include <linux/of_graph.h>
11 #include <linux/of_reserved_mem.h>
12 #include <linux/platform_device.h>
13 #include <linux/dma-mapping.h>
14 #ifdef CONFIG_DEBUG_FS
15 #include <linux/debugfs.h>
16 #include <linux/seq_file.h>
19 #include <drm/drm_print.h>
21 #include "komeda_dev.h"
23 static int komeda_register_show(struct seq_file
*sf
, void *x
)
25 struct komeda_dev
*mdev
= sf
->private;
28 if (mdev
->funcs
->dump_register
)
29 mdev
->funcs
->dump_register(mdev
, sf
);
31 for (i
= 0; i
< mdev
->n_pipelines
; i
++)
32 komeda_pipeline_dump_register(mdev
->pipelines
[i
], sf
);
37 static int komeda_register_open(struct inode
*inode
, struct file
*filp
)
39 return single_open(filp
, komeda_register_show
, inode
->i_private
);
42 static const struct file_operations komeda_register_fops
= {
44 .open
= komeda_register_open
,
47 .release
= single_release
,
50 #ifdef CONFIG_DEBUG_FS
51 static void komeda_debugfs_init(struct komeda_dev
*mdev
)
53 if (!debugfs_initialized())
56 mdev
->debugfs_root
= debugfs_create_dir("komeda", NULL
);
57 debugfs_create_file("register", 0444, mdev
->debugfs_root
,
58 mdev
, &komeda_register_fops
);
63 core_id_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
65 struct komeda_dev
*mdev
= dev_to_mdev(dev
);
67 return snprintf(buf
, PAGE_SIZE
, "0x%08x\n", mdev
->chip
.core_id
);
69 static DEVICE_ATTR_RO(core_id
);
72 config_id_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
74 struct komeda_dev
*mdev
= dev_to_mdev(dev
);
75 struct komeda_pipeline
*pipe
= mdev
->pipelines
[0];
76 union komeda_config_id config_id
;
79 memset(&config_id
, 0, sizeof(config_id
));
81 config_id
.max_line_sz
= pipe
->layers
[0]->hsize_in
.end
;
82 config_id
.n_pipelines
= mdev
->n_pipelines
;
83 config_id
.n_scalers
= pipe
->n_scalers
;
84 config_id
.n_layers
= pipe
->n_layers
;
85 config_id
.n_richs
= 0;
86 for (i
= 0; i
< pipe
->n_layers
; i
++) {
87 if (pipe
->layers
[i
]->layer_type
== KOMEDA_FMT_RICH_LAYER
)
90 return snprintf(buf
, PAGE_SIZE
, "0x%08x\n", config_id
.value
);
92 static DEVICE_ATTR_RO(config_id
);
94 static struct attribute
*komeda_sysfs_entries
[] = {
95 &dev_attr_core_id
.attr
,
96 &dev_attr_config_id
.attr
,
100 static struct attribute_group komeda_sysfs_attr_group
= {
101 .attrs
= komeda_sysfs_entries
,
104 static int komeda_parse_pipe_dt(struct komeda_dev
*mdev
, struct device_node
*np
)
106 struct komeda_pipeline
*pipe
;
111 ret
= of_property_read_u32(np
, "reg", &pipe_id
);
112 if (ret
!= 0 || pipe_id
>= mdev
->n_pipelines
)
115 pipe
= mdev
->pipelines
[pipe_id
];
117 clk
= of_clk_get_by_name(np
, "pxclk");
119 DRM_ERROR("get pxclk for pipeline %d failed!\n", pipe_id
);
125 pipe
->of_output_dev
=
126 of_graph_get_remote_node(np
, KOMEDA_OF_PORT_OUTPUT
, 0);
127 pipe
->of_output_port
=
128 of_graph_get_port_by_id(np
, KOMEDA_OF_PORT_OUTPUT
);
130 pipe
->of_node
= of_node_get(np
);
135 static int komeda_parse_dt(struct device
*dev
, struct komeda_dev
*mdev
)
137 struct platform_device
*pdev
= to_platform_device(dev
);
138 struct device_node
*child
, *np
= dev
->of_node
;
141 mdev
->irq
= platform_get_irq(pdev
, 0);
143 DRM_ERROR("could not get IRQ number.\n");
147 /* Get the optional framebuffer memory resource */
148 ret
= of_reserved_mem_device_init(dev
);
149 if (ret
&& ret
!= -ENODEV
)
153 for_each_available_child_of_node(np
, child
) {
154 if (of_node_cmp(child
->name
, "pipeline") == 0) {
155 ret
= komeda_parse_pipe_dt(mdev
, child
);
157 DRM_ERROR("parse pipeline dt error!\n");
167 struct komeda_dev
*komeda_dev_create(struct device
*dev
)
169 struct platform_device
*pdev
= to_platform_device(dev
);
170 const struct komeda_product_data
*product
;
171 struct komeda_dev
*mdev
;
172 struct resource
*io_res
;
175 product
= of_device_get_match_data(dev
);
177 return ERR_PTR(-ENODEV
);
179 io_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
181 DRM_ERROR("No registers defined.\n");
182 return ERR_PTR(-ENODEV
);
185 mdev
= devm_kzalloc(dev
, sizeof(*mdev
), GFP_KERNEL
);
187 return ERR_PTR(-ENOMEM
);
189 mutex_init(&mdev
->lock
);
192 mdev
->reg_base
= devm_ioremap_resource(dev
, io_res
);
193 if (IS_ERR(mdev
->reg_base
)) {
194 DRM_ERROR("Map register space failed.\n");
195 err
= PTR_ERR(mdev
->reg_base
);
196 mdev
->reg_base
= NULL
;
200 mdev
->aclk
= devm_clk_get(dev
, "aclk");
201 if (IS_ERR(mdev
->aclk
)) {
202 DRM_ERROR("Get engine clk failed.\n");
203 err
= PTR_ERR(mdev
->aclk
);
208 clk_prepare_enable(mdev
->aclk
);
210 mdev
->funcs
= product
->identify(mdev
->reg_base
, &mdev
->chip
);
211 if (!komeda_product_match(mdev
, product
->product_id
)) {
212 DRM_ERROR("DT configured %x mismatch with real HW %x.\n",
214 MALIDP_CORE_ID_PRODUCT_ID(mdev
->chip
.core_id
));
219 DRM_INFO("Found ARM Mali-D%x version r%dp%d\n",
220 MALIDP_CORE_ID_PRODUCT_ID(mdev
->chip
.core_id
),
221 MALIDP_CORE_ID_MAJOR(mdev
->chip
.core_id
),
222 MALIDP_CORE_ID_MINOR(mdev
->chip
.core_id
));
224 mdev
->funcs
->init_format_table(mdev
);
226 err
= mdev
->funcs
->enum_resources(mdev
);
228 DRM_ERROR("enumerate display resource failed.\n");
232 err
= komeda_parse_dt(dev
, mdev
);
234 DRM_ERROR("parse device tree failed.\n");
238 err
= komeda_assemble_pipelines(mdev
);
240 DRM_ERROR("assemble display pipelines failed.\n");
244 dev
->dma_parms
= &mdev
->dma_parms
;
245 dma_set_max_seg_size(dev
, DMA_BIT_MASK(32));
247 mdev
->iommu
= iommu_get_domain_for_dev(mdev
->dev
);
249 DRM_INFO("continue without IOMMU support!\n");
251 if (mdev
->iommu
&& mdev
->funcs
->connect_iommu
) {
252 err
= mdev
->funcs
->connect_iommu(mdev
);
259 err
= sysfs_create_group(&dev
->kobj
, &komeda_sysfs_attr_group
);
261 DRM_ERROR("create sysfs group failed.\n");
265 #ifdef CONFIG_DEBUG_FS
266 komeda_debugfs_init(mdev
);
272 komeda_dev_destroy(mdev
);
276 void komeda_dev_destroy(struct komeda_dev
*mdev
)
278 struct device
*dev
= mdev
->dev
;
279 const struct komeda_dev_funcs
*funcs
= mdev
->funcs
;
282 sysfs_remove_group(&dev
->kobj
, &komeda_sysfs_attr_group
);
284 #ifdef CONFIG_DEBUG_FS
285 debugfs_remove_recursive(mdev
->debugfs_root
);
288 if (mdev
->iommu
&& mdev
->funcs
->disconnect_iommu
)
289 mdev
->funcs
->disconnect_iommu(mdev
);
292 for (i
= 0; i
< mdev
->n_pipelines
; i
++) {
293 komeda_pipeline_destroy(mdev
, mdev
->pipelines
[i
]);
294 mdev
->pipelines
[i
] = NULL
;
297 mdev
->n_pipelines
= 0;
299 of_reserved_mem_device_release(dev
);
301 if (funcs
&& funcs
->cleanup
)
302 funcs
->cleanup(mdev
);
304 if (mdev
->reg_base
) {
305 devm_iounmap(dev
, mdev
->reg_base
);
306 mdev
->reg_base
= NULL
;
310 clk_disable_unprepare(mdev
->aclk
);
311 devm_clk_put(dev
, mdev
->aclk
);
315 devm_kfree(dev
, mdev
);