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