xref: /openbmc/linux/drivers/soc/mediatek/mtk-mmsys.c (revision f27ef285)
113032709SMatthias Brugger // SPDX-License-Identifier: GPL-2.0-only
213032709SMatthias Brugger /*
313032709SMatthias Brugger  * Copyright (c) 2014 MediaTek Inc.
413032709SMatthias Brugger  * Author: James Liao <jamesjj.liao@mediatek.com>
513032709SMatthias Brugger  */
613032709SMatthias Brugger 
7*f27ef285SEnric Balletbo i Serra #include <linux/delay.h>
82c758e30SEnric Balletbo i Serra #include <linux/device.h>
951c0e618SYongqiang Niu #include <linux/io.h>
1013032709SMatthias Brugger #include <linux/of_device.h>
1113032709SMatthias Brugger #include <linux/platform_device.h>
12*f27ef285SEnric Balletbo i Serra #include <linux/reset-controller.h>
132c758e30SEnric Balletbo i Serra #include <linux/soc/mediatek/mtk-mmsys.h>
142c758e30SEnric Balletbo i Serra 
1544014763SCK Hu #include "mtk-mmsys.h"
16060f7875SFabien Parent #include "mt8167-mmsys.h"
171ff1270fSHsin-Yi Wang #include "mt8183-mmsys.h"
18d687e056SYongqiang Niu #include "mt8192-mmsys.h"
19bc3fc5c0SFabien Parent #include "mt8365-mmsys.h"
2013032709SMatthias Brugger 
21c292b133SEnric Balletbo i Serra static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
22c292b133SEnric Balletbo i Serra 	.clk_driver = "clk-mt2701-mm",
2344014763SCK Hu 	.routes = mmsys_default_routing_table,
2444014763SCK Hu 	.num_routes = ARRAY_SIZE(mmsys_default_routing_table),
25c292b133SEnric Balletbo i Serra };
26c292b133SEnric Balletbo i Serra 
279c5a0a3aSEnric Balletbo i Serra static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
289c5a0a3aSEnric Balletbo i Serra 	.clk_driver = "clk-mt2712-mm",
2944014763SCK Hu 	.routes = mmsys_default_routing_table,
3044014763SCK Hu 	.num_routes = ARRAY_SIZE(mmsys_default_routing_table),
319c5a0a3aSEnric Balletbo i Serra };
329c5a0a3aSEnric Balletbo i Serra 
3332956ddaSMatthias Brugger static const struct mtk_mmsys_driver_data mt6779_mmsys_driver_data = {
3432956ddaSMatthias Brugger 	.clk_driver = "clk-mt6779-mm",
3532956ddaSMatthias Brugger };
3632956ddaSMatthias Brugger 
37cad4e379SMatthias Brugger static const struct mtk_mmsys_driver_data mt6797_mmsys_driver_data = {
38cad4e379SMatthias Brugger 	.clk_driver = "clk-mt6797-mm",
39cad4e379SMatthias Brugger };
40cad4e379SMatthias Brugger 
41060f7875SFabien Parent static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data = {
42060f7875SFabien Parent 	.clk_driver = "clk-mt8167-mm",
43060f7875SFabien Parent 	.routes = mt8167_mmsys_routing_table,
44060f7875SFabien Parent 	.num_routes = ARRAY_SIZE(mt8167_mmsys_routing_table),
45060f7875SFabien Parent };
46060f7875SFabien Parent 
4713032709SMatthias Brugger static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
4813032709SMatthias Brugger 	.clk_driver = "clk-mt8173-mm",
4944014763SCK Hu 	.routes = mmsys_default_routing_table,
5044014763SCK Hu 	.num_routes = ARRAY_SIZE(mmsys_default_routing_table),
5113032709SMatthias Brugger };
5213032709SMatthias Brugger 
531f9adbc7SMatthias Brugger static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
541f9adbc7SMatthias Brugger 	.clk_driver = "clk-mt8183-mm",
551ff1270fSHsin-Yi Wang 	.routes = mmsys_mt8183_routing_table,
561ff1270fSHsin-Yi Wang 	.num_routes = ARRAY_SIZE(mmsys_mt8183_routing_table),
571f9adbc7SMatthias Brugger };
581f9adbc7SMatthias Brugger 
59d687e056SYongqiang Niu static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = {
60d687e056SYongqiang Niu 	.clk_driver = "clk-mt8192-mm",
61d687e056SYongqiang Niu 	.routes = mmsys_mt8192_routing_table,
62d687e056SYongqiang Niu 	.num_routes = ARRAY_SIZE(mmsys_mt8192_routing_table),
63d687e056SYongqiang Niu };
64d687e056SYongqiang Niu 
65bc3fc5c0SFabien Parent static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
66bc3fc5c0SFabien Parent 	.clk_driver = "clk-mt8365-mm",
67bc3fc5c0SFabien Parent 	.routes = mt8365_mmsys_routing_table,
68bc3fc5c0SFabien Parent 	.num_routes = ARRAY_SIZE(mt8365_mmsys_routing_table),
69bc3fc5c0SFabien Parent };
70bc3fc5c0SFabien Parent 
71ce15e7faSCK Hu struct mtk_mmsys {
72ce15e7faSCK Hu 	void __iomem *regs;
73ce15e7faSCK Hu 	const struct mtk_mmsys_driver_data *data;
74*f27ef285SEnric Balletbo i Serra 	spinlock_t lock; /* protects mmsys_sw_rst_b reg */
75*f27ef285SEnric Balletbo i Serra 	struct reset_controller_dev rcdev;
76ce15e7faSCK Hu };
77ce15e7faSCK Hu 
782c758e30SEnric Balletbo i Serra void mtk_mmsys_ddp_connect(struct device *dev,
792c758e30SEnric Balletbo i Serra 			   enum mtk_ddp_comp_id cur,
802c758e30SEnric Balletbo i Serra 			   enum mtk_ddp_comp_id next)
812c758e30SEnric Balletbo i Serra {
82ce15e7faSCK Hu 	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
8344014763SCK Hu 	const struct mtk_mmsys_routes *routes = mmsys->data->routes;
8444014763SCK Hu 	u32 reg;
8544014763SCK Hu 	int i;
862c758e30SEnric Balletbo i Serra 
8744014763SCK Hu 	for (i = 0; i < mmsys->data->num_routes; i++)
8844014763SCK Hu 		if (cur == routes[i].from_comp && next == routes[i].to_comp) {
897bdcead7SCK Hu 			reg = readl_relaxed(mmsys->regs + routes[i].addr);
907bdcead7SCK Hu 			reg &= ~routes[i].mask;
917bdcead7SCK Hu 			reg |= routes[i].val;
9244014763SCK Hu 			writel_relaxed(reg, mmsys->regs + routes[i].addr);
932c758e30SEnric Balletbo i Serra 		}
942c758e30SEnric Balletbo i Serra }
952c758e30SEnric Balletbo i Serra EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_connect);
962c758e30SEnric Balletbo i Serra 
972c758e30SEnric Balletbo i Serra void mtk_mmsys_ddp_disconnect(struct device *dev,
982c758e30SEnric Balletbo i Serra 			      enum mtk_ddp_comp_id cur,
992c758e30SEnric Balletbo i Serra 			      enum mtk_ddp_comp_id next)
1002c758e30SEnric Balletbo i Serra {
101ce15e7faSCK Hu 	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
10244014763SCK Hu 	const struct mtk_mmsys_routes *routes = mmsys->data->routes;
10344014763SCK Hu 	u32 reg;
10444014763SCK Hu 	int i;
1052c758e30SEnric Balletbo i Serra 
10644014763SCK Hu 	for (i = 0; i < mmsys->data->num_routes; i++)
10744014763SCK Hu 		if (cur == routes[i].from_comp && next == routes[i].to_comp) {
1087bdcead7SCK Hu 			reg = readl_relaxed(mmsys->regs + routes[i].addr);
1097bdcead7SCK Hu 			reg &= ~routes[i].mask;
11044014763SCK Hu 			writel_relaxed(reg, mmsys->regs + routes[i].addr);
1112c758e30SEnric Balletbo i Serra 		}
1122c758e30SEnric Balletbo i Serra }
1132c758e30SEnric Balletbo i Serra EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect);
1142c758e30SEnric Balletbo i Serra 
115*f27ef285SEnric Balletbo i Serra static int mtk_mmsys_reset_update(struct reset_controller_dev *rcdev, unsigned long id,
116*f27ef285SEnric Balletbo i Serra 				  bool assert)
117*f27ef285SEnric Balletbo i Serra {
118*f27ef285SEnric Balletbo i Serra 	struct mtk_mmsys *mmsys = container_of(rcdev, struct mtk_mmsys, rcdev);
119*f27ef285SEnric Balletbo i Serra 	unsigned long flags;
120*f27ef285SEnric Balletbo i Serra 	u32 reg;
121*f27ef285SEnric Balletbo i Serra 
122*f27ef285SEnric Balletbo i Serra 	spin_lock_irqsave(&mmsys->lock, flags);
123*f27ef285SEnric Balletbo i Serra 
124*f27ef285SEnric Balletbo i Serra 	reg = readl_relaxed(mmsys->regs + MMSYS_SW0_RST_B);
125*f27ef285SEnric Balletbo i Serra 
126*f27ef285SEnric Balletbo i Serra 	if (assert)
127*f27ef285SEnric Balletbo i Serra 		reg &= ~BIT(id);
128*f27ef285SEnric Balletbo i Serra 	else
129*f27ef285SEnric Balletbo i Serra 		reg |= BIT(id);
130*f27ef285SEnric Balletbo i Serra 
131*f27ef285SEnric Balletbo i Serra 	writel_relaxed(reg, mmsys->regs + MMSYS_SW0_RST_B);
132*f27ef285SEnric Balletbo i Serra 
133*f27ef285SEnric Balletbo i Serra 	spin_unlock_irqrestore(&mmsys->lock, flags);
134*f27ef285SEnric Balletbo i Serra 
135*f27ef285SEnric Balletbo i Serra 	return 0;
136*f27ef285SEnric Balletbo i Serra }
137*f27ef285SEnric Balletbo i Serra 
138*f27ef285SEnric Balletbo i Serra static int mtk_mmsys_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
139*f27ef285SEnric Balletbo i Serra {
140*f27ef285SEnric Balletbo i Serra 	return mtk_mmsys_reset_update(rcdev, id, true);
141*f27ef285SEnric Balletbo i Serra }
142*f27ef285SEnric Balletbo i Serra 
143*f27ef285SEnric Balletbo i Serra static int mtk_mmsys_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
144*f27ef285SEnric Balletbo i Serra {
145*f27ef285SEnric Balletbo i Serra 	return mtk_mmsys_reset_update(rcdev, id, false);
146*f27ef285SEnric Balletbo i Serra }
147*f27ef285SEnric Balletbo i Serra 
148*f27ef285SEnric Balletbo i Serra static int mtk_mmsys_reset(struct reset_controller_dev *rcdev, unsigned long id)
149*f27ef285SEnric Balletbo i Serra {
150*f27ef285SEnric Balletbo i Serra 	int ret;
151*f27ef285SEnric Balletbo i Serra 
152*f27ef285SEnric Balletbo i Serra 	ret = mtk_mmsys_reset_assert(rcdev, id);
153*f27ef285SEnric Balletbo i Serra 	if (ret)
154*f27ef285SEnric Balletbo i Serra 		return ret;
155*f27ef285SEnric Balletbo i Serra 
156*f27ef285SEnric Balletbo i Serra 	usleep_range(1000, 1100);
157*f27ef285SEnric Balletbo i Serra 
158*f27ef285SEnric Balletbo i Serra 	return mtk_mmsys_reset_deassert(rcdev, id);
159*f27ef285SEnric Balletbo i Serra }
160*f27ef285SEnric Balletbo i Serra 
161*f27ef285SEnric Balletbo i Serra static const struct reset_control_ops mtk_mmsys_reset_ops = {
162*f27ef285SEnric Balletbo i Serra 	.assert = mtk_mmsys_reset_assert,
163*f27ef285SEnric Balletbo i Serra 	.deassert = mtk_mmsys_reset_deassert,
164*f27ef285SEnric Balletbo i Serra 	.reset = mtk_mmsys_reset,
165*f27ef285SEnric Balletbo i Serra };
166*f27ef285SEnric Balletbo i Serra 
16713032709SMatthias Brugger static int mtk_mmsys_probe(struct platform_device *pdev)
16813032709SMatthias Brugger {
1692c758e30SEnric Balletbo i Serra 	struct device *dev = &pdev->dev;
17013032709SMatthias Brugger 	struct platform_device *clks;
171667c7692SEnric Balletbo i Serra 	struct platform_device *drm;
172ce15e7faSCK Hu 	struct mtk_mmsys *mmsys;
1732c758e30SEnric Balletbo i Serra 	int ret;
1742c758e30SEnric Balletbo i Serra 
175ce15e7faSCK Hu 	mmsys = devm_kzalloc(dev, sizeof(*mmsys), GFP_KERNEL);
176ce15e7faSCK Hu 	if (!mmsys)
177ce15e7faSCK Hu 		return -ENOMEM;
178ce15e7faSCK Hu 
179ce15e7faSCK Hu 	mmsys->regs = devm_platform_ioremap_resource(pdev, 0);
180ce15e7faSCK Hu 	if (IS_ERR(mmsys->regs)) {
181ce15e7faSCK Hu 		ret = PTR_ERR(mmsys->regs);
182cc657602SEnric Balletbo i Serra 		dev_err(dev, "Failed to ioremap mmsys registers: %d\n", ret);
1832c758e30SEnric Balletbo i Serra 		return ret;
1842c758e30SEnric Balletbo i Serra 	}
1852c758e30SEnric Balletbo i Serra 
186*f27ef285SEnric Balletbo i Serra 	spin_lock_init(&mmsys->lock);
187*f27ef285SEnric Balletbo i Serra 
188*f27ef285SEnric Balletbo i Serra 	mmsys->rcdev.owner = THIS_MODULE;
189*f27ef285SEnric Balletbo i Serra 	mmsys->rcdev.nr_resets = 32;
190*f27ef285SEnric Balletbo i Serra 	mmsys->rcdev.ops = &mtk_mmsys_reset_ops;
191*f27ef285SEnric Balletbo i Serra 	mmsys->rcdev.of_node = pdev->dev.of_node;
192*f27ef285SEnric Balletbo i Serra 	ret = devm_reset_controller_register(&pdev->dev, &mmsys->rcdev);
193*f27ef285SEnric Balletbo i Serra 	if (ret) {
194*f27ef285SEnric Balletbo i Serra 		dev_err(&pdev->dev, "Couldn't register mmsys reset controller: %d\n", ret);
195*f27ef285SEnric Balletbo i Serra 		return ret;
196*f27ef285SEnric Balletbo i Serra 	}
197*f27ef285SEnric Balletbo i Serra 
198ce15e7faSCK Hu 	mmsys->data = of_device_get_match_data(&pdev->dev);
199ce15e7faSCK Hu 	platform_set_drvdata(pdev, mmsys);
20013032709SMatthias Brugger 
201ce15e7faSCK Hu 	clks = platform_device_register_data(&pdev->dev, mmsys->data->clk_driver,
20213032709SMatthias Brugger 					     PLATFORM_DEVID_AUTO, NULL, 0);
20313032709SMatthias Brugger 	if (IS_ERR(clks))
20413032709SMatthias Brugger 		return PTR_ERR(clks);
20513032709SMatthias Brugger 
206667c7692SEnric Balletbo i Serra 	drm = platform_device_register_data(&pdev->dev, "mediatek-drm",
207667c7692SEnric Balletbo i Serra 					    PLATFORM_DEVID_AUTO, NULL, 0);
208ff34e17cSWei Yongjun 	if (IS_ERR(drm)) {
209ff34e17cSWei Yongjun 		platform_device_unregister(clks);
210667c7692SEnric Balletbo i Serra 		return PTR_ERR(drm);
211ff34e17cSWei Yongjun 	}
212667c7692SEnric Balletbo i Serra 
21313032709SMatthias Brugger 	return 0;
21413032709SMatthias Brugger }
21513032709SMatthias Brugger 
21613032709SMatthias Brugger static const struct of_device_id of_match_mtk_mmsys[] = {
21713032709SMatthias Brugger 	{
218c292b133SEnric Balletbo i Serra 		.compatible = "mediatek,mt2701-mmsys",
219c292b133SEnric Balletbo i Serra 		.data = &mt2701_mmsys_driver_data,
220c292b133SEnric Balletbo i Serra 	},
221c292b133SEnric Balletbo i Serra 	{
2229c5a0a3aSEnric Balletbo i Serra 		.compatible = "mediatek,mt2712-mmsys",
2239c5a0a3aSEnric Balletbo i Serra 		.data = &mt2712_mmsys_driver_data,
2249c5a0a3aSEnric Balletbo i Serra 	},
2259c5a0a3aSEnric Balletbo i Serra 	{
22632956ddaSMatthias Brugger 		.compatible = "mediatek,mt6779-mmsys",
22732956ddaSMatthias Brugger 		.data = &mt6779_mmsys_driver_data,
22832956ddaSMatthias Brugger 	},
22932956ddaSMatthias Brugger 	{
230cad4e379SMatthias Brugger 		.compatible = "mediatek,mt6797-mmsys",
231cad4e379SMatthias Brugger 		.data = &mt6797_mmsys_driver_data,
232cad4e379SMatthias Brugger 	},
233cad4e379SMatthias Brugger 	{
234060f7875SFabien Parent 		.compatible = "mediatek,mt8167-mmsys",
235060f7875SFabien Parent 		.data = &mt8167_mmsys_driver_data,
236060f7875SFabien Parent 	},
237060f7875SFabien Parent 	{
23813032709SMatthias Brugger 		.compatible = "mediatek,mt8173-mmsys",
23913032709SMatthias Brugger 		.data = &mt8173_mmsys_driver_data,
24013032709SMatthias Brugger 	},
2411f9adbc7SMatthias Brugger 	{
2421f9adbc7SMatthias Brugger 		.compatible = "mediatek,mt8183-mmsys",
2431f9adbc7SMatthias Brugger 		.data = &mt8183_mmsys_driver_data,
2441f9adbc7SMatthias Brugger 	},
245bc3fc5c0SFabien Parent 	{
246d687e056SYongqiang Niu 		.compatible = "mediatek,mt8192-mmsys",
247d687e056SYongqiang Niu 		.data = &mt8192_mmsys_driver_data,
248d687e056SYongqiang Niu 	},
249d687e056SYongqiang Niu 	{
250bc3fc5c0SFabien Parent 		.compatible = "mediatek,mt8365-mmsys",
251bc3fc5c0SFabien Parent 		.data = &mt8365_mmsys_driver_data,
252bc3fc5c0SFabien Parent 	},
25313032709SMatthias Brugger 	{ }
25413032709SMatthias Brugger };
25513032709SMatthias Brugger 
25613032709SMatthias Brugger static struct platform_driver mtk_mmsys_drv = {
25713032709SMatthias Brugger 	.driver = {
25813032709SMatthias Brugger 		.name = "mtk-mmsys",
25913032709SMatthias Brugger 		.of_match_table = of_match_mtk_mmsys,
26013032709SMatthias Brugger 	},
26113032709SMatthias Brugger 	.probe = mtk_mmsys_probe,
26213032709SMatthias Brugger };
26313032709SMatthias Brugger 
26413032709SMatthias Brugger builtin_platform_driver(mtk_mmsys_drv);
265