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.21 455 lines 13 kB view raw
1/* 2 * Workaround for device erratum PCI 9. 3 * See Motorola's "XPC826xA Family Device Errata Reference." 4 * The erratum applies to all 8260 family Hip4 processors. It is scheduled 5 * to be fixed in HiP4 Rev C. Erratum PCI 9 states that a simultaneous PCI 6 * inbound write transaction and PCI outbound read transaction can result in a 7 * bus deadlock. The suggested workaround is to use the IDMA controller to 8 * perform all reads from PCI configuration, memory, and I/O space. 9 * 10 * Author: andy_lowe@mvista.com 11 * 12 * 2003 (c) MontaVista Software, Inc. This file is licensed under 13 * the terms of the GNU General Public License version 2. This program 14 * is licensed "as is" without any warranty of any kind, whether express 15 * or implied. 16 */ 17#include <linux/kernel.h> 18#include <linux/module.h> 19#include <linux/pci.h> 20#include <linux/types.h> 21#include <linux/string.h> 22 23#include <asm/io.h> 24#include <asm/pci-bridge.h> 25#include <asm/machdep.h> 26#include <asm/byteorder.h> 27#include <asm/mpc8260.h> 28#include <asm/immap_cpm2.h> 29#include <asm/cpm2.h> 30 31#include "m82xx_pci.h" 32 33#ifdef CONFIG_8260_PCI9 34/*#include <asm/mpc8260_pci9.h>*/ /* included in asm/io.h */ 35 36#define IDMA_XFER_BUF_SIZE 64 /* size of the IDMA transfer buffer */ 37 38/* define a structure for the IDMA dpram usage */ 39typedef struct idma_dpram_s { 40 idma_t pram; /* IDMA parameter RAM */ 41 u_char xfer_buf[IDMA_XFER_BUF_SIZE]; /* IDMA transfer buffer */ 42 idma_bd_t bd; /* buffer descriptor */ 43} idma_dpram_t; 44 45/* define offsets relative to start of IDMA dpram */ 46#define IDMA_XFER_BUF_OFFSET (sizeof(idma_t)) 47#define IDMA_BD_OFFSET (sizeof(idma_t) + IDMA_XFER_BUF_SIZE) 48 49/* define globals */ 50static volatile idma_dpram_t *idma_dpram; 51 52/* Exactly one of CONFIG_8260_PCI9_IDMAn must be defined, 53 * where n is 1, 2, 3, or 4. This selects the IDMA channel used for 54 * the PCI9 workaround. 55 */ 56#ifdef CONFIG_8260_PCI9_IDMA1 57#define IDMA_CHAN 0 58#define PROFF_IDMA PROFF_IDMA1_BASE 59#define IDMA_PAGE CPM_CR_IDMA1_PAGE 60#define IDMA_SBLOCK CPM_CR_IDMA1_SBLOCK 61#endif 62#ifdef CONFIG_8260_PCI9_IDMA2 63#define IDMA_CHAN 1 64#define PROFF_IDMA PROFF_IDMA2_BASE 65#define IDMA_PAGE CPM_CR_IDMA2_PAGE 66#define IDMA_SBLOCK CPM_CR_IDMA2_SBLOCK 67#endif 68#ifdef CONFIG_8260_PCI9_IDMA3 69#define IDMA_CHAN 2 70#define PROFF_IDMA PROFF_IDMA3_BASE 71#define IDMA_PAGE CPM_CR_IDMA3_PAGE 72#define IDMA_SBLOCK CPM_CR_IDMA3_SBLOCK 73#endif 74#ifdef CONFIG_8260_PCI9_IDMA4 75#define IDMA_CHAN 3 76#define PROFF_IDMA PROFF_IDMA4_BASE 77#define IDMA_PAGE CPM_CR_IDMA4_PAGE 78#define IDMA_SBLOCK CPM_CR_IDMA4_SBLOCK 79#endif 80 81void idma_pci9_init(void) 82{ 83 uint dpram_offset; 84 volatile idma_t *pram; 85 volatile im_idma_t *idma_reg; 86 volatile cpm2_map_t *immap = cpm2_immr; 87 88 /* allocate IDMA dpram */ 89 dpram_offset = cpm_dpalloc(sizeof(idma_dpram_t), 64); 90 idma_dpram = cpm_dpram_addr(dpram_offset); 91 92 /* initialize the IDMA parameter RAM */ 93 memset((void *)idma_dpram, 0, sizeof(idma_dpram_t)); 94 pram = &idma_dpram->pram; 95 pram->ibase = dpram_offset + IDMA_BD_OFFSET; 96 pram->dpr_buf = dpram_offset + IDMA_XFER_BUF_OFFSET; 97 pram->ss_max = 32; 98 pram->dts = 32; 99 100 /* initialize the IDMA_BASE pointer to the IDMA parameter RAM */ 101 *((ushort *) &immap->im_dprambase[PROFF_IDMA]) = dpram_offset; 102 103 /* initialize the IDMA registers */ 104 idma_reg = (volatile im_idma_t *) &immap->im_sdma.sdma_idsr1; 105 idma_reg[IDMA_CHAN].idmr = 0; /* mask all IDMA interrupts */ 106 idma_reg[IDMA_CHAN].idsr = 0xff; /* clear all event flags */ 107 108 printk(KERN_WARNING 109 "Using IDMA%d for MPC8260 device erratum PCI 9 workaround\n", 110 IDMA_CHAN + 1); 111 112 return; 113} 114 115/* Use the IDMA controller to transfer data from I/O memory to local RAM. 116 * The src address must be a physical address suitable for use by the DMA 117 * controller with no translation. The dst address must be a kernel virtual 118 * address. The dst address is translated to a physical address via 119 * virt_to_phys(). 120 * The sinc argument specifies whether or not the source address is incremented 121 * by the DMA controller. The source address is incremented if and only if sinc 122 * is non-zero. The destination address is always incremented since the 123 * destination is always host RAM. 124 */ 125static void 126idma_pci9_read(u8 *dst, u8 *src, int bytes, int unit_size, int sinc) 127{ 128 unsigned long flags; 129 volatile idma_t *pram = &idma_dpram->pram; 130 volatile idma_bd_t *bd = &idma_dpram->bd; 131 volatile cpm2_map_t *immap = cpm2_immr; 132 133 local_irq_save(flags); 134 135 /* initialize IDMA parameter RAM for this transfer */ 136 if (sinc) 137 pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_SINC 138 | IDMA_DCM_DINC | IDMA_DCM_SD_MEM2MEM; 139 else 140 pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_DINC 141 | IDMA_DCM_SD_MEM2MEM; 142 pram->ibdptr = pram->ibase; 143 pram->sts = unit_size; 144 pram->istate = 0; 145 146 /* initialize the buffer descriptor */ 147 bd->dst = virt_to_phys(dst); 148 bd->src = (uint) src; 149 bd->len = bytes; 150 bd->flags = IDMA_BD_V | IDMA_BD_W | IDMA_BD_I | IDMA_BD_L | IDMA_BD_DGBL 151 | IDMA_BD_DBO_BE | IDMA_BD_SBO_BE | IDMA_BD_SDTB; 152 153 /* issue the START_IDMA command to the CP */ 154 while (immap->im_cpm.cp_cpcr & CPM_CR_FLG); 155 immap->im_cpm.cp_cpcr = mk_cr_cmd(IDMA_PAGE, IDMA_SBLOCK, 0, 156 CPM_CR_START_IDMA) | CPM_CR_FLG; 157 while (immap->im_cpm.cp_cpcr & CPM_CR_FLG); 158 159 /* wait for transfer to complete */ 160 while(bd->flags & IDMA_BD_V); 161 162 local_irq_restore(flags); 163 164 return; 165} 166 167/* Use the IDMA controller to transfer data from I/O memory to local RAM. 168 * The dst address must be a physical address suitable for use by the DMA 169 * controller with no translation. The src address must be a kernel virtual 170 * address. The src address is translated to a physical address via 171 * virt_to_phys(). 172 * The dinc argument specifies whether or not the dest address is incremented 173 * by the DMA controller. The source address is incremented if and only if sinc 174 * is non-zero. The source address is always incremented since the 175 * source is always host RAM. 176 */ 177static void 178idma_pci9_write(u8 *dst, u8 *src, int bytes, int unit_size, int dinc) 179{ 180 unsigned long flags; 181 volatile idma_t *pram = &idma_dpram->pram; 182 volatile idma_bd_t *bd = &idma_dpram->bd; 183 volatile cpm2_map_t *immap = cpm2_immr; 184 185 local_irq_save(flags); 186 187 /* initialize IDMA parameter RAM for this transfer */ 188 if (dinc) 189 pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_SINC 190 | IDMA_DCM_DINC | IDMA_DCM_SD_MEM2MEM; 191 else 192 pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_SINC 193 | IDMA_DCM_SD_MEM2MEM; 194 pram->ibdptr = pram->ibase; 195 pram->sts = unit_size; 196 pram->istate = 0; 197 198 /* initialize the buffer descriptor */ 199 bd->dst = (uint) dst; 200 bd->src = virt_to_phys(src); 201 bd->len = bytes; 202 bd->flags = IDMA_BD_V | IDMA_BD_W | IDMA_BD_I | IDMA_BD_L | IDMA_BD_DGBL 203 | IDMA_BD_DBO_BE | IDMA_BD_SBO_BE | IDMA_BD_SDTB; 204 205 /* issue the START_IDMA command to the CP */ 206 while (immap->im_cpm.cp_cpcr & CPM_CR_FLG); 207 immap->im_cpm.cp_cpcr = mk_cr_cmd(IDMA_PAGE, IDMA_SBLOCK, 0, 208 CPM_CR_START_IDMA) | CPM_CR_FLG; 209 while (immap->im_cpm.cp_cpcr & CPM_CR_FLG); 210 211 /* wait for transfer to complete */ 212 while(bd->flags & IDMA_BD_V); 213 214 local_irq_restore(flags); 215 216 return; 217} 218 219/* Same as idma_pci9_read, but 16-bit little-endian byte swapping is performed 220 * if the unit_size is 2, and 32-bit little-endian byte swapping is performed if 221 * the unit_size is 4. 222 */ 223static void 224idma_pci9_read_le(u8 *dst, u8 *src, int bytes, int unit_size, int sinc) 225{ 226 int i; 227 u8 *p; 228 229 idma_pci9_read(dst, src, bytes, unit_size, sinc); 230 switch(unit_size) { 231 case 2: 232 for (i = 0, p = dst; i < bytes; i += 2, p += 2) 233 swab16s((u16 *) p); 234 break; 235 case 4: 236 for (i = 0, p = dst; i < bytes; i += 4, p += 4) 237 swab32s((u32 *) p); 238 break; 239 default: 240 break; 241 } 242} 243EXPORT_SYMBOL(idma_pci9_init); 244EXPORT_SYMBOL(idma_pci9_read); 245EXPORT_SYMBOL(idma_pci9_read_le); 246 247static inline int is_pci_mem(unsigned long addr) 248{ 249 if (addr >= M82xx_PCI_LOWER_MMIO && 250 addr <= M82xx_PCI_UPPER_MMIO) 251 return 1; 252 if (addr >= M82xx_PCI_LOWER_MEM && 253 addr <= M82xx_PCI_UPPER_MEM) 254 return 1; 255 return 0; 256} 257 258#define is_pci_mem(pa) ( (pa > 0x80000000) && (pa < 0xc0000000)) 259int readb(volatile unsigned char *addr) 260{ 261 u8 val; 262 unsigned long pa = iopa((unsigned long) addr); 263 264 if (!is_pci_mem(pa)) 265 return in_8(addr); 266 267 idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0); 268 return val; 269} 270 271int readw(volatile unsigned short *addr) 272{ 273 u16 val; 274 unsigned long pa = iopa((unsigned long) addr); 275 276 if (!is_pci_mem(pa)) 277 return in_le16(addr); 278 279 idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0); 280 return swab16(val); 281} 282 283unsigned readl(volatile unsigned *addr) 284{ 285 u32 val; 286 unsigned long pa = iopa((unsigned long) addr); 287 288 if (!is_pci_mem(pa)) 289 return in_le32(addr); 290 291 idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0); 292 return swab32(val); 293} 294 295int inb(unsigned port) 296{ 297 u8 val; 298 u8 *addr = (u8 *)(port + _IO_BASE); 299 300 idma_pci9_read((u8 *)&val, (u8 *)addr, sizeof(val), sizeof(val), 0); 301 return val; 302} 303 304int inw(unsigned port) 305{ 306 u16 val; 307 u8 *addr = (u8 *)(port + _IO_BASE); 308 309 idma_pci9_read((u8 *)&val, (u8 *)addr, sizeof(val), sizeof(val), 0); 310 return swab16(val); 311} 312 313unsigned inl(unsigned port) 314{ 315 u32 val; 316 u8 *addr = (u8 *)(port + _IO_BASE); 317 318 idma_pci9_read((u8 *)&val, (u8 *)addr, sizeof(val), sizeof(val), 0); 319 return swab32(val); 320} 321 322void insb(unsigned port, void *buf, int ns) 323{ 324 u8 *addr = (u8 *)(port + _IO_BASE); 325 326 idma_pci9_read((u8 *)buf, (u8 *)addr, ns*sizeof(u8), sizeof(u8), 0); 327} 328 329void insw(unsigned port, void *buf, int ns) 330{ 331 u8 *addr = (u8 *)(port + _IO_BASE); 332 333 idma_pci9_read((u8 *)buf, (u8 *)addr, ns*sizeof(u16), sizeof(u16), 0); 334} 335 336void insl(unsigned port, void *buf, int nl) 337{ 338 u8 *addr = (u8 *)(port + _IO_BASE); 339 340 idma_pci9_read((u8 *)buf, (u8 *)addr, nl*sizeof(u32), sizeof(u32), 0); 341} 342 343void *memcpy_fromio(void *dest, unsigned long src, size_t count) 344{ 345 unsigned long pa = iopa((unsigned long) src); 346 347 if (is_pci_mem(pa)) 348 idma_pci9_read((u8 *)dest, (u8 *)pa, count, 32, 1); 349 else 350 memcpy(dest, (void *)src, count); 351 return dest; 352} 353 354EXPORT_SYMBOL(readb); 355EXPORT_SYMBOL(readw); 356EXPORT_SYMBOL(readl); 357EXPORT_SYMBOL(inb); 358EXPORT_SYMBOL(inw); 359EXPORT_SYMBOL(inl); 360EXPORT_SYMBOL(insb); 361EXPORT_SYMBOL(insw); 362EXPORT_SYMBOL(insl); 363EXPORT_SYMBOL(memcpy_fromio); 364 365#endif /* ifdef CONFIG_8260_PCI9 */ 366 367/* Indirect PCI routines adapted from arch/ppc/kernel/indirect_pci.c. 368 * Copyright (C) 1998 Gabriel Paubert. 369 */ 370#ifndef CONFIG_8260_PCI9 371#define cfg_read(val, addr, type, op) *val = op((type)(addr)) 372#else 373#define cfg_read(val, addr, type, op) \ 374 idma_pci9_read_le((u8*)(val),(u8*)(addr),sizeof(*(val)),sizeof(*(val)),0) 375#endif 376 377#define cfg_write(val, addr, type, op) op((type *)(addr), (val)) 378 379static int indirect_write_config(struct pci_bus *pbus, unsigned int devfn, int where, 380 int size, u32 value) 381{ 382 struct pci_controller *hose = pbus->sysdata; 383 u8 cfg_type = 0; 384 if (ppc_md.pci_exclude_device) 385 if (ppc_md.pci_exclude_device(pbus->number, devfn)) 386 return PCIBIOS_DEVICE_NOT_FOUND; 387 388 if (hose->set_cfg_type) 389 if (pbus->number != hose->first_busno) 390 cfg_type = 1; 391 392 out_be32(hose->cfg_addr, 393 (((where & 0xfc) | cfg_type) << 24) | (devfn << 16) 394 | ((pbus->number - hose->bus_offset) << 8) | 0x80); 395 396 switch (size) 397 { 398 case 1: 399 cfg_write(value, hose->cfg_data + (where & 3), u8, out_8); 400 break; 401 case 2: 402 cfg_write(value, hose->cfg_data + (where & 2), u16, out_le16); 403 break; 404 case 4: 405 cfg_write(value, hose->cfg_data + (where & 0), u32, out_le32); 406 break; 407 } 408 return PCIBIOS_SUCCESSFUL; 409} 410 411static int indirect_read_config(struct pci_bus *pbus, unsigned int devfn, int where, 412 int size, u32 *value) 413{ 414 struct pci_controller *hose = pbus->sysdata; 415 u8 cfg_type = 0; 416 if (ppc_md.pci_exclude_device) 417 if (ppc_md.pci_exclude_device(pbus->number, devfn)) 418 return PCIBIOS_DEVICE_NOT_FOUND; 419 420 if (hose->set_cfg_type) 421 if (pbus->number != hose->first_busno) 422 cfg_type = 1; 423 424 out_be32(hose->cfg_addr, 425 (((where & 0xfc) | cfg_type) << 24) | (devfn << 16) 426 | ((pbus->number - hose->bus_offset) << 8) | 0x80); 427 428 switch (size) 429 { 430 case 1: 431 cfg_read(value, hose->cfg_data + (where & 3), u8 *, in_8); 432 break; 433 case 2: 434 cfg_read(value, hose->cfg_data + (where & 2), u16 *, in_le16); 435 break; 436 case 4: 437 cfg_read(value, hose->cfg_data + (where & 0), u32 *, in_le32); 438 break; 439 } 440 return PCIBIOS_SUCCESSFUL; 441} 442 443static struct pci_ops indirect_pci_ops = 444{ 445 .read = indirect_read_config, 446 .write = indirect_write_config, 447}; 448 449void 450setup_m8260_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) 451{ 452 hose->ops = &indirect_pci_ops; 453 hose->cfg_addr = (unsigned int *) ioremap(cfg_addr, 4); 454 hose->cfg_data = (unsigned char *) ioremap(cfg_data, 4); 455}