Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: tegra: Add Tegra AHB driver

Tegra AHB Bus conforms to the AMBA Specification (Rev 2.0) Advanced
High-performance Bus (AHB) architecture.

The AHB Arbiter controls AHB bus master arbitration. This effectively
forms a second level of arbitration for access to the memory
controller through the AHB Slave Memory device. The AHB pre-fetch
logic can be configured to enhance performance for devices doing
sequential access. Each AHB master is assigned to either the high or
low priority bin. Both Tegra20/30 have this AHB bus.

Some of configuration params could be passed from DT too if needed.

Signed-off-by: Hiroshi DOYU <hdoyu@nvidia.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>

authored by

Hiroshi DOYU and committed by
Stephen Warren
87d0bab2 e816b57a

+283 -3
+11
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-ahb.txt
··· 1 + NVIDIA Tegra AHB 2 + 3 + Required properties: 4 + - compatible : "nvidia,tegra20-ahb" or "nvidia,tegra30-ahb" 5 + - reg : Should contain 1 register ranges(address and length) 6 + 7 + Example: 8 + ahb: ahb@6000c004 { 9 + compatible = "nvidia,tegra20-ahb"; 10 + reg = <0x6000c004 0x10c>; /* AHB Arbitration + Gizmo Controller */ 11 + };
+8
arch/arm/mach-tegra/Kconfig
··· 50 50 depends on ARCH_TEGRA_2x_SOC 51 51 select PCI 52 52 53 + config TEGRA_AHB 54 + bool "Enable AHB driver for NVIDIA Tegra SoCs" 55 + default y 56 + help 57 + Adds AHB configuration functionality for NVIDIA Tegra SoCs, 58 + which controls AHB bus master arbitration and some 59 + perfomance parameters(priority, prefech size). 60 + 53 61 comment "Tegra board type" 54 62 55 63 config MACH_HARMONY
+1 -1
drivers/Makefile
··· 18 18 # PnP must come after ACPI since it will eventually need to check if acpi 19 19 # was used and do nothing if so 20 20 obj-$(CONFIG_PNP) += pnp/ 21 - obj-$(CONFIG_ARM_AMBA) += amba/ 21 + obj-y += amba/ 22 22 # Many drivers will want to use DMA so this has to be made available 23 23 # really early. 24 24 obj-$(CONFIG_DMA_ENGINE) += dma/
+2 -2
drivers/amba/Makefile
··· 1 - obj-y += bus.o 2 - 1 + obj-$(CONFIG_ARM_AMBA) += bus.o 2 + obj-$(CONFIG_TEGRA_AHB) += tegra-ahb.o
+261
drivers/amba/tegra-ahb.c
··· 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/kernel.h> 24 + #include <linux/module.h> 25 + #include <linux/platform_device.h> 26 + #include <linux/io.h> 27 + 28 + #define DRV_NAME "tegra-ahb" 29 + 30 + #define AHB_ARBITRATION_DISABLE 0x00 31 + #define AHB_ARBITRATION_PRIORITY_CTRL 0x04 32 + #define AHB_PRIORITY_WEIGHT(x) (((x) & 0x7) << 29) 33 + #define PRIORITY_SELECT_USB BIT(6) 34 + #define PRIORITY_SELECT_USB2 BIT(18) 35 + #define PRIORITY_SELECT_USB3 BIT(17) 36 + 37 + #define AHB_GIZMO_AHB_MEM 0x0c 38 + #define ENB_FAST_REARBITRATE BIT(2) 39 + #define DONT_SPLIT_AHB_WR BIT(7) 40 + 41 + #define AHB_GIZMO_APB_DMA 0x10 42 + #define AHB_GIZMO_IDE 0x18 43 + #define AHB_GIZMO_USB 0x1c 44 + #define AHB_GIZMO_AHB_XBAR_BRIDGE 0x20 45 + #define AHB_GIZMO_CPU_AHB_BRIDGE 0x24 46 + #define AHB_GIZMO_COP_AHB_BRIDGE 0x28 47 + #define AHB_GIZMO_XBAR_APB_CTLR 0x2c 48 + #define AHB_GIZMO_VCP_AHB_BRIDGE 0x30 49 + #define AHB_GIZMO_NAND 0x3c 50 + #define AHB_GIZMO_SDMMC4 0x44 51 + #define AHB_GIZMO_XIO 0x48 52 + #define AHB_GIZMO_BSEV 0x60 53 + #define AHB_GIZMO_BSEA 0x70 54 + #define AHB_GIZMO_NOR 0x74 55 + #define AHB_GIZMO_USB2 0x78 56 + #define AHB_GIZMO_USB3 0x7c 57 + #define IMMEDIATE BIT(18) 58 + 59 + #define AHB_GIZMO_SDMMC1 0x80 60 + #define AHB_GIZMO_SDMMC2 0x84 61 + #define AHB_GIZMO_SDMMC3 0x88 62 + #define AHB_MEM_PREFETCH_CFG_X 0xd8 63 + #define AHB_ARBITRATION_XBAR_CTRL 0xdc 64 + #define AHB_MEM_PREFETCH_CFG3 0xe0 65 + #define AHB_MEM_PREFETCH_CFG4 0xe4 66 + #define AHB_MEM_PREFETCH_CFG1 0xec 67 + #define AHB_MEM_PREFETCH_CFG2 0xf0 68 + #define PREFETCH_ENB BIT(31) 69 + #define MST_ID(x) (((x) & 0x1f) << 26) 70 + #define AHBDMA_MST_ID MST_ID(5) 71 + #define USB_MST_ID MST_ID(6) 72 + #define USB2_MST_ID MST_ID(18) 73 + #define USB3_MST_ID MST_ID(17) 74 + #define ADDR_BNDRY(x) (((x) & 0xf) << 21) 75 + #define INACTIVITY_TIMEOUT(x) (((x) & 0xffff) << 0) 76 + 77 + #define AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID 0xf8 78 + 79 + static const u32 tegra_ahb_gizmo[] = { 80 + AHB_ARBITRATION_DISABLE, 81 + AHB_ARBITRATION_PRIORITY_CTRL, 82 + AHB_GIZMO_AHB_MEM, 83 + AHB_GIZMO_APB_DMA, 84 + AHB_GIZMO_IDE, 85 + AHB_GIZMO_USB, 86 + AHB_GIZMO_AHB_XBAR_BRIDGE, 87 + AHB_GIZMO_CPU_AHB_BRIDGE, 88 + AHB_GIZMO_COP_AHB_BRIDGE, 89 + AHB_GIZMO_XBAR_APB_CTLR, 90 + AHB_GIZMO_VCP_AHB_BRIDGE, 91 + AHB_GIZMO_NAND, 92 + AHB_GIZMO_SDMMC4, 93 + AHB_GIZMO_XIO, 94 + AHB_GIZMO_BSEV, 95 + AHB_GIZMO_BSEA, 96 + AHB_GIZMO_NOR, 97 + AHB_GIZMO_USB2, 98 + AHB_GIZMO_USB3, 99 + AHB_GIZMO_SDMMC1, 100 + AHB_GIZMO_SDMMC2, 101 + AHB_GIZMO_SDMMC3, 102 + AHB_MEM_PREFETCH_CFG_X, 103 + AHB_ARBITRATION_XBAR_CTRL, 104 + AHB_MEM_PREFETCH_CFG3, 105 + AHB_MEM_PREFETCH_CFG4, 106 + AHB_MEM_PREFETCH_CFG1, 107 + AHB_MEM_PREFETCH_CFG2, 108 + AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID, 109 + }; 110 + 111 + struct tegra_ahb { 112 + void __iomem *regs; 113 + struct device *dev; 114 + u32 ctx[0]; 115 + }; 116 + 117 + static inline u32 gizmo_readl(struct tegra_ahb *ahb, u32 offset) 118 + { 119 + return readl(ahb->regs + offset); 120 + } 121 + 122 + static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset) 123 + { 124 + writel(value, ahb->regs + offset); 125 + } 126 + 127 + static int tegra_ahb_suspend(struct device *dev) 128 + { 129 + int i; 130 + struct tegra_ahb *ahb = dev_get_drvdata(dev); 131 + 132 + for (i = 0; i < ARRAY_SIZE(tegra_ahb_gizmo); i++) 133 + ahb->ctx[i] = gizmo_readl(ahb, tegra_ahb_gizmo[i]); 134 + return 0; 135 + } 136 + 137 + static int tegra_ahb_resume(struct device *dev) 138 + { 139 + int i; 140 + struct tegra_ahb *ahb = dev_get_drvdata(dev); 141 + 142 + for (i = 0; i < ARRAY_SIZE(tegra_ahb_gizmo); i++) 143 + gizmo_writel(ahb, ahb->ctx[i], tegra_ahb_gizmo[i]); 144 + return 0; 145 + } 146 + 147 + static UNIVERSAL_DEV_PM_OPS(tegra_ahb_pm, 148 + tegra_ahb_suspend, 149 + tegra_ahb_resume, NULL); 150 + 151 + static void tegra_ahb_gizmo_init(struct tegra_ahb *ahb) 152 + { 153 + u32 val; 154 + 155 + val = gizmo_readl(ahb, AHB_GIZMO_AHB_MEM); 156 + val |= ENB_FAST_REARBITRATE | IMMEDIATE | DONT_SPLIT_AHB_WR; 157 + gizmo_writel(ahb, val, AHB_GIZMO_AHB_MEM); 158 + 159 + val = gizmo_readl(ahb, AHB_GIZMO_USB); 160 + val |= IMMEDIATE; 161 + gizmo_writel(ahb, val, AHB_GIZMO_USB); 162 + 163 + val = gizmo_readl(ahb, AHB_GIZMO_USB2); 164 + val |= IMMEDIATE; 165 + gizmo_writel(ahb, val, AHB_GIZMO_USB2); 166 + 167 + val = gizmo_readl(ahb, AHB_GIZMO_USB3); 168 + val |= IMMEDIATE; 169 + gizmo_writel(ahb, val, AHB_GIZMO_USB3); 170 + 171 + val = gizmo_readl(ahb, AHB_ARBITRATION_PRIORITY_CTRL); 172 + val |= PRIORITY_SELECT_USB | 173 + PRIORITY_SELECT_USB2 | 174 + PRIORITY_SELECT_USB3 | 175 + AHB_PRIORITY_WEIGHT(7); 176 + gizmo_writel(ahb, val, AHB_ARBITRATION_PRIORITY_CTRL); 177 + 178 + val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG1); 179 + val &= ~MST_ID(~0); 180 + val |= PREFETCH_ENB | 181 + AHBDMA_MST_ID | 182 + ADDR_BNDRY(0xc) | 183 + INACTIVITY_TIMEOUT(0x1000); 184 + gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG1); 185 + 186 + val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG2); 187 + val &= ~MST_ID(~0); 188 + val |= PREFETCH_ENB | 189 + USB_MST_ID | 190 + ADDR_BNDRY(0xc) | 191 + INACTIVITY_TIMEOUT(0x1000); 192 + gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG2); 193 + 194 + val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG3); 195 + val &= ~MST_ID(~0); 196 + val |= PREFETCH_ENB | 197 + USB3_MST_ID | 198 + ADDR_BNDRY(0xc) | 199 + INACTIVITY_TIMEOUT(0x1000); 200 + gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG3); 201 + 202 + val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG4); 203 + val &= ~MST_ID(~0); 204 + val |= PREFETCH_ENB | 205 + USB2_MST_ID | 206 + ADDR_BNDRY(0xc) | 207 + INACTIVITY_TIMEOUT(0x1000); 208 + gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG4); 209 + } 210 + 211 + static int __devinit tegra_ahb_probe(struct platform_device *pdev) 212 + { 213 + struct resource *res; 214 + struct tegra_ahb *ahb; 215 + size_t bytes; 216 + 217 + bytes = sizeof(*ahb) + sizeof(u32) * ARRAY_SIZE(tegra_ahb_gizmo); 218 + ahb = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL); 219 + if (!ahb) 220 + return -ENOMEM; 221 + 222 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 223 + if (!res) 224 + return -ENODEV; 225 + ahb->regs = devm_request_and_ioremap(&pdev->dev, res); 226 + if (!ahb->regs) 227 + return -EBUSY; 228 + 229 + ahb->dev = &pdev->dev; 230 + platform_set_drvdata(pdev, ahb); 231 + tegra_ahb_gizmo_init(ahb); 232 + return 0; 233 + } 234 + 235 + static int __devexit tegra_ahb_remove(struct platform_device *pdev) 236 + { 237 + return 0; 238 + } 239 + 240 + static const struct of_device_id tegra_ahb_of_match[] __devinitconst = { 241 + { .compatible = "nvidia,tegra30-ahb", }, 242 + { .compatible = "nvidia,tegra20-ahb", }, 243 + {}, 244 + }; 245 + 246 + static struct platform_driver tegra_ahb_driver = { 247 + .probe = tegra_ahb_probe, 248 + .remove = __devexit_p(tegra_ahb_remove), 249 + .driver = { 250 + .name = DRV_NAME, 251 + .owner = THIS_MODULE, 252 + .of_match_table = tegra_ahb_of_match, 253 + .pm = &tegra_ahb_pm, 254 + }, 255 + }; 256 + module_platform_driver(tegra_ahb_driver); 257 + 258 + MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>"); 259 + MODULE_DESCRIPTION("Tegra AHB driver"); 260 + MODULE_LICENSE("GPL v2"); 261 + MODULE_ALIAS("platform:" DRV_NAME);