aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2014-02-22 10:53:30 -0500
committerTejun Heo <tj@kernel.org>2014-02-22 15:35:41 -0500
commit039ece38da45f5e6a94be3aa7611cf3634bc2461 (patch)
treec496379b086ca1c4251b1fd914ecafb68eb22063 /drivers/ata
parentb2a52b6a0a03000d07edb359b4059d4d871a7602 (diff)
libahci: Allow drivers to override start_engine
Allwinner A10 and A20 ARM SoCs have an AHCI sata controller which needs a special register to be poked before starting the DMA engine. This register gets reset on an ahci_stop_engine call, so there is no other place then ahci_start_engine where this poking can be done. This commit allows drivers to override ahci_start_engine behavior for use by the Allwinner AHCI driver (and potentially other drivers in the future). Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci.c6
-rw-r--r--drivers/ata/ahci.h6
-rw-r--r--drivers/ata/libahci.c26
-rw-r--r--drivers/ata/sata_highbank.c3
4 files changed, 31 insertions, 10 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index b6a49ce71f6e..1d4efe540604 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -563,6 +563,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
563 unsigned long deadline) 563 unsigned long deadline)
564{ 564{
565 struct ata_port *ap = link->ap; 565 struct ata_port *ap = link->ap;
566 struct ahci_host_priv *hpriv = ap->host->private_data;
566 bool online; 567 bool online;
567 int rc; 568 int rc;
568 569
@@ -573,7 +574,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
573 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 574 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
574 deadline, &online, NULL); 575 deadline, &online, NULL);
575 576
576 ahci_start_engine(ap); 577 hpriv->start_engine(ap);
577 578
578 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 579 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
579 580
@@ -588,6 +589,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
588{ 589{
589 struct ata_port *ap = link->ap; 590 struct ata_port *ap = link->ap;
590 struct ahci_port_priv *pp = ap->private_data; 591 struct ahci_port_priv *pp = ap->private_data;
592 struct ahci_host_priv *hpriv = ap->host->private_data;
591 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 593 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
592 struct ata_taskfile tf; 594 struct ata_taskfile tf;
593 bool online; 595 bool online;
@@ -603,7 +605,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
603 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 605 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
604 deadline, &online, NULL); 606 deadline, &online, NULL);
605 607
606 ahci_start_engine(ap); 608 hpriv->start_engine(ap);
607 609
608 /* The pseudo configuration device on SIMG4726 attached to 610 /* The pseudo configuration device on SIMG4726 attached to
609 * ASUS P5W-DH Deluxe doesn't send signature FIS after 611 * ASUS P5W-DH Deluxe doesn't send signature FIS after
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 2289efdf8203..64d1a99de5e4 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -323,6 +323,12 @@ struct ahci_host_priv {
323 u32 em_msg_type; /* EM message type */ 323 u32 em_msg_type; /* EM message type */
324 struct clk *clk; /* Only for platforms supporting clk */ 324 struct clk *clk; /* Only for platforms supporting clk */
325 void *plat_data; /* Other platform data */ 325 void *plat_data; /* Other platform data */
326 /*
327 * Optional ahci_start_engine override, if not set this gets set to the
328 * default ahci_start_engine during ahci_save_initial_config, this can
329 * be overridden anytime before the host is activated.
330 */
331 void (*start_engine)(struct ata_port *ap);
326}; 332};
327 333
328extern int ahci_ignore_sss; 334extern int ahci_ignore_sss;
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 956851f0d44f..7985ae782679 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -393,6 +393,9 @@ static ssize_t ahci_show_em_supported(struct device *dev,
393 * 393 *
394 * If inconsistent, config values are fixed up by this function. 394 * If inconsistent, config values are fixed up by this function.
395 * 395 *
396 * If it is not set already this function sets hpriv->start_engine to
397 * ahci_start_engine.
398 *
396 * LOCKING: 399 * LOCKING:
397 * None. 400 * None.
398 */ 401 */
@@ -499,6 +502,9 @@ void ahci_save_initial_config(struct device *dev,
499 hpriv->cap = cap; 502 hpriv->cap = cap;
500 hpriv->cap2 = cap2; 503 hpriv->cap2 = cap2;
501 hpriv->port_map = port_map; 504 hpriv->port_map = port_map;
505
506 if (!hpriv->start_engine)
507 hpriv->start_engine = ahci_start_engine;
502} 508}
503EXPORT_SYMBOL_GPL(ahci_save_initial_config); 509EXPORT_SYMBOL_GPL(ahci_save_initial_config);
504 510
@@ -765,7 +771,7 @@ static void ahci_start_port(struct ata_port *ap)
765 771
766 /* enable DMA */ 772 /* enable DMA */
767 if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE)) 773 if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE))
768 ahci_start_engine(ap); 774 hpriv->start_engine(ap);
769 775
770 /* turn on LEDs */ 776 /* turn on LEDs */
771 if (ap->flags & ATA_FLAG_EM) { 777 if (ap->flags & ATA_FLAG_EM) {
@@ -1234,7 +1240,7 @@ int ahci_kick_engine(struct ata_port *ap)
1234 1240
1235 /* restart engine */ 1241 /* restart engine */
1236 out_restart: 1242 out_restart:
1237 ahci_start_engine(ap); 1243 hpriv->start_engine(ap);
1238 return rc; 1244 return rc;
1239} 1245}
1240EXPORT_SYMBOL_GPL(ahci_kick_engine); 1246EXPORT_SYMBOL_GPL(ahci_kick_engine);
@@ -1426,6 +1432,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
1426 const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); 1432 const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
1427 struct ata_port *ap = link->ap; 1433 struct ata_port *ap = link->ap;
1428 struct ahci_port_priv *pp = ap->private_data; 1434 struct ahci_port_priv *pp = ap->private_data;
1435 struct ahci_host_priv *hpriv = ap->host->private_data;
1429 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 1436 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
1430 struct ata_taskfile tf; 1437 struct ata_taskfile tf;
1431 bool online; 1438 bool online;
@@ -1443,7 +1450,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
1443 rc = sata_link_hardreset(link, timing, deadline, &online, 1450 rc = sata_link_hardreset(link, timing, deadline, &online,
1444 ahci_check_ready); 1451 ahci_check_ready);
1445 1452
1446 ahci_start_engine(ap); 1453 hpriv->start_engine(ap);
1447 1454
1448 if (online) 1455 if (online)
1449 *class = ahci_dev_classify(ap); 1456 *class = ahci_dev_classify(ap);
@@ -2007,10 +2014,12 @@ static void ahci_thaw(struct ata_port *ap)
2007 2014
2008void ahci_error_handler(struct ata_port *ap) 2015void ahci_error_handler(struct ata_port *ap)
2009{ 2016{
2017 struct ahci_host_priv *hpriv = ap->host->private_data;
2018
2010 if (!(ap->pflags & ATA_PFLAG_FROZEN)) { 2019 if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
2011 /* restart engine */ 2020 /* restart engine */
2012 ahci_stop_engine(ap); 2021 ahci_stop_engine(ap);
2013 ahci_start_engine(ap); 2022 hpriv->start_engine(ap);
2014 } 2023 }
2015 2024
2016 sata_pmp_error_handler(ap); 2025 sata_pmp_error_handler(ap);
@@ -2031,6 +2040,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
2031 2040
2032static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) 2041static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
2033{ 2042{
2043 struct ahci_host_priv *hpriv = ap->host->private_data;
2034 void __iomem *port_mmio = ahci_port_base(ap); 2044 void __iomem *port_mmio = ahci_port_base(ap);
2035 struct ata_device *dev = ap->link.device; 2045 struct ata_device *dev = ap->link.device;
2036 u32 devslp, dm, dito, mdat, deto; 2046 u32 devslp, dm, dito, mdat, deto;
@@ -2094,7 +2104,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
2094 PORT_DEVSLP_ADSE); 2104 PORT_DEVSLP_ADSE);
2095 writel(devslp, port_mmio + PORT_DEVSLP); 2105 writel(devslp, port_mmio + PORT_DEVSLP);
2096 2106
2097 ahci_start_engine(ap); 2107 hpriv->start_engine(ap);
2098 2108
2099 /* enable device sleep feature for the drive */ 2109 /* enable device sleep feature for the drive */
2100 err_mask = ata_dev_set_feature(dev, 2110 err_mask = ata_dev_set_feature(dev,
@@ -2106,6 +2116,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
2106 2116
2107static void ahci_enable_fbs(struct ata_port *ap) 2117static void ahci_enable_fbs(struct ata_port *ap)
2108{ 2118{
2119 struct ahci_host_priv *hpriv = ap->host->private_data;
2109 struct ahci_port_priv *pp = ap->private_data; 2120 struct ahci_port_priv *pp = ap->private_data;
2110 void __iomem *port_mmio = ahci_port_base(ap); 2121 void __iomem *port_mmio = ahci_port_base(ap);
2111 u32 fbs; 2122 u32 fbs;
@@ -2134,11 +2145,12 @@ static void ahci_enable_fbs(struct ata_port *ap)
2134 } else 2145 } else
2135 dev_err(ap->host->dev, "Failed to enable FBS\n"); 2146 dev_err(ap->host->dev, "Failed to enable FBS\n");
2136 2147
2137 ahci_start_engine(ap); 2148 hpriv->start_engine(ap);
2138} 2149}
2139 2150
2140static void ahci_disable_fbs(struct ata_port *ap) 2151static void ahci_disable_fbs(struct ata_port *ap)
2141{ 2152{
2153 struct ahci_host_priv *hpriv = ap->host->private_data;
2142 struct ahci_port_priv *pp = ap->private_data; 2154 struct ahci_port_priv *pp = ap->private_data;
2143 void __iomem *port_mmio = ahci_port_base(ap); 2155 void __iomem *port_mmio = ahci_port_base(ap);
2144 u32 fbs; 2156 u32 fbs;
@@ -2166,7 +2178,7 @@ static void ahci_disable_fbs(struct ata_port *ap)
2166 pp->fbs_enabled = false; 2178 pp->fbs_enabled = false;
2167 } 2179 }
2168 2180
2169 ahci_start_engine(ap); 2181 hpriv->start_engine(ap);
2170} 2182}
2171 2183
2172static void ahci_pmp_attach(struct ata_port *ap) 2184static void ahci_pmp_attach(struct ata_port *ap)
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 5a68b7b8f491..d4df0bf9a55a 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -402,6 +402,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
402 static const unsigned long timing[] = { 5, 100, 500}; 402 static const unsigned long timing[] = { 5, 100, 500};
403 struct ata_port *ap = link->ap; 403 struct ata_port *ap = link->ap;
404 struct ahci_port_priv *pp = ap->private_data; 404 struct ahci_port_priv *pp = ap->private_data;
405 struct ahci_host_priv *hpriv = ap->host->private_data;
405 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 406 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
406 struct ata_taskfile tf; 407 struct ata_taskfile tf;
407 bool online; 408 bool online;
@@ -430,7 +431,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
430 break; 431 break;
431 } while (!online && retry--); 432 } while (!online && retry--);
432 433
433 ahci_start_engine(ap); 434 hpriv->start_engine(ap);
434 435
435 if (online) 436 if (online)
436 *class = ahci_dev_classify(ap); 437 *class = ahci_dev_classify(ap);