uboot/drivers/pci/tsi108_pci.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2004 Tundra Semiconductor Corp.
   3 * Alex Bounine <alexandreb@tundra.com>
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8/*
   9 * PCI initialisation for the Tsi108 EMU board.
  10 */
  11
  12#include <config.h>
  13
  14#include <common.h>
  15#include <pci.h>
  16#include <asm/io.h>
  17#include <tsi108.h>
  18#if defined(CONFIG_OF_LIBFDT)
  19#include <libfdt.h>
  20#include <fdt_support.h>
  21#endif
  22
  23struct pci_controller local_hose;
  24
  25void tsi108_clear_pci_error (void)
  26{
  27        u32 err_stat, err_addr, pci_stat;
  28
  29        /*
  30         * Quietly clear errors signalled as result of PCI/X configuration read
  31         * requests.
  32         */
  33        /* Read PB Error Log Registers */
  34        err_stat = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
  35                                     TSI108_PB_REG_OFFSET + PB_ERRCS);
  36        err_addr = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
  37                                     TSI108_PB_REG_OFFSET + PB_AERR);
  38        if (err_stat & PB_ERRCS_ES) {
  39                /* Clear PCI/X bus errors if applicable */
  40                if ((err_addr & 0xFF000000) == CONFIG_SYS_PCI_CFG_BASE) {
  41                        /* Clear error flag */
  42                        *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE +
  43                                  TSI108_PB_REG_OFFSET + PB_ERRCS) =
  44                            PB_ERRCS_ES;
  45
  46                        /* Clear read error reported in PB_ISR */
  47                        *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE +
  48                                  TSI108_PB_REG_OFFSET + PB_ISR) =
  49                            PB_ISR_PBS_RD_ERR;
  50
  51                /* Clear errors reported by PCI CSR (Normally Master Abort) */
  52                        pci_stat = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
  53                                                     TSI108_PCI_REG_OFFSET +
  54                                                     PCI_CSR);
  55                        *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
  56                                          TSI108_PCI_REG_OFFSET + PCI_CSR) =
  57                            pci_stat;
  58
  59                        *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
  60                                          TSI108_PCI_REG_OFFSET +
  61                                          PCI_IRP_STAT) = PCI_IRP_STAT_P_CSR;
  62                }
  63        }
  64
  65        return;
  66}
  67
  68unsigned int __get_pci_config_dword (u32 addr)
  69{
  70        unsigned int retval;
  71
  72        __asm__ __volatile__ ("       lwbrx %0,0,%1\n"
  73                             "1:     eieio\n"
  74                             "2:\n"
  75                             ".section .fixup,\"ax\"\n"
  76                             "3:     li %0,-1\n"
  77                             "       b 2b\n"
  78                             ".section __ex_table,\"a\"\n"
  79                             "       .align 2\n"
  80                             "       .long 1b,3b\n"
  81                             ".section .text.__get_pci_config_dword"
  82                                : "=r"(retval) : "r"(addr));
  83
  84        return (retval);
  85}
  86
  87static int tsi108_read_config_dword (struct pci_controller *hose,
  88                                    pci_dev_t dev, int offset, u32 * value)
  89{
  90        dev &= (CONFIG_SYS_PCI_CFG_SIZE - 1);
  91        dev |= (CONFIG_SYS_PCI_CFG_BASE | (offset & 0xfc));
  92        *value = __get_pci_config_dword(dev);
  93        if (0xFFFFFFFF == *value)
  94                tsi108_clear_pci_error ();
  95        return 0;
  96}
  97
  98static int tsi108_write_config_dword (struct pci_controller *hose,
  99                                     pci_dev_t dev, int offset, u32 value)
 100{
 101        dev &= (CONFIG_SYS_PCI_CFG_SIZE - 1);
 102        dev |= (CONFIG_SYS_PCI_CFG_BASE | (offset & 0xfc));
 103
 104        out_le32 ((volatile unsigned *)dev, value);
 105
 106        return 0;
 107}
 108
 109void pci_init_board (void)
 110{
 111        struct pci_controller *hose = (struct pci_controller *)&local_hose;
 112
 113        hose->first_busno = 0;
 114        hose->last_busno = 0xff;
 115
 116        pci_set_region (hose->regions + 0,
 117                       CONFIG_SYS_PCI_MEMORY_BUS,
 118                       CONFIG_SYS_PCI_MEMORY_PHYS,
 119                       CONFIG_SYS_PCI_MEMORY_SIZE, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
 120
 121        /* PCI memory space */
 122        pci_set_region (hose->regions + 1,
 123                       CONFIG_SYS_PCI_MEM_BUS,
 124                       CONFIG_SYS_PCI_MEM_PHYS, CONFIG_SYS_PCI_MEM_SIZE, PCI_REGION_MEM);
 125
 126        /* PCI I/O space */
 127        pci_set_region (hose->regions + 2,
 128                       CONFIG_SYS_PCI_IO_BUS,
 129                       CONFIG_SYS_PCI_IO_PHYS, CONFIG_SYS_PCI_IO_SIZE, PCI_REGION_IO);
 130
 131        hose->region_count = 3;
 132
 133        pci_set_ops (hose,
 134                    pci_hose_read_config_byte_via_dword,
 135                    pci_hose_read_config_word_via_dword,
 136                    tsi108_read_config_dword,
 137                    pci_hose_write_config_byte_via_dword,
 138                    pci_hose_write_config_word_via_dword,
 139                    tsi108_write_config_dword);
 140
 141        pci_register_hose (hose);
 142
 143        hose->last_busno = pci_hose_scan (hose);
 144
 145        debug ("Done PCI initialization\n");
 146        return;
 147}
 148
 149#if defined(CONFIG_OF_LIBFDT)
 150void ft_pci_setup(void *blob, bd_t *bd)
 151{
 152        int nodeoffset;
 153        int tmp[2];
 154        const char *path;
 155
 156        nodeoffset = fdt_path_offset(blob, "/aliases");
 157        if (nodeoffset >= 0) {
 158                path = fdt_getprop(blob, nodeoffset, "pci", NULL);
 159                if (path) {
 160                        tmp[0] = cpu_to_be32(local_hose.first_busno);
 161                        tmp[1] = cpu_to_be32(local_hose.last_busno);
 162                        do_fixup_by_path(blob, path, "bus-range",
 163                                &tmp, sizeof(tmp), 1);
 164                }
 165        }
 166}
 167#endif /* CONFIG_OF_LIBFDT */
 168