diff options
| -rw-r--r-- | drivers/amba/tegra-ahb.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c index 30759a55efe4..b0b688c481e8 100644 --- a/drivers/amba/tegra-ahb.c +++ b/drivers/amba/tegra-ahb.c | |||
| @@ -82,6 +82,16 @@ | |||
| 82 | 82 | ||
| 83 | #define AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE BIT(17) | 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 | static struct platform_driver tegra_ahb_driver; | 95 | static struct platform_driver tegra_ahb_driver; |
| 86 | 96 | ||
| 87 | static const u32 tegra_ahb_gizmo[] = { | 97 | static const u32 tegra_ahb_gizmo[] = { |
| @@ -124,12 +134,12 @@ struct tegra_ahb { | |||
| 124 | 134 | ||
| 125 | static inline u32 gizmo_readl(struct tegra_ahb *ahb, u32 offset) | 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 | static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset) | 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 | #ifdef CONFIG_TEGRA_IOMMU_SMMU | 145 | #ifdef CONFIG_TEGRA_IOMMU_SMMU |
| @@ -258,6 +268,15 @@ static int tegra_ahb_probe(struct platform_device *pdev) | |||
| 258 | return -ENOMEM; | 268 | return -ENOMEM; |
| 259 | 269 | ||
| 260 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 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 | ahb->regs = devm_ioremap_resource(&pdev->dev, res); | 280 | ahb->regs = devm_ioremap_resource(&pdev->dev, res); |
| 262 | if (IS_ERR(ahb->regs)) | 281 | if (IS_ERR(ahb->regs)) |
| 263 | return PTR_ERR(ahb->regs); | 282 | return PTR_ERR(ahb->regs); |
