aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/cyclades.c
diff options
context:
space:
mode:
authorJiri Slaby <jirislaby@gmail.com>2007-07-17 07:05:16 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-17 13:23:10 -0400
commit054f5b0aaa58dfc841635e52b6c1cc2b14ec37fc (patch)
treef2356ddebc9e11d1eb5c178d4443dcf3e9612088 /drivers/char/cyclades.c
parentcf3a386c083c0cc4eb9f01a8818b9499ae56e73f (diff)
Char: cyclades, add firmware loading
cyclades, add firmware loading Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/cyclades.c')
-rw-r--r--drivers/char/cyclades.c351
1 files changed, 328 insertions, 23 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index e04005b5f8a6..b9bd4f67efb4 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -646,6 +646,7 @@
646#include <linux/delay.h> 646#include <linux/delay.h>
647#include <linux/spinlock.h> 647#include <linux/spinlock.h>
648#include <linux/bitops.h> 648#include <linux/bitops.h>
649#include <linux/firmware.h>
649 650
650#include <asm/system.h> 651#include <asm/system.h>
651#include <asm/io.h> 652#include <asm/io.h>
@@ -680,6 +681,44 @@ static void cy_send_xchar(struct tty_struct *tty, char ch);
680 681
681#define STD_COM_FLAGS (0) 682#define STD_COM_FLAGS (0)
682 683
684/* firmware stuff */
685#define ZL_MAX_BLOCKS 16
686#define DRIVER_VERSION 0x02010203
687#define RAM_SIZE 0x80000
688
689#define Z_FPGA_LOADED(X) ((readl(&(X)->init_ctrl) & (1<<17)) != 0)
690
691enum zblock_type {
692 ZBLOCK_PRG = 0,
693 ZBLOCK_FPGA = 1
694};
695
696struct zfile_header {
697 char name[64];
698 char date[32];
699 char aux[32];
700 u32 n_config;
701 u32 config_offset;
702 u32 n_blocks;
703 u32 block_offset;
704 u32 reserved[9];
705} __attribute__ ((packed));
706
707struct zfile_config {
708 char name[64];
709 u32 mailbox;
710 u32 function;
711 u32 n_blocks;
712 u32 block_list[ZL_MAX_BLOCKS];
713} __attribute__ ((packed));
714
715struct zfile_block {
716 u32 type;
717 u32 file_offset;
718 u32 ram_offset;
719 u32 size;
720} __attribute__ ((packed));
721
683static struct tty_driver *cy_serial_driver; 722static struct tty_driver *cy_serial_driver;
684 723
685#ifdef CONFIG_ISA 724#ifdef CONFIG_ISA
@@ -4735,17 +4774,295 @@ static int __init cy_detect_isa(void)
4735} /* cy_detect_isa */ 4774} /* cy_detect_isa */
4736 4775
4737#ifdef CONFIG_PCI 4776#ifdef CONFIG_PCI
4738static void __devinit plx_init(void __iomem * addr, __u32 initctl) 4777static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
4778{
4779 unsigned int a;
4780
4781 for (a = 0; a < size && *str; a++, str++)
4782 if (*str & 0x80)
4783 return -EINVAL;
4784
4785 for (; a < size; a++, str++)
4786 if (*str)
4787 return -EINVAL;
4788
4789 return 0;
4790}
4791
4792static inline void __devinit cyz_fpga_copy(void __iomem *fpga, u8 *data,
4793 unsigned int size)
4794{
4795 for (; size > 0; size--) {
4796 cy_writel(fpga, *data++);
4797 udelay(10);
4798 }
4799}
4800
4801static void __devinit plx_init(struct pci_dev *pdev, int irq,
4802 struct RUNTIME_9060 __iomem *addr)
4739{ 4803{
4740 /* Reset PLX */ 4804 /* Reset PLX */
4741 cy_writel(addr + initctl, readl(addr + initctl) | 0x40000000); 4805 cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000);
4742 udelay(100L); 4806 udelay(100L);
4743 cy_writel(addr + initctl, readl(addr + initctl) & ~0x40000000); 4807 cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000);
4744 4808
4745 /* Reload Config. Registers from EEPROM */ 4809 /* Reload Config. Registers from EEPROM */
4746 cy_writel(addr + initctl, readl(addr + initctl) | 0x20000000); 4810 cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000);
4747 udelay(100L); 4811 udelay(100L);
4748 cy_writel(addr + initctl, readl(addr + initctl) & ~0x20000000); 4812 cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000);
4813
4814 /* For some yet unknown reason, once the PLX9060 reloads the EEPROM,
4815 * the IRQ is lost and, thus, we have to re-write it to the PCI config.
4816 * registers. This will remain here until we find a permanent fix.
4817 */
4818 pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
4819}
4820
4821static int __devinit __cyz_load_fw(const struct firmware *fw,
4822 const char *name, const u32 mailbox, void __iomem *base,
4823 void __iomem *fpga)
4824{
4825 void *ptr = fw->data;
4826 struct zfile_header *h = ptr;
4827 struct zfile_config *c, *cs;
4828 struct zfile_block *b, *bs;
4829 unsigned int a, tmp, len = fw->size;
4830#define BAD_FW KERN_ERR "Bad firmware: "
4831 if (len < sizeof(*h)) {
4832 printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h));
4833 return -EINVAL;
4834 }
4835
4836 cs = ptr + h->config_offset;
4837 bs = ptr + h->block_offset;
4838
4839 if ((void *)(cs + h->n_config) > ptr + len ||
4840 (void *)(bs + h->n_blocks) > ptr + len) {
4841 printk(BAD_FW "too short");
4842 return -EINVAL;
4843 }
4844
4845 if (cyc_isfwstr(h->name, sizeof(h->name)) ||
4846 cyc_isfwstr(h->date, sizeof(h->date))) {
4847 printk(BAD_FW "bad formatted header string\n");
4848 return -EINVAL;
4849 }
4850
4851 if (strncmp(name, h->name, sizeof(h->name))) {
4852 printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name);
4853 return -EINVAL;
4854 }
4855
4856 tmp = 0;
4857 for (c = cs; c < cs + h->n_config; c++) {
4858 for (a = 0; a < c->n_blocks; a++)
4859 if (c->block_list[a] > h->n_blocks) {
4860 printk(BAD_FW "bad block ref number in cfgs\n");
4861 return -EINVAL;
4862 }
4863 if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */
4864 tmp++;
4865 }
4866 if (!tmp) {
4867 printk(BAD_FW "nothing appropriate\n");
4868 return -EINVAL;
4869 }
4870
4871 for (b = bs; b < bs + h->n_blocks; b++)
4872 if (b->file_offset + b->size > len) {
4873 printk(BAD_FW "bad block data offset\n");
4874 return -EINVAL;
4875 }
4876
4877 /* everything is OK, let's seek'n'load it */
4878 for (c = cs; c < cs + h->n_config; c++)
4879 if (c->mailbox == mailbox && c->function == 0)
4880 break;
4881
4882 for (a = 0; a < c->n_blocks; a++) {
4883 b = &bs[c->block_list[a]];
4884 if (b->type == ZBLOCK_FPGA) {
4885 if (fpga != NULL)
4886 cyz_fpga_copy(fpga, ptr + b->file_offset,
4887 b->size);
4888 } else {
4889 if (base != NULL)
4890 memcpy_toio(base + b->ram_offset,
4891 ptr + b->file_offset, b->size);
4892 }
4893 }
4894#undef BAD_FW
4895 return 0;
4896}
4897
4898static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
4899 struct RUNTIME_9060 __iomem *ctl_addr, int irq)
4900{
4901 const struct firmware *fw;
4902 struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS;
4903 struct CUSTOM_REG __iomem *cust = base_addr;
4904 struct ZFW_CTRL __iomem *pt_zfwctrl;
4905 u8 *tmp;
4906 u32 mailbox, status;
4907 unsigned int i;
4908 int retval;
4909
4910 retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev);
4911 if (retval) {
4912 dev_err(&pdev->dev, "can't get firmware\n");
4913 goto err;
4914 }
4915
4916 /* Check whether the firmware is already loaded and running. If
4917 positive, skip this board */
4918 if (Z_FPGA_LOADED(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
4919 u32 cntval = readl(base_addr + 0x190);
4920
4921 udelay(100);
4922 if (cntval != readl(base_addr + 0x190)) {
4923 /* FW counter is working, FW is running */
4924 dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. "
4925 "Skipping board.\n");
4926 retval = 0;
4927 goto err_rel;
4928 }
4929 }
4930
4931 /* start boot */
4932 cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) &
4933 ~0x00030800UL);
4934
4935 mailbox = readl(&ctl_addr->mail_box_0);
4936
4937 if (mailbox == 0 || Z_FPGA_LOADED(ctl_addr)) {
4938 /* stops CPU and set window to beginning of RAM */
4939 cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
4940 cy_writel(&cust->cpu_stop, 0);
4941 cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
4942 udelay(100);
4943 }
4944
4945 plx_init(pdev, irq, ctl_addr);
4946
4947 if (mailbox != 0) {
4948 /* load FPGA */
4949 retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL,
4950 base_addr);
4951 if (retval)
4952 goto err_rel;
4953 if (!Z_FPGA_LOADED(ctl_addr)) {
4954 dev_err(&pdev->dev, "fw upload successful, but fw is "
4955 "not loaded\n");
4956 goto err_rel;
4957 }
4958 }
4959
4960 /* stops CPU and set window to beginning of RAM */
4961 cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
4962 cy_writel(&cust->cpu_stop, 0);
4963 cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
4964 udelay(100);
4965
4966 /* clear memory */
4967 for (tmp = base_addr; (void *)tmp < base_addr + RAM_SIZE; tmp++)
4968 cy_writeb(tmp, 255);
4969 if (mailbox != 0) {
4970 /* set window to last 512K of RAM */
4971 cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE);
4972 //sleep(1);
4973 for (tmp = base_addr; (void *)tmp < base_addr + RAM_SIZE; tmp++)
4974 cy_writeb(tmp, 255);
4975 /* set window to beginning of RAM */
4976 cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
4977 //sleep(1);
4978 }
4979
4980 retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL);
4981 release_firmware(fw);
4982 if (retval)
4983 goto err;
4984
4985 /* finish boot and start boards */
4986 cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
4987 cy_writel(&cust->cpu_start, 0);
4988 cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
4989 i = 0;
4990 while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40)
4991 msleep(100);
4992 if (status != ZFIRM_ID) {
4993 if (status == ZFIRM_HLT) {
4994 dev_err(&pdev->dev, "you need an external power supply "
4995 "for this number of ports. Firmware halted and "
4996 "board reset.\n");
4997 retval = -EIO;
4998 goto err;
4999 }
5000 dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting "
5001 "some more time\n", status);
5002 while ((status = readl(&fid->signature)) != ZFIRM_ID &&
5003 i++ < 200)
5004 msleep(100);
5005 if (status != ZFIRM_ID) {
5006 dev_err(&pdev->dev, "Board not started in 20 seconds! "
5007 "Giving up. (fid->signature = 0x%x)\n",
5008 status);
5009 dev_info(&pdev->dev, "*** Warning ***: if you are "
5010 "upgrading the FW, please power cycle the "
5011 "system before loading the new FW to the "
5012 "Cyclades-Z.\n");
5013
5014 if (Z_FPGA_LOADED(ctl_addr))
5015 plx_init(pdev, irq, ctl_addr);
5016
5017 retval = -EIO;
5018 goto err;
5019 }
5020 dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n",
5021 i / 10);
5022 }
5023 pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr);
5024
5025 dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n",
5026 base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
5027 base_addr + readl(&fid->zfwctrl_addr));
5028
5029 dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n",
5030 readl(&pt_zfwctrl->board_ctrl.fw_version),
5031 readl(&pt_zfwctrl->board_ctrl.n_channel));
5032
5033 if (readl(&pt_zfwctrl->board_ctrl.n_channel) == 0) {
5034 dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
5035 "check the connection between the Z host card and the "
5036 "serial expanders.\n");
5037
5038 if (Z_FPGA_LOADED(ctl_addr))
5039 plx_init(pdev, irq, ctl_addr);
5040
5041 dev_info(&pdev->dev, "Null number of ports detected. Board "
5042 "reset.\n");
5043 retval = 0;
5044 goto err;
5045 }
5046
5047 cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX);
5048 cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION);
5049
5050 /*
5051 Early firmware failed to start looking for commands.
5052 This enables firmware interrupts for those commands.
5053 */
5054 cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
5055 (1 << 17));
5056 cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
5057 0x00030800UL);
5058
5059 plx_init(pdev, irq, ctl_addr);
5060
5061 return 0;
5062err_rel:
5063 release_firmware(fw);
5064err:
5065 return retval;
4749} 5066}
4750 5067
4751static int __devinit cy_pci_probe(struct pci_dev *pdev, 5068static int __devinit cy_pci_probe(struct pci_dev *pdev,
@@ -4827,16 +5144,9 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
4827 } 5144 }
4828 5145
4829 /* Disable interrupts on the PLX before resetting it */ 5146 /* Disable interrupts on the PLX before resetting it */
4830 cy_writew(addr0 + 0x68, 5147 cy_writew(addr0 + 0x68, readw(addr0 + 0x68) & ~0x0900);
4831 readw(addr0 + 0x68) & ~0x0900);
4832 5148
4833 plx_init(addr0, 0x6c); 5149 plx_init(pdev, irq, addr0);
4834 /* For some yet unknown reason, once the PLX9060 reloads
4835 the EEPROM, the IRQ is lost and, thus, we have to
4836 re-write it to the PCI config. registers.
4837 This will remain here until we find a permanent
4838 fix. */
4839 pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
4840 5150
4841 mailbox = (u32)readl(&ctl_addr->mail_box_0); 5151 mailbox = (u32)readl(&ctl_addr->mail_box_0);
4842 5152
@@ -4877,6 +5187,9 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
4877 if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) 5187 if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
4878 cy_writel(addr2 + ID_ADDRESS, 0L); 5188 cy_writel(addr2 + ID_ADDRESS, 0L);
4879 5189
5190 retval = cyz_load_fw(pdev, addr2, addr0, irq);
5191 if (retval)
5192 goto err_unmap;
4880 /* This must be a Cyclades-8Zo/PCI. The extendable 5193 /* This must be a Cyclades-8Zo/PCI. The extendable
4881 version will have a different device_id and will 5194 version will have a different device_id and will
4882 be allocated its maximum number of ports. */ 5195 be allocated its maximum number of ports. */
@@ -4953,15 +5266,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
4953 case PLX_9060: 5266 case PLX_9060:
4954 case PLX_9080: 5267 case PLX_9080:
4955 default: /* Old boards, use PLX_9060 */ 5268 default: /* Old boards, use PLX_9060 */
4956 5269 plx_init(pdev, irq, addr0);
4957 plx_init(addr0, 0x6c);
4958 /* For some yet unknown reason, once the PLX9060 reloads
4959 the EEPROM, the IRQ is lost and, thus, we have to
4960 re-write it to the PCI config. registers.
4961 This will remain here until we find a permanent
4962 fix. */
4963 pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
4964
4965 cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900); 5270 cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900);
4966 break; 5271 break;
4967 } 5272 }