[PATCH v2 00/17] Misc changes for CSSI boards

This series contains misc fixes and changes for CSSI boards.
Main changes are: - Fix and optimise mpc8xx SPI driver - Add support for LM74 temperature sensor - Add support for loading FPGA on MCR3000
I will send a pull request later before close of the merge window.
Changes since v1: - Added temperature and FPGA support and SPI driver optimisation
Christophe Leroy (13): board: cssi: Fix SPI nodes in DTS spi: mpc8xx: Add GPIO dependency spi: mpc8xx: Fix transfert when input or output buffer is NULL thermal: Add support for TI LM74 board: cssi: Add support for SPI bus on MCR3000 board board: cssi: add support for reading temperature powerpc: 8xx: Set SDMA configuration register correcly spi: mpc8xx: Allow transfer of more than MAX_BUFFER len spi: mpc8xx: Use 16 bit mode for large transfers with even size spi: mpc8xx: Set up speed as requested board: cssi: Use HAVE_VENDOR_COMMON_LIB logic board: cssi: Load FPGA on MCR3000 board board: cssi: Read and display MCR board address
Hugo Dubois (2): board: cssi: Initialise port F on MIAE board: cssi: Properly initialise MAC address for fibre on CMPC885 board
Jean-Michel CASAUBON (2): board: cssi: Fix MCR3000 board environment board: cssi: Allow use without HUSH shell
arch/powerpc/cpu/mpc8xx/cpu_init.c | 6 ++ arch/powerpc/dts/cmpc885.dts | 18 ++++- arch/powerpc/dts/cmpcpro.dts | 16 +++- arch/powerpc/dts/mcr3000.dts | 41 +++++++++++ board/cssi/cmpc885/Makefile | 2 +- board/cssi/cmpc885/cmpc885.c | 4 +- board/cssi/cmpc885/cmpc885.env | 4 +- board/cssi/cmpcpro/Makefile | 2 +- board/cssi/cmpcpro/cmpcpro.env | 4 +- board/cssi/common/Makefile | 8 ++ board/cssi/common/common.c | 42 ++++++++++- board/cssi/mcr3000/Makefile | 1 + board/cssi/mcr3000/fpga_code.h | 10 +++ board/cssi/mcr3000/mcr3000.c | 58 +++++++++++++++ board/cssi/mcr3000/mcr3000.env | 2 +- board/cssi/mcr3000/mcr3000_gpio.c | 109 ++++++++++++++++++++++++++++ configs/CMPC885_defconfig | 3 + configs/CMPCPRO_defconfig | 3 + configs/MCR3000_defconfig | 8 ++ drivers/spi/Kconfig | 2 +- drivers/spi/mpc8xx_spi.c | 113 ++++++++++++++++++++++++----- drivers/thermal/Kconfig | 6 ++ drivers/thermal/Makefile | 1 + drivers/thermal/ti-lm74.c | 52 +++++++++++++ 24 files changed, 476 insertions(+), 39 deletions(-) create mode 100644 board/cssi/common/Makefile create mode 100644 board/cssi/mcr3000/fpga_code.h create mode 100644 board/cssi/mcr3000/mcr3000_gpio.c create mode 100644 drivers/thermal/ti-lm74.c

From: Jean-Michel CASAUBON jean-michel.casaubon@csgroup.eu
Remove a stray semicolon in MCR3000 board environment.
Signed-off-by: Jean-Michel CASAUBON jean-michel.casaubon@csgroup.eu Reviewed-by: DUBOIS Hugo hugo.dubois.ext@csgroup.eu Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- board/cssi/mcr3000/mcr3000.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/board/cssi/mcr3000/mcr3000.env b/board/cssi/mcr3000/mcr3000.env index 372ab09094..380c10c4ce 100644 --- a/board/cssi/mcr3000/mcr3000.env +++ b/board/cssi/mcr3000/mcr3000.env @@ -8,7 +8,7 @@ dhcp_ip=ip=:::::eth0:dhcp console_args=console=ttyCPM0,115200N8 loadkernel=ubi part nand0;ubifsmount ubi0;ubifsload ${loadaddr} /boot/${filename};ubifsumount; ubi detach bootcmd=run flashboot -flashboot=setenv bootargs ${console_args} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:mcr3k:eth0:off;${ofl_args}; run loadkernel; bootm ${loadaddr} +flashboot=setenv bootargs ${console_args} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:mcr3k:eth0:off ${ofl_args}; run loadkernel; bootm ${loadaddr} tftpboot=setenv bootargs ${console_args} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:mcr3k:eth0:off ${ofl_args}; tftp ${loadaddr} ${filename}; bootm ${loadaddr} dhcpboot=dhcp ${loadaddr} ${filename};setenv bootargs ${console_args} ${dhcp_ip} ${ofl_args}; bootm ${loadaddr} update=echo 'Updating ubi image'; if tftp 0x2000 $ubifile; then nand erase.chip; nand write 0x2000 0x00 $filesize; fi

When adding additional SPI peripherals, the reg property needs to be added, and this leads to the following error:
arch/powerpc/dts/cmpc885.dtb: Warning (reg_format): /immr@ff000000/spi@aa0/temp@1:reg: property has invalid length (4 bytes) (#address-cells == 1, #size-cells == 1) arch/powerpc/dts/cmpc885.dtb: Warning (reg_format): /immr@ff000000/spi@aa0/temp@2:reg: property has invalid length (4 bytes) (#address-cells == 1, #size-cells == 1)
Fix it by removing cell-index and cell-size which is unused and add reg property. Also fix node name to be in line with reg value. Also add missing compatible for eeprom node.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- arch/powerpc/dts/cmpc885.dts | 6 +++--- arch/powerpc/dts/cmpcpro.dts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/dts/cmpc885.dts b/arch/powerpc/dts/cmpc885.dts index 7b9566a0fa..9a33e7e77c 100644 --- a/arch/powerpc/dts/cmpc885.dts +++ b/arch/powerpc/dts/cmpc885.dts @@ -83,13 +83,13 @@ spi: spi@aa0 { status = "okay"; #address-cells = <1>; - #size-cells = <1>; - cell-index = <0>; + #size-cells = <0>; compatible = "fsl,mpc8xx-spi"; gpios = <&CPM1_PIO_B 21 1>; /* /EEPROM_CS ACTIVE_LOW */
eeprom@0 { - cell-index = <1>; + reg = <0>; + compatible = "atmel,at25", "cs,eeprom"; }; }; }; diff --git a/arch/powerpc/dts/cmpcpro.dts b/arch/powerpc/dts/cmpcpro.dts index c27d9dba33..78f8a9f4d3 100644 --- a/arch/powerpc/dts/cmpcpro.dts +++ b/arch/powerpc/dts/cmpcpro.dts @@ -142,9 +142,9 @@ mode = "cpu"; gpios = <&qe_pio_d 3 1>; clock-frequency = <0>; - eeprom@3 { + eeprom@0 { + reg = <0>; compatible = "atmel,at25", "cs,eeprom"; - cell-index = <1>; }; }; eth0: ucc@3000 {

From: Jean-Michel CASAUBON jean-michel.casaubon@csgroup.eu
HUSH shell is not always wanted/desirable.
Add missing braces in environment in order to allow use without HUSH shell.
Signed-off-by: Jean-Michel CASAUBON jean-michel.casaubon@csgroup.eu Cc: DUBOIS Hugo hugo.dubois.ext@csgroup.eu Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- board/cssi/cmpc885/cmpc885.env | 4 ++-- board/cssi/cmpcpro/cmpcpro.env | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/board/cssi/cmpc885/cmpc885.env b/board/cssi/cmpc885/cmpc885.env index 51ab5ce2cf..570117cd36 100644 --- a/board/cssi/cmpc885/cmpc885.env +++ b/board/cssi/cmpc885/cmpc885.env @@ -2,6 +2,6 @@ loadaddr=0x1a00000 filename=cmpc885.itb console_args=console=ttyCPM0,115200N8 loadkernel=ubi part nand0;ubifsmount ubi0;ubifsload ${loadaddr} /boot/${filename};ubifsumount; ubi detach -flashboot=setenv bootargs ${console_args} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0:off ${ofl_args}; run loadkernel; bootm $loadaddr#$config -tftpboot=setenv bootargs ${console_args} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0:off ${ofl_args}; tftp ${loadaddr} ${filename};bootm $loadaddr#$config +flashboot=setenv bootargs ${console_args} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0:off ${ofl_args}; run loadkernel; bootm ${loadaddr}#${config} +tftpboot=setenv bootargs ${console_args} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0:off ${ofl_args}; tftp ${loadaddr} ${filename};bootm ${loadaddr}#${config} update=echo 'Updating ubi image'; if tftp $loadaddr $ubifile; then nand erase.chip; nand write $loadaddr 0x00 $filesize; fi; diff --git a/board/cssi/cmpcpro/cmpcpro.env b/board/cssi/cmpcpro/cmpcpro.env index 7394b8386e..47b436ff6b 100644 --- a/board/cssi/cmpcpro/cmpcpro.env +++ b/board/cssi/cmpcpro/cmpcpro.env @@ -3,6 +3,6 @@ filename=cmpcpro.itb netdev=eth0 console_args=console=ttyS0,115200N8 loadkernel=ubi part nand0;ubifsmount ubi0; ubifsload ${loadaddr} /boot/${filename}; ubifsumount; ubi detach -flashboot=mw.w 90000040 0x000E 1; setenv bootargs ${console_args} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0:off ${ofl_args}; run loadkernel; bootm $loadaddr#$config -tftpboot=mw.w 90000040 0x000E 1; setenv bootargs ${console_args} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0:off ${ofl_args}; tftp ${loadaddr} ${filename}; bootm $loadaddr#$config +flashboot=mw.w 90000040 0x000E 1; setenv bootargs ${console_args} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0:off ${ofl_args}; run loadkernel; bootm ${loadaddr}#${config} +tftpboot=mw.w 90000040 0x000E 1; setenv bootargs ${console_args} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0:off ${ofl_args}; tftp ${loadaddr} ${filename}; bootm ${loadaddr}#${config} update=echo 'Updating ubi image'; mw.w 90000040 0x000E 1; if tftp $loadaddr $ubifile; then nand erase.chip; nand write $loadaddr 0x00 $filesize; fi;

From: Hugo Dubois hugo.dubois.ext@csgroup.eu
When equipped with the SRSA audio board, MIAE equipment has an additional port called port F.
Initialise that port just like other ports of the board, so that it is already configured when starting Linux kernel.
Signed-off-by: Hugo Dubois hugo.dubois.ext@csgroup.eu Reviewed-by: CASAUBON Jean Michel jean-michel.casaubon@csgroup.eu Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- board/cssi/common/common.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/board/cssi/common/common.c b/board/cssi/common/common.c index 7ecf772620..6848efd43b 100644 --- a/board/cssi/common/common.c +++ b/board/cssi/common/common.c @@ -208,12 +208,44 @@ void misc_init_r_common(void) } }
+static void iop_setup_fpgam_common(void) +{ + u8 far_id = in_8(ADDR_FPGA_R_BASE + 0x43) >> 5; + + if (far_id == FAR_CASRSA) { + /* + * PFDIR[15] = 0 [0x01] + * PFDIR[14] = 1 [0x02] + * PFDIR[13] = 1 [0x04] + */ + clrsetbits_8(ADDR_FPGA_R_BASE + 0x37, 0x01, 0x06); + /* + * PFODR[15] = 1 [0x01] + * PFODR[14] = 0 [0x02] + * PFODR[13] = 0 [0x04] + */ + clrsetbits_8(ADDR_FPGA_R_BASE + 0x39, 0x06, 0x01); + /* + * PFDAT[15] = 0 [0x01] + * PFDAT[14] = 1 [0x02] + * PFDAT[13] = 1 [0x04] + * PFDAT[12] = 1 [0x08] + */ + clrsetbits_8(ADDR_FPGA_R_BASE + 0x3B, 0x01, 0x0E); + + /* Setup TOR_OUT */ + out_8(ADDR_FPGA_R_BASE + 0x32, 0x2A); + } +} + void iop_setup_common(void) { u8 type = in_8(ADDR_FPGA_R_BASE);
- if (type == TYPE_MCR) + if (type == TYPE_MCR) { iop_setup_mcr(); - else if (type == TYPE_MIAE) + } else if (type == TYPE_MIAE) { iop_setup_miae(); + iop_setup_fpgam_common(); + } }

From: Hugo Dubois hugo.dubois.ext@csgroup.eu
CMPC885 board can be pluged on a mother board with fibre interface, so fibre interface MAC address must be initialised for that case.
Signed-off-by: Hugo Dubois hugo.dubois.ext@csgroup.eu Reviewed-by: CASAUBON Jean Michel jean-michel.casaubon@csgroup.eu Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- board/cssi/cmpc885/cmpc885.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/board/cssi/cmpc885/cmpc885.c b/board/cssi/cmpc885/cmpc885.c index e11cfafaa5..49c13056ed 100644 --- a/board/cssi/cmpc885/cmpc885.c +++ b/board/cssi/cmpc885/cmpc885.c @@ -114,8 +114,10 @@ static int setup_mac(void) if (memcmp(din + EE_OFF_MAC1, &ident, sizeof(ident)) == 0) eth_env_set_enetaddr("ethaddr", din + EE_OFF_MAC1);
- if (memcmp(din + EE_OFF_MAC2, &ident, sizeof(ident)) == 0) + if (memcmp(din + EE_OFF_MAC2, &ident, sizeof(ident)) == 0) { eth_env_set_enetaddr("eth1addr", din + EE_OFF_MAC2); + eth_env_set_enetaddr("eth2addr", din + EE_OFF_MAC2); + }
return 0; }

Since commit 773ad4ebb1d6 ("spi, mpc8xx: Add support for chipselect via GPIO and fixups"), DM_GPIO is required for 8xx SPI.
Add the missing dependency to avoid build failures.
Fixes: 773ad4ebb1d6 ("spi, mpc8xx: Add support for chipselect via GPIO and fixups") Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 69b184b0d9..612434633b 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -262,7 +262,7 @@ config MESON_SPIFC_A1
config MPC8XX_SPI bool "MPC8XX SPI Driver" - depends on MPC8xx + depends on MPC8xx && DM_GPIO help Enable support for SPI on MPC8XX

xfer ops can be passed a NULL input or output buffer. At the time being the driver ignores it and overwrites memory at 0.
Define a dummy buffer and use it when either input or output buffer is NULL. Bail out when both are NULL as it shouldn't.
Also increase MAX_BUFFER len to 32k as the current is pretty low.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- drivers/spi/mpc8xx_spi.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/spi/mpc8xx_spi.c b/drivers/spi/mpc8xx_spi.c index 5c8d760935..2aa9c7d5df 100644 --- a/drivers/spi/mpc8xx_spi.c +++ b/drivers/spi/mpc8xx_spi.c @@ -29,7 +29,7 @@ #define CPM_SPI_BASE_RX CPM_SPI_BASE #define CPM_SPI_BASE_TX (CPM_SPI_BASE + sizeof(cbd_t))
-#define MAX_BUFFER 0x104 +#define MAX_BUFFER 0x8000 /* Max possible is 0xffff. We want power of 2 */
struct mpc8xx_priv { spi_t __iomem *spi; @@ -37,6 +37,8 @@ struct mpc8xx_priv { int max_cs; };
+static char dummy_buffer[MAX_BUFFER]; + static int mpc8xx_spi_set_mode(struct udevice *dev, uint mod) { return 0; @@ -154,6 +156,8 @@ static int mpc8xx_spi_xfer(struct udevice *dev, unsigned int bitlen, int tm; size_t count = (bitlen + 7) / 8;
+ if (!din && !dout) + return -EINVAL; if (count > MAX_BUFFER) return -EINVAL;
@@ -165,12 +169,12 @@ static int mpc8xx_spi_xfer(struct udevice *dev, unsigned int bitlen, mpc8xx_spi_cs_activate(dev);
/* Setting tx bd status and data length */ - out_be32(&tbdf->cbd_bufaddr, (ulong)dout); + out_be32(&tbdf->cbd_bufaddr, dout ? (ulong)dout : (ulong)dummy_buffer); out_be16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_LAST | BD_SC_WRAP); out_be16(&tbdf->cbd_datlen, count);
/* Setting rx bd status and data length */ - out_be32(&rbdf->cbd_bufaddr, (ulong)din); + out_be32(&rbdf->cbd_bufaddr, din ? (ulong)din : (ulong)dummy_buffer); out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_WRAP); out_be16(&rbdf->cbd_datlen, 0); /* rx length has no significance */

LM74 is a SPI temperature sensor.
Implement a driver to read temperature from it.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- drivers/thermal/Kconfig | 6 +++++ drivers/thermal/Makefile | 1 + drivers/thermal/ti-lm74.c | 52 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 drivers/thermal/ti-lm74.c
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 681b621760..440eb64a56 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -41,4 +41,10 @@ config TI_DRA7_THERMAL Enable thermal support for for the Texas Instruments DRA752 SoC family. The driver supports reading CPU temperature.
+config TI_LM74_THERMAL + bool "Temperature sensor driver for TI LM74 chip" + help + Enable thermal support for the Texas Instruments LM74 chip. + The driver supports reading CPU temperature. + endif # if DM_THERMAL diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 8acc7d20cb..b5ab0fc221 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o obj-$(CONFIG_IMX_SCU_THERMAL) += imx_scu_thermal.o obj-$(CONFIG_TI_DRA7_THERMAL) += ti-bandgap.o obj-$(CONFIG_IMX_TMU) += imx_tmu.o +obj-$(CONFIG_TI_LM74_THERMAL) += ti-lm74.o diff --git a/drivers/thermal/ti-lm74.c b/drivers/thermal/ti-lm74.c new file mode 100644 index 0000000000..7d56f75df0 --- /dev/null +++ b/drivers/thermal/ti-lm74.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * TI LM74 temperature sensor driver + * + * Copyright (C) 2024 CS GROUP France + * + */ + +#include <dm.h> +#include <thermal.h> +#include <spi.h> + +static int ti_lm74_get_temp(struct udevice *dev, int *temp) +{ + char buf[2]; + s16 raw; + int ret; + + ret = dm_spi_claim_bus(dev); + if (ret) + return ret; + + ret = dm_spi_xfer(dev, 16, NULL, buf, SPI_XFER_BEGIN | SPI_XFER_END); + + dm_spi_release_bus(dev); + if (ret) + return ret; + + raw = ((buf[0] << 8) + buf[1]) >> 3; + + *temp = (((int)raw * 125) + 1000) / 2000; + + return 0; +} + +static struct dm_thermal_ops ti_lm74_ops = { + .get_temp = ti_lm74_get_temp, +}; + +static const struct udevice_id of_ti_lm74_match[] = { + { + .compatible = "ti,lm74", + }, + {}, +}; + +U_BOOT_DRIVER(ti_bandgap_thermal) = { + .name = "ti_lm74_thermal", + .id = UCLASS_THERMAL, + .ops = &ti_lm74_ops, + .of_match = of_ti_lm74_match, +};

MCR3000 board has some components tied to the SPI bus, like the Texas Instruments LM74 temperature sensor.
Add support for SPI bus. The SPI chipselects are a bit special in the way that they are driven by 3 bits in a register of the board's CPLD where the value writen in those bits exclusively activates one of the 7 possible chipselects and value 0 sets all chipselets to inactive.
So add a special GPIO driver that simulates GPIOs for those chipselect.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- arch/powerpc/dts/mcr3000.dts | 31 +++++++++ board/cssi/mcr3000/Makefile | 1 + board/cssi/mcr3000/mcr3000.c | 5 ++ board/cssi/mcr3000/mcr3000_gpio.c | 109 ++++++++++++++++++++++++++++++ configs/MCR3000_defconfig | 5 ++ 5 files changed, 151 insertions(+) create mode 100644 board/cssi/mcr3000/mcr3000_gpio.c
diff --git a/arch/powerpc/dts/mcr3000.dts b/arch/powerpc/dts/mcr3000.dts index c4d7737bc6..edcd8358d0 100644 --- a/arch/powerpc/dts/mcr3000.dts +++ b/arch/powerpc/dts/mcr3000.dts @@ -26,6 +26,37 @@ timeout-sec = <2>; hw_margin_ms = <1000>; }; + + spi: spi@aa0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + compatible = "fsl,mpc8xx-spi"; + }; + }; + + localbus@ff000100 { + compatible = "s3k,mcr3000-localbus", "fsl,pq1-localbus", "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + reg = <0xff000100 0x40>; // ORx and BRx register + + ranges = <0 0 0x04000000 0x04000000 // BOOT + 1 0 0x00000000 0x04000000 // SDRAM + 2 0 0x08000000 0x04000000 // RAMDP + 3 0 0x0C000000 0x04000000 // NAND + 4 0 0x10000000 0x04000000 // Periphs + 5 0 0x14000000 0x04000000 // FPGA + 6 0 0x18000000 0x04000000 // mezzanine + 7 0 0x1c000000 0x04000000>; // DSP + + csspi: gpio-controller@2 { + #gpio-cells = <2>; + compatible = "s3k,mcr3000-cpld-csspi"; + reg = <4 0x802 2>; + gpio-controller; + }; };
SERIAL: smc@0 { diff --git a/board/cssi/mcr3000/Makefile b/board/cssi/mcr3000/Makefile index 7803016af3..846fd680e9 100644 --- a/board/cssi/mcr3000/Makefile +++ b/board/cssi/mcr3000/Makefile @@ -6,3 +6,4 @@
obj-y += mcr3000.o obj-$(CONFIG_CMD_NAND) += nand.o +obj-$(CONFIG_MPC8XX_SPI) += mcr3000_gpio.o diff --git a/board/cssi/mcr3000/mcr3000.c b/board/cssi/mcr3000/mcr3000.c index 8857c9e42c..537d7fa124 100644 --- a/board/cssi/mcr3000/mcr3000.c +++ b/board/cssi/mcr3000/mcr3000.c @@ -116,6 +116,11 @@ int misc_init_r(void) clrbits_be16(&iop->iop_pcpar, 0x4); clrbits_be16(&iop->iop_pcdir, 0x4);
+ /* Activate SPI */ + clrsetbits_be32(&immr->im_cpm.cp_pbpar, 0x1, 0xe); + setbits_be32(&immr->im_cpm.cp_pbdir, 0xf); + clrbits_be32(&immr->im_cpm.cp_pbdat, 0x1); + /* if BTN_ACQ_AL is pressed then bootdelay is changed to 60 second */ if ((in_be16(&iop->iop_pcdat) & 0x0004) == 0) env_set("bootdelay", "60"); diff --git a/board/cssi/mcr3000/mcr3000_gpio.c b/board/cssi/mcr3000/mcr3000_gpio.c new file mode 100644 index 0000000000..2bba14e6e5 --- /dev/null +++ b/board/cssi/mcr3000/mcr3000_gpio.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2024 CS GROUP France + * Christophe Leroy christophe.leroy@csgroup.eu + */ + +#include <asm/io.h> +#include <dm.h> +#include <mapmem.h> +#include <asm/gpio.h> +#include <malloc.h> + +#include "../common/common.h" + +struct mcr3000_spi_gpio_plat { + ulong addr; +}; + +struct mcr3000_spi_gpio_data { + void __iomem *base; +}; + +static int mcr3000_spi_gpio_set_value(struct udevice *dev, uint gpio, int value) +{ + struct mcr3000_spi_gpio_data *data = dev_get_priv(dev); + + if (value) + clrsetbits_be16(data->base, 7 << 5, (gpio & 7) << 5); + else + clrbits_be16(data->base, 7 << 5); + + return 0; +} + +static int mcr3000_spi_gpio_get_value(struct udevice *dev, uint gpio) +{ + struct mcr3000_spi_gpio_data *data = dev_get_priv(dev); + + return gpio == ((in_be16(data->base) >> 5) & 7); +} + +static int mcr3000_spi_gpio_direction_input(struct udevice *dev, uint gpio) +{ + return 0; +} + +static int mcr3000_spi_gpio_get_function(struct udevice *dev, uint gpio) +{ + return GPIOF_OUTPUT; +} + +static int mcr3000_spi_gpio_ofdata_to_platdata(struct udevice *dev) +{ + struct mcr3000_spi_gpio_plat *plat = dev_get_plat(dev); + fdt_addr_t addr; + u32 reg[2]; + + dev_read_u32_array(dev, "reg", reg, 2); + addr = dev_translate_address(dev, reg); + + plat->addr = addr; + + return 0; +} + +static int mcr3000_spi_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct mcr3000_spi_gpio_data *data = dev_get_priv(dev); + struct mcr3000_spi_gpio_plat *plat = dev_get_plat(dev); + char name[32], *str; + + data->base = map_sysmem(plat->addr, 2); + + snprintf(name, sizeof(name), "CHIPSELECT@%lx_", plat->addr); + str = strdup(name); + + if (!str) + return -ENOMEM; + + uc_priv->bank_name = str; + uc_priv->gpio_count = 16; + + return 0; +} + +static const struct dm_gpio_ops gpio_mcr3000_spi_ops = { + .get_value = mcr3000_spi_gpio_get_value, + .set_value = mcr3000_spi_gpio_set_value, + .direction_input = mcr3000_spi_gpio_direction_input, + .direction_output = mcr3000_spi_gpio_set_value, + .get_function = mcr3000_spi_gpio_get_function, +}; + +static const struct udevice_id mcr3000_spi_gpio_ids[] = { + { .compatible = "s3k,mcr3000-cpld-csspi"}, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(mcr3000_spi_gpio) = { + .name = "mcr3000_spi_chipselect", + .id = UCLASS_GPIO, + .ops = &gpio_mcr3000_spi_ops, + .of_to_plat = mcr3000_spi_gpio_ofdata_to_platdata, + .plat_auto = sizeof(struct mcr3000_spi_gpio_plat), + .of_match = mcr3000_spi_gpio_ids, + .probe = mcr3000_spi_gpio_probe, + .priv_auto = sizeof(struct mcr3000_spi_gpio_data), +}; diff --git a/configs/MCR3000_defconfig b/configs/MCR3000_defconfig index 8a88fb445c..ce34c2aa88 100644 --- a/configs/MCR3000_defconfig +++ b/configs/MCR3000_defconfig @@ -2,6 +2,7 @@ CONFIG_PPC=y CONFIG_TEXT_BASE=0x4000000 CONFIG_ENV_SIZE=0x2000 CONFIG_ENV_SECT_SIZE=0x2000 +CONFIG_DM_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="mcr3000" CONFIG_SYS_MONITOR_LEN=327680 CONFIG_SYS_CLK_FREQ=132000000 @@ -91,6 +92,7 @@ CONFIG_SYS_OR6_PRELIM=0xFFFF0908 CONFIG_SYS_BR7_PRELIM_BOOL=y CONFIG_SYS_BR7_PRELIM=0x1C000001 CONFIG_SYS_OR7_PRELIM=0xFFFF810A +CONFIG_MPC8XX_GPIO=y # CONFIG_MMC is not set CONFIG_MTD=y CONFIG_DM_MTD=y @@ -102,6 +104,9 @@ CONFIG_SYS_MAX_FLASH_SECT=35 CONFIG_MTD_RAW_NAND=y CONFIG_MPC8XX_FEC=y CONFIG_DM_SERIAL=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_MPC8XX_SPI=y CONFIG_WDT=y CONFIG_WDT_MPC8xxx_BME=y CONFIG_LZMA=y

All CSSI boards have an LM74 chip as temperature sensor.
Enable it.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- arch/powerpc/dts/cmpc885.dts | 12 +++++++++++- arch/powerpc/dts/cmpcpro.dts | 12 +++++++++++- arch/powerpc/dts/mcr3000.dts | 6 ++++++ configs/CMPC885_defconfig | 3 +++ configs/CMPCPRO_defconfig | 3 +++ configs/MCR3000_defconfig | 3 +++ 6 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/dts/cmpc885.dts b/arch/powerpc/dts/cmpc885.dts index 9a33e7e77c..454ceb91ca 100644 --- a/arch/powerpc/dts/cmpc885.dts +++ b/arch/powerpc/dts/cmpc885.dts @@ -85,12 +85,22 @@ #address-cells = <1>; #size-cells = <0>; compatible = "fsl,mpc8xx-spi"; - gpios = <&CPM1_PIO_B 21 1>; /* /EEPROM_CS ACTIVE_LOW */ + gpios = <&CPM1_PIO_B 21 1 /* /EEPROM_CS ACTIVE_LOW */ + &CPM1_PIO_B 23 1 /* Temperature mother board */ + &CPM1_PIO_B 14 1>; /* Temperature CPU board */
eeprom@0 { reg = <0>; compatible = "atmel,at25", "cs,eeprom"; }; + temp@1 { + reg = <1>; + compatible = "ti,lm74"; + }; + temp@2 { + reg = <2>; + compatible = "ti,lm74"; + }; }; }; }; diff --git a/arch/powerpc/dts/cmpcpro.dts b/arch/powerpc/dts/cmpcpro.dts index 78f8a9f4d3..1dfa864ebb 100644 --- a/arch/powerpc/dts/cmpcpro.dts +++ b/arch/powerpc/dts/cmpcpro.dts @@ -140,12 +140,22 @@ compatible = "fsl,mpc832x-spi"; reg = <0x4c0 0x40>; mode = "cpu"; - gpios = <&qe_pio_d 3 1>; + gpios = <&qe_pio_d 3 1 + &qe_pio_c 5 1 /* TEMP mother board */ + &qe_pio_c 3 1>; /* TEMP CPU board */ clock-frequency = <0>; eeprom@0 { reg = <0>; compatible = "atmel,at25", "cs,eeprom"; }; + temp@1 { + reg = <1>; + compatible = "ti,lm74"; + }; + temp@2 { + reg = <2>; + compatible = "ti,lm74"; + }; }; eth0: ucc@3000 { device_type = "network"; diff --git a/arch/powerpc/dts/mcr3000.dts b/arch/powerpc/dts/mcr3000.dts index edcd8358d0..f678951e22 100644 --- a/arch/powerpc/dts/mcr3000.dts +++ b/arch/powerpc/dts/mcr3000.dts @@ -33,6 +33,12 @@ #size-cells = <0>; cell-index = <0>; compatible = "fsl,mpc8xx-spi"; + gpios = <&csspi 2 0>; + + temp@0 { + reg = <0>; + compatible = "ti,lm74"; + }; }; };
diff --git a/configs/CMPC885_defconfig b/configs/CMPC885_defconfig index bbe8d5be7e..11c24f72a8 100644 --- a/configs/CMPC885_defconfig +++ b/configs/CMPC885_defconfig @@ -50,6 +50,7 @@ CONFIG_CMD_ASKENV=y # CONFIG_CMD_LOADS is not set CONFIG_CMD_MTD=y CONFIG_CMD_NAND=y +CONFIG_CMD_TEMPERATURE=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_MII_INIT=y @@ -107,6 +108,8 @@ CONFIG_DM_SERIAL=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_MPC8XX_SPI=y +CONFIG_DM_THERMAL=y +CONFIG_TI_LM74_THERMAL=y CONFIG_WDT=y CONFIG_WDT_MPC8xxx_BME=y # CONFIG_REGEX is not set diff --git a/configs/CMPCPRO_defconfig b/configs/CMPCPRO_defconfig index cefed63f24..f8f5c9fd86 100644 --- a/configs/CMPCPRO_defconfig +++ b/configs/CMPCPRO_defconfig @@ -134,6 +134,7 @@ CONFIG_CMD_ASKENV=y # CONFIG_CMD_LOADS is not set CONFIG_CMD_MTD=y CONFIG_CMD_NAND=y +CONFIG_CMD_TEMPERATURE=y CONFIG_CMD_DHCP=y CONFIG_BOOTP_BOOTFILESIZE=y CONFIG_CMD_MII=y @@ -197,6 +198,8 @@ CONFIG_DM_SPI=y CONFIG_MPC8XXX_SPI=y CONFIG_SYSRESET=y CONFIG_SYSRESET_MPC83XX=y +CONFIG_DM_THERMAL=y +CONFIG_TI_LM74_THERMAL=y CONFIG_WDT=y CONFIG_WDT_MPC8xxx=y # CONFIG_REGEX is not set diff --git a/configs/MCR3000_defconfig b/configs/MCR3000_defconfig index ce34c2aa88..f2eac2c544 100644 --- a/configs/MCR3000_defconfig +++ b/configs/MCR3000_defconfig @@ -47,6 +47,7 @@ CONFIG_CMD_ASKENV=y # CONFIG_CMD_LOADS is not set CONFIG_CMD_MTD=y CONFIG_CMD_NAND=y +CONFIG_CMD_TEMPERATURE=y # CONFIG_CMD_ECHO is not set # CONFIG_CMD_ITEST is not set # CONFIG_CMD_SOURCE is not set @@ -107,6 +108,8 @@ CONFIG_DM_SERIAL=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_MPC8XX_SPI=y +CONFIG_DM_THERMAL=y +CONFIG_TI_LM74_THERMAL=y CONFIG_WDT=y CONFIG_WDT_MPC8xxx_BME=y CONFIG_LZMA=y

SDMA configuration register needs to be set up only once and doesn't belong to drivers. Also, the value to be used is different on mpc885.
So do the init in cpu_init_f() with 0x40 for mpc885 and 0x1 for others.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- arch/powerpc/cpu/mpc8xx/cpu_init.c | 6 ++++++ drivers/spi/mpc8xx_spi.c | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/cpu/mpc8xx/cpu_init.c b/arch/powerpc/cpu/mpc8xx/cpu_init.c index aac4203a6e..d1abe8f00b 100644 --- a/arch/powerpc/cpu/mpc8xx/cpu_init.c +++ b/arch/powerpc/cpu/mpc8xx/cpu_init.c @@ -92,6 +92,12 @@ void cpu_init_f(immap_t __iomem *immr) CONFIG_SYS_PLPRCR); #endif
+ /* Set SDMA configuration register */ + if (IS_ENABLED(CONFIG_MPC885)) + out_be32(&immr->im_siu_conf.sc_sdcr, 0x0040); + else + out_be32(&immr->im_siu_conf.sc_sdcr, 0x0001); + /* * Memory Controller: */ diff --git a/drivers/spi/mpc8xx_spi.c b/drivers/spi/mpc8xx_spi.c index 2aa9c7d5df..0d142f12e9 100644 --- a/drivers/spi/mpc8xx_spi.c +++ b/drivers/spi/mpc8xx_spi.c @@ -103,10 +103,6 @@ static int mpc8xx_spi_probe(struct udevice *dev) while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) ;
-/* 5 */ - /* Set SDMA configuration register */ - out_be32(&immr->im_siu_conf.sc_sdcr, 0x0001); - /* 6 */ /* Set to big endian. */ out_8(&spi->spi_tfcr, SMC_EB);

Perform multiple transfer of size MAX_BUFFER when the data to be transferred is longer than MAX_BUFFER.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- drivers/spi/mpc8xx_spi.c | 48 ++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 14 deletions(-)
diff --git a/drivers/spi/mpc8xx_spi.c b/drivers/spi/mpc8xx_spi.c index 0d142f12e9..a193ac711b 100644 --- a/drivers/spi/mpc8xx_spi.c +++ b/drivers/spi/mpc8xx_spi.c @@ -143,27 +143,17 @@ static void mpc8xx_spi_cs_deactivate(struct udevice *dev) dm_gpio_set_value(&priv->gpios[platdata->cs], 0); }
-static int mpc8xx_spi_xfer(struct udevice *dev, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) +static int mpc8xx_spi_xfer_one(struct udevice *dev, size_t count, + const void *dout, void *din) { immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; cpm8xx_t __iomem *cp = &immr->im_cpm; cbd_t __iomem *tbdf, *rbdf; int tm; - size_t count = (bitlen + 7) / 8; - - if (!din && !dout) - return -EINVAL; - if (count > MAX_BUFFER) - return -EINVAL;
tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX]; rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX];
- /* Set CS for device */ - if (flags & SPI_XFER_BEGIN) - mpc8xx_spi_cs_activate(dev); - /* Setting tx bd status and data length */ out_be32(&tbdf->cbd_bufaddr, dout ? (ulong)dout : (ulong)dummy_buffer); out_be16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_LAST | BD_SC_WRAP); @@ -196,13 +186,43 @@ static int mpc8xx_spi_xfer(struct udevice *dev, unsigned int bitlen, }
if (tm >= 1000) - printf("*** spi_xfer: Time out while xferring to/from SPI!\n"); + return -ETIMEDOUT; + + return 0; +}
+static int mpc8xx_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + size_t count = (bitlen + 7) / 8; + size_t offset = 0; + int ret = 0; + + if (!din && !dout) + return -EINVAL; + + /* Set CS for device */ + if (flags & SPI_XFER_BEGIN) + mpc8xx_spi_cs_activate(dev); + + while (count > 0 && !ret) { + size_t chunk = min(count, (size_t)MAX_BUFFER); + const void *out = dout ? dout + offset : NULL; + void *in = din ? din + offset : NULL; + + ret = mpc8xx_spi_xfer_one(dev, chunk, out, in); + + offset += chunk; + count -= chunk; + } /* Clear CS for device */ if (flags & SPI_XFER_END) mpc8xx_spi_cs_deactivate(dev);
- return 0; + if (ret) + printf("*** spi_xfer: Time out while xferring to/from SPI!\n"); + + return ret; }
static int mpc8xx_spi_ofdata_to_platdata(struct udevice *dev)

On CPM, the RISC core is a lot more efficiant when doing transfers in 16-bits chunks than in 8-bits chunks, but unfortunately the words need to be byte swapped.
So, for large tranfers with an even size, allocate a temporary buffer and byte-swap data before and after transfer.
This change allows setting higher speed for transfer. For instance on an MPC 8xx (CPM1 comms RISC processor), the documentation tells that transfer in byte mode at 1 kbit/s uses 0.200% of CPM load at 25 MHz while a word transfer at the same speed uses 0.032% of CPM load. This means the speed can be 6 times higher in word mode for the same CPM load.
For small transfers, the load reduction is not worth the CPU load required to allocate the temporary buffer, so do it only when data size is over 64 bytes.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- drivers/spi/mpc8xx_spi.c | 44 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-)
diff --git a/drivers/spi/mpc8xx_spi.c b/drivers/spi/mpc8xx_spi.c index a193ac711b..b1abfbf4fc 100644 --- a/drivers/spi/mpc8xx_spi.c +++ b/drivers/spi/mpc8xx_spi.c @@ -18,6 +18,7 @@
#include <common.h> #include <dm.h> +#include <malloc.h> #include <mpc8xx.h> #include <spi.h> #include <linux/delay.h> @@ -30,6 +31,7 @@ #define CPM_SPI_BASE_TX (CPM_SPI_BASE + sizeof(cbd_t))
#define MAX_BUFFER 0x8000 /* Max possible is 0xffff. We want power of 2 */ +#define MIN_HWORD_XFER 64 /* Minimum size for 16 bits transfer */
struct mpc8xx_priv { spi_t __iomem *spi; @@ -149,23 +151,46 @@ static int mpc8xx_spi_xfer_one(struct udevice *dev, size_t count, immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; cpm8xx_t __iomem *cp = &immr->im_cpm; cbd_t __iomem *tbdf, *rbdf; + void *bufout, *bufin; + u16 spmode_len; int tm;
tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX]; rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX];
+ if (!(count & 1) && count >= MIN_HWORD_XFER) { + spmode_len = SPMODE_LEN(16); + if (dout) { + int i; + + bufout = malloc(count); + for (i = 0; i < count; i += 2) + *(u16 *)(bufout + i) = swab16(*(u16 *)(dout + i)); + } else { + bufout = NULL; + } + if (din) + bufin = malloc(count); + else + bufin = NULL; + } else { + spmode_len = SPMODE_LEN(8); + bufout = (void *)dout; + bufin = din; + } + /* Setting tx bd status and data length */ - out_be32(&tbdf->cbd_bufaddr, dout ? (ulong)dout : (ulong)dummy_buffer); + out_be32(&tbdf->cbd_bufaddr, bufout ? (ulong)bufout : (ulong)dummy_buffer); out_be16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_LAST | BD_SC_WRAP); out_be16(&tbdf->cbd_datlen, count);
/* Setting rx bd status and data length */ - out_be32(&rbdf->cbd_bufaddr, din ? (ulong)din : (ulong)dummy_buffer); + out_be32(&rbdf->cbd_bufaddr, bufin ? (ulong)bufin : (ulong)dummy_buffer); out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_WRAP); out_be16(&rbdf->cbd_datlen, 0); /* rx length has no significance */
clrsetbits_be16(&cp->cp_spmode, ~SPMODE_LOOP, SPMODE_REV | SPMODE_MSTR | - SPMODE_EN | SPMODE_LEN(8) | SPMODE_PM(0x8)); + SPMODE_EN | spmode_len | SPMODE_PM(0x8)); out_8(&cp->cp_spim, 0); /* Mask all SPI events */ out_8(&cp->cp_spie, SPI_EMASK); /* Clear all SPI events */
@@ -188,6 +213,19 @@ static int mpc8xx_spi_xfer_one(struct udevice *dev, size_t count, if (tm >= 1000) return -ETIMEDOUT;
+ if (!(count & 1) && count > MIN_HWORD_XFER) { + if (dout) + free(bufout); + if (din) { + int i; + + bufout = malloc(count); + for (i = 0; i < count; i += 2) + *(u16 *)(din + i) = swab16(*(u16 *)(bufin + i)); + free(bufin); + } + } + return 0; }

Set the speed requested through mpc8xx_spi_set_speed() instead of hardcoding a fixed speed.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- drivers/spi/mpc8xx_spi.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/mpc8xx_spi.c b/drivers/spi/mpc8xx_spi.c index b1abfbf4fc..e1448cc619 100644 --- a/drivers/spi/mpc8xx_spi.c +++ b/drivers/spi/mpc8xx_spi.c @@ -48,6 +48,21 @@ static int mpc8xx_spi_set_mode(struct udevice *dev, uint mod)
static int mpc8xx_spi_set_speed(struct udevice *dev, uint speed) { + immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; + cpm8xx_t __iomem *cp = &immr->im_cpm; + u8 pm = (gd->arch.brg_clk - 1) / (speed * 16); + + if (pm > 16) { + setbits_be16(&cp->cp_spmode, SPMODE_DIV16); + pm /= 16; + if (pm > 16) + pm = 16; + } else { + clrbits_be16(&cp->cp_spmode, SPMODE_DIV16); + } + + clrsetbits_be16(&cp->cp_spmode, SPMODE_PM(0xf), SPMODE_PM(pm)); + return 0; }
@@ -189,8 +204,8 @@ static int mpc8xx_spi_xfer_one(struct udevice *dev, size_t count, out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_WRAP); out_be16(&rbdf->cbd_datlen, 0); /* rx length has no significance */
- clrsetbits_be16(&cp->cp_spmode, ~SPMODE_LOOP, SPMODE_REV | SPMODE_MSTR | - SPMODE_EN | spmode_len | SPMODE_PM(0x8)); + clrsetbits_be16(&cp->cp_spmode, ~(SPMODE_LOOP | SPMODE_PM(0xf) | SPMODE_DIV16), + SPMODE_REV | SPMODE_MSTR | SPMODE_EN | spmode_len); out_8(&cp->cp_spim, 0); /* Mask all SPI events */ out_8(&cp->cp_spie, SPI_EMASK); /* Clear all SPI events */

Instead of cross using cross-directory makefile directives, add a Makefile in board/cssi/common/ directory in order to benefit from HAVE_VENDOR_COMMON_LIB logic.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- board/cssi/cmpc885/Makefile | 2 +- board/cssi/cmpcpro/Makefile | 2 +- board/cssi/common/Makefile | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 board/cssi/common/Makefile
diff --git a/board/cssi/cmpc885/Makefile b/board/cssi/cmpc885/Makefile index baf9e5ab4f..6c055097cd 100644 --- a/board/cssi/cmpc885/Makefile +++ b/board/cssi/cmpc885/Makefile @@ -5,6 +5,6 @@ # Christophe Leroy christophe.leroy@c-s.fr #
-obj-y += cmpc885.o ../common/common.o +obj-y += cmpc885.o obj-y += sdram.o obj-$(CONFIG_CMD_NAND) += nand.o diff --git a/board/cssi/cmpcpro/Makefile b/board/cssi/cmpcpro/Makefile index 73ff451ea1..30837781af 100644 --- a/board/cssi/cmpcpro/Makefile +++ b/board/cssi/cmpcpro/Makefile @@ -5,4 +5,4 @@ # SPDX-License-Identifier: GPL-2.0+ #
-obj-y += cmpcpro.o nand.o ../common/common.o +obj-y += cmpcpro.o nand.o diff --git a/board/cssi/common/Makefile b/board/cssi/common/Makefile new file mode 100644 index 0000000000..973582639e --- /dev/null +++ b/board/cssi/common/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2024 CS GROUP France +# Christophe Leroy christophe.leroy@csgroup.eu +# + +obj-$(CONFIG_TARGET_CMPC885) += common.o +obj-$(CONFIG_TARGET_CMPCPRO) += common.o

Unlike CMPC885 and CMPCPRO boards, the FPGA of MCR3000 board doesn't load code automatically but needs to be loaded by software through SPI.
Until now it was loaded later by Linux, but we'd like U-boot to have access to some information that require the FPGA, like board address in racks.
So, implemented the load of FPGA in U-boot.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- To avoid spamming your email boxes, the code isn't included in the emailed patch but will be present in the PULL request --- arch/powerpc/dts/mcr3000.dts | 6 ++++- board/cssi/mcr3000/fpga_code.h | 10 +++++++ board/cssi/mcr3000/mcr3000.c | 48 ++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 board/cssi/mcr3000/fpga_code.h
diff --git a/arch/powerpc/dts/mcr3000.dts b/arch/powerpc/dts/mcr3000.dts index f678951e22..aa46007b8d 100644 --- a/arch/powerpc/dts/mcr3000.dts +++ b/arch/powerpc/dts/mcr3000.dts @@ -33,12 +33,16 @@ #size-cells = <0>; cell-index = <0>; compatible = "fsl,mpc8xx-spi"; - gpios = <&csspi 2 0>; + gpios = <&csspi 2 0 + &csspi 0 0>;
temp@0 { reg = <0>; compatible = "ti,lm74"; }; + fpga@1 { + reg = <1>; + }; }; };
diff --git a/board/cssi/mcr3000/fpga_code.h b/board/cssi/mcr3000/fpga_code.h new file mode 100644 index 0000000000..0d710ba41f --- /dev/null +++ b/board/cssi/mcr3000/fpga_code.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2010 CS Systemes d'Information + * + * uCORE FPGA code for MCR3000 board + */ + +u32 fpga_code[] = { + 0xdeadbeef, +}; diff --git a/board/cssi/mcr3000/mcr3000.c b/board/cssi/mcr3000/mcr3000.c index 537d7fa124..15a2d0d946 100644 --- a/board/cssi/mcr3000/mcr3000.c +++ b/board/cssi/mcr3000/mcr3000.c @@ -13,12 +13,15 @@ #include <mpc8xx.h> #include <fdt_support.h> #include <serial.h> +#include <spi.h> #include <asm/global_data.h> #include <asm/io.h> #include <dm/uclass.h> #include <wdt.h> #include <linux/delay.h>
+#include "fpga_code.h" + DECLARE_GLOBAL_DATA_PTR;
#define SDRAM_MAX_SIZE (32 * 1024 * 1024) @@ -107,6 +110,49 @@ int dram_init(void) return 0; }
+static int load_fpga(void) +{ + immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; + struct udevice *master; + struct spi_slave *slave; + int ret; + + ret = uclass_get_device(UCLASS_SPI, 0, &master); + if (ret) + return ret; + + ret = _spi_get_bus_and_cs(0, 1, 10000000, 0, "spi_generic_drv", + "generic_0:0", &master, &slave); + if (ret) + return ret; + + ret = spi_claim_bus(slave); + + printf("FPGA Init ... "); + + clrbits_be32(&immr->im_cpm.cp_pbdat, 0x20000); + while ((in_be32(&immr->im_cpm.cp_pbdat) & 0x8000)) + ; + setbits_be32(&immr->im_cpm.cp_pbdat, 0x20000); + while (!(in_be32(&immr->im_cpm.cp_pbdat) & 0x8000)) + ; + + printf("Loading ... "); + + ret = spi_xfer(slave, sizeof(fpga_code) * BITS_PER_BYTE, fpga_code, NULL, 0); + + spi_release_bus(slave); + + if ((in_be32(&immr->im_cpm.cp_pbdat) & 0x4000)) { + printf("Done\n"); + } else { + printf("FAILED\n"); + ret = -EINVAL; + } + + return ret; +} + int misc_init_r(void) { immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; @@ -121,6 +167,8 @@ int misc_init_r(void) setbits_be32(&immr->im_cpm.cp_pbdir, 0xf); clrbits_be32(&immr->im_cpm.cp_pbdat, 0x1);
+ load_fpga(); + /* if BTN_ACQ_AL is pressed then bootdelay is changed to 60 second */ if ((in_be16(&iop->iop_pcdat) & 0x0004) == 0) env_set("bootdelay", "60");

MCR boards are plugged in racks. The position in the rack can be read in a register.
For MCR3000, that's provided by the FPGA so check it is loaded before reading the address.
For the other boards, the FPGA is loaded by hardware so it can be read inconditionnaly.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu --- board/cssi/common/common.c | 6 +++++- board/cssi/mcr3000/mcr3000.c | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/board/cssi/common/common.c b/board/cssi/common/common.c index 6848efd43b..0292a9016e 100644 --- a/board/cssi/common/common.c +++ b/board/cssi/common/common.c @@ -164,7 +164,7 @@ int checkboard_common(void)
void misc_init_r_common(void) { - u8 tmp, far_id; + u8 tmp, far_id, addr; int count = 3;
switch (in_8(ADDR_FPGA_R_BASE)) { @@ -173,6 +173,10 @@ void misc_init_r_common(void) if ((in_8(ADDR_FPGA_R_BASE + 0x31) & FPGA_R_ACQ_AL_FAV) == 0) env_set("bootdelay", "60");
+ addr = in_8(ADDR_FPGA_R_BASE + 0x43); + printf("Board address: 0x%2.2x (System %d Rack %d Slot %d)\n", + addr, addr >> 7, (addr >> 4) & 7, addr & 15); + env_set("config", CFG_BOARD_MCR3000_2G); env_set("hostname", CFG_BOARD_MCR3000_2G); break; diff --git a/board/cssi/mcr3000/mcr3000.c b/board/cssi/mcr3000/mcr3000.c index 15a2d0d946..48e82a902d 100644 --- a/board/cssi/mcr3000/mcr3000.c +++ b/board/cssi/mcr3000/mcr3000.c @@ -167,7 +167,12 @@ int misc_init_r(void) setbits_be32(&immr->im_cpm.cp_pbdir, 0xf); clrbits_be32(&immr->im_cpm.cp_pbdat, 0x1);
- load_fpga(); + if (!load_fpga()) { + u8 addr = in_be16((void *)0x1400009c); + + printf("Board address: 0x%2.2x (System %d Rack %d Slot %d)\n", + addr, addr >> 7, (addr >> 4) & 7, addr & 15); + }
/* if BTN_ACQ_AL is pressed then bootdelay is changed to 60 second */ if ((in_be16(&iop->iop_pcdat) & 0x0004) == 0)
participants (1)
-
Christophe Leroy