Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 1999, 2000, 2004  MIPS Technologies, Inc.
0004  *  All rights reserved.
0005  *  Authors: Carsten Langgaard <carstenl@mips.com>
0006  *       Maciej W. Rozycki <macro@mips.com>
0007  */
0008 #include <linux/types.h>
0009 #include <linux/pci.h>
0010 #include <linux/kernel.h>
0011 
0012 #include <asm/gt64120.h>
0013 
0014 #define PCI_ACCESS_READ  0
0015 #define PCI_ACCESS_WRITE 1
0016 
0017 /*
0018  *  PCI configuration cycle AD bus definition
0019  */
0020 /* Type 0 */
0021 #define PCI_CFG_TYPE0_REG_SHF       0
0022 #define PCI_CFG_TYPE0_FUNC_SHF      8
0023 
0024 /* Type 1 */
0025 #define PCI_CFG_TYPE1_REG_SHF       0
0026 #define PCI_CFG_TYPE1_FUNC_SHF      8
0027 #define PCI_CFG_TYPE1_DEV_SHF       11
0028 #define PCI_CFG_TYPE1_BUS_SHF       16
0029 
0030 static int gt64xxx_pci0_pcibios_config_access(unsigned char access_type,
0031         struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
0032 {
0033     unsigned char busnum = bus->number;
0034     u32 intr;
0035 
0036     if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0)))
0037         return -1;  /* Because of a bug in the galileo (for slot 31). */
0038 
0039     /* Clear cause register bits */
0040     GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
0041                      GT_INTRCAUSE_TARABORT0_BIT));
0042 
0043     /* Setup address */
0044     GT_WRITE(GT_PCI0_CFGADDR_OFS,
0045          (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) |
0046          (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
0047          ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
0048          GT_PCI0_CFGADDR_CONFIGEN_BIT);
0049 
0050     if (access_type == PCI_ACCESS_WRITE) {
0051         if (busnum == 0 && PCI_SLOT(devfn) == 0) {
0052             /*
0053              * The Galileo system controller is acting
0054              * differently than other devices.
0055              */
0056             GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
0057         } else
0058             __GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
0059     } else {
0060         if (busnum == 0 && PCI_SLOT(devfn) == 0) {
0061             /*
0062              * The Galileo system controller is acting
0063              * differently than other devices.
0064              */
0065             *data = GT_READ(GT_PCI0_CFGDATA_OFS);
0066         } else
0067             *data = __GT_READ(GT_PCI0_CFGDATA_OFS);
0068     }
0069 
0070     /* Check for master or target abort */
0071     intr = GT_READ(GT_INTRCAUSE_OFS);
0072 
0073     if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
0074         /* Error occurred */
0075 
0076         /* Clear bits */
0077         GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
0078                          GT_INTRCAUSE_TARABORT0_BIT));
0079 
0080         return -1;
0081     }
0082 
0083     return 0;
0084 }
0085 
0086 
0087 /*
0088  * We can't address 8 and 16 bit words directly.  Instead we have to
0089  * read/write a 32bit word and mask/modify the data we actually want.
0090  */
0091 static int gt64xxx_pci0_pcibios_read(struct pci_bus *bus, unsigned int devfn,
0092         int where, int size, u32 * val)
0093 {
0094     u32 data = 0;
0095 
0096     if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
0097                            where, &data))
0098         return PCIBIOS_DEVICE_NOT_FOUND;
0099 
0100     if (size == 1)
0101         *val = (data >> ((where & 3) << 3)) & 0xff;
0102     else if (size == 2)
0103         *val = (data >> ((where & 3) << 3)) & 0xffff;
0104     else
0105         *val = data;
0106 
0107     return PCIBIOS_SUCCESSFUL;
0108 }
0109 
0110 static int gt64xxx_pci0_pcibios_write(struct pci_bus *bus, unsigned int devfn,
0111         int where, int size, u32 val)
0112 {
0113     u32 data = 0;
0114 
0115     if (size == 4)
0116         data = val;
0117     else {
0118         if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_READ, bus,
0119                                devfn, where, &data))
0120             return PCIBIOS_DEVICE_NOT_FOUND;
0121 
0122         if (size == 1)
0123             data = (data & ~(0xff << ((where & 3) << 3))) |
0124                 (val << ((where & 3) << 3));
0125         else if (size == 2)
0126             data = (data & ~(0xffff << ((where & 3) << 3))) |
0127                 (val << ((where & 3) << 3));
0128     }
0129 
0130     if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
0131                            where, &data))
0132         return PCIBIOS_DEVICE_NOT_FOUND;
0133 
0134     return PCIBIOS_SUCCESSFUL;
0135 }
0136 
0137 struct pci_ops gt64xxx_pci0_ops = {
0138     .read   = gt64xxx_pci0_pcibios_read,
0139     .write  = gt64xxx_pci0_pcibios_write
0140 };