1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * SNI specific PCI support for RM200/RM300.
7  *
8  * Copyright (C) 1997 - 2000, 2003 Ralf Baechle
9  */
10 #include <linux/config.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/pci.h>
14 #include <linux/types.h>
15 #include <asm/byteorder.h>
16 #include <asm/sni.h>
17 
18 #define mkaddr(dev, where)                                                   \
19 do {                                                                         \
20 	if ((dev)->bus->number == 0)                                         \
21 		return -1;                                                   \
22 	*(volatile u32 *)PCIMT_CONFIG_ADDRESS =                              \
23 		 ((dev->bus->number    & 0xff) << 0x10) |                    \
24 	         ((dev->devfn & 0xff) << 0x08) |                             \
25 	         (where  & 0xfc);                                            \
26 } while(0)
27 
28 /*
29  * We can't address 8 and 16 bit words directly.  Instead we have to
30  * read/write a 32bit word and mask/modify the data we actually want.
31  */
pcimt_read_config_byte(struct pci_dev * dev,int where,unsigned char * val)32 static int pcimt_read_config_byte (struct pci_dev *dev,
33                                    int where, unsigned char *val)
34 {
35 	u32 res;
36 
37 	mkaddr(dev, where);
38 	res = *(volatile u32 *)PCIMT_CONFIG_DATA;
39 	res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xff;
40 	*val = res;
41 
42 	return PCIBIOS_SUCCESSFUL;
43 }
44 
pcimt_read_config_word(struct pci_dev * dev,int where,unsigned short * val)45 static int pcimt_read_config_word (struct pci_dev *dev,
46                                    int where, unsigned short *val)
47 {
48 	u32 res;
49 
50 	if (where & 1)
51 		return PCIBIOS_BAD_REGISTER_NUMBER;
52 	mkaddr(dev, where);
53 	res = *(volatile u32 *)PCIMT_CONFIG_DATA;
54 	res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xffff;
55 	*val = res;
56 
57 	return PCIBIOS_SUCCESSFUL;
58 }
59 
pcimt_read_config_dword(struct pci_dev * dev,int where,unsigned int * val)60 static int pcimt_read_config_dword (struct pci_dev *dev,
61                                     int where, unsigned int *val)
62 {
63 	u32 res;
64 
65 		if (where & 3)
66 		return PCIBIOS_BAD_REGISTER_NUMBER;
67 	mkaddr(dev, where);
68 	res = *(volatile u32 *)PCIMT_CONFIG_DATA;
69 	res = le32_to_cpu(res);
70 	*val = res;
71 
72 	return PCIBIOS_SUCCESSFUL;
73 }
74 
pcimt_write_config_byte(struct pci_dev * dev,int where,unsigned char val)75 static int pcimt_write_config_byte (struct pci_dev *dev,
76                                     int where, unsigned char val)
77 {
78 	mkaddr(dev, where);
79 	*(volatile u8 *)(PCIMT_CONFIG_DATA + (where & 3)) = val;
80 
81 	return PCIBIOS_SUCCESSFUL;
82 }
83 
pcimt_write_config_word(struct pci_dev * dev,int where,unsigned short val)84 static int pcimt_write_config_word (struct pci_dev *dev,
85                                     int where, unsigned short val)
86 {
87 	if (where & 1)
88 		return PCIBIOS_BAD_REGISTER_NUMBER;
89 	mkaddr(dev, where);
90 	*(volatile u16 *)(PCIMT_CONFIG_DATA + (where & 3)) = le16_to_cpu(val);
91 
92 	return PCIBIOS_SUCCESSFUL;
93 }
94 
pcimt_write_config_dword(struct pci_dev * dev,int where,unsigned int val)95 static int pcimt_write_config_dword (struct pci_dev *dev,
96                                      int where, unsigned int val)
97 {
98 	if (where & 3)
99 		return PCIBIOS_BAD_REGISTER_NUMBER;
100 	mkaddr(dev, where);
101 	*(volatile u32 *)PCIMT_CONFIG_DATA = le32_to_cpu(val);
102 
103 	return PCIBIOS_SUCCESSFUL;
104 }
105 
106 struct pci_ops sni_pci_ops = {
107 	pcimt_read_config_byte,
108 	pcimt_read_config_word,
109 	pcimt_read_config_dword,
110 	pcimt_write_config_byte,
111 	pcimt_write_config_word,
112 	pcimt_write_config_dword
113 };
114