1 /* 2 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 3 * Copyright (C) 2011 Google, Inc. 4 * 5 * Author: 6 * Jay Cheng <jacheng@nvidia.com> 7 * James Wylder <james.wylder@motorola.com> 8 * Benoit Goby <benoit@android.com> 9 * Colin Cross <ccross@android.com> 10 * Hiroshi DOYU <hdoyu@nvidia.com> 11 * 12 * This software is licensed under the terms of the GNU General Public 13 * License version 2, as published by the Free Software Foundation, and 14 * may be copied, distributed, and modified under those terms. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 */ 22 23 #include <linux/err.h> 24 #include <linux/kernel.h> 25 #include <linux/module.h> 26 #include <linux/platform_device.h> 27 #include <linux/io.h> 28 #include <linux/tegra-ahb.h> 29 30 #define DRV_NAME "tegra-ahb" 31 32 #define AHB_ARBITRATION_DISABLE 0x00 33 #define AHB_ARBITRATION_PRIORITY_CTRL 0x04 34 #define AHB_PRIORITY_WEIGHT(x) (((x) & 0x7) << 29) 35 #define PRIORITY_SELECT_USB BIT(6) 36 #define PRIORITY_SELECT_USB2 BIT(18) 37 #define PRIORITY_SELECT_USB3 BIT(17) 38 39 #define AHB_GIZMO_AHB_MEM 0x0c 40 #define ENB_FAST_REARBITRATE BIT(2) 41 #define DONT_SPLIT_AHB_WR BIT(7) 42 43 #define AHB_GIZMO_APB_DMA 0x10 44 #define AHB_GIZMO_IDE 0x18 45 #define AHB_GIZMO_USB 0x1c 46 #define AHB_GIZMO_AHB_XBAR_BRIDGE 0x20 47 #define AHB_GIZMO_CPU_AHB_BRIDGE 0x24 48 #define AHB_GIZMO_COP_AHB_BRIDGE 0x28 49 #define AHB_GIZMO_XBAR_APB_CTLR 0x2c 50 #define AHB_GIZMO_VCP_AHB_BRIDGE 0x30 51 #define AHB_GIZMO_NAND 0x3c 52 #define AHB_GIZMO_SDMMC4 0x44 53 #define AHB_GIZMO_XIO 0x48 54 #define AHB_GIZMO_BSEV 0x60 55 #define AHB_GIZMO_BSEA 0x70 56 #define AHB_GIZMO_NOR 0x74 57 #define AHB_GIZMO_USB2 0x78 58 #define AHB_GIZMO_USB3 0x7c 59 #define IMMEDIATE BIT(18) 60 61 #define AHB_GIZMO_SDMMC1 0x80 62 #define AHB_GIZMO_SDMMC2 0x84 63 #define AHB_GIZMO_SDMMC3 0x88 64 #define AHB_MEM_PREFETCH_CFG_X 0xd8 65 #define AHB_ARBITRATION_XBAR_CTRL 0xdc 66 #define AHB_MEM_PREFETCH_CFG3 0xe0 67 #define AHB_MEM_PREFETCH_CFG4 0xe4 68 #define AHB_MEM_PREFETCH_CFG1 0xec 69 #define AHB_MEM_PREFETCH_CFG2 0xf0 70 #define PREFETCH_ENB BIT(31) 71 #define MST_ID(x) (((x) & 0x1f) << 26) 72 #define AHBDMA_MST_ID MST_ID(5) 73 #define USB_MST_ID MST_ID(6) 74 #define USB2_MST_ID MST_ID(18) 75 #define USB3_MST_ID MST_ID(17) 76 #define ADDR_BNDRY(x) (((x) & 0xf) << 21) 77 #define INACTIVITY_TIMEOUT(x) (((x) & 0xffff) << 0) 78 79 #define AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID 0xf8 80 81 #define AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE BIT(17) 82 83 static struct platform_driver tegra_ahb_driver; 84 85 static const u32 tegra_ahb_gizmo[] = { 86 AHB_ARBITRATION_DISABLE, 87 AHB_ARBITRATION_PRIORITY_CTRL, 88 AHB_GIZMO_AHB_MEM, 89 AHB_GIZMO_APB_DMA, 90 AHB_GIZMO_IDE, 91 AHB_GIZMO_USB, 92 AHB_GIZMO_AHB_XBAR_BRIDGE, 93 AHB_GIZMO_CPU_AHB_BRIDGE, 94 AHB_GIZMO_COP_AHB_BRIDGE, 95 AHB_GIZMO_XBAR_APB_CTLR, 96 AHB_GIZMO_VCP_AHB_BRIDGE, 97 AHB_GIZMO_NAND, 98 AHB_GIZMO_SDMMC4, 99 AHB_GIZMO_XIO, 100 AHB_GIZMO_BSEV, 101 AHB_GIZMO_BSEA, 102 AHB_GIZMO_NOR, 103 AHB_GIZMO_USB2, 104 AHB_GIZMO_USB3, 105 AHB_GIZMO_SDMMC1, 106 AHB_GIZMO_SDMMC2, 107 AHB_GIZMO_SDMMC3, 108 AHB_MEM_PREFETCH_CFG_X, 109 AHB_ARBITRATION_XBAR_CTRL, 110 AHB_MEM_PREFETCH_CFG3, 111 AHB_MEM_PREFETCH_CFG4, 112 AHB_MEM_PREFETCH_CFG1, 113 AHB_MEM_PREFETCH_CFG2, 114 AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID, 115 }; 116 117 struct tegra_ahb { 118 void __iomem *regs; 119 struct device *dev; 120 u32 ctx[0]; 121 }; 122 123 static inline u32 gizmo_readl(struct tegra_ahb *ahb, u32 offset) 124 { 125 return readl(ahb->regs + offset); 126 } 127 128 static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset) 129 { 130 writel(value, ahb->regs + offset); 131 } 132 133 #ifdef CONFIG_TEGRA_IOMMU_SMMU 134 static int tegra_ahb_match_by_smmu(struct device *dev, void *data) 135 { 136 struct tegra_ahb *ahb = dev_get_drvdata(dev); 137 struct device_node *dn = data; 138 139 return (ahb->dev->of_node == dn) ? 1 : 0; 140 } 141 142 int tegra_ahb_enable_smmu(struct device_node *dn) 143 { 144 struct device *dev; 145 u32 val; 146 struct tegra_ahb *ahb; 147 148 dev = driver_find_device(&tegra_ahb_driver.driver, NULL, dn, 149 tegra_ahb_match_by_smmu); 150 if (!dev) 151 return -EPROBE_DEFER; 152 ahb = dev_get_drvdata(dev); 153 val = gizmo_readl(ahb, AHB_ARBITRATION_XBAR_CTRL); 154 val |= AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE; 155 gizmo_writel(ahb, val, AHB_ARBITRATION_XBAR_CTRL); 156 return 0; 157 } 158 EXPORT_SYMBOL(tegra_ahb_enable_smmu); 159 #endif 160 161 #ifdef CONFIG_PM 162 static int tegra_ahb_suspend(struct device *dev) 163 { 164 int i; 165 struct tegra_ahb *ahb = dev_get_drvdata(dev); 166 167 for (i = 0; i < ARRAY_SIZE(tegra_ahb_gizmo); i++) 168 ahb->ctx[i] = gizmo_readl(ahb, tegra_ahb_gizmo[i]); 169 return 0; 170 } 171 172 static int tegra_ahb_resume(struct device *dev) 173 { 174 int i; 175 struct tegra_ahb *ahb = dev_get_drvdata(dev); 176 177 for (i = 0; i < ARRAY_SIZE(tegra_ahb_gizmo); i++) 178 gizmo_writel(ahb, ahb->ctx[i], tegra_ahb_gizmo[i]); 179 return 0; 180 } 181 #endif 182 183 static UNIVERSAL_DEV_PM_OPS(tegra_ahb_pm, 184 tegra_ahb_suspend, 185 tegra_ahb_resume, NULL); 186 187 static void tegra_ahb_gizmo_init(struct tegra_ahb *ahb) 188 { 189 u32 val; 190 191 val = gizmo_readl(ahb, AHB_GIZMO_AHB_MEM); 192 val |= ENB_FAST_REARBITRATE | IMMEDIATE | DONT_SPLIT_AHB_WR; 193 gizmo_writel(ahb, val, AHB_GIZMO_AHB_MEM); 194 195 val = gizmo_readl(ahb, AHB_GIZMO_USB); 196 val |= IMMEDIATE; 197 gizmo_writel(ahb, val, AHB_GIZMO_USB); 198 199 val = gizmo_readl(ahb, AHB_GIZMO_USB2); 200 val |= IMMEDIATE; 201 gizmo_writel(ahb, val, AHB_GIZMO_USB2); 202 203 val = gizmo_readl(ahb, AHB_GIZMO_USB3); 204 val |= IMMEDIATE; 205 gizmo_writel(ahb, val, AHB_GIZMO_USB3); 206 207 val = gizmo_readl(ahb, AHB_ARBITRATION_PRIORITY_CTRL); 208 val |= PRIORITY_SELECT_USB | 209 PRIORITY_SELECT_USB2 | 210 PRIORITY_SELECT_USB3 | 211 AHB_PRIORITY_WEIGHT(7); 212 gizmo_writel(ahb, val, AHB_ARBITRATION_PRIORITY_CTRL); 213 214 val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG1); 215 val &= ~MST_ID(~0); 216 val |= PREFETCH_ENB | 217 AHBDMA_MST_ID | 218 ADDR_BNDRY(0xc) | 219 INACTIVITY_TIMEOUT(0x1000); 220 gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG1); 221 222 val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG2); 223 val &= ~MST_ID(~0); 224 val |= PREFETCH_ENB | 225 USB_MST_ID | 226 ADDR_BNDRY(0xc) | 227 INACTIVITY_TIMEOUT(0x1000); 228 gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG2); 229 230 val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG3); 231 val &= ~MST_ID(~0); 232 val |= PREFETCH_ENB | 233 USB3_MST_ID | 234 ADDR_BNDRY(0xc) | 235 INACTIVITY_TIMEOUT(0x1000); 236 gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG3); 237 238 val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG4); 239 val &= ~MST_ID(~0); 240 val |= PREFETCH_ENB | 241 USB2_MST_ID | 242 ADDR_BNDRY(0xc) | 243 INACTIVITY_TIMEOUT(0x1000); 244 gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG4); 245 } 246 247 static int tegra_ahb_probe(struct platform_device *pdev) 248 { 249 struct resource *res; 250 struct tegra_ahb *ahb; 251 size_t bytes; 252 253 bytes = sizeof(*ahb) + sizeof(u32) * ARRAY_SIZE(tegra_ahb_gizmo); 254 ahb = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL); 255 if (!ahb) 256 return -ENOMEM; 257 258 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 259 ahb->regs = devm_ioremap_resource(&pdev->dev, res); 260 if (IS_ERR(ahb->regs)) 261 return PTR_ERR(ahb->regs); 262 263 ahb->dev = &pdev->dev; 264 platform_set_drvdata(pdev, ahb); 265 tegra_ahb_gizmo_init(ahb); 266 return 0; 267 } 268 269 static const struct of_device_id tegra_ahb_of_match[] = { 270 { .compatible = "nvidia,tegra30-ahb", }, 271 { .compatible = "nvidia,tegra20-ahb", }, 272 {}, 273 }; 274 275 static struct platform_driver tegra_ahb_driver = { 276 .probe = tegra_ahb_probe, 277 .driver = { 278 .name = DRV_NAME, 279 .owner = THIS_MODULE, 280 .of_match_table = tegra_ahb_of_match, 281 .pm = &tegra_ahb_pm, 282 }, 283 }; 284 module_platform_driver(tegra_ahb_driver); 285 286 MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>"); 287 MODULE_DESCRIPTION("Tegra AHB driver"); 288 MODULE_LICENSE("GPL v2"); 289 MODULE_ALIAS("platform:" DRV_NAME); 290