uboot/cmd/tsi148.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2009 Reinhard Arlt, reinhard.arlt@esd-electronics.com
   4 *
   5 * base on universe.h by
   6 *
   7 * (C) Copyright 2003 Stefan Roese, stefan.roese@esd-electronics.com
   8 */
   9
  10#include <common.h>
  11#include <command.h>
  12#include <log.h>
  13#include <malloc.h>
  14#include <asm/io.h>
  15#include <pci.h>
  16
  17#include <tsi148.h>
  18
  19#define LPCI_VENDOR PCI_VENDOR_ID_TUNDRA
  20#define LPCI_DEVICE PCI_DEVICE_ID_TUNDRA_TSI148
  21
  22typedef struct _TSI148_DEV TSI148_DEV;
  23
  24struct _TSI148_DEV {
  25        int           bus;
  26        pci_dev_t     busdevfn;
  27        TSI148       *uregs;
  28        unsigned int  pci_bs;
  29};
  30
  31static TSI148_DEV *dev;
  32
  33/*
  34 * Most of the TSI148 register are BIGENDIAN
  35 * This is the reason for the __raw_writel(htonl(x), x) usage!
  36 */
  37
  38int tsi148_init(void)
  39{
  40        int j, result;
  41        pci_dev_t busdevfn;
  42        unsigned int val;
  43
  44        busdevfn = pci_find_device(LPCI_VENDOR, LPCI_DEVICE, 0);
  45        if (busdevfn == -1) {
  46                puts("Tsi148: No Tundra Tsi148 found!\n");
  47                return -1;
  48        }
  49
  50        /* Lets turn Latency off */
  51        pci_write_config_dword(busdevfn, 0x0c, 0);
  52
  53        dev = malloc(sizeof(*dev));
  54        if (NULL == dev) {
  55                puts("Tsi148: No memory!\n");
  56                return -1;
  57        }
  58
  59        memset(dev, 0, sizeof(*dev));
  60        dev->busdevfn = busdevfn;
  61
  62        pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_0, &val);
  63        val &= ~0xf;
  64        dev->uregs = (TSI148 *)val;
  65
  66        debug("Tsi148: Base    : %p\n", dev->uregs);
  67
  68        /* check mapping */
  69        debug("Tsi148: Read via mapping, PCI_ID = %08X\n",
  70              readl(&dev->uregs->pci_id));
  71        if (((LPCI_DEVICE << 16) | LPCI_VENDOR) != readl(&dev->uregs->pci_id)) {
  72                printf("Tsi148: Cannot read PCI-ID via Mapping: %08x\n",
  73                       readl(&dev->uregs->pci_id));
  74                result = -1;
  75                goto break_30;
  76        }
  77
  78        debug("Tsi148: PCI_BS = %08X\n", readl(&dev->uregs->pci_mbarl));
  79
  80        dev->pci_bs = readl(&dev->uregs->pci_mbarl);
  81
  82        /* turn off windows */
  83        for (j = 0; j < 8; j++) {
  84                __raw_writel(htonl(0x00000000), &dev->uregs->outbound[j].otat);
  85                __raw_writel(htonl(0x00000000), &dev->uregs->inbound[j].itat);
  86        }
  87
  88        /* Tsi148 VME timeout etc */
  89        __raw_writel(htonl(0x00000084), &dev->uregs->vctrl);
  90
  91#ifdef DEBUG
  92        if ((__raw_readl(&dev->uregs->vstat) & 0x00000100) != 0)
  93                printf("Tsi148: System Controller!\n");
  94        else
  95                printf("Tsi148: Not System Controller!\n");
  96#endif
  97
  98        /*
  99         * Lets turn off interrupts
 100         */
 101        /* Disable interrupts in Tsi148 first */
 102        __raw_writel(htonl(0x00000000), &dev->uregs->inten);
 103        /* Disable interrupt out */
 104        __raw_writel(htonl(0x00000000), &dev->uregs->inteo);
 105        eieio();
 106        /* Reset all IRQ's */
 107        __raw_writel(htonl(0x03ff3f00), &dev->uregs->intc);
 108        /* Map all ints to 0 */
 109        __raw_writel(htonl(0x00000000), &dev->uregs->intm1);
 110        __raw_writel(htonl(0x00000000), &dev->uregs->intm2);
 111        eieio();
 112
 113        val = __raw_readl(&dev->uregs->vstat);
 114        val &= ~(0x00004000);
 115        __raw_writel(val, &dev->uregs->vstat);
 116        eieio();
 117
 118        debug("Tsi148: register struct size %08x\n", sizeof(TSI148));
 119
 120        return 0;
 121
 122 break_30:
 123        free(dev);
 124        dev = NULL;
 125
 126        return result;
 127}
 128
 129/*
 130 * Create pci slave window (access: pci -> vme)
 131 */
 132int tsi148_pci_slave_window(unsigned int pciAddr, unsigned int vmeAddr,
 133                            int size, int vam, int vdw)
 134{
 135        int result, i;
 136        unsigned int ctl = 0;
 137
 138        if (NULL == dev) {
 139                result = -1;
 140                goto exit_10;
 141        }
 142
 143        for (i = 0; i < 8; i++) {
 144                if (0x00000000 == readl(&dev->uregs->outbound[i].otat))
 145                        break;
 146        }
 147
 148        if (i > 7) {
 149                printf("Tsi148: No Image available\n");
 150                result = -1;
 151                goto exit_10;
 152        }
 153
 154        debug("Tsi148: Using image %d\n", i);
 155
 156        printf("Tsi148: Pci addr %08x\n", pciAddr);
 157
 158        __raw_writel(htonl(pciAddr), &dev->uregs->outbound[i].otsal);
 159        __raw_writel(0x00000000, &dev->uregs->outbound[i].otsau);
 160        __raw_writel(htonl(pciAddr + size), &dev->uregs->outbound[i].oteal);
 161        __raw_writel(0x00000000, &dev->uregs->outbound[i].oteau);
 162        __raw_writel(htonl(vmeAddr - pciAddr), &dev->uregs->outbound[i].otofl);
 163        __raw_writel(0x00000000, &dev->uregs->outbound[i].otofu);
 164
 165        switch (vam & VME_AM_Axx) {
 166        case VME_AM_A16:
 167                ctl = 0x00000000;
 168                break;
 169        case VME_AM_A24:
 170                ctl = 0x00000001;
 171                break;
 172        case VME_AM_A32:
 173                ctl = 0x00000002;
 174                break;
 175        }
 176
 177        switch (vam & VME_AM_Mxx) {
 178        case VME_AM_DATA:
 179                ctl |= 0x00000000;
 180                break;
 181        case VME_AM_PROG:
 182                ctl |= 0x00000010;
 183                break;
 184        }
 185
 186        if (vam & VME_AM_SUP)
 187                ctl |= 0x00000020;
 188
 189        switch (vdw & VME_FLAG_Dxx) {
 190        case VME_FLAG_D16:
 191                ctl |= 0x00000000;
 192                break;
 193        case VME_FLAG_D32:
 194                ctl |= 0x00000040;
 195                break;
 196        }
 197
 198        ctl |= 0x80040000;      /* enable, no prefetch */
 199
 200        __raw_writel(htonl(ctl), &dev->uregs->outbound[i].otat);
 201
 202        debug("Tsi148: window-addr                =%p\n",
 203              &dev->uregs->outbound[i].otsau);
 204        debug("Tsi148: pci slave window[%d] attr  =%08x\n",
 205              i, ntohl(__raw_readl(&dev->uregs->outbound[i].otat)));
 206        debug("Tsi148: pci slave window[%d] start =%08x\n",
 207              i, ntohl(__raw_readl(&dev->uregs->outbound[i].otsal)));
 208        debug("Tsi148: pci slave window[%d] end   =%08x\n",
 209              i, ntohl(__raw_readl(&dev->uregs->outbound[i].oteal)));
 210        debug("Tsi148: pci slave window[%d] offset=%08x\n",
 211              i, ntohl(__raw_readl(&dev->uregs->outbound[i].otofl)));
 212
 213        return 0;
 214
 215 exit_10:
 216        return -result;
 217}
 218
 219unsigned int tsi148_eval_vam(int vam)
 220{
 221        unsigned int ctl = 0;
 222
 223        switch (vam & VME_AM_Axx) {
 224        case VME_AM_A16:
 225                ctl = 0x00000000;
 226                break;
 227        case VME_AM_A24:
 228                ctl = 0x00000010;
 229                break;
 230        case VME_AM_A32:
 231                ctl = 0x00000020;
 232                break;
 233        }
 234        switch (vam & VME_AM_Mxx) {
 235        case VME_AM_DATA:
 236                ctl |= 0x00000001;
 237                break;
 238        case VME_AM_PROG:
 239                ctl |= 0x00000002;
 240                break;
 241        case (VME_AM_PROG | VME_AM_DATA):
 242                ctl |= 0x00000003;
 243                break;
 244        }
 245
 246        if (vam & VME_AM_SUP)
 247                ctl |= 0x00000008;
 248        if (vam & VME_AM_USR)
 249                ctl |= 0x00000004;
 250
 251        return ctl;
 252}
 253
 254/*
 255 * Create vme slave window (access: vme -> pci)
 256 */
 257int tsi148_vme_slave_window(unsigned int vmeAddr, unsigned int pciAddr,
 258                            int size, int vam)
 259{
 260        int result, i;
 261        unsigned int ctl = 0;
 262
 263        if (NULL == dev) {
 264                result = -1;
 265                goto exit_10;
 266        }
 267
 268        for (i = 0; i < 8; i++) {
 269                if (0x00000000 == readl(&dev->uregs->inbound[i].itat))
 270                        break;
 271        }
 272
 273        if (i > 7) {
 274                printf("Tsi148: No Image available\n");
 275                result = -1;
 276                goto exit_10;
 277        }
 278
 279        debug("Tsi148: Using image %d\n", i);
 280
 281        __raw_writel(htonl(vmeAddr), &dev->uregs->inbound[i].itsal);
 282        __raw_writel(0x00000000, &dev->uregs->inbound[i].itsau);
 283        __raw_writel(htonl(vmeAddr + size), &dev->uregs->inbound[i].iteal);
 284        __raw_writel(0x00000000, &dev->uregs->inbound[i].iteau);
 285        __raw_writel(htonl(pciAddr - vmeAddr), &dev->uregs->inbound[i].itofl);
 286        if (vmeAddr > pciAddr)
 287                __raw_writel(0xffffffff, &dev->uregs->inbound[i].itofu);
 288        else
 289                __raw_writel(0x00000000, &dev->uregs->inbound[i].itofu);
 290
 291        ctl = tsi148_eval_vam(vam);
 292        ctl |= 0x80000000;      /* enable */
 293        __raw_writel(htonl(ctl), &dev->uregs->inbound[i].itat);
 294
 295        debug("Tsi148: window-addr                =%p\n",
 296              &dev->uregs->inbound[i].itsau);
 297        debug("Tsi148: vme slave window[%d] attr  =%08x\n",
 298              i, ntohl(__raw_readl(&dev->uregs->inbound[i].itat)));
 299        debug("Tsi148: vme slave window[%d] start =%08x\n",
 300              i, ntohl(__raw_readl(&dev->uregs->inbound[i].itsal)));
 301        debug("Tsi148: vme slave window[%d] end   =%08x\n",
 302              i, ntohl(__raw_readl(&dev->uregs->inbound[i].iteal)));
 303        debug("Tsi148: vme slave window[%d] offset=%08x\n",
 304              i, ntohl(__raw_readl(&dev->uregs->inbound[i].itofl)));
 305
 306        return 0;
 307
 308 exit_10:
 309        return -result;
 310}
 311
 312/*
 313 * Create vme slave window (access: vme -> gcsr)
 314 */
 315int tsi148_vme_gcsr_window(unsigned int vmeAddr, int vam)
 316{
 317        int result;
 318        unsigned int ctl;
 319
 320        result = 0;
 321
 322        if (NULL == dev) {
 323                result = 1;
 324        } else {
 325                __raw_writel(htonl(vmeAddr), &dev->uregs->gbal);
 326                __raw_writel(0x00000000, &dev->uregs->gbau);
 327
 328                ctl = tsi148_eval_vam(vam);
 329                ctl |= 0x00000080;      /* enable */
 330                __raw_writel(htonl(ctl), &dev->uregs->gcsrat);
 331        }
 332
 333        return result;
 334}
 335
 336/*
 337 * Create vme slave window (access: vme -> crcsr)
 338 */
 339int tsi148_vme_crcsr_window(unsigned int vmeAddr)
 340{
 341        int result;
 342        unsigned int ctl;
 343
 344        result = 0;
 345
 346        if (NULL == dev) {
 347                result = 1;
 348        } else {
 349                __raw_writel(htonl(vmeAddr), &dev->uregs->crol);
 350                __raw_writel(0x00000000, &dev->uregs->crou);
 351
 352                ctl = 0x00000080;       /* enable */
 353                __raw_writel(htonl(ctl), &dev->uregs->crat);
 354        }
 355
 356        return result;
 357}
 358
 359/*
 360 * Create vme slave window (access: vme -> crg)
 361 */
 362int tsi148_vme_crg_window(unsigned int vmeAddr, int vam)
 363{
 364        int result;
 365        unsigned int ctl;
 366
 367        result = 0;
 368
 369        if (NULL == dev) {
 370                result = 1;
 371        } else {
 372                __raw_writel(htonl(vmeAddr), &dev->uregs->cbal);
 373                __raw_writel(0x00000000, &dev->uregs->cbau);
 374
 375                ctl = tsi148_eval_vam(vam);
 376                ctl |= 0x00000080;      /* enable */
 377                __raw_writel(htonl(ctl), &dev->uregs->crgat);
 378        }
 379
 380        return result;
 381}
 382
 383/*
 384 * Tundra Tsi148 configuration
 385 */
 386int do_tsi148(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 387{
 388        ulong addr1 = 0, addr2 = 0, size = 0, vam = 0, vdw = 0;
 389        char cmd = 'x';
 390
 391        /* get parameter */
 392        if (argc > 1)
 393                cmd = argv[1][0];
 394        if (argc > 2)
 395                addr1 = hextoul(argv[2], NULL);
 396        if (argc > 3)
 397                addr2 = hextoul(argv[3], NULL);
 398        if (argc > 4)
 399                size = hextoul(argv[4], NULL);
 400        if (argc > 5)
 401                vam = hextoul(argv[5], NULL);
 402        if (argc > 6)
 403                vdw = hextoul(argv[6], NULL);
 404
 405        switch (cmd) {
 406        case 'c':
 407                if (strcmp(argv[1], "crg") == 0) {
 408                        vam = addr2;
 409                        printf("Tsi148: Configuring VME CRG Window "
 410                               "(VME->CRG):\n");
 411                        printf("  vme=%08lx vam=%02lx\n", addr1, vam);
 412                        tsi148_vme_crg_window(addr1, vam);
 413                } else {
 414                        printf("Tsi148: Configuring VME CR/CSR Window "
 415                               "(VME->CR/CSR):\n");
 416                        printf("  pci=%08lx\n", addr1);
 417                        tsi148_vme_crcsr_window(addr1);
 418                }
 419                break;
 420        case 'i':               /* init */
 421                tsi148_init();
 422                break;
 423        case 'g':
 424                vam = addr2;
 425                printf("Tsi148: Configuring VME GCSR Window (VME->GCSR):\n");
 426                printf("  vme=%08lx vam=%02lx\n", addr1, vam);
 427                tsi148_vme_gcsr_window(addr1, vam);
 428                break;
 429        case 'v':               /* vme */
 430                printf("Tsi148: Configuring VME Slave Window (VME->PCI):\n");
 431                printf("  vme=%08lx pci=%08lx size=%08lx vam=%02lx\n",
 432                       addr1, addr2, size, vam);
 433                tsi148_vme_slave_window(addr1, addr2, size, vam);
 434                break;
 435        case 'p':               /* pci */
 436                printf("Tsi148: Configuring PCI Slave Window (PCI->VME):\n");
 437                printf("  pci=%08lx vme=%08lx size=%08lx vam=%02lx vdw=%02lx\n",
 438                       addr1, addr2, size, vam, vdw);
 439                tsi148_pci_slave_window(addr1, addr2, size, vam, vdw);
 440                break;
 441        default:
 442                printf("Tsi148: Command %s not supported!\n", argv[1]);
 443        }
 444
 445        return 0;
 446}
 447
 448U_BOOT_CMD(
 449        tsi148, 7,      1,      do_tsi148,
 450        "initialize and configure Turndra Tsi148\n",
 451        "init\n"
 452        "    - initialize tsi148\n"
 453        "tsi148 vme   [vme_addr] [pci_addr] [size] [vam]\n"
 454        "    - create vme slave window (access: vme->pci)\n"
 455        "tsi148 pci   [pci_addr] [vme_addr] [size] [vam] [vdw]\n"
 456        "    - create pci slave window (access: pci->vme)\n"
 457        "tsi148 crg   [vme_addr] [vam]\n"
 458        "    - create vme slave window: (access vme->CRG\n"
 459        "tsi148 crcsr [pci_addr]\n"
 460        "    - create vme slave window: (access vme->CR/CSR\n"
 461        "tsi148 gcsr  [vme_addr] [vam]\n"
 462        "    - create vme slave window: (access vme->GCSR\n"
 463        "    [vam] = VMEbus Address-Modifier:  01 -> A16 Address Space\n"
 464        "                                      02 -> A24 Address Space\n"
 465        "                                      03 -> A32 Address Space\n"
 466        "                                      04 -> Usr        AM Code\n"
 467        "                                      08 -> Supervisor AM Code\n"
 468        "                                      10 -> Data AM Code\n"
 469        "                                      20 -> Program AM Code\n"
 470        "    [vdw] = VMEbus Maximum Datawidth: 02 -> D16 Data Width\n"
 471        "                                      03 -> D32 Data Width\n"
 472);
 473