[PATCH v2 00/11] Misc fixes + 8xx CPM relocation

This series adds misc fixes for cssi boards and activates CPM relocation in order to enable the use of SCC4 in QMC (QUICC Multi-Channel) mode.
Changes in v2: - Patch 5: Update r1 at once (From Joakim) - Patch 6: New to avoid sparse warnings with memcpy_toio() - Patch 7 and 8: Fixed sparse warnings
Christophe Leroy (11): board: cssi: Remove duplicated FPGA loading sequence on CMPC885 board: cssi: Remove stale macro from cmpcpro.c board: cssi: Load CMPC885's motherboard FPGA earlier powerpc: mpc8xx: CPM parameter RAM can be anywhere powerpc: mpc8xx: Reorganise init RAM powerpc: Force cast on memcpy_toio() powerpc: mpc885: Add CPM USB-SOF microcode for CPM15 ERRATA powerpc: mpc8xx: Add SMC relocation CPM microcode spi, mpc8xx: Take parameter RAM relocation into account serial, mpc8xx: Take parameter RAM relocation into account board: cssi: Activate SMC relocation on CMPC885 board for MIAE device
arch/powerpc/cpu/mpc8xx/Kconfig | 45 ++++++++ arch/powerpc/cpu/mpc8xx/Makefile | 2 + arch/powerpc/cpu/mpc8xx/cpu.c | 2 +- arch/powerpc/cpu/mpc8xx/micropatch_smc.c | 105 +++++++++++++++++++ arch/powerpc/cpu/mpc8xx/micropatch_usb_sof.c | 38 +++++++ arch/powerpc/cpu/mpc8xx/start.S | 8 +- arch/powerpc/include/asm/cpm_8xx.h | 41 +++++--- arch/powerpc/include/asm/immap_8xx.h | 8 +- arch/powerpc/include/asm/io.h | 6 +- board/cssi/cmpc885/cmpc885.c | 43 ++------ board/cssi/cmpcpro/cmpcpro.c | 5 - configs/CMPC885_defconfig | 3 +- drivers/serial/serial_mpc8xx.c | 24 ++--- drivers/spi/mpc8xx_spi.c | 8 +- include/configs/cmpc885.h | 1 + include/configs/mcr3000.h | 1 + 16 files changed, 254 insertions(+), 86 deletions(-) create mode 100644 arch/powerpc/cpu/mpc8xx/micropatch_smc.c create mode 100644 arch/powerpc/cpu/mpc8xx/micropatch_usb_sof.c

A duplicated FPGA loading sequence appears after FPGA reset.
Remove it.
Fixes: dac3c6f625 ("board: cssi: Add new board MCR3000_2G") Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- board/cssi/cmpc885/cmpc885.c | 14 -------------- 1 file changed, 14 deletions(-)
diff --git a/board/cssi/cmpc885/cmpc885.c b/board/cssi/cmpc885/cmpc885.c index 540b9d3c78..02da4d9a87 100644 --- a/board/cssi/cmpc885/cmpc885.c +++ b/board/cssi/cmpc885/cmpc885.c @@ -896,20 +896,6 @@ int board_early_init_r(void) } }
- /* is FPGA firmware loaded ? */ - if (!(in_be32(&cp->cp_pedat) & 0x00000001)) { - printf("Reloading FPGA firmware\n"); - - /* Load FPGA firmware */ - /* Activate PROG_FPGA_FIRMWARE for 1 usec */ - clrbits_be32(&cp->cp_pedat, 0x00000002); - udelay(1); - setbits_be32(&cp->cp_pedat, 0x00000002); - - /* Wait 200ms before checking DONE_FPGA_FIRMWARE */ - mdelay(200); - } - iop_setup_common(); } else { iop_setup_cmpc885();

Three unused macros were left over. Remove them.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- board/cssi/cmpcpro/cmpcpro.c | 5 ----- 1 file changed, 5 deletions(-)
diff --git a/board/cssi/cmpcpro/cmpcpro.c b/board/cssi/cmpcpro/cmpcpro.c index 3e9ba6a4cc..8a30c48e35 100644 --- a/board/cssi/cmpcpro/cmpcpro.c +++ b/board/cssi/cmpcpro/cmpcpro.c @@ -397,8 +397,3 @@ void ft_board_setup_phy3(void)
setbits_be32(&immr->qepio.ioport[2].pdat, 0x00000400); } - -#define ADDR_FPGA_R_BASE ((unsigned char __iomem *)CONFIG_FPGA_BASE) -#define ADDR_FPGA_R_ALARMES_IN ((unsigned char __iomem *)CONFIG_FPGA_BASE + 0x31) -#define ADDR_FPGA_R_FAV ((unsigned char __iomem *)CONFIG_FPGA_BASE + 0x44) -

In order to know the motherboard type earlier, perform I/O ports initialisation and FPGA loading in board_early_init_f() instead of board_early_init_r().
This is needed to be able to load mpc8xx CPM microcode base on motherboard type and before starting to use the CPM.
Console is not available yet so remove the printfs.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- board/cssi/cmpc885/cmpc885.c | 25 +++++-------------------- configs/CMPC885_defconfig | 1 - 2 files changed, 5 insertions(+), 21 deletions(-)
diff --git a/board/cssi/cmpc885/cmpc885.c b/board/cssi/cmpc885/cmpc885.c index 02da4d9a87..40128f170a 100644 --- a/board/cssi/cmpc885/cmpc885.c +++ b/board/cssi/cmpc885/cmpc885.c @@ -586,13 +586,8 @@ void iop_setup_miae(void) setbits_be32(&cp->cp_peso, 0x00031980); }
-int board_early_init_f(void) -{ - return 0; -} - /* Specific board initialization */ -int board_early_init_r(void) +int board_early_init_f(void) { immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; iop8xx_t __iomem *iop = &immr->im_ioport; @@ -864,8 +859,6 @@ int board_early_init_r(void)
/* Check if fpga firmware is loaded */ if (!(in_be32(&cp->cp_pedat) & 0x00000001)) { - printf("Reloading FPGA firmware.\n"); - /* Load fpga firmware */ /* Activate PROG_FPGA_FIRMWARE for 1 usec */ clrbits_be32(&cp->cp_pedat, 0x00000002); @@ -874,12 +867,8 @@ int board_early_init_r(void)
/* Wait 200 msec and check DONE_FPGA_FIRMWARE */ mdelay(200); - if (!(in_be32(&cp->cp_pedat) & 0x00000001)) { - for (;;) { - printf("error loading firmware.\n"); - mdelay(500); - } - } + if (!(in_be32(&cp->cp_pedat) & 0x00000001)) + hang();
/* Send a reset signal and wait for 20 msec */ clrbits_be16(ADDR_CPLD_R_RESET, R_RST_STATUS); @@ -889,12 +878,8 @@ int board_early_init_r(void)
/* Wait 300 msec and check the reset state */ mdelay(300); - if (!(in_be16(ADDR_CPLD_R_RESET) & R_RESET_STATUS)) { - for (;;) { - printf("Could not reset FPGA.\n"); - mdelay(500); - } - } + if (!(in_be16(ADDR_CPLD_R_RESET) & R_RESET_STATUS)) + hang();
iop_setup_common(); } else { diff --git a/configs/CMPC885_defconfig b/configs/CMPC885_defconfig index 0a24684389..ca5dfd2b83 100644 --- a/configs/CMPC885_defconfig +++ b/configs/CMPC885_defconfig @@ -31,7 +31,6 @@ CONFIG_AUTOBOOT_STOP_STR_ENABLE=y CONFIG_AUTOBOOT_STOP_STR_SHA256="4813494d137e1631bba301d5acab6e7bb7aa74ce1185d456565ef51d737677b2" CONFIG_USE_BOOTCOMMAND=y CONFIG_BOOTCOMMAND="run flashboot" -CONFIG_BOARD_EARLY_INIT_R=y CONFIG_MISC_INIT_R=y CONFIG_HUSH_PARSER=y # CONFIG_CMD_BDI is not set

With relocation, CPM parameter RAM can be anywhere in the dual port RAM, so don't split dual port RAM.
Remove dparam and dparam16 members of struct comm_proc
PROFF_XXX become offsets from the start of dual port RAM, then they are now consistant with the offsets in RPBASE registers.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- arch/powerpc/cpu/mpc8xx/cpu.c | 2 +- arch/powerpc/include/asm/cpm_8xx.h | 18 +++++++++--------- arch/powerpc/include/asm/immap_8xx.h | 8 +------- drivers/serial/serial_mpc8xx.c | 2 +- drivers/spi/mpc8xx_spi.c | 2 +- 5 files changed, 13 insertions(+), 19 deletions(-)
diff --git a/arch/powerpc/cpu/mpc8xx/cpu.c b/arch/powerpc/cpu/mpc8xx/cpu.c index 9b587fbbe8..56383cecde 100644 --- a/arch/powerpc/cpu/mpc8xx/cpu.c +++ b/arch/powerpc/cpu/mpc8xx/cpu.c @@ -127,7 +127,7 @@ static int check_CPU(long clock, uint pvr, uint immr) return -1;
k = (immr << 16) | - in_be16(&immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)]); + in_be16((u16 __iomem *)&immap->im_cpm.cp_dpmem[PROFF_REVNUM]);
/* * Some boards use sockets so different CPUs can be used. diff --git a/arch/powerpc/include/asm/cpm_8xx.h b/arch/powerpc/include/asm/cpm_8xx.h index 85903d2108..09c24efd91 100644 --- a/arch/powerpc/include/asm/cpm_8xx.h +++ b/arch/powerpc/include/asm/cpm_8xx.h @@ -92,15 +92,15 @@ typedef struct cpm_buf_desc {
/* Parameter RAM offsets. */ -#define PROFF_SCC1 ((uint)0x0000) -#define PROFF_IIC ((uint)0x0080) -#define PROFF_REVNUM ((uint)0x00b0) -#define PROFF_SCC2 ((uint)0x0100) -#define PROFF_SPI ((uint)0x0180) -#define PROFF_SCC3 ((uint)0x0200) -#define PROFF_SMC1 ((uint)0x0280) -#define PROFF_SCC4 ((uint)0x0300) -#define PROFF_SMC2 ((uint)0x0380) +#define PROFF_SCC1 ((uint)0x1c00) +#define PROFF_IIC ((uint)0x1c80) +#define PROFF_REVNUM ((uint)0x1cb0) +#define PROFF_SCC2 ((uint)0x1d00) +#define PROFF_SPI ((uint)0x1d80) +#define PROFF_SCC3 ((uint)0x1e00) +#define PROFF_SMC1 ((uint)0x1e80) +#define PROFF_SCC4 ((uint)0x1f00) +#define PROFF_SMC2 ((uint)0x1f80)
/* Define enough so I can at least use the serial port as a UART. */ diff --git a/arch/powerpc/include/asm/immap_8xx.h b/arch/powerpc/include/asm/immap_8xx.h index 3999a02b9c..cf1300f6e2 100644 --- a/arch/powerpc/include/asm/immap_8xx.h +++ b/arch/powerpc/include/asm/immap_8xx.h @@ -437,13 +437,7 @@ typedef struct comm_proc { * depending upon the devices used and options chosen. * Some processors don't have all of it populated. */ - u_char cp_dpmem[0x1C00]; /* BD / Data / ucode */ - - /* Parameter RAM */ - union { - u_char cp_dparam[0x400]; - u16 cp_dparam16[0x200]; - }; + u_char cp_dpmem[0x2000]; /* BD / Data / ucode / Param RAM */ } cpm8xx_t;
/* Internal memory map. diff --git a/drivers/serial/serial_mpc8xx.c b/drivers/serial/serial_mpc8xx.c index b8d6a81b65..beffc34d11 100644 --- a/drivers/serial/serial_mpc8xx.c +++ b/drivers/serial/serial_mpc8xx.c @@ -89,7 +89,7 @@ static int serial_mpc8xx_probe(struct udevice *dev) /* initialize pointers to SMC */
sp = cp->cp_smc + SMC_INDEX; - up = (smc_uart_t __iomem *)&cp->cp_dparam[PROFF_SMC]; + up = (smc_uart_t __iomem *)&cp->cp_dpmem[PROFF_SMC]; /* Disable relocation */ out_be16(&up->smc_rpbase, 0);
diff --git a/drivers/spi/mpc8xx_spi.c b/drivers/spi/mpc8xx_spi.c index d84d7aea88..734b0751a9 100644 --- a/drivers/spi/mpc8xx_spi.c +++ b/drivers/spi/mpc8xx_spi.c @@ -51,7 +51,7 @@ static int mpc8xx_spi_probe(struct udevice *dev) { immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; cpm8xx_t __iomem *cp = &immr->im_cpm; - spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dparam[PROFF_SPI]; + spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dpmem[PROFF_SPI]; cbd_t __iomem *tbdf, *rbdf;
/* Disable relocation */

Using SMC relocation microcode patch or USB-SOF microcode patch will disable DPRAM memory from 0x2000 to 0x2400 and from 0x2f00 to 0x3000.
At the time being, init RAM is setup to use 0x2800-0x2e00, but the stack pointer goes beyond 0x2800 and even beyond 0x2400.
For the time being we are not going to use any microcode patch that uses memory about 0x3000, so reorganise setup to use: - 0x2800 - 0x2e00 for init malloc and global data and CPM buffers - 0x3000 - 0x3c00 for init stack
For more details about CPM dual port ram, see commit b1d62424cb ("powerpc: mpc8xx: redistribute data in CPM dpram")
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- arch/powerpc/cpu/mpc8xx/start.S | 8 +++++--- arch/powerpc/include/asm/cpm_8xx.h | 16 ++++++++-------- include/configs/cmpc885.h | 1 + include/configs/mcr3000.h | 1 + 4 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/arch/powerpc/cpu/mpc8xx/start.S b/arch/powerpc/cpu/mpc8xx/start.S index 0aa73fca12..78429515ae 100644 --- a/arch/powerpc/cpu/mpc8xx/start.S +++ b/arch/powerpc/cpu/mpc8xx/start.S @@ -141,14 +141,16 @@ in_flash: mtspr DER, r2
/* set up the stack on top of internal DPRAM */ - lis r3, (CFG_SYS_INIT_RAM_ADDR + CFG_SYS_INIT_RAM_SIZE)@h - ori r3, r3, (CFG_SYS_INIT_RAM_ADDR + CFG_SYS_INIT_RAM_SIZE)@l + lis r3, CFG_SYS_INIT_SP@h + ori r3, r3, CFG_SYS_INIT_SP@l stw r0, -4(r3) stw r0, -8(r3) addi r1, r3, -8
+ lis r3, (CFG_SYS_INIT_RAM_ADDR + CFG_SYS_INIT_RAM_SIZE)@h + ori r3, r3, (CFG_SYS_INIT_RAM_ADDR + CFG_SYS_INIT_RAM_SIZE)@l + bl board_init_f_alloc_reserve - addi r1, r3, -8
/* Zeroise the CPM dpram */ lis r4, CONFIG_SYS_IMMR@h diff --git a/arch/powerpc/include/asm/cpm_8xx.h b/arch/powerpc/include/asm/cpm_8xx.h index 09c24efd91..77ffcce5a6 100644 --- a/arch/powerpc/include/asm/cpm_8xx.h +++ b/arch/powerpc/include/asm/cpm_8xx.h @@ -51,14 +51,14 @@ /* * DPRAM defines and allocation functions */ -#define CPM_SERIAL_BASE 0x1800 -#define CPM_I2C_BASE 0x1820 -#define CPM_SPI_BASE 0x1840 -#define CPM_FEC_BASE 0x1860 -#define CPM_SERIAL2_BASE 0x18e0 -#define CPM_SCC_BASE 0x1900 -#define CPM_POST_BASE 0x1980 -#define CPM_WLKBD_BASE 0x1a00 +#define CPM_SERIAL_BASE 0x0800 +#define CPM_I2C_BASE 0x0820 +#define CPM_SPI_BASE 0x0840 +#define CPM_FEC_BASE 0x0860 +#define CPM_SERIAL2_BASE 0x08E0 +#define CPM_SCC_BASE 0x0900 +#define CPM_POST_BASE 0x0980 +#define CPM_WLKBD_BASE 0x0a00
#define BD_IIC_START ((uint) 0x0400) /* <- please use CPM_I2C_BASE !! */
diff --git a/include/configs/cmpc885.h b/include/configs/cmpc885.h index b76230e9a4..545365e112 100644 --- a/include/configs/cmpc885.h +++ b/include/configs/cmpc885.h @@ -9,6 +9,7 @@ /* Definitions for initial stack pointer and data area (in DPRAM) */ #define CFG_SYS_INIT_RAM_ADDR (CONFIG_SYS_IMMR + 0x2800) #define CFG_SYS_INIT_RAM_SIZE (0x2e00 - 0x2800) +#define CFG_SYS_INIT_SP (CONFIG_SYS_IMMR + 0x3c00)
/* RAM configuration (note that CFG_SYS_SDRAM_BASE must be zero) */ #define CFG_SYS_SDRAM_BASE 0x00000000 diff --git a/include/configs/mcr3000.h b/include/configs/mcr3000.h index 6b16b050ff..a07761fdbb 100644 --- a/include/configs/mcr3000.h +++ b/include/configs/mcr3000.h @@ -14,6 +14,7 @@ /* Definitions for initial stack pointer and data area (in DPRAM) */ #define CFG_SYS_INIT_RAM_ADDR (CONFIG_SYS_IMMR + 0x2800) #define CFG_SYS_INIT_RAM_SIZE (0x2e00 - 0x2800) +#define CFG_SYS_INIT_SP (CONFIG_SYS_IMMR + 0x3c00)
/* RAM configuration (note that CFG_SYS_SDRAM_BASE must be zero) */ #define CFG_SYS_SDRAM_BASE 0x00000000

sparse reports the following warning:
CHECK arch/powerpc/cpu/mpc8xx/micropatch_usb_sof.c arch/powerpc/cpu/mpc8xx/micropatch_usb_sof.c:29:9: warning: cast removes address space 'asn:2' of expression arch/powerpc/cpu/mpc8xx/micropatch_usb_sof.c:30:9: warning: cast removes address space 'asn:2' of expression
This is because of (void *) casts for using memcpy() as a substitute.
Do like other architectures, __force the cast to silence the warning
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- arch/powerpc/include/asm/io.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h index 998a82aa0d..f63cae0bc8 100644 --- a/arch/powerpc/include/asm/io.h +++ b/arch/powerpc/include/asm/io.h @@ -95,9 +95,9 @@ extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
#define IO_SPACE_LIMIT ~0
-#define memset_io(a,b,c) memset((void *)(a),(b),(c)) -#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) -#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) +#define memset_io(a,b,c) memset((void __force *)(a),(b),(c)) +#define memcpy_fromio(a,b,c) memcpy((a),(void __force *)(b),(c)) +#define memcpy_toio(a,b,c) memcpy((void __force *)(a),(b),(c))
/* * Enforce In-order Execution of I/O:

MPC885 CPU has the following ERRATA:
When the USB controller is configured in Host mode, and the SOF generation (SFTE=1 in USMOD register) is being used, there may be false CRC error indication in other SCCs. Although the data is received correctly, the CRC result will be corrupted.
Add capability to load the related microcode to fix it. The microcode binary data is copied from Linux kernel.
Other microcode will be added in following patch so make it a Kconfig choice.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- arch/powerpc/cpu/mpc8xx/Kconfig | 25 +++++++++++++ arch/powerpc/cpu/mpc8xx/Makefile | 1 + arch/powerpc/cpu/mpc8xx/micropatch_usb_sof.c | 38 ++++++++++++++++++++ arch/powerpc/include/asm/cpm_8xx.h | 7 ++++ 4 files changed, 71 insertions(+) create mode 100644 arch/powerpc/cpu/mpc8xx/micropatch_usb_sof.c
diff --git a/arch/powerpc/cpu/mpc8xx/Kconfig b/arch/powerpc/cpu/mpc8xx/Kconfig index bfd903bc10..52caf06aac 100644 --- a/arch/powerpc/cpu/mpc8xx/Kconfig +++ b/arch/powerpc/cpu/mpc8xx/Kconfig @@ -30,6 +30,31 @@ config MPC885
endchoice
+choice + prompt "Microcode patch selection" + default NO_UCODE_PATCH + help + This allows loading of CPM microcode. + + Only one microcode can be loaded at a time. + +config NO_UCODE_PATCH + bool "None" + +config USB_SOF_UCODE_PATCH + bool "USB SOF patch" + depends on MPC885 + help + This microcode fixes CPM15 errata: + + When the USB controller is configured in Host mode, and the + SOF generation (SFTE=1 in USMOD register) is being used, + there may be false CRC error indication in other SCCs. + Although the data is received correctly, the CRC result + will be corrupted. + +endchoice + comment "Specific commands"
config CMD_IMMAP diff --git a/arch/powerpc/cpu/mpc8xx/Makefile b/arch/powerpc/cpu/mpc8xx/Makefile index 8918a26288..5a6561e024 100644 --- a/arch/powerpc/cpu/mpc8xx/Makefile +++ b/arch/powerpc/cpu/mpc8xx/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_CMD_IMMAP) += immap.o obj-y += interrupts.o obj-y += speed.o obj-y += cache.o +obj-$(CONFIG_USB_SOF_UCODE_PATCH) += micropatch_usb_sof.o diff --git a/arch/powerpc/cpu/mpc8xx/micropatch_usb_sof.c b/arch/powerpc/cpu/mpc8xx/micropatch_usb_sof.c new file mode 100644 index 0000000000..7fc640df90 --- /dev/null +++ b/arch/powerpc/cpu/mpc8xx/micropatch_usb_sof.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Microcode patches for the CPM as supplied by Motorola. + */ + +#include <linux/string.h> +#include <linux/io.h> +#include <asm/immap_8xx.h> +#include <asm/cpm_8xx.h> + +/* + * USB SOF patch arrays. + */ +static uint patch_2000[] = { + 0x7fff0000, 0x7ffd0000, 0x7ffb0000, 0x49f7ba5b, + 0xba383ffb, 0xf9b8b46d, 0xe5ab4e07, 0xaf77bffe, + 0x3f7bbf79, 0xba5bba38, 0xe7676076, 0x60750000 +}; + +static uint patch_2f00[] = { + 0x3030304c, 0xcab9e441, 0xa1aaf220 +}; + +void cpm_load_patch(cpm8xx_t __iomem *cp) +{ + out_be16(&cp->cp_rccr, 0); + + memcpy_toio(cp->cp_dpmem, patch_2000, sizeof(patch_2000)); + memcpy_toio(cp->cp_dpmem + 0xf00, patch_2f00, sizeof(patch_2f00)); + + out_be16(&cp->cp_cpmcr1, 0); + out_be16(&cp->cp_cpmcr2, 0); + out_be16(&cp->cp_cpmcr3, 0); + out_be16(&cp->cp_cpmcr4, 0); + + out_be16(&cp->cp_rccr, 9); +} diff --git a/arch/powerpc/include/asm/cpm_8xx.h b/arch/powerpc/include/asm/cpm_8xx.h index 77ffcce5a6..98476cdf30 100644 --- a/arch/powerpc/include/asm/cpm_8xx.h +++ b/arch/powerpc/include/asm/cpm_8xx.h @@ -684,4 +684,11 @@ void irq_install_handler(int vec, void (*handler)(void *), void *dev_id); #define CICR_HP_MASK ((uint)0x00001f00) /* Hi-pri int. */ #define CICR_IEN ((uint)0x00000080) /* Int. enable */ #define CICR_SPS ((uint)0x00000001) /* SCC Spread */ + +#ifdef CONFIG_NO_UCODE_PATCH +static inline void cpm_load_patch(cpm8xx_t __iomem *cp) { } +#else +void cpm_load_patch(cpm8xx_t __iomem *cp); +#endif + #endif /* __CPM_8XX__ */

In order to use QMC mode in the CPM, a SCC requires more space in parameter RAM.
After SCC1 there is I2C parameter RAM and after SCC2 there is SPI parameter RAM. MPC866 and MPC885 can already relocate I2C and. SPI parameter RAM.
But in order to free space after SCC3 and SCC4, SMC1 and SMC2 need to be relocated. In order to do so, a CPM microcode patch is required.
Binary data for that patch is copied from Linux kernel.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- arch/powerpc/cpu/mpc8xx/Kconfig | 20 +++++ arch/powerpc/cpu/mpc8xx/Makefile | 1 + arch/powerpc/cpu/mpc8xx/micropatch_smc.c | 105 +++++++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 arch/powerpc/cpu/mpc8xx/micropatch_smc.c
diff --git a/arch/powerpc/cpu/mpc8xx/Kconfig b/arch/powerpc/cpu/mpc8xx/Kconfig index 52caf06aac..bd2af8dc10 100644 --- a/arch/powerpc/cpu/mpc8xx/Kconfig +++ b/arch/powerpc/cpu/mpc8xx/Kconfig @@ -53,6 +53,26 @@ config USB_SOF_UCODE_PATCH Although the data is received correctly, the CRC result will be corrupted.
+config SMC_UCODE_PATCH + bool "SMC relocation patch" + help + This microcode relocates SMC1 and SMC2 parameter RAMs to allow + extended parameter RAM for SCC3 and SCC4 (ex: for QMC mode) + +config SMC1_RPBASE + hex "SMC1 relocation offset" + depends on SMC_UCODE_PATCH + default 0x1e80 + help + Offset of SMC1 parameter RAM to be written to RPBASE register. + +config SMC2_RPBASE + hex "SMC2 relocation offset" + depends on SMC_UCODE_PATCH + default 0x1f80 + help + Offset of SMC2 parameter RAM to be written to RPBASE register. + endchoice
comment "Specific commands" diff --git a/arch/powerpc/cpu/mpc8xx/Makefile b/arch/powerpc/cpu/mpc8xx/Makefile index 5a6561e024..28a21eeb76 100644 --- a/arch/powerpc/cpu/mpc8xx/Makefile +++ b/arch/powerpc/cpu/mpc8xx/Makefile @@ -13,3 +13,4 @@ obj-y += interrupts.o obj-y += speed.o obj-y += cache.o obj-$(CONFIG_USB_SOF_UCODE_PATCH) += micropatch_usb_sof.o +obj-$(CONFIG_SMC_UCODE_PATCH) += micropatch_smc.o diff --git a/arch/powerpc/cpu/mpc8xx/micropatch_smc.c b/arch/powerpc/cpu/mpc8xx/micropatch_smc.c new file mode 100644 index 0000000000..89406797cc --- /dev/null +++ b/arch/powerpc/cpu/mpc8xx/micropatch_smc.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Microcode patches for the CPM as supplied by Motorola. + */ + +#include <linux/string.h> +#include <linux/io.h> +#include <asm/immap_8xx.h> +#include <asm/cpm_8xx.h> + +static uint patch_2000[] = { + 0x3fff0000, 0x3ffd0000, 0x3ffb0000, 0x3ff90000, + 0x5fefeff8, 0x5f91eff8, 0x3ff30000, 0x3ff10000, + 0x3a11e710, 0xedf0ccb9, 0xf318ed66, 0x7f0e5fe2, + 0x7fedbb38, 0x3afe7468, 0x7fedf4d8, 0x8ffbb92d, + 0xb83b77fd, 0xb0bb5eb9, 0xdfda7fed, 0x90bde74d, + 0x6f0dcbd3, 0xe7decfed, 0xcb50cfed, 0xcfeddf6d, + 0x914d4f74, 0x5eaedfcb, 0x9ee0e7df, 0xefbb6ffb, + 0xe7ef7f0e, 0x9ee57fed, 0xebb7effa, 0xeb30affb, + 0x7fea90b3, 0x7e0cf09f, 0xbffff318, 0x5fffdfff, + 0xac35efea, 0x7fce1fc1, 0xe2ff5fbd, 0xaffbe2ff, + 0x5fbfaffb, 0xf9a87d0f, 0xaef8770f, 0x7d0fb0a2, + 0xeffbbfff, 0xcfef5fba, 0x7d0fbfff, 0x5fba4cf8, + 0x7fddd09b, 0x49f847fd, 0x7efdf097, 0x7fedfffd, + 0x7dfdf093, 0xef7e7e1e, 0x5fba7f0e, 0x3a11e710, + 0xedf0cc87, 0xfb18ad0a, 0x1f85bbb8, 0x74283b7e, + 0x7375e4bb, 0x2ab64fb8, 0x5c7de4bb, 0x32fdffbf, + 0x5f0843f8, 0x7ce3e1bb, 0xe74f7ded, 0x6f0f4fe8, + 0xc7ba32be, 0x73f2efeb, 0x600b4f78, 0xe5bb760b, + 0x5388aef8, 0x4ef80b6a, 0xcfef9ee5, 0xabf8751f, + 0xefef5b88, 0x741f4fe8, 0x751e760d, 0x7fdb70dd, + 0x741cafce, 0xefcc7fce, 0x751e7088, 0x741ce7bb, + 0x334ecfed, 0xafdbefeb, 0xe5bb760b, 0x53ceaef8, + 0xafe8e7eb, 0x4bf8771e, 0x7e007fed, 0x4fcbe2cc, + 0x7fbc3085, 0x7b0f7a0f, 0x34b177fd, 0xb0e75e93, + 0xdf313e3b, 0xaf78741f, 0x741f30cc, 0xcfef5f08, + 0x741f3e88, 0xafb8771e, 0x5f437fed, 0x0bafe2cc, + 0x741ccfec, 0xe5ca53a9, 0x6fcb4f74, 0x5e89df27, + 0x2a923d14, 0x4b8fdf0c, 0x751f741c, 0x6c1eeffa, + 0xefea7fce, 0x6ffc309a, 0xefec3fca, 0x308fdf0a, + 0xadf85e7a, 0xaf7daefd, 0x5e7adf0a, 0x5e7aafdd, + 0x761f1088, 0x1e7c7efd, 0x3089fffe, 0x4908fb18, + 0x5fffdfff, 0xafbbf0f7, 0x4ef85f43, 0xadf81489, + 0x7a0f7089, 0xcfef5089, 0x7a0fdf0c, 0x5e7cafed, + 0xbc6e780f, 0xefef780f, 0xefef790f, 0xa7f85eeb, + 0xffef790f, 0xefef790f, 0x1489df0a, 0x5e7aadfd, + 0x5f09fffb, 0xe79aded9, 0xeff96079, 0x607ae79a, + 0xded8eff9, 0x60795edb, 0x607acfef, 0xefefefdf, + 0xefbfef7f, 0xeeffedff, 0xebffe7ff, 0xafefafdf, + 0xafbfaf7f, 0xaeffadff, 0xabffa7ff, 0x6fef6fdf, + 0x6fbf6f7f, 0x6eff6dff, 0x6bff67ff, 0x2fef2fdf, + 0x2fbf2f7f, 0x2eff2dff, 0x2bff27ff, 0x4e08fd1f, + 0xe5ff6e0f, 0xaff87eef, 0x7e0ffdef, 0xf11f6079, + 0xabf8f51e, 0x7e0af11c, 0x37cfae16, 0x7fec909a, + 0xadf8efdc, 0xcfeae52f, 0x7d0fe12b, 0xf11c6079, + 0x7e0a4df8, 0xcfea5ea0, 0x7d0befec, 0xcfea5ea2, + 0xe522efdc, 0x5ea2cfda, 0x4e08fd1f, 0x6e0faff8, + 0x7c1f761f, 0xfdeff91f, 0x6079abf8, 0x761cee00, + 0xf91f2bfb, 0xefefcfec, 0xf91f6079, 0x761c27fb, + 0xefdf5e83, 0xcfdc7fdd, 0x50f84bf8, 0x47fd7c1f, + 0x761ccfcf, 0x7eef7fed, 0x7dfd70ef, 0xef7e7f1e, + 0x771efb18, 0x6079e722, 0xe6bbe5bb, 0x2e66e5bb, + 0x600b2ee1, 0xe2bbe2bb, 0xe2bbe2bb, 0x2f5ee2bb, + 0xe2bb2ff9, 0x6079e2bb, +}; + +static uint patch_2f00[] = { + 0x30303030, 0x3e3e3030, 0xaf79b9b3, 0xbaa3b979, + 0x9693369f, 0x79f79777, 0x97333fff, 0xfb3b9e9f, + 0x79b91d11, 0x9e13f3ff, 0x3f9b6bd9, 0xe173d136, + 0x695669d1, 0x697b3daf, 0x79b93a3a, 0x3f979f91, + 0x379ff976, 0xf99777fd, 0x9779737d, 0xe9d6bbf9, + 0xbfffd9df, 0x97f7fd97, 0x6f7b9bff, 0xf9bd9683, + 0x397db973, 0xd97b3b9f, 0xd7f9f733, 0x9993bb9e, + 0xe1f9ef93, 0x73773337, 0xb936917d, 0x11f87379, + 0xb979d336, 0x8b7ded73, 0x1b7d9337, 0x31f3f22f, + 0x3f2327ee, 0xeeeeeeee, 0xeeeeeeee, 0xeeeeeeee, + 0xeeeeee4b, 0xf4fbdbd2, 0x58bb1878, 0x577fdfd2, + 0xd573b773, 0xf7374b4f, 0xbdbd25b8, 0xb177d2d1, + 0x7376856b, 0xbfdd687b, 0xdd2fff8f, 0x78ffff8f, + 0xf22f0000, +}; + +void cpm_load_patch(cpm8xx_t __iomem *cp) +{ + smc_uart_t __iomem *smp; + + out_be16(&cp->cp_rccr, 0); + + memcpy_toio(cp->cp_dpmem, patch_2000, sizeof(patch_2000)); + memcpy_toio(cp->cp_dpmem + 0xf00, patch_2f00, sizeof(patch_2f00)); + + smp = (smc_uart_t __iomem *)&cp->cp_dpmem[PROFF_SMC1]; + out_be16(&smp->smc_rpbase, CONFIG_SMC1_RPBASE); + smp = (smc_uart_t __iomem *)&cp->cp_dpmem[PROFF_SMC2]; + out_be16(&smp->smc_rpbase, CONFIG_SMC2_RPBASE); + + out_be16(&cp->cp_cpmcr1, 0x8080); + out_be16(&cp->cp_cpmcr2, 0x8088); + out_be16(&cp->cp_cpmcr3, 0); + out_be16(&cp->cp_cpmcr4, 0); + + out_be16(&cp->cp_rccr, 2); +}

Instead of inhibiting parameter RAM relocation, take it into account.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- drivers/spi/mpc8xx_spi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/mpc8xx_spi.c b/drivers/spi/mpc8xx_spi.c index 734b0751a9..5c8d760935 100644 --- a/drivers/spi/mpc8xx_spi.c +++ b/drivers/spi/mpc8xx_spi.c @@ -52,10 +52,12 @@ static int mpc8xx_spi_probe(struct udevice *dev) immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; cpm8xx_t __iomem *cp = &immr->im_cpm; spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dpmem[PROFF_SPI]; + u16 spi_rpbase; cbd_t __iomem *tbdf, *rbdf;
- /* Disable relocation */ - out_be16(&spi->spi_rpbase, 0x1d80); + spi_rpbase = in_be16(&spi->spi_rpbase); + if (spi_rpbase) + spi = (spi_t __iomem *)&cp->cp_dpmem[spi_rpbase];
/* 1 */ /* Initialize the parameter ram.

Instead of inhibiting parameter RAM relacation, take into account the configured one.
It means INIT_TRX command cannot be used and must be done manually as explained in the microcode patch application note.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- drivers/serial/serial_mpc8xx.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/serial/serial_mpc8xx.c b/drivers/serial/serial_mpc8xx.c index beffc34d11..d82760c7f1 100644 --- a/drivers/serial/serial_mpc8xx.c +++ b/drivers/serial/serial_mpc8xx.c @@ -83,6 +83,7 @@ static int serial_mpc8xx_probe(struct udevice *dev) immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR; smc_t __iomem *sp; smc_uart_t __iomem *up; + u16 smc_rpbase; cpm8xx_t __iomem *cp = &(im->im_cpm); struct serialbuffer __iomem *rtx;
@@ -90,8 +91,10 @@ static int serial_mpc8xx_probe(struct udevice *dev)
sp = cp->cp_smc + SMC_INDEX; up = (smc_uart_t __iomem *)&cp->cp_dpmem[PROFF_SMC]; - /* Disable relocation */ - out_be16(&up->smc_rpbase, 0); + + smc_rpbase = in_be16(&up->smc_rpbase); + if (smc_rpbase) + up = (smc_uart_t __iomem *)&cp->cp_dpmem[smc_rpbase];
/* Disable transmitter/receiver. */ clrbits_be16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN); @@ -154,15 +157,12 @@ static int serial_mpc8xx_probe(struct udevice *dev) out_be16(&up->smc_maxidl, CONFIG_SYS_MAXIDLE); out_be32(&rtx->rxindex, 0);
- /* Initialize Tx/Rx parameters. */ - while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) /* wait if cp is busy */ - ; - - out_be16(&cp->cp_cpcr, - mk_cr_cmd(CPM_CR_CH_SMC, CPM_CR_INIT_TRX) | CPM_CR_FLG); - - while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) /* wait if cp is busy */ - ; + out_be32(&up->smc_rstate, 0); + out_be32(&up->smc_tstate, 0); + out_be16(&up->smc_rbptr, CPM_SERIAL_BASE); + out_be16(&up->smc_tbptr, CPM_SERIAL_BASE + sizeof(cbd_t)); + out_be16(&up->smc_brkcr, 1); + out_be16(&up->smc_brkec, 0);
/* Enable transmitter/receiver. */ setbits_be16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN);

When CMPC885 board is used for MIAE device, SCC2 SCC3 and SMC2 are used for serial lines. Therefore only SCC4 is available for handling the TDM line.
In order to use SCC4 in QMC mode without loosing SMC2, SMC2 must be relocated.
Activate SMC relocation and relocate SMC2 at offset 0x1fc0 which is unused.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- board/cssi/cmpc885/cmpc885.c | 4 ++++ configs/CMPC885_defconfig | 2 ++ 2 files changed, 6 insertions(+)
diff --git a/board/cssi/cmpc885/cmpc885.c b/board/cssi/cmpc885/cmpc885.c index 40128f170a..5e6aa8b8cf 100644 --- a/board/cssi/cmpc885/cmpc885.c +++ b/board/cssi/cmpc885/cmpc885.c @@ -11,6 +11,7 @@ #include <env.h> #include <common.h> #include <mpc8xx.h> +#include <asm/cpm_8xx.h> #include <asm/io.h> #include <dm.h> #include <stdio.h> @@ -451,6 +452,9 @@ void iop_setup_miae(void) /* Wait reset on FPGA_F */ udelay(100);
+ /* Load CPM relocation code */ + cpm_load_patch(cp); + /* Set the front panel LED color to red */ clrbits_8((unsigned char __iomem *)CONFIG_FPGA_BASE + 0x44, 0x02);
diff --git a/configs/CMPC885_defconfig b/configs/CMPC885_defconfig index ca5dfd2b83..f55af97f08 100644 --- a/configs/CMPC885_defconfig +++ b/configs/CMPC885_defconfig @@ -10,6 +10,8 @@ CONFIG_MPC8xx=y # CONFIG_PCI is not set CONFIG_TARGET_CMPC885=y CONFIG_MPC885=y +CONFIG_SMC_UCODE_PATCH=y +CONFIG_SMC2_RPBASE=0x1fc0 CONFIG_CMD_IMMAP=y CONFIG_SYS_SIUMCR=0x00620000 CONFIG_SYS_TBSCR=0x00C3
participants (2)
-
Christophe Leroy
-
Joakim Tjernlund