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