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(®s->canmisc) & MSCAN_BOHOLD)) > + dev_err(dev->dev.parent, "Oops, not bus-off"); I think this error-message could be improved :) > + else > + out_8(®s->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(®s->cantier, 0); > - out_8(®s->canrier, 0); > - setbits8(®s->canctl0, MSCAN_SLPRQ | MSCAN_INITRQ); > + if (priv->type != MSCAN_TYPE_MPC5121) { > + out_8(®s->cantier, 0); > + out_8(®s->canrier, 0); > + setbits8(®s->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(®s->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(®s->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/ |
signature.asc
Description: Digital signature
_______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev