Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Mar 2010 11:22:44 -0300
From:      Luiz Otavio O Souza <loos.br@gmail.com>
To:        Grzegorz Bernacki <gjb@semihalf.com>
Cc:        embedded@freebsd.org, Andrew Turner <andrew@fubar.geek.nz>
Subject:   Re: NAND Flash Framework for review
Message-ID:  <776ADF3A-4C68-486A-8640-DE0DD6B8874E@gmail.com>
In-Reply-To: <4B9F72BC.1050609@semihalf.com>
References:  <0AE04EFA-A3EB-4939-BD81-607C00355B67@semihalf.com>	<20100314165825.121d346b@fubar.geek.nz>	<CC419602-A9E8-4FE2-A5A5-0BFBD8240EDD@gmail.com>	<4B9E1697.9090602@semihalf.com> <20100316101044.0401295e@fubar.geek.nz> <4B9F72BC.1050609@semihalf.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--Apple-Mail-32-531872463
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=us-ascii

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@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 >=3D 128MB and pagesize > 512 then you have a
>>>> large page device).
>>>>=20
>>> 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.
>=20
> 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




--Apple-Mail-32-531872463
Content-Disposition: attachment;
	filename=nand2-20100316-diff.txt
Content-Type: text/plain;
	name="nand2-20100316-diff.txt"
Content-Transfer-Encoding: quoted-printable

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;
=20
 	cg =3D &chip->chip_geom;
+	blocks_per_chip =3D (params->chip_size << 20) /
+	    (params->page_size * params->pages_per_block);
=20
-	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);
=20
@@ -186,7 +189,6 @@
 	cg->block_size =3D cg->page_size * cg->pgs_per_blk;
 	cg->chip_size =3D cg->block_size * cg->blks_per_chip;
=20
-
 	shift =3D fls(cg->pgs_per_blk - 1);
 	cg->pg_mask =3D (1 << shift) - 1;
 	cg->blk_shift =3D 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
=20
 #define NAND_MAN_SAMSUNG		0xec
+#define NAND_MAN_HYNIX			0xad
=20
 struct nand_id {
-	uint8_t manufacturer_id;
-	uint8_t device_id;
+	uint8_t man_id;
+	uint8_t dev_id;
 };
=20
 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;
 };
=20
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_
=20
-static uint16_t default_software_ecc_positions_16[] =3D {0, 1, 2, 3, 4, =
5};
+/*static uint16_t default_software_ecc_positions_16[] =3D {0, 1, 2, 3, =
6, 7}; */
+static uint16_t default_software_ecc_positions_16[] =3D {10, 8, 9, 15, =
13, 14};
=20
 static uint16_t default_software_ecc_positions_64[] =3D {
-	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
 };
=20
 #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);
=20
+static int nand_send_address(device_t nand, int32_t row, int32_t col,
+    int8_t id);
+
 static device_method_t onand_methods[] =3D {
 	/* device interface */
 	DEVMETHOD(device_probe,			onfi_nand_probe),
@@ -180,9 +183,8 @@
 	struct nandbus_ivar *ivar;
=20
 	ivar =3D device_get_ivars(dev);
-	if (ivar && !ivar->is_onfi &&
-	    (ivar->man_id =3D=3D NAND_MAN_SAMSUNG) && (ivar->dev_id =3D=3D=
 0xd3)) {
-		device_set_desc(dev, "Large Samsung NAND");
+	if (ivar && !ivar->is_onfi && ivar->params->page_size >=3D 512) =
{
+		device_set_desc(dev, ivar->params->name);
 		return (BUS_PROBE_DEFAULT);
 	}
=20
@@ -195,9 +197,8 @@
 	struct nandbus_ivar *ivar;
=20
 	ivar =3D device_get_ivars(dev);
-	if (ivar && !ivar->is_onfi &&
-	    (ivar->man_id =3D=3D NAND_MAN_SAMSUNG) && (ivar->dev_id =3D=3D=
 0x75)) {
-		device_set_desc(dev, "Small Samsung NAND");
+	if (ivar && !ivar->is_onfi && ivar->params->page_size =3D=3D =
512) {
+		device_set_desc(dev, ivar->params->name);
 		return (BUS_PROBE_DEFAULT);
 	}
=20
@@ -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 =3D dev;
=20
 	ivar =3D device_get_ivars(dev);
-	chip->id.manufacturer_id =3D ivar->man_id;
-	chip->id.device_id =3D ivar->dev_id;
+	chip->id.man_id =3D ivar->man_id;
+	chip->id.dev_id =3D ivar->dev_id;
 	chip->num =3D ivar->cs;
=20
 	/* TODO remove when HW ECC supported */
@@ -243,16 +243,8 @@
 		free(onfi_params, M_DEVBUF);
=20
 	} else {
-		chip_params =3D nand_get_params(&chip->id);
-		if (chip_params =3D=3D NULL) {
-			debug("Chip description not found!"
-				"(manuf: 0x%0x, chipid: 0x%0x)\n",
-				chip->id.manufacturer_id,
-				chip->id.device_id);
-			return (EINVAL);
-		}
=20
-		nand_set_params(chip, chip_params);
+		nand_set_params(chip, ivar->params);
 	}
=20
 	err =3D nand_init_stat(chip);
@@ -343,7 +335,7 @@
 	if (nandbus_send_command(nandbus, NAND_CMD_READ_PARAMETER))
 		return (ENXIO);
=20
-	if (nandbus_send_address(nandbus, -1, -1, PAGE_PARAMETER_DEF))
+	if (nand_send_address(chip->dev, -1, -1, PAGE_PARAMETER_DEF))
 		return (ENXIO);
=20
 	if (nandbus_start_command(nandbus))
@@ -360,13 +352,15 @@
 }
=20
 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 =3D device_get_parent(nand);
+
 	if (nandbus_send_command(nandbus, start_command))
 		return (ENXIO);
=20
-	if (nandbus_send_address(nandbus, row, column, -1))
+	if (nand_send_address(nand, row, column, -1))
 		return (ENXIO);
=20
 	if (nandbus_send_command(nandbus, end_command))
@@ -396,16 +390,17 @@
=20
 	page_to_row(&chip->chip_geom, page, &row);
=20
-	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);
=20
 	DELAY(chip->t_r);
-	if (check_fail(nandbus))
-		return (ENXIO);
=20
 	nandbus_read_buffer(nandbus, buf, len);
=20
+	if (check_fail(nandbus))
+		return (ENXIO);
+
 	pg_stat =3D &(chip->pg_stat[page]);
 	pg_stat->page_raw_read++;
=20
@@ -431,27 +426,29 @@
=20
 	offset +=3D chip->chip_geom.page_size;
=20
-	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);
=20
 	DELAY(chip->t_r);
=20
+	nandbus_read_buffer(nandbus, buf, len);
+
 	if (check_fail(nandbus))
 		return (ENXIO);
=20
-	nandbus_read_buffer(nandbus, buf, len);
-
 	return (0);
 }
=20
 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 =3D device_get_parent(nand);
+
 	if (nandbus_send_command(nandbus, NAND_CMD_PROG))
 		return (ENXIO);
=20
-	if (nandbus_send_address(nandbus, row, column, -1))
+	if (nand_send_address(nand, row, column, -1))
 		return (ENXIO);
=20
 	return (0);
@@ -491,7 +488,7 @@
 	if (!can_write(nandbus))
 		return (ENXIO);
=20
-	if (send_start_program_page(nandbus, row, offset))
+	if (send_start_program_page(nand, row, offset))
 		return (ENXIO);
=20
 	nandbus_write_buffer(nandbus, buf, len);
@@ -531,7 +528,7 @@
 	if (!can_write(nandbus))
 		return (ENXIO);
=20
-	if (send_start_program_page(nandbus, row, offset))
+	if (send_start_program_page(nand, row, offset))
 		return (ENXIO);
=20
 	nandbus_write_buffer(nandbus, buf, len);
@@ -571,7 +568,7 @@
 	if (!can_write(nandbus))
 		return (ENXIO);
=20
-	if (send_start_program_page(nandbus, row, offset))
+	if (send_start_program_page(nand, row, offset))
 		return (ENXIO);
=20
 	nandbus_write_buffer(nandbus, buf, len);
@@ -588,13 +585,14 @@
 }
=20
 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 =3D device_get_parent(nand);
=20
 	if (nandbus_send_command(nandbus, NAND_CMD_ERASE))
 		return (ENXIO);
=20
-	if (nandbus_send_address(nandbus, row, -1, -1))
+	if (nand_send_address(nand, row, -1, -1))
 		return (ENXIO);
=20
 	if (nandbus_send_command(nandbus, second_command))
@@ -615,8 +613,8 @@
 	int row;
=20
 	debug("%p erase block  %x", nand, block);
-	chip =3D device_get_softc(nand);
 	nandbus =3D device_get_parent(nand);
+	chip =3D device_get_softc(nand);
=20
 	if (block >=3D (chip->chip_geom.blks_per_lun * =
chip->chip_geom.luns))
 		return (ENXIO);
@@ -629,7 +627,7 @@
 	if (!can_write(nandbus))
 		return (ENXIO);
=20
-	send_erase_block(nandbus, row, NAND_CMD_ERASE_END);
+	send_erase_block(nand, row, NAND_CMD_ERASE_END);
=20
 	DELAY(chip->t_bers);
=20
@@ -651,8 +649,8 @@
 	int row;
=20
 	debug("%p erase block  %x", nand, block);
-	chip =3D device_get_softc(nand);
 	nandbus =3D device_get_parent(nand);
+	chip =3D device_get_softc(nand);
=20
 	if (block >=3D (chip->chip_geom.blks_per_lun * =
chip->chip_geom.luns))
 		return (ENXIO);
@@ -663,7 +661,7 @@
 	if (!can_write(nandbus))
 		return (ENXIO);
=20
-	send_erase_block(nandbus, row, NAND_CMD_ERASE_INTLV);
+	send_erase_block(nand, row, NAND_CMD_ERASE_INTLV);
=20
 	DELAY(chip->t_bers);
=20
@@ -720,13 +718,15 @@
 }
=20
 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 =3D device_get_parent(nand);
+
 	if (nandbus_send_command(nandbus, start_command))
 		return (ENXIO);
=20
-	if (nandbus_send_address(nandbus, row, column, -1))
+	if (nand_send_address(nand, row, column, -1))
 		return (ENXIO);
=20
 	if (nandbus_start_command(nandbus))
@@ -755,10 +755,10 @@
 	page_to_row(&chip->chip_geom, page, &row);
=20
 	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);
 	}
=20
@@ -790,7 +790,7 @@
=20
 	page_to_row(&chip->chip_geom, page, &row);
=20
-	if (send_small_read_page(nandbus, NAND_CMD_SMALLOOB, row, =
offset))
+	if (send_small_read_page(nand, NAND_CMD_SMALLOOB, row, offset))
 		return (ENXIO);
=20
 	DELAY(chip->t_r);
@@ -831,7 +831,7 @@
 			return (ENXIO);
 	}
=20
-	if (send_start_program_page(nandbus, row, offset))
+	if (send_start_program_page(nand, row, offset))
 		return (ENXIO);
=20
 	nandbus_write_buffer(nandbus, buf, len);
@@ -870,7 +870,7 @@
 	if (nandbus_send_command(nandbus, NAND_CMD_SMALLOOB))
 		return (ENXIO);
=20
-	if (send_start_program_page(nandbus, row, offset))
+	if (send_start_program_page(nand, row, offset))
 		return (ENXIO);
=20
 	nandbus_write_buffer(nandbus, buf, len);
@@ -886,6 +886,46 @@
 	return (0);
 }
=20
+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 =3D 0;
+	int i;
+
+	nandbus =3D device_get_parent(nand);
+	ivar =3D device_get_ivars(nand);
+
+	if (id !=3D -1) {
+		debug("send_address: send id %02x", id);
+		err =3D nandbus_send_address(nandbus, id);
+	}
+
+	if (!err && col !=3D -1) {
+		for (i =3D 0; i < ivar->cols; i++, col >>=3D 8) {
+			addr =3D (uint8_t)(col & 0xff);
+			debug("send_address: send address column %02x", =
addr);
+			err =3D nandbus_send_address(nandbus, addr);
+			if (err)
+				break;
+		}
+	}
+
+	if (!err && row !=3D -1) {
+		for (i =3D 0; i < ivar->rows; i++, row >>=3D 8) {
+			addr =3D (uint8_t)(row & 0xff);
+			debug("send_address: send address row %02x", =
addr);
+			err =3D 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 @@
=20
 	page_to_row(&chip->chip_geom, page, &row);
=20
-	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);
=20
 	DELAY(chip->t_r);
@@ -1040,7 +1080,7 @@
 	if (!can_write(nandbus))
 		return (ENXIO);
=20
-	if (send_start_program_page(nandbus, row, 0))
+	if (send_start_program_page(nand, row, 0))
 		return (ENXIO);
=20
 	if (send_end_program_page(nandbus, NAND_CMD_PROG_INTLV))
@@ -1079,7 +1119,7 @@
 	if (!can_write(nandbus))
 		return (ENXIO);
=20
-	if (send_start_program_page(nandbus, row, 0))
+	if (send_start_program_page(dev, row, 0))
 		return (ENXIO);
=20
 	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 =3D "gnand";
 	disk->d_drv1 =3D chip;
 	disk->d_maxsize =3D chip->chip_geom.block_size;
-	disk->d_sectorsize =3D chip->chip_geom.block_size;
+//	disk->d_sectorsize =3D chip->chip_geom.block_size;
+	disk->d_sectorsize =3D chip->chip_geom.page_size;
 	disk->d_mediasize =3D chip->chip_geom.chip_size;
 	disk->d_pagesize =3D chip->chip_geom.page_size;
 	disk->d_oobsize =3D chip->chip_geom.oob_size;
@@ -262,8 +263,7 @@
 	disk->d_flags =3D DISKFLAG_CANDELETE;
=20
 	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);
=20
 	gnand_create(disk);
=20
@@ -279,7 +279,7 @@
 	TASK_INIT(&chip->iotask, 0, nand_io_proc, chip);
=20
 	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);
=20
 	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>
=20
 struct nand_params nand_ids[] =3D {
-	{{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 },
 };
=20
 struct nand_params *nand_get_params(struct nand_id *id)
@@ -47,8 +51,8 @@
 	int i;
=20
 	for (i =3D 0; i < sizeof(nand_ids) / sizeof(nand_ids[0]); i++)
-		if (nand_ids[i].id.manufacturer_id =3D=3D =
id->manufacturer_id &&
-		    nand_ids[i].id.device_id =3D=3D id->device_id)
+		if (nand_ids[i].id.man_id =3D=3D id->man_id &&
+		    nand_ids[i].id.dev_id =3D=3D id->dev_id)
 			return (&nand_ids[i]);
=20
 	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 =3D 0;
+	struct nand_softc *nfc_sc;
+	struct nand_params *chip_params;
+	uint8_t cs, onfi, found =3D 0;
=20
 	sc =3D device_get_softc(dev);
 	sc->dev =3D dev;
@@ -172,10 +174,10 @@
 			continue;
=20
 		/* 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;
=20
-		if (man_id =3D=3D 0xff)
+		if (chip_id.man_id =3D=3D 0xff)
 			continue;
=20
 		/* Check if chip is ONFI compliant */
@@ -183,17 +185,39 @@
 			continue;
 		}
=20
+		chip_params =3D nand_get_params(&chip_id);
+		if (chip_params =3D=3D NULL) {
+			debug("Chip description not found!"
+				"(manuf: 0x%0x, chipid: 0x%0x)\n",
+				chip_id.man_id, chip_id.dev_id);
+			continue;
+		}
+
 		ivar =3D malloc(sizeof(struct nandbus_ivar),
 		    M_DEVBUF, M_NOWAIT);
 		if (!ivar)
 			return (ENOMEM);
=20
 		ivar->cs =3D cs;
-		ivar->man_id =3D man_id;
-		ivar->dev_id =3D dev_id;
+		ivar->cols =3D 1;
+		ivar->rows =3D 2;
+		ivar->params =3D chip_params;
+		ivar->man_id =3D chip_id.man_id;
+		ivar->dev_id =3D chip_id.dev_id;
 		ivar->is_onfi =3D onfi;
 		ivar->chip_cdev_name =3D nfc_sc->chip_cdev_name;
=20
+		/*
+		 * check what type of device we have.
+		 * devices bigger than 32MiB have on more row (3)
+		 */=20
+		if (chip_params->chip_size > 32)
+			ivar->rows++;
+		/* large page devices have one more col (2) */
+		if (chip_params->chip_size >=3D 128 &&
+		    chip_params->page_size > 512)
+			ivar->cols++;
+
 		child =3D device_add_child(dev, NULL, -1);
 		device_set_ivars(child, ivar);
 		found =3D 1;
@@ -254,7 +278,7 @@
 		return (ENXIO);
 	}
=20
-	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);
 	}
=20
-	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 @@
 }
=20
 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;
=20
-	if ((err =3D 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 =3D NFC_SEND_ADDRESS(device_get_parent(dev), address)))
+		debug("Err: Could not send address %x, err %x", address, =
err);
=20
 	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_
=20
 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;
 };
=20
 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;
 };
=20
 # 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 @@
=20
=20
 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 =3D device_get_softc(dev);
-
-	if (id !=3D -1) {
-		debug("mv_nand: send address %x", id);
-		MV_NAND_WRITE(MV_NAND_ADDRESS, id);
-	}
=20
-	/* TODO add number of address cycles to function parameters */
-	if (column !=3D -1) {
-		debug("mv_nand: send address %x",
-				column & 0xff);
-		MV_NAND_WRITE(MV_NAND_ADDRESS, column & 0xff);
-	}
-
-	if (row !=3D -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);
=20
 	return (0);
 }

--Apple-Mail-32-531872463--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?776ADF3A-4C68-486A-8640-DE0DD6B8874E>