2 * Copyright (C) 2008 David Müller, <d.mueller@elsoft.ch>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the version 2 of the GNU General Public License
6 * as published by the Free Software Foundation
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/interrupt.h>
21 #include <linux/netdevice.h>
22 #include <linux/delay.h>
23 #include <linux/platform_device.h>
24 #include <linux/can.h>
25 #include <linux/can/dev.h>
30 #define DRV_NAME "pipcan"
32 MODULE_AUTHOR("David Müller <d.mueller@elsoft.ch>");
33 MODULE_DESCRIPTION("Socket-CAN driver for MPL PIPCAN module");
34 MODULE_SUPPORTED_DEVICE("MPL PIPCAN module");
35 MODULE_LICENSE("GPL v2");
37 #define PIPCAN_CAN_CLOCK (16000000 / 2)
39 #define PIPCAN_OCR (OCR_TX1_PUSHPULL)
40 #define PIPCAN_CDR (CDR_CBP | CDR_CLK_OFF)
42 #define PIPCAN_IOSIZE (0x100)
44 #define PIPCAN_RES (0x804)
45 #define PIPCAN_RST (0x805)
47 static u8 pc_read_reg(struct net_device *dev, int reg)
49 return inb(dev->base_addr + reg);
52 static void pc_write_reg(struct net_device *dev, int reg, u8 val)
54 outb(val, dev->base_addr + reg);
57 static int __init pc_probe(struct platform_device *pdev)
59 struct net_device *dev;
60 struct sja1000_priv *priv;
65 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
66 irq = platform_get_irq(pdev, 0);
71 if (!request_region(res->start, res->end - res->start + 1, DRV_NAME))
75 dev = alloc_sja1000dev(0);
79 priv = netdev_priv(dev);
81 priv->read_reg = pc_read_reg;
82 priv->write_reg = pc_write_reg;
83 priv->can.bittiming.clock = PIPCAN_CAN_CLOCK;
84 priv->ocr = PIPCAN_OCR;
85 priv->cdr = PIPCAN_CDR;
88 dev->base_addr = res->start;
90 dev_set_drvdata(&pdev->dev, dev);
91 SET_NETDEV_DEV(dev, &pdev->dev);
94 outb(inb(PIPCAN_RST) & ~0x01, PIPCAN_RST);
96 rc = register_sja1000dev(dev);
98 dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
103 dev_info(&pdev->dev, "device registered (base_addr=%#lx, irq=%d)\n",
104 dev->base_addr, dev->irq);
108 free_sja1000dev(dev);
111 release_region(res->start, res->end - res->start + 1);
117 static int __exit pc_remove(struct platform_device *pdev)
119 struct net_device *dev = dev_get_drvdata(&pdev->dev);
120 struct resource *res;
122 dev_set_drvdata(&pdev->dev, NULL);
123 unregister_sja1000dev(dev);
124 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
126 free_sja1000dev(dev);
128 release_region(res->start, res->end - res->start + 1);
131 outb(inb(PIPCAN_RST) | 0x01, PIPCAN_RST);
136 static struct platform_driver pc_driver = {
137 .remove = __exit_p(pc_remove),
140 .owner = THIS_MODULE,
144 static struct platform_device *pc_pdev;
145 static const u16 pipcan_ioport[] = {0x1000, 0x8000, 0xE000};
147 static int __init pc_init(void)
149 struct resource r[2];
150 int rc, addr, irq, idx;
153 /* get PIPCAN resources from EPLD */
154 pc_res = inb(PIPCAN_RES);
156 idx = (pc_res & 0x0F);
157 if ((idx <= 0) || (idx > ARRAY_SIZE(pipcan_ioport))) {
158 printk(KERN_ERR DRV_NAME " invalid base address\n");
161 addr = pipcan_ioport[idx-1];
163 irq = (pc_res >> 4) & 0x0F;
164 if ((irq < 3) || (irq == 8) || (irq == 13)) {
165 printk(KERN_ERR DRV_NAME " invalid IRQ\n");
169 /* fill in resources */
170 memset(&r, 0, sizeof(r));
172 r[0].end = addr + PIPCAN_IOSIZE - 1;
173 r[0].name = DRV_NAME;
174 r[0].flags = IORESOURCE_IO;
175 r[1].start = r[1].end = irq;
176 r[1].name = DRV_NAME;
177 r[1].flags = IORESOURCE_IRQ;
179 pc_pdev = platform_device_register_simple(DRV_NAME, 0, r,
182 return PTR_ERR(pc_pdev);
184 rc = platform_driver_probe(&pc_driver, pc_probe);
186 platform_device_unregister(pc_pdev);
187 printk(KERN_ERR DRV_NAME
188 " platform_driver_probe() failed (%d)\n", rc);
194 static void __exit pc_exit(void)
196 platform_driver_unregister(&pc_driver);
197 platform_device_unregister(pc_pdev);
200 module_init(pc_init);
201 module_exit(pc_exit);