]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/ppc/syslib/m8260_pci_erratum9.c
[POWERPC] remove unused io accessors
[karo-tx-linux.git] / arch / ppc / syslib / m8260_pci_erratum9.c
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 */
39 typedef 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 */
50 static 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
81 void 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("<4>Using IDMA%d for MPC8260 device erratum PCI 9 workaround\n",
109                 IDMA_CHAN + 1);
110
111         return;
112 }
113
114 /* Use the IDMA controller to transfer data from I/O memory to local RAM.
115  * The src address must be a physical address suitable for use by the DMA 
116  * controller with no translation.  The dst address must be a kernel virtual 
117  * address.  The dst address is translated to a physical address via 
118  * virt_to_phys().
119  * The sinc argument specifies whether or not the source address is incremented
120  * by the DMA controller.  The source address is incremented if and only if sinc
121  * is non-zero.  The destination address is always incremented since the 
122  * destination is always host RAM.
123  */
124 static void 
125 idma_pci9_read(u8 *dst, u8 *src, int bytes, int unit_size, int sinc)
126 {
127         unsigned long flags;
128         volatile idma_t *pram = &idma_dpram->pram;
129         volatile idma_bd_t *bd = &idma_dpram->bd;
130         volatile cpm2_map_t *immap = cpm2_immr;
131
132         local_irq_save(flags);
133
134         /* initialize IDMA parameter RAM for this transfer */
135         if (sinc)
136                 pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_SINC
137                           | IDMA_DCM_DINC | IDMA_DCM_SD_MEM2MEM;
138         else
139                 pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_DINC 
140                           | IDMA_DCM_SD_MEM2MEM;
141         pram->ibdptr = pram->ibase;
142         pram->sts = unit_size;
143         pram->istate = 0;
144
145         /* initialize the buffer descriptor */
146         bd->dst = virt_to_phys(dst);
147         bd->src = (uint) src;
148         bd->len = bytes;
149         bd->flags = IDMA_BD_V | IDMA_BD_W | IDMA_BD_I | IDMA_BD_L | IDMA_BD_DGBL
150                   | IDMA_BD_DBO_BE | IDMA_BD_SBO_BE | IDMA_BD_SDTB;
151
152         /* issue the START_IDMA command to the CP */
153         while (immap->im_cpm.cp_cpcr & CPM_CR_FLG);
154         immap->im_cpm.cp_cpcr = mk_cr_cmd(IDMA_PAGE, IDMA_SBLOCK, 0,
155                                          CPM_CR_START_IDMA) | CPM_CR_FLG;
156         while (immap->im_cpm.cp_cpcr & CPM_CR_FLG);
157
158         /* wait for transfer to complete */
159         while(bd->flags & IDMA_BD_V);
160
161         local_irq_restore(flags);
162
163         return;
164 }
165
166 /* Use the IDMA controller to transfer data from I/O memory to local RAM.
167  * The dst address must be a physical address suitable for use by the DMA 
168  * controller with no translation.  The src address must be a kernel virtual 
169  * address.  The src address is translated to a physical address via 
170  * virt_to_phys().
171  * The dinc argument specifies whether or not the dest address is incremented
172  * by the DMA controller.  The source address is incremented if and only if sinc
173  * is non-zero.  The source address is always incremented since the 
174  * source is always host RAM.
175  */
176 static void 
177 idma_pci9_write(u8 *dst, u8 *src, int bytes, int unit_size, int dinc)
178 {
179         unsigned long flags;
180         volatile idma_t *pram = &idma_dpram->pram;
181         volatile idma_bd_t *bd = &idma_dpram->bd;
182         volatile cpm2_map_t *immap = cpm2_immr;
183
184         local_irq_save(flags);
185
186         /* initialize IDMA parameter RAM for this transfer */
187         if (dinc)
188                 pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_SINC
189                           | IDMA_DCM_DINC | IDMA_DCM_SD_MEM2MEM;
190         else
191                 pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_SINC 
192                           | IDMA_DCM_SD_MEM2MEM;
193         pram->ibdptr = pram->ibase;
194         pram->sts = unit_size;
195         pram->istate = 0;
196
197         /* initialize the buffer descriptor */
198         bd->dst = (uint) dst;
199         bd->src = virt_to_phys(src);
200         bd->len = bytes;
201         bd->flags = IDMA_BD_V | IDMA_BD_W | IDMA_BD_I | IDMA_BD_L | IDMA_BD_DGBL
202                   | IDMA_BD_DBO_BE | IDMA_BD_SBO_BE | IDMA_BD_SDTB;
203
204         /* issue the START_IDMA command to the CP */
205         while (immap->im_cpm.cp_cpcr & CPM_CR_FLG);
206         immap->im_cpm.cp_cpcr = mk_cr_cmd(IDMA_PAGE, IDMA_SBLOCK, 0,
207                                          CPM_CR_START_IDMA) | CPM_CR_FLG;
208         while (immap->im_cpm.cp_cpcr & CPM_CR_FLG);
209
210         /* wait for transfer to complete */
211         while(bd->flags & IDMA_BD_V);
212
213         local_irq_restore(flags);
214
215         return;
216 }
217
218 /* Same as idma_pci9_read, but 16-bit little-endian byte swapping is performed
219  * if the unit_size is 2, and 32-bit little-endian byte swapping is performed if
220  * the unit_size is 4.
221  */
222 static void 
223 idma_pci9_read_le(u8 *dst, u8 *src, int bytes, int unit_size, int sinc)
224 {
225         int i;
226         u8 *p;
227
228         idma_pci9_read(dst, src, bytes, unit_size, sinc);
229         switch(unit_size) {
230                 case 2:
231                         for (i = 0, p = dst; i < bytes; i += 2, p += 2)
232                                 swab16s((u16 *) p);
233                         break;
234                 case 4:
235                         for (i = 0, p = dst; i < bytes; i += 4, p += 4)
236                                 swab32s((u32 *) p);
237                         break;
238                 default:
239                         break;
240         }
241 }
242 EXPORT_SYMBOL(idma_pci9_init);
243 EXPORT_SYMBOL(idma_pci9_read);
244 EXPORT_SYMBOL(idma_pci9_read_le);
245
246 static inline int is_pci_mem(unsigned long addr)
247 {
248         if (addr >= M82xx_PCI_LOWER_MMIO &&
249                 addr <= M82xx_PCI_UPPER_MMIO)
250                 return 1;
251         if (addr >= M82xx_PCI_LOWER_MEM &&
252                 addr <= M82xx_PCI_UPPER_MEM)
253                 return 1;
254         return 0;
255 }
256
257 #define is_pci_mem(pa) ( (pa > 0x80000000) && (pa < 0xc0000000))
258 int readb(volatile unsigned char *addr)
259 {
260         u8 val;
261         unsigned long pa = iopa((unsigned long) addr);
262
263         if (!is_pci_mem(pa))
264                 return in_8(addr);
265
266         idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0);
267         return val;
268 }
269
270 int readw(volatile unsigned short *addr)
271 {
272         u16 val;
273         unsigned long pa = iopa((unsigned long) addr);
274
275         if (!is_pci_mem(pa))
276                 return in_le16(addr);
277
278         idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0);
279         return swab16(val);
280 }
281
282 unsigned readl(volatile unsigned *addr)
283 {
284         u32 val;
285         unsigned long pa = iopa((unsigned long) addr);
286
287         if (!is_pci_mem(pa))
288                 return in_le32(addr);
289
290         idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0);
291         return swab32(val);
292 }
293
294 int inb(unsigned port)
295 {
296         u8 val;
297         u8 *addr = (u8 *)(port + _IO_BASE);
298
299         idma_pci9_read((u8 *)&val, (u8 *)addr, sizeof(val), sizeof(val), 0);
300         return val;
301 }
302
303 int inw(unsigned port)
304 {
305         u16 val;
306         u8 *addr = (u8 *)(port + _IO_BASE);
307
308         idma_pci9_read((u8 *)&val, (u8 *)addr, sizeof(val), sizeof(val), 0);
309         return swab16(val);
310 }
311
312 unsigned inl(unsigned port)
313 {
314         u32 val;
315         u8 *addr = (u8 *)(port + _IO_BASE);
316
317         idma_pci9_read((u8 *)&val, (u8 *)addr, sizeof(val), sizeof(val), 0);
318         return swab32(val);
319 }
320
321 void insb(unsigned port, void *buf, int ns)
322 {
323         u8 *addr = (u8 *)(port + _IO_BASE);
324
325         idma_pci9_read((u8 *)buf, (u8 *)addr, ns*sizeof(u8), sizeof(u8), 0);
326 }
327
328 void insw(unsigned port, void *buf, int ns)
329 {
330         u8 *addr = (u8 *)(port + _IO_BASE);
331
332         idma_pci9_read((u8 *)buf, (u8 *)addr, ns*sizeof(u16), sizeof(u16), 0);
333 }
334
335 void insl(unsigned port, void *buf, int nl)
336 {
337         u8 *addr = (u8 *)(port + _IO_BASE);
338
339         idma_pci9_read((u8 *)buf, (u8 *)addr, nl*sizeof(u32), sizeof(u32), 0);
340 }
341
342 void *memcpy_fromio(void *dest, unsigned long src, size_t count)
343 {
344         unsigned long pa = iopa((unsigned long) src);
345
346         if (is_pci_mem(pa))
347                 idma_pci9_read((u8 *)dest, (u8 *)pa, count, 32, 1);
348         else
349                 memcpy(dest, (void *)src, count);
350         return dest;
351 }
352
353 EXPORT_SYMBOL(readb);
354 EXPORT_SYMBOL(readw);
355 EXPORT_SYMBOL(readl);
356 EXPORT_SYMBOL(inb);
357 EXPORT_SYMBOL(inw);
358 EXPORT_SYMBOL(inl);
359 EXPORT_SYMBOL(insb);
360 EXPORT_SYMBOL(insw);
361 EXPORT_SYMBOL(insl);
362 EXPORT_SYMBOL(memcpy_fromio);
363
364 #endif  /* ifdef CONFIG_8260_PCI9 */
365
366 /* Indirect PCI routines adapted from arch/ppc/kernel/indirect_pci.c.
367  * Copyright (C) 1998 Gabriel Paubert.
368  */
369 #ifndef CONFIG_8260_PCI9
370 #define cfg_read(val, addr, type, op)   *val = op((type)(addr))
371 #else
372 #define cfg_read(val, addr, type, op) \
373         idma_pci9_read_le((u8*)(val),(u8*)(addr),sizeof(*(val)),sizeof(*(val)),0)
374 #endif
375
376 #define cfg_write(val, addr, type, op)  op((type *)(addr), (val))
377
378 static int indirect_write_config(struct pci_bus *pbus, unsigned int devfn, int where,
379                          int size, u32 value)
380 {
381         struct pci_controller *hose = pbus->sysdata;
382         u8 cfg_type = 0;
383         if (ppc_md.pci_exclude_device)
384                 if (ppc_md.pci_exclude_device(pbus->number, devfn))
385                         return PCIBIOS_DEVICE_NOT_FOUND;
386
387         if (hose->set_cfg_type)
388                 if (pbus->number != hose->first_busno)
389                         cfg_type = 1;
390
391         out_be32(hose->cfg_addr,
392                  (((where & 0xfc) | cfg_type) << 24) | (devfn << 16)
393                  | ((pbus->number - hose->bus_offset) << 8) | 0x80);
394
395         switch (size)
396         {
397                 case 1:
398                         cfg_write(value, hose->cfg_data + (where & 3), u8, out_8);
399                         break;
400                 case 2:
401                         cfg_write(value, hose->cfg_data + (where & 2), u16, out_le16);
402                         break;
403                 case 4:
404                         cfg_write(value, hose->cfg_data + (where & 0), u32, out_le32);
405                         break;
406         }               
407         return PCIBIOS_SUCCESSFUL;
408 }
409
410 static int indirect_read_config(struct pci_bus *pbus, unsigned int devfn, int where,
411                          int size, u32 *value)
412 {
413         struct pci_controller *hose = pbus->sysdata;
414         u8 cfg_type = 0;
415         if (ppc_md.pci_exclude_device)
416                 if (ppc_md.pci_exclude_device(pbus->number, devfn))
417                         return PCIBIOS_DEVICE_NOT_FOUND;
418
419         if (hose->set_cfg_type)
420                 if (pbus->number != hose->first_busno)
421                         cfg_type = 1;
422
423         out_be32(hose->cfg_addr,
424                  (((where & 0xfc) | cfg_type) << 24) | (devfn << 16)
425                  | ((pbus->number - hose->bus_offset) << 8) | 0x80);
426
427         switch (size)
428         {
429                 case 1:
430                         cfg_read(value, hose->cfg_data + (where & 3), u8 *, in_8);
431                         break;
432                 case 2:
433                         cfg_read(value, hose->cfg_data + (where & 2), u16 *, in_le16);
434                         break;
435                 case 4:
436                         cfg_read(value, hose->cfg_data + (where & 0), u32 *, in_le32);
437                         break;
438         }               
439         return PCIBIOS_SUCCESSFUL;
440 }
441
442 static struct pci_ops indirect_pci_ops =
443 {
444         .read = indirect_read_config,
445         .write = indirect_write_config,
446 };
447
448 void
449 setup_m8260_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
450 {
451         hose->ops = &indirect_pci_ops;
452         hose->cfg_addr = (unsigned int *) ioremap(cfg_addr, 4);
453         hose->cfg_data = (unsigned char *) ioremap(cfg_data, 4);
454 }