uboot/drivers/pci/tsi108_pci.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2004 Tundra Semiconductor Corp.
   3 * Alex Bounine <alexandreb@tundra.com>
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24/*
  25 * PCI initialisation for the Tsi108 EMU board.
  26 */
  27
  28#include <config.h>
  29
  30#include <common.h>
  31#include <pci.h>
  32#include <asm/io.h>
  33#include <tsi108.h>
  34#if defined(CONFIG_OF_LIBFDT)
  35#include <libfdt.h>
  36#include <fdt_support.h>
  37#endif
  38
  39struct pci_controller local_hose;
  40
  41void tsi108_clear_pci_error (void)
  42{
  43        u32 err_stat, err_addr, pci_stat;
  44
  45        /*
  46         * Quietly clear errors signalled as result of PCI/X configuration read
  47         * requests.
  48         */
  49        /* Read PB Error Log Registers */
  50        err_stat = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
  51                                     TSI108_PB_REG_OFFSET + PB_ERRCS);
  52        err_addr = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
  53                                     TSI108_PB_REG_OFFSET + PB_AERR);
  54        if (err_stat & PB_ERRCS_ES) {
  55                /* Clear PCI/X bus errors if applicable */
  56                if ((err_addr & 0xFF000000) == CONFIG_SYS_PCI_CFG_BASE) {
  57                        /* Clear error flag */
  58                        *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE +
  59                                  TSI108_PB_REG_OFFSET + PB_ERRCS) =
  60                            PB_ERRCS_ES;
  61
  62                        /* Clear read error reported in PB_ISR */
  63                        *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE +
  64                                  TSI108_PB_REG_OFFSET + PB_ISR) =
  65                            PB_ISR_PBS_RD_ERR;
  66
  67                /* Clear errors reported by PCI CSR (Normally Master Abort) */
  68                        pci_stat = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
  69                                                     TSI108_PCI_REG_OFFSET +
  70                                                     PCI_CSR);
  71                        *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
  72                                          TSI108_PCI_REG_OFFSET + PCI_CSR) =
  73                            pci_stat;
  74
  75                        *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
  76                                          TSI108_PCI_REG_OFFSET +
  77                                          PCI_IRP_STAT) = PCI_IRP_STAT_P_CSR;
  78                }
  79        }
  80
  81        return;
  82}
  83
  84unsigned int __get_pci_config_dword (u32 addr)
  85{
  86        unsigned int retval;
  87
  88        __asm__ __volatile__ ("       lwbrx %0,0,%1\n"
  89                             "1:     eieio\n"
  90                             "2:\n"
  91                             ".section .fixup,\"ax\"\n"
  92                             "3:     li %0,-1\n"
  93                             "       b 2b\n"
  94                             ".section __ex_table,\"a\"\n"
  95                             "       .align 2\n"
  96                             "       .long 1b,3b\n"
  97                             ".text":"=r"(retval):"r"(addr));
  98
  99        return (retval);
 100}
 101
 102static int tsi108_read_config_dword (struct pci_controller *hose,
 103                                    pci_dev_t dev, int offset, u32 * value)
 104{
 105        dev &= (CONFIG_SYS_PCI_CFG_SIZE - 1);
 106        dev |= (CONFIG_SYS_PCI_CFG_BASE | (offset & 0xfc));
 107        *value = __get_pci_config_dword(dev);
 108        if (0xFFFFFFFF == *value)
 109                tsi108_clear_pci_error ();
 110        return 0;
 111}
 112
 113static int tsi108_write_config_dword (struct pci_controller *hose,
 114                                     pci_dev_t dev, int offset, u32 value)
 115{
 116        dev &= (CONFIG_SYS_PCI_CFG_SIZE - 1);
 117        dev |= (CONFIG_SYS_PCI_CFG_BASE | (offset & 0xfc));
 118
 119        out_le32 ((volatile unsigned *)dev, value);
 120
 121        return 0;
 122}
 123
 124void pci_init_board (void)
 125{
 126        struct pci_controller *hose = (struct pci_controller *)&local_hose;
 127
 128        hose->first_busno = 0;
 129        hose->last_busno = 0xff;
 130
 131        pci_set_region (hose->regions + 0,
 132                       CONFIG_SYS_PCI_MEMORY_BUS,
 133                       CONFIG_SYS_PCI_MEMORY_PHYS,
 134                       CONFIG_SYS_PCI_MEMORY_SIZE, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
 135
 136        /* PCI memory space */
 137        pci_set_region (hose->regions + 1,
 138                       CONFIG_SYS_PCI_MEM_BUS,
 139                       CONFIG_SYS_PCI_MEM_PHYS, CONFIG_SYS_PCI_MEM_SIZE, PCI_REGION_MEM);
 140
 141        /* PCI I/O space */
 142        pci_set_region (hose->regions + 2,
 143                       CONFIG_SYS_PCI_IO_BUS,
 144                       CONFIG_SYS_PCI_IO_PHYS, CONFIG_SYS_PCI_IO_SIZE, PCI_REGION_IO);
 145
 146        hose->region_count = 3;
 147
 148        pci_set_ops (hose,
 149                    pci_hose_read_config_byte_via_dword,
 150                    pci_hose_read_config_word_via_dword,
 151                    tsi108_read_config_dword,
 152                    pci_hose_write_config_byte_via_dword,
 153                    pci_hose_write_config_word_via_dword,
 154                    tsi108_write_config_dword);
 155
 156        pci_register_hose (hose);
 157
 158        hose->last_busno = pci_hose_scan (hose);
 159
 160        debug ("Done PCI initialization\n");
 161        return;
 162}
 163
 164#if defined(CONFIG_OF_LIBFDT)
 165void ft_pci_setup(void *blob, bd_t *bd)
 166{
 167        int nodeoffset;
 168        int tmp[2];
 169        const char *path;
 170
 171        nodeoffset = fdt_path_offset(blob, "/aliases");
 172        if (nodeoffset >= 0) {
 173                path = fdt_getprop(blob, nodeoffset, "pci", NULL);
 174                if (path) {
 175                        tmp[0] = cpu_to_be32(local_hose.first_busno);
 176                        tmp[1] = cpu_to_be32(local_hose.last_busno);
 177                        do_fixup_by_path(blob, path, "bus-range",
 178                                &tmp, sizeof(tmp), 1);
 179                }
 180        }
 181}
 182#endif /* CONFIG_OF_LIBFDT */
 183