Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ops-bonito64.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1999, 2000, 2004 MIPS Technologies, Inc.
3  * All rights reserved.
4  * Authors: Carsten Langgaard <[email protected]>
5  * Maciej W. Rozycki <[email protected]>
6  *
7  * This program is free software; you can distribute it and/or modify it
8  * under the terms of the GNU General Public License (Version 2) as
9  * published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14  * for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19  *
20  * MIPS boards specific PCI support.
21  */
22 #include <linux/types.h>
23 #include <linux/pci.h>
24 #include <linux/kernel.h>
25 #include <linux/init.h>
26 
28 
29 #define PCI_ACCESS_READ 0
30 #define PCI_ACCESS_WRITE 1
31 
32 #define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(_pcictrl_bonito_pcicfg + (offset))
33 #define ID_SEL_BEGIN 10
34 #define MAX_DEV_NUM (31 - ID_SEL_BEGIN)
35 
36 
37 static int bonito64_pcibios_config_access(unsigned char access_type,
38  struct pci_bus *bus,
39  unsigned int devfn, int where,
40  u32 * data)
41 {
42  u32 busnum = bus->number;
43  u32 addr, type;
44  u32 dummy;
45  void *addrp;
46  int device = PCI_SLOT(devfn);
47  int function = PCI_FUNC(devfn);
48  int reg = where & ~3;
49 
50  if (busnum == 0) {
51  /* Type 0 configuration for onboard PCI bus */
52  if (device > MAX_DEV_NUM)
53  return -1;
54 
55  addr = (1 << (device + ID_SEL_BEGIN)) | (function << 8) | reg;
56  type = 0;
57  } else {
58  /* Type 1 configuration for offboard PCI bus */
59  addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
60  type = 0x10000;
61  }
62 
63  /* Clear aborts */
65 
66  BONITO_PCIMAP_CFG = (addr >> 16) | type;
67 
68  /* Flush Bonito register block */
69  dummy = BONITO_PCIMAP_CFG;
70  mmiowb();
71 
72  addrp = CFG_SPACE_REG(addr & 0xffff);
73  if (access_type == PCI_ACCESS_WRITE) {
74  writel(cpu_to_le32(*data), addrp);
75  /* Wait till done */
76  while (BONITO_PCIMSTAT & 0xF);
77  } else {
78  *data = le32_to_cpu(readl(addrp));
79  }
80 
81  /* Detect Master/Target abort */
84  /* Error occurred */
85 
86  /* Clear bits */
89 
90  return -1;
91  }
92 
93  return 0;
94 
95 }
96 
97 
98 /*
99  * We can't address 8 and 16 bit words directly. Instead we have to
100  * read/write a 32bit word and mask/modify the data we actually want.
101  */
102 static int bonito64_pcibios_read(struct pci_bus *bus, unsigned int devfn,
103  int where, int size, u32 * val)
104 {
105  u32 data = 0;
106 
107  if ((size == 2) && (where & 1))
109  else if ((size == 4) && (where & 3))
111 
112  if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
113  &data))
114  return -1;
115 
116  if (size == 1)
117  *val = (data >> ((where & 3) << 3)) & 0xff;
118  else if (size == 2)
119  *val = (data >> ((where & 3) << 3)) & 0xffff;
120  else
121  *val = data;
122 
123  return PCIBIOS_SUCCESSFUL;
124 }
125 
126 static int bonito64_pcibios_write(struct pci_bus *bus, unsigned int devfn,
127  int where, int size, u32 val)
128 {
129  u32 data = 0;
130 
131  if ((size == 2) && (where & 1))
133  else if ((size == 4) && (where & 3))
135 
136  if (size == 4)
137  data = val;
138  else {
139  if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
140  where, &data))
141  return -1;
142 
143  if (size == 1)
144  data = (data & ~(0xff << ((where & 3) << 3))) |
145  (val << ((where & 3) << 3));
146  else if (size == 2)
147  data = (data & ~(0xffff << ((where & 3) << 3))) |
148  (val << ((where & 3) << 3));
149  }
150 
151  if (bonito64_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
152  &data))
153  return -1;
154 
155  return PCIBIOS_SUCCESSFUL;
156 }
157 
159  .read = bonito64_pcibios_read,
160  .write = bonito64_pcibios_write
161 };