Hi John, Thank you. I had assumed this would probably only be of any use on the HH2B. If you are going to try it (or bits of it) out on the fritz3370, I should perhaps add that BTSimonh's patch for the 3.3.8 kernel (I take it he didn't ever submit it here?) also reset the chip in the chip select function (at the end of case 0) and masked out NANDM at the end of the probe function. I removed those changes because they didn't seem to make any difference. But could the errors on the fritz3370 simply be due to wrong pinmux settings?
Ben On Tue, 2014-01-21 at 21:43 +0100, John Crispin wrote: > Hi Ben, > > oh dear, how i hate the ebu ... > > i will start by testing this patch on the fritz3370 where i have been > seeing jffs2 errors. > > in general i am all for merging this, i will need a few days to think > about this. > > John > > On 21/01/2014 20:50, Ben Mulvihill wrote: > > Together with other contributors at the now defunct psidoc site, I > > have produced a device tree and some patches to get the BT Home Hub 2B > > (Lantiq Danube-S) working with recent trunk builds. More work is needed > > before they are ready for submitting, but before going any further, I'd > > be very grateful for some advice from John Crispin or anyone else who > > wants to chip in. > > > > The Home Hub 2B has both nand and nor flash connected to the ebu, plus > > an ath9k pci wireless card, and the main difficulty is getting all three > > working at the same time without interfering with each other. The nand > > driver currently in trunk works fine, provided that open-drain is > > enabled on the ebu cs1 pin, and provided that wireless is off. However, > > the only way to get the nor chip to work reliably seems to be disable > > open-drain on ebu cs1, at which point the nand driver generates jffs2 > > errors. Regardless whether open-drain is enabled or not, switching on > > wireless also causes jffs2 errors. > > > > The solution we are using (basically an updated version of a patch > > produced by BTSimonh for the 3.3.8 kernel) is to disable open drain on > > ebu cs1 and patch the nand driver as follows: > > - move locking from the individual read and write functions to the > > chip select function, so that an entire read or write operation can > > complete uninterrupted; > > - mask pci request lines during nand access; > > - additional waiting after each nand command. > > An option in the device tree enables or disables the above. > > The latest version of my patch is appended to the message, for comment > > only - I am not submitting it at this stage. > > > > It solves the problem, and the factory firmware does something similar, > > but it feels like a hack to work round a bug elsewhere. Could it not be > > that that the ebu needs to be set up differently for this hardware > > configuration? Is some chip select logic needed in the nor driver? > > I'd love to understand what the settings in the ebu registers actually > > do, but am I right in thinking that there are no publicly available > > datasheets for Lantiq SOCs? > > > > Any enlightenment you can provide will be gratefully received. > > > > Thank you, > > > > Ben Mulvihill > > > > --- a/drivers/mtd/nand/xway_nand.c 2014-01-21 20:21:11.000000000 +0100 > > +++ b/drivers/mtd/nand/xway_nand.c 2014-01-21 20:29:16.000000000 +0100 > > @@ -54,8 +54,28 @@ > > #define NAND_CON_CSMUX (1 << 1) > > #define NAND_CON_NANDM 1 > > > > +#define DANUBE_PCI_REG32( addr ) (*(volatile u32 *)(addr)) > > +#define PCI_CR_PR_OFFSET (KSEG1+0x1E105400) > > +#define PCI_CR_PC_ARB (PCI_CR_PR_OFFSET + 0x0080) > > + > > static u32 xway_latchcmd; > > > > +/* > > + * req_mask provides a mechanism to prevent interference between > > + * nand and pci (probably only relevant for the BT Home Hub 2B). > > + * Setting it causes the corresponding pci req pins to be masked > > + * during nand access, and also moves ebu locking from the read/write > > + * functions to the chip select function to ensure that the whole > > + * operation runs with interrupts disabled. > > + * In addition it switches on some extra waiting in xway_cmd_ctrl(). > > + * This seems to be necessary if the ebu_cs1 pin has open-drain disabled, > > + * which in turn seems to be necessary for the nor chip to be recognised > > + * reliably, on a board (Home Hub 2B again) which has both nor and nand. > > + */ > > + > > +static __be32 req_mask = 0; > > +static int pci_masked = 0; > > + > > static void xway_reset_chip(struct nand_chip *chip) > > { > > unsigned long nandaddr = (unsigned long) chip->IO_ADDR_W; > > @@ -80,15 +100,36 @@ > > > > static void xway_select_chip(struct mtd_info *mtd, int chip) > > { > > + static unsigned long flags; > > > > switch (chip) { > > case -1: > > ltq_ebu_w32_mask(NAND_CON_CE, 0, EBU_NAND_CON); > > ltq_ebu_w32_mask(NAND_CON_NANDM, 0, EBU_NAND_CON); > > + > > + if (req_mask) { > > + BUG_ON(!pci_masked); > > + /* Unmask all external PCI request */ > > + DANUBE_PCI_REG32(PCI_CR_PC_ARB) &= ~(req_mask << 16); > > + pci_masked = 0; > > + > > + spin_unlock_irqrestore(&ebu_lock, flags); > > + } > > + > > break; > > case 0: > > + if (req_mask) { > > + BUG_ON(pci_masked); > > + spin_lock_irqsave(&ebu_lock, flags); > > + > > + /* Mask all external PCI request */ > > + DANUBE_PCI_REG32(PCI_CR_PC_ARB) |= (req_mask << 16); > > + pci_masked = 1; > > + } > > + > > ltq_ebu_w32_mask(0, NAND_CON_NANDM, EBU_NAND_CON); > > ltq_ebu_w32_mask(0, NAND_CON_CE, EBU_NAND_CON); > > + > > break; > > default: > > BUG(); > > @@ -101,6 +142,12 @@ > > unsigned long nandaddr = (unsigned long) this->IO_ADDR_W; > > unsigned long flags; > > > > + if (req_mask) { > > + if (cmd != NAND_CMD_STATUS) > > + ltq_ebu_w32(EBU_NAND_WAIT, 0); /* Clear nand ready */ > > + } > > + > > + > > if (ctrl & NAND_CTRL_CHANGE) { > > if (ctrl & NAND_CLE) > > xway_latchcmd = NAND_WRITE_CMD; > > @@ -109,11 +156,31 @@ > > } > > > > if (cmd != NAND_CMD_NONE) { > > - spin_lock_irqsave(&ebu_lock, flags); > > + if (!req_mask) > > + spin_lock_irqsave(&ebu_lock, flags); > > writeb(cmd, (void __iomem *) (nandaddr | xway_latchcmd)); > > while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0) > > ; > > - spin_unlock_irqrestore(&ebu_lock, flags); > > + if (!req_mask) > > + spin_unlock_irqrestore(&ebu_lock, flags); > > + } > > + > > + if (req_mask) { > > + /* > > + * program and erase have their own busy handlers > > + * status and sequential in needs no delay > > + */ > > + switch (cmd) { > > + case NAND_CMD_ERASE1: > > + case NAND_CMD_SEQIN: > > + case NAND_CMD_STATUS: > > + case NAND_CMD_READID: > > + return; > > + } > > + > > + /* wait until command is processed */ > > + while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_RD) == 0) > > + ; > > } > > } > > > > @@ -129,9 +196,11 @@ > > unsigned long flags; > > int ret; > > > > - spin_lock_irqsave(&ebu_lock, flags); > > + if (!req_mask) > > + spin_lock_irqsave(&ebu_lock, flags); > > ret = ltq_r8((void __iomem *)(nandaddr | NAND_READ_DATA)); > > - spin_unlock_irqrestore(&ebu_lock, flags); > > + if (!req_mask) > > + spin_unlock_irqrestore(&ebu_lock, flags); > > > > return ret; > > } > > @@ -143,10 +212,12 @@ > > unsigned long flags; > > int i; > > > > - spin_lock_irqsave(&ebu_lock, flags); > > + if (!req_mask) > > + spin_lock_irqsave(&ebu_lock, flags); > > for (i = 0; i < len; i++) > > buf[i] = ltq_r8((void __iomem *)(nandaddr | NAND_READ_DATA)); > > - spin_unlock_irqrestore(&ebu_lock, flags); > > + if (!req_mask) > > + spin_unlock_irqrestore(&ebu_lock, flags); > > } > > > > static void xway_write_buf(struct mtd_info *mtd, const u_char *buf, int > > len) > > @@ -156,16 +227,20 @@ > > unsigned long flags; > > int i; > > > > - spin_lock_irqsave(&ebu_lock, flags); > > + if (!req_mask) > > + spin_lock_irqsave(&ebu_lock, flags); > > for (i = 0; i < len; i++) > > ltq_w8(buf[i], (void __iomem *)nandaddr); > > - spin_unlock_irqrestore(&ebu_lock, flags); > > + if (!req_mask) > > + spin_unlock_irqrestore(&ebu_lock, flags); > > } > > > > static int xway_nand_probe(struct platform_device *pdev) > > { > > struct nand_chip *this = platform_get_drvdata(pdev); > > unsigned long nandaddr = (unsigned long) this->IO_ADDR_W; > > + const __be32 *req_mask_ptr = of_get_property(pdev->dev.of_node, > > + "req-mask", NULL); > > const __be32 *cs = of_get_property(pdev->dev.of_node, > > "lantiq,cs", NULL); > > u32 cs_flag = 0; > > @@ -174,6 +249,8 @@ > > if (cs && (*cs == 1)) > > cs_flag = NAND_CON_IN_CS1 | NAND_CON_OUT_CS1; > > > > + req_mask = (req_mask_ptr ? *req_mask_ptr : 0); > > + > > /* setup the EBU to run in NAND mode on our base addr */ > > ltq_ebu_w32(CPHYSADDR(nandaddr) > > | ADDSEL1_MASK(3) | ADDSEL1_REGEN, EBU_ADDSEL1); > > _______________________________________________ > > openwrt-devel mailing list > > openwrt-devel@lists.openwrt.org > > https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel > > > _______________________________________________ > openwrt-devel mailing list > openwrt-devel@lists.openwrt.org > https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel