NAND Flash Framework for review
Luiz Otavio O Souza
loos.br at gmail.com
Tue Mar 16 14:22:50 UTC 2010
On Mar 16, 2010, at 8:59 AM, Grzegorz Bernacki wrote:
> Andrew Turner wrote:
>> On Mon, 15 Mar 2010 12:14:31 +0100
>> Grzegorz Bernacki <gjb at semihalf.com> wrote:
>>>>> Chip drivers:
>>>>> - lnand and snand have magic numbers to figure out which drive to
>>>>> use. We should move these to a flag in the chip parameters.
>>>> We just need to add the chip size in nand_params and based on that
>>>> we can calculate the number of address cycles (see below) and the
>>>> type of chip (if chip >= 128MB and pagesize > 512 then you have a
>>>> large page device).
>>>>
>>> Yes, I was thinking about adding size of page and column address to
>>> parameters of nfc_send_address.
>> Why not just send each address byte separately like when the command is
>> sent? This will then push the requirement to know how many address
>> bytes to the chip driver.
>
> I choose to send whole address in one call to make implementation of mpc8572
> driver easier. This controller requires to divide address into block number and
> page & column number and write them into corresponding registers. It would be
> complicated (however, not impossible) to combine full address from bytes sending
> via consecutive nfc_send_address calls. On the other hand sending whole address
> in one call should not complicated drivers for controllers which just send address
> byte after byte.
> I was thinking about adding address type parameter to nfc_send_address(). It will
> tell controller how many address cycles chip requires. It will be defined
> using pattern (row_bytes << 4) | (col_bytes), for example:
> #define ADDR_TYPE_2ROW_1COL 0x21
> #define ADDR_TYPE_2ROW_2COL 0x22
> #define ADDR_TYPE_2ROW 0x20 (for erase command)
> #define ADDR_TYPE_ID 0xff (for read id command)
> It will allow to get rid of (-1) value for unused parameters. Also maybe it would be
> better to define address as a structure
> struct nand_addr {
> uint32_t row;
> uint32_t column;
> uint8_t id;
> uint8_t type;
> }
But then we need to keep the logic for sending the address cycles on the driver (and we'll get a lot of duplicated code on the tree).
Look at my patch on how it simplify the send_address routine on nfc_mv.c
And yes, you need to deal with multiple calls in some kind of drivers/controllers.
> The second thing is wait for ready/busy pin. I will add it to nfc methods. When not
> implemented it will return ENXIO by default. It will be used in nandbus_wait_ready function. It will be called in loop instead of sending STATUS command (unless it return ENXIO on first invocation).
> Is it good approach? What do you think?
Well, they are different things...
The ready/busy pin tells you when the chip is busy in some internal operation (erasing a block, putting data on the buffer after you send all the address cycles for a read, etc).
You should use the ready/busy pin to wait for the right time to read the data after sending the command and when you don't have access to this pin you can fallback to default delays.
The read status command is used to tell when a read/write/erase command fails. If you have a fail after write or erase blocks then you have a bad block.
About the patch (what it changes):
I've changed the blocks_per_chip to chip_size, because there are a few chips that support a kind of extended id bytes which contains the basic chip information (page size, spare size, access time, block size and organization - 8X16 bits) but not the number of blocks per chip, so if we have the chip size we can calculate all the rest.
The readextendedid() routine is not on the patch, i'll add it in the next days (i've it here somewhere...).
I did not touch on onfi routines (don't know too much about it and don't have a device to test).
You can ignore the changes on ecc bytes positions for now (but the original positions you are using overlaps with bad block mark byte).
The patch also fixes the probe of small and large page devices (no more magic numbers :-)).
There is another two fixes on large page routines, the original code tries to read the status right after sending the address cycles and then you can't read the real data, you just read the status register.
That's it.
Thanks,
Luiz
-------------- next part --------------
diff -ru nand2/sys/dev/nand/nand.c mips-nand2/src/sys/dev/nand/nand.c
--- nand2/sys/dev/nand/nand.c 2010-03-07 12:26:49.000000000 -0300
+++ mips-nand2/src/sys/dev/nand/nand.c 2010-03-16 10:38:19.000000000 -0300
@@ -114,10 +114,13 @@
nand_set_params(struct nand_chip *chip, struct nand_params *params)
{
struct chip_geom *cg;
+ uint32_t blocks_per_chip;
cg = &chip->chip_geom;
+ blocks_per_chip = (params->chip_size << 20) /
+ (params->page_size * params->pages_per_block);
- init_chip_geom(cg, 1, params->blocks_per_chip,
+ init_chip_geom(cg, 1, blocks_per_chip,
params->pages_per_block, params->page_size,
params->oob_size);
@@ -186,7 +189,6 @@
cg->block_size = cg->page_size * cg->pgs_per_blk;
cg->chip_size = cg->block_size * cg->blks_per_chip;
-
shift = fls(cg->pgs_per_blk - 1);
cg->pg_mask = (1 << shift) - 1;
cg->blk_shift = shift;
diff -ru nand2/sys/dev/nand/nand.h mips-nand2/src/sys/dev/nand/nand.h
--- nand2/sys/dev/nand/nand.h 2010-03-07 12:26:49.000000000 -0300
+++ mips-nand2/src/sys/dev/nand/nand.h 2010-03-16 08:39:45.000000000 -0300
@@ -116,19 +116,20 @@
#define NAND_ECC_MODE_MASK 0x3f
#define NAND_MAN_SAMSUNG 0xec
+#define NAND_MAN_HYNIX 0xad
struct nand_id {
- uint8_t manufacturer_id;
- uint8_t device_id;
+ uint8_t man_id;
+ uint8_t dev_id;
};
struct nand_params {
struct nand_id id;
char *name;
+ uint32_t chip_size;
uint32_t page_size;
uint32_t oob_size;
uint32_t pages_per_block;
- uint32_t blocks_per_chip;
uint32_t flags;
};
diff -ru nand2/sys/dev/nand/nand_ecc_pos.h mips-nand2/src/sys/dev/nand/nand_ecc_pos.h
--- nand2/sys/dev/nand/nand_ecc_pos.h 2010-03-07 12:26:50.000000000 -0300
+++ mips-nand2/src/sys/dev/nand/nand_ecc_pos.h 2010-03-12 22:06:08.000000000 -0300
@@ -29,13 +29,14 @@
#ifndef _DEV_NAND_ECC_POS_H_
#define _DEV_NAND_ECC_POS_H_
-static uint16_t default_software_ecc_positions_16[] = {0, 1, 2, 3, 4, 5};
+/*static uint16_t default_software_ecc_positions_16[] = {0, 1, 2, 3, 6, 7}; */
+static uint16_t default_software_ecc_positions_16[] = {10, 8, 9, 15, 13, 14};
static uint16_t default_software_ecc_positions_64[] = {
- 0, 1, 2, 3, 4, 5,
- 15, 16, 17, 18, 19, 20, 21,
- 31, 32, 33, 34, 35, 36, 37,
- 47, 48, 49, 50, 51, 52, 53
+
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63
};
#endif /* _DEV_NAND_ECC_POS_H_ */
diff -ru nand2/sys/dev/nand/nand_generic.c mips-nand2/src/sys/dev/nand/nand_generic.c
--- nand2/sys/dev/nand/nand_generic.c 2010-03-07 18:38:33.000000000 -0300
+++ mips-nand2/src/sys/dev/nand/nand_generic.c 2010-03-16 10:39:18.000000000 -0300
@@ -88,6 +88,9 @@
static int onfi_read_parameter(struct nand_chip *chip,
struct onfi_params *params);
+static int nand_send_address(device_t nand, int32_t row, int32_t col,
+ int8_t id);
+
static device_method_t onand_methods[] = {
/* device interface */
DEVMETHOD(device_probe, onfi_nand_probe),
@@ -180,9 +183,8 @@
struct nandbus_ivar *ivar;
ivar = device_get_ivars(dev);
- if (ivar && !ivar->is_onfi &&
- (ivar->man_id == NAND_MAN_SAMSUNG) && (ivar->dev_id == 0xd3)) {
- device_set_desc(dev, "Large Samsung NAND");
+ if (ivar && !ivar->is_onfi && ivar->params->page_size >= 512) {
+ device_set_desc(dev, ivar->params->name);
return (BUS_PROBE_DEFAULT);
}
@@ -195,9 +197,8 @@
struct nandbus_ivar *ivar;
ivar = device_get_ivars(dev);
- if (ivar && !ivar->is_onfi &&
- (ivar->man_id == NAND_MAN_SAMSUNG) && (ivar->dev_id == 0x75)) {
- device_set_desc(dev, "Small Samsung NAND");
+ if (ivar && !ivar->is_onfi && ivar->params->page_size == 512) {
+ device_set_desc(dev, ivar->params->name);
return (BUS_PROBE_DEFAULT);
}
@@ -208,7 +209,6 @@
generic_nand_attach(device_t dev)
{
struct nand_chip *chip;
- struct nand_params *chip_params;
struct nandbus_ivar *ivar;
struct onfi_params *onfi_params;
device_t nandbus, nfc;
@@ -218,8 +218,8 @@
chip->dev = dev;
ivar = device_get_ivars(dev);
- chip->id.manufacturer_id = ivar->man_id;
- chip->id.device_id = ivar->dev_id;
+ chip->id.man_id = ivar->man_id;
+ chip->id.dev_id = ivar->dev_id;
chip->num = ivar->cs;
/* TODO remove when HW ECC supported */
@@ -243,16 +243,8 @@
free(onfi_params, M_DEVBUF);
} else {
- chip_params = nand_get_params(&chip->id);
- if (chip_params == NULL) {
- debug("Chip description not found!"
- "(manuf: 0x%0x, chipid: 0x%0x)\n",
- chip->id.manufacturer_id,
- chip->id.device_id);
- return (EINVAL);
- }
- nand_set_params(chip, chip_params);
+ nand_set_params(chip, ivar->params);
}
err = nand_init_stat(chip);
@@ -343,7 +335,7 @@
if (nandbus_send_command(nandbus, NAND_CMD_READ_PARAMETER))
return (ENXIO);
- if (nandbus_send_address(nandbus, -1, -1, PAGE_PARAMETER_DEF))
+ if (nand_send_address(chip->dev, -1, -1, PAGE_PARAMETER_DEF))
return (ENXIO);
if (nandbus_start_command(nandbus))
@@ -360,13 +352,15 @@
}
static int
-send_read_page(device_t nandbus, uint8_t start_command, uint8_t end_command,
+send_read_page(device_t nand, uint8_t start_command, uint8_t end_command,
uint32_t row, uint32_t column)
{
+ device_t nandbus = device_get_parent(nand);
+
if (nandbus_send_command(nandbus, start_command))
return (ENXIO);
- if (nandbus_send_address(nandbus, row, column, -1))
+ if (nand_send_address(nand, row, column, -1))
return (ENXIO);
if (nandbus_send_command(nandbus, end_command))
@@ -396,16 +390,17 @@
page_to_row(&chip->chip_geom, page, &row);
- if (send_read_page(nandbus, NAND_CMD_READ, NAND_CMD_READ_END, row,
+ if (send_read_page(nand, NAND_CMD_READ, NAND_CMD_READ_END, row,
offset))
return (ENXIO);
DELAY(chip->t_r);
- if (check_fail(nandbus))
- return (ENXIO);
nandbus_read_buffer(nandbus, buf, len);
+ if (check_fail(nandbus))
+ return (ENXIO);
+
pg_stat = &(chip->pg_stat[page]);
pg_stat->page_raw_read++;
@@ -431,27 +426,29 @@
offset += chip->chip_geom.page_size;
- if (send_read_page(nandbus, NAND_CMD_READ, NAND_CMD_READ_END, row,
+ if (send_read_page(nand, NAND_CMD_READ, NAND_CMD_READ_END, row,
offset))
return (ENXIO);
DELAY(chip->t_r);
+ nandbus_read_buffer(nandbus, buf, len);
+
if (check_fail(nandbus))
return (ENXIO);
- nandbus_read_buffer(nandbus, buf, len);
-
return (0);
}
static int
-send_start_program_page(device_t nandbus, uint32_t row, uint32_t column)
+send_start_program_page(device_t nand, uint32_t row, uint32_t column)
{
+ device_t nandbus = device_get_parent(nand);
+
if (nandbus_send_command(nandbus, NAND_CMD_PROG))
return (ENXIO);
- if (nandbus_send_address(nandbus, row, column, -1))
+ if (nand_send_address(nand, row, column, -1))
return (ENXIO);
return (0);
@@ -491,7 +488,7 @@
if (!can_write(nandbus))
return (ENXIO);
- if (send_start_program_page(nandbus, row, offset))
+ if (send_start_program_page(nand, row, offset))
return (ENXIO);
nandbus_write_buffer(nandbus, buf, len);
@@ -531,7 +528,7 @@
if (!can_write(nandbus))
return (ENXIO);
- if (send_start_program_page(nandbus, row, offset))
+ if (send_start_program_page(nand, row, offset))
return (ENXIO);
nandbus_write_buffer(nandbus, buf, len);
@@ -571,7 +568,7 @@
if (!can_write(nandbus))
return (ENXIO);
- if (send_start_program_page(nandbus, row, offset))
+ if (send_start_program_page(nand, row, offset))
return (ENXIO);
nandbus_write_buffer(nandbus, buf, len);
@@ -588,13 +585,14 @@
}
static int
-send_erase_block(device_t nandbus, uint32_t row, uint8_t second_command)
+send_erase_block(device_t nand, uint32_t row, uint8_t second_command)
{
+ device_t nandbus = device_get_parent(nand);
if (nandbus_send_command(nandbus, NAND_CMD_ERASE))
return (ENXIO);
- if (nandbus_send_address(nandbus, row, -1, -1))
+ if (nand_send_address(nand, row, -1, -1))
return (ENXIO);
if (nandbus_send_command(nandbus, second_command))
@@ -615,8 +613,8 @@
int row;
debug("%p erase block %x", nand, block);
- chip = device_get_softc(nand);
nandbus = device_get_parent(nand);
+ chip = device_get_softc(nand);
if (block >= (chip->chip_geom.blks_per_lun * chip->chip_geom.luns))
return (ENXIO);
@@ -629,7 +627,7 @@
if (!can_write(nandbus))
return (ENXIO);
- send_erase_block(nandbus, row, NAND_CMD_ERASE_END);
+ send_erase_block(nand, row, NAND_CMD_ERASE_END);
DELAY(chip->t_bers);
@@ -651,8 +649,8 @@
int row;
debug("%p erase block %x", nand, block);
- chip = device_get_softc(nand);
nandbus = device_get_parent(nand);
+ chip = device_get_softc(nand);
if (block >= (chip->chip_geom.blks_per_lun * chip->chip_geom.luns))
return (ENXIO);
@@ -663,7 +661,7 @@
if (!can_write(nandbus))
return (ENXIO);
- send_erase_block(nandbus, row, NAND_CMD_ERASE_INTLV);
+ send_erase_block(nand, row, NAND_CMD_ERASE_INTLV);
DELAY(chip->t_bers);
@@ -720,13 +718,15 @@
}
static int
-send_small_read_page(device_t nandbus, uint8_t start_command,
+send_small_read_page(device_t nand, uint8_t start_command,
uint32_t row, uint32_t column)
{
+ device_t nandbus = device_get_parent(nand);
+
if (nandbus_send_command(nandbus, start_command))
return (ENXIO);
- if (nandbus_send_address(nandbus, row, column, -1))
+ if (nand_send_address(nand, row, column, -1))
return (ENXIO);
if (nandbus_start_command(nandbus))
@@ -755,10 +755,10 @@
page_to_row(&chip->chip_geom, page, &row);
if (offset < 256) {
- if (send_small_read_page(nandbus, NAND_CMD_SMALLA, row, offset))
+ if (send_small_read_page(nand, NAND_CMD_SMALLA, row, offset))
return (ENXIO);
} else {
- if (send_small_read_page(nandbus, NAND_CMD_SMALLB, row, offset))
+ if (send_small_read_page(nand, NAND_CMD_SMALLB, row, offset))
return (ENXIO);
}
@@ -790,7 +790,7 @@
page_to_row(&chip->chip_geom, page, &row);
- if (send_small_read_page(nandbus, NAND_CMD_SMALLOOB, row, offset))
+ if (send_small_read_page(nand, NAND_CMD_SMALLOOB, row, offset))
return (ENXIO);
DELAY(chip->t_r);
@@ -831,7 +831,7 @@
return (ENXIO);
}
- if (send_start_program_page(nandbus, row, offset))
+ if (send_start_program_page(nand, row, offset))
return (ENXIO);
nandbus_write_buffer(nandbus, buf, len);
@@ -870,7 +870,7 @@
if (nandbus_send_command(nandbus, NAND_CMD_SMALLOOB))
return (ENXIO);
- if (send_start_program_page(nandbus, row, offset))
+ if (send_start_program_page(nand, row, offset))
return (ENXIO);
nandbus_write_buffer(nandbus, buf, len);
@@ -886,6 +886,46 @@
return (0);
}
+int
+nand_send_address(device_t nand, int32_t row, int32_t col, int8_t id)
+{
+ struct nandbus_ivar *ivar;
+ device_t nandbus;
+ uint8_t addr;
+ int err = 0;
+ int i;
+
+ nandbus = device_get_parent(nand);
+ ivar = device_get_ivars(nand);
+
+ if (id != -1) {
+ debug("send_address: send id %02x", id);
+ err = nandbus_send_address(nandbus, id);
+ }
+
+ if (!err && col != -1) {
+ for (i = 0; i < ivar->cols; i++, col >>= 8) {
+ addr = (uint8_t)(col & 0xff);
+ debug("send_address: send address column %02x", addr);
+ err = nandbus_send_address(nandbus, addr);
+ if (err)
+ break;
+ }
+ }
+
+ if (!err && row != -1) {
+ for (i = 0; i < ivar->rows; i++, row >>= 8) {
+ addr = (uint8_t)(row & 0xff);
+ debug("send_address: send address row %02x", addr);
+ err = nandbus_send_address(nandbus, addr);
+ if (err)
+ break;
+ }
+ }
+
+ return (err);
+}
+
#if 0
int
nand_chng_read_col(device_t nand, uint32_t col, void *buf, size_t len)
@@ -960,7 +1000,7 @@
page_to_row(&chip->chip_geom, page, &row);
- if (send_read_page(nandbus, NAND_CMD_READ, NAND_CMD_READ_CPBK, row, 0))
+ if (send_read_page(nand, NAND_CMD_READ, NAND_CMD_READ_CPBK, row, 0))
return (ENXIO);
DELAY(chip->t_r);
@@ -1040,7 +1080,7 @@
if (!can_write(nandbus))
return (ENXIO);
- if (send_start_program_page(nandbus, row, 0))
+ if (send_start_program_page(nand, row, 0))
return (ENXIO);
if (send_end_program_page(nandbus, NAND_CMD_PROG_INTLV))
@@ -1079,7 +1119,7 @@
if (!can_write(nandbus))
return (ENXIO);
- if (send_start_program_page(nandbus, row, 0))
+ if (send_start_program_page(dev, row, 0))
return (ENXIO);
nandbus_write_buffer(nandbus, buf, len);
diff -ru nand2/sys/dev/nand/nand_geom.c mips-nand2/src/sys/dev/nand/nand_geom.c
--- nand2/sys/dev/nand/nand_geom.c 2010-03-07 12:26:50.000000000 -0300
+++ mips-nand2/src/sys/dev/nand/nand_geom.c 2010-03-16 10:40:30.000000000 -0300
@@ -252,7 +252,8 @@
disk->d_name = "gnand";
disk->d_drv1 = chip;
disk->d_maxsize = chip->chip_geom.block_size;
- disk->d_sectorsize = chip->chip_geom.block_size;
+// disk->d_sectorsize = chip->chip_geom.block_size;
+ disk->d_sectorsize = chip->chip_geom.page_size;
disk->d_mediasize = chip->chip_geom.chip_size;
disk->d_pagesize = chip->chip_geom.page_size;
disk->d_oobsize = chip->chip_geom.oob_size;
@@ -262,8 +263,7 @@
disk->d_flags = DISKFLAG_CANDELETE;
snprintf(disk->d_ident, sizeof(disk->d_ident),
- "nand: Man:0x%02x Dev:0x%02x", chip->id.manufacturer_id,
- chip->id.device_id);
+ "nand: Man:0x%02x Dev:0x%02x", chip->id.man_id, chip->id.dev_id);
gnand_create(disk);
@@ -279,7 +279,7 @@
TASK_INIT(&chip->iotask, 0, nand_io_proc, chip);
device_printf(chip->dev, "Created gnand%d for chip [0x%0x, 0x%0x]\n",
- disk->d_unit, chip->id.manufacturer_id, chip->id.device_id);
+ disk->d_unit, chip->id.man_id, chip->id.dev_id);
return (0);
}
diff -ru nand2/sys/dev/nand/nand_id.c mips-nand2/src/sys/dev/nand/nand_id.c
--- nand2/sys/dev/nand/nand_id.c 2010-03-07 12:26:50.000000000 -0300
+++ mips-nand2/src/sys/dev/nand/nand_id.c 2010-03-16 08:45:12.000000000 -0300
@@ -33,13 +33,17 @@
#include <dev/nand/nand.h>
struct nand_params nand_ids[] = {
- {{NAND_MAN_SAMSUNG, 0x75},
- "Samsung K9F5608U0B", 0x200, 0x10,
- 0x20, 0x800, 0 },
-
- {{NAND_MAN_SAMSUNG, 0xd3},
- "Samsung NAND 1GiB 3,3V 8-bit", 0x800, 0x40,
- 0x40, 0x2000, 0 },
+ { { NAND_MAN_SAMSUNG, 0x75 }, "Samsung K9F5608U0B",
+ 0x20, 0x200, 0x10, 0x20, 0 },
+
+ { { NAND_MAN_SAMSUNG, 0xd3 }, "Samsung NAND 1GiB 3,3V 8-bit",
+ 0x400, 0x800, 0x40, 0x40, 0 },
+
+ { { NAND_MAN_HYNIX, 0x76 }, "Hynix NAND 64MiB 3,3V 8-bit",
+ 0x40, 0x200, 0x10, 0x20, 0 },
+
+ { { NAND_MAN_HYNIX, 0xdc }, "Hynix NAND 512MiB 3,3V 8-bit",
+ 0x200, 0x800, 0x40, 0x80, 0 },
};
struct nand_params *nand_get_params(struct nand_id *id)
@@ -47,8 +51,8 @@
int i;
for (i = 0; i < sizeof(nand_ids) / sizeof(nand_ids[0]); i++)
- if (nand_ids[i].id.manufacturer_id == id->manufacturer_id &&
- nand_ids[i].id.device_id == id->device_id)
+ if (nand_ids[i].id.man_id == id->man_id &&
+ nand_ids[i].id.dev_id == id->dev_id)
return (&nand_ids[i]);
return (NULL);
diff -ru nand2/sys/dev/nand/nandbus.c mips-nand2/src/sys/dev/nand/nandbus.c
--- nand2/sys/dev/nand/nandbus.c 2010-03-07 12:26:51.000000000 -0300
+++ mips-nand2/src/sys/dev/nand/nandbus.c 2010-03-16 10:41:57.000000000 -0300
@@ -146,10 +146,12 @@
nandbus_attach(device_t dev)
{
device_t child, nfc;
+ struct nand_id chip_id;
struct nandbus_softc *sc;
struct nandbus_ivar *ivar;
- struct nand_softc* nfc_sc;
- uint8_t cs, man_id, dev_id, onfi, found = 0;
+ struct nand_softc *nfc_sc;
+ struct nand_params *chip_params;
+ uint8_t cs, onfi, found = 0;
sc = device_get_softc(dev);
sc->dev = dev;
@@ -172,10 +174,10 @@
continue;
/* Read manufacturer and device id */
- if (nand_readid(dev, &man_id, &dev_id))
+ if (nand_readid(dev, &chip_id.man_id, &chip_id.dev_id))
continue;
- if (man_id == 0xff)
+ if (chip_id.man_id == 0xff)
continue;
/* Check if chip is ONFI compliant */
@@ -183,17 +185,39 @@
continue;
}
+ chip_params = nand_get_params(&chip_id);
+ if (chip_params == NULL) {
+ debug("Chip description not found!"
+ "(manuf: 0x%0x, chipid: 0x%0x)\n",
+ chip_id.man_id, chip_id.dev_id);
+ continue;
+ }
+
ivar = malloc(sizeof(struct nandbus_ivar),
M_DEVBUF, M_NOWAIT);
if (!ivar)
return (ENOMEM);
ivar->cs = cs;
- ivar->man_id = man_id;
- ivar->dev_id = dev_id;
+ ivar->cols = 1;
+ ivar->rows = 2;
+ ivar->params = chip_params;
+ ivar->man_id = chip_id.man_id;
+ ivar->dev_id = chip_id.dev_id;
ivar->is_onfi = onfi;
ivar->chip_cdev_name = nfc_sc->chip_cdev_name;
+ /*
+ * check what type of device we have.
+ * devices bigger than 32MiB have on more row (3)
+ */
+ if (chip_params->chip_size > 32)
+ ivar->rows++;
+ /* large page devices have one more col (2) */
+ if (chip_params->chip_size >= 128 &&
+ chip_params->page_size > 512)
+ ivar->cols++;
+
child = device_add_child(dev, NULL, -1);
device_set_ivars(child, ivar);
found = 1;
@@ -254,7 +278,7 @@
return (ENXIO);
}
- if (NFC_SEND_ADDRESS(nfc, -1, -1, 0)) {
+ if (NFC_SEND_ADDRESS(nfc, 0)) {
debug("Error : could not sent address to chip");
return (ENXIO);
}
@@ -290,7 +314,7 @@
return (ENXIO);
}
- if (NFC_SEND_ADDRESS(nfc, -1, -1, ONFI_SIG_ADDR)) {
+ if (NFC_SEND_ADDRESS(nfc, ONFI_SIG_ADDR)) {
debug("Error : could not sent address to chip");
return (ENXIO);
}
@@ -381,13 +405,12 @@
}
int
-nandbus_send_address(device_t dev, int32_t row, int32_t col, int8_t off)
+nandbus_send_address(device_t dev, uint8_t address)
{
int err;
- if ((err = NFC_SEND_ADDRESS(device_get_parent(dev), row, col, off)))
- debug("Err: Could not send %x-%x-%x address, err %d",
- row, col, off, err);
+ if ((err = NFC_SEND_ADDRESS(device_get_parent(dev), address)))
+ debug("Err: Could not send address %x, err %x", address, err);
return (err);
}
diff -ru nand2/sys/dev/nand/nandbus.h mips-nand2/src/sys/dev/nand/nandbus.h
--- nand2/sys/dev/nand/nandbus.h 2010-03-07 12:26:51.000000000 -0300
+++ mips-nand2/src/sys/dev/nand/nandbus.h 2010-03-16 09:34:06.000000000 -0300
@@ -30,11 +30,14 @@
#define _NANDBUS_H_
struct nandbus_ivar {
- uint8_t cs;
- uint8_t man_id;
- uint8_t dev_id;
- uint8_t is_onfi;
- char *chip_cdev_name;
+ uint8_t cs;
+ uint8_t cols;
+ uint8_t rows;
+ uint8_t man_id;
+ uint8_t dev_id;
+ uint8_t is_onfi;
+ char *chip_cdev_name;
+ struct nand_params *params;
};
extern devclass_t nandbus_devclass;
@@ -47,7 +50,7 @@
void nandbus_read_buffer(device_t dev, void *buf, uint32_t len);
int nandbus_select_cs(device_t dev, uint8_t cs);
int nandbus_send_command(device_t dev, uint8_t command);
-int nandbus_send_address(device_t dev, int32_t row, int32_t col, int8_t off);
+int nandbus_send_address(device_t dev, uint8_t address);
int nandbus_start_command(device_t dev);
int nandbus_wait_ready(device_t dev, uint8_t *status);
void nandbus_write_buffer(device_t dev, void *buf, uint32_t len);
diff -ru nand2/sys/dev/nand/nfc_if.m mips-nand2/src/sys/dev/nand/nfc_if.m
--- nand2/sys/dev/nand/nfc_if.m 2010-03-07 12:26:52.000000000 -0300
+++ mips-nand2/src/sys/dev/nand/nfc_if.m 2010-03-16 07:36:05.000000000 -0300
@@ -57,9 +57,7 @@
#
METHOD int send_address {
device_t dev;
- int32_t page;
- int32_t column;
- int8_t id;
+ uint8_t address;
};
# Read byte
diff -ru nand2/sys/dev/nand/nfc_mv.c mips-nand2/src/sys/dev/nand/nfc_mv.c
--- nand2/sys/dev/nand/nfc_mv.c 2010-03-07 12:34:07.000000000 -0300
+++ mips-nand2/src/sys/dev/nand/nfc_mv.c 2010-03-16 08:10:25.000000000 -0300
@@ -74,8 +74,7 @@
static int mv_nand_attach(device_t dev);
static int mv_nand_probe(device_t dev);
static int mv_nand_send_command(device_t dev, uint8_t command);
-static int mv_nand_send_address(device_t dev, int32_t row,
- int32_t column, int8_t id);
+static int mv_nand_send_address(device_t dev, uint8_t addr);
static uint8_t mv_nand_read_byte(device_t dev);
static void mv_nand_read_buf(device_t dev, void* buf, uint32_t len);
static void mv_nand_write_buf(device_t dev, void* buf, uint32_t len);
@@ -140,30 +139,10 @@
static int
-mv_nand_send_address(device_t dev, int32_t row, int32_t column,
- int8_t id)
+mv_nand_send_address(device_t dev, uint8_t addr)
{
- struct mv_nand_softc *sc;
- sc = device_get_softc(dev);
-
- if (id != -1) {
- debug("mv_nand: send address %x", id);
- MV_NAND_WRITE(MV_NAND_ADDRESS, id);
- }
- /* TODO add number of address cycles to function parameters */
- if (column != -1) {
- debug("mv_nand: send address %x",
- column & 0xff);
- MV_NAND_WRITE(MV_NAND_ADDRESS, column & 0xff);
- }
-
- if (row != -1) {
- debug("mv_nand: send address %x %x",
- row & 0xff, (row >> 8) & 0xff);
- MV_NAND_WRITE(MV_NAND_ADDRESS, row & 0xff);
- MV_NAND_WRITE(MV_NAND_ADDRESS, (row >> 8) & 0xff);
- }
+ MV_NAND_WRITE(MV_NAND_ADDRESS, addr);
return (0);
}
More information about the freebsd-embedded
mailing list