Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 1999, 2000, 2004, 2005  MIPS Technologies, Inc.
0004  *    All rights reserved.
0005  *    Authors: Carsten Langgaard <carstenl@mips.com>
0006  *         Maciej W. Rozycki <macro@mips.com>
0007  * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
0008  *
0009  * MIPS boards specific PCI support.
0010  */
0011 #include <linux/types.h>
0012 #include <linux/pci.h>
0013 #include <linux/kernel.h>
0014 
0015 #include <asm/mips-boards/msc01_pci.h>
0016 
0017 #define PCI_ACCESS_READ  0
0018 #define PCI_ACCESS_WRITE 1
0019 
0020 /*
0021  *  PCI configuration cycle AD bus definition
0022  */
0023 /* Type 0 */
0024 #define PCI_CFG_TYPE0_REG_SHF       0
0025 #define PCI_CFG_TYPE0_FUNC_SHF      8
0026 
0027 /* Type 1 */
0028 #define PCI_CFG_TYPE1_REG_SHF       0
0029 #define PCI_CFG_TYPE1_FUNC_SHF      8
0030 #define PCI_CFG_TYPE1_DEV_SHF       11
0031 #define PCI_CFG_TYPE1_BUS_SHF       16
0032 
0033 static int msc_pcibios_config_access(unsigned char access_type,
0034     struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
0035 {
0036     unsigned char busnum = bus->number;
0037     u32 intr;
0038 
0039     /* Clear status register bits. */
0040     MSC_WRITE(MSC01_PCI_INTSTAT,
0041           (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT));
0042 
0043     MSC_WRITE(MSC01_PCI_CFGADDR,
0044           ((busnum << MSC01_PCI_CFGADDR_BNUM_SHF) |
0045            (PCI_SLOT(devfn) << MSC01_PCI_CFGADDR_DNUM_SHF) |
0046            (PCI_FUNC(devfn) << MSC01_PCI_CFGADDR_FNUM_SHF) |
0047            ((where / 4) << MSC01_PCI_CFGADDR_RNUM_SHF)));
0048 
0049     /* Perform access */
0050     if (access_type == PCI_ACCESS_WRITE)
0051         MSC_WRITE(MSC01_PCI_CFGDATA, *data);
0052     else
0053         MSC_READ(MSC01_PCI_CFGDATA, *data);
0054 
0055     /* Detect Master/Target abort */
0056     MSC_READ(MSC01_PCI_INTSTAT, intr);
0057     if (intr & (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT)) {
0058         /* Error occurred */
0059 
0060         /* Clear bits */
0061         MSC_WRITE(MSC01_PCI_INTSTAT,
0062               (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT));
0063 
0064         return -1;
0065     }
0066 
0067     return 0;
0068 }
0069 
0070 
0071 /*
0072  * We can't address 8 and 16 bit words directly.  Instead we have to
0073  * read/write a 32bit word and mask/modify the data we actually want.
0074  */
0075 static int msc_pcibios_read(struct pci_bus *bus, unsigned int devfn,
0076                  int where, int size, u32 * val)
0077 {
0078     u32 data = 0;
0079 
0080     if ((size == 2) && (where & 1))
0081         return PCIBIOS_BAD_REGISTER_NUMBER;
0082     else if ((size == 4) && (where & 3))
0083         return PCIBIOS_BAD_REGISTER_NUMBER;
0084 
0085     if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
0086                       &data))
0087         return -1;
0088 
0089     if (size == 1)
0090         *val = (data >> ((where & 3) << 3)) & 0xff;
0091     else if (size == 2)
0092         *val = (data >> ((where & 3) << 3)) & 0xffff;
0093     else
0094         *val = data;
0095 
0096     return PCIBIOS_SUCCESSFUL;
0097 }
0098 
0099 static int msc_pcibios_write(struct pci_bus *bus, unsigned int devfn,
0100                   int where, int size, u32 val)
0101 {
0102     u32 data = 0;
0103 
0104     if ((size == 2) && (where & 1))
0105         return PCIBIOS_BAD_REGISTER_NUMBER;
0106     else if ((size == 4) && (where & 3))
0107         return PCIBIOS_BAD_REGISTER_NUMBER;
0108 
0109     if (size == 4)
0110         data = val;
0111     else {
0112         if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
0113                           where, &data))
0114             return -1;
0115 
0116         if (size == 1)
0117             data = (data & ~(0xff << ((where & 3) << 3))) |
0118                 (val << ((where & 3) << 3));
0119         else if (size == 2)
0120             data = (data & ~(0xffff << ((where & 3) << 3))) |
0121                 (val << ((where & 3) << 3));
0122     }
0123 
0124     if (msc_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
0125                        &data))
0126         return -1;
0127 
0128     return PCIBIOS_SUCCESSFUL;
0129 }
0130 
0131 struct pci_ops msc_pci_ops = {
0132     .read = msc_pcibios_read,
0133     .write = msc_pcibios_write
0134 };