Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2014 MediaTek Inc.
0004  * Author: James Liao <jamesjj.liao@mediatek.com>
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; /* protects mmsys_sw_rst_b reg */
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         /* This SoC has multiple mmsys channels */
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);