diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/pca953x.c | 112 | ||||
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/nand.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 29 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_util.c | 63 |
5 files changed, 162 insertions, 46 deletions
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 6e82bd6..359fdee 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c @@ -17,8 +17,8 @@ */ /* - * Driver for NXP's 4 and 8 bit I2C gpio expanders (eg pca9537, pca9557, etc) - * TODO: support additional devices with more than 8-bits GPIO + * Driver for NXP's 4, 8 and 16 bit I2C gpio expanders (eg pca9537, pca9557, + * pca9539, etc) */ #include <common.h> @@ -38,20 +38,81 @@ enum { PCA953X_CMD_INVERT, }; +#ifdef CONFIG_SYS_I2C_PCA953X_WIDTH +struct pca953x_chip_ngpio { + uint8_t chip; + uint8_t ngpio; +}; + +static struct pca953x_chip_ngpio pca953x_chip_ngpios[] = + CONFIG_SYS_I2C_PCA953X_WIDTH; + +#define NUM_CHIP_GPIOS (sizeof(pca953x_chip_ngpios) / \ + sizeof(struct pca953x_chip_ngpio)) + +/* + * Determine the number of GPIO pins supported. If we don't know we assume + * 8 pins. + */ +static int pca953x_ngpio(uint8_t chip) +{ + int i; + + for (i = 0; i < NUM_CHIP_GPIOS; i++) + if (pca953x_chip_ngpios[i].chip == chip) + return pca953x_chip_ngpios[i].ngpio; + + return 8; +} +#else +static int pca953x_ngpio(uint8_t chip) +{ + return 8; +} +#endif + /* * Modify masked bits in register */ static int pca953x_reg_write(uint8_t chip, uint addr, uint mask, uint data) { - uint8_t val; + uint8_t valb; + uint16_t valw; - if (i2c_read(chip, addr, 1, &val, 1)) - return -1; + if (pca953x_ngpio(chip) <= 8) { + if (i2c_read(chip, addr, 1, &valb, 1)) + return -1; + + valb &= ~mask; + valb |= data; + + return i2c_write(chip, addr, 1, &valb, 1); + } else { + if (i2c_read(chip, addr << 1, 1, (u8*)&valw, 2)) + return -1; - val &= ~mask; - val |= data; + valw &= ~mask; + valw |= data; - return i2c_write(chip, addr, 1, &val, 1); + return i2c_write(chip, addr << 1, 1, (u8*)&valw, 2); + } +} + +static int pca953x_reg_read(uint8_t chip, uint addr, uint *data) +{ + uint8_t valb; + uint16_t valw; + + if (pca953x_ngpio(chip) <= 8) { + if (i2c_read(chip, addr, 1, &valb, 1)) + return -1; + *data = (int)valb; + } else { + if (i2c_read(chip, addr << 1, 1, (u8*)&valw, 2)) + return -1; + *data = (int)valw; + } + return 0; } /* @@ -86,9 +147,9 @@ int pca953x_set_dir(uint8_t chip, uint mask, uint data) */ int pca953x_get_val(uint8_t chip) { - uint8_t val; + uint val; - if (i2c_read(chip, 0, 1, &val, 1)) + if (pca953x_reg_read(chip, PCA953X_IN, &val) < 0) return -1; return (int)val; @@ -102,37 +163,44 @@ int pca953x_get_val(uint8_t chip) static int pca953x_info(uint8_t chip) { int i; - uint8_t data; + uint data; + int nr_gpio = pca953x_ngpio(chip); + int msb = nr_gpio - 1; - printf("pca953x@ 0x%x:\n\n", chip); - printf("gpio pins: 76543210\n"); - printf("-------------------\n"); + printf("pca953x@ 0x%x (%d pins):\n\n", chip, nr_gpio); + printf("gpio pins: "); + for (i = msb; i >= 0; i--) + printf("%x", i); + printf("\n"); + for (i = 11 + nr_gpio; i > 0; i--) + printf("-"); + printf("\n"); - if (i2c_read(chip, PCA953X_CONF, 1, &data, 1)) + if (pca953x_reg_read(chip, PCA953X_CONF, &data) < 0) return -1; printf("conf: "); - for (i = 7; i >= 0; i--) + for (i = msb; i >= 0; i--) printf("%c", data & (1 << i) ? 'i' : 'o'); printf("\n"); - if (i2c_read(chip, PCA953X_POL, 1, &data, 1)) + if (pca953x_reg_read(chip, PCA953X_POL, &data) < 0) return -1; printf("invert: "); - for (i = 7; i >= 0; i--) + for (i = msb; i >= 0; i--) printf("%c", data & (1 << i) ? '1' : '0'); printf("\n"); - if (i2c_read(chip, PCA953X_IN, 1, &data, 1)) + if (pca953x_reg_read(chip, PCA953X_IN, &data) < 0) return -1; printf("input: "); - for (i = 7; i >= 0; i--) + for (i = msb; i >= 0; i--) printf("%c", data & (1 << i) ? '1' : '0'); printf("\n"); - if (i2c_read(chip, PCA953X_OUT, 1, &data, 1)) + if (pca953x_reg_read(chip, PCA953X_OUT, &data) < 0) return -1; printf("output: "); - for (i = 7; i >= 0; i--) + for (i = msb; i >= 0; i--) printf("%c", data & (1 << i) ? '1' : '0'); printf("\n"); diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index d5eb54a..ab8bbb3 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -296,7 +296,7 @@ int board_nand_init(struct nand_chip *nand) mtd->priv = nand; /* Detect NAND chips */ - if (nand_scan_ident(mtd, 1)) { + if (nand_scan_ident(mtd, 1, NULL)) { printk(KERN_WARNING "NAND Flash not found !\n"); return -ENXIO; } diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c index c0e068a..d987f4c 100644 --- a/drivers/mtd/nand/nand.c +++ b/drivers/mtd/nand/nand.c @@ -43,7 +43,7 @@ static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, ulong base_addr) { int maxchips = CONFIG_SYS_NAND_MAX_CHIPS; - int __attribute__((unused)) i = 0; + static int __attribute__((unused)) i = 0; if (maxchips < 1) maxchips = 1; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5239c1f..3b96b0e 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2414,10 +2414,10 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) */ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, struct nand_chip *chip, - int busw, int *maf_id) + int busw, int *maf_id, + const struct nand_flash_dev *type) { - const struct nand_flash_dev *type = NULL; - int i, dev_id, maf_idx; + int dev_id, maf_idx; int tmp_id, tmp_manf; /* Select the device */ @@ -2456,15 +2456,14 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, return ERR_PTR(-ENODEV); } - /* Lookup the flash id */ - for (i = 0; nand_flash_ids[i].name != NULL; i++) { - if (dev_id == nand_flash_ids[i].id) { - type = &nand_flash_ids[i]; - break; - } - } + if (!type) + type = nand_flash_ids; + + for (; type->name != NULL; type++) + if (dev_id == type->id) + break; - if (!type) { + if (!type->name) { /* supress warning if there is no nand */ if (*maf_id != 0x00 && *maf_id != 0xff && dev_id != 0x00 && dev_id != 0xff) @@ -2580,13 +2579,15 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, * nand_scan_ident - [NAND Interface] Scan for the NAND device * @mtd: MTD device structure * @maxchips: Number of chips to scan for + * @table: Alternative NAND ID table * * This is the first phase of the normal nand_scan() function. It * reads the flash ID and sets up MTD fields accordingly. * * The mtd->owner field must be set to the module of the caller. */ -int nand_scan_ident(struct mtd_info *mtd, int maxchips) +int nand_scan_ident(struct mtd_info *mtd, int maxchips, + const struct nand_flash_dev *table) { int i, busw, nand_maf_id; struct nand_chip *chip = mtd->priv; @@ -2598,7 +2599,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips) nand_set_defaults(chip, busw); /* Read the flash type */ - type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id); + type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id, table); if (IS_ERR(type)) { #ifndef CONFIG_SYS_NAND_QUIET_TEST @@ -2869,7 +2870,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips) { int ret; - ret = nand_scan_ident(mtd, maxchips); + ret = nand_scan_ident(mtd, maxchips, NULL); if (!ret) ret = nand_scan_tail(mtd); return ret; diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 22c7411..8b4f738 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -447,17 +447,34 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length) * @param nand NAND device * @param offset offset in flash * @param length buffer length - * @param buf buffer to read from + * @param buffer buffer to read from + * @param withoob whether write with yaffs format * @return 0 in case of success */ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, - u_char *buffer) + u_char *buffer, int withoob) { - int rval; + int rval = 0, blocksize; size_t left_to_write = *length; u_char *p_buffer = buffer; int need_skip; +#ifdef CONFIG_CMD_NAND_YAFFS + if (withoob) { + int pages; + pages = nand->erasesize / nand->writesize; + blocksize = (pages * nand->oobsize) + nand->erasesize; + if (*length % (nand->writesize + nand->oobsize)) { + printf ("Attempt to write incomplete page" + " in yaffs mode\n"); + return -EINVAL; + } + } else +#endif + { + blocksize = nand->erasesize; + } + /* * nand_write() handles unaligned, partial page writes. * @@ -506,12 +523,44 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, continue; } - if (left_to_write < (nand->erasesize - block_offset)) + if (left_to_write < (blocksize - block_offset)) write_size = left_to_write; else - write_size = nand->erasesize - block_offset; + write_size = blocksize - block_offset; + +#ifdef CONFIG_CMD_NAND_YAFFS + if (withoob) { + int page, pages; + size_t pagesize = nand->writesize; + size_t pagesize_oob = pagesize + nand->oobsize; + struct mtd_oob_ops ops; + + ops.len = pagesize; + ops.ooblen = nand->oobsize; + ops.mode = MTD_OOB_AUTO; + ops.ooboffs = 0; + + pages = write_size / pagesize_oob; + for (page = 0; page < pages; page++) { + ops.datbuf = p_buffer; + ops.oobbuf = ops.datbuf + pagesize; + + rval = nand->write_oob(nand, offset, &ops); + if (!rval) + break; + + offset += pagesize; + p_buffer += pagesize_oob; + } + } + else +#endif + { + rval = nand_write (nand, offset, &write_size, p_buffer); + offset += write_size; + p_buffer += write_size; + } - rval = nand_write (nand, offset, &write_size, p_buffer); if (rval != 0) { printf ("NAND write to offset %llx failed %d\n", offset, rval); @@ -520,8 +569,6 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, } left_to_write -= write_size; - offset += write_size; - p_buffer += write_size; } return 0; |