1/* 2 * 3 * BRIEF MODULE DESCRIPTION 4 * 5 * 2.6 port, Embedded Alley Solutions, Inc 6 * 7 * Based on: 8 * Author: source@mvista.com 9 * 10 * This program is free software; you can distribute it and/or modify it 11 * under the terms of the GNU General Public License (Version 2) as 12 * published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 * for more details. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write to the Free Software Foundation, Inc., 21 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 22 */ 23#include <linux/types.h> 24#include <linux/pci.h> 25#include <linux/kernel.h> 26#include <linux/init.h> 27#include <linux/vmalloc.h> 28#include <linux/delay.h> 29 30#include <asm/mach-pnx8550/pci.h> 31#include <asm/mach-pnx8550/glb.h> 32#include <asm/debug.h> 33 34 35static inline void clear_status(void) 36{ 37 unsigned long pci_stat; 38 39 pci_stat = inl(PCI_BASE | PCI_GPPM_STATUS); 40 outl(pci_stat, PCI_BASE | PCI_GPPM_ICLR); 41} 42 43static inline unsigned int 44calc_cfg_addr(struct pci_bus *bus, unsigned int devfn, int where) 45{ 46 unsigned int addr; 47 48 addr = ((bus->number > 0) ? (((bus->number & 0xff) << PCI_CFG_BUS_SHIFT) | 1) : 0); 49 addr |= ((devfn & 0xff) << PCI_CFG_FUNC_SHIFT) | (where & 0xfc); 50 51 return addr; 52} 53 54static int 55config_access(unsigned int pci_cmd, struct pci_bus *bus, unsigned int devfn, int where, unsigned int pci_mode, unsigned int *val) 56{ 57 unsigned int flags; 58 unsigned long loops = 0; 59 unsigned long ioaddr = calc_cfg_addr(bus, devfn, where); 60 61 local_irq_save(flags); 62 /*Clear pending interrupt status */ 63 if (inl(PCI_BASE | PCI_GPPM_STATUS)) { 64 clear_status(); 65 while (!(inl(PCI_BASE | PCI_GPPM_STATUS) == 0)) ; 66 } 67 68 outl(ioaddr, PCI_BASE | PCI_GPPM_ADDR); 69 70 if ((pci_cmd == PCI_CMD_IOW) || (pci_cmd == PCI_CMD_CONFIG_WRITE)) 71 outl(*val, PCI_BASE | PCI_GPPM_WDAT); 72 73 outl(INIT_PCI_CYCLE | pci_cmd | (pci_mode & PCI_BYTE_ENABLE_MASK), 74 PCI_BASE | PCI_GPPM_CTRL); 75 76 loops = 77 ((loops_per_jiffy * 78 PCI_IO_JIFFIES_TIMEOUT) >> (PCI_IO_JIFFIES_SHIFT)); 79 while (1) { 80 if (inl(PCI_BASE | PCI_GPPM_STATUS) & GPPM_DONE) { 81 if ((pci_cmd == PCI_CMD_IOR) || 82 (pci_cmd == PCI_CMD_CONFIG_READ)) 83 *val = inl(PCI_BASE | PCI_GPPM_RDAT); 84 clear_status(); 85 local_irq_restore(flags); 86 return PCIBIOS_SUCCESSFUL; 87 } else if (inl(PCI_BASE | PCI_GPPM_STATUS) & GPPM_R_MABORT) { 88 break; 89 } 90 91 loops--; 92 if (loops == 0) { 93 printk("%s : Arbiter Locked.\n", __FUNCTION__); 94 } 95 } 96 97 clear_status(); 98 if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_IOW)) { 99 printk("%s timeout (GPPM_CTRL=%X) ioaddr %lX pci_cmd %X\n", 100 __FUNCTION__, inl(PCI_BASE | PCI_GPPM_CTRL), ioaddr, 101 pci_cmd); 102 } 103 104 if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_CONFIG_READ)) 105 *val = 0xffffffff; 106 local_irq_restore(flags); 107 return PCIBIOS_DEVICE_NOT_FOUND; 108} 109 110/* 111 * We can't address 8 and 16 bit words directly. Instead we have to 112 * read/write a 32bit word and mask/modify the data we actually want. 113 */ 114static int 115read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 * val) 116{ 117 unsigned int data = 0; 118 int err; 119 120 if (bus == 0) 121 return -1; 122 123 err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(1 << (where & 3)), &data); 124 switch (where & 0x03) { 125 case 0: 126 *val = (unsigned char)(data & 0x000000ff); 127 break; 128 case 1: 129 *val = (unsigned char)((data & 0x0000ff00) >> 8); 130 break; 131 case 2: 132 *val = (unsigned char)((data & 0x00ff0000) >> 16); 133 break; 134 case 3: 135 *val = (unsigned char)((data & 0xff000000) >> 24); 136 break; 137 } 138 139 return err; 140} 141 142static int 143read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 * val) 144{ 145 unsigned int data = 0; 146 int err; 147 148 if (bus == 0) 149 return -1; 150 151 if (where & 0x01) 152 return PCIBIOS_BAD_REGISTER_NUMBER; 153 154 err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(3 << (where & 3)), &data); 155 switch (where & 0x02) { 156 case 0: 157 *val = (unsigned short)(data & 0x0000ffff); 158 break; 159 case 2: 160 *val = (unsigned short)((data & 0xffff0000) >> 16); 161 break; 162 } 163 164 return err; 165} 166 167static int 168read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 * val) 169{ 170 int err; 171 if (bus == 0) 172 return -1; 173 174 if (where & 0x03) 175 return PCIBIOS_BAD_REGISTER_NUMBER; 176 177 err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, 0, val); 178 179 return err; 180} 181 182static int 183write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val) 184{ 185 unsigned int data = (unsigned int)val; 186 int err; 187 188 if (bus == 0) 189 return -1; 190 191 switch (where & 0x03) { 192 case 1: 193 data = (data << 8); 194 break; 195 case 2: 196 data = (data << 16); 197 break; 198 case 3: 199 data = (data << 24); 200 break; 201 default: 202 break; 203 } 204 205 err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, ~(1 << (where & 3)), &data); 206 207 return err; 208} 209 210static int 211write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val) 212{ 213 unsigned int data = (unsigned int)val; 214 int err; 215 216 if (bus == 0) 217 return -1; 218 219 if (where & 0x01) 220 return PCIBIOS_BAD_REGISTER_NUMBER; 221 222 switch (where & 0x02) { 223 case 2: 224 data = (data << 16); 225 break; 226 default: 227 break; 228 } 229 err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, ~(3 << (where & 3)), &data); 230 231 return err; 232} 233 234static int 235write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val) 236{ 237 int err; 238 if (bus == 0) 239 return -1; 240 241 if (where & 0x03) 242 return PCIBIOS_BAD_REGISTER_NUMBER; 243 244 err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, 0, &val); 245 246 return err; 247} 248 249static int config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) 250{ 251 switch (size) { 252 case 1: { 253 u8 _val; 254 int rc = read_config_byte(bus, devfn, where, &_val); 255 *val = _val; 256 return rc; 257 } 258 case 2: { 259 u16 _val; 260 int rc = read_config_word(bus, devfn, where, &_val); 261 *val = _val; 262 return rc; 263 } 264 default: 265 return read_config_dword(bus, devfn, where, val); 266 } 267} 268 269static int config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) 270{ 271 switch (size) { 272 case 1: 273 return write_config_byte(bus, devfn, where, (u8) val); 274 case 2: 275 return write_config_word(bus, devfn, where, (u16) val); 276 default: 277 return write_config_dword(bus, devfn, where, val); 278 } 279} 280 281struct pci_ops pnx8550_pci_ops = { 282 config_read, 283 config_write 284}; 285