Blame view

arch/mips/pci/ops-gt64xxx_pci0.c 4.25 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
aa0980b80   Maciej W. Rozycki   Fixes for system ...
2
3
4
5
   * Copyright (C) 1999, 2000, 2004  MIPS Technologies, Inc.
   *	All rights reserved.
   *	Authors: Carsten Langgaard <carstenl@mips.com>
   *		 Maciej W. Rozycki <macro@mips.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
   *
   *  This program is free software; you can distribute it and/or modify it
   *  under the terms of the GNU General Public License (Version 2) as
   *  published by the Free Software Foundation.
   *
   *  This program is distributed in the hope it will be useful, but WITHOUT
   *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   *  for more details.
   *
   *  You should have received a copy of the GNU General Public License along
   *  with this program; if not, write to the Free Software Foundation, Inc.,
   *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
   */
  #include <linux/types.h>
  #include <linux/pci.h>
  #include <linux/kernel.h>
  
  #include <asm/gt64120.h>
  
  #define PCI_ACCESS_READ  0
  #define PCI_ACCESS_WRITE 1
  
  /*
   *  PCI configuration cycle AD bus definition
   */
  /* Type 0 */
  #define PCI_CFG_TYPE0_REG_SHF           0
  #define PCI_CFG_TYPE0_FUNC_SHF          8
  
  /* Type 1 */
  #define PCI_CFG_TYPE1_REG_SHF           0
  #define PCI_CFG_TYPE1_FUNC_SHF          8
  #define PCI_CFG_TYPE1_DEV_SHF           11
  #define PCI_CFG_TYPE1_BUS_SHF           16
252161ecc   Yoichi Yuasa   [MIPS] merge GT64...
41
42
  static int gt64xxx_pci0_pcibios_config_access(unsigned char access_type,
  		struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
  {
  	unsigned char busnum = bus->number;
  	u32 intr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  	if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0)))
  		return -1;	/* Because of a bug in the galileo (for slot 31). */
  
  	/* Clear cause register bits */
  	GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
  	                             GT_INTRCAUSE_TARABORT0_BIT));
  
  	/* Setup address */
  	GT_WRITE(GT_PCI0_CFGADDR_OFS,
  		 (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) |
  		 (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
  		 ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
  		 GT_PCI0_CFGADDR_CONFIGEN_BIT);
  
  	if (access_type == PCI_ACCESS_WRITE) {
  		if (busnum == 0 && PCI_SLOT(devfn) == 0) {
  			/*
  			 * The Galileo system controller is acting
  			 * differently than other devices.
  			 */
  			GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
  		} else
  			__GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
  	} else {
  		if (busnum == 0 && PCI_SLOT(devfn) == 0) {
  			/*
  			 * The Galileo system controller is acting
  			 * differently than other devices.
  			 */
  			*data = GT_READ(GT_PCI0_CFGDATA_OFS);
  		} else
  			*data = __GT_READ(GT_PCI0_CFGDATA_OFS);
  	}
  
  	/* Check for master or target abort */
  	intr = GT_READ(GT_INTRCAUSE_OFS);
  
  	if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
  		/* Error occurred */
  
  		/* Clear bits */
  		GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
  		                             GT_INTRCAUSE_TARABORT0_BIT));
  
  		return -1;
  	}
  
  	return 0;
  }
  
  
  /*
   * We can't address 8 and 16 bit words directly.  Instead we have to
   * read/write a 32bit word and mask/modify the data we actually want.
   */
252161ecc   Yoichi Yuasa   [MIPS] merge GT64...
101
102
  static int gt64xxx_pci0_pcibios_read(struct pci_bus *bus, unsigned int devfn,
  		int where, int size, u32 * val)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
  {
  	u32 data = 0;
252161ecc   Yoichi Yuasa   [MIPS] merge GT64...
105
106
  	if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
  	                                       where, &data))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
112
113
114
115
116
117
  		return PCIBIOS_DEVICE_NOT_FOUND;
  
  	if (size == 1)
  		*val = (data >> ((where & 3) << 3)) & 0xff;
  	else if (size == 2)
  		*val = (data >> ((where & 3) << 3)) & 0xffff;
  	else
  		*val = data;
  
  	return PCIBIOS_SUCCESSFUL;
  }
252161ecc   Yoichi Yuasa   [MIPS] merge GT64...
118
119
  static int gt64xxx_pci0_pcibios_write(struct pci_bus *bus, unsigned int devfn,
  		int where, int size, u32 val)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
123
124
125
  {
  	u32 data = 0;
  
  	if (size == 4)
  		data = val;
  	else {
252161ecc   Yoichi Yuasa   [MIPS] merge GT64...
126
127
  		if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_READ, bus,
  		                                       devfn, where, &data))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
131
132
133
134
135
136
  			return PCIBIOS_DEVICE_NOT_FOUND;
  
  		if (size == 1)
  			data = (data & ~(0xff << ((where & 3) << 3))) |
  				(val << ((where & 3) << 3));
  		else if (size == 2)
  			data = (data & ~(0xffff << ((where & 3) << 3))) |
  				(val << ((where & 3) << 3));
  	}
252161ecc   Yoichi Yuasa   [MIPS] merge GT64...
137
138
  	if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
  	                                       where, &data))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
  		return PCIBIOS_DEVICE_NOT_FOUND;
  
  	return PCIBIOS_SUCCESSFUL;
  }
252161ecc   Yoichi Yuasa   [MIPS] merge GT64...
143
144
145
  struct pci_ops gt64xxx_pci0_ops = {
  	.read	= gt64xxx_pci0_pcibios_read,
  	.write	= gt64xxx_pci0_pcibios_write
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
  };