u64 pci_addr = entry->res->start - entry->offset;
u64 cpu_addr = entry->res->start;
u64 cpu_end = entry->res->end;
- u64 size_id = 0;
int id = *index;
u64 size;
- while (cpu_addr < cpu_end) {
+ /*
+ * According to the RZ/G3S HW manual (Rev.1.10, section 34.6.6.7) and
+ * RZ/G3E HW manual (Rev.1.15, section 6.6.7.6):
+ * - Each window must be a single memory size of power of two
+ * - Mask registers must be set to (2^N - 1)
+ * - Bit carry must not occur when adding base and mask registers,
+ * meaning the base address must be aligned to the window size
+ *
+ * Split non-power-of-2 regions into multiple windows to satisfy
+ * these constraints without over-mapping.
+ */
+ while (cpu_addr <= cpu_end) {
+ u64 remaining_size = cpu_end - cpu_addr + 1;
+ u64 align_limit;
+
if (id >= RZG3S_MAX_WINDOWS)
return dev_err_probe(host->dev, -ENOSPC,
"Failed to map inbound window for resource (%s)\n",
entry->res->name);
- size = resource_size(entry->res) - size_id;
+ /* Start with largest power-of-two that fits in remaining size */
+ size = 1ULL << __fls(remaining_size);
/*
- * According to the RZ/G3S HW manual (Rev.1.10,
- * section 34.3.1.71 AXI Window Mask (Lower) Registers) the min
- * size is 4K.
+ * The "no bit carry" rule requires base addresses to be
+ * aligned to the window size. Find the maximum window size
+ * that both addresses can support based on their natural
+ * alignment (lowest set bit).
*/
- size = max(size, SZ_4K);
+ align_limit = min(cpu_addr ? (1ULL << __ffs(cpu_addr)) : ~0ULL,
+ pci_addr ? (1ULL << __ffs(pci_addr)) : ~0ULL);
- /*
- * According the RZ/G3S HW manual (Rev.1.10, sections:
- * - 34.3.1.69 AXI Window Base (Lower) Registers
- * - 34.3.1.71 AXI Window Mask (Lower) Registers
- * - 34.3.1.73 AXI Destination (Lower) Registers)
- * the CPU addr, PCIe addr, size should be 4K aligned and be a
- * power of 2.
- */
- size = ALIGN(size, SZ_4K);
- size = roundup_pow_of_two(size);
-
- cpu_addr = ALIGN(cpu_addr, SZ_4K);
- pci_addr = ALIGN(pci_addr, SZ_4K);
+ size = min(size, align_limit);
/*
- * According to the RZ/G3S HW manual (Rev.1.10, section
- * 34.3.1.71 AXI Window Mask (Lower) Registers) HW expects first
- * 12 LSB bits to be 0xfff. Subtract 1 from size for this.
+ * Minimum window size is 4KB.
+ * See RZ/G3S HW manual (Rev.1.10, section 34.3.1.71) and
+ * RZ/G3E HW manual (Rev.1.15, section 6.6.4.1.3.(74)).
*/
+ size = max(size, SZ_4K);
+
rzg3s_pcie_set_inbound_window(host, cpu_addr, pci_addr,
size - 1, id);
pci_addr += size;
cpu_addr += size;
- size_id = size;
id++;
}
*index = id;