1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * drivers/soc/tegra/flowctrl.c 4 * 5 * Functions and macros to control the flowcontroller 6 * 7 * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. 8 */ 9 10 #include <linux/cpumask.h> 11 #include <linux/init.h> 12 #include <linux/io.h> 13 #include <linux/kernel.h> 14 #include <linux/of.h> 15 #include <linux/of_address.h> 16 #include <linux/platform_device.h> 17 18 #include <soc/tegra/common.h> 19 #include <soc/tegra/flowctrl.h> 20 #include <soc/tegra/fuse.h> 21 22 static u8 flowctrl_offset_halt_cpu[] = { 23 FLOW_CTRL_HALT_CPU0_EVENTS, 24 FLOW_CTRL_HALT_CPU1_EVENTS, 25 FLOW_CTRL_HALT_CPU1_EVENTS + 8, 26 FLOW_CTRL_HALT_CPU1_EVENTS + 16, 27 }; 28 29 static u8 flowctrl_offset_cpu_csr[] = { 30 FLOW_CTRL_CPU0_CSR, 31 FLOW_CTRL_CPU1_CSR, 32 FLOW_CTRL_CPU1_CSR + 8, 33 FLOW_CTRL_CPU1_CSR + 16, 34 }; 35 36 static void __iomem *tegra_flowctrl_base; 37 38 static void flowctrl_update(u8 offset, u32 value) 39 { 40 if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base), 41 "Tegra flowctrl not initialised!\n")) 42 return; 43 44 writel(value, tegra_flowctrl_base + offset); 45 46 /* ensure the update has reached the flow controller */ 47 wmb(); 48 readl_relaxed(tegra_flowctrl_base + offset); 49 } 50 51 u32 flowctrl_read_cpu_csr(unsigned int cpuid) 52 { 53 u8 offset = flowctrl_offset_cpu_csr[cpuid]; 54 55 if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base), 56 "Tegra flowctrl not initialised!\n")) 57 return 0; 58 59 return readl(tegra_flowctrl_base + offset); 60 } 61 62 void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value) 63 { 64 return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value); 65 } 66 67 void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value) 68 { 69 return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value); 70 } 71 72 void flowctrl_cpu_suspend_enter(unsigned int cpuid) 73 { 74 unsigned int reg; 75 int i; 76 77 reg = flowctrl_read_cpu_csr(cpuid); 78 switch (tegra_get_chip_id()) { 79 case TEGRA20: 80 /* clear wfe bitmap */ 81 reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP; 82 /* clear wfi bitmap */ 83 reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP; 84 /* pwr gating on wfe */ 85 reg |= TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 << cpuid; 86 break; 87 case TEGRA30: 88 case TEGRA114: 89 case TEGRA124: 90 /* clear wfe bitmap */ 91 reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP; 92 /* clear wfi bitmap */ 93 reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP; 94 /* pwr gating on wfi */ 95 reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid; 96 break; 97 } 98 reg |= FLOW_CTRL_CSR_INTR_FLAG; /* clear intr flag */ 99 reg |= FLOW_CTRL_CSR_EVENT_FLAG; /* clear event flag */ 100 reg |= FLOW_CTRL_CSR_ENABLE; /* pwr gating */ 101 flowctrl_write_cpu_csr(cpuid, reg); 102 103 for (i = 0; i < num_possible_cpus(); i++) { 104 if (i == cpuid) 105 continue; 106 reg = flowctrl_read_cpu_csr(i); 107 reg |= FLOW_CTRL_CSR_EVENT_FLAG; 108 reg |= FLOW_CTRL_CSR_INTR_FLAG; 109 flowctrl_write_cpu_csr(i, reg); 110 } 111 } 112 113 void flowctrl_cpu_suspend_exit(unsigned int cpuid) 114 { 115 unsigned int reg; 116 117 /* Disable powergating via flow controller for CPU0 */ 118 reg = flowctrl_read_cpu_csr(cpuid); 119 switch (tegra_get_chip_id()) { 120 case TEGRA20: 121 /* clear wfe bitmap */ 122 reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP; 123 /* clear wfi bitmap */ 124 reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP; 125 break; 126 case TEGRA30: 127 case TEGRA114: 128 case TEGRA124: 129 /* clear wfe bitmap */ 130 reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP; 131 /* clear wfi bitmap */ 132 reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP; 133 break; 134 } 135 reg &= ~FLOW_CTRL_CSR_ENABLE; /* clear enable */ 136 reg |= FLOW_CTRL_CSR_INTR_FLAG; /* clear intr */ 137 reg |= FLOW_CTRL_CSR_EVENT_FLAG; /* clear event */ 138 flowctrl_write_cpu_csr(cpuid, reg); 139 } 140 141 static int tegra_flowctrl_probe(struct platform_device *pdev) 142 { 143 void __iomem *base = tegra_flowctrl_base; 144 struct resource *res; 145 146 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 147 tegra_flowctrl_base = devm_ioremap_resource(&pdev->dev, res); 148 if (IS_ERR(tegra_flowctrl_base)) 149 return PTR_ERR(tegra_flowctrl_base); 150 151 iounmap(base); 152 153 return 0; 154 } 155 156 static const struct of_device_id tegra_flowctrl_match[] = { 157 { .compatible = "nvidia,tegra210-flowctrl" }, 158 { .compatible = "nvidia,tegra124-flowctrl" }, 159 { .compatible = "nvidia,tegra114-flowctrl" }, 160 { .compatible = "nvidia,tegra30-flowctrl" }, 161 { .compatible = "nvidia,tegra20-flowctrl" }, 162 { } 163 }; 164 165 static struct platform_driver tegra_flowctrl_driver = { 166 .driver = { 167 .name = "tegra-flowctrl", 168 .suppress_bind_attrs = true, 169 .of_match_table = tegra_flowctrl_match, 170 }, 171 .probe = tegra_flowctrl_probe, 172 }; 173 builtin_platform_driver(tegra_flowctrl_driver); 174 175 static int __init tegra_flowctrl_init(void) 176 { 177 struct resource res; 178 struct device_node *np; 179 180 if (!soc_is_tegra()) 181 return 0; 182 183 np = of_find_matching_node(NULL, tegra_flowctrl_match); 184 if (np) { 185 if (of_address_to_resource(np, 0, &res) < 0) { 186 pr_err("failed to get flowctrl register\n"); 187 return -ENXIO; 188 } 189 of_node_put(np); 190 } else if (IS_ENABLED(CONFIG_ARM)) { 191 /* 192 * Hardcoded fallback for 32-bit Tegra 193 * devices if device tree node is missing. 194 */ 195 res.start = 0x60007000; 196 res.end = 0x60007fff; 197 res.flags = IORESOURCE_MEM; 198 } else { 199 /* 200 * At this point we're running on a Tegra, 201 * that doesn't support the flow controller 202 * (eg. Tegra186), so just return. 203 */ 204 return 0; 205 } 206 207 tegra_flowctrl_base = ioremap_nocache(res.start, resource_size(&res)); 208 if (!tegra_flowctrl_base) 209 return -ENXIO; 210 211 return 0; 212 } 213 early_initcall(tegra_flowctrl_init); 214