Re: IXP42x rev. A0 support for network devices

From: John Woods
Date: Sun Apr 26 2009 - 19:07:04 EST


On Sun, Apr 26, 2009 at 5:58 PM, Krzysztof Halasa <khc@xxxxxxxxx> wrote:
> Hi,
>
> well, I finally found that old prototype board with IXP425 rev A0 and
> I was even able to implant some modern RedBoot to it, so I gave it
> a try.
>
> It seems that a list of rev. A0 bugs (or "bugs") isn't that long after
> all (those affecting Ethernet at least). Basically the QMgr IRQ status
> is unreliable, and the undocumented "feature" register is write-only.
>
> This patch is a bit of handcraft but it applies to 2.6.29 and
> probably to older kernels.
> Benoit, John, please let me know if it works or not. Thanks.
> --
> Krzysztof Halasa
>
> --- a/arch/arm/mach-ixp4xx/include/mach/cpu.h
> +++ b/arch/arm/mach-ixp4xx/include/mach/cpu.h
> @@ -26,6 +26,8 @@
>  #define IXP46X_PROCESSOR_ID_VALUE      0x69054200
>  #define IXP46X_PROCESSOR_ID_MASK       0xfffffff0
>
> +#define cpu_is_ixp42x_rev_a0() ((read_cpuid_id() & (IXP4XX_PROCESSOR_ID_MASK | 0xF)) == \
> +                               IXP42X_PROCESSOR_ID_VALUE)
>  #define cpu_is_ixp42x()        ((read_cpuid_id() & IXP4XX_PROCESSOR_ID_MASK) == \
>                         IXP42X_PROCESSOR_ID_VALUE)
>  #define cpu_is_ixp43x()        ((read_cpuid_id() & IXP43X_PROCESSOR_ID_MASK) == \
> @@ -35,6 +35,9 @@
>  {
>        unsigned int val = ~*IXP4XX_EXP_CFG2;
>        val &= ~IXP4XX_FEATURE_RESERVED;
> +       if (cpu_is_ixp42x_rev_a0())
> +               return ~IXP4XX_FEATURE_IXP46X_ONLY & ~(IXP4XX_FEATURE_RCOMP |
> +                                                      IXP4XX_FEATURE_AES);
>        if (!cpu_is_ixp46x())
>                val &= ~IXP4XX_FEATURE_IXP46X_ONLY;
>
> --- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c
> +++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
> @@ -386,15 +386,6 @@ static int npe_reset(struct npe *npe)
>        /* reset the NPE */
>        ixp4xx_write_feature_bits(val &
>                                  ~(IXP4XX_FEATURE_RESET_NPEA << npe->id));
> -       for (i = 0; i < MAX_RETRIES; i++) {
> -               if (!(ixp4xx_read_feature_bits() &
> -                     (IXP4XX_FEATURE_RESET_NPEA << npe->id)))
> -                       break;  /* reset completed */
> -               udelay(1);
> -       }
> -       if (i == MAX_RETRIES)
> -               return -ETIMEDOUT;
> -
>        /* deassert reset */
>        ixp4xx_write_feature_bits(val |
>                                  (IXP4XX_FEATURE_RESET_NPEA << npe->id));
> --- a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
> +++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
> @@ -41,6 +41,31 @@ void qmgr_set_irq(unsigned int queue, int src,
>  }
>
>
> +static irqreturn_t qmgr_irq1_a0(int irq, void *pdev)
> +{
> +       int i, ret = 0;
> +
> +       /* ACK - it may also clear newly requested irqs so don't rely on it */
> +       __raw_writel(__raw_readl(&qmgr_regs->irqstat[0]),
> +                    &qmgr_regs->irqstat[0]);
> +
> +       for (i = 0; i < HALF_QUEUES; i++) {
> +               u32 src, stat;
> +               if (!(qmgr_regs->irqen[0] & BIT(i)))
> +                       continue;
> +               src = qmgr_regs->irqsrc[i >> 3];
> +               stat = qmgr_regs->stat1[i >> 3];
> +               if (src & 4) /* the IRQ condition is inverted */
> +                       stat = ~stat;
> +               if (stat & BIT(src & 3)) {
> +                       irq_handlers[i](irq_pdevs[i]);
> +                       ret = IRQ_HANDLED;
> +               }
> +       }
> +       return ret;
> +}
> +
> +
>  static irqreturn_t qmgr_irq1(int irq, void *pdev)
>  {
>        int i;
> @@ -250,8 +275,8 @@ static int qmgr_init(void)
>        for (i = 0; i < QUEUES; i++)
>                __raw_writel(0, &qmgr_regs->sram[i]);
>
> -       err = request_irq(IRQ_IXP4XX_QM1, qmgr_irq1, 0,
> -                         "IXP4xx Queue Manager", NULL);
> +       err = request_irq(IRQ_IXP4XX_QM1, cpu_is_ixp42x_rev_a0() ? qmgr_irq1_a0
> +                         : qmgr_irq1, 0, "IXP4xx Queue Manager", NULL);
>        if (err) {
>                printk(KERN_ERR "qmgr: failed to request IRQ%i\n",
>                       IRQ_IXP4XX_QM1);
>

Hi Krzysztof,

I should be able to test it, in a day.
Thank You!

John Woods
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/