mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	m68k/q40: Replace q40ide driver with pata_falcon and falconide
This allows m68k q40 systems to switch from the deprecated IDE subsystem to libata. Enhance the byte-swapping falconide and pata_falcon platform drivers to accept an irq resource, for use on q40. Atari ST-DMA IRQ arrangements seem to co-exist with q40 IRQ arrangements without too much mess. The new IO resources were added solely for the purpose of making request_region() reservations identical to those made by q40ide: these regions aren't used for actual IO. Cc: Michael Schmitz <schmitzmic@gmail.com> Cc: Richard Zidlicky <rz@linux-m68k.org> Reviewed-and-tested-by: Michael Schmitz <schmitzmic@gmail.com> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Finn Thain <fthain@linux-m68k.org> Link: https://lore.kernel.org/r/eefb7e9c2291e09fb4e065ce06bc105f05bb9e06.1623287706.git.fthain@linux-m68k.org Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
		
							parent
							
								
									cabd10be0b
								
							
						
					
					
						commit
						44b1fbc0f5
					
				
					 10 changed files with 147 additions and 251 deletions
				
			
		| 
						 | 
				
			
			@ -875,16 +875,8 @@ static const struct resource atari_scsi_tt_rsrc[] __initconst = {
 | 
			
		|||
#define FALCON_IDE_BASE	0xfff00000
 | 
			
		||||
 | 
			
		||||
static const struct resource atari_falconide_rsrc[] __initconst = {
 | 
			
		||||
	{
 | 
			
		||||
		.flags = IORESOURCE_MEM,
 | 
			
		||||
		.start = FALCON_IDE_BASE,
 | 
			
		||||
		.end   = FALCON_IDE_BASE + 0x39,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		.flags = IORESOURCE_IRQ,
 | 
			
		||||
		.start = IRQ_MFP_FSCSI,
 | 
			
		||||
		.end   = IRQ_MFP_FSCSI,
 | 
			
		||||
	},
 | 
			
		||||
	DEFINE_RES_MEM(FALCON_IDE_BASE, 0x38),
 | 
			
		||||
	DEFINE_RES_MEM(FALCON_IDE_BASE + 0x38, 2),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int __init atari_platform_init(void)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -351,7 +351,6 @@ CONFIG_BLK_DEV_PLATFORM=y
 | 
			
		|||
CONFIG_BLK_DEV_GAYLE=y
 | 
			
		||||
CONFIG_BLK_DEV_BUDDHA=y
 | 
			
		||||
CONFIG_BLK_DEV_FALCON_IDE=y
 | 
			
		||||
CONFIG_BLK_DEV_Q40IDE=y
 | 
			
		||||
CONFIG_RAID_ATTRS=m
 | 
			
		||||
CONFIG_SCSI=y
 | 
			
		||||
CONFIG_BLK_DEV_SD=y
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -317,7 +317,7 @@ CONFIG_DUMMY_IRQ=m
 | 
			
		|||
CONFIG_IDE=y
 | 
			
		||||
CONFIG_IDE_GD_ATAPI=y
 | 
			
		||||
CONFIG_BLK_DEV_IDECD=y
 | 
			
		||||
CONFIG_BLK_DEV_Q40IDE=y
 | 
			
		||||
CONFIG_BLK_DEV_FALCON_IDE=y
 | 
			
		||||
CONFIG_RAID_ATTRS=m
 | 
			
		||||
CONFIG_SCSI=y
 | 
			
		||||
CONFIG_BLK_DEV_SD=y
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -286,14 +286,39 @@ static int q40_set_rtc_pll(struct rtc_pll_info *pll)
 | 
			
		|||
		return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static __init int q40_add_kbd_device(void)
 | 
			
		||||
{
 | 
			
		||||
	struct platform_device *pdev;
 | 
			
		||||
#define PCIDE_BASE1	0x1f0
 | 
			
		||||
#define PCIDE_BASE2	0x170
 | 
			
		||||
#define PCIDE_CTL	0x206
 | 
			
		||||
 | 
			
		||||
static const struct resource q40_pata_rsrc_0[] __initconst = {
 | 
			
		||||
	DEFINE_RES_MEM(q40_isa_io_base + PCIDE_BASE1 * 4, 0x38),
 | 
			
		||||
	DEFINE_RES_MEM(q40_isa_io_base + (PCIDE_BASE1 + PCIDE_CTL) * 4, 2),
 | 
			
		||||
	DEFINE_RES_IO(PCIDE_BASE1, 8),
 | 
			
		||||
	DEFINE_RES_IO(PCIDE_BASE1 + PCIDE_CTL, 1),
 | 
			
		||||
	DEFINE_RES_IRQ(14),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct resource q40_pata_rsrc_1[] __initconst = {
 | 
			
		||||
	DEFINE_RES_MEM(q40_isa_io_base + PCIDE_BASE2 * 4, 0x38),
 | 
			
		||||
	DEFINE_RES_MEM(q40_isa_io_base + (PCIDE_BASE2 + PCIDE_CTL) * 4, 2),
 | 
			
		||||
	DEFINE_RES_IO(PCIDE_BASE2, 8),
 | 
			
		||||
	DEFINE_RES_IO(PCIDE_BASE2 + PCIDE_CTL, 1),
 | 
			
		||||
	DEFINE_RES_IRQ(15),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static __init int q40_platform_init(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!MACH_IS_Q40)
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
 | 
			
		||||
	pdev = platform_device_register_simple("q40kbd", -1, NULL, 0);
 | 
			
		||||
	return PTR_ERR_OR_ZERO(pdev);
 | 
			
		||||
	platform_device_register_simple("q40kbd", -1, NULL, 0);
 | 
			
		||||
 | 
			
		||||
	platform_device_register_simple("atari-falcon-ide", 0, q40_pata_rsrc_0,
 | 
			
		||||
					ARRAY_SIZE(q40_pata_rsrc_0));
 | 
			
		||||
 | 
			
		||||
	platform_device_register_simple("atari-falcon-ide", 1, q40_pata_rsrc_1,
 | 
			
		||||
					ARRAY_SIZE(q40_pata_rsrc_1));
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
arch_initcall(q40_add_kbd_device);
 | 
			
		||||
arch_initcall(q40_platform_init);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1015,11 +1015,11 @@ config PATA_CMD640_PCI
 | 
			
		|||
	  If unsure, say N.
 | 
			
		||||
 | 
			
		||||
config PATA_FALCON
 | 
			
		||||
	tristate "Atari Falcon PATA support"
 | 
			
		||||
	depends on M68K && ATARI
 | 
			
		||||
	tristate "Atari Falcon and Q40/Q60 PATA support"
 | 
			
		||||
	depends on M68K && (ATARI || Q40)
 | 
			
		||||
	help
 | 
			
		||||
	  This option enables support for the on-board IDE
 | 
			
		||||
	  interface on the Atari Falcon.
 | 
			
		||||
	  interface on the Atari Falcon and Q40/Q60.
 | 
			
		||||
 | 
			
		||||
	  If unsure, say N.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,8 +33,6 @@
 | 
			
		|||
#define DRV_NAME "pata_falcon"
 | 
			
		||||
#define DRV_VERSION "0.1.0"
 | 
			
		||||
 | 
			
		||||
#define ATA_HD_CONTROL	0x39
 | 
			
		||||
 | 
			
		||||
static struct scsi_host_template pata_falcon_sht = {
 | 
			
		||||
	ATA_PIO_SHT(DRV_NAME),
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -121,23 +119,42 @@ static struct ata_port_operations pata_falcon_ops = {
 | 
			
		|||
 | 
			
		||||
static int __init pata_falcon_init_one(struct platform_device *pdev)
 | 
			
		||||
{
 | 
			
		||||
	struct resource *res;
 | 
			
		||||
	struct resource *base_mem_res, *ctl_mem_res;
 | 
			
		||||
	struct resource *base_res, *ctl_res, *irq_res;
 | 
			
		||||
	struct ata_host *host;
 | 
			
		||||
	struct ata_port *ap;
 | 
			
		||||
	void __iomem *base;
 | 
			
		||||
	int irq = 0;
 | 
			
		||||
 | 
			
		||||
	dev_info(&pdev->dev, "Atari Falcon PATA controller\n");
 | 
			
		||||
	dev_info(&pdev->dev, "Atari Falcon and Q40/Q60 PATA controller\n");
 | 
			
		||||
 | 
			
		||||
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | 
			
		||||
	if (!res)
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
 | 
			
		||||
	if (!devm_request_mem_region(&pdev->dev, res->start,
 | 
			
		||||
				     resource_size(res), DRV_NAME)) {
 | 
			
		||||
	base_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 | 
			
		||||
	if (base_res && !devm_request_region(&pdev->dev, base_res->start,
 | 
			
		||||
					   resource_size(base_res), DRV_NAME)) {
 | 
			
		||||
		dev_err(&pdev->dev, "resources busy\n");
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1);
 | 
			
		||||
	if (ctl_res && !devm_request_region(&pdev->dev, ctl_res->start,
 | 
			
		||||
					    resource_size(ctl_res), DRV_NAME)) {
 | 
			
		||||
		dev_err(&pdev->dev, "resources busy\n");
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	base_mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | 
			
		||||
	if (!base_mem_res)
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
	if (!devm_request_mem_region(&pdev->dev, base_mem_res->start,
 | 
			
		||||
				     resource_size(base_mem_res), DRV_NAME)) {
 | 
			
		||||
		dev_err(&pdev->dev, "resources busy\n");
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctl_mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 | 
			
		||||
	if (!ctl_mem_res)
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
 | 
			
		||||
	/* allocate host */
 | 
			
		||||
	host = ata_host_alloc(&pdev->dev, 1);
 | 
			
		||||
	if (!host)
 | 
			
		||||
| 
						 | 
				
			
			@ -147,10 +164,10 @@ static int __init pata_falcon_init_one(struct platform_device *pdev)
 | 
			
		|||
	ap->ops = &pata_falcon_ops;
 | 
			
		||||
	ap->pio_mask = ATA_PIO4;
 | 
			
		||||
	ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY;
 | 
			
		||||
	ap->flags |= ATA_FLAG_PIO_POLLING;
 | 
			
		||||
 | 
			
		||||
	base = (void __iomem *)res->start;
 | 
			
		||||
	ap->ioaddr.data_addr		= base;
 | 
			
		||||
	base = (void __iomem *)base_mem_res->start;
 | 
			
		||||
	/* N.B. this assumes data_addr will be used for word-sized I/O only */
 | 
			
		||||
	ap->ioaddr.data_addr		= base + 0 + 0 * 4;
 | 
			
		||||
	ap->ioaddr.error_addr		= base + 1 + 1 * 4;
 | 
			
		||||
	ap->ioaddr.feature_addr		= base + 1 + 1 * 4;
 | 
			
		||||
	ap->ioaddr.nsect_addr		= base + 1 + 2 * 4;
 | 
			
		||||
| 
						 | 
				
			
			@ -161,14 +178,25 @@ static int __init pata_falcon_init_one(struct platform_device *pdev)
 | 
			
		|||
	ap->ioaddr.status_addr		= base + 1 + 7 * 4;
 | 
			
		||||
	ap->ioaddr.command_addr		= base + 1 + 7 * 4;
 | 
			
		||||
 | 
			
		||||
	ap->ioaddr.altstatus_addr	= base + ATA_HD_CONTROL;
 | 
			
		||||
	ap->ioaddr.ctl_addr		= base + ATA_HD_CONTROL;
 | 
			
		||||
	base = (void __iomem *)ctl_mem_res->start;
 | 
			
		||||
	ap->ioaddr.altstatus_addr	= base + 1;
 | 
			
		||||
	ap->ioaddr.ctl_addr		= base + 1;
 | 
			
		||||
 | 
			
		||||
	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", (unsigned long)base,
 | 
			
		||||
		      (unsigned long)base + ATA_HD_CONTROL);
 | 
			
		||||
	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx",
 | 
			
		||||
		      (unsigned long)base_mem_res->start,
 | 
			
		||||
		      (unsigned long)ctl_mem_res->start);
 | 
			
		||||
 | 
			
		||||
	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 | 
			
		||||
	if (irq_res && irq_res->start > 0) {
 | 
			
		||||
		irq = irq_res->start;
 | 
			
		||||
	} else {
 | 
			
		||||
		ap->flags |= ATA_FLAG_PIO_POLLING;
 | 
			
		||||
		ata_port_desc(ap, "no IRQ, using PIO polling");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* activate */
 | 
			
		||||
	return ata_host_activate(host, 0, NULL, 0, &pata_falcon_sht);
 | 
			
		||||
	return ata_host_activate(host, irq, irq ? ata_sff_interrupt : NULL,
 | 
			
		||||
				 IRQF_SHARED, &pata_falcon_sht);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int __exit pata_falcon_remove_one(struct platform_device *pdev)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -731,21 +731,13 @@ config BLK_DEV_BUDDHA
 | 
			
		|||
	  to one of its IDE interfaces.
 | 
			
		||||
 | 
			
		||||
config BLK_DEV_FALCON_IDE
 | 
			
		||||
	tristate "Falcon IDE interface support"
 | 
			
		||||
	depends on ATARI
 | 
			
		||||
	tristate "Falcon and Q40/Q60 IDE interface support"
 | 
			
		||||
	depends on ATARI || Q40
 | 
			
		||||
	help
 | 
			
		||||
	  This is the IDE driver for the on-board IDE interface on the Atari
 | 
			
		||||
	  Falcon. Say Y if you have a Falcon and want to use IDE devices (hard
 | 
			
		||||
	  disks, CD-ROM drives, etc.) that are connected to the on-board IDE
 | 
			
		||||
	  interface.
 | 
			
		||||
 | 
			
		||||
config BLK_DEV_Q40IDE
 | 
			
		||||
	tristate "Q40/Q60 IDE interface support"
 | 
			
		||||
	depends on Q40
 | 
			
		||||
	help
 | 
			
		||||
	  Enable the on-board IDE controller in the Q40/Q60.  This should
 | 
			
		||||
	  normally be on; disable it only if you are running a custom hard
 | 
			
		||||
	  drive subsystem through an expansion card.
 | 
			
		||||
	  Falcon and Q40/Q60. Say Y if you have such a machine and want to use
 | 
			
		||||
	  IDE devices (hard disks, CD-ROM drives, etc.) that are connected to
 | 
			
		||||
	  the on-board IDE interface.
 | 
			
		||||
 | 
			
		||||
config BLK_DEV_PALMCHIP_BK3710
 | 
			
		||||
	tristate "Palmchip bk3710 IDE controller support"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,6 @@ obj-$(CONFIG_BLK_DEV_4DRIVES)		+= ide-4drives.o
 | 
			
		|||
 | 
			
		||||
obj-$(CONFIG_BLK_DEV_GAYLE)		+= gayle.o
 | 
			
		||||
obj-$(CONFIG_BLK_DEV_FALCON_IDE)	+= falconide.o
 | 
			
		||||
obj-$(CONFIG_BLK_DEV_Q40IDE)		+= q40ide.o
 | 
			
		||||
obj-$(CONFIG_BLK_DEV_BUDDHA)		+= buddha.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_BLK_DEV_AEC62XX)		+= aec62xx.o
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,12 +25,7 @@
 | 
			
		|||
 | 
			
		||||
#define DRV_NAME "falconide"
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     *  Offsets from base address
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
#define ATA_HD_CONTROL	0x39
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_ATARI
 | 
			
		||||
    /*
 | 
			
		||||
     *  falconide_intr_lock is used to obtain access to the IDE interrupt,
 | 
			
		||||
     *  which is shared between several drivers.
 | 
			
		||||
| 
						 | 
				
			
			@ -55,6 +50,7 @@ static void falconide_get_lock(irq_handler_t handler, void *data)
 | 
			
		|||
		falconide_intr_lock = 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void falconide_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
 | 
			
		||||
				 void *buf, unsigned int len)
 | 
			
		||||
| 
						 | 
				
			
			@ -98,8 +94,10 @@ static const struct ide_tp_ops falconide_tp_ops = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
static const struct ide_port_info falconide_port_info = {
 | 
			
		||||
#ifdef CONFIG_ATARI
 | 
			
		||||
	.get_lock		= falconide_get_lock,
 | 
			
		||||
	.release_lock		= falconide_release_lock,
 | 
			
		||||
#endif
 | 
			
		||||
	.tp_ops			= &falconide_tp_ops,
 | 
			
		||||
	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE |
 | 
			
		||||
				  IDE_HFLAG_NO_DMA,
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +105,8 @@ static const struct ide_port_info falconide_port_info = {
 | 
			
		|||
	.chipset		= ide_generic,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void __init falconide_setup_ports(struct ide_hw *hw, unsigned long base)
 | 
			
		||||
static void __init falconide_setup_ports(struct ide_hw *hw, unsigned long base,
 | 
			
		||||
					 unsigned long ctl, int irq)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -118,9 +117,9 @@ static void __init falconide_setup_ports(struct ide_hw *hw, unsigned long base)
 | 
			
		|||
	for (i = 1; i < 8; i++)
 | 
			
		||||
		hw->io_ports_array[i] = base + 1 + i * 4;
 | 
			
		||||
 | 
			
		||||
	hw->io_ports.ctl_addr = base + ATA_HD_CONTROL;
 | 
			
		||||
	hw->io_ports.ctl_addr = ctl + 1;
 | 
			
		||||
 | 
			
		||||
	hw->irq = IRQ_MFP_IDE;
 | 
			
		||||
	hw->irq = irq;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
| 
						 | 
				
			
			@ -129,37 +128,69 @@ static void __init falconide_setup_ports(struct ide_hw *hw, unsigned long base)
 | 
			
		|||
 | 
			
		||||
static int __init falconide_init(struct platform_device *pdev)
 | 
			
		||||
{
 | 
			
		||||
	struct resource *res;
 | 
			
		||||
	struct resource *base_mem_res, *ctl_mem_res;
 | 
			
		||||
	struct resource *base_res, *ctl_res, *irq_res;
 | 
			
		||||
	struct ide_host *host;
 | 
			
		||||
	struct ide_hw hw, *hws[] = { &hw };
 | 
			
		||||
	unsigned long base;
 | 
			
		||||
	int rc;
 | 
			
		||||
	int irq;
 | 
			
		||||
 | 
			
		||||
	dev_info(&pdev->dev, "Atari Falcon IDE controller\n");
 | 
			
		||||
	dev_info(&pdev->dev, "Atari Falcon and Q40/Q60 IDE controller\n");
 | 
			
		||||
 | 
			
		||||
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | 
			
		||||
	if (!res)
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
 | 
			
		||||
	if (!devm_request_mem_region(&pdev->dev, res->start,
 | 
			
		||||
				     resource_size(res), DRV_NAME)) {
 | 
			
		||||
	base_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 | 
			
		||||
	if (base_res && !devm_request_region(&pdev->dev, base_res->start,
 | 
			
		||||
					   resource_size(base_res), DRV_NAME)) {
 | 
			
		||||
		dev_err(&pdev->dev, "resources busy\n");
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	base = (unsigned long)res->start;
 | 
			
		||||
 | 
			
		||||
	falconide_setup_ports(&hw, base);
 | 
			
		||||
 | 
			
		||||
	host = ide_host_alloc(&falconide_port_info, hws, 1);
 | 
			
		||||
	if (host == NULL) {
 | 
			
		||||
		rc = -ENOMEM;
 | 
			
		||||
		goto err;
 | 
			
		||||
	ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 | 
			
		||||
	if (ctl_res && !devm_request_region(&pdev->dev, ctl_res->start,
 | 
			
		||||
					   resource_size(ctl_res), DRV_NAME)) {
 | 
			
		||||
		dev_err(&pdev->dev, "resources busy\n");
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	falconide_get_lock(NULL, NULL);
 | 
			
		||||
	base_mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 | 
			
		||||
	if (!base_mem_res)
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
 | 
			
		||||
	if (!devm_request_mem_region(&pdev->dev, base_mem_res->start,
 | 
			
		||||
				     resource_size(base_mem_res), DRV_NAME)) {
 | 
			
		||||
		dev_err(&pdev->dev, "resources busy\n");
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctl_mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 | 
			
		||||
	if (!ctl_mem_res)
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
 | 
			
		||||
	if (MACH_IS_ATARI) {
 | 
			
		||||
		irq = IRQ_MFP_IDE;
 | 
			
		||||
	} else {
 | 
			
		||||
		irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 | 
			
		||||
		if (irq_res && irq_res->start > 0)
 | 
			
		||||
			irq = irq_res->start;
 | 
			
		||||
		else
 | 
			
		||||
			return -ENODEV;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	falconide_setup_ports(&hw, base_mem_res->start, ctl_mem_res->start, irq);
 | 
			
		||||
 | 
			
		||||
	host = ide_host_alloc(&falconide_port_info, hws, 1);
 | 
			
		||||
	if (!host)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	if (!MACH_IS_ATARI) {
 | 
			
		||||
		host->get_lock = NULL;
 | 
			
		||||
		host->release_lock = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (host->get_lock)
 | 
			
		||||
		host->get_lock(NULL, NULL);
 | 
			
		||||
	rc = ide_host_register(host, &falconide_port_info, hws);
 | 
			
		||||
	falconide_release_lock();
 | 
			
		||||
	if (host->release_lock)
 | 
			
		||||
		host->release_lock();
 | 
			
		||||
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto err_free;
 | 
			
		||||
| 
						 | 
				
			
			@ -168,8 +199,6 @@ static int __init falconide_init(struct platform_device *pdev)
 | 
			
		|||
	return 0;
 | 
			
		||||
err_free:
 | 
			
		||||
	ide_host_free(host);
 | 
			
		||||
err:
 | 
			
		||||
	release_mem_region(res->start, resource_size(res));
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,168 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 *  Q40 I/O port IDE Driver
 | 
			
		||||
 *
 | 
			
		||||
 *     (c) Richard Zidlicky
 | 
			
		||||
 *
 | 
			
		||||
 *  This file is subject to the terms and conditions of the GNU General Public
 | 
			
		||||
 *  License.  See the file COPYING in the main directory of this archive for
 | 
			
		||||
 *  more details.
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/blkdev.h>
 | 
			
		||||
#include <linux/ide.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/ide.h>
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     *  Bases of the IDE interfaces
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
#define Q40IDE_NUM_HWIFS	2
 | 
			
		||||
 | 
			
		||||
#define PCIDE_BASE1	0x1f0
 | 
			
		||||
#define PCIDE_BASE2	0x170
 | 
			
		||||
#define PCIDE_BASE3	0x1e8
 | 
			
		||||
#define PCIDE_BASE4	0x168
 | 
			
		||||
#define PCIDE_BASE5	0x1e0
 | 
			
		||||
#define PCIDE_BASE6	0x160
 | 
			
		||||
 | 
			
		||||
static const unsigned long pcide_bases[Q40IDE_NUM_HWIFS] = {
 | 
			
		||||
    PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4  , PCIDE_BASE5,
 | 
			
		||||
    PCIDE_BASE6 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int q40ide_default_irq(unsigned long base)
 | 
			
		||||
{
 | 
			
		||||
           switch (base) {
 | 
			
		||||
	            case 0x1f0: return 14;
 | 
			
		||||
		    case 0x170: return 15;
 | 
			
		||||
		    case 0x1e8: return 11;
 | 
			
		||||
		    default:
 | 
			
		||||
			return 0;
 | 
			
		||||
	   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Addresses are pretranslated for Q40 ISA access.
 | 
			
		||||
 */
 | 
			
		||||
static void q40_ide_setup_ports(struct ide_hw *hw, unsigned long base, int irq)
 | 
			
		||||
{
 | 
			
		||||
	memset(hw, 0, sizeof(*hw));
 | 
			
		||||
	/* BIG FAT WARNING: 
 | 
			
		||||
	   assumption: only DATA port is ever used in 16 bit mode */
 | 
			
		||||
	hw->io_ports.data_addr = Q40_ISA_IO_W(base);
 | 
			
		||||
	hw->io_ports.error_addr = Q40_ISA_IO_B(base + 1);
 | 
			
		||||
	hw->io_ports.nsect_addr = Q40_ISA_IO_B(base + 2);
 | 
			
		||||
	hw->io_ports.lbal_addr = Q40_ISA_IO_B(base + 3);
 | 
			
		||||
	hw->io_ports.lbam_addr = Q40_ISA_IO_B(base + 4);
 | 
			
		||||
	hw->io_ports.lbah_addr = Q40_ISA_IO_B(base + 5);
 | 
			
		||||
	hw->io_ports.device_addr = Q40_ISA_IO_B(base + 6);
 | 
			
		||||
	hw->io_ports.status_addr = Q40_ISA_IO_B(base + 7);
 | 
			
		||||
	hw->io_ports.ctl_addr = Q40_ISA_IO_B(base + 0x206);
 | 
			
		||||
 | 
			
		||||
	hw->irq = irq;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void q40ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
 | 
			
		||||
			      void *buf, unsigned int len)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long data_addr = drive->hwif->io_ports.data_addr;
 | 
			
		||||
 | 
			
		||||
	if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) {
 | 
			
		||||
		__ide_mm_insw(data_addr, buf, (len + 1) / 2);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	raw_insw_swapw((u16 *)data_addr, buf, (len + 1) / 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void q40ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
 | 
			
		||||
			       void *buf, unsigned int len)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long data_addr = drive->hwif->io_ports.data_addr;
 | 
			
		||||
 | 
			
		||||
	if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) {
 | 
			
		||||
		__ide_mm_outsw(data_addr, buf, (len + 1) / 2);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	raw_outsw_swapw((u16 *)data_addr, buf, (len + 1) / 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Q40 has a byte-swapped IDE interface */
 | 
			
		||||
static const struct ide_tp_ops q40ide_tp_ops = {
 | 
			
		||||
	.exec_command		= ide_exec_command,
 | 
			
		||||
	.read_status		= ide_read_status,
 | 
			
		||||
	.read_altstatus		= ide_read_altstatus,
 | 
			
		||||
	.write_devctl		= ide_write_devctl,
 | 
			
		||||
 | 
			
		||||
	.dev_select		= ide_dev_select,
 | 
			
		||||
	.tf_load		= ide_tf_load,
 | 
			
		||||
	.tf_read		= ide_tf_read,
 | 
			
		||||
 | 
			
		||||
	.input_data		= q40ide_input_data,
 | 
			
		||||
	.output_data		= q40ide_output_data,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct ide_port_info q40ide_port_info = {
 | 
			
		||||
	.tp_ops			= &q40ide_tp_ops,
 | 
			
		||||
	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
 | 
			
		||||
	.irq_flags		= IRQF_SHARED,
 | 
			
		||||
	.chipset		= ide_generic,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 * the static array is needed to have the name reported in /proc/ioports,
 | 
			
		||||
 * hwif->name unfortunately isn't available yet
 | 
			
		||||
 */
 | 
			
		||||
static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
 | 
			
		||||
	"ide0", "ide1"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *  Probe for Q40 IDE interfaces
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static int __init q40ide_init(void)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    struct ide_hw hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL };
 | 
			
		||||
 | 
			
		||||
    if (!MACH_IS_Q40)
 | 
			
		||||
      return -ENODEV;
 | 
			
		||||
 | 
			
		||||
    printk(KERN_INFO "ide: Q40 IDE controller\n");
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
 | 
			
		||||
	const char *name = q40_ide_names[i];
 | 
			
		||||
 | 
			
		||||
	if (!request_region(pcide_bases[i], 8, name)) {
 | 
			
		||||
		printk("could not reserve ports %lx-%lx for %s\n",
 | 
			
		||||
		       pcide_bases[i],pcide_bases[i]+8,name);
 | 
			
		||||
		continue;
 | 
			
		||||
	}
 | 
			
		||||
	if (!request_region(pcide_bases[i]+0x206, 1, name)) {
 | 
			
		||||
		printk("could not reserve port %lx for %s\n",
 | 
			
		||||
		       pcide_bases[i]+0x206,name);
 | 
			
		||||
		release_region(pcide_bases[i], 8);
 | 
			
		||||
		continue;
 | 
			
		||||
	}
 | 
			
		||||
	q40_ide_setup_ports(&hw[i], pcide_bases[i],
 | 
			
		||||
			q40ide_default_irq(pcide_bases[i]));
 | 
			
		||||
 | 
			
		||||
	hws[i] = &hw[i];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ide_host_add(&q40ide_port_info, hws, Q40IDE_NUM_HWIFS, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module_init(q40ide_init);
 | 
			
		||||
 | 
			
		||||
MODULE_LICENSE("GPL");
 | 
			
		||||
		Loading…
	
		Reference in a new issue