11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * H8/300 generic IDE interface
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ide.h>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11eb3aff5530d22eb4be0a99c9d39c9ffde7b9891aBartlomiej Zolnierkiewicz#define DRV_NAME "ide-h8300"
12eb3aff5530d22eb4be0a99c9d39c9ffde7b9891aBartlomiej Zolnierkiewicz
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define bswap(d) \
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds({					\
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 r;				\
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__("mov.b %w1,r1h\n\t"	\
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"mov.b %x1,r1l\n\t"	\
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"mov.w r1,%0"		\
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		:"=r"(r)		\
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		:"r"(d)			\
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		:"er1");		\
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(r);				\
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds})
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mm_outsw(unsigned long addr, void *buf, u32 len)
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short *bp = (unsigned short *)buf;
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (; len > 0; len--, bp++)
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*(volatile u16 *)addr = bswap(*bp);
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mm_insw(unsigned long addr, void *buf, u32 len)
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short *bp = (unsigned short *)buf;
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (; len > 0; len--, bp++)
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*bp = bswap(*(volatile u16 *)addr);
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39adb1af9803d167091c2cb4de14014185054bfe2cBartlomiej Zolnierkiewiczstatic void h8300_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
40f04ff9cbb6389a6db64659cf917a1b6ac159f9f2Bartlomiej Zolnierkiewicz			     void *buf, unsigned int len)
41f04ff9cbb6389a6db64659cf917a1b6ac159f9f2Bartlomiej Zolnierkiewicz{
42f04ff9cbb6389a6db64659cf917a1b6ac159f9f2Bartlomiej Zolnierkiewicz	mm_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
43f04ff9cbb6389a6db64659cf917a1b6ac159f9f2Bartlomiej Zolnierkiewicz}
44f04ff9cbb6389a6db64659cf917a1b6ac159f9f2Bartlomiej Zolnierkiewicz
45adb1af9803d167091c2cb4de14014185054bfe2cBartlomiej Zolnierkiewiczstatic void h8300_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
46f04ff9cbb6389a6db64659cf917a1b6ac159f9f2Bartlomiej Zolnierkiewicz			      void *buf, unsigned int len)
47f04ff9cbb6389a6db64659cf917a1b6ac159f9f2Bartlomiej Zolnierkiewicz{
48f04ff9cbb6389a6db64659cf917a1b6ac159f9f2Bartlomiej Zolnierkiewicz	mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
49f04ff9cbb6389a6db64659cf917a1b6ac159f9f2Bartlomiej Zolnierkiewicz}
50f04ff9cbb6389a6db64659cf917a1b6ac159f9f2Bartlomiej Zolnierkiewicz
51374e042c3e767ac2e5a40b78529220e0b3de793cBartlomiej Zolnierkiewiczstatic const struct ide_tp_ops h8300_tp_ops = {
52374e042c3e767ac2e5a40b78529220e0b3de793cBartlomiej Zolnierkiewicz	.exec_command		= ide_exec_command,
53374e042c3e767ac2e5a40b78529220e0b3de793cBartlomiej Zolnierkiewicz	.read_status		= ide_read_status,
54374e042c3e767ac2e5a40b78529220e0b3de793cBartlomiej Zolnierkiewicz	.read_altstatus		= ide_read_altstatus,
55ecf3a31d2a08a419bdf919456f1724f5b72bde2cSergei Shtylyov	.write_devctl		= ide_write_devctl,
56374e042c3e767ac2e5a40b78529220e0b3de793cBartlomiej Zolnierkiewicz
57abb596b25edac1ec1acc4ef53df190771661c3d2Sergei Shtylyov	.dev_select		= ide_dev_select,
58cfd30daa0d6cbdb0bbc2bc40a10097231b23b204Sergei Shtylyov	.tf_load		= ide_tf_load,
59cfd30daa0d6cbdb0bbc2bc40a10097231b23b204Sergei Shtylyov	.tf_read		= ide_tf_read,
60374e042c3e767ac2e5a40b78529220e0b3de793cBartlomiej Zolnierkiewicz
61374e042c3e767ac2e5a40b78529220e0b3de793cBartlomiej Zolnierkiewicz	.input_data		= h8300_input_data,
62374e042c3e767ac2e5a40b78529220e0b3de793cBartlomiej Zolnierkiewicz	.output_data		= h8300_output_data,
63374e042c3e767ac2e5a40b78529220e0b3de793cBartlomiej Zolnierkiewicz};
64374e042c3e767ac2e5a40b78529220e0b3de793cBartlomiej Zolnierkiewicz
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define H8300_IDE_GAP (2)
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
679f36d31437922354d104a2db407f397e79e4027eBartlomiej Zolnierkiewiczstatic inline void hw_setup(struct ide_hw *hw)
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
719f36d31437922354d104a2db407f397e79e4027eBartlomiej Zolnierkiewicz	memset(hw, 0, sizeof(*hw));
724c3032d8a4d6c97bd6e02bcab524ef2428d89561Bartlomiej Zolnierkiewicz	for (i = 0; i <= 7; i++)
734c3032d8a4d6c97bd6e02bcab524ef2428d89561Bartlomiej Zolnierkiewicz		hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i;
744c3032d8a4d6c97bd6e02bcab524ef2428d89561Bartlomiej Zolnierkiewicz	hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ;
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
78f81eb80bbb949f9498980c785ef7dd4c994a4909Bartlomiej Zolnierkiewiczstatic const struct ide_port_info h8300_port_info = {
79374e042c3e767ac2e5a40b78529220e0b3de793cBartlomiej Zolnierkiewicz	.tp_ops			= &h8300_tp_ops,
80f81eb80bbb949f9498980c785ef7dd4c994a4909Bartlomiej Zolnierkiewicz	.host_flags		= IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA,
8129e52cf793ded6bece50de50e738596f94f07d9fBartlomiej Zolnierkiewicz	.chipset		= ide_generic,
82f81eb80bbb949f9498980c785ef7dd4c994a4909Bartlomiej Zolnierkiewicz};
83f81eb80bbb949f9498980c785ef7dd4c994a4909Bartlomiej Zolnierkiewicz
84ade2daf9c6e57845fe83a24e0a9fa1c03c6e91b1Bartlomiej Zolnierkiewiczstatic int __init h8300_ide_init(void)
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
869f36d31437922354d104a2db407f397e79e4027eBartlomiej Zolnierkiewicz	struct ide_hw hw, *hws[] = { &hw };
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
88740c397cc64272917a4c4c283649579d2044a836Bartlomiej Zolnierkiewicz	printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n");
89740c397cc64272917a4c4c283649579d2044a836Bartlomiej Zolnierkiewicz
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300"))
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_busy;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!request_region(CONFIG_H8300_IDE_ALT, H8300_IDE_GAP, "ide-h8300")) {
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		release_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8);
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_busy;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hw_setup(&hw);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
99dca3983059a4481e4ae97bbf0ac4b4c21429e1a5Bartlomiej Zolnierkiewicz	return ide_host_add(&h8300_port_info, hws, 1, NULL);
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_busy:
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
103ade2daf9c6e57845fe83a24e0a9fa1c03c6e91b1Bartlomiej Zolnierkiewicz
104ade2daf9c6e57845fe83a24e0a9fa1c03c6e91b1Bartlomiej Zolnierkiewicz	return -EBUSY;
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
106ade2daf9c6e57845fe83a24e0a9fa1c03c6e91b1Bartlomiej Zolnierkiewicz
107ade2daf9c6e57845fe83a24e0a9fa1c03c6e91b1Bartlomiej Zolnierkiewiczmodule_init(h8300_ide_init);
108f95dc32001445c6706ce0c337628b7c12d42a267Adrian Bunk
109f95dc32001445c6706ce0c337628b7c12d42a267Adrian BunkMODULE_LICENSE("GPL");
110