18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Copyright (C) 1995-2000  Linus Torvalds & author (see below)
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci/*
78c2ecf20Sopenharmony_ci *  HT-6560B EIDE-controller support
88c2ecf20Sopenharmony_ci *  To activate controller support use kernel parameter "ide0=ht6560b".
98c2ecf20Sopenharmony_ci *  Use hdparm utility to enable PIO mode support.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci *  Author:    Mikko Ala-Fossi            <maf@iki.fi>
128c2ecf20Sopenharmony_ci *             Jan Evert van Grootheest   <j.e.van.grootheest@caiway.nl>
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci */
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#define DRV_NAME	"ht6560b"
178c2ecf20Sopenharmony_ci#define HT6560B_VERSION "v0.08"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include <linux/module.h>
208c2ecf20Sopenharmony_ci#include <linux/types.h>
218c2ecf20Sopenharmony_ci#include <linux/kernel.h>
228c2ecf20Sopenharmony_ci#include <linux/delay.h>
238c2ecf20Sopenharmony_ci#include <linux/timer.h>
248c2ecf20Sopenharmony_ci#include <linux/mm.h>
258c2ecf20Sopenharmony_ci#include <linux/ioport.h>
268c2ecf20Sopenharmony_ci#include <linux/blkdev.h>
278c2ecf20Sopenharmony_ci#include <linux/ide.h>
288c2ecf20Sopenharmony_ci#include <linux/init.h>
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#include <asm/io.h>
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* #define DEBUG */  /* remove comments for DEBUG messages */
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/*
358c2ecf20Sopenharmony_ci * The special i/o-port that HT-6560B uses to configuration:
368c2ecf20Sopenharmony_ci *    bit0 (0x01): "1" selects secondary interface
378c2ecf20Sopenharmony_ci *    bit2 (0x04): "1" enables FIFO function
388c2ecf20Sopenharmony_ci *    bit5 (0x20): "1" enables prefetched data read function  (???)
398c2ecf20Sopenharmony_ci *
408c2ecf20Sopenharmony_ci * The special i/o-port that HT-6560A uses to configuration:
418c2ecf20Sopenharmony_ci *    bit0 (0x01): "1" selects secondary interface
428c2ecf20Sopenharmony_ci *    bit1 (0x02): "1" enables prefetched data read function
438c2ecf20Sopenharmony_ci *    bit2 (0x04): "0" enables multi-master system	      (?)
448c2ecf20Sopenharmony_ci *    bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time	      (?)
458c2ecf20Sopenharmony_ci */
468c2ecf20Sopenharmony_ci#define HT_CONFIG_PORT	  0x3e6
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic inline u8 HT_CONFIG(ide_drive_t *drive)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	return ((unsigned long)ide_get_drivedata(drive) & 0xff00) >> 8;
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/*
548c2ecf20Sopenharmony_ci * FIFO + PREFETCH (both a/b-model)
558c2ecf20Sopenharmony_ci */
568c2ecf20Sopenharmony_ci#define HT_CONFIG_DEFAULT 0x1c /* no prefetch */
578c2ecf20Sopenharmony_ci/* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */
588c2ecf20Sopenharmony_ci#define HT_SECONDARY_IF	  0x01
598c2ecf20Sopenharmony_ci#define HT_PREFETCH_MODE  0x20
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/*
628c2ecf20Sopenharmony_ci * ht6560b Timing values:
638c2ecf20Sopenharmony_ci *
648c2ecf20Sopenharmony_ci * I reviewed some assembler source listings of htide drivers and found
658c2ecf20Sopenharmony_ci * out how they setup those cycle time interfacing values, as they at Holtek
668c2ecf20Sopenharmony_ci * call them. IDESETUP.COM that is supplied with the drivers figures out
678c2ecf20Sopenharmony_ci * optimal values and fetches those values to drivers. I found out that
688c2ecf20Sopenharmony_ci * they use Select register to fetch timings to the ide board right after
698c2ecf20Sopenharmony_ci * interface switching. After that it was quite easy to add code to
708c2ecf20Sopenharmony_ci * ht6560b.c.
718c2ecf20Sopenharmony_ci *
728c2ecf20Sopenharmony_ci * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine
738c2ecf20Sopenharmony_ci * for hda and hdc. But hdb needed higher values to work, so I guess
748c2ecf20Sopenharmony_ci * that sometimes it is necessary to give higher value than IDESETUP
758c2ecf20Sopenharmony_ci * gives.   [see cmd640.c for an extreme example of this. -ml]
768c2ecf20Sopenharmony_ci *
778c2ecf20Sopenharmony_ci * Perhaps I should explain something about these timing values:
788c2ecf20Sopenharmony_ci * The higher nibble of value is the Recovery Time  (rt) and the lower nibble
798c2ecf20Sopenharmony_ci * of the value is the Active Time  (at). Minimum value 2 is the fastest and
808c2ecf20Sopenharmony_ci * the maximum value 15 is the slowest. Default values should be 15 for both.
818c2ecf20Sopenharmony_ci * So 0x24 means 2 for rt and 4 for at. Each of the drives should have
828c2ecf20Sopenharmony_ci * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or
838c2ecf20Sopenharmony_ci * similar. If value is too small there will be all sorts of failures.
848c2ecf20Sopenharmony_ci *
858c2ecf20Sopenharmony_ci * Timing byte consists of
868c2ecf20Sopenharmony_ci *	High nibble:  Recovery Cycle Time  (rt)
878c2ecf20Sopenharmony_ci *	     The valid values range from 2 to 15. The default is 15.
888c2ecf20Sopenharmony_ci *
898c2ecf20Sopenharmony_ci *	Low nibble:   Active Cycle Time	   (at)
908c2ecf20Sopenharmony_ci *	     The valid values range from 2 to 15. The default is 15.
918c2ecf20Sopenharmony_ci *
928c2ecf20Sopenharmony_ci * You can obtain optimized timing values by running Holtek IDESETUP.COM
938c2ecf20Sopenharmony_ci * for DOS. DOS drivers get their timing values from command line, where
948c2ecf20Sopenharmony_ci * the first value is the Recovery Time and the second value is the
958c2ecf20Sopenharmony_ci * Active Time for each drive. Smaller value gives higher speed.
968c2ecf20Sopenharmony_ci * In case of failures you should probably fall back to a higher value.
978c2ecf20Sopenharmony_ci */
988c2ecf20Sopenharmony_cistatic inline u8 HT_TIMING(ide_drive_t *drive)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	return (unsigned long)ide_get_drivedata(drive) & 0x00ff;
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci#define HT_TIMING_DEFAULT 0xff
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/*
1068c2ecf20Sopenharmony_ci * This routine handles interface switching for the peculiar hardware design
1078c2ecf20Sopenharmony_ci * on the F.G.I./Holtek HT-6560B VLB IDE interface.
1088c2ecf20Sopenharmony_ci * The HT-6560B can only enable one IDE port at a time, and requires a
1098c2ecf20Sopenharmony_ci * silly sequence (below) whenever we switch between primary and secondary.
1108c2ecf20Sopenharmony_ci */
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci/*
1138c2ecf20Sopenharmony_ci * This routine is invoked from ide.c to prepare for access to a given drive.
1148c2ecf20Sopenharmony_ci */
1158c2ecf20Sopenharmony_cistatic void ht6560b_dev_select(ide_drive_t *drive)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	ide_hwif_t *hwif = drive->hwif;
1188c2ecf20Sopenharmony_ci	unsigned long flags;
1198c2ecf20Sopenharmony_ci	static u8 current_select = 0;
1208c2ecf20Sopenharmony_ci	static u8 current_timing = 0;
1218c2ecf20Sopenharmony_ci	u8 select, timing;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	local_irq_save(flags);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	select = HT_CONFIG(drive);
1268c2ecf20Sopenharmony_ci	timing = HT_TIMING(drive);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	/*
1298c2ecf20Sopenharmony_ci	 * Need to enforce prefetch sometimes because otherwise
1308c2ecf20Sopenharmony_ci	 * it'll hang (hard).
1318c2ecf20Sopenharmony_ci	 */
1328c2ecf20Sopenharmony_ci	if (drive->media != ide_disk ||
1338c2ecf20Sopenharmony_ci	    (drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
1348c2ecf20Sopenharmony_ci		select |= HT_PREFETCH_MODE;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	if (select != current_select || timing != current_timing) {
1378c2ecf20Sopenharmony_ci		current_select = select;
1388c2ecf20Sopenharmony_ci		current_timing = timing;
1398c2ecf20Sopenharmony_ci		(void)inb(HT_CONFIG_PORT);
1408c2ecf20Sopenharmony_ci		(void)inb(HT_CONFIG_PORT);
1418c2ecf20Sopenharmony_ci		(void)inb(HT_CONFIG_PORT);
1428c2ecf20Sopenharmony_ci		(void)inb(HT_CONFIG_PORT);
1438c2ecf20Sopenharmony_ci		outb(select, HT_CONFIG_PORT);
1448c2ecf20Sopenharmony_ci		/*
1458c2ecf20Sopenharmony_ci		 * Set timing for this drive:
1468c2ecf20Sopenharmony_ci		 */
1478c2ecf20Sopenharmony_ci		outb(timing, hwif->io_ports.device_addr);
1488c2ecf20Sopenharmony_ci		(void)inb(hwif->io_ports.status_addr);
1498c2ecf20Sopenharmony_ci#ifdef DEBUG
1508c2ecf20Sopenharmony_ci		printk("ht6560b: %s: select=%#x timing=%#x\n",
1518c2ecf20Sopenharmony_ci			drive->name, select, timing);
1528c2ecf20Sopenharmony_ci#endif
1538c2ecf20Sopenharmony_ci	}
1548c2ecf20Sopenharmony_ci	local_irq_restore(flags);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	outb(drive->select | ATA_DEVICE_OBS, hwif->io_ports.device_addr);
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci/*
1608c2ecf20Sopenharmony_ci * Autodetection and initialization of ht6560b
1618c2ecf20Sopenharmony_ci */
1628c2ecf20Sopenharmony_cistatic int __init try_to_init_ht6560b(void)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	u8 orig_value;
1658c2ecf20Sopenharmony_ci	int i;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	/* Autodetect ht6560b */
1688c2ecf20Sopenharmony_ci	if ((orig_value = inb(HT_CONFIG_PORT)) == 0xff)
1698c2ecf20Sopenharmony_ci		return 0;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	for (i=3;i>0;i--) {
1728c2ecf20Sopenharmony_ci		outb(0x00, HT_CONFIG_PORT);
1738c2ecf20Sopenharmony_ci		if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) {
1748c2ecf20Sopenharmony_ci			outb(orig_value, HT_CONFIG_PORT);
1758c2ecf20Sopenharmony_ci			return 0;
1768c2ecf20Sopenharmony_ci		}
1778c2ecf20Sopenharmony_ci	}
1788c2ecf20Sopenharmony_ci	outb(0x00, HT_CONFIG_PORT);
1798c2ecf20Sopenharmony_ci	if ((~inb(HT_CONFIG_PORT))& 0x3f) {
1808c2ecf20Sopenharmony_ci		outb(orig_value, HT_CONFIG_PORT);
1818c2ecf20Sopenharmony_ci		return 0;
1828c2ecf20Sopenharmony_ci	}
1838c2ecf20Sopenharmony_ci	/*
1848c2ecf20Sopenharmony_ci	 * Ht6560b autodetected
1858c2ecf20Sopenharmony_ci	 */
1868c2ecf20Sopenharmony_ci	outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
1878c2ecf20Sopenharmony_ci	outb(HT_TIMING_DEFAULT, 0x1f6);	/* Select register */
1888c2ecf20Sopenharmony_ci	(void)inb(0x1f7);		/* Status register */
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	printk("ht6560b " HT6560B_VERSION
1918c2ecf20Sopenharmony_ci	       ": chipset detected and initialized"
1928c2ecf20Sopenharmony_ci#ifdef DEBUG
1938c2ecf20Sopenharmony_ci	       " with debug enabled"
1948c2ecf20Sopenharmony_ci#endif
1958c2ecf20Sopenharmony_ci	       "\n"
1968c2ecf20Sopenharmony_ci		);
1978c2ecf20Sopenharmony_ci	return 1;
1988c2ecf20Sopenharmony_ci}
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistatic u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	int active_time, recovery_time;
2038c2ecf20Sopenharmony_ci	int active_cycles, recovery_cycles;
2048c2ecf20Sopenharmony_ci	int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci        if (pio) {
2078c2ecf20Sopenharmony_ci		unsigned int cycle_time;
2088c2ecf20Sopenharmony_ci		struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci		cycle_time = ide_pio_cycle_time(drive, pio);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci		/*
2138c2ecf20Sopenharmony_ci		 *  Just like opti621.c we try to calculate the
2148c2ecf20Sopenharmony_ci		 *  actual cycle time for recovery and activity
2158c2ecf20Sopenharmony_ci		 *  according system bus speed.
2168c2ecf20Sopenharmony_ci		 */
2178c2ecf20Sopenharmony_ci		active_time = t->active;
2188c2ecf20Sopenharmony_ci		recovery_time = cycle_time - active_time - t->setup;
2198c2ecf20Sopenharmony_ci		/*
2208c2ecf20Sopenharmony_ci		 *  Cycle times should be Vesa bus cycles
2218c2ecf20Sopenharmony_ci		 */
2228c2ecf20Sopenharmony_ci		active_cycles   = (active_time   * bus_speed + 999) / 1000;
2238c2ecf20Sopenharmony_ci		recovery_cycles = (recovery_time * bus_speed + 999) / 1000;
2248c2ecf20Sopenharmony_ci		/*
2258c2ecf20Sopenharmony_ci		 *  Upper and lower limits
2268c2ecf20Sopenharmony_ci		 */
2278c2ecf20Sopenharmony_ci		if (active_cycles   < 2)  active_cycles   = 2;
2288c2ecf20Sopenharmony_ci		if (recovery_cycles < 2)  recovery_cycles = 2;
2298c2ecf20Sopenharmony_ci		if (active_cycles   > 15) active_cycles   = 15;
2308c2ecf20Sopenharmony_ci		if (recovery_cycles > 15) recovery_cycles = 0;  /* 0==16 */
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci#ifdef DEBUG
2338c2ecf20Sopenharmony_ci		printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)\n", drive->name, pio, recovery_cycles, recovery_time, active_cycles, active_time);
2348c2ecf20Sopenharmony_ci#endif
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci		return (u8)((recovery_cycles << 4) | active_cycles);
2378c2ecf20Sopenharmony_ci	} else {
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci#ifdef DEBUG
2408c2ecf20Sopenharmony_ci		printk("ht6560b: drive %s setting pio=0\n", drive->name);
2418c2ecf20Sopenharmony_ci#endif
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci		return HT_TIMING_DEFAULT;    /* default setting */
2448c2ecf20Sopenharmony_ci	}
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(ht6560b_lock);
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci/*
2508c2ecf20Sopenharmony_ci *  Enable/Disable so called prefetch mode
2518c2ecf20Sopenharmony_ci */
2528c2ecf20Sopenharmony_cistatic void ht_set_prefetch(ide_drive_t *drive, u8 state)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	unsigned long flags, config;
2558c2ecf20Sopenharmony_ci	int t = HT_PREFETCH_MODE << 8;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ht6560b_lock, flags);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	config = (unsigned long)ide_get_drivedata(drive);
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	/*
2628c2ecf20Sopenharmony_ci	 *  Prefetch mode and unmask irq seems to conflict
2638c2ecf20Sopenharmony_ci	 */
2648c2ecf20Sopenharmony_ci	if (state) {
2658c2ecf20Sopenharmony_ci		config |= t;   /* enable prefetch mode */
2668c2ecf20Sopenharmony_ci		drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
2678c2ecf20Sopenharmony_ci		drive->dev_flags &= ~IDE_DFLAG_UNMASK;
2688c2ecf20Sopenharmony_ci	} else {
2698c2ecf20Sopenharmony_ci		config &= ~t;  /* disable prefetch mode */
2708c2ecf20Sopenharmony_ci		drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
2718c2ecf20Sopenharmony_ci	}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	ide_set_drivedata(drive, (void *)config);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ht6560b_lock, flags);
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci#ifdef DEBUG
2788c2ecf20Sopenharmony_ci	printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis"));
2798c2ecf20Sopenharmony_ci#endif
2808c2ecf20Sopenharmony_ci}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_cistatic void ht6560b_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
2838c2ecf20Sopenharmony_ci{
2848c2ecf20Sopenharmony_ci	unsigned long flags, config;
2858c2ecf20Sopenharmony_ci	const u8 pio = drive->pio_mode - XFER_PIO_0;
2868c2ecf20Sopenharmony_ci	u8 timing;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	switch (pio) {
2898c2ecf20Sopenharmony_ci	case 8:         /* set prefetch off */
2908c2ecf20Sopenharmony_ci	case 9:         /* set prefetch on */
2918c2ecf20Sopenharmony_ci		ht_set_prefetch(drive, pio & 1);
2928c2ecf20Sopenharmony_ci		return;
2938c2ecf20Sopenharmony_ci	}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	timing = ht_pio2timings(drive, pio);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ht6560b_lock, flags);
2988c2ecf20Sopenharmony_ci	config = (unsigned long)ide_get_drivedata(drive);
2998c2ecf20Sopenharmony_ci	config &= 0xff00;
3008c2ecf20Sopenharmony_ci	config |= timing;
3018c2ecf20Sopenharmony_ci	ide_set_drivedata(drive, (void *)config);
3028c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ht6560b_lock, flags);
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci#ifdef DEBUG
3058c2ecf20Sopenharmony_ci	printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing);
3068c2ecf20Sopenharmony_ci#endif
3078c2ecf20Sopenharmony_ci}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_cistatic void __init ht6560b_init_dev(ide_drive_t *drive)
3108c2ecf20Sopenharmony_ci{
3118c2ecf20Sopenharmony_ci	ide_hwif_t *hwif = drive->hwif;
3128c2ecf20Sopenharmony_ci	/* Setting default configurations for drives. */
3138c2ecf20Sopenharmony_ci	unsigned long t = (HT_CONFIG_DEFAULT << 8) | HT_TIMING_DEFAULT;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	if (hwif->channel)
3168c2ecf20Sopenharmony_ci		t |= (HT_SECONDARY_IF << 8);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	ide_set_drivedata(drive, (void *)t);
3198c2ecf20Sopenharmony_ci}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic bool probe_ht6560b;
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_cimodule_param_named(probe, probe_ht6560b, bool, 0);
3248c2ecf20Sopenharmony_ciMODULE_PARM_DESC(probe, "probe for HT6560B chipset");
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cistatic const struct ide_tp_ops ht6560b_tp_ops = {
3278c2ecf20Sopenharmony_ci	.exec_command		= ide_exec_command,
3288c2ecf20Sopenharmony_ci	.read_status		= ide_read_status,
3298c2ecf20Sopenharmony_ci	.read_altstatus		= ide_read_altstatus,
3308c2ecf20Sopenharmony_ci	.write_devctl		= ide_write_devctl,
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	.dev_select		= ht6560b_dev_select,
3338c2ecf20Sopenharmony_ci	.tf_load		= ide_tf_load,
3348c2ecf20Sopenharmony_ci	.tf_read		= ide_tf_read,
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	.input_data		= ide_input_data,
3378c2ecf20Sopenharmony_ci	.output_data		= ide_output_data,
3388c2ecf20Sopenharmony_ci};
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_cistatic const struct ide_port_ops ht6560b_port_ops = {
3418c2ecf20Sopenharmony_ci	.init_dev		= ht6560b_init_dev,
3428c2ecf20Sopenharmony_ci	.set_pio_mode		= ht6560b_set_pio_mode,
3438c2ecf20Sopenharmony_ci};
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic const struct ide_port_info ht6560b_port_info __initconst = {
3468c2ecf20Sopenharmony_ci	.name			= DRV_NAME,
3478c2ecf20Sopenharmony_ci	.chipset		= ide_ht6560b,
3488c2ecf20Sopenharmony_ci	.tp_ops 		= &ht6560b_tp_ops,
3498c2ecf20Sopenharmony_ci	.port_ops		= &ht6560b_port_ops,
3508c2ecf20Sopenharmony_ci	.host_flags		= IDE_HFLAG_SERIALIZE | /* is this needed? */
3518c2ecf20Sopenharmony_ci				  IDE_HFLAG_NO_DMA |
3528c2ecf20Sopenharmony_ci				  IDE_HFLAG_ABUSE_PREFETCH,
3538c2ecf20Sopenharmony_ci	.pio_mask		= ATA_PIO4,
3548c2ecf20Sopenharmony_ci};
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_cistatic int __init ht6560b_init(void)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	if (probe_ht6560b == 0)
3598c2ecf20Sopenharmony_ci		return -ENODEV;
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	if (!request_region(HT_CONFIG_PORT, 1, DRV_NAME)) {
3628c2ecf20Sopenharmony_ci		printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
3638c2ecf20Sopenharmony_ci			__func__);
3648c2ecf20Sopenharmony_ci		return -ENODEV;
3658c2ecf20Sopenharmony_ci	}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	if (!try_to_init_ht6560b()) {
3688c2ecf20Sopenharmony_ci		printk(KERN_NOTICE "%s: HBA not found\n", __func__);
3698c2ecf20Sopenharmony_ci		goto release_region;
3708c2ecf20Sopenharmony_ci	}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	return ide_legacy_device_add(&ht6560b_port_info, 0);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_cirelease_region:
3758c2ecf20Sopenharmony_ci	release_region(HT_CONFIG_PORT, 1);
3768c2ecf20Sopenharmony_ci	return -ENODEV;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cimodule_init(ht6560b_init);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ciMODULE_AUTHOR("See Local File");
3828c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("HT-6560B EIDE-controller support");
3838c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
384