Hi Rafal, Le dimanche 05 août 2012 22:03:07, Rafał Miłecki a écrit : > This is basic driver for NAND flash memory that allows reading it's > content. It was succesfully tested on Netgear WNDR4500 which is BCM4706 > based router. > > This driver has been written using specs at: > http://bcm-v4.sipsolutions.net/NAND_Flash The big problem that I see with your driver is that it does not interface with the MTD subsystem, and therefore: - does not conform to the MTD API for reading pages, blocks etc... - duplicates NAND flash detection in a manner which is far less robust than what the MTD NAND subsystem already does I guess that this driver enables you do some stuff on your router, but clearly you should aim at writing a real MTD driver instead of having such an ad-hoc solution. > > Signed-off-by: Rafał Miłecki <zajec5@xxxxxxxxx> > CC: Larry Finger <Larry.Finger@xxxxxxxxxxxx> > CC: Hauke Mehrtens <hauke@xxxxxxxxxx> > --- > V2: Split bcma_nflash_read into three functions as suggested by Hauke > Use bcma_* for printing > --- > drivers/bcma/Kconfig | 4 +- > drivers/bcma/bcma_private.h | 2 +- > drivers/bcma/driver_chipcommon_nflash.c | 402 > ++++++++++++++++++++++++++- drivers/bcma/driver_chipcommon_pmu.c | > 2 +- > include/linux/bcma/bcma_driver_chipcommon.h | 88 ++++++ > 5 files changed, 490 insertions(+), 8 deletions(-) > > diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig > index 8d1f777..a58d7a9 100644 > --- a/drivers/bcma/Kconfig > +++ b/drivers/bcma/Kconfig > @@ -53,8 +53,8 @@ config BCMA_SFLASH > default y > > config BCMA_NFLASH > - bool > - depends on BCMA_DRIVER_MIPS && BROKEN > + bool "Support for NAND flash" > + depends on BCMA_DRIVER_MIPS > default y > > config BCMA_DRIVER_GMAC_CMN > diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h > index 3cf9cc9..9895c7e 100644 > --- a/drivers/bcma/bcma_private.h > +++ b/drivers/bcma/bcma_private.h > @@ -68,7 +68,7 @@ int bcma_nflash_init(struct bcma_drv_cc *cc); > #else > static inline int bcma_nflash_init(struct bcma_drv_cc *cc) > { > - bcma_err(cc->core->bus, "NAND flash not supported\n"); > + bcma_err(cc->core->bus, "NAND flash support not enabled\n"); > return 0; > } > #endif /* CONFIG_BCMA_NFLASH */ > diff --git a/drivers/bcma/driver_chipcommon_nflash.c > b/drivers/bcma/driver_chipcommon_nflash.c index 574d624..0d11e6f 100644 > --- a/drivers/bcma/driver_chipcommon_nflash.c > +++ b/drivers/bcma/driver_chipcommon_nflash.c > @@ -2,18 +2,412 @@ > * Broadcom specific AMBA > * ChipCommon NAND flash interface > * > + * Copyright 2012, Rafał Miłecki <zajec5@xxxxxxxxx> > + * > * Licensed under the GNU/GPL. See COPYING for details. > */ > > +#include "bcma_private.h" > #include <linux/bcma/bcma.h> > #include <linux/bcma/bcma_driver_chipcommon.h> > #include <linux/delay.h> > > -#include "bcma_private.h" > +/* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 > has + * shown 6 retries were enough. */ > +#define NFLASH_READY_RETRIES 100 > > -/* Initialize NAND flash access */ > -int bcma_nflash_init(struct bcma_drv_cc *cc) > +/************************************************** > + * Various helpers > + **************************************************/ > + > +static inline u8 bcma_nflash_ns_to_cycle(u16 ns, u16 clock) > +{ > + return ((ns * 1000 * clock) / 1000000) + 1; > +} > + > +static void bcma_nflash_enable(struct bcma_drv_cc *cc, bool enable) > +{ > + if (cc->core->id.rev == 38) { > + if (cc->status & BCMA_CC_CHIPST_REV38_NAND_BOOT) > + return; > + if (enable) > + bcma_chipco_chipctl_maskset(cc, 1, ~0, 0x10000); > + else > + bcma_chipco_chipctl_maskset(cc, 1, ~0x10000, 0); > + } > +} > + > +static int bcma_nflash_ctl_cmd(struct bcma_drv_cc *cc, u32 code) > +{ > + int i = 0; > + > + bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, 0x80000000 | code); > + for (i = 0; i < NFLASH_READY_RETRIES; i++) { > + if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & 0x80000000)) { > + i = 0; > + break; > + } > + } > + if (i) { > + bcma_err(cc->core->bus, "NFLASH control command not ready!\n"); > + return -EBUSY; > + } > + return 0; > +} > + > +int bcma_nflash_poll(struct bcma_drv_cc *cc) > +{ > + int i; > + u32 tmp; > + > + if (cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { > + for (i = 0; i < NFLASH_READY_RETRIES; i++) { > + if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & > + 0x04000000) { > + if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & > + BCMA_CC_NFLASH_CTL_ERR) { > + bcma_err(cc->core->bus, "Error on polling\n"); > + return -EBUSY; > + } else { > + return 0; > + } > + } > + } > + } else { > + for (i = 0; i < NFLASH_READY_RETRIES; i++) { > + tmp = bcma_cc_read32(cc, BCMA_CC_NAND_INTFC_STATUS); > + if ((tmp & 0xC0000000) == 0xC0000000) > + return 0; > + } > + } > + bcma_err(cc->core->bus, "Polling timeout!\n"); > + return -EBUSY; > +} > + > +static void bcma_nflash_cmd(struct bcma_drv_cc *cc, u32 code) > +{ > + bcma_cc_write32(cc, BCMA_CC_NAND_CMD_START, code); > + bcma_cc_read32(cc, BCMA_CC_NAND_CMD_START); > +} > + > +static char *bcma_nflash_check_id(u8 *id) > +{ > + switch (id[0]) { > + case 0x01: > + return "AMD"; > + case 0x20: > + return "Numonyx"; > + case 0x2c: > + return "Micron"; > + case 0x98: > + return "Toshiba"; > + case 0xad: > + return "Hynix"; > + case 0xec: > + return "Samsung"; > + } > + return NULL; > +} > + > +/************************************************** > + * Initialize NAND flash access > + **************************************************/ > + > +static int bcma_nflash_init_bcm4706(struct bcma_drv_cc *cc) > +{ > + struct bcma_bus *bus = cc->core->bus; > + struct bcma_nflash *nflash = &cc->nflash; > + > + u32 freq, code, val, tmp; > + u16 clock; > + u8 w0, w1, w2, w3, w4; > + u8 cbits, tbits; > + u8 csize, rbits, bsize; > + char *name; > + int i; > + > + /* TODO: Set bit 0x8 in CC flashstrconfig Register */ > + > + if (cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) { > + freq = 100000000; > + } else { > + freq = bcma_chipco_pll_read(cc, 4); > + freq = (freq * 0xFFF) >> 3; > + freq = (freq * 25000000) >> 3; > + } > + clock = freq / 1000000; > + w0 = bcma_nflash_ns_to_cycle(15, clock); > + w1 = bcma_nflash_ns_to_cycle(20, clock); > + w2 = bcma_nflash_ns_to_cycle(10, clock); > + w3 = bcma_nflash_ns_to_cycle(10, clock); > + w4 = bcma_nflash_ns_to_cycle(100, clock); > + bcma_cc_write32(cc, BCMA_CC_NFLASH_WAITCNT0, > + (w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0)); > + if (bcma_nflash_ctl_cmd(cc, 0x40000000 | 0x01000000 | 0x00080000 | > + 0x00010000 | 0x00000090)) > + return -EBUSY; > + > + for (i = 0; i < 5; i++) { > + /* Useless Broadcom condition dropped */ > + code = 0x40000000 | 0x00100000; > + if (bcma_nflash_ctl_cmd(cc, code)) > + return -EBUSY; > + else > + nflash->id[i] = > + bcma_cc_read32(cc, BCMA_CC_NFLASH_DATA) & 0xFF; > + } > + > + name = bcma_nflash_check_id(nflash->id); > + if (name == NULL) { > + bcma_err(bus, "Invalid flash id: 0x%X\n", nflash->id[0]); > + /* TODO: Clear bit 8 of Register flashstrconfig */ > + return -ENOTSUPP; > + } > + > + nflash->type = nflash->id[0]; > + nflash->pagesize = 1024 << (nflash->id[3] & 0x3); > + nflash->blocksize = (64 * 1024) << ((nflash->id[3] >> 4) & 0x3); > + tmp = (8 << ((nflash->id[3] >> 2) & 0x1)); > + nflash->oobsize = tmp * nflash->pagesize / 512; > + nflash->size = (8 << ((nflash->id[4] >> 4) & 0x7)) * > + (1 << ((nflash->id[4] >> 2) & 0x3)); > + > + tbits = ffs(nflash->size); /* find first bit set */ > + if (!tbits || tbits != fls(nflash->size)) { > + bcma_err(bus, "Invalid flash size 0x%X\n", nflash->size); > + return -ENOTSUPP; > + } > + tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */ > + > + cbits = ffs(nflash->pagesize); > + if (!cbits || cbits != fls(nflash->pagesize)) { > + bcma_err(bus, "Invalid flash pagesize 0x%X\n", > + nflash->pagesize); > + return -ENOTSUPP; > + } > + > + nflash->col_mask = (1 << cbits) - 1; > + nflash->row_shift = cbits; > + csize = (cbits + 7) / 8; > + rbits = tbits - cbits + 1; > + bsize = (rbits + 7) / 8; > + val = ((bsize - 1) << 6) | ((csize - 1) << 4) | 2; > + bcma_cc_write32(cc, BCMA_CC_NFLASH_CONF, val); > + > + bcma_info(bus, "Found %s %dMiB NAND flash, pagesize: %dB, blocksize: > %dKiB\n", + name, nflash->size, nflash->pagesize, > + nflash->blocksize / 1024); > + nflash->present = true; > + return 0; > +} > + > +static int bcma_nflash_init_default(struct bcma_drv_cc *cc) > { > - bcma_err(cc->core->bus, "NAND flash support is broken\n"); > + struct bcma_bus *bus = cc->core->bus; > + struct bcma_nflash *nflash = &cc->nflash; > + u32 id, id2, ncfg, control, val; > + char *name; > + int i; > + > + bcma_nflash_enable(cc, true); > + bcma_nflash_cmd(cc, 7); > + if (bcma_nflash_poll(cc) < 0) { > + bcma_nflash_enable(cc, false); > + return -EBUSY; > + } > + bcma_nflash_enable(cc, false); > + > + id = bcma_cc_read32(cc, BCMA_CC_NAND_DEVID); > + id2 = bcma_cc_read32(cc, BCMA_CC_NAND_DEVID_X); > + for (i = 0; i < 5; i++) { > + if (i < 4) > + nflash->id[i] = (id >> (8 * i)) & 0xff; > + else > + nflash->id[i] = id2 & 0xff; > + } > + > + name = bcma_nflash_check_id(nflash->id); > + if (name == NULL) { > + bcma_err(bus, "Invalid flash id: 0x%X\n", nflash->id[0]); > + return -ENOTSUPP; > + } > + > + nflash->type = nflash->id[0]; > + > + ncfg = bcma_cc_read32(cc, BCMA_CC_NAND_CONFIG); > + switch ((ncfg >> 20) & 3) { > + case 0: > + nflash->pagesize = 0x200; > + break; > + case 1: > + nflash->pagesize = 0x800; > + break; > + case 2: > + nflash->pagesize = 0x1000; > + break; > + default: > + nflash->pagesize = 0x2000; > + break; > + } > + val = (ncfg >> 28) & 7; > + switch (val) { > + case 0: > + nflash->blocksize = 0x4000; > + break; > + case 1: > + nflash->blocksize = 0x20000; > + break; > + case 2: > + nflash->blocksize = 0x2000; > + break; > + case 3: > + nflash->blocksize = 0x80000; > + break; > + case 4: > + nflash->blocksize = 0x40000; > + break; > + default: > + nflash->blocksize = 0; > + bcma_err(bus, "Unknown blocksize\n"); > + return -ENOTSUPP; > + } > + nflash->size = (1 << (val - 1)) * 8; > + > + control = bcma_cc_read32(cc, BCMA_CC_NAND_ACC_CONTROL); > + nflash->ecclevel = (control & 0x000f0000) >> 16; > + nflash->ecclevel0 = (control & 0x00f00000) >> 20; > + if (nflash->ecclevel != nflash->ecclevel0) { > + control = control & ~(0x00ff0000); > + control = control | (nflash->ecclevel0 << 20) | > + (nflash->ecclevel0 << 16); > + bcma_cc_write32(cc, BCMA_CC_NAND_ACC_CONTROL, control); > + nflash->ecclevel = nflash->ecclevel0; > + } > + nflash->numblocks = (nflash->size * (1 << 10)) / > + (nflash->blocksize >> 10); > + if (nflash->size == 0) { > + bcma_err(bus, "Invalid flash size\n"); > + return -ENOTSUPP; > + } > + > + bcma_info(bus, "Found %s %dMiB NAND flash, pagesize: %dB, blocksize: > %dKiB\n", + name, nflash->size, nflash->pagesize, > + nflash->blocksize / 1024); > + nflash->present = true; > return 0; > } > + > +int bcma_nflash_init(struct bcma_drv_cc *cc) > +{ > + struct bcma_bus *bus = cc->core->bus; > + > + if (cc->core->bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 && > + cc->core->id.rev != 0x38) { > + bcma_err(bus, "NAND flash on unsupported board!\n"); > + return -ENOTSUPP; > + } > + > + if (!(cc->capabilities & BCMA_CC_CAP_NFLASH)) { > + bcma_err(bus, "NAND flash not present according to ChipCommon\n"); > + return -ENODEV; > + } > + > + if (cc->nflash.present) { > + bcma_warn(bus, "NAND flash already initialized"); > + return 0; > + } > + > + if (cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) > + return bcma_nflash_init_bcm4706(cc); > + else > + return bcma_nflash_init_default(cc); > +} > + > +/************************************************** > + * R/W ops > + **************************************************/ > + > +static int bcma_nflash_read_bcm4706(struct bcma_drv_cc *cc, uint offset, > + uint len, u8 *buf) > +{ > + struct bcma_nflash *nflash = &cc->nflash; > + u32 page_offset, page_addr, ctrlcode; > + u32 *dest = (u32 *)buf; > + uint remains = len; > + int i; > + > + while (remains > 0) { > + page_offset = offset & (nflash->pagesize - 1); > + page_addr = (offset & ~(nflash->pagesize - 1)) * > + 2 + page_offset; > + bcma_cc_write32(cc, BCMA_CC_NFLASH_COL_ADDR, > + page_addr & nflash->col_mask); > + bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR, > + page_addr >> nflash->row_shift); > + > + ctrlcode = 0x40000000 | 0x00080000 | 0x00040000 | 0x00020000 | > + 0x00010000 | 0x3000; > + if (bcma_nflash_ctl_cmd(cc, ctrlcode)) > + break; > + if (bcma_nflash_poll(cc) < 0) > + break; > + for (i = 0; i < 512; i += 4, dest++) { > + if (i < 508) > + ctrlcode = 0x40000000 | 0x30000000 | 0x00100000; > + else > + ctrlcode = 0x30000000 | 0x00100000; > + if (bcma_nflash_ctl_cmd(cc, ctrlcode)) > + return len - remains; > + *dest = bcma_cc_read32(cc, BCMA_CC_NFLASH_DATA); > + } > + remains -= 512; > + offset += 512; > + } > + return len - remains; > +} > + > +static int bcma_nflash_read_default(struct bcma_drv_cc *cc, uint offset, > + uint len, u8 *buf) > +{ > + u32 *dest = (u32 *)buf; > + uint remains = len; > + int i; > + > + bcma_nflash_enable(cc, true); > + while (remains > 0) { > + bcma_cc_write32(cc, BCMA_CC_NAND_CMD_ADDR, offset); > + bcma_nflash_cmd(cc, 1); > + if (bcma_nflash_poll(cc) < 0) > + break; > + if (!(bcma_cc_read32(cc, BCMA_CC_NAND_INTFC_STATUS) & > + 0x20000000)) > + break; > + for (i = 0; i < 512; i += 4, dest++) > + *dest = bcma_cc_read32(cc, BCMA_CC_NAND_CACHE_DATA); > + remains -= 512; > + offset += 512; > + } > + bcma_nflash_enable(cc, false); > + return len - remains; > +} > + > +int bcma_nflash_read(struct bcma_drv_cc *cc, uint offset, uint len, u8 > *buf) +{ > + struct bcma_nflash *nflash = &cc->nflash; > + u32 mask = 0x1FF; > + u32 tmp; > + > + if ((offset & mask) != 0 || (len & mask) != 0) > + return 0; > + > + tmp = (offset + len) >> 20; > + if (tmp > nflash->size) > + return 0; > + if (tmp == nflash->size && ((offset + len) & ((1 << 20) - 1)) != 0) > + return 0; > + > + if (cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) > + return bcma_nflash_read_bcm4706(cc, offset, len, buf); > + else > + return bcma_nflash_read_default(cc, offset, len, buf); > +} > diff --git a/drivers/bcma/driver_chipcommon_pmu.c > b/drivers/bcma/driver_chipcommon_pmu.c index 4432617..fd6620e 100644 > --- a/drivers/bcma/driver_chipcommon_pmu.c > +++ b/drivers/bcma/driver_chipcommon_pmu.c > @@ -13,7 +13,7 @@ > #include <linux/export.h> > #include <linux/bcma/bcma.h> > > -static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) > +u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) > { > bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); > bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); > diff --git a/include/linux/bcma/bcma_driver_chipcommon.h > b/include/linux/bcma/bcma_driver_chipcommon.h index 3c80885..c80d8f1 > 100644 > --- a/include/linux/bcma/bcma_driver_chipcommon.h > +++ b/include/linux/bcma/bcma_driver_chipcommon.h > @@ -94,6 +94,7 @@ > #define BCMA_CC_CHIPST_4706_SFLASH_TYPE BIT(2) /* 0: 8b-p/ST-s flash, 1: > 16b-p/Atmal-s flash */ #define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* > 0: little, 1: big endian */ #define > BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */ > +#define BCMA_CC_CHIPST_REV38_NAND_BOOT BIT(4) /* NAND boot, valid for > CC rev 38 */ #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ > #define BCMA_CC_JCMD_START 0x80000000 > #define BCMA_CC_JCMD_BUSY 0x80000000 > @@ -260,6 +261,14 @@ > #define BCMA_CC_SROM_CONTROL_SIZE_16K 0x00000004 > #define BCMA_CC_SROM_CONTROL_SIZE_SHIFT 1 > #define BCMA_CC_SROM_CONTROL_PRESENT 0x00000001 > +/* NAND flash registers for BCM4706 (corerev = 31) */ > +#define BCMA_CC_NFLASH_CTL 0x01A0 > +#define BCMA_CC_NFLASH_CTL_ERR 0x08000000 > +#define BCMA_CC_NFLASH_CONF 0x01A4 > +#define BCMA_CC_NFLASH_COL_ADDR 0x01A8 > +#define BCMA_CC_NFLASH_ROW_ADDR 0x01AC > +#define BCMA_CC_NFLASH_DATA 0x01B0 > +#define BCMA_CC_NFLASH_WAITCNT0 0x01B4 > /* 0x1E0 is defined as shared BCMA_CLKCTLST */ > #define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) > */ #define BCMA_CC_UART0_DATA 0x0300 > @@ -319,6 +328,60 @@ > #define BCMA_CC_PLLCTL_ADDR 0x0660 > #define BCMA_CC_PLLCTL_DATA 0x0664 > #define BCMA_CC_SPROM 0x0800 /* SPROM beginning */ > +/* NAND flash MLC controller registers (corerev >= 38) */ > +#define BCMA_CC_NAND_REVISION 0x0C00 > +#define BCMA_CC_NAND_CMD_START 0x0C04 > +#define BCMA_CC_NAND_CMD_ADDR_X 0x0C08 > +#define BCMA_CC_NAND_CMD_ADDR 0x0C0C > +#define BCMA_CC_NAND_CMD_END_ADDR 0x0C10 > +#define BCMA_CC_NAND_CS_NAND_SELECT 0x0C14 > +#define BCMA_CC_NAND_CS_NAND_XOR 0x0C18 > +#define BCMA_CC_NAND_SPARE_RD0 0x0C20 > +#define BCMA_CC_NAND_SPARE_RD4 0x0C24 > +#define BCMA_CC_NAND_SPARE_RD8 0x0C28 > +#define BCMA_CC_NAND_SPARE_RD12 0x0C2C > +#define BCMA_CC_NAND_SPARE_WR0 0x0C30 > +#define BCMA_CC_NAND_SPARE_WR4 0x0C34 > +#define BCMA_CC_NAND_SPARE_WR8 0x0C38 > +#define BCMA_CC_NAND_SPARE_WR12 0x0C3C > +#define BCMA_CC_NAND_ACC_CONTROL 0x0C40 > +#define BCMA_CC_NAND_CONFIG 0x0C48 > +#define BCMA_CC_NAND_TIMING_1 0x0C50 > +#define BCMA_CC_NAND_TIMING_2 0x0C54 > +#define BCMA_CC_NAND_SEMAPHORE 0x0C58 > +#define BCMA_CC_NAND_DEVID 0x0C60 > +#define BCMA_CC_NAND_DEVID_X 0x0C64 > +#define BCMA_CC_NAND_BLOCK_LOCK_STATUS 0x0C68 > +#define BCMA_CC_NAND_INTFC_STATUS 0x0C6C > +#define BCMA_CC_NAND_ECC_CORR_ADDR_X 0x0C70 > +#define BCMA_CC_NAND_ECC_CORR_ADDR 0x0C74 > +#define BCMA_CC_NAND_ECC_UNC_ADDR_X 0x0C78 > +#define BCMA_CC_NAND_ECC_UNC_ADDR 0x0C7C > +#define BCMA_CC_NAND_READ_ERROR_COUNT 0x0C80 > +#define BCMA_CC_NAND_CORR_STAT_THRESHOLD 0x0C84 > +#define BCMA_CC_NAND_READ_ADDR_X 0x0C90 > +#define BCMA_CC_NAND_READ_ADDR 0x0C94 > +#define BCMA_CC_NAND_PAGE_PROGRAM_ADDR_X 0x0C98 > +#define BCMA_CC_NAND_PAGE_PROGRAM_ADDR 0x0C9C > +#define BCMA_CC_NAND_COPY_BACK_ADDR_X 0x0CA0 > +#define BCMA_CC_NAND_COPY_BACK_ADDR 0x0CA4 > +#define BCMA_CC_NAND_BLOCK_ERASE_ADDR_X 0x0CA8 > +#define BCMA_CC_NAND_BLOCK_ERASE_ADDR 0x0CAC > +#define BCMA_CC_NAND_INV_READ_ADDR_X 0x0CB0 > +#define BCMA_CC_NAND_INV_READ_ADDR 0x0CB4 > +#define BCMA_CC_NAND_BLK_WR_PROTECT 0x0CC0 > +#define BCMA_CC_NAND_ACC_CONTROL_CS1 0x0CD0 > +#define BCMA_CC_NAND_CONFIG_CS1 0x0CD4 > +#define BCMA_CC_NAND_TIMING_1_CS1 0x0CD8 > +#define BCMA_CC_NAND_TIMING_2_CS1 0x0CDC > +#define BCMA_CC_NAND_SPARE_RD16 0x0D30 > +#define BCMA_CC_NAND_SPARE_RD20 0x0D34 > +#define BCMA_CC_NAND_SPARE_RD24 0x0D38 > +#define BCMA_CC_NAND_SPARE_RD28 0x0D3C > +#define BCMA_CC_NAND_CACHE_ADDR 0x0D40 > +#define BCMA_CC_NAND_CACHE_DATA 0x0D44 > +#define BCMA_CC_NAND_CTRL_CONFIG 0x0D48 > +#define BCMA_CC_NAND_CTRL_STATUS 0x0D4C > > /* Divider allocation in 4716/47162/5356 */ > #define BCMA_CC_PMU5_MAINPLL_CPU 1 > @@ -424,6 +487,26 @@ struct bcma_pflash { > u32 window_size; > }; > > +#ifdef CONFIG_BCMA_NFLASH > +struct bcma_nflash { > + bool present; > + > + uint blocksize; /* Block size */ > + uint pagesize; /* Page size */ > + uint oobsize; /* OOB size per page */ > + uint numblocks; /* Number of blocks */ > + u32 type; /* Type */ > + uint size; /* Total size */ > + u8 id[5]; > + uint ecclevel; /* ECC algorithm for blocks other than block 0 */ > + uint ecclevel0; /* ECC algorithm for blocks 0 */ > + > + /* BCM4706 specific */ > + u32 col_mask; > + u32 row_shift; > +}; > +#endif > + > struct bcma_serial_port { > void *regs; > unsigned long clockspeed; > @@ -442,8 +525,12 @@ struct bcma_drv_cc { > /* Fast Powerup Delay constant */ > u16 fast_pwrup_delay; > struct bcma_chipcommon_pmu pmu; > + > #ifdef CONFIG_BCMA_DRIVER_MIPS > struct bcma_pflash pflash; > +#ifdef CONFIG_BCMA_NFLASH > + struct bcma_nflash nflash; > +#endif > > int nr_serial_ports; > struct bcma_serial_port serial_ports[4]; > @@ -488,6 +575,7 @@ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, > u32 mask, u32 value); /* PMU support */ > extern void bcma_pmu_init(struct bcma_drv_cc *cc); > > +u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset); > extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, > u32 value); > extern void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, -- Florian -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html