@@ -82,6 +82,16 @@
#define AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE BIT(17)
+/*
+ * INCORRECT_BASE_ADDR_LOW_BYTE: Legacy kernel DT files for Tegra SoCs
+ * prior to Tegra124 generally use a physical base address ending in
+ * 0x4 for the AHB IP block. According to the TRM, the low byte
+ * should be 0x0. During device probing, this macro is used to detect
+ * whether the passed-in physical address is incorrect, and if so, to
+ * correct it.
+ */
+#define INCORRECT_BASE_ADDR_LOW_BYTE 0x4
+
static struct platform_driver tegra_ahb_driver;
static const u32 tegra_ahb_gizmo[] = {
@@ -124,12 +134,12 @@ struct tegra_ahb {
static inline u32 gizmo_readl(struct tegra_ahb *ahb, u32 offset)
{
- return readl(ahb->regs - 4 + offset);
+ return readl(ahb->regs + offset);
}
static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset)
{
- writel(value, ahb->regs - 4 + offset);
+ writel(value, ahb->regs + offset);
}
#ifdef CONFIG_TEGRA_IOMMU_SMMU
@@ -258,6 +268,15 @@ static int tegra_ahb_probe(struct platform_device *pdev)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ /* Correct the IP block base address if necessary */
+ if (res &&
+ (res->start & INCORRECT_BASE_ADDR_LOW_BYTE) ==
+ INCORRECT_BASE_ADDR_LOW_BYTE) {
+ dev_warn(&pdev->dev, "incorrect AHB base address in DT data - enabling workaround\n");
+ res->start -= INCORRECT_BASE_ADDR_LOW_BYTE;
+ }
+
ahb->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ahb->regs))
return PTR_ERR(ahb->regs);