^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * SDK7786 FPGA Support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010 Paul Mundt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/bcd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <mach/fpga.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/sizes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define FPGA_REGS_OFFSET 0x03fff800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define FPGA_REGS_SIZE 0x490
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * The FPGA can be mapped in any of the generally available areas,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * so we attempt to scan for it using the fixed SRSTR read magic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Once the FPGA is located, the rest of the mapping data for the other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * components can be determined dynamically from its section mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static void __iomem *sdk7786_fpga_probe(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned long area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * Iterate over all of the areas where the FPGA could be mapped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * The possible range is anywhere from area 0 through 6, area 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * is reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) for (area = PA_AREA0; area < PA_AREA7; area += SZ_64M) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) base = ioremap(area + FPGA_REGS_OFFSET, FPGA_REGS_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (!base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* Failed to remap this area, move along. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (ioread16(base + SRSTR) == SRSTR_MAGIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return base; /* Found it! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) iounmap(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) void __iomem *sdk7786_fpga_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) void __init sdk7786_fpga_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u16 version, date;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) sdk7786_fpga_base = sdk7786_fpga_probe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (unlikely(!sdk7786_fpga_base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) panic("FPGA detection failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) version = fpga_read_reg(FPGAVR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) date = fpga_read_reg(FPGADR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) pr_info("\tFPGA version:\t%d.%d (built on %d/%d/%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) bcd2bin(version >> 8) & 0xf, bcd2bin(version & 0xf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ((date >> 12) & 0xf) + 2000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) (date >> 8) & 0xf, bcd2bin(date & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }