diff options
Diffstat (limited to 'drivers/ata/sata_fsl.c')
| -rw-r--r-- | drivers/ata/sata_fsl.c | 357 |
1 files changed, 272 insertions, 85 deletions
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index b0214d00d50..616a6d2ac20 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -6,7 +6,7 @@ * Author: Ashish Kalra <ashish.kalra@freescale.com> * Li Yang <leoli@freescale.com> * - * Copyright (c) 2006-2007 Freescale Semiconductor, Inc. + * Copyright (c) 2006-2007, 2011-2012 Freescale Semiconductor, Inc. * * 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 @@ -24,8 +24,19 @@ #include <scsi/scsi_cmnd.h> #include <linux/libata.h> #include <asm/io.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/of_platform.h> +static unsigned int intr_coalescing_count; +module_param(intr_coalescing_count, int, S_IRUGO); +MODULE_PARM_DESC(intr_coalescing_count, + "INT coalescing count threshold (1..31)"); + +static unsigned int intr_coalescing_ticks; +module_param(intr_coalescing_ticks, int, S_IRUGO); +MODULE_PARM_DESC(intr_coalescing_ticks, + "INT coalescing timer threshold in AHB ticks"); /* Controller information */ enum { SATA_FSL_QUEUE_DEPTH = 16, @@ -33,8 +44,7 @@ enum { SATA_FSL_MAX_PRD_USABLE = SATA_FSL_MAX_PRD - 1, SATA_FSL_MAX_PRD_DIRECT = 16, /* Direct PRDT entries */ - SATA_FSL_HOST_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + SATA_FSL_HOST_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | ATA_FLAG_PMP | ATA_FLAG_NCQ | ATA_FLAG_AN), SATA_FSL_MAX_CMDS = SATA_FSL_QUEUE_DEPTH, @@ -43,7 +53,7 @@ enum { /* * SATA-FSL host controller supports a max. of (15+1) direct PRDEs, and - * chained indirect PRDEs upto a max count of 63. + * chained indirect PRDEs up to a max count of 63. * We are allocating an array of 63 PRDEs contiguously, but PRDE#15 will * be setup as an indirect descriptor, pointing to it's next * (contiguous) PRDE. Though chained indirect PRDE arrays are @@ -84,6 +94,16 @@ enum { }; /* + * Interrupt Coalescing Control Register bitdefs */ +enum { + ICC_MIN_INT_COUNT_THRESHOLD = 1, + ICC_MAX_INT_COUNT_THRESHOLD = ((1 << 5) - 1), + ICC_MIN_INT_TICKS_THRESHOLD = 0, + ICC_MAX_INT_TICKS_THRESHOLD = ((1 << 19) - 1), + ICC_SAFE_INT_TICKS = 1, +}; + +/* * Host Controller command register set - per port */ enum { @@ -105,6 +125,7 @@ enum { ONLINE = (1 << 31), GOING_OFFLINE = (1 << 30), BIST_ERR = (1 << 29), + CLEAR_ERROR = (1 << 27), FATAL_ERR_HC_MASTER_ERR = (1 << 18), FATAL_ERR_PARITY_ERR_TX = (1 << 17), @@ -125,6 +146,7 @@ enum { FATAL_ERR_CRC_ERR_RX | FATAL_ERR_FIFO_OVRFL_TX | FATAL_ERR_FIFO_OVRFL_RX, + INT_ON_DATA_LENGTH_MISMATCH = (1 << 12), INT_ON_FATAL_ERR = (1 << 5), INT_ON_PHYRDY_CHG = (1 << 4), @@ -141,6 +163,7 @@ enum { */ HCONTROL_ONLINE_PHY_RST = (1 << 31), HCONTROL_FORCE_OFFLINE = (1 << 30), + HCONTROL_LEGACY = (1 << 28), HCONTROL_PARITY_PROT_MOD = (1 << 14), HCONTROL_DPATH_PARITY = (1 << 12), HCONTROL_SNOOP_ENABLE = (1 << 10), @@ -158,7 +181,8 @@ enum { IE_ON_SINGL_DEVICE_ERR | IE_ON_CMD_COMPLETE, EXT_INDIRECT_SEG_PRD_FLAG = (1 << 31), - DATA_SNOOP_ENABLE = (1 << 22), + DATA_SNOOP_ENABLE_V1 = (1 << 22), + DATA_SNOOP_ENABLE_V2 = (1 << 28), }; /* @@ -186,6 +210,11 @@ enum { COMMANDSTAT = 0x20, }; +/* TRANSCFG (transport-layer) configuration control */ +enum { + TRANSCFG_RX_WATER_MARK = (1 << 4), +}; + /* PHY (link-layer) configuration control */ enum { PHY_BIST_ENABLE = 0x01, @@ -256,8 +285,110 @@ struct sata_fsl_host_priv { void __iomem *ssr_base; void __iomem *csr_base; int irq; + int data_snoop; + struct device_attribute intr_coalescing; + struct device_attribute rx_watermark; }; +static void fsl_sata_set_irq_coalescing(struct ata_host *host, + unsigned int count, unsigned int ticks) +{ + struct sata_fsl_host_priv *host_priv = host->private_data; + void __iomem *hcr_base = host_priv->hcr_base; + unsigned long flags; + + if (count > ICC_MAX_INT_COUNT_THRESHOLD) + count = ICC_MAX_INT_COUNT_THRESHOLD; + else if (count < ICC_MIN_INT_COUNT_THRESHOLD) + count = ICC_MIN_INT_COUNT_THRESHOLD; + + if (ticks > ICC_MAX_INT_TICKS_THRESHOLD) + ticks = ICC_MAX_INT_TICKS_THRESHOLD; + else if ((ICC_MIN_INT_TICKS_THRESHOLD == ticks) && + (count > ICC_MIN_INT_COUNT_THRESHOLD)) + ticks = ICC_SAFE_INT_TICKS; + + spin_lock_irqsave(&host->lock, flags); + iowrite32((count << 24 | ticks), hcr_base + ICC); + + intr_coalescing_count = count; + intr_coalescing_ticks = ticks; + spin_unlock_irqrestore(&host->lock, flags); + + DPRINTK("interrupt coalescing, count = 0x%x, ticks = %x\n", + intr_coalescing_count, intr_coalescing_ticks); + DPRINTK("ICC register status: (hcr base: 0x%x) = 0x%x\n", + hcr_base, ioread32(hcr_base + ICC)); +} + +static ssize_t fsl_sata_intr_coalescing_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d %d\n", + intr_coalescing_count, intr_coalescing_ticks); +} + +static ssize_t fsl_sata_intr_coalescing_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int coalescing_count, coalescing_ticks; + + if (sscanf(buf, "%d%d", + &coalescing_count, + &coalescing_ticks) != 2) { + printk(KERN_ERR "fsl-sata: wrong parameter format.\n"); + return -EINVAL; + } + + fsl_sata_set_irq_coalescing(dev_get_drvdata(dev), + coalescing_count, coalescing_ticks); + + return strlen(buf); +} + +static ssize_t fsl_sata_rx_watermark_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned int rx_watermark; + unsigned long flags; + struct ata_host *host = dev_get_drvdata(dev); + struct sata_fsl_host_priv *host_priv = host->private_data; + void __iomem *csr_base = host_priv->csr_base; + + spin_lock_irqsave(&host->lock, flags); + rx_watermark = ioread32(csr_base + TRANSCFG); + rx_watermark &= 0x1f; + + spin_unlock_irqrestore(&host->lock, flags); + return sprintf(buf, "%d\n", rx_watermark); +} + +static ssize_t fsl_sata_rx_watermark_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int rx_watermark; + unsigned long flags; + struct ata_host *host = dev_get_drvdata(dev); + struct sata_fsl_host_priv *host_priv = host->private_data; + void __iomem *csr_base = host_priv->csr_base; + u32 temp; + + if (sscanf(buf, "%d", &rx_watermark) != 1) { + printk(KERN_ERR "fsl-sata: wrong parameter format.\n"); + return -EINVAL; + } + + spin_lock_irqsave(&host->lock, flags); + temp = ioread32(csr_base + TRANSCFG); + temp &= 0xffffffe0; + iowrite32(temp | rx_watermark, csr_base + TRANSCFG); + + spin_unlock_irqrestore(&host->lock, flags); + return strlen(buf); +} + static inline unsigned int sata_fsl_tag(unsigned int tag, void __iomem *hcr_base) { @@ -308,7 +439,8 @@ static void sata_fsl_setup_cmd_hdr_entry(struct sata_fsl_port_priv *pp, } static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc, - u32 *ttl, dma_addr_t cmd_desc_paddr) + u32 *ttl, dma_addr_t cmd_desc_paddr, + int data_snoop) { struct scatterlist *sg; unsigned int num_prde = 0; @@ -338,13 +470,12 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc, (unsigned long long)sg_addr, sg_len); /* warn if each s/g element is not dword aligned */ - if (sg_addr & 0x03) - ata_port_printk(qc->ap, KERN_ERR, - "s/g addr unaligned : 0x%llx\n", - (unsigned long long)sg_addr); - if (sg_len & 0x03) - ata_port_printk(qc->ap, KERN_ERR, - "s/g len unaligned : 0x%x\n", sg_len); + if (unlikely(sg_addr & 0x03)) + ata_port_err(qc->ap, "s/g addr unaligned : 0x%llx\n", + (unsigned long long)sg_addr); + if (unlikely(sg_len & 0x03)) + ata_port_err(qc->ap, "s/g len unaligned : 0x%x\n", + sg_len); if (num_prde == (SATA_FSL_MAX_PRD_DIRECT - 1) && sg_next(sg) != NULL) { @@ -358,8 +489,7 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc, ttl_dwords += sg_len; prd->dba = cpu_to_le32(sg_addr); - prd->ddc_and_ext = - cpu_to_le32(DATA_SNOOP_ENABLE | (sg_len & ~0x03)); + prd->ddc_and_ext = cpu_to_le32(data_snoop | (sg_len & ~0x03)); VPRINTK("sg_fill, ttl=%d, dba=0x%x, ddc=0x%x\n", ttl_dwords, prd->dba, prd->ddc_and_ext); @@ -374,7 +504,7 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc, /* set indirect extension flag along with indirect ext. size */ prd_ptr_to_indirect_ext->ddc_and_ext = cpu_to_le32((EXT_INDIRECT_SEG_PRD_FLAG | - DATA_SNOOP_ENABLE | + data_snoop | (indirect_ext_segment_sz & ~0x03))); } @@ -417,7 +547,8 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc) if (qc->flags & ATA_QCFLAG_DMAMAP) num_prde = sata_fsl_fill_sg(qc, (void *)cd, - &ttl_dwords, cd_paddr); + &ttl_dwords, cd_paddr, + host_priv->data_snoop); if (qc->tf.protocol == ATA_PROT_NCQ) desc_info |= FPDMA_QUEUED_CMD; @@ -643,21 +774,6 @@ static int sata_fsl_port_start(struct ata_port *ap) VPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL)); VPRINTK("CHBA = 0x%x\n", ioread32(hcr_base + CHBA)); -#ifdef CONFIG_MPC8315_DS - /* - * Workaround for 8315DS board 3gbps link-up issue, - * currently limit SATA port to GEN1 speed - */ - sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp); - temp &= ~(0xF << 4); - temp |= (0x1 << 4); - sata_fsl_scr_write(&ap->link, SCR_CONTROL, temp); - - sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp); - dev_printk(KERN_WARNING, dev, "scr_control, speed limited to %x\n", - temp); -#endif - return 0; } @@ -733,8 +849,7 @@ try_offline_again: 1, 500); if (temp & ONLINE) { - ata_port_printk(ap, KERN_ERR, - "Hardreset failed, not off-lined %d\n", i); + ata_port_err(ap, "Hardreset failed, not off-lined %d\n", i); /* * Try to offline controller atleast twice @@ -770,8 +885,7 @@ try_offline_again: temp = ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, 0, 1, 500); if (!(temp & ONLINE)) { - ata_port_printk(ap, KERN_ERR, - "Hardreset failed, not on-lined\n"); + ata_port_err(ap, "Hardreset failed, not on-lined\n"); goto err; } @@ -787,9 +901,8 @@ try_offline_again: temp = ata_wait_register(ap, hcr_base + HSTATUS, 0xFF, 0, 1, 500); if ((!(temp & 0x10)) || ata_link_offline(link)) { - ata_port_printk(ap, KERN_WARNING, - "No Device OR PHYRDY change,Hstatus = 0x%x\n", - ioread32(hcr_base + HSTATUS)); + ata_port_warn(ap, "No Device OR PHYRDY change,Hstatus = 0x%x\n", + ioread32(hcr_base + HSTATUS)); *class = ATA_DEV_NONE; return 0; } @@ -802,13 +915,12 @@ try_offline_again: 500, jiffies_to_msecs(deadline - start_jiffies)); if ((temp & 0xFF) != 0x18) { - ata_port_printk(ap, KERN_WARNING, "No Signature Update\n"); + ata_port_warn(ap, "No Signature Update\n"); *class = ATA_DEV_NONE; goto do_followup_srst; } else { - ata_port_printk(ap, KERN_INFO, - "Signature Update detected @ %d msecs\n", - jiffies_to_msecs(jiffies - start_jiffies)); + ata_port_info(ap, "Signature Update detected @ %d msecs\n", + jiffies_to_msecs(jiffies - start_jiffies)); *class = sata_fsl_dev_classify(ap); return 0; } @@ -883,7 +995,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class, temp = ata_wait_register(ap, CQ + hcr_base, 0x1, 0x1, 1, 5000); if (temp & 0x1) { - ata_port_printk(ap, KERN_WARNING, "ATA_SRST issue failed\n"); + ata_port_warn(ap, "ATA_SRST issue failed\n"); DPRINTK("Softreset@5000,CQ=0x%x,CA=0x%x,CC=0x%x\n", ioread32(CQ + hcr_base), @@ -900,7 +1012,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class, ata_msleep(ap, 1); /* - * SATA device enters reset state after receving a Control register + * SATA device enters reset state after receiving a Control register * FIS with SRST bit asserted and it awaits another H2D Control reg. * FIS with SRST bit cleared, then the device does internal diags & * initialization, followed by indicating it's initialization status @@ -1040,12 +1152,15 @@ static void sata_fsl_error_intr(struct ata_port *ap) /* find out the offending link and qc */ if (ap->nr_pmp_links) { + unsigned int dev_num; + dereg = ioread32(hcr_base + DE); iowrite32(dereg, hcr_base + DE); iowrite32(cereg, hcr_base + CE); - if (dereg < ap->nr_pmp_links) { - link = &ap->pmp_link[dereg]; + dev_num = ffs(dereg) - 1; + if (dev_num < ap->nr_pmp_links && dereg != 0) { + link = &ap->pmp_link[dev_num]; ehi = &link->eh_info; qc = ata_qc_from_tag(ap, link->active_tag); /* @@ -1100,25 +1215,54 @@ static void sata_fsl_host_intr(struct ata_port *ap) u32 hstatus, done_mask = 0; struct ata_queued_cmd *qc; u32 SError; + u32 tag; + u32 status_mask = INT_ON_ERROR; hstatus = ioread32(hcr_base + HSTATUS); sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError); + /* Read command completed register */ + done_mask = ioread32(hcr_base + CC); + + /* Workaround for data length mismatch errata */ + if (unlikely(hstatus & INT_ON_DATA_LENGTH_MISMATCH)) { + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + qc = ata_qc_from_tag(ap, tag); + if (qc && ata_is_atapi(qc->tf.protocol)) { + u32 hcontrol; + /* Set HControl[27] to clear error registers */ + hcontrol = ioread32(hcr_base + HCONTROL); + iowrite32(hcontrol | CLEAR_ERROR, + hcr_base + HCONTROL); + + /* Clear HControl[27] */ + iowrite32(hcontrol & ~CLEAR_ERROR, + hcr_base + HCONTROL); + + /* Clear SError[E] bit */ + sata_fsl_scr_write(&ap->link, SCR_ERROR, + SError); + + /* Ignore fatal error and device error */ + status_mask &= ~(INT_ON_SINGL_DEVICE_ERR + | INT_ON_FATAL_ERR); + break; + } + } + } + if (unlikely(SError & 0xFFFF0000)) { DPRINTK("serror @host_intr : 0x%x\n", SError); sata_fsl_error_intr(ap); } - if (unlikely(hstatus & INT_ON_ERROR)) { + if (unlikely(hstatus & status_mask)) { DPRINTK("error interrupt!!\n"); sata_fsl_error_intr(ap); return; } - /* Read command completed register */ - done_mask = ioread32(hcr_base + CC); - VPRINTK("Status of all queues :\n"); VPRINTK("done_mask/CC = 0x%x, CA = 0x%x, CE=0x%x,CQ=0x%x,apqa=0x%x\n", done_mask, @@ -1192,8 +1336,7 @@ static irqreturn_t sata_fsl_interrupt(int irq, void *dev_instance) if (ap) { sata_fsl_host_intr(ap); } else { - dev_printk(KERN_WARNING, host->dev, - "interrupt on disabled port 0\n"); + dev_warn(host->dev, "interrupt on disabled port 0\n"); } iowrite32(interrupt_enables, hcr_base + HSTATUS); @@ -1220,6 +1363,10 @@ static int sata_fsl_init_controller(struct ata_host *host) * part of the port_start() callback */ + /* sata controller to operate in enterprise mode */ + temp = ioread32(hcr_base + HCONTROL); + iowrite32(temp & ~HCONTROL_LEGACY, hcr_base + HCONTROL); + /* ack. any pending IRQs for this controller/port */ temp = ioread32(hcr_base + HSTATUS); if (temp & 0x3F) @@ -1237,6 +1384,13 @@ static int sata_fsl_init_controller(struct ata_host *host) iowrite32(0x00000FFFF, hcr_base + CE); iowrite32(0x00000FFFF, hcr_base + DE); + /* + * reset the number of command complete bits which will cause the + * interrupt to be signaled + */ + fsl_sata_set_irq_coalescing(host, intr_coalescing_count, + intr_coalescing_ticks); + /* * host controller will be brought on-line, during xx_port_start() * callback, that should also initiate the OOB, COMINIT sequence @@ -1293,8 +1447,7 @@ static const struct ata_port_info sata_fsl_port_info[] = { }, }; -static int sata_fsl_probe(struct platform_device *ofdev, - const struct of_device_id *match) +static int sata_fsl_probe(struct platform_device *ofdev) { int retval = -ENXIO; void __iomem *hcr_base = NULL; @@ -1302,13 +1455,13 @@ static int sata_fsl_probe(struct platform_device *ofdev, void __iomem *csr_base = NULL; struct sata_fsl_host_priv *host_priv = NULL; int irq; - struct ata_host *host; + struct ata_host *host = NULL; + u32 temp; struct ata_port_info pi = sata_fsl_port_info[0]; const struct ata_port_info *ppi[] = { &pi, NULL }; - dev_printk(KERN_INFO, &ofdev->dev, - "Sata FSL Platform/CSB Driver init\n"); + dev_info(&ofdev->dev, "Sata FSL Platform/CSB Driver init\n"); hcr_base = of_iomap(ofdev->dev.of_node, 0); if (!hcr_base) @@ -1317,6 +1470,12 @@ static int sata_fsl_probe(struct platform_device *ofdev, ssr_base = hcr_base + 0x100; csr_base = hcr_base + 0x140; + if (!of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc8315-sata")) { + temp = ioread32(csr_base + TRANSCFG); + temp = temp & 0xffffffe0; + iowrite32(temp | TRANSCFG_RX_WATER_MARK, csr_base + TRANSCFG); + } + DPRINTK("@reset i/o = 0x%x\n", ioread32(csr_base + TRANSCFG)); DPRINTK("sizeof(cmd_desc) = %d\n", sizeof(struct command_desc)); DPRINTK("sizeof(#define cmd_desc) = %d\n", SATA_FSL_CMD_DESC_SIZE); @@ -1331,13 +1490,22 @@ static int sata_fsl_probe(struct platform_device *ofdev, irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); if (irq < 0) { - dev_printk(KERN_ERR, &ofdev->dev, "invalid irq from platform\n"); + dev_err(&ofdev->dev, "invalid irq from platform\n"); goto error_exit_with_cleanup; } host_priv->irq = irq; + if (of_device_is_compatible(ofdev->dev.of_node, "fsl,pq-sata-v2")) + host_priv->data_snoop = DATA_SNOOP_ENABLE_V2; + else + host_priv->data_snoop = DATA_SNOOP_ENABLE_V1; + /* allocate host structure */ host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_FSL_MAX_PORTS); + if (!host) { + retval = -ENOMEM; + goto error_exit_with_cleanup; + } /* host->iomap is not used currently */ host->private_data = host_priv; @@ -1353,28 +1521,51 @@ static int sata_fsl_probe(struct platform_device *ofdev, ata_host_activate(host, irq, sata_fsl_interrupt, SATA_FSL_IRQ_FLAG, &sata_fsl_sht); - dev_set_drvdata(&ofdev->dev, host); + 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); + host_priv->intr_coalescing.attr.name = "intr_coalescing"; + host_priv->intr_coalescing.attr.mode = S_IRUGO | S_IWUSR; + retval = device_create_file(host->dev, &host_priv->intr_coalescing); + if (retval) + goto error_exit_with_cleanup; + + host_priv->rx_watermark.show = fsl_sata_rx_watermark_show; + host_priv->rx_watermark.store = fsl_sata_rx_watermark_store; + sysfs_attr_init(&host_priv->rx_watermark.attr); + host_priv->rx_watermark.attr.name = "rx_watermark"; + host_priv->rx_watermark.attr.mode = S_IRUGO | S_IWUSR; + retval = device_create_file(host->dev, &host_priv->rx_watermark); + if (retval) { + device_remove_file(&ofdev->dev, &host_priv->intr_coalescing); + goto error_exit_with_cleanup; + } return 0; error_exit_with_cleanup: + if (host) + ata_host_detach(host); + if (hcr_base) iounmap(hcr_base); - if (host_priv) - kfree(host_priv); + kfree(host_priv); return retval; } static int sata_fsl_remove(struct platform_device *ofdev) { - struct ata_host *host = dev_get_drvdata(&ofdev->dev); + struct ata_host *host = platform_get_drvdata(ofdev); struct sata_fsl_host_priv *host_priv = host->private_data; - ata_host_detach(host); + device_remove_file(&ofdev->dev, &host_priv->intr_coalescing); + device_remove_file(&ofdev->dev, &host_priv->rx_watermark); - dev_set_drvdata(&ofdev->dev, NULL); + ata_host_detach(host); irq_dispose_mapping(host_priv->irq); iounmap(host_priv->hcr_base); @@ -1383,16 +1574,16 @@ static int sata_fsl_remove(struct platform_device *ofdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int sata_fsl_suspend(struct platform_device *op, pm_message_t state) { - struct ata_host *host = dev_get_drvdata(&op->dev); + struct ata_host *host = platform_get_drvdata(op); return ata_host_suspend(host, state); } static int sata_fsl_resume(struct platform_device *op) { - struct ata_host *host = dev_get_drvdata(&op->dev); + struct ata_host *host = platform_get_drvdata(op); struct sata_fsl_host_priv *host_priv = host->private_data; int ret; void __iomem *hcr_base = host_priv->hcr_base; @@ -1401,14 +1592,19 @@ static int sata_fsl_resume(struct platform_device *op) ret = sata_fsl_init_controller(host); if (ret) { - dev_printk(KERN_ERR, &op->dev, - "Error initialize hardware\n"); + dev_err(&op->dev, "Error initializing hardware\n"); return ret; } /* Recovery the CHBA register in host controller cmd register set */ iowrite32(pp->cmdslot_paddr & 0xffffffff, hcr_base + CHBA); + iowrite32((ioread32(hcr_base + HCONTROL) + | HCONTROL_ONLINE_PHY_RST + | HCONTROL_SNOOP_ENABLE + | HCONTROL_PMP_ATTACHED), + hcr_base + HCONTROL); + ata_host_resume(host); return 0; } @@ -1418,12 +1614,15 @@ static struct of_device_id fsl_sata_match[] = { { .compatible = "fsl,pq-sata", }, + { + .compatible = "fsl,pq-sata-v2", + }, {}, }; MODULE_DEVICE_TABLE(of, fsl_sata_match); -static struct of_platform_driver fsl_sata_driver = { +static struct platform_driver fsl_sata_driver = { .driver = { .name = "fsl-sata", .owner = THIS_MODULE, @@ -1431,27 +1630,15 @@ static struct of_platform_driver fsl_sata_driver = { }, .probe = sata_fsl_probe, .remove = sata_fsl_remove, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP .suspend = sata_fsl_suspend, .resume = sata_fsl_resume, #endif }; -static int __init sata_fsl_init(void) -{ - of_register_platform_driver(&fsl_sata_driver); - return 0; -} - -static void __exit sata_fsl_exit(void) -{ - of_unregister_platform_driver(&fsl_sata_driver); -} +module_platform_driver(fsl_sata_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ashish Kalra, Freescale Semiconductor"); MODULE_DESCRIPTION("Freescale 3.0Gbps SATA controller low level driver"); MODULE_VERSION("1.10"); - -module_init(sata_fsl_init); -module_exit(sata_fsl_exit); |
