diff options
| -rw-r--r-- | drivers/ata/ahci.h | 3 | ||||
| -rw-r--r-- | drivers/ata/ahci_da850.c | 175 | ||||
| -rw-r--r-- | drivers/ata/libahci.c | 18 |
3 files changed, 174 insertions, 22 deletions
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 0cc08f892fea..5db6ab261643 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h | |||
| @@ -398,6 +398,9 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, | |||
| 398 | int pmp, unsigned long deadline, | 398 | int pmp, unsigned long deadline, |
| 399 | int (*check_ready)(struct ata_link *link)); | 399 | int (*check_ready)(struct ata_link *link)); |
| 400 | 400 | ||
| 401 | int ahci_do_hardreset(struct ata_link *link, unsigned int *class, | ||
| 402 | unsigned long deadline, bool *online); | ||
| 403 | |||
| 401 | unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); | 404 | unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); |
| 402 | int ahci_stop_engine(struct ata_port *ap); | 405 | int ahci_stop_engine(struct ata_port *ap); |
| 403 | void ahci_start_fis_rx(struct ata_port *ap); | 406 | void ahci_start_fis_rx(struct ata_port *ap); |
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c index 267a3d3e79f4..1a50cd3b4233 100644 --- a/drivers/ata/ahci_da850.c +++ b/drivers/ata/ahci_da850.c | |||
| @@ -16,7 +16,8 @@ | |||
| 16 | #include <linux/ahci_platform.h> | 16 | #include <linux/ahci_platform.h> |
| 17 | #include "ahci.h" | 17 | #include "ahci.h" |
| 18 | 18 | ||
| 19 | #define DRV_NAME "ahci_da850" | 19 | #define DRV_NAME "ahci_da850" |
| 20 | #define HARDRESET_RETRIES 5 | ||
| 20 | 21 | ||
| 21 | /* SATA PHY Control Register offset from AHCI base */ | 22 | /* SATA PHY Control Register offset from AHCI base */ |
| 22 | #define SATA_P0PHYCR_REG 0x178 | 23 | #define SATA_P0PHYCR_REG 0x178 |
| @@ -28,17 +29,8 @@ | |||
| 28 | #define SATA_PHY_TXSWING(x) ((x) << 19) | 29 | #define SATA_PHY_TXSWING(x) ((x) << 19) |
| 29 | #define SATA_PHY_ENPLL(x) ((x) << 31) | 30 | #define SATA_PHY_ENPLL(x) ((x) << 31) |
| 30 | 31 | ||
| 31 | /* | ||
| 32 | * The multiplier needed for 1.5GHz PLL output. | ||
| 33 | * | ||
| 34 | * NOTE: This is currently hardcoded to be suitable for 100MHz crystal | ||
| 35 | * frequency (which is used by DA850 EVM board) and may need to be changed | ||
| 36 | * if you would like to use this driver on some other board. | ||
| 37 | */ | ||
| 38 | #define DA850_SATA_CLK_MULTIPLIER 7 | ||
| 39 | |||
| 40 | static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg, | 32 | static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg, |
| 41 | void __iomem *ahci_base) | 33 | void __iomem *ahci_base, u32 mpy) |
| 42 | { | 34 | { |
| 43 | unsigned int val; | 35 | unsigned int val; |
| 44 | 36 | ||
| @@ -47,18 +39,122 @@ static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg, | |||
| 47 | val &= ~BIT(0); | 39 | val &= ~BIT(0); |
| 48 | writel(val, pwrdn_reg); | 40 | writel(val, pwrdn_reg); |
| 49 | 41 | ||
| 50 | val = SATA_PHY_MPY(DA850_SATA_CLK_MULTIPLIER + 1) | SATA_PHY_LOS(1) | | 42 | val = SATA_PHY_MPY(mpy) | SATA_PHY_LOS(1) | SATA_PHY_RXCDR(4) | |
| 51 | SATA_PHY_RXCDR(4) | SATA_PHY_RXEQ(1) | SATA_PHY_TXSWING(3) | | 43 | SATA_PHY_RXEQ(1) | SATA_PHY_TXSWING(3) | SATA_PHY_ENPLL(1); |
| 52 | SATA_PHY_ENPLL(1); | ||
| 53 | 44 | ||
| 54 | writel(val, ahci_base + SATA_P0PHYCR_REG); | 45 | writel(val, ahci_base + SATA_P0PHYCR_REG); |
| 55 | } | 46 | } |
| 56 | 47 | ||
| 48 | static u32 ahci_da850_calculate_mpy(unsigned long refclk_rate) | ||
| 49 | { | ||
| 50 | u32 pll_output = 1500000000, needed; | ||
| 51 | |||
| 52 | /* | ||
| 53 | * We need to determine the value of the multiplier (MPY) bits. | ||
| 54 | * In order to include the 12.5 multiplier we need to first divide | ||
| 55 | * the refclk rate by ten. | ||
| 56 | * | ||
| 57 | * __div64_32() turned out to be unreliable, sometimes returning | ||
| 58 | * false results. | ||
| 59 | */ | ||
| 60 | WARN((refclk_rate % 10) != 0, "refclk must be divisible by 10"); | ||
| 61 | needed = pll_output / (refclk_rate / 10); | ||
| 62 | |||
| 63 | /* | ||
| 64 | * What we have now is (multiplier * 10). | ||
| 65 | * | ||
| 66 | * Let's determine the actual register value we need to write. | ||
| 67 | */ | ||
| 68 | |||
| 69 | switch (needed) { | ||
| 70 | case 50: | ||
| 71 | return 0x1; | ||
| 72 | case 60: | ||
| 73 | return 0x2; | ||
| 74 | case 80: | ||
| 75 | return 0x4; | ||
| 76 | case 100: | ||
| 77 | return 0x5; | ||
| 78 | case 120: | ||
| 79 | return 0x6; | ||
| 80 | case 125: | ||
| 81 | return 0x7; | ||
| 82 | case 150: | ||
| 83 | return 0x8; | ||
| 84 | case 200: | ||
| 85 | return 0x9; | ||
| 86 | case 250: | ||
| 87 | return 0xa; | ||
| 88 | default: | ||
| 89 | /* | ||
| 90 | * We should have divided evenly - if not, return an invalid | ||
| 91 | * value. | ||
| 92 | */ | ||
| 93 | return 0; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | static int ahci_da850_softreset(struct ata_link *link, | ||
| 98 | unsigned int *class, unsigned long deadline) | ||
| 99 | { | ||
| 100 | int pmp, ret; | ||
| 101 | |||
| 102 | pmp = sata_srst_pmp(link); | ||
| 103 | |||
| 104 | /* | ||
| 105 | * There's an issue with the SATA controller on da850 SoCs: if we | ||
| 106 | * enable Port Multiplier support, but the drive is connected directly | ||
| 107 | * to the board, it can't be detected. As a workaround: if PMP is | ||
| 108 | * enabled, we first call ahci_do_softreset() and pass it the result of | ||
| 109 | * sata_srst_pmp(). If this call fails, we retry with pmp = 0. | ||
| 110 | */ | ||
| 111 | ret = ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready); | ||
| 112 | if (pmp && ret == -EBUSY) | ||
| 113 | return ahci_do_softreset(link, class, 0, | ||
| 114 | deadline, ahci_check_ready); | ||
| 115 | |||
| 116 | return ret; | ||
| 117 | } | ||
| 118 | |||
| 119 | static int ahci_da850_hardreset(struct ata_link *link, | ||
| 120 | unsigned int *class, unsigned long deadline) | ||
| 121 | { | ||
| 122 | int ret, retry = HARDRESET_RETRIES; | ||
| 123 | bool online; | ||
| 124 | |||
| 125 | /* | ||
| 126 | * In order to correctly service the LCD controller of the da850 SoC, | ||
| 127 | * we increased the PLL0 frequency to 456MHz from the default 300MHz. | ||
| 128 | * | ||
| 129 | * This made the SATA controller unstable and the hardreset operation | ||
| 130 | * does not always succeed the first time. Before really giving up to | ||
| 131 | * bring up the link, retry the reset a couple times. | ||
| 132 | */ | ||
| 133 | do { | ||
| 134 | ret = ahci_do_hardreset(link, class, deadline, &online); | ||
| 135 | if (online) | ||
| 136 | return ret; | ||
| 137 | } while (retry--); | ||
| 138 | |||
| 139 | return ret; | ||
| 140 | } | ||
| 141 | |||
| 142 | static struct ata_port_operations ahci_da850_port_ops = { | ||
| 143 | .inherits = &ahci_platform_ops, | ||
| 144 | .softreset = ahci_da850_softreset, | ||
| 145 | /* | ||
| 146 | * No need to override .pmp_softreset - it's only used for actual | ||
| 147 | * PMP-enabled ports. | ||
| 148 | */ | ||
| 149 | .hardreset = ahci_da850_hardreset, | ||
| 150 | .pmp_hardreset = ahci_da850_hardreset, | ||
| 151 | }; | ||
| 152 | |||
| 57 | static const struct ata_port_info ahci_da850_port_info = { | 153 | static const struct ata_port_info ahci_da850_port_info = { |
| 58 | .flags = AHCI_FLAG_COMMON, | 154 | .flags = AHCI_FLAG_COMMON, |
| 59 | .pio_mask = ATA_PIO4, | 155 | .pio_mask = ATA_PIO4, |
| 60 | .udma_mask = ATA_UDMA6, | 156 | .udma_mask = ATA_UDMA6, |
| 61 | .port_ops = &ahci_platform_ops, | 157 | .port_ops = &ahci_da850_port_ops, |
| 62 | }; | 158 | }; |
| 63 | 159 | ||
| 64 | static struct scsi_host_template ahci_platform_sht = { | 160 | static struct scsi_host_template ahci_platform_sht = { |
| @@ -69,14 +165,52 @@ static int ahci_da850_probe(struct platform_device *pdev) | |||
| 69 | { | 165 | { |
| 70 | struct device *dev = &pdev->dev; | 166 | struct device *dev = &pdev->dev; |
| 71 | struct ahci_host_priv *hpriv; | 167 | struct ahci_host_priv *hpriv; |
| 72 | struct resource *res; | ||
| 73 | void __iomem *pwrdn_reg; | 168 | void __iomem *pwrdn_reg; |
| 169 | struct resource *res; | ||
| 170 | struct clk *clk; | ||
| 171 | u32 mpy; | ||
| 74 | int rc; | 172 | int rc; |
| 75 | 173 | ||
| 76 | hpriv = ahci_platform_get_resources(pdev); | 174 | hpriv = ahci_platform_get_resources(pdev); |
| 77 | if (IS_ERR(hpriv)) | 175 | if (IS_ERR(hpriv)) |
| 78 | return PTR_ERR(hpriv); | 176 | return PTR_ERR(hpriv); |
| 79 | 177 | ||
| 178 | /* | ||
| 179 | * Internally ahci_platform_get_resources() calls clk_get(dev, NULL) | ||
| 180 | * when trying to obtain the functional clock. This SATA controller | ||
| 181 | * uses two clocks for which we specify two connection ids. If we don't | ||
| 182 | * have the functional clock at this point - call clk_get() again with | ||
| 183 | * con_id = "fck". | ||
| 184 | */ | ||
| 185 | if (!hpriv->clks[0]) { | ||
| 186 | clk = clk_get(dev, "fck"); | ||
| 187 | if (IS_ERR(clk)) | ||
| 188 | return PTR_ERR(clk); | ||
| 189 | |||
| 190 | hpriv->clks[0] = clk; | ||
| 191 | } | ||
| 192 | |||
| 193 | /* | ||
| 194 | * The second clock used by ahci-da850 is the external REFCLK. If we | ||
| 195 | * didn't get it from ahci_platform_get_resources(), let's try to | ||
| 196 | * specify the con_id in clk_get(). | ||
| 197 | */ | ||
| 198 | if (!hpriv->clks[1]) { | ||
| 199 | clk = clk_get(dev, "refclk"); | ||
| 200 | if (IS_ERR(clk)) { | ||
| 201 | dev_err(dev, "unable to obtain the reference clock"); | ||
| 202 | return -ENODEV; | ||
| 203 | } | ||
| 204 | |||
| 205 | hpriv->clks[1] = clk; | ||
| 206 | } | ||
| 207 | |||
| 208 | mpy = ahci_da850_calculate_mpy(clk_get_rate(hpriv->clks[1])); | ||
| 209 | if (mpy == 0) { | ||
| 210 | dev_err(dev, "invalid REFCLK multiplier value: 0x%x", mpy); | ||
| 211 | return -EINVAL; | ||
| 212 | } | ||
| 213 | |||
| 80 | rc = ahci_platform_enable_resources(hpriv); | 214 | rc = ahci_platform_enable_resources(hpriv); |
| 81 | if (rc) | 215 | if (rc) |
| 82 | return rc; | 216 | return rc; |
| @@ -89,7 +223,7 @@ static int ahci_da850_probe(struct platform_device *pdev) | |||
| 89 | if (!pwrdn_reg) | 223 | if (!pwrdn_reg) |
| 90 | goto disable_resources; | 224 | goto disable_resources; |
| 91 | 225 | ||
| 92 | da850_sata_init(dev, pwrdn_reg, hpriv->mmio); | 226 | da850_sata_init(dev, pwrdn_reg, hpriv->mmio, mpy); |
| 93 | 227 | ||
| 94 | rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info, | 228 | rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info, |
| 95 | &ahci_platform_sht); | 229 | &ahci_platform_sht); |
| @@ -105,11 +239,18 @@ disable_resources: | |||
| 105 | static SIMPLE_DEV_PM_OPS(ahci_da850_pm_ops, ahci_platform_suspend, | 239 | static SIMPLE_DEV_PM_OPS(ahci_da850_pm_ops, ahci_platform_suspend, |
| 106 | ahci_platform_resume); | 240 | ahci_platform_resume); |
| 107 | 241 | ||
| 242 | static const struct of_device_id ahci_da850_of_match[] = { | ||
| 243 | { .compatible = "ti,da850-ahci", }, | ||
| 244 | { }, | ||
| 245 | }; | ||
| 246 | MODULE_DEVICE_TABLE(of, ahci_da850_of_match); | ||
| 247 | |||
| 108 | static struct platform_driver ahci_da850_driver = { | 248 | static struct platform_driver ahci_da850_driver = { |
| 109 | .probe = ahci_da850_probe, | 249 | .probe = ahci_da850_probe, |
| 110 | .remove = ata_platform_remove_one, | 250 | .remove = ata_platform_remove_one, |
| 111 | .driver = { | 251 | .driver = { |
| 112 | .name = DRV_NAME, | 252 | .name = DRV_NAME, |
| 253 | .of_match_table = ahci_da850_of_match, | ||
| 113 | .pm = &ahci_da850_pm_ops, | 254 | .pm = &ahci_da850_pm_ops, |
| 114 | }, | 255 | }, |
| 115 | }; | 256 | }; |
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index ee7db3119b18..3159f9e66d8f 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c | |||
| @@ -1519,8 +1519,8 @@ static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class, | |||
| 1519 | return rc; | 1519 | return rc; |
| 1520 | } | 1520 | } |
| 1521 | 1521 | ||
| 1522 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, | 1522 | int ahci_do_hardreset(struct ata_link *link, unsigned int *class, |
| 1523 | unsigned long deadline) | 1523 | unsigned long deadline, bool *online) |
| 1524 | { | 1524 | { |
| 1525 | const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); | 1525 | const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); |
| 1526 | struct ata_port *ap = link->ap; | 1526 | struct ata_port *ap = link->ap; |
| @@ -1528,7 +1528,6 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class, | |||
| 1528 | struct ahci_host_priv *hpriv = ap->host->private_data; | 1528 | struct ahci_host_priv *hpriv = ap->host->private_data; |
| 1529 | u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; | 1529 | u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; |
| 1530 | struct ata_taskfile tf; | 1530 | struct ata_taskfile tf; |
| 1531 | bool online; | ||
| 1532 | int rc; | 1531 | int rc; |
| 1533 | 1532 | ||
| 1534 | DPRINTK("ENTER\n"); | 1533 | DPRINTK("ENTER\n"); |
| @@ -1540,17 +1539,26 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class, | |||
| 1540 | tf.command = ATA_BUSY; | 1539 | tf.command = ATA_BUSY; |
| 1541 | ata_tf_to_fis(&tf, 0, 0, d2h_fis); | 1540 | ata_tf_to_fis(&tf, 0, 0, d2h_fis); |
| 1542 | 1541 | ||
| 1543 | rc = sata_link_hardreset(link, timing, deadline, &online, | 1542 | rc = sata_link_hardreset(link, timing, deadline, online, |
| 1544 | ahci_check_ready); | 1543 | ahci_check_ready); |
| 1545 | 1544 | ||
| 1546 | hpriv->start_engine(ap); | 1545 | hpriv->start_engine(ap); |
| 1547 | 1546 | ||
| 1548 | if (online) | 1547 | if (*online) |
| 1549 | *class = ahci_dev_classify(ap); | 1548 | *class = ahci_dev_classify(ap); |
| 1550 | 1549 | ||
| 1551 | DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); | 1550 | DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); |
| 1552 | return rc; | 1551 | return rc; |
| 1553 | } | 1552 | } |
| 1553 | EXPORT_SYMBOL_GPL(ahci_do_hardreset); | ||
| 1554 | |||
| 1555 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, | ||
| 1556 | unsigned long deadline) | ||
| 1557 | { | ||
| 1558 | bool online; | ||
| 1559 | |||
| 1560 | return ahci_do_hardreset(link, class, deadline, &online); | ||
| 1561 | } | ||
| 1554 | 1562 | ||
| 1555 | static void ahci_postreset(struct ata_link *link, unsigned int *class) | 1563 | static void ahci_postreset(struct ata_link *link, unsigned int *class) |
| 1556 | { | 1564 | { |
