diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/pci/ops-bonito64.c | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/pci/ops-bonito64.c')
-rw-r--r-- | arch/mips/pci/ops-bonito64.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c new file mode 100644 index 000000000..4d5fe614f --- /dev/null +++ b/arch/mips/pci/ops-bonito64.c | |||
@@ -0,0 +1,148 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /* | ||
3 | * Copyright (C) 1999, 2000, 2004 MIPS Technologies, Inc. | ||
4 | * All rights reserved. | ||
5 | * Authors: Carsten Langgaard <carstenl@mips.com> | ||
6 | * Maciej W. Rozycki <macro@mips.com> | ||
7 | * | ||
8 | * MIPS boards specific PCI support. | ||
9 | */ | ||
10 | #include <linux/types.h> | ||
11 | #include <linux/pci.h> | ||
12 | #include <linux/kernel.h> | ||
13 | |||
14 | #include <asm/mips-boards/bonito64.h> | ||
15 | |||
16 | #define PCI_ACCESS_READ 0 | ||
17 | #define PCI_ACCESS_WRITE 1 | ||
18 | |||
19 | #define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(_pcictrl_bonito_pcicfg + (offset)) | ||
20 | #define ID_SEL_BEGIN 10 | ||
21 | #define MAX_DEV_NUM (31 - ID_SEL_BEGIN) | ||
22 | |||
23 | |||
24 | static int bonito64_pcibios_config_access(unsigned char access_type, | ||
25 | struct pci_bus *bus, | ||
26 | unsigned int devfn, int where, | ||
27 | u32 * data) | ||
28 | { | ||
29 | u32 busnum = bus->number; | ||
30 | u32 addr, type; | ||
31 | u32 dummy; | ||
32 | void *addrp; | ||
33 | int device = PCI_SLOT(devfn); | ||
34 | int function = PCI_FUNC(devfn); | ||
35 | int reg = where & ~3; | ||
36 | |||
37 | if (busnum == 0) { | ||
38 | /* Type 0 configuration for onboard PCI bus */ | ||
39 | if (device > MAX_DEV_NUM) | ||
40 | return -1; | ||
41 | |||
42 | addr = (1 << (device + ID_SEL_BEGIN)) | (function << 8) | reg; | ||
43 | type = 0; | ||
44 | } else { | ||
45 | /* Type 1 configuration for offboard PCI bus */ | ||
46 | addr = (busnum << 16) | (device << 11) | (function << 8) | reg; | ||
47 | type = 0x10000; | ||
48 | } | ||
49 | |||
50 | /* Clear aborts */ | ||
51 | BONITO_PCICMD |= BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR; | ||
52 | |||
53 | BONITO_PCIMAP_CFG = (addr >> 16) | type; | ||
54 | |||
55 | /* Flush Bonito register block */ | ||
56 | dummy = BONITO_PCIMAP_CFG; | ||
57 | mmiowb(); | ||
58 | |||
59 | addrp = CFG_SPACE_REG(addr & 0xffff); | ||
60 | if (access_type == PCI_ACCESS_WRITE) { | ||
61 | writel(cpu_to_le32(*data), addrp); | ||
62 | /* Wait till done */ | ||
63 | while (BONITO_PCIMSTAT & 0xF); | ||
64 | } else { | ||
65 | *data = le32_to_cpu(readl(addrp)); | ||
66 | } | ||
67 | |||
68 | /* Detect Master/Target abort */ | ||
69 | if (BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR | | ||
70 | BONITO_PCICMD_MTABORT_CLR)) { | ||
71 | /* Error occurred */ | ||
72 | |||
73 | /* Clear bits */ | ||
74 | BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR | | ||
75 | BONITO_PCICMD_MTABORT_CLR); | ||
76 | |||
77 | return -1; | ||
78 | } | ||
79 | |||
80 | return 0; | ||
81 | |||
82 | } | ||
83 | |||
84 | |||
85 | /* | ||
86 | * We can't address 8 and 16 bit words directly. Instead we have to | ||
87 | * read/write a 32bit word and mask/modify the data we actually want. | ||
88 | */ | ||
89 | static int bonito64_pcibios_read(struct pci_bus *bus, unsigned int devfn, | ||
90 | int where, int size, u32 * val) | ||
91 | { | ||
92 | u32 data = 0; | ||
93 | |||
94 | if ((size == 2) && (where & 1)) | ||
95 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
96 | else if ((size == 4) && (where & 3)) | ||
97 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
98 | |||
99 | if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, | ||
100 | &data)) | ||
101 | return -1; | ||
102 | |||
103 | if (size == 1) | ||
104 | *val = (data >> ((where & 3) << 3)) & 0xff; | ||
105 | else if (size == 2) | ||
106 | *val = (data >> ((where & 3) << 3)) & 0xffff; | ||
107 | else | ||
108 | *val = data; | ||
109 | |||
110 | return PCIBIOS_SUCCESSFUL; | ||
111 | } | ||
112 | |||
113 | static int bonito64_pcibios_write(struct pci_bus *bus, unsigned int devfn, | ||
114 | int where, int size, u32 val) | ||
115 | { | ||
116 | u32 data = 0; | ||
117 | |||
118 | if ((size == 2) && (where & 1)) | ||
119 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
120 | else if ((size == 4) && (where & 3)) | ||
121 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
122 | |||
123 | if (size == 4) | ||
124 | data = val; | ||
125 | else { | ||
126 | if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, | ||
127 | where, &data)) | ||
128 | return -1; | ||
129 | |||
130 | if (size == 1) | ||
131 | data = (data & ~(0xff << ((where & 3) << 3))) | | ||
132 | (val << ((where & 3) << 3)); | ||
133 | else if (size == 2) | ||
134 | data = (data & ~(0xffff << ((where & 3) << 3))) | | ||
135 | (val << ((where & 3) << 3)); | ||
136 | } | ||
137 | |||
138 | if (bonito64_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, | ||
139 | &data)) | ||
140 | return -1; | ||
141 | |||
142 | return PCIBIOS_SUCCESSFUL; | ||
143 | } | ||
144 | |||
145 | struct pci_ops bonito64_pci_ops = { | ||
146 | .read = bonito64_pcibios_read, | ||
147 | .write = bonito64_pcibios_write | ||
148 | }; | ||