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/tx4927.h> |
19 | |
20 | int __init tx4927_report_pciclk(void) |
21 | { |
22 | int pciclk = 0; |
23 | |
24 | pr_info("PCIC --%s PCICLK:" , |
25 | (__raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_PCI66) ? |
26 | " PCI66" : "" ); |
27 | if (__raw_readq(addr: &tx4927_ccfgptr->pcfg) & TX4927_PCFG_PCICLKEN_ALL) { |
28 | u64 ccfg = __raw_readq(addr: &tx4927_ccfgptr->ccfg); |
29 | switch ((unsigned long)ccfg & |
30 | TX4927_CCFG_PCIDIVMODE_MASK) { |
31 | case TX4927_CCFG_PCIDIVMODE_2_5: |
32 | pciclk = txx9_cpu_clock * 2 / 5; break; |
33 | case TX4927_CCFG_PCIDIVMODE_3: |
34 | pciclk = txx9_cpu_clock / 3; break; |
35 | case TX4927_CCFG_PCIDIVMODE_5: |
36 | pciclk = txx9_cpu_clock / 5; break; |
37 | case TX4927_CCFG_PCIDIVMODE_6: |
38 | pciclk = txx9_cpu_clock / 6; break; |
39 | } |
40 | pr_cont("Internal(%u.%uMHz)" , |
41 | (pciclk + 50000) / 1000000, |
42 | ((pciclk + 50000) / 100000) % 10); |
43 | } else { |
44 | pr_cont("External" ); |
45 | pciclk = -1; |
46 | } |
47 | pr_cont("\n" ); |
48 | return pciclk; |
49 | } |
50 | |
51 | int __init tx4927_pciclk66_setup(void) |
52 | { |
53 | int pciclk; |
54 | |
55 | /* Assert M66EN */ |
56 | tx4927_ccfg_set(TX4927_CCFG_PCI66); |
57 | /* Double PCICLK (if possible) */ |
58 | if (__raw_readq(addr: &tx4927_ccfgptr->pcfg) & TX4927_PCFG_PCICLKEN_ALL) { |
59 | unsigned int pcidivmode = 0; |
60 | u64 ccfg = __raw_readq(addr: &tx4927_ccfgptr->ccfg); |
61 | pcidivmode = (unsigned long)ccfg & |
62 | TX4927_CCFG_PCIDIVMODE_MASK; |
63 | switch (pcidivmode) { |
64 | case TX4927_CCFG_PCIDIVMODE_5: |
65 | case TX4927_CCFG_PCIDIVMODE_2_5: |
66 | pcidivmode = TX4927_CCFG_PCIDIVMODE_2_5; |
67 | pciclk = txx9_cpu_clock * 2 / 5; |
68 | break; |
69 | case TX4927_CCFG_PCIDIVMODE_6: |
70 | case TX4927_CCFG_PCIDIVMODE_3: |
71 | default: |
72 | pcidivmode = TX4927_CCFG_PCIDIVMODE_3; |
73 | pciclk = txx9_cpu_clock / 3; |
74 | } |
75 | tx4927_ccfg_change(TX4927_CCFG_PCIDIVMODE_MASK, |
76 | pcidivmode); |
77 | pr_debug("PCICLK: ccfg:%08lx\n" , |
78 | (unsigned long)__raw_readq(&tx4927_ccfgptr->ccfg)); |
79 | } else |
80 | pciclk = -1; |
81 | return pciclk; |
82 | } |
83 | |
84 | void __init tx4927_setup_pcierr_irq(void) |
85 | { |
86 | if (request_irq(TXX9_IRQ_BASE + TX4927_IR_PCIERR, |
87 | tx4927_pcierr_interrupt, |
88 | 0, "PCI error" , |
89 | (void *)TX4927_PCIC_REG)) |
90 | pr_warn("Failed to request irq for PCIERR\n" ); |
91 | } |
92 | |