diff options
Diffstat (limited to 'arch/arm/boards/ls1046ardb/board.c')
-rw-r--r-- | arch/arm/boards/ls1046ardb/board.c | 162 |
1 files changed, 160 insertions, 2 deletions
diff --git a/arch/arm/boards/ls1046ardb/board.c b/arch/arm/boards/ls1046ardb/board.c index 0846df9fad..ee70171ca3 100644 --- a/arch/arm/boards/ls1046ardb/board.c +++ b/arch/arm/boards/ls1046ardb/board.c @@ -2,13 +2,134 @@ #include <common.h> #include <init.h> +#include <bbu.h> +#include <net.h> +#include <crc.h> +#include <fs.h> #include <envfs.h> +#include <libfile.h> #include <asm/memory.h> #include <linux/sizes.h> #include <linux/clk.h> #include <linux/clkdev.h> #include <asm/system.h> -#include <mach/layerscape.h> +#include <mach/layerscape/layerscape.h> +#include <mach/layerscape/bbu.h> +#include <of_address.h> +#include <linux/fsl_ifc.h> + +#define MAX_NUM_PORTS 16 +struct nxid { + u8 id[4]; /* 0x00 - 0x03 EEPROM Tag 'NXID' */ + u8 sn[12]; /* 0x04 - 0x0F Serial Number */ + u8 errata[5]; /* 0x10 - 0x14 Errata Level */ + u8 date[6]; /* 0x15 - 0x1a Build Date */ + u8 res_0; /* 0x1b Reserved */ + u32 version; /* 0x1c - 0x1f NXID Version */ + u8 tempcal[8]; /* 0x20 - 0x27 Temperature Calibration Factors */ + u8 tempcalsys[2]; /* 0x28 - 0x29 System Temperature Calibration Factors */ + u8 tempcalflags; /* 0x2a Temperature Calibration Flags */ + u8 res_1[21]; /* 0x2b - 0x3f Reserved */ + u8 mac_count; /* 0x40 Number of MAC addresses */ + u8 mac_flag; /* 0x41 MAC table flags */ + u8 mac[MAX_NUM_PORTS][6]; /* 0x42 - 0xa1 MAC addresses */ + u8 res_2[90]; /* 0xa2 - 0xfb Reserved */ + u32 crc; /* 0xfc - 0xff CRC32 checksum */ +} __packed; + +static int nxid_is_valid(struct nxid *nxid) +{ + unsigned char id[] = { 'N', 'X', 'I', 'D' }; + int i; + + for (i = 0; i < ARRAY_SIZE(id); i++) + if (nxid->id[i] != id[i]) + return false; + return true; +} + +static struct nxid *nxp_nxid_read(const char *filename, unsigned int offset) +{ + struct nxid *nxid; + int fd, ret, i, n; + struct device_node *root; + u32 crc, crc_expected; + + nxid = xzalloc(sizeof(*nxid)); + + fd = open(filename, O_RDONLY); + if (fd < 0) { + ret = -errno; + goto out; + } + + ret = pread(fd, nxid, sizeof(*nxid), offset); + if (ret < 0) { + close(fd); + goto out; + } + + if (!nxid_is_valid(nxid)) { + ret = -ENODEV; + goto out; + } + + crc = crc32(0, nxid, 256 - 4); + crc_expected = be32_to_cpu(nxid->crc); + if (crc != crc_expected) { + pr_err("CRC mismatch (%08x != %08x)\n", crc, crc_expected); + ret = -EINVAL; + goto out; + } + + root = of_get_root_node(); + + i = n = 0; + + /* + * The MAC addresses in the nxid structure are in the order of enabled + * network interfaces. We have to find the network interfaces by their + * aliases and skip assigning MAC addresses to disabled devices. + */ + while (1) { + struct device_node *np; + char alias[sizeof("ethernetxxx")]; + + sprintf(alias, "ethernet%d", n); + + np = of_find_node_by_alias(root, alias); + if (!np) + goto out; + + n++; + if (!of_device_is_available(np)) + continue; + + of_eth_register_ethaddr(np, (char *)nxid->mac[i]); + + i++; + + if (i == nxid->mac_count) + break; + } + + ret = 0; +out: + if (ret) { + free(nxid); + nxid = ERR_PTR(ret); + } + + return nxid; +} + +static int rdb_late_init(void) +{ + nxp_nxid_read("/dev/eeprom", 256); + + return 0; +} +late_initcall(rdb_late_init); static int rdb_mem_init(void) { @@ -28,6 +149,40 @@ static int rdb_mem_init(void) } mem_initcall(rdb_mem_init); +static int rdb_nand_init(void) +{ + struct device_node *np; + void __iomem *ifc; + + np = of_find_compatible_node(NULL, NULL, "fsl,ifc"); + if (!np) + return -EINVAL; + + ifc = of_iomap(np, 0); + if (!ifc) + return -EINVAL; + + set_ifc_cspr(ifc, IFC_CS0, CSPR_PHYS_ADDR(0x7e800000) | + CSPR_PORT_SIZE_8 | CSPR_MSEL_NAND | CSPR_V); + set_ifc_csor(ifc, IFC_CS0, CSOR_NAND_ECC_ENC_EN | CSOR_NAND_ECC_DEC_EN | + CSOR_NAND_ECC_MODE_8 | + CSOR_NAND_RAL_3 | CSOR_NAND_PGS_4K | + CSOR_NAND_SPRZ_224 | CSOR_NAND_PB(64) | + CSOR_NAND_TRHZ_20); + set_ifc_amask(ifc, IFC_CS0, IFC_AMASK(64*1024)); + set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM0, FTIM0_NAND_TCCST(0x07) | + FTIM0_NAND_TWP(0x18) | FTIM0_NAND_TWCHT(0x07) | + FTIM0_NAND_TWH(0x0a)); + set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM1, FTIM1_NAND_TADLE(0x32) | + FTIM1_NAND_TWBE(0x39) | FTIM1_NAND_TRR(0x0e)| + FTIM1_NAND_TRP(0x18)); + set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM2, FTIM2_NAND_TRAD(0xf) | + FTIM2_NAND_TREH(0xa) | FTIM2_NAND_TWHRE(0x1e)); + set_ifc_ftim(ifc, IFC_CS0, IFC_FTIM3, 0); + + return 0; +} + static int rdb_postcore_init(void) { if (!of_machine_is_compatible("fsl,ls1046a-rdb")) @@ -35,7 +190,10 @@ static int rdb_postcore_init(void) defaultenv_append_directory(defaultenv_ls1046ardb); - return 0; + ls1046a_bbu_mmc_register_handler("sd", "/dev/mmc0.barebox", + BBU_HANDLER_FLAG_DEFAULT); + + return rdb_nand_init(); } postcore_initcall(rdb_postcore_init); |