On Sat, Jan 02, 2010 at 09:17:53AM +0100, Wolfgang Grandegger wrote:
> From: Wolfgang Grandegger <w...@denx.de>
> 
> The main differences compared to the MSCAN on the MPC5200 are:
> 
> - More flexibility in choosing the CAN source clock and frequency:
> 
>   Three different clock sources can be selected: "ip", "ref" or "sys".
>   For the latter two, a clock divider can be defined as well. If the
>   clock source is not specified by the device tree, we first try to
>   find an optimal CAN source clock based on the system clock. If that
>   is not possible, the reference clock will be used.
> 
> - The behavior of bus-off recovery is configurable:
> 
>   To comply with the usual handling of Socket-CAN bus-off recovery,
>   "recovery on request" is selected (instead of automatic recovery).
> 
> Signed-off-by: Wolfgang Grandegger <w...@denx.de>
> ---
>  drivers/net/can/mscan/Kconfig       |    2 +-
>  drivers/net/can/mscan/mpc5xxx_can.c |  234 
> +++++++++++++++++++++++++++++------
>  drivers/net/can/mscan/mscan.c       |   41 +++++--
>  drivers/net/can/mscan/mscan.h       |   81 ++++++------
>  4 files changed, 271 insertions(+), 87 deletions(-)
> 
> diff --git a/drivers/net/can/mscan/Kconfig b/drivers/net/can/mscan/Kconfig
> index cd0f2d6..723d009 100644
> --- a/drivers/net/can/mscan/Kconfig
> +++ b/drivers/net/can/mscan/Kconfig
> @@ -11,7 +11,7 @@ if CAN_MSCAN
>  
>  config CAN_MPC5XXX
>       tristate "Freescale MPC5xxx onboard CAN controller"
> -     depends on PPC_MPC52xx
> +     depends on (PPC_MPC52xx || PPC_MPC512x)
>       ---help---
>         If you say yes here you get support for Freescale's MPC5xxx
>         onboard CAN controller.
> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c 
> b/drivers/net/can/mscan/mpc5xxx_can.c
> index 1de6f63..42c719b 100644
> --- a/drivers/net/can/mscan/mpc5xxx_can.c
> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> @@ -29,6 +29,7 @@
>  #include <linux/can/dev.h>
>  #include <linux/of_platform.h>
>  #include <sysdev/fsl_soc.h>
> +#include <linux/clk.h>
>  #include <linux/io.h>
>  #include <asm/mpc52xx.h>
>  
> @@ -36,22 +37,15 @@
>  
>  #define DRV_NAME "mpc5xxx_can"
>  
> +#ifdef CONFIG_PPC_MPC5200
>  static struct of_device_id mpc52xx_cdm_ids[] __devinitdata = {
>       { .compatible = "fsl,mpc5200-cdm", },
>       {}
>  };
>  
> -/*
> - * Get frequency of the MSCAN clock source
> - *
> - * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock (IP_CLK)
> - * can be selected. According to the MPC5200 user's manual, the oscillator
> - * clock is the better choice as it has less jitter but due to a hardware
> - * bug, it can not be selected for the old MPC5200 Rev. A chips.
> - */
> -
> -static unsigned int  __devinit mpc52xx_can_clock_freq(struct of_device *of,
> -                                                   int clock_src)
> +static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev,
> +                                        const char *clock_name,
> +                                        int *mscan_clksrc)
>  {
>       unsigned int pvr;
>       struct mpc52xx_cdm  __iomem *cdm;
> @@ -61,11 +55,24 @@ static unsigned int  __devinit 
> mpc52xx_can_clock_freq(struct of_device *of,
>  
>       pvr = mfspr(SPRN_PVR);
>  
> -     freq = mpc5xxx_get_bus_frequency(of->node);
> +     /*
> +      * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock
> +      * (IP_CLK) can be selected as MSCAN clock source. According to
> +      * the MPC5200 user's manual, the oscillator clock is the better
> +      * choice as it has less jitter. For this reason, it is selected
> +      * by default. Unfortunately, it can not be selected for the old
> +      * MPC5200 Rev. A chips due toa hardware bug (check errata).

s/toa/to a/

> +      */
> +     if (clock_name && strcmp(clock_name, "ip") == 0)
> +             *mscan_clksrc = MSCAN_CLKSRC_BUS;
> +     else
> +             *mscan_clksrc = MSCAN_CLKSRC_XTAL;
> +
> +     freq = mpc5xxx_get_bus_frequency(ofdev->node);
>       if (!freq)
>               return 0;
>  
> -     if (clock_src == MSCAN_CLKSRC_BUS || pvr == 0x80822011)
> +     if (*mscan_clksrc == MSCAN_CLKSRC_BUS || pvr == 0x80822011)
>               return freq;
>  
>       /* Determine SYS_XTAL_IN frequency from the clock domain settings */
> @@ -75,7 +82,6 @@ static unsigned int  __devinit 
> mpc52xx_can_clock_freq(struct of_device *of,
>               return 0;
>       }
>       cdm = of_iomap(np_cdm, 0);
> -     of_node_put(np_cdm);
>  
>       if (in_8(&cdm->ipb_clk_sel) & 0x1)
>               freq *= 2;
> @@ -84,10 +90,157 @@ static unsigned int  __devinit 
> mpc52xx_can_clock_freq(struct of_device *of,
>       freq *= (val & (1 << 5)) ? 8 : 4;
>       freq /= (val & (1 << 6)) ? 12 : 16;
>  
> +     of_node_put(np_cdm);
>       iounmap(cdm);
>  
>       return freq;
>  }
> +#else /* !CONFIG_PPC_MPC5200 */
> +static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev,
> +                                        const char *clock_name,
> +                                        int *mscan_clksrc)
> +{
> +     return 0;
> +}
> +#endif /* CONFIG_PPC_MPC5200 */

Hmmm, I don't really like those empty functions. I once used the data-field of
struct of_device_id, which carried a function pointer to a specific
init-function for the matched device. What do you think about such an approach?

> +
> +#ifdef CONFIG_PPC_MPC512x
> +struct mpc512x_clockctl {
> +     u32 spmr;               /* System PLL Mode Reg */
> +     u32 sccr[2];            /* System Clk Ctrl Reg 1 & 2 */
> +     u32 scfr1;              /* System Clk Freq Reg 1 */
> +     u32 scfr2;              /* System Clk Freq Reg 2 */
> +     u32 reserved;
> +     u32 bcr;                /* Bread Crumb Reg */
> +     u32 pccr[12];           /* PSC Clk Ctrl Reg 0-11 */
> +     u32 spccr;              /* SPDIF Clk Ctrl Reg */
> +     u32 cccr;               /* CFM Clk Ctrl Reg */
> +     u32 dccr;               /* DIU Clk Cnfg Reg */
> +     u32 mccr[4];            /* MSCAN Clk Ctrl Reg 1-3 */
> +};
> +
> +static struct of_device_id mpc512x_clock_ids[] __devinitdata = {
> +     { .compatible = "fsl,mpc5121-clock", },
> +     {}
> +};
> +
> +static u32  __devinit mpc512x_can_get_clock(struct of_device *ofdev,
> +                                         const char *clock_name,
> +                                         int *mscan_clksrc,
> +                                         ssize_t mscan_addr)
> +{
> +     struct mpc512x_clockctl __iomem *clockctl;
> +     struct device_node *np_clock;
> +     struct clk *sys_clk, *ref_clk;
> +     int plen, clockidx, clocksrc = -1;
> +     u32 sys_freq, val, clockdiv = 1, freq = 0;
> +     const u32 *pval;
> +
> +     np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
> +     if (!np_clock) {
> +             dev_err(&ofdev->dev, "couldn't find clock node\n");
> +             return -ENODEV;
> +     }
> +     clockctl = of_iomap(np_clock, 0);
> +     if (!clockctl) {
> +             dev_err(&ofdev->dev, "couldn't map clock registers\n");
> +             return 0;
> +     }
> +
> +     /* Determine the MSCAN device index from the physical address */
> +     clockidx = (mscan_addr & 0x80) ? 1 : 0;
> +     if (mscan_addr & 0x2000)
> +             clockidx += 2;

The PSCs use 'cell-index', here we use mscan_addr to derive the index. This is
not consistent, but should be IMHO. Now, which is the preferred way? I think
I'd go for 'cell-index', as other processors might have mscan_addr shuffled.
Also, we could use 'of_iomap' again in the probe_routine.

> +
> +     /*
> +      * Clock source and divider selection: 3 different clock sources
> +      * can be selected: "ip", "ref" or "sys". For the latetr two, a
> +      * clock divider can be defined as well. If the clock source is
> +      * not specified by the device tree, we first try to find an
> +      * optimal CAN source clock based on the system clock. If that
> +      * is not posslible, the reference clock will be used.
> +      */
> +     if (clock_name && !strcmp(clock_name, "ip")) {
> +             *mscan_clksrc = MSCAN_CLKSRC_IPS;
> +             freq = mpc5xxx_get_bus_frequency(ofdev->node);
> +     } else {
> +             *mscan_clksrc = MSCAN_CLKSRC_BUS;
> +
> +             pval = of_get_property(ofdev->node,
> +                                    "fsl,mscan-clock-divider", &plen);
> +             if (pval && plen == sizeof(*pval))
> +                     clockdiv = *pval;
> +             if (!clockdiv)
> +                     clockdiv = 1;
> +
> +             if (!clock_name || !strcmp(clock_name, "sys")) {
> +                     sys_clk = clk_get(&ofdev->dev, "sys_clk");
> +                     if (!sys_clk) {
> +                             dev_err(&ofdev->dev, "couldn't get sys_clk\n");
> +                             goto exit_unmap;
> +                     }
> +                     /* Get and round up/down sys clock rate */
> +                     sys_freq = 1000000 *
> +                             ((clk_get_rate(sys_clk) + 499999) / 1000000);
> +
> +                     if (!clock_name) {
> +                             /* A multiple of 16 MHz would be optimal */
> +                             if ((sys_freq % 16000000) == 0) {
> +                                     clocksrc = 0;
> +                                     clockdiv = sys_freq / 16000000;
> +                                     freq = sys_freq / clockdiv;
> +                             }
> +                     } else {
> +                             clocksrc = 0;
> +                             freq = sys_freq / clockdiv;
> +                     }
> +             }
> +
> +             if (clocksrc < 0) {
> +                     ref_clk = clk_get(&ofdev->dev, "ref_clk");
> +                     if (!ref_clk) {
> +                             dev_err(&ofdev->dev, "couldn't get ref_clk\n");
> +                             goto exit_unmap;
> +                     }
> +                     clocksrc = 1;
> +                     freq = clk_get_rate(ref_clk) / clockdiv;
> +             }
> +     }
> +
> +     /* Disable clock */
> +     out_be32(&clockctl->mccr[clockidx], 0x0);
> +     if (clocksrc >= 0) {
> +             /* Set source and divider */
> +             val = (clocksrc << 14) | ((clockdiv - 1) << 17);
> +             out_be32(&clockctl->mccr[clockidx], val);
> +             /* Dnable clock */

Enable

> +             out_be32(&clockctl->mccr[clockidx], val | 0x10000);
> +     }
> +
> +     /* Enable MSCAN clock domain */
> +     val = in_be32(&clockctl->sccr[1]);
> +     if (!(val & (1 << 25)))
> +             out_be32(&clockctl->sccr[1], val | (1 << 25));
> +
> +     dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
> +             *mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
> +             clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
> +
> +exit_unmap:
> +     of_node_put(np_clock);
> +     iounmap(clockctl);
> +
> +     return freq;
> +}
> +#else /* !CONFIG_PPC_MPC512x */
> +static u32  __devinit mpc512x_can_get_clock(struct of_device *ofdev,
> +                                         const char *clock_name,
> +                                         int *mscan_clksrc,
> +                                         ssize_t mscan_addr)
> +{
> +     return 0;
> +}
> +#endif /* CONFIG_PPC_MPC512x */
>  
>  static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
>                                      const struct of_device_id *id)
> @@ -95,15 +248,21 @@ static int __devinit mpc5xxx_can_probe(struct of_device 
> *ofdev,
>       struct device_node *np = ofdev->node;
>       struct net_device *dev;
>       struct mscan_priv *priv;
> +     struct resource res;
>       void __iomem *base;
> -     const char *clk_src;
> -     int err, irq, clock_src;
> +     const char *clock_name = NULL;
> +     int irq, clock_src = 0;
> +     int err = -ENOMEM;
>  
> -     base = of_iomap(ofdev->node, 0);
> +     if (of_address_to_resource(np, 0, &res)) {
> +             dev_err(&ofdev->dev, "couldn't get resource address\n");
> +             return err;
> +     }
> +
> +     base = ioremap(res.start, resource_size(&res));
>       if (!base) {
>               dev_err(&ofdev->dev, "couldn't ioremap\n");
> -             err = -ENOMEM;
> -             goto exit_release_mem;
> +             return err;
>       }
>  
>       irq = irq_of_parse_and_map(np, 0);
> @@ -114,31 +273,27 @@ static int __devinit mpc5xxx_can_probe(struct of_device 
> *ofdev,
>       }
>  
>       dev = alloc_mscandev();
> -     if (!dev) {
> -             err = -ENOMEM;
> +     if (!dev)
>               goto exit_dispose_irq;
> -     }
>  
>       priv = netdev_priv(dev);
>       priv->reg_base = base;
>       dev->irq = irq;
>  
> -     /*
> -      * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock
> -      * (IP_CLK) can be selected as MSCAN clock source. According to
> -      * the MPC5200 user's manual, the oscillator clock is the better
> -      * choice as it has less jitter. For this reason, it is selected
> -      * by default.
> -      */
> -     clk_src = of_get_property(np, "fsl,mscan-clock-source", NULL);
> -     if (clk_src && strcmp(clk_src, "ip") == 0)
> -             clock_src = MSCAN_CLKSRC_BUS;
> -     else
> -             clock_src = MSCAN_CLKSRC_XTAL;
> -     priv->can.clock.freq = mpc52xx_can_clock_freq(ofdev, clock_src);
> +     clock_name = of_get_property(np, "fsl,mscan-clock-source", NULL);
> +
> +     if (of_device_is_compatible(np, "fsl,mpc5121-mscan")) {
> +             priv->type = MSCAN_TYPE_MPC5121;
> +             priv->can.clock.freq =
> +                     mpc512x_can_get_clock(ofdev, clock_name, &clock_src,
> +                                           res.start);
> +     } else {
> +             priv->type = MSCAN_TYPE_MPC5200;
> +             priv->can.clock.freq =
> +                     mpc52xx_can_get_clock(ofdev, clock_name, &clock_src);
> +     }
>       if (!priv->can.clock.freq) {
> -             dev_err(&ofdev->dev, "couldn't get MSCAN clock frequency\n");
> -             err = -ENODEV;
> +             dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n");
>               goto exit_free_mscan;
>       }
>  
> @@ -164,7 +319,7 @@ exit_dispose_irq:
>       irq_dispose_mapping(irq);
>  exit_unmap_mem:
>       iounmap(base);
> -exit_release_mem:
> +
>       return err;
>  }
>  
> @@ -227,6 +382,7 @@ static int mpc5xxx_can_resume(struct of_device *ofdev)
>  
>  static struct of_device_id __devinitdata mpc5xxx_can_table[] = {
>       {.compatible = "fsl,mpc5200-mscan"},
> +     {.compatible = "fsl,mpc5121-mscan"},
>       {},
>  };
>  
> @@ -255,5 +411,5 @@ static void __exit mpc5xxx_can_exit(void)
>  module_exit(mpc5xxx_can_exit);
>  
>  MODULE_AUTHOR("Wolfgang Grandegger <w...@grandegger.com>");
> -MODULE_DESCRIPTION("Freescale MPC5200 CAN driver");
> +MODULE_DESCRIPTION("Freescale MPC5200 and MPC521x CAN driver");

simply 5xxx?

>  MODULE_LICENSE("GPL v2");
> diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
> index abdf5e8..9812aa0 100644
> --- a/drivers/net/can/mscan/mscan.c
> +++ b/drivers/net/can/mscan/mscan.c
> @@ -169,6 +169,27 @@ static int mscan_start(struct net_device *dev)
>       return 0;
>  }
>  
> +static int mscan_restart(struct net_device *dev)
> +{
> +     struct mscan_priv *priv = netdev_priv(dev);
> +
> +     if (priv->type == MSCAN_TYPE_MPC5121) {
> +             struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +
> +             priv->can.state = CAN_STATE_ERROR_ACTIVE;
> +             if (!(in_8(&regs->canmisc) & MSCAN_BOHOLD))
> +                     dev_err(dev->dev.parent, "Oops, not bus-off");

I think this error-message could be improved :)

> +             else
> +                     out_8(&regs->canmisc, MSCAN_BOHOLD);
> +     } else {
> +             if (priv->can.state <= CAN_STATE_BUS_OFF)
> +                     mscan_set_mode(dev, MSCAN_INIT_MODE);
> +             return mscan_start(dev);
> +     }
> +
> +     return 0;
> +}
> +
>  static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device 
> *dev)
>  {
>       struct can_frame *frame = (struct can_frame *)skb->data;
> @@ -364,9 +385,12 @@ static void mscan_get_err_frame(struct net_device *dev, 
> struct can_frame *frame,
>                        * automatically. To avoid that we stop the chip doing
>                        * a light-weight stop (we are in irq-context).
>                        */
> -                     out_8(&regs->cantier, 0);
> -                     out_8(&regs->canrier, 0);
> -                     setbits8(&regs->canctl0, MSCAN_SLPRQ | MSCAN_INITRQ);
> +                     if (priv->type != MSCAN_TYPE_MPC5121) {
> +                             out_8(&regs->cantier, 0);
> +                             out_8(&regs->canrier, 0);
> +                             setbits8(&regs->canctl0,
> +                                      MSCAN_SLPRQ | MSCAN_INITRQ);
> +                     }
>                       can_bus_off(dev);
>                       break;
>               default:
> @@ -496,9 +520,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum 
> can_mode mode)
>  
>       switch (mode) {
>       case CAN_MODE_START:
> -             if (priv->can.state <= CAN_STATE_BUS_OFF)
> -                     mscan_set_mode(dev, MSCAN_INIT_MODE);
> -             ret = mscan_start(dev);
> +             ret = mscan_restart(dev);
>               if (ret)
>                       break;
>               if (netif_queue_stopped(dev))
> @@ -597,18 +619,21 @@ static const struct net_device_ops mscan_netdev_ops = {
>         .ndo_start_xmit         = mscan_start_xmit,
>  };
>  
> -int register_mscandev(struct net_device *dev, int clock_src)
> +int register_mscandev(struct net_device *dev, int mscan_clksrc)
>  {
>       struct mscan_priv *priv = netdev_priv(dev);
>       struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
>       u8 ctl1;
>  
>       ctl1 = in_8(&regs->canctl1);
> -     if (clock_src)
> +     if (mscan_clksrc)
>               ctl1 |= MSCAN_CLKSRC;
>       else
>               ctl1 &= ~MSCAN_CLKSRC;
>  
> +     if (priv->type == MSCAN_TYPE_MPC5121)
> +             ctl1 |= MSCAN_BORM; /* bus-off recovery upon request */
> +
>       ctl1 |= MSCAN_CANE;
>       out_8(&regs->canctl1, ctl1);
>       udelay(100);
> diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
> index 00fc4aa..2114942 100644
> --- a/drivers/net/can/mscan/mscan.h
> +++ b/drivers/net/can/mscan/mscan.h
> @@ -39,17 +39,19 @@
>  #define MSCAN_LOOPB          0x20
>  #define MSCAN_LISTEN         0x10
>  #define MSCAN_WUPM           0x04
> +#define MSCAN_BORM           0x08

This should be one line up to keep the sorting intact.

>  #define MSCAN_SLPAK          0x02
>  #define MSCAN_INITAK         0x01
>  
> -/* Use the MPC5200 MSCAN variant? */
> +/* Use the MPC5XXX MSCAN variant? */
>  #ifdef CONFIG_PPC
> -#define MSCAN_FOR_MPC5200
> +#define MSCAN_FOR_MPC5XXX
>  #endif
>  
> -#ifdef MSCAN_FOR_MPC5200
> +#ifdef MSCAN_FOR_MPC5XXX
>  #define MSCAN_CLKSRC_BUS     0
>  #define MSCAN_CLKSRC_XTAL    MSCAN_CLKSRC
> +#define MSCAN_CLKSRC_IPS     MSCAN_CLKSRC
>  #else
>  #define MSCAN_CLKSRC_BUS     MSCAN_CLKSRC
>  #define MSCAN_CLKSRC_XTAL    0
> @@ -136,7 +138,7 @@
>  #define MSCAN_EFF_RTR_SHIFT  0
>  #define MSCAN_EFF_FLAGS              0x18    /* IDE + SRR */
>  
> -#ifdef MSCAN_FOR_MPC5200
> +#ifdef MSCAN_FOR_MPC5XXX
>  #define _MSCAN_RESERVED_(n, num) u8 _res##n[num]
>  #define _MSCAN_RESERVED_DSR_SIZE     2
>  #else
> @@ -165,67 +167,66 @@ struct mscan_regs {
>       u8 cantbsel;                            /* + 0x14     0x0a */
>       u8 canidac;                             /* + 0x15     0x0b */
>       u8 reserved;                            /* + 0x16     0x0c */
> -     _MSCAN_RESERVED_(6, 5);                 /* + 0x17          */
> -#ifndef MSCAN_FOR_MPC5200
> -     u8 canmisc;                             /*            0x0d */
> -#endif
> +     _MSCAN_RESERVED_(6, 2);                 /* + 0x17          */
> +     u8 canmisc;                             /* + 0x19     0x0d */
> +     _MSCAN_RESERVED_(7, 2);                 /* + 0x1a          */
>       u8 canrxerr;                            /* + 0x1c     0x0e */
>       u8 cantxerr;                            /* + 0x1d     0x0f */
> -     _MSCAN_RESERVED_(7, 2);                 /* + 0x1e          */
> +     _MSCAN_RESERVED_(8, 2);                 /* + 0x1e          */
>       u16 canidar1_0;                         /* + 0x20     0x10 */
> -     _MSCAN_RESERVED_(8, 2);                 /* + 0x22          */
> +     _MSCAN_RESERVED_(9, 2);                 /* + 0x22          */
>       u16 canidar3_2;                         /* + 0x24     0x12 */
> -     _MSCAN_RESERVED_(9, 2);                 /* + 0x26          */
> +     _MSCAN_RESERVED_(10, 2);                /* + 0x26          */
>       u16 canidmr1_0;                         /* + 0x28     0x14 */
> -     _MSCAN_RESERVED_(10, 2);                /* + 0x2a          */
> +     _MSCAN_RESERVED_(11, 2);                /* + 0x2a          */
>       u16 canidmr3_2;                         /* + 0x2c     0x16 */
> -     _MSCAN_RESERVED_(11, 2);                /* + 0x2e          */
> +     _MSCAN_RESERVED_(12, 2);                /* + 0x2e          */
>       u16 canidar5_4;                         /* + 0x30     0x18 */
> -     _MSCAN_RESERVED_(12, 2);                /* + 0x32          */
> +     _MSCAN_RESERVED_(13, 2);                /* + 0x32          */
>       u16 canidar7_6;                         /* + 0x34     0x1a */
> -     _MSCAN_RESERVED_(13, 2);                /* + 0x36          */
> +     _MSCAN_RESERVED_(14, 2);                /* + 0x36          */
>       u16 canidmr5_4;                         /* + 0x38     0x1c */
> -     _MSCAN_RESERVED_(14, 2);                /* + 0x3a          */
> +     _MSCAN_RESERVED_(15, 2);                /* + 0x3a          */
>       u16 canidmr7_6;                         /* + 0x3c     0x1e */
> -     _MSCAN_RESERVED_(15, 2);                /* + 0x3e          */
> +     _MSCAN_RESERVED_(16, 2);                /* + 0x3e          */
>       struct {
>               u16 idr1_0;                     /* + 0x40     0x20 */
> -              _MSCAN_RESERVED_(16, 2);       /* + 0x42          */
> +             _MSCAN_RESERVED_(17, 2);        /* + 0x42          */
>               u16 idr3_2;                     /* + 0x44     0x22 */
> -              _MSCAN_RESERVED_(17, 2);       /* + 0x46          */
> +             _MSCAN_RESERVED_(18, 2);        /* + 0x46          */
>               u16 dsr1_0;                     /* + 0x48     0x24 */
> -              _MSCAN_RESERVED_(18, 2);       /* + 0x4a          */
> +             _MSCAN_RESERVED_(19, 2);        /* + 0x4a          */
>               u16 dsr3_2;                     /* + 0x4c     0x26 */
> -              _MSCAN_RESERVED_(19, 2);       /* + 0x4e          */
> +             _MSCAN_RESERVED_(20, 2);        /* + 0x4e          */
>               u16 dsr5_4;                     /* + 0x50     0x28 */
> -              _MSCAN_RESERVED_(20, 2);       /* + 0x52          */
> +             _MSCAN_RESERVED_(21, 2);        /* + 0x52          */
>               u16 dsr7_6;                     /* + 0x54     0x2a */
> -              _MSCAN_RESERVED_(21, 2);       /* + 0x56          */
> +             _MSCAN_RESERVED_(22, 2);        /* + 0x56          */
>               u8 dlr;                         /* + 0x58     0x2c */
> -              u8:8;                          /* + 0x59     0x2d */
> -              _MSCAN_RESERVED_(22, 2);       /* + 0x5a          */
> +             u8 reserved;                    /* + 0x59     0x2d */
> +             _MSCAN_RESERVED_(23, 2);        /* + 0x5a          */
>               u16 time;                       /* + 0x5c     0x2e */
>       } rx;
> -      _MSCAN_RESERVED_(23, 2);               /* + 0x5e          */
> +     _MSCAN_RESERVED_(24, 2);                /* + 0x5e          */
>       struct {
>               u16 idr1_0;                     /* + 0x60     0x30 */
> -              _MSCAN_RESERVED_(24, 2);       /* + 0x62          */
> +             _MSCAN_RESERVED_(25, 2);        /* + 0x62          */
>               u16 idr3_2;                     /* + 0x64     0x32 */
> -              _MSCAN_RESERVED_(25, 2);       /* + 0x66          */
> +             _MSCAN_RESERVED_(26, 2);        /* + 0x66          */
>               u16 dsr1_0;                     /* + 0x68     0x34 */
> -              _MSCAN_RESERVED_(26, 2);       /* + 0x6a          */
> +             _MSCAN_RESERVED_(27, 2);        /* + 0x6a          */
>               u16 dsr3_2;                     /* + 0x6c     0x36 */
> -              _MSCAN_RESERVED_(27, 2);       /* + 0x6e          */
> +             _MSCAN_RESERVED_(28, 2);        /* + 0x6e          */
>               u16 dsr5_4;                     /* + 0x70     0x38 */
> -              _MSCAN_RESERVED_(28, 2);       /* + 0x72          */
> +             _MSCAN_RESERVED_(29, 2);        /* + 0x72          */
>               u16 dsr7_6;                     /* + 0x74     0x3a */
> -              _MSCAN_RESERVED_(29, 2);       /* + 0x76          */
> +             _MSCAN_RESERVED_(30, 2);        /* + 0x76          */
>               u8 dlr;                         /* + 0x78     0x3c */
>               u8 tbpr;                        /* + 0x79     0x3d */
> -              _MSCAN_RESERVED_(30, 2);       /* + 0x7a          */
> +             _MSCAN_RESERVED_(31, 2);        /* + 0x7a          */
>               u16 time;                       /* + 0x7c     0x3e */
>       } tx;
> -      _MSCAN_RESERVED_(31, 2);               /* + 0x7e          */
> +     _MSCAN_RESERVED_(32, 2);                /* + 0x7e          */
>  } __attribute__ ((packed));
>  
>  #undef _MSCAN_RESERVED_
> @@ -238,6 +239,12 @@ struct mscan_regs {
>  #define MSCAN_SET_MODE_RETRIES       255
>  #define MSCAN_ECHO_SKB_MAX   3
>  
> +/* MSCAN type variants */
> +enum {
> +     MSCAN_TYPE_MPC5200,
> +     MSCAN_TYPE_MPC5121
> +};
> +
>  #define BTR0_BRP_MASK                0x3f
>  #define BTR0_SJW_SHIFT               6
>  #define BTR0_SJW_MASK                (0x3 << BTR0_SJW_SHIFT)
> @@ -270,6 +277,7 @@ struct tx_queue_entry {
>  
>  struct mscan_priv {
>       struct can_priv can;    /* must be the first member */
> +     unsigned int type;      /* MSCAN type variants */
>       long open_time;
>       unsigned long flags;
>       void __iomem *reg_base; /* ioremap'ed address to registers */
> @@ -285,11 +293,6 @@ struct mscan_priv {
>  };
>  
>  extern struct net_device *alloc_mscandev(void);
> -/*
> - * clock_src:
> - *   1 = The MSCAN clock source is the onchip Bus Clock.
> - *   0 = The MSCAN clock source is the chip Oscillator Clock.
> - */
>  extern int register_mscandev(struct net_device *dev, int clock_src);

s/clock_src/mscan_clksrc/

>  extern void unregister_mscandev(struct net_device *dev);
>  
> -- 
> 1.6.2.5
> 

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

Attachment: signature.asc
Description: Digital signature

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

Reply via email to