diff options
author | Andy Fleming <afleming@gmail.com> | 2015-11-04 15:48:32 -0600 |
---|---|---|
committer | York Sun <yorksun@freescale.com> | 2015-11-04 15:19:34 -0800 |
commit | 87e29878caba758ed3e09e9912ac8eb6dfc55f39 (patch) | |
tree | d98b04c33498eb2bb30dac21961d1bb32637823c /board | |
parent | c79e1c1ce9e5c1ddf6fac631e4741999f8a0cc58 (diff) |
mpc85xx: Add support for the Varisys Cyrus board
This board runs a P5020 or P5040 chip, and utilizes
an EEPROM with similar formatting to the Freescale P5020DS.
Large amounts of this code were developed by
Adrian Cox <adrian at humboldt dot co dot uk>
Signed-off-by: Andy Fleming <afleming@gmail.com>
Reviewed-by: York Sun <yorksun@freescale.com>
Diffstat (limited to 'board')
-rw-r--r-- | board/varisys/common/Makefile | 23 | ||||
-rw-r--r-- | board/varisys/common/eeprom.h | 6 | ||||
-rw-r--r-- | board/varisys/common/sys_eeprom.c | 498 | ||||
-rw-r--r-- | board/varisys/cyrus/Kconfig | 12 | ||||
-rw-r--r-- | board/varisys/cyrus/MAINTAINERS | 7 | ||||
-rw-r--r-- | board/varisys/cyrus/Makefile | 8 | ||||
-rw-r--r-- | board/varisys/cyrus/README | 19 | ||||
-rw-r--r-- | board/varisys/cyrus/cyrus.c | 116 | ||||
-rw-r--r-- | board/varisys/cyrus/cyrus.h | 11 | ||||
-rw-r--r-- | board/varisys/cyrus/ddr.c | 188 | ||||
-rw-r--r-- | board/varisys/cyrus/eth.c | 100 | ||||
-rw-r--r-- | board/varisys/cyrus/law.c | 27 | ||||
-rw-r--r-- | board/varisys/cyrus/pbi.cfg | 35 | ||||
-rw-r--r-- | board/varisys/cyrus/pci.c | 23 | ||||
-rw-r--r-- | board/varisys/cyrus/rcw_p5020_v2.cfg | 11 | ||||
-rw-r--r-- | board/varisys/cyrus/rcw_p5040.cfg | 11 | ||||
-rw-r--r-- | board/varisys/cyrus/tlb.c | 106 |
17 files changed, 1201 insertions, 0 deletions
diff --git a/board/varisys/common/Makefile b/board/varisys/common/Makefile new file mode 100644 index 00000000000..1e6dcbb6de3 --- /dev/null +++ b/board/varisys/common/Makefile @@ -0,0 +1,23 @@ +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +MINIMAL= + +ifdef CONFIG_SPL_BUILD +ifdef CONFIG_SPL_INIT_MINIMAL +MINIMAL=y +endif +endif + +ifdef MINIMAL +# necessary to create built-in.o +obj- := __dummy__.o +else +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_ID_EEPROM) += sys_eeprom.o +endif +endif diff --git a/board/varisys/common/eeprom.h b/board/varisys/common/eeprom.h new file mode 100644 index 00000000000..004816a0fd4 --- /dev/null +++ b/board/varisys/common/eeprom.h @@ -0,0 +1,6 @@ +/* EEPROM init functions for Cyrus */ + + +void init_eeprom(int bus_num, int addr, int addr_len); +void mac_read_from_fixed_id(void); +int mac_read_from_eeprom_common(void); diff --git a/board/varisys/common/sys_eeprom.c b/board/varisys/common/sys_eeprom.c new file mode 100644 index 00000000000..b55ab818e69 --- /dev/null +++ b/board/varisys/common/sys_eeprom.c @@ -0,0 +1,498 @@ +/* + * Based on board/freescale/common/sys_eeprom.c + * Copyright 2006, 2008-2009, 2011 Freescale Semiconductor + * + * This defines the API for storing board information in the + * eeprom. It has been adapted from an earlier version of the + * Freescale API, but has a number of key differences. Because + * the two APIs are independent and may diverge further, the + * Varisys version of the API is implemented separately here. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <i2c.h> +#include <linux/ctype.h> + +#include "eeprom.h" + +#ifdef CONFIG_SYS_I2C_EEPROM_NXID_MAC +#define MAX_NUM_PORTS CONFIG_SYS_I2C_EEPROM_NXID_MAC +#else +#define MAX_NUM_PORTS 8 +#endif +#define NXID_VERSION 0 + +/** + * static eeprom: EEPROM layout for NXID formats + * + * See Freescale application note AN3638 for details. + */ +static struct __attribute__ ((__packed__)) eeprom { + 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 - x MAC addresses */ + u32 crc; /* x+1 CRC32 checksum */ +} e; + +/* Set to 1 if we've read EEPROM into memory */ +static int has_been_read; + +/* Is this a valid NXID EEPROM? */ +#define is_valid ((e.id[0] == 'N') || (e.id[1] == 'X') || \ + (e.id[2] == 'I') || (e.id[3] == 'D')) + +/** Fixed ID field in EEPROM */ +static unsigned char uid[16]; + +static int eeprom_bus_num = -1; +static int eeprom_addr; +static int eeprom_addr_len; + +/** + * This must be called before any eeprom access. + */ +void init_eeprom(int bus_num, int addr, int addr_len) +{ + eeprom_bus_num = bus_num; + eeprom_addr = addr; + eeprom_addr_len = addr_len; +} + +/** + * show_eeprom - display the contents of the EEPROM + */ +void show_eeprom(void) +{ + int i; + unsigned int crc; + + /* EEPROM tag ID, either CCID or NXID */ + printf("ID: %c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3], + be32_to_cpu(e.version)); + + /* Serial number */ + printf("SN: %s\n", e.sn); + + printf("UID: "); + for (i = 0; i < 16; i++) + printf("%02x", uid[i]); + printf("\n"); + + /* Errata level. */ + printf("Errata: %s\n", e.errata); + + /* Build date, BCD date values, as YYMMDDhhmmss */ + printf("Build date: 20%02x/%02x/%02x %02x:%02x:%02x %s\n", + e.date[0], e.date[1], e.date[2], + e.date[3] & 0x7F, e.date[4], e.date[5], + e.date[3] & 0x80 ? "PM" : ""); + + /* Show MAC addresses */ + for (i = 0; i < min(e.mac_count, (u8)MAX_NUM_PORTS); i++) { + u8 *p = e.mac[i]; + + printf("Eth%u: %02x:%02x:%02x:%02x:%02x:%02x\n", i, + p[0], p[1], p[2], p[3], p[4], p[5]); + } + + crc = crc32(0, (void *)&e, sizeof(e) - 4); + + if (crc == be32_to_cpu(e.crc)) + printf("CRC: %08x\n", be32_to_cpu(e.crc)); + else + printf("CRC: %08x (should be %08x)\n", + be32_to_cpu(e.crc), crc); + +#ifdef DEBUG + printf("EEPROM dump: (0x%x bytes)\n", sizeof(e)); + for (i = 0; i < sizeof(e); i++) { + if ((i % 16) == 0) + printf("%02X: ", i); + printf("%02X ", ((u8 *)&e)[i]); + if (((i % 16) == 15) || (i == sizeof(e) - 1)) + printf("\n"); + } +#endif +} + +/** + * read_eeprom - read the EEPROM into memory + */ +int read_eeprom(void) +{ + int ret; + unsigned int bus; + + if (eeprom_bus_num < 0) { + printf("EEPROM not configured\n"); + return -1; + } + + if (has_been_read) + return 0; + + bus = i2c_get_bus_num(); + i2c_set_bus_num(eeprom_bus_num); + + ret = i2c_read(eeprom_addr, 0, eeprom_addr_len, + (void *)&e, sizeof(e)); + + + /* Fixed address of ID field */ + i2c_read(0x5f, 0x80, 1, uid, 16); + + i2c_set_bus_num(bus); + +#ifdef DEBUG + show_eeprom(); +#endif + + has_been_read = (ret == 0) ? 1 : 0; + + return ret; +} + +/** + * update_crc - update the CRC + * + * This function should be called after each update to the EEPROM structure, + * to make sure the CRC is always correct. + */ +static void update_crc(void) +{ + u32 crc, crc_offset = offsetof(struct eeprom, crc); + + crc = crc32(0, (void *)&e, crc_offset); + e.crc = cpu_to_be32(crc); +} + +/** + * prog_eeprom - write the EEPROM from memory + */ +static int prog_eeprom(void) +{ + int ret = 0; + int i; + void *p; + unsigned int bus; + + if (eeprom_bus_num < 0) { + printf("EEPROM not configured\n"); + return -1; + } + + /* Set the reserved values to 0xFF */ + e.res_0 = 0xFF; + memset(e.res_1, 0xFF, sizeof(e.res_1)); + update_crc(); + + bus = i2c_get_bus_num(); + i2c_set_bus_num(eeprom_bus_num); + + /* + * The AT24C02 datasheet says that data can only be written in page + * mode, which means 8 bytes at a time, and it takes up to 5ms to + * complete a given write. + */ + for (i = 0, p = &e; i < sizeof(e); i += 8, p += 8) { + ret = i2c_write(eeprom_addr, i, eeprom_addr_len, + p, min((int)(sizeof(e) - i), 8)); + if (ret) + break; + udelay(5000); /* 5ms write cycle timing */ + } + + if (!ret) { + /* Verify the write by reading back the EEPROM and comparing */ + struct eeprom e2; + + ret = i2c_read(eeprom_addr, 0, + eeprom_addr_len, (void *)&e2, sizeof(e2)); + if (!ret && memcmp(&e, &e2, sizeof(e))) + ret = -1; + } + + i2c_set_bus_num(bus); + + if (ret) { + printf("Programming failed.\n"); + has_been_read = 0; + return -1; + } + + printf("Programming passed.\n"); + return 0; +} + +/** + * h2i - converts hex character into a number + * + * This function takes a hexadecimal character (e.g. '7' or 'C') and returns + * the integer equivalent. + */ +static inline u8 h2i(char p) +{ + if ((p >= '0') && (p <= '9')) + return p - '0'; + + if ((p >= 'A') && (p <= 'F')) + return (p - 'A') + 10; + + if ((p >= 'a') && (p <= 'f')) + return (p - 'a') + 10; + + return 0; +} + +/** + * set_date - stores the build date into the EEPROM + * + * This function takes a pointer to a string in the format "YYMMDDhhmmss" + * (2-digit year, 2-digit month, etc), converts it to a 6-byte BCD string, + * and stores it in the build date field of the EEPROM local copy. + */ +static void set_date(const char *string) +{ + unsigned int i; + + if (strlen(string) != 12) { + printf("Usage: mac date YYMMDDhhmmss\n"); + return; + } + + for (i = 0; i < 6; i++) + e.date[i] = h2i(string[2 * i]) << 4 | h2i(string[2 * i + 1]); + + update_crc(); +} + +/** + * set_mac_address - stores a MAC address into the EEPROM + * + * This function takes a pointer to MAC address string + * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number) and + * stores it in one of the MAC address fields of the EEPROM local copy. + */ +static void set_mac_address(unsigned int index, const char *string) +{ + char *p = (char *)string; + unsigned int i; + + if ((index >= MAX_NUM_PORTS) || !string) { + printf("Usage: mac <n> XX:XX:XX:XX:XX:XX\n"); + return; + } + + for (i = 0; *p && (i < 6); i++) { + e.mac[index][i] = simple_strtoul(p, &p, 16); + if (*p == ':') + p++; + } + + update_crc(); +} + +int do_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char cmd; + + if (argc == 1) { + show_eeprom(); + return 0; + } + + cmd = argv[1][0]; + + if (cmd == 'r') { + read_eeprom(); + return 0; + } + + if (cmd == 'i') { + memcpy(e.id, "NXID", sizeof(e.id)); + e.version = NXID_VERSION; + update_crc(); + return 0; + } + + if (!is_valid) { + printf("Please read the EEPROM ('r') and/or set the ID ('i') first.\n"); + return 0; + } + + if (argc == 2) { + switch (cmd) { + case 's': /* save */ + prog_eeprom(); + break; + default: + return cmd_usage(cmdtp); + } + + return 0; + } + + /* We know we have at least one parameter */ + + switch (cmd) { + case 'n': /* serial number */ + memset(e.sn, 0, sizeof(e.sn)); + strncpy((char *)e.sn, argv[2], sizeof(e.sn) - 1); + update_crc(); + break; + case 'e': /* errata */ + memset(e.errata, 0, 5); + strncpy((char *)e.errata, argv[2], 4); + update_crc(); + break; + case 'd': /* date BCD format YYMMDDhhmmss */ + set_date(argv[2]); + break; + case 'p': /* MAC table size */ + e.mac_count = simple_strtoul(argv[2], NULL, 16); + update_crc(); + break; + case '0' ... '9': /* "mac 0" through "mac 22" */ + set_mac_address(simple_strtoul(argv[1], NULL, 10), argv[2]); + break; + case 'h': /* help */ + default: + return cmd_usage(cmdtp); + } + + return 0; +} + +int mac_read_from_generic_eeprom(const char *envvar, int chip, + int address, int mac_bus) +{ + int ret; + unsigned int bus; + unsigned char mac[6]; + char ethaddr[18]; + + bus = i2c_get_bus_num(); + i2c_set_bus_num(mac_bus); + + ret = i2c_read(chip, address, 1, mac, 6); + + i2c_set_bus_num(bus); + + if (!ret) { + sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], + mac[1], + mac[2], + mac[3], + mac[4], + mac[5]); + + printf("MAC: %s\n", ethaddr); + setenv(envvar, ethaddr); + } + + return ret; +} + +void mac_read_from_fixed_id(void) +{ +#ifdef CONFIG_SYS_I2C_MAC1_CHIP_ADDR + mac_read_from_generic_eeprom("ethaddr", CONFIG_SYS_I2C_MAC1_CHIP_ADDR, + CONFIG_SYS_I2C_MAC1_DATA_ADDR, CONFIG_SYS_I2C_MAC1_BUS); +#endif +#ifdef CONFIG_SYS_I2C_MAC2_CHIP_ADDR + mac_read_from_generic_eeprom("eth1addr", CONFIG_SYS_I2C_MAC2_CHIP_ADDR, + CONFIG_SYS_I2C_MAC2_DATA_ADDR, CONFIG_SYS_I2C_MAC2_BUS); +#endif +} + +/** + * mac_read_from_eeprom - read the MAC addresses from EEPROM + * + * This function reads the MAC addresses from EEPROM and sets the + * appropriate environment variables for each one read. + * + * The environment variables are only set if they haven't been set already. + * This ensures that any user-saved variables are never overwritten. + * + * This function must be called after relocation. + * + * For NXID v1 EEPROMs, we support loading and up-converting the older NXID v0 + * format. In a v0 EEPROM, there are only eight MAC addresses and the CRC is + * located at a different offset. + */ +int mac_read_from_eeprom_common(void) +{ + unsigned int i; + u32 crc, crc_offset = offsetof(struct eeprom, crc); + u32 *crcp; /* Pointer to the CRC in the data read from the EEPROM */ + + puts("EEPROM: "); + + if (read_eeprom()) { + printf("Read failed.\n"); + return 0; + } + + if (!is_valid) { + printf("Invalid ID (%02x %02x %02x %02x)\n", + e.id[0], e.id[1], e.id[2], e.id[3]); + return 0; + } + + crc = crc32(0, (void *)&e, crc_offset); + crcp = (void *)&e + crc_offset; + if (crc != be32_to_cpu(*crcp)) { + printf("CRC mismatch (%08x != %08x)\n", crc, + be32_to_cpu(e.crc)); + return 0; + } + + /* + * MAC address #9 in v1 occupies the same position as the CRC in v0. + * Erase it so that it's not mistaken for a MAC address. We'll + * update the CRC later. + */ + if (e.version == 0) + memset(e.mac[8], 0xff, 6); + + for (i = 0; i < min(e.mac_count, (u8)MAX_NUM_PORTS); i++) { + if (memcmp(&e.mac[i], "\0\0\0\0\0\0", 6) && + memcmp(&e.mac[i], "\xFF\xFF\xFF\xFF\xFF\xFF", 6)) { + char ethaddr[18]; + char enetvar[9]; + + sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", + e.mac[i][0], + e.mac[i][1], + e.mac[i][2], + e.mac[i][3], + e.mac[i][4], + e.mac[i][5]); + sprintf(enetvar, i ? "eth%daddr" : "ethaddr", i); + /* Only initialize environment variables that are blank + * (i.e. have not yet been set) + */ + if (!getenv(enetvar)) + setenv(enetvar, ethaddr); + } + } + + printf("%c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3], + be32_to_cpu(e.version)); + + return 0; +} diff --git a/board/varisys/cyrus/Kconfig b/board/varisys/cyrus/Kconfig new file mode 100644 index 00000000000..d9ea7ef89c5 --- /dev/null +++ b/board/varisys/cyrus/Kconfig @@ -0,0 +1,12 @@ +if TARGET_CYRUS + +config SYS_BOARD + default "cyrus" + +config SYS_VENDOR + default "varisys" + +config SYS_CONFIG_NAME + default "cyrus" + +endif diff --git a/board/varisys/cyrus/MAINTAINERS b/board/varisys/cyrus/MAINTAINERS new file mode 100644 index 00000000000..53b4a886bd4 --- /dev/null +++ b/board/varisys/cyrus/MAINTAINERS @@ -0,0 +1,7 @@ +Cyrus BOARD +M: Andy Fleming <afleming@gmail.com> +S: Maintained +F: board/varisys/cyrus/ +F: include/configs/cyrus.h +F: configs/Cyrus_P5020_defconfig +F: configs/Cyrus_P5040_defconfig diff --git a/board/varisys/cyrus/Makefile b/board/varisys/cyrus/Makefile new file mode 100644 index 00000000000..303fc422af1 --- /dev/null +++ b/board/varisys/cyrus/Makefile @@ -0,0 +1,8 @@ +# + +obj-y += $(BOARD).o +obj-y += ddr.o +obj-y += law.o +obj-y += tlb.o +obj-y += eth.o +obj-$(CONFIG_PCI) += pci.o diff --git a/board/varisys/cyrus/README b/board/varisys/cyrus/README new file mode 100644 index 00000000000..9595dcb7cc3 --- /dev/null +++ b/board/varisys/cyrus/README @@ -0,0 +1,19 @@ +Rebuilding u-boot for Cyrus + +The Cyrus defconfigs are Cyrus_P5020_defconfig and Cyrus_P5040_defconfig. + +They currently disable size optimization in order to avoid a relocation +bug in some versions of GCC. As the output size is a constant, the size +optimization is not currently important. + +Cyrus boots off a microSD card in a slot on the motherboard. This requires +that the u-boot is built for the Pre-Boot Loader on the P5020/P5040. +In order to reflash u-boot, you must download u-boot.pbl, then write it +onto the card. To do that from u-boot: + +> tftp 1000000 u-boot.pbl +> mmc write 1000000 8 672 + +If you want to do this via a card reader in linux: + +> dd if=u-boot.pbl of=/dev/sdX bs=512 oseek=8 diff --git a/board/varisys/cyrus/cyrus.c b/board/varisys/cyrus/cyrus.c new file mode 100644 index 00000000000..79c363cf841 --- /dev/null +++ b/board/varisys/cyrus/cyrus.c @@ -0,0 +1,116 @@ +/* + * Based on corenet_ds.c + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <netdev.h> +#include <linux/compiler.h> +#include <asm/mmu.h> +#include <asm/processor.h> +#include <asm/cache.h> +#include <asm/immap_85xx.h> +#include <asm/fsl_law.h> +#include <asm/fsl_serdes.h> +#include <asm/fsl_portals.h> +#include <asm/fsl_liodn.h> +#include <fm_eth.h> +#include <pci.h> + +#include "cyrus.h" +#include "../common/eeprom.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define GPIO_OPENDRAIN 0x30000000 +#define GPIO_DIR 0x3c000004 +#define GPIO_INITIAL 0x30000000 +#define GPIO_VGA_SWITCH 0x00001000 + +int checkboard(void) +{ + printf("Board: CYRUS\n"); + + return 0; +} + +int board_early_init_f(void) +{ + ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR); + + /* + * Only use DDR1_MCK0/3 and DDR2_MCK0/3 + * disable DDR1_MCK1/2/4/5 and DDR2_MCK1/2/4/5 to reduce + * the noise introduced by these unterminated and unused clock pairs. + */ + setbits_be32(&gur->ddrclkdr, 0x001B001B); + + /* Set GPIO reset lines to open-drain, tristate */ + setbits_be32(&pgpio->gpdat, GPIO_INITIAL); + setbits_be32(&pgpio->gpodr, GPIO_OPENDRAIN); + + /* Set GPIO Direction */ + setbits_be32(&pgpio->gpdir, GPIO_DIR); + + return 0; +} + +int board_early_init_r(void) +{ + fsl_lbc_t *lbc = LBC_BASE_ADDR; + + out_be32(&lbc->lbcr, 0); + /* 1 clock LALE cycle */ + out_be32(&lbc->lcrr, 0x80000000 | CONFIG_SYS_LBC_LCRR); + + set_liodns(); + +#ifdef CONFIG_SYS_DPAA_QBMAN + setup_portals(); +#endif + print_lbc_regs(); + return 0; +} + +int misc_init_r(void) +{ + return 0; +} + +int ft_board_setup(void *blob, bd_t *bd) +{ + phys_addr_t base; + phys_size_t size; + + ft_cpu_setup(blob, bd); + + base = getenv_bootm_low(); + size = getenv_bootm_size(); + + fdt_fixup_memory(blob, (u64)base, (u64)size); + +#ifdef CONFIG_PCI + pci_of_setup(blob, bd); +#endif + + fdt_fixup_liodn(blob); + fdt_fixup_dr_usb(blob, bd); + +#ifdef CONFIG_SYS_DPAA_FMAN + fdt_fixup_fman_ethernet(blob); +#endif + + return 0; +} + +int mac_read_from_eeprom(void) +{ + init_eeprom(CONFIG_SYS_EEPROM_BUS_NUM, + CONFIG_SYS_I2C_EEPROM_ADDR, + CONFIG_SYS_I2C_EEPROM_ADDR_LEN); + + return mac_read_from_eeprom_common(); +} diff --git a/board/varisys/cyrus/cyrus.h b/board/varisys/cyrus/cyrus.h new file mode 100644 index 00000000000..8cd52ba3c5a --- /dev/null +++ b/board/varisys/cyrus/cyrus.h @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CYRUS_H +#define __CYRUS_H + +void fdt_fixup_board_enet(void *blob); +void pci_of_setup(void *blob, bd_t *bd); + +#endif diff --git a/board/varisys/cyrus/ddr.c b/board/varisys/cyrus/ddr.c new file mode 100644 index 00000000000..bb1d29a94cd --- /dev/null +++ b/board/varisys/cyrus/ddr.c @@ -0,0 +1,188 @@ +/* + * Based on corenet_ds ddr code + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <i2c.h> +#include <hwconfig.h> +#include <asm/mmu.h> +#include <fsl_ddr_sdram.h> +#include <fsl_ddr_dimm_params.h> +#include <asm/fsl_law.h> + +DECLARE_GLOBAL_DATA_PTR; + + +struct board_specific_parameters { + u32 n_ranks; + u32 datarate_mhz_high; + u32 clk_adjust; + u32 wrlvl_start; + u32 cpo; + u32 write_data_delay; + u32 force_2t; +}; + +/* + * This table contains all valid speeds we want to override with board + * specific parameters. datarate_mhz_high values need to be in ascending order + * for each n_ranks group. + */ +static const struct board_specific_parameters udimm0[] = { + /* + * memory controller 0 + * num| hi| clk| wrlvl | cpo |wrdata|2T + * ranks| mhz|adjst| start | |delay | + */ + {4, 850, 4, 6, 0xff, 2, 0}, + {4, 950, 5, 7, 0xff, 2, 0}, + {4, 1050, 5, 8, 0xff, 2, 0}, + {4, 1250, 5, 10, 0xff, 2, 0}, + {4, 1350, 5, 11, 0xff, 2, 0}, + {4, 1666, 5, 12, 0xff, 2, 0}, + {2, 850, 5, 6, 0xff, 2, 0}, + {2, 1050, 5, 7, 0xff, 2, 0}, + {2, 1250, 4, 6, 0xff, 2, 0}, + {2, 1350, 5, 7, 0xff, 2, 0}, + {2, 1666, 5, 8, 0xff, 2, 0}, + {1, 1250, 4, 6, 0xff, 2, 0}, + {1, 1335, 4, 7, 0xff, 2, 0}, + {1, 1666, 4, 8, 0xff, 2, 0}, + {} +}; + +/* + * The two slots have slightly different timing. The center values are good + * for both slots. We use identical speed tables for them. In future use, if + * DIMMs have fewer center values that require two separated tables, copy the + * udimm0 table to udimm1 and make changes to clk_adjust and wrlvl_start. + */ +static const struct board_specific_parameters *udimms[] = { + udimm0, + udimm0, +}; + +static const struct board_specific_parameters rdimm0[] = { + /* + * memory controller 0 + * num| hi| clk| wrlvl | cpo |wrdata|2T + * ranks| mhz|adjst| start | |delay | + */ + {4, 850, 4, 6, 0xff, 2, 0}, + {4, 950, 5, 7, 0xff, 2, 0}, + {4, 1050, 5, 8, 0xff, 2, 0}, + {4, 1250, 5, 10, 0xff, 2, 0}, + {4, 1350, 5, 11, 0xff, 2, 0}, + {4, 1666, 5, 12, 0xff, 2, 0}, + {2, 850, 4, 6, 0xff, 2, 0}, + {2, 1050, 4, 7, 0xff, 2, 0}, + {2, 1666, 4, 8, 0xff, 2, 0}, + {1, 850, 4, 5, 0xff, 2, 0}, + {1, 950, 4, 7, 0xff, 2, 0}, + {1, 1666, 4, 8, 0xff, 2, 0}, + {} +}; + +/* + * The two slots have slightly different timing. See comments above. + */ +static const struct board_specific_parameters *rdimms[] = { + rdimm0, + rdimm0, +}; + +void fsl_ddr_board_options(memctl_options_t *popts, + dimm_params_t *pdimm, + unsigned int ctrl_num) +{ + const struct board_specific_parameters *pbsp, *pbsp_highest = NULL; + ulong ddr_freq; + + if (ctrl_num > 1) { + printf("Wrong parameter for controller number %d", ctrl_num); + return; + } + if (!pdimm->n_ranks) + return; + + if (popts->registered_dimm_en) + pbsp = rdimms[ctrl_num]; + else + pbsp = udimms[ctrl_num]; + + + /* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr + * freqency and n_banks specified in board_specific_parameters table. + */ + ddr_freq = get_ddr_freq(0) / 1000000; + while (pbsp->datarate_mhz_high) { + if (pbsp->n_ranks == pdimm->n_ranks) { + if (ddr_freq <= pbsp->datarate_mhz_high) { + popts->cpo_override = pbsp->cpo; + popts->write_data_delay = + pbsp->write_data_delay; + popts->clk_adjust = pbsp->clk_adjust; + popts->wrlvl_start = pbsp->wrlvl_start; + popts->twot_en = pbsp->force_2t; + goto found; + } + pbsp_highest = pbsp; + } + pbsp++; + } + + if (pbsp_highest) { + printf("Error: board specific timing not found for data rate %lu MT/s!\nTrying to use the highest speed (%u) parameters\n", + ddr_freq, pbsp_highest->datarate_mhz_high); + popts->cpo_override = pbsp_highest->cpo; + popts->write_data_delay = pbsp_highest->write_data_delay; + popts->clk_adjust = pbsp_highest->clk_adjust; + popts->wrlvl_start = pbsp_highest->wrlvl_start; + popts->twot_en = pbsp_highest->force_2t; + } else { + panic("DIMM is not supported by this board"); + } +found: + /* + * Factors to consider for half-strength driver enable: + * - number of DIMMs installed + */ + popts->half_strength_driver_enable = 0; + /* + * Write leveling override + */ + popts->wrlvl_override = 1; + popts->wrlvl_sample = 0xf; + + /* + * Rtt and Rtt_WR override + */ + popts->rtt_override = 0; + + /* Enable ZQ calibration */ + popts->zq_en = 1; + + /* DHC_EN =1, ODT = 60 Ohm */ + popts->ddr_cdr1 = DDR_CDR1_DHC_EN; +} + +phys_size_t initdram(int board_type) +{ + phys_size_t dram_size; + + puts("Initializing...."); + + if (!fsl_use_spd()) + panic("Cyrus only supports using SPD for DRAM\n"); + + puts("using SPD\n"); + dram_size = fsl_ddr_sdram(); + + dram_size = setup_ddr_tlbs(dram_size / 0x100000); + dram_size *= 0x100000; + + debug(" DDR: "); + return dram_size; +} diff --git a/board/varisys/cyrus/eth.c b/board/varisys/cyrus/eth.c new file mode 100644 index 00000000000..bcadc677948 --- /dev/null +++ b/board/varisys/cyrus/eth.c @@ -0,0 +1,100 @@ +/* + * Author Adrian Cox + * Based somewhat on board/freescale/corenet_ds/eth_hydra.c + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <netdev.h> +#include <asm/fsl_serdes.h> +#include <fm_eth.h> +#include <fsl_mdio.h> +#include <malloc.h> +#include <fdt_support.h> +#include <fsl_dtsec.h> + +#ifdef CONFIG_FMAN_ENET + +#define FIRST_PORT_ADDR 3 +#define SECOND_PORT_ADDR 7 + +#ifdef CONFIG_PPC_P5040 +#define FIRST_PORT FM1_DTSEC5 +#define SECOND_PORT FM2_DTSEC5 +#else +#define FIRST_PORT FM1_DTSEC4 +#define SECOND_PORT FM1_DTSEC5 +#endif + +#define IS_VALID_PORT(p) ((p) == FIRST_PORT || (p) == SECOND_PORT) + +static void cyrus_phy_tuning(int phy) +{ + /* + * Enable RGMII delay on Tx and Rx for CPU port + */ + printf("Tuning PHY @ %d\n", phy); + + /* sets address 0x104 or reg 260 for writing */ + miiphy_write(DEFAULT_FM_MDIO_NAME, phy, 0xb, 0x8104); + /* Sets RXC/TXC to +0.96ns and TX_CTL/RX_CTL to -0.84ns */ + miiphy_write(DEFAULT_FM_MDIO_NAME, phy, 0xc, 0xf0f0); + /* sets address 0x105 or reg 261 for writing */ + miiphy_write(DEFAULT_FM_MDIO_NAME, phy, 0xb, 0x8105); + /* writes to address 0x105 , RXD[3..0] to -0. */ + miiphy_write(DEFAULT_FM_MDIO_NAME, phy, 0xc, 0x0000); + /* sets address 0x106 or reg 261 for writing */ + miiphy_write(DEFAULT_FM_MDIO_NAME, phy, 0xb, 0x8106); + /* writes to address 0x106 , TXD[3..0] to -0.84ns */ + miiphy_write(DEFAULT_FM_MDIO_NAME, phy, 0xc, 0x0000); + /* force re-negotiation */ + miiphy_write(DEFAULT_FM_MDIO_NAME, phy, 0x0, 0x1340); +} +#endif + +int board_eth_init(bd_t *bis) +{ +#ifdef CONFIG_FMAN_ENET + struct fsl_pq_mdio_info dtsec_mdio_info; + unsigned int i; + + printf("Initializing Fman\n"); + + + /* Register the real 1G MDIO bus */ + dtsec_mdio_info.regs = + (struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR; + dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME; + + fsl_pq_mdio_init(bis, &dtsec_mdio_info); + + + fm_info_set_phy_address(FIRST_PORT, FIRST_PORT_ADDR); + fm_info_set_mdio(FIRST_PORT, + miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME)); + fm_info_set_phy_address(SECOND_PORT, SECOND_PORT_ADDR); + fm_info_set_mdio(SECOND_PORT, + miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME)); + + /* Never disable DTSEC1 - it controls MDIO */ + for (i = FM1_DTSEC2; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { + if (!IS_VALID_PORT(i)) + fm_disable_port(i); + } + +#ifdef CONFIG_PPC_P5040 + for (i = FM2_DTSEC2; i < FM2_DTSEC1 + CONFIG_SYS_NUM_FM2_DTSEC; i++) { + if (!IS_VALID_PORT(i)) + fm_disable_port(i); + } +#endif + + cpu_eth_init(bis); + + cyrus_phy_tuning(FIRST_PORT_ADDR); + cyrus_phy_tuning(SECOND_PORT_ADDR); +#endif + + return pci_eth_init(bis); +} diff --git a/board/varisys/cyrus/law.c b/board/varisys/cyrus/law.c new file mode 100644 index 00000000000..91e1d852464 --- /dev/null +++ b/board/varisys/cyrus/law.c @@ -0,0 +1,27 @@ +/* + * Author: Adrian Cox + * Based on corenet_ds law files. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/fsl_law.h> +#include <asm/mmu.h> + +struct law_entry law_table[] = { + SET_LAW(CONFIG_SYS_LBC0_BASE_PHYS, LAW_SIZE_64K, LAW_TRGT_IF_LBC), + SET_LAW(CONFIG_SYS_LBC1_BASE_PHYS, LAW_SIZE_4K, LAW_TRGT_IF_LBC), +#ifdef CONFIG_SYS_BMAN_MEM_PHYS + SET_LAW(CONFIG_SYS_BMAN_MEM_PHYS, LAW_SIZE_2M, LAW_TRGT_IF_BMAN), +#endif +#ifdef CONFIG_SYS_QMAN_MEM_PHYS + SET_LAW(CONFIG_SYS_QMAN_MEM_PHYS, LAW_SIZE_2M, LAW_TRGT_IF_QMAN), +#endif +#ifdef CONFIG_SYS_DCSRBAR_PHYS + /* Limit DCSR to 32M to access NPC Trace Buffer */ + SET_LAW(CONFIG_SYS_DCSRBAR_PHYS, LAW_SIZE_32M, LAW_TRGT_IF_DCSR), +#endif +}; + +int num_law_entries = ARRAY_SIZE(law_table); diff --git a/board/varisys/cyrus/pbi.cfg b/board/varisys/cyrus/pbi.cfg new file mode 100644 index 00000000000..9b330ddcc49 --- /dev/null +++ b/board/varisys/cyrus/pbi.cfg @@ -0,0 +1,35 @@ +# +# Copyright 2012 Freescale Semiconductor, Inc. +# +# Refer docs/README.pblimage for more details about how-to configure +# and create PBL boot image +# +# SPDX-License-Identifier: GPL-2.0+ +# + +#PBI commands +#Initialize CPC1 as 1MB SRAM +09010000 00200400 +09138000 00000000 +091380c0 00000100 +09010100 00000000 +09010104 fff0000b +09010f00 08000000 +09010000 80000000 +#Configure LAW for CPC1 +09000d00 00000000 +09000d04 fff00000 +09000d08 81000013 +09000010 00000000 +09000014 ff000000 +09000018 81000000 +#Initialize eSPI controller, default configuration is slow for eSPI to +#load data, this configuration comes from u-boot eSPI driver. +09110000 80000403 +09110020 2d170008 +09110024 00100008 +09110028 00100008 +0911002c 00100008 +#Flush PBL data +09138000 00000000 +091380c0 00000000 diff --git a/board/varisys/cyrus/pci.c b/board/varisys/cyrus/pci.c new file mode 100644 index 00000000000..4780e8c147a --- /dev/null +++ b/board/varisys/cyrus/pci.c @@ -0,0 +1,23 @@ +/* + * Copyright 2007-2011 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <pci.h> +#include <asm/fsl_pci.h> +#include <libfdt.h> +#include <fdt_support.h> +#include <asm/fsl_serdes.h> + +void pci_init_board(void) +{ + fsl_pcie_init_board(0); +} + +void pci_of_setup(void *blob, bd_t *bd) +{ + FT_FSL_PCI_SETUP; +} diff --git a/board/varisys/cyrus/rcw_p5020_v2.cfg b/board/varisys/cyrus/rcw_p5020_v2.cfg new file mode 100644 index 00000000000..9188080605a --- /dev/null +++ b/board/varisys/cyrus/rcw_p5020_v2.cfg @@ -0,0 +1,11 @@ +# +# Default RCW for Cyrus P5020 +# + +#PBL preamble and RCW header +aa55aa55 010e0100 +#64 bytes RCW data +0c540000 00000000 1e1e0000 00000000 +44808c00 ff002000 68000000 45000000 +00000000 00000000 00000000 0003000f +a0000000 00000000 00000000 00000000 diff --git a/board/varisys/cyrus/rcw_p5040.cfg b/board/varisys/cyrus/rcw_p5040.cfg new file mode 100644 index 00000000000..52844815686 --- /dev/null +++ b/board/varisys/cyrus/rcw_p5040.cfg @@ -0,0 +1,11 @@ +# +# Default RCW for Cyrus P5040 +# + +#PBL preamble and RCW header +aa55aa55 010e0100 +#64 bytes RCW data +90e00000 00000000 acac9800 00440000 +44808c00 ff29a000 68000000 61000000 +00000000 00000000 00000000 0003000f +a0000000 00000000 00000000 00000000 diff --git a/board/varisys/cyrus/tlb.c b/board/varisys/cyrus/tlb.c new file mode 100644 index 00000000000..3fa58644bb3 --- /dev/null +++ b/board/varisys/cyrus/tlb.c @@ -0,0 +1,106 @@ +/* + * Author: Adrian Cox + * Based on corenet_ds tlb code + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/mmu.h> + +struct fsl_e_tlb_entry tlb_table[] = { + /* TLB 0 - for temp stack in cache */ + SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR, + CONFIG_SYS_INIT_RAM_ADDR_PHYS, + MAS3_SW|MAS3_SR, 0, + 0, 0, BOOKE_PAGESZ_4K, 0), + SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 4 * 1024, + CONFIG_SYS_INIT_RAM_ADDR_PHYS + 4 * 1024, + MAS3_SW|MAS3_SR, 0, + 0, 0, BOOKE_PAGESZ_4K, 0), + SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 8 * 1024, + CONFIG_SYS_INIT_RAM_ADDR_PHYS + 8 * 1024, + MAS3_SW|MAS3_SR, 0, + 0, 0, BOOKE_PAGESZ_4K, 0), + SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 12 * 1024, + CONFIG_SYS_INIT_RAM_ADDR_PHYS + 12 * 1024, + MAS3_SW|MAS3_SR, 0, + 0, 0, BOOKE_PAGESZ_4K, 0), + + /* TLB 1 */ + /* *I*** - Covers boot page */ +#if defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SYS_INIT_L3_ADDR) + /* + * *I*G - L3SRAM. When L3 is used as 1M SRAM, the address of the + * SRAM is at 0xfff00000, it covered the 0xfffff000. + */ + SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L3_ADDR, CONFIG_SYS_INIT_L3_ADDR, + MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 0, BOOKE_PAGESZ_1M, 1), +#else + SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000, + MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 0, BOOKE_PAGESZ_4K, 1), +#endif + + /* *I*G* - CCSRBAR */ + SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS, + MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 1, BOOKE_PAGESZ_16M, 1), + + /* Local Bus */ + SET_TLB_ENTRY(1, CONFIG_SYS_LBC0_BASE, CONFIG_SYS_LBC0_BASE_PHYS, + MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 2, BOOKE_PAGESZ_64K, 1), + SET_TLB_ENTRY(1, CONFIG_SYS_LBC1_BASE, CONFIG_SYS_LBC1_BASE_PHYS, + MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 3, BOOKE_PAGESZ_4K, 1), + + /* *I*G* - PCI */ + SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT, CONFIG_SYS_PCIE1_MEM_PHYS, + MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 4, BOOKE_PAGESZ_1G, 1), + + /* *I*G* - PCI */ + SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT + 0x40000000, + CONFIG_SYS_PCIE1_MEM_PHYS + 0x40000000, + MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 5, BOOKE_PAGESZ_256M, 1), + + SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT + 0x50000000, + CONFIG_SYS_PCIE1_MEM_PHYS + 0x50000000, + MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 6, BOOKE_PAGESZ_256M, 1), + + /* *I*G* - PCI I/O */ + SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_IO_VIRT, CONFIG_SYS_PCIE1_IO_PHYS, + MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 7, BOOKE_PAGESZ_256K, 1), + + /* Bman/Qman */ +#ifdef CONFIG_SYS_BMAN_MEM_PHYS + SET_TLB_ENTRY(1, CONFIG_SYS_BMAN_MEM_BASE, CONFIG_SYS_BMAN_MEM_PHYS, + MAS3_SW|MAS3_SR, 0, + 0, 9, BOOKE_PAGESZ_1M, 1), + SET_TLB_ENTRY(1, CONFIG_SYS_BMAN_MEM_BASE + 0x00100000, + CONFIG_SYS_BMAN_MEM_PHYS + 0x00100000, + MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 10, BOOKE_PAGESZ_1M, 1), +#endif +#ifdef CONFIG_SYS_QMAN_MEM_PHYS + SET_TLB_ENTRY(1, CONFIG_SYS_QMAN_MEM_BASE, CONFIG_SYS_QMAN_MEM_PHYS, + MAS3_SW|MAS3_SR, 0, + 0, 11, BOOKE_PAGESZ_1M, 1), + SET_TLB_ENTRY(1, CONFIG_SYS_QMAN_MEM_BASE + 0x00100000, + CONFIG_SYS_QMAN_MEM_PHYS + 0x00100000, + MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 12, BOOKE_PAGESZ_1M, 1), +#endif +#ifdef CONFIG_SYS_DCSRBAR_PHYS + SET_TLB_ENTRY(1, CONFIG_SYS_DCSRBAR, CONFIG_SYS_DCSRBAR_PHYS, + MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, + 0, 13, BOOKE_PAGESZ_4M, 1), +#endif +}; + +int num_tlb_entries = ARRAY_SIZE(tlb_table); |