]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - arch/mips/pci/ops-loongson3.c
Merge remote-tracking branches 'asoc/topic/ac97', 'asoc/topic/ac97-mfd', 'asoc/topic...
[mirror_ubuntu-focal-kernel.git] / arch / mips / pci / ops-loongson3.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
c7d3555a
HC
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
16static 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 u_int64_t addr, type;
22 void *addrp;
23 int device = PCI_SLOT(devfn);
24 int function = PCI_FUNC(devfn);
25 int reg = where & ~3;
26
27 addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
28 if (busnum == 0) {
29 if (device > 31)
30 return PCIBIOS_DEVICE_NOT_FOUND;
31 addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE) | (addr & 0xffff));
32 type = 0;
33
34 } else {
35 addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE_TP1) | (addr));
36 type = 0x10000;
37 }
38
39 if (access_type == PCI_ACCESS_WRITE)
40 writel(*data, addrp);
41 else {
42 *data = readl(addrp);
43 if (*data == 0xffffffff) {
44 *data = -1;
45 return PCIBIOS_DEVICE_NOT_FOUND;
46 }
47 }
48 return PCIBIOS_SUCCESSFUL;
49}
50
51static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn,
52 int where, int size, u32 *val)
53{
54 u32 data = 0;
55 int ret = loongson3_pci_config_access(PCI_ACCESS_READ,
56 bus, devfn, where, &data);
57
58 if (ret != PCIBIOS_SUCCESSFUL)
59 return ret;
60
61 if (size == 1)
62 *val = (data >> ((where & 3) << 3)) & 0xff;
63 else if (size == 2)
64 *val = (data >> ((where & 3) << 3)) & 0xffff;
65 else
66 *val = data;
67
68 return PCIBIOS_SUCCESSFUL;
69}
70
71static int loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn,
72 int where, int size, u32 val)
73{
74 u32 data = 0;
75 int ret;
76
77 if (size == 4)
78 data = val;
79 else {
80 ret = loongson3_pci_config_access(PCI_ACCESS_READ,
81 bus, devfn, where, &data);
82 if (ret != PCIBIOS_SUCCESSFUL)
83 return ret;
84
85 if (size == 1)
86 data = (data & ~(0xff << ((where & 3) << 3))) |
87 (val << ((where & 3) << 3));
88 else if (size == 2)
89 data = (data & ~(0xffff << ((where & 3) << 3))) |
90 (val << ((where & 3) << 3));
91 }
92
93 ret = loongson3_pci_config_access(PCI_ACCESS_WRITE,
94 bus, devfn, where, &data);
95
96 return ret;
97}
98
99struct pci_ops loongson_pci_ops = {
100 .read = loongson3_pci_pcibios_read,
101 .write = loongson3_pci_pcibios_write
102};