linux/arch/mips/pci/pci-tx4938.c
<<
>>
Prefs
   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
  20int __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
  59void __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
  71int __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
 115int __init 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
 135void __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