xref: /openbmc/linux/arch/mips/pci/ops-bonito64.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1 /*
2  * Carsten Langgaard, carstenl@mips.com
3  * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
4  *
5  *  This program is free software; you can distribute it and/or modify it
6  *  under the terms of the GNU General Public License (Version 2) as
7  *  published by the Free Software Foundation.
8  *
9  *  This program is distributed in the hope it will be useful, but WITHOUT
10  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  *  for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along
15  *  with this program; if not, write to the Free Software Foundation, Inc.,
16  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17  *
18  * MIPS boards specific PCI support.
19  */
20 #include <linux/config.h>
21 #include <linux/types.h>
22 #include <linux/pci.h>
23 #include <linux/kernel.h>
24 #include <linux/init.h>
25 
26 #include <asm/mips-boards/bonito64.h>
27 
28 #define PCI_ACCESS_READ  0
29 #define PCI_ACCESS_WRITE 1
30 
31 /*
32  *  PCI configuration cycle AD bus definition
33  */
34 /* Type 0 */
35 #define PCI_CFG_TYPE0_REG_SHF           0
36 #define PCI_CFG_TYPE0_FUNC_SHF          8
37 
38 /* Type 1 */
39 #define PCI_CFG_TYPE1_REG_SHF           0
40 #define PCI_CFG_TYPE1_FUNC_SHF          8
41 #define PCI_CFG_TYPE1_DEV_SHF           11
42 #define PCI_CFG_TYPE1_BUS_SHF           16
43 
44 static int bonito64_pcibios_config_access(unsigned char access_type,
45 				      struct pci_bus *bus,
46 				      unsigned int devfn, int where,
47 				      u32 * data)
48 {
49 	unsigned char busnum = bus->number;
50 	u32 dummy;
51 	u64 pci_addr;
52 
53 	/* Algorithmics Bonito64 system controller. */
54 
55 	if ((busnum == 0) && (PCI_SLOT(devfn) > 21)) {
56 		/* We number bus 0 devices from 0..21 */
57 		return -1;
58 	}
59 
60 #ifdef CONFIG_MIPS_BOARDS_GEN
61 	if ((busnum == 0) && (PCI_SLOT(devfn) == 17)) {
62 		/* MIPS Core boards have Bonito connected as device 17 */
63 		return -1;
64 	}
65 #endif
66 
67 	/* Clear cause register bits */
68 	BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
69 			  BONITO_PCICMD_MTABORT_CLR);
70 
71 	/*
72 	 * Setup pattern to be used as PCI "address" for
73 	 * Type 0 cycle
74 	 */
75 	if (busnum == 0) {
76 		/* IDSEL */
77 		pci_addr = (u64) 1 << (PCI_SLOT(devfn) + 10);
78 	} else {
79 		/* Bus number */
80 		pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF;
81 
82 		/* Device number */
83 		pci_addr |=
84 		    PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF;
85 	}
86 
87 	/* Function (same for Type 0/1) */
88 	pci_addr |= PCI_FUNC(devfn) << PCI_CFG_TYPE0_FUNC_SHF;
89 
90 	/* Register number (same for Type 0/1) */
91 	pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF;
92 
93 	if (busnum == 0) {
94 		/* Type 0 */
95 		BONITO_PCIMAP_CFG = pci_addr >> 16;
96 	} else {
97 		/* Type 1 */
98 		BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000;
99 	}
100 
101 	pci_addr &= 0xffff;
102 
103 	/* Flush Bonito register block */
104 	dummy = BONITO_PCIMAP_CFG;
105 	iob();		/* sync */
106 
107 	/* Perform access */
108 	if (access_type == PCI_ACCESS_WRITE) {
109 		*(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr) = *(u32 *) data;
110 
111 		/* Wait till done */
112 		while (BONITO_PCIMSTAT & 0xF);
113 	} else {
114 		*(u32 *) data = *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr);
115 	}
116 
117 	/* Detect Master/Target abort */
118 	if (BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR |
119 			     BONITO_PCICMD_MTABORT_CLR)) {
120 		/* Error occurred */
121 
122 		/* Clear bits */
123 		BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
124 				  BONITO_PCICMD_MTABORT_CLR);
125 
126 		return -1;
127 	}
128 
129 	return 0;
130 }
131 
132 
133 /*
134  * We can't address 8 and 16 bit words directly.  Instead we have to
135  * read/write a 32bit word and mask/modify the data we actually want.
136  */
137 static int bonito64_pcibios_read(struct pci_bus *bus, unsigned int devfn,
138 			     int where, int size, u32 * val)
139 {
140 	u32 data = 0;
141 
142 	if ((size == 2) && (where & 1))
143 		return PCIBIOS_BAD_REGISTER_NUMBER;
144 	else if ((size == 4) && (where & 3))
145 		return PCIBIOS_BAD_REGISTER_NUMBER;
146 
147 	if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
148 				       &data))
149 		return -1;
150 
151 	if (size == 1)
152 		*val = (data >> ((where & 3) << 3)) & 0xff;
153 	else if (size == 2)
154 		*val = (data >> ((where & 3) << 3)) & 0xffff;
155 	else
156 		*val = data;
157 
158 	return PCIBIOS_SUCCESSFUL;
159 }
160 
161 static int bonito64_pcibios_write(struct pci_bus *bus, unsigned int devfn,
162 			      int where, int size, u32 val)
163 {
164 	u32 data = 0;
165 
166 	if ((size == 2) && (where & 1))
167 		return PCIBIOS_BAD_REGISTER_NUMBER;
168 	else if ((size == 4) && (where & 3))
169 		return PCIBIOS_BAD_REGISTER_NUMBER;
170 
171 	if (size == 4)
172 		data = val;
173 	else {
174 		if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
175 		                               where, &data))
176 			return -1;
177 
178 		if (size == 1)
179 			data = (data & ~(0xff << ((where & 3) << 3))) |
180 				(val << ((where & 3) << 3));
181 		else if (size == 2)
182 			data = (data & ~(0xffff << ((where & 3) << 3))) |
183 				(val << ((where & 3) << 3));
184 	}
185 
186 	if (bonito64_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
187 				       &data))
188 		return -1;
189 
190 	return PCIBIOS_SUCCESSFUL;
191 }
192 
193 struct pci_ops bonito64_pci_ops = {
194 	.read = bonito64_pcibios_read,
195 	.write = bonito64_pcibios_write
196 };
197