diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_schizo.c')
| -rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 51 | 
1 files changed, 51 insertions, 0 deletions
| diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 5753175b94e6..68b1a63a178c 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -15,6 +15,7 @@  #include <asm/iommu.h>  #include <asm/irq.h>  #include <asm/upa.h> +#include <asm/pstate.h>  #include "pci_impl.h"  #include "iommu_common.h" @@ -326,6 +327,44 @@ static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)  	return ret;  } +static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2) +{ +	unsigned long sync_reg = (unsigned long) _arg2; +	u64 mask = 1 << (__irq_ino(__irq(bucket)) & IMAP_INO); +	u64 val; +	int limit; + +	schizo_write(sync_reg, mask); + +	limit = 100000; +	val = 0; +	while (--limit) { +		val = schizo_read(sync_reg); +		if (!(val & mask)) +			break; +	} +	if (limit <= 0) { +		printk("tomatillo_wsync_handler: DMA won't sync [%lx:%lx]\n", +		       val, mask); +	} + +	if (_arg1) { +		static unsigned char cacheline[64] +			__attribute__ ((aligned (64))); + +		__asm__ __volatile__("rd %%fprs, %0\n\t" +				     "or %0, %4, %1\n\t" +				     "wr %1, 0x0, %%fprs\n\t" +				     "stda %%f0, [%5] %6\n\t" +				     "wr %0, 0x0, %%fprs\n\t" +				     "membar #Sync" +				     : "=&r" (mask), "=&r" (val) +				     : "0" (mask), "1" (val), +				     "i" (FPRS_FEF), "r" (&cacheline[0]), +				     "i" (ASI_BLK_COMMIT_P)); +	} +} +  static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,  				     struct pci_dev *pdev,  				     unsigned int ino) @@ -369,6 +408,15 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,  	bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap));  	bucket->flags |= IBF_PCI; +	if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { +		struct irq_desc *p = bucket->irq_info; + +		p->pre_handler = tomatillo_wsync_handler; +		p->pre_handler_arg1 = ((pbm->chip_version <= 4) ? +				       (void *) 1 : (void *) 0); +		p->pre_handler_arg2 = (void *) pbm->sync_reg; +	} +  	return __irq(bucket);  } @@ -2015,6 +2063,9 @@ static void __init schizo_pbm_init(struct pci_controller_info *p,  	pbm->pbm_regs = pr_regs[0].phys_addr;  	pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL; +	if (chip_type == PBM_CHIP_TYPE_TOMATILLO) +		pbm->sync_reg = pr_regs[3].phys_addr + 0x1a18UL; +  	sprintf(pbm->name,  		(chip_type == PBM_CHIP_TYPE_TOMATILLO ?  		 "TOMATILLO%d PBM%c" : | 
