Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * drivers/soc/tegra/flowctrl.c
0004  *
0005  * Functions and macros to control the flowcontroller
0006  *
0007  * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
0008  */
0009 
0010 #include <linux/cpumask.h>
0011 #include <linux/init.h>
0012 #include <linux/io.h>
0013 #include <linux/kernel.h>
0014 #include <linux/of.h>
0015 #include <linux/of_address.h>
0016 #include <linux/platform_device.h>
0017 
0018 #include <soc/tegra/common.h>
0019 #include <soc/tegra/flowctrl.h>
0020 #include <soc/tegra/fuse.h>
0021 
0022 static u8 flowctrl_offset_halt_cpu[] = {
0023     FLOW_CTRL_HALT_CPU0_EVENTS,
0024     FLOW_CTRL_HALT_CPU1_EVENTS,
0025     FLOW_CTRL_HALT_CPU1_EVENTS + 8,
0026     FLOW_CTRL_HALT_CPU1_EVENTS + 16,
0027 };
0028 
0029 static u8 flowctrl_offset_cpu_csr[] = {
0030     FLOW_CTRL_CPU0_CSR,
0031     FLOW_CTRL_CPU1_CSR,
0032     FLOW_CTRL_CPU1_CSR + 8,
0033     FLOW_CTRL_CPU1_CSR + 16,
0034 };
0035 
0036 static void __iomem *tegra_flowctrl_base;
0037 
0038 static void flowctrl_update(u8 offset, u32 value)
0039 {
0040     if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base),
0041               "Tegra flowctrl not initialised!\n"))
0042         return;
0043 
0044     writel(value, tegra_flowctrl_base + offset);
0045 
0046     /* ensure the update has reached the flow controller */
0047     wmb();
0048     readl_relaxed(tegra_flowctrl_base + offset);
0049 }
0050 
0051 u32 flowctrl_read_cpu_csr(unsigned int cpuid)
0052 {
0053     u8 offset = flowctrl_offset_cpu_csr[cpuid];
0054 
0055     if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base),
0056               "Tegra flowctrl not initialised!\n"))
0057         return 0;
0058 
0059     return readl(tegra_flowctrl_base + offset);
0060 }
0061 
0062 void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value)
0063 {
0064     return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value);
0065 }
0066 
0067 void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value)
0068 {
0069     return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value);
0070 }
0071 
0072 void flowctrl_cpu_suspend_enter(unsigned int cpuid)
0073 {
0074     unsigned int reg;
0075     int i;
0076 
0077     reg = flowctrl_read_cpu_csr(cpuid);
0078     switch (tegra_get_chip_id()) {
0079     case TEGRA20:
0080         /* clear wfe bitmap */
0081         reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
0082         /* clear wfi bitmap */
0083         reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP;
0084         /* pwr gating on wfe */
0085         reg |= TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 << cpuid;
0086         break;
0087     case TEGRA30:
0088     case TEGRA114:
0089     case TEGRA124:
0090         /* clear wfe bitmap */
0091         reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
0092         /* clear wfi bitmap */
0093         reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;
0094 
0095         if (tegra_get_chip_id() == TEGRA30) {
0096             /*
0097              * The wfi doesn't work well on Tegra30 because
0098              * CPU hangs under some odd circumstances after
0099              * power-gating (like memory running off PLLP),
0100              * hence use wfe that is working perfectly fine.
0101              * Note that Tegra30 TRM doc clearly stands that
0102              * wfi should be used for the "Cluster Switching",
0103              * while wfe for the power-gating, just like it
0104              * is done on Tegra20.
0105              */
0106             reg |= TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 << cpuid;
0107         } else {
0108             /* pwr gating on wfi */
0109             reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid;
0110         }
0111         break;
0112     }
0113     reg |= FLOW_CTRL_CSR_INTR_FLAG;         /* clear intr flag */
0114     reg |= FLOW_CTRL_CSR_EVENT_FLAG;        /* clear event flag */
0115     reg |= FLOW_CTRL_CSR_ENABLE;            /* pwr gating */
0116     flowctrl_write_cpu_csr(cpuid, reg);
0117 
0118     for (i = 0; i < num_possible_cpus(); i++) {
0119         if (i == cpuid)
0120             continue;
0121         reg = flowctrl_read_cpu_csr(i);
0122         reg |= FLOW_CTRL_CSR_EVENT_FLAG;
0123         reg |= FLOW_CTRL_CSR_INTR_FLAG;
0124         flowctrl_write_cpu_csr(i, reg);
0125     }
0126 }
0127 
0128 void flowctrl_cpu_suspend_exit(unsigned int cpuid)
0129 {
0130     unsigned int reg;
0131 
0132     /* Disable powergating via flow controller for CPU0 */
0133     reg = flowctrl_read_cpu_csr(cpuid);
0134     switch (tegra_get_chip_id()) {
0135     case TEGRA20:
0136         /* clear wfe bitmap */
0137         reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
0138         /* clear wfi bitmap */
0139         reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP;
0140         break;
0141     case TEGRA30:
0142     case TEGRA114:
0143     case TEGRA124:
0144         /* clear wfe bitmap */
0145         reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
0146         /* clear wfi bitmap */
0147         reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;
0148         break;
0149     }
0150     reg &= ~FLOW_CTRL_CSR_ENABLE;           /* clear enable */
0151     reg |= FLOW_CTRL_CSR_INTR_FLAG;         /* clear intr */
0152     reg |= FLOW_CTRL_CSR_EVENT_FLAG;        /* clear event */
0153     flowctrl_write_cpu_csr(cpuid, reg);
0154 }
0155 
0156 static int tegra_flowctrl_probe(struct platform_device *pdev)
0157 {
0158     void __iomem *base = tegra_flowctrl_base;
0159     struct resource *res;
0160 
0161     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0162     tegra_flowctrl_base = devm_ioremap_resource(&pdev->dev, res);
0163     if (IS_ERR(tegra_flowctrl_base))
0164         return PTR_ERR(tegra_flowctrl_base);
0165 
0166     iounmap(base);
0167 
0168     return 0;
0169 }
0170 
0171 static const struct of_device_id tegra_flowctrl_match[] = {
0172     { .compatible = "nvidia,tegra210-flowctrl" },
0173     { .compatible = "nvidia,tegra124-flowctrl" },
0174     { .compatible = "nvidia,tegra114-flowctrl" },
0175     { .compatible = "nvidia,tegra30-flowctrl" },
0176     { .compatible = "nvidia,tegra20-flowctrl" },
0177     { }
0178 };
0179 
0180 static struct platform_driver tegra_flowctrl_driver = {
0181     .driver = {
0182         .name = "tegra-flowctrl",
0183         .suppress_bind_attrs = true,
0184         .of_match_table = tegra_flowctrl_match,
0185     },
0186     .probe = tegra_flowctrl_probe,
0187 };
0188 builtin_platform_driver(tegra_flowctrl_driver);
0189 
0190 static int __init tegra_flowctrl_init(void)
0191 {
0192     struct resource res;
0193     struct device_node *np;
0194 
0195     if (!soc_is_tegra())
0196         return 0;
0197 
0198     np = of_find_matching_node(NULL, tegra_flowctrl_match);
0199     if (np) {
0200         if (of_address_to_resource(np, 0, &res) < 0) {
0201             pr_err("failed to get flowctrl register\n");
0202             return -ENXIO;
0203         }
0204         of_node_put(np);
0205     } else if (IS_ENABLED(CONFIG_ARM)) {
0206         /*
0207          * Hardcoded fallback for 32-bit Tegra
0208          * devices if device tree node is missing.
0209          */
0210         res.start = 0x60007000;
0211         res.end = 0x60007fff;
0212         res.flags = IORESOURCE_MEM;
0213     } else {
0214         /*
0215          * At this point we're running on a Tegra,
0216          * that doesn't support the flow controller
0217          * (eg. Tegra186), so just return.
0218          */
0219         return 0;
0220     }
0221 
0222     tegra_flowctrl_base = ioremap(res.start, resource_size(&res));
0223     if (!tegra_flowctrl_base)
0224         return -ENXIO;
0225 
0226     return 0;
0227 }
0228 early_initcall(tegra_flowctrl_init);