// SPDX-License-Identifier: GPL-2.0-only /* * Libata driver for the HighPoint 371N, 372N, and 302N UDMA66 ATA controllers. * * This driver is heavily based upon: * * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 * * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> * Portions Copyright (C) 2001 Sun Microsystems, Inc. * Portions Copyright (C) 2003 Red Hat Inc * Portions Copyright (C) 2005-2010 MontaVista Software, Inc. * * * TODO * Work out best PLL policy
*/ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/blkdev.h> #include <linux/delay.h> #include <scsi/scsi_host.h> #include <linux/libata.h>
/* key for bus clock timings * bit * 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA. * cycles = value + 1 * 4:8 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA. * cycles = value + 1 * 9:12 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file * register access. * 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file * register access. * 18:20 udma_cycle_time. Clock cycles for UDMA xfer. * 21 CLK frequency for UDMA: 0=ATA clock, 1=dual ATA clock. * 22:24 pre_high_time. Time to initialize 1st cycle for PIO and MW DMA xfer. * 25:27 cmd_pre_high_time. Time to initialize 1st PIO cycle for task file * register access. * 28 UDMA enable. * 29 DMA enable. * 30 PIO_MST enable. If set, the chip is in bus master mode during * PIO xfer. * 31 FIFO enable. Only for PIO.
*/
/** * hpt3x2n_find_mode - reset the hpt3x2n bus * @ap: ATA port * @speed: transfer mode * * Return the 32bit register programming information for this channel * that matches the speed provided. For the moment the clocks table * is hard coded but easy to change. This will be needed if we use * different DPLLs
*/
while (clocks->xfer_speed) { if (clocks->xfer_speed == speed) return clocks->timing;
clocks++;
}
BUG(); return 0xffffffffU; /* silence compiler warning */
}
/** * hpt372n_filter - mode selection filter * @adev: ATA device * @mask: mode mask * * The Marvell bridge chips used on the HighPoint SATA cards do not seem * to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
*/ staticunsignedint hpt372n_filter(struct ata_device *adev, unsignedint mask)
{ if (ata_id_is_sata(adev->id))
mask &= ~((0xE << ATA_SHIFT_UDMA) | ATA_MASK_MWDMA);
return mask;
}
/** * hpt3x2n_cable_detect - Detect the cable type * @ap: ATA port to detect on * * Return the cable type attached to this port
*/
/** * hpt3x2n_pre_reset - reset the hpt3x2n bus * @link: ATA link to reset * @deadline: deadline jiffies for the operation * * Perform the initial reset handling for the 3x2n series controllers. * Reset the hardware and state machine,
*/
/** * hpt3x2n_set_clock - clock control * @ap: ATA port * @source: 0x21 or 0x23 for PLL or PCI sourced clock * * Switch the ATA bus clock between the PLL and PCI clock sources * while correctly isolating the bus and resetting internal logic * * We must use the DPLL for * - writing * - second channel UDMA7 (SATA ports) or higher * - 66MHz PCI * * or we will underclock the device and get reduced performance.
*/
/* Reset state machines, avoid enabling the disabled channels */
iowrite8(ioread8(bmdma+0x70) | 0x32, bmdma+0x70);
iowrite8(ioread8(bmdma+0x74) | 0x32, bmdma+0x74);
/* Complete reset */
iowrite8(0x00, bmdma+0x79);
/* Reconnect channels to bus */
iowrite8(0x00, bmdma+0x73);
iowrite8(0x00, bmdma+0x77);
}
staticint hpt3x2n_use_dpll(struct ata_port *ap, int writing)
{ long flags = (long)ap->host->private_data;
/* See if we should use the DPLL */ if (writing) return USE_DPLL; /* Needed for write */ if (flags & PCI66) return USE_DPLL; /* Needed at 66Mhz */ return 0;
}
/** * hpt3xn_calibrate_dpll - Calibrate the DPLL loop * @dev: PCI device * * Perform a calibration cycle on the HPT3xN DPLL. Returns 1 if this * succeeds
*/
/* * Some devices do not let this value be accessed via PCI space * according to the old driver.
*/
fcnt = inl(pci_resource_start(pdev, 4) + 0x90); if ((fcnt >> 12) != 0xABCDE) {
u32 total = 0; int i;
u16 sr;
dev_warn(&pdev->dev, "BIOS clock data not set\n");
/* This is the process the HPT371 BIOS is reported to use */ for (i = 0; i < 128; i++) {
pci_read_config_word(pdev, 0x78, &sr);
total += sr & 0x1FF;
udelay(15);
}
fcnt = total / 128;
}
fcnt &= 0x1FF;
freq = (fcnt * base) / 192; /* in MHz */
/* Clamp to bands */ if (freq < 40) return 33; if (freq < 45) return 40; if (freq < 55) return 50; return 66;
}
/** * hpt3x2n_init_one - Initialise an HPT37X/302 * @dev: PCI device * @id: Entry in match table * * Initialise an HPT3x2n device. There are some interesting complications * here. Firstly the chip may report 366 and be one of several variants. * Secondly all the timings depend on the clock for the chip which we must * detect and look up * * This is the known chip mappings. It may be missing a couple of later * releases. * * Chip version PCI Rev Notes * HPT372 4 (HPT366) 5 Other driver * HPT372N 4 (HPT366) 6 UDMA133 * HPT372 5 (HPT372) 1 Other driver * HPT372N 5 (HPT372) 2 UDMA133 * HPT302 6 (HPT302) * Other driver * HPT302N 6 (HPT302) > 1 UDMA133 * HPT371 7 (HPT371) * Other driver * HPT371N 7 (HPT371) > 1 UDMA133 * HPT374 8 (HPT374) * Other driver * HPT372N 9 (HPT372N) * UDMA133 * * (1) UDMA133 support depends on the bus clock
*/
/* * HPT371 chips physically have only one channel, the secondary one, * but the primary channel registers do exist! Go figure... * So, we manually disable the non-existing channel here * (if the BIOS hasn't done this already).
*/ if (dev->device == PCI_DEVICE_ID_TTI_HPT371) {
u8 mcr1;
pci_read_config_byte(dev, 0x50, &mcr1);
mcr1 &= ~0x04;
pci_write_config_byte(dev, 0x50, mcr1);
}
/* * Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or * 50 for UDMA100. Right now we always use 66
*/
/* Unlike the 37x we don't try jiggling the frequency */ for (adjust = 0; adjust < 8; adjust++) { if (hpt3xn_calibrate_dpll(dev)) break;
pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low);
} if (adjust == 8) {
dev_err(&dev->dev, "DPLL did not stabilize!\n"); return -ENODEV;
}
dev_info(&dev->dev, "bus clock %dMHz, using 66MHz DPLL\n", pci_mhz);
/* * Set our private data up. We only need a few flags * so we use it directly.
*/ if (pci_mhz > 60)
hpriv = (void *)(PCI66 | USE_DPLL);
/* * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in * the MISC. register to stretch the UltraDMA Tss timing. * NOTE: This register is only writeable via I/O space.
*/ if (dev->device == PCI_DEVICE_ID_TTI_HPT371)
outb(inb(iobase + 0x9c) | 0x04, iobase + 0x9c);
/* Now kick off ATA set up */ return ata_pci_bmdma_init_one(dev, ppi, &hpt3x2n_sht, hpriv, 0);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.