aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2012-05-14 16:53:49 -0400
committerArnd Bergmann <arnd@arndb.de>2012-05-15 07:30:41 -0400
commit21b7f153dd0d7366197c37e7a630c7585db0b8ea (patch)
tree065ad22312b08aca338479a823d60bec23fde120
parent0200c0a66cb727fae13bcd938d44a0841a6530d1 (diff)
parent89c788bab1f0374ae05aef7560066442ceb55384 (diff)
Merge branch 'for-3.5/ahb' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra into next/drivers
* tegra/ahb: ARM: tegra: Add SMMU enabler in AHB ARM: tegra: Add Tegra AHB driver Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-ahb.txt11
-rw-r--r--arch/arm/mach-tegra/Kconfig8
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra-ahb.h19
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/amba/Makefile4
-rw-r--r--drivers/amba/tegra-ahb.c293
6 files changed, 334 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-ahb.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-ahb.txt
new file mode 100644
index 000000000000..234406d41c12
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-ahb.txt
@@ -0,0 +1,11 @@
1NVIDIA Tegra AHB
2
3Required properties:
4- compatible : "nvidia,tegra20-ahb" or "nvidia,tegra30-ahb"
5- reg : Should contain 1 register ranges(address and length)
6
7Example:
8 ahb: ahb@6000c004 {
9 compatible = "nvidia,tegra20-ahb";
10 reg = <0x6000c004 0x10c>; /* AHB Arbitration + Gizmo Controller */
11 };
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 204d3d4d7388..6a113a9bb87a 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -50,6 +50,14 @@ config TEGRA_PCI
50 depends on ARCH_TEGRA_2x_SOC 50 depends on ARCH_TEGRA_2x_SOC
51 select PCI 51 select PCI
52 52
53config 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
53comment "Tegra board type" 61comment "Tegra board type"
54 62
55config MACH_HARMONY 63config MACH_HARMONY
diff --git a/arch/arm/mach-tegra/include/mach/tegra-ahb.h b/arch/arm/mach-tegra/include/mach/tegra-ahb.h
new file mode 100644
index 000000000000..e0f8c84b1d8c
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/tegra-ahb.h
@@ -0,0 +1,19 @@
1/*
2 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13
14#ifndef __MACH_TEGRA_AHB_H__
15#define __MACH_TEGRA_AHB_H__
16
17extern int tegra_ahb_enable_smmu(struct device_node *ahb);
18
19#endif /* __MACH_TEGRA_AHB_H__ */
diff --git a/drivers/Makefile b/drivers/Makefile
index 95952c82bf16..fd7176390168 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_SFI) += sfi/
18# PnP must come after ACPI since it will eventually need to check if acpi 18# PnP must come after ACPI since it will eventually need to check if acpi
19# was used and do nothing if so 19# was used and do nothing if so
20obj-$(CONFIG_PNP) += pnp/ 20obj-$(CONFIG_PNP) += pnp/
21obj-$(CONFIG_ARM_AMBA) += amba/ 21obj-y += amba/
22# Many drivers will want to use DMA so this has to be made available 22# Many drivers will want to use DMA so this has to be made available
23# really early. 23# really early.
24obj-$(CONFIG_DMA_ENGINE) += dma/ 24obj-$(CONFIG_DMA_ENGINE) += dma/
diff --git a/drivers/amba/Makefile b/drivers/amba/Makefile
index 40fe74097be2..66e81c2f1e3c 100644
--- a/drivers/amba/Makefile
+++ b/drivers/amba/Makefile
@@ -1,2 +1,2 @@
1obj-y += bus.o 1obj-$(CONFIG_ARM_AMBA) += bus.o
2 2obj-$(CONFIG_TEGRA_AHB) += tegra-ahb.o
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c
new file mode 100644
index 000000000000..aa0b1f160528
--- /dev/null
+++ b/drivers/amba/tegra-ahb.c
@@ -0,0 +1,293 @@
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#define AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE BIT(17)
80
81static struct platform_driver tegra_ahb_driver;
82
83static const u32 tegra_ahb_gizmo[] = {
84 AHB_ARBITRATION_DISABLE,
85 AHB_ARBITRATION_PRIORITY_CTRL,
86 AHB_GIZMO_AHB_MEM,
87 AHB_GIZMO_APB_DMA,
88 AHB_GIZMO_IDE,
89 AHB_GIZMO_USB,
90 AHB_GIZMO_AHB_XBAR_BRIDGE,
91 AHB_GIZMO_CPU_AHB_BRIDGE,
92 AHB_GIZMO_COP_AHB_BRIDGE,
93 AHB_GIZMO_XBAR_APB_CTLR,
94 AHB_GIZMO_VCP_AHB_BRIDGE,
95 AHB_GIZMO_NAND,
96 AHB_GIZMO_SDMMC4,
97 AHB_GIZMO_XIO,
98 AHB_GIZMO_BSEV,
99 AHB_GIZMO_BSEA,
100 AHB_GIZMO_NOR,
101 AHB_GIZMO_USB2,
102 AHB_GIZMO_USB3,
103 AHB_GIZMO_SDMMC1,
104 AHB_GIZMO_SDMMC2,
105 AHB_GIZMO_SDMMC3,
106 AHB_MEM_PREFETCH_CFG_X,
107 AHB_ARBITRATION_XBAR_CTRL,
108 AHB_MEM_PREFETCH_CFG3,
109 AHB_MEM_PREFETCH_CFG4,
110 AHB_MEM_PREFETCH_CFG1,
111 AHB_MEM_PREFETCH_CFG2,
112 AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID,
113};
114
115struct tegra_ahb {
116 void __iomem *regs;
117 struct device *dev;
118 u32 ctx[0];
119};
120
121static inline u32 gizmo_readl(struct tegra_ahb *ahb, u32 offset)
122{
123 return readl(ahb->regs + offset);
124}
125
126static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset)
127{
128 writel(value, ahb->regs + offset);
129}
130
131#ifdef CONFIG_ARCH_TEGRA_3x_SOC
132static int tegra_ahb_match_by_smmu(struct device *dev, void *data)
133{
134 struct tegra_ahb *ahb = dev_get_drvdata(dev);
135 struct device_node *dn = data;
136
137 return (ahb->dev->of_node == dn) ? 1 : 0;
138}
139
140int tegra_ahb_enable_smmu(struct device_node *dn)
141{
142 struct device *dev;
143 u32 val;
144 struct tegra_ahb *ahb;
145
146 dev = driver_find_device(&tegra_ahb_driver.driver, NULL, dn,
147 tegra_ahb_match_by_smmu);
148 if (!dev)
149 return -EPROBE_DEFER;
150 ahb = dev_get_drvdata(dev);
151 val = gizmo_readl(ahb, AHB_ARBITRATION_XBAR_CTRL);
152 val |= AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE;
153 gizmo_writel(ahb, val, AHB_ARBITRATION_XBAR_CTRL);
154 return 0;
155}
156EXPORT_SYMBOL(tegra_ahb_enable_smmu);
157#endif
158
159static int tegra_ahb_suspend(struct device *dev)
160{
161 int i;
162 struct tegra_ahb *ahb = dev_get_drvdata(dev);
163
164 for (i = 0; i < ARRAY_SIZE(tegra_ahb_gizmo); i++)
165 ahb->ctx[i] = gizmo_readl(ahb, tegra_ahb_gizmo[i]);
166 return 0;
167}
168
169static int tegra_ahb_resume(struct device *dev)
170{
171 int i;
172 struct tegra_ahb *ahb = dev_get_drvdata(dev);
173
174 for (i = 0; i < ARRAY_SIZE(tegra_ahb_gizmo); i++)
175 gizmo_writel(ahb, ahb->ctx[i], tegra_ahb_gizmo[i]);
176 return 0;
177}
178
179static UNIVERSAL_DEV_PM_OPS(tegra_ahb_pm,
180 tegra_ahb_suspend,
181 tegra_ahb_resume, NULL);
182
183static void tegra_ahb_gizmo_init(struct tegra_ahb *ahb)
184{
185 u32 val;
186
187 val = gizmo_readl(ahb, AHB_GIZMO_AHB_MEM);
188 val |= ENB_FAST_REARBITRATE | IMMEDIATE | DONT_SPLIT_AHB_WR;
189 gizmo_writel(ahb, val, AHB_GIZMO_AHB_MEM);
190
191 val = gizmo_readl(ahb, AHB_GIZMO_USB);
192 val |= IMMEDIATE;
193 gizmo_writel(ahb, val, AHB_GIZMO_USB);
194
195 val = gizmo_readl(ahb, AHB_GIZMO_USB2);
196 val |= IMMEDIATE;
197 gizmo_writel(ahb, val, AHB_GIZMO_USB2);
198
199 val = gizmo_readl(ahb, AHB_GIZMO_USB3);
200 val |= IMMEDIATE;
201 gizmo_writel(ahb, val, AHB_GIZMO_USB3);
202
203 val = gizmo_readl(ahb, AHB_ARBITRATION_PRIORITY_CTRL);
204 val |= PRIORITY_SELECT_USB |
205 PRIORITY_SELECT_USB2 |
206 PRIORITY_SELECT_USB3 |
207 AHB_PRIORITY_WEIGHT(7);
208 gizmo_writel(ahb, val, AHB_ARBITRATION_PRIORITY_CTRL);
209
210 val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG1);
211 val &= ~MST_ID(~0);
212 val |= PREFETCH_ENB |
213 AHBDMA_MST_ID |
214 ADDR_BNDRY(0xc) |
215 INACTIVITY_TIMEOUT(0x1000);
216 gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG1);
217
218 val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG2);
219 val &= ~MST_ID(~0);
220 val |= PREFETCH_ENB |
221 USB_MST_ID |
222 ADDR_BNDRY(0xc) |
223 INACTIVITY_TIMEOUT(0x1000);
224 gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG2);
225
226 val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG3);
227 val &= ~MST_ID(~0);
228 val |= PREFETCH_ENB |
229 USB3_MST_ID |
230 ADDR_BNDRY(0xc) |
231 INACTIVITY_TIMEOUT(0x1000);
232 gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG3);
233
234 val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG4);
235 val &= ~MST_ID(~0);
236 val |= PREFETCH_ENB |
237 USB2_MST_ID |
238 ADDR_BNDRY(0xc) |
239 INACTIVITY_TIMEOUT(0x1000);
240 gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG4);
241}
242
243static int __devinit tegra_ahb_probe(struct platform_device *pdev)
244{
245 struct resource *res;
246 struct tegra_ahb *ahb;
247 size_t bytes;
248
249 bytes = sizeof(*ahb) + sizeof(u32) * ARRAY_SIZE(tegra_ahb_gizmo);
250 ahb = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL);
251 if (!ahb)
252 return -ENOMEM;
253
254 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
255 if (!res)
256 return -ENODEV;
257 ahb->regs = devm_request_and_ioremap(&pdev->dev, res);
258 if (!ahb->regs)
259 return -EBUSY;
260
261 ahb->dev = &pdev->dev;
262 platform_set_drvdata(pdev, ahb);
263 tegra_ahb_gizmo_init(ahb);
264 return 0;
265}
266
267static int __devexit tegra_ahb_remove(struct platform_device *pdev)
268{
269 return 0;
270}
271
272static const struct of_device_id tegra_ahb_of_match[] __devinitconst = {
273 { .compatible = "nvidia,tegra30-ahb", },
274 { .compatible = "nvidia,tegra20-ahb", },
275 {},
276};
277
278static struct platform_driver tegra_ahb_driver = {
279 .probe = tegra_ahb_probe,
280 .remove = __devexit_p(tegra_ahb_remove),
281 .driver = {
282 .name = DRV_NAME,
283 .owner = THIS_MODULE,
284 .of_match_table = tegra_ahb_of_match,
285 .pm = &tegra_ahb_pm,
286 },
287};
288module_platform_driver(tegra_ahb_driver);
289
290MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");
291MODULE_DESCRIPTION("Tegra AHB driver");
292MODULE_LICENSE("GPL v2");
293MODULE_ALIAS("platform:" DRV_NAME);