1 /* 2 * linux/arch/mips/pci/pci-tx4938.c 3 * 4 * Based on linux/arch/mips/txx9/rbtx4938/setup.c, 5 * and RBTX49xx patch from CELF patch archive. 6 * 7 * Copyright 2001, 2003-2005 MontaVista Software Inc. 8 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) 9 * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 10 * 11 * This file is subject to the terms and conditions of the GNU General Public 12 * License. See the file "COPYING" in the main directory of this archive 13 * for more details. 14 */ 15 #include <linux/init.h> 16 #include <linux/pci.h> 17 #include <linux/kernel.h> 18 #include <linux/interrupt.h> 19 #include <asm/txx9/generic.h> 20 #include <asm/txx9/tx4938.h> 21 22 int __init tx4938_report_pciclk(void) 23 { 24 int pciclk = 0; 25 26 printk(KERN_INFO "PCIC --%s PCICLK:", 27 (__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCI66) ? 28 " PCI66" : ""); 29 if (__raw_readq(&tx4938_ccfgptr->pcfg) & TX4938_PCFG_PCICLKEN_ALL) { 30 u64 ccfg = __raw_readq(&tx4938_ccfgptr->ccfg); 31 switch ((unsigned long)ccfg & 32 TX4938_CCFG_PCIDIVMODE_MASK) { 33 case TX4938_CCFG_PCIDIVMODE_4: 34 pciclk = txx9_cpu_clock / 4; break; 35 case TX4938_CCFG_PCIDIVMODE_4_5: 36 pciclk = txx9_cpu_clock * 2 / 9; break; 37 case TX4938_CCFG_PCIDIVMODE_5: 38 pciclk = txx9_cpu_clock / 5; break; 39 case TX4938_CCFG_PCIDIVMODE_5_5: 40 pciclk = txx9_cpu_clock * 2 / 11; break; 41 case TX4938_CCFG_PCIDIVMODE_8: 42 pciclk = txx9_cpu_clock / 8; break; 43 case TX4938_CCFG_PCIDIVMODE_9: 44 pciclk = txx9_cpu_clock / 9; break; 45 case TX4938_CCFG_PCIDIVMODE_10: 46 pciclk = txx9_cpu_clock / 10; break; 47 case TX4938_CCFG_PCIDIVMODE_11: 48 pciclk = txx9_cpu_clock / 11; break; 49 } 50 printk("Internal(%u.%uMHz)", 51 (pciclk + 50000) / 1000000, 52 ((pciclk + 50000) / 100000) % 10); 53 } else { 54 printk("External"); 55 pciclk = -1; 56 } 57 printk("\n"); 58 return pciclk; 59 } 60 61 void __init tx4938_report_pci1clk(void) 62 { 63 __u64 ccfg = __raw_readq(&tx4938_ccfgptr->ccfg); 64 unsigned int pciclk = 65 txx9_gbus_clock / ((ccfg & TX4938_CCFG_PCI1DMD) ? 4 : 2); 66 67 printk(KERN_INFO "PCIC1 -- %sPCICLK:%u.%uMHz\n", 68 (ccfg & TX4938_CCFG_PCI1_66) ? "PCI66 " : "", 69 (pciclk + 50000) / 1000000, 70 ((pciclk + 50000) / 100000) % 10); 71 } 72 73 int __init tx4938_pciclk66_setup(void) 74 { 75 int pciclk; 76 77 /* Assert M66EN */ 78 tx4938_ccfg_set(TX4938_CCFG_PCI66); 79 /* Double PCICLK (if possible) */ 80 if (__raw_readq(&tx4938_ccfgptr->pcfg) & TX4938_PCFG_PCICLKEN_ALL) { 81 unsigned int pcidivmode = 0; 82 u64 ccfg = __raw_readq(&tx4938_ccfgptr->ccfg); 83 pcidivmode = (unsigned long)ccfg & 84 TX4938_CCFG_PCIDIVMODE_MASK; 85 switch (pcidivmode) { 86 case TX4938_CCFG_PCIDIVMODE_8: 87 case TX4938_CCFG_PCIDIVMODE_4: 88 pcidivmode = TX4938_CCFG_PCIDIVMODE_4; 89 pciclk = txx9_cpu_clock / 4; 90 break; 91 case TX4938_CCFG_PCIDIVMODE_9: 92 case TX4938_CCFG_PCIDIVMODE_4_5: 93 pcidivmode = TX4938_CCFG_PCIDIVMODE_4_5; 94 pciclk = txx9_cpu_clock * 2 / 9; 95 break; 96 case TX4938_CCFG_PCIDIVMODE_10: 97 case TX4938_CCFG_PCIDIVMODE_5: 98 pcidivmode = TX4938_CCFG_PCIDIVMODE_5; 99 pciclk = txx9_cpu_clock / 5; 100 break; 101 case TX4938_CCFG_PCIDIVMODE_11: 102 case TX4938_CCFG_PCIDIVMODE_5_5: 103 default: 104 pcidivmode = TX4938_CCFG_PCIDIVMODE_5_5; 105 pciclk = txx9_cpu_clock * 2 / 11; 106 break; 107 } 108 tx4938_ccfg_change(TX4938_CCFG_PCIDIVMODE_MASK, 109 pcidivmode); 110 printk(KERN_DEBUG "PCICLK: ccfg:%08lx\n", 111 (unsigned long)__raw_readq(&tx4938_ccfgptr->ccfg)); 112 } else 113 pciclk = -1; 114 return pciclk; 115 } 116 117 int __init tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot) 118 { 119 if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4938_pcic1ptr) { 120 switch (slot) { 121 case TX4927_PCIC_IDSEL_AD_TO_SLOT(31): 122 if (__raw_readq(&tx4938_ccfgptr->pcfg) & 123 TX4938_PCFG_ETH0_SEL) 124 return TXX9_IRQ_BASE + TX4938_IR_ETH0; 125 break; 126 case TX4927_PCIC_IDSEL_AD_TO_SLOT(30): 127 if (__raw_readq(&tx4938_ccfgptr->pcfg) & 128 TX4938_PCFG_ETH1_SEL) 129 return TXX9_IRQ_BASE + TX4938_IR_ETH1; 130 break; 131 } 132 return 0; 133 } 134 return -1; 135 } 136 137 void __init tx4938_setup_pcierr_irq(void) 138 { 139 if (request_irq(TXX9_IRQ_BASE + TX4938_IR_PCIERR, 140 tx4927_pcierr_interrupt, 141 IRQF_DISABLED, "PCI error", 142 (void *)TX4927_PCIC_REG)) 143 printk(KERN_WARNING "Failed to request irq for PCIERR\n"); 144 } 145