diff options
author | Arnd Bergmann <arnd@arndb.de> | 2017-02-16 11:14:07 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2017-02-16 11:14:07 -0500 |
commit | db27dd05b1da6e658494a2570680f8d0ddbc578c (patch) | |
tree | ca1326af658938687081a47a6b16a8cbdedf38ae | |
parent | d2aff02f92598f8361f488424cdf1053edf3081d (diff) | |
parent | cdf0ead3747200d527f37170d3fdd41e368f88b0 (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.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 | { |