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                             ".section .text.__get_pci_config_dword"
  98                                : "=r"(retval) : "r"(addr));
  99
 100        return (retval);
 101}
 102
 103static int tsi108_read_config_dword (struct pci_controller *hose,
 104                                    pci_dev_t dev, int offset, u32 * value)
 105{
 106        dev &= (CONFIG_SYS_PCI_CFG_SIZE - 1);
 107        dev |= (CONFIG_SYS_PCI_CFG_BASE | (offset & 0xfc));
 108        *value = __get_pci_config_dword(dev);
 109        if (0xFFFFFFFF == *value)
 110                tsi108_clear_pci_error ();
 111        return 0;
 112}
 113
 114static int tsi108_write_config_dword (struct pci_controller *hose,
 115                                     pci_dev_t dev, int offset, u32 value)
 116{
 117        dev &= (CONFIG_SYS_PCI_CFG_SIZE - 1);
 118        dev |= (CONFIG_SYS_PCI_CFG_BASE | (offset & 0xfc));
 119
 120        out_le32 ((volatile unsigned *)dev, value);
 121
 122        return 0;
 123}
 124
 125void pci_init_board (void)
 126{
 127        struct pci_controller *hose = (struct pci_controller *)&local_hose;
 128
 129        hose->first_busno = 0;
 130        hose->last_busno = 0xff;
 131
 132        pci_set_region (hose->regions + 0,
 133                       CONFIG_SYS_PCI_MEMORY_BUS,
 134                       CONFIG_SYS_PCI_MEMORY_PHYS,
 135                       CONFIG_SYS_PCI_MEMORY_SIZE, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
 136
 137        /* PCI memory space */
 138        pci_set_region (hose->regions + 1,
 139                       CONFIG_SYS_PCI_MEM_BUS,
 140                       CONFIG_SYS_PCI_MEM_PHYS, CONFIG_SYS_PCI_MEM_SIZE, PCI_REGION_MEM);
 141
 142        /* PCI I/O space */
 143        pci_set_region (hose->regions + 2,
 144                       CONFIG_SYS_PCI_IO_BUS,
 145                       CONFIG_SYS_PCI_IO_PHYS, CONFIG_SYS_PCI_IO_SIZE, PCI_REGION_IO);
 146
 147        hose->region_count = 3;
 148
 149        pci_set_ops (hose,
 150                    pci_hose_read_config_byte_via_dword,
 151                    pci_hose_read_config_word_via_dword,
 152                    tsi108_read_config_dword,
 153                    pci_hose_write_config_byte_via_dword,
 154                    pci_hose_write_config_word_via_dword,
 155                    tsi108_write_config_dword);
 156
 157        pci_register_hose (hose);
 158
 159        hose->last_busno = pci_hose_scan (hose);
 160
 161        debug ("Done PCI initialization\n");
 162        return;
 163}
 164
 165#if defined(CONFIG_OF_LIBFDT)
 166void ft_pci_setup(void *blob, bd_t *bd)
 167{
 168        int nodeoffset;
 169        int tmp[2];
 170        const char *path;
 171
 172        nodeoffset = fdt_path_offset(blob, "/aliases");
 173        if (nodeoffset >= 0) {
 174                path = fdt_getprop(blob, nodeoffset, "pci", NULL);
 175                if (path) {
 176                        tmp[0] = cpu_to_be32(local_hose.first_busno);
 177                        tmp[1] = cpu_to_be32(local_hose.last_busno);
 178                        do_fixup_by_path(blob, path, "bus-range",
 179                                &tmp, sizeof(tmp), 1);
 180                }
 181        }
 182}
 183#endif /* CONFIG_OF_LIBFDT */
 184