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