From dd21f09669ee65500f1f9bce5c4024cf817f3c79 Mon Sep 17 00:00:00 2001 From: Rainer Boschung Date: Mon, 27 Jan 2014 11:49:04 +0100 Subject: kmp204x: support for QRIO1 bootcounter Make use of the QRIO1 32bit register at 0x20 as bootcounter register Check for BOOTCOUNT_MAGIC pattern when before bootcounter value is read Signed-off-by: Rainer Boschung Signed-off-by: Valentin Longchamp [York Sun: Minor change to commit message] Signed-off-by: York Sun --- board/keymile/kmp204x/kmp204x.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'board/keymile') diff --git a/board/keymile/kmp204x/kmp204x.c b/board/keymile/kmp204x/kmp204x.c index f02642aece..20a32642bb 100644 --- a/board/keymile/kmp204x/kmp204x.c +++ b/board/keymile/kmp204x/kmp204x.c @@ -133,26 +133,6 @@ void qrio_prstcfg(u8 bit, u8 mode) out_be32(qrio_base + PRSTCFG_OFF, prstcfg); } - -#define BOOTCOUNT_OFF 0x12 - -void bootcount_store(ulong counter) -{ - u8 val; - void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; - - val = (counter <= 255) ? (u8)counter : 255; - out_8(qrio_base + BOOTCOUNT_OFF, val); -} - -ulong bootcount_load(void) -{ - u8 val; - void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; - val = in_8(qrio_base + BOOTCOUNT_OFF); - return val; -} - #define NUM_SRDS_BANKS 2 #define PHY_RST 15 -- cgit From 87ea2c0ff345ad59280bdf4702c3450a81e3c265 Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Mon, 27 Jan 2014 11:49:05 +0100 Subject: kmp204x: introduce QRIO GPIO functions The QRIO GPIO functions can be of general interest. They are thus added to a qrio.c and their prototype are available from kmp204x.h. The QRIO prst function are also included in this file, as well as the functions required for the I2C deblocking support (open-drain). Signed-off-by: Valentin Longchamp [York Sun: Remove extra blank line in board/keymile/kmp204x/qrio.c] Signed-off-by: York Sun --- board/keymile/kmp204x/Makefile | 2 +- board/keymile/kmp204x/kmp204x.c | 56 --------------- board/keymile/kmp204x/kmp204x.h | 10 +++ board/keymile/kmp204x/qrio.c | 146 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 157 insertions(+), 57 deletions(-) create mode 100644 board/keymile/kmp204x/qrio.c (limited to 'board/keymile') diff --git a/board/keymile/kmp204x/Makefile b/board/keymile/kmp204x/Makefile index 3e69ee2f15..c57ca08e14 100644 --- a/board/keymile/kmp204x/Makefile +++ b/board/keymile/kmp204x/Makefile @@ -8,5 +8,5 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y := kmp204x.o ddr.o eth.o tlb.o pci.o law.o \ +obj-y := kmp204x.o ddr.o eth.o tlb.o pci.o law.o qrio.o \ ../common/common.o ../common/ivm.o diff --git a/board/keymile/kmp204x/kmp204x.c b/board/keymile/kmp204x/kmp204x.c index 20a32642bb..bbb2453155 100644 --- a/board/keymile/kmp204x/kmp204x.c +++ b/board/keymile/kmp204x/kmp204x.c @@ -77,62 +77,6 @@ unsigned long get_board_sys_clk(unsigned long dummy) return 66666666; } -#define WDMASK_OFF 0x16 - -static void qrio_wdmask(u8 bit, bool wden) -{ - u16 wdmask; - void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; - - wdmask = in_be16(qrio_base + WDMASK_OFF); - - if (wden) - wdmask |= (1 << bit); - else - wdmask &= ~(1 << bit); - - out_be16(qrio_base + WDMASK_OFF, wdmask); -} - -#define PRST_OFF 0x1a - -void qrio_prst(u8 bit, bool en, bool wden) -{ - u16 prst; - void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; - - qrio_wdmask(bit, wden); - - prst = in_be16(qrio_base + PRST_OFF); - - if (en) - prst &= ~(1 << bit); - else - prst |= (1 << bit); - - out_be16(qrio_base + PRST_OFF, prst); -} - -#define PRSTCFG_OFF 0x1c - -void qrio_prstcfg(u8 bit, u8 mode) -{ - u32 prstcfg; - u8 i; - void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; - - prstcfg = in_be32(qrio_base + PRSTCFG_OFF); - - for (i = 0; i < 2; i++) { - if (mode & (1< + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +#include "../common/common.h" +#include "kmp204x.h" + +/* QRIO GPIO register offsets */ +#define DIRECT_OFF 0x18 +#define GPRT_OFF 0x1c + +int qrio_get_gpio(u8 port_off, u8 gpio_nr) +{ + u32 gprt; + + void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; + + gprt = in_be32(qrio_base + port_off + GPRT_OFF); + + return (gprt >> gpio_nr) & 1U; +} + +void qrio_set_gpio(u8 port_off, u8 gpio_nr, bool value) +{ + u32 gprt, mask; + + void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; + + mask = 1U << gpio_nr; + + gprt = in_be32(qrio_base + port_off + GPRT_OFF); + if (value) + gprt |= mask; + else + gprt &= ~mask; + + out_be32(qrio_base + port_off + GPRT_OFF, gprt); +} + +void qrio_gpio_direction_output(u8 port_off, u8 gpio_nr, bool value) +{ + u32 direct, mask; + + void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; + + mask = 1U << gpio_nr; + + direct = in_be32(qrio_base + port_off + DIRECT_OFF); + direct |= mask; + out_be32(qrio_base + port_off + DIRECT_OFF, direct); + + qrio_set_gpio(port_off, gpio_nr, value); +} + +void qrio_gpio_direction_input(u8 port_off, u8 gpio_nr) +{ + u32 direct, mask; + + void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; + + mask = 1U << gpio_nr; + + direct = in_be32(qrio_base + port_off + DIRECT_OFF); + direct &= ~mask; + out_be32(qrio_base + port_off + DIRECT_OFF, direct); +} + +void qrio_set_opendrain_gpio(u8 port_off, u8 gpio_nr, u8 val) +{ + u32 direct, mask; + + void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; + + mask = 1U << gpio_nr; + + direct = in_be32(qrio_base + port_off + DIRECT_OFF); + if (val == 0) + /* set to output -> GPIO drives low */ + direct |= mask; + else + /* set to input -> GPIO floating */ + direct &= ~mask; + + out_be32(qrio_base + port_off + DIRECT_OFF, direct); +} + +#define WDMASK_OFF 0x16 + +static void qrio_wdmask(u8 bit, bool wden) +{ + u16 wdmask; + void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; + + wdmask = in_be16(qrio_base + WDMASK_OFF); + + if (wden) + wdmask |= (1 << bit); + else + wdmask &= ~(1 << bit); + + out_be16(qrio_base + WDMASK_OFF, wdmask); +} + +#define PRST_OFF 0x1a + +void qrio_prst(u8 bit, bool en, bool wden) +{ + u16 prst; + void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; + + qrio_wdmask(bit, wden); + + prst = in_be16(qrio_base + PRST_OFF); + + if (en) + prst &= ~(1 << bit); + else + prst |= (1 << bit); + + out_be16(qrio_base + PRST_OFF, prst); +} + +#define PRSTCFG_OFF 0x1c + +void qrio_prstcfg(u8 bit, u8 mode) +{ + u32 prstcfg; + u8 i; + void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; + + prstcfg = in_be32(qrio_base + PRSTCFG_OFF); + + for (i = 0; i < 2; i++) { + if (mode & (1< Date: Mon, 3 Feb 2014 08:45:40 +0100 Subject: kmp204x: I2C deblocking support This patch adds support for using some GPIOs that are connected to the I2C bus to force the bus lines state and perform some bus deblocking sequences. The KM common deblocking algorithm from board/keymile/common/common.c is used. The GPIO lines used for deblocking the I2C bus are some external GPIOs provided by the QRIO CPLD: - SCL = GPIOA_20 - SDA = GPIOA_21 The QRIO GPIOs act in an open-drain-like manner, for 0 the line is driven low and for 1 the GPIO is set as input and the line gets pulled-up. Signed-off-by: Rainer Boschung Signed-off-by: Valentin Longchamp Reviewed-by: York Sun --- board/keymile/kmp204x/kmp204x.c | 53 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) (limited to 'board/keymile') diff --git a/board/keymile/kmp204x/kmp204x.c b/board/keymile/kmp204x/kmp204x.c index bbb2453155..a6c23a2c35 100644 --- a/board/keymile/kmp204x/kmp204x.c +++ b/board/keymile/kmp204x/kmp204x.c @@ -33,12 +33,51 @@ int checkboard(void) return 0; } -/* TODO: implement the I2C deblocking function */ -int i2c_make_abort(void) +/* I2C deblocking uses the algorithm defined in board/keymile/common/common.c + * 2 dedicated QRIO GPIOs externally pull the SCL and SDA lines + * For I2C only the low state is activly driven and high state is pulled-up + * by a resistor. Therefore the deblock GPIOs are used + * -> as an active output to drive a low state + * -> as an open-drain input to have a pulled-up high state + */ + +/* QRIO GPIOs used for deblocking */ +#define DEBLOCK_PORT1 GPIO_A +#define DEBLOCK_SCL1 20 +#define DEBLOCK_SDA1 21 + +/* By default deblock GPIOs are floating */ +static void i2c_deblock_gpio_cfg(void) +{ + /* set I2C bus 1 deblocking GPIOs input, but 0 value for open drain */ + qrio_gpio_direction_input(DEBLOCK_PORT1, DEBLOCK_SCL1); + qrio_gpio_direction_input(DEBLOCK_PORT1, DEBLOCK_SDA1); + + qrio_set_gpio(DEBLOCK_PORT1, DEBLOCK_SCL1, 0); + qrio_set_gpio(DEBLOCK_PORT1, DEBLOCK_SDA1, 0); +} + +void set_sda(int state) +{ + qrio_set_opendrain_gpio(DEBLOCK_PORT1, DEBLOCK_SDA1, state); +} + +void set_scl(int state) +{ + qrio_set_opendrain_gpio(DEBLOCK_PORT1, DEBLOCK_SCL1, state); +} + +int get_sda(void) +{ + return qrio_get_gpio(DEBLOCK_PORT1, DEBLOCK_SDA1); +} + +int get_scl(void) { - return 1; + return qrio_get_gpio(DEBLOCK_PORT1, DEBLOCK_SCL1); } + #define ZL30158_RST 8 #define ZL30343_RST 9 @@ -77,6 +116,14 @@ unsigned long get_board_sys_clk(unsigned long dummy) return 66666666; } +int misc_init_f(void) +{ + /* configure QRIO pis for i2c deblocking */ + i2c_deblock_gpio_cfg(); + + return 0; +} + #define NUM_SRDS_BANKS 2 #define PHY_RST 15 -- cgit From fabb9297fa6bf88f44c36225c57b7779fc51f737 Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Mon, 27 Jan 2014 11:49:07 +0100 Subject: kmp204x: implement workaround for A-006559 According to the errata, some bits of an undocumented register in the DCSR must be set for every core in order to avoid a possible data or instruction corruption. This is required for the 2.0 revision of the P2041 that should be used as soon as available in our design. Signed-off-by: Valentin Longchamp Reviewed-by: York Sun --- board/keymile/kmp204x/pbi.cfg | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'board/keymile') diff --git a/board/keymile/kmp204x/pbi.cfg b/board/keymile/kmp204x/pbi.cfg index f38dcf9c8c..9af8bd5b57 100644 --- a/board/keymile/kmp204x/pbi.cfg +++ b/board/keymile/kmp204x/pbi.cfg @@ -8,6 +8,16 @@ # #PBI commands +#Workaround for A-006559 needed for rev 2.0 of P2041 silicon +#Freescale's errarta sheet suggests it may be done with PBI +09000010 00000000 +09000014 00000000 +09000018 81d00000 +09021008 0000f000 +09021028 0000f000 +09021048 0000f000 +09021068 0000f000 +09000018 00000000 #Initialize CPC1 as 1MB SRAM 09010000 00200400 09138000 00000000 -- cgit From 1f07a71b965d751864dd1064d6c848500d30a090 Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Mon, 27 Jan 2014 11:49:09 +0100 Subject: kmp204x: update I2C field of RCW On the previous HW revision (now unsupported), there was a need for external DMA signals and thus the I2C3/4 signals were used DMA1_DONE/ACK/REQ. These signals now are configured as GPIO[16:19]. Signed-off-by: Valentin Longchamp Reviewed-by: York Sun --- board/keymile/kmp204x/rcw_kmp204x.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'board/keymile') diff --git a/board/keymile/kmp204x/rcw_kmp204x.cfg b/board/keymile/kmp204x/rcw_kmp204x.cfg index f2b7fe3d42..2d4c48cb9c 100644 --- a/board/keymile/kmp204x/rcw_kmp204x.cfg +++ b/board/keymile/kmp204x/rcw_kmp204x.cfg @@ -7,5 +7,5 @@ aa55aa55 010e0100 #64 bytes RCW data 14600000 00000000 28200000 00000000 148E70CF CFC02000 58000000 41000000 -00000000 00000000 00000000 F4428002 +00000000 00000000 00000000 F0428002 00000000 00000000 00000000 00000000 -- cgit From 27c78e06f2b42bd6285ed104ece23f6c69e42e6f Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Mon, 27 Jan 2014 11:49:12 +0100 Subject: kmp204x: initial support for PCIe FPGA configuration The PEXHC PCIe configuration mechanism ensures that the FPGA get configured at power-up. Since all the PCIe devices should be configured when the kernel start, u-boot has to take care that the FPGA gets configured also in other reset scenarios, mostly because of possible configuration change. The used mechanism is taken from the km_kirkwood design and adapted to the kmp204x case (slightly different HW and PCIe configuration). Signed-off-by: Valentin Longchamp Reviewed-by: York Sun --- board/keymile/kmp204x/kmp204x.c | 7 +++- board/keymile/kmp204x/pci.c | 85 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) (limited to 'board/keymile') diff --git a/board/keymile/kmp204x/kmp204x.c b/board/keymile/kmp204x/kmp204x.c index a6c23a2c35..95a19cdb2c 100644 --- a/board/keymile/kmp204x/kmp204x.c +++ b/board/keymile/kmp204x/kmp204x.c @@ -101,6 +101,7 @@ int board_early_init_f(void) int board_early_init_r(void) { + int ret = 0; /* Flush d-cache and invalidate i-cache of any FLASH data */ flush_dcache(); invalidate_icache(); @@ -108,7 +109,11 @@ int board_early_init_r(void) set_liodns(); setup_portals(); - return 0; + ret = trigger_fpga_config(); + if (ret) + printf("error triggering PCIe FPGA config\n"); + + return ret; } unsigned long get_board_sys_clk(unsigned long dummy) diff --git a/board/keymile/kmp204x/pci.c b/board/keymile/kmp204x/pci.c index ec20c8afb4..a484eb5749 100644 --- a/board/keymile/kmp204x/pci.c +++ b/board/keymile/kmp204x/pci.c @@ -14,18 +14,103 @@ #include #include #include +#include #include "kmp204x.h" +#define PROM_SEL_L 11 +/* control the PROM_SEL_L signal*/ +static void toggle_fpga_eeprom_bus(bool cpu_own) +{ + qrio_gpio_direction_output(GPIO_A, PROM_SEL_L, !cpu_own); +} + +#define CONF_SEL_L 10 +#define FPGA_PROG_L 19 +#define FPGA_DONE 18 +#define FPGA_INIT_L 17 + +int trigger_fpga_config(void) +{ + int ret = 0, init_l; + /* approx 10ms */ + u32 timeout = 10000; + + /* make sure the FPGA_can access the EEPROM */ + toggle_fpga_eeprom_bus(false); + + /* assert CONF_SEL_L to be able to drive FPGA_PROG_L */ + qrio_gpio_direction_output(GPIO_A, CONF_SEL_L, 0); + + /* trigger the config start */ + qrio_gpio_direction_output(GPIO_A, FPGA_PROG_L, 0); + + /* small delay for INIT_L line */ + udelay(10); + + /* wait for FPGA_INIT to be asserted */ + do { + init_l = qrio_get_gpio(GPIO_A, FPGA_INIT_L); + if (timeout-- == 0) { + printf("FPGA_INIT timeout\n"); + ret = -EFAULT; + break; + } + udelay(10); + } while (init_l); + + /* deassert FPGA_PROG, config should start */ + qrio_set_gpio(GPIO_A, FPGA_PROG_L, 1); + + return ret; +} + +/* poll the FPGA_DONE signal and give the EEPROM back to the QorIQ */ +static int wait_for_fpga_config(void) +{ + int ret = 0, done; + /* approx 5 s */ + u32 timeout = 500000; + + printf("PCIe FPGA config:"); + do { + done = qrio_get_gpio(GPIO_A, FPGA_DONE); + if (timeout-- == 0) { + printf(" FPGA_DONE timeout\n"); + ret = -EFAULT; + goto err_out; + } + udelay(10); + } while (!done); + + printf(" done\n"); + +err_out: + /* deactive CONF_SEL and give the CPU conf EEPROM access */ + qrio_set_gpio(GPIO_A, CONF_SEL_L, 1); + toggle_fpga_eeprom_bus(true); + + return ret; +} + #define PCIE_SW_RST 14 +#define PEXHC_SW_RST 13 #define HOOPER_SW_RST 12 void pci_init_board(void) { + /* first wait for the PCIe FPGA to be configured + * it has been triggered earlier in board_early_init_r */ + int ret = wait_for_fpga_config(); + if (ret) + printf("error finishing PCIe FPGA config\n"); + qrio_prst(PCIE_SW_RST, false, false); + qrio_prst(PEXHC_SW_RST, false, false); qrio_prst(HOOPER_SW_RST, false, false); /* Hooper is not direcly PCIe capable */ mdelay(50); + fsl_pcie_init_board(0); } -- cgit