18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Promise TX2/TX4/TX2000/133 IDE driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Split from:
68c2ecf20Sopenharmony_ci *  linux/drivers/ide/pdc202xx.c	Version 0.35	Mar. 30, 2002
78c2ecf20Sopenharmony_ci *  Copyright (C) 1998-2002		Andre Hedrick <andre@linux-ide.org>
88c2ecf20Sopenharmony_ci *  Copyright (C) 2005-2007		MontaVista Software, Inc.
98c2ecf20Sopenharmony_ci *  Portions Copyright (C) 1999 Promise Technology, Inc.
108c2ecf20Sopenharmony_ci *  Author: Frank Tiernan (frankt@promise.com)
118c2ecf20Sopenharmony_ci *  Released under terms of General Public License
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/module.h>
158c2ecf20Sopenharmony_ci#include <linux/types.h>
168c2ecf20Sopenharmony_ci#include <linux/kernel.h>
178c2ecf20Sopenharmony_ci#include <linux/delay.h>
188c2ecf20Sopenharmony_ci#include <linux/pci.h>
198c2ecf20Sopenharmony_ci#include <linux/init.h>
208c2ecf20Sopenharmony_ci#include <linux/ide.h>
218c2ecf20Sopenharmony_ci#include <linux/ktime.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include <asm/io.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_PMAC
268c2ecf20Sopenharmony_ci#include <asm/prom.h>
278c2ecf20Sopenharmony_ci#endif
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define DRV_NAME "pdc202xx_new"
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#undef DEBUG
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#ifdef DEBUG
348c2ecf20Sopenharmony_ci#define DBG(fmt, args...) printk("%s: " fmt, __func__, ## args)
358c2ecf20Sopenharmony_ci#else
368c2ecf20Sopenharmony_ci#define DBG(fmt, args...)
378c2ecf20Sopenharmony_ci#endif
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic u8 max_dma_rate(struct pci_dev *pdev)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	u8 mode;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	switch(pdev->device) {
448c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_PROMISE_20277:
458c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_PROMISE_20276:
468c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_PROMISE_20275:
478c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_PROMISE_20271:
488c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_PROMISE_20269:
498c2ecf20Sopenharmony_ci			mode = 4;
508c2ecf20Sopenharmony_ci			break;
518c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_PROMISE_20270:
528c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_PROMISE_20268:
538c2ecf20Sopenharmony_ci			mode = 3;
548c2ecf20Sopenharmony_ci			break;
558c2ecf20Sopenharmony_ci		default:
568c2ecf20Sopenharmony_ci			return 0;
578c2ecf20Sopenharmony_ci	}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	return mode;
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/**
638c2ecf20Sopenharmony_ci * get_indexed_reg - Get indexed register
648c2ecf20Sopenharmony_ci * @hwif: for the port address
658c2ecf20Sopenharmony_ci * @index: index of the indexed register
668c2ecf20Sopenharmony_ci */
678c2ecf20Sopenharmony_cistatic u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	u8 value;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	outb(index, hwif->dma_base + 1);
728c2ecf20Sopenharmony_ci	value = inb(hwif->dma_base + 3);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	DBG("index[%02X] value[%02X]\n", index, value);
758c2ecf20Sopenharmony_ci	return value;
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci/**
798c2ecf20Sopenharmony_ci * set_indexed_reg - Set indexed register
808c2ecf20Sopenharmony_ci * @hwif: for the port address
818c2ecf20Sopenharmony_ci * @index: index of the indexed register
828c2ecf20Sopenharmony_ci */
838c2ecf20Sopenharmony_cistatic void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	outb(index, hwif->dma_base + 1);
868c2ecf20Sopenharmony_ci	outb(value, hwif->dma_base + 3);
878c2ecf20Sopenharmony_ci	DBG("index[%02X] value[%02X]\n", index, value);
888c2ecf20Sopenharmony_ci}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci/*
918c2ecf20Sopenharmony_ci * ATA Timing Tables based on 133 MHz PLL output clock.
928c2ecf20Sopenharmony_ci *
938c2ecf20Sopenharmony_ci * If the PLL outputs 100 MHz clock, the ASIC hardware will set
948c2ecf20Sopenharmony_ci * the timing registers automatically when "set features" command is
958c2ecf20Sopenharmony_ci * issued to the device. However, if the PLL output clock is 133 MHz,
968c2ecf20Sopenharmony_ci * the following tables must be used.
978c2ecf20Sopenharmony_ci */
988c2ecf20Sopenharmony_cistatic struct pio_timing {
998c2ecf20Sopenharmony_ci	u8 reg0c, reg0d, reg13;
1008c2ecf20Sopenharmony_ci} pio_timings [] = {
1018c2ecf20Sopenharmony_ci	{ 0xfb, 0x2b, 0xac },	/* PIO mode 0, IORDY off, Prefetch off */
1028c2ecf20Sopenharmony_ci	{ 0x46, 0x29, 0xa4 },	/* PIO mode 1, IORDY off, Prefetch off */
1038c2ecf20Sopenharmony_ci	{ 0x23, 0x26, 0x64 },	/* PIO mode 2, IORDY off, Prefetch off */
1048c2ecf20Sopenharmony_ci	{ 0x27, 0x0d, 0x35 },	/* PIO mode 3, IORDY on,  Prefetch off */
1058c2ecf20Sopenharmony_ci	{ 0x23, 0x09, 0x25 },	/* PIO mode 4, IORDY on,  Prefetch off */
1068c2ecf20Sopenharmony_ci};
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic struct mwdma_timing {
1098c2ecf20Sopenharmony_ci	u8 reg0e, reg0f;
1108c2ecf20Sopenharmony_ci} mwdma_timings [] = {
1118c2ecf20Sopenharmony_ci	{ 0xdf, 0x5f }, 	/* MWDMA mode 0 */
1128c2ecf20Sopenharmony_ci	{ 0x6b, 0x27 }, 	/* MWDMA mode 1 */
1138c2ecf20Sopenharmony_ci	{ 0x69, 0x25 }, 	/* MWDMA mode 2 */
1148c2ecf20Sopenharmony_ci};
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic struct udma_timing {
1178c2ecf20Sopenharmony_ci	u8 reg10, reg11, reg12;
1188c2ecf20Sopenharmony_ci} udma_timings [] = {
1198c2ecf20Sopenharmony_ci	{ 0x4a, 0x0f, 0xd5 },	/* UDMA mode 0 */
1208c2ecf20Sopenharmony_ci	{ 0x3a, 0x0a, 0xd0 },	/* UDMA mode 1 */
1218c2ecf20Sopenharmony_ci	{ 0x2a, 0x07, 0xcd },	/* UDMA mode 2 */
1228c2ecf20Sopenharmony_ci	{ 0x1a, 0x05, 0xcd },	/* UDMA mode 3 */
1238c2ecf20Sopenharmony_ci	{ 0x1a, 0x03, 0xcd },	/* UDMA mode 4 */
1248c2ecf20Sopenharmony_ci	{ 0x1a, 0x02, 0xcb },	/* UDMA mode 5 */
1258c2ecf20Sopenharmony_ci	{ 0x1a, 0x01, 0xcb },	/* UDMA mode 6 */
1268c2ecf20Sopenharmony_ci};
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistatic void pdcnew_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	struct pci_dev *dev	= to_pci_dev(hwif->dev);
1318c2ecf20Sopenharmony_ci	u8 adj			= (drive->dn & 1) ? 0x08 : 0x00;
1328c2ecf20Sopenharmony_ci	const u8 speed		= drive->dma_mode;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	/*
1358c2ecf20Sopenharmony_ci	 * IDE core issues SETFEATURES_XFER to the drive first (thanks to
1368c2ecf20Sopenharmony_ci	 * IDE_HFLAG_POST_SET_MODE in ->host_flags).  PDC202xx hardware will
1378c2ecf20Sopenharmony_ci	 * automatically set the timing registers based on 100 MHz PLL output.
1388c2ecf20Sopenharmony_ci	 *
1398c2ecf20Sopenharmony_ci	 * As we set up the PLL to output 133 MHz for UltraDMA/133 capable
1408c2ecf20Sopenharmony_ci	 * chips, we must override the default register settings...
1418c2ecf20Sopenharmony_ci	 */
1428c2ecf20Sopenharmony_ci	if (max_dma_rate(dev) == 4) {
1438c2ecf20Sopenharmony_ci		u8 mode = speed & 0x07;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci		if (speed >= XFER_UDMA_0) {
1468c2ecf20Sopenharmony_ci			set_indexed_reg(hwif, 0x10 + adj,
1478c2ecf20Sopenharmony_ci					udma_timings[mode].reg10);
1488c2ecf20Sopenharmony_ci			set_indexed_reg(hwif, 0x11 + adj,
1498c2ecf20Sopenharmony_ci					udma_timings[mode].reg11);
1508c2ecf20Sopenharmony_ci			set_indexed_reg(hwif, 0x12 + adj,
1518c2ecf20Sopenharmony_ci					udma_timings[mode].reg12);
1528c2ecf20Sopenharmony_ci		} else {
1538c2ecf20Sopenharmony_ci			set_indexed_reg(hwif, 0x0e + adj,
1548c2ecf20Sopenharmony_ci					mwdma_timings[mode].reg0e);
1558c2ecf20Sopenharmony_ci			set_indexed_reg(hwif, 0x0f + adj,
1568c2ecf20Sopenharmony_ci					mwdma_timings[mode].reg0f);
1578c2ecf20Sopenharmony_ci		}
1588c2ecf20Sopenharmony_ci	} else if (speed == XFER_UDMA_2) {
1598c2ecf20Sopenharmony_ci		/* Set tHOLD bit to 0 if using UDMA mode 2 */
1608c2ecf20Sopenharmony_ci		u8 tmp = get_indexed_reg(hwif, 0x10 + adj);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci		set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f);
1638c2ecf20Sopenharmony_ci 	}
1648c2ecf20Sopenharmony_ci}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistatic void pdcnew_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct pci_dev *dev = to_pci_dev(hwif->dev);
1698c2ecf20Sopenharmony_ci	u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
1708c2ecf20Sopenharmony_ci	const u8 pio = drive->pio_mode - XFER_PIO_0;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	if (max_dma_rate(dev) == 4) {
1738c2ecf20Sopenharmony_ci		set_indexed_reg(hwif, 0x0c + adj, pio_timings[pio].reg0c);
1748c2ecf20Sopenharmony_ci		set_indexed_reg(hwif, 0x0d + adj, pio_timings[pio].reg0d);
1758c2ecf20Sopenharmony_ci		set_indexed_reg(hwif, 0x13 + adj, pio_timings[pio].reg13);
1768c2ecf20Sopenharmony_ci	}
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_cistatic u8 pdcnew_cable_detect(ide_hwif_t *hwif)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	if (get_indexed_reg(hwif, 0x0b) & 0x04)
1828c2ecf20Sopenharmony_ci		return ATA_CBL_PATA40;
1838c2ecf20Sopenharmony_ci	else
1848c2ecf20Sopenharmony_ci		return ATA_CBL_PATA80;
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic void pdcnew_reset(ide_drive_t *drive)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	/*
1908c2ecf20Sopenharmony_ci	 * Deleted this because it is redundant from the caller.
1918c2ecf20Sopenharmony_ci	 */
1928c2ecf20Sopenharmony_ci	printk(KERN_WARNING "pdc202xx_new: %s channel reset.\n",
1938c2ecf20Sopenharmony_ci		drive->hwif->channel ? "Secondary" : "Primary");
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci/**
1978c2ecf20Sopenharmony_ci * read_counter - Read the byte count registers
1988c2ecf20Sopenharmony_ci * @dma_base: for the port address
1998c2ecf20Sopenharmony_ci */
2008c2ecf20Sopenharmony_cistatic long read_counter(u32 dma_base)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	u32  pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08;
2038c2ecf20Sopenharmony_ci	u8   cnt0, cnt1, cnt2, cnt3;
2048c2ecf20Sopenharmony_ci	long count = 0, last;
2058c2ecf20Sopenharmony_ci	int  retry = 3;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	do {
2088c2ecf20Sopenharmony_ci		last = count;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci		/* Read the current count */
2118c2ecf20Sopenharmony_ci		outb(0x20, pri_dma_base + 0x01);
2128c2ecf20Sopenharmony_ci		cnt0 = inb(pri_dma_base + 0x03);
2138c2ecf20Sopenharmony_ci		outb(0x21, pri_dma_base + 0x01);
2148c2ecf20Sopenharmony_ci		cnt1 = inb(pri_dma_base + 0x03);
2158c2ecf20Sopenharmony_ci		outb(0x20, sec_dma_base + 0x01);
2168c2ecf20Sopenharmony_ci		cnt2 = inb(sec_dma_base + 0x03);
2178c2ecf20Sopenharmony_ci		outb(0x21, sec_dma_base + 0x01);
2188c2ecf20Sopenharmony_ci		cnt3 = inb(sec_dma_base + 0x03);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci		count = (cnt3 << 23) | (cnt2 << 15) | (cnt1 << 8) | cnt0;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci		/*
2238c2ecf20Sopenharmony_ci		 * The 30-bit decrementing counter is read in 4 pieces.
2248c2ecf20Sopenharmony_ci		 * Incorrect value may be read when the most significant bytes
2258c2ecf20Sopenharmony_ci		 * are changing...
2268c2ecf20Sopenharmony_ci		 */
2278c2ecf20Sopenharmony_ci	} while (retry-- && (((last ^ count) & 0x3fff8000) || last < count));
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	DBG("cnt0[%02X] cnt1[%02X] cnt2[%02X] cnt3[%02X]\n",
2308c2ecf20Sopenharmony_ci		  cnt0, cnt1, cnt2, cnt3);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	return count;
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci/**
2368c2ecf20Sopenharmony_ci * detect_pll_input_clock - Detect the PLL input clock in Hz.
2378c2ecf20Sopenharmony_ci * @dma_base: for the port address
2388c2ecf20Sopenharmony_ci * E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock.
2398c2ecf20Sopenharmony_ci */
2408c2ecf20Sopenharmony_cistatic long detect_pll_input_clock(unsigned long dma_base)
2418c2ecf20Sopenharmony_ci{
2428c2ecf20Sopenharmony_ci	ktime_t start_time, end_time;
2438c2ecf20Sopenharmony_ci	long start_count, end_count;
2448c2ecf20Sopenharmony_ci	long pll_input, usec_elapsed;
2458c2ecf20Sopenharmony_ci	u8 scr1;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	start_count = read_counter(dma_base);
2488c2ecf20Sopenharmony_ci	start_time = ktime_get();
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	/* Start the test mode */
2518c2ecf20Sopenharmony_ci	outb(0x01, dma_base + 0x01);
2528c2ecf20Sopenharmony_ci	scr1 = inb(dma_base + 0x03);
2538c2ecf20Sopenharmony_ci	DBG("scr1[%02X]\n", scr1);
2548c2ecf20Sopenharmony_ci	outb(scr1 | 0x40, dma_base + 0x03);
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	/* Let the counter run for 10 ms. */
2578c2ecf20Sopenharmony_ci	mdelay(10);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	end_count = read_counter(dma_base);
2608c2ecf20Sopenharmony_ci	end_time = ktime_get();
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	/* Stop the test mode */
2638c2ecf20Sopenharmony_ci	outb(0x01, dma_base + 0x01);
2648c2ecf20Sopenharmony_ci	scr1 = inb(dma_base + 0x03);
2658c2ecf20Sopenharmony_ci	DBG("scr1[%02X]\n", scr1);
2668c2ecf20Sopenharmony_ci	outb(scr1 & ~0x40, dma_base + 0x03);
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	/*
2698c2ecf20Sopenharmony_ci	 * Calculate the input clock in Hz
2708c2ecf20Sopenharmony_ci	 * (the clock counter is 30 bit wide and counts down)
2718c2ecf20Sopenharmony_ci	 */
2728c2ecf20Sopenharmony_ci	usec_elapsed = ktime_us_delta(end_time, start_time);
2738c2ecf20Sopenharmony_ci	pll_input = ((start_count - end_count) & 0x3fffffff) / 10 *
2748c2ecf20Sopenharmony_ci		(10000000 / usec_elapsed);
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	DBG("start[%ld] end[%ld]\n", start_count, end_count);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	return pll_input;
2798c2ecf20Sopenharmony_ci}
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_PMAC
2828c2ecf20Sopenharmony_cistatic void apple_kiwi_init(struct pci_dev *pdev)
2838c2ecf20Sopenharmony_ci{
2848c2ecf20Sopenharmony_ci	struct device_node *np = pci_device_to_OF_node(pdev);
2858c2ecf20Sopenharmony_ci	u8 conf;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	if (np == NULL || !of_device_is_compatible(np, "kiwi-root"))
2888c2ecf20Sopenharmony_ci		return;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	if (pdev->revision >= 0x03) {
2918c2ecf20Sopenharmony_ci		/* Setup chip magic config stuff (from darwin) */
2928c2ecf20Sopenharmony_ci		pci_read_config_byte (pdev, 0x40, &conf);
2938c2ecf20Sopenharmony_ci		pci_write_config_byte(pdev, 0x40, (conf | 0x01));
2948c2ecf20Sopenharmony_ci	}
2958c2ecf20Sopenharmony_ci}
2968c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_PMAC */
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_cistatic int init_chipset_pdcnew(struct pci_dev *dev)
2998c2ecf20Sopenharmony_ci{
3008c2ecf20Sopenharmony_ci	const char *name = DRV_NAME;
3018c2ecf20Sopenharmony_ci	unsigned long dma_base = pci_resource_start(dev, 4);
3028c2ecf20Sopenharmony_ci	unsigned long sec_dma_base = dma_base + 0x08;
3038c2ecf20Sopenharmony_ci	long pll_input, pll_output, ratio;
3048c2ecf20Sopenharmony_ci	int f, r;
3058c2ecf20Sopenharmony_ci	u8 pll_ctl0, pll_ctl1;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	if (dma_base == 0)
3088c2ecf20Sopenharmony_ci		return -EFAULT;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_PMAC
3118c2ecf20Sopenharmony_ci	apple_kiwi_init(dev);
3128c2ecf20Sopenharmony_ci#endif
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	/* Calculate the required PLL output frequency */
3158c2ecf20Sopenharmony_ci	switch(max_dma_rate(dev)) {
3168c2ecf20Sopenharmony_ci		case 4: /* it's 133 MHz for Ultra133 chips */
3178c2ecf20Sopenharmony_ci			pll_output = 133333333;
3188c2ecf20Sopenharmony_ci			break;
3198c2ecf20Sopenharmony_ci		case 3: /* and  100 MHz for Ultra100 chips */
3208c2ecf20Sopenharmony_ci		default:
3218c2ecf20Sopenharmony_ci			pll_output = 100000000;
3228c2ecf20Sopenharmony_ci			break;
3238c2ecf20Sopenharmony_ci	}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	/*
3268c2ecf20Sopenharmony_ci	 * Detect PLL input clock.
3278c2ecf20Sopenharmony_ci	 * On some systems, where PCI bus is running at non-standard clock rate
3288c2ecf20Sopenharmony_ci	 * (e.g. 25 or 40 MHz), we have to adjust the cycle time.
3298c2ecf20Sopenharmony_ci	 * PDC20268 and newer chips employ PLL circuit to help correct timing
3308c2ecf20Sopenharmony_ci	 * registers setting.
3318c2ecf20Sopenharmony_ci	 */
3328c2ecf20Sopenharmony_ci	pll_input = detect_pll_input_clock(dma_base);
3338c2ecf20Sopenharmony_ci	printk(KERN_INFO "%s %s: PLL input clock is %ld kHz\n",
3348c2ecf20Sopenharmony_ci		name, pci_name(dev), pll_input / 1000);
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	/* Sanity check */
3378c2ecf20Sopenharmony_ci	if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) {
3388c2ecf20Sopenharmony_ci		printk(KERN_ERR "%s %s: Bad PLL input clock %ld Hz, giving up!"
3398c2ecf20Sopenharmony_ci			"\n", name, pci_name(dev), pll_input);
3408c2ecf20Sopenharmony_ci		goto out;
3418c2ecf20Sopenharmony_ci	}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci#ifdef DEBUG
3448c2ecf20Sopenharmony_ci	DBG("pll_output is %ld Hz\n", pll_output);
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	/* Show the current clock value of PLL control register
3478c2ecf20Sopenharmony_ci	 * (maybe already configured by the BIOS)
3488c2ecf20Sopenharmony_ci	 */
3498c2ecf20Sopenharmony_ci	outb(0x02, sec_dma_base + 0x01);
3508c2ecf20Sopenharmony_ci	pll_ctl0 = inb(sec_dma_base + 0x03);
3518c2ecf20Sopenharmony_ci	outb(0x03, sec_dma_base + 0x01);
3528c2ecf20Sopenharmony_ci	pll_ctl1 = inb(sec_dma_base + 0x03);
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
3558c2ecf20Sopenharmony_ci#endif
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	/*
3588c2ecf20Sopenharmony_ci	 * Calculate the ratio of F, R and NO
3598c2ecf20Sopenharmony_ci	 * POUT = (F + 2) / (( R + 2) * NO)
3608c2ecf20Sopenharmony_ci	 */
3618c2ecf20Sopenharmony_ci	ratio = pll_output / (pll_input / 1000);
3628c2ecf20Sopenharmony_ci	if (ratio < 8600L) { /* 8.6x */
3638c2ecf20Sopenharmony_ci		/* Using NO = 0x01, R = 0x0d */
3648c2ecf20Sopenharmony_ci		r = 0x0d;
3658c2ecf20Sopenharmony_ci	} else if (ratio < 12900L) { /* 12.9x */
3668c2ecf20Sopenharmony_ci		/* Using NO = 0x01, R = 0x08 */
3678c2ecf20Sopenharmony_ci		r = 0x08;
3688c2ecf20Sopenharmony_ci	} else if (ratio < 16100L) { /* 16.1x */
3698c2ecf20Sopenharmony_ci		/* Using NO = 0x01, R = 0x06 */
3708c2ecf20Sopenharmony_ci		r = 0x06;
3718c2ecf20Sopenharmony_ci	} else if (ratio < 64000L) { /* 64x */
3728c2ecf20Sopenharmony_ci		r = 0x00;
3738c2ecf20Sopenharmony_ci	} else {
3748c2ecf20Sopenharmony_ci		/* Invalid ratio */
3758c2ecf20Sopenharmony_ci		printk(KERN_ERR "%s %s: Bad ratio %ld, giving up!\n",
3768c2ecf20Sopenharmony_ci			name, pci_name(dev), ratio);
3778c2ecf20Sopenharmony_ci		goto out;
3788c2ecf20Sopenharmony_ci	}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	f = (ratio * (r + 2)) / 1000 - 2;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	DBG("F[%d] R[%d] ratio*1000[%ld]\n", f, r, ratio);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	if (unlikely(f < 0 || f > 127)) {
3858c2ecf20Sopenharmony_ci		/* Invalid F */
3868c2ecf20Sopenharmony_ci		printk(KERN_ERR "%s %s: F[%d] invalid!\n",
3878c2ecf20Sopenharmony_ci			name, pci_name(dev), f);
3888c2ecf20Sopenharmony_ci		goto out;
3898c2ecf20Sopenharmony_ci	}
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	pll_ctl0 = (u8) f;
3928c2ecf20Sopenharmony_ci	pll_ctl1 = (u8) r;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	DBG("Writing pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	outb(0x02,     sec_dma_base + 0x01);
3978c2ecf20Sopenharmony_ci	outb(pll_ctl0, sec_dma_base + 0x03);
3988c2ecf20Sopenharmony_ci	outb(0x03,     sec_dma_base + 0x01);
3998c2ecf20Sopenharmony_ci	outb(pll_ctl1, sec_dma_base + 0x03);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	/* Wait the PLL circuit to be stable */
4028c2ecf20Sopenharmony_ci	mdelay(30);
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci#ifdef DEBUG
4058c2ecf20Sopenharmony_ci	/*
4068c2ecf20Sopenharmony_ci	 *  Show the current clock value of PLL control register
4078c2ecf20Sopenharmony_ci	 */
4088c2ecf20Sopenharmony_ci	outb(0x02, sec_dma_base + 0x01);
4098c2ecf20Sopenharmony_ci	pll_ctl0 = inb(sec_dma_base + 0x03);
4108c2ecf20Sopenharmony_ci	outb(0x03, sec_dma_base + 0x01);
4118c2ecf20Sopenharmony_ci	pll_ctl1 = inb(sec_dma_base + 0x03);
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
4148c2ecf20Sopenharmony_ci#endif
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci out:
4178c2ecf20Sopenharmony_ci	return 0;
4188c2ecf20Sopenharmony_ci}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_cistatic struct pci_dev *pdc20270_get_dev2(struct pci_dev *dev)
4218c2ecf20Sopenharmony_ci{
4228c2ecf20Sopenharmony_ci	struct pci_dev *dev2;
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	dev2 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn) + 1,
4258c2ecf20Sopenharmony_ci						PCI_FUNC(dev->devfn)));
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	if (dev2 &&
4288c2ecf20Sopenharmony_ci	    dev2->vendor == dev->vendor &&
4298c2ecf20Sopenharmony_ci	    dev2->device == dev->device) {
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci		if (dev2->irq != dev->irq) {
4328c2ecf20Sopenharmony_ci			dev2->irq = dev->irq;
4338c2ecf20Sopenharmony_ci			printk(KERN_INFO DRV_NAME " %s: PCI config space "
4348c2ecf20Sopenharmony_ci				"interrupt fixed\n", pci_name(dev));
4358c2ecf20Sopenharmony_ci		}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci		return dev2;
4388c2ecf20Sopenharmony_ci	}
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	return NULL;
4418c2ecf20Sopenharmony_ci}
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_cistatic const struct ide_port_ops pdcnew_port_ops = {
4448c2ecf20Sopenharmony_ci	.set_pio_mode		= pdcnew_set_pio_mode,
4458c2ecf20Sopenharmony_ci	.set_dma_mode		= pdcnew_set_dma_mode,
4468c2ecf20Sopenharmony_ci	.resetproc		= pdcnew_reset,
4478c2ecf20Sopenharmony_ci	.cable_detect		= pdcnew_cable_detect,
4488c2ecf20Sopenharmony_ci};
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci#define DECLARE_PDCNEW_DEV(udma) \
4518c2ecf20Sopenharmony_ci	{ \
4528c2ecf20Sopenharmony_ci		.name		= DRV_NAME, \
4538c2ecf20Sopenharmony_ci		.init_chipset	= init_chipset_pdcnew, \
4548c2ecf20Sopenharmony_ci		.port_ops	= &pdcnew_port_ops, \
4558c2ecf20Sopenharmony_ci		.host_flags	= IDE_HFLAG_POST_SET_MODE | \
4568c2ecf20Sopenharmony_ci				  IDE_HFLAG_ERROR_STOPS_FIFO | \
4578c2ecf20Sopenharmony_ci				  IDE_HFLAG_OFF_BOARD, \
4588c2ecf20Sopenharmony_ci		.pio_mask	= ATA_PIO4, \
4598c2ecf20Sopenharmony_ci		.mwdma_mask	= ATA_MWDMA2, \
4608c2ecf20Sopenharmony_ci		.udma_mask	= udma, \
4618c2ecf20Sopenharmony_ci	}
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_cistatic const struct ide_port_info pdcnew_chipsets[] = {
4648c2ecf20Sopenharmony_ci	/* 0: PDC202{68,70} */		DECLARE_PDCNEW_DEV(ATA_UDMA5),
4658c2ecf20Sopenharmony_ci	/* 1: PDC202{69,71,75,76,77} */	DECLARE_PDCNEW_DEV(ATA_UDMA6),
4668c2ecf20Sopenharmony_ci};
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci/**
4698c2ecf20Sopenharmony_ci *	pdc202new_init_one	-	called when a pdc202xx is found
4708c2ecf20Sopenharmony_ci *	@dev: the pdc202new device
4718c2ecf20Sopenharmony_ci *	@id: the matching pci id
4728c2ecf20Sopenharmony_ci *
4738c2ecf20Sopenharmony_ci *	Called when the PCI registration layer (or the IDE initialization)
4748c2ecf20Sopenharmony_ci *	finds a device matching our IDE device tables.
4758c2ecf20Sopenharmony_ci */
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_cistatic int pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id)
4788c2ecf20Sopenharmony_ci{
4798c2ecf20Sopenharmony_ci	const struct ide_port_info *d = &pdcnew_chipsets[id->driver_data];
4808c2ecf20Sopenharmony_ci	struct pci_dev *bridge = dev->bus->self;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	if (dev->device == PCI_DEVICE_ID_PROMISE_20270 && bridge &&
4838c2ecf20Sopenharmony_ci	    bridge->vendor == PCI_VENDOR_ID_DEC &&
4848c2ecf20Sopenharmony_ci	    bridge->device == PCI_DEVICE_ID_DEC_21150) {
4858c2ecf20Sopenharmony_ci		struct pci_dev *dev2;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci		if (PCI_SLOT(dev->devfn) & 2)
4888c2ecf20Sopenharmony_ci			return -ENODEV;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci		dev2 = pdc20270_get_dev2(dev);
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci		if (dev2) {
4938c2ecf20Sopenharmony_ci			int ret = ide_pci_init_two(dev, dev2, d, NULL);
4948c2ecf20Sopenharmony_ci			if (ret < 0)
4958c2ecf20Sopenharmony_ci				pci_dev_put(dev2);
4968c2ecf20Sopenharmony_ci			return ret;
4978c2ecf20Sopenharmony_ci		}
4988c2ecf20Sopenharmony_ci	}
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	if (dev->device == PCI_DEVICE_ID_PROMISE_20276 && bridge &&
5018c2ecf20Sopenharmony_ci	    bridge->vendor == PCI_VENDOR_ID_INTEL &&
5028c2ecf20Sopenharmony_ci	    (bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
5038c2ecf20Sopenharmony_ci	     bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
5048c2ecf20Sopenharmony_ci		printk(KERN_INFO DRV_NAME " %s: attached to I2O RAID controller,"
5058c2ecf20Sopenharmony_ci			" skipping\n", pci_name(dev));
5068c2ecf20Sopenharmony_ci		return -ENODEV;
5078c2ecf20Sopenharmony_ci	}
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	return ide_pci_init_one(dev, d, NULL);
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_cistatic void pdc202new_remove(struct pci_dev *dev)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	struct ide_host *host = pci_get_drvdata(dev);
5158c2ecf20Sopenharmony_ci	struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	ide_pci_remove(dev);
5188c2ecf20Sopenharmony_ci	pci_dev_put(dev2);
5198c2ecf20Sopenharmony_ci}
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_cistatic const struct pci_device_id pdc202new_pci_tbl[] = {
5228c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20268), 0 },
5238c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20269), 1 },
5248c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), 0 },
5258c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 1 },
5268c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 1 },
5278c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 1 },
5288c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 1 },
5298c2ecf20Sopenharmony_ci	{ 0, },
5308c2ecf20Sopenharmony_ci};
5318c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_cistatic struct pci_driver pdc202new_pci_driver = {
5348c2ecf20Sopenharmony_ci	.name		= "Promise_IDE",
5358c2ecf20Sopenharmony_ci	.id_table	= pdc202new_pci_tbl,
5368c2ecf20Sopenharmony_ci	.probe		= pdc202new_init_one,
5378c2ecf20Sopenharmony_ci	.remove		= pdc202new_remove,
5388c2ecf20Sopenharmony_ci	.suspend	= ide_pci_suspend,
5398c2ecf20Sopenharmony_ci	.resume		= ide_pci_resume,
5408c2ecf20Sopenharmony_ci};
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_cistatic int __init pdc202new_ide_init(void)
5438c2ecf20Sopenharmony_ci{
5448c2ecf20Sopenharmony_ci	return ide_pci_register_driver(&pdc202new_pci_driver);
5458c2ecf20Sopenharmony_ci}
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_cistatic void __exit pdc202new_ide_exit(void)
5488c2ecf20Sopenharmony_ci{
5498c2ecf20Sopenharmony_ci	pci_unregister_driver(&pdc202new_pci_driver);
5508c2ecf20Sopenharmony_ci}
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_cimodule_init(pdc202new_ide_init);
5538c2ecf20Sopenharmony_cimodule_exit(pdc202new_ide_exit);
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ciMODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
5568c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PCI driver module for Promise PDC20268 and higher");
5578c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
558