diff options
| -rw-r--r-- | drivers/net/can/mscan/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/net/can/mscan/mpc5xxx_can.c | 246 | ||||
| -rw-r--r-- | drivers/net/can/mscan/mscan.c | 51 | ||||
| -rw-r--r-- | drivers/net/can/mscan/mscan.h | 86 |
4 files changed, 295 insertions, 95 deletions
diff --git a/drivers/net/can/mscan/Kconfig b/drivers/net/can/mscan/Kconfig index cd0f2d6f375d..27d1d398e25e 100644 --- a/drivers/net/can/mscan/Kconfig +++ b/drivers/net/can/mscan/Kconfig | |||
| @@ -11,12 +11,13 @@ if CAN_MSCAN | |||
| 11 | 11 | ||
| 12 | config CAN_MPC5XXX | 12 | config CAN_MPC5XXX |
| 13 | tristate "Freescale MPC5xxx onboard CAN controller" | 13 | tristate "Freescale MPC5xxx onboard CAN controller" |
| 14 | depends on PPC_MPC52xx | 14 | depends on (PPC_MPC52xx || PPC_MPC512x) |
| 15 | ---help--- | 15 | ---help--- |
| 16 | If you say yes here you get support for Freescale's MPC5xxx | 16 | If you say yes here you get support for Freescale's MPC5xxx |
| 17 | onboard CAN controller. | 17 | onboard CAN controller. Currently, the MPC5200, MPC5200B and |
| 18 | MPC5121 (Rev. 2 and later) are supported. | ||
| 18 | 19 | ||
| 19 | This driver can also be built as a module. If so, the module | 20 | This driver can also be built as a module. If so, the module |
| 20 | will be called mscan-mpc5xxx.ko. | 21 | will be called mscan-mpc5xxx.ko. |
| 21 | 22 | ||
| 22 | endif | 23 | endif |
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 1de6f6349b16..f73487f723b8 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/can/dev.h> | 29 | #include <linux/can/dev.h> |
| 30 | #include <linux/of_platform.h> | 30 | #include <linux/of_platform.h> |
| 31 | #include <sysdev/fsl_soc.h> | 31 | #include <sysdev/fsl_soc.h> |
| 32 | #include <linux/clk.h> | ||
| 32 | #include <linux/io.h> | 33 | #include <linux/io.h> |
| 33 | #include <asm/mpc52xx.h> | 34 | #include <asm/mpc52xx.h> |
| 34 | 35 | ||
| @@ -36,22 +37,21 @@ | |||
| 36 | 37 | ||
| 37 | #define DRV_NAME "mpc5xxx_can" | 38 | #define DRV_NAME "mpc5xxx_can" |
| 38 | 39 | ||
| 39 | static struct of_device_id mpc52xx_cdm_ids[] __devinitdata = { | 40 | struct mpc5xxx_can_data { |
| 41 | unsigned int type; | ||
| 42 | u32 (*get_clock)(struct of_device *ofdev, const char *clock_name, | ||
| 43 | int *mscan_clksrc); | ||
| 44 | }; | ||
| 45 | |||
| 46 | #ifdef CONFIG_PPC_MPC5200 | ||
| 47 | static struct of_device_id __devinitdata mpc52xx_cdm_ids[] = { | ||
| 40 | { .compatible = "fsl,mpc5200-cdm", }, | 48 | { .compatible = "fsl,mpc5200-cdm", }, |
| 41 | {} | 49 | {} |
| 42 | }; | 50 | }; |
| 43 | 51 | ||
| 44 | /* | 52 | static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, |
| 45 | * Get frequency of the MSCAN clock source | 53 | const char *clock_name, |
| 46 | * | 54 | int *mscan_clksrc) |
| 47 | * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock (IP_CLK) | ||
| 48 | * can be selected. According to the MPC5200 user's manual, the oscillator | ||
| 49 | * clock is the better choice as it has less jitter but due to a hardware | ||
| 50 | * bug, it can not be selected for the old MPC5200 Rev. A chips. | ||
| 51 | */ | ||
| 52 | |||
| 53 | static unsigned int __devinit mpc52xx_can_clock_freq(struct of_device *of, | ||
| 54 | int clock_src) | ||
| 55 | { | 55 | { |
| 56 | unsigned int pvr; | 56 | unsigned int pvr; |
| 57 | struct mpc52xx_cdm __iomem *cdm; | 57 | struct mpc52xx_cdm __iomem *cdm; |
| @@ -61,11 +61,24 @@ static unsigned int __devinit mpc52xx_can_clock_freq(struct of_device *of, | |||
| 61 | 61 | ||
| 62 | pvr = mfspr(SPRN_PVR); | 62 | pvr = mfspr(SPRN_PVR); |
| 63 | 63 | ||
| 64 | freq = mpc5xxx_get_bus_frequency(of->node); | 64 | /* |
| 65 | * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock | ||
| 66 | * (IP_CLK) can be selected as MSCAN clock source. According to | ||
| 67 | * the MPC5200 user's manual, the oscillator clock is the better | ||
| 68 | * choice as it has less jitter. For this reason, it is selected | ||
| 69 | * by default. Unfortunately, it can not be selected for the old | ||
| 70 | * MPC5200 Rev. A chips due to a hardware bug (check errata). | ||
| 71 | */ | ||
| 72 | if (clock_name && strcmp(clock_name, "ip") == 0) | ||
| 73 | *mscan_clksrc = MSCAN_CLKSRC_BUS; | ||
| 74 | else | ||
| 75 | *mscan_clksrc = MSCAN_CLKSRC_XTAL; | ||
| 76 | |||
| 77 | freq = mpc5xxx_get_bus_frequency(ofdev->node); | ||
| 65 | if (!freq) | 78 | if (!freq) |
| 66 | return 0; | 79 | return 0; |
| 67 | 80 | ||
| 68 | if (clock_src == MSCAN_CLKSRC_BUS || pvr == 0x80822011) | 81 | if (*mscan_clksrc == MSCAN_CLKSRC_BUS || pvr == 0x80822011) |
| 69 | return freq; | 82 | return freq; |
| 70 | 83 | ||
| 71 | /* Determine SYS_XTAL_IN frequency from the clock domain settings */ | 84 | /* Determine SYS_XTAL_IN frequency from the clock domain settings */ |
| @@ -75,7 +88,6 @@ static unsigned int __devinit mpc52xx_can_clock_freq(struct of_device *of, | |||
| 75 | return 0; | 88 | return 0; |
| 76 | } | 89 | } |
| 77 | cdm = of_iomap(np_cdm, 0); | 90 | cdm = of_iomap(np_cdm, 0); |
| 78 | of_node_put(np_cdm); | ||
| 79 | 91 | ||
| 80 | if (in_8(&cdm->ipb_clk_sel) & 0x1) | 92 | if (in_8(&cdm->ipb_clk_sel) & 0x1) |
| 81 | freq *= 2; | 93 | freq *= 2; |
| @@ -84,26 +96,174 @@ static unsigned int __devinit mpc52xx_can_clock_freq(struct of_device *of, | |||
| 84 | freq *= (val & (1 << 5)) ? 8 : 4; | 96 | freq *= (val & (1 << 5)) ? 8 : 4; |
| 85 | freq /= (val & (1 << 6)) ? 12 : 16; | 97 | freq /= (val & (1 << 6)) ? 12 : 16; |
| 86 | 98 | ||
| 99 | of_node_put(np_cdm); | ||
| 87 | iounmap(cdm); | 100 | iounmap(cdm); |
| 88 | 101 | ||
| 89 | return freq; | 102 | return freq; |
| 90 | } | 103 | } |
| 104 | #else /* !CONFIG_PPC_MPC5200 */ | ||
| 105 | static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, | ||
| 106 | const char *clock_name, | ||
| 107 | int *mscan_clksrc) | ||
| 108 | { | ||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | #endif /* CONFIG_PPC_MPC5200 */ | ||
| 112 | |||
| 113 | #ifdef CONFIG_PPC_MPC512x | ||
| 114 | struct mpc512x_clockctl { | ||
| 115 | u32 spmr; /* System PLL Mode Reg */ | ||
| 116 | u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */ | ||
| 117 | u32 scfr1; /* System Clk Freq Reg 1 */ | ||
| 118 | u32 scfr2; /* System Clk Freq Reg 2 */ | ||
| 119 | u32 reserved; | ||
| 120 | u32 bcr; /* Bread Crumb Reg */ | ||
| 121 | u32 pccr[12]; /* PSC Clk Ctrl Reg 0-11 */ | ||
| 122 | u32 spccr; /* SPDIF Clk Ctrl Reg */ | ||
| 123 | u32 cccr; /* CFM Clk Ctrl Reg */ | ||
| 124 | u32 dccr; /* DIU Clk Cnfg Reg */ | ||
| 125 | u32 mccr[4]; /* MSCAN Clk Ctrl Reg 1-3 */ | ||
| 126 | }; | ||
| 127 | |||
| 128 | static struct of_device_id __devinitdata mpc512x_clock_ids[] = { | ||
| 129 | { .compatible = "fsl,mpc5121-clock", }, | ||
| 130 | {} | ||
| 131 | }; | ||
| 132 | |||
| 133 | static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, | ||
| 134 | const char *clock_name, | ||
| 135 | int *mscan_clksrc) | ||
| 136 | { | ||
| 137 | struct mpc512x_clockctl __iomem *clockctl; | ||
| 138 | struct device_node *np_clock; | ||
| 139 | struct clk *sys_clk, *ref_clk; | ||
| 140 | int plen, clockidx, clocksrc = -1; | ||
| 141 | u32 sys_freq, val, clockdiv = 1, freq = 0; | ||
| 142 | const u32 *pval; | ||
| 143 | |||
| 144 | np_clock = of_find_matching_node(NULL, mpc512x_clock_ids); | ||
| 145 | if (!np_clock) { | ||
| 146 | dev_err(&ofdev->dev, "couldn't find clock node\n"); | ||
| 147 | return -ENODEV; | ||
| 148 | } | ||
| 149 | clockctl = of_iomap(np_clock, 0); | ||
| 150 | if (!clockctl) { | ||
| 151 | dev_err(&ofdev->dev, "couldn't map clock registers\n"); | ||
| 152 | return 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | /* Determine the MSCAN device index from the physical address */ | ||
| 156 | pval = of_get_property(ofdev->node, "reg", &plen); | ||
| 157 | BUG_ON(!pval || plen < sizeof(*pval)); | ||
| 158 | clockidx = (*pval & 0x80) ? 1 : 0; | ||
| 159 | if (*pval & 0x2000) | ||
| 160 | clockidx += 2; | ||
| 161 | |||
| 162 | /* | ||
| 163 | * Clock source and divider selection: 3 different clock sources | ||
| 164 | * can be selected: "ip", "ref" or "sys". For the latter two, a | ||
| 165 | * clock divider can be defined as well. If the clock source is | ||
| 166 | * not specified by the device tree, we first try to find an | ||
| 167 | * optimal CAN source clock based on the system clock. If that | ||
| 168 | * is not posslible, the reference clock will be used. | ||
| 169 | */ | ||
| 170 | if (clock_name && !strcmp(clock_name, "ip")) { | ||
| 171 | *mscan_clksrc = MSCAN_CLKSRC_IPS; | ||
| 172 | freq = mpc5xxx_get_bus_frequency(ofdev->node); | ||
| 173 | } else { | ||
| 174 | *mscan_clksrc = MSCAN_CLKSRC_BUS; | ||
| 175 | |||
| 176 | pval = of_get_property(ofdev->node, | ||
| 177 | "fsl,mscan-clock-divider", &plen); | ||
| 178 | if (pval && plen == sizeof(*pval)) | ||
| 179 | clockdiv = *pval; | ||
| 180 | if (!clockdiv) | ||
| 181 | clockdiv = 1; | ||
| 182 | |||
| 183 | if (!clock_name || !strcmp(clock_name, "sys")) { | ||
| 184 | sys_clk = clk_get(&ofdev->dev, "sys_clk"); | ||
| 185 | if (!sys_clk) { | ||
| 186 | dev_err(&ofdev->dev, "couldn't get sys_clk\n"); | ||
| 187 | goto exit_unmap; | ||
| 188 | } | ||
| 189 | /* Get and round up/down sys clock rate */ | ||
| 190 | sys_freq = 1000000 * | ||
| 191 | ((clk_get_rate(sys_clk) + 499999) / 1000000); | ||
| 192 | |||
| 193 | if (!clock_name) { | ||
| 194 | /* A multiple of 16 MHz would be optimal */ | ||
| 195 | if ((sys_freq % 16000000) == 0) { | ||
| 196 | clocksrc = 0; | ||
| 197 | clockdiv = sys_freq / 16000000; | ||
| 198 | freq = sys_freq / clockdiv; | ||
| 199 | } | ||
| 200 | } else { | ||
| 201 | clocksrc = 0; | ||
| 202 | freq = sys_freq / clockdiv; | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | if (clocksrc < 0) { | ||
| 207 | ref_clk = clk_get(&ofdev->dev, "ref_clk"); | ||
| 208 | if (!ref_clk) { | ||
| 209 | dev_err(&ofdev->dev, "couldn't get ref_clk\n"); | ||
| 210 | goto exit_unmap; | ||
| 211 | } | ||
| 212 | clocksrc = 1; | ||
| 213 | freq = clk_get_rate(ref_clk) / clockdiv; | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | /* Disable clock */ | ||
| 218 | out_be32(&clockctl->mccr[clockidx], 0x0); | ||
| 219 | if (clocksrc >= 0) { | ||
| 220 | /* Set source and divider */ | ||
| 221 | val = (clocksrc << 14) | ((clockdiv - 1) << 17); | ||
| 222 | out_be32(&clockctl->mccr[clockidx], val); | ||
| 223 | /* Enable clock */ | ||
| 224 | out_be32(&clockctl->mccr[clockidx], val | 0x10000); | ||
| 225 | } | ||
| 226 | |||
| 227 | /* Enable MSCAN clock domain */ | ||
| 228 | val = in_be32(&clockctl->sccr[1]); | ||
| 229 | if (!(val & (1 << 25))) | ||
| 230 | out_be32(&clockctl->sccr[1], val | (1 << 25)); | ||
| 231 | |||
| 232 | dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n", | ||
| 233 | *mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" : | ||
| 234 | clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv); | ||
| 235 | |||
| 236 | exit_unmap: | ||
| 237 | of_node_put(np_clock); | ||
| 238 | iounmap(clockctl); | ||
| 239 | |||
| 240 | return freq; | ||
| 241 | } | ||
| 242 | #else /* !CONFIG_PPC_MPC512x */ | ||
| 243 | static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, | ||
| 244 | const char *clock_name, | ||
| 245 | int *mscan_clksrc) | ||
| 246 | { | ||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | #endif /* CONFIG_PPC_MPC512x */ | ||
| 91 | 250 | ||
| 92 | static int __devinit mpc5xxx_can_probe(struct of_device *ofdev, | 251 | static int __devinit mpc5xxx_can_probe(struct of_device *ofdev, |
| 93 | const struct of_device_id *id) | 252 | const struct of_device_id *id) |
| 94 | { | 253 | { |
| 254 | struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data; | ||
| 95 | struct device_node *np = ofdev->node; | 255 | struct device_node *np = ofdev->node; |
| 96 | struct net_device *dev; | 256 | struct net_device *dev; |
| 97 | struct mscan_priv *priv; | 257 | struct mscan_priv *priv; |
| 98 | void __iomem *base; | 258 | void __iomem *base; |
| 99 | const char *clk_src; | 259 | const char *clock_name = NULL; |
| 100 | int err, irq, clock_src; | 260 | int irq, mscan_clksrc = 0; |
| 261 | int err = -ENOMEM; | ||
| 101 | 262 | ||
| 102 | base = of_iomap(ofdev->node, 0); | 263 | base = of_iomap(np, 0); |
| 103 | if (!base) { | 264 | if (!base) { |
| 104 | dev_err(&ofdev->dev, "couldn't ioremap\n"); | 265 | dev_err(&ofdev->dev, "couldn't ioremap\n"); |
| 105 | err = -ENOMEM; | 266 | return err; |
| 106 | goto exit_release_mem; | ||
| 107 | } | 267 | } |
| 108 | 268 | ||
| 109 | irq = irq_of_parse_and_map(np, 0); | 269 | irq = irq_of_parse_and_map(np, 0); |
| @@ -114,37 +274,27 @@ static int __devinit mpc5xxx_can_probe(struct of_device *ofdev, | |||
| 114 | } | 274 | } |
| 115 | 275 | ||
| 116 | dev = alloc_mscandev(); | 276 | dev = alloc_mscandev(); |
| 117 | if (!dev) { | 277 | if (!dev) |
| 118 | err = -ENOMEM; | ||
| 119 | goto exit_dispose_irq; | 278 | goto exit_dispose_irq; |
| 120 | } | ||
| 121 | 279 | ||
| 122 | priv = netdev_priv(dev); | 280 | priv = netdev_priv(dev); |
| 123 | priv->reg_base = base; | 281 | priv->reg_base = base; |
| 124 | dev->irq = irq; | 282 | dev->irq = irq; |
| 125 | 283 | ||
| 126 | /* | 284 | clock_name = of_get_property(np, "fsl,mscan-clock-source", NULL); |
| 127 | * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock | 285 | |
| 128 | * (IP_CLK) can be selected as MSCAN clock source. According to | 286 | BUG_ON(!data); |
| 129 | * the MPC5200 user's manual, the oscillator clock is the better | 287 | priv->type = data->type; |
| 130 | * choice as it has less jitter. For this reason, it is selected | 288 | priv->can.clock.freq = data->get_clock(ofdev, clock_name, |
| 131 | * by default. | 289 | &mscan_clksrc); |
| 132 | */ | ||
| 133 | clk_src = of_get_property(np, "fsl,mscan-clock-source", NULL); | ||
| 134 | if (clk_src && strcmp(clk_src, "ip") == 0) | ||
| 135 | clock_src = MSCAN_CLKSRC_BUS; | ||
| 136 | else | ||
| 137 | clock_src = MSCAN_CLKSRC_XTAL; | ||
| 138 | priv->can.clock.freq = mpc52xx_can_clock_freq(ofdev, clock_src); | ||
| 139 | if (!priv->can.clock.freq) { | 290 | if (!priv->can.clock.freq) { |
| 140 | dev_err(&ofdev->dev, "couldn't get MSCAN clock frequency\n"); | 291 | dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n"); |
| 141 | err = -ENODEV; | ||
| 142 | goto exit_free_mscan; | 292 | goto exit_free_mscan; |
| 143 | } | 293 | } |
| 144 | 294 | ||
| 145 | SET_NETDEV_DEV(dev, &ofdev->dev); | 295 | SET_NETDEV_DEV(dev, &ofdev->dev); |
| 146 | 296 | ||
| 147 | err = register_mscandev(dev, clock_src); | 297 | err = register_mscandev(dev, mscan_clksrc); |
| 148 | if (err) { | 298 | if (err) { |
| 149 | dev_err(&ofdev->dev, "registering %s failed (err=%d)\n", | 299 | dev_err(&ofdev->dev, "registering %s failed (err=%d)\n", |
| 150 | DRV_NAME, err); | 300 | DRV_NAME, err); |
| @@ -164,7 +314,7 @@ exit_dispose_irq: | |||
| 164 | irq_dispose_mapping(irq); | 314 | irq_dispose_mapping(irq); |
| 165 | exit_unmap_mem: | 315 | exit_unmap_mem: |
| 166 | iounmap(base); | 316 | iounmap(base); |
| 167 | exit_release_mem: | 317 | |
| 168 | return err; | 318 | return err; |
| 169 | } | 319 | } |
| 170 | 320 | ||
| @@ -225,8 +375,20 @@ static int mpc5xxx_can_resume(struct of_device *ofdev) | |||
| 225 | } | 375 | } |
| 226 | #endif | 376 | #endif |
| 227 | 377 | ||
| 378 | static struct mpc5xxx_can_data __devinitdata mpc5200_can_data = { | ||
| 379 | .type = MSCAN_TYPE_MPC5200, | ||
| 380 | .get_clock = mpc52xx_can_get_clock, | ||
| 381 | }; | ||
| 382 | |||
| 383 | static struct mpc5xxx_can_data __devinitdata mpc5121_can_data = { | ||
| 384 | .type = MSCAN_TYPE_MPC5121, | ||
| 385 | .get_clock = mpc512x_can_get_clock, | ||
| 386 | }; | ||
| 387 | |||
| 228 | static struct of_device_id __devinitdata mpc5xxx_can_table[] = { | 388 | static struct of_device_id __devinitdata mpc5xxx_can_table[] = { |
| 229 | {.compatible = "fsl,mpc5200-mscan"}, | 389 | { .compatible = "fsl,mpc5200-mscan", .data = &mpc5200_can_data, }, |
| 390 | /* Note that only MPC5121 Rev. 2 (and later) is supported */ | ||
| 391 | { .compatible = "fsl,mpc5121-mscan", .data = &mpc5121_can_data, }, | ||
| 230 | {}, | 392 | {}, |
| 231 | }; | 393 | }; |
| 232 | 394 | ||
| @@ -255,5 +417,5 @@ static void __exit mpc5xxx_can_exit(void) | |||
| 255 | module_exit(mpc5xxx_can_exit); | 417 | module_exit(mpc5xxx_can_exit); |
| 256 | 418 | ||
| 257 | MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>"); | 419 | MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>"); |
| 258 | MODULE_DESCRIPTION("Freescale MPC5200 CAN driver"); | 420 | MODULE_DESCRIPTION("Freescale MPC5xxx CAN driver"); |
| 259 | MODULE_LICENSE("GPL v2"); | 421 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 0dcbe8cfab64..500d18918bd5 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c | |||
| @@ -152,6 +152,12 @@ static int mscan_start(struct net_device *dev) | |||
| 152 | priv->shadow_canrier = 0; | 152 | priv->shadow_canrier = 0; |
| 153 | priv->flags = 0; | 153 | priv->flags = 0; |
| 154 | 154 | ||
| 155 | if (priv->type == MSCAN_TYPE_MPC5121) { | ||
| 156 | /* Clear pending bus-off condition */ | ||
| 157 | if (in_8(®s->canmisc) & MSCAN_BOHOLD) | ||
| 158 | out_8(®s->canmisc, MSCAN_BOHOLD); | ||
| 159 | } | ||
| 160 | |||
| 155 | err = mscan_set_mode(dev, MSCAN_NORMAL_MODE); | 161 | err = mscan_set_mode(dev, MSCAN_NORMAL_MODE); |
| 156 | if (err) | 162 | if (err) |
| 157 | return err; | 163 | return err; |
| @@ -163,8 +169,29 @@ static int mscan_start(struct net_device *dev) | |||
| 163 | out_8(®s->cantier, 0); | 169 | out_8(®s->cantier, 0); |
| 164 | 170 | ||
| 165 | /* Enable receive interrupts. */ | 171 | /* Enable receive interrupts. */ |
| 166 | out_8(®s->canrier, MSCAN_OVRIE | MSCAN_RXFIE | MSCAN_CSCIE | | 172 | out_8(®s->canrier, MSCAN_RX_INTS_ENABLE); |
| 167 | MSCAN_RSTATE1 | MSCAN_RSTATE0 | MSCAN_TSTATE1 | MSCAN_TSTATE0); | 173 | |
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | static int mscan_restart(struct net_device *dev) | ||
| 178 | { | ||
| 179 | struct mscan_priv *priv = netdev_priv(dev); | ||
| 180 | |||
| 181 | if (priv->type == MSCAN_TYPE_MPC5121) { | ||
| 182 | struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; | ||
| 183 | |||
| 184 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | ||
| 185 | WARN(!(in_8(®s->canmisc) & MSCAN_BOHOLD), | ||
| 186 | "bus-off state expected"); | ||
| 187 | out_8(®s->canmisc, MSCAN_BOHOLD); | ||
| 188 | /* Re-enable receive interrupts. */ | ||
| 189 | out_8(®s->canrier, MSCAN_RX_INTS_ENABLE); | ||
| 190 | } else { | ||
| 191 | if (priv->can.state <= CAN_STATE_BUS_OFF) | ||
| 192 | mscan_set_mode(dev, MSCAN_INIT_MODE); | ||
| 193 | return mscan_start(dev); | ||
| 194 | } | ||
| 168 | 195 | ||
| 169 | return 0; | 196 | return 0; |
| 170 | } | 197 | } |
| @@ -362,9 +389,12 @@ static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame, | |||
| 362 | * automatically. To avoid that we stop the chip doing | 389 | * automatically. To avoid that we stop the chip doing |
| 363 | * a light-weight stop (we are in irq-context). | 390 | * a light-weight stop (we are in irq-context). |
| 364 | */ | 391 | */ |
| 365 | out_8(®s->cantier, 0); | 392 | if (priv->type != MSCAN_TYPE_MPC5121) { |
| 366 | out_8(®s->canrier, 0); | 393 | out_8(®s->cantier, 0); |
| 367 | setbits8(®s->canctl0, MSCAN_SLPRQ | MSCAN_INITRQ); | 394 | out_8(®s->canrier, 0); |
| 395 | setbits8(®s->canctl0, | ||
| 396 | MSCAN_SLPRQ | MSCAN_INITRQ); | ||
| 397 | } | ||
| 368 | can_bus_off(dev); | 398 | can_bus_off(dev); |
| 369 | break; | 399 | break; |
| 370 | default: | 400 | default: |
| @@ -494,9 +524,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode) | |||
| 494 | 524 | ||
| 495 | switch (mode) { | 525 | switch (mode) { |
| 496 | case CAN_MODE_START: | 526 | case CAN_MODE_START: |
| 497 | if (priv->can.state <= CAN_STATE_BUS_OFF) | 527 | ret = mscan_restart(dev); |
| 498 | mscan_set_mode(dev, MSCAN_INIT_MODE); | ||
| 499 | ret = mscan_start(dev); | ||
| 500 | if (ret) | 528 | if (ret) |
| 501 | break; | 529 | break; |
| 502 | if (netif_queue_stopped(dev)) | 530 | if (netif_queue_stopped(dev)) |
| @@ -595,18 +623,21 @@ static const struct net_device_ops mscan_netdev_ops = { | |||
| 595 | .ndo_start_xmit = mscan_start_xmit, | 623 | .ndo_start_xmit = mscan_start_xmit, |
| 596 | }; | 624 | }; |
| 597 | 625 | ||
| 598 | int register_mscandev(struct net_device *dev, int clock_src) | 626 | int register_mscandev(struct net_device *dev, int mscan_clksrc) |
| 599 | { | 627 | { |
| 600 | struct mscan_priv *priv = netdev_priv(dev); | 628 | struct mscan_priv *priv = netdev_priv(dev); |
| 601 | struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; | 629 | struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; |
| 602 | u8 ctl1; | 630 | u8 ctl1; |
| 603 | 631 | ||
| 604 | ctl1 = in_8(®s->canctl1); | 632 | ctl1 = in_8(®s->canctl1); |
| 605 | if (clock_src) | 633 | if (mscan_clksrc) |
| 606 | ctl1 |= MSCAN_CLKSRC; | 634 | ctl1 |= MSCAN_CLKSRC; |
| 607 | else | 635 | else |
| 608 | ctl1 &= ~MSCAN_CLKSRC; | 636 | ctl1 &= ~MSCAN_CLKSRC; |
| 609 | 637 | ||
| 638 | if (priv->type == MSCAN_TYPE_MPC5121) | ||
| 639 | ctl1 |= MSCAN_BORM; /* bus-off recovery upon request */ | ||
| 640 | |||
| 610 | ctl1 |= MSCAN_CANE; | 641 | ctl1 |= MSCAN_CANE; |
| 611 | out_8(®s->canctl1, ctl1); | 642 | out_8(®s->canctl1, ctl1); |
| 612 | udelay(100); | 643 | udelay(100); |
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h index 00fc4aaf1ed8..4ff966473bc9 100644 --- a/drivers/net/can/mscan/mscan.h +++ b/drivers/net/can/mscan/mscan.h | |||
| @@ -38,18 +38,20 @@ | |||
| 38 | #define MSCAN_CLKSRC 0x40 | 38 | #define MSCAN_CLKSRC 0x40 |
| 39 | #define MSCAN_LOOPB 0x20 | 39 | #define MSCAN_LOOPB 0x20 |
| 40 | #define MSCAN_LISTEN 0x10 | 40 | #define MSCAN_LISTEN 0x10 |
| 41 | #define MSCAN_BORM 0x08 | ||
| 41 | #define MSCAN_WUPM 0x04 | 42 | #define MSCAN_WUPM 0x04 |
| 42 | #define MSCAN_SLPAK 0x02 | 43 | #define MSCAN_SLPAK 0x02 |
| 43 | #define MSCAN_INITAK 0x01 | 44 | #define MSCAN_INITAK 0x01 |
| 44 | 45 | ||
| 45 | /* Use the MPC5200 MSCAN variant? */ | 46 | /* Use the MPC5XXX MSCAN variant? */ |
| 46 | #ifdef CONFIG_PPC | 47 | #ifdef CONFIG_PPC |
| 47 | #define MSCAN_FOR_MPC5200 | 48 | #define MSCAN_FOR_MPC5XXX |
| 48 | #endif | 49 | #endif |
| 49 | 50 | ||
| 50 | #ifdef MSCAN_FOR_MPC5200 | 51 | #ifdef MSCAN_FOR_MPC5XXX |
| 51 | #define MSCAN_CLKSRC_BUS 0 | 52 | #define MSCAN_CLKSRC_BUS 0 |
| 52 | #define MSCAN_CLKSRC_XTAL MSCAN_CLKSRC | 53 | #define MSCAN_CLKSRC_XTAL MSCAN_CLKSRC |
| 54 | #define MSCAN_CLKSRC_IPS MSCAN_CLKSRC | ||
| 53 | #else | 55 | #else |
| 54 | #define MSCAN_CLKSRC_BUS MSCAN_CLKSRC | 56 | #define MSCAN_CLKSRC_BUS MSCAN_CLKSRC |
| 55 | #define MSCAN_CLKSRC_XTAL 0 | 57 | #define MSCAN_CLKSRC_XTAL 0 |
| @@ -136,7 +138,7 @@ | |||
| 136 | #define MSCAN_EFF_RTR_SHIFT 0 | 138 | #define MSCAN_EFF_RTR_SHIFT 0 |
| 137 | #define MSCAN_EFF_FLAGS 0x18 /* IDE + SRR */ | 139 | #define MSCAN_EFF_FLAGS 0x18 /* IDE + SRR */ |
| 138 | 140 | ||
| 139 | #ifdef MSCAN_FOR_MPC5200 | 141 | #ifdef MSCAN_FOR_MPC5XXX |
| 140 | #define _MSCAN_RESERVED_(n, num) u8 _res##n[num] | 142 | #define _MSCAN_RESERVED_(n, num) u8 _res##n[num] |
| 141 | #define _MSCAN_RESERVED_DSR_SIZE 2 | 143 | #define _MSCAN_RESERVED_DSR_SIZE 2 |
| 142 | #else | 144 | #else |
| @@ -165,67 +167,66 @@ struct mscan_regs { | |||
| 165 | u8 cantbsel; /* + 0x14 0x0a */ | 167 | u8 cantbsel; /* + 0x14 0x0a */ |
| 166 | u8 canidac; /* + 0x15 0x0b */ | 168 | u8 canidac; /* + 0x15 0x0b */ |
| 167 | u8 reserved; /* + 0x16 0x0c */ | 169 | u8 reserved; /* + 0x16 0x0c */ |
| 168 | _MSCAN_RESERVED_(6, 5); /* + 0x17 */ | 170 | _MSCAN_RESERVED_(6, 2); /* + 0x17 */ |
| 169 | #ifndef MSCAN_FOR_MPC5200 | 171 | u8 canmisc; /* + 0x19 0x0d */ |
| 170 | u8 canmisc; /* 0x0d */ | 172 | _MSCAN_RESERVED_(7, 2); /* + 0x1a */ |
| 171 | #endif | ||
| 172 | u8 canrxerr; /* + 0x1c 0x0e */ | 173 | u8 canrxerr; /* + 0x1c 0x0e */ |
| 173 | u8 cantxerr; /* + 0x1d 0x0f */ | 174 | u8 cantxerr; /* + 0x1d 0x0f */ |
| 174 | _MSCAN_RESERVED_(7, 2); /* + 0x1e */ | 175 | _MSCAN_RESERVED_(8, 2); /* + 0x1e */ |
| 175 | u16 canidar1_0; /* + 0x20 0x10 */ | 176 | u16 canidar1_0; /* + 0x20 0x10 */ |
| 176 | _MSCAN_RESERVED_(8, 2); /* + 0x22 */ | 177 | _MSCAN_RESERVED_(9, 2); /* + 0x22 */ |
| 177 | u16 canidar3_2; /* + 0x24 0x12 */ | 178 | u16 canidar3_2; /* + 0x24 0x12 */ |
| 178 | _MSCAN_RESERVED_(9, 2); /* + 0x26 */ | 179 | _MSCAN_RESERVED_(10, 2); /* + 0x26 */ |
| 179 | u16 canidmr1_0; /* + 0x28 0x14 */ | 180 | u16 canidmr1_0; /* + 0x28 0x14 */ |
| 180 | _MSCAN_RESERVED_(10, 2); /* + 0x2a */ | 181 | _MSCAN_RESERVED_(11, 2); /* + 0x2a */ |
| 181 | u16 canidmr3_2; /* + 0x2c 0x16 */ | 182 | u16 canidmr3_2; /* + 0x2c 0x16 */ |
| 182 | _MSCAN_RESERVED_(11, 2); /* + 0x2e */ | 183 | _MSCAN_RESERVED_(12, 2); /* + 0x2e */ |
| 183 | u16 canidar5_4; /* + 0x30 0x18 */ | 184 | u16 canidar5_4; /* + 0x30 0x18 */ |
| 184 | _MSCAN_RESERVED_(12, 2); /* + 0x32 */ | 185 | _MSCAN_RESERVED_(13, 2); /* + 0x32 */ |
| 185 | u16 canidar7_6; /* + 0x34 0x1a */ | 186 | u16 canidar7_6; /* + 0x34 0x1a */ |
| 186 | _MSCAN_RESERVED_(13, 2); /* + 0x36 */ | 187 | _MSCAN_RESERVED_(14, 2); /* + 0x36 */ |
| 187 | u16 canidmr5_4; /* + 0x38 0x1c */ | 188 | u16 canidmr5_4; /* + 0x38 0x1c */ |
| 188 | _MSCAN_RESERVED_(14, 2); /* + 0x3a */ | 189 | _MSCAN_RESERVED_(15, 2); /* + 0x3a */ |
| 189 | u16 canidmr7_6; /* + 0x3c 0x1e */ | 190 | u16 canidmr7_6; /* + 0x3c 0x1e */ |
| 190 | _MSCAN_RESERVED_(15, 2); /* + 0x3e */ | 191 | _MSCAN_RESERVED_(16, 2); /* + 0x3e */ |
| 191 | struct { | 192 | struct { |
| 192 | u16 idr1_0; /* + 0x40 0x20 */ | 193 | u16 idr1_0; /* + 0x40 0x20 */ |
| 193 | _MSCAN_RESERVED_(16, 2); /* + 0x42 */ | 194 | _MSCAN_RESERVED_(17, 2); /* + 0x42 */ |
| 194 | u16 idr3_2; /* + 0x44 0x22 */ | 195 | u16 idr3_2; /* + 0x44 0x22 */ |
| 195 | _MSCAN_RESERVED_(17, 2); /* + 0x46 */ | 196 | _MSCAN_RESERVED_(18, 2); /* + 0x46 */ |
| 196 | u16 dsr1_0; /* + 0x48 0x24 */ | 197 | u16 dsr1_0; /* + 0x48 0x24 */ |
| 197 | _MSCAN_RESERVED_(18, 2); /* + 0x4a */ | 198 | _MSCAN_RESERVED_(19, 2); /* + 0x4a */ |
| 198 | u16 dsr3_2; /* + 0x4c 0x26 */ | 199 | u16 dsr3_2; /* + 0x4c 0x26 */ |
| 199 | _MSCAN_RESERVED_(19, 2); /* + 0x4e */ | 200 | _MSCAN_RESERVED_(20, 2); /* + 0x4e */ |
| 200 | u16 dsr5_4; /* + 0x50 0x28 */ | 201 | u16 dsr5_4; /* + 0x50 0x28 */ |
| 201 | _MSCAN_RESERVED_(20, 2); /* + 0x52 */ | 202 | _MSCAN_RESERVED_(21, 2); /* + 0x52 */ |
| 202 | u16 dsr7_6; /* + 0x54 0x2a */ | 203 | u16 dsr7_6; /* + 0x54 0x2a */ |
| 203 | _MSCAN_RESERVED_(21, 2); /* + 0x56 */ | 204 | _MSCAN_RESERVED_(22, 2); /* + 0x56 */ |
| 204 | u8 dlr; /* + 0x58 0x2c */ | 205 | u8 dlr; /* + 0x58 0x2c */ |
| 205 | u8:8; /* + 0x59 0x2d */ | 206 | u8 reserved; /* + 0x59 0x2d */ |
| 206 | _MSCAN_RESERVED_(22, 2); /* + 0x5a */ | 207 | _MSCAN_RESERVED_(23, 2); /* + 0x5a */ |
| 207 | u16 time; /* + 0x5c 0x2e */ | 208 | u16 time; /* + 0x5c 0x2e */ |
| 208 | } rx; | 209 | } rx; |
| 209 | _MSCAN_RESERVED_(23, 2); /* + 0x5e */ | 210 | _MSCAN_RESERVED_(24, 2); /* + 0x5e */ |
| 210 | struct { | 211 | struct { |
| 211 | u16 idr1_0; /* + 0x60 0x30 */ | 212 | u16 idr1_0; /* + 0x60 0x30 */ |
| 212 | _MSCAN_RESERVED_(24, 2); /* + 0x62 */ | 213 | _MSCAN_RESERVED_(25, 2); /* + 0x62 */ |
| 213 | u16 idr3_2; /* + 0x64 0x32 */ | 214 | u16 idr3_2; /* + 0x64 0x32 */ |
| 214 | _MSCAN_RESERVED_(25, 2); /* + 0x66 */ | 215 | _MSCAN_RESERVED_(26, 2); /* + 0x66 */ |
| 215 | u16 dsr1_0; /* + 0x68 0x34 */ | 216 | u16 dsr1_0; /* + 0x68 0x34 */ |
| 216 | _MSCAN_RESERVED_(26, 2); /* + 0x6a */ | 217 | _MSCAN_RESERVED_(27, 2); /* + 0x6a */ |
| 217 | u16 dsr3_2; /* + 0x6c 0x36 */ | 218 | u16 dsr3_2; /* + 0x6c 0x36 */ |
| 218 | _MSCAN_RESERVED_(27, 2); /* + 0x6e */ | 219 | _MSCAN_RESERVED_(28, 2); /* + 0x6e */ |
| 219 | u16 dsr5_4; /* + 0x70 0x38 */ | 220 | u16 dsr5_4; /* + 0x70 0x38 */ |
| 220 | _MSCAN_RESERVED_(28, 2); /* + 0x72 */ | 221 | _MSCAN_RESERVED_(29, 2); /* + 0x72 */ |
| 221 | u16 dsr7_6; /* + 0x74 0x3a */ | 222 | u16 dsr7_6; /* + 0x74 0x3a */ |
| 222 | _MSCAN_RESERVED_(29, 2); /* + 0x76 */ | 223 | _MSCAN_RESERVED_(30, 2); /* + 0x76 */ |
| 223 | u8 dlr; /* + 0x78 0x3c */ | 224 | u8 dlr; /* + 0x78 0x3c */ |
| 224 | u8 tbpr; /* + 0x79 0x3d */ | 225 | u8 tbpr; /* + 0x79 0x3d */ |
| 225 | _MSCAN_RESERVED_(30, 2); /* + 0x7a */ | 226 | _MSCAN_RESERVED_(31, 2); /* + 0x7a */ |
| 226 | u16 time; /* + 0x7c 0x3e */ | 227 | u16 time; /* + 0x7c 0x3e */ |
| 227 | } tx; | 228 | } tx; |
| 228 | _MSCAN_RESERVED_(31, 2); /* + 0x7e */ | 229 | _MSCAN_RESERVED_(32, 2); /* + 0x7e */ |
| 229 | } __attribute__ ((packed)); | 230 | } __attribute__ ((packed)); |
| 230 | 231 | ||
| 231 | #undef _MSCAN_RESERVED_ | 232 | #undef _MSCAN_RESERVED_ |
| @@ -237,6 +238,15 @@ struct mscan_regs { | |||
| 237 | #define MSCAN_POWEROFF_MODE (MSCAN_CSWAI | MSCAN_SLPRQ) | 238 | #define MSCAN_POWEROFF_MODE (MSCAN_CSWAI | MSCAN_SLPRQ) |
| 238 | #define MSCAN_SET_MODE_RETRIES 255 | 239 | #define MSCAN_SET_MODE_RETRIES 255 |
| 239 | #define MSCAN_ECHO_SKB_MAX 3 | 240 | #define MSCAN_ECHO_SKB_MAX 3 |
| 241 | #define MSCAN_RX_INTS_ENABLE (MSCAN_OVRIE | MSCAN_RXFIE | MSCAN_CSCIE | \ | ||
| 242 | MSCAN_RSTATE1 | MSCAN_RSTATE0 | \ | ||
| 243 | MSCAN_TSTATE1 | MSCAN_TSTATE0) | ||
| 244 | |||
| 245 | /* MSCAN type variants */ | ||
| 246 | enum { | ||
| 247 | MSCAN_TYPE_MPC5200, | ||
| 248 | MSCAN_TYPE_MPC5121 | ||
| 249 | }; | ||
| 240 | 250 | ||
| 241 | #define BTR0_BRP_MASK 0x3f | 251 | #define BTR0_BRP_MASK 0x3f |
| 242 | #define BTR0_SJW_SHIFT 6 | 252 | #define BTR0_SJW_SHIFT 6 |
| @@ -270,6 +280,7 @@ struct tx_queue_entry { | |||
| 270 | 280 | ||
| 271 | struct mscan_priv { | 281 | struct mscan_priv { |
| 272 | struct can_priv can; /* must be the first member */ | 282 | struct can_priv can; /* must be the first member */ |
| 283 | unsigned int type; /* MSCAN type variants */ | ||
| 273 | long open_time; | 284 | long open_time; |
| 274 | unsigned long flags; | 285 | unsigned long flags; |
| 275 | void __iomem *reg_base; /* ioremap'ed address to registers */ | 286 | void __iomem *reg_base; /* ioremap'ed address to registers */ |
| @@ -285,12 +296,7 @@ struct mscan_priv { | |||
| 285 | }; | 296 | }; |
| 286 | 297 | ||
| 287 | extern struct net_device *alloc_mscandev(void); | 298 | extern struct net_device *alloc_mscandev(void); |
| 288 | /* | 299 | extern int register_mscandev(struct net_device *dev, int mscan_clksrc); |
| 289 | * clock_src: | ||
| 290 | * 1 = The MSCAN clock source is the onchip Bus Clock. | ||
| 291 | * 0 = The MSCAN clock source is the chip Oscillator Clock. | ||
| 292 | */ | ||
| 293 | extern int register_mscandev(struct net_device *dev, int clock_src); | ||
| 294 | extern void unregister_mscandev(struct net_device *dev); | 300 | extern void unregister_mscandev(struct net_device *dev); |
| 295 | 301 | ||
| 296 | #endif /* __MSCAN_H__ */ | 302 | #endif /* __MSCAN_H__ */ |
