17c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen/*
27c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * AVR32 SMC/CFC PATA Driver
37c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *
47c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * Copyright (C) 2007 Atmel Norway
57c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *
67c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * This program is free software; you can redistribute it and/or
77c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * modify it under the terms of the GNU General Public License version
87c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * 2 as published by the Free Software Foundation.
97c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen */
107c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
117c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#define DEBUG
127c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
137c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <linux/kernel.h>
147c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <linux/module.h>
157c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <linux/init.h>
167c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <linux/device.h>
177c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <linux/platform_device.h>
187c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <linux/delay.h>
197c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <linux/interrupt.h>
207c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <linux/irq.h>
215a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
227c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <scsi/scsi_host.h>
237c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <linux/ata.h>
247c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <linux/libata.h>
257c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <linux/err.h>
267c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#include <linux/io.h>
277c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
283663b736a5083b3bce74520b637f630f01f66a7fHaavard Skinnemoen#include <mach/board.h>
293663b736a5083b3bce74520b637f630f01f66a7fHaavard Skinnemoen#include <mach/smc.h>
307c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
317c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#define DRV_NAME "pata_at32"
321c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen#define DRV_VERSION "0.0.3"
337c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
347c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen/*
357c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * CompactFlash controller memory layout relative to the base address:
367c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *
377c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	Attribute memory:  0000 0000 -> 003f ffff
387c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	Common memory:	   0040 0000 -> 007f ffff
397c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	I/O memory:	   0080 0000 -> 00bf ffff
407c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	True IDE Mode:	   00c0 0000 -> 00df ffff
417c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	Alt IDE Mode:	   00e0 0000 -> 00ff ffff
427c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *
437c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * Only True IDE and Alt True IDE mode are needed for this driver.
447c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *
457c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	True IDE mode	  => CS0 = 0, CS1 = 1 (cmd, error, stat, etc)
467c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	Alt True IDE mode => CS0 = 1, CS1 = 0 (ctl, alt_stat)
477c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen */
487c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#define CF_IDE_OFFSET	  0x00c00000
497c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#define CF_ALT_IDE_OFFSET 0x00e00000
507c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#define CF_RES_SIZE	  2048
517c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
527c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen/*
537c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * Define DEBUG_BUS if you are doing debugging of your own EBI -> PATA
547c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * adaptor with a logic analyzer or similar.
557c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen */
567c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#undef DEBUG_BUS
577c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
587c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen/*
597c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * ATA PIO modes
607c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *
617c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	Name	| Mb/s	| Min cycle time | Mask
627c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	--------+-------+----------------+--------
637c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	Mode 0	| 3.3	| 600 ns	 | 0x01
647c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	Mode 1	| 5.2	| 383 ns	 | 0x03
657c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	Mode 2	| 8.3	| 240 ns	 | 0x07
667c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	Mode 3	| 11.1	| 180 ns	 | 0x0f
677c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen *	Mode 4	| 16.7	| 120 ns	 | 0x1f
681c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen *
691c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen * Alter PIO_MASK below according to table to set maximal PIO mode.
707c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen */
7114bdef982caeda19afe34010482867c18217c641Erik Inge Bolsøenum {
7214bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø  PIO_MASK = ATA_PIO4,
7314bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø};
747c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
757c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen/*
767c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * Struct containing private information about device.
777c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen */
787c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenstruct at32_ide_info {
797c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	unsigned int		irq;
807c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct resource		res_ide;
817c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct resource		res_alt;
827c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	void __iomem		*ide_addr;
837c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	void __iomem		*alt_addr;
847c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	unsigned int		cs;
857c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct smc_config	smc;
867c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen};
877c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
887c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen/*
897c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * Setup SMC for the given ATA timing.
907c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen */
917c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenstatic int pata_at32_setup_timing(struct device *dev,
927c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen				  struct at32_ide_info *info,
931c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen				  const struct ata_timing *ata)
947c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen{
957c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct smc_config *smc = &info->smc;
961c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	struct smc_timing timing;
977c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
987c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	int active;
997c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	int recover;
1007c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1011c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	memset(&timing, 0, sizeof(struct smc_timing));
1021c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen
1037c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Total cycle time */
1041c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	timing.read_cycle  = ata->cyc8b;
1057c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1067c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* DIOR <= CFIOR timings */
1071c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	timing.nrd_setup   = ata->setup;
1081c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	timing.nrd_pulse   = ata->act8b;
1091c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	timing.nrd_recover = ata->rec8b;
1101c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen
1111c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	/* Convert nanosecond timing to clock cycles */
1121c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	smc_set_timing(smc, &timing);
1137c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1141c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	/* Add one extra cycle setup due to signal ring */
1151c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	smc->nrd_setup = smc->nrd_setup + 1;
1161c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen
1171c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	active  = smc->nrd_setup + smc->nrd_pulse;
1187c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	recover = smc->read_cycle - active;
1197c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1201c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	/* Need at least two cycles recovery */
1211c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	if (recover < 2)
1221c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	  smc->read_cycle = active + 2;
1237c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1247c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */
1251c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	smc->ncs_read_setup = 1;
1261c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	smc->ncs_read_pulse = smc->read_cycle - 2;
1277c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1287c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Write timings same as read timings */
1297c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	smc->write_cycle = smc->read_cycle;
1307c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	smc->nwe_setup = smc->nrd_setup;
1317c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	smc->nwe_pulse = smc->nrd_pulse;
1327c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	smc->ncs_write_setup = smc->ncs_read_setup;
1337c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	smc->ncs_write_pulse = smc->ncs_read_pulse;
1347c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1351c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	/* Do some debugging output of ATA and SMC timings */
1361c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	dev_dbg(dev, "ATA: C=%d S=%d P=%d R=%d\n",
1371c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen		ata->cyc8b, ata->setup, ata->act8b, ata->rec8b);
1381c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen
1391c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	dev_dbg(dev, "SMC: C=%d S=%d P=%d NS=%d NP=%d\n",
1407c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		smc->read_cycle, smc->nrd_setup, smc->nrd_pulse,
1411c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen		smc->ncs_read_setup, smc->ncs_read_pulse);
1427c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1437c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Finally, configure the SMC */
1447c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	return smc_set_configuration(info->cs, smc);
1457c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen}
1467c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1477c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen/*
1487c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * Procedures for libATA.
1497c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen */
1507c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenstatic void pata_at32_set_piomode(struct ata_port *ap, struct ata_device *adev)
1517c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen{
1527c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct ata_timing timing;
1537c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct at32_ide_info *info = ap->host->private_data;
1547c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1557c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	int ret;
1567c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1577c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Compute ATA timing */
1587c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ret = ata_timing_compute(adev, adev->pio_mode, &timing, 1000, 0);
1597c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (ret) {
1607c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		dev_warn(ap->dev, "Failed to compute ATA timing %d\n", ret);
1617c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		return;
1627c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	}
1637c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1647c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Setup SMC to ATA timing */
1657c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ret = pata_at32_setup_timing(ap->dev, info, &timing);
1667c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (ret) {
1677c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		dev_warn(ap->dev, "Failed to setup ATA timing %d\n", ret);
1687c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		return;
1697c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	}
1707c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen}
1717c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1727c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenstatic struct scsi_host_template at32_sht = {
17368d1d07b510bb57a504588adc2bd2758adea0965Tejun Heo	ATA_PIO_SHT(DRV_NAME),
1747c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen};
1757c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1767c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenstatic struct ata_port_operations at32_port_ops = {
177029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits		= &ata_sff_port_ops,
1787c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	.cable_detect		= ata_cable_40wire,
179029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.set_piomode		= pata_at32_set_piomode,
1807c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen};
1817c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1827c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenstatic int __init pata_at32_init_one(struct device *dev,
1837c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen				     struct at32_ide_info *info)
1847c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen{
1857c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct ata_host *host;
1867c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct ata_port *ap;
1877c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1887c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	host = ata_host_alloc(dev, 1);
1897c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (!host)
1907c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		return -ENOMEM;
1917c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1927c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap = host->ports[0];
1937c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1947c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Setup ATA bindings */
1957c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ops	     = &at32_port_ops;
1967c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->pio_mask = PIO_MASK;
1973696df309971b3427cb9cb039138a1732a865a0bSergei Shtylyov	ap->flags   |= ATA_FLAG_SLAVE_POSS;
1987c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
1997c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/*
2007c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	 * Since all 8-bit taskfile transfers has to go on the lower
2017c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	 * byte of the data bus and there is a bug in the SMC that
2027c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	 * makes it impossible to alter the bus width during runtime,
2037c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	 * we need to hardwire the address signals as follows:
2047c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	 *
2057c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	 *	A_IDE(2:0) <= A_EBI(3:1)
2067c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	 *
2077c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	 * This makes all addresses on the EBI even, thus all data
2087c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	 * will be on the lower byte of the data bus.  All addresses
2097c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	 * used by libATA need to be altered according to this.
2107c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	 */
2117c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ioaddr.altstatus_addr = info->alt_addr + (0x06 << 1);
2127c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ioaddr.ctl_addr	  = info->alt_addr + (0x06 << 1);
2137c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2147c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ioaddr.data_addr	  = info->ide_addr + (ATA_REG_DATA << 1);
2157c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ioaddr.error_addr	  = info->ide_addr + (ATA_REG_ERR << 1);
2167c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ioaddr.feature_addr	  = info->ide_addr + (ATA_REG_FEATURE << 1);
2177c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ioaddr.nsect_addr	  = info->ide_addr + (ATA_REG_NSECT << 1);
2187c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ioaddr.lbal_addr	  = info->ide_addr + (ATA_REG_LBAL << 1);
2197c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ioaddr.lbam_addr	  = info->ide_addr + (ATA_REG_LBAM << 1);
2207c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ioaddr.lbah_addr	  = info->ide_addr + (ATA_REG_LBAH << 1);
2217c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ioaddr.device_addr	  = info->ide_addr + (ATA_REG_DEVICE << 1);
2227c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ioaddr.status_addr	  = info->ide_addr + (ATA_REG_STATUS << 1);
2237c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ap->ioaddr.command_addr	  = info->ide_addr + (ATA_REG_CMD << 1);
2247c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2257c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Set info as private data of ATA host */
2267c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	host->private_data = info;
2277c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2287c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Register ATA device and return */
2299363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo	return ata_host_activate(host, info->irq, ata_sff_interrupt,
2307c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen				 IRQF_SHARED | IRQF_TRIGGER_RISING,
2317c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen				 &at32_sht);
2327c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen}
2337c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2347c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen/*
2357c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * This function may come in handy for people analyzing their own
2367c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen * EBI -> PATA adaptors.
2377c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen */
2387c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#ifdef DEBUG_BUS
2397c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2407c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenstatic void __init pata_at32_debug_bus(struct device *dev,
2417c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen				       struct at32_ide_info *info)
2427c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen{
2437c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	const int d1 = 0xff;
2447c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	const int d2 = 0x00;
2457c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2467c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	int i;
2477c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2487c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Write 8-bit values (registers) */
2497c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	iowrite8(d1, info->alt_addr + (0x06 << 1));
2507c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	iowrite8(d2, info->alt_addr + (0x06 << 1));
2517c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2527c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	for (i = 0; i < 8; i++) {
2537c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		iowrite8(d1, info->ide_addr + (i << 1));
2547c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		iowrite8(d2, info->ide_addr + (i << 1));
2557c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	}
2567c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2577c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Write 16 bit values (data) */
2587c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	iowrite16(d1,	   info->ide_addr);
2597c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	iowrite16(d1 << 8, info->ide_addr);
2607c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2617c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	iowrite16(d1,	   info->ide_addr);
2627c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	iowrite16(d1 << 8, info->ide_addr);
2637c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen}
2647c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2657c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#endif
2667c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2677c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenstatic int __init pata_at32_probe(struct platform_device *pdev)
2687c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen{
2697c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	const struct ata_timing initial_timing =
2707c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		{XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0};
2717c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2727c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct device		 *dev = &pdev->dev;
2737c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct at32_ide_info	 *info;
2747c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct ide_platform_data *board = pdev->dev.platform_data;
2757c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct resource		 *res;
2767c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2777c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	int irq;
2787c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	int ret;
2797c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2807c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (!board)
2817c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		return -ENXIO;
2827c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2837c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2847c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (!res)
2857c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		return -ENXIO;
2867c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2877c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Retrive IRQ */
2887c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	irq = platform_get_irq(pdev, 0);
2897c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (irq < 0)
2907c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		return irq;
2917c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2921967b7ff75dca31a488fce113f94cabdd4f3d7bdJoe Perches	/* Setup struct containing private information */
2937c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info = kzalloc(sizeof(struct at32_ide_info), GFP_KERNEL);
2947c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (!info)
2957c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		return -ENOMEM;
2967c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
2977c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->irq = irq;
2987c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->cs  = board->cs;
2997c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3007c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Request memory resources */
3017c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->res_ide.start = res->start + CF_IDE_OFFSET;
3027c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->res_ide.end   = info->res_ide.start + CF_RES_SIZE - 1;
3037c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->res_ide.name  = "ide";
3047c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->res_ide.flags = IORESOURCE_MEM;
3057c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3067c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ret = request_resource(res, &info->res_ide);
3077c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (ret)
3087c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		goto err_req_res_ide;
3097c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3107c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->res_alt.start = res->start + CF_ALT_IDE_OFFSET;
3117c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->res_alt.end   = info->res_alt.start + CF_RES_SIZE - 1;
3127c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->res_alt.name  = "alt";
3137c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->res_alt.flags = IORESOURCE_MEM;
3147c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3157c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ret = request_resource(res, &info->res_alt);
3167c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (ret)
3177c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		goto err_req_res_alt;
3187c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3197c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	/* Setup non-timing elements of SMC */
3207c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->smc.bus_width	 = 2; /* 16 bit data bus */
3217c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->smc.nrd_controlled = 1; /* Sample data on rising edge of NRD */
3227c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->smc.nwe_controlled = 0; /* Drive data on falling edge of NCS */
3237c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->smc.nwait_mode	 = 3; /* NWAIT is in READY mode */
3247c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->smc.byte_write	 = 0; /* Byte select access type */
3257c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->smc.tdf_mode	 = 0; /* TDF optimization disabled */
3267c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->smc.tdf_cycles	 = 0; /* No TDF wait cycles */
3277c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3281c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	/* Setup SMC to ATA timing */
3297c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ret = pata_at32_setup_timing(dev, info, &initial_timing);
3307c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (ret)
3317c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		goto err_setup_timing;
3327c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3331c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	/* Map ATA address space */
3347c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ret = -ENOMEM;
3357c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->ide_addr = devm_ioremap(dev, info->res_ide.start, 16);
3367c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info->alt_addr = devm_ioremap(dev, info->res_alt.start, 16);
3377c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (!info->ide_addr || !info->alt_addr)
3387c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		goto err_ioremap;
3397c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3407c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#ifdef DEBUG_BUS
3417c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	pata_at32_debug_bus(dev, info);
3427c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen#endif
3437c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3441c20a493caa30c5d47a394f9dbd86e6282323db9Kristoffer Nyborg Gregertsen	/* Setup and register ATA device */
3457c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ret = pata_at32_init_one(dev, info);
3467c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (ret)
3477c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		goto err_ata_device;
3487c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3497c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	return 0;
3507c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3517c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen err_ata_device:
3527c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen err_ioremap:
3537c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen err_setup_timing:
3547c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	release_resource(&info->res_alt);
3557c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen err_req_res_alt:
3567c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	release_resource(&info->res_ide);
3577c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen err_req_res_ide:
3587c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	kfree(info);
3597c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3607c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	return ret;
3617c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen}
3627c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3637c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenstatic int __exit pata_at32_remove(struct platform_device *pdev)
3647c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen{
3657c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct ata_host *host = platform_get_drvdata(pdev);
3667c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	struct at32_ide_info *info;
3677c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3687c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (!host)
3697c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		return 0;
3707c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3717c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	info = host->private_data;
3727c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	ata_host_detach(host);
3737c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3747c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	if (!info)
3757c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		return 0;
3767c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3777c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	release_resource(&info->res_ide);
3787c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	release_resource(&info->res_alt);
3797c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3807c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	kfree(info);
3817c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3827c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	return 0;
3837c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen}
3847c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
385458622fcdc5b316de8d74efd7e610803f0308c14Kay Sievers/* work with hotplug and coldplug */
386458622fcdc5b316de8d74efd7e610803f0308c14Kay SieversMODULE_ALIAS("platform:at32_ide");
387458622fcdc5b316de8d74efd7e610803f0308c14Kay Sievers
3887c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenstatic struct platform_driver pata_at32_driver = {
3897c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	.remove	       = __exit_p(pata_at32_remove),
3907c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	.driver	       = {
3917c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		.name  = "at32_ide",
3927c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen		.owner = THIS_MODULE,
3937c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	},
3947c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen};
3957c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
3967c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenstatic int __init pata_at32_init(void)
3977c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen{
3987c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	return platform_driver_probe(&pata_at32_driver, pata_at32_probe);
3997c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen}
4007c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
4017c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenstatic void __exit pata_at32_exit(void)
4027c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen{
4037c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen	platform_driver_unregister(&pata_at32_driver);
4047c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen}
4057c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
4067c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenmodule_init(pata_at32_init);
4077c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsenmodule_exit(pata_at32_exit);
4087c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg Gregertsen
4097c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg GregertsenMODULE_LICENSE("GPL");
4107c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg GregertsenMODULE_DESCRIPTION("AVR32 SMC/CFC PATA Driver");
4117c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg GregertsenMODULE_AUTHOR("Kristoffer Nyborg Gregertsen <kngregertsen@norway.atmel.com>");
4127c9ef8e418374aec0a62e64d9b40d457634fd039Kristoffer Nyborg GregertsenMODULE_VERSION(DRV_VERSION);
413