diff options
author | Konrad Zapalowicz <bergo.torino@gmail.com> | 2014-11-06 18:05:33 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-11-06 18:18:00 -0500 |
commit | 03a8482c17dd0ae3251451d54cbbc03f930f21d5 (patch) | |
tree | 96455dcd31958809a6f80e0c275548a103095fd0 | |
parent | 95db1ccb15ae3703f751891ce1ee8f7734c21c96 (diff) |
drivers: serial: jsm: Enable support for Digi Classic adapters
This commit enables support for the Digi Classic adapters line in the
jsm driver. This means changes in:
- device probing code
- device cleanup code
- driver description (Kconfig)
The init/cleanup code is based on the staging/dgnc driver.
Signed-off-by: Konrad Zapalowicz <bergo.torino@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/tty/serial/Kconfig | 4 | ||||
-rw-r--r-- | drivers/tty/serial/jsm/jsm.h | 4 | ||||
-rw-r--r-- | drivers/tty/serial/jsm/jsm_driver.c | 151 | ||||
-rw-r--r-- | drivers/tty/serial/jsm/jsm_tty.c | 2 |
4 files changed, 128 insertions, 33 deletions
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 7088373efc15..e71a28b4b94e 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
@@ -1029,11 +1029,11 @@ config SERIAL_VR41XX_CONSOLE | |||
1029 | a console on a serial port, say Y. Otherwise, say N. | 1029 | a console on a serial port, say Y. Otherwise, say N. |
1030 | 1030 | ||
1031 | config SERIAL_JSM | 1031 | config SERIAL_JSM |
1032 | tristate "Digi International NEO PCI Support" | 1032 | tristate "Digi International NEO and Classic PCI Support" |
1033 | depends on PCI | 1033 | depends on PCI |
1034 | select SERIAL_CORE | 1034 | select SERIAL_CORE |
1035 | help | 1035 | help |
1036 | This is a driver for Digi International's Neo series | 1036 | This is a driver for Digi International's Neo and Classic series |
1037 | of cards which provide multiple serial ports. You would need | 1037 | of cards which provide multiple serial ports. You would need |
1038 | something like this to connect more than two modems to your Linux | 1038 | something like this to connect more than two modems to your Linux |
1039 | box, for instance in order to become a dial-in server. This driver | 1039 | box, for instance in order to become a dial-in server. This driver |
diff --git a/drivers/tty/serial/jsm/jsm.h b/drivers/tty/serial/jsm/jsm.h index 309428273571..662523d66704 100644 --- a/drivers/tty/serial/jsm/jsm.h +++ b/drivers/tty/serial/jsm/jsm.h | |||
@@ -68,6 +68,10 @@ do { \ | |||
68 | #define MAX_STOPS_SENT 5 | 68 | #define MAX_STOPS_SENT 5 |
69 | 69 | ||
70 | /* Board ids */ | 70 | /* Board ids */ |
71 | #define PCI_DEVICE_ID_CLASSIC_4 0x0028 | ||
72 | #define PCI_DEVICE_ID_CLASSIC_8 0x0029 | ||
73 | #define PCI_DEVICE_ID_CLASSIC_4_422 0x00D0 | ||
74 | #define PCI_DEVICE_ID_CLASSIC_8_422 0x00D1 | ||
71 | #define PCI_DEVICE_ID_NEO_4 0x00B0 | 75 | #define PCI_DEVICE_ID_NEO_4 0x00B0 |
72 | #define PCI_DEVICE_ID_NEO_1_422 0x00CC | 76 | #define PCI_DEVICE_ID_NEO_1_422 0x00CC |
73 | #define PCI_DEVICE_ID_NEO_1_422_485 0x00CD | 77 | #define PCI_DEVICE_ID_NEO_1_422_485 0x00CD |
diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c index d2885a7bb090..0927ddf3d071 100644 --- a/drivers/tty/serial/jsm/jsm_driver.c +++ b/drivers/tty/serial/jsm/jsm_driver.c | |||
@@ -31,8 +31,7 @@ | |||
31 | #include "jsm.h" | 31 | #include "jsm.h" |
32 | 32 | ||
33 | MODULE_AUTHOR("Digi International, http://www.digi.com"); | 33 | MODULE_AUTHOR("Digi International, http://www.digi.com"); |
34 | MODULE_DESCRIPTION("Driver for the Digi International " | 34 | MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line"); |
35 | "Neo PCI based product line"); | ||
36 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
37 | MODULE_SUPPORTED_DEVICE("jsm"); | 36 | MODULE_SUPPORTED_DEVICE("jsm"); |
38 | 37 | ||
@@ -50,7 +49,7 @@ struct uart_driver jsm_uart_driver = { | |||
50 | }; | 49 | }; |
51 | 50 | ||
52 | static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, | 51 | static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, |
53 | pci_channel_state_t state); | 52 | pci_channel_state_t state); |
54 | static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev); | 53 | static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev); |
55 | static void jsm_io_resume(struct pci_dev *pdev); | 54 | static void jsm_io_resume(struct pci_dev *pdev); |
56 | 55 | ||
@@ -68,7 +67,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
68 | { | 67 | { |
69 | int rc = 0; | 68 | int rc = 0; |
70 | struct jsm_board *brd; | 69 | struct jsm_board *brd; |
71 | static int adapter_count = 0; | 70 | static int adapter_count; |
72 | 71 | ||
73 | rc = pci_enable_device(pdev); | 72 | rc = pci_enable_device(pdev); |
74 | if (rc) { | 73 | if (rc) { |
@@ -82,10 +81,8 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
82 | goto out_disable_device; | 81 | goto out_disable_device; |
83 | } | 82 | } |
84 | 83 | ||
85 | brd = kzalloc(sizeof(struct jsm_board), GFP_KERNEL); | 84 | brd = kzalloc(sizeof(*brd), GFP_KERNEL); |
86 | if (!brd) { | 85 | if (!brd) { |
87 | dev_err(&pdev->dev, | ||
88 | "memory allocation for board structure failed\n"); | ||
89 | rc = -ENOMEM; | 86 | rc = -ENOMEM; |
90 | goto out_release_regions; | 87 | goto out_release_regions; |
91 | } | 88 | } |
@@ -95,7 +92,6 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
95 | brd->pci_dev = pdev; | 92 | brd->pci_dev = pdev; |
96 | 93 | ||
97 | switch (pdev->device) { | 94 | switch (pdev->device) { |
98 | |||
99 | case PCI_DEVICE_ID_NEO_2DB9: | 95 | case PCI_DEVICE_ID_NEO_2DB9: |
100 | case PCI_DEVICE_ID_NEO_2DB9PRI: | 96 | case PCI_DEVICE_ID_NEO_2DB9PRI: |
101 | case PCI_DEVICE_ID_NEO_2RJ45: | 97 | case PCI_DEVICE_ID_NEO_2RJ45: |
@@ -104,6 +100,8 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
104 | brd->maxports = 2; | 100 | brd->maxports = 2; |
105 | break; | 101 | break; |
106 | 102 | ||
103 | case PCI_DEVICE_ID_CLASSIC_4: | ||
104 | case PCI_DEVICE_ID_CLASSIC_4_422: | ||
107 | case PCI_DEVICE_ID_NEO_4: | 105 | case PCI_DEVICE_ID_NEO_4: |
108 | case PCIE_DEVICE_ID_NEO_4: | 106 | case PCIE_DEVICE_ID_NEO_4: |
109 | case PCIE_DEVICE_ID_NEO_4RJ45: | 107 | case PCIE_DEVICE_ID_NEO_4RJ45: |
@@ -111,6 +109,8 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
111 | brd->maxports = 4; | 109 | brd->maxports = 4; |
112 | break; | 110 | break; |
113 | 111 | ||
112 | case PCI_DEVICE_ID_CLASSIC_8: | ||
113 | case PCI_DEVICE_ID_CLASSIC_8_422: | ||
114 | case PCI_DEVICE_ID_DIGI_NEO_8: | 114 | case PCI_DEVICE_ID_DIGI_NEO_8: |
115 | case PCIE_DEVICE_ID_NEO_8: | 115 | case PCIE_DEVICE_ID_NEO_8: |
116 | case PCIE_DEVICE_ID_NEO_8RJ45: | 116 | case PCIE_DEVICE_ID_NEO_8RJ45: |
@@ -129,36 +129,109 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
129 | 129 | ||
130 | brd->irq = pdev->irq; | 130 | brd->irq = pdev->irq; |
131 | 131 | ||
132 | jsm_dbg(INIT, &brd->pci_dev, "jsm_found_board - NEO adapter\n"); | 132 | switch (pdev->device) { |
133 | case PCI_DEVICE_ID_CLASSIC_4: | ||
134 | case PCI_DEVICE_ID_CLASSIC_4_422: | ||
135 | case PCI_DEVICE_ID_CLASSIC_8: | ||
136 | case PCI_DEVICE_ID_CLASSIC_8_422: | ||
137 | |||
138 | jsm_dbg(INIT, &brd->pci_dev, | ||
139 | "jsm_found_board - Classic adapter\n"); | ||
140 | |||
141 | /* | ||
142 | * For PCI ClassicBoards | ||
143 | * PCI Local Address (.i.e. "resource" number) space | ||
144 | * 0 PLX Memory Mapped Config | ||
145 | * 1 PLX I/O Mapped Config | ||
146 | * 2 I/O Mapped UARTs and Status | ||
147 | * 3 Memory Mapped VPD | ||
148 | * 4 Memory Mapped UARTs and Status | ||
149 | */ | ||
150 | |||
151 | /* Get the PCI Base Address Registers */ | ||
152 | brd->membase = pci_resource_start(pdev, 4); | ||
153 | brd->membase_end = pci_resource_end(pdev, 4); | ||
154 | |||
155 | if (brd->membase & 0x1) | ||
156 | brd->membase &= ~0x3; | ||
157 | else | ||
158 | brd->membase &= ~0xF; | ||
159 | |||
160 | brd->iobase = pci_resource_start(pdev, 1); | ||
161 | brd->iobase_end = pci_resource_end(pdev, 1); | ||
162 | brd->iobase = ((unsigned int)(brd->iobase)) & 0xFFFE; | ||
163 | |||
164 | /* Assign the board_ops struct */ | ||
165 | brd->bd_ops = &jsm_cls_ops; | ||
166 | |||
167 | brd->bd_uart_offset = 0x8; | ||
168 | brd->bd_dividend = 921600; | ||
169 | |||
170 | brd->re_map_membase = ioremap(brd->membase, | ||
171 | pci_resource_len(pdev, 4)); | ||
172 | if (!brd->re_map_membase) { | ||
173 | dev_err(&pdev->dev, | ||
174 | "Card has no PCI Memory resources, failing board.\n"); | ||
175 | rc = -ENOMEM; | ||
176 | goto out_kfree_brd; | ||
177 | } | ||
133 | 178 | ||
134 | /* get the PCI Base Address Registers */ | 179 | /* |
135 | brd->membase = pci_resource_start(pdev, 0); | 180 | * Enable Local Interrupt 1 (0x1), |
136 | brd->membase_end = pci_resource_end(pdev, 0); | 181 | * Local Interrupt 1 Polarity Active high (0x2), |
182 | * Enable PCI interrupt (0x43) | ||
183 | */ | ||
184 | outb(0x43, brd->iobase + 0x4c); | ||
137 | 185 | ||
138 | if (brd->membase & 1) | 186 | break; |
139 | brd->membase &= ~3; | ||
140 | else | ||
141 | brd->membase &= ~15; | ||
142 | 187 | ||
143 | /* Assign the board_ops struct */ | 188 | case PCI_DEVICE_ID_NEO_2DB9: |
144 | brd->bd_ops = &jsm_neo_ops; | 189 | case PCI_DEVICE_ID_NEO_2DB9PRI: |
190 | case PCI_DEVICE_ID_NEO_2RJ45: | ||
191 | case PCI_DEVICE_ID_NEO_2RJ45PRI: | ||
192 | case PCI_DEVICE_ID_NEO_2_422_485: | ||
193 | case PCI_DEVICE_ID_NEO_4: | ||
194 | case PCIE_DEVICE_ID_NEO_4: | ||
195 | case PCIE_DEVICE_ID_NEO_4RJ45: | ||
196 | case PCIE_DEVICE_ID_NEO_4_IBM: | ||
197 | case PCI_DEVICE_ID_DIGI_NEO_8: | ||
198 | case PCIE_DEVICE_ID_NEO_8: | ||
199 | case PCIE_DEVICE_ID_NEO_8RJ45: | ||
145 | 200 | ||
146 | brd->bd_uart_offset = 0x200; | 201 | jsm_dbg(INIT, &brd->pci_dev, "jsm_found_board - NEO adapter\n"); |
147 | brd->bd_dividend = 921600; | ||
148 | 202 | ||
149 | brd->re_map_membase = ioremap(brd->membase, pci_resource_len(pdev, 0)); | 203 | /* get the PCI Base Address Registers */ |
150 | if (!brd->re_map_membase) { | 204 | brd->membase = pci_resource_start(pdev, 0); |
151 | dev_err(&pdev->dev, | 205 | brd->membase_end = pci_resource_end(pdev, 0); |
152 | "card has no PCI Memory resources, " | 206 | |
153 | "failing board.\n"); | 207 | if (brd->membase & 1) |
154 | rc = -ENOMEM; | 208 | brd->membase &= ~0x3; |
155 | goto out_kfree_brd; | 209 | else |
210 | brd->membase &= ~0xF; | ||
211 | |||
212 | /* Assign the board_ops struct */ | ||
213 | brd->bd_ops = &jsm_neo_ops; | ||
214 | |||
215 | brd->bd_uart_offset = 0x200; | ||
216 | brd->bd_dividend = 921600; | ||
217 | |||
218 | brd->re_map_membase = ioremap(brd->membase, | ||
219 | pci_resource_len(pdev, 0)); | ||
220 | if (!brd->re_map_membase) { | ||
221 | dev_err(&pdev->dev, | ||
222 | "Card has no PCI Memory resources, failing board.\n"); | ||
223 | rc = -ENOMEM; | ||
224 | goto out_kfree_brd; | ||
225 | } | ||
226 | |||
227 | break; | ||
228 | default: | ||
229 | return -ENXIO; | ||
156 | } | 230 | } |
157 | 231 | ||
158 | rc = request_irq(brd->irq, brd->bd_ops->intr, | 232 | rc = request_irq(brd->irq, brd->bd_ops->intr, IRQF_SHARED, "JSM", brd); |
159 | IRQF_SHARED, "JSM", brd); | ||
160 | if (rc) { | 233 | if (rc) { |
161 | printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); | 234 | dev_warn(&pdev->dev, "Failed to hook IRQ %d\n", brd->irq); |
162 | goto out_iounmap; | 235 | goto out_iounmap; |
163 | } | 236 | } |
164 | 237 | ||
@@ -178,7 +251,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
178 | } | 251 | } |
179 | 252 | ||
180 | /* Log the information about the board */ | 253 | /* Log the information about the board */ |
181 | dev_info(&pdev->dev, "board %d: Digi Neo (rev %d), irq %d\n", | 254 | dev_info(&pdev->dev, "board %d: Digi Classic/Neo (rev %d), irq %d\n", |
182 | adapter_count, brd->rev, brd->irq); | 255 | adapter_count, brd->rev, brd->irq); |
183 | 256 | ||
184 | pci_set_drvdata(pdev, brd); | 257 | pci_set_drvdata(pdev, brd); |
@@ -205,6 +278,18 @@ static void jsm_remove_one(struct pci_dev *pdev) | |||
205 | struct jsm_board *brd = pci_get_drvdata(pdev); | 278 | struct jsm_board *brd = pci_get_drvdata(pdev); |
206 | int i = 0; | 279 | int i = 0; |
207 | 280 | ||
281 | switch (pdev->device) { | ||
282 | case PCI_DEVICE_ID_CLASSIC_4: | ||
283 | case PCI_DEVICE_ID_CLASSIC_4_422: | ||
284 | case PCI_DEVICE_ID_CLASSIC_8: | ||
285 | case PCI_DEVICE_ID_CLASSIC_8_422: | ||
286 | /* Tell card not to interrupt anymore. */ | ||
287 | outb(0x0, brd->iobase + 0x4c); | ||
288 | break; | ||
289 | default: | ||
290 | break; | ||
291 | } | ||
292 | |||
208 | jsm_remove_uart_port(brd); | 293 | jsm_remove_uart_port(brd); |
209 | 294 | ||
210 | free_irq(brd->irq, brd); | 295 | free_irq(brd->irq, brd); |
@@ -239,6 +324,10 @@ static struct pci_device_id jsm_pci_tbl[] = { | |||
239 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4), 0, 0, 11 }, | 324 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4), 0, 0, 11 }, |
240 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4RJ45), 0, 0, 12 }, | 325 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4RJ45), 0, 0, 12 }, |
241 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_8RJ45), 0, 0, 13 }, | 326 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_8RJ45), 0, 0, 13 }, |
327 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_CLASSIC_4), 0, 0, 14 }, | ||
328 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_CLASSIC_4_422), 0, 0, 15 }, | ||
329 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_CLASSIC_8), 0, 0, 16 }, | ||
330 | { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_CLASSIC_8_422), 0, 0, 17 }, | ||
242 | { 0, } | 331 | { 0, } |
243 | }; | 332 | }; |
244 | MODULE_DEVICE_TABLE(pci, jsm_pci_tbl); | 333 | MODULE_DEVICE_TABLE(pci, jsm_pci_tbl); |
diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c index 8814680630a4..4259e5af8467 100644 --- a/drivers/tty/serial/jsm/jsm_tty.c +++ b/drivers/tty/serial/jsm/jsm_tty.c | |||
@@ -425,6 +425,8 @@ int jsm_tty_init(struct jsm_board *brd) | |||
425 | 425 | ||
426 | if (brd->bd_uart_offset == 0x200) | 426 | if (brd->bd_uart_offset == 0x200) |
427 | ch->ch_neo_uart = vaddr + (brd->bd_uart_offset * i); | 427 | ch->ch_neo_uart = vaddr + (brd->bd_uart_offset * i); |
428 | else | ||
429 | ch->ch_cls_uart = vaddr + (brd->bd_uart_offset * i); | ||
428 | 430 | ||
429 | ch->ch_bd = brd; | 431 | ch->ch_bd = brd; |
430 | ch->ch_portnum = i; | 432 | ch->ch_portnum = i; |