uboot/board/dave/common/pci.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   3 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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#include <common.h>
  25#include <asm/ppc4xx.h>
  26#include <asm/processor.h>
  27#include <pci.h>
  28
  29
  30u_long pci9054_iobase;
  31
  32
  33#define PCI_PRIMARY_CAR (0x500000dc) /* PCI config address reg */
  34#define PCI_PRIMARY_CDR (0x80000000) /* PCI config data    reg */
  35
  36
  37/*-----------------------------------------------------------------------------+
  38|  Subroutine:  pci9054_read_config_dword
  39|  Description: Read a PCI configuration register
  40|  Inputs:
  41|               hose            PCI Controller
  42|               dev             PCI Bus+Device+Function number
  43|               offset          Configuration register number
  44|               value           Address of the configuration register value
  45|  Return value:
  46|               0               Successful
  47+-----------------------------------------------------------------------------*/
  48int pci9054_read_config_dword(struct pci_controller *hose,
  49                              pci_dev_t dev, int offset, u32* value)
  50{
  51  unsigned long      conAdrVal;
  52  unsigned long      val;
  53
  54  /* generate coded value for CON_ADR register */
  55  conAdrVal = dev | (offset & 0xfc) | 0x80000000;
  56
  57  /* Load the CON_ADR (CAR) value first, then read from CON_DATA (CDR) */
  58  *(unsigned long *)PCI_PRIMARY_CAR = conAdrVal;
  59
  60  /* Note: *pResult comes back as -1 if machine check happened */
  61  val = in32r(PCI_PRIMARY_CDR);
  62
  63  *value = (unsigned long) val;
  64
  65  out32r(PCI_PRIMARY_CAR, 0);
  66
  67  if ((*(unsigned long *)0x50000304) & 0x60000000)
  68    {
  69      /* clear pci master/target abort bits */
  70      *(unsigned long *)0x50000304 = *(unsigned long *)0x50000304;
  71    }
  72
  73  return 0;
  74}
  75
  76/*-----------------------------------------------------------------------------+
  77|  Subroutine:  pci9054_write_config_dword
  78|  Description: Write a PCI configuration register.
  79|  Inputs:
  80|               hose            PCI Controller
  81|               dev             PCI Bus+Device+Function number
  82|               offset          Configuration register number
  83|               Value           Configuration register value
  84|  Return value:
  85|               0               Successful
  86| Updated for pass2 errata #6. Need to disable interrupts and clear the
  87| PCICFGADR reg after writing the PCICFGDATA reg.
  88+-----------------------------------------------------------------------------*/
  89int pci9054_write_config_dword(struct pci_controller *hose,
  90                               pci_dev_t dev, int offset, u32 value)
  91{
  92  unsigned long      conAdrVal;
  93
  94  conAdrVal = dev | (offset & 0xfc) | 0x80000000;
  95
  96  *(unsigned long *)PCI_PRIMARY_CAR = conAdrVal;
  97
  98  out32r(PCI_PRIMARY_CDR, value);
  99
 100  out32r(PCI_PRIMARY_CAR, 0);
 101
 102  /* clear pci master/target abort bits */
 103  *(unsigned long *)0x50000304 = *(unsigned long *)0x50000304;
 104
 105  return (0);
 106}
 107
 108/*-----------------------------------------------------------------------
 109 */
 110
 111#ifdef CONFIG_DASA_SIM
 112static void pci_dasa_sim_config_pci9054(struct pci_controller *hose, pci_dev_t dev,
 113                                        struct pci_config_table *_)
 114{
 115  unsigned int iobase;
 116  unsigned short status = 0;
 117  unsigned char timer;
 118
 119  /*
 120   * Configure PLX PCI9054
 121   */
 122  pci_read_config_word(CONFIG_SYS_PCI9054_DEV_FN, PCI_COMMAND, &status);
 123  status |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
 124  pci_write_config_word(CONFIG_SYS_PCI9054_DEV_FN, PCI_COMMAND, status);
 125
 126  /* Check the latency timer for values >= 0x60.
 127   */
 128  pci_read_config_byte(CONFIG_SYS_PCI9054_DEV_FN, PCI_LATENCY_TIMER, &timer);
 129  if (timer < 0x60)
 130    {
 131      pci_write_config_byte(CONFIG_SYS_PCI9054_DEV_FN, PCI_LATENCY_TIMER, 0x60);
 132    }
 133
 134  /* Set I/O base register.
 135   */
 136  pci_write_config_dword(CONFIG_SYS_PCI9054_DEV_FN, PCI_BASE_ADDRESS_0, CONFIG_SYS_PCI9054_IOBASE);
 137  pci_read_config_dword(CONFIG_SYS_PCI9054_DEV_FN, PCI_BASE_ADDRESS_0, &iobase);
 138
 139  pci9054_iobase = pci_mem_to_phys(CONFIG_SYS_PCI9054_DEV_FN, iobase & PCI_BASE_ADDRESS_MEM_MASK);
 140
 141  if (pci9054_iobase == 0xffffffff)
 142    {
 143      printf("Error: Can not set I/O base register.\n");
 144      return;
 145    }
 146}
 147#endif
 148
 149static struct pci_config_table pci9054_config_table[] = {
 150#ifndef CONFIG_PCI_PNP
 151  { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
 152    PCI_BUS(CONFIG_SYS_ETH_DEV_FN), PCI_DEV(CONFIG_SYS_ETH_DEV_FN), PCI_FUNC(CONFIG_SYS_ETH_DEV_FN),
 153    pci_cfgfunc_config_device, { CONFIG_SYS_ETH_IOBASE,
 154                                 CONFIG_SYS_ETH_IOBASE,
 155                                 PCI_COMMAND_IO | PCI_COMMAND_MASTER }},
 156#ifdef CONFIG_DASA_SIM
 157  { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
 158    PCI_BUS(CONFIG_SYS_PCI9054_DEV_FN), PCI_DEV(CONFIG_SYS_PCI9054_DEV_FN), PCI_FUNC(CONFIG_SYS_PCI9054_DEV_FN),
 159    pci_dasa_sim_config_pci9054 },
 160#endif
 161#endif
 162  { }
 163};
 164
 165static struct pci_controller pci9054_hose = {
 166  config_table: pci9054_config_table,
 167};
 168
 169void pci_init(void)
 170{
 171  struct pci_controller *hose = &pci9054_hose;
 172
 173  /*
 174   * Register the hose
 175   */
 176  hose->first_busno = 0;
 177  hose->last_busno = 0xff;
 178
 179  /* System memory space */
 180  pci_set_region(hose->regions + 0,
 181                 0x00000000, 0x00000000, 0x01000000,
 182                 PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
 183
 184  /* PCI Memory space */
 185  pci_set_region(hose->regions + 1,
 186                 0x00000000, 0xc0000000, 0x10000000,
 187                 PCI_REGION_MEM);
 188
 189  pci_set_ops(hose,
 190              pci_hose_read_config_byte_via_dword,
 191              pci_hose_read_config_word_via_dword,
 192              pci9054_read_config_dword,
 193              pci_hose_write_config_byte_via_dword,
 194              pci_hose_write_config_word_via_dword,
 195              pci9054_write_config_dword);
 196
 197  hose->region_count = 2;
 198
 199  pci_register_hose(hose);
 200
 201  hose->last_busno = pci_hose_scan(hose);
 202}
 203