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); | ||
