uboot/drivers/power/domain/imx8m-power-domain.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright 2017 NXP
   4 */
   5
   6#include <common.h>
   7#include <clk.h>
   8#include <dm.h>
   9#include <malloc.h>
  10#include <power-domain-uclass.h>
  11#include <asm/global_data.h>
  12#include <asm/io.h>
  13#include <asm/mach-imx/sys_proto.h>
  14#include <dm/device-internal.h>
  15#include <dm/device.h>
  16#include <dm/device_compat.h>
  17#include <imx_sip.h>
  18#include <linux/bitmap.h>
  19#include <wait_bit.h>
  20
  21#include <dt-bindings/power/imx8mm-power.h>
  22#include <dt-bindings/power/imx8mn-power.h>
  23#include <dt-bindings/power/imx8mp-power.h>
  24#include <dt-bindings/power/imx8mq-power.h>
  25
  26DECLARE_GLOBAL_DATA_PTR;
  27
  28#define GPC_PGC_CPU_MAPPING                     0x0ec
  29#define IMX8MP_GPC_PGC_CPU_MAPPING              0x1cc
  30
  31#define IMX8M_PCIE2_A53_DOMAIN                  BIT(15)
  32#define IMX8M_OTG2_A53_DOMAIN                   BIT(5)
  33#define IMX8M_OTG1_A53_DOMAIN                   BIT(4)
  34#define IMX8M_PCIE1_A53_DOMAIN                  BIT(3)
  35
  36#define IMX8MM_OTG2_A53_DOMAIN                  BIT(5)
  37#define IMX8MM_OTG1_A53_DOMAIN                  BIT(4)
  38#define IMX8MM_PCIE_A53_DOMAIN                  BIT(3)
  39
  40#define IMX8MN_OTG1_A53_DOMAIN                  BIT(4)
  41#define IMX8MN_MIPI_A53_DOMAIN                  BIT(2)
  42
  43#define IMX8MP_HSIOMIX_A53_DOMAIN               BIT(19)
  44#define IMX8MP_USB2_PHY_A53_DOMAIN              BIT(5)
  45#define IMX8MP_USB1_PHY_A53_DOMAIN              BIT(4)
  46#define IMX8MP_PCIE_PHY_A53_DOMAIN              BIT(3)
  47
  48#define IMX8MP_GPC_PU_PGC_SW_PUP_REQ            0x0d8
  49#define IMX8MP_GPC_PU_PGC_SW_PDN_REQ            0x0e4
  50
  51#define GPC_PU_PGC_SW_PUP_REQ                   0x0f8
  52#define GPC_PU_PGC_SW_PDN_REQ                   0x104
  53
  54#define IMX8M_PCIE2_SW_Pxx_REQ                  BIT(13)
  55#define IMX8M_OTG2_SW_Pxx_REQ                   BIT(3)
  56#define IMX8M_OTG1_SW_Pxx_REQ                   BIT(2)
  57#define IMX8M_PCIE1_SW_Pxx_REQ                  BIT(1)
  58
  59#define IMX8MM_OTG2_SW_Pxx_REQ                  BIT(3)
  60#define IMX8MM_OTG1_SW_Pxx_REQ                  BIT(2)
  61#define IMX8MM_PCIE_SW_Pxx_REQ                  BIT(1)
  62
  63#define IMX8MN_OTG1_SW_Pxx_REQ                  BIT(2)
  64#define IMX8MN_MIPI_SW_Pxx_REQ                  BIT(0)
  65
  66#define IMX8MP_HSIOMIX_Pxx_REQ                  BIT(17)
  67#define IMX8MP_USB2_PHY_Pxx_REQ                 BIT(3)
  68#define IMX8MP_USB1_PHY_Pxx_REQ                 BIT(2)
  69#define IMX8MP_PCIE_PHY_SW_Pxx_REQ              BIT(1)
  70
  71#define GPC_M4_PU_PDN_FLG                       0x1bc
  72
  73#define IMX8MP_GPC_PU_PWRHSK                    0x190
  74#define GPC_PU_PWRHSK                           0x1fc
  75
  76#define IMX8MM_HSIO_HSK_PWRDNACKN               (BIT(23) | BIT(24))
  77#define IMX8MM_HSIO_HSK_PWRDNREQN               (BIT(5) | BIT(6))
  78
  79#define IMX8MN_HSIO_HSK_PWRDNACKN               BIT(23)
  80#define IMX8MN_HSIO_HSK_PWRDNREQN               BIT(5)
  81
  82#define IMX8MP_HSIOMIX_PWRDNACKN                BIT(28)
  83#define IMX8MP_HSIOMIX_PWRDNREQN                BIT(12)
  84
  85/*
  86 * The PGC offset values in Reference Manual
  87 * (Rev. 1, 01/2018 and the older ones) GPC chapter's
  88 * GPC_PGC memory map are incorrect, below offset
  89 * values are from design RTL.
  90 */
  91#define IMX8M_PGC_PCIE1                 17
  92#define IMX8M_PGC_OTG1                  18
  93#define IMX8M_PGC_OTG2                  19
  94#define IMX8M_PGC_PCIE2                 29
  95
  96#define IMX8MM_PGC_PCIE                 17
  97#define IMX8MM_PGC_OTG1                 18
  98#define IMX8MM_PGC_OTG2                 19
  99
 100#define IMX8MN_PGC_OTG1                 18
 101
 102#define IMX8MP_PGC_PCIE                 13
 103#define IMX8MP_PGC_USB1                 14
 104#define IMX8MP_PGC_USB2                 15
 105#define IMX8MP_PGC_HSIOMIX              29
 106
 107#define GPC_PGC_CTRL(n)                 (0x800 + (n) * 0x40)
 108#define GPC_PGC_SR(n)                   (GPC_PGC_CTRL(n) + 0xc)
 109
 110#define GPC_PGC_CTRL_PCR                BIT(0)
 111
 112struct imx_pgc_regs {
 113        u16 map;
 114        u16 pup;
 115        u16 pdn;
 116        u16 hsk;
 117};
 118
 119struct imx_pgc_domain {
 120        unsigned long pgc;
 121
 122        const struct {
 123                u32 pxx;
 124                u32 map;
 125                u32 hskreq;
 126                u32 hskack;
 127        } bits;
 128
 129        const bool keep_clocks;
 130};
 131
 132struct imx_pgc_domain_data {
 133        const struct imx_pgc_domain *domains;
 134        size_t domains_num;
 135        const struct imx_pgc_regs *pgc_regs;
 136};
 137
 138struct imx8m_power_domain_plat {
 139        struct power_domain pd;
 140        const struct imx_pgc_domain *domain;
 141        const struct imx_pgc_regs *regs;
 142        struct clk_bulk clk;
 143        void __iomem *base;
 144        int resource_id;
 145        int has_pd;
 146};
 147
 148#if defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MQ)
 149static const struct imx_pgc_regs imx7_pgc_regs = {
 150        .map = GPC_PGC_CPU_MAPPING,
 151        .pup = GPC_PU_PGC_SW_PUP_REQ,
 152        .pdn = GPC_PU_PGC_SW_PDN_REQ,
 153        .hsk = GPC_PU_PWRHSK,
 154};
 155#endif
 156
 157#ifdef CONFIG_IMX8MQ
 158static const struct imx_pgc_domain imx8m_pgc_domains[] = {
 159        [IMX8M_POWER_DOMAIN_PCIE1] = {
 160                .bits  = {
 161                        .pxx = IMX8M_PCIE1_SW_Pxx_REQ,
 162                        .map = IMX8M_PCIE1_A53_DOMAIN,
 163                },
 164                .pgc   = BIT(IMX8M_PGC_PCIE1),
 165        },
 166
 167        [IMX8M_POWER_DOMAIN_USB_OTG1] = {
 168                .bits  = {
 169                        .pxx = IMX8M_OTG1_SW_Pxx_REQ,
 170                        .map = IMX8M_OTG1_A53_DOMAIN,
 171                },
 172                .pgc   = BIT(IMX8M_PGC_OTG1),
 173        },
 174
 175        [IMX8M_POWER_DOMAIN_USB_OTG2] = {
 176                .bits  = {
 177                        .pxx = IMX8M_OTG2_SW_Pxx_REQ,
 178                        .map = IMX8M_OTG2_A53_DOMAIN,
 179                },
 180                .pgc   = BIT(IMX8M_PGC_OTG2),
 181        },
 182
 183        [IMX8M_POWER_DOMAIN_PCIE2] = {
 184                .bits  = {
 185                        .pxx = IMX8M_PCIE2_SW_Pxx_REQ,
 186                        .map = IMX8M_PCIE2_A53_DOMAIN,
 187                },
 188                .pgc   = BIT(IMX8M_PGC_PCIE2),
 189        },
 190};
 191
 192static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
 193        .domains = imx8m_pgc_domains,
 194        .domains_num = ARRAY_SIZE(imx8m_pgc_domains),
 195        .pgc_regs = &imx7_pgc_regs,
 196};
 197#endif
 198
 199#ifdef CONFIG_IMX8MM
 200static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
 201        [IMX8MM_POWER_DOMAIN_HSIOMIX] = {
 202                .bits  = {
 203                        .pxx = 0, /* no power sequence control */
 204                        .map = 0, /* no power sequence control */
 205                        .hskreq = IMX8MM_HSIO_HSK_PWRDNREQN,
 206                        .hskack = IMX8MM_HSIO_HSK_PWRDNACKN,
 207                },
 208                .keep_clocks = true,
 209        },
 210
 211        [IMX8MM_POWER_DOMAIN_PCIE] = {
 212                .bits  = {
 213                        .pxx = IMX8MM_PCIE_SW_Pxx_REQ,
 214                        .map = IMX8MM_PCIE_A53_DOMAIN,
 215                },
 216                .pgc   = BIT(IMX8MM_PGC_PCIE),
 217        },
 218
 219        [IMX8MM_POWER_DOMAIN_OTG1] = {
 220                .bits  = {
 221                        .pxx = IMX8MM_OTG1_SW_Pxx_REQ,
 222                        .map = IMX8MM_OTG1_A53_DOMAIN,
 223                },
 224                .pgc   = BIT(IMX8MM_PGC_OTG1),
 225        },
 226
 227        [IMX8MM_POWER_DOMAIN_OTG2] = {
 228                .bits  = {
 229                        .pxx = IMX8MM_OTG2_SW_Pxx_REQ,
 230                        .map = IMX8MM_OTG2_A53_DOMAIN,
 231                },
 232                .pgc   = BIT(IMX8MM_PGC_OTG2),
 233        },
 234};
 235
 236static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = {
 237        .domains = imx8mm_pgc_domains,
 238        .domains_num = ARRAY_SIZE(imx8mm_pgc_domains),
 239        .pgc_regs = &imx7_pgc_regs,
 240};
 241#endif
 242
 243#ifdef CONFIG_IMX8MN
 244static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
 245        [IMX8MN_POWER_DOMAIN_HSIOMIX] = {
 246                .bits  = {
 247                        .pxx = 0, /* no power sequence control */
 248                        .map = 0, /* no power sequence control */
 249                        .hskreq = IMX8MN_HSIO_HSK_PWRDNREQN,
 250                        .hskack = IMX8MN_HSIO_HSK_PWRDNACKN,
 251                },
 252                .keep_clocks = true,
 253        },
 254
 255        [IMX8MN_POWER_DOMAIN_OTG1] = {
 256                .bits  = {
 257                        .pxx = IMX8MN_OTG1_SW_Pxx_REQ,
 258                        .map = IMX8MN_OTG1_A53_DOMAIN,
 259                },
 260                .pgc   = BIT(IMX8MN_PGC_OTG1),
 261        },
 262};
 263
 264static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
 265        .domains = imx8mn_pgc_domains,
 266        .domains_num = ARRAY_SIZE(imx8mn_pgc_domains),
 267        .pgc_regs = &imx7_pgc_regs,
 268};
 269#endif
 270
 271#ifdef CONFIG_IMX8MP
 272static const struct imx_pgc_domain imx8mp_pgc_domains[] = {
 273        [IMX8MP_POWER_DOMAIN_PCIE_PHY] = {
 274                .bits = {
 275                        .pxx = IMX8MP_PCIE_PHY_SW_Pxx_REQ,
 276                        .map = IMX8MP_PCIE_PHY_A53_DOMAIN,
 277                },
 278                .pgc = BIT(IMX8MP_PGC_PCIE),
 279        },
 280
 281        [IMX8MP_POWER_DOMAIN_USB1_PHY] = {
 282                .bits = {
 283                        .pxx = IMX8MP_USB1_PHY_Pxx_REQ,
 284                        .map = IMX8MP_USB1_PHY_A53_DOMAIN,
 285                },
 286                .pgc = BIT(IMX8MP_PGC_USB1),
 287        },
 288
 289        [IMX8MP_POWER_DOMAIN_USB2_PHY] = {
 290                .bits = {
 291                        .pxx = IMX8MP_USB2_PHY_Pxx_REQ,
 292                        .map = IMX8MP_USB2_PHY_A53_DOMAIN,
 293                },
 294                .pgc = BIT(IMX8MP_PGC_USB2),
 295        },
 296
 297        [IMX8MP_POWER_DOMAIN_HSIOMIX] = {
 298                .bits = {
 299                        .pxx = IMX8MP_HSIOMIX_Pxx_REQ,
 300                        .map = IMX8MP_HSIOMIX_A53_DOMAIN,
 301                        .hskreq = IMX8MP_HSIOMIX_PWRDNREQN,
 302                        .hskack = IMX8MP_HSIOMIX_PWRDNACKN,
 303                },
 304                .pgc = BIT(IMX8MP_PGC_HSIOMIX),
 305                .keep_clocks = true,
 306        },
 307};
 308
 309static const struct imx_pgc_regs imx8mp_pgc_regs = {
 310        .map = IMX8MP_GPC_PGC_CPU_MAPPING,
 311        .pup = IMX8MP_GPC_PU_PGC_SW_PUP_REQ,
 312        .pdn = IMX8MP_GPC_PU_PGC_SW_PDN_REQ,
 313        .hsk = IMX8MP_GPC_PU_PWRHSK,
 314};
 315
 316static const struct imx_pgc_domain_data imx8mp_pgc_domain_data = {
 317        .domains = imx8mp_pgc_domains,
 318        .domains_num = ARRAY_SIZE(imx8mp_pgc_domains),
 319        .pgc_regs = &imx8mp_pgc_regs,
 320};
 321#endif
 322
 323static int imx8m_power_domain_on(struct power_domain *power_domain)
 324{
 325        struct udevice *dev = power_domain->dev;
 326        struct imx8m_power_domain_plat *pdata = dev_get_plat(dev);
 327        const struct imx_pgc_domain *domain = pdata->domain;
 328        const struct imx_pgc_regs *regs = pdata->regs;
 329        void __iomem *base = pdata->base;
 330        u32 pgc;
 331        int ret;
 332
 333        if (pdata->clk.count) {
 334                ret = clk_enable_bulk(&pdata->clk);
 335                if (ret) {
 336                        dev_err(dev, "failed to enable reset clocks\n");
 337                        return ret;
 338                }
 339        }
 340
 341        if (domain->bits.pxx) {
 342                /* request the domain to power up */
 343                setbits_le32(base + regs->pup, domain->bits.pxx);
 344
 345                /*
 346                 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
 347                 * for PUP_REQ/PDN_REQ bit to be cleared
 348                 */
 349                ret = wait_for_bit_le32(base + regs->pup, domain->bits.pxx,
 350                                        false, 1000, false);
 351                if (ret) {
 352                        dev_err(dev, "failed to command PGC\n");
 353                        goto out_clk_disable;
 354                }
 355
 356                /* disable power control */
 357                for_each_set_bit(pgc, &domain->pgc, 32) {
 358                        clrbits_le32(base + GPC_PGC_CTRL(pgc),
 359                                     GPC_PGC_CTRL_PCR);
 360                }
 361        }
 362
 363        /* delay for reset to propagate */
 364        udelay(5);
 365
 366        /* request the ADB400 to power up */
 367        if (domain->bits.hskreq)
 368                setbits_le32(base + regs->hsk, domain->bits.hskreq);
 369
 370        /* Disable reset clocks for all devices in the domain */
 371        if (!domain->keep_clocks && pdata->clk.count)
 372                clk_disable_bulk(&pdata->clk);
 373
 374        return 0;
 375
 376out_clk_disable:
 377        if (pdata->clk.count)
 378                clk_disable_bulk(&pdata->clk);
 379        return ret;
 380}
 381
 382static int imx8m_power_domain_off(struct power_domain *power_domain)
 383{
 384        struct udevice *dev = power_domain->dev;
 385        struct imx8m_power_domain_plat *pdata = dev_get_plat(dev);
 386        const struct imx_pgc_domain *domain = pdata->domain;
 387        const struct imx_pgc_regs *regs = pdata->regs;
 388        void __iomem *base = pdata->base;
 389        u32 pgc;
 390        int ret;
 391
 392        /* Enable reset clocks for all devices in the domain */
 393        if (!domain->keep_clocks && pdata->clk.count) {
 394                ret = clk_enable_bulk(&pdata->clk);
 395                if (ret)
 396                        return ret;
 397        }
 398
 399        /* request the ADB400 to power down */
 400        if (domain->bits.hskreq) {
 401                clrbits_le32(base + regs->hsk, domain->bits.hskreq);
 402
 403                ret = wait_for_bit_le32(base + regs->hsk, domain->bits.hskack,
 404                                        false, 1000, false);
 405                if (ret) {
 406                        dev_err(dev, "failed to power down ADB400\n");
 407                        goto out_clk_disable;
 408                }
 409        }
 410
 411        if (domain->bits.pxx) {
 412                /* enable power control */
 413                for_each_set_bit(pgc, &domain->pgc, 32) {
 414                        setbits_le32(base + GPC_PGC_CTRL(pgc),
 415                                     GPC_PGC_CTRL_PCR);
 416                }
 417
 418                /* request the domain to power down */
 419                setbits_le32(base + regs->pdn, domain->bits.pxx);
 420
 421                /*
 422                 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
 423                 * for PUP_REQ/PDN_REQ bit to be cleared
 424                 */
 425                ret = wait_for_bit_le32(base + regs->pdn, domain->bits.pxx,
 426                                        false, 1000, false);
 427                if (ret) {
 428                        dev_err(dev, "failed to command PGC\n");
 429                        goto out_clk_disable;
 430                }
 431        }
 432
 433        /* Disable reset clocks for all devices in the domain */
 434        if (pdata->clk.count)
 435                clk_disable_bulk(&pdata->clk);
 436
 437        if (pdata->has_pd)
 438                power_domain_off(&pdata->pd);
 439
 440        return 0;
 441
 442out_clk_disable:
 443        if (!domain->keep_clocks && pdata->clk.count)
 444                clk_disable_bulk(&pdata->clk);
 445
 446        return ret;
 447}
 448
 449static int imx8m_power_domain_of_xlate(struct power_domain *power_domain,
 450                                      struct ofnode_phandle_args *args)
 451{
 452        return 0;
 453}
 454
 455static int imx8m_power_domain_bind(struct udevice *dev)
 456{
 457        int offset;
 458        const char *name;
 459        int ret = 0;
 460
 461        offset = dev_of_offset(dev);
 462        for (offset = fdt_first_subnode(gd->fdt_blob, offset); offset > 0;
 463             offset = fdt_next_subnode(gd->fdt_blob, offset)) {
 464                /* Bind the subnode to this driver */
 465                name = fdt_get_name(gd->fdt_blob, offset, NULL);
 466
 467                /* Descend into 'pgc' subnode */
 468                if (!strstr(name, "power-domain")) {
 469                        offset = fdt_first_subnode(gd->fdt_blob, offset);
 470                        name = fdt_get_name(gd->fdt_blob, offset, NULL);
 471                }
 472
 473                ret = device_bind_with_driver_data(dev, dev->driver, name,
 474                                                   dev->driver_data,
 475                                                   offset_to_ofnode(offset),
 476                                                   NULL);
 477
 478                if (ret == -ENODEV)
 479                        printf("Driver '%s' refuses to bind\n",
 480                               dev->driver->name);
 481
 482                if (ret)
 483                        printf("Error binding driver '%s': %d\n",
 484                               dev->driver->name, ret);
 485        }
 486
 487        return 0;
 488}
 489
 490static int imx8m_power_domain_probe(struct udevice *dev)
 491{
 492        struct imx8m_power_domain_plat *pdata = dev_get_plat(dev);
 493        int ret;
 494
 495        /* Nothing to do for non-"power-domain" driver instances. */
 496        if (!strstr(dev->name, "power-domain"))
 497                return 0;
 498
 499        /* Grab optional power domain clock. */
 500        ret = clk_get_bulk(dev, &pdata->clk);
 501        if (ret && ret != -ENOENT) {
 502                dev_err(dev, "Failed to get domain clock (%d)\n", ret);
 503                return ret;
 504        }
 505
 506        return 0;
 507}
 508
 509static int imx8m_power_domain_of_to_plat(struct udevice *dev)
 510{
 511        struct imx8m_power_domain_plat *pdata = dev_get_plat(dev);
 512        struct imx_pgc_domain_data *domain_data =
 513                (struct imx_pgc_domain_data *)dev_get_driver_data(dev);
 514
 515        pdata->resource_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 516                                            "reg", -1);
 517        pdata->domain = &domain_data->domains[pdata->resource_id];
 518        pdata->regs = domain_data->pgc_regs;
 519        pdata->base = dev_read_addr_ptr(dev->parent);
 520
 521        if (!power_domain_get(dev, &pdata->pd))
 522                pdata->has_pd = 1;
 523
 524        return 0;
 525}
 526
 527static const struct udevice_id imx8m_power_domain_ids[] = {
 528#ifdef CONFIG_IMX8MQ
 529        { .compatible = "fsl,imx8mq-gpc", .data = (long)&imx8m_pgc_domain_data },
 530#endif
 531#ifdef CONFIG_IMX8MM
 532        { .compatible = "fsl,imx8mm-gpc", .data = (long)&imx8mm_pgc_domain_data },
 533#endif
 534#ifdef CONFIG_IMX8MN
 535        { .compatible = "fsl,imx8mn-gpc", .data = (long)&imx8mn_pgc_domain_data },
 536#endif
 537#ifdef CONFIG_IMX8MP
 538        { .compatible = "fsl,imx8mp-gpc", .data = (long)&imx8mp_pgc_domain_data },
 539#endif
 540        { }
 541};
 542
 543struct power_domain_ops imx8m_power_domain_ops = {
 544        .on = imx8m_power_domain_on,
 545        .off = imx8m_power_domain_off,
 546        .of_xlate = imx8m_power_domain_of_xlate,
 547};
 548
 549U_BOOT_DRIVER(imx8m_power_domain) = {
 550        .name = "imx8m_power_domain",
 551        .id = UCLASS_POWER_DOMAIN,
 552        .of_match = imx8m_power_domain_ids,
 553        .bind = imx8m_power_domain_bind,
 554        .probe = imx8m_power_domain_probe,
 555        .of_to_plat = imx8m_power_domain_of_to_plat,
 556        .plat_auto      = sizeof(struct imx8m_power_domain_plat),
 557        .ops = &imx8m_power_domain_ops,
 558};
 559