1*a430fa06SMiquel Raynal // SPDX-License-Identifier: GPL-2.0+ 2*a430fa06SMiquel Raynal /* 3*a430fa06SMiquel Raynal * (C) Copyright 2006 4*a430fa06SMiquel Raynal * KwikByte <kb9200_dev@kwikbyte.com> 5*a430fa06SMiquel Raynal * 6*a430fa06SMiquel Raynal * (C) Copyright 2009 7*a430fa06SMiquel Raynal * Matthias Kaehlcke <matthias@kaehlcke.net> 8*a430fa06SMiquel Raynal */ 9*a430fa06SMiquel Raynal 10*a430fa06SMiquel Raynal #include <common.h> 11*a430fa06SMiquel Raynal #include <asm/io.h> 12*a430fa06SMiquel Raynal #include <asm/arch/AT91RM9200.h> 13*a430fa06SMiquel Raynal #include <asm/arch/hardware.h> 14*a430fa06SMiquel Raynal 15*a430fa06SMiquel Raynal #include <nand.h> 16*a430fa06SMiquel Raynal 17*a430fa06SMiquel Raynal /* 18*a430fa06SMiquel Raynal * hardware specific access to control-lines 19*a430fa06SMiquel Raynal */ 20*a430fa06SMiquel Raynal 21*a430fa06SMiquel Raynal #define MASK_ALE (1 << 22) /* our ALE is A22 */ 22*a430fa06SMiquel Raynal #define MASK_CLE (1 << 21) /* our CLE is A21 */ 23*a430fa06SMiquel Raynal 24*a430fa06SMiquel Raynal #define KB9202_NAND_NCE (1 << 28) /* EN* on D28 */ 25*a430fa06SMiquel Raynal #define KB9202_NAND_BUSY (1 << 29) /* RB* on D29 */ 26*a430fa06SMiquel Raynal 27*a430fa06SMiquel Raynal #define KB9202_SMC2_NWS (1 << 2) 28*a430fa06SMiquel Raynal #define KB9202_SMC2_TDF (1 << 8) 29*a430fa06SMiquel Raynal #define KB9202_SMC2_RWSETUP (1 << 24) 30*a430fa06SMiquel Raynal #define KB9202_SMC2_RWHOLD (1 << 29) 31*a430fa06SMiquel Raynal 32*a430fa06SMiquel Raynal /* 33*a430fa06SMiquel Raynal * Board-specific function to access device control signals 34*a430fa06SMiquel Raynal */ 35*a430fa06SMiquel Raynal static void kb9202_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) 36*a430fa06SMiquel Raynal { 37*a430fa06SMiquel Raynal struct nand_chip *this = mtd_to_nand(mtd); 38*a430fa06SMiquel Raynal 39*a430fa06SMiquel Raynal if (ctrl & NAND_CTRL_CHANGE) { 40*a430fa06SMiquel Raynal ulong IO_ADDR_W = (ulong) this->IO_ADDR_W; 41*a430fa06SMiquel Raynal 42*a430fa06SMiquel Raynal /* clear ALE and CLE bits */ 43*a430fa06SMiquel Raynal IO_ADDR_W &= ~(MASK_ALE | MASK_CLE); 44*a430fa06SMiquel Raynal 45*a430fa06SMiquel Raynal if (ctrl & NAND_CLE) 46*a430fa06SMiquel Raynal IO_ADDR_W |= MASK_CLE; 47*a430fa06SMiquel Raynal 48*a430fa06SMiquel Raynal if (ctrl & NAND_ALE) 49*a430fa06SMiquel Raynal IO_ADDR_W |= MASK_ALE; 50*a430fa06SMiquel Raynal 51*a430fa06SMiquel Raynal this->IO_ADDR_W = (void *) IO_ADDR_W; 52*a430fa06SMiquel Raynal 53*a430fa06SMiquel Raynal if (ctrl & NAND_NCE) 54*a430fa06SMiquel Raynal writel(KB9202_NAND_NCE, AT91C_PIOC_CODR); 55*a430fa06SMiquel Raynal else 56*a430fa06SMiquel Raynal writel(KB9202_NAND_NCE, AT91C_PIOC_SODR); 57*a430fa06SMiquel Raynal } 58*a430fa06SMiquel Raynal 59*a430fa06SMiquel Raynal if (cmd != NAND_CMD_NONE) 60*a430fa06SMiquel Raynal writeb(cmd, this->IO_ADDR_W); 61*a430fa06SMiquel Raynal } 62*a430fa06SMiquel Raynal 63*a430fa06SMiquel Raynal 64*a430fa06SMiquel Raynal /* 65*a430fa06SMiquel Raynal * Board-specific function to access the device ready signal. 66*a430fa06SMiquel Raynal */ 67*a430fa06SMiquel Raynal static int kb9202_nand_ready(struct mtd_info *mtd) 68*a430fa06SMiquel Raynal { 69*a430fa06SMiquel Raynal return readl(AT91C_PIOC_PDSR) & KB9202_NAND_BUSY; 70*a430fa06SMiquel Raynal } 71*a430fa06SMiquel Raynal 72*a430fa06SMiquel Raynal 73*a430fa06SMiquel Raynal /* 74*a430fa06SMiquel Raynal * Board-specific NAND init. Copied from include/linux/mtd/nand.h for reference. 75*a430fa06SMiquel Raynal * 76*a430fa06SMiquel Raynal * struct nand_chip - NAND Private Flash Chip Data 77*a430fa06SMiquel Raynal * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device 78*a430fa06SMiquel Raynal * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device 79*a430fa06SMiquel Raynal * @hwcontrol: [BOARDSPECIFIC] hardwarespecific function for accesing control-lines 80*a430fa06SMiquel Raynal * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line 81*a430fa06SMiquel Raynal * If set to NULL no access to ready/busy is available and the ready/busy information 82*a430fa06SMiquel Raynal * is read from the chip status register 83*a430fa06SMiquel Raynal * @enable_hwecc: [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only 84*a430fa06SMiquel Raynal * be provided if a hardware ECC is available 85*a430fa06SMiquel Raynal * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines 86*a430fa06SMiquel Raynal * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR) 87*a430fa06SMiquel Raynal * @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about 88*a430fa06SMiquel Raynal * special functionality. See the defines for further explanation 89*a430fa06SMiquel Raynal */ 90*a430fa06SMiquel Raynal /* 91*a430fa06SMiquel Raynal * This routine initializes controller and GPIOs. 92*a430fa06SMiquel Raynal */ 93*a430fa06SMiquel Raynal int board_nand_init(struct nand_chip *nand) 94*a430fa06SMiquel Raynal { 95*a430fa06SMiquel Raynal unsigned int value; 96*a430fa06SMiquel Raynal 97*a430fa06SMiquel Raynal nand->ecc.mode = NAND_ECC_SOFT; 98*a430fa06SMiquel Raynal nand->cmd_ctrl = kb9202_nand_hwcontrol; 99*a430fa06SMiquel Raynal nand->dev_ready = kb9202_nand_ready; 100*a430fa06SMiquel Raynal 101*a430fa06SMiquel Raynal /* in case running outside of bootloader */ 102*a430fa06SMiquel Raynal writel(1 << AT91C_ID_PIOC, AT91C_PMC_PCER); 103*a430fa06SMiquel Raynal 104*a430fa06SMiquel Raynal /* setup nand flash access (allow ample margin) */ 105*a430fa06SMiquel Raynal /* 4 wait states, 1 setup, 1 hold, 1 float for 8-bit device */ 106*a430fa06SMiquel Raynal writel(AT91C_SMC2_WSEN | KB9202_SMC2_NWS | KB9202_SMC2_TDF | 107*a430fa06SMiquel Raynal AT91C_SMC2_DBW_8 | KB9202_SMC2_RWSETUP | KB9202_SMC2_RWHOLD, 108*a430fa06SMiquel Raynal AT91C_SMC_CSR3); 109*a430fa06SMiquel Raynal 110*a430fa06SMiquel Raynal /* enable internal NAND controller */ 111*a430fa06SMiquel Raynal value = readl(AT91C_EBI_CSA); 112*a430fa06SMiquel Raynal value |= AT91C_EBI_CS3A_SMC_SmartMedia; 113*a430fa06SMiquel Raynal writel(value, AT91C_EBI_CSA); 114*a430fa06SMiquel Raynal 115*a430fa06SMiquel Raynal /* enable SMOE/SMWE */ 116*a430fa06SMiquel Raynal writel(AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE, AT91C_PIOC_ASR); 117*a430fa06SMiquel Raynal writel(AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE, AT91C_PIOC_PDR); 118*a430fa06SMiquel Raynal writel(AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE, AT91C_PIOC_OER); 119*a430fa06SMiquel Raynal 120*a430fa06SMiquel Raynal /* set NCE to high */ 121*a430fa06SMiquel Raynal writel(KB9202_NAND_NCE, AT91C_PIOC_SODR); 122*a430fa06SMiquel Raynal 123*a430fa06SMiquel Raynal /* disable output on pin connected to the busy line of the NAND */ 124*a430fa06SMiquel Raynal writel(KB9202_NAND_BUSY, AT91C_PIOC_ODR); 125*a430fa06SMiquel Raynal 126*a430fa06SMiquel Raynal /* enable the PIO to control NCE and BUSY */ 127*a430fa06SMiquel Raynal writel(KB9202_NAND_NCE | KB9202_NAND_BUSY, AT91C_PIOC_PER); 128*a430fa06SMiquel Raynal 129*a430fa06SMiquel Raynal /* enable output for NCE */ 130*a430fa06SMiquel Raynal writel(KB9202_NAND_NCE, AT91C_PIOC_OER); 131*a430fa06SMiquel Raynal 132*a430fa06SMiquel Raynal return (0); 133*a430fa06SMiquel Raynal } 134