sata_svw.c 15 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 *  sata_svw.c - ServerWorks / Apple K2 SATA
 *
 *  Maintained by: Benjamin Herrenschmidt <benh@kernel.crashing.org> and
 *		   Jeff Garzik <jgarzik@pobox.com>
 *  		    Please ALWAYS copy linux-ide@vger.kernel.org
 *		    on emails.
 *
 *  Copyright 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
 *
 *  Bits from Jeff Garzik, Copyright RedHat, Inc.
 *
 *  This driver probably works with non-Apple versions of the
 *  Broadcom chipset...
 *
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *
 *  libata documentation is available via 'make {ps|pdf}docs',
 *  as Documentation/DocBook/libata.*
 *
 *  Hardware documentation available under NDA.
Linus Torvalds's avatar
Linus Torvalds committed
36 37 38 39 40 41 42 43 44 45
 *
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
46
#include <linux/device.h>
Linus Torvalds's avatar
Linus Torvalds committed
47
#include <scsi/scsi_host.h>
48 49
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi.h>
Linus Torvalds's avatar
Linus Torvalds committed
50 51 52 53 54 55 56 57
#include <linux/libata.h>

#ifdef CONFIG_PPC_OF
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#endif /* CONFIG_PPC_OF */

#define DRV_NAME	"sata_svw"
58
#define DRV_VERSION	"2.3"
Linus Torvalds's avatar
Linus Torvalds committed
59

60
enum {
61 62 63
	/* ap->flags bits */
	K2_FLAG_SATA_8_PORTS		= (1 << 24),
	K2_FLAG_NO_ATAPI_DMA		= (1 << 25),
64
	K2_FLAG_BAR_POS_3			= (1 << 26),
65

66 67 68 69 70 71 72 73 74 75 76
	/* Taskfile registers offsets */
	K2_SATA_TF_CMD_OFFSET		= 0x00,
	K2_SATA_TF_DATA_OFFSET		= 0x00,
	K2_SATA_TF_ERROR_OFFSET		= 0x04,
	K2_SATA_TF_NSECT_OFFSET		= 0x08,
	K2_SATA_TF_LBAL_OFFSET		= 0x0c,
	K2_SATA_TF_LBAM_OFFSET		= 0x10,
	K2_SATA_TF_LBAH_OFFSET		= 0x14,
	K2_SATA_TF_DEVICE_OFFSET	= 0x18,
	K2_SATA_TF_CMDSTAT_OFFSET      	= 0x1c,
	K2_SATA_TF_CTL_OFFSET		= 0x20,
Linus Torvalds's avatar
Linus Torvalds committed
77

78 79
	/* DMA base */
	K2_SATA_DMA_CMD_OFFSET		= 0x30,
Linus Torvalds's avatar
Linus Torvalds committed
80

81 82 83 84
	/* SCRs base */
	K2_SATA_SCR_STATUS_OFFSET	= 0x40,
	K2_SATA_SCR_ERROR_OFFSET	= 0x44,
	K2_SATA_SCR_CONTROL_OFFSET	= 0x48,
Linus Torvalds's avatar
Linus Torvalds committed
85

86 87 88 89
	/* Others */
	K2_SATA_SICR1_OFFSET		= 0x80,
	K2_SATA_SICR2_OFFSET		= 0x84,
	K2_SATA_SIM_OFFSET		= 0x88,
Linus Torvalds's avatar
Linus Torvalds committed
90

91 92
	/* Port stride */
	K2_SATA_PORT_OFFSET		= 0x100,
93

94 95 96 97
	chip_svw4			= 0,
	chip_svw8			= 1,
	chip_svw42			= 2,	/* bar 3 */
	chip_svw43			= 3,	/* bar 5 */
98 99
};

100 101
static u8 k2_stat_check_status(struct ata_port *ap);

Linus Torvalds's avatar
Linus Torvalds committed
102

103 104
static int k2_sata_check_atapi_dma(struct ata_queued_cmd *qc)
{
105 106
	u8 cmnd = qc->scsicmd->cmnd[0];

107 108
	if (qc->ap->flags & K2_FLAG_NO_ATAPI_DMA)
		return -1;	/* ATAPI DMA not supported */
109 110 111 112 113 114 115 116 117 118 119 120 121
	else {
		switch (cmnd) {
		case READ_10:
		case READ_12:
		case READ_16:
		case WRITE_10:
		case WRITE_12:
		case WRITE_16:
			return 0;

		default:
			return -1;
		}
122

123
	}
124 125
}

126 127
static int k2_sata_scr_read(struct ata_link *link,
			    unsigned int sc_reg, u32 *val)
Linus Torvalds's avatar
Linus Torvalds committed
128 129
{
	if (sc_reg > SCR_CONTROL)
130
		return -EINVAL;
131
	*val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 4));
132
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
133 134 135
}


136 137
static int k2_sata_scr_write(struct ata_link *link,
			     unsigned int sc_reg, u32 val)
Linus Torvalds's avatar
Linus Torvalds committed
138 139
{
	if (sc_reg > SCR_CONTROL)
140
		return -EINVAL;
141
	writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 4));
142
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
143 144
}

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
static int k2_sata_softreset(struct ata_link *link,
			     unsigned int *class, unsigned long deadline)
{
	u8 dmactl;
	void __iomem *mmio = link->ap->ioaddr.bmdma_addr;

	dmactl = readb(mmio + ATA_DMA_CMD);

	/* Clear the start bit */
	if (dmactl & ATA_DMA_START) {
		dmactl &= ~ATA_DMA_START;
		writeb(dmactl, mmio + ATA_DMA_CMD);
	}

	return ata_sff_softreset(link, class, deadline);
}

static int k2_sata_hardreset(struct ata_link *link,
			     unsigned int *class, unsigned long deadline)
{
	u8 dmactl;
	void __iomem *mmio = link->ap->ioaddr.bmdma_addr;

	dmactl = readb(mmio + ATA_DMA_CMD);

	/* Clear the start bit */
	if (dmactl & ATA_DMA_START) {
		dmactl &= ~ATA_DMA_START;
		writeb(dmactl, mmio + ATA_DMA_CMD);
	}

	return sata_sff_hardreset(link, class, deadline);
}
Linus Torvalds's avatar
Linus Torvalds committed
178

179
static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
Linus Torvalds's avatar
Linus Torvalds committed
180 181 182 183 184
{
	struct ata_ioports *ioaddr = &ap->ioaddr;
	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;

	if (tf->ctl != ap->last_ctl) {
Tejun Heo's avatar
Tejun Heo committed
185
		writeb(tf->ctl, ioaddr->ctl_addr);
Linus Torvalds's avatar
Linus Torvalds committed
186 187 188 189
		ap->last_ctl = tf->ctl;
		ata_wait_idle(ap);
	}
	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
190
		writew(tf->feature | (((u16)tf->hob_feature) << 8),
Tejun Heo's avatar
Tejun Heo committed
191
		       ioaddr->feature_addr);
192
		writew(tf->nsect | (((u16)tf->hob_nsect) << 8),
Tejun Heo's avatar
Tejun Heo committed
193
		       ioaddr->nsect_addr);
194
		writew(tf->lbal | (((u16)tf->hob_lbal) << 8),
Tejun Heo's avatar
Tejun Heo committed
195
		       ioaddr->lbal_addr);
196
		writew(tf->lbam | (((u16)tf->hob_lbam) << 8),
Tejun Heo's avatar
Tejun Heo committed
197
		       ioaddr->lbam_addr);
198
		writew(tf->lbah | (((u16)tf->hob_lbah) << 8),
Tejun Heo's avatar
Tejun Heo committed
199
		       ioaddr->lbah_addr);
Linus Torvalds's avatar
Linus Torvalds committed
200
	} else if (is_addr) {
Tejun Heo's avatar
Tejun Heo committed
201 202 203 204 205
		writew(tf->feature, ioaddr->feature_addr);
		writew(tf->nsect, ioaddr->nsect_addr);
		writew(tf->lbal, ioaddr->lbal_addr);
		writew(tf->lbam, ioaddr->lbam_addr);
		writew(tf->lbah, ioaddr->lbah_addr);
Linus Torvalds's avatar
Linus Torvalds committed
206 207 208
	}

	if (tf->flags & ATA_TFLAG_DEVICE)
Tejun Heo's avatar
Tejun Heo committed
209
		writeb(tf->device, ioaddr->device_addr);
Linus Torvalds's avatar
Linus Torvalds committed
210 211 212 213 214 215 216 217

	ata_wait_idle(ap);
}


static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
	struct ata_ioports *ioaddr = &ap->ioaddr;
218
	u16 nsect, lbal, lbam, lbah, feature;
Linus Torvalds's avatar
Linus Torvalds committed
219

220
	tf->command = k2_stat_check_status(ap);
Tejun Heo's avatar
Tejun Heo committed
221 222 223 224 225 226
	tf->device = readw(ioaddr->device_addr);
	feature = readw(ioaddr->error_addr);
	nsect = readw(ioaddr->nsect_addr);
	lbal = readw(ioaddr->lbal_addr);
	lbam = readw(ioaddr->lbam_addr);
	lbah = readw(ioaddr->lbah_addr);
227 228 229 230 231 232

	tf->feature = feature;
	tf->nsect = nsect;
	tf->lbal = lbal;
	tf->lbam = lbam;
	tf->lbah = lbah;
Linus Torvalds's avatar
Linus Torvalds committed
233 234

	if (tf->flags & ATA_TFLAG_LBA48) {
235
		tf->hob_feature = feature >> 8;
Linus Torvalds's avatar
Linus Torvalds committed
236 237 238 239
		tf->hob_nsect = nsect >> 8;
		tf->hob_lbal = lbal >> 8;
		tf->hob_lbam = lbam >> 8;
		tf->hob_lbah = lbah >> 8;
240
	}
Linus Torvalds's avatar
Linus Torvalds committed
241 242 243 244 245 246 247
}

/**
 *	k2_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
 *	@qc: Info associated with this ATA transaction.
 *
 *	LOCKING:
Jeff Garzik's avatar
Jeff Garzik committed
248
 *	spin_lock_irqsave(host lock)
Linus Torvalds's avatar
Linus Torvalds committed
249 250
 */

251
static void k2_bmdma_setup_mmio(struct ata_queued_cmd *qc)
Linus Torvalds's avatar
Linus Torvalds committed
252 253 254 255
{
	struct ata_port *ap = qc->ap;
	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
	u8 dmactl;
256 257
	void __iomem *mmio = ap->ioaddr.bmdma_addr;

Linus Torvalds's avatar
Linus Torvalds committed
258 259
	/* load PRD table addr. */
	mb();	/* make sure PRD table writes are visible to controller */
260
	writel(ap->bmdma_prd_dma, mmio + ATA_DMA_TABLE_OFS);
Linus Torvalds's avatar
Linus Torvalds committed
261 262 263 264 265 266 267 268 269 270

	/* specify data direction, triple-check start bit is clear */
	dmactl = readb(mmio + ATA_DMA_CMD);
	dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
	if (!rw)
		dmactl |= ATA_DMA_WR;
	writeb(dmactl, mmio + ATA_DMA_CMD);

	/* issue r/w command if this is not a ATA DMA command*/
	if (qc->tf.protocol != ATA_PROT_DMA)
Tejun Heo's avatar
Tejun Heo committed
271
		ap->ops->sff_exec_command(ap, &qc->tf);
Linus Torvalds's avatar
Linus Torvalds committed
272 273 274 275 276 277 278
}

/**
 *	k2_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
 *	@qc: Info associated with this ATA transaction.
 *
 *	LOCKING:
Jeff Garzik's avatar
Jeff Garzik committed
279
 *	spin_lock_irqsave(host lock)
Linus Torvalds's avatar
Linus Torvalds committed
280 281
 */

282
static void k2_bmdma_start_mmio(struct ata_queued_cmd *qc)
Linus Torvalds's avatar
Linus Torvalds committed
283 284
{
	struct ata_port *ap = qc->ap;
285
	void __iomem *mmio = ap->ioaddr.bmdma_addr;
Linus Torvalds's avatar
Linus Torvalds committed
286 287 288 289 290
	u8 dmactl;

	/* start host DMA transaction */
	dmactl = readb(mmio + ATA_DMA_CMD);
	writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
	/* This works around possible data corruption.

	   On certain SATA controllers that can be seen when the r/w
	   command is given to the controller before the host DMA is
	   started.

	   On a Read command, the controller would initiate the
	   command to the drive even before it sees the DMA
	   start. When there are very fast drives connected to the
	   controller, or when the data request hits in the drive
	   cache, there is the possibility that the drive returns a
	   part or all of the requested data to the controller before
	   the DMA start is issued.  In this case, the controller
	   would become confused as to what to do with the data.  In
	   the worst case when all the data is returned back to the
	   controller, the controller could hang. In other cases it
	   could return partial data returning in data
	   corruption. This problem has been seen in PPC systems and
	   can also appear on an system with very fast disks, where
	   the SATA controller is sitting behind a number of bridges,
	   and hence there is significant latency between the r/w
	   command and the start command. */
	/* issue r/w command if the access is to ATA */
Linus Torvalds's avatar
Linus Torvalds committed
314
	if (qc->tf.protocol == ATA_PROT_DMA)
Tejun Heo's avatar
Tejun Heo committed
315
		ap->ops->sff_exec_command(ap, &qc->tf);
Linus Torvalds's avatar
Linus Torvalds committed
316 317
}

318

Linus Torvalds's avatar
Linus Torvalds committed
319 320
static u8 k2_stat_check_status(struct ata_port *ap)
{
321
	return readl(ap->ioaddr.status_addr);
Linus Torvalds's avatar
Linus Torvalds committed
322 323 324
}

#ifdef CONFIG_PPC_OF
325
static int k2_sata_show_info(struct seq_file *m, struct Scsi_Host *shost)
Linus Torvalds's avatar
Linus Torvalds committed
326 327 328
{
	struct ata_port *ap;
	struct device_node *np;
329
	int index;
Linus Torvalds's avatar
Linus Torvalds committed
330 331

	/* Find  the ata_port */
332
	ap = ata_shost_to_port(shost);
Linus Torvalds's avatar
Linus Torvalds committed
333 334 335 336
	if (ap == NULL)
		return 0;

	/* Find the OF node for the PCI device proper */
Jeff Garzik's avatar
Jeff Garzik committed
337
	np = pci_device_to_OF_node(to_pci_dev(ap->host->dev));
Linus Torvalds's avatar
Linus Torvalds committed
338 339 340 341
	if (np == NULL)
		return 0;

	/* Match it to a port node */
Jeff Garzik's avatar
Jeff Garzik committed
342
	index = (ap == ap->host->ports[0]) ? 0 : 1;
Linus Torvalds's avatar
Linus Torvalds committed
343
	for (np = np->child; np != NULL; np = np->sibling) {
344
		const u32 *reg = of_get_property(np, "reg", NULL);
Linus Torvalds's avatar
Linus Torvalds committed
345 346
		if (!reg)
			continue;
347 348
		if (index == *reg) {
			seq_printf(m, "devspec: %s\n", np->full_name);
Linus Torvalds's avatar
Linus Torvalds committed
349
			break;
350
		}
Linus Torvalds's avatar
Linus Torvalds committed
351
	}
352
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
353 354 355 356
}
#endif /* CONFIG_PPC_OF */


357
static struct scsi_host_template k2_sata_sht = {
358
	ATA_BMDMA_SHT(DRV_NAME),
Linus Torvalds's avatar
Linus Torvalds committed
359
#ifdef CONFIG_PPC_OF
360
	.show_info		= k2_sata_show_info,
Linus Torvalds's avatar
Linus Torvalds committed
361 362 363 364
#endif
};


365 366
static struct ata_port_operations k2_sata_ops = {
	.inherits		= &ata_bmdma_port_ops,
367 368
	.softreset              = k2_sata_softreset,
	.hardreset              = k2_sata_hardreset,
Tejun Heo's avatar
Tejun Heo committed
369 370 371
	.sff_tf_load		= k2_sata_tf_load,
	.sff_tf_read		= k2_sata_tf_read,
	.sff_check_status	= k2_stat_check_status,
372
	.check_atapi_dma	= k2_sata_check_atapi_dma,
Linus Torvalds's avatar
Linus Torvalds committed
373 374 375 376 377 378
	.bmdma_setup		= k2_bmdma_setup_mmio,
	.bmdma_start		= k2_bmdma_start_mmio,
	.scr_read		= k2_sata_scr_read,
	.scr_write		= k2_sata_scr_write,
};

379
static const struct ata_port_info k2_port_info[] = {
380
	/* chip_svw4 */
381
	{
382
		.flags		= ATA_FLAG_SATA | K2_FLAG_NO_ATAPI_DMA,
383 384
		.pio_mask	= ATA_PIO4,
		.mwdma_mask	= ATA_MWDMA2,
385
		.udma_mask	= ATA_UDMA6,
386 387
		.port_ops	= &k2_sata_ops,
	},
388
	/* chip_svw8 */
389
	{
390 391
		.flags		= ATA_FLAG_SATA | K2_FLAG_NO_ATAPI_DMA |
				  K2_FLAG_SATA_8_PORTS,
392 393
		.pio_mask	= ATA_PIO4,
		.mwdma_mask	= ATA_MWDMA2,
394
		.udma_mask	= ATA_UDMA6,
395 396
		.port_ops	= &k2_sata_ops,
	},
397 398
	/* chip_svw42 */
	{
399
		.flags		= ATA_FLAG_SATA | K2_FLAG_BAR_POS_3,
400 401
		.pio_mask	= ATA_PIO4,
		.mwdma_mask	= ATA_MWDMA2,
402 403 404 405 406
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &k2_sata_ops,
	},
	/* chip_svw43 */
	{
407
		.flags		= ATA_FLAG_SATA,
408 409
		.pio_mask	= ATA_PIO4,
		.mwdma_mask	= ATA_MWDMA2,
410 411 412
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &k2_sata_ops,
	},
413 414
};

Tejun Heo's avatar
Tejun Heo committed
415
static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base)
Linus Torvalds's avatar
Linus Torvalds committed
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
{
	port->cmd_addr		= base + K2_SATA_TF_CMD_OFFSET;
	port->data_addr		= base + K2_SATA_TF_DATA_OFFSET;
	port->feature_addr	=
	port->error_addr	= base + K2_SATA_TF_ERROR_OFFSET;
	port->nsect_addr	= base + K2_SATA_TF_NSECT_OFFSET;
	port->lbal_addr		= base + K2_SATA_TF_LBAL_OFFSET;
	port->lbam_addr		= base + K2_SATA_TF_LBAM_OFFSET;
	port->lbah_addr		= base + K2_SATA_TF_LBAH_OFFSET;
	port->device_addr	= base + K2_SATA_TF_DEVICE_OFFSET;
	port->command_addr	=
	port->status_addr	= base + K2_SATA_TF_CMDSTAT_OFFSET;
	port->altstatus_addr	=
	port->ctl_addr		= base + K2_SATA_TF_CTL_OFFSET;
	port->bmdma_addr	= base + K2_SATA_DMA_CMD_OFFSET;
	port->scr_addr		= base + K2_SATA_SCR_STATUS_OFFSET;
}


435
static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
Linus Torvalds's avatar
Linus Torvalds committed
436
{
437 438 439
	const struct ata_port_info *ppi[] =
		{ &k2_port_info[ent->driver_data], NULL };
	struct ata_host *host;
440
	void __iomem *mmio_base;
441
	int n_ports, i, rc, bar_pos;
Linus Torvalds's avatar
Linus Torvalds committed
442

443
	ata_print_version_once(&pdev->dev, DRV_VERSION);
Linus Torvalds's avatar
Linus Torvalds committed
444

445 446 447 448 449 450 451 452 453
	/* allocate host */
	n_ports = 4;
	if (ppi[0]->flags & K2_FLAG_SATA_8_PORTS)
		n_ports = 8;

	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
	if (!host)
		return -ENOMEM;

454 455 456
	bar_pos = 5;
	if (ppi[0]->flags & K2_FLAG_BAR_POS_3)
		bar_pos = 3;
Linus Torvalds's avatar
Linus Torvalds committed
457 458 459 460
	/*
	 * If this driver happens to only be useful on Apple's K2, then
	 * we should check that here as it has a normal Serverworks ID
	 */
461
	rc = pcim_enable_device(pdev);
Linus Torvalds's avatar
Linus Torvalds committed
462 463
	if (rc)
		return rc;
464

Linus Torvalds's avatar
Linus Torvalds committed
465 466 467 468
	/*
	 * Check if we have resources mapped at all (second function may
	 * have been disabled by firmware)
	 */
469 470 471 472 473 474
	if (pci_resource_len(pdev, bar_pos) == 0) {
		/* In IDE mode we need to pin the device to ensure that
			pcim_release does not clear the busmaster bit in config
			space, clearing causes busmaster DMA to fail on
			ports 3 & 4 */
		pcim_pin_device(pdev);
Linus Torvalds's avatar
Linus Torvalds committed
475
		return -ENODEV;
476
	}
Linus Torvalds's avatar
Linus Torvalds committed
477

Tejun Heo's avatar
Tejun Heo committed
478
	/* Request and iomap PCI regions */
479
	rc = pcim_iomap_regions(pdev, 1 << bar_pos, DRV_NAME);
Tejun Heo's avatar
Tejun Heo committed
480
	if (rc == -EBUSY)
481
		pcim_pin_device(pdev);
Tejun Heo's avatar
Tejun Heo committed
482
	if (rc)
483
		return rc;
484
	host->iomap = pcim_iomap_table(pdev);
485
	mmio_base = host->iomap[bar_pos];
486 487 488 489

	/* different controllers have different number of ports - currently 4 or 8 */
	/* All ports are on the same function. Multi-function device is no
	 * longer available. This should not be seen in any system. */
490 491 492 493 494 495 496 497 498
	for (i = 0; i < host->n_ports; i++) {
		struct ata_port *ap = host->ports[i];
		unsigned int offset = i * K2_SATA_PORT_OFFSET;

		k2_sata_setup_port(&ap->ioaddr, mmio_base + offset);

		ata_port_pbar_desc(ap, 5, -1, "mmio");
		ata_port_pbar_desc(ap, 5, offset, "port");
	}
Linus Torvalds's avatar
Linus Torvalds committed
499 500 501

	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
	if (rc)
502
		return rc;
Linus Torvalds's avatar
Linus Torvalds committed
503 504
	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
	if (rc)
505
		return rc;
Linus Torvalds's avatar
Linus Torvalds committed
506

Tejun Heo's avatar
Tejun Heo committed
507 508 509 510 511 512 513 514 515 516
	/* Clear a magic bit in SCR1 according to Darwin, those help
	 * some funky seagate drives (though so far, those were already
	 * set by the firmware on the machines I had access to)
	 */
	writel(readl(mmio_base + K2_SATA_SICR1_OFFSET) & ~0x00040000,
	       mmio_base + K2_SATA_SICR1_OFFSET);

	/* Clear SATA error & interrupts we don't use */
	writel(0xffffffff, mmio_base + K2_SATA_SCR_ERROR_OFFSET);
	writel(0x0, mmio_base + K2_SATA_SIM_OFFSET);
Linus Torvalds's avatar
Linus Torvalds committed
517 518

	pci_set_master(pdev);
519
	return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
Tejun Heo's avatar
Tejun Heo committed
520
				 IRQF_SHARED, &k2_sata_sht);
Linus Torvalds's avatar
Linus Torvalds committed
521 522
}

523 524 525 526 527 528
/* 0x240 is device ID for Apple K2 device
 * 0x241 is device ID for Serverworks Frodo4
 * 0x242 is device ID for Serverworks Frodo8
 * 0x24a is device ID for BCM5785 (aka HT1000) HT southbridge integrated SATA
 * controller
 * */
529
static const struct pci_device_id k2_sata_pci_tbl[] = {
530
	{ PCI_VDEVICE(SERVERWORKS, 0x0240), chip_svw4 },
531 532
	{ PCI_VDEVICE(SERVERWORKS, 0x0241), chip_svw8 },
	{ PCI_VDEVICE(SERVERWORKS, 0x0242), chip_svw4 },
533 534 535 536
	{ PCI_VDEVICE(SERVERWORKS, 0x024a), chip_svw4 },
	{ PCI_VDEVICE(SERVERWORKS, 0x024b), chip_svw4 },
	{ PCI_VDEVICE(SERVERWORKS, 0x0410), chip_svw42 },
	{ PCI_VDEVICE(SERVERWORKS, 0x0411), chip_svw43 },
537

Linus Torvalds's avatar
Linus Torvalds committed
538 539 540 541 542 543 544 545 546 547
	{ }
};

static struct pci_driver k2_sata_pci_driver = {
	.name			= DRV_NAME,
	.id_table		= k2_sata_pci_tbl,
	.probe			= k2_sata_init_one,
	.remove			= ata_pci_remove_one,
};

Axel Lin's avatar
Axel Lin committed
548
module_pci_driver(k2_sata_pci_driver);
Linus Torvalds's avatar
Linus Torvalds committed
549 550 551 552 553 554

MODULE_AUTHOR("Benjamin Herrenschmidt");
MODULE_DESCRIPTION("low-level driver for K2 SATA controller");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, k2_sata_pci_tbl);
MODULE_VERSION(DRV_VERSION);