1bd628c1bSjames qian wang (Arm Technology China) // SPDX-License-Identifier: GPL-2.0
2bd628c1bSjames qian wang (Arm Technology China) /*
3bd628c1bSjames qian wang (Arm Technology China)  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4bd628c1bSjames qian wang (Arm Technology China)  * Author: James.Qian.Wang <james.qian.wang@arm.com>
5bd628c1bSjames qian wang (Arm Technology China)  *
6bd628c1bSjames qian wang (Arm Technology China)  */
76649a95dSSam Ravnborg #include <linux/io.h>
8e87cae37SLowry Li (Arm Technology China) #include <linux/iommu.h>
9*722d4f06SRob Herring #include <linux/of.h>
10bd628c1bSjames qian wang (Arm Technology China) #include <linux/of_graph.h>
11a8c16b75SMihail Atanassov #include <linux/of_reserved_mem.h>
126649a95dSSam Ravnborg #include <linux/platform_device.h>
13efb46508Sjames qian wang (Arm Technology China) #include <linux/pm_runtime.h>
14a260e0b8SLowry Li (Arm Technology China) #include <linux/dma-mapping.h>
157d3cfb70Sjames qian wang (Arm Technology China) #ifdef CONFIG_DEBUG_FS
167d3cfb70Sjames qian wang (Arm Technology China) #include <linux/debugfs.h>
177d3cfb70Sjames qian wang (Arm Technology China) #include <linux/seq_file.h>
187d3cfb70Sjames qian wang (Arm Technology China) #endif
196649a95dSSam Ravnborg 
206649a95dSSam Ravnborg #include <drm/drm_print.h>
216649a95dSSam Ravnborg 
22bd628c1bSjames qian wang (Arm Technology China) #include "komeda_dev.h"
23bd628c1bSjames qian wang (Arm Technology China) 
komeda_register_show(struct seq_file * sf,void * x)247d3cfb70Sjames qian wang (Arm Technology China) static int komeda_register_show(struct seq_file *sf, void *x)
257d3cfb70Sjames qian wang (Arm Technology China) {
267d3cfb70Sjames qian wang (Arm Technology China) 	struct komeda_dev *mdev = sf->private;
277d3cfb70Sjames qian wang (Arm Technology China) 	int i;
287d3cfb70Sjames qian wang (Arm Technology China) 
29aefdaa15SLowry Li (Arm Technology China) 	seq_puts(sf, "\n====== Komeda register dump =========\n");
30aefdaa15SLowry Li (Arm Technology China) 
31efb46508Sjames qian wang (Arm Technology China) 	pm_runtime_get_sync(mdev->dev);
32efb46508Sjames qian wang (Arm Technology China) 
337d3cfb70Sjames qian wang (Arm Technology China) 	if (mdev->funcs->dump_register)
347d3cfb70Sjames qian wang (Arm Technology China) 		mdev->funcs->dump_register(mdev, sf);
357d3cfb70Sjames qian wang (Arm Technology China) 
367d3cfb70Sjames qian wang (Arm Technology China) 	for (i = 0; i < mdev->n_pipelines; i++)
377d3cfb70Sjames qian wang (Arm Technology China) 		komeda_pipeline_dump_register(mdev->pipelines[i], sf);
387d3cfb70Sjames qian wang (Arm Technology China) 
39efb46508Sjames qian wang (Arm Technology China) 	pm_runtime_put(mdev->dev);
40efb46508Sjames qian wang (Arm Technology China) 
417d3cfb70Sjames qian wang (Arm Technology China) 	return 0;
427d3cfb70Sjames qian wang (Arm Technology China) }
437d3cfb70Sjames qian wang (Arm Technology China) 
44ef52d585SQinglang Miao DEFINE_SHOW_ATTRIBUTE(komeda_register);
457d3cfb70Sjames qian wang (Arm Technology China) 
4657683268SLiviu Dudau #ifdef CONFIG_DEBUG_FS
komeda_debugfs_init(struct komeda_dev * mdev)477d3cfb70Sjames qian wang (Arm Technology China) static void komeda_debugfs_init(struct komeda_dev *mdev)
487d3cfb70Sjames qian wang (Arm Technology China) {
497d3cfb70Sjames qian wang (Arm Technology China) 	if (!debugfs_initialized())
507d3cfb70Sjames qian wang (Arm Technology China) 		return;
517d3cfb70Sjames qian wang (Arm Technology China) 
527d3cfb70Sjames qian wang (Arm Technology China) 	mdev->debugfs_root = debugfs_create_dir("komeda", NULL);
537d3cfb70Sjames qian wang (Arm Technology China) 	debugfs_create_file("register", 0444, mdev->debugfs_root,
547d3cfb70Sjames qian wang (Arm Technology China) 			    mdev, &komeda_register_fops);
558894cd58SMihail Atanassov 	debugfs_create_x16("err_verbosity", 0664, mdev->debugfs_root,
568894cd58SMihail Atanassov 			   &mdev->err_verbosity);
577d3cfb70Sjames qian wang (Arm Technology China) }
5857683268SLiviu Dudau #endif
597d3cfb70Sjames qian wang (Arm Technology China) 
6055223394Sjames qian wang (Arm Technology China) static ssize_t
core_id_show(struct device * dev,struct device_attribute * attr,char * buf)6155223394Sjames qian wang (Arm Technology China) core_id_show(struct device *dev, struct device_attribute *attr, char *buf)
6255223394Sjames qian wang (Arm Technology China) {
6355223394Sjames qian wang (Arm Technology China) 	struct komeda_dev *mdev = dev_to_mdev(dev);
6455223394Sjames qian wang (Arm Technology China) 
656f6ab533STian Tao 	return sysfs_emit(buf, "0x%08x\n", mdev->chip.core_id);
6655223394Sjames qian wang (Arm Technology China) }
6755223394Sjames qian wang (Arm Technology China) static DEVICE_ATTR_RO(core_id);
6855223394Sjames qian wang (Arm Technology China) 
6955223394Sjames qian wang (Arm Technology China) static ssize_t
config_id_show(struct device * dev,struct device_attribute * attr,char * buf)7055223394Sjames qian wang (Arm Technology China) config_id_show(struct device *dev, struct device_attribute *attr, char *buf)
7155223394Sjames qian wang (Arm Technology China) {
7255223394Sjames qian wang (Arm Technology China) 	struct komeda_dev *mdev = dev_to_mdev(dev);
7355223394Sjames qian wang (Arm Technology China) 	struct komeda_pipeline *pipe = mdev->pipelines[0];
7455223394Sjames qian wang (Arm Technology China) 	union komeda_config_id config_id;
7555223394Sjames qian wang (Arm Technology China) 	int i;
7655223394Sjames qian wang (Arm Technology China) 
7755223394Sjames qian wang (Arm Technology China) 	memset(&config_id, 0, sizeof(config_id));
7855223394Sjames qian wang (Arm Technology China) 
7955223394Sjames qian wang (Arm Technology China) 	config_id.max_line_sz = pipe->layers[0]->hsize_in.end;
8055223394Sjames qian wang (Arm Technology China) 	config_id.n_pipelines = mdev->n_pipelines;
8155223394Sjames qian wang (Arm Technology China) 	config_id.n_scalers = pipe->n_scalers;
8255223394Sjames qian wang (Arm Technology China) 	config_id.n_layers = pipe->n_layers;
8355223394Sjames qian wang (Arm Technology China) 	config_id.n_richs = 0;
8455223394Sjames qian wang (Arm Technology China) 	for (i = 0; i < pipe->n_layers; i++) {
8555223394Sjames qian wang (Arm Technology China) 		if (pipe->layers[i]->layer_type == KOMEDA_FMT_RICH_LAYER)
8655223394Sjames qian wang (Arm Technology China) 			config_id.n_richs++;
8755223394Sjames qian wang (Arm Technology China) 	}
886f6ab533STian Tao 	return sysfs_emit(buf, "0x%08x\n", config_id.value);
8955223394Sjames qian wang (Arm Technology China) }
9055223394Sjames qian wang (Arm Technology China) static DEVICE_ATTR_RO(config_id);
9155223394Sjames qian wang (Arm Technology China) 
925fcd0551SMihail Atanassov static ssize_t
aclk_hz_show(struct device * dev,struct device_attribute * attr,char * buf)935fcd0551SMihail Atanassov aclk_hz_show(struct device *dev, struct device_attribute *attr, char *buf)
945fcd0551SMihail Atanassov {
955fcd0551SMihail Atanassov 	struct komeda_dev *mdev = dev_to_mdev(dev);
965fcd0551SMihail Atanassov 
976f6ab533STian Tao 	return sysfs_emit(buf, "%lu\n", clk_get_rate(mdev->aclk));
985fcd0551SMihail Atanassov }
995fcd0551SMihail Atanassov static DEVICE_ATTR_RO(aclk_hz);
1005fcd0551SMihail Atanassov 
10155223394Sjames qian wang (Arm Technology China) static struct attribute *komeda_sysfs_entries[] = {
10255223394Sjames qian wang (Arm Technology China) 	&dev_attr_core_id.attr,
10355223394Sjames qian wang (Arm Technology China) 	&dev_attr_config_id.attr,
1045fcd0551SMihail Atanassov 	&dev_attr_aclk_hz.attr,
10555223394Sjames qian wang (Arm Technology China) 	NULL,
10655223394Sjames qian wang (Arm Technology China) };
10755223394Sjames qian wang (Arm Technology China) 
10855223394Sjames qian wang (Arm Technology China) static struct attribute_group komeda_sysfs_attr_group = {
10955223394Sjames qian wang (Arm Technology China) 	.attrs = komeda_sysfs_entries,
11055223394Sjames qian wang (Arm Technology China) };
11155223394Sjames qian wang (Arm Technology China) 
komeda_parse_pipe_dt(struct komeda_pipeline * pipe)112b25bc78fSjames qian wang (Arm Technology China) static int komeda_parse_pipe_dt(struct komeda_pipeline *pipe)
11329e56aecSjames qian wang (Arm Technology China) {
114b25bc78fSjames qian wang (Arm Technology China) 	struct device_node *np = pipe->of_node;
11529e56aecSjames qian wang (Arm Technology China) 	struct clk *clk;
11629e56aecSjames qian wang (Arm Technology China) 
11729e56aecSjames qian wang (Arm Technology China) 	clk = of_clk_get_by_name(np, "pxclk");
11829e56aecSjames qian wang (Arm Technology China) 	if (IS_ERR(clk)) {
119b25bc78fSjames qian wang (Arm Technology China) 		DRM_ERROR("get pxclk for pipeline %d failed!\n", pipe->id);
12029e56aecSjames qian wang (Arm Technology China) 		return PTR_ERR(clk);
12129e56aecSjames qian wang (Arm Technology China) 	}
12229e56aecSjames qian wang (Arm Technology China) 	pipe->pxlclk = clk;
12329e56aecSjames qian wang (Arm Technology China) 
12429e56aecSjames qian wang (Arm Technology China) 	/* enum ports */
1258965ad84Sjames qian wang (Arm Technology China) 	pipe->of_output_links[0] =
12629e56aecSjames qian wang (Arm Technology China) 		of_graph_get_remote_node(np, KOMEDA_OF_PORT_OUTPUT, 0);
1278965ad84Sjames qian wang (Arm Technology China) 	pipe->of_output_links[1] =
1288965ad84Sjames qian wang (Arm Technology China) 		of_graph_get_remote_node(np, KOMEDA_OF_PORT_OUTPUT, 1);
12929e56aecSjames qian wang (Arm Technology China) 	pipe->of_output_port =
13029e56aecSjames qian wang (Arm Technology China) 		of_graph_get_port_by_id(np, KOMEDA_OF_PORT_OUTPUT);
13129e56aecSjames qian wang (Arm Technology China) 
1328965ad84Sjames qian wang (Arm Technology China) 	pipe->dual_link = pipe->of_output_links[0] && pipe->of_output_links[1];
13329e56aecSjames qian wang (Arm Technology China) 
13429e56aecSjames qian wang (Arm Technology China) 	return 0;
13529e56aecSjames qian wang (Arm Technology China) }
13629e56aecSjames qian wang (Arm Technology China) 
komeda_parse_dt(struct device * dev,struct komeda_dev * mdev)13729e56aecSjames qian wang (Arm Technology China) static int komeda_parse_dt(struct device *dev, struct komeda_dev *mdev)
13829e56aecSjames qian wang (Arm Technology China) {
1390dac37bfSjames qian wang (Arm Technology China) 	struct platform_device *pdev = to_platform_device(dev);
14029e56aecSjames qian wang (Arm Technology China) 	struct device_node *child, *np = dev->of_node;
141b25bc78fSjames qian wang (Arm Technology China) 	struct komeda_pipeline *pipe;
142b25bc78fSjames qian wang (Arm Technology China) 	u32 pipe_id = U32_MAX;
143b25bc78fSjames qian wang (Arm Technology China) 	int ret = -1;
14429e56aecSjames qian wang (Arm Technology China) 
1450dac37bfSjames qian wang (Arm Technology China) 	mdev->irq  = platform_get_irq(pdev, 0);
1460dac37bfSjames qian wang (Arm Technology China) 	if (mdev->irq < 0) {
1470dac37bfSjames qian wang (Arm Technology China) 		DRM_ERROR("could not get IRQ number.\n");
1480dac37bfSjames qian wang (Arm Technology China) 		return mdev->irq;
1490dac37bfSjames qian wang (Arm Technology China) 	}
15029e56aecSjames qian wang (Arm Technology China) 
151a8c16b75SMihail Atanassov 	/* Get the optional framebuffer memory resource */
152a8c16b75SMihail Atanassov 	ret = of_reserved_mem_device_init(dev);
153a8c16b75SMihail Atanassov 	if (ret && ret != -ENODEV)
154a8c16b75SMihail Atanassov 		return ret;
155a8c16b75SMihail Atanassov 
15629e56aecSjames qian wang (Arm Technology China) 	for_each_available_child_of_node(np, child) {
157b25bc78fSjames qian wang (Arm Technology China) 		if (of_node_name_eq(child, "pipeline")) {
158b25bc78fSjames qian wang (Arm Technology China) 			of_property_read_u32(child, "reg", &pipe_id);
159b25bc78fSjames qian wang (Arm Technology China) 			if (pipe_id >= mdev->n_pipelines) {
160b25bc78fSjames qian wang (Arm Technology China) 				DRM_WARN("Skip the redundant DT node: pipeline-%u.\n",
161b25bc78fSjames qian wang (Arm Technology China) 					 pipe_id);
162b25bc78fSjames qian wang (Arm Technology China) 				continue;
16329e56aecSjames qian wang (Arm Technology China) 			}
164b25bc78fSjames qian wang (Arm Technology China) 			mdev->pipelines[pipe_id]->of_node = of_node_get(child);
16529e56aecSjames qian wang (Arm Technology China) 		}
16629e56aecSjames qian wang (Arm Technology China) 	}
16729e56aecSjames qian wang (Arm Technology China) 
168b25bc78fSjames qian wang (Arm Technology China) 	for (pipe_id = 0; pipe_id < mdev->n_pipelines; pipe_id++) {
169b25bc78fSjames qian wang (Arm Technology China) 		pipe = mdev->pipelines[pipe_id];
170b25bc78fSjames qian wang (Arm Technology China) 
171b25bc78fSjames qian wang (Arm Technology China) 		if (!pipe->of_node) {
172b25bc78fSjames qian wang (Arm Technology China) 			DRM_ERROR("Pipeline-%d doesn't have a DT node.\n",
173b25bc78fSjames qian wang (Arm Technology China) 				  pipe->id);
174b25bc78fSjames qian wang (Arm Technology China) 			return -EINVAL;
175b25bc78fSjames qian wang (Arm Technology China) 		}
176b25bc78fSjames qian wang (Arm Technology China) 		ret = komeda_parse_pipe_dt(pipe);
177b25bc78fSjames qian wang (Arm Technology China) 		if (ret)
17829e56aecSjames qian wang (Arm Technology China) 			return ret;
17929e56aecSjames qian wang (Arm Technology China) 	}
18029e56aecSjames qian wang (Arm Technology China) 
181b25bc78fSjames qian wang (Arm Technology China) 	return 0;
182b25bc78fSjames qian wang (Arm Technology China) }
183b25bc78fSjames qian wang (Arm Technology China) 
komeda_dev_create(struct device * dev)184bd628c1bSjames qian wang (Arm Technology China) struct komeda_dev *komeda_dev_create(struct device *dev)
185bd628c1bSjames qian wang (Arm Technology China) {
186bd628c1bSjames qian wang (Arm Technology China) 	struct platform_device *pdev = to_platform_device(dev);
187b25bc78fSjames qian wang (Arm Technology China) 	komeda_identify_func komeda_identify;
188bd628c1bSjames qian wang (Arm Technology China) 	struct komeda_dev *mdev;
189bd628c1bSjames qian wang (Arm Technology China) 	int err = 0;
190bd628c1bSjames qian wang (Arm Technology China) 
191b25bc78fSjames qian wang (Arm Technology China) 	komeda_identify = of_device_get_match_data(dev);
192b25bc78fSjames qian wang (Arm Technology China) 	if (!komeda_identify)
193bd628c1bSjames qian wang (Arm Technology China) 		return ERR_PTR(-ENODEV);
194bd628c1bSjames qian wang (Arm Technology China) 
195bd628c1bSjames qian wang (Arm Technology China) 	mdev = devm_kzalloc(dev, sizeof(*mdev), GFP_KERNEL);
196bd628c1bSjames qian wang (Arm Technology China) 	if (!mdev)
197bd628c1bSjames qian wang (Arm Technology China) 		return ERR_PTR(-ENOMEM);
198bd628c1bSjames qian wang (Arm Technology China) 
19920d84aa8Sjames qian wang (Arm Technology China) 	mutex_init(&mdev->lock);
20020d84aa8Sjames qian wang (Arm Technology China) 
201bd628c1bSjames qian wang (Arm Technology China) 	mdev->dev = dev;
20250ec5b56SMarkus Elfring 	mdev->reg_base = devm_platform_ioremap_resource(pdev, 0);
203bd628c1bSjames qian wang (Arm Technology China) 	if (IS_ERR(mdev->reg_base)) {
204bd628c1bSjames qian wang (Arm Technology China) 		DRM_ERROR("Map register space failed.\n");
205bd628c1bSjames qian wang (Arm Technology China) 		err = PTR_ERR(mdev->reg_base);
206bd628c1bSjames qian wang (Arm Technology China) 		mdev->reg_base = NULL;
207bd628c1bSjames qian wang (Arm Technology China) 		goto err_cleanup;
208bd628c1bSjames qian wang (Arm Technology China) 	}
209bd628c1bSjames qian wang (Arm Technology China) 
2106f84da0cSjames qian wang (Arm Technology China) 	mdev->aclk = devm_clk_get(dev, "aclk");
2116f84da0cSjames qian wang (Arm Technology China) 	if (IS_ERR(mdev->aclk)) {
21228be315cSjames qian wang (Arm Technology China) 		DRM_ERROR("Get engine clk failed.\n");
2136f84da0cSjames qian wang (Arm Technology China) 		err = PTR_ERR(mdev->aclk);
2146f84da0cSjames qian wang (Arm Technology China) 		mdev->aclk = NULL;
215bd628c1bSjames qian wang (Arm Technology China) 		goto err_cleanup;
216bd628c1bSjames qian wang (Arm Technology China) 	}
217bd628c1bSjames qian wang (Arm Technology China) 
2186f84da0cSjames qian wang (Arm Technology China) 	clk_prepare_enable(mdev->aclk);
219bd628c1bSjames qian wang (Arm Technology China) 
220b25bc78fSjames qian wang (Arm Technology China) 	mdev->funcs = komeda_identify(mdev->reg_base, &mdev->chip);
221b25bc78fSjames qian wang (Arm Technology China) 	if (!mdev->funcs) {
222b25bc78fSjames qian wang (Arm Technology China) 		DRM_ERROR("Failed to identify the HW.\n");
223bd628c1bSjames qian wang (Arm Technology China) 		err = -ENODEV;
2242ebb6701SLowry Li (Arm Technology China) 		goto disable_clk;
225bd628c1bSjames qian wang (Arm Technology China) 	}
226bd628c1bSjames qian wang (Arm Technology China) 
227bd628c1bSjames qian wang (Arm Technology China) 	DRM_INFO("Found ARM Mali-D%x version r%dp%d\n",
228bd628c1bSjames qian wang (Arm Technology China) 		 MALIDP_CORE_ID_PRODUCT_ID(mdev->chip.core_id),
229bd628c1bSjames qian wang (Arm Technology China) 		 MALIDP_CORE_ID_MAJOR(mdev->chip.core_id),
230bd628c1bSjames qian wang (Arm Technology China) 		 MALIDP_CORE_ID_MINOR(mdev->chip.core_id));
231bd628c1bSjames qian wang (Arm Technology China) 
232981d29d2Sjames qian wang (Arm Technology China) 	mdev->funcs->init_format_table(mdev);
233981d29d2Sjames qian wang (Arm Technology China) 
234bd628c1bSjames qian wang (Arm Technology China) 	err = mdev->funcs->enum_resources(mdev);
235bd628c1bSjames qian wang (Arm Technology China) 	if (err) {
236bd628c1bSjames qian wang (Arm Technology China) 		DRM_ERROR("enumerate display resource failed.\n");
2372ebb6701SLowry Li (Arm Technology China) 		goto disable_clk;
238bd628c1bSjames qian wang (Arm Technology China) 	}
239bd628c1bSjames qian wang (Arm Technology China) 
24029e56aecSjames qian wang (Arm Technology China) 	err = komeda_parse_dt(dev, mdev);
24129e56aecSjames qian wang (Arm Technology China) 	if (err) {
24229e56aecSjames qian wang (Arm Technology China) 		DRM_ERROR("parse device tree failed.\n");
2432ebb6701SLowry Li (Arm Technology China) 		goto disable_clk;
24429e56aecSjames qian wang (Arm Technology China) 	}
24529e56aecSjames qian wang (Arm Technology China) 
246321e925cSjames qian wang (Arm Technology China) 	err = komeda_assemble_pipelines(mdev);
247321e925cSjames qian wang (Arm Technology China) 	if (err) {
248321e925cSjames qian wang (Arm Technology China) 		DRM_ERROR("assemble display pipelines failed.\n");
2492ebb6701SLowry Li (Arm Technology China) 		goto disable_clk;
250321e925cSjames qian wang (Arm Technology China) 	}
251321e925cSjames qian wang (Arm Technology China) 
2521c831adeSRobin Murphy 	dma_set_max_seg_size(dev, U32_MAX);
253a260e0b8SLowry Li (Arm Technology China) 
254e87cae37SLowry Li (Arm Technology China) 	mdev->iommu = iommu_get_domain_for_dev(mdev->dev);
255e87cae37SLowry Li (Arm Technology China) 	if (!mdev->iommu)
256e87cae37SLowry Li (Arm Technology China) 		DRM_INFO("continue without IOMMU support!\n");
257e87cae37SLowry Li (Arm Technology China) 
2582ebb6701SLowry Li (Arm Technology China) 	clk_disable_unprepare(mdev->aclk);
2592ebb6701SLowry Li (Arm Technology China) 
26055223394Sjames qian wang (Arm Technology China) 	err = sysfs_create_group(&dev->kobj, &komeda_sysfs_attr_group);
26155223394Sjames qian wang (Arm Technology China) 	if (err) {
26255223394Sjames qian wang (Arm Technology China) 		DRM_ERROR("create sysfs group failed.\n");
26355223394Sjames qian wang (Arm Technology China) 		goto err_cleanup;
26455223394Sjames qian wang (Arm Technology China) 	}
26555223394Sjames qian wang (Arm Technology China) 
2668894cd58SMihail Atanassov 	mdev->err_verbosity = KOMEDA_DEV_PRINT_ERR_EVENTS;
2678894cd58SMihail Atanassov 
2687d3cfb70Sjames qian wang (Arm Technology China) #ifdef CONFIG_DEBUG_FS
2697d3cfb70Sjames qian wang (Arm Technology China) 	komeda_debugfs_init(mdev);
2707d3cfb70Sjames qian wang (Arm Technology China) #endif
2717d3cfb70Sjames qian wang (Arm Technology China) 
272bd628c1bSjames qian wang (Arm Technology China) 	return mdev;
273bd628c1bSjames qian wang (Arm Technology China) 
2742ebb6701SLowry Li (Arm Technology China) disable_clk:
2752ebb6701SLowry Li (Arm Technology China) 	clk_disable_unprepare(mdev->aclk);
276bd628c1bSjames qian wang (Arm Technology China) err_cleanup:
277bd628c1bSjames qian wang (Arm Technology China) 	komeda_dev_destroy(mdev);
278bd628c1bSjames qian wang (Arm Technology China) 	return ERR_PTR(err);
279bd628c1bSjames qian wang (Arm Technology China) }
280bd628c1bSjames qian wang (Arm Technology China) 
komeda_dev_destroy(struct komeda_dev * mdev)281bd628c1bSjames qian wang (Arm Technology China) void komeda_dev_destroy(struct komeda_dev *mdev)
282bd628c1bSjames qian wang (Arm Technology China) {
283bd628c1bSjames qian wang (Arm Technology China) 	struct device *dev = mdev->dev;
284ba1b9f8cSjames qian wang (Arm Technology China) 	const struct komeda_dev_funcs *funcs = mdev->funcs;
285bd628c1bSjames qian wang (Arm Technology China) 	int i;
286bd628c1bSjames qian wang (Arm Technology China) 
28755223394Sjames qian wang (Arm Technology China) 	sysfs_remove_group(&dev->kobj, &komeda_sysfs_attr_group);
28855223394Sjames qian wang (Arm Technology China) 
2897d3cfb70Sjames qian wang (Arm Technology China) #ifdef CONFIG_DEBUG_FS
2907d3cfb70Sjames qian wang (Arm Technology China) 	debugfs_remove_recursive(mdev->debugfs_root);
2917d3cfb70Sjames qian wang (Arm Technology China) #endif
2927d3cfb70Sjames qian wang (Arm Technology China) 
2932ebb6701SLowry Li (Arm Technology China) 	if (mdev->aclk)
2942ebb6701SLowry Li (Arm Technology China) 		clk_prepare_enable(mdev->aclk);
2952ebb6701SLowry Li (Arm Technology China) 
296bd628c1bSjames qian wang (Arm Technology China) 	for (i = 0; i < mdev->n_pipelines; i++) {
297bd628c1bSjames qian wang (Arm Technology China) 		komeda_pipeline_destroy(mdev, mdev->pipelines[i]);
298bd628c1bSjames qian wang (Arm Technology China) 		mdev->pipelines[i] = NULL;
299bd628c1bSjames qian wang (Arm Technology China) 	}
300bd628c1bSjames qian wang (Arm Technology China) 
301bd628c1bSjames qian wang (Arm Technology China) 	mdev->n_pipelines = 0;
302bd628c1bSjames qian wang (Arm Technology China) 
303a8c16b75SMihail Atanassov 	of_reserved_mem_device_release(dev);
304a8c16b75SMihail Atanassov 
305bd628c1bSjames qian wang (Arm Technology China) 	if (funcs && funcs->cleanup)
306bd628c1bSjames qian wang (Arm Technology China) 		funcs->cleanup(mdev);
307bd628c1bSjames qian wang (Arm Technology China) 
308bd628c1bSjames qian wang (Arm Technology China) 	if (mdev->reg_base) {
309bd628c1bSjames qian wang (Arm Technology China) 		devm_iounmap(dev, mdev->reg_base);
310bd628c1bSjames qian wang (Arm Technology China) 		mdev->reg_base = NULL;
311bd628c1bSjames qian wang (Arm Technology China) 	}
312bd628c1bSjames qian wang (Arm Technology China) 
3136f84da0cSjames qian wang (Arm Technology China) 	if (mdev->aclk) {
3146f84da0cSjames qian wang (Arm Technology China) 		clk_disable_unprepare(mdev->aclk);
3156f84da0cSjames qian wang (Arm Technology China) 		devm_clk_put(dev, mdev->aclk);
3166f84da0cSjames qian wang (Arm Technology China) 		mdev->aclk = NULL;
317bd628c1bSjames qian wang (Arm Technology China) 	}
318bd628c1bSjames qian wang (Arm Technology China) 
319bd628c1bSjames qian wang (Arm Technology China) 	devm_kfree(dev, mdev);
320bd628c1bSjames qian wang (Arm Technology China) }
3212ebb6701SLowry Li (Arm Technology China) 
komeda_dev_resume(struct komeda_dev * mdev)3222ebb6701SLowry Li (Arm Technology China) int komeda_dev_resume(struct komeda_dev *mdev)
3232ebb6701SLowry Li (Arm Technology China) {
3242ebb6701SLowry Li (Arm Technology China) 	clk_prepare_enable(mdev->aclk);
3252ebb6701SLowry Li (Arm Technology China) 
326efb46508Sjames qian wang (Arm Technology China) 	mdev->funcs->enable_irq(mdev);
327efb46508Sjames qian wang (Arm Technology China) 
328efb46508Sjames qian wang (Arm Technology China) 	if (mdev->iommu && mdev->funcs->connect_iommu)
329efb46508Sjames qian wang (Arm Technology China) 		if (mdev->funcs->connect_iommu(mdev))
3302ebb6701SLowry Li (Arm Technology China) 			DRM_ERROR("connect iommu failed.\n");
3312ebb6701SLowry Li (Arm Technology China) 
332efb46508Sjames qian wang (Arm Technology China) 	return 0;
3332ebb6701SLowry Li (Arm Technology China) }
3342ebb6701SLowry Li (Arm Technology China) 
komeda_dev_suspend(struct komeda_dev * mdev)3352ebb6701SLowry Li (Arm Technology China) int komeda_dev_suspend(struct komeda_dev *mdev)
3362ebb6701SLowry Li (Arm Technology China) {
337efb46508Sjames qian wang (Arm Technology China) 	if (mdev->iommu && mdev->funcs->disconnect_iommu)
338efb46508Sjames qian wang (Arm Technology China) 		if (mdev->funcs->disconnect_iommu(mdev))
3392ebb6701SLowry Li (Arm Technology China) 			DRM_ERROR("disconnect iommu failed.\n");
3402ebb6701SLowry Li (Arm Technology China) 
341efb46508Sjames qian wang (Arm Technology China) 	mdev->funcs->disable_irq(mdev);
3422ebb6701SLowry Li (Arm Technology China) 
3432ebb6701SLowry Li (Arm Technology China) 	clk_disable_unprepare(mdev->aclk);
3442ebb6701SLowry Li (Arm Technology China) 
345efb46508Sjames qian wang (Arm Technology China) 	return 0;
3462ebb6701SLowry Li (Arm Technology China) }
347