diff options
Diffstat (limited to 'drivers/char/cyclades.c')
-rw-r--r-- | drivers/char/cyclades.c | 623 |
1 files changed, 318 insertions, 305 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index a49232746438..e5de0409b37c 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -4698,7 +4698,8 @@ static int __init cy_detect_isa(void) | |||
4698 | #endif /* CONFIG_ISA */ | 4698 | #endif /* CONFIG_ISA */ |
4699 | } /* cy_detect_isa */ | 4699 | } /* cy_detect_isa */ |
4700 | 4700 | ||
4701 | static void plx_init(void __iomem * addr, __u32 initctl) | 4701 | #ifdef CONFIG_PCI |
4702 | static void __devinit plx_init(void __iomem * addr, __u32 initctl) | ||
4702 | { | 4703 | { |
4703 | /* Reset PLX */ | 4704 | /* Reset PLX */ |
4704 | cy_writel(addr + initctl, readl(addr + initctl) | 0x40000000); | 4705 | cy_writel(addr + initctl, readl(addr + initctl) | 0x40000000); |
@@ -4800,355 +4801,367 @@ static int __devinit cy_init_Ze(unsigned long cy_pci_phys0, | |||
4800 | return 0; | 4801 | return 0; |
4801 | } | 4802 | } |
4802 | 4803 | ||
4803 | /* | 4804 | static int __devinit cy_pci_probe(struct pci_dev *pdev, |
4804 | * --------------------------------------------------------------------- | 4805 | const struct pci_device_id *ent) |
4805 | * cy_detect_pci() - Test PCI bus presence and Cyclom-Ye/PCI. | ||
4806 | * sets global variables and return the number of PCI boards found. | ||
4807 | * --------------------------------------------------------------------- | ||
4808 | */ | ||
4809 | static int __init cy_detect_pci(void) | ||
4810 | { | 4806 | { |
4811 | #ifdef CONFIG_PCI | ||
4812 | |||
4813 | struct pci_dev *pdev = NULL; | ||
4814 | unsigned char cyy_rev_id; | 4807 | unsigned char cyy_rev_id; |
4815 | unsigned char cy_pci_irq = 0; | 4808 | unsigned char cy_pci_irq; |
4816 | __u32 cy_pci_phys0, cy_pci_phys2; | 4809 | __u32 cy_pci_phys0, cy_pci_phys2, mailbox; |
4817 | void __iomem *cy_pci_addr0, *cy_pci_addr2; | 4810 | void __iomem *cy_pci_addr0, *cy_pci_addr2; |
4818 | unsigned short i, j, cy_pci_nchan, plx_ver; | 4811 | unsigned int device_id; |
4819 | unsigned short device_id, dev_index = 0; | 4812 | unsigned short j, cy_pci_nchan, plx_ver; |
4820 | __u32 mailbox; | ||
4821 | int retval; | 4813 | int retval; |
4822 | 4814 | ||
4823 | for (i = 0; i < NR_CARDS; i++) { | 4815 | retval = pci_enable_device(pdev); |
4824 | /* look for a Cyclades card by vendor and device id */ | 4816 | if (retval) { |
4825 | while ((device_id = cy_pci_dev_id[dev_index].device) != 0) { | 4817 | dev_err(&pdev->dev, "cannot enable device\n"); |
4826 | if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES, | 4818 | return retval; |
4827 | device_id, pdev)) == NULL) { | 4819 | } |
4828 | dev_index++; /* try next device id */ | ||
4829 | } else { | ||
4830 | break; /* found a board */ | ||
4831 | } | ||
4832 | } | ||
4833 | 4820 | ||
4834 | if (device_id == 0) | 4821 | /* read PCI configuration area */ |
4835 | break; | 4822 | cy_pci_irq = pdev->irq; |
4823 | cy_pci_phys0 = pci_resource_start(pdev, 0); | ||
4824 | cy_pci_phys2 = pci_resource_start(pdev, 2); | ||
4825 | pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id); | ||
4836 | 4826 | ||
4837 | if (pci_enable_device(pdev)) | 4827 | device_id = pdev->device & ~PCI_DEVICE_ID_MASK; |
4838 | continue; | ||
4839 | 4828 | ||
4840 | /* read PCI configuration area */ | 4829 | if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || |
4841 | cy_pci_irq = pdev->irq; | 4830 | device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { |
4842 | cy_pci_phys0 = pci_resource_start(pdev, 0); | 4831 | #ifdef CY_PCI_DEBUG |
4843 | cy_pci_phys2 = pci_resource_start(pdev, 2); | 4832 | printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", |
4844 | pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id); | 4833 | pdev->bus->number, pdev->devfn); |
4834 | printk("rev_id=%d) IRQ%d\n", | ||
4835 | cyy_rev_id, (int)cy_pci_irq); | ||
4836 | printk("Cyclom-Y/PCI:found winaddr=0x%lx " | ||
4837 | "ctladdr=0x%lx\n", | ||
4838 | (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); | ||
4839 | #endif | ||
4845 | 4840 | ||
4846 | device_id &= ~PCI_DEVICE_ID_MASK; | 4841 | if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { |
4842 | printk(" Warning: PCI I/O bit incorrectly " | ||
4843 | "set. Ignoring it...\n"); | ||
4844 | pdev->resource[2].flags &= ~IORESOURCE_IO; | ||
4845 | } | ||
4847 | 4846 | ||
4848 | if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || | 4847 | /* Although we don't use this I/O region, we should |
4849 | device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { | 4848 | request it from the kernel anyway, to avoid problems |
4850 | #ifdef CY_PCI_DEBUG | 4849 | with other drivers accessing it. */ |
4850 | retval = pci_request_regions(pdev, "Cyclom-Y"); | ||
4851 | if (retval) { | ||
4852 | printk(KERN_ERR "cyclades: failed to reserve " | ||
4853 | "PCI resources\n"); | ||
4854 | return retval; | ||
4855 | } | ||
4856 | #if defined(__alpha__) | ||
4857 | if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ | ||
4851 | printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", | 4858 | printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", |
4852 | pdev->bus->number, pdev->devfn); | 4859 | pdev->bus->number, pdev->devfn); |
4853 | printk("rev_id=%d) IRQ%d\n", | 4860 | printk("rev_id=%d) IRQ%d\n", |
4854 | cyy_rev_id, (int)cy_pci_irq); | 4861 | cyy_rev_id, (int)cy_pci_irq); |
4855 | printk("Cyclom-Y/PCI:found winaddr=0x%lx " | 4862 | printk("Cyclom-Y/PCI:found winaddr=0x%lx " |
4856 | "ctladdr=0x%lx\n", | 4863 | "ctladdr=0x%lx\n", |
4857 | (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); | 4864 | (ulong)cy_pci_phys2, |
4858 | #endif | 4865 | (ulong)cy_pci_phys0); |
4859 | 4866 | printk("Cyclom-Y/PCI not supported for low " | |
4860 | if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { | 4867 | "addresses in Alpha systems.\n"); |
4861 | printk(" Warning: PCI I/O bit incorrectly " | 4868 | return -EIO; |
4862 | "set. Ignoring it...\n"); | 4869 | } |
4863 | pdev->resource[2].flags &= ~IORESOURCE_IO; | ||
4864 | } | ||
4865 | |||
4866 | /* Although we don't use this I/O region, we should | ||
4867 | request it from the kernel anyway, to avoid problems | ||
4868 | with other drivers accessing it. */ | ||
4869 | if (pci_request_regions(pdev, "Cyclom-Y") != 0) { | ||
4870 | printk(KERN_ERR "cyclades: failed to reserve " | ||
4871 | "PCI resources\n"); | ||
4872 | continue; | ||
4873 | } | ||
4874 | #if defined(__alpha__) | ||
4875 | if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ | ||
4876 | printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", | ||
4877 | pdev->bus->number, pdev->devfn); | ||
4878 | printk("rev_id=%d) IRQ%d\n", | ||
4879 | cyy_rev_id, (int)cy_pci_irq); | ||
4880 | printk("Cyclom-Y/PCI:found winaddr=0x%lx " | ||
4881 | "ctladdr=0x%lx\n", | ||
4882 | (ulong)cy_pci_phys2, | ||
4883 | (ulong)cy_pci_phys0); | ||
4884 | printk("Cyclom-Y/PCI not supported for low " | ||
4885 | "addresses in Alpha systems.\n"); | ||
4886 | i--; | ||
4887 | continue; | ||
4888 | } | ||
4889 | #endif | 4870 | #endif |
4890 | cy_pci_addr0 = pci_iomap(pdev, 0, CyPCI_Yctl); | 4871 | cy_pci_addr0 = pci_iomap(pdev, 0, CyPCI_Yctl); |
4891 | cy_pci_addr2 = pci_iomap(pdev, 2, CyPCI_Ywin); | 4872 | cy_pci_addr2 = pci_iomap(pdev, 2, CyPCI_Ywin); |
4892 | 4873 | ||
4893 | #ifdef CY_PCI_DEBUG | 4874 | #ifdef CY_PCI_DEBUG |
4894 | printk("Cyclom-Y/PCI: relocate winaddr=0x%lx " | 4875 | printk("Cyclom-Y/PCI: relocate winaddr=0x%lx " |
4895 | "ctladdr=0x%lx\n", | 4876 | "ctladdr=0x%lx\n", |
4896 | (u_long)cy_pci_addr2, (u_long)cy_pci_addr0); | 4877 | (u_long)cy_pci_addr2, (u_long)cy_pci_addr0); |
4897 | #endif | 4878 | #endif |
4898 | cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP * | 4879 | cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP * |
4899 | cyy_init_card(cy_pci_addr2, 1)); | 4880 | cyy_init_card(cy_pci_addr2, 1)); |
4900 | if (cy_pci_nchan == 0) { | 4881 | if (cy_pci_nchan == 0) { |
4901 | printk("Cyclom-Y PCI host card with "); | 4882 | printk("Cyclom-Y PCI host card with "); |
4902 | printk("no Serial-Modules at 0x%lx.\n", | 4883 | printk("no Serial-Modules at 0x%lx.\n", |
4903 | (ulong) cy_pci_phys2); | 4884 | (ulong) cy_pci_phys2); |
4904 | i--; | 4885 | return -EIO; |
4905 | continue; | 4886 | } |
4906 | } | 4887 | if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { |
4907 | if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { | 4888 | printk("Cyclom-Y/PCI found at 0x%lx ", |
4908 | printk("Cyclom-Y/PCI found at 0x%lx ", | 4889 | (ulong) cy_pci_phys2); |
4909 | (ulong) cy_pci_phys2); | 4890 | printk("but no channels are available.\n"); |
4910 | printk("but no channels are available.\n"); | 4891 | printk("Change NR_PORTS in cyclades.c and " |
4911 | printk("Change NR_PORTS in cyclades.c and " | 4892 | "recompile kernel.\n"); |
4912 | "recompile kernel.\n"); | 4893 | return -EIO; |
4913 | return i; | 4894 | } |
4914 | } | 4895 | /* fill the next cy_card structure available */ |
4915 | /* fill the next cy_card structure available */ | 4896 | for (j = 0; j < NR_CARDS; j++) { |
4916 | for (j = 0; j < NR_CARDS; j++) { | 4897 | if (cy_card[j].base_addr == 0) |
4917 | if (cy_card[j].base_addr == 0) | ||
4918 | break; | ||
4919 | } | ||
4920 | if (j == NR_CARDS) { /* no more cy_cards available */ | ||
4921 | printk("Cyclom-Y/PCI found at 0x%lx ", | ||
4922 | (ulong) cy_pci_phys2); | ||
4923 | printk("but no more cards can be used.\n"); | ||
4924 | printk("Change NR_CARDS in cyclades.c and " | ||
4925 | "recompile kernel.\n"); | ||
4926 | return i; | ||
4927 | } | ||
4928 | |||
4929 | /* allocate IRQ */ | ||
4930 | if (request_irq(cy_pci_irq, cyy_interrupt, | ||
4931 | IRQF_SHARED, "Cyclom-Y", &cy_card[j])) { | ||
4932 | printk("Cyclom-Y/PCI found at 0x%lx ", | ||
4933 | (ulong) cy_pci_phys2); | ||
4934 | printk("but could not allocate IRQ%d.\n", | ||
4935 | cy_pci_irq); | ||
4936 | return i; | ||
4937 | } | ||
4938 | |||
4939 | /* set cy_card */ | ||
4940 | cy_card[j].base_phys = (ulong) cy_pci_phys2; | ||
4941 | cy_card[j].ctl_phys = (ulong) cy_pci_phys0; | ||
4942 | cy_card[j].base_addr = cy_pci_addr2; | ||
4943 | cy_card[j].ctl_addr = cy_pci_addr0; | ||
4944 | cy_card[j].irq = (int)cy_pci_irq; | ||
4945 | cy_card[j].bus_index = 1; | ||
4946 | cy_card[j].first_line = cy_next_channel; | ||
4947 | cy_card[j].num_chips = cy_pci_nchan / 4; | ||
4948 | cy_card[j].pdev = pdev; | ||
4949 | pci_set_drvdata(pdev, &cy_card[j]); | ||
4950 | |||
4951 | /* enable interrupts in the PCI interface */ | ||
4952 | plx_ver = readb(cy_pci_addr2 + CyPLX_VER) & 0x0f; | ||
4953 | switch (plx_ver) { | ||
4954 | case PLX_9050: | ||
4955 | |||
4956 | cy_writeb(cy_pci_addr0 + 0x4c, 0x43); | ||
4957 | break; | 4898 | break; |
4899 | } | ||
4900 | if (j == NR_CARDS) { /* no more cy_cards available */ | ||
4901 | printk("Cyclom-Y/PCI found at 0x%lx ", | ||
4902 | (ulong) cy_pci_phys2); | ||
4903 | printk("but no more cards can be used.\n"); | ||
4904 | printk("Change NR_CARDS in cyclades.c and " | ||
4905 | "recompile kernel.\n"); | ||
4906 | return -EIO; | ||
4907 | } | ||
4958 | 4908 | ||
4959 | case PLX_9060: | 4909 | /* allocate IRQ */ |
4960 | case PLX_9080: | 4910 | retval = request_irq(cy_pci_irq, cyy_interrupt, |
4961 | default: /* Old boards, use PLX_9060 */ | 4911 | IRQF_SHARED, "Cyclom-Y", &cy_card[j]); |
4962 | 4912 | if (retval) { | |
4963 | plx_init(cy_pci_addr0, 0x6c); | 4913 | printk("Cyclom-Y/PCI found at 0x%lx ", |
4964 | /* For some yet unknown reason, once the PLX9060 reloads | 4914 | (ulong) cy_pci_phys2); |
4965 | the EEPROM, the IRQ is lost and, thus, we have to | 4915 | printk("but could not allocate IRQ%d.\n", |
4966 | re-write it to the PCI config. registers. | 4916 | cy_pci_irq); |
4967 | This will remain here until we find a permanent | 4917 | return retval; |
4968 | fix. */ | 4918 | } |
4969 | pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, | ||
4970 | cy_pci_irq); | ||
4971 | |||
4972 | cy_writew(cy_pci_addr0 + 0x68, | ||
4973 | readw(cy_pci_addr0 + 0x68) | 0x0900); | ||
4974 | break; | ||
4975 | } | ||
4976 | 4919 | ||
4977 | /* print message */ | 4920 | /* set cy_card */ |
4978 | printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", | 4921 | cy_card[j].base_phys = (ulong) cy_pci_phys2; |
4979 | j + 1, (ulong)cy_pci_phys2, | 4922 | cy_card[j].ctl_phys = (ulong) cy_pci_phys0; |
4980 | (ulong) (cy_pci_phys2 + CyPCI_Ywin - 1), | 4923 | cy_card[j].base_addr = cy_pci_addr2; |
4981 | (int)cy_pci_irq); | 4924 | cy_card[j].ctl_addr = cy_pci_addr0; |
4982 | printk("%d channels starting from port %d.\n", | 4925 | cy_card[j].irq = (int)cy_pci_irq; |
4983 | cy_pci_nchan, cy_next_channel); | 4926 | cy_card[j].bus_index = 1; |
4927 | cy_card[j].first_line = cy_next_channel; | ||
4928 | cy_card[j].num_chips = cy_pci_nchan / 4; | ||
4929 | cy_card[j].pdev = pdev; | ||
4930 | pci_set_drvdata(pdev, &cy_card[j]); | ||
4984 | 4931 | ||
4985 | cy_next_channel += cy_pci_nchan; | 4932 | /* enable interrupts in the PCI interface */ |
4986 | } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) { | 4933 | plx_ver = readb(cy_pci_addr2 + CyPLX_VER) & 0x0f; |
4987 | /* print message */ | 4934 | switch (plx_ver) { |
4988 | printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", | 4935 | case PLX_9050: |
4989 | pdev->bus->number, pdev->devfn); | 4936 | |
4990 | printk("rev_id=%d) IRQ%d\n", | 4937 | cy_writeb(cy_pci_addr0 + 0x4c, 0x43); |
4991 | cyy_rev_id, (int)cy_pci_irq); | ||
4992 | printk("Cyclades-Z/PCI: found winaddr=0x%lx " | ||
4993 | "ctladdr=0x%lx\n", | ||
4994 | (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); | ||
4995 | printk("Cyclades-Z/PCI not supported for low " | ||
4996 | "addresses\n"); | ||
4997 | break; | 4938 | break; |
4998 | } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { | ||
4999 | #ifdef CY_PCI_DEBUG | ||
5000 | printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", | ||
5001 | pdev->bus->number, pdev->devfn); | ||
5002 | printk("rev_id=%d) IRQ%d\n", | ||
5003 | cyy_rev_id, (int)cy_pci_irq); | ||
5004 | printk("Cyclades-Z/PCI: found winaddr=0x%lx " | ||
5005 | "ctladdr=0x%lx\n", | ||
5006 | (ulong) cy_pci_phys2, (ulong) cy_pci_phys0); | ||
5007 | #endif | ||
5008 | cy_pci_addr0 = pci_iomap(pdev, 0, CyPCI_Zctl); | ||
5009 | 4939 | ||
5010 | /* Disable interrupts on the PLX before resetting it */ | 4940 | case PLX_9060: |
5011 | cy_writew(cy_pci_addr0 + 0x68, | 4941 | case PLX_9080: |
5012 | readw(cy_pci_addr0 + 0x68) & ~0x0900); | 4942 | default: /* Old boards, use PLX_9060 */ |
5013 | 4943 | ||
5014 | plx_init(cy_pci_addr0, 0x6c); | 4944 | plx_init(cy_pci_addr0, 0x6c); |
5015 | /* For some yet unknown reason, once the PLX9060 reloads | 4945 | /* For some yet unknown reason, once the PLX9060 reloads |
5016 | the EEPROM, the IRQ is lost and, thus, we have to | 4946 | the EEPROM, the IRQ is lost and, thus, we have to |
5017 | re-write it to the PCI config. registers. | 4947 | re-write it to the PCI config. registers. |
5018 | This will remain here until we find a permanent | 4948 | This will remain here until we find a permanent |
5019 | fix. */ | 4949 | fix. */ |
5020 | pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, | 4950 | pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, |
5021 | cy_pci_irq); | 4951 | cy_pci_irq); |
5022 | 4952 | ||
5023 | mailbox = (__u32)readl(&((struct RUNTIME_9060 __iomem *) | 4953 | cy_writew(cy_pci_addr0 + 0x68, |
5024 | cy_pci_addr0)->mail_box_0); | 4954 | readw(cy_pci_addr0 + 0x68) | 0x0900); |
4955 | break; | ||
4956 | } | ||
5025 | 4957 | ||
5026 | if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { | 4958 | /* print message */ |
5027 | printk(" Warning: PCI I/O bit incorrectly " | 4959 | printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", |
5028 | "set. Ignoring it...\n"); | 4960 | j + 1, (ulong)cy_pci_phys2, |
5029 | pdev->resource[2].flags &= ~IORESOURCE_IO; | 4961 | (ulong) (cy_pci_phys2 + CyPCI_Ywin - 1), |
5030 | } | 4962 | (int)cy_pci_irq); |
4963 | printk("%d channels starting from port %d.\n", | ||
4964 | cy_pci_nchan, cy_next_channel); | ||
5031 | 4965 | ||
5032 | /* Although we don't use this I/O region, we should | 4966 | cy_next_channel += cy_pci_nchan; |
5033 | request it from the kernel anyway, to avoid problems | 4967 | } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) { |
5034 | with other drivers accessing it. */ | 4968 | /* print message */ |
5035 | if (pci_request_regions(pdev, "Cyclades-Z") != 0) { | 4969 | printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", |
5036 | printk(KERN_ERR "cyclades: failed to reserve " | 4970 | pdev->bus->number, pdev->devfn); |
5037 | "PCI resources\n"); | 4971 | printk("rev_id=%d) IRQ%d\n", |
5038 | continue; | 4972 | cyy_rev_id, (int)cy_pci_irq); |
5039 | } | 4973 | printk("Cyclades-Z/PCI: found winaddr=0x%lx " |
4974 | "ctladdr=0x%lx\n", | ||
4975 | (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); | ||
4976 | printk("Cyclades-Z/PCI not supported for low " | ||
4977 | "addresses\n"); | ||
4978 | return -EIO; | ||
4979 | } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { | ||
4980 | #ifdef CY_PCI_DEBUG | ||
4981 | printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", | ||
4982 | pdev->bus->number, pdev->devfn); | ||
4983 | printk("rev_id=%d) IRQ%d\n", | ||
4984 | cyy_rev_id, (int)cy_pci_irq); | ||
4985 | printk("Cyclades-Z/PCI: found winaddr=0x%lx " | ||
4986 | "ctladdr=0x%lx\n", | ||
4987 | (ulong) cy_pci_phys2, (ulong) cy_pci_phys0); | ||
4988 | #endif | ||
4989 | cy_pci_addr0 = pci_iomap(pdev, 0, CyPCI_Zctl); | ||
4990 | |||
4991 | /* Disable interrupts on the PLX before resetting it */ | ||
4992 | cy_writew(cy_pci_addr0 + 0x68, | ||
4993 | readw(cy_pci_addr0 + 0x68) & ~0x0900); | ||
4994 | |||
4995 | plx_init(cy_pci_addr0, 0x6c); | ||
4996 | /* For some yet unknown reason, once the PLX9060 reloads | ||
4997 | the EEPROM, the IRQ is lost and, thus, we have to | ||
4998 | re-write it to the PCI config. registers. | ||
4999 | This will remain here until we find a permanent | ||
5000 | fix. */ | ||
5001 | pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, | ||
5002 | cy_pci_irq); | ||
5040 | 5003 | ||
5041 | if (mailbox == ZE_V1) { | 5004 | mailbox = (__u32)readl(&((struct RUNTIME_9060 __iomem *) |
5042 | retval = cy_init_Ze(cy_pci_phys0, cy_pci_phys2, | 5005 | cy_pci_addr0)->mail_box_0); |
5043 | cy_pci_addr0, cy_pci_irq, pdev); | 5006 | |
5044 | if (retval < 0) | 5007 | if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { |
5045 | i--; | 5008 | printk(" Warning: PCI I/O bit incorrectly " |
5046 | continue; | 5009 | "set. Ignoring it...\n"); |
5047 | } else { | 5010 | pdev->resource[2].flags &= ~IORESOURCE_IO; |
5048 | cy_pci_addr2 = pci_iomap(pdev, 2, CyPCI_Zwin); | 5011 | } |
5049 | } | 5012 | |
5013 | /* Although we don't use this I/O region, we should | ||
5014 | request it from the kernel anyway, to avoid problems | ||
5015 | with other drivers accessing it. */ | ||
5016 | retval = pci_request_regions(pdev, "Cyclades-Z"); | ||
5017 | if (retval) { | ||
5018 | printk(KERN_ERR "cyclades: failed to reserve " | ||
5019 | "PCI resources\n"); | ||
5020 | return retval; | ||
5021 | } | ||
5022 | |||
5023 | if (mailbox == ZE_V1) { | ||
5024 | retval = cy_init_Ze(cy_pci_phys0, cy_pci_phys2, | ||
5025 | cy_pci_addr0, cy_pci_irq, pdev); | ||
5026 | return retval; | ||
5027 | } else { | ||
5028 | cy_pci_addr2 = pci_iomap(pdev, 2, CyPCI_Zwin); | ||
5029 | } | ||
5050 | 5030 | ||
5051 | #ifdef CY_PCI_DEBUG | 5031 | #ifdef CY_PCI_DEBUG |
5052 | printk("Cyclades-Z/PCI: relocate winaddr=0x%lx " | 5032 | printk("Cyclades-Z/PCI: relocate winaddr=0x%lx " |
5053 | "ctladdr=0x%lx\n", | 5033 | "ctladdr=0x%lx\n", |
5054 | (ulong) cy_pci_addr2, (ulong) cy_pci_addr0); | 5034 | (ulong) cy_pci_addr2, (ulong) cy_pci_addr0); |
5055 | if (mailbox == ZO_V1) { | 5035 | if (mailbox == ZO_V1) { |
5056 | cy_writel(&((struct RUNTIME_9060 *) | 5036 | cy_writel(&((struct RUNTIME_9060 *) |
5057 | (cy_pci_addr0))->loc_addr_base, | 5037 | (cy_pci_addr0))->loc_addr_base, |
5058 | WIN_CREG); | 5038 | WIN_CREG); |
5059 | printk("Cyclades-8Zo/PCI: FPGA id %lx, ver " | 5039 | printk("Cyclades-8Zo/PCI: FPGA id %lx, ver " |
5060 | "%lx\n", (ulong) (0xff & | 5040 | "%lx\n", (ulong) (0xff & |
5061 | readl(&((struct CUSTOM_REG *) | 5041 | readl(&((struct CUSTOM_REG *) |
5062 | (cy_pci_addr2))->fpga_id)), | 5042 | (cy_pci_addr2))->fpga_id)), |
5063 | (ulong)(0xff & | 5043 | (ulong)(0xff & |
5064 | readl(&((struct CUSTOM_REG *) | 5044 | readl(&((struct CUSTOM_REG *) |
5065 | (cy_pci_addr2))-> | 5045 | (cy_pci_addr2))-> |
5066 | fpga_version))); | 5046 | fpga_version))); |
5067 | cy_writel(&((struct RUNTIME_9060 *) | 5047 | cy_writel(&((struct RUNTIME_9060 *) |
5068 | (cy_pci_addr0))->loc_addr_base, | 5048 | (cy_pci_addr0))->loc_addr_base, |
5069 | WIN_RAM); | 5049 | WIN_RAM); |
5070 | } else { | 5050 | } else { |
5071 | printk("Cyclades-Z/PCI: New Cyclades-Z board. " | 5051 | printk("Cyclades-Z/PCI: New Cyclades-Z board. " |
5072 | "FPGA not loaded\n"); | 5052 | "FPGA not loaded\n"); |
5073 | } | 5053 | } |
5074 | #endif | 5054 | #endif |
5075 | /* The following clears the firmware id word. This | 5055 | /* The following clears the firmware id word. This |
5076 | ensures that the driver will not attempt to talk to | 5056 | ensures that the driver will not attempt to talk to |
5077 | the board until it has been properly initialized. | 5057 | the board until it has been properly initialized. |
5078 | */ | 5058 | */ |
5079 | if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) | 5059 | if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) |
5080 | cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L); | 5060 | cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L); |
5081 | 5061 | ||
5082 | /* This must be a Cyclades-8Zo/PCI. The extendable | 5062 | /* This must be a Cyclades-8Zo/PCI. The extendable |
5083 | version will have a different device_id and will | 5063 | version will have a different device_id and will |
5084 | be allocated its maximum number of ports. */ | 5064 | be allocated its maximum number of ports. */ |
5085 | cy_pci_nchan = 8; | 5065 | cy_pci_nchan = 8; |
5086 | 5066 | ||
5087 | if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { | 5067 | if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { |
5088 | printk("Cyclades-8Zo/PCI found at 0x%lx but" | 5068 | printk("Cyclades-8Zo/PCI found at 0x%lx but" |
5089 | "no channels are available.\nChange " | 5069 | "no channels are available.\nChange " |
5090 | "NR_PORTS in cyclades.c and recompile " | 5070 | "NR_PORTS in cyclades.c and recompile " |
5091 | "kernel.\n", (ulong)cy_pci_phys2); | 5071 | "kernel.\n", (ulong)cy_pci_phys2); |
5092 | return i; | 5072 | return -EIO; |
5093 | } | 5073 | } |
5094 | 5074 | ||
5095 | /* fill the next cy_card structure available */ | 5075 | /* fill the next cy_card structure available */ |
5096 | for (j = 0; j < NR_CARDS; j++) { | 5076 | for (j = 0; j < NR_CARDS; j++) { |
5097 | if (cy_card[j].base_addr == 0) | 5077 | if (cy_card[j].base_addr == 0) |
5098 | break; | 5078 | break; |
5099 | } | 5079 | } |
5100 | if (j == NR_CARDS) { /* no more cy_cards available */ | 5080 | if (j == NR_CARDS) { /* no more cy_cards available */ |
5101 | printk("Cyclades-8Zo/PCI found at 0x%lx but" | 5081 | printk("Cyclades-8Zo/PCI found at 0x%lx but" |
5102 | "no more cards can be used.\nChange " | 5082 | "no more cards can be used.\nChange " |
5103 | "NR_CARDS in cyclades.c and recompile " | 5083 | "NR_CARDS in cyclades.c and recompile " |
5104 | "kernel.\n", (ulong)cy_pci_phys2); | 5084 | "kernel.\n", (ulong)cy_pci_phys2); |
5105 | return i; | 5085 | return -EIO; |
5106 | } | 5086 | } |
5107 | #ifdef CONFIG_CYZ_INTR | 5087 | #ifdef CONFIG_CYZ_INTR |
5108 | /* allocate IRQ only if board has an IRQ */ | 5088 | /* allocate IRQ only if board has an IRQ */ |
5109 | if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) { | 5089 | if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) { |
5110 | if (request_irq(cy_pci_irq, cyz_interrupt, | 5090 | retval = request_irq(cy_pci_irq, cyz_interrupt, |
5111 | IRQF_SHARED, "Cyclades-Z", | 5091 | IRQF_SHARED, "Cyclades-Z", |
5112 | &cy_card[j])) { | 5092 | &cy_card[j]); |
5113 | printk("Cyclom-8Zo/PCI found at 0x%lx " | 5093 | if (retval) { |
5114 | "but could not allocate " | 5094 | printk("Cyclom-8Zo/PCI found at 0x%lx " |
5115 | "IRQ%d.\n", (ulong)cy_pci_phys2, | 5095 | "but could not allocate " |
5116 | cy_pci_irq); | 5096 | "IRQ%d.\n", (ulong)cy_pci_phys2, |
5117 | return i; | 5097 | cy_pci_irq); |
5118 | } | 5098 | return retval; |
5119 | } | 5099 | } |
5100 | } | ||
5120 | #endif /* CONFIG_CYZ_INTR */ | 5101 | #endif /* CONFIG_CYZ_INTR */ |
5121 | 5102 | ||
5122 | /* set cy_card */ | 5103 | /* set cy_card */ |
5123 | cy_card[j].base_phys = cy_pci_phys2; | 5104 | cy_card[j].base_phys = cy_pci_phys2; |
5124 | cy_card[j].ctl_phys = cy_pci_phys0; | 5105 | cy_card[j].ctl_phys = cy_pci_phys0; |
5125 | cy_card[j].base_addr = cy_pci_addr2; | 5106 | cy_card[j].base_addr = cy_pci_addr2; |
5126 | cy_card[j].ctl_addr = cy_pci_addr0; | 5107 | cy_card[j].ctl_addr = cy_pci_addr0; |
5127 | cy_card[j].irq = (int)cy_pci_irq; | 5108 | cy_card[j].irq = (int)cy_pci_irq; |
5128 | cy_card[j].bus_index = 1; | 5109 | cy_card[j].bus_index = 1; |
5129 | cy_card[j].first_line = cy_next_channel; | 5110 | cy_card[j].first_line = cy_next_channel; |
5130 | cy_card[j].num_chips = -1; | 5111 | cy_card[j].num_chips = -1; |
5131 | cy_card[j].pdev = pdev; | 5112 | cy_card[j].pdev = pdev; |
5132 | pci_set_drvdata(pdev, &cy_card[j]); | 5113 | pci_set_drvdata(pdev, &cy_card[j]); |
5133 | 5114 | ||
5134 | /* print message */ | 5115 | /* print message */ |
5135 | #ifdef CONFIG_CYZ_INTR | 5116 | #ifdef CONFIG_CYZ_INTR |
5136 | /* don't report IRQ if board is no IRQ */ | 5117 | /* don't report IRQ if board is no IRQ */ |
5137 | if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) | 5118 | if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) |
5138 | printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, " | 5119 | printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, " |
5139 | "IRQ%d, ", j + 1, (ulong)cy_pci_phys2, | 5120 | "IRQ%d, ", j + 1, (ulong)cy_pci_phys2, |
5140 | (ulong) (cy_pci_phys2 + CyPCI_Zwin - 1), | 5121 | (ulong) (cy_pci_phys2 + CyPCI_Zwin - 1), |
5141 | (int)cy_pci_irq); | 5122 | (int)cy_pci_irq); |
5142 | else | 5123 | else |
5143 | #endif /* CONFIG_CYZ_INTR */ | 5124 | #endif /* CONFIG_CYZ_INTR */ |
5144 | printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ", | 5125 | printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ", |
5145 | j + 1, (ulong)cy_pci_phys2, | 5126 | j + 1, (ulong)cy_pci_phys2, |
5146 | (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1)); | 5127 | (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1)); |
5128 | |||
5129 | printk("%d channels starting from port %d.\n", | ||
5130 | cy_pci_nchan, cy_next_channel); | ||
5131 | cy_next_channel += cy_pci_nchan; | ||
5132 | } | ||
5133 | |||
5134 | return 0; | ||
5135 | } | ||
5136 | #endif | ||
5137 | |||
5138 | /* | ||
5139 | * --------------------------------------------------------------------- | ||
5140 | * cy_detect_pci() - Test PCI bus presence and Cyclom-Ye/PCI. | ||
5141 | * sets global variables and return the number of PCI boards found. | ||
5142 | * --------------------------------------------------------------------- | ||
5143 | */ | ||
5144 | static int __init cy_detect_pci(void) | ||
5145 | { | ||
5146 | #ifdef CONFIG_PCI | ||
5147 | struct pci_dev *pdev = NULL; | ||
5148 | unsigned int i, device_id, dev_index = 0; | ||
5147 | 5149 | ||
5148 | printk("%d channels starting from port %d.\n", | 5150 | for (i = 0; i < NR_CARDS; i++) { |
5149 | cy_pci_nchan, cy_next_channel); | 5151 | /* look for a Cyclades card by vendor and device id */ |
5150 | cy_next_channel += cy_pci_nchan; | 5152 | while ((device_id = cy_pci_dev_id[dev_index].device) != 0) { |
5153 | if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES, | ||
5154 | device_id, pdev)) == NULL) { | ||
5155 | dev_index++; /* try next device id */ | ||
5156 | } else { | ||
5157 | break; /* found a board */ | ||
5158 | } | ||
5151 | } | 5159 | } |
5160 | |||
5161 | if (device_id == 0) | ||
5162 | break; | ||
5163 | |||
5164 | i -= !!cy_pci_probe(pdev, &cy_pci_dev_id[dev_index]); | ||
5152 | } | 5165 | } |
5153 | 5166 | ||
5154 | return i; | 5167 | return i; |