1/* $NetBSD: nand_samsung.c,v 1.10 2017/11/09 21:45:24 jmcneill 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.10 2017/11/09 21:45:24 jmcneill Exp $"); 41 42#include "nand.h" 43#include "onfi.h" 44 45enum { 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 52enum { 53 NAND_SAMSUNG_PLANENUMMASK = 0x3 << 2, 54 NAND_SAMSUNG_PLANESIZEMASK = 0x7 << 4 55}; 56 57int 58nand_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 = 2ull * 1024 * 1024 * 1024 / 8; 185 break; 186 case 0x6: 187 planesize = 4ull * 1024 * 1024 * 1024 / 8; 188 break; 189 case 0x7: 190 planesize = 8ull * 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