xref: /linux/drivers/gpu/drm/arm/display/komeda/komeda_dev.c (revision bd628c1bed7902ec1f24ba0fe70758949146abbe)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4  * Author: James.Qian.Wang <james.qian.wang@arm.com>
5  *
6  */
7 #include <linux/platform_device.h>
8 #include <linux/of_device.h>
9 #include <linux/of_graph.h>
10 #include "komeda_dev.h"
11 
12 struct komeda_dev *komeda_dev_create(struct device *dev)
13 {
14 	struct platform_device *pdev = to_platform_device(dev);
15 	const struct komeda_product_data *product;
16 	struct komeda_dev *mdev;
17 	struct resource *io_res;
18 	int err = 0;
19 
20 	product = of_device_get_match_data(dev);
21 	if (!product)
22 		return ERR_PTR(-ENODEV);
23 
24 	io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
25 	if (!io_res) {
26 		DRM_ERROR("No registers defined.\n");
27 		return ERR_PTR(-ENODEV);
28 	}
29 
30 	mdev = devm_kzalloc(dev, sizeof(*mdev), GFP_KERNEL);
31 	if (!mdev)
32 		return ERR_PTR(-ENOMEM);
33 
34 	mdev->dev = dev;
35 	mdev->reg_base = devm_ioremap_resource(dev, io_res);
36 	if (IS_ERR(mdev->reg_base)) {
37 		DRM_ERROR("Map register space failed.\n");
38 		err = PTR_ERR(mdev->reg_base);
39 		mdev->reg_base = NULL;
40 		goto err_cleanup;
41 	}
42 
43 	mdev->pclk = devm_clk_get(dev, "pclk");
44 	if (IS_ERR(mdev->pclk)) {
45 		DRM_ERROR("Get APB clk failed.\n");
46 		err = PTR_ERR(mdev->pclk);
47 		mdev->pclk = NULL;
48 		goto err_cleanup;
49 	}
50 
51 	/* Enable APB clock to access the registers */
52 	clk_prepare_enable(mdev->pclk);
53 
54 	mdev->funcs = product->identify(mdev->reg_base, &mdev->chip);
55 	if (!komeda_product_match(mdev, product->product_id)) {
56 		DRM_ERROR("DT configured %x mismatch with real HW %x.\n",
57 			  product->product_id,
58 			  MALIDP_CORE_ID_PRODUCT_ID(mdev->chip.core_id));
59 		err = -ENODEV;
60 		goto err_cleanup;
61 	}
62 
63 	DRM_INFO("Found ARM Mali-D%x version r%dp%d\n",
64 		 MALIDP_CORE_ID_PRODUCT_ID(mdev->chip.core_id),
65 		 MALIDP_CORE_ID_MAJOR(mdev->chip.core_id),
66 		 MALIDP_CORE_ID_MINOR(mdev->chip.core_id));
67 
68 	err = mdev->funcs->enum_resources(mdev);
69 	if (err) {
70 		DRM_ERROR("enumerate display resource failed.\n");
71 		goto err_cleanup;
72 	}
73 
74 	return mdev;
75 
76 err_cleanup:
77 	komeda_dev_destroy(mdev);
78 	return ERR_PTR(err);
79 }
80 
81 void komeda_dev_destroy(struct komeda_dev *mdev)
82 {
83 	struct device *dev = mdev->dev;
84 	struct komeda_dev_funcs *funcs = mdev->funcs;
85 	int i;
86 
87 	for (i = 0; i < mdev->n_pipelines; i++) {
88 		komeda_pipeline_destroy(mdev, mdev->pipelines[i]);
89 		mdev->pipelines[i] = NULL;
90 	}
91 
92 	mdev->n_pipelines = 0;
93 
94 	if (funcs && funcs->cleanup)
95 		funcs->cleanup(mdev);
96 
97 	if (mdev->reg_base) {
98 		devm_iounmap(dev, mdev->reg_base);
99 		mdev->reg_base = NULL;
100 	}
101 
102 	if (mdev->mclk) {
103 		devm_clk_put(dev, mdev->mclk);
104 		mdev->mclk = NULL;
105 	}
106 
107 	if (mdev->pclk) {
108 		clk_disable_unprepare(mdev->pclk);
109 		devm_clk_put(dev, mdev->pclk);
110 		mdev->pclk = NULL;
111 	}
112 
113 	devm_kfree(dev, mdev);
114 }
115