diff options
author | Christophe Leroy <christophe.leroy@csgroup.eu> | 2023-04-04 13:09:36 +0200 |
---|---|---|
committer | Christophe Leroy <christophe.leroy@csgroup.eu> | 2023-04-28 17:52:23 +0200 |
commit | 4d0c8db74d83e43dec4e7481b2d1e194f51d907b (patch) | |
tree | 0d629f90439e93a7ff04911557e9c9259671d8b4 /board/cssi | |
parent | 78ba7b61da1271d982ff9c87b879d197ef911776 (diff) | |
download | u-boot-4d0c8db74d83e43dec4e7481b2d1e194f51d907b.tar.gz |
board: cssi: Add CPU board CMPCPRO
CSSI has another CPU board, similar to the CMPC885 board
that get plugged on the two base boards MCR3000_2G and MIAE.
That CPU board is called CMPCPRO because it has a MPC8321E CPU,
also known as Power QUICC II PRO.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Diffstat (limited to 'board/cssi')
-rw-r--r-- | board/cssi/MAINTAINERS | 2 | ||||
-rw-r--r-- | board/cssi/cmpcpro/Kconfig | 26 | ||||
-rw-r--r-- | board/cssi/cmpcpro/Makefile | 8 | ||||
-rw-r--r-- | board/cssi/cmpcpro/cmpcpro.c | 404 | ||||
-rw-r--r-- | board/cssi/cmpcpro/cmpcpro.env | 8 | ||||
-rw-r--r-- | board/cssi/cmpcpro/nand.c | 43 |
6 files changed, 491 insertions, 0 deletions
diff --git a/board/cssi/MAINTAINERS b/board/cssi/MAINTAINERS index d8e7b5e9b6..f82dd3b789 100644 --- a/board/cssi/MAINTAINERS +++ b/board/cssi/MAINTAINERS @@ -6,3 +6,5 @@ F: include/configs/mcr3000.h F: configs/MCR3000_defconfig F: include/configs/cmpc885.h F: configs/CMPC885_defconfig +F: include/configs/cmpcpro.h +F: configs/CMPCPRO_defconfig diff --git a/board/cssi/cmpcpro/Kconfig b/board/cssi/cmpcpro/Kconfig new file mode 100644 index 0000000000..b5d998ae5a --- /dev/null +++ b/board/cssi/cmpcpro/Kconfig @@ -0,0 +1,26 @@ +if TARGET_CMPCPRO + +config SYS_BOARD + default "cmpcpro" + +config SYS_VENDOR + default "cssi" + +config SYS_CONFIG_NAME + default "cmpcpro" + +config TEXT_BASE + default 0x40000000 + +config CPLD_BASE + hex + default 0x90000000 + +config FPGA_BASE + hex + default 0x80000000 + +config PCI + default no + +endif diff --git a/board/cssi/cmpcpro/Makefile b/board/cssi/cmpcpro/Makefile new file mode 100644 index 0000000000..73ff451ea1 --- /dev/null +++ b/board/cssi/cmpcpro/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += cmpcpro.o nand.o ../common/common.o diff --git a/board/cssi/cmpcpro/cmpcpro.c b/board/cssi/cmpcpro/cmpcpro.c new file mode 100644 index 0000000000..3e9ba6a4cc --- /dev/null +++ b/board/cssi/cmpcpro/cmpcpro.c @@ -0,0 +1,404 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2006-2023 CS GROUP France + */ + +#include <command.h> +#include <common.h> +#include <dm.h> +#include <env.h> +#include <env_internal.h> +#include <eeprom.h> +#include <fdt_support.h> +#include <hang.h> +#include <ioports.h> +#include <mpc83xx.h> +#include <netdev.h> +#include <spi.h> +#include <stdarg.h> +#include <stdlib.h> + +#include <linux/delay.h> +#include <linux/immap_qe.h> +#include <linux/libfdt.h> +#include <linux/log2.h> +#include <linux/sizes.h> + +#include <asm/io.h> +#include <asm/global_data.h> +#include <asm/mmu.h> + +#include <u-boot/crc.h> + +#include "../common/common.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define ADDR_FPGA_BASE ((unsigned char __iomem *)CONFIG_CPLD_BASE) +#define ADDR_FPGA_RESET_G (ADDR_FPGA_BASE + 0x40) +#define ADDR_FPGA_REG_ETAT (ADDR_FPGA_BASE + 0x42) + +#define R_ETAT_PRES_BASE 0x01 +#define RESET_G_OK 0x08 + +/* SPI EEPROM parameters */ +#define MAX_SPI_BYTES 0x28 +#define EE_OFF_MAC1 0x10 +#define EE_OFF_MAC2 0x16 +#define EE_OFF_MAC3 0x1C + +static uint upma_table[] = { + /* Read Single-Beat (RSS) */ + 0x00AC0C00, 0x00FC1C40, 0x30FCE045, 0xFFFF0C00, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* Read Burst (RBS) */ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* Write Single-Beat (WSS) */ + 0x00A30C00, 0x00F31C40, 0x3FF3C045, 0xFFFF0C00, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* Write Burst (WBS) */ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* Refresh Timer (RTS) */ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* Exception Condition (EXS) */ + 0xFFFF0C01, 0xFFFF0C01, 0xFFFF0C01, 0xFFFF0C01, +}; + +const qe_iop_conf_t qe_iop_conf_tab[] = { + /* ETH3 */ + {1, 0, 1, 0, 1}, /* TxD0 */ + {1, 1, 1, 0, 1}, /* TxD1 */ + {1, 2, 1, 0, 1}, /* TxD2 */ + {1, 3, 1, 0, 1}, /* TxD3 */ + {1, 9, 1, 0, 1}, /* TxER */ + {1, 12, 1, 0, 1}, /* TxEN */ + {3, 24, 2, 0, 1}, /* TxCLK->CLK10 */ + + {1, 4, 2, 0, 1}, /* RxD0 */ + {1, 5, 2, 0, 1}, /* RxD1 */ + {1, 6, 2, 0, 1}, /* RxD2 */ + {1, 7, 2, 0, 1}, /* RxD3 */ + {1, 8, 2, 0, 1}, /* RxER */ + {1, 10, 2, 0, 1}, /* RxDV */ + {0, 13, 2, 0, 1}, /* RxCLK->CLK9 */ + {1, 11, 2, 0, 1}, /* COL */ + {1, 13, 2, 0, 1}, /* CRS */ + + /* ETH4 */ + {1, 18, 1, 0, 1}, /* TxD0 */ + {1, 19, 1, 0, 1}, /* TxD1 */ + {1, 20, 1, 0, 1}, /* TxD2 */ + {1, 21, 1, 0, 1}, /* TxD3 */ + {1, 27, 1, 0, 1}, /* TxER */ + {1, 30, 1, 0, 1}, /* TxEN */ + {3, 6, 2, 0, 1}, /* TxCLK->CLK8 */ + + {1, 22, 2, 0, 1}, /* RxD0 */ + {1, 23, 2, 0, 1}, /* RxD1 */ + {1, 24, 2, 0, 1}, /* RxD2 */ + {1, 25, 2, 0, 1}, /* RxD3 */ + {1, 26, 1, 0, 1}, /* RxER */ + {1, 28, 2, 0, 1}, /* Rx_DV */ + {3, 31, 2, 0, 1}, /* RxCLK->CLK7 */ + {1, 29, 2, 0, 1}, /* COL */ + {1, 31, 2, 0, 1}, /* CRS */ + + {3, 4, 3, 0, 2}, /* MDIO */ + {3, 5, 1, 0, 2}, /* MDC */ + + {0, 0, 0, 0, QE_IOP_TAB_END}, /* END of table */ +}; + +void iop_setup_miae(void) +{ + immap_t __iomem *im = (immap_t *)CONFIG_SYS_IMMR; + + /* PORTA configuration */ + out_be32(&im->qepio.ioport[0].pdat, 0x00808000); + out_be32(&im->qepio.ioport[0].podr, 0x00008000); + out_be32(&im->qepio.ioport[0].dir1, 0x40800968); + out_be32(&im->qepio.ioport[0].dir2, 0x650A0896); + out_be32(&im->qepio.ioport[0].ppar1, 0x40400204); + out_be32(&im->qepio.ioport[0].ppar2, 0x05050464); + + /* PORTB configuration */ + out_be32(&im->qepio.ioport[1].pdat, 0x00018000); + out_be32(&im->qepio.ioport[1].podr, 0x00000000); + out_be32(&im->qepio.ioport[1].dir1, 0x50A08949); + out_be32(&im->qepio.ioport[1].dir2, 0x5C0C6890); + out_be32(&im->qepio.ioport[1].ppar1, 0x50504644); + out_be32(&im->qepio.ioport[1].ppar2, 0x080800A0); + + /* PORTC configuration */ + out_be32(&im->qepio.ioport[2].pdat, 0x3D000108); + out_be32(&im->qepio.ioport[2].podr, 0x00000000); + out_be32(&im->qepio.ioport[2].dir1, 0x45518000); + out_be32(&im->qepio.ioport[2].dir2, 0xA8119561); + out_be32(&im->qepio.ioport[2].ppar1, 0x80008000); + out_be32(&im->qepio.ioport[2].ppar2, 0x00000000); + + /* PORTD configuration */ + out_be32(&im->qepio.ioport[3].pdat, 0x1000E000); + out_be32(&im->qepio.ioport[3].podr, 0x0000E000); + out_be32(&im->qepio.ioport[3].dir1, 0xFDD20800); + out_be32(&im->qepio.ioport[3].dir2, 0x54155228); + out_be32(&im->qepio.ioport[3].ppar1, 0x54A30C00); + out_be32(&im->qepio.ioport[3].ppar2, 0x00000100); +} + +void iop_setup_mcr(void) +{ + immap_t __iomem *im = (immap_t *)CONFIG_SYS_IMMR; + + /* PORTA configuration */ + out_be32(&im->qepio.ioport[0].pdat, 0x00808004); + out_be32(&im->qepio.ioport[0].podr, 0x00000000); + out_be32(&im->qepio.ioport[0].dir1, 0x40800A68); + out_be32(&im->qepio.ioport[0].dir2, 0x650A0896); + out_be32(&im->qepio.ioport[0].ppar1, 0x40400004); + out_be32(&im->qepio.ioport[0].ppar2, 0x05050444); + + /* PORTB configuration */ + out_be32(&im->qepio.ioport[1].pdat, 0x00008000); + out_be32(&im->qepio.ioport[1].podr, 0x00000004); + out_be32(&im->qepio.ioport[1].dir1, 0x50A08A4A); + out_be32(&im->qepio.ioport[1].dir2, 0x5C0C6890); + out_be32(&im->qepio.ioport[1].ppar1, 0x50504444); + out_be32(&im->qepio.ioport[1].ppar2, 0x08080080); + + /* PORTC configuration */ + out_be32(&im->qepio.ioport[2].pdat, 0x3D000018); + out_be32(&im->qepio.ioport[2].podr, 0x00000400); + out_be32(&im->qepio.ioport[2].dir1, 0x45518000); + out_be32(&im->qepio.ioport[2].dir2, 0xA8129561); + out_be32(&im->qepio.ioport[2].ppar1, 0x80008000); + out_be32(&im->qepio.ioport[2].ppar2, 0x00000000); + + /* PORTD configuration */ + out_be32(&im->qepio.ioport[3].pdat, 0x1000E000); + out_be32(&im->qepio.ioport[3].podr, 0x0000E000); + out_be32(&im->qepio.ioport[3].dir1, 0xFDD20800); + out_be32(&im->qepio.ioport[3].dir2, 0x54155228); + out_be32(&im->qepio.ioport[3].ppar1, 0x54A30C00); + out_be32(&im->qepio.ioport[3].ppar2, 0x00000100); +} + +static void iop_setup_cmpcpro(void) +{ + immap_t __iomem *im = (immap_t *)CONFIG_SYS_IMMR; + + /* PORTA configuration */ + out_be32(&im->qepio.ioport[0].pdat, 0x00000000); + out_be32(&im->qepio.ioport[0].podr, 0x00000000); + out_be32(&im->qepio.ioport[0].dir1, 0x50A84020); + out_be32(&im->qepio.ioport[0].dir2, 0x00000000); + out_be32(&im->qepio.ioport[0].ppar1, 0xF0FCC000); + out_be32(&im->qepio.ioport[0].ppar2, 0x00000000); + + /* PORTB configuration */ + out_be32(&im->qepio.ioport[1].pdat, 0x00000000); + out_be32(&im->qepio.ioport[1].podr, 0x00000000); + out_be32(&im->qepio.ioport[1].dir1, 0x00000000); + out_be32(&im->qepio.ioport[1].dir2, 0x00006800); + out_be32(&im->qepio.ioport[1].ppar1, 0x00000000); + out_be32(&im->qepio.ioport[1].ppar2, 0x00000000); + + /* PORTC configuration */ + out_be32(&im->qepio.ioport[2].pdat, 0x19000000); + out_be32(&im->qepio.ioport[2].podr, 0x00000000); + out_be32(&im->qepio.ioport[2].dir1, 0x01410000); + out_be32(&im->qepio.ioport[2].dir2, 0xA8009400); + out_be32(&im->qepio.ioport[2].ppar1, 0x00000000); + out_be32(&im->qepio.ioport[2].ppar2, 0x00000000); + + /* PORTD configuration */ + out_be32(&im->qepio.ioport[3].pdat, 0x1000E000); + out_be32(&im->qepio.ioport[3].podr, 0x0000E000); + out_be32(&im->qepio.ioport[3].dir1, 0xFD020000); + out_be32(&im->qepio.ioport[3].dir2, 0x54055000); + out_be32(&im->qepio.ioport[3].ppar1, 0x54030000); + out_be32(&im->qepio.ioport[3].ppar2, 0x00000000); +} + +int board_early_init_r(void) +{ + immap_t __iomem *im = (immap_t *)CONFIG_SYS_IMMR; + fsl_lbc_t *lbus = &im->im_lbc; + + upmconfig(UPMA, upma_table, ARRAY_SIZE(upma_table)); + + out_be32(&lbus->mamr, 0x00044440); + + /* configure LBCR register */ + out_be32(&lbus->lbcr, 0x00000500); + sync(); + + if (in_8(ADDR_FPGA_REG_ETAT) & R_ETAT_PRES_BASE) { + int i; + + /* Initialize signal PROG_FPGA_FIRMWARE */ + setbits_be32(&im->qepio.ioport[0].pdat, 0x00008000); + setbits_be32(&im->qepio.ioport[0].dir2, 0x60000002); + setbits_be32(&im->qepio.ioport[0].podr, 0x00008000); + + mdelay(1); + + /* Now read CPDATA[31] to check if FPGA is loaded */ + if (!in_be32(&im->qepio.ioport[0].pdat) & 0x00000001) { + printf("Reloading FPGA firmware.\n"); + + clrbits_be32(&im->qepio.ioport[0].pdat, 0x00008000); + udelay(1); + setbits_be32(&im->qepio.ioport[0].pdat, 0x00008000); + + /* Wait 200 msec and check DONE_FPGA_FIRMWARE */ + mdelay(200); + if (!(in_be32(&im->qepio.ioport[0].pdat) & 0x00000001)) { + for (;;) { + printf("error loading firmware.\n"); + mdelay(500); + } + } + + /* Send a reset signal and wait for 20 msec */ + out_8(ADDR_FPGA_RESET_G, in_8(ADDR_FPGA_RESET_G) | RESET_G_OK); + mdelay(20); + out_8(ADDR_FPGA_RESET_G, in_8(ADDR_FPGA_RESET_G) & ~RESET_G_OK); + } + + /* Wait 300 msec and check the reset state */ + mdelay(300); + for (i = 0; !(in_8(ADDR_FPGA_REG_ETAT) & RESET_G_OK); i++) { + for (;;) { + printf("Could not reset FPGA.\n"); + mdelay(500); + } + } + + iop_setup_common(); + + /* clocks configuration */ + out_be32(&qe_immr->qmx.cmxsi1cr_l, 0x00040004); + out_be32(&qe_immr->qmx.cmxsi1syr, 0x00000000); + } else { + iop_setup_cmpcpro(); + } + + return 0; +} + +int dram_init(int board_type) +{ + immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR; + + out_be32(&im->sysconf.ddrlaw[0].bar, CFG_SYS_DDR_SDRAM_BASE & LAWBAR_BAR); + out_be32(&im->sysconf.ddrlaw[0].ar, LAWAR_EN | ((ilog2(SZ_512M) - 1) & LAWAR_SIZE)); + + out_be32(&im->ddr.sdram_clk_cntl, CFG_SYS_DDR_CLK_CNTL); + out_be32(&im->ddr.csbnds[0].csbnds, CFG_SYS_DDR_CS0_BNDS); + out_be32(&im->ddr.cs_config[0], CFG_SYS_DDR_CS0_CONFIG); + + out_be32(&im->ddr.timing_cfg_0, CFG_SYS_DDR_TIMING_0); + out_be32(&im->ddr.timing_cfg_1, CFG_SYS_DDR_TIMING_1); + out_be32(&im->ddr.timing_cfg_2, CFG_SYS_DDR_TIMING_2); + out_be32(&im->ddr.timing_cfg_3, CFG_SYS_DDR_TIMING_3); + out_be32(&im->ddr.sdram_cfg, CFG_SYS_DDR_SDRAM_CFG); + out_be32(&im->ddr.sdram_cfg2, CFG_SYS_DDR_SDRAM_CFG2); + out_be32(&im->ddr.sdram_mode, CFG_SYS_DDR_MODE); + out_be32(&im->ddr.sdram_mode2, CFG_SYS_DDR_MODE2); + out_be32(&im->ddr.sdram_interval, CFG_SYS_DDR_INTERVAL); + udelay(200); + + setbits_be32(&im->ddr.sdram_cfg, SDRAM_CFG_MEM_EN); + + gd->ram_size = SZ_512M; + + return 0; +} + +int checkboard(void) +{ + printf("Board: "); + + /* Is a motherboard present ? */ + if (in_8(ADDR_FPGA_REG_ETAT) & R_ETAT_PRES_BASE) + return checkboard_common(); + + printf("CMPCPRO (CS GROUP)\n"); + + return 0; +} + +/* Reads MAC addresses from SPI EEPROM */ +static int setup_mac(void) +{ + uchar din[MAX_SPI_BYTES]; + int ret; + unsigned long ident = 0x08005120; + + ret = read_eeprom(din, sizeof(din)); + if (ret) + return ret; + + if (memcmp(din + EE_OFF_MAC1, &ident, sizeof(ident)) == 0) { + eth_env_set_enetaddr("ethaddr", din + EE_OFF_MAC1); + eth_env_set_enetaddr("eth3addr", din + EE_OFF_MAC1); + } + + if (memcmp(din + EE_OFF_MAC2, &ident, sizeof(ident)) == 0) + eth_env_set_enetaddr("eth1addr", din + EE_OFF_MAC2); + + if (memcmp(din + EE_OFF_MAC3, &ident, sizeof(ident)) == 0) + eth_env_set_enetaddr("eth2addr", din + EE_OFF_MAC3); + + return 0; +} + +int misc_init_r(void) +{ + /* we do not modify environment variable area if CRC is false */ + /* Verify if mother board is present */ + if (in_8(ADDR_FPGA_REG_ETAT) & R_ETAT_PRES_BASE) { + misc_init_r_common(); + } else { + env_set("config", CFG_BOARD_CMPCXXX); + env_set("hostname", CFG_BOARD_CMPCXXX); + } + + if (setup_mac()) + printf("Error retrieving mac addresses\n"); + + return 0; +} + +int ft_board_setup(void *blob, struct bd_info *bd) +{ + ft_cpu_setup(blob, bd); + + /* MIAE only */ + if (!(in_8(ADDR_FPGA_REG_ETAT) & R_ETAT_PRES_BASE)) + return 0; + + return ft_board_setup_common(blob); +} + +void ft_board_setup_phy3(void) +{ + /* switch to phy3 with gpio, we'll only use phy3 */ + immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; + + 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) + diff --git a/board/cssi/cmpcpro/cmpcpro.env b/board/cssi/cmpcpro/cmpcpro.env new file mode 100644 index 0000000000..7394b8386e --- /dev/null +++ b/board/cssi/cmpcpro/cmpcpro.env @@ -0,0 +1,8 @@ +loadaddr=0x1a00000 +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 +update=echo 'Updating ubi image'; mw.w 90000040 0x000E 1; if tftp $loadaddr $ubifile; then nand erase.chip; nand write $loadaddr 0x00 $filesize; fi; diff --git a/board/cssi/cmpcpro/nand.c b/board/cssi/cmpcpro/nand.c new file mode 100644 index 0000000000..d8b4197314 --- /dev/null +++ b/board/cssi/cmpcpro/nand.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010-2023 CS GROUP France + * Florent TRINH THAI (florent.trinh-thai@csgroup.eu) + * Stephane FRANJOU (stephane.franjou@csgroup.eu) + */ + +#include <config.h> +#include <nand.h> +#include <linux/bitops.h> +#include <linux/mtd/rawnand.h> +#include <asm/io.h> + +#define BIT_CLE BIT(6) +#define BIT_ALE BIT(5) + +static u32 nand_mask(unsigned int ctrl) +{ + return ((ctrl & NAND_CLE) ? BIT_CLE : 0) | + ((ctrl & NAND_ALE) ? BIT_ALE : 0); +} + +static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl) +{ + immap_t __iomem *immr = (immap_t *)CONFIG_SYS_IMMR; + struct nand_chip *chip = mtd_to_nand(mtdinfo); + + if (ctrl & NAND_CTRL_CHANGE) + clrsetbits_be32(&immr->qepio.ioport[2].pdat, + BIT_CLE | BIT_ALE, nand_mask(ctrl)); + + if (cmd != NAND_CMD_NONE) + out_8(chip->IO_ADDR_W, cmd); +} + +int board_nand_init(struct nand_chip *nand) +{ + nand->chip_delay = 60; + nand->ecc.mode = NAND_ECC_SOFT; + nand->cmd_ctrl = nand_hwcontrol; + + return 0; +} |