linux/drivers/memory/mtk-smi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2015-2016 MediaTek Inc.
   4 * Author: Yong Wu <yong.wu@mediatek.com>
   5 */
   6#include <linux/clk.h>
   7#include <linux/component.h>
   8#include <linux/device.h>
   9#include <linux/err.h>
  10#include <linux/io.h>
  11#include <linux/module.h>
  12#include <linux/of.h>
  13#include <linux/of_platform.h>
  14#include <linux/platform_device.h>
  15#include <linux/pm_runtime.h>
  16#include <soc/mediatek/smi.h>
  17#include <dt-bindings/memory/mt2701-larb-port.h>
  18
  19/* mt8173 */
  20#define SMI_LARB_MMU_EN         0xf00
  21
  22/* mt2701 */
  23#define REG_SMI_SECUR_CON_BASE          0x5c0
  24
  25/* every register control 8 port, register offset 0x4 */
  26#define REG_SMI_SECUR_CON_OFFSET(id)    (((id) >> 3) << 2)
  27#define REG_SMI_SECUR_CON_ADDR(id)      \
  28        (REG_SMI_SECUR_CON_BASE + REG_SMI_SECUR_CON_OFFSET(id))
  29
  30/*
  31 * every port have 4 bit to control, bit[port + 3] control virtual or physical,
  32 * bit[port + 2 : port + 1] control the domain, bit[port] control the security
  33 * or non-security.
  34 */
  35#define SMI_SECUR_CON_VAL_MSK(id)       (~(0xf << (((id) & 0x7) << 2)))
  36#define SMI_SECUR_CON_VAL_VIRT(id)      BIT((((id) & 0x7) << 2) + 3)
  37/* mt2701 domain should be set to 3 */
  38#define SMI_SECUR_CON_VAL_DOMAIN(id)    (0x3 << ((((id) & 0x7) << 2) + 1))
  39
  40/* mt2712 */
  41#define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
  42#define F_MMU_EN                BIT(0)
  43
  44struct mtk_smi_larb_gen {
  45        bool need_larbid;
  46        int port_in_larb[MTK_LARB_NR_MAX + 1];
  47        void (*config_port)(struct device *);
  48};
  49
  50struct mtk_smi {
  51        struct device                   *dev;
  52        struct clk                      *clk_apb, *clk_smi;
  53        struct clk                      *clk_async; /*only needed by mt2701*/
  54        void __iomem                    *smi_ao_base;
  55};
  56
  57struct mtk_smi_larb { /* larb: local arbiter */
  58        struct mtk_smi                  smi;
  59        void __iomem                    *base;
  60        struct device                   *smi_common_dev;
  61        const struct mtk_smi_larb_gen   *larb_gen;
  62        int                             larbid;
  63        u32                             *mmu;
  64};
  65
  66enum mtk_smi_gen {
  67        MTK_SMI_GEN1,
  68        MTK_SMI_GEN2
  69};
  70
  71static int mtk_smi_enable(const struct mtk_smi *smi)
  72{
  73        int ret;
  74
  75        ret = pm_runtime_get_sync(smi->dev);
  76        if (ret < 0)
  77                return ret;
  78
  79        ret = clk_prepare_enable(smi->clk_apb);
  80        if (ret)
  81                goto err_put_pm;
  82
  83        ret = clk_prepare_enable(smi->clk_smi);
  84        if (ret)
  85                goto err_disable_apb;
  86
  87        return 0;
  88
  89err_disable_apb:
  90        clk_disable_unprepare(smi->clk_apb);
  91err_put_pm:
  92        pm_runtime_put_sync(smi->dev);
  93        return ret;
  94}
  95
  96static void mtk_smi_disable(const struct mtk_smi *smi)
  97{
  98        clk_disable_unprepare(smi->clk_smi);
  99        clk_disable_unprepare(smi->clk_apb);
 100        pm_runtime_put_sync(smi->dev);
 101}
 102
 103int mtk_smi_larb_get(struct device *larbdev)
 104{
 105        struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
 106        const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
 107        struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
 108        int ret;
 109
 110        /* Enable the smi-common's power and clocks */
 111        ret = mtk_smi_enable(common);
 112        if (ret)
 113                return ret;
 114
 115        /* Enable the larb's power and clocks */
 116        ret = mtk_smi_enable(&larb->smi);
 117        if (ret) {
 118                mtk_smi_disable(common);
 119                return ret;
 120        }
 121
 122        /* Configure the iommu info for this larb */
 123        larb_gen->config_port(larbdev);
 124
 125        return 0;
 126}
 127EXPORT_SYMBOL_GPL(mtk_smi_larb_get);
 128
 129void mtk_smi_larb_put(struct device *larbdev)
 130{
 131        struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
 132        struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
 133
 134        /*
 135         * Don't de-configure the iommu info for this larb since there may be
 136         * several modules in this larb.
 137         * The iommu info will be reset after power off.
 138         */
 139
 140        mtk_smi_disable(&larb->smi);
 141        mtk_smi_disable(common);
 142}
 143EXPORT_SYMBOL_GPL(mtk_smi_larb_put);
 144
 145static int
 146mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
 147{
 148        struct mtk_smi_larb *larb = dev_get_drvdata(dev);
 149        struct mtk_smi_iommu *smi_iommu = data;
 150        unsigned int         i;
 151
 152        if (larb->larb_gen->need_larbid) {
 153                larb->mmu = &smi_iommu->larb_imu[larb->larbid].mmu;
 154                return 0;
 155        }
 156
 157        /*
 158         * If there is no larbid property, Loop to find the corresponding
 159         * iommu information.
 160         */
 161        for (i = 0; i < smi_iommu->larb_nr; i++) {
 162                if (dev == smi_iommu->larb_imu[i].dev) {
 163                        /* The 'mmu' may be updated in iommu-attach/detach. */
 164                        larb->mmu = &smi_iommu->larb_imu[i].mmu;
 165                        return 0;
 166                }
 167        }
 168        return -ENODEV;
 169}
 170
 171static void mtk_smi_larb_config_port_mt2712(struct device *dev)
 172{
 173        struct mtk_smi_larb *larb = dev_get_drvdata(dev);
 174        u32 reg;
 175        int i;
 176
 177        /*
 178         * larb 8/9 is the bdpsys larb, the iommu_en is enabled defaultly.
 179         * Don't need to set it again.
 180         */
 181        if (larb->larbid == 8 || larb->larbid == 9)
 182                return;
 183
 184        for_each_set_bit(i, (unsigned long *)larb->mmu, 32) {
 185                reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i));
 186                reg |= F_MMU_EN;
 187                writel(reg, larb->base + SMI_LARB_NONSEC_CON(i));
 188        }
 189}
 190
 191static void mtk_smi_larb_config_port_mt8173(struct device *dev)
 192{
 193        struct mtk_smi_larb *larb = dev_get_drvdata(dev);
 194
 195        writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
 196}
 197
 198static void mtk_smi_larb_config_port_gen1(struct device *dev)
 199{
 200        struct mtk_smi_larb *larb = dev_get_drvdata(dev);
 201        const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
 202        struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
 203        int i, m4u_port_id, larb_port_num;
 204        u32 sec_con_val, reg_val;
 205
 206        m4u_port_id = larb_gen->port_in_larb[larb->larbid];
 207        larb_port_num = larb_gen->port_in_larb[larb->larbid + 1]
 208                        - larb_gen->port_in_larb[larb->larbid];
 209
 210        for (i = 0; i < larb_port_num; i++, m4u_port_id++) {
 211                if (*larb->mmu & BIT(i)) {
 212                        /* bit[port + 3] controls the virtual or physical */
 213                        sec_con_val = SMI_SECUR_CON_VAL_VIRT(m4u_port_id);
 214                } else {
 215                        /* do not need to enable m4u for this port */
 216                        continue;
 217                }
 218                reg_val = readl(common->smi_ao_base
 219                        + REG_SMI_SECUR_CON_ADDR(m4u_port_id));
 220                reg_val &= SMI_SECUR_CON_VAL_MSK(m4u_port_id);
 221                reg_val |= sec_con_val;
 222                reg_val |= SMI_SECUR_CON_VAL_DOMAIN(m4u_port_id);
 223                writel(reg_val,
 224                        common->smi_ao_base
 225                        + REG_SMI_SECUR_CON_ADDR(m4u_port_id));
 226        }
 227}
 228
 229static void
 230mtk_smi_larb_unbind(struct device *dev, struct device *master, void *data)
 231{
 232        /* Do nothing as the iommu is always enabled. */
 233}
 234
 235static const struct component_ops mtk_smi_larb_component_ops = {
 236        .bind = mtk_smi_larb_bind,
 237        .unbind = mtk_smi_larb_unbind,
 238};
 239
 240static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = {
 241        /* mt8173 do not need the port in larb */
 242        .config_port = mtk_smi_larb_config_port_mt8173,
 243};
 244
 245static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
 246        .need_larbid = true,
 247        .port_in_larb = {
 248                LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
 249                LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
 250        },
 251        .config_port = mtk_smi_larb_config_port_gen1,
 252};
 253
 254static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = {
 255        .need_larbid = true,
 256        .config_port = mtk_smi_larb_config_port_mt2712,
 257};
 258
 259static const struct of_device_id mtk_smi_larb_of_ids[] = {
 260        {
 261                .compatible = "mediatek,mt8173-smi-larb",
 262                .data = &mtk_smi_larb_mt8173
 263        },
 264        {
 265                .compatible = "mediatek,mt2701-smi-larb",
 266                .data = &mtk_smi_larb_mt2701
 267        },
 268        {
 269                .compatible = "mediatek,mt2712-smi-larb",
 270                .data = &mtk_smi_larb_mt2712
 271        },
 272        {}
 273};
 274
 275static int mtk_smi_larb_probe(struct platform_device *pdev)
 276{
 277        struct mtk_smi_larb *larb;
 278        struct resource *res;
 279        struct device *dev = &pdev->dev;
 280        struct device_node *smi_node;
 281        struct platform_device *smi_pdev;
 282        int err;
 283
 284        larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
 285        if (!larb)
 286                return -ENOMEM;
 287
 288        larb->larb_gen = of_device_get_match_data(dev);
 289        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 290        larb->base = devm_ioremap_resource(dev, res);
 291        if (IS_ERR(larb->base))
 292                return PTR_ERR(larb->base);
 293
 294        larb->smi.clk_apb = devm_clk_get(dev, "apb");
 295        if (IS_ERR(larb->smi.clk_apb))
 296                return PTR_ERR(larb->smi.clk_apb);
 297
 298        larb->smi.clk_smi = devm_clk_get(dev, "smi");
 299        if (IS_ERR(larb->smi.clk_smi))
 300                return PTR_ERR(larb->smi.clk_smi);
 301        larb->smi.dev = dev;
 302
 303        if (larb->larb_gen->need_larbid) {
 304                err = of_property_read_u32(dev->of_node, "mediatek,larb-id",
 305                                           &larb->larbid);
 306                if (err) {
 307                        dev_err(dev, "missing larbid property\n");
 308                        return err;
 309                }
 310        }
 311
 312        smi_node = of_parse_phandle(dev->of_node, "mediatek,smi", 0);
 313        if (!smi_node)
 314                return -EINVAL;
 315
 316        smi_pdev = of_find_device_by_node(smi_node);
 317        of_node_put(smi_node);
 318        if (smi_pdev) {
 319                if (!platform_get_drvdata(smi_pdev))
 320                        return -EPROBE_DEFER;
 321                larb->smi_common_dev = &smi_pdev->dev;
 322        } else {
 323                dev_err(dev, "Failed to get the smi_common device\n");
 324                return -EINVAL;
 325        }
 326
 327        pm_runtime_enable(dev);
 328        platform_set_drvdata(pdev, larb);
 329        return component_add(dev, &mtk_smi_larb_component_ops);
 330}
 331
 332static int mtk_smi_larb_remove(struct platform_device *pdev)
 333{
 334        pm_runtime_disable(&pdev->dev);
 335        component_del(&pdev->dev, &mtk_smi_larb_component_ops);
 336        return 0;
 337}
 338
 339static struct platform_driver mtk_smi_larb_driver = {
 340        .probe  = mtk_smi_larb_probe,
 341        .remove = mtk_smi_larb_remove,
 342        .driver = {
 343                .name = "mtk-smi-larb",
 344                .of_match_table = mtk_smi_larb_of_ids,
 345        }
 346};
 347
 348static const struct of_device_id mtk_smi_common_of_ids[] = {
 349        {
 350                .compatible = "mediatek,mt8173-smi-common",
 351                .data = (void *)MTK_SMI_GEN2
 352        },
 353        {
 354                .compatible = "mediatek,mt2701-smi-common",
 355                .data = (void *)MTK_SMI_GEN1
 356        },
 357        {
 358                .compatible = "mediatek,mt2712-smi-common",
 359                .data = (void *)MTK_SMI_GEN2
 360        },
 361        {}
 362};
 363
 364static int mtk_smi_common_probe(struct platform_device *pdev)
 365{
 366        struct device *dev = &pdev->dev;
 367        struct mtk_smi *common;
 368        struct resource *res;
 369        enum mtk_smi_gen smi_gen;
 370        int ret;
 371
 372        common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL);
 373        if (!common)
 374                return -ENOMEM;
 375        common->dev = dev;
 376
 377        common->clk_apb = devm_clk_get(dev, "apb");
 378        if (IS_ERR(common->clk_apb))
 379                return PTR_ERR(common->clk_apb);
 380
 381        common->clk_smi = devm_clk_get(dev, "smi");
 382        if (IS_ERR(common->clk_smi))
 383                return PTR_ERR(common->clk_smi);
 384
 385        /*
 386         * for mtk smi gen 1, we need to get the ao(always on) base to config
 387         * m4u port, and we need to enable the aync clock for transform the smi
 388         * clock into emi clock domain, but for mtk smi gen2, there's no smi ao
 389         * base.
 390         */
 391        smi_gen = (enum mtk_smi_gen)of_device_get_match_data(dev);
 392        if (smi_gen == MTK_SMI_GEN1) {
 393                res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 394                common->smi_ao_base = devm_ioremap_resource(dev, res);
 395                if (IS_ERR(common->smi_ao_base))
 396                        return PTR_ERR(common->smi_ao_base);
 397
 398                common->clk_async = devm_clk_get(dev, "async");
 399                if (IS_ERR(common->clk_async))
 400                        return PTR_ERR(common->clk_async);
 401
 402                ret = clk_prepare_enable(common->clk_async);
 403                if (ret)
 404                        return ret;
 405        }
 406        pm_runtime_enable(dev);
 407        platform_set_drvdata(pdev, common);
 408        return 0;
 409}
 410
 411static int mtk_smi_common_remove(struct platform_device *pdev)
 412{
 413        pm_runtime_disable(&pdev->dev);
 414        return 0;
 415}
 416
 417static struct platform_driver mtk_smi_common_driver = {
 418        .probe  = mtk_smi_common_probe,
 419        .remove = mtk_smi_common_remove,
 420        .driver = {
 421                .name = "mtk-smi-common",
 422                .of_match_table = mtk_smi_common_of_ids,
 423        }
 424};
 425
 426static int __init mtk_smi_init(void)
 427{
 428        int ret;
 429
 430        ret = platform_driver_register(&mtk_smi_common_driver);
 431        if (ret != 0) {
 432                pr_err("Failed to register SMI driver\n");
 433                return ret;
 434        }
 435
 436        ret = platform_driver_register(&mtk_smi_larb_driver);
 437        if (ret != 0) {
 438                pr_err("Failed to register SMI-LARB driver\n");
 439                goto err_unreg_smi;
 440        }
 441        return ret;
 442
 443err_unreg_smi:
 444        platform_driver_unregister(&mtk_smi_common_driver);
 445        return ret;
 446}
 447
 448module_init(mtk_smi_init);
 449