Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.13 444 lines 11 kB view raw
1/* 2 * hades-pci.c - Hardware specific PCI BIOS functions the Hades Atari clone. 3 * 4 * Written by Wout Klaren. 5 */ 6 7#include <linux/config.h> 8#include <linux/init.h> 9#include <linux/kernel.h> 10#include <asm/io.h> 11 12#if 0 13# define DBG_DEVS(args) printk args 14#else 15# define DBG_DEVS(args) 16#endif 17 18#if defined(CONFIG_PCI) && defined(CONFIG_HADES) 19 20#include <linux/slab.h> 21#include <linux/mm.h> 22#include <linux/pci.h> 23 24#include <asm/atarihw.h> 25#include <asm/atariints.h> 26#include <asm/byteorder.h> 27#include <asm/pci.h> 28 29#define HADES_MEM_BASE 0x80000000 30#define HADES_MEM_SIZE 0x20000000 31#define HADES_CONFIG_BASE 0xA0000000 32#define HADES_CONFIG_SIZE 0x10000000 33#define HADES_IO_BASE 0xB0000000 34#define HADES_IO_SIZE 0x10000000 35#define HADES_VIRT_IO_SIZE 0x00010000 /* Only 64k is remapped and actually used. */ 36 37#define N_SLOTS 4 /* Number of PCI slots. */ 38 39static const char pci_mem_name[] = "PCI memory space"; 40static const char pci_io_name[] = "PCI I/O space"; 41static const char pci_config_name[] = "PCI config space"; 42 43static struct resource config_space = { 44 .name = pci_config_name, 45 .start = HADES_CONFIG_BASE, 46 .end = HADES_CONFIG_BASE + HADES_CONFIG_SIZE - 1 47}; 48static struct resource io_space = { 49 .name = pci_io_name, 50 .start = HADES_IO_BASE, 51 .end = HADES_IO_BASE + HADES_IO_SIZE - 1 52}; 53 54static const unsigned long pci_conf_base_phys[] = { 55 0xA0080000, 0xA0040000, 0xA0020000, 0xA0010000 56}; 57static unsigned long pci_conf_base_virt[N_SLOTS]; 58static unsigned long pci_io_base_virt; 59 60/* 61 * static void *mk_conf_addr(unsigned char bus, unsigned char device_fn, 62 * unsigned char where) 63 * 64 * Calculate the address of the PCI configuration area of the given 65 * device. 66 * 67 * BUG: boards with multiple functions are probably not correctly 68 * supported. 69 */ 70 71static void *mk_conf_addr(struct pci_dev *dev, int where) 72{ 73 int device = dev->devfn >> 3, function = dev->devfn & 7; 74 void *result; 75 76 DBG_DEVS(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p)\n", 77 dev->bus->number, dev->devfn, where, pci_addr)); 78 79 if (device > 3) 80 { 81 DBG_DEVS(("mk_conf_addr: device (%d) > 3, returning NULL\n", device)); 82 return NULL; 83 } 84 85 if (dev->bus->number != 0) 86 { 87 DBG_DEVS(("mk_conf_addr: bus (%d) > 0, returning NULL\n", device)); 88 return NULL; 89 } 90 91 result = (void *) (pci_conf_base_virt[device] | (function << 8) | (where)); 92 DBG_DEVS(("mk_conf_addr: returning pci_addr 0x%lx\n", (unsigned long) result)); 93 return result; 94} 95 96static int hades_read_config_byte(struct pci_dev *dev, int where, u8 *value) 97{ 98 volatile unsigned char *pci_addr; 99 100 *value = 0xff; 101 102 if ((pci_addr = (unsigned char *) mk_conf_addr(dev, where)) == NULL) 103 return PCIBIOS_DEVICE_NOT_FOUND; 104 105 *value = *pci_addr; 106 107 return PCIBIOS_SUCCESSFUL; 108} 109 110static int hades_read_config_word(struct pci_dev *dev, int where, u16 *value) 111{ 112 volatile unsigned short *pci_addr; 113 114 *value = 0xffff; 115 116 if (where & 0x1) 117 return PCIBIOS_BAD_REGISTER_NUMBER; 118 119 if ((pci_addr = (unsigned short *) mk_conf_addr(dev, where)) == NULL) 120 return PCIBIOS_DEVICE_NOT_FOUND; 121 122 *value = le16_to_cpu(*pci_addr); 123 124 return PCIBIOS_SUCCESSFUL; 125} 126 127static int hades_read_config_dword(struct pci_dev *dev, int where, u32 *value) 128{ 129 volatile unsigned int *pci_addr; 130 unsigned char header_type; 131 int result; 132 133 *value = 0xffffffff; 134 135 if (where & 0x3) 136 return PCIBIOS_BAD_REGISTER_NUMBER; 137 138 if ((pci_addr = (unsigned int *) mk_conf_addr(dev, where)) == NULL) 139 return PCIBIOS_DEVICE_NOT_FOUND; 140 141 *value = le32_to_cpu(*pci_addr); 142 143 /* 144 * Check if the value is an address on the bus. If true, add the 145 * base address of the PCI memory or PCI I/O area on the Hades. 146 */ 147 148 if ((result = hades_read_config_byte(dev, PCI_HEADER_TYPE, 149 &header_type)) != PCIBIOS_SUCCESSFUL) 150 return result; 151 152 if (((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_1)) || 153 ((header_type != PCI_HEADER_TYPE_BRIDGE) && ((where >= PCI_BASE_ADDRESS_2) && 154 (where <= PCI_BASE_ADDRESS_5)))) 155 { 156 if ((*value & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) 157 { 158 /* 159 * Base address register that contains an I/O address. If the 160 * address is valid on the Hades (0 <= *value < HADES_VIRT_IO_SIZE), 161 * add 'pci_io_base_virt' to the value. 162 */ 163 164 if (*value < HADES_VIRT_IO_SIZE) 165 *value += pci_io_base_virt; 166 } 167 else 168 { 169 /* 170 * Base address register that contains an memory address. If the 171 * address is valid on the Hades (0 <= *value < HADES_MEM_SIZE), 172 * add HADES_MEM_BASE to the value. 173 */ 174 175 if (*value == 0) 176 { 177 /* 178 * Base address is 0. Test if this base 179 * address register is used. 180 */ 181 182 *pci_addr = 0xffffffff; 183 if (*pci_addr != 0) 184 { 185 *pci_addr = *value; 186 if (*value < HADES_MEM_SIZE) 187 *value += HADES_MEM_BASE; 188 } 189 } 190 else 191 { 192 if (*value < HADES_MEM_SIZE) 193 *value += HADES_MEM_BASE; 194 } 195 } 196 } 197 198 return PCIBIOS_SUCCESSFUL; 199} 200 201static int hades_write_config_byte(struct pci_dev *dev, int where, u8 value) 202{ 203 volatile unsigned char *pci_addr; 204 205 if ((pci_addr = (unsigned char *) mk_conf_addr(dev, where)) == NULL) 206 return PCIBIOS_DEVICE_NOT_FOUND; 207 208 *pci_addr = value; 209 210 return PCIBIOS_SUCCESSFUL; 211} 212 213static int hades_write_config_word(struct pci_dev *dev, int where, u16 value) 214{ 215 volatile unsigned short *pci_addr; 216 217 if ((pci_addr = (unsigned short *) mk_conf_addr(dev, where)) == NULL) 218 return PCIBIOS_DEVICE_NOT_FOUND; 219 220 *pci_addr = cpu_to_le16(value); 221 222 return PCIBIOS_SUCCESSFUL; 223} 224 225static int hades_write_config_dword(struct pci_dev *dev, int where, u32 value) 226{ 227 volatile unsigned int *pci_addr; 228 unsigned char header_type; 229 int result; 230 231 if ((pci_addr = (unsigned int *) mk_conf_addr(dev, where)) == NULL) 232 return PCIBIOS_DEVICE_NOT_FOUND; 233 234 /* 235 * Check if the value is an address on the bus. If true, subtract the 236 * base address of the PCI memory or PCI I/O area on the Hades. 237 */ 238 239 if ((result = hades_read_config_byte(dev, PCI_HEADER_TYPE, 240 &header_type)) != PCIBIOS_SUCCESSFUL) 241 return result; 242 243 if (((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_1)) || 244 ((header_type != PCI_HEADER_TYPE_BRIDGE) && ((where >= PCI_BASE_ADDRESS_2) && 245 (where <= PCI_BASE_ADDRESS_5)))) 246 { 247 if ((value & PCI_BASE_ADDRESS_SPACE) == 248 PCI_BASE_ADDRESS_SPACE_IO) 249 { 250 /* 251 * I/O address. Check if the address is valid address on 252 * the Hades (pci_io_base_virt <= value < pci_io_base_virt + 253 * HADES_VIRT_IO_SIZE) or if the value is 0xffffffff. If not 254 * true do not write the base address register. If it is a 255 * valid base address subtract 'pci_io_base_virt' from the value. 256 */ 257 258 if ((value >= pci_io_base_virt) && (value < (pci_io_base_virt + 259 HADES_VIRT_IO_SIZE))) 260 value -= pci_io_base_virt; 261 else 262 { 263 if (value != 0xffffffff) 264 return PCIBIOS_SET_FAILED; 265 } 266 } 267 else 268 { 269 /* 270 * Memory address. Check if the address is valid address on 271 * the Hades (HADES_MEM_BASE <= value < HADES_MEM_BASE + HADES_MEM_SIZE) or 272 * if the value is 0xffffffff. If not true do not write 273 * the base address register. If it is a valid base address 274 * subtract HADES_MEM_BASE from the value. 275 */ 276 277 if ((value >= HADES_MEM_BASE) && (value < (HADES_MEM_BASE + HADES_MEM_SIZE))) 278 value -= HADES_MEM_BASE; 279 else 280 { 281 if (value != 0xffffffff) 282 return PCIBIOS_SET_FAILED; 283 } 284 } 285 } 286 287 *pci_addr = cpu_to_le32(value); 288 289 return PCIBIOS_SUCCESSFUL; 290} 291 292/* 293 * static inline void hades_fixup(void) 294 * 295 * Assign IRQ numbers as used by Linux to the interrupt pins 296 * of the PCI cards. 297 */ 298 299static void __init hades_fixup(int pci_modify) 300{ 301 char irq_tab[4] = { 302 [0] = IRQ_TT_MFP_IO0, /* Slot 0. */ 303 [1] = IRQ_TT_MFP_IO1, /* Slot 1. */ 304 [2] = IRQ_TT_MFP_SCC, /* Slot 2. */ 305 [3] = IRQ_TT_MFP_SCSIDMA /* Slot 3. */ 306 }; 307 struct pci_dev *dev = NULL; 308 unsigned char slot; 309 310 /* 311 * Go through all devices, fixing up irqs as we see fit: 312 */ 313 314 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) 315 { 316 if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) 317 { 318 slot = PCI_SLOT(dev->devfn); /* Determine slot number. */ 319 dev->irq = irq_tab[slot]; 320 if (pci_modify) 321 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); 322 } 323 } 324} 325 326/* 327 * static void hades_conf_device(struct pci_dev *dev) 328 * 329 * Machine dependent Configure the given device. 330 * 331 * Parameters: 332 * 333 * dev - the pci device. 334 */ 335 336static void __init hades_conf_device(struct pci_dev *dev) 337{ 338 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0); 339} 340 341static struct pci_ops hades_pci_ops = { 342 .read_byte = hades_read_config_byte, 343 .read_word = hades_read_config_word, 344 .read_dword = hades_read_config_dword, 345 .write_byte = hades_write_config_byte, 346 .write_word = hades_write_config_word, 347 .write_dword = hades_write_config_dword 348}; 349 350/* 351 * struct pci_bus_info *init_hades_pci(void) 352 * 353 * Machine specific initialisation: 354 * 355 * - Allocate and initialise a 'pci_bus_info' structure 356 * - Initialise hardware 357 * 358 * Result: pointer to 'pci_bus_info' structure. 359 */ 360 361struct pci_bus_info * __init init_hades_pci(void) 362{ 363 struct pci_bus_info *bus; 364 int i; 365 366 /* 367 * Remap I/O and configuration space. 368 */ 369 370 pci_io_base_virt = (unsigned long) ioremap(HADES_IO_BASE, HADES_VIRT_IO_SIZE); 371 372 for (i = 0; i < N_SLOTS; i++) 373 pci_conf_base_virt[i] = (unsigned long) ioremap(pci_conf_base_phys[i], 0x10000); 374 375 /* 376 * Allocate memory for bus info structure. 377 */ 378 379 bus = kmalloc(sizeof(struct pci_bus_info), GFP_KERNEL); 380 if (!bus) 381 return NULL; 382 memset(bus, 0, sizeof(struct pci_bus_info)); 383 384 /* 385 * Claim resources. The m68k has no separate I/O space, both 386 * PCI memory space and PCI I/O space are in memory space. Therefore 387 * the I/O resources are requested in memory space as well. 388 */ 389 390 if (request_resource(&iomem_resource, &config_space) != 0) 391 { 392 kfree(bus); 393 return NULL; 394 } 395 396 if (request_resource(&iomem_resource, &io_space) != 0) 397 { 398 release_resource(&config_space); 399 kfree(bus); 400 return NULL; 401 } 402 403 bus->mem_space.start = HADES_MEM_BASE; 404 bus->mem_space.end = HADES_MEM_BASE + HADES_MEM_SIZE - 1; 405 bus->mem_space.name = pci_mem_name; 406#if 1 407 if (request_resource(&iomem_resource, &bus->mem_space) != 0) 408 { 409 release_resource(&io_space); 410 release_resource(&config_space); 411 kfree(bus); 412 return NULL; 413 } 414#endif 415 bus->io_space.start = pci_io_base_virt; 416 bus->io_space.end = pci_io_base_virt + HADES_VIRT_IO_SIZE - 1; 417 bus->io_space.name = pci_io_name; 418#if 1 419 if (request_resource(&ioport_resource, &bus->io_space) != 0) 420 { 421 release_resource(&bus->mem_space); 422 release_resource(&io_space); 423 release_resource(&config_space); 424 kfree(bus); 425 return NULL; 426 } 427#endif 428 /* 429 * Set hardware dependent functions. 430 */ 431 432 bus->m68k_pci_ops = &hades_pci_ops; 433 bus->fixup = hades_fixup; 434 bus->conf_device = hades_conf_device; 435 436 /* 437 * Select high to low edge for PCI interrupts. 438 */ 439 440 tt_mfp.active_edge &= ~0x27; 441 442 return bus; 443} 444#endif