Commit 77b93e5e9b28328f76556e0c0b94889df47077d7
Committed by
Tom Rini
1 parent
d9098ee55f
Exists in
v2017.01-smarct4x
and in
25 other branches
mtd: OneNAND: allow board init function fail
Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
Showing 6 changed files with 28 additions and 20 deletions Inline Diff
board/micronas/vct/ebi_onenand.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2008 Stefan Roese <sr@denx.de>, DENX Software Engineering | 2 | * (C) Copyright 2008 Stefan Roese <sr@denx.de>, DENX Software Engineering |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: GPL-2.0+ | 4 | * SPDX-License-Identifier: GPL-2.0+ |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <common.h> | 7 | #include <common.h> |
8 | #include <asm/io.h> | 8 | #include <asm/io.h> |
9 | #include <linux/mtd/mtd.h> | 9 | #include <linux/mtd/mtd.h> |
10 | #include <linux/mtd/onenand.h> | 10 | #include <linux/mtd/onenand.h> |
11 | #include "vct.h" | 11 | #include "vct.h" |
12 | 12 | ||
13 | #define BURST_SIZE_WORDS 4 | 13 | #define BURST_SIZE_WORDS 4 |
14 | 14 | ||
15 | static u16 ebi_nand_read_word(void __iomem *addr) | 15 | static u16 ebi_nand_read_word(void __iomem *addr) |
16 | { | 16 | { |
17 | reg_write(EBI_CPU_IO_ACCS(EBI_BASE), (EXT_DEVICE_CHANNEL_2 | (u32)addr)); | 17 | reg_write(EBI_CPU_IO_ACCS(EBI_BASE), (EXT_DEVICE_CHANNEL_2 | (u32)addr)); |
18 | ebi_wait(); | 18 | ebi_wait(); |
19 | 19 | ||
20 | return reg_read(EBI_IO_ACCS_DATA(EBI_BASE)) >> 16; | 20 | return reg_read(EBI_IO_ACCS_DATA(EBI_BASE)) >> 16; |
21 | } | 21 | } |
22 | 22 | ||
23 | static void ebi_nand_write_word(u16 data, void __iomem * addr) | 23 | static void ebi_nand_write_word(u16 data, void __iomem * addr) |
24 | { | 24 | { |
25 | ebi_wait(); | 25 | ebi_wait(); |
26 | reg_write(EBI_IO_ACCS_DATA(EBI_BASE), (data << 16)); | 26 | reg_write(EBI_IO_ACCS_DATA(EBI_BASE), (data << 16)); |
27 | reg_write(EBI_CPU_IO_ACCS(EBI_BASE), | 27 | reg_write(EBI_CPU_IO_ACCS(EBI_BASE), |
28 | EXT_DEVICE_CHANNEL_2 | EBI_CPU_WRITE | (u32)addr); | 28 | EXT_DEVICE_CHANNEL_2 | EBI_CPU_WRITE | (u32)addr); |
29 | ebi_wait(); | 29 | ebi_wait(); |
30 | } | 30 | } |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * EBI initialization for OneNAND FLASH access | 33 | * EBI initialization for OneNAND FLASH access |
34 | */ | 34 | */ |
35 | int ebi_init_onenand(void) | 35 | int ebi_init_onenand(void) |
36 | { | 36 | { |
37 | reg_write(EBI_DEV1_CONFIG1(EBI_BASE), 0x83000); | 37 | reg_write(EBI_DEV1_CONFIG1(EBI_BASE), 0x83000); |
38 | 38 | ||
39 | reg_write(EBI_DEV2_CONFIG1(EBI_BASE), 0x00403002); | 39 | reg_write(EBI_DEV2_CONFIG1(EBI_BASE), 0x00403002); |
40 | reg_write(EBI_DEV2_CONFIG2(EBI_BASE), 0x50); | 40 | reg_write(EBI_DEV2_CONFIG2(EBI_BASE), 0x50); |
41 | 41 | ||
42 | reg_write(EBI_DEV3_CONFIG1(EBI_BASE), 0x00403002); | 42 | reg_write(EBI_DEV3_CONFIG1(EBI_BASE), 0x00403002); |
43 | reg_write(EBI_DEV3_CONFIG2(EBI_BASE), 0x0); /* byte/word ordering */ | 43 | reg_write(EBI_DEV3_CONFIG2(EBI_BASE), 0x0); /* byte/word ordering */ |
44 | 44 | ||
45 | reg_write(EBI_DEV2_TIM1_RD1(EBI_BASE), 0x00504000); | 45 | reg_write(EBI_DEV2_TIM1_RD1(EBI_BASE), 0x00504000); |
46 | reg_write(EBI_DEV2_TIM1_RD2(EBI_BASE), 0x00001000); | 46 | reg_write(EBI_DEV2_TIM1_RD2(EBI_BASE), 0x00001000); |
47 | reg_write(EBI_DEV2_TIM1_WR1(EBI_BASE), 0x12002223); | 47 | reg_write(EBI_DEV2_TIM1_WR1(EBI_BASE), 0x12002223); |
48 | reg_write(EBI_DEV2_TIM1_WR2(EBI_BASE), 0x3FC02220); | 48 | reg_write(EBI_DEV2_TIM1_WR2(EBI_BASE), 0x3FC02220); |
49 | reg_write(EBI_DEV3_TIM1_RD1(EBI_BASE), 0x00504000); | 49 | reg_write(EBI_DEV3_TIM1_RD1(EBI_BASE), 0x00504000); |
50 | reg_write(EBI_DEV3_TIM1_RD2(EBI_BASE), 0x00001000); | 50 | reg_write(EBI_DEV3_TIM1_RD2(EBI_BASE), 0x00001000); |
51 | reg_write(EBI_DEV3_TIM1_WR1(EBI_BASE), 0x05001000); | 51 | reg_write(EBI_DEV3_TIM1_WR1(EBI_BASE), 0x05001000); |
52 | reg_write(EBI_DEV3_TIM1_WR2(EBI_BASE), 0x00010200); | 52 | reg_write(EBI_DEV3_TIM1_WR2(EBI_BASE), 0x00010200); |
53 | 53 | ||
54 | reg_write(EBI_DEV2_TIM_EXT(EBI_BASE), 0xFFF00000); | 54 | reg_write(EBI_DEV2_TIM_EXT(EBI_BASE), 0xFFF00000); |
55 | reg_write(EBI_DEV2_EXT_ACC(EBI_BASE), 0x0FFFFFFF); | 55 | reg_write(EBI_DEV2_EXT_ACC(EBI_BASE), 0x0FFFFFFF); |
56 | 56 | ||
57 | reg_write(EBI_DEV3_TIM_EXT(EBI_BASE), 0xFFF00000); | 57 | reg_write(EBI_DEV3_TIM_EXT(EBI_BASE), 0xFFF00000); |
58 | reg_write(EBI_DEV3_EXT_ACC(EBI_BASE), 0x0FFFFFFF); | 58 | reg_write(EBI_DEV3_EXT_ACC(EBI_BASE), 0x0FFFFFFF); |
59 | 59 | ||
60 | /* prepare DMA configuration for EBI */ | 60 | /* prepare DMA configuration for EBI */ |
61 | reg_write(EBI_DEV3_FIFO_CONFIG(EBI_BASE), 0x0101ff00); | 61 | reg_write(EBI_DEV3_FIFO_CONFIG(EBI_BASE), 0x0101ff00); |
62 | 62 | ||
63 | /* READ only no byte order change, TAG 1 used */ | 63 | /* READ only no byte order change, TAG 1 used */ |
64 | reg_write(EBI_DEV3_DMA_CONFIG2(EBI_BASE), 0x00000004); | 64 | reg_write(EBI_DEV3_DMA_CONFIG2(EBI_BASE), 0x00000004); |
65 | 65 | ||
66 | reg_write(EBI_TAG1_SYS_ID(EBI_BASE), 0x0); /* SCC DMA channel 0 */ | 66 | reg_write(EBI_TAG1_SYS_ID(EBI_BASE), 0x0); /* SCC DMA channel 0 */ |
67 | reg_write(EBI_TAG2_SYS_ID(EBI_BASE), 0x1); | 67 | reg_write(EBI_TAG2_SYS_ID(EBI_BASE), 0x1); |
68 | reg_write(EBI_TAG3_SYS_ID(EBI_BASE), 0x2); | 68 | reg_write(EBI_TAG3_SYS_ID(EBI_BASE), 0x2); |
69 | reg_write(EBI_TAG4_SYS_ID(EBI_BASE), 0x3); | 69 | reg_write(EBI_TAG4_SYS_ID(EBI_BASE), 0x3); |
70 | 70 | ||
71 | return 0; | 71 | return 0; |
72 | } | 72 | } |
73 | 73 | ||
74 | static void *memcpy_16_from_onenand(void *dst, const void *src, unsigned int len) | 74 | static void *memcpy_16_from_onenand(void *dst, const void *src, unsigned int len) |
75 | { | 75 | { |
76 | void *ret = dst; | 76 | void *ret = dst; |
77 | u16 *d = dst; | 77 | u16 *d = dst; |
78 | u16 *s = (u16 *)src; | 78 | u16 *s = (u16 *)src; |
79 | 79 | ||
80 | len >>= 1; | 80 | len >>= 1; |
81 | while (len-- > 0) | 81 | while (len-- > 0) |
82 | *d++ = ebi_nand_read_word(s++); | 82 | *d++ = ebi_nand_read_word(s++); |
83 | 83 | ||
84 | return ret; | 84 | return ret; |
85 | } | 85 | } |
86 | 86 | ||
87 | static void *memcpy_32_from_onenand(void *dst, const void *src, unsigned int len) | 87 | static void *memcpy_32_from_onenand(void *dst, const void *src, unsigned int len) |
88 | { | 88 | { |
89 | void *ret = dst; | 89 | void *ret = dst; |
90 | u32 *d = (u32 *)dst; | 90 | u32 *d = (u32 *)dst; |
91 | u32 s = (u32)src; | 91 | u32 s = (u32)src; |
92 | u32 bytes_per_block = BURST_SIZE_WORDS * sizeof(int); | 92 | u32 bytes_per_block = BURST_SIZE_WORDS * sizeof(int); |
93 | u32 n_blocks = len / bytes_per_block; | 93 | u32 n_blocks = len / bytes_per_block; |
94 | u32 block = 0; | 94 | u32 block = 0; |
95 | u32 burst_word; | 95 | u32 burst_word; |
96 | 96 | ||
97 | for (block = 0; block < n_blocks; block++) { | 97 | for (block = 0; block < n_blocks; block++) { |
98 | /* Trigger read channel 3 */ | 98 | /* Trigger read channel 3 */ |
99 | reg_write(EBI_CPU_IO_ACCS(EBI_BASE), | 99 | reg_write(EBI_CPU_IO_ACCS(EBI_BASE), |
100 | (EXT_DEVICE_CHANNEL_3 | (s + (block * bytes_per_block)))); | 100 | (EXT_DEVICE_CHANNEL_3 | (s + (block * bytes_per_block)))); |
101 | /* Poll status to see whether read has finished */ | 101 | /* Poll status to see whether read has finished */ |
102 | ebi_wait(); | 102 | ebi_wait(); |
103 | 103 | ||
104 | /* Squirrel the data away in a safe place */ | 104 | /* Squirrel the data away in a safe place */ |
105 | for (burst_word = 0; burst_word < BURST_SIZE_WORDS; burst_word++) | 105 | for (burst_word = 0; burst_word < BURST_SIZE_WORDS; burst_word++) |
106 | *d++ = reg_read(EBI_IO_ACCS_DATA(EBI_BASE)); | 106 | *d++ = reg_read(EBI_IO_ACCS_DATA(EBI_BASE)); |
107 | } | 107 | } |
108 | 108 | ||
109 | return ret; | 109 | return ret; |
110 | } | 110 | } |
111 | 111 | ||
112 | static void *memcpy_16_to_onenand(void *dst, const void *src, unsigned int len) | 112 | static void *memcpy_16_to_onenand(void *dst, const void *src, unsigned int len) |
113 | { | 113 | { |
114 | void *ret = dst; | 114 | void *ret = dst; |
115 | u16 *d = dst; | 115 | u16 *d = dst; |
116 | u16 *s = (u16 *)src; | 116 | u16 *s = (u16 *)src; |
117 | 117 | ||
118 | len >>= 1; | 118 | len >>= 1; |
119 | while (len-- > 0) | 119 | while (len-- > 0) |
120 | ebi_nand_write_word(*s++, d++); | 120 | ebi_nand_write_word(*s++, d++); |
121 | 121 | ||
122 | return ret; | 122 | return ret; |
123 | } | 123 | } |
124 | 124 | ||
125 | static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area) | 125 | static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area) |
126 | { | 126 | { |
127 | struct onenand_chip *this = mtd->priv; | 127 | struct onenand_chip *this = mtd->priv; |
128 | 128 | ||
129 | if (ONENAND_CURRENT_BUFFERRAM(this)) { | 129 | if (ONENAND_CURRENT_BUFFERRAM(this)) { |
130 | if (area == ONENAND_DATARAM) | 130 | if (area == ONENAND_DATARAM) |
131 | return mtd->writesize; | 131 | return mtd->writesize; |
132 | if (area == ONENAND_SPARERAM) | 132 | if (area == ONENAND_SPARERAM) |
133 | return mtd->oobsize; | 133 | return mtd->oobsize; |
134 | } | 134 | } |
135 | 135 | ||
136 | return 0; | 136 | return 0; |
137 | } | 137 | } |
138 | 138 | ||
139 | static int ebi_read_bufferram(struct mtd_info *mtd, loff_t addr, int area, | 139 | static int ebi_read_bufferram(struct mtd_info *mtd, loff_t addr, int area, |
140 | unsigned char *buffer, int offset, | 140 | unsigned char *buffer, int offset, |
141 | size_t count) | 141 | size_t count) |
142 | { | 142 | { |
143 | struct onenand_chip *this = mtd->priv; | 143 | struct onenand_chip *this = mtd->priv; |
144 | void __iomem *bufferram; | 144 | void __iomem *bufferram; |
145 | 145 | ||
146 | bufferram = this->base + area; | 146 | bufferram = this->base + area; |
147 | bufferram += onenand_bufferram_offset(mtd, area); | 147 | bufferram += onenand_bufferram_offset(mtd, area); |
148 | 148 | ||
149 | if (count < 4) | 149 | if (count < 4) |
150 | memcpy_16_from_onenand(buffer, bufferram + offset, count); | 150 | memcpy_16_from_onenand(buffer, bufferram + offset, count); |
151 | else | 151 | else |
152 | memcpy_32_from_onenand(buffer, bufferram + offset, count); | 152 | memcpy_32_from_onenand(buffer, bufferram + offset, count); |
153 | 153 | ||
154 | return 0; | 154 | return 0; |
155 | } | 155 | } |
156 | 156 | ||
157 | static int ebi_write_bufferram(struct mtd_info *mtd, loff_t addr, int area, | 157 | static int ebi_write_bufferram(struct mtd_info *mtd, loff_t addr, int area, |
158 | const unsigned char *buffer, int offset, | 158 | const unsigned char *buffer, int offset, |
159 | size_t count) | 159 | size_t count) |
160 | { | 160 | { |
161 | struct onenand_chip *this = mtd->priv; | 161 | struct onenand_chip *this = mtd->priv; |
162 | void __iomem *bufferram; | 162 | void __iomem *bufferram; |
163 | 163 | ||
164 | bufferram = this->base + area; | 164 | bufferram = this->base + area; |
165 | bufferram += onenand_bufferram_offset(mtd, area); | 165 | bufferram += onenand_bufferram_offset(mtd, area); |
166 | 166 | ||
167 | memcpy_16_to_onenand(bufferram + offset, buffer, count); | 167 | memcpy_16_to_onenand(bufferram + offset, buffer, count); |
168 | 168 | ||
169 | return 0; | 169 | return 0; |
170 | } | 170 | } |
171 | 171 | ||
172 | void onenand_board_init(struct mtd_info *mtd) | 172 | int onenand_board_init(struct mtd_info *mtd) |
173 | { | 173 | { |
174 | struct onenand_chip *chip = mtd->priv; | 174 | struct onenand_chip *chip = mtd->priv; |
175 | 175 | ||
176 | /* | 176 | /* |
177 | * Insert board specific OneNAND access functions | 177 | * Insert board specific OneNAND access functions |
178 | */ | 178 | */ |
179 | chip->read_word = ebi_nand_read_word; | 179 | chip->read_word = ebi_nand_read_word; |
180 | chip->write_word = ebi_nand_write_word; | 180 | chip->write_word = ebi_nand_write_word; |
181 | 181 | ||
182 | chip->read_bufferram = ebi_read_bufferram; | 182 | chip->read_bufferram = ebi_read_bufferram; |
183 | chip->write_bufferram = ebi_write_bufferram; | 183 | chip->write_bufferram = ebi_write_bufferram; |
184 | |||
185 | return 0; | ||
184 | } | 186 | } |
185 | 187 |
board/samsung/goni/onenand.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2008-2009 Samsung Electronics | 2 | * Copyright (C) 2008-2009 Samsung Electronics |
3 | * Kyungmin Park <kyungmin.park@samsung.com> | 3 | * Kyungmin Park <kyungmin.park@samsung.com> |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <common.h> | 8 | #include <common.h> |
9 | #include <linux/mtd/mtd.h> | 9 | #include <linux/mtd/mtd.h> |
10 | #include <linux/mtd/onenand.h> | 10 | #include <linux/mtd/onenand.h> |
11 | #include <linux/mtd/samsung_onenand.h> | 11 | #include <linux/mtd/samsung_onenand.h> |
12 | #include <onenand_uboot.h> | 12 | #include <onenand_uboot.h> |
13 | 13 | ||
14 | void onenand_board_init(struct mtd_info *mtd) | 14 | int onenand_board_init(struct mtd_info *mtd) |
15 | { | 15 | { |
16 | struct onenand_chip *this = mtd->priv; | 16 | struct onenand_chip *this = mtd->priv; |
17 | 17 | ||
18 | this->base = (void *)CONFIG_SYS_ONENAND_BASE; | 18 | this->base = (void *)CONFIG_SYS_ONENAND_BASE; |
19 | this->options |= ONENAND_RUNTIME_BADBLOCK_CHECK; | 19 | this->options |= ONENAND_RUNTIME_BADBLOCK_CHECK; |
20 | this->chip_probe = s5pc110_chip_probe; | 20 | this->chip_probe = s5pc110_chip_probe; |
21 | |||
22 | return 0; | ||
21 | } | 23 | } |
22 | 24 |
board/samsung/smdkc100/onenand.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2008-2009 Samsung Electronics | 2 | * Copyright (C) 2008-2009 Samsung Electronics |
3 | * Kyungmin Park <kyungmin.park@samsung.com> | 3 | * Kyungmin Park <kyungmin.park@samsung.com> |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <common.h> | 8 | #include <common.h> |
9 | #include <linux/compat.h> | 9 | #include <linux/compat.h> |
10 | #include <linux/mtd/mtd.h> | 10 | #include <linux/mtd/mtd.h> |
11 | #include <linux/mtd/onenand.h> | 11 | #include <linux/mtd/onenand.h> |
12 | #include <linux/mtd/samsung_onenand.h> | 12 | #include <linux/mtd/samsung_onenand.h> |
13 | 13 | ||
14 | #include <onenand_uboot.h> | 14 | #include <onenand_uboot.h> |
15 | 15 | ||
16 | #include <asm/io.h> | 16 | #include <asm/io.h> |
17 | #include <asm/arch/clock.h> | 17 | #include <asm/arch/clock.h> |
18 | 18 | ||
19 | void onenand_board_init(struct mtd_info *mtd) | 19 | int onenand_board_init(struct mtd_info *mtd) |
20 | { | 20 | { |
21 | struct onenand_chip *this = mtd->priv; | 21 | struct onenand_chip *this = mtd->priv; |
22 | struct s5pc100_clock *clk = | 22 | struct s5pc100_clock *clk = |
23 | (struct s5pc100_clock *)samsung_get_base_clock(); | 23 | (struct s5pc100_clock *)samsung_get_base_clock(); |
24 | struct samsung_onenand *onenand; | 24 | struct samsung_onenand *onenand; |
25 | int value; | 25 | int value; |
26 | 26 | ||
27 | this->base = (void *)S5PC100_ONENAND_BASE; | 27 | this->base = (void *)S5PC100_ONENAND_BASE; |
28 | onenand = (struct samsung_onenand *)this->base; | 28 | onenand = (struct samsung_onenand *)this->base; |
29 | 29 | ||
30 | /* D0 Domain memory clock gating */ | 30 | /* D0 Domain memory clock gating */ |
31 | value = readl(&clk->gate_d01); | 31 | value = readl(&clk->gate_d01); |
32 | value &= ~(1 << 2); /* CLK_ONENANDC */ | 32 | value &= ~(1 << 2); /* CLK_ONENANDC */ |
33 | value |= (1 << 2); | 33 | value |= (1 << 2); |
34 | writel(value, &clk->gate_d01); | 34 | writel(value, &clk->gate_d01); |
35 | 35 | ||
36 | value = readl(&clk->src0); | 36 | value = readl(&clk->src0); |
37 | value &= ~(1 << 24); /* MUX_1nand: 0 from HCLKD0 */ | 37 | value &= ~(1 << 24); /* MUX_1nand: 0 from HCLKD0 */ |
38 | value &= ~(1 << 20); /* MUX_HREF: 0 from FIN_27M */ | 38 | value &= ~(1 << 20); /* MUX_HREF: 0 from FIN_27M */ |
39 | writel(value, &clk->src0); | 39 | writel(value, &clk->src0); |
40 | 40 | ||
41 | value = readl(&clk->div1); | 41 | value = readl(&clk->div1); |
42 | value &= ~(3 << 16); /* PCLKD1_RATIO */ | 42 | value &= ~(3 << 16); /* PCLKD1_RATIO */ |
43 | value |= (1 << 16); | 43 | value |= (1 << 16); |
44 | writel(value, &clk->div1); | 44 | writel(value, &clk->div1); |
45 | 45 | ||
46 | writel(ONENAND_MEM_RESET_COLD, &onenand->mem_reset); | 46 | writel(ONENAND_MEM_RESET_COLD, &onenand->mem_reset); |
47 | 47 | ||
48 | while (!(readl(&onenand->int_err_stat) & RST_CMP)) | 48 | while (!(readl(&onenand->int_err_stat) & RST_CMP)) |
49 | continue; | 49 | continue; |
50 | 50 | ||
51 | writel(RST_CMP, &onenand->int_err_ack); | 51 | writel(RST_CMP, &onenand->int_err_ack); |
52 | 52 | ||
53 | /* | 53 | /* |
54 | * Access_Clock [2:0] | 54 | * Access_Clock [2:0] |
55 | * 166 MHz, 134 Mhz : 3 | 55 | * 166 MHz, 134 Mhz : 3 |
56 | * 100 Mhz, 60 Mhz : 2 | 56 | * 100 Mhz, 60 Mhz : 2 |
57 | */ | 57 | */ |
58 | writel(0x3, &onenand->acc_clock); | 58 | writel(0x3, &onenand->acc_clock); |
59 | 59 | ||
60 | writel(INT_ERR_ALL, &onenand->int_err_mask); | 60 | writel(INT_ERR_ALL, &onenand->int_err_mask); |
61 | writel(1 << 0, &onenand->int_pin_en); /* Enable */ | 61 | writel(1 << 0, &onenand->int_pin_en); /* Enable */ |
62 | 62 | ||
63 | value = readl(&onenand->int_err_mask); | 63 | value = readl(&onenand->int_err_mask); |
64 | value &= ~RDY_ACT; | 64 | value &= ~RDY_ACT; |
65 | writel(value, &onenand->int_err_mask); | 65 | writel(value, &onenand->int_err_mask); |
66 | 66 | ||
67 | s3c_onenand_init(mtd); | 67 | s3c_onenand_init(mtd); |
68 | |||
69 | return 0; | ||
68 | } | 70 | } |
69 | 71 |
board/samsung/universal_c210/onenand.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2010 Samsung Electronics | 2 | * Copyright (C) 2010 Samsung Electronics |
3 | * Kyungmin Park <kyungmin.park@samsung.com> | 3 | * Kyungmin Park <kyungmin.park@samsung.com> |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <common.h> | 8 | #include <common.h> |
9 | #include <linux/mtd/mtd.h> | 9 | #include <linux/mtd/mtd.h> |
10 | #include <linux/mtd/onenand.h> | 10 | #include <linux/mtd/onenand.h> |
11 | #include <linux/mtd/samsung_onenand.h> | 11 | #include <linux/mtd/samsung_onenand.h> |
12 | 12 | ||
13 | void onenand_board_init(struct mtd_info *mtd) | 13 | int onenand_board_init(struct mtd_info *mtd) |
14 | { | 14 | { |
15 | struct onenand_chip *this = mtd->priv; | 15 | struct onenand_chip *this = mtd->priv; |
16 | 16 | ||
17 | this->base = (void *)CONFIG_SYS_ONENAND_BASE; | 17 | this->base = (void *)CONFIG_SYS_ONENAND_BASE; |
18 | this->options |= ONENAND_RUNTIME_BADBLOCK_CHECK; | 18 | this->options |= ONENAND_RUNTIME_BADBLOCK_CHECK; |
19 | this->chip_probe = s5pc210_chip_probe; | 19 | this->chip_probe = s5pc210_chip_probe; |
20 | |||
21 | return 0; | ||
20 | } | 22 | } |
21 | 23 |
drivers/mtd/onenand/onenand_uboot.c
1 | /* | 1 | /* |
2 | * drivers/mtd/onenand/onenand_uboot.c | 2 | * drivers/mtd/onenand/onenand_uboot.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005-2008 Samsung Electronics | 4 | * Copyright (C) 2005-2008 Samsung Electronics |
5 | * Kyungmin Park <kyungmin.park@samsung.com> | 5 | * Kyungmin Park <kyungmin.park@samsung.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | /* | 12 | /* |
13 | * OneNAND initialization at U-Boot | 13 | * OneNAND initialization at U-Boot |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <common.h> | 16 | #include <common.h> |
17 | #include <linux/compat.h> | 17 | #include <linux/compat.h> |
18 | #include <linux/mtd/mtd.h> | 18 | #include <linux/mtd/mtd.h> |
19 | #include <linux/mtd/onenand.h> | 19 | #include <linux/mtd/onenand.h> |
20 | 20 | ||
21 | struct mtd_info onenand_mtd; | 21 | struct mtd_info onenand_mtd; |
22 | struct onenand_chip onenand_chip; | 22 | struct onenand_chip onenand_chip; |
23 | static __attribute__((unused)) char dev_name[] = "onenand0"; | 23 | static __attribute__((unused)) char dev_name[] = "onenand0"; |
24 | 24 | ||
25 | void onenand_init(void) | 25 | void onenand_init(void) |
26 | { | 26 | { |
27 | int err = 0; | ||
27 | memset(&onenand_mtd, 0, sizeof(struct mtd_info)); | 28 | memset(&onenand_mtd, 0, sizeof(struct mtd_info)); |
28 | memset(&onenand_chip, 0, sizeof(struct onenand_chip)); | 29 | memset(&onenand_chip, 0, sizeof(struct onenand_chip)); |
29 | 30 | ||
30 | onenand_mtd.priv = &onenand_chip; | 31 | onenand_mtd.priv = &onenand_chip; |
31 | 32 | ||
32 | #ifdef CONFIG_USE_ONENAND_BOARD_INIT | 33 | #ifdef CONFIG_USE_ONENAND_BOARD_INIT |
33 | /* | 34 | /* It's used for some board init required */ |
34 | * It's used for some board init required | 35 | err = onenand_board_init(&onenand_mtd); |
35 | */ | ||
36 | onenand_board_init(&onenand_mtd); | ||
37 | #else | 36 | #else |
38 | onenand_chip.base = (void *) CONFIG_SYS_ONENAND_BASE; | 37 | onenand_chip.base = (void *) CONFIG_SYS_ONENAND_BASE; |
39 | #endif | 38 | #endif |
40 | 39 | ||
41 | onenand_scan(&onenand_mtd, 1); | 40 | if (!err && !(onenand_scan(&onenand_mtd, 1))) { |
42 | 41 | ||
43 | if (onenand_chip.device_id & DEVICE_IS_FLEXONENAND) | 42 | if (onenand_chip.device_id & DEVICE_IS_FLEXONENAND) |
44 | puts("Flex-"); | 43 | puts("Flex-"); |
45 | puts("OneNAND: "); | 44 | puts("OneNAND: "); |
46 | print_size(onenand_chip.chipsize, "\n"); | ||
47 | 45 | ||
48 | #ifdef CONFIG_MTD_DEVICE | 46 | #ifdef CONFIG_MTD_DEVICE |
49 | /* | 47 | /* |
50 | * Add MTD device so that we can reference it later | 48 | * Add MTD device so that we can reference it later |
51 | * via the mtdcore infrastructure (e.g. ubi). | 49 | * via the mtdcore infrastructure (e.g. ubi). |
52 | */ | 50 | */ |
53 | onenand_mtd.name = dev_name; | 51 | onenand_mtd.name = dev_name; |
54 | add_mtd_device(&onenand_mtd); | 52 | add_mtd_device(&onenand_mtd); |
55 | #endif | 53 | #endif |
54 | } |
include/onenand_uboot.h
1 | /* | 1 | /* |
2 | * Header file for OneNAND support for U-Boot | 2 | * Header file for OneNAND support for U-Boot |
3 | * | 3 | * |
4 | * Adaptation from kernel to U-Boot | 4 | * Adaptation from kernel to U-Boot |
5 | * | 5 | * |
6 | * Copyright (C) 2005-2007 Samsung Electronics | 6 | * Copyright (C) 2005-2007 Samsung Electronics |
7 | * Kyungmin Park <kyungmin.park@samsung.com> | 7 | * Kyungmin Park <kyungmin.park@samsung.com> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #ifndef __UBOOT_ONENAND_H | 14 | #ifndef __UBOOT_ONENAND_H |
15 | #define __UBOOT_ONENAND_H | 15 | #define __UBOOT_ONENAND_H |
16 | 16 | ||
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | 18 | ||
19 | /* Forward declarations */ | 19 | /* Forward declarations */ |
20 | struct mtd_info; | 20 | struct mtd_info; |
21 | struct mtd_oob_ops; | 21 | struct mtd_oob_ops; |
22 | struct erase_info; | 22 | struct erase_info; |
23 | struct onenand_chip; | 23 | struct onenand_chip; |
24 | 24 | ||
25 | extern struct mtd_info onenand_mtd; | 25 | extern struct mtd_info onenand_mtd; |
26 | extern struct onenand_chip onenand_chip; | 26 | extern struct onenand_chip onenand_chip; |
27 | 27 | ||
28 | /* board */ | 28 | /* board */ |
29 | extern void onenand_board_init(struct mtd_info *); | 29 | extern int onenand_board_init(struct mtd_info *); |
30 | 30 | ||
31 | /* Functions */ | 31 | /* Functions */ |
32 | extern void onenand_init(void); | 32 | extern void onenand_init(void); |
33 | extern int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, | 33 | extern int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, |
34 | size_t * retlen, u_char * buf); | 34 | size_t * retlen, u_char * buf); |
35 | extern int onenand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); | 35 | extern int onenand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); |
36 | extern int onenand_write(struct mtd_info *mtd, loff_t from, size_t len, | 36 | extern int onenand_write(struct mtd_info *mtd, loff_t from, size_t len, |
37 | size_t * retlen, const u_char * buf); | 37 | size_t * retlen, const u_char * buf); |
38 | extern int onenand_erase(struct mtd_info *mtd, struct erase_info *instr); | 38 | extern int onenand_erase(struct mtd_info *mtd, struct erase_info *instr); |
39 | 39 | ||
40 | extern char *onenand_print_device_info(int device, int version); | 40 | extern char *onenand_print_device_info(int device, int version); |
41 | 41 | ||
42 | extern unsigned onenand_block(struct onenand_chip *this, loff_t addr); | 42 | extern unsigned onenand_block(struct onenand_chip *this, loff_t addr); |
43 | 43 | ||
44 | extern loff_t onenand_addr(struct onenand_chip *this, int block); | 44 | extern loff_t onenand_addr(struct onenand_chip *this, int block); |
45 | 45 | ||
46 | extern int flexonenand_region(struct mtd_info *mtd, loff_t addr); | 46 | extern int flexonenand_region(struct mtd_info *mtd, loff_t addr); |
47 | 47 | ||
48 | extern int flexonenand_set_boundary(struct mtd_info *mtd, int die, | 48 | extern int flexonenand_set_boundary(struct mtd_info *mtd, int die, |
49 | int boundary, int lock); | 49 | int boundary, int lock); |
50 | 50 | ||
51 | /* SPL */ | 51 | /* SPL */ |
52 | int onenand_spl_read_block(int block, int offset, int len, void *dst); | 52 | int onenand_spl_read_block(int block, int offset, int len, void *dst); |
53 | void onenand_spl_load_image(uint32_t offs, uint32_t size, void *dst); | 53 | void onenand_spl_load_image(uint32_t offs, uint32_t size, void *dst); |
54 | 54 | ||
55 | #endif /* __UBOOT_ONENAND_H */ | 55 | #endif /* __UBOOT_ONENAND_H */ |
56 | 56 |