1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "onfi.h"
6 
7 #include <string.h>
8 #include <unistd.h>
9 
10 #include <ddk/debug.h>
11 
12 /*
13  * Database of settings for the NAND flash devices we support.
14  * Note on chip_delay: chip_delay is the delay after we enqueue certain ONFI
15  * commands (RESET, READSTART). The value of 30us was experimentally picked for
16  * the Samsung NAND, and 20us for the Toshiba NAND. It turns out that a value
17  * of 25us works better for the Micron NAND (25us reduces the number of ECC
18  * errors significantly).
19  * TODO(ZX-2696): Determine the value of chip delay more scientifically.
20  */
21 struct nand_chip_table nand_chip_table[] = {
22     {0x2C, 0xDC, "Micron", "MT29F4G08ABAEA", {20, 16, 15}, 25, true, 512, 0, 0, 0, 0},
23     {0xEC, 0xDC, "Samsung", "K9F4G08U0F", {25, 20, 15}, 30, true, 512, 0, 0, 0, 0},
24     /* TODO: This works. but doublecheck Toshiba nand_timings from datasheet */
25     {0x98, 0xDC, "Toshiba", "TC58NVG2S0F", {25, 20, /* 15 */ 25}, 25, true, 512, 0, 0, 0, 0},
26 };
27 
28 #define NAND_CHIP_TABLE_SIZE \
29     (sizeof(nand_chip_table) / sizeof(struct nand_chip_table))
30 
31 /*
32  * Find the entry in the NAND chip table database based on manufacturer
33  * id and device id
34  */
find_nand_chip_table(uint8_t manuf_id,uint8_t device_id)35 struct nand_chip_table* find_nand_chip_table(uint8_t manuf_id,
36                                              uint8_t device_id) {
37     for (uint32_t i = 0; i < NAND_CHIP_TABLE_SIZE; i++)
38         if (manuf_id == nand_chip_table[i].manufacturer_id &&
39             device_id == nand_chip_table[i].device_id)
40             return &nand_chip_table[i];
41     return NULL;
42 }
43 
44 /*
45  * onfi_wait() and onfi_command() are generic ONFI protocol compliant.
46  *
47  * Generic wait function used by both program (write) and erase
48  * functionality.
49  */
onfi_wait(onfi_callback_t * cb,uint32_t timeout_ms)50 zx_status_t onfi_wait(onfi_callback_t* cb, uint32_t timeout_ms) {
51     uint64_t total_time = 0;
52     uint8_t cmd_status;
53 
54     cb->cmd_ctrl(cb->ctx, NAND_CMD_STATUS, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
55     cb->cmd_ctrl(cb->ctx, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
56     while (!((cmd_status = cb->read_byte(cb->ctx)) & NAND_STATUS_READY)) {
57         usleep(10);
58         total_time += 10;
59         if (total_time > (timeout_ms * 1000)) {
60             break;
61         }
62     }
63     if (!(cmd_status & NAND_STATUS_READY)) {
64         zxlogf(ERROR, "nand command wait timed out\n");
65         return ZX_ERR_TIMED_OUT;
66     }
67     if (cmd_status & NAND_STATUS_FAIL) {
68         zxlogf(ERROR, "%s: nand command returns error\n", __func__);
69         return ZX_ERR_IO;
70     }
71     return ZX_OK;
72 }
73 
74 /*
75  * Send onfi command down to the controller.
76  */
onfi_command(onfi_callback_t * cb,uint32_t command,int32_t column,int32_t page_addr,uint32_t capacity_mb,uint32_t chip_delay_us,int buswidth_16)77 void onfi_command(onfi_callback_t* cb, uint32_t command,
78                   int32_t column, int32_t page_addr,
79                   uint32_t capacity_mb, uint32_t chip_delay_us,
80                   int buswidth_16) {
81     cb->cmd_ctrl(cb->ctx, command, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
82     if (column != -1 || page_addr != -1) {
83         uint32_t ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
84 
85         if (column != -1) {
86             /* 16 bit buswidth ? */
87             if (buswidth_16)
88                 column >>= 1;
89             cb->cmd_ctrl(cb->ctx, column, ctrl);
90             ctrl &= ~NAND_CTRL_CHANGE;
91             cb->cmd_ctrl(cb->ctx, column >> 8, ctrl);
92         }
93         if (page_addr != -1) {
94             cb->cmd_ctrl(cb->ctx, page_addr, ctrl);
95             cb->cmd_ctrl(cb->ctx, page_addr >> 8,
96                               NAND_NCE | NAND_ALE);
97             /* one more address cycle for devices > 128M */
98             if (capacity_mb > 128)
99                 cb->cmd_ctrl(cb->ctx, page_addr >> 16, NAND_NCE | NAND_ALE);
100         }
101     }
102     cb->cmd_ctrl(cb->ctx, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
103 
104     if (command == NAND_CMD_ERASE1 || command == NAND_CMD_ERASE2 ||
105         command == NAND_CMD_SEQIN || command == NAND_CMD_PAGEPROG)
106         return;
107     if (command == NAND_CMD_RESET) {
108         usleep(chip_delay_us);
109         cb->cmd_ctrl(cb->ctx, NAND_CMD_STATUS, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
110         cb->cmd_ctrl(cb->ctx, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
111         /* We have to busy loop until ready */
112         while (!(cb->read_byte(cb->ctx) & NAND_STATUS_READY))
113             ;
114         return;
115     }
116     if (command == NAND_CMD_READ0) {
117         cb->cmd_ctrl(cb->ctx, NAND_CMD_READSTART, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
118         cb->cmd_ctrl(cb->ctx, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
119     }
120     usleep(chip_delay_us);
121 }
122