Hi,
i am pretty sure the pinmux is set correctly on the board, however i
will reverify it.
do you have a link to btsimonh's 3.3.8 patch ?
John
On 21/01/2014 23:52, Ben Mulvihill wrote:
> 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
>>> [email protected]
>>> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
>>>
>> _______________________________________________
>> openwrt-devel mailing list
>> [email protected]
>> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
> _______________________________________________
> openwrt-devel mailing list
> [email protected]
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
>
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel