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/tx4938.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ciint __init tx4938_report_pciclk(void)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	int pciclk = 0;
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	pr_info("PCIC --%s PCICLK:",
258c2ecf20Sopenharmony_ci		(__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCI66) ?
268c2ecf20Sopenharmony_ci		" PCI66" : "");
278c2ecf20Sopenharmony_ci	if (__raw_readq(&tx4938_ccfgptr->pcfg) & TX4938_PCFG_PCICLKEN_ALL) {
288c2ecf20Sopenharmony_ci		u64 ccfg = __raw_readq(&tx4938_ccfgptr->ccfg);
298c2ecf20Sopenharmony_ci		switch ((unsigned long)ccfg &
308c2ecf20Sopenharmony_ci			TX4938_CCFG_PCIDIVMODE_MASK) {
318c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_4:
328c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock / 4; break;
338c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_4_5:
348c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock * 2 / 9; break;
358c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_5:
368c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock / 5; break;
378c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_5_5:
388c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock * 2 / 11; break;
398c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_8:
408c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock / 8; break;
418c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_9:
428c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock / 9; break;
438c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_10:
448c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock / 10; break;
458c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_11:
468c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock / 11; break;
478c2ecf20Sopenharmony_ci		}
488c2ecf20Sopenharmony_ci		pr_cont("Internal(%u.%uMHz)",
498c2ecf20Sopenharmony_ci			(pciclk + 50000) / 1000000,
508c2ecf20Sopenharmony_ci			((pciclk + 50000) / 100000) % 10);
518c2ecf20Sopenharmony_ci	} else {
528c2ecf20Sopenharmony_ci		pr_cont("External");
538c2ecf20Sopenharmony_ci		pciclk = -1;
548c2ecf20Sopenharmony_ci	}
558c2ecf20Sopenharmony_ci	pr_cont("\n");
568c2ecf20Sopenharmony_ci	return pciclk;
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_civoid __init tx4938_report_pci1clk(void)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	__u64 ccfg = __raw_readq(&tx4938_ccfgptr->ccfg);
628c2ecf20Sopenharmony_ci	unsigned int pciclk =
638c2ecf20Sopenharmony_ci		txx9_gbus_clock / ((ccfg & TX4938_CCFG_PCI1DMD) ? 4 : 2);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	pr_info("PCIC1 -- %sPCICLK:%u.%uMHz\n",
668c2ecf20Sopenharmony_ci		(ccfg & TX4938_CCFG_PCI1_66) ? "PCI66 " : "",
678c2ecf20Sopenharmony_ci		(pciclk + 50000) / 1000000,
688c2ecf20Sopenharmony_ci		((pciclk + 50000) / 100000) % 10);
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ciint __init tx4938_pciclk66_setup(void)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	int pciclk;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	/* Assert M66EN */
768c2ecf20Sopenharmony_ci	tx4938_ccfg_set(TX4938_CCFG_PCI66);
778c2ecf20Sopenharmony_ci	/* Double PCICLK (if possible) */
788c2ecf20Sopenharmony_ci	if (__raw_readq(&tx4938_ccfgptr->pcfg) & TX4938_PCFG_PCICLKEN_ALL) {
798c2ecf20Sopenharmony_ci		unsigned int pcidivmode = 0;
808c2ecf20Sopenharmony_ci		u64 ccfg = __raw_readq(&tx4938_ccfgptr->ccfg);
818c2ecf20Sopenharmony_ci		pcidivmode = (unsigned long)ccfg &
828c2ecf20Sopenharmony_ci			TX4938_CCFG_PCIDIVMODE_MASK;
838c2ecf20Sopenharmony_ci		switch (pcidivmode) {
848c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_8:
858c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_4:
868c2ecf20Sopenharmony_ci			pcidivmode = TX4938_CCFG_PCIDIVMODE_4;
878c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock / 4;
888c2ecf20Sopenharmony_ci			break;
898c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_9:
908c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_4_5:
918c2ecf20Sopenharmony_ci			pcidivmode = TX4938_CCFG_PCIDIVMODE_4_5;
928c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock * 2 / 9;
938c2ecf20Sopenharmony_ci			break;
948c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_10:
958c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_5:
968c2ecf20Sopenharmony_ci			pcidivmode = TX4938_CCFG_PCIDIVMODE_5;
978c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock / 5;
988c2ecf20Sopenharmony_ci			break;
998c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_11:
1008c2ecf20Sopenharmony_ci		case TX4938_CCFG_PCIDIVMODE_5_5:
1018c2ecf20Sopenharmony_ci		default:
1028c2ecf20Sopenharmony_ci			pcidivmode = TX4938_CCFG_PCIDIVMODE_5_5;
1038c2ecf20Sopenharmony_ci			pciclk = txx9_cpu_clock * 2 / 11;
1048c2ecf20Sopenharmony_ci			break;
1058c2ecf20Sopenharmony_ci		}
1068c2ecf20Sopenharmony_ci		tx4938_ccfg_change(TX4938_CCFG_PCIDIVMODE_MASK,
1078c2ecf20Sopenharmony_ci				   pcidivmode);
1088c2ecf20Sopenharmony_ci		pr_debug("PCICLK: ccfg:%08lx\n",
1098c2ecf20Sopenharmony_ci			 (unsigned long)__raw_readq(&tx4938_ccfgptr->ccfg));
1108c2ecf20Sopenharmony_ci	} else
1118c2ecf20Sopenharmony_ci		pciclk = -1;
1128c2ecf20Sopenharmony_ci	return pciclk;
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ciint tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4938_pcic1ptr) {
1188c2ecf20Sopenharmony_ci		switch (slot) {
1198c2ecf20Sopenharmony_ci		case TX4927_PCIC_IDSEL_AD_TO_SLOT(31):
1208c2ecf20Sopenharmony_ci			if (__raw_readq(&tx4938_ccfgptr->pcfg) &
1218c2ecf20Sopenharmony_ci			    TX4938_PCFG_ETH0_SEL)
1228c2ecf20Sopenharmony_ci				return TXX9_IRQ_BASE + TX4938_IR_ETH0;
1238c2ecf20Sopenharmony_ci			break;
1248c2ecf20Sopenharmony_ci		case TX4927_PCIC_IDSEL_AD_TO_SLOT(30):
1258c2ecf20Sopenharmony_ci			if (__raw_readq(&tx4938_ccfgptr->pcfg) &
1268c2ecf20Sopenharmony_ci			    TX4938_PCFG_ETH1_SEL)
1278c2ecf20Sopenharmony_ci				return TXX9_IRQ_BASE + TX4938_IR_ETH1;
1288c2ecf20Sopenharmony_ci			break;
1298c2ecf20Sopenharmony_ci		}
1308c2ecf20Sopenharmony_ci		return 0;
1318c2ecf20Sopenharmony_ci	}
1328c2ecf20Sopenharmony_ci	return -1;
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_civoid __init tx4938_setup_pcierr_irq(void)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	if (request_irq(TXX9_IRQ_BASE + TX4938_IR_PCIERR,
1388c2ecf20Sopenharmony_ci			tx4927_pcierr_interrupt,
1398c2ecf20Sopenharmony_ci			0, "PCI error",
1408c2ecf20Sopenharmony_ci			(void *)TX4927_PCIC_REG))
1418c2ecf20Sopenharmony_ci		pr_warn("Failed to request irq for PCIERR\n");
1428c2ecf20Sopenharmony_ci}
143