Hi Anatolij,

I had a close look...

Anatolij Gustschin wrote:
>     drivers/net/fs_enet/*
>         Enable fs_enet driver to work 5121 FEC
>         Enable it with CONFIG_FS_ENET_MPC5121_FEC
> 
> Signed-off-by: John Rigby <jcri...@gmail.com>
> Signed-off-by: Piotr Ziecik <ko...@semihalf.com>
> Signed-off-by: Wolfgang Denk <w...@denx.de>
> Signed-off-by: Anatolij Gustschin <ag...@denx.de>
> Cc: <linuxppc-...@ozlabs.org>
> Cc: Grant Likely <grant.lik...@secretlab.ca>
> ---
> Changes since previous submited version:
> 
> - explicit type usage in register tables.
> - don't use same variable name "fecp" for variables of
>   different types.
> - avoid re-checking the compatible by passing data pointer
>   in the match struct.
> 
>  drivers/net/fs_enet/Kconfig        |   10 +-
>  drivers/net/fs_enet/fs_enet-main.c |    4 +
>  drivers/net/fs_enet/fs_enet.h      |   40 +++++++-
>  drivers/net/fs_enet/mac-fec.c      |  212 
> +++++++++++++++++++++++++-----------
>  drivers/net/fs_enet/mii-fec.c      |   76 ++++++++++---
>  drivers/net/fs_enet/mpc5121_fec.h  |   64 +++++++++++
>  drivers/net/fs_enet/mpc8xx_fec.h   |   37 ++++++
>  7 files changed, 356 insertions(+), 87 deletions(-)
>  create mode 100644 drivers/net/fs_enet/mpc5121_fec.h
>  create mode 100644 drivers/net/fs_enet/mpc8xx_fec.h
> 
> diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
> index 562ea68..fc073b5 100644
> --- a/drivers/net/fs_enet/Kconfig
> +++ b/drivers/net/fs_enet/Kconfig
> @@ -1,9 +1,13 @@
>  config FS_ENET
>         tristate "Freescale Ethernet Driver"
> -       depends on CPM1 || CPM2
> +       depends on CPM1 || CPM2 || PPC_MPC512x
>         select MII
>         select PHYLIB
>  
> +config FS_ENET_MPC5121_FEC
> +     def_bool y if (FS_ENET && PPC_MPC512x)
> +     select FS_ENET_HAS_FEC
> +
>  config FS_ENET_HAS_SCC
>       bool "Chip has an SCC usable for ethernet"
>       depends on FS_ENET && (CPM1 || CPM2)
> @@ -16,13 +20,13 @@ config FS_ENET_HAS_FCC
>  
>  config FS_ENET_HAS_FEC
>       bool "Chip has an FEC usable for ethernet"
> -     depends on FS_ENET && CPM1
> +     depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC)
>       select FS_ENET_MDIO_FEC
>       default y
>  
>  config FS_ENET_MDIO_FEC
>       tristate "MDIO driver for FEC"
> -     depends on FS_ENET && CPM1
> +     depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC)
>  
>  config FS_ENET_MDIO_FCC
>       tristate "MDIO driver for FCC"
> diff --git a/drivers/net/fs_enet/fs_enet-main.c 
> b/drivers/net/fs_enet/fs_enet-main.c
> index c34a7e0..6bce5c8 100644
> --- a/drivers/net/fs_enet/fs_enet-main.c
> +++ b/drivers/net/fs_enet/fs_enet-main.c
> @@ -1095,6 +1095,10 @@ static struct of_device_id fs_enet_match[] = {
>  #endif
>  #ifdef CONFIG_FS_ENET_HAS_FEC
>       {
> +             .compatible = "fsl,mpc5121-fec",
> +             .data = (void *)&fs_fec_ops,
> +     },
> +     {
>               .compatible = "fsl,pq1-fec-enet",
>               .data = (void *)&fs_fec_ops,
>       },
> diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
> index ef01e09..df935e8 100644
> --- a/drivers/net/fs_enet/fs_enet.h
> +++ b/drivers/net/fs_enet/fs_enet.h
> @@ -13,11 +13,47 @@
>  
>  #ifdef CONFIG_CPM1
>  #include <asm/cpm1.h>
> +#endif
> +
> +#if defined(CONFIG_FS_ENET_HAS_FEC)
> +#include <asm/cpm.h>
> +#include "mpc8xx_fec.h"
> +#include "mpc5121_fec.h"

Do we really need the new header files? Why not adding the struct
definitions here or use "struct fec" from 8xx_immap.h. See below.

>  struct fec_info {
> -     fec_t __iomem *fecp;
> +     void __iomem *fecp;

A name like fec_base or base_addr would help to avoid confusion with a
pointer to the old fec struct.

> +     u32 __iomem *fec_r_cntrl;
> +     u32 __iomem *fec_ecntrl;
> +     u32 __iomem *fec_ievent;
> +     u32 __iomem *fec_mii_data;
> +     u32 __iomem *fec_mii_speed;
>       u32 mii_speed;
>  };
> +
> +struct reg_tbl {

A more specific name would be nice, e.g. "fec_reg_tbl" or "fec_regs".

> +     u32 __iomem *fec_ievent;
> +     u32 __iomem *fec_imask;
> +     u32 __iomem *fec_r_des_active;
> +     u32 __iomem *fec_x_des_active;
> +     u32 __iomem *fec_r_des_start;
> +     u32 __iomem *fec_x_des_start;
> +     u32 __iomem *fec_r_cntrl;
> +     u32 __iomem *fec_ecntrl;
> +     u32 __iomem *fec_ivec;
> +     u32 __iomem *fec_mii_speed;
> +     u32 __iomem *fec_addr_low;
> +     u32 __iomem *fec_addr_high;
> +     u32 __iomem *fec_hash_table_high;
> +     u32 __iomem *fec_hash_table_low;
> +     u32 __iomem *fec_r_buff_size;
> +     u32 __iomem *fec_r_bound;
> +     u32 __iomem *fec_r_fstart;
> +     u32 __iomem *fec_x_fstart;
> +     u32 __iomem *fec_fun_code;
> +     u32 __iomem *fec_r_hash;
> +     u32 __iomem *fec_x_cntrl;
> +     u32 __iomem *fec_dma_control;
> +};
>  #endif
>  
>  #ifdef CONFIG_CPM2
> @@ -113,7 +149,9 @@ struct fs_enet_private {
>               struct {
>                       int idx;                /* FEC1 = 0, FEC2 = 1  */
>                       void __iomem *fecp;     /* hw registers        */

See above.

> +                     struct reg_tbl *rtbl;   /* used registers table */
>                       u32 hthi, htlo;         /* state for multicast */
> +                     u32 fec_id;
>               } fec;
>  
>               struct {
> diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
> index a664aa1..fe9e368 100644
> --- a/drivers/net/fs_enet/mac-fec.c
> +++ b/drivers/net/fs_enet/mac-fec.c
> @@ -64,29 +64,40 @@
>  #endif
>  
>  /* write */
> -#define FW(_fecp, _reg, _v) __fs_out32(&(_fecp)->fec_ ## _reg, (_v))
> +#define FW(_regp, _reg, _v) __fs_out32((_regp)->fec_ ## _reg, (_v))
>  
>  /* read */
> -#define FR(_fecp, _reg)      __fs_in32(&(_fecp)->fec_ ## _reg)
> +#define FR(_regp, _reg)      __fs_in32((_regp)->fec_ ## _reg)
>  
>  /* set bits */
> -#define FS(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) | (_v))
> +#define FS(_regp, _reg, _v) FW(_regp, _reg, FR(_regp, _reg) | (_v))
>  
>  /* clear bits */
> -#define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
> +#define FC(_regp, _reg, _v) FW(_regp, _reg, FR(_regp, _reg) & ~(_v))
> +
> +/* register address macros */
> +#define fec_reg_addr(_type, _reg) \
> +     (fep->fec.rtbl->fec_##_reg = (u32 __iomem *)((u32)fep->fec.fecp + \
> +                             (u32)&((__typeof__(_type) *)NULL)->fec_##_reg))

I think you don't need the cast in the first line and using "offsetof"
would simplify the macro further. I would also use _fep as first
argument to make this macro function more transparent.

> +#define fec_reg_mpc8xx(_reg) \
> +     fec_reg_addr(struct mpc8xx_fec, _reg)
> +
> +#define fec_reg_mpc5121(_reg) \
> +     fec_reg_addr(struct mpc5121_fec, _reg)

Also, s/fec_reg_addr/fec_set_reg_addr/ would give the three macros above
a more appropriate name.

>  /*
>   * Delay to wait for FEC reset command to complete (in us)
>   */
>  #define FEC_RESET_DELAY              50
>  
> -static int whack_reset(fec_t __iomem *fecp)
> +static int whack_reset(struct reg_tbl *regp)
>  {
>       int i;
>  
> -     FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
> +     FW(regp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
>       for (i = 0; i < FEC_RESET_DELAY; i++) {
> -             if ((FR(fecp, ecntrl) & FEC_ECNTRL_RESET) == 0)
> +             if ((FR(regp, ecntrl) & FEC_ECNTRL_RESET) == 0)
>                       return 0;       /* OK */
>               udelay(1);
>       }
> @@ -106,6 +117,50 @@ static int do_pd_setup(struct fs_enet_private *fep)
>       if (!fep->fcc.fccp)
>               return -EINVAL;
>  
> +     fep->fec.rtbl = kzalloc(sizeof(*fep->fec.rtbl), GFP_KERNEL);
> +     if (!fep->fec.rtbl) {
> +             iounmap(fep->fec.fecp);
> +             return -ENOMEM;
> +     }

Any reason why not adding the struct directly to fep->fec? It would save
some code for alloc/free and the addresses would be "closer" (cache wise).

> +     if (of_device_is_compatible(ofdev->node, "fsl,mpc5121-fec")) {
> +             fep->fec.fec_id = FS_ENET_MPC5121_FEC;
> +             fec_reg_mpc5121(ievent);
> +             fec_reg_mpc5121(imask);
> +             fec_reg_mpc5121(r_cntrl);
> +             fec_reg_mpc5121(ecntrl);
> +             fec_reg_mpc5121(r_des_active);
> +             fec_reg_mpc5121(x_des_active);
> +             fec_reg_mpc5121(r_des_start);
> +             fec_reg_mpc5121(x_des_start);
> +             fec_reg_mpc5121(addr_low);
> +             fec_reg_mpc5121(addr_high);
> +             fec_reg_mpc5121(hash_table_high);
> +             fec_reg_mpc5121(hash_table_low);
> +             fec_reg_mpc5121(r_buff_size);
> +             fec_reg_mpc5121(mii_speed);
> +             fec_reg_mpc5121(x_cntrl);
> +             fec_reg_mpc5121(dma_control);
> +     } else {
> +             fec_reg_mpc8xx(ievent);
> +             fec_reg_mpc8xx(imask);
> +             fec_reg_mpc8xx(r_cntrl);
> +             fec_reg_mpc8xx(ecntrl);
> +             fec_reg_mpc8xx(mii_speed);
> +             fec_reg_mpc8xx(r_des_active);
> +             fec_reg_mpc8xx(x_des_active);
> +             fec_reg_mpc8xx(r_des_start);
> +             fec_reg_mpc8xx(x_des_start);
> +             fec_reg_mpc8xx(ivec);
> +             fec_reg_mpc8xx(addr_low);
> +             fec_reg_mpc8xx(addr_high);
> +             fec_reg_mpc8xx(hash_table_high);
> +             fec_reg_mpc8xx(hash_table_low);
> +             fec_reg_mpc8xx(r_buff_size);
> +             fec_reg_mpc8xx(x_fstart);
> +             fec_reg_mpc8xx(r_hash);
> +             fec_reg_mpc8xx(x_cntrl);
> +     }
>       return 0;
>  }
>  
> @@ -162,15 +217,17 @@ static void free_bd(struct net_device *dev)
>  
>  static void cleanup_data(struct net_device *dev)
>  {
> -     /* nothing */
> +     struct fs_enet_private *fep = netdev_priv(dev);
> +
> +     kfree(fep->fec.rtbl);
>  }

See above.

[snip]
> +++ b/drivers/net/fs_enet/mpc5121_fec.h
> @@ -0,0 +1,64 @@
> +/*
> + * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
> + *
> + * Author: John Rigby, <jri...@freescale.com>
> + *
> + * Modified version of drivers/net/fec.h:
> + *
> + *   fec.h  --  Fast Ethernet Controller for Motorola ColdFire SoC
> + *              processors.
> + *
> + *   (C) Copyright 2000-2005, Greg Ungerer (g...@snapgear.com)
> + *   (C) Copyright 2000-2001, Lineo (www.lineo.com)
> + *
> + * This is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +#ifndef MPC5121_FEC_H
> +#define MPC5121_FEC_H
> +
> +struct mpc5121_fec {
> +     u32 fec_reserved0;
> +     u32 fec_ievent;                 /* Interrupt event reg */
> +     u32 fec_imask;                  /* Interrupt mask reg */
> +     u32 fec_reserved1;
> +     u32 fec_r_des_active;           /* Receive descriptor reg */
> +     u32 fec_x_des_active;           /* Transmit descriptor reg */
> +     u32 fec_reserved2[3];
> +     u32 fec_ecntrl;                 /* Ethernet control reg */
> +     u32 fec_reserved3[6];
> +     u32 fec_mii_data;               /* MII manage frame reg */
> +     u32 fec_mii_speed;              /* MII speed control reg */
> +     u32 fec_reserved4[7];
> +     u32 fec_mib_ctrlstat;           /* MIB control/status reg */
> +     u32 fec_reserved5[7];
> +     u32 fec_r_cntrl;                /* Receive control reg */
> +     u32 fec_reserved6[15];
> +     u32 fec_x_cntrl;                /* Transmit Control reg */
> +     u32 fec_reserved7[7];
> +     u32 fec_addr_low;               /* Low 32bits MAC address */
> +     u32 fec_addr_high;              /* High 16bits MAC address */
> +     u32 fec_opd;                    /* Opcode + Pause duration */
> +     u32 fec_reserved8[10];
> +     u32 fec_hash_table_high;        /* High 32bits hash table */
> +     u32 fec_hash_table_low;         /* Low 32bits hash table */
> +     u32 fec_grp_hash_table_high;    /* High 32bits hash table */
> +     u32 fec_grp_hash_table_low;     /* Low 32bits hash table */
> +     u32 fec_reserved9[7];
> +     u32 fec_x_wmrk;                 /* FIFO transmit water mark */
> +     u32 fec_reserved10;
> +     u32 fec_r_bound;                /* FIFO receive bound reg */
> +     u32 fec_r_fstart;               /* FIFO receive start reg */
> +     u32 fec_reserved11[11];
> +     u32 fec_r_des_start;            /* Receive descriptor ring */
> +     u32 fec_x_des_start;            /* Transmit descriptor ring */
> +     u32 fec_r_buff_size;            /* Maximum receive buff size */
> +     u32 fec_reserved12[26];
> +     u32 fec_dma_control;            /* DMA Endian and other ctrl */
> +};
> +
> +#define FS_ENET_MPC5121_FEC  0x1
> +
> +#endif /* MPC5121_FEC_H */
> diff --git a/drivers/net/fs_enet/mpc8xx_fec.h 
> b/drivers/net/fs_enet/mpc8xx_fec.h
> new file mode 100644
> index 0000000..aa78445
> --- /dev/null
> +++ b/drivers/net/fs_enet/mpc8xx_fec.h
> @@ -0,0 +1,37 @@
> +/* MPC860T Fast Ethernet Controller.  It isn't part of the CPM, but
> + * it fits within the address space.
> + */
> +

The usual "#ifndef" stuff is missing, in case you keep it.

> +struct mpc8xx_fec {
> +     uint    fec_addr_low;           /* lower 32 bits of station address */
> +     ushort  fec_addr_high;          /* upper 16 bits of station address */
> +     ushort  res1;                   /* reserved                         */
> +     uint    fec_hash_table_high;    /* upper 32-bits of hash table      */
> +     uint    fec_hash_table_low;     /* lower 32-bits of hash table      */
> +     uint    fec_r_des_start;        /* beginning of Rx descriptor ring  */
> +     uint    fec_x_des_start;        /* beginning of Tx descriptor ring  */
> +     uint    fec_r_buff_size;        /* Rx buffer size                   */
> +     uint    res2[9];                /* reserved                         */
> +     uint    fec_ecntrl;             /* ethernet control register        */
> +     uint    fec_ievent;             /* interrupt event register         */
> +     uint    fec_imask;              /* interrupt mask register          */
> +     uint    fec_ivec;               /* interrupt level and vector status */
> +     uint    fec_r_des_active;       /* Rx ring updated flag             */
> +     uint    fec_x_des_active;       /* Tx ring updated flag             */
> +     uint    res3[10];               /* reserved                         */
> +     uint    fec_mii_data;           /* MII data register                */
> +     uint    fec_mii_speed;          /* MII speed control register       */
> +     uint    res4[17];               /* reserved                         */
> +     uint    fec_r_bound;            /* end of RAM (read-only)           */
> +     uint    fec_r_fstart;           /* Rx FIFO start address            */
> +     uint    res5[6];                /* reserved                         */
> +     uint    fec_x_fstart;           /* Tx FIFO start address            */
> +     uint    res6[17];               /* reserved                         */
> +     uint    fec_fun_code;           /* fec SDMA function code           */
> +     uint    res7[3];                /* reserved                         */
> +     uint    fec_r_cntrl;            /* Rx control register              */
> +     uint    fec_r_hash;             /* Rx hash register                 */
> +     uint    res8[14];               /* reserved                         */
> +     uint    fec_x_cntrl;            /* Tx control register              */
> +     uint    res9[0x1e];             /* reserved                         */
> +};

As mentioned above, I do not see a need for two extra header files. The
struct(s) could be added to fec.h. Also a similar "struct fec" is
already defined in "arch/powerpc/include/asm/8xx_immap.h", which could
be used instead of "struct mpc8xx_fec" above.

Wolfgang.
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to