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