PageRenderTime 53ms CodeModel.GetById 17ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/ppc/syslib/m8260_pci_erratum9.c

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