|
82 | 82 |
|
83 | 83 | #define AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE BIT(17)
|
84 | 84 |
|
| 85 | +/* |
| 86 | + * INCORRECT_BASE_ADDR_LOW_BYTE: Legacy kernel DT files for Tegra SoCs |
| 87 | + * prior to Tegra124 generally use a physical base address ending in |
| 88 | + * 0x4 for the AHB IP block. According to the TRM, the low byte |
| 89 | + * should be 0x0. During device probing, this macro is used to detect |
| 90 | + * whether the passed-in physical address is incorrect, and if so, to |
| 91 | + * correct it. |
| 92 | + */ |
| 93 | +#define INCORRECT_BASE_ADDR_LOW_BYTE 0x4 |
| 94 | + |
85 | 95 | static struct platform_driver tegra_ahb_driver;
|
86 | 96 |
|
87 | 97 | static const u32 tegra_ahb_gizmo[] = {
|
@@ -124,12 +134,12 @@ struct tegra_ahb {
|
124 | 134 |
|
125 | 135 | static inline u32 gizmo_readl(struct tegra_ahb *ahb, u32 offset)
|
126 | 136 | {
|
127 |
| - return readl(ahb->regs - 4 + offset); |
| 137 | + return readl(ahb->regs + offset); |
128 | 138 | }
|
129 | 139 |
|
130 | 140 | static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset)
|
131 | 141 | {
|
132 |
| - writel(value, ahb->regs - 4 + offset); |
| 142 | + writel(value, ahb->regs + offset); |
133 | 143 | }
|
134 | 144 |
|
135 | 145 | #ifdef CONFIG_TEGRA_IOMMU_SMMU
|
@@ -258,6 +268,15 @@ static int tegra_ahb_probe(struct platform_device *pdev)
|
258 | 268 | return -ENOMEM;
|
259 | 269 |
|
260 | 270 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
| 271 | + |
| 272 | + /* Correct the IP block base address if necessary */ |
| 273 | + if (res && |
| 274 | + (res->start & INCORRECT_BASE_ADDR_LOW_BYTE) == |
| 275 | + INCORRECT_BASE_ADDR_LOW_BYTE) { |
| 276 | + dev_warn(&pdev->dev, "incorrect AHB base address in DT data - enabling workaround\n"); |
| 277 | + res->start -= INCORRECT_BASE_ADDR_LOW_BYTE; |
| 278 | + } |
| 279 | + |
261 | 280 | ahb->regs = devm_ioremap_resource(&pdev->dev, res);
|
262 | 281 | if (IS_ERR(ahb->regs))
|
263 | 282 | return PTR_ERR(ahb->regs);
|
|
0 commit comments