Merge branch 'for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata

Pull libata updates from Tejun Heo:

 - Christoph added support for TCG OPAL self encrypting disks

 - Minwoo added support for ATA PASS-THROUGH(32)

 - Linus Walleij removed spurious drvdata assignments in some drivers

 - Support for a few new device and other fixes

* 'for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata: (33 commits)
  sd: add support for TCG OPAL self encrypting disks
  libata: fix build warning from unused goto label
  libata: Support for an ATA PASS-THROUGH(32) command.
  ahci: Add Device ID for ASMedia 1061R and 1062R
  sata_via: Enable optional hotplug on VT6420
  ata: ahci_brcm: Avoid writing to read-only registers
  libata: Add the AHCI_HFLAG_NO_WRITE_TO_RO flag
  libata: Add the AHCI_HFLAG_YES_ALPM flag
  ata: ftide010: fix resource printing
  libata: make the function name in comment match the actual function
  ata: sata_rcar: make of_device_ids const.
  ata: pata_octeon_cf: make of_device_ids const.
  libata: Convert bare printks to pr_cont
  libahci: wrong comments in ahci_do_softreset()
  ata: declare ata_port_info structures as const
  ata: Add driver for Faraday Technology FTIDE010
  ata: Add DT bindings for the Gemini SATA bridge
  ata: Add DT bindings for Faraday Technology FTIDE010
  libata: implement SECURITY PROTOCOL IN/OUT
  libata: factor out a ata_identify_page_supported helper
  ...
This commit is contained in:
Linus Torvalds 2017-07-06 09:41:58 -07:00
commit 109a5db504
36 changed files with 1589 additions and 236 deletions

View file

@ -213,6 +213,16 @@ config SATA_FSL
If unsure, say N.
config SATA_GEMINI
tristate "Gemini SATA bridge support"
depends on PATA_FTIDE010
default ARCH_GEMINI
help
This enabled support for the FTIDE010 to SATA bridge
found in Cortina Systems Gemini platform.
If unsure, say N.
config SATA_AHCI_SEATTLE
tristate "AMD Seattle 6.0Gbps AHCI SATA host controller support"
depends on ARCH_SEATTLE
@ -599,6 +609,17 @@ config PATA_EP93XX
If unsure, say N.
config PATA_FTIDE010
tristate "Faraday Technology FTIDE010 PATA support"
depends on OF
depends on ARM
default ARCH_GEMINI
help
This option enables support for the Faraday FTIDE010
PATA controller found in the Cortina Gemini SoCs.
If unsure, say N.
config PATA_HPT366
tristate "HPT 366/368 PATA support"
depends on PCI

View file

@ -7,6 +7,7 @@ obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o
obj-$(CONFIG_SATA_AHCI_SEATTLE) += ahci_seattle.o libahci.o libahci_platform.o
obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o
obj-$(CONFIG_SATA_FSL) += sata_fsl.o
obj-$(CONFIG_SATA_GEMINI) += sata_gemini.o
obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
@ -60,6 +61,7 @@ obj-$(CONFIG_PATA_CS5536) += pata_cs5536.o
obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o
obj-$(CONFIG_PATA_EFAR) += pata_efar.o
obj-$(CONFIG_PATA_EP93XX) += pata_ep93xx.o
obj-$(CONFIG_PATA_FTIDE010) += pata_ftide010.o
obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o
obj-$(CONFIG_PATA_HPT37X) += pata_hpt37x.o
obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x2n.o

View file

@ -548,6 +548,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */
{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */
{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */
{ PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */
{ PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */
/*
* Samsung SSDs found on some macbooks. NCQ times out if MSI is

View file

@ -248,6 +248,9 @@ enum {
AHCI_HFLAG_MULTI_MSI = 0,
#endif
AHCI_HFLAG_WAKE_BEFORE_STOP = (1 << 22), /* wake before DMA stop */
AHCI_HFLAG_YES_ALPM = (1 << 23), /* force ALPM cap on */
AHCI_HFLAG_NO_WRITE_TO_RO = (1 << 24), /* don't write to read
only registers */
/* ap->flags bits */

View file

@ -39,7 +39,6 @@
#define PIODATA_ENDIAN_SHIFT 6
#define ENDIAN_SWAP_NONE 0
#define ENDIAN_SWAP_FULL 2
#define OVERRIDE_HWINIT BIT(16)
#define SATA_TOP_CTRL_TP_CTRL 0x8
#define SATA_TOP_CTRL_PHY_CTRL 0xc
#define SATA_TOP_CTRL_PHY_CTRL_1 0x0
@ -126,17 +125,13 @@ static inline void brcm_sata_writereg(u32 val, void __iomem *addr)
static void brcm_sata_alpm_init(struct ahci_host_priv *hpriv)
{
struct brcm_ahci_priv *priv = hpriv->plat_data;
u32 bus_ctrl, port_ctrl, host_caps;
u32 port_ctrl, host_caps;
int i;
/* Enable support for ALPM */
bus_ctrl = brcm_sata_readreg(priv->top_ctrl +
SATA_TOP_CTRL_BUS_CTRL);
brcm_sata_writereg(bus_ctrl | OVERRIDE_HWINIT,
priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
host_caps = readl(hpriv->mmio + HOST_CAP);
writel(host_caps | HOST_CAP_ALPM, hpriv->mmio);
brcm_sata_writereg(bus_ctrl, priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
if (!(host_caps & HOST_CAP_ALPM))
hpriv->flags |= AHCI_HFLAG_YES_ALPM;
/*
* Adjust timeout to allow PLL sufficient time to lock while waking
@ -360,6 +355,7 @@ static int brcm_ahci_probe(struct platform_device *pdev)
if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ)
hpriv->flags |= AHCI_HFLAG_NO_NCQ;
hpriv->flags |= AHCI_HFLAG_NO_WRITE_TO_RO;
ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
&ahci_platform_sht);

View file

@ -47,12 +47,14 @@
#define SATA_ECC_DISABLE 0x00020000
#define ECC_DIS_ARMV8_CH2 0x80000000
#define ECC_DIS_LS1088A 0x40000000
enum ahci_qoriq_type {
AHCI_LS1021A,
AHCI_LS1043A,
AHCI_LS2080A,
AHCI_LS1046A,
AHCI_LS1088A,
AHCI_LS2088A,
};
@ -68,6 +70,7 @@ static const struct of_device_id ahci_qoriq_of_match[] = {
{ .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A},
{ .compatible = "fsl,ls2080a-ahci", .data = (void *)AHCI_LS2080A},
{ .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A},
{ .compatible = "fsl,ls1088a-ahci", .data = (void *)AHCI_LS1088A},
{ .compatible = "fsl,ls2088a-ahci", .data = (void *)AHCI_LS2088A},
{},
};
@ -203,6 +206,17 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
break;
case AHCI_LS1088A:
if (!qpriv->ecc_addr)
return -EINVAL;
writel(readl(qpriv->ecc_addr) | ECC_DIS_LS1088A,
qpriv->ecc_addr);
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
if (qpriv->is_dmacoherent)
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
break;
case AHCI_LS2088A:
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);

View file

@ -504,6 +504,11 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
cap &= ~HOST_CAP_FBS;
}
if (!(cap & HOST_CAP_ALPM) && (hpriv->flags & AHCI_HFLAG_YES_ALPM)) {
dev_info(dev, "controller can do ALPM, turning on CAP_ALPM\n");
cap |= HOST_CAP_ALPM;
}
if (hpriv->force_port_map && port_map != hpriv->force_port_map) {
dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
port_map, hpriv->force_port_map);
@ -940,7 +945,8 @@ int ahci_reset_controller(struct ata_host *host)
/* Some registers might be cleared on reset. Restore
* initial values.
*/
ahci_restore_initial_config(host);
if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO))
ahci_restore_initial_config(host);
} else
dev_info(host->dev, "skipping global host reset\n");
@ -1400,7 +1406,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
ata_tf_init(link->device, &tf);
/* issue the first D2H Register FIS */
/* issue the first H2D Register FIS */
msecs = 0;
now = jiffies;
if (time_after(deadline, now))
@ -1417,7 +1423,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
/* spec says at least 5us, but be generous and sleep for 1ms */
ata_msleep(ap, 1);
/* issue the second D2H Register FIS */
/* issue the second H2D Register FIS */
tf.ctl &= ~ATA_SRST;
ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);

View file

@ -2047,6 +2047,110 @@ retry:
return rc;
}
/**
* ata_read_log_page - read a specific log page
* @dev: target device
* @log: log to read
* @page: page to read
* @buf: buffer to store read page
* @sectors: number of sectors to read
*
* Read log page using READ_LOG_EXT command.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0 on success, AC_ERR_* mask otherwise.
*/
unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
u8 page, void *buf, unsigned int sectors)
{
unsigned long ap_flags = dev->link->ap->flags;
struct ata_taskfile tf;
unsigned int err_mask;
bool dma = false;
DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page);
/*
* Return error without actually issuing the command on controllers
* which e.g. lockup on a read log page.
*/
if (ap_flags & ATA_FLAG_NO_LOG_PAGE)
return AC_ERR_DEV;
retry:
ata_tf_init(dev, &tf);
if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id) &&
!(dev->horkage & ATA_HORKAGE_NO_NCQ_LOG)) {
tf.command = ATA_CMD_READ_LOG_DMA_EXT;
tf.protocol = ATA_PROT_DMA;
dma = true;
} else {
tf.command = ATA_CMD_READ_LOG_EXT;
tf.protocol = ATA_PROT_PIO;
dma = false;
}
tf.lbal = log;
tf.lbam = page;
tf.nsect = sectors;
tf.hob_nsect = sectors >> 8;
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
buf, sectors * ATA_SECT_SIZE, 0);
if (err_mask && dma) {
dev->horkage |= ATA_HORKAGE_NO_NCQ_LOG;
ata_dev_warn(dev, "READ LOG DMA EXT failed, trying unqueued\n");
goto retry;
}
DPRINTK("EXIT, err_mask=%x\n", err_mask);
return err_mask;
}
static bool ata_log_supported(struct ata_device *dev, u8 log)
{
struct ata_port *ap = dev->link->ap;
if (ata_read_log_page(dev, ATA_LOG_DIRECTORY, 0, ap->sector_buf, 1))
return false;
return get_unaligned_le16(&ap->sector_buf[log * 2]) ? true : false;
}
static bool ata_identify_page_supported(struct ata_device *dev, u8 page)
{
struct ata_port *ap = dev->link->ap;
unsigned int err, i;
if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE)) {
ata_dev_warn(dev, "ATA Identify Device Log not supported\n");
return false;
}
/*
* Read IDENTIFY DEVICE data log, page 0, to figure out if the page is
* supported.
*/
err = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, 0, ap->sector_buf,
1);
if (err) {
ata_dev_info(dev,
"failed to get Device Identify Log Emask 0x%x\n",
err);
return false;
}
for (i = 0; i < ap->sector_buf[8]; i++) {
if (ap->sector_buf[9 + i] == page)
return true;
}
return false;
}
static int ata_do_link_spd_horkage(struct ata_device *dev)
{
struct ata_link *plink = ata_dev_phys_link(dev);
@ -2094,21 +2198,9 @@ static void ata_dev_config_ncq_send_recv(struct ata_device *dev)
{
struct ata_port *ap = dev->link->ap;
unsigned int err_mask;
int log_index = ATA_LOG_NCQ_SEND_RECV * 2;
u16 log_pages;
err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY,
0, ap->sector_buf, 1);
if (err_mask) {
ata_dev_dbg(dev,
"failed to get Log Directory Emask 0x%x\n",
err_mask);
return;
}
log_pages = get_unaligned_le16(&ap->sector_buf[log_index]);
if (!log_pages) {
ata_dev_warn(dev,
"NCQ Send/Recv Log not supported\n");
if (!ata_log_supported(dev, ATA_LOG_NCQ_SEND_RECV)) {
ata_dev_warn(dev, "NCQ Send/Recv Log not supported\n");
return;
}
err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_SEND_RECV,
@ -2135,19 +2227,8 @@ static void ata_dev_config_ncq_non_data(struct ata_device *dev)
{
struct ata_port *ap = dev->link->ap;
unsigned int err_mask;
int log_index = ATA_LOG_NCQ_NON_DATA * 2;
u16 log_pages;
err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY,
0, ap->sector_buf, 1);
if (err_mask) {
ata_dev_dbg(dev,
"failed to get Log Directory Emask 0x%x\n",
err_mask);
return;
}
log_pages = get_unaligned_le16(&ap->sector_buf[log_index]);
if (!log_pages) {
if (!ata_log_supported(dev, ATA_LOG_NCQ_NON_DATA)) {
ata_dev_warn(dev,
"NCQ Send/Recv Log not supported\n");
return;
@ -2176,7 +2257,7 @@ static void ata_dev_config_ncq_prio(struct ata_device *dev)
}
err_mask = ata_read_log_page(dev,
ATA_LOG_SATA_ID_DEV_DATA,
ATA_LOG_IDENTIFY_DEVICE,
ATA_LOG_SATA_SETTINGS,
ap->sector_buf,
1);
@ -2275,8 +2356,6 @@ static void ata_dev_config_zac(struct ata_device *dev)
struct ata_port *ap = dev->link->ap;
unsigned int err_mask;
u8 *identify_buf = ap->sector_buf;
int log_index = ATA_LOG_SATA_ID_DEV_DATA * 2, i, found = 0;
u16 log_pages;
dev->zac_zones_optimal_open = U32_MAX;
dev->zac_zones_optimal_nonseq = U32_MAX;
@ -2296,44 +2375,7 @@ static void ata_dev_config_zac(struct ata_device *dev)
if (!(dev->flags & ATA_DFLAG_ZAC))
return;
/*
* Read Log Directory to figure out if IDENTIFY DEVICE log
* is supported.
*/
err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY,
0, ap->sector_buf, 1);
if (err_mask) {
ata_dev_info(dev,
"failed to get Log Directory Emask 0x%x\n",
err_mask);
return;
}
log_pages = get_unaligned_le16(&ap->sector_buf[log_index]);
if (log_pages == 0) {
ata_dev_warn(dev,
"ATA Identify Device Log not supported\n");
return;
}
/*
* Read IDENTIFY DEVICE data log, page 0, to figure out
* if page 9 is supported.
*/
err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA, 0,
identify_buf, 1);
if (err_mask) {
ata_dev_info(dev,
"failed to get Device Identify Log Emask 0x%x\n",
err_mask);
return;
}
log_pages = identify_buf[8];
for (i = 0; i < log_pages; i++) {
if (identify_buf[9 + i] == ATA_LOG_ZONED_INFORMATION) {
found++;
break;
}
}
if (!found) {
if (!ata_identify_page_supported(dev, ATA_LOG_ZONED_INFORMATION)) {
ata_dev_warn(dev,
"ATA Zoned Information Log not supported\n");
return;
@ -2342,7 +2384,7 @@ static void ata_dev_config_zac(struct ata_device *dev)
/*
* Read IDENTIFY DEVICE data log, page 9 (Zoned-device information)
*/
err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA,
err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE,
ATA_LOG_ZONED_INFORMATION,
identify_buf, 1);
if (!err_mask) {
@ -2363,6 +2405,37 @@ static void ata_dev_config_zac(struct ata_device *dev)
}
}
static void ata_dev_config_trusted(struct ata_device *dev)
{
struct ata_port *ap = dev->link->ap;
u64 trusted_cap;
unsigned int err;
if (!ata_identify_page_supported(dev, ATA_LOG_SECURITY)) {
ata_dev_warn(dev,
"Security Log not supported\n");
return;
}
err = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, ATA_LOG_SECURITY,
ap->sector_buf, 1);
if (err) {
ata_dev_dbg(dev,
"failed to read Security Log, Emask 0x%x\n", err);
return;
}
trusted_cap = get_unaligned_le64(&ap->sector_buf[40]);
if (!(trusted_cap & (1ULL << 63))) {
ata_dev_dbg(dev,
"Trusted Computing capability qword not valid!\n");
return;
}
if (trusted_cap & (1 << 0))
dev->flags |= ATA_DFLAG_TRUSTED;
}
/**
* ata_dev_configure - Configure the specified ATA/ATAPI device
* @dev: Target device to configure
@ -2571,7 +2644,7 @@ int ata_dev_configure(struct ata_device *dev)
dev->flags |= ATA_DFLAG_DEVSLP;
err_mask = ata_read_log_page(dev,
ATA_LOG_SATA_ID_DEV_DATA,
ATA_LOG_IDENTIFY_DEVICE,
ATA_LOG_SATA_SETTINGS,
sata_setting,
1);
@ -2587,7 +2660,8 @@ int ata_dev_configure(struct ata_device *dev)
}
ata_dev_config_sense_reporting(dev);
ata_dev_config_zac(dev);
dev->cdb_len = 16;
ata_dev_config_trusted(dev);
dev->cdb_len = 32;
}
/* ATAPI-specific feature tests */

View file

@ -1487,70 +1487,6 @@ static const char *ata_err_string(unsigned int err_mask)
return "unknown error";
}
/**
* ata_read_log_page - read a specific log page
* @dev: target device
* @log: log to read
* @page: page to read
* @buf: buffer to store read page
* @sectors: number of sectors to read
*
* Read log page using READ_LOG_EXT command.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0 on success, AC_ERR_* mask otherwise.
*/
unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
u8 page, void *buf, unsigned int sectors)
{
unsigned long ap_flags = dev->link->ap->flags;
struct ata_taskfile tf;
unsigned int err_mask;
bool dma = false;
DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page);
/*
* Return error without actually issuing the command on controllers
* which e.g. lockup on a read log page.
*/
if (ap_flags & ATA_FLAG_NO_LOG_PAGE)
return AC_ERR_DEV;
retry:
ata_tf_init(dev, &tf);
if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id) &&
!(dev->horkage & ATA_HORKAGE_NO_NCQ_LOG)) {
tf.command = ATA_CMD_READ_LOG_DMA_EXT;
tf.protocol = ATA_PROT_DMA;
dma = true;
} else {
tf.command = ATA_CMD_READ_LOG_EXT;
tf.protocol = ATA_PROT_PIO;
dma = false;
}
tf.lbal = log;
tf.lbam = page;
tf.nsect = sectors;
tf.hob_nsect = sectors >> 8;
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
buf, sectors * ATA_SECT_SIZE, 0);
if (err_mask && dma) {
dev->horkage |= ATA_HORKAGE_NO_NCQ_LOG;
ata_dev_warn(dev, "READ LOG DMA EXT failed, trying unqueued\n");
goto retry;
}
DPRINTK("EXIT, err_mask=%x\n", err_mask);
return err_mask;
}
/**
* ata_eh_read_log_10h - Read log page 10h for NCQ error details
* @dev: Device to read log page 10h from

View file

@ -903,32 +903,32 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf)
{
u8 stat = tf->command, err = tf->feature;
printk(KERN_WARNING "ata%u: status=0x%02x { ", id, stat);
pr_warn("ata%u: status=0x%02x { ", id, stat);
if (stat & ATA_BUSY) {
printk("Busy }\n"); /* Data is not valid in this case */
pr_cont("Busy }\n"); /* Data is not valid in this case */
} else {
if (stat & ATA_DRDY) printk("DriveReady ");
if (stat & ATA_DF) printk("DeviceFault ");
if (stat & ATA_DSC) printk("SeekComplete ");
if (stat & ATA_DRQ) printk("DataRequest ");
if (stat & ATA_CORR) printk("CorrectedError ");
if (stat & ATA_SENSE) printk("Sense ");
if (stat & ATA_ERR) printk("Error ");
printk("}\n");
if (stat & ATA_DRDY) pr_cont("DriveReady ");
if (stat & ATA_DF) pr_cont("DeviceFault ");
if (stat & ATA_DSC) pr_cont("SeekComplete ");
if (stat & ATA_DRQ) pr_cont("DataRequest ");
if (stat & ATA_CORR) pr_cont("CorrectedError ");
if (stat & ATA_SENSE) pr_cont("Sense ");
if (stat & ATA_ERR) pr_cont("Error ");
pr_cont("}\n");
if (err) {
printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err);
if (err & ATA_ABORTED) printk("DriveStatusError ");
pr_warn("ata%u: error=0x%02x { ", id, err);
if (err & ATA_ABORTED) pr_cont("DriveStatusError ");
if (err & ATA_ICRC) {
if (err & ATA_ABORTED)
printk("BadCRC ");
else printk("Sector ");
pr_cont("BadCRC ");
else pr_cont("Sector ");
}
if (err & ATA_UNC) printk("UncorrectableError ");
if (err & ATA_IDNF) printk("SectorIdNotFound ");
if (err & ATA_TRK0NF) printk("TrackZeroNotFound ");
if (err & ATA_AMNF) printk("AddrMarkNotFound ");
printk("}\n");
if (err & ATA_UNC) pr_cont("UncorrectableError ");
if (err & ATA_IDNF) pr_cont("SectorIdNotFound ");
if (err & ATA_TRK0NF) pr_cont("TrackZeroNotFound ");
if (err & ATA_AMNF) pr_cont("AddrMarkNotFound ");
pr_cont("}\n");
}
}
}
@ -1059,8 +1059,7 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
translate_done:
if (verbose)
printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x "
"to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n",
pr_err("ata%u: translated ATA stat/err 0x%02x/%02x to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n",
id, drv_stat, drv_err, *sk, *asc, *ascq);
return;
}
@ -1322,6 +1321,9 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
blk_queue_flush_queueable(q, false);
if (dev->flags & ATA_DFLAG_TRUSTED)
sdev->security_supported = 1;
dev->sdev = sdev;
return 0;
}
@ -3127,7 +3129,7 @@ ata_scsi_map_proto(u8 byte1)
* ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile
* @qc: command structure to be initialized
*
* Handles either 12 or 16-byte versions of the CDB.
* Handles either 12, 16, or 32-byte versions of the CDB.
*
* RETURNS:
* Zero on success, non-zero on failure.
@ -3139,13 +3141,19 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
struct ata_device *dev = qc->dev;
const u8 *cdb = scmd->cmnd;
u16 fp;
u16 cdb_offset = 0;
if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) {
/* 7Fh variable length cmd means a ata pass-thru(32) */
if (cdb[0] == VARIABLE_LENGTH_CMD)
cdb_offset = 9;
tf->protocol = ata_scsi_map_proto(cdb[1 + cdb_offset]);
if (tf->protocol == ATA_PROT_UNKNOWN) {
fp = 1;
goto invalid_fld;
}
if (ata_is_ncq(tf->protocol) && (cdb[2] & 0x3) == 0)
if (ata_is_ncq(tf->protocol) && (cdb[2 + cdb_offset] & 0x3) == 0)
tf->protocol = ATA_PROT_NCQ_NODATA;
/* enable LBA */
@ -3181,7 +3189,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
tf->lbah = cdb[12];
tf->device = cdb[13];
tf->command = cdb[14];
} else {
} else if (cdb[0] == ATA_12) {
/*
* 12-byte CDB - incapable of extended commands.
*/
@ -3194,6 +3202,30 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
tf->lbah = cdb[7];
tf->device = cdb[8];
tf->command = cdb[9];
} else {
/*
* 32-byte CDB - may contain extended command fields.
*
* If that is the case, copy the upper byte register values.
*/
if (cdb[10] & 0x01) {
tf->hob_feature = cdb[20];
tf->hob_nsect = cdb[22];
tf->hob_lbal = cdb[16];
tf->hob_lbam = cdb[15];
tf->hob_lbah = cdb[14];
tf->flags |= ATA_TFLAG_LBA48;
} else
tf->flags &= ~ATA_TFLAG_LBA48;
tf->feature = cdb[21];
tf->nsect = cdb[23];
tf->lbal = cdb[19];
tf->lbam = cdb[18];
tf->lbah = cdb[17];
tf->device = cdb[24];
tf->command = cdb[25];
tf->auxiliary = get_unaligned_be32(&cdb[28]);
}
/* For NCQ commands copy the tag value */
@ -3564,6 +3596,11 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf)
dev->class == ATA_DEV_ZAC)
supported = 3;
break;
case SECURITY_PROTOCOL_IN:
case SECURITY_PROTOCOL_OUT:
if (dev->flags & ATA_DFLAG_TRUSTED)
supported = 3;
break;
default:
break;
}
@ -3910,7 +3947,7 @@ static int ata_mselect_control(struct ata_queued_cmd *qc,
}
/**
* ata_scsiop_mode_select - Simulate MODE SELECT 6, 10 commands
* ata_scsi_mode_select_xlat - Simulate MODE SELECT 6, 10 commands
* @qc: Storage for translated ATA taskfile
*
* Converts a MODE SELECT command to an ATA SET FEATURES taskfile.
@ -4068,6 +4105,99 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc)
return 1;
}
static u8 ata_scsi_trusted_op(u32 len, bool send, bool dma)
{
if (len == 0)
return ATA_CMD_TRUSTED_NONDATA;
else if (send)
return dma ? ATA_CMD_TRUSTED_SND_DMA : ATA_CMD_TRUSTED_SND;
else
return dma ? ATA_CMD_TRUSTED_RCV_DMA : ATA_CMD_TRUSTED_RCV;
}
static unsigned int ata_scsi_security_inout_xlat(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *scmd = qc->scsicmd;
const u8 *cdb = scmd->cmnd;
struct ata_taskfile *tf = &qc->tf;
u8 secp = cdb[1];
bool send = (cdb[0] == SECURITY_PROTOCOL_OUT);
u16 spsp = get_unaligned_be16(&cdb[2]);
u32 len = get_unaligned_be32(&cdb[6]);
bool dma = !(qc->dev->flags & ATA_DFLAG_PIO);
/*
* We don't support the ATA "security" protocol.
*/
if (secp == 0xef) {
ata_scsi_set_invalid_field(qc->dev, scmd, 1, 0);
return 1;
}
if (cdb[4] & 7) { /* INC_512 */
if (len > 0xffff) {
ata_scsi_set_invalid_field(qc->dev, scmd, 6, 0);
return 1;
}
} else {
if (len > 0x01fffe00) {
ata_scsi_set_invalid_field(qc->dev, scmd, 6, 0);
return 1;
}
/* convert to the sector-based ATA addressing */
len = (len + 511) / 512;
}
tf->protocol = dma ? ATA_PROT_DMA : ATA_PROT_PIO;
tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR | ATA_TFLAG_LBA;
if (send)
tf->flags |= ATA_TFLAG_WRITE;
tf->command = ata_scsi_trusted_op(len, send, dma);
tf->feature = secp;
tf->lbam = spsp & 0xff;
tf->lbah = spsp >> 8;
if (len) {
tf->nsect = len & 0xff;
tf->lbal = len >> 8;
} else {
if (!send)
tf->lbah = (1 << 7);
}
ata_qc_set_pc_nbytes(qc);
return 0;
}
/**
* ata_scsi_var_len_cdb_xlat - SATL variable length CDB to Handler
* @qc: Command to be translated
*
* Translate a SCSI variable length CDB to specified commands.
* It checks a service action value in CDB to call corresponding handler.
*
* RETURNS:
* Zero on success, non-zero on failure
*
*/
static unsigned int ata_scsi_var_len_cdb_xlat(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *scmd = qc->scsicmd;
const u8 *cdb = scmd->cmnd;
const u16 sa = get_unaligned_be16(&cdb[8]);
/*
* if service action represents a ata pass-thru(32) command,
* then pass it to ata_scsi_pass_thru handler.
*/
if (sa == ATA_32)
return ata_scsi_pass_thru(qc);
/* unsupported service action */
return 1;
}
/**
* ata_get_xlat_func - check if SCSI to ATA translation is possible
* @dev: ATA device
@ -4108,6 +4238,9 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
case ATA_16:
return ata_scsi_pass_thru;
case VARIABLE_LENGTH_CMD:
return ata_scsi_var_len_cdb_xlat;
case MODE_SELECT:
case MODE_SELECT_10:
return ata_scsi_mode_select_xlat;
@ -4119,6 +4252,12 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
case ZBC_OUT:
return ata_scsi_zbc_out_xlat;
case SECURITY_PROTOCOL_IN:
case SECURITY_PROTOCOL_OUT:
if (!(dev->flags & ATA_DFLAG_TRUSTED))
break;
return ata_scsi_security_inout_xlat;
case START_STOP:
return ata_scsi_start_stop_xlat;
}
@ -4386,7 +4525,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
shost->max_id = 16;
shost->max_lun = 1;
shost->max_channel = 1;
shost->max_cmd_len = 16;
shost->max_cmd_len = 32;
/* Schedule policy is determined by ->qc_defer()
* callback and it needs to see every deferred qc.

View file

@ -716,24 +716,10 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
if (PageHighMem(page)) {
unsigned long flags;
/* FIXME: use a bounce buffer */
local_irq_save(flags);
buf = kmap_atomic(page);
/* do the actual data transfer */
ap->ops->sff_data_xfer(qc, buf + offset, qc->sect_size,
do_write);
kunmap_atomic(buf);
local_irq_restore(flags);
} else {
buf = page_address(page);
ap->ops->sff_data_xfer(qc, buf + offset, qc->sect_size,
do_write);
}
/* do the actual data transfer */
buf = kmap_atomic(page);
ap->ops->sff_data_xfer(qc, buf + offset, qc->sect_size, do_write);
kunmap_atomic(buf);
if (!do_write && !PageSlab(page))
flush_dcache_page(page);
@ -861,24 +847,10 @@ next_sg:
DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
if (PageHighMem(page)) {
unsigned long flags;
/* FIXME: use bounce buffer */
local_irq_save(flags);
buf = kmap_atomic(page);
/* do the actual data transfer */
consumed = ap->ops->sff_data_xfer(qc, buf + offset,
count, rw);
kunmap_atomic(buf);
local_irq_restore(flags);
} else {
buf = page_address(page);
consumed = ap->ops->sff_data_xfer(qc, buf + offset,
count, rw);
}
/* do the actual data transfer */
buf = kmap_atomic(page);
consumed = ap->ops->sff_data_xfer(qc, buf + offset, count, rw);
kunmap_atomic(buf);
bytes -= min(bytes, consumed);
qc->curbytes += count;

View file

@ -98,6 +98,8 @@ extern struct ata_port *ata_port_alloc(struct ata_host *host);
extern const char *sata_spd_string(unsigned int spd);
extern int ata_port_probe(struct ata_port *ap);
extern void __ata_port_probe(struct ata_port *ap);
extern unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
u8 page, void *buf, unsigned int sectors);
#define to_ata_port(d) container_of(d, struct ata_port, tdev)
@ -160,8 +162,6 @@ extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
unsigned int action);
extern void ata_eh_done(struct ata_link *link, struct ata_device *dev,
unsigned int action);
extern unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
u8 page, void *buf, unsigned int sectors);
extern void ata_eh_autopsy(struct ata_port *ap);
const char *ata_get_cmd_descript(u8 command);
extern void ata_eh_report(struct ata_port *ap);

View file

@ -1597,8 +1597,6 @@ static int bfin_atapi_probe(struct platform_device *pdev)
return -ENODEV;
}
platform_set_drvdata(pdev, host);
return 0;
}

View file

@ -944,7 +944,6 @@ static int ep93xx_pata_probe(struct platform_device *pdev)
goto err_rel_gpio;
}
platform_set_drvdata(pdev, drv_data);
drv_data->pdev = pdev;
drv_data->ide_base = ide_base;
drv_data->udma_in_phys = mem_res->start + IDEUDMADATAIN;

567
drivers/ata/pata_ftide010.c Normal file
View file

@ -0,0 +1,567 @@
/*
* Faraday Technology FTIDE010 driver
* Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
*
* Includes portions of the SL2312/SL3516/Gemini PATA driver
* Copyright (C) 2003 StorLine, Inc <jason@storlink.com.tw>
* Copyright (C) 2009 Janos Laube <janos.dev@gmail.com>
* Copyright (C) 2010 Frederic Pecourt <opengemini@free.fr>
* Copyright (C) 2011 Tobias Waldvogel <tobias.waldvogel@gmail.com>
*/
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/libata.h>
#include <linux/bitops.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/clk.h>
#include "sata_gemini.h"
#define DRV_NAME "pata_ftide010"
/**
* struct ftide010 - state container for the Faraday FTIDE010
* @dev: pointer back to the device representing this controller
* @base: remapped I/O space address
* @pclk: peripheral clock for the IDE block
* @host: pointer to the ATA host for this device
* @master_cbl: master cable type
* @slave_cbl: slave cable type
* @sg: Gemini SATA bridge pointer, if running on the Gemini
* @master_to_sata0: Gemini SATA bridge: the ATA master is connected
* to the SATA0 bridge
* @slave_to_sata0: Gemini SATA bridge: the ATA slave is connected
* to the SATA0 bridge
* @master_to_sata1: Gemini SATA bridge: the ATA master is connected
* to the SATA1 bridge
* @slave_to_sata1: Gemini SATA bridge: the ATA slave is connected
* to the SATA1 bridge
*/
struct ftide010 {
struct device *dev;
void __iomem *base;
struct clk *pclk;
struct ata_host *host;
unsigned int master_cbl;
unsigned int slave_cbl;
/* Gemini-specific properties */
struct sata_gemini *sg;
bool master_to_sata0;
bool slave_to_sata0;
bool master_to_sata1;
bool slave_to_sata1;
};
#define FTIDE010_DMA_REG 0x00
#define FTIDE010_DMA_STATUS 0x02
#define FTIDE010_IDE_BMDTPR 0x04
#define FTIDE010_IDE_DEVICE_ID 0x08
#define FTIDE010_PIO_TIMING 0x10
#define FTIDE010_MWDMA_TIMING 0x11
#define FTIDE010_UDMA_TIMING0 0x12 /* Master */
#define FTIDE010_UDMA_TIMING1 0x13 /* Slave */
#define FTIDE010_CLK_MOD 0x14
/* These registers are mapped directly to the IDE registers */
#define FTIDE010_CMD_DATA 0x20
#define FTIDE010_ERROR_FEATURES 0x21
#define FTIDE010_NSECT 0x22
#define FTIDE010_LBAL 0x23
#define FTIDE010_LBAM 0x24
#define FTIDE010_LBAH 0x25
#define FTIDE010_DEVICE 0x26
#define FTIDE010_STATUS_COMMAND 0x27
#define FTIDE010_ALTSTAT_CTRL 0x36
/* Set this bit for UDMA mode 5 and 6 */
#define FTIDE010_UDMA_TIMING_MODE_56 BIT(7)
/* 0 = 50 MHz, 1 = 66 MHz */
#define FTIDE010_CLK_MOD_DEV0_CLK_SEL BIT(0)
#define FTIDE010_CLK_MOD_DEV1_CLK_SEL BIT(1)
/* Enable UDMA on a device */
#define FTIDE010_CLK_MOD_DEV0_UDMA_EN BIT(4)
#define FTIDE010_CLK_MOD_DEV1_UDMA_EN BIT(5)
static struct scsi_host_template pata_ftide010_sht = {
ATA_BMDMA_SHT(DRV_NAME),
};
/*
* Bus timings
*
* The unit of the below required timings is two clock periods of the ATA
* reference clock which is 30 nanoseconds per unit at 66MHz and 20
* nanoseconds per unit at 50 MHz. The PIO timings assume 33MHz speed for
* PIO.
*
* pio_active_time: array of 5 elements for T2 timing for Mode 0,
* 1, 2, 3 and 4. Range 0..15.
* pio_recovery_time: array of 5 elements for T2l timing for Mode 0,
* 1, 2, 3 and 4. Range 0..15.
* mdma_50_active_time: array of 4 elements for Td timing for multi
* word DMA, Mode 0, 1, and 2 at 50 MHz. Range 0..15.
* mdma_50_recovery_time: array of 4 elements for Tk timing for
* multi word DMA, Mode 0, 1 and 2 at 50 MHz. Range 0..15.
* mdma_66_active_time: array of 4 elements for Td timing for multi
* word DMA, Mode 0, 1 and 2 at 66 MHz. Range 0..15.
* mdma_66_recovery_time: array of 4 elements for Tk timing for
* multi word DMA, Mode 0, 1 and 2 at 66 MHz. Range 0..15.
* udma_50_setup_time: array of 4 elements for Tvds timing for ultra
* DMA, Mode 0, 1, 2, 3, 4 and 5 at 50 MHz. Range 0..7.
* udma_50_hold_time: array of 4 elements for Tdvh timing for
* multi word DMA, Mode 0, 1, 2, 3, 4 and 5 at 50 MHz, Range 0..7.
* udma_66_setup_time: array of 4 elements for Tvds timing for multi
* word DMA, Mode 0, 1, 2, 3, 4, 5 and 6 at 66 MHz. Range 0..7.
* udma_66_hold_time: array of 4 elements for Tdvh timing for
* multi word DMA, Mode 0, 1, 2, 3, 4, 5 and 6 at 66 MHz. Range 0..7.
*/
static const u8 pio_active_time[5] = {10, 10, 10, 3, 3};
static const u8 pio_recovery_time[5] = {10, 3, 1, 3, 1};
static const u8 mwdma_50_active_time[3] = {6, 2, 2};
static const u8 mwdma_50_recovery_time[3] = {6, 2, 1};
static const u8 mwdma_66_active_time[3] = {8, 3, 3};
static const u8 mwdma_66_recovery_time[3] = {8, 2, 1};
static const u8 udma_50_setup_time[6] = {3, 3, 2, 2, 1, 1};
static const u8 udma_50_hold_time[6] = {3, 1, 1, 1, 1, 1};
static const u8 udma_66_setup_time[7] = {4, 4, 3, 2, };
static const u8 udma_66_hold_time[7] = {};
/*
* We set 66 MHz for all MWDMA modes
*/
static const bool set_mdma_66_mhz[] = { true, true, true, true };
/*
* We set 66 MHz for UDMA modes 3, 4 and 6 and no others
*/
static const bool set_udma_66_mhz[] = { false, false, false, true, true, false, true };
static void ftide010_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
struct ftide010 *ftide = ap->host->private_data;
u8 speed = adev->dma_mode;
u8 devno = adev->devno & 1;
u8 udma_en_mask;
u8 f66m_en_mask;
u8 clkreg;
u8 timreg;
u8 i;
/* Target device 0 (master) or 1 (slave) */
if (!devno) {
udma_en_mask = FTIDE010_CLK_MOD_DEV0_UDMA_EN;
f66m_en_mask = FTIDE010_CLK_MOD_DEV0_CLK_SEL;
} else {
udma_en_mask = FTIDE010_CLK_MOD_DEV1_UDMA_EN;
f66m_en_mask = FTIDE010_CLK_MOD_DEV1_CLK_SEL;
}
clkreg = readb(ftide->base + FTIDE010_CLK_MOD);
clkreg &= ~udma_en_mask;
clkreg &= ~f66m_en_mask;
if (speed & XFER_UDMA_0) {
i = speed & ~XFER_UDMA_0;
dev_dbg(ftide->dev, "set UDMA mode %02x, index %d\n",
speed, i);
clkreg |= udma_en_mask;
if (set_udma_66_mhz[i]) {
clkreg |= f66m_en_mask;
timreg = udma_66_setup_time[i] << 4 |
udma_66_hold_time[i];
} else {
timreg = udma_50_setup_time[i] << 4 |
udma_50_hold_time[i];
}
/* A special bit needs to be set for modes 5 and 6 */
if (i >= 5)
timreg |= FTIDE010_UDMA_TIMING_MODE_56;
dev_dbg(ftide->dev, "UDMA write clkreg = %02x, timreg = %02x\n",
clkreg, timreg);
writeb(clkreg, ftide->base + FTIDE010_CLK_MOD);
writeb(timreg, ftide->base + FTIDE010_UDMA_TIMING0 + devno);
} else {
i = speed & ~XFER_MW_DMA_0;
dev_dbg(ftide->dev, "set MWDMA mode %02x, index %d\n",
speed, i);
if (set_mdma_66_mhz[i]) {
clkreg |= f66m_en_mask;
timreg = mwdma_66_active_time[i] << 4 |
mwdma_66_recovery_time[i];
} else {
timreg = mwdma_50_active_time[i] << 4 |
mwdma_50_recovery_time[i];
}
dev_dbg(ftide->dev,
"MWDMA write clkreg = %02x, timreg = %02x\n",
clkreg, timreg);
/* This will affect all devices */
writeb(clkreg, ftide->base + FTIDE010_CLK_MOD);
writeb(timreg, ftide->base + FTIDE010_MWDMA_TIMING);
}
/*
* Store the current device (master or slave) in ap->private_data
* so that .qc_issue() can detect if this changes and reprogram
* the DMA settings.
*/
ap->private_data = adev;
return;
}
static void ftide010_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
struct ftide010 *ftide = ap->host->private_data;
u8 pio = adev->pio_mode - XFER_PIO_0;
dev_dbg(ftide->dev, "set PIO mode %02x, index %d\n",
adev->pio_mode, pio);
writeb(pio_active_time[pio] << 4 | pio_recovery_time[pio],
ftide->base + FTIDE010_PIO_TIMING);
}
/*
* We implement our own qc_issue() callback since we may need to set up
* the timings differently for master and slave transfers: the CLK_MOD_REG
* and MWDMA_TIMING_REG is shared between master and slave, so reprogramming
* this may be necessary.
*/
static unsigned int ftide010_qc_issue(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct ata_device *adev = qc->dev;
/*
* If the device changed, i.e. slave->master, master->slave,
* then set up the DMA mode again so we are sure the timings
* are correct.
*/
if (adev != ap->private_data && ata_dma_enabled(adev))
ftide010_set_dmamode(ap, adev);
return ata_bmdma_qc_issue(qc);
}
static struct ata_port_operations pata_ftide010_port_ops = {
.inherits = &ata_bmdma_port_ops,
.set_dmamode = ftide010_set_dmamode,
.set_piomode = ftide010_set_piomode,
.qc_issue = ftide010_qc_issue,
};
static struct ata_port_info ftide010_port_info[] = {
{
.flags = ATA_FLAG_SLAVE_POSS,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.pio_mask = ATA_PIO4,
.port_ops = &pata_ftide010_port_ops,
},
};
#if IS_ENABLED(CONFIG_SATA_GEMINI)
static int pata_ftide010_gemini_port_start(struct ata_port *ap)
{
struct ftide010 *ftide = ap->host->private_data;
struct device *dev = ftide->dev;
struct sata_gemini *sg = ftide->sg;
int bridges = 0;
int ret;
ret = ata_bmdma_port_start(ap);
if (ret)
return ret;
if (ftide->master_to_sata0) {
dev_info(dev, "SATA0 (master) start\n");
ret = gemini_sata_start_bridge(sg, 0);
if (!ret)
bridges++;
}
if (ftide->master_to_sata1) {
dev_info(dev, "SATA1 (master) start\n");
ret = gemini_sata_start_bridge(sg, 1);
if (!ret)
bridges++;
}
/* Avoid double-starting */
if (ftide->slave_to_sata0 && !ftide->master_to_sata0) {
dev_info(dev, "SATA0 (slave) start\n");
ret = gemini_sata_start_bridge(sg, 0);
if (!ret)
bridges++;
}
/* Avoid double-starting */
if (ftide->slave_to_sata1 && !ftide->master_to_sata1) {
dev_info(dev, "SATA1 (slave) start\n");
ret = gemini_sata_start_bridge(sg, 1);
if (!ret)
bridges++;
}
dev_info(dev, "brought %d bridges online\n", bridges);
return (bridges > 0) ? 0 : -EINVAL; // -ENODEV;
}
static void pata_ftide010_gemini_port_stop(struct ata_port *ap)
{
struct ftide010 *ftide = ap->host->private_data;
struct device *dev = ftide->dev;
struct sata_gemini *sg = ftide->sg;
if (ftide->master_to_sata0) {
dev_info(dev, "SATA0 (master) stop\n");
gemini_sata_stop_bridge(sg, 0);
}
if (ftide->master_to_sata1) {
dev_info(dev, "SATA1 (master) stop\n");
gemini_sata_stop_bridge(sg, 1);
}
/* Avoid double-stopping */
if (ftide->slave_to_sata0 && !ftide->master_to_sata0) {
dev_info(dev, "SATA0 (slave) stop\n");
gemini_sata_stop_bridge(sg, 0);
}
/* Avoid double-stopping */
if (ftide->slave_to_sata1 && !ftide->master_to_sata1) {
dev_info(dev, "SATA1 (slave) stop\n");
gemini_sata_stop_bridge(sg, 1);
}
}
static int pata_ftide010_gemini_cable_detect(struct ata_port *ap)
{
struct ftide010 *ftide = ap->host->private_data;
/*
* Return the master cable, I have no clue how to return a different
* cable for the slave than for the master.
*/
return ftide->master_cbl;
}
static int pata_ftide010_gemini_init(struct ftide010 *ftide,
bool is_ata1)
{
struct device *dev = ftide->dev;
struct sata_gemini *sg;
enum gemini_muxmode muxmode;
/* Look up SATA bridge */
sg = gemini_sata_bridge_get();
if (IS_ERR(sg))
return PTR_ERR(sg);
ftide->sg = sg;
muxmode = gemini_sata_get_muxmode(sg);
/* Special ops */
pata_ftide010_port_ops.port_start =
pata_ftide010_gemini_port_start;
pata_ftide010_port_ops.port_stop =
pata_ftide010_gemini_port_stop;
pata_ftide010_port_ops.cable_detect =
pata_ftide010_gemini_cable_detect;
/* Flag port as SATA-capable */
if (gemini_sata_bridge_enabled(sg, is_ata1))
ftide010_port_info[0].flags |= ATA_FLAG_SATA;
/*
* We assume that a simple 40-wire cable is used in the PATA mode.
* if you're adding a system using the PATA interface, make sure
* the right cable is set up here, it might be necessary to use
* special hardware detection or encode the cable type in the device
* tree with special properties.
*/
if (!is_ata1) {
switch (muxmode) {
case GEMINI_MUXMODE_0:
ftide->master_cbl = ATA_CBL_SATA;
ftide->slave_cbl = ATA_CBL_PATA40;
ftide->master_to_sata0 = true;
break;
case GEMINI_MUXMODE_1:
ftide->master_cbl = ATA_CBL_SATA;
ftide->slave_cbl = ATA_CBL_NONE;
ftide->master_to_sata0 = true;
break;
case GEMINI_MUXMODE_2:
ftide->master_cbl = ATA_CBL_PATA40;
ftide->slave_cbl = ATA_CBL_PATA40;
break;
case GEMINI_MUXMODE_3:
ftide->master_cbl = ATA_CBL_SATA;
ftide->slave_cbl = ATA_CBL_SATA;
ftide->master_to_sata0 = true;
ftide->slave_to_sata1 = true;
break;
}
} else {
switch (muxmode) {
case GEMINI_MUXMODE_0:
ftide->master_cbl = ATA_CBL_SATA;
ftide->slave_cbl = ATA_CBL_NONE;
ftide->master_to_sata1 = true;
break;
case GEMINI_MUXMODE_1:
ftide->master_cbl = ATA_CBL_SATA;
ftide->slave_cbl = ATA_CBL_PATA40;
ftide->master_to_sata1 = true;
break;
case GEMINI_MUXMODE_2:
ftide->master_cbl = ATA_CBL_SATA;
ftide->slave_cbl = ATA_CBL_SATA;
ftide->slave_to_sata0 = true;
ftide->master_to_sata1 = true;
break;
case GEMINI_MUXMODE_3:
ftide->master_cbl = ATA_CBL_PATA40;
ftide->slave_cbl = ATA_CBL_PATA40;
break;
}
}
dev_info(dev, "set up Gemini PATA%d\n", is_ata1);
return 0;
}
#else
static int pata_ftide010_gemini_init(struct ftide010 *ftide,
bool is_ata1)
{
return -ENOTSUPP;
}
#endif
static int pata_ftide010_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
const struct ata_port_info pi = ftide010_port_info[0];
const struct ata_port_info *ppi[] = { &pi, NULL };
struct ftide010 *ftide;
struct resource *res;
int irq;
int ret;
int i;
ftide = devm_kzalloc(dev, sizeof(*ftide), GFP_KERNEL);
if (!ftide)
return -ENOMEM;
ftide->dev = dev;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
ftide->base = devm_ioremap_resource(dev, res);
if (IS_ERR(ftide->base))
return PTR_ERR(ftide->base);
ftide->pclk = devm_clk_get(dev, "PCLK");
if (!IS_ERR(ftide->pclk)) {
ret = clk_prepare_enable(ftide->pclk);
if (ret) {
dev_err(dev, "failed to enable PCLK\n");
return ret;
}
}
/* Some special Cortina Gemini init, if needed */
if (of_device_is_compatible(np, "cortina,gemini-pata")) {
/*
* We need to know which instance is probing (the
* Gemini has two instances of FTIDE010) and we do
* this simply by looking at the physical base
* address, which is 0x63400000 for ATA1, else we
* are ATA0. This will also set up the cable types.
*/
ret = pata_ftide010_gemini_init(ftide,
(res->start == 0x63400000));
if (ret)
goto err_dis_clk;
} else {
/* Else assume we are connected using PATA40 */
ftide->master_cbl = ATA_CBL_PATA40;
ftide->slave_cbl = ATA_CBL_PATA40;
}
ftide->host = ata_host_alloc_pinfo(dev, ppi, 1);
if (!ftide->host) {
ret = -ENOMEM;
goto err_dis_clk;
}
ftide->host->private_data = ftide;
for (i = 0; i < ftide->host->n_ports; i++) {
struct ata_port *ap = ftide->host->ports[i];
struct ata_ioports *ioaddr = &ap->ioaddr;
ioaddr->bmdma_addr = ftide->base + FTIDE010_DMA_REG;
ioaddr->cmd_addr = ftide->base + FTIDE010_CMD_DATA;
ioaddr->ctl_addr = ftide->base + FTIDE010_ALTSTAT_CTRL;
ioaddr->altstatus_addr = ftide->base + FTIDE010_ALTSTAT_CTRL;
ata_sff_std_ports(ioaddr);
}
dev_info(dev, "device ID %08x, irq %d, reg %pR\n",
readl(ftide->base + FTIDE010_IDE_DEVICE_ID), irq, res);
ret = ata_host_activate(ftide->host, irq, ata_bmdma_interrupt,
0, &pata_ftide010_sht);
if (ret)
goto err_dis_clk;
return 0;
err_dis_clk:
if (!IS_ERR(ftide->pclk))
clk_disable_unprepare(ftide->pclk);
return ret;
}
static int pata_ftide010_remove(struct platform_device *pdev)
{
struct ata_host *host = platform_get_drvdata(pdev);
struct ftide010 *ftide = host->private_data;
ata_host_detach(ftide->host);
if (!IS_ERR(ftide->pclk))
clk_disable_unprepare(ftide->pclk);
return 0;
}
static const struct of_device_id pata_ftide010_of_match[] = {
{
.compatible = "faraday,ftide010",
},
{},
};
static struct platform_driver pata_ftide010_driver = {
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(pata_ftide010_of_match),
},
.probe = pata_ftide010_probe,
.remove = pata_ftide010_remove,
};
module_platform_driver(pata_ftide010_driver);
MODULE_AUTHOR("Linus Walleij <[email protected]>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);

View file

@ -1038,7 +1038,7 @@ static void octeon_cf_shutdown(struct device *dev)
}
}
static struct of_device_id octeon_cf_match[] = {
static const struct of_device_id octeon_cf_match[] = {
{
.compatible = "cavium,ebt3000-compact-flash",
},

View file

@ -148,8 +148,6 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
if (!ah)
return -ENOMEM;
platform_set_drvdata(pdev, ah);
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;

View file

@ -292,7 +292,7 @@ static struct ata_port_operations rdc_pata_ops = {
.prereset = rdc_pata_prereset,
};
static struct ata_port_info rdc_port_info = {
static const struct ata_port_info rdc_port_info = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,

View file

@ -582,8 +582,6 @@ static int __init pata_s3c_probe(struct platform_device *pdev)
/* Set endianness and enable the interface */
pata_s3c_hwinit(info, pdata);
platform_set_drvdata(pdev, host);
ret = ata_host_activate(host, info->irq,
info->irq ? pata_s3c_irq : NULL,
0, &pata_s3c_sht);

View file

@ -81,7 +81,7 @@ static struct ata_port_operations sch_pata_ops = {
.set_dmamode = sch_set_dmamode,
};
static struct ata_port_info sch_port_info = {
static const struct ata_port_info sch_port_info = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,

View file

@ -1285,7 +1285,6 @@ static int sata_dwc_probe(struct platform_device *ofdev)
if (err)
dev_err(&ofdev->dev, "failed to activate host");
dev_set_drvdata(&ofdev->dev, host);
return 0;
error_out:

View file

@ -1523,8 +1523,6 @@ static int sata_fsl_probe(struct platform_device *ofdev)
ata_host_activate(host, irq, sata_fsl_interrupt, SATA_FSL_IRQ_FLAG,
&sata_fsl_sht);
platform_set_drvdata(ofdev, host);
host_priv->intr_coalescing.show = fsl_sata_intr_coalescing_show;
host_priv->intr_coalescing.store = fsl_sata_intr_coalescing_store;
sysfs_attr_init(&host_priv->intr_coalescing.attr);

438
drivers/ata/sata_gemini.c Normal file
View file

@ -0,0 +1,438 @@
/*
* Cortina Systems Gemini SATA bridge add-on to Faraday FTIDE010
* Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/bitops.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/delay.h>
#include <linux/reset.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/clk.h>
#include <linux/io.h>
#include "sata_gemini.h"
#define DRV_NAME "gemini_sata_bridge"
/**
* struct sata_gemini - a state container for a Gemini SATA bridge
* @dev: the containing device
* @base: remapped I/O memory base
* @muxmode: the current muxing mode
* @ide_pins: if the device is using the plain IDE interface pins
* @sata_bridge: if the device enables the SATA bridge
* @sata0_reset: SATA0 reset handler
* @sata1_reset: SATA1 reset handler
* @sata0_pclk: SATA0 PCLK handler
* @sata1_pclk: SATA1 PCLK handler
*/
struct sata_gemini {
struct device *dev;
void __iomem *base;
enum gemini_muxmode muxmode;
bool ide_pins;
bool sata_bridge;
struct reset_control *sata0_reset;
struct reset_control *sata1_reset;
struct clk *sata0_pclk;
struct clk *sata1_pclk;
};
/* Global IDE PAD Skew Control Register */
#define GEMINI_GLOBAL_IDE_SKEW_CTRL 0x18
#define GEMINI_IDE1_HOST_STROBE_DELAY_SHIFT 28
#define GEMINI_IDE1_DEVICE_STROBE_DELAY_SHIFT 24
#define GEMINI_IDE1_OUTPUT_IO_SKEW_SHIFT 20
#define GEMINI_IDE1_INPUT_IO_SKEW_SHIFT 16
#define GEMINI_IDE0_HOST_STROBE_DELAY_SHIFT 12
#define GEMINI_IDE0_DEVICE_STROBE_DELAY_SHIFT 8
#define GEMINI_IDE0_OUTPUT_IO_SKEW_SHIFT 4
#define GEMINI_IDE0_INPUT_IO_SKEW_SHIFT 0
/* Miscellaneous Control Register */
#define GEMINI_GLOBAL_MISC_CTRL 0x30
/*
* Values of IDE IOMUX bits in the misc control register
*
* Bits 26:24 are "IDE IO Select", which decides what SATA
* adapters are connected to which of the two IDE/ATA
* controllers in the Gemini. We can connect the two IDE blocks
* to one SATA adapter each, both acting as master, or one IDE
* blocks to two SATA adapters so the IDE block can act in a
* master/slave configuration.
*
* We also bring out different blocks on the actual IDE
* pins (not SATA pins) if (and only if) these are muxed in.
*
* 111-100 - Reserved
* Mode 0: 000 - ata0 master <-> sata0
* ata1 master <-> sata1
* ata0 slave interface brought out on IDE pads
* Mode 1: 001 - ata0 master <-> sata0
* ata1 master <-> sata1
* ata1 slave interface brought out on IDE pads
* Mode 2: 010 - ata1 master <-> sata1
* ata1 slave <-> sata0
* ata0 master and slave interfaces brought out
* on IDE pads
* Mode 3: 011 - ata0 master <-> sata0
* ata1 slave <-> sata1
* ata1 master and slave interfaces brought out
* on IDE pads
*/
#define GEMINI_IDE_IOMUX_MASK (7 << 24)
#define GEMINI_IDE_IOMUX_MODE0 (0 << 24)
#define GEMINI_IDE_IOMUX_MODE1 (1 << 24)
#define GEMINI_IDE_IOMUX_MODE2 (2 << 24)
#define GEMINI_IDE_IOMUX_MODE3 (3 << 24)
#define GEMINI_IDE_IOMUX_SHIFT (24)
#define GEMINI_IDE_PADS_ENABLE BIT(4)
#define GEMINI_PFLASH_PADS_DISABLE BIT(1)
/*
* Registers directly controlling the PATA<->SATA adapters
*/
#define GEMINI_SATA_ID 0x00
#define GEMINI_SATA_PHY_ID 0x04
#define GEMINI_SATA0_STATUS 0x08
#define GEMINI_SATA1_STATUS 0x0c
#define GEMINI_SATA0_CTRL 0x18
#define GEMINI_SATA1_CTRL 0x1c
#define GEMINI_SATA_STATUS_BIST_DONE BIT(5)
#define GEMINI_SATA_STATUS_BIST_OK BIT(4)
#define GEMINI_SATA_STATUS_PHY_READY BIT(0)
#define GEMINI_SATA_CTRL_PHY_BIST_EN BIT(14)
#define GEMINI_SATA_CTRL_PHY_FORCE_IDLE BIT(13)
#define GEMINI_SATA_CTRL_PHY_FORCE_READY BIT(12)
#define GEMINI_SATA_CTRL_PHY_AFE_LOOP_EN BIT(10)
#define GEMINI_SATA_CTRL_PHY_DIG_LOOP_EN BIT(9)
#define GEMINI_SATA_CTRL_HOTPLUG_DETECT_EN BIT(4)
#define GEMINI_SATA_CTRL_ATAPI_EN BIT(3)
#define GEMINI_SATA_CTRL_BUS_WITH_20 BIT(2)
#define GEMINI_SATA_CTRL_SLAVE_EN BIT(1)
#define GEMINI_SATA_CTRL_EN BIT(0)
/*
* There is only ever one instance of this bridge on a system,
* so create a singleton so that the FTIDE010 instances can grab
* a reference to it.
*/
static struct sata_gemini *sg_singleton;
struct sata_gemini *gemini_sata_bridge_get(void)
{
if (sg_singleton)
return sg_singleton;
return ERR_PTR(-EPROBE_DEFER);
}
EXPORT_SYMBOL(gemini_sata_bridge_get);
bool gemini_sata_bridge_enabled(struct sata_gemini *sg, bool is_ata1)
{
if (!sg->sata_bridge)
return false;
/*
* In muxmode 2 and 3 one of the ATA controllers is
* actually not connected to any SATA bridge.
*/
if ((sg->muxmode == GEMINI_MUXMODE_2) &&
!is_ata1)
return false;
if ((sg->muxmode == GEMINI_MUXMODE_3) &&
is_ata1)
return false;
return true;
}
EXPORT_SYMBOL(gemini_sata_bridge_enabled);
enum gemini_muxmode gemini_sata_get_muxmode(struct sata_gemini *sg)
{
return sg->muxmode;
}
EXPORT_SYMBOL(gemini_sata_get_muxmode);
static int gemini_sata_setup_bridge(struct sata_gemini *sg,
unsigned int bridge)
{
unsigned long timeout = jiffies + (HZ * 1);
bool bridge_online;
u32 val;
if (bridge == 0) {
val = GEMINI_SATA_CTRL_HOTPLUG_DETECT_EN | GEMINI_SATA_CTRL_EN;
/* SATA0 slave mode is only used in muxmode 2 */
if (sg->muxmode == GEMINI_MUXMODE_2)
val |= GEMINI_SATA_CTRL_SLAVE_EN;
writel(val, sg->base + GEMINI_SATA0_CTRL);
} else {
val = GEMINI_SATA_CTRL_HOTPLUG_DETECT_EN | GEMINI_SATA_CTRL_EN;
/* SATA1 slave mode is only used in muxmode 3 */
if (sg->muxmode == GEMINI_MUXMODE_3)
val |= GEMINI_SATA_CTRL_SLAVE_EN;
writel(val, sg->base + GEMINI_SATA1_CTRL);
}
/* Vendor code waits 10 ms here */
msleep(10);
/* Wait for PHY to become ready */
do {
msleep(100);
if (bridge == 0)
val = readl(sg->base + GEMINI_SATA0_STATUS);
else
val = readl(sg->base + GEMINI_SATA1_STATUS);
if (val & GEMINI_SATA_STATUS_PHY_READY)
break;
} while (time_before(jiffies, timeout));
bridge_online = !!(val & GEMINI_SATA_STATUS_PHY_READY);
dev_info(sg->dev, "SATA%d PHY %s\n", bridge,
bridge_online ? "ready" : "not ready");
return bridge_online ? 0: -ENODEV;
}
int gemini_sata_start_bridge(struct sata_gemini *sg, unsigned int bridge)
{
struct clk *pclk;
int ret;
if (bridge == 0)
pclk = sg->sata0_pclk;
else
pclk = sg->sata1_pclk;
clk_enable(pclk);
msleep(10);
/* Do not keep clocking a bridge that is not online */
ret = gemini_sata_setup_bridge(sg, bridge);
if (ret)
clk_disable(pclk);
return ret;
}
EXPORT_SYMBOL(gemini_sata_start_bridge);
void gemini_sata_stop_bridge(struct sata_gemini *sg, unsigned int bridge)
{
if (bridge == 0)
clk_disable(sg->sata0_pclk);
else if (bridge == 1)
clk_disable(sg->sata1_pclk);
}
EXPORT_SYMBOL(gemini_sata_stop_bridge);
int gemini_sata_reset_bridge(struct sata_gemini *sg,
unsigned int bridge)
{
if (bridge == 0)
reset_control_reset(sg->sata0_reset);
else
reset_control_reset(sg->sata1_reset);
msleep(10);
return gemini_sata_setup_bridge(sg, bridge);
}
EXPORT_SYMBOL(gemini_sata_reset_bridge);
static int gemini_sata_bridge_init(struct sata_gemini *sg)
{
struct device *dev = sg->dev;
u32 sata_id, sata_phy_id;
int ret;
sg->sata0_pclk = devm_clk_get(dev, "SATA0_PCLK");
if (IS_ERR(sg->sata0_pclk)) {
dev_err(dev, "no SATA0 PCLK");
return -ENODEV;
}
sg->sata1_pclk = devm_clk_get(dev, "SATA1_PCLK");
if (IS_ERR(sg->sata1_pclk)) {
dev_err(dev, "no SATA1 PCLK");
return -ENODEV;
}
ret = clk_prepare_enable(sg->sata0_pclk);
if (ret) {
pr_err("failed to enable SATA0 PCLK\n");
return ret;
}
ret = clk_prepare_enable(sg->sata1_pclk);
if (ret) {
pr_err("failed to enable SATA1 PCLK\n");
clk_disable_unprepare(sg->sata0_pclk);
return ret;
}
sg->sata0_reset = devm_reset_control_get(dev, "sata0");
if (IS_ERR(sg->sata0_reset)) {
dev_err(dev, "no SATA0 reset controller\n");
clk_disable_unprepare(sg->sata1_pclk);
clk_disable_unprepare(sg->sata0_pclk);
return PTR_ERR(sg->sata0_reset);
}
sg->sata1_reset = devm_reset_control_get(dev, "sata1");
if (IS_ERR(sg->sata1_reset)) {
dev_err(dev, "no SATA1 reset controller\n");
clk_disable_unprepare(sg->sata1_pclk);
clk_disable_unprepare(sg->sata0_pclk);
return PTR_ERR(sg->sata1_reset);
}
sata_id = readl(sg->base + GEMINI_SATA_ID);
sata_phy_id = readl(sg->base + GEMINI_SATA_PHY_ID);
sg->sata_bridge = true;
clk_disable(sg->sata0_pclk);
clk_disable(sg->sata1_pclk);
dev_info(dev, "SATA ID %08x, PHY ID: %08x\n", sata_id, sata_phy_id);
return 0;
}
static int gemini_sata_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct sata_gemini *sg;
static struct regmap *map;
struct resource *res;
enum gemini_muxmode muxmode;
u32 gmode;
u32 gmask;
u32 val;
int ret;
sg = devm_kzalloc(dev, sizeof(*sg), GFP_KERNEL);
if (!sg)
return -ENOMEM;
sg->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
sg->base = devm_ioremap_resource(dev, res);
if (IS_ERR(sg->base))
return PTR_ERR(sg->base);
map = syscon_regmap_lookup_by_phandle(np, "syscon");
if (IS_ERR(map)) {
dev_err(dev, "no global syscon\n");
return PTR_ERR(map);
}
/* Set up the SATA bridge if need be */
if (of_property_read_bool(np, "cortina,gemini-enable-sata-bridge")) {
ret = gemini_sata_bridge_init(sg);
if (ret)
return ret;
}
if (of_property_read_bool(np, "cortina,gemini-enable-ide-pins"))
sg->ide_pins = true;
if (!sg->sata_bridge && !sg->ide_pins) {
dev_err(dev, "neither SATA bridge or IDE output enabled\n");
ret = -EINVAL;
goto out_unprep_clk;
}
ret = of_property_read_u32(np, "cortina,gemini-ata-muxmode", &muxmode);
if (ret) {
dev_err(dev, "could not parse ATA muxmode\n");
goto out_unprep_clk;
}
if (muxmode > GEMINI_MUXMODE_3) {
dev_err(dev, "illegal muxmode %d\n", muxmode);
ret = -EINVAL;
goto out_unprep_clk;
}
sg->muxmode = muxmode;
gmask = GEMINI_IDE_IOMUX_MASK;
gmode = (muxmode << GEMINI_IDE_IOMUX_SHIFT);
/*
* If we mux out the IDE, parallel flash must be disabled.
* SATA0 and SATA1 have dedicated pins and may coexist with
* parallel flash.
*/
if (sg->ide_pins)
gmode |= GEMINI_IDE_PADS_ENABLE | GEMINI_PFLASH_PADS_DISABLE;
else
gmask |= GEMINI_IDE_PADS_ENABLE;
ret = regmap_update_bits(map, GEMINI_GLOBAL_MISC_CTRL, gmask, gmode);
if (ret) {
dev_err(dev, "unable to set up IDE muxing\n");
ret = -ENODEV;
goto out_unprep_clk;
}
/* FIXME: add more elaborate IDE skew control handling */
if (sg->ide_pins) {
ret = regmap_read(map, GEMINI_GLOBAL_IDE_SKEW_CTRL, &val);
if (ret) {
dev_err(dev, "cannot read IDE skew control register\n");
return ret;
}
dev_info(dev, "IDE skew control: %08x\n", val);
}
dev_info(dev, "set up the Gemini IDE/SATA nexus\n");
platform_set_drvdata(pdev, sg);
sg_singleton = sg;
return 0;
out_unprep_clk:
if (sg->sata_bridge) {
clk_unprepare(sg->sata1_pclk);
clk_unprepare(sg->sata0_pclk);
}
return ret;
}
static int gemini_sata_remove(struct platform_device *pdev)
{
struct sata_gemini *sg = platform_get_drvdata(pdev);
if (sg->sata_bridge) {
clk_unprepare(sg->sata1_pclk);
clk_unprepare(sg->sata0_pclk);
}
sg_singleton = NULL;
return 0;
}
static const struct of_device_id gemini_sata_of_match[] = {
{
.compatible = "cortina,gemini-sata-bridge",
},
{},
};
static struct platform_driver gemini_sata_driver = {
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(gemini_sata_of_match),
},
.probe = gemini_sata_probe,
.remove = gemini_sata_remove,
};
module_platform_driver(gemini_sata_driver);
MODULE_AUTHOR("Linus Walleij <[email protected]>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);

21
drivers/ata/sata_gemini.h Normal file
View file

@ -0,0 +1,21 @@
/* Header for the Gemini SATA bridge */
#ifndef SATA_GEMINI_H
#define SATA_GEMINI_H
struct sata_gemini;
enum gemini_muxmode {
GEMINI_MUXMODE_0 = 0,
GEMINI_MUXMODE_1,
GEMINI_MUXMODE_2,
GEMINI_MUXMODE_3,
};
struct sata_gemini *gemini_sata_bridge_get(void);
bool gemini_sata_bridge_enabled(struct sata_gemini *sg, bool is_ata1);
enum gemini_muxmode gemini_sata_get_muxmode(struct sata_gemini *sg);
int gemini_sata_start_bridge(struct sata_gemini *sg, unsigned int bridge);
void gemini_sata_stop_bridge(struct sata_gemini *sg, unsigned int bridge);
int gemini_sata_reset_bridge(struct sata_gemini *sg, unsigned int bridge);
#endif

View file

@ -737,7 +737,7 @@ static struct ata_port_operations inic_port_ops = {
.port_start = inic_port_start,
};
static struct ata_port_info inic_port_info = {
static const struct ata_port_info inic_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,

View file

@ -828,7 +828,7 @@ static void sata_rcar_init_controller(struct ata_host *host)
iowrite32(ATAPI_INT_ENABLE_SATAINT, base + ATAPI_INT_ENABLE_REG);
}
static struct of_device_id sata_rcar_match[] = {
static const struct of_device_id sata_rcar_match[] = {
{
/* Deprecated by "renesas,sata-r8a7779" */
.compatible = "renesas,rcar-sata",

View file

@ -80,6 +80,10 @@ struct svia_priv {
bool wd_workaround;
};
static int vt6420_hotplug;
module_param_named(vt6420_hotplug, vt6420_hotplug, int, 0644);
MODULE_PARM_DESC(vt6420_hotplug, "Enable hot-plug support for VT6420 (0=Don't support, 1=support)");
static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
#ifdef CONFIG_PM_SLEEP
static int svia_pci_device_resume(struct pci_dev *pdev);
@ -166,7 +170,7 @@ static const struct ata_port_info vt6420_port_info = {
.port_ops = &vt6420_sata_ops,
};
static struct ata_port_info vt6421_sport_info = {
static const struct ata_port_info vt6421_sport_info = {
.flags = ATA_FLAG_SATA,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
@ -174,7 +178,7 @@ static struct ata_port_info vt6421_sport_info = {
.port_ops = &vt6421_sata_ops,
};
static struct ata_port_info vt6421_pport_info = {
static const struct ata_port_info vt6421_pport_info = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
/* No MWDMA */
@ -182,7 +186,7 @@ static struct ata_port_info vt6421_pport_info = {
.port_ops = &vt6421_pata_ops,
};
static struct ata_port_info vt8251_port_info = {
static const struct ata_port_info vt8251_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
@ -473,6 +477,11 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
struct ata_host *host;
int rc;
if (vt6420_hotplug) {
ppi[0]->port_ops->scr_read = svia_scr_read;
ppi[0]->port_ops->scr_write = svia_scr_write;
}
rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
if (rc)
return rc;
@ -556,7 +565,7 @@ static void svia_wd_fix(struct pci_dev *pdev)
pci_write_config_byte(pdev, 0x52, tmp8 | BIT(2));
}
static irqreturn_t vt6421_interrupt(int irq, void *dev_instance)
static irqreturn_t vt642x_interrupt(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
irqreturn_t rc = ata_bmdma_interrupt(irq, dev_instance);
@ -644,7 +653,7 @@ static void svia_configure(struct pci_dev *pdev, int board_id,
pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
}
if (board_id == vt6421) {
if ((board_id == vt6420 && vt6420_hotplug) || board_id == vt6421) {
/* enable IRQ on hotplug */
pci_read_config_byte(pdev, SVIA_MISC_3, &tmp8);
if ((tmp8 & SATA_HOTPLUG) != SATA_HOTPLUG) {
@ -744,8 +753,8 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
svia_configure(pdev, board_id, hpriv);
pci_set_master(pdev);
if (board_id == vt6421)
return ata_host_activate(host, pdev->irq, vt6421_interrupt,
if ((board_id == vt6420 && vt6420_hotplug) || board_id == vt6421)
return ata_host_activate(host, pdev->irq, vt642x_interrupt,
IRQF_SHARED, &svia_sht);
else
return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,