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