diff options
Diffstat (limited to 'drivers/serial/ioc4_serial.c')
-rw-r--r-- | drivers/serial/ioc4_serial.c | 336 |
1 files changed, 144 insertions, 192 deletions
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index ba4e13a22a50..793c3a7cbe47 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/serial_reg.h> | 20 | #include <linux/serial_reg.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
23 | #include <linux/ioc4_common.h> | 23 | #include <linux/ioc4.h> |
24 | #include <linux/serial_core.h> | 24 | #include <linux/serial_core.h> |
25 | 25 | ||
26 | /* | 26 | /* |
@@ -130,12 +130,19 @@ | |||
130 | IOC4_SIO_IR_S3_TX_EXPLICIT) | 130 | IOC4_SIO_IR_S3_TX_EXPLICIT) |
131 | 131 | ||
132 | /* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES */ | 132 | /* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES */ |
133 | #define IOC4_OTHER_IR_ATA_INT 0x00000001 /* ATAPI intr pass-thru */ | 133 | #define IOC4_OTHER_IR_ATA_INT 0x00000001 /* ATAPI intr pass-thru */ |
134 | #define IOC4_OTHER_IR_ATA_MEMERR 0x00000002 /* ATAPI DMA PCI error */ | 134 | #define IOC4_OTHER_IR_ATA_MEMERR 0x00000002 /* ATAPI DMA PCI error */ |
135 | #define IOC4_OTHER_IR_S0_MEMERR 0x00000004 /* Port 0 PCI error */ | 135 | #define IOC4_OTHER_IR_S0_MEMERR 0x00000004 /* Port 0 PCI error */ |
136 | #define IOC4_OTHER_IR_S1_MEMERR 0x00000008 /* Port 1 PCI error */ | 136 | #define IOC4_OTHER_IR_S1_MEMERR 0x00000008 /* Port 1 PCI error */ |
137 | #define IOC4_OTHER_IR_S2_MEMERR 0x00000010 /* Port 2 PCI error */ | 137 | #define IOC4_OTHER_IR_S2_MEMERR 0x00000010 /* Port 2 PCI error */ |
138 | #define IOC4_OTHER_IR_S3_MEMERR 0x00000020 /* Port 3 PCI error */ | 138 | #define IOC4_OTHER_IR_S3_MEMERR 0x00000020 /* Port 3 PCI error */ |
139 | #define IOC4_OTHER_IR_KBD_INT 0x00000040 /* Keyboard/mouse */ | ||
140 | #define IOC4_OTHER_IR_RESERVED 0x007fff80 /* Reserved */ | ||
141 | #define IOC4_OTHER_IR_RT_INT 0x00800000 /* INT_OUT section output */ | ||
142 | #define IOC4_OTHER_IR_GEN_INT 0xff000000 /* Generic pins */ | ||
143 | |||
144 | #define IOC4_OTHER_IR_SER_MEMERR (IOC4_OTHER_IR_S0_MEMERR | IOC4_OTHER_IR_S1_MEMERR | \ | ||
145 | IOC4_OTHER_IR_S2_MEMERR | IOC4_OTHER_IR_S3_MEMERR) | ||
139 | 146 | ||
140 | /* Bitmasks for IOC4_SIO_CR */ | 147 | /* Bitmasks for IOC4_SIO_CR */ |
141 | #define IOC4_SIO_CR_CMD_PULSE_SHIFT 0 /* byte bus strobe shift */ | 148 | #define IOC4_SIO_CR_CMD_PULSE_SHIFT 0 /* byte bus strobe shift */ |
@@ -274,70 +281,24 @@ struct ioc4_uartregs { | |||
274 | #define i4u_dlm u2.dlm | 281 | #define i4u_dlm u2.dlm |
275 | #define i4u_fcr u3.fcr | 282 | #define i4u_fcr u3.fcr |
276 | 283 | ||
277 | /* PCI memory space register map addressed using pci_bar0 */ | 284 | /* Serial port registers used for DMA serial I/O */ |
278 | struct ioc4_memregs { | 285 | struct ioc4_serial { |
279 | struct ioc4_mem { | 286 | uint32_t sbbr01_l; |
280 | /* Miscellaneous IOC4 registers */ | 287 | uint32_t sbbr01_h; |
281 | uint32_t pci_err_addr_l; | 288 | uint32_t sbbr23_l; |
282 | uint32_t pci_err_addr_h; | 289 | uint32_t sbbr23_h; |
283 | uint32_t sio_ir; | 290 | |
284 | uint32_t other_ir; | 291 | struct ioc4_serialregs port_0; |
285 | 292 | struct ioc4_serialregs port_1; | |
286 | /* These registers are read-only for general kernel code. */ | 293 | struct ioc4_serialregs port_2; |
287 | uint32_t sio_ies_ro; | 294 | struct ioc4_serialregs port_3; |
288 | uint32_t other_ies_ro; | 295 | struct ioc4_uartregs uart_0; |
289 | uint32_t sio_iec_ro; | 296 | struct ioc4_uartregs uart_1; |
290 | uint32_t other_iec_ro; | 297 | struct ioc4_uartregs uart_2; |
291 | uint32_t sio_cr; | 298 | struct ioc4_uartregs uart_3; |
292 | uint32_t misc_fill1; | 299 | } ioc4_serial; |
293 | uint32_t int_out; | ||
294 | uint32_t misc_fill2; | ||
295 | uint32_t gpcr_s; | ||
296 | uint32_t gpcr_c; | ||
297 | uint32_t gpdr; | ||
298 | uint32_t misc_fill3; | ||
299 | uint32_t gppr_0; | ||
300 | uint32_t gppr_1; | ||
301 | uint32_t gppr_2; | ||
302 | uint32_t gppr_3; | ||
303 | uint32_t gppr_4; | ||
304 | uint32_t gppr_5; | ||
305 | uint32_t gppr_6; | ||
306 | uint32_t gppr_7; | ||
307 | } ioc4_mem; | ||
308 | |||
309 | char misc_fill4[0x100 - 0x5C - 4]; | ||
310 | |||
311 | /* ATA/ATAP registers */ | ||
312 | uint32_t ata_notused[9]; | ||
313 | char ata_fill1[0x140 - 0x120 - 4]; | ||
314 | uint32_t ata_notused1[8]; | ||
315 | char ata_fill2[0x200 - 0x15C - 4]; | ||
316 | |||
317 | /* Keyboard and mouse registers */ | ||
318 | uint32_t km_notused[5];; | ||
319 | char km_fill1[0x300 - 0x210 - 4]; | ||
320 | |||
321 | /* Serial port registers used for DMA serial I/O */ | ||
322 | struct ioc4_serial { | ||
323 | uint32_t sbbr01_l; | ||
324 | uint32_t sbbr01_h; | ||
325 | uint32_t sbbr23_l; | ||
326 | uint32_t sbbr23_h; | ||
327 | |||
328 | struct ioc4_serialregs port_0; | ||
329 | struct ioc4_serialregs port_1; | ||
330 | struct ioc4_serialregs port_2; | ||
331 | struct ioc4_serialregs port_3; | ||
332 | struct ioc4_uartregs uart_0; | ||
333 | struct ioc4_uartregs uart_1; | ||
334 | struct ioc4_uartregs uart_2; | ||
335 | struct ioc4_uartregs uart_3; | ||
336 | } ioc4_serial; | ||
337 | }; | ||
338 | 300 | ||
339 | /* UART clock speed */ | 301 | /* UART clock speed */ |
340 | #define IOC4_SER_XIN_CLK IOC4_SER_XIN_CLK_66 | ||
341 | #define IOC4_SER_XIN_CLK_66 66666667 | 302 | #define IOC4_SER_XIN_CLK_66 66666667 |
342 | #define IOC4_SER_XIN_CLK_33 33333333 | 303 | #define IOC4_SER_XIN_CLK_33 33333333 |
343 | 304 | ||
@@ -412,8 +373,8 @@ enum sio_proto { | |||
412 | | UART_LCR_WLEN7 | UART_LCR_WLEN8) | 373 | | UART_LCR_WLEN7 | UART_LCR_WLEN8) |
413 | #define LCR_MASK_STOP_BITS (UART_LCR_STOP) | 374 | #define LCR_MASK_STOP_BITS (UART_LCR_STOP) |
414 | 375 | ||
415 | #define PENDING(_p) (readl(&(_p)->ip_mem->sio_ir) & _p->ip_ienb) | 376 | #define PENDING(_p) (readl(&(_p)->ip_mem->sio_ir.raw) & _p->ip_ienb) |
416 | #define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir) | 377 | #define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir.raw) |
417 | 378 | ||
418 | /* Default to 4k buffers */ | 379 | /* Default to 4k buffers */ |
419 | #ifdef IOC4_1K_BUFFERS | 380 | #ifdef IOC4_1K_BUFFERS |
@@ -447,7 +408,7 @@ struct ioc4_control { | |||
447 | */ | 408 | */ |
448 | #define MAX_IOC4_INTR_ENTS (8 * sizeof(uint32_t)) | 409 | #define MAX_IOC4_INTR_ENTS (8 * sizeof(uint32_t)) |
449 | struct ioc4_soft { | 410 | struct ioc4_soft { |
450 | struct ioc4_mem __iomem *is_ioc4_mem_addr; | 411 | struct ioc4_misc_regs __iomem *is_ioc4_misc_addr; |
451 | struct ioc4_serial __iomem *is_ioc4_serial_addr; | 412 | struct ioc4_serial __iomem *is_ioc4_serial_addr; |
452 | 413 | ||
453 | /* Each interrupt type has an entry in the array */ | 414 | /* Each interrupt type has an entry in the array */ |
@@ -486,7 +447,7 @@ struct ioc4_port { | |||
486 | struct ioc4_soft *ip_ioc4_soft; | 447 | struct ioc4_soft *ip_ioc4_soft; |
487 | 448 | ||
488 | /* pci mem addresses */ | 449 | /* pci mem addresses */ |
489 | struct ioc4_mem __iomem *ip_mem; | 450 | struct ioc4_misc_regs __iomem *ip_mem; |
490 | struct ioc4_serial __iomem *ip_serial; | 451 | struct ioc4_serial __iomem *ip_serial; |
491 | struct ioc4_serialregs __iomem *ip_serial_regs; | 452 | struct ioc4_serialregs __iomem *ip_serial_regs; |
492 | struct ioc4_uartregs __iomem *ip_uart_regs; | 453 | struct ioc4_uartregs __iomem *ip_uart_regs; |
@@ -553,7 +514,7 @@ struct hooks { | |||
553 | uint32_t intr_dma_error; | 514 | uint32_t intr_dma_error; |
554 | uint32_t intr_clear; | 515 | uint32_t intr_clear; |
555 | uint32_t intr_all; | 516 | uint32_t intr_all; |
556 | char rs422_select_pin; | 517 | int rs422_select_pin; |
557 | }; | 518 | }; |
558 | 519 | ||
559 | static struct hooks hooks_array[IOC4_NUM_SERIAL_PORTS] = { | 520 | static struct hooks hooks_array[IOC4_NUM_SERIAL_PORTS] = { |
@@ -669,7 +630,7 @@ static void handle_intr(void *arg, uint32_t sio_ir); | |||
669 | static inline void | 630 | static inline void |
670 | write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type) | 631 | write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type) |
671 | { | 632 | { |
672 | struct ioc4_mem __iomem *mem = ioc4_soft->is_ioc4_mem_addr; | 633 | struct ioc4_misc_regs __iomem *mem = ioc4_soft->is_ioc4_misc_addr; |
673 | unsigned long flags; | 634 | unsigned long flags; |
674 | 635 | ||
675 | spin_lock_irqsave(&ioc4_soft->is_ir_lock, flags); | 636 | spin_lock_irqsave(&ioc4_soft->is_ir_lock, flags); |
@@ -678,11 +639,11 @@ write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type) | |||
678 | case IOC4_SIO_INTR_TYPE: | 639 | case IOC4_SIO_INTR_TYPE: |
679 | switch (which) { | 640 | switch (which) { |
680 | case IOC4_W_IES: | 641 | case IOC4_W_IES: |
681 | writel(val, &mem->sio_ies_ro); | 642 | writel(val, &mem->sio_ies.raw); |
682 | break; | 643 | break; |
683 | 644 | ||
684 | case IOC4_W_IEC: | 645 | case IOC4_W_IEC: |
685 | writel(val, &mem->sio_iec_ro); | 646 | writel(val, &mem->sio_iec.raw); |
686 | break; | 647 | break; |
687 | } | 648 | } |
688 | break; | 649 | break; |
@@ -690,11 +651,11 @@ write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type) | |||
690 | case IOC4_OTHER_INTR_TYPE: | 651 | case IOC4_OTHER_INTR_TYPE: |
691 | switch (which) { | 652 | switch (which) { |
692 | case IOC4_W_IES: | 653 | case IOC4_W_IES: |
693 | writel(val, &mem->other_ies_ro); | 654 | writel(val, &mem->other_ies.raw); |
694 | break; | 655 | break; |
695 | 656 | ||
696 | case IOC4_W_IEC: | 657 | case IOC4_W_IEC: |
697 | writel(val, &mem->other_iec_ro); | 658 | writel(val, &mem->other_iec.raw); |
698 | break; | 659 | break; |
699 | } | 660 | } |
700 | break; | 661 | break; |
@@ -747,7 +708,8 @@ static int set_baud(struct ioc4_port *port, int baud) | |||
747 | */ | 708 | */ |
748 | static struct ioc4_port *get_ioc4_port(struct uart_port *the_port) | 709 | static struct ioc4_port *get_ioc4_port(struct uart_port *the_port) |
749 | { | 710 | { |
750 | struct ioc4_control *control = dev_get_drvdata(the_port->dev); | 711 | struct ioc4_driver_data *idd = dev_get_drvdata(the_port->dev); |
712 | struct ioc4_control *control = idd->idd_serial_data; | ||
751 | int ii; | 713 | int ii; |
752 | 714 | ||
753 | if (control) { | 715 | if (control) { |
@@ -782,7 +744,7 @@ static struct ioc4_port *get_ioc4_port(struct uart_port *the_port) | |||
782 | static inline uint32_t | 744 | static inline uint32_t |
783 | pending_intrs(struct ioc4_soft *soft, int type) | 745 | pending_intrs(struct ioc4_soft *soft, int type) |
784 | { | 746 | { |
785 | struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr; | 747 | struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr; |
786 | unsigned long flag; | 748 | unsigned long flag; |
787 | uint32_t intrs = 0; | 749 | uint32_t intrs = 0; |
788 | 750 | ||
@@ -793,11 +755,11 @@ pending_intrs(struct ioc4_soft *soft, int type) | |||
793 | 755 | ||
794 | switch (type) { | 756 | switch (type) { |
795 | case IOC4_SIO_INTR_TYPE: | 757 | case IOC4_SIO_INTR_TYPE: |
796 | intrs = readl(&mem->sio_ir) & readl(&mem->sio_ies_ro); | 758 | intrs = readl(&mem->sio_ir.raw) & readl(&mem->sio_ies.raw); |
797 | break; | 759 | break; |
798 | 760 | ||
799 | case IOC4_OTHER_INTR_TYPE: | 761 | case IOC4_OTHER_INTR_TYPE: |
800 | intrs = readl(&mem->other_ir) & readl(&mem->other_ies_ro); | 762 | intrs = readl(&mem->other_ir.raw) & readl(&mem->other_ies.raw); |
801 | 763 | ||
802 | /* Don't process any ATA interrupte */ | 764 | /* Don't process any ATA interrupte */ |
803 | intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR); | 765 | intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR); |
@@ -826,7 +788,7 @@ static int inline port_init(struct ioc4_port *port) | |||
826 | 788 | ||
827 | /* Wait until any pending bus activity for this port has ceased */ | 789 | /* Wait until any pending bus activity for this port has ceased */ |
828 | do | 790 | do |
829 | sio_cr = readl(&port->ip_mem->sio_cr); | 791 | sio_cr = readl(&port->ip_mem->sio_cr.raw); |
830 | while (!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE)); | 792 | while (!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE)); |
831 | 793 | ||
832 | /* Finish reset sequence */ | 794 | /* Finish reset sequence */ |
@@ -899,7 +861,7 @@ static int inline port_init(struct ioc4_port *port) | |||
899 | write_ireg(port->ip_ioc4_soft, hooks->intr_clear, | 861 | write_ireg(port->ip_ioc4_soft, hooks->intr_clear, |
900 | IOC4_W_IEC, IOC4_SIO_INTR_TYPE); | 862 | IOC4_W_IEC, IOC4_SIO_INTR_TYPE); |
901 | port->ip_ienb &= ~hooks->intr_clear; | 863 | port->ip_ienb &= ~hooks->intr_clear; |
902 | writel(hooks->intr_clear, &port->ip_mem->sio_ir); | 864 | writel(hooks->intr_clear, &port->ip_mem->sio_ir.raw); |
903 | return 0; | 865 | return 0; |
904 | } | 866 | } |
905 | 867 | ||
@@ -918,23 +880,23 @@ static void handle_dma_error_intr(void *arg, uint32_t other_ir) | |||
918 | spin_lock_irqsave(&port->ip_lock, flags); | 880 | spin_lock_irqsave(&port->ip_lock, flags); |
919 | 881 | ||
920 | /* ACK the interrupt */ | 882 | /* ACK the interrupt */ |
921 | writel(hooks->intr_dma_error, &port->ip_mem->other_ir); | 883 | writel(hooks->intr_dma_error, &port->ip_mem->other_ir.raw); |
922 | 884 | ||
923 | if (readl(&port->ip_mem->pci_err_addr_l) & IOC4_PCI_ERR_ADDR_VLD) { | 885 | if (readl(&port->ip_mem->pci_err_addr_l.raw) & IOC4_PCI_ERR_ADDR_VLD) { |
924 | printk(KERN_ERR | 886 | printk(KERN_ERR |
925 | "PCI error address is 0x%lx, " | 887 | "PCI error address is 0x%lx, " |
926 | "master is serial port %c %s\n", | 888 | "master is serial port %c %s\n", |
927 | (((uint64_t)readl(&port->ip_mem->pci_err_addr_h) | 889 | (((uint64_t)readl(&port->ip_mem->pci_err_addr_h) |
928 | << 32) | 890 | << 32) |
929 | | readl(&port->ip_mem->pci_err_addr_l)) | 891 | | readl(&port->ip_mem->pci_err_addr_l.raw)) |
930 | & IOC4_PCI_ERR_ADDR_ADDR_MSK, '1' + | 892 | & IOC4_PCI_ERR_ADDR_ADDR_MSK, '1' + |
931 | ((char)(readl(&port->ip_mem-> pci_err_addr_l) & | 893 | ((char)(readl(&port->ip_mem->pci_err_addr_l.raw) & |
932 | IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1), | 894 | IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1), |
933 | (readl(&port->ip_mem->pci_err_addr_l) | 895 | (readl(&port->ip_mem->pci_err_addr_l.raw) |
934 | & IOC4_PCI_ERR_ADDR_MST_TYP_MSK) | 896 | & IOC4_PCI_ERR_ADDR_MST_TYP_MSK) |
935 | ? "RX" : "TX"); | 897 | ? "RX" : "TX"); |
936 | 898 | ||
937 | if (readl(&port->ip_mem->pci_err_addr_l) | 899 | if (readl(&port->ip_mem->pci_err_addr_l.raw) |
938 | & IOC4_PCI_ERR_ADDR_MUL_ERR) { | 900 | & IOC4_PCI_ERR_ADDR_MUL_ERR) { |
939 | printk(KERN_ERR | 901 | printk(KERN_ERR |
940 | "Multiple errors occurred\n"); | 902 | "Multiple errors occurred\n"); |
@@ -1018,26 +980,26 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) | |||
1018 | "other_ies = 0x%x\n", | 980 | "other_ies = 0x%x\n", |
1019 | (intr_type == IOC4_SIO_INTR_TYPE) ? "sio" : | 981 | (intr_type == IOC4_SIO_INTR_TYPE) ? "sio" : |
1020 | "other", this_ir, | 982 | "other", this_ir, |
1021 | readl(&soft->is_ioc4_mem_addr->sio_ir), | 983 | readl(&soft->is_ioc4_misc_addr->sio_ir.raw), |
1022 | readl(&soft->is_ioc4_mem_addr->sio_ies_ro), | 984 | readl(&soft->is_ioc4_misc_addr->sio_ies.raw), |
1023 | readl(&soft->is_ioc4_mem_addr->other_ir), | 985 | readl(&soft->is_ioc4_misc_addr->other_ir.raw), |
1024 | readl(&soft->is_ioc4_mem_addr->other_ies_ro)); | 986 | readl(&soft->is_ioc4_misc_addr->other_ies.raw)); |
1025 | } | 987 | } |
1026 | } | 988 | } |
1027 | #ifdef DEBUG_INTERRUPTS | 989 | #ifdef DEBUG_INTERRUPTS |
1028 | { | 990 | { |
1029 | struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr; | 991 | struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr; |
1030 | spinlock_t *lp = &soft->is_ir_lock; | 992 | spinlock_t *lp = &soft->is_ir_lock; |
1031 | unsigned long flag; | 993 | unsigned long flag; |
1032 | 994 | ||
1033 | spin_lock_irqsave(&soft->is_ir_lock, flag); | 995 | spin_lock_irqsave(&soft->is_ir_lock, flag); |
1034 | printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies_ro 0x%x " | 996 | printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies 0x%x " |
1035 | "other_ir 0x%x other_ies_ro 0x%x mask 0x%x\n", | 997 | "other_ir 0x%x other_ies 0x%x mask 0x%x\n", |
1036 | __FUNCTION__, __LINE__, | 998 | __FUNCTION__, __LINE__, |
1037 | (void *)mem, readl(&mem->sio_ir), | 999 | (void *)mem, readl(&mem->sio_ir.raw), |
1038 | readl(&mem->sio_ies_ro), | 1000 | readl(&mem->sio_ies.raw), |
1039 | readl(&mem->other_ir), | 1001 | readl(&mem->other_ir.raw), |
1040 | readl(&mem->other_ies_ro), | 1002 | readl(&mem->other_ies.raw), |
1041 | IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR); | 1003 | IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR); |
1042 | spin_unlock_irqrestore(&soft->is_ir_lock, flag); | 1004 | spin_unlock_irqrestore(&soft->is_ir_lock, flag); |
1043 | } | 1005 | } |
@@ -1049,21 +1011,20 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) | |||
1049 | * ioc4_attach_local - Device initialization. | 1011 | * ioc4_attach_local - Device initialization. |
1050 | * Called at *_attach() time for each | 1012 | * Called at *_attach() time for each |
1051 | * IOC4 with serial ports in the system. | 1013 | * IOC4 with serial ports in the system. |
1052 | * @control: ioc4_control ptr | 1014 | * @idd: Master module data for this IOC4 |
1053 | * @pdev: PCI handle for this device | ||
1054 | * @soft: soft struct for this device | ||
1055 | * @ioc4: ioc4 mem space | ||
1056 | */ | 1015 | */ |
1057 | static int inline ioc4_attach_local(struct pci_dev *pdev, | 1016 | static int inline ioc4_attach_local(struct ioc4_driver_data *idd) |
1058 | struct ioc4_control *control, | ||
1059 | struct ioc4_soft *soft, void __iomem *ioc4_mem, | ||
1060 | void __iomem *ioc4_serial) | ||
1061 | { | 1017 | { |
1062 | struct ioc4_port *port; | 1018 | struct ioc4_port *port; |
1063 | struct ioc4_port *ports[IOC4_NUM_SERIAL_PORTS]; | 1019 | struct ioc4_port *ports[IOC4_NUM_SERIAL_PORTS]; |
1064 | int port_number; | 1020 | int port_number; |
1065 | uint16_t ioc4_revid_min = 62; | 1021 | uint16_t ioc4_revid_min = 62; |
1066 | uint16_t ioc4_revid; | 1022 | uint16_t ioc4_revid; |
1023 | struct pci_dev *pdev = idd->idd_pdev; | ||
1024 | struct ioc4_control* control = idd->idd_serial_data; | ||
1025 | struct ioc4_soft *soft = control->ic_soft; | ||
1026 | void __iomem *ioc4_misc = idd->idd_misc_regs; | ||
1027 | void __iomem *ioc4_serial = soft->is_ioc4_serial_addr; | ||
1067 | 1028 | ||
1068 | /* IOC4 firmware must be at least rev 62 */ | 1029 | /* IOC4 firmware must be at least rev 62 */ |
1069 | pci_read_config_word(pdev, PCI_COMMAND_SPECIAL, &ioc4_revid); | 1030 | pci_read_config_word(pdev, PCI_COMMAND_SPECIAL, &ioc4_revid); |
@@ -1076,7 +1037,7 @@ static int inline ioc4_attach_local(struct pci_dev *pdev, | |||
1076 | ioc4_revid, ioc4_revid_min); | 1037 | ioc4_revid, ioc4_revid_min); |
1077 | return -EPERM; | 1038 | return -EPERM; |
1078 | } | 1039 | } |
1079 | BUG_ON(ioc4_mem == NULL); | 1040 | BUG_ON(ioc4_misc == NULL); |
1080 | BUG_ON(ioc4_serial == NULL); | 1041 | BUG_ON(ioc4_serial == NULL); |
1081 | 1042 | ||
1082 | /* Create port structures for each port */ | 1043 | /* Create port structures for each port */ |
@@ -1100,10 +1061,18 @@ static int inline ioc4_attach_local(struct pci_dev *pdev, | |||
1100 | port->ip_ioc4_soft = soft; | 1061 | port->ip_ioc4_soft = soft; |
1101 | port->ip_pdev = pdev; | 1062 | port->ip_pdev = pdev; |
1102 | port->ip_ienb = 0; | 1063 | port->ip_ienb = 0; |
1103 | port->ip_pci_bus_speed = IOC4_SER_XIN_CLK; | 1064 | /* Use baud rate calculations based on detected PCI |
1065 | * bus speed. Simply test whether the PCI clock is | ||
1066 | * running closer to 66MHz or 33MHz. | ||
1067 | */ | ||
1068 | if (idd->count_period/IOC4_EXTINT_COUNT_DIVISOR < 20) { | ||
1069 | port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_66; | ||
1070 | } else { | ||
1071 | port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_33; | ||
1072 | } | ||
1104 | port->ip_baud = 9600; | 1073 | port->ip_baud = 9600; |
1105 | port->ip_control = control; | 1074 | port->ip_control = control; |
1106 | port->ip_mem = ioc4_mem; | 1075 | port->ip_mem = ioc4_misc; |
1107 | port->ip_serial = ioc4_serial; | 1076 | port->ip_serial = ioc4_serial; |
1108 | 1077 | ||
1109 | /* point to the right hook */ | 1078 | /* point to the right hook */ |
@@ -1604,14 +1573,12 @@ static int ioc4_set_proto(struct ioc4_port *port, enum sio_proto proto) | |||
1604 | switch (proto) { | 1573 | switch (proto) { |
1605 | case PROTO_RS232: | 1574 | case PROTO_RS232: |
1606 | /* Clear the appropriate GIO pin */ | 1575 | /* Clear the appropriate GIO pin */ |
1607 | writel(0, (&port->ip_mem->gppr_0 + | 1576 | writel(0, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw)); |
1608 | hooks->rs422_select_pin)); | ||
1609 | break; | 1577 | break; |
1610 | 1578 | ||
1611 | case PROTO_RS422: | 1579 | case PROTO_RS422: |
1612 | /* Set the appropriate GIO pin */ | 1580 | /* Set the appropriate GIO pin */ |
1613 | writel(1, (&port->ip_mem->gppr_0 + | 1581 | writel(1, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw)); |
1614 | hooks->rs422_select_pin)); | ||
1615 | break; | 1582 | break; |
1616 | 1583 | ||
1617 | default: | 1584 | default: |
@@ -1885,7 +1852,7 @@ static void handle_intr(void *arg, uint32_t sio_ir) | |||
1885 | if (sio_ir & hooks->intr_delta_dcd) { | 1852 | if (sio_ir & hooks->intr_delta_dcd) { |
1886 | /* ACK the interrupt */ | 1853 | /* ACK the interrupt */ |
1887 | writel(hooks->intr_delta_dcd, | 1854 | writel(hooks->intr_delta_dcd, |
1888 | &port->ip_mem->sio_ir); | 1855 | &port->ip_mem->sio_ir.raw); |
1889 | 1856 | ||
1890 | shadow = readl(&port->ip_serial_regs->shadow); | 1857 | shadow = readl(&port->ip_serial_regs->shadow); |
1891 | 1858 | ||
@@ -1907,7 +1874,7 @@ static void handle_intr(void *arg, uint32_t sio_ir) | |||
1907 | if (sio_ir & hooks->intr_delta_cts) { | 1874 | if (sio_ir & hooks->intr_delta_cts) { |
1908 | /* ACK the interrupt */ | 1875 | /* ACK the interrupt */ |
1909 | writel(hooks->intr_delta_cts, | 1876 | writel(hooks->intr_delta_cts, |
1910 | &port->ip_mem->sio_ir); | 1877 | &port->ip_mem->sio_ir.raw); |
1911 | 1878 | ||
1912 | shadow = readl(&port->ip_serial_regs->shadow); | 1879 | shadow = readl(&port->ip_serial_regs->shadow); |
1913 | 1880 | ||
@@ -1928,7 +1895,7 @@ static void handle_intr(void *arg, uint32_t sio_ir) | |||
1928 | if (sio_ir & hooks->intr_rx_timer) { | 1895 | if (sio_ir & hooks->intr_rx_timer) { |
1929 | /* ACK the interrupt */ | 1896 | /* ACK the interrupt */ |
1930 | writel(hooks->intr_rx_timer, | 1897 | writel(hooks->intr_rx_timer, |
1931 | &port->ip_mem->sio_ir); | 1898 | &port->ip_mem->sio_ir.raw); |
1932 | 1899 | ||
1933 | if ((port->ip_notify & N_DATA_READY) | 1900 | if ((port->ip_notify & N_DATA_READY) |
1934 | && (port->ip_port)) { | 1901 | && (port->ip_port)) { |
@@ -1974,7 +1941,7 @@ static void handle_intr(void *arg, uint32_t sio_ir) | |||
1974 | 1941 | ||
1975 | /* ACK the interrupt */ | 1942 | /* ACK the interrupt */ |
1976 | writel(hooks->intr_tx_explicit, | 1943 | writel(hooks->intr_tx_explicit, |
1977 | &port->ip_mem->sio_ir); | 1944 | &port->ip_mem->sio_ir.raw); |
1978 | 1945 | ||
1979 | if (port->ip_notify & N_OUTPUT_LOWAT) | 1946 | if (port->ip_notify & N_OUTPUT_LOWAT) |
1980 | ioc4_cb_output_lowat(port); | 1947 | ioc4_cb_output_lowat(port); |
@@ -2634,7 +2601,8 @@ ioc4_serial_core_attach(struct pci_dev *pdev) | |||
2634 | { | 2601 | { |
2635 | struct ioc4_port *port; | 2602 | struct ioc4_port *port; |
2636 | struct uart_port *the_port; | 2603 | struct uart_port *the_port; |
2637 | struct ioc4_control *control = pci_get_drvdata(pdev); | 2604 | struct ioc4_driver_data *idd = pci_get_drvdata(pdev); |
2605 | struct ioc4_control *control = idd->idd_serial_data; | ||
2638 | int ii; | 2606 | int ii; |
2639 | 2607 | ||
2640 | DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n", | 2608 | DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n", |
@@ -2680,55 +2648,29 @@ ioc4_serial_core_attach(struct pci_dev *pdev) | |||
2680 | 2648 | ||
2681 | /** | 2649 | /** |
2682 | * ioc4_serial_attach_one - register attach function | 2650 | * ioc4_serial_attach_one - register attach function |
2683 | * called per card found from ioc4_serial_detect as part | 2651 | * called per card found from IOC4 master module. |
2684 | * of module_init(). | 2652 | * @idd: Master module data for this IOC4 |
2685 | * @pdev: handle for this card | ||
2686 | * @pci_id: pci id for this card | ||
2687 | */ | 2653 | */ |
2688 | int | 2654 | int |
2689 | ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id) | 2655 | ioc4_serial_attach_one(struct ioc4_driver_data *idd) |
2690 | { | 2656 | { |
2691 | struct ioc4_mem __iomem *mem; | 2657 | unsigned long tmp_addr1; |
2692 | unsigned long tmp_addr, tmp_addr1; | ||
2693 | struct ioc4_serial __iomem *serial; | 2658 | struct ioc4_serial __iomem *serial; |
2694 | struct ioc4_soft *soft; | 2659 | struct ioc4_soft *soft; |
2695 | struct ioc4_control *control; | 2660 | struct ioc4_control *control; |
2696 | int tmp, ret = 0; | 2661 | int ret = 0; |
2697 | 2662 | ||
2698 | 2663 | ||
2699 | DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, pdev, pci_id)); | 2664 | DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev, idd->idd_pci_id)); |
2700 | |||
2701 | /* Map in the ioc4 memory */ | ||
2702 | tmp_addr = pci_resource_start(pdev, 0); | ||
2703 | if (!tmp_addr) { | ||
2704 | printk(KERN_WARNING | ||
2705 | "ioc4 (%p) : unable to get PIO mapping for " | ||
2706 | "MEM space\n", (void *)pdev); | ||
2707 | return -ENODEV; | ||
2708 | } | ||
2709 | if (!request_region(tmp_addr, sizeof(struct ioc4_mem), "sioc4_mem")) { | ||
2710 | printk(KERN_ALERT | ||
2711 | "ioc4 (%p): unable to get request region for " | ||
2712 | "MEM space\n", (void *)pdev); | ||
2713 | return -ENODEV; | ||
2714 | } | ||
2715 | mem = ioremap(tmp_addr, sizeof(struct ioc4_mem)); | ||
2716 | if (!mem) { | ||
2717 | printk(KERN_WARNING | ||
2718 | "ioc4 (%p) : unable to remap ioc4 memory\n", | ||
2719 | (void *)pdev); | ||
2720 | ret = -ENODEV; | ||
2721 | goto out1; | ||
2722 | } | ||
2723 | 2665 | ||
2724 | /* request serial registers */ | 2666 | /* request serial registers */ |
2725 | tmp_addr1 = pci_resource_start(pdev, 0) + IOC4_SERIAL_OFFSET; | 2667 | tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET; |
2726 | 2668 | ||
2727 | if (!request_region(tmp_addr1, sizeof(struct ioc4_serial), | 2669 | if (!request_region(tmp_addr1, sizeof(struct ioc4_serial), |
2728 | "sioc4_uart")) { | 2670 | "sioc4_uart")) { |
2729 | printk(KERN_WARNING | 2671 | printk(KERN_WARNING |
2730 | "ioc4 (%p): unable to get request region for " | 2672 | "ioc4 (%p): unable to get request region for " |
2731 | "uart space\n", (void *)pdev); | 2673 | "uart space\n", (void *)idd->idd_pdev); |
2732 | ret = -ENODEV; | 2674 | ret = -ENODEV; |
2733 | goto out1; | 2675 | goto out1; |
2734 | } | 2676 | } |
@@ -2736,12 +2678,12 @@ ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id) | |||
2736 | if (!serial) { | 2678 | if (!serial) { |
2737 | printk(KERN_WARNING | 2679 | printk(KERN_WARNING |
2738 | "ioc4 (%p) : unable to remap ioc4 serial register\n", | 2680 | "ioc4 (%p) : unable to remap ioc4 serial register\n", |
2739 | (void *)pdev); | 2681 | (void *)idd->idd_pdev); |
2740 | ret = -ENODEV; | 2682 | ret = -ENODEV; |
2741 | goto out2; | 2683 | goto out2; |
2742 | } | 2684 | } |
2743 | DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n", | 2685 | DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n", |
2744 | __FUNCTION__, (void *)mem, (void *)serial)); | 2686 | __FUNCTION__, (void *)idd->idd_misc_regs, (void *)serial)); |
2745 | 2687 | ||
2746 | /* Get memory for the new card */ | 2688 | /* Get memory for the new card */ |
2747 | control = kmalloc(sizeof(struct ioc4_control) * IOC4_NUM_SERIAL_PORTS, | 2689 | control = kmalloc(sizeof(struct ioc4_control) * IOC4_NUM_SERIAL_PORTS, |
@@ -2754,59 +2696,56 @@ ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id) | |||
2754 | goto out2; | 2696 | goto out2; |
2755 | } | 2697 | } |
2756 | memset(control, 0, sizeof(struct ioc4_control)); | 2698 | memset(control, 0, sizeof(struct ioc4_control)); |
2757 | pci_set_drvdata(pdev, control); | 2699 | idd->idd_serial_data = control; |
2758 | 2700 | ||
2759 | /* Allocate the soft structure */ | 2701 | /* Allocate the soft structure */ |
2760 | soft = kmalloc(sizeof(struct ioc4_soft), GFP_KERNEL); | 2702 | soft = kmalloc(sizeof(struct ioc4_soft), GFP_KERNEL); |
2761 | if (!soft) { | 2703 | if (!soft) { |
2762 | printk(KERN_WARNING | 2704 | printk(KERN_WARNING |
2763 | "ioc4 (%p): unable to get memory for the soft struct\n", | 2705 | "ioc4 (%p): unable to get memory for the soft struct\n", |
2764 | (void *)pdev); | 2706 | (void *)idd->idd_pdev); |
2765 | ret = -ENOMEM; | 2707 | ret = -ENOMEM; |
2766 | goto out3; | 2708 | goto out3; |
2767 | } | 2709 | } |
2768 | memset(soft, 0, sizeof(struct ioc4_soft)); | 2710 | memset(soft, 0, sizeof(struct ioc4_soft)); |
2769 | 2711 | ||
2770 | spin_lock_init(&soft->is_ir_lock); | 2712 | spin_lock_init(&soft->is_ir_lock); |
2771 | soft->is_ioc4_mem_addr = mem; | 2713 | soft->is_ioc4_misc_addr = idd->idd_misc_regs; |
2772 | soft->is_ioc4_serial_addr = serial; | 2714 | soft->is_ioc4_serial_addr = serial; |
2773 | 2715 | ||
2774 | /* Init the IOC4 */ | 2716 | /* Init the IOC4 */ |
2775 | pci_read_config_dword(pdev, PCI_COMMAND, &tmp); | 2717 | writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT, |
2776 | pci_write_config_dword(pdev, PCI_COMMAND, | 2718 | &idd->idd_misc_regs->sio_cr.raw); |
2777 | tmp | PCI_COMMAND_PARITY | PCI_COMMAND_SERR); | ||
2778 | |||
2779 | writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT, &mem->sio_cr); | ||
2780 | 2719 | ||
2781 | /* Enable serial port mode select generic PIO pins as outputs */ | 2720 | /* Enable serial port mode select generic PIO pins as outputs */ |
2782 | writel(IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL | 2721 | writel(IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL |
2783 | | IOC4_GPCR_UART2_MODESEL | IOC4_GPCR_UART3_MODESEL, | 2722 | | IOC4_GPCR_UART2_MODESEL | IOC4_GPCR_UART3_MODESEL, |
2784 | &mem->gpcr_s); | 2723 | &idd->idd_misc_regs->gpcr_s.raw); |
2785 | 2724 | ||
2786 | /* Clear and disable all interrupts */ | 2725 | /* Clear and disable all serial interrupts */ |
2787 | write_ireg(soft, ~0, IOC4_W_IEC, IOC4_SIO_INTR_TYPE); | 2726 | write_ireg(soft, ~0, IOC4_W_IEC, IOC4_SIO_INTR_TYPE); |
2788 | writel(~0, &mem->sio_ir); | 2727 | writel(~0, &idd->idd_misc_regs->sio_ir.raw); |
2789 | write_ireg(soft, ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR), | 2728 | write_ireg(soft, IOC4_OTHER_IR_SER_MEMERR, IOC4_W_IEC, |
2790 | IOC4_W_IEC, IOC4_OTHER_INTR_TYPE); | 2729 | IOC4_OTHER_INTR_TYPE); |
2791 | writel(~(IOC4_OTHER_IR_ATA_MEMERR | IOC4_OTHER_IR_ATA_MEMERR), | 2730 | writel(IOC4_OTHER_IR_SER_MEMERR, &idd->idd_misc_regs->other_ir.raw); |
2792 | &mem->other_ir); | ||
2793 | control->ic_soft = soft; | 2731 | control->ic_soft = soft; |
2794 | if (!request_irq(pdev->irq, ioc4_intr, SA_SHIRQ, | 2732 | |
2733 | /* Hook up interrupt handler */ | ||
2734 | if (!request_irq(idd->idd_pdev->irq, ioc4_intr, SA_SHIRQ, | ||
2795 | "sgi-ioc4serial", (void *)soft)) { | 2735 | "sgi-ioc4serial", (void *)soft)) { |
2796 | control->ic_irq = pdev->irq; | 2736 | control->ic_irq = idd->idd_pdev->irq; |
2797 | } else { | 2737 | } else { |
2798 | printk(KERN_WARNING | 2738 | printk(KERN_WARNING |
2799 | "%s : request_irq fails for IRQ 0x%x\n ", | 2739 | "%s : request_irq fails for IRQ 0x%x\n ", |
2800 | __FUNCTION__, pdev->irq); | 2740 | __FUNCTION__, idd->idd_pdev->irq); |
2801 | } | 2741 | } |
2802 | if ((ret = ioc4_attach_local(pdev, control, soft, | 2742 | ret = ioc4_attach_local(idd); |
2803 | soft->is_ioc4_mem_addr, | 2743 | if (ret) |
2804 | soft->is_ioc4_serial_addr))) | ||
2805 | goto out4; | 2744 | goto out4; |
2806 | 2745 | ||
2807 | /* register port with the serial core */ | 2746 | /* register port with the serial core */ |
2808 | 2747 | ||
2809 | if ((ret = ioc4_serial_core_attach(pdev))) | 2748 | if ((ret = ioc4_serial_core_attach(idd->idd_pdev))) |
2810 | goto out4; | 2749 | goto out4; |
2811 | 2750 | ||
2812 | return ret; | 2751 | return ret; |
@@ -2819,7 +2758,6 @@ out3: | |||
2819 | out2: | 2758 | out2: |
2820 | release_region(tmp_addr1, sizeof(struct ioc4_serial)); | 2759 | release_region(tmp_addr1, sizeof(struct ioc4_serial)); |
2821 | out1: | 2760 | out1: |
2822 | release_region(tmp_addr, sizeof(struct ioc4_mem)); | ||
2823 | 2761 | ||
2824 | return ret; | 2762 | return ret; |
2825 | } | 2763 | } |
@@ -2828,11 +2766,10 @@ out1: | |||
2828 | /** | 2766 | /** |
2829 | * ioc4_serial_remove_one - detach function | 2767 | * ioc4_serial_remove_one - detach function |
2830 | * | 2768 | * |
2831 | * @pdev: handle for this card | 2769 | * @idd: IOC4 master module data for this IOC4 |
2832 | */ | 2770 | */ |
2833 | 2771 | ||
2834 | #if 0 | 2772 | int ioc4_serial_remove_one(struct ioc4_driver_data *idd) |
2835 | void ioc4_serial_remove_one(struct pci_dev *pdev) | ||
2836 | { | 2773 | { |
2837 | int ii; | 2774 | int ii; |
2838 | struct ioc4_control *control; | 2775 | struct ioc4_control *control; |
@@ -2840,7 +2777,7 @@ void ioc4_serial_remove_one(struct pci_dev *pdev) | |||
2840 | struct ioc4_port *port; | 2777 | struct ioc4_port *port; |
2841 | struct ioc4_soft *soft; | 2778 | struct ioc4_soft *soft; |
2842 | 2779 | ||
2843 | control = pci_get_drvdata(pdev); | 2780 | control = idd->idd_serial_data; |
2844 | 2781 | ||
2845 | for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) { | 2782 | for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) { |
2846 | the_port = &control->ic_port[ii].icp_uart_port; | 2783 | the_port = &control->ic_port[ii].icp_uart_port; |
@@ -2867,10 +2804,17 @@ void ioc4_serial_remove_one(struct pci_dev *pdev) | |||
2867 | kfree(soft); | 2804 | kfree(soft); |
2868 | } | 2805 | } |
2869 | kfree(control); | 2806 | kfree(control); |
2870 | pci_set_drvdata(pdev, NULL); | 2807 | idd->idd_serial_data = NULL; |
2871 | uart_unregister_driver(&ioc4_uart); | 2808 | |
2809 | return 0; | ||
2872 | } | 2810 | } |
2873 | #endif | 2811 | |
2812 | static struct ioc4_submodule ioc4_serial_submodule = { | ||
2813 | .is_name = "IOC4_serial", | ||
2814 | .is_owner = THIS_MODULE, | ||
2815 | .is_probe = ioc4_serial_attach_one, | ||
2816 | .is_remove = ioc4_serial_remove_one, | ||
2817 | }; | ||
2874 | 2818 | ||
2875 | /** | 2819 | /** |
2876 | * ioc4_serial_init - module init | 2820 | * ioc4_serial_init - module init |
@@ -2886,12 +2830,20 @@ int ioc4_serial_init(void) | |||
2886 | __FUNCTION__); | 2830 | __FUNCTION__); |
2887 | return ret; | 2831 | return ret; |
2888 | } | 2832 | } |
2889 | return 0; | 2833 | |
2834 | /* register with IOC4 main module */ | ||
2835 | return ioc4_register_submodule(&ioc4_serial_submodule); | ||
2836 | } | ||
2837 | |||
2838 | static void __devexit ioc4_serial_exit(void) | ||
2839 | { | ||
2840 | ioc4_unregister_submodule(&ioc4_serial_submodule); | ||
2841 | uart_unregister_driver(&ioc4_uart); | ||
2890 | } | 2842 | } |
2891 | 2843 | ||
2844 | module_init(ioc4_serial_init); | ||
2845 | module_exit(ioc4_serial_exit); | ||
2846 | |||
2892 | MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>"); | 2847 | MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>"); |
2893 | MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC4 Base-IO Card"); | 2848 | MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC4 Base-IO Card"); |
2894 | MODULE_LICENSE("GPL"); | 2849 | MODULE_LICENSE("GPL"); |
2895 | |||
2896 | EXPORT_SYMBOL(ioc4_serial_init); | ||
2897 | EXPORT_SYMBOL(ioc4_serial_attach_one); | ||