aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libahci.c
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/libahci.c
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/libahci.c')
-rw-r--r--drivers/ata/libahci.c26
1 files changed, 19 insertions, 7 deletions
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)