diff options
-rw-r--r-- | common/cmd_universe.c | 391 | ||||
-rw-r--r-- | include/universe.h | 157 |
2 files changed, 548 insertions, 0 deletions
diff --git a/common/cmd_universe.c b/common/cmd_universe.c new file mode 100644 index 0000000..6388546 --- /dev/null +++ b/common/cmd_universe.c @@ -0,0 +1,391 @@ +/* + * (C) Copyright 2003 Stefan Roese, stefan.roese@esd-electronics.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> +#include <malloc.h> +#include <asm/io.h> +#include <pci.h> + +#include <universe.h> + + +#if (CONFIG_COMMANDS & CFG_CMD_UNIVERSE) + +#undef DBG + +#ifdef DBG +# define UNI_DBG(fmt) printf fmt +#else +# define UNI_DBG(fmt) +#endif + +#define UNI_PRINT(fmt) printf fmt + + +#define PCI_VENDOR PCI_VENDOR_ID_TUNDRA +#define PCI_DEVICE PCI_DEVICE_ID_TUNDRA_CA91C042 + + +typedef struct _UNI_DEV UNI_DEV; + +struct _UNI_DEV { + int bus; + pci_dev_t busdevfn; + UNIVERSE *uregs; + unsigned int pci_bs; +}; + +static UNI_DEV *dev; + + +int universe_init(void) +{ + int j, result, lastError = 0; + pci_dev_t busdevfn; + unsigned int val; + + busdevfn = pci_find_device(PCI_VENDOR, PCI_DEVICE, 0); + if (busdevfn == -1) { + puts("No Tundra Universe found!\n"); + return -1; + } + + /* Lets turn Latency off */ + pci_write_config_dword(busdevfn, 0x0c, 0); + + dev = malloc(sizeof(*dev)); + if (NULL == dev) { + puts("UNIVERSE: No memory!\n"); + result = -1; + goto break_20; + } + + memset(dev, 0, sizeof(*dev)); + dev->busdevfn = busdevfn; + + pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_1, &val); + val &= ~0xf; + dev->uregs = (UNIVERSE *)val; + + UNI_DBG(("UNIVERSE-Base : %p\n", dev->uregs)); + + /* check mapping */ + UNI_DBG((" Read via mapping, PCI_ID = %08X\n", readl(&dev->uregs->pci_id))); + if (((PCI_DEVICE <<16) | PCI_VENDOR) != readl(&dev->uregs->pci_id)) { + UNI_PRINT(("UNIVERSE: Cannot read PCI-ID via Mapping: %08x\n", + readl(&dev->uregs->pci_id))); + result = -1; + goto break_30; + } + + UNI_DBG(("PCI_BS = %08X\n", readl(&dev->uregs->pci_bs))); + + dev->pci_bs = readl(&dev->uregs->pci_bs); + + /* turn off windows */ + for (j=0; j <4; j ++) { + writel(0x00800000, &dev->uregs->lsi[j].ctl); + writel(0x00800000, &dev->uregs->vsi[j].ctl); + } + + /* + * Write to Misc Register + * Set VME Bus Time-out + * Arbitration Mode + * DTACK Enable + */ + writel(0x15060000, &dev->uregs->misc_ctl); + + /* + * Lets turn off interrupts + */ + writel(0x00000000,&dev->uregs->lint_en); /* Disable interrupts in the Universe first */ + writel(0x0000FFFF,&dev->uregs->lint_stat); /* Clear Any Pending Interrupts */ + eieio(); + writel(0x0000, &dev->uregs->lint_map0); /* Map all ints to 0 */ + writel(0x0000, &dev->uregs->lint_map1); /* Map all ints to 0 */ + eieio(); + + break_30: + free(dev); + break_20: + lastError = result; + + return 0; +} + + +/* + * Create pci slave window (access: pci -> vme) + */ +int universe_pci_slave_window(unsigned int pciAddr, unsigned int vmeAddr, int size, int vam, int pms, int vdw) +{ + int result, i; + unsigned int ctl = 0; + + if (NULL == dev) { + result = -1; + goto exit_10; + } + + for (i = 0; i < 4; i++) { + if (0x00800000 == readl(&dev->uregs->lsi[i].ctl)) + break; + } + + if (i == 4) { + UNI_PRINT(("universe: No Image available\n")); + result = -1; + goto exit_10; + } + + UNI_DBG(("universe: Using image %d\n", i)); + + writel(pciAddr , &dev->uregs->lsi[i].bs); + writel((pciAddr + size), &dev->uregs->lsi[i].bd); + writel((vmeAddr - pciAddr), &dev->uregs->lsi[i].to); + + switch (vam & VME_AM_Axx) { + case VME_AM_A16: + ctl = 0x00000000; + break; + case VME_AM_A24: + ctl = 0x00010000; + break; + case VME_AM_A32: + ctl = 0x00020000; + break; + } + + switch (vam & VME_AM_Mxx) { + case VME_AM_DATA: + ctl |= 0x00000000; + break; + case VME_AM_PROG: + ctl |= 0x00008000; + break; + } + + if (vam & VME_AM_SUP) { + ctl |= 0x00001000; + + } + + switch (vdw & VME_FLAG_Dxx) { + case VME_FLAG_D8: + ctl |= 0x00000000; + break; + case VME_FLAG_D16: + ctl |= 0x00400000; + break; + case VME_FLAG_D32: + ctl |= 0x00800000; + break; + } + + switch (pms & PCI_MS_Mxx) { + case PCI_MS_MEM: + ctl = 0x00000000; + break; + case PCI_MS_IO: + ctl = 0x00000001; + break; + case PCI_MS_CONFIG: + ctl = 0x00000002; + break; + } + + ctl |= 0x80000000; /* enable */ + + writel(ctl, &dev->uregs->lsi[i].ctl); + + UNI_DBG(("universe: window-addr=%p\n", &dev->uregs->lsi[i].ctl)); + UNI_DBG(("universe: pci slave window[%d] ctl=%08x\n", i, readl(&dev->uregs->lsi[i].ctl))); + UNI_DBG(("universe: pci slave window[%d] bs=%08x\n", i, readl(&dev->uregs->lsi[i].bs))); + UNI_DBG(("universe: pci slave window[%d] bd=%08x\n", i, readl(&dev->uregs->lsi[i].bd))); + UNI_DBG(("universe: pci slave window[%d] to=%08x\n", i, readl(&dev->uregs->lsi[i].to))); + + return 0; + + exit_10: + return -result; +} + + +/* + * Create vme slave window (access: vme -> pci) + */ +int universe_vme_slave_window(unsigned int vmeAddr, unsigned int pciAddr, int size, int vam, int pms) +{ + int result, i; + unsigned int ctl = 0; + + if (NULL == dev) { + result = -1; + goto exit_10; + } + + for (i = 0; i < 4; i++) { + if (0x00800000 == readl(&dev->uregs->vsi[i].ctl)) + break; + } + + if (i == 4) { + UNI_PRINT(("universe: No Image available\n")); + result = -1; + goto exit_10; + } + + UNI_DBG(("universe: Using image %d\n", i)); + + writel(vmeAddr , &dev->uregs->vsi[i].bs); + writel((vmeAddr + size), &dev->uregs->vsi[i].bd); + writel((pciAddr - vmeAddr), &dev->uregs->vsi[i].to); + + switch (vam & VME_AM_Axx) { + case VME_AM_A16: + ctl = 0x00000000; + break; + case VME_AM_A24: + ctl = 0x00010000; + break; + case VME_AM_A32: + ctl = 0x00020000; + break; + } + + switch (vam & VME_AM_Mxx) { + case VME_AM_DATA: + ctl |= 0x00000000; + break; + case VME_AM_PROG: + ctl |= 0x00800000; + break; + } + + if (vam & VME_AM_SUP) { + ctl |= 0x00100000; + + } + + switch (pms & PCI_MS_Mxx) { + case PCI_MS_MEM: + ctl = 0x00000000; + break; + case PCI_MS_IO: + ctl = 0x00000001; + break; + case PCI_MS_CONFIG: + ctl = 0x00000002; + break; + } + + ctl |= 0x80f00000; /* enable */ + + writel(ctl, &dev->uregs->vsi[i].ctl); + + UNI_DBG(("universe: window-addr=%p\n", &dev->uregs->vsi[i].ctl)); + UNI_DBG(("universe: vme slave window[%d] ctl=%08x\n", i, readl(&dev->uregs->vsi[i].ctl))); + UNI_DBG(("universe: vme slave window[%d] bs=%08x\n", i, readl(&dev->uregs->vsi[i].bs))); + UNI_DBG(("universe: vme slave window[%d] bd=%08x\n", i, readl(&dev->uregs->vsi[i].bd))); + UNI_DBG(("universe: vme slave window[%d] to=%08x\n", i, readl(&dev->uregs->vsi[i].to))); + + return 0; + + exit_10: + return -result; +} + + +/* + * Tundra Universe configuration + */ +int do_universe(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong addr1 = 0, addr2 = 0, size = 0, vam = 0, pms = 0, vdw = 0; + char cmd = 'x'; + + /* get parameter */ + if (argc > 1) + cmd = argv[1][0]; + if (argc > 2) + addr1 = simple_strtoul(argv[2], NULL, 16); + if (argc > 3) + addr2 = simple_strtoul(argv[3], NULL, 16); + if (argc > 4) + size = simple_strtoul(argv[4], NULL, 16); + if (argc > 5) + vam = simple_strtoul(argv[5], NULL, 16); + if (argc > 6) + pms = simple_strtoul(argv[6], NULL, 16); + if (argc > 7) + vdw = simple_strtoul(argv[7], NULL, 16); + + switch (cmd) { + case 'i': /* init */ + universe_init(); + break; + case 'v': /* vme */ + printf("Configuring Universe VME Slave Window (VME->PCI):\n"); + printf(" vme=%08lx pci=%08lx size=%08lx vam=%02lx pms=%02lx\n", + addr1, addr2, size, vam, pms); + universe_vme_slave_window(addr1, addr2, size, vam, pms); + break; + case 'p': /* pci */ + printf("Configuring Universe PCI Slave Window (PCI->VME):\n"); + printf(" pci=%08lx vme=%08lx size=%08lx vam=%02lx pms=%02lx vdw=%02lx\n", + addr1, addr2, size, vam, pms, vdw); + universe_pci_slave_window(addr1, addr2, size, vam, pms, vdw); + break; + default: + printf("Universe command %s not supported!\n", argv[1]); + } + + return 0; +} + + +U_BOOT_CMD( + universe, 8, 1, do_universe, + "universe- initialize and configure Turndra Universe\n", + "init\n" + " - initialize universe\n" + "universe vme [vme_addr] [pci_addr] [size] [vam] [pms]\n" + " - create vme slave window (access: vme->pci)\n" + "universe pci [pci_addr] [vme_addr] [size] [vam] [pms] [vdw]\n" + " - create pci slave window (access: pci->vme)\n" + " [vam] = VMEbus Address-Modifier: 01 -> A16 Address Space\n" + " 02 -> A24 Address Space\n" + " 03 -> A32 Address Space\n" + " 04 -> Supervisor AM Code\n" + " 10 -> Data AM Code\n" + " 20 -> Program AM Code\n" + " [pms] = PCI Memory Space: 01 -> Memory Space\n" + " 02 -> I/O Space\n" + " 03 -> Configuration Space\n" + " [vdw] = VMEbus Maximum Datawidth: 01 -> D8 Data Width\n" + " 02 -> D16 Data Width\n" + " 03 -> D32 Data Width\n" +); + +#endif /* (CONFIG_COMMANDS & CFG_CMD_UNIVERSE) */ diff --git a/include/universe.h b/include/universe.h new file mode 100644 index 0000000..684e927 --- /dev/null +++ b/include/universe.h @@ -0,0 +1,157 @@ +/* + * (C) Copyright 2003 Stefan Roese, stefan.roese@esd-electronics.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _universe_h +#define _universe_h + + +typedef struct _UNIVERSE UNIVERSE; +typedef struct _SLAVE_IMAGE SLAVE_IMAGE; +typedef struct _TDMA_CMD_PACKET TDMA_CMD_PACKET; + + +struct _SLAVE_IMAGE { + unsigned int ctl; /* Control */ + unsigned int bs; /* Base */ + unsigned int bd; /* Bound */ + unsigned int to; /* Translation */ + unsigned int reserved; +}; + +struct _UNIVERSE { + unsigned int pci_id; + unsigned int pci_csr; + unsigned int pci_class; + unsigned int pci_misc0; + unsigned int pci_bs; + unsigned int spare0[10]; + unsigned int pci_misc1; + unsigned int spare1[48]; + SLAVE_IMAGE lsi[4]; + unsigned int spare2[8]; + unsigned int scyc_ctl; + unsigned int scyc_addr; + unsigned int scyc_en; + unsigned int scyc_cmp; + unsigned int scyc_swp; + unsigned int lmisc; + unsigned int slsi; + unsigned int l_cmderr; + unsigned int laerr; + unsigned int spare3[27]; + unsigned int dctl; + unsigned int dtbc; + unsigned int dla; + unsigned int spare4[1]; + unsigned int dva; + unsigned int spare5[1]; + unsigned int dcpp; + unsigned int spare6[1]; + unsigned int dgcs; + unsigned int d_llue; + unsigned int spare7[54]; + unsigned int lint_en; + unsigned int lint_stat; + unsigned int lint_map0; + unsigned int lint_map1; + unsigned int vint_en; + unsigned int vint_stat; + unsigned int vint_map0; + unsigned int vint_map1; + unsigned int statid; + unsigned int vx_statid[7]; + unsigned int spare8[48]; + unsigned int mast_ctl; + unsigned int misc_ctl; + unsigned int misc_stat; + unsigned int user_am; + unsigned int spare9[700]; + SLAVE_IMAGE vsi[4]; + unsigned int spare10[8]; + unsigned int vrai_ctl; + unsigned int vrai_bs; + unsigned int spare11[2]; + unsigned int vcsr_ctl; + unsigned int vcsr_to; + unsigned int v_amerr; + unsigned int vaerr; + unsigned int spare12[25]; + unsigned int vcsr_clr; + unsigned int vcsr_set; + unsigned int vcsr_bs; +}; + +#define IRQ_VOWN 0x0001 +#define IRQ_VIRQ1 0x0002 +#define IRQ_VIRQ2 0x0004 +#define IRQ_VIRQ3 0x0008 +#define IRQ_VIRQ4 0x0010 +#define IRQ_VIRQ5 0x0020 +#define IRQ_VIRQ6 0x0040 +#define IRQ_VIRQ7 0x0080 +#define IRQ_DMA 0x0100 +#define IRQ_LERR 0x0200 +#define IRQ_VERR 0x0400 +#define IRQ_res 0x0800 +#define IRQ_IACK 0x1000 +#define IRQ_SWINT 0x2000 +#define IRQ_SYSFAIL 0x4000 +#define IRQ_ACFAIL 0x8000 + +struct _TDMA_CMD_PACKET { + unsigned int dctl; /* DMA Control */ + unsigned int dtbc; /* Transfer Byte Count */ + unsigned int dlv; /* PCI Address */ + unsigned int res1; /* Reserved */ + unsigned int dva; /* Vme Address */ + unsigned int res2; /* Reserved */ + unsigned int dcpp; /* Pointer to Numed Cmd Packet with rPN */ + unsigned int res3; /* Reserved */ +}; + +#define VME_AM_A16 0x01 +#define VME_AM_A24 0x02 +#define VME_AM_A32 0x03 +#define VME_AM_Axx 0x03 +#define VME_AM_SUP 0x04 +#define VME_AM_DATA 0x10 +#define VME_AM_PROG 0x20 +#define VME_AM_Mxx 0x30 + +#define VME_FLAG_D8 0x01 +#define VME_FLAG_D16 0x02 +#define VME_FLAG_D32 0x03 +#define VME_FLAG_Dxx 0x03 + +#define PCI_MS_MEM 0x01 +#define PCI_MS_IO 0x02 +#define PCI_MS_CONFIG 0x03 +#define PCI_MS_Mxx 0x03 + +#endif + + + + + + + |