1 /* $NetBSD: nand_samsung.c,v 1.9 2012/11/03 12:12:48 ahoka Exp $ */
2
3 /*-
4 * Copyright (c) 2012 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Adam Hoka.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Device specific functions for legacy Samsung NAND chips
34 *
35 * Currently supported:
36 * K9XXG08UXA
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: nand_samsung.c,v 1.9 2012/11/03 12:12:48 ahoka Exp $");
41
42 #include "nand.h"
43 #include "onfi.h"
44
45 enum {
46 NAND_SAMSUNG_PAGEMASK = 0x3,
47 NAND_SAMSUNG_SPAREMASK = 0x1 << 2,
48 NAND_SAMSUNG_BLOCKMASK = 0x3 << 4,
49 NAND_SAMSUNG_BITSMASK = 0x1 << 6
50 };
51
52 enum {
53 NAND_SAMSUNG_PLANENUMMASK = 0x3 << 2,
54 NAND_SAMSUNG_PLANESIZEMASK = 0x7 << 4
55 };
56
57 int
nand_read_parameters_samsung(device_t self,struct nand_chip * const chip)58 nand_read_parameters_samsung(device_t self, struct nand_chip * const chip)
59 {
60 uint8_t mfgrid;
61 uint8_t devid;
62 uint8_t params1;
63 uint8_t params2;
64 uint8_t params3;
65
66 /* Only for Samsung devices, obviously */
67 if (chip->nc_manf_id != NAND_MFR_SAMSUNG) {
68 return 1;
69 }
70
71 nand_select(self, true);
72 nand_command(self, ONFI_READ_ID);
73 nand_address(self, 0x00);
74 nand_read_1(self, &mfgrid);
75 nand_read_1(self, &devid);
76 nand_read_1(self, ¶ms1);
77 nand_read_1(self, ¶ms2);
78 nand_read_1(self, ¶ms3);
79 nand_select(self, false);
80
81 aprint_debug_dev(self,
82 "ID Definition table: 0x%2.x 0x%2.x 0x%2.x 0x%2.x 0x%2.x\n",
83 mfgrid, devid, params1, params2, params3);
84
85 /* K9XXG08UXA */
86 if (devid == 0xdc) {
87 /* From the documentation */
88 chip->nc_addr_cycles_column = 2;
89 chip->nc_addr_cycles_row = 3;
90
91 switch (params2 & NAND_SAMSUNG_PAGEMASK) {
92 case 0x0:
93 chip->nc_page_size = 1024;
94 break;
95 case 0x1:
96 chip->nc_page_size = 2048;
97 break;
98 case 0x2:
99 chip->nc_page_size = 4096;
100 break;
101 case 0x3:
102 chip->nc_page_size = 8192;
103 break;
104 default:
105 KASSERTMSG(false, "ID Data parsing bug detected!");
106 }
107
108 switch ((params2 & NAND_SAMSUNG_BLOCKMASK) >> 4) {
109 case 0x0:
110 chip->nc_block_size = 64 * 1024;
111 break;
112 case 0x1:
113 chip->nc_block_size = 128 * 1024;
114 break;
115 case 0x2:
116 chip->nc_block_size = 256 * 1024;
117 break;
118 case 0x3:
119 chip->nc_block_size = 512 * 1024;
120 break;
121 default:
122 KASSERTMSG(false, "ID Data parsing bug detected!");
123 }
124
125 /* 8/16 bytes per 512 bytes! XXX do i get this right? */
126 switch ((params2 & NAND_SAMSUNG_SPAREMASK) >> 2) {
127 case 0x0:
128 chip->nc_spare_size = 8 * chip->nc_page_size / 512;
129 break;
130 case 0x1:
131 chip->nc_spare_size = 16 * chip->nc_page_size / 512;
132 break;
133 default:
134 KASSERTMSG(false, "ID Data parsing bug detected!");
135 }
136
137 switch ((params2 & NAND_SAMSUNG_BITSMASK) >> 6) {
138 case 0x0:
139 /* its an 8bit chip */
140 break;
141 case 0x1:
142 chip->nc_flags |= NC_BUSWIDTH_16;
143 break;
144 default:
145 KASSERTMSG(false, "ID Data parsing bug detected!");
146 }
147
148 switch ((params3 & NAND_SAMSUNG_PLANENUMMASK) >> 2) {
149 case 0x0:
150 chip->nc_num_luns = 1;
151 break;
152 case 0x1:
153 chip->nc_num_luns = 2;
154 break;
155 case 0x2:
156 chip->nc_num_luns = 4;
157 break;
158 case 0x3:
159 chip->nc_num_luns = 8;
160 break;
161 default:
162 KASSERTMSG(false, "ID Data parsing bug detected!");
163 }
164
165 /* This one reads in megabit for some reason */
166 uint64_t planesize = 0;
167 switch ((params3 & NAND_SAMSUNG_PLANESIZEMASK) >> 4) {
168 case 0x0:
169 planesize = 64 * 1024 * 1024 / 8;
170 break;
171 case 0x1:
172 planesize = 128 * 1024 * 1024 / 8;
173 break;
174 case 0x2:
175 planesize = 256 * 1024 * 1024 / 8;
176 break;
177 case 0x3:
178 planesize = 512 * 1024 * 1024 / 8;
179 break;
180 case 0x4:
181 planesize = 1024 * 1024 * 1024 / 8;
182 break;
183 case 0x5:
184 planesize = 2ul * 1024 * 1024 * 1024 / 8;
185 break;
186 case 0x6:
187 planesize = 4ul * 1024 * 1024 * 1024 / 8;
188 break;
189 case 0x7:
190 planesize = 8ul * 1024 * 1024 * 1024 / 8;
191 break;
192 default:
193 KASSERTMSG(false, "ID Data parsing bug detected!");
194 }
195
196 chip->nc_lun_blocks = planesize / chip->nc_block_size;
197 chip->nc_size = planesize * chip->nc_num_luns;
198
199 aprint_normal_dev(self, "vendor: Samsung, model: K9XXG08UXA\n");
200 } else {
201 return 1;
202 }
203
204 return 0;
205 }
206