0001
0002
0003
0004
0005
0006
0007 #include <linux/delay.h>
0008 #include <linux/device.h>
0009 #include <linux/io.h>
0010 #include <linux/of_device.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/reset-controller.h>
0013 #include <linux/soc/mediatek/mtk-mmsys.h>
0014
0015 #include "mtk-mmsys.h"
0016 #include "mt8167-mmsys.h"
0017 #include "mt8183-mmsys.h"
0018 #include "mt8186-mmsys.h"
0019 #include "mt8192-mmsys.h"
0020 #include "mt8195-mmsys.h"
0021 #include "mt8365-mmsys.h"
0022
0023 static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
0024 .clk_driver = "clk-mt2701-mm",
0025 .routes = mmsys_default_routing_table,
0026 .num_routes = ARRAY_SIZE(mmsys_default_routing_table),
0027 };
0028
0029 static const struct mtk_mmsys_match_data mt2701_mmsys_match_data = {
0030 .num_drv_data = 1,
0031 .drv_data = {
0032 &mt2701_mmsys_driver_data,
0033 },
0034 };
0035
0036 static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
0037 .clk_driver = "clk-mt2712-mm",
0038 .routes = mmsys_default_routing_table,
0039 .num_routes = ARRAY_SIZE(mmsys_default_routing_table),
0040 };
0041
0042 static const struct mtk_mmsys_match_data mt2712_mmsys_match_data = {
0043 .num_drv_data = 1,
0044 .drv_data = {
0045 &mt2712_mmsys_driver_data,
0046 },
0047 };
0048
0049 static const struct mtk_mmsys_driver_data mt6779_mmsys_driver_data = {
0050 .clk_driver = "clk-mt6779-mm",
0051 };
0052
0053 static const struct mtk_mmsys_match_data mt6779_mmsys_match_data = {
0054 .num_drv_data = 1,
0055 .drv_data = {
0056 &mt6779_mmsys_driver_data,
0057 },
0058 };
0059
0060 static const struct mtk_mmsys_driver_data mt6797_mmsys_driver_data = {
0061 .clk_driver = "clk-mt6797-mm",
0062 };
0063
0064 static const struct mtk_mmsys_match_data mt6797_mmsys_match_data = {
0065 .num_drv_data = 1,
0066 .drv_data = {
0067 &mt6797_mmsys_driver_data,
0068 },
0069 };
0070
0071 static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data = {
0072 .clk_driver = "clk-mt8167-mm",
0073 .routes = mt8167_mmsys_routing_table,
0074 .num_routes = ARRAY_SIZE(mt8167_mmsys_routing_table),
0075 };
0076
0077 static const struct mtk_mmsys_match_data mt8167_mmsys_match_data = {
0078 .num_drv_data = 1,
0079 .drv_data = {
0080 &mt8167_mmsys_driver_data,
0081 },
0082 };
0083
0084 static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
0085 .clk_driver = "clk-mt8173-mm",
0086 .routes = mmsys_default_routing_table,
0087 .num_routes = ARRAY_SIZE(mmsys_default_routing_table),
0088 .sw0_rst_offset = MT8183_MMSYS_SW0_RST_B,
0089 };
0090
0091 static const struct mtk_mmsys_match_data mt8173_mmsys_match_data = {
0092 .num_drv_data = 1,
0093 .drv_data = {
0094 &mt8173_mmsys_driver_data,
0095 },
0096 };
0097
0098 static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
0099 .clk_driver = "clk-mt8183-mm",
0100 .routes = mmsys_mt8183_routing_table,
0101 .num_routes = ARRAY_SIZE(mmsys_mt8183_routing_table),
0102 .sw0_rst_offset = MT8183_MMSYS_SW0_RST_B,
0103 };
0104
0105 static const struct mtk_mmsys_match_data mt8183_mmsys_match_data = {
0106 .num_drv_data = 1,
0107 .drv_data = {
0108 &mt8183_mmsys_driver_data,
0109 },
0110 };
0111
0112 static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data = {
0113 .clk_driver = "clk-mt8186-mm",
0114 .routes = mmsys_mt8186_routing_table,
0115 .num_routes = ARRAY_SIZE(mmsys_mt8186_routing_table),
0116 .sw0_rst_offset = MT8186_MMSYS_SW0_RST_B,
0117 };
0118
0119 static const struct mtk_mmsys_match_data mt8186_mmsys_match_data = {
0120 .num_drv_data = 1,
0121 .drv_data = {
0122 &mt8186_mmsys_driver_data,
0123 },
0124 };
0125
0126 static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = {
0127 .clk_driver = "clk-mt8192-mm",
0128 .routes = mmsys_mt8192_routing_table,
0129 .num_routes = ARRAY_SIZE(mmsys_mt8192_routing_table),
0130 .sw0_rst_offset = MT8186_MMSYS_SW0_RST_B,
0131 };
0132
0133 static const struct mtk_mmsys_match_data mt8192_mmsys_match_data = {
0134 .num_drv_data = 1,
0135 .drv_data = {
0136 &mt8192_mmsys_driver_data,
0137 },
0138 };
0139
0140 static const struct mtk_mmsys_driver_data mt8195_vdosys0_driver_data = {
0141 .io_start = 0x1c01a000,
0142 .clk_driver = "clk-mt8195-vdo0",
0143 .routes = mmsys_mt8195_routing_table,
0144 .num_routes = ARRAY_SIZE(mmsys_mt8195_routing_table),
0145 };
0146
0147 static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
0148 .io_start = 0x1c100000,
0149 .clk_driver = "clk-mt8195-vdo1",
0150 };
0151
0152 static const struct mtk_mmsys_match_data mt8195_mmsys_match_data = {
0153 .num_drv_data = 2,
0154 .drv_data = {
0155 &mt8195_vdosys0_driver_data,
0156 &mt8195_vdosys1_driver_data,
0157 },
0158 };
0159
0160 static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
0161 .clk_driver = "clk-mt8365-mm",
0162 .routes = mt8365_mmsys_routing_table,
0163 .num_routes = ARRAY_SIZE(mt8365_mmsys_routing_table),
0164 };
0165
0166 static const struct mtk_mmsys_match_data mt8365_mmsys_match_data = {
0167 .num_drv_data = 1,
0168 .drv_data = {
0169 &mt8365_mmsys_driver_data,
0170 },
0171 };
0172
0173 struct mtk_mmsys {
0174 void __iomem *regs;
0175 const struct mtk_mmsys_driver_data *data;
0176 spinlock_t lock;
0177 struct reset_controller_dev rcdev;
0178 phys_addr_t io_start;
0179 };
0180
0181 static int mtk_mmsys_find_match_drvdata(struct mtk_mmsys *mmsys,
0182 const struct mtk_mmsys_match_data *match)
0183 {
0184 int i;
0185
0186 for (i = 0; i < match->num_drv_data; i++)
0187 if (mmsys->io_start == match->drv_data[i]->io_start)
0188 return i;
0189
0190 return -EINVAL;
0191 }
0192
0193 void mtk_mmsys_ddp_connect(struct device *dev,
0194 enum mtk_ddp_comp_id cur,
0195 enum mtk_ddp_comp_id next)
0196 {
0197 struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
0198 const struct mtk_mmsys_routes *routes = mmsys->data->routes;
0199 u32 reg;
0200 int i;
0201
0202 for (i = 0; i < mmsys->data->num_routes; i++)
0203 if (cur == routes[i].from_comp && next == routes[i].to_comp) {
0204 reg = readl_relaxed(mmsys->regs + routes[i].addr);
0205 reg &= ~routes[i].mask;
0206 reg |= routes[i].val;
0207 writel_relaxed(reg, mmsys->regs + routes[i].addr);
0208 }
0209 }
0210 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_connect);
0211
0212 void mtk_mmsys_ddp_disconnect(struct device *dev,
0213 enum mtk_ddp_comp_id cur,
0214 enum mtk_ddp_comp_id next)
0215 {
0216 struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
0217 const struct mtk_mmsys_routes *routes = mmsys->data->routes;
0218 u32 reg;
0219 int i;
0220
0221 for (i = 0; i < mmsys->data->num_routes; i++)
0222 if (cur == routes[i].from_comp && next == routes[i].to_comp) {
0223 reg = readl_relaxed(mmsys->regs + routes[i].addr);
0224 reg &= ~routes[i].mask;
0225 writel_relaxed(reg, mmsys->regs + routes[i].addr);
0226 }
0227 }
0228 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect);
0229
0230 static int mtk_mmsys_reset_update(struct reset_controller_dev *rcdev, unsigned long id,
0231 bool assert)
0232 {
0233 struct mtk_mmsys *mmsys = container_of(rcdev, struct mtk_mmsys, rcdev);
0234 unsigned long flags;
0235 u32 reg;
0236
0237 spin_lock_irqsave(&mmsys->lock, flags);
0238
0239 reg = readl_relaxed(mmsys->regs + mmsys->data->sw0_rst_offset);
0240
0241 if (assert)
0242 reg &= ~BIT(id);
0243 else
0244 reg |= BIT(id);
0245
0246 writel_relaxed(reg, mmsys->regs + mmsys->data->sw0_rst_offset);
0247
0248 spin_unlock_irqrestore(&mmsys->lock, flags);
0249
0250 return 0;
0251 }
0252
0253 static int mtk_mmsys_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
0254 {
0255 return mtk_mmsys_reset_update(rcdev, id, true);
0256 }
0257
0258 static int mtk_mmsys_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
0259 {
0260 return mtk_mmsys_reset_update(rcdev, id, false);
0261 }
0262
0263 static int mtk_mmsys_reset(struct reset_controller_dev *rcdev, unsigned long id)
0264 {
0265 int ret;
0266
0267 ret = mtk_mmsys_reset_assert(rcdev, id);
0268 if (ret)
0269 return ret;
0270
0271 usleep_range(1000, 1100);
0272
0273 return mtk_mmsys_reset_deassert(rcdev, id);
0274 }
0275
0276 static const struct reset_control_ops mtk_mmsys_reset_ops = {
0277 .assert = mtk_mmsys_reset_assert,
0278 .deassert = mtk_mmsys_reset_deassert,
0279 .reset = mtk_mmsys_reset,
0280 };
0281
0282 static int mtk_mmsys_probe(struct platform_device *pdev)
0283 {
0284 struct device *dev = &pdev->dev;
0285 struct platform_device *clks;
0286 struct platform_device *drm;
0287 const struct mtk_mmsys_match_data *match_data;
0288 struct mtk_mmsys *mmsys;
0289 struct resource *res;
0290 int ret;
0291
0292 mmsys = devm_kzalloc(dev, sizeof(*mmsys), GFP_KERNEL);
0293 if (!mmsys)
0294 return -ENOMEM;
0295
0296 mmsys->regs = devm_platform_ioremap_resource(pdev, 0);
0297 if (IS_ERR(mmsys->regs)) {
0298 ret = PTR_ERR(mmsys->regs);
0299 dev_err(dev, "Failed to ioremap mmsys registers: %d\n", ret);
0300 return ret;
0301 }
0302
0303 spin_lock_init(&mmsys->lock);
0304
0305 mmsys->rcdev.owner = THIS_MODULE;
0306 mmsys->rcdev.nr_resets = 32;
0307 mmsys->rcdev.ops = &mtk_mmsys_reset_ops;
0308 mmsys->rcdev.of_node = pdev->dev.of_node;
0309 ret = devm_reset_controller_register(&pdev->dev, &mmsys->rcdev);
0310 if (ret) {
0311 dev_err(&pdev->dev, "Couldn't register mmsys reset controller: %d\n", ret);
0312 return ret;
0313 }
0314
0315 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0316 if (!res) {
0317 dev_err(dev, "Couldn't get mmsys resource\n");
0318 return -EINVAL;
0319 }
0320 mmsys->io_start = res->start;
0321
0322 match_data = of_device_get_match_data(dev);
0323 if (match_data->num_drv_data > 1) {
0324
0325 ret = mtk_mmsys_find_match_drvdata(mmsys, match_data);
0326 if (ret < 0) {
0327 dev_err(dev, "Couldn't get match driver data\n");
0328 return ret;
0329 }
0330 mmsys->data = match_data->drv_data[ret];
0331 } else {
0332 dev_dbg(dev, "Using single mmsys channel\n");
0333 mmsys->data = match_data->drv_data[0];
0334 }
0335
0336 platform_set_drvdata(pdev, mmsys);
0337
0338 clks = platform_device_register_data(&pdev->dev, mmsys->data->clk_driver,
0339 PLATFORM_DEVID_AUTO, NULL, 0);
0340 if (IS_ERR(clks))
0341 return PTR_ERR(clks);
0342
0343 drm = platform_device_register_data(&pdev->dev, "mediatek-drm",
0344 PLATFORM_DEVID_AUTO, NULL, 0);
0345 if (IS_ERR(drm)) {
0346 platform_device_unregister(clks);
0347 return PTR_ERR(drm);
0348 }
0349
0350 return 0;
0351 }
0352
0353 static const struct of_device_id of_match_mtk_mmsys[] = {
0354 {
0355 .compatible = "mediatek,mt2701-mmsys",
0356 .data = &mt2701_mmsys_match_data,
0357 },
0358 {
0359 .compatible = "mediatek,mt2712-mmsys",
0360 .data = &mt2712_mmsys_match_data,
0361 },
0362 {
0363 .compatible = "mediatek,mt6779-mmsys",
0364 .data = &mt6779_mmsys_match_data,
0365 },
0366 {
0367 .compatible = "mediatek,mt6797-mmsys",
0368 .data = &mt6797_mmsys_match_data,
0369 },
0370 {
0371 .compatible = "mediatek,mt8167-mmsys",
0372 .data = &mt8167_mmsys_match_data,
0373 },
0374 {
0375 .compatible = "mediatek,mt8173-mmsys",
0376 .data = &mt8173_mmsys_match_data,
0377 },
0378 {
0379 .compatible = "mediatek,mt8183-mmsys",
0380 .data = &mt8183_mmsys_match_data,
0381 },
0382 {
0383 .compatible = "mediatek,mt8186-mmsys",
0384 .data = &mt8186_mmsys_match_data,
0385 },
0386 {
0387 .compatible = "mediatek,mt8192-mmsys",
0388 .data = &mt8192_mmsys_match_data,
0389 },
0390 {
0391 .compatible = "mediatek,mt8195-mmsys",
0392 .data = &mt8195_mmsys_match_data,
0393 },
0394 {
0395 .compatible = "mediatek,mt8365-mmsys",
0396 .data = &mt8365_mmsys_match_data,
0397 },
0398 { }
0399 };
0400
0401 static struct platform_driver mtk_mmsys_drv = {
0402 .driver = {
0403 .name = "mtk-mmsys",
0404 .of_match_table = of_match_mtk_mmsys,
0405 },
0406 .probe = mtk_mmsys_probe,
0407 };
0408
0409 builtin_platform_driver(mtk_mmsys_drv);