diff options
author | Sebastian Haas <haas@ems-wuensche.com> | 2009-07-21 15:38:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-07-23 21:01:02 -0400 |
commit | dd52856ba24ed2f67679c86f207e5a9bab1eb93b (patch) | |
tree | 613b683066df53b38d028a2e002e750b25d8fd19 /drivers/net/can | |
parent | 69222e2cb01ac3faaa8ca758c5ee036c191b8b9f (diff) |
can: sja1000: Add support for the new 4 channel EMS CPC-PCI cards
This patch adds support to the ems_pci driver for the new, v2,
4 channel CPC-PCI/PCIe/104P CAN cards from EMS Dr. Thomas Wuensche.
Signed-off-by: Sebastian Haas <haas@ems-wuensche.com>
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/Kconfig | 7 | ||||
-rw-r--r-- | drivers/net/can/sja1000/ems_pci.c | 152 |
2 files changed, 112 insertions, 47 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 33821a81cbf..30ae55d7167 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig | |||
@@ -61,11 +61,12 @@ config CAN_SJA1000_OF_PLATFORM | |||
61 | you may want to enable this option. | 61 | you may want to enable this option. |
62 | 62 | ||
63 | config CAN_EMS_PCI | 63 | config CAN_EMS_PCI |
64 | tristate "EMS CPC-PCI and CPC-PCIe Card" | 64 | tristate "EMS CPC-PCI, CPC-PCIe and CPC-104P Card" |
65 | depends on PCI && CAN_SJA1000 | 65 | depends on PCI && CAN_SJA1000 |
66 | ---help--- | 66 | ---help--- |
67 | This driver is for the one or two channel CPC-PCI and CPC-PCIe | 67 | This driver is for the one, two or four channel CPC-PCI, |
68 | cards from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de). | 68 | CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche |
69 | (http://www.ems-wuensche.de). | ||
69 | 70 | ||
70 | config CAN_KVASER_PCI | 71 | config CAN_KVASER_PCI |
71 | tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards" | 72 | tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards" |
diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c index 121b64101d7..7d84b8ac9c1 100644 --- a/drivers/net/can/sja1000/ems_pci.c +++ b/drivers/net/can/sja1000/ems_pci.c | |||
@@ -32,13 +32,16 @@ | |||
32 | #define DRV_NAME "ems_pci" | 32 | #define DRV_NAME "ems_pci" |
33 | 33 | ||
34 | MODULE_AUTHOR("Sebastian Haas <haas@ems-wuenche.com>"); | 34 | MODULE_AUTHOR("Sebastian Haas <haas@ems-wuenche.com>"); |
35 | MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-PCI/PCIe CAN cards"); | 35 | MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-PCI/PCIe/104P CAN cards"); |
36 | MODULE_SUPPORTED_DEVICE("EMS CPC-PCI/PCIe CAN card"); | 36 | MODULE_SUPPORTED_DEVICE("EMS CPC-PCI/PCIe/104P CAN card"); |
37 | MODULE_LICENSE("GPL v2"); | 37 | MODULE_LICENSE("GPL v2"); |
38 | 38 | ||
39 | #define EMS_PCI_MAX_CHAN 2 | 39 | #define EMS_PCI_V1_MAX_CHAN 2 |
40 | #define EMS_PCI_V2_MAX_CHAN 4 | ||
41 | #define EMS_PCI_MAX_CHAN EMS_PCI_V2_MAX_CHAN | ||
40 | 42 | ||
41 | struct ems_pci_card { | 43 | struct ems_pci_card { |
44 | int version; | ||
42 | int channels; | 45 | int channels; |
43 | 46 | ||
44 | struct pci_dev *pci_dev; | 47 | struct pci_dev *pci_dev; |
@@ -63,12 +66,22 @@ struct ems_pci_card { | |||
63 | #define PITA2_MISC_CONFIG 0x04000000 /* Multiplexed parallel interface */ | 66 | #define PITA2_MISC_CONFIG 0x04000000 /* Multiplexed parallel interface */ |
64 | 67 | ||
65 | /* | 68 | /* |
69 | * Register definitions for the PLX 9030 | ||
70 | */ | ||
71 | #define PLX_ICSR 0x4c /* Interrupt Control/Status register */ | ||
72 | #define PLX_ICSR_LINTI1_ENA 0x0001 /* LINTi1 Enable */ | ||
73 | #define PLX_ICSR_PCIINT_ENA 0x0040 /* PCI Interrupt Enable */ | ||
74 | #define PLX_ICSR_LINTI1_CLR 0x0400 /* Local Edge Triggerable Interrupt Clear */ | ||
75 | #define PLX_ICSR_ENA_CLR (PLX_ICSR_LINTI1_ENA | PLX_ICSR_PCIINT_ENA | \ | ||
76 | PLX_ICSR_LINTI1_CLR) | ||
77 | |||
78 | /* | ||
66 | * The board configuration is probably following: | 79 | * The board configuration is probably following: |
67 | * RX1 is connected to ground. | 80 | * RX1 is connected to ground. |
68 | * TX1 is not connected. | 81 | * TX1 is not connected. |
69 | * CLKO is not connected. | 82 | * CLKO is not connected. |
70 | * Setting the OCR register to 0xDA is a good idea. | 83 | * Setting the OCR register to 0xDA is a good idea. |
71 | * This means normal output mode , push-pull and the correct polarity. | 84 | * This means normal output mode, push-pull and the correct polarity. |
72 | */ | 85 | */ |
73 | #define EMS_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL) | 86 | #define EMS_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL) |
74 | 87 | ||
@@ -79,17 +92,21 @@ struct ems_pci_card { | |||
79 | * is driven by the first one CLKOUT output. | 92 | * is driven by the first one CLKOUT output. |
80 | */ | 93 | */ |
81 | #define EMS_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) | 94 | #define EMS_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) |
82 | #define EMS_PCI_MEM_SIZE 4096 /* Size of the remapped io-memory */ | 95 | |
96 | #define EMS_PCI_V1_BASE_BAR 1 | ||
97 | #define EMS_PCI_V1_MEM_SIZE 4096 | ||
98 | #define EMS_PCI_V2_BASE_BAR 2 | ||
99 | #define EMS_PCI_V2_MEM_SIZE 128 | ||
83 | #define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */ | 100 | #define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */ |
84 | #define EMS_PCI_CAN_CTRL_SIZE 0x200 /* memory size for each controller */ | 101 | #define EMS_PCI_CAN_CTRL_SIZE 0x200 /* memory size for each controller */ |
85 | 102 | ||
86 | #define EMS_PCI_PORT_BYTES 0x4 /* Each register occupies 4 bytes */ | ||
87 | |||
88 | #define EMS_PCI_VENDOR_ID 0x110a /* PCI device and vendor ID */ | ||
89 | #define EMS_PCI_DEVICE_ID 0x2104 | ||
90 | |||
91 | static struct pci_device_id ems_pci_tbl[] = { | 103 | static struct pci_device_id ems_pci_tbl[] = { |
92 | {EMS_PCI_VENDOR_ID, EMS_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, | 104 | /* CPC-PCI v1 */ |
105 | {PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,}, | ||
106 | /* CPC-PCI v2 */ | ||
107 | {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_PLX, 0x4000}, | ||
108 | /* CPC-104P v2 */ | ||
109 | {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_PLX, 0x4002}, | ||
93 | {0,} | 110 | {0,} |
94 | }; | 111 | }; |
95 | MODULE_DEVICE_TABLE(pci, ems_pci_tbl); | 112 | MODULE_DEVICE_TABLE(pci, ems_pci_tbl); |
@@ -97,28 +114,47 @@ MODULE_DEVICE_TABLE(pci, ems_pci_tbl); | |||
97 | /* | 114 | /* |
98 | * Helper to read internal registers from card logic (not CAN) | 115 | * Helper to read internal registers from card logic (not CAN) |
99 | */ | 116 | */ |
100 | static u8 ems_pci_readb(struct ems_pci_card *card, unsigned int port) | 117 | static u8 ems_pci_v1_readb(struct ems_pci_card *card, unsigned int port) |
101 | { | 118 | { |
102 | return readb(card->base_addr + (port * EMS_PCI_PORT_BYTES)); | 119 | return readb(card->base_addr + (port * 4)); |
103 | } | 120 | } |
104 | 121 | ||
105 | static u8 ems_pci_read_reg(const struct sja1000_priv *priv, int port) | 122 | static u8 ems_pci_v1_read_reg(const struct sja1000_priv *priv, int port) |
106 | { | 123 | { |
107 | return readb(priv->reg_base + (port * EMS_PCI_PORT_BYTES)); | 124 | return readb(priv->reg_base + (port * 4)); |
108 | } | 125 | } |
109 | 126 | ||
110 | static void ems_pci_write_reg(const struct sja1000_priv *priv, int port, u8 val) | 127 | static void ems_pci_v1_write_reg(const struct sja1000_priv *priv, |
128 | int port, u8 val) | ||
111 | { | 129 | { |
112 | writeb(val, priv->reg_base + (port * EMS_PCI_PORT_BYTES)); | 130 | writeb(val, priv->reg_base + (port * 4)); |
113 | } | 131 | } |
114 | 132 | ||
115 | static void ems_pci_post_irq(const struct sja1000_priv *priv) | 133 | static void ems_pci_v1_post_irq(const struct sja1000_priv *priv) |
116 | { | 134 | { |
117 | struct ems_pci_card *card = (struct ems_pci_card *)priv->priv; | 135 | struct ems_pci_card *card = (struct ems_pci_card *)priv->priv; |
118 | 136 | ||
119 | /* reset int flag of pita */ | 137 | /* reset int flag of pita */ |
120 | writel(PITA2_ICR_INT0_EN | PITA2_ICR_INT0, card->conf_addr | 138 | writel(PITA2_ICR_INT0_EN | PITA2_ICR_INT0, |
121 | + PITA2_ICR); | 139 | card->conf_addr + PITA2_ICR); |
140 | } | ||
141 | |||
142 | static u8 ems_pci_v2_read_reg(const struct sja1000_priv *priv, int port) | ||
143 | { | ||
144 | return readb(priv->reg_base + port); | ||
145 | } | ||
146 | |||
147 | static void ems_pci_v2_write_reg(const struct sja1000_priv *priv, | ||
148 | int port, u8 val) | ||
149 | { | ||
150 | writeb(val, priv->reg_base + port); | ||
151 | } | ||
152 | |||
153 | static void ems_pci_v2_post_irq(const struct sja1000_priv *priv) | ||
154 | { | ||
155 | struct ems_pci_card *card = (struct ems_pci_card *)priv->priv; | ||
156 | |||
157 | writel(PLX_ICSR_ENA_CLR, card->conf_addr + PLX_ICSR); | ||
122 | } | 158 | } |
123 | 159 | ||
124 | /* | 160 | /* |
@@ -130,12 +166,12 @@ static inline int ems_pci_check_chan(const struct sja1000_priv *priv) | |||
130 | unsigned char res; | 166 | unsigned char res; |
131 | 167 | ||
132 | /* Make sure SJA1000 is in reset mode */ | 168 | /* Make sure SJA1000 is in reset mode */ |
133 | ems_pci_write_reg(priv, REG_MOD, 1); | 169 | priv->write_reg(priv, REG_MOD, 1); |
134 | 170 | ||
135 | ems_pci_write_reg(priv, REG_CDR, CDR_PELICAN); | 171 | priv->write_reg(priv, REG_CDR, CDR_PELICAN); |
136 | 172 | ||
137 | /* read reset-values */ | 173 | /* read reset-values */ |
138 | res = ems_pci_read_reg(priv, REG_CDR); | 174 | res = priv->read_reg(priv, REG_CDR); |
139 | 175 | ||
140 | if (res == CDR_PELICAN) | 176 | if (res == CDR_PELICAN) |
141 | return 1; | 177 | return 1; |
@@ -188,6 +224,7 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev, | |||
188 | struct sja1000_priv *priv; | 224 | struct sja1000_priv *priv; |
189 | struct net_device *dev; | 225 | struct net_device *dev; |
190 | struct ems_pci_card *card; | 226 | struct ems_pci_card *card; |
227 | int max_chan, mem_size, base_bar; | ||
191 | int err, i; | 228 | int err, i; |
192 | 229 | ||
193 | /* Enabling PCI device */ | 230 | /* Enabling PCI device */ |
@@ -210,37 +247,52 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev, | |||
210 | 247 | ||
211 | card->channels = 0; | 248 | card->channels = 0; |
212 | 249 | ||
213 | /* Remap PITA configuration space, and controller memory area */ | 250 | if (pdev->vendor == PCI_VENDOR_ID_PLX) { |
214 | card->conf_addr = pci_iomap(pdev, 0, EMS_PCI_MEM_SIZE); | 251 | card->version = 2; /* CPC-PCI v2 */ |
252 | max_chan = EMS_PCI_V2_MAX_CHAN; | ||
253 | base_bar = EMS_PCI_V2_BASE_BAR; | ||
254 | mem_size = EMS_PCI_V2_MEM_SIZE; | ||
255 | } else { | ||
256 | card->version = 1; /* CPC-PCI v1 */ | ||
257 | max_chan = EMS_PCI_V1_MAX_CHAN; | ||
258 | base_bar = EMS_PCI_V1_BASE_BAR; | ||
259 | mem_size = EMS_PCI_V1_MEM_SIZE; | ||
260 | } | ||
261 | |||
262 | /* Remap configuration space and controller memory area */ | ||
263 | card->conf_addr = pci_iomap(pdev, 0, mem_size); | ||
215 | if (card->conf_addr == NULL) { | 264 | if (card->conf_addr == NULL) { |
216 | err = -ENOMEM; | 265 | err = -ENOMEM; |
217 | goto failure_cleanup; | 266 | goto failure_cleanup; |
218 | } | 267 | } |
219 | 268 | ||
220 | card->base_addr = pci_iomap(pdev, 1, EMS_PCI_MEM_SIZE); | 269 | card->base_addr = pci_iomap(pdev, base_bar, mem_size); |
221 | if (card->base_addr == NULL) { | 270 | if (card->base_addr == NULL) { |
222 | err = -ENOMEM; | 271 | err = -ENOMEM; |
223 | goto failure_cleanup; | 272 | goto failure_cleanup; |
224 | } | 273 | } |
225 | 274 | ||
226 | /* Configure PITA-2 parallel interface (enable MUX) */ | 275 | if (card->version == 1) { |
227 | writel(PITA2_MISC_CONFIG, card->conf_addr + PITA2_MISC); | 276 | /* Configure PITA-2 parallel interface (enable MUX) */ |
228 | 277 | writel(PITA2_MISC_CONFIG, card->conf_addr + PITA2_MISC); | |
229 | /* Check for unique EMS CAN signature */ | 278 | |
230 | if (ems_pci_readb(card, 0) != 0x55 || | 279 | /* Check for unique EMS CAN signature */ |
231 | ems_pci_readb(card, 1) != 0xAA || | 280 | if (ems_pci_v1_readb(card, 0) != 0x55 || |
232 | ems_pci_readb(card, 2) != 0x01 || | 281 | ems_pci_v1_readb(card, 1) != 0xAA || |
233 | ems_pci_readb(card, 3) != 0xCB || | 282 | ems_pci_v1_readb(card, 2) != 0x01 || |
234 | ems_pci_readb(card, 4) != 0x11) { | 283 | ems_pci_v1_readb(card, 3) != 0xCB || |
235 | dev_err(&pdev->dev, "Not EMS Dr. Thomas Wuensche interface\n"); | 284 | ems_pci_v1_readb(card, 4) != 0x11) { |
236 | err = -ENODEV; | 285 | dev_err(&pdev->dev, |
237 | goto failure_cleanup; | 286 | "Not EMS Dr. Thomas Wuensche interface\n"); |
287 | err = -ENODEV; | ||
288 | goto failure_cleanup; | ||
289 | } | ||
238 | } | 290 | } |
239 | 291 | ||
240 | ems_pci_card_reset(card); | 292 | ems_pci_card_reset(card); |
241 | 293 | ||
242 | /* Detect available channels */ | 294 | /* Detect available channels */ |
243 | for (i = 0; i < EMS_PCI_MAX_CHAN; i++) { | 295 | for (i = 0; i < max_chan; i++) { |
244 | dev = alloc_sja1000dev(0); | 296 | dev = alloc_sja1000dev(0); |
245 | if (dev == NULL) { | 297 | if (dev == NULL) { |
246 | err = -ENOMEM; | 298 | err = -ENOMEM; |
@@ -255,20 +307,32 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev, | |||
255 | dev->irq = pdev->irq; | 307 | dev->irq = pdev->irq; |
256 | priv->reg_base = card->base_addr + EMS_PCI_CAN_BASE_OFFSET | 308 | priv->reg_base = card->base_addr + EMS_PCI_CAN_BASE_OFFSET |
257 | + (i * EMS_PCI_CAN_CTRL_SIZE); | 309 | + (i * EMS_PCI_CAN_CTRL_SIZE); |
310 | if (card->version == 1) { | ||
311 | priv->read_reg = ems_pci_v1_read_reg; | ||
312 | priv->write_reg = ems_pci_v1_write_reg; | ||
313 | priv->post_irq = ems_pci_v1_post_irq; | ||
314 | } else { | ||
315 | priv->read_reg = ems_pci_v2_read_reg; | ||
316 | priv->write_reg = ems_pci_v2_write_reg; | ||
317 | priv->post_irq = ems_pci_v2_post_irq; | ||
318 | } | ||
258 | 319 | ||
259 | /* Check if channel is present */ | 320 | /* Check if channel is present */ |
260 | if (ems_pci_check_chan(priv)) { | 321 | if (ems_pci_check_chan(priv)) { |
261 | priv->read_reg = ems_pci_read_reg; | ||
262 | priv->write_reg = ems_pci_write_reg; | ||
263 | priv->post_irq = ems_pci_post_irq; | ||
264 | priv->can.clock.freq = EMS_PCI_CAN_CLOCK; | 322 | priv->can.clock.freq = EMS_PCI_CAN_CLOCK; |
265 | priv->ocr = EMS_PCI_OCR; | 323 | priv->ocr = EMS_PCI_OCR; |
266 | priv->cdr = EMS_PCI_CDR; | 324 | priv->cdr = EMS_PCI_CDR; |
267 | 325 | ||
268 | SET_NETDEV_DEV(dev, &pdev->dev); | 326 | SET_NETDEV_DEV(dev, &pdev->dev); |
269 | 327 | ||
270 | /* Enable interrupts from card */ | 328 | if (card->version == 1) |
271 | writel(PITA2_ICR_INT0_EN, card->conf_addr + PITA2_ICR); | 329 | /* reset int flag of pita */ |
330 | writel(PITA2_ICR_INT0_EN | PITA2_ICR_INT0, | ||
331 | card->conf_addr + PITA2_ICR); | ||
332 | else | ||
333 | /* enable IRQ in PLX 9030 */ | ||
334 | writel(PLX_ICSR_ENA_CLR, | ||
335 | card->conf_addr + PLX_ICSR); | ||
272 | 336 | ||
273 | /* Register SJA1000 device */ | 337 | /* Register SJA1000 device */ |
274 | err = register_sja1000dev(dev); | 338 | err = register_sja1000dev(dev); |