blob: 87eba92ba8415f7c4537dfc5f5cee4775a3d2fa3 [file] [log] [blame]
/*
* sata_brcmstb.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...
*
*
* 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.
*
* BRCM NOTE:
* 2.6.29.1 version was ported from 2.6.18-6.6a. PMP support is disabled.
* remove all QDMA/NCQ and PMP support
*/
#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>
#include <linux/device.h>
#include <scsi/scsi_host.h>
#include <linux/spinlock.h>
#include <linux/libata.h>
#include <linux/pm.h>
#include <linux/clk.h>
#include <linux/version.h>
#include <linux/pm_runtime.h>
#ifdef CONFIG_PPC_OF
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#endif /* CONFIG_PPC_OF */
#define DRV_NAME "sata_brcmstb"
#define DRV_VERSION "4.0"
#include <asm/brcmstb/brcmstb.h>
static int ssc; /* aka: bcmssc, gSataInterpolation */
static int s2; /* aka: bcmsata2, gSata2_3Gbps */
module_param(ssc, int, 0444);
module_param(s2, int, 0444);
struct k2_host_priv {
spinlock_t lock;
int sleep_flag;
struct clk *clk;
void __iomem *mmio_base;
unsigned long hp_jif;
};
#define SLEEP_FLAG(host) ({ \
struct ata_host *h = (host); \
struct k2_host_priv *hp = h->private_data; \
hp->sleep_flag; \
})
#define SET_SLEEP_FLAG(host, val) do { \
struct ata_host *h = (host); \
struct k2_host_priv *hp = h->private_data; \
hp->sleep_flag = (val); \
} while (0)
#define K2_AWAKE 0
#define K2_SLEEPING 1
#define K2_OFF 2
static int k2_power_on(void *arg);
#define K2_POWER_ON(host) do { \
if (SLEEP_FLAG(host) != K2_AWAKE) \
k2_power_on(host); \
} while (0)
/*
* if bcmsata2=1, but device only support SATA I,
* then downgrade to SATA I and reset SATA core
*/
#define AUTO_NEG_SPEED
static unsigned int new_speed_mask;
enum {
/* ap->flags bits */
K2_FLAG_SATA_8_PORTS = (1 << 24),
K2_FLAG_NO_ATAPI_DMA = (1 << 25),
K2_FLAG_BAR_POS_3 = (1 << 26),
K2_FLAG_BRCM_SATA2 = (1 << 27),
/* 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,
/* DMA base */
K2_SATA_DMA_CMD_OFFSET = 0x30,
/* SCRs base */
K2_SATA_SCR_STATUS_OFFSET = 0x40, /* aka SCR0 */
K2_SATA_SCR_ERROR_OFFSET = 0x44, /* aka SCR1 */
K2_SATA_SCR_CONTROL_OFFSET = 0x48, /* aka SCR2 */
K2_SATA_SCR_ACTIVE_OFFSET = 0x4c, /* aka SCR3 */
/* Others */
K2_SATA_SICR1_OFFSET = 0x80,
K2_SATA_SICR2_OFFSET = 0x84,
K2_SATA_SIMR_OFFSET = 0x88, /* SATA intr mask register */
K2_SATA_MDIO_OFFSET = 0x8c, /* SATA MDIO access register */
K2_SATA_SCQR_OFFSET = 0x94, /* SATA command queue depth */
K2_SATA_QAL_OFFSET = 0xa0, /* QDMA ring address lower */
K2_SATA_QAU_OFFSET = 0xa4, /* QDMA ring address upper */
K2_SATA_QPI_OFFSET = 0xa8, /* QDMA producer index */
K2_SATA_QCI_OFFSET = 0xac, /* QDMA consumer index */
K2_SATA_QCR_OFFSET = 0xb0, /* QDMA control register */
K2_SATA_QDR_OFFSET = 0xb4, /* QDMA queue depth */
K2_SATA_QSR_OFFSET = 0xb8, /* QDMA status register */
K2_SATA_QMR_OFFSET = 0xbc, /* QDMA interrupt mask */
K2_SATA_QCI2_OFFSET = 0xc0, /* QDMA internal QCI for NCQ */
K2_SATA_E0_OFFSET = 0xe0,
K2_SATA_F0_OFFSET = 0xf0,
/* Port stride */
K2_SATA_PORT_OFFSET = 0x100,
K2_SATA_GLOBAL_STATUS = 0x1004,
K2_SATA_GLOBAL_MASK = 0x1018,
chip_sata1 = 0,
chip_sata2 = 1,
};
#define PORT_BASE(x, y) ((x) + (K2_SATA_PORT_OFFSET * (unsigned)(y)))
#define PORT_MMIO(x) PORT_BASE((void __iomem *) \
((x)->host->iomap[5]), \
(x)->port_no)
/*
* Extra init functions for stblinux platforms
*/
#define WRITE_CMD 1
#define READ_CMD 2
#define CMD_DONE (1 << 15)
#define SATA_MMIO 0x24
/*
* 1. port is SATA port ( 0 or 1)
* 2. reg is the address of the MDIO register ( see spec )
* 3. MMIO_BASE_ADDR is MMIO base address from SATA PCI configuration
* registers addr 24-27
*/
static int mdio_read_reg(void __iomem *mmio_base, int port,
int reg)
{
void __iomem *mdio = mmio_base + K2_SATA_MDIO_OFFSET;
unsigned int pSel = 1 << port;
uint32_t cmd = WRITE_CMD;
if (reg > 0x13)
return -1;
/* Select Port */
writel(pSel<<16 | (cmd << 13) | 7, mdio);
while (!(readl(mdio) & CMD_DONE))
udelay(1);
writel((READ_CMD << 13) + reg, mdio);
while (!(readl(mdio) & CMD_DONE))
udelay(1);
return readl(mdio) >> 16;
}
static void mdio_write_reg(void __iomem *mmio_base, int port,
int reg, uint16_t val)
{
void __iomem *mdio = mmio_base + K2_SATA_MDIO_OFFSET;
unsigned int pSel = 1 << port;
uint32_t cmd = WRITE_CMD;
if (reg > 0x13)
return;
/* Select Port */
writel(pSel<<16 | (cmd << 13) | 7, mdio);
while (!(readl(mdio) & CMD_DONE))
udelay(1);
writel((val << 16) + (WRITE_CMD << 13) + reg, mdio);
while (!(readl(mdio) & CMD_DONE))
udelay(1);
}
static void DisablePHY(void __iomem *mmio_base, int port)
{
uint32_t *pScr2 = PORT_BASE(mmio_base, port) +
K2_SATA_SCR_CONTROL_OFFSET;
writel(1, pScr2);
}
static void EnablePHY(void __iomem *mmio_base, int port)
{
uint32_t *pScr2 = PORT_BASE(mmio_base, port) +
K2_SATA_SCR_CONTROL_OFFSET;
writel(0, pScr2);
}
static void bcm_sg_workaround(void __iomem *mmio_base, int port)
{
int tmp16;
DisablePHY(mmio_base, port);
/*
* Do Interpolation when
* spread spectrucm clocking (SSC) is NOT enabled. But, the code must
* be used for a system with SSC-enabled drive.
* ssc is not zero when the argument bcmssc=1 is specified
*/
if (ssc) {
tmp16 = mdio_read_reg(mmio_base, port, 9);
mdio_write_reg(mmio_base, port, 9, tmp16 | 1);
}
/* Do analog reset */
tmp16 = mdio_read_reg(mmio_base, port, 4);
tmp16 |= 8;
mdio_write_reg(mmio_base, port, 4, tmp16);
udelay(1000);
tmp16 &= 0xFFF7;
mdio_write_reg(mmio_base, port, 4, tmp16);
udelay(1000);
/* Enable PHY */
EnablePHY(mmio_base, port);
}
/*
* This routine change (lower) bandwidth of SATA PLL to lower jitter
* from main internal ref clk in attempt to use on chip refclock
*/
static void brcm_SetPllTxRxCtrl(void __iomem *mmio_base, int port)
{
int tmp16;
/* Change Tx control */
mdio_write_reg(mmio_base, port, 0xa, 0x0260);
mdio_write_reg(mmio_base, port, 0x11, 0x0a10);
/* Change Rx control */
tmp16 = mdio_read_reg(mmio_base, port, 0xF);
tmp16 &= 0xc000;
tmp16 |= 0x1000;
mdio_write_reg(mmio_base, port, 0xF, tmp16);
}
static void brcm_TunePLL(void __iomem *mmio_base, int port)
{
int tmp;
int i;
/* program VCO step bit [12:10] start with 111 */
mdio_write_reg(mmio_base, port, 0x13, 0x1c00);
udelay(100000);
/* start pll tuner */
mdio_write_reg(mmio_base, port, 0x13, 0x1e00);
udelay(10000);
/* check lock bit */
tmp = mdio_read_reg(mmio_base, port, 0x7);
for (i = 0; i < 10000; i++) {
tmp = mdio_read_reg(mmio_base, port, 0x7);
if ((tmp & 0x8000) == 0x8000)
return;
udelay(1);
}
DPRINTK("PLL did not lock\n");
}
static void brcm_EnableOOBWindowFix(void __iomem *mmio_base, int port)
{
int sval;
/* Port 0 Transmit Control Register */
sval = mdio_read_reg(mmio_base, port, 0x0D);
sval |= 0x400;
mdio_write_reg(mmio_base, port, 0x0D, sval);
}
static void brcm_Enable256AlignDetection(void __iomem *mmio_base, int port)
{
uint32_t tmp32;
void __iomem *port_mmio;
port_mmio = PORT_BASE(mmio_base, port);
tmp32 = readl(port_mmio + K2_SATA_SICR1_OFFSET);
tmp32 |= 0x08000000;
writel(tmp32, port_mmio + K2_SATA_SICR1_OFFSET);
tmp32 = readl(port_mmio + K2_SATA_SICR2_OFFSET);
tmp32 |= 0x00800000;
writel(tmp32, port_mmio + K2_SATA_SICR2_OFFSET);
}
static void brcm_AnalogReset(void __iomem *mmio_base, int port)
{
/* do analog reset */
mdio_write_reg(mmio_base, port, 0x4, 8);
udelay(10000);
mdio_write_reg(mmio_base, port, 0x4, 0);
bcm_sg_workaround(mmio_base, port);
}
static void brcm_InitSata_1_5Gb(void __iomem *mmio_base, int port)
{
int tmp;
volatile uint32_t tmp32;
void __iomem *port_mmio;
port_mmio = PORT_BASE(mmio_base, port);
/* reset deskew TX FIFO */
mdio_write_reg(mmio_base, port, 7, 1<<port);
mdio_write_reg(mmio_base, port, 0xd, 0x4800);
udelay(10000);
mdio_write_reg(mmio_base, port, 0xd, 0x0800);
udelay(10000);
/* Enable low speed (1.5G) mode */
tmp = mdio_read_reg(mmio_base, port, 8);
mdio_write_reg(mmio_base, port, 8, tmp | 0x10);
/* Enable lock monitor.. if not set the lock bit is not updated */
tmp = mdio_read_reg(mmio_base, port, 0x13);
mdio_write_reg(mmio_base, port, 0x13, tmp|2);
udelay(10000);
/* disable 3G feature */
tmp32 = readl(port_mmio + K2_SATA_F0_OFFSET);
writel(tmp32 & 0xfffffbff, port_mmio + K2_SATA_F0_OFFSET);
udelay(10000);
/* enable 4G addressing support */
tmp32 = readl(port_mmio + K2_SATA_SICR2_OFFSET);
writel(tmp32 | 0x20009400, port_mmio + K2_SATA_SICR2_OFFSET);
tmp32 = readl(port_mmio + K2_SATA_SICR1_OFFSET);
tmp32 &= 0xffff0000;
writel(tmp32 | 0x00000f10, port_mmio + K2_SATA_SICR1_OFFSET);
/* Clean up the fifo */
tmp32 = readl(port_mmio + K2_SATA_E0_OFFSET);
writel(tmp32 | 2, port_mmio + K2_SATA_E0_OFFSET);
brcm_SetPllTxRxCtrl(mmio_base, port);
brcm_EnableOOBWindowFix(mmio_base, port);
brcm_Enable256AlignDetection(mmio_base, port);
if (!port) {
#ifdef CONFIG_BRCM_SATA_75MHZ_PLL
/* use 75Mhz PLL clock */
mdio_write_reg(mmio_base, port, 0, 0x2004);
#else
/* use 100Mhz PLL clock */
mdio_write_reg(mmio_base, port, 0, 0x1404);
#endif
brcm_TunePLL(mmio_base, port);
brcm_AnalogReset(mmio_base, port);
udelay(10000);
}
writel(0, port_mmio + K2_SATA_SCR_CONTROL_OFFSET);
}
static void brcm_InitSata2_3Gb(void __iomem *mmio_base, int port)
{
volatile uint16_t tmp;
volatile uint32_t tmp32;
void __iomem *port_base;
port_base = PORT_BASE(mmio_base, port);
/* reset deskew TX FIFO */
mdio_write_reg(mmio_base, port, 7, 1<<port);
mdio_write_reg(mmio_base, port, 0xd, 0x4800);
udelay(10000);
mdio_write_reg(mmio_base, port, 0xd, 0x0800);
udelay(10000);
/* run at 3G mode */
tmp = mdio_read_reg(mmio_base, port, 8);
mdio_write_reg(mmio_base, port, 8, tmp & ~(0x10));
udelay(10000);
/* Enable lock monitor. if not set the lock bit is not updated */
tmp = mdio_read_reg(mmio_base, port, 0x13);
mdio_write_reg(mmio_base, port, 0x13, tmp|2);
/* Enable 3Gb interface */
tmp32 = readl(port_base + K2_SATA_F0_OFFSET);
writel(tmp32 | 0x10500, port_base + K2_SATA_F0_OFFSET);
udelay(10000);
/* enable 4G addressing support */
tmp32 = readl(port_base + K2_SATA_SICR2_OFFSET);
writel(tmp32 | 0x20009400, port_base + K2_SATA_SICR2_OFFSET);
tmp32 = readl(port_base + K2_SATA_SICR1_OFFSET);
tmp32 &= 0xffff0000;
writel(tmp32 | 0x00000f10, port_base + K2_SATA_SICR1_OFFSET);
/* Clean up the fifo */
tmp32 = readl(port_base + K2_SATA_E0_OFFSET);
writel(tmp32|2, port_base + K2_SATA_E0_OFFSET);
/* Tweak PLL, Tx, and Rx */
brcm_SetPllTxRxCtrl(mmio_base, port);
brcm_EnableOOBWindowFix(mmio_base, port);
brcm_Enable256AlignDetection(mmio_base, port);
if (!port) {
#ifdef CONFIG_BRCM_SATA_75MHZ_PLL
/* use 75Mhz PLL clock */
mdio_write_reg(mmio_base, port, 0, 0x2004);
#else
/* use 100Mhz PLL clock */
mdio_write_reg(mmio_base, port, 0, 0x1404);
#endif
brcm_TunePLL(mmio_base, port);
brcm_AnalogReset(mmio_base, port);
udelay(10000);
}
writel(0, port_base + K2_SATA_SCR_CONTROL_OFFSET);
}
/* Kernel argument bcmsata2=0|1 */
static inline void brcm_initsata2(void __iomem *mmio_base, int num_ports)
{
int port;
unsigned int first = 1;
retry_brcm_initsata2:
for (port = 0; port < num_ports; port++)
writel(1, (void *)(mmio_base + port*K2_SATA_PORT_OFFSET +
K2_SATA_SCR_CONTROL_OFFSET));
for (port = 0; port < num_ports; port++) {
/*
* Turn on 3Gbps if bcmsata2=1 is specified as kernel argument
* during bootup
*/
if (s2) {
if (new_speed_mask == 0)
brcm_InitSata2_3Gb(mmio_base, port);
else if (new_speed_mask & (1<<port))
brcm_InitSata_1_5Gb(mmio_base, port);
} else
brcm_InitSata_1_5Gb(mmio_base, port);
}
#ifdef AUTO_NEG_SPEED
if (s2 && first) {
int port;
msleep(10);
for (port = 0; port < num_ports; port++) {
unsigned int status = readl((void *)(mmio_base +
port*K2_SATA_PORT_OFFSET +
K2_SATA_SCR_STATUS_OFFSET));
if ((status & 0xf) >= 0x5 &&
(status & 0xf0) == 0 &&
(status & 0xf00) == 0)
new_speed_mask |= 1<<port;
}
first = 0;
if (new_speed_mask)
goto retry_brcm_initsata2;
}
new_speed_mask = 0;
#endif
}
void k2_sata_postreset(struct ata_link *link, unsigned int *classes)
{
struct ata_port *ap = link->ap;
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
unsigned int reg = readl(port + K2_SATA_SIMR_OFFSET);
if (ap->ops->freeze)
ap->ops->freeze(ap);
writel(reg | SERR_PHYRDY_CHG, port + K2_SATA_SIMR_OFFSET);
if (ap->ops->thaw)
ap->ops->thaw(ap);
return ata_std_postreset(link, classes);
}
static void bcm97xxx_sata_init(struct pci_dev *dev,
void __iomem *mmio_base,
int n_ports,
int sata2_core)
{
int reg;
int port;
void __iomem *port_base;
if (sata2_core) {
brcm_initsata2(mmio_base, n_ports);
/* Skip all workarounds. Those have been fixed with 65nm */
return;
}
/*
* Before accessing the MDIO registers through pci space disable
* external MDIO access. write MDIO register at offset 0x07 with
* (1 << port number) where port number starts at 0.
* Read MDIO register at offset 0x0D into variable reg.
* reg_0d = reg_0d | 0x04
* Write reg_0d to MDIO register at offset 0x0D.
*/
for (port = 0; port < n_ports; port++) {
/* Put PHY in reset */
port_base = PORT_BASE(mmio_base, 0);
reg = readl(port_base+K2_SATA_SCR_CONTROL_OFFSET);
writel((reg & ~0xf) | 1, port_base+K2_SATA_SCR_CONTROL_OFFSET);
/* Choose the port and read reg 0xd */
reg = mdio_read_reg(mmio_base, port, 0xd);
reg |= 0x4;
mdio_write_reg(mmio_base, port, 0xd, reg);
reg = mdio_read_reg(mmio_base, port, 0xd);
/* Re-enable PHY */
reg = readl(port_base+K2_SATA_SCR_CONTROL_OFFSET);
writel(reg & ~0xf, port_base+K2_SATA_SCR_CONTROL_OFFSET);
}
/* PR22401: Identify Seagate drives with ST controllers */
for (port = 0; port < n_ports; port++)
bcm_sg_workaround(mmio_base, port);
}
/*
* Common (legacy/QDMA) functions
*/
static int k2_sata_scr_read(struct ata_link *link,
unsigned int sc_reg,
u32 *val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
*val = readl((void *) link->ap->ioaddr.scr_addr + (sc_reg * 4));
return 0;
}
static int k2_sata_scr_write(struct ata_link *link,
unsigned int sc_reg,
u32 val)
{
if (sc_reg > SCR_CONTROL)
return -EINVAL;
writel(val, (void *) link->ap->ioaddr.scr_addr + (sc_reg * 4));
return 0;
}
static u8 k2_stat_check_status(struct ata_port *ap)
{
return readl((void *) ap->ioaddr.status_addr);
}
static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
u16 nsect, lbal, lbam, lbah, feature;
void __iomem *port_mmio = PORT_MMIO(ap);
u32 qcr, qsr;
qcr = readl(port_mmio + K2_SATA_QCR_OFFSET);
/* QDMA active, unpaused - pause the queue to read taskfile */
if ((qcr & 3) == 1) {
int i = 0;
writel(qcr | 2, port_mmio + K2_SATA_QCR_OFFSET);
do {
qsr = readl(port_mmio + K2_SATA_QSR_OFFSET);
if (qsr & 2)
break;
if (++i == 1000) {
ata_port_printk(ap, KERN_WARNING,
"error pausing queue for taskfile read\n");
break;
}
udelay(1);
} while (1);
}
tf->command = k2_stat_check_status(ap);
tf->device = readw((void *)ioaddr->device_addr);
feature = readw((void *)ioaddr->error_addr);
nsect = readw((void *)ioaddr->nsect_addr);
lbal = readw((void *)ioaddr->lbal_addr);
lbam = readw((void *)ioaddr->lbam_addr);
lbah = readw((void *)ioaddr->lbah_addr);
tf->feature = feature;
tf->nsect = nsect;
tf->lbal = lbal;
tf->lbam = lbam;
tf->lbah = lbah;
if (tf->flags & ATA_TFLAG_LBA48) {
tf->hob_feature = feature >> 8;
tf->hob_nsect = nsect >> 8;
tf->hob_lbal = lbal >> 8;
tf->hob_lbam = lbam >> 8;
tf->hob_lbah = lbah >> 8;
}
/* unpause queue */
if ((qcr & 3) == 1)
writel(qcr, port_mmio + K2_SATA_QCR_OFFSET);
}
#ifdef CONFIG_PPC_OF
/*
* k2_sata_proc_info
* inout : decides on the direction of the dataflow and the meaning of the
* variables
* buffer: If inout==FALSE data is being written to it else read from it
* *start: If inout==FALSE start of the valid data in the buffer
* offset: If inout==FALSE offset from the beginning of the imaginary file
* from which we start writing into the buffer
* length: If inout==FALSE max number of bytes to be written into the buffer
* else number of bytes in the buffer
*/
static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
off_t offset, int count, int inout)
{
struct ata_port *ap;
struct device_node *np;
int len, index;
/* Find the ata_port */
ap = ata_shost_to_port(shost);
if (ap == NULL)
return 0;
/* Find the OF node for the PCI device proper */
np = pci_device_to_OF_node(to_pci_dev(ap->host->dev));
if (np == NULL)
return 0;
/* Match it to a port node */
index = (ap == ap->host->ports[0]) ? 0 : 1;
for (np = np->child; np != NULL; np = np->sibling) {
const u32 *reg = get_property(np, "reg", NULL);
if (!reg)
continue;
if (index == *reg)
break;
}
if (np == NULL)
return 0;
len = sprintf(page, "devspec: %s\n", np->full_name);
return len;
}
#endif /* CONFIG_PPC_OF */
/*
* Legacy-only functions
*/
static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
if (tf->ctl != ap->last_ctl) {
writeb(tf->ctl, ioaddr->ctl_addr);
ap->last_ctl = tf->ctl;
ata_wait_idle(ap);
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
writew(tf->feature | (((u16)tf->hob_feature) << 8),
(void *)ioaddr->feature_addr);
writew(tf->nsect | (((u16)tf->hob_nsect) << 8),
(void *)ioaddr->nsect_addr);
writew(tf->lbal | (((u16)tf->hob_lbal) << 8),
(void *)ioaddr->lbal_addr);
writew(tf->lbam | (((u16)tf->hob_lbam) << 8),
(void *)ioaddr->lbam_addr);
writew(tf->lbah | (((u16)tf->hob_lbah) << 8),
(void *)ioaddr->lbah_addr);
} else if (is_addr) {
writew(tf->feature, (void *)ioaddr->feature_addr);
writew(tf->nsect, (void *)ioaddr->nsect_addr);
writew(tf->lbal, (void *)ioaddr->lbal_addr);
writew(tf->lbam, (void *)ioaddr->lbam_addr);
writew(tf->lbah, (void *)ioaddr->lbah_addr);
}
if (tf->flags & ATA_TFLAG_DEVICE)
writeb(tf->device, (void *)ioaddr->device_addr);
ata_wait_idle(ap);
}
/**
* k2_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
static void k2_bmdma_setup_mmio(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
u8 dmactl;
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
/* load PRD table addr. */
mb(); /* make sure PRD table writes are visible to controller */
writel(ap->bmdma_prd_dma, mmio + ATA_DMA_TABLE_OFS);
/* 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)
ap->ops->sff_exec_command(ap, &qc->tf);
}
/**
* k2_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
static void k2_bmdma_start_mmio(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
u8 dmactl;
/* start host DMA transaction */
dmactl = readb(mmio + ATA_DMA_CMD);
writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
/* There is a race condition in 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 */
if (qc->tf.protocol == ATA_PROT_DMA)
ap->ops->sff_exec_command(ap, &qc->tf);
}
static int k2_sata_port_start(struct ata_port *ap)
{
ata_bmdma_port_start(ap);
return 0;
}
static void k2_sata_error_handler(struct ata_port *ap)
{
ata_sff_error_handler(ap);
}
static irqreturn_t k2_sata_interrupt(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
unsigned int i;
unsigned int handled = 0;
unsigned long flags;
struct k2_host_priv *hp = host->private_data;
spin_lock_irqsave(&host->lock, flags);
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap;
struct ata_link *link;
ap = host->ports[i];
ata_for_each_link(link, ap, EDGE) {
int rc;
unsigned int serror;
rc = sata_scr_read(link, SCR_ERROR, &serror);
if (rc == 0) {
if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG)) {
if (time_after(jiffies, hp->hp_jif)) {
struct ata_eh_info *ehi =
&ap->link.eh_info;
unsigned long hp_flags;
sata_scr_write(link, SCR_ERROR, serror);
spin_lock_irqsave(&hp->lock, hp_flags);
hp->hp_jif = jiffies + 2*HZ;
spin_unlock_irqrestore(&hp->lock,
hp_flags);
ata_ehi_hotplugged(ehi);
ata_ehi_push_desc(ehi, "hotplug");
ata_port_freeze(ap);
handled |= IRQ_HANDLED;
} else {
sata_scr_write(link, SCR_ERROR, serror);
handled |= IRQ_HANDLED;
}
}
}
}
}
spin_unlock_irqrestore(&host->lock, flags);
if (handled & IRQ_HANDLED)
return handled;
return ata_bmdma_interrupt(irq, dev_instance);
}
/*
* Power management
*/
static void k2_sata_clk_disable(struct device *dev)
{
struct ata_host *host = dev_get_drvdata(dev);
struct k2_host_priv *hp = host->private_data;
clk_disable(hp->clk);
}
static void k2_sata_clk_enable(struct device *dev)
{
struct ata_host *host = dev_get_drvdata(dev);
struct k2_host_priv *hp = host->private_data;
clk_enable(hp->clk);
}
static int k2_power_off(void *arg)
{
struct ata_host *host = arg;
struct pci_dev *pdev = to_pci_dev(host->dev);
struct k2_host_priv *hp = host->private_data;
int i, active = 0;
unsigned long flags;
unsigned int retries = 100;
spin_lock_irqsave(&hp->lock, flags);
if (SLEEP_FLAG(host) == K2_SLEEPING || SLEEP_FLAG(host) == K2_OFF) {
spin_unlock_irqrestore(&hp->lock, flags);
return 0;
}
do {
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap;
struct ata_link *link;
struct ata_device *dev;
ap = host->ports[i];
/*
* dev->sdev is set to NULL in ata_scsi_slave_destroy()
* upon hot or warm unplug. If it is non-NULL,
* the device is still enabled and it is unsafe to
* power off the core.
*/
ata_for_each_link(link, ap, EDGE) {
ata_for_each_dev(dev, link, ALL) {
if (dev->sdev)
active++;
}
}
}
if (!active)
break;
active = 0;
msleep(100);
} while (retries--);
if (active) {
spin_unlock_irqrestore(&hp->lock, flags);
return -EBUSY;
} else {
void __iomem *port_base;
SET_SLEEP_FLAG(host, K2_OFF);
/* put all ports in Slumber mode */
for (i = 0; i < host->n_ports; i++) {
port_base = PORT_BASE(hp->mmio_base, i);
writel(readl(port_base + K2_SATA_SICR1_OFFSET) |
(1 << 25), port_base + K2_SATA_SICR1_OFFSET);
udelay(10);
writel((readl(port_base + K2_SATA_SICR2_OFFSET) &
~(7 << 18)) | (2 << 18),
port_base + K2_SATA_SICR2_OFFSET);
udelay(50);
writel((readl(port_base + K2_SATA_SICR2_OFFSET) &
~(7 << 18)) | (0 << 18),
port_base + K2_SATA_SICR2_OFFSET);
}
disable_irq(pdev->irq);
k2_sata_clk_disable(host->dev);
spin_unlock_irqrestore(&hp->lock, flags);
return 0;
}
}
static int k2_power_on(void *arg)
{
struct ata_host *host = arg;
struct pci_dev *pdev = to_pci_dev(host->dev);
struct k2_host_priv *hp = host->private_data;
void __iomem *port_base;
int i;
unsigned long flags;
spin_lock_irqsave(&hp->lock, flags);
if (SLEEP_FLAG(host) == K2_AWAKE) {
spin_unlock_irqrestore(&hp->lock, flags);
return 0;
}
k2_sata_clk_enable(host->dev);
brcm_initsata2(hp->mmio_base, host->n_ports);
enable_irq(pdev->irq);
/* wake up all ports */
for (i = 0; i < host->n_ports; i++) {
port_base = PORT_BASE(hp->mmio_base, i);
writel(readl(port_base + K2_SATA_SICR1_OFFSET) &
~(1 << 25), port_base + K2_SATA_SICR1_OFFSET);
udelay(10);
writel((readl(port_base + K2_SATA_SICR2_OFFSET) &
~(7 << 18)) | (4 << 18),
port_base + K2_SATA_SICR2_OFFSET);
udelay(50);
writel((readl(port_base + K2_SATA_SICR2_OFFSET) &
~(7 << 18)) | (0 << 18),
port_base + K2_SATA_SICR2_OFFSET);
}
SET_SLEEP_FLAG(host, K2_AWAKE);
spin_unlock_irqrestore(&hp->lock, flags);
return 0;
}
static int k2_sata_pm_cb(int event, void *arg)
{
if (event == PM_EVENT_SUSPEND)
return k2_power_off(arg);
else if (event == PM_EVENT_RESUME)
return k2_power_on(arg);
else
return -EINVAL;
}
static void k2_sata_remove_one(struct pci_dev *pdev)
{
struct device *dev = &pdev->dev;
struct ata_host *host = dev_get_drvdata(dev);
struct k2_host_priv *hp = host->private_data;
brcm_pm_unregister_cb("sata");
pm_runtime_get_noresume(&pdev->dev);
K2_POWER_ON(host);
ata_pci_remove_one(pdev);
clk_disable(hp->clk);
clk_put(hp->clk);
kfree(hp);
}
static int k2_sata_suspend(struct device *dev)
{
struct ata_host *host = dev_get_drvdata(dev);
struct pci_dev *pdev = to_pci_dev(host->dev);
struct k2_host_priv *hp = host->private_data;
int i;
void __iomem *port_base;
unsigned long flags;
spin_lock_irqsave(&hp->lock, flags);
if (SLEEP_FLAG(host) == K2_SLEEPING || SLEEP_FLAG(host) == K2_OFF) {
spin_unlock_irqrestore(&hp->lock, flags);
return 0;
}
SET_SLEEP_FLAG(host, K2_SLEEPING);
/* put all ports in Slumber mode */
for (i = 0; i < host->n_ports; i++) {
port_base = PORT_BASE(hp->mmio_base, i);
writel(readl(port_base + K2_SATA_SICR1_OFFSET) |
(1 << 25), port_base + K2_SATA_SICR1_OFFSET);
udelay(10);
writel((readl(port_base + K2_SATA_SICR2_OFFSET) &
~(7 << 18)) | (2 << 18),
port_base + K2_SATA_SICR2_OFFSET);
udelay(50);
writel((readl(port_base + K2_SATA_SICR2_OFFSET) &
~(7 << 18)) | (0 << 18),
port_base + K2_SATA_SICR2_OFFSET);
}
disable_irq(pdev->irq);
k2_sata_clk_disable(dev);
spin_unlock_irqrestore(&hp->lock, flags);
return 0;
}
static int k2_sata_resume(struct device *dev)
{
struct ata_host *host = dev_get_drvdata(dev);
struct pci_dev *pdev = to_pci_dev(host->dev);
struct k2_host_priv *hp = host->private_data;
void __iomem *port_base;
int i;
unsigned long flags;
spin_lock_irqsave(&hp->lock, flags);
if (SLEEP_FLAG(host) == K2_AWAKE || SLEEP_FLAG(host) == K2_OFF) {
spin_unlock_irqrestore(&hp->lock, flags);
return 0;
}
k2_sata_clk_enable(dev);
brcm_initsata2(hp->mmio_base, host->n_ports);
enable_irq(pdev->irq);
/* wake up all ports */
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap;
struct ata_link *link;
port_base = PORT_BASE(hp->mmio_base, i);
writel(readl(port_base + K2_SATA_SICR1_OFFSET) &
~(1 << 25), port_base + K2_SATA_SICR1_OFFSET);
udelay(10);
writel((readl(port_base + K2_SATA_SICR2_OFFSET) &
~(7 << 18)) | (4 << 18),
port_base + K2_SATA_SICR2_OFFSET);
udelay(50);
writel((readl(port_base + K2_SATA_SICR2_OFFSET) &
~(7 << 18)) | (0 << 18),
port_base + K2_SATA_SICR2_OFFSET);
ap = host->ports[i];
ata_for_each_link(link, ap, EDGE) {
spin_unlock_irqrestore(&hp->lock, flags);
sata_std_hardreset(link, NULL, 1000);
spin_lock_irqsave(&hp->lock, flags);
}
}
SET_SLEEP_FLAG(host, K2_AWAKE);
spin_unlock_irqrestore(&hp->lock, flags);
return 0;
}
static int k2_sata_runtime_suspend(struct device *dev)
{
return k2_sata_suspend(dev);
}
static int k2_sata_runtime_resume(struct device *dev)
{
return k2_sata_resume(dev);
}
static int k2_sata_runtime_idle(struct device *dev)
{
dev_printk(KERN_DEBUG, dev, "%s [%lu] disabling the SATA clock\n",
__func__, jiffies);
return 0; /* ignored by pm core */
}
/*
* Driver initialization
*/
static struct scsi_host_template k2_sata_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
.proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
#ifdef CONFIG_PPC_OF
.proc_info = k2_sata_proc_info,
#endif
.bios_param = ata_std_bios_param,
};
static struct ata_port_operations k2_sata_ops = {
.inherits = &ata_bmdma_port_ops,
.sff_tf_read = k2_sata_tf_read,
.sff_check_status = k2_stat_check_status,
.scr_read = k2_sata_scr_read,
.scr_write = k2_sata_scr_write,
.port_start = k2_sata_port_start,
.error_handler = k2_sata_error_handler,
.postreset = k2_sata_postreset,
.bmdma_setup = k2_bmdma_setup_mmio,
.bmdma_start = k2_bmdma_start_mmio,
.sff_tf_load = k2_sata_tf_load,
};
static const struct ata_port_info k2_port_info[] = {
/* chip_sata1 */
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA7,
.port_ops = &k2_sata_ops,
},
/* chip_sata2 */
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA |
K2_FLAG_BRCM_SATA2,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA7,
.port_ops = &k2_sata_ops,
},
};
static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base)
{
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;
}
static int k2_sata_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
static int printed_version;
const struct ata_port_info *ppi[] = {
&k2_port_info[ent->driver_data], NULL };
struct ata_host *host;
void __iomem *mmio_base;
int n_ports, i, rc, bar_pos;
struct k2_host_priv *hp;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
#ifdef CONFIG_BRCM_SATA_SINGLE_PORT
n_ports = 1;
#else
n_ports = 2;
#endif
host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
if (!host)
return -ENOMEM;
host->private_data = hp = kzalloc(sizeof(*hp), GFP_KERNEL);
if (!hp)
return -ENOMEM;
spin_lock_init(&hp->lock);
hp->clk = clk_get(&pdev->dev, "sata");
clk_enable(hp->clk);
hp->sleep_flag = K2_AWAKE;
bar_pos = 5;
if (ppi[0]->flags & K2_FLAG_BAR_POS_3)
bar_pos = 3;
/*
* 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
*/
rc = pcim_enable_device(pdev);
if (rc)
return rc;
/*
* Check if we have resources mapped at all (second function may
* have been disabled by firmware)
*/
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);
return -ENODEV;
}
/* Request and iomap PCI regions */
rc = pcim_iomap_regions(pdev, 1 << bar_pos, DRV_NAME);
if (rc == -EBUSY)
pcim_pin_device(pdev);
if (rc)
return rc;
host->iomap = pcim_iomap_table(pdev);
hp->mmio_base = mmio_base = host->iomap[bar_pos];
/* 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.
*/
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");
}
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
return rc;
rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
return rc;
/* 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_SIMR_OFFSET);
pci_set_master(pdev);
bcm97xxx_sata_init(pdev, mmio_base, n_ports,
ppi[0]->flags & K2_FLAG_BRCM_SATA2);
hp->hp_jif = jiffies;
rc = ata_host_activate(host, pdev->irq, k2_sata_interrupt,
IRQF_SHARED, &k2_sata_sht);
if (rc)
return rc;
brcm_pm_register_cb("sata", k2_sata_pm_cb, host);
/* pci core incremented pm counter before calling probe,
* we are decrementing it to enable runtime pm */
pm_runtime_put_noidle(&pdev->dev);
return 0;
}
static const struct pci_device_id k2_sata_pci_tbl[] = {
{ PCI_VDEVICE(SERVERWORKS, 0x0242), chip_sata1 }, /* 7401 and older */
{ PCI_VDEVICE(BROADCOM, 0x8602), chip_sata2 }, /* 7400 and newer */
{ }
};
static const struct dev_pm_ops k2_sata_pm_ops = {
.suspend_noirq = k2_sata_suspend,
.resume_noirq = k2_sata_resume,
.runtime_suspend = k2_sata_runtime_suspend,
.runtime_resume = k2_sata_runtime_resume,
.runtime_idle = k2_sata_runtime_idle,
};
static struct pci_driver k2_sata_pci_driver = {
.name = DRV_NAME,
.id_table = k2_sata_pci_tbl,
.probe = k2_sata_init_one,
.remove = k2_sata_remove_one,
.driver.pm = &k2_sata_pm_ops,
};
static int __init k2_sata_init(void)
{
return pci_register_driver(&k2_sata_pci_driver);
}
static void __exit k2_sata_exit(void)
{
pci_unregister_driver(&k2_sata_pci_driver);
}
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);
module_init(k2_sata_init);
module_exit(k2_sata_exit);