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