aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2017-02-16 11:14:07 -0500
committerArnd Bergmann <arnd@arndb.de>2017-02-16 11:14:07 -0500
commitdb27dd05b1da6e658494a2570680f8d0ddbc578c (patch)
treeca1326af658938687081a47a6b16a8cbdedf38ae
parentd2aff02f92598f8361f488424cdf1053edf3081d (diff)
parentcdf0ead3747200d527f37170d3fdd41e368f88b0 (diff)
Merge tag 'davinci-for-v4.11/drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci into next/drivers
Merge "Driver updates for SATA support on DA850." from Sekhar Nori: These have been acked by SATA maintainer Tejun Heo. Tejun preferred these be queued through ARM-SoC because of the dependencies with platform code. * tag 'davinci-for-v4.11/drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci: sata: ahci-da850: un-hardcode the MPY bits sata: ahci-da850: add a workaround for controller instability sata: ahci: export ahci_do_hardreset() locally sata: ahci-da850: implement a workaround for the softreset quirk sata: ahci-da850: add device tree match table sata: ahci-da850: get the sata clock using a connection id
-rw-r--r--drivers/ata/ahci.h3
-rw-r--r--drivers/ata/ahci_da850.c175
-rw-r--r--drivers/ata/libahci.c18
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
401int ahci_do_hardreset(struct ata_link *link, unsigned int *class,
402 unsigned long deadline, bool *online);
403
401unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); 404unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
402int ahci_stop_engine(struct ata_port *ap); 405int ahci_stop_engine(struct ata_port *ap);
403void ahci_start_fis_rx(struct ata_port *ap); 406void 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
40static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg, 32static 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
48static 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
97static 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
119static 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
142static 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
57static const struct ata_port_info ahci_da850_port_info = { 153static 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
64static struct scsi_host_template ahci_platform_sht = { 160static 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:
105static SIMPLE_DEV_PM_OPS(ahci_da850_pm_ops, ahci_platform_suspend, 239static SIMPLE_DEV_PM_OPS(ahci_da850_pm_ops, ahci_platform_suspend,
106 ahci_platform_resume); 240 ahci_platform_resume);
107 241
242static const struct of_device_id ahci_da850_of_match[] = {
243 { .compatible = "ti,da850-ahci", },
244 { },
245};
246MODULE_DEVICE_TABLE(of, ahci_da850_of_match);
247
108static struct platform_driver ahci_da850_driver = { 248static 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
1522static int ahci_hardreset(struct ata_link *link, unsigned int *class, 1522int 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}
1553EXPORT_SYMBOL_GPL(ahci_do_hardreset);
1554
1555static 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
1555static void ahci_postreset(struct ata_link *link, unsigned int *class) 1563static void ahci_postreset(struct ata_link *link, unsigned int *class)
1556{ 1564{