18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
38c2ecf20Sopenharmony_ci *	    and RBTX49xx patch from CELF patch archive.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2001, 2003-2005 MontaVista Software Inc.
68c2ecf20Sopenharmony_ci * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
78c2ecf20Sopenharmony_ci * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
108c2ecf20Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
118c2ecf20Sopenharmony_ci * for more details.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci#include <linux/init.h>
148c2ecf20Sopenharmony_ci#include <linux/pci.h>
158c2ecf20Sopenharmony_ci#include <linux/kernel.h>
168c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
178c2ecf20Sopenharmony_ci#include <asm/txx9/generic.h>
188c2ecf20Sopenharmony_ci#include <asm/txx9/tx4927.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ciint __init tx4927_report_pciclk(void)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	int pciclk = 0;
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	pr_info("PCIC --%s PCICLK:",
258c2ecf20Sopenharmony_ci		(__raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_PCI66) ?
268c2ecf20Sopenharmony_ci		" PCI66" : "");
278c2ecf20Sopenharmony_ci	if (__raw_readq(&tx4927_ccfgptr->pcfg) & TX4927_PCFG_PCICLKEN_ALL) {
288c2ecf20Sopenharmony_ci		u64 ccfg = __raw_readq(&tx4927_ccfgptr->ccfg);
298c2ecf20Sopenharmony_ci		switch ((unsigned long)ccfg &
308c2ecf20Sopenharmony_ci			TX4927_CCFG_PCIDIVMODE_MASK) {
318c2ecf20Sopenharmony_ci		case TX4927_CCFG_PCIDIVMODE_2_5:
328c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock * 2 / 5; break;
338c2ecf20Sopenharmony_ci		case TX4927_CCFG_PCIDIVMODE_3:
348c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock / 3; break;
358c2ecf20Sopenharmony_ci		case TX4927_CCFG_PCIDIVMODE_5:
368c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock / 5; break;
378c2ecf20Sopenharmony_ci		case TX4927_CCFG_PCIDIVMODE_6:
388c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock / 6; break;
398c2ecf20Sopenharmony_ci		}
408c2ecf20Sopenharmony_ci		pr_cont("Internal(%u.%uMHz)",
418c2ecf20Sopenharmony_ci			(pciclk + 50000) / 1000000,
428c2ecf20Sopenharmony_ci			((pciclk + 50000) / 100000) % 10);
438c2ecf20Sopenharmony_ci	} else {
448c2ecf20Sopenharmony_ci		pr_cont("External");
458c2ecf20Sopenharmony_ci		pciclk = -1;
468c2ecf20Sopenharmony_ci	}
478c2ecf20Sopenharmony_ci	pr_cont("\n");
488c2ecf20Sopenharmony_ci	return pciclk;
498c2ecf20Sopenharmony_ci}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ciint __init tx4927_pciclk66_setup(void)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	int pciclk;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	/* Assert M66EN */
568c2ecf20Sopenharmony_ci	tx4927_ccfg_set(TX4927_CCFG_PCI66);
578c2ecf20Sopenharmony_ci	/* Double PCICLK (if possible) */
588c2ecf20Sopenharmony_ci	if (__raw_readq(&tx4927_ccfgptr->pcfg) & TX4927_PCFG_PCICLKEN_ALL) {
598c2ecf20Sopenharmony_ci		unsigned int pcidivmode = 0;
608c2ecf20Sopenharmony_ci		u64 ccfg = __raw_readq(&tx4927_ccfgptr->ccfg);
618c2ecf20Sopenharmony_ci		pcidivmode = (unsigned long)ccfg &
628c2ecf20Sopenharmony_ci			TX4927_CCFG_PCIDIVMODE_MASK;
638c2ecf20Sopenharmony_ci		switch (pcidivmode) {
648c2ecf20Sopenharmony_ci		case TX4927_CCFG_PCIDIVMODE_5:
658c2ecf20Sopenharmony_ci		case TX4927_CCFG_PCIDIVMODE_2_5:
668c2ecf20Sopenharmony_ci			pcidivmode = TX4927_CCFG_PCIDIVMODE_2_5;
678c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock * 2 / 5;
688c2ecf20Sopenharmony_ci			break;
698c2ecf20Sopenharmony_ci		case TX4927_CCFG_PCIDIVMODE_6:
708c2ecf20Sopenharmony_ci		case TX4927_CCFG_PCIDIVMODE_3:
718c2ecf20Sopenharmony_ci		default:
728c2ecf20Sopenharmony_ci			pcidivmode = TX4927_CCFG_PCIDIVMODE_3;
738c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock / 3;
748c2ecf20Sopenharmony_ci		}
758c2ecf20Sopenharmony_ci		tx4927_ccfg_change(TX4927_CCFG_PCIDIVMODE_MASK,
768c2ecf20Sopenharmony_ci				   pcidivmode);
778c2ecf20Sopenharmony_ci		pr_debug("PCICLK: ccfg:%08lx\n",
788c2ecf20Sopenharmony_ci			 (unsigned long)__raw_readq(&tx4927_ccfgptr->ccfg));
798c2ecf20Sopenharmony_ci	} else
808c2ecf20Sopenharmony_ci		pciclk = -1;
818c2ecf20Sopenharmony_ci	return pciclk;
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_civoid __init tx4927_setup_pcierr_irq(void)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	if (request_irq(TXX9_IRQ_BASE + TX4927_IR_PCIERR,
878c2ecf20Sopenharmony_ci			tx4927_pcierr_interrupt,
888c2ecf20Sopenharmony_ci			0, "PCI error",
898c2ecf20Sopenharmony_ci			(void *)TX4927_PCIC_REG))
908c2ecf20Sopenharmony_ci		pr_warn("Failed to request irq for PCIERR\n");
918c2ecf20Sopenharmony_ci}
92