2 * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
3 * Copyright (C) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the version 2 of the GNU General Public License
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/interrupt.h>
22 #include <linux/netdevice.h>
23 #include <linux/delay.h>
24 #include <linux/pci.h>
25 #include <linux/can.h>
26 #include <linux/can/dev.h>
27 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
35 #define DRV_NAME "ixxat_pci"
37 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
38 MODULE_DESCRIPTION("Socket-CAN driver for IXXAT PC-I 04/PCI PCI cards");
39 MODULE_SUPPORTED_DEVICE("IXXAT PC-I 04/PCI card");
40 MODULE_LICENSE("GPL v2");
42 /* Maximum number of interfaces supported on one card. Currently
43 * we only support a maximum of two interfaces, which is the maximum
44 * of what Ixxat sells anyway.
46 #define IXXAT_PCI_MAX_CAN 2
49 struct pci_dev *pci_dev;
50 struct net_device *dev[IXXAT_PCI_MAX_CAN];
52 void __iomem *base_addr;
55 #define IXXAT_PCI_CAN_CLOCK (16000000 / 2)
57 #define IXXAT_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX0_INVERT | \
59 #define IXXAT_PCI_CDR 0
61 #define CHANNEL_RESET_OFFSET 0x110
62 #define CHANNEL_OFFSET 0x200
64 #define INTCSR_OFFSET 0x4c /* Offset in PLX9050 conf registers */
65 #define INTCSR_LINTI1 (1 << 0)
66 #define INTCSR_LINTI2 (1 << 3)
67 #define INTCSR_PCI (1 << 6)
69 /* PCI vender, device and sub-device ID */
70 #define IXXAT_PCI_VENDOR_ID 0x10b5
71 #define IXXAT_PCI_DEVICE_ID 0x9050
72 #define IXXAT_PCI_SUB_SYS_ID 0x2540
74 #define IXXAT_PCI_BASE_SIZE 0x400
76 static struct pci_device_id ixxat_pci_tbl[] = {
77 {IXXAT_PCI_VENDOR_ID, IXXAT_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
81 MODULE_DEVICE_TABLE(pci, ixxat_pci_tbl);
83 static u8 ixxat_pci_read_reg(struct net_device *ndev, int port)
86 val = readb((void __iomem *)(ndev->base_addr + port));
90 static void ixxat_pci_write_reg(struct net_device *ndev, int port, u8 val)
92 writeb(val, (void __iomem *)(ndev->base_addr + port));
95 static void ixxat_pci_del_chan(struct pci_dev *pdev, struct net_device *ndev)
97 dev_info(&pdev->dev, "Removing device %s\n", ndev->name);
99 unregister_sja1000dev(ndev);
101 free_sja1000dev(ndev);
104 static struct net_device *ixxat_pci_add_chan(struct pci_dev *pdev,
105 void __iomem *base_addr)
107 struct net_device *ndev;
108 struct sja1000_priv *priv;
111 ndev = alloc_sja1000dev(0);
113 return ERR_PTR(-ENOMEM);
115 priv = netdev_priv(ndev);
117 ndev->base_addr = (unsigned long)base_addr;
119 priv->read_reg = ixxat_pci_read_reg;
120 priv->write_reg = ixxat_pci_write_reg;
122 priv->can.bittiming.clock = IXXAT_PCI_CAN_CLOCK;
124 priv->ocr = IXXAT_PCI_OCR;
125 priv->cdr = IXXAT_PCI_CDR;
127 /* Set and enable PCI interrupts */
128 ndev->irq = pdev->irq;
130 dev_dbg(&pdev->dev, "base_addr=%#lx irq=%d\n",
131 ndev->base_addr, ndev->irq);
133 SET_NETDEV_DEV(ndev, &pdev->dev);
135 err = register_sja1000dev(ndev);
137 dev_err(&pdev->dev, "Failed to register (err=%d)\n", err);
144 free_sja1000dev(ndev);
148 static int __devinit ixxat_pci_init_one(struct pci_dev *pdev,
149 const struct pci_device_id *ent)
151 struct ixxat_pci *board;
152 int err, intcsr = INTCSR_LINTI1 | INTCSR_PCI;
154 void __iomem *base_addr;
156 dev_info(&pdev->dev, "Initializing device %04x:%04x\n",
157 pdev->vendor, pdev->device);
159 board = kzalloc(sizeof(*board), GFP_KERNEL);
163 err = pci_enable_device(pdev);
167 err = pci_request_regions(pdev, DRV_NAME);
171 err = pci_read_config_word(pdev, 0x2e, &sub_sys_id);
173 goto failure_release_pci;
175 if (sub_sys_id != IXXAT_PCI_SUB_SYS_ID)
178 /* Enable memory and I/O space */
179 err = pci_write_config_word(pdev, 0x04, 0x3);
181 goto failure_release_pci;
183 board->conf_addr = pci_resource_start(pdev, 1);
185 base_addr = pci_iomap(pdev, 2, IXXAT_PCI_BASE_SIZE);
186 if (base_addr == 0) {
188 goto failure_release_pci;
191 board->base_addr = base_addr;
193 writeb(0x1, base_addr + CHANNEL_RESET_OFFSET);
194 writeb(0x1, base_addr + CHANNEL_OFFSET + CHANNEL_RESET_OFFSET);
197 board->dev[0] = ixxat_pci_add_chan(pdev, base_addr);
198 if (IS_ERR(board->dev[0]))
199 goto failure_iounmap;
201 /* Check if second channel is available */
202 if ((readb(base_addr + CHANNEL_OFFSET + REG_MOD) & 0xa1) == 0x21 &&
203 readb(base_addr + CHANNEL_OFFSET + REG_SR) == 0x0c &&
204 readb(base_addr + CHANNEL_OFFSET + REG_IR) == 0xe0) {
205 board->dev[1] = ixxat_pci_add_chan(pdev,
206 base_addr + CHANNEL_OFFSET);
207 if (IS_ERR(board->dev[1]))
208 goto failure_unreg_dev0;
210 intcsr |= INTCSR_LINTI2;
213 /* enable interrupt(s) in PLX9050 */
214 outb(intcsr, board->conf_addr + INTCSR_OFFSET);
216 pci_set_drvdata(pdev, board);
221 ixxat_pci_del_chan(pdev, board->dev[0]);
224 pci_iounmap(pdev, board->base_addr);
227 pci_release_regions(pdev);
235 static void __devexit ixxat_pci_remove_one(struct pci_dev *pdev)
237 struct ixxat_pci *board = pci_get_drvdata(pdev);
240 /* Disable interrupts in PLX9050*/
241 outb(0, board->conf_addr + INTCSR_OFFSET);
243 for (i = 0; i < IXXAT_PCI_MAX_CAN; i++) {
246 ixxat_pci_del_chan(pdev, board->dev[i]);
249 pci_iounmap(pdev, board->base_addr);
251 pci_release_regions(pdev);
252 pci_disable_device(pdev);
253 pci_set_drvdata(pdev, NULL);
258 static struct pci_driver ixxat_pci_driver = {
260 .id_table = ixxat_pci_tbl,
261 .probe = ixxat_pci_init_one,
262 .remove = __devexit_p(ixxat_pci_remove_one),
265 static int __init ixxat_pci_init(void)
267 return pci_register_driver(&ixxat_pci_driver);
270 static void __exit ixxat_pci_exit(void)
272 pci_unregister_driver(&ixxat_pci_driver);
275 module_init(ixxat_pci_init);
276 module_exit(ixxat_pci_exit);