1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2014 MediaTek Inc. 4 * Author: James Liao <jamesjj.liao@mediatek.com> 5 */ 6 7 #include <linux/delay.h> 8 #include <linux/device.h> 9 #include <linux/io.h> 10 #include <linux/of_device.h> 11 #include <linux/platform_device.h> 12 #include <linux/reset-controller.h> 13 #include <linux/soc/mediatek/mtk-mmsys.h> 14 15 #include "mtk-mmsys.h" 16 #include "mt8167-mmsys.h" 17 #include "mt8183-mmsys.h" 18 #include "mt8192-mmsys.h" 19 #include "mt8365-mmsys.h" 20 21 static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = { 22 .clk_driver = "clk-mt2701-mm", 23 .routes = mmsys_default_routing_table, 24 .num_routes = ARRAY_SIZE(mmsys_default_routing_table), 25 }; 26 27 static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = { 28 .clk_driver = "clk-mt2712-mm", 29 .routes = mmsys_default_routing_table, 30 .num_routes = ARRAY_SIZE(mmsys_default_routing_table), 31 }; 32 33 static const struct mtk_mmsys_driver_data mt6779_mmsys_driver_data = { 34 .clk_driver = "clk-mt6779-mm", 35 }; 36 37 static const struct mtk_mmsys_driver_data mt6797_mmsys_driver_data = { 38 .clk_driver = "clk-mt6797-mm", 39 }; 40 41 static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data = { 42 .clk_driver = "clk-mt8167-mm", 43 .routes = mt8167_mmsys_routing_table, 44 .num_routes = ARRAY_SIZE(mt8167_mmsys_routing_table), 45 }; 46 47 static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = { 48 .clk_driver = "clk-mt8173-mm", 49 .routes = mmsys_default_routing_table, 50 .num_routes = ARRAY_SIZE(mmsys_default_routing_table), 51 }; 52 53 static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = { 54 .clk_driver = "clk-mt8183-mm", 55 .routes = mmsys_mt8183_routing_table, 56 .num_routes = ARRAY_SIZE(mmsys_mt8183_routing_table), 57 }; 58 59 static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = { 60 .clk_driver = "clk-mt8192-mm", 61 .routes = mmsys_mt8192_routing_table, 62 .num_routes = ARRAY_SIZE(mmsys_mt8192_routing_table), 63 }; 64 65 static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = { 66 .clk_driver = "clk-mt8365-mm", 67 .routes = mt8365_mmsys_routing_table, 68 .num_routes = ARRAY_SIZE(mt8365_mmsys_routing_table), 69 }; 70 71 struct mtk_mmsys { 72 void __iomem *regs; 73 const struct mtk_mmsys_driver_data *data; 74 spinlock_t lock; /* protects mmsys_sw_rst_b reg */ 75 struct reset_controller_dev rcdev; 76 }; 77 78 void mtk_mmsys_ddp_connect(struct device *dev, 79 enum mtk_ddp_comp_id cur, 80 enum mtk_ddp_comp_id next) 81 { 82 struct mtk_mmsys *mmsys = dev_get_drvdata(dev); 83 const struct mtk_mmsys_routes *routes = mmsys->data->routes; 84 u32 reg; 85 int i; 86 87 for (i = 0; i < mmsys->data->num_routes; i++) 88 if (cur == routes[i].from_comp && next == routes[i].to_comp) { 89 reg = readl_relaxed(mmsys->regs + routes[i].addr); 90 reg &= ~routes[i].mask; 91 reg |= routes[i].val; 92 writel_relaxed(reg, mmsys->regs + routes[i].addr); 93 } 94 } 95 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_connect); 96 97 void mtk_mmsys_ddp_disconnect(struct device *dev, 98 enum mtk_ddp_comp_id cur, 99 enum mtk_ddp_comp_id next) 100 { 101 struct mtk_mmsys *mmsys = dev_get_drvdata(dev); 102 const struct mtk_mmsys_routes *routes = mmsys->data->routes; 103 u32 reg; 104 int i; 105 106 for (i = 0; i < mmsys->data->num_routes; i++) 107 if (cur == routes[i].from_comp && next == routes[i].to_comp) { 108 reg = readl_relaxed(mmsys->regs + routes[i].addr); 109 reg &= ~routes[i].mask; 110 writel_relaxed(reg, mmsys->regs + routes[i].addr); 111 } 112 } 113 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect); 114 115 static int mtk_mmsys_reset_update(struct reset_controller_dev *rcdev, unsigned long id, 116 bool assert) 117 { 118 struct mtk_mmsys *mmsys = container_of(rcdev, struct mtk_mmsys, rcdev); 119 unsigned long flags; 120 u32 reg; 121 122 spin_lock_irqsave(&mmsys->lock, flags); 123 124 reg = readl_relaxed(mmsys->regs + MMSYS_SW0_RST_B); 125 126 if (assert) 127 reg &= ~BIT(id); 128 else 129 reg |= BIT(id); 130 131 writel_relaxed(reg, mmsys->regs + MMSYS_SW0_RST_B); 132 133 spin_unlock_irqrestore(&mmsys->lock, flags); 134 135 return 0; 136 } 137 138 static int mtk_mmsys_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) 139 { 140 return mtk_mmsys_reset_update(rcdev, id, true); 141 } 142 143 static int mtk_mmsys_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) 144 { 145 return mtk_mmsys_reset_update(rcdev, id, false); 146 } 147 148 static int mtk_mmsys_reset(struct reset_controller_dev *rcdev, unsigned long id) 149 { 150 int ret; 151 152 ret = mtk_mmsys_reset_assert(rcdev, id); 153 if (ret) 154 return ret; 155 156 usleep_range(1000, 1100); 157 158 return mtk_mmsys_reset_deassert(rcdev, id); 159 } 160 161 static const struct reset_control_ops mtk_mmsys_reset_ops = { 162 .assert = mtk_mmsys_reset_assert, 163 .deassert = mtk_mmsys_reset_deassert, 164 .reset = mtk_mmsys_reset, 165 }; 166 167 static int mtk_mmsys_probe(struct platform_device *pdev) 168 { 169 struct device *dev = &pdev->dev; 170 struct platform_device *clks; 171 struct platform_device *drm; 172 struct mtk_mmsys *mmsys; 173 int ret; 174 175 mmsys = devm_kzalloc(dev, sizeof(*mmsys), GFP_KERNEL); 176 if (!mmsys) 177 return -ENOMEM; 178 179 mmsys->regs = devm_platform_ioremap_resource(pdev, 0); 180 if (IS_ERR(mmsys->regs)) { 181 ret = PTR_ERR(mmsys->regs); 182 dev_err(dev, "Failed to ioremap mmsys registers: %d\n", ret); 183 return ret; 184 } 185 186 spin_lock_init(&mmsys->lock); 187 188 mmsys->rcdev.owner = THIS_MODULE; 189 mmsys->rcdev.nr_resets = 32; 190 mmsys->rcdev.ops = &mtk_mmsys_reset_ops; 191 mmsys->rcdev.of_node = pdev->dev.of_node; 192 ret = devm_reset_controller_register(&pdev->dev, &mmsys->rcdev); 193 if (ret) { 194 dev_err(&pdev->dev, "Couldn't register mmsys reset controller: %d\n", ret); 195 return ret; 196 } 197 198 mmsys->data = of_device_get_match_data(&pdev->dev); 199 platform_set_drvdata(pdev, mmsys); 200 201 clks = platform_device_register_data(&pdev->dev, mmsys->data->clk_driver, 202 PLATFORM_DEVID_AUTO, NULL, 0); 203 if (IS_ERR(clks)) 204 return PTR_ERR(clks); 205 206 drm = platform_device_register_data(&pdev->dev, "mediatek-drm", 207 PLATFORM_DEVID_AUTO, NULL, 0); 208 if (IS_ERR(drm)) { 209 platform_device_unregister(clks); 210 return PTR_ERR(drm); 211 } 212 213 return 0; 214 } 215 216 static const struct of_device_id of_match_mtk_mmsys[] = { 217 { 218 .compatible = "mediatek,mt2701-mmsys", 219 .data = &mt2701_mmsys_driver_data, 220 }, 221 { 222 .compatible = "mediatek,mt2712-mmsys", 223 .data = &mt2712_mmsys_driver_data, 224 }, 225 { 226 .compatible = "mediatek,mt6779-mmsys", 227 .data = &mt6779_mmsys_driver_data, 228 }, 229 { 230 .compatible = "mediatek,mt6797-mmsys", 231 .data = &mt6797_mmsys_driver_data, 232 }, 233 { 234 .compatible = "mediatek,mt8167-mmsys", 235 .data = &mt8167_mmsys_driver_data, 236 }, 237 { 238 .compatible = "mediatek,mt8173-mmsys", 239 .data = &mt8173_mmsys_driver_data, 240 }, 241 { 242 .compatible = "mediatek,mt8183-mmsys", 243 .data = &mt8183_mmsys_driver_data, 244 }, 245 { 246 .compatible = "mediatek,mt8192-mmsys", 247 .data = &mt8192_mmsys_driver_data, 248 }, 249 { 250 .compatible = "mediatek,mt8365-mmsys", 251 .data = &mt8365_mmsys_driver_data, 252 }, 253 { } 254 }; 255 256 static struct platform_driver mtk_mmsys_drv = { 257 .driver = { 258 .name = "mtk-mmsys", 259 .of_match_table = of_match_mtk_mmsys, 260 }, 261 .probe = mtk_mmsys_probe, 262 }; 263 264 builtin_platform_driver(mtk_mmsys_drv); 265