uboot/drivers/pci/pci_gt64120.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2013 Gabor Juhos <juhosg@openwrt.org>
   3 *
   4 * Based on the Linux implementation.
   5 *   Copyright (C) 1999, 2000, 2004  MIPS Technologies, Inc.
   6 *   Authors: Carsten Langgaard <carstenl@mips.com>
   7 *            Maciej W. Rozycki <macro@mips.com>
   8 *
   9 * SPDX-License-Identifier:     GPL-2.0
  10 */
  11
  12#include <common.h>
  13#include <gt64120.h>
  14#include <pci.h>
  15#include <pci_gt64120.h>
  16
  17#include <asm/io.h>
  18
  19#define PCI_ACCESS_READ  0
  20#define PCI_ACCESS_WRITE 1
  21
  22struct gt64120_regs {
  23        u8      unused_000[0xc18];
  24        u32     intrcause;
  25        u8      unused_c1c[0x0dc];
  26        u32     pci0_cfgaddr;
  27        u32     pci0_cfgdata;
  28};
  29
  30struct gt64120_pci_controller {
  31        struct pci_controller hose;
  32        struct gt64120_regs *regs;
  33};
  34
  35static inline struct gt64120_pci_controller *
  36hose_to_gt64120(struct pci_controller *hose)
  37{
  38        return container_of(hose, struct gt64120_pci_controller, hose);
  39}
  40
  41#define GT_INTRCAUSE_ABORT_BITS \
  42                (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)
  43
  44static int gt_config_access(struct gt64120_pci_controller *gt,
  45                            unsigned char access_type, pci_dev_t bdf,
  46                            int where, u32 *data)
  47{
  48        unsigned int bus = PCI_BUS(bdf);
  49        unsigned int dev = PCI_DEV(bdf);
  50        unsigned int devfn = PCI_DEV(bdf) << 3 | PCI_FUNC(bdf);
  51        u32 intr;
  52        u32 addr;
  53        u32 val;
  54
  55        if (bus == 0 && dev >= 31) {
  56                /* Because of a bug in the galileo (for slot 31). */
  57                return -1;
  58        }
  59
  60        if (access_type == PCI_ACCESS_WRITE)
  61                debug("PCI WR %02x:%02x.%x reg:%02d data:%08x\n",
  62                      PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), where, *data);
  63
  64        /* Clear cause register bits */
  65        writel(~GT_INTRCAUSE_ABORT_BITS, &gt->regs->intrcause);
  66
  67        addr = GT_PCI0_CFGADDR_CONFIGEN_BIT;
  68        addr |= bus << GT_PCI0_CFGADDR_BUSNUM_SHF;
  69        addr |= devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF;
  70        addr |= (where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF;
  71
  72        /* Setup address */
  73        writel(addr, &gt->regs->pci0_cfgaddr);
  74
  75        if (access_type == PCI_ACCESS_WRITE) {
  76                if (bus == 0 && dev == 0) {
  77                        /*
  78                         * The Galileo system controller is acting
  79                         * differently than other devices.
  80                         */
  81                        val = *data;
  82                } else {
  83                        val = cpu_to_le32(*data);
  84                }
  85
  86                writel(val, &gt->regs->pci0_cfgdata);
  87        } else {
  88                val = readl(&gt->regs->pci0_cfgdata);
  89
  90                if (bus == 0 && dev == 0) {
  91                        /*
  92                         * The Galileo system controller is acting
  93                         * differently than other devices.
  94                         */
  95                        *data = val;
  96                } else {
  97                        *data = le32_to_cpu(val);
  98                }
  99        }
 100
 101        /* Check for master or target abort */
 102        intr = readl(&gt->regs->intrcause);
 103        if (intr & GT_INTRCAUSE_ABORT_BITS) {
 104                /* Error occurred, clear abort bits */
 105                writel(~GT_INTRCAUSE_ABORT_BITS, &gt->regs->intrcause);
 106                return -1;
 107        }
 108
 109        if (access_type == PCI_ACCESS_READ)
 110                debug("PCI RD %02x:%02x.%x reg:%02d data:%08x\n",
 111                      PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), where, *data);
 112
 113        return 0;
 114}
 115
 116static int gt_read_config_dword(struct pci_controller *hose, pci_dev_t dev,
 117                                int where, u32 *value)
 118{
 119        struct gt64120_pci_controller *gt = hose_to_gt64120(hose);
 120
 121        *value = 0xffffffff;
 122        return gt_config_access(gt, PCI_ACCESS_READ, dev, where, value);
 123}
 124
 125static int gt_write_config_dword(struct pci_controller *hose, pci_dev_t dev,
 126                                 int where, u32 value)
 127{
 128        struct gt64120_pci_controller *gt = hose_to_gt64120(hose);
 129        u32 data = value;
 130
 131        return gt_config_access(gt, PCI_ACCESS_WRITE, dev, where, &data);
 132}
 133
 134void gt64120_pci_init(void *regs, unsigned long sys_bus, unsigned long sys_phys,
 135                     unsigned long sys_size, unsigned long mem_bus,
 136                     unsigned long mem_phys, unsigned long mem_size,
 137                     unsigned long io_bus, unsigned long io_phys,
 138                     unsigned long io_size)
 139{
 140        static struct gt64120_pci_controller global_gt;
 141        struct gt64120_pci_controller *gt;
 142        struct pci_controller *hose;
 143
 144        gt = &global_gt;
 145        gt->regs = regs;
 146
 147        hose = &gt->hose;
 148
 149        hose->first_busno = 0;
 150        hose->last_busno = 0;
 151
 152        /* System memory space */
 153        pci_set_region(&hose->regions[0], sys_bus, sys_phys, sys_size,
 154                       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
 155
 156        /* PCI memory space */
 157        pci_set_region(&hose->regions[1], mem_bus, mem_phys, mem_size,
 158                       PCI_REGION_MEM);
 159
 160        /* PCI I/O space */
 161        pci_set_region(&hose->regions[2], io_bus, io_phys, io_size,
 162                       PCI_REGION_IO);
 163
 164        hose->region_count = 3;
 165
 166        pci_set_ops(hose,
 167                    pci_hose_read_config_byte_via_dword,
 168                    pci_hose_read_config_word_via_dword,
 169                    gt_read_config_dword,
 170                    pci_hose_write_config_byte_via_dword,
 171                    pci_hose_write_config_word_via_dword,
 172                    gt_write_config_dword);
 173
 174        pci_register_hose(hose);
 175        hose->last_busno = pci_hose_scan(hose);
 176}
 177