root/arch/mips/pci/ops-loongson3.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. loongson3_pci_config_access
  2. loongson3_pci_pcibios_read
  3. loongson3_pci_pcibios_write

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/types.h>
   3 #include <linux/pci.h>
   4 #include <linux/kernel.h>
   5 
   6 #include <asm/mips-boards/bonito64.h>
   7 
   8 #include <loongson.h>
   9 
  10 #define PCI_ACCESS_READ  0
  11 #define PCI_ACCESS_WRITE 1
  12 
  13 #define HT1LO_PCICFG_BASE      0x1a000000
  14 #define HT1LO_PCICFG_BASE_TP1  0x1b000000
  15 
  16 static int loongson3_pci_config_access(unsigned char access_type,
  17                 struct pci_bus *bus, unsigned int devfn,
  18                 int where, u32 *data)
  19 {
  20         unsigned char busnum = bus->number;
  21         int function = PCI_FUNC(devfn);
  22         int device = PCI_SLOT(devfn);
  23         int reg = where & ~3;
  24         void *addrp;
  25         u64 addr;
  26 
  27         if (where < PCI_CFG_SPACE_SIZE) { /* standard config */
  28                 addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
  29                 if (busnum == 0) {
  30                         if (device > 31)
  31                                 return PCIBIOS_DEVICE_NOT_FOUND;
  32                         addrp = (void *)TO_UNCAC(HT1LO_PCICFG_BASE | addr);
  33                 } else {
  34                         addrp = (void *)TO_UNCAC(HT1LO_PCICFG_BASE_TP1 | addr);
  35                 }
  36         } else if (where < PCI_CFG_SPACE_EXP_SIZE) {  /* extended config */
  37                 struct pci_dev *rootdev;
  38 
  39                 rootdev = pci_get_domain_bus_and_slot(0, 0, 0);
  40                 if (!rootdev)
  41                         return PCIBIOS_DEVICE_NOT_FOUND;
  42 
  43                 addr = pci_resource_start(rootdev, 3);
  44                 if (!addr)
  45                         return PCIBIOS_DEVICE_NOT_FOUND;
  46 
  47                 addr |= busnum << 20 | device << 15 | function << 12 | reg;
  48                 addrp = (void *)TO_UNCAC(addr);
  49         } else {
  50                 return PCIBIOS_DEVICE_NOT_FOUND;
  51         }
  52 
  53         if (access_type == PCI_ACCESS_WRITE)
  54                 writel(*data, addrp);
  55         else {
  56                 *data = readl(addrp);
  57                 if (*data == 0xffffffff) {
  58                         *data = -1;
  59                         return PCIBIOS_DEVICE_NOT_FOUND;
  60                 }
  61         }
  62         return PCIBIOS_SUCCESSFUL;
  63 }
  64 
  65 static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn,
  66                                  int where, int size, u32 *val)
  67 {
  68         u32 data = 0;
  69         int ret = loongson3_pci_config_access(PCI_ACCESS_READ,
  70                         bus, devfn, where, &data);
  71 
  72         if (ret != PCIBIOS_SUCCESSFUL)
  73                 return ret;
  74 
  75         if (size == 1)
  76                 *val = (data >> ((where & 3) << 3)) & 0xff;
  77         else if (size == 2)
  78                 *val = (data >> ((where & 3) << 3)) & 0xffff;
  79         else
  80                 *val = data;
  81 
  82         return PCIBIOS_SUCCESSFUL;
  83 }
  84 
  85 static int loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn,
  86                                   int where, int size, u32 val)
  87 {
  88         u32 data = 0;
  89         int ret;
  90 
  91         if (size == 4)
  92                 data = val;
  93         else {
  94                 ret = loongson3_pci_config_access(PCI_ACCESS_READ,
  95                                 bus, devfn, where, &data);
  96                 if (ret != PCIBIOS_SUCCESSFUL)
  97                         return ret;
  98 
  99                 if (size == 1)
 100                         data = (data & ~(0xff << ((where & 3) << 3))) |
 101                             (val << ((where & 3) << 3));
 102                 else if (size == 2)
 103                         data = (data & ~(0xffff << ((where & 3) << 3))) |
 104                             (val << ((where & 3) << 3));
 105         }
 106 
 107         ret = loongson3_pci_config_access(PCI_ACCESS_WRITE,
 108                         bus, devfn, where, &data);
 109 
 110         return ret;
 111 }
 112 
 113 struct pci_ops loongson_pci_ops = {
 114         .read = loongson3_pci_pcibios_read,
 115         .write = loongson3_pci_pcibios_write
 116 };

/* [<][>][^][v][top][bottom][index][help] */