]>
Commit | Line | Data |
---|---|---|
a73ed350 SG |
1 | /* |
2 | * Copyright (C) 2015 Xilinx, Inc. | |
3 | * CEVA AHCI SATA platform driver | |
4 | * | |
5 | * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms and conditions of the GNU General Public License, | |
9 | * version 2, as published by the Free Software Foundation. | |
10 | * | |
11 | * This program is distributed in the hope it will be useful, but WITHOUT | |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 | * more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License along with | |
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #include <linux/ahci_platform.h> | |
21 | #include <linux/kernel.h> | |
22 | #include <linux/libata.h> | |
23 | #include <linux/module.h> | |
24 | #include <linux/of_device.h> | |
25 | #include <linux/platform_device.h> | |
26 | #include "ahci.h" | |
27 | ||
28 | /* Vendor Specific Register Offsets */ | |
29 | #define AHCI_VEND_PCFG 0xA4 | |
30 | #define AHCI_VEND_PPCFG 0xA8 | |
31 | #define AHCI_VEND_PP2C 0xAC | |
32 | #define AHCI_VEND_PP3C 0xB0 | |
33 | #define AHCI_VEND_PP4C 0xB4 | |
34 | #define AHCI_VEND_PP5C 0xB8 | |
3bc867de | 35 | #define AHCI_VEND_AXICC 0xBC |
a73ed350 SG |
36 | #define AHCI_VEND_PAXIC 0xC0 |
37 | #define AHCI_VEND_PTC 0xC8 | |
38 | ||
39 | /* Vendor Specific Register bit definitions */ | |
40 | #define PAXIC_ADBW_BW64 0x1 | |
f0a559aa AKV |
41 | #define PAXIC_MAWID(i) (((i) * 2) << 4) |
42 | #define PAXIC_MARID(i) (((i) * 2) << 12) | |
43 | #define PAXIC_MARIDD(i) ((((i) * 2) + 1) << 16) | |
44 | #define PAXIC_MAWIDD(i) ((((i) * 2) + 1) << 8) | |
a73ed350 SG |
45 | #define PAXIC_OTL (0x4 << 20) |
46 | ||
3bc867de AKV |
47 | /* Register bit definitions for cache control */ |
48 | #define AXICC_ARCA_VAL (0xF << 0) | |
49 | #define AXICC_ARCF_VAL (0xF << 4) | |
50 | #define AXICC_ARCH_VAL (0xF << 8) | |
51 | #define AXICC_ARCP_VAL (0xF << 12) | |
52 | #define AXICC_AWCFD_VAL (0xF << 16) | |
53 | #define AXICC_AWCD_VAL (0xF << 20) | |
54 | #define AXICC_AWCF_VAL (0xF << 24) | |
55 | ||
a73ed350 SG |
56 | #define PCFG_TPSS_VAL (0x32 << 16) |
57 | #define PCFG_TPRS_VAL (0x2 << 12) | |
58 | #define PCFG_PAD_VAL 0x2 | |
59 | ||
60 | #define PPCFG_TTA 0x1FFFE | |
61 | #define PPCFG_PSSO_EN (1 << 28) | |
62 | #define PPCFG_PSS_EN (1 << 29) | |
63 | #define PPCFG_ESDF_EN (1 << 31) | |
64 | ||
a73ed350 SG |
65 | #define PP5C_RIT 0x60216 |
66 | #define PP5C_RCT (0x7f0 << 20) | |
67 | ||
68 | #define PTC_RX_WM_VAL 0x40 | |
69 | #define PTC_RSVD (1 << 27) | |
70 | ||
71 | #define PORT0_BASE 0x100 | |
72 | #define PORT1_BASE 0x180 | |
73 | ||
74 | /* Port Control Register Bit Definitions */ | |
e8fc8b85 | 75 | #define PORT_SCTL_SPD_GEN3 (0x3 << 4) |
a73ed350 SG |
76 | #define PORT_SCTL_SPD_GEN2 (0x2 << 4) |
77 | #define PORT_SCTL_SPD_GEN1 (0x1 << 4) | |
78 | #define PORT_SCTL_IPM (0x3 << 8) | |
79 | ||
80 | #define PORT_BASE 0x100 | |
81 | #define PORT_OFFSET 0x80 | |
82 | #define NR_PORTS 2 | |
83 | #define DRV_NAME "ahci-ceva" | |
84 | #define CEVA_FLAG_BROKEN_GEN2 1 | |
85 | ||
05e890d8 AKV |
86 | static unsigned int rx_watermark = PTC_RX_WM_VAL; |
87 | module_param(rx_watermark, uint, 0644); | |
88 | MODULE_PARM_DESC(rx_watermark, "RxWaterMark value (0 - 0x80)"); | |
89 | ||
a73ed350 SG |
90 | struct ceva_ahci_priv { |
91 | struct platform_device *ahci_pdev; | |
fe8365bb AKV |
92 | /* Port Phy2Cfg Register */ |
93 | u32 pp2c[NR_PORTS]; | |
94 | u32 pp3c[NR_PORTS]; | |
95 | u32 pp4c[NR_PORTS]; | |
96 | u32 pp5c[NR_PORTS]; | |
3bc867de AKV |
97 | /* Axi Cache Control Register */ |
98 | u32 axicc; | |
99 | bool is_cci_enabled; | |
a73ed350 SG |
100 | int flags; |
101 | }; | |
102 | ||
ff0d6377 AKV |
103 | static unsigned int ceva_ahci_read_id(struct ata_device *dev, |
104 | struct ata_taskfile *tf, u16 *id) | |
105 | { | |
106 | u32 err_mask; | |
107 | ||
108 | err_mask = ata_do_dev_read_id(dev, tf, id); | |
109 | if (err_mask) | |
110 | return err_mask; | |
111 | /* | |
112 | * Since CEVA controller does not support device sleep feature, we | |
113 | * need to clear DEVSLP (bit 8) in word78 of the IDENTIFY DEVICE data. | |
114 | */ | |
115 | id[ATA_ID_FEATURE_SUPP] &= cpu_to_le16(~(1 << 8)); | |
116 | ||
117 | return 0; | |
118 | } | |
119 | ||
a73ed350 SG |
120 | static struct ata_port_operations ahci_ceva_ops = { |
121 | .inherits = &ahci_platform_ops, | |
ff0d6377 | 122 | .read_id = ceva_ahci_read_id, |
a73ed350 SG |
123 | }; |
124 | ||
125 | static const struct ata_port_info ahci_ceva_port_info = { | |
126 | .flags = AHCI_FLAG_COMMON, | |
127 | .pio_mask = ATA_PIO4, | |
128 | .udma_mask = ATA_UDMA6, | |
129 | .port_ops = &ahci_ceva_ops, | |
130 | }; | |
131 | ||
132 | static void ahci_ceva_setup(struct ahci_host_priv *hpriv) | |
133 | { | |
134 | void __iomem *mmio = hpriv->mmio; | |
135 | struct ceva_ahci_priv *cevapriv = hpriv->plat_data; | |
136 | u32 tmp; | |
137 | int i; | |
138 | ||
a73ed350 SG |
139 | /* Set AHCI Enable */ |
140 | tmp = readl(mmio + HOST_CTL); | |
141 | tmp |= HOST_AHCI_EN; | |
142 | writel(tmp, mmio + HOST_CTL); | |
143 | ||
144 | for (i = 0; i < NR_PORTS; i++) { | |
145 | /* TPSS TPRS scalars, CISE and Port Addr */ | |
146 | tmp = PCFG_TPSS_VAL | PCFG_TPRS_VAL | (PCFG_PAD_VAL + i); | |
147 | writel(tmp, mmio + AHCI_VEND_PCFG); | |
148 | ||
6e037fb7 AKV |
149 | /* |
150 | * AXI Data bus width to 64 | |
151 | * Set Mem Addr Read, Write ID for data transfers | |
f0a559aa | 152 | * Set Mem Addr Read ID, Write ID for non-data transfers |
6e037fb7 AKV |
153 | * Transfer limit to 72 DWord |
154 | */ | |
f0a559aa AKV |
155 | tmp = PAXIC_ADBW_BW64 | PAXIC_MAWIDD(i) | PAXIC_MARIDD(i) | |
156 | PAXIC_MAWID(i) | PAXIC_MARID(i) | PAXIC_OTL; | |
6e037fb7 AKV |
157 | writel(tmp, mmio + AHCI_VEND_PAXIC); |
158 | ||
3bc867de AKV |
159 | /* Set AXI cache control register if CCi is enabled */ |
160 | if (cevapriv->is_cci_enabled) { | |
161 | tmp = readl(mmio + AHCI_VEND_AXICC); | |
162 | tmp |= AXICC_ARCA_VAL | AXICC_ARCF_VAL | | |
163 | AXICC_ARCH_VAL | AXICC_ARCP_VAL | | |
164 | AXICC_AWCFD_VAL | AXICC_AWCD_VAL | | |
165 | AXICC_AWCF_VAL; | |
166 | writel(tmp, mmio + AHCI_VEND_AXICC); | |
167 | } | |
168 | ||
a73ed350 SG |
169 | /* Port Phy Cfg register enables */ |
170 | tmp = PPCFG_TTA | PPCFG_PSS_EN | PPCFG_ESDF_EN; | |
171 | writel(tmp, mmio + AHCI_VEND_PPCFG); | |
172 | ||
173 | /* Phy Control OOB timing parameters COMINIT */ | |
fe8365bb | 174 | writel(cevapriv->pp2c[i], mmio + AHCI_VEND_PP2C); |
a73ed350 SG |
175 | |
176 | /* Phy Control OOB timing parameters COMWAKE */ | |
fe8365bb | 177 | writel(cevapriv->pp3c[i], mmio + AHCI_VEND_PP3C); |
a73ed350 SG |
178 | |
179 | /* Phy Control Burst timing setting */ | |
fe8365bb | 180 | writel(cevapriv->pp4c[i], mmio + AHCI_VEND_PP4C); |
a73ed350 SG |
181 | |
182 | /* Rate Change Timer and Retry Interval Timer setting */ | |
fe8365bb | 183 | writel(cevapriv->pp5c[i], mmio + AHCI_VEND_PP5C); |
a73ed350 SG |
184 | |
185 | /* Rx Watermark setting */ | |
05e890d8 | 186 | tmp = rx_watermark | PTC_RSVD; |
a73ed350 SG |
187 | writel(tmp, mmio + AHCI_VEND_PTC); |
188 | ||
e8fc8b85 AKV |
189 | /* Default to Gen 3 Speed and Gen 1 if Gen2 is broken */ |
190 | tmp = PORT_SCTL_SPD_GEN3 | PORT_SCTL_IPM; | |
a73ed350 SG |
191 | if (cevapriv->flags & CEVA_FLAG_BROKEN_GEN2) |
192 | tmp = PORT_SCTL_SPD_GEN1 | PORT_SCTL_IPM; | |
193 | writel(tmp, mmio + PORT_SCR_CTL + PORT_BASE + PORT_OFFSET * i); | |
194 | } | |
195 | } | |
196 | ||
197 | static struct scsi_host_template ahci_platform_sht = { | |
198 | AHCI_SHT(DRV_NAME), | |
199 | }; | |
200 | ||
201 | static int ceva_ahci_probe(struct platform_device *pdev) | |
202 | { | |
203 | struct device_node *np = pdev->dev.of_node; | |
204 | struct device *dev = &pdev->dev; | |
205 | struct ahci_host_priv *hpriv; | |
206 | struct ceva_ahci_priv *cevapriv; | |
3bc867de | 207 | enum dev_dma_attr attr; |
a73ed350 SG |
208 | int rc; |
209 | ||
210 | cevapriv = devm_kzalloc(dev, sizeof(*cevapriv), GFP_KERNEL); | |
211 | if (!cevapriv) | |
212 | return -ENOMEM; | |
213 | ||
214 | cevapriv->ahci_pdev = pdev; | |
215 | ||
216 | hpriv = ahci_platform_get_resources(pdev); | |
217 | if (IS_ERR(hpriv)) | |
218 | return PTR_ERR(hpriv); | |
219 | ||
220 | rc = ahci_platform_enable_resources(hpriv); | |
221 | if (rc) | |
222 | return rc; | |
223 | ||
224 | if (of_property_read_bool(np, "ceva,broken-gen2")) | |
225 | cevapriv->flags = CEVA_FLAG_BROKEN_GEN2; | |
226 | ||
fe8365bb AKV |
227 | /* Read OOB timing value for COMINIT from device-tree */ |
228 | if (of_property_read_u8_array(np, "ceva,p0-cominit-params", | |
229 | (u8 *)&cevapriv->pp2c[0], 4) < 0) { | |
230 | dev_warn(dev, "ceva,p0-cominit-params property not defined\n"); | |
231 | return -EINVAL; | |
232 | } | |
233 | ||
234 | if (of_property_read_u8_array(np, "ceva,p1-cominit-params", | |
235 | (u8 *)&cevapriv->pp2c[1], 4) < 0) { | |
236 | dev_warn(dev, "ceva,p1-cominit-params property not defined\n"); | |
237 | return -EINVAL; | |
238 | } | |
239 | ||
240 | /* Read OOB timing value for COMWAKE from device-tree*/ | |
241 | if (of_property_read_u8_array(np, "ceva,p0-comwake-params", | |
242 | (u8 *)&cevapriv->pp3c[0], 4) < 0) { | |
243 | dev_warn(dev, "ceva,p0-comwake-params property not defined\n"); | |
244 | return -EINVAL; | |
245 | } | |
246 | ||
247 | if (of_property_read_u8_array(np, "ceva,p1-comwake-params", | |
248 | (u8 *)&cevapriv->pp3c[1], 4) < 0) { | |
249 | dev_warn(dev, "ceva,p1-comwake-params property not defined\n"); | |
250 | return -EINVAL; | |
251 | } | |
252 | ||
253 | /* Read phy BURST timing value from device-tree */ | |
254 | if (of_property_read_u8_array(np, "ceva,p0-burst-params", | |
255 | (u8 *)&cevapriv->pp4c[0], 4) < 0) { | |
256 | dev_warn(dev, "ceva,p0-burst-params property not defined\n"); | |
257 | return -EINVAL; | |
258 | } | |
259 | ||
260 | if (of_property_read_u8_array(np, "ceva,p1-burst-params", | |
261 | (u8 *)&cevapriv->pp4c[1], 4) < 0) { | |
262 | dev_warn(dev, "ceva,p1-burst-params property not defined\n"); | |
263 | return -EINVAL; | |
264 | } | |
265 | ||
266 | /* Read phy RETRY interval timing value from device-tree */ | |
267 | if (of_property_read_u16_array(np, "ceva,p0-retry-params", | |
268 | (u16 *)&cevapriv->pp5c[0], 2) < 0) { | |
269 | dev_warn(dev, "ceva,p0-retry-params property not defined\n"); | |
270 | return -EINVAL; | |
271 | } | |
272 | ||
273 | if (of_property_read_u16_array(np, "ceva,p1-retry-params", | |
274 | (u16 *)&cevapriv->pp5c[1], 2) < 0) { | |
275 | dev_warn(dev, "ceva,p1-retry-params property not defined\n"); | |
276 | return -EINVAL; | |
277 | } | |
278 | ||
3bc867de AKV |
279 | /* |
280 | * Check if CCI is enabled for SATA. The DEV_DMA_COHERENT is returned | |
281 | * if CCI is enabled, so check for DEV_DMA_COHERENT. | |
282 | */ | |
283 | attr = device_get_dma_attr(dev); | |
284 | cevapriv->is_cci_enabled = (attr == DEV_DMA_COHERENT); | |
285 | ||
a73ed350 SG |
286 | hpriv->plat_data = cevapriv; |
287 | ||
288 | /* CEVA specific initialization */ | |
289 | ahci_ceva_setup(hpriv); | |
290 | ||
291 | rc = ahci_platform_init_host(pdev, hpriv, &ahci_ceva_port_info, | |
292 | &ahci_platform_sht); | |
293 | if (rc) | |
294 | goto disable_resources; | |
295 | ||
296 | return 0; | |
297 | ||
298 | disable_resources: | |
299 | ahci_platform_disable_resources(hpriv); | |
300 | return rc; | |
301 | } | |
302 | ||
303 | static int __maybe_unused ceva_ahci_suspend(struct device *dev) | |
304 | { | |
26bf3b66 | 305 | return ahci_platform_suspend(dev); |
a73ed350 SG |
306 | } |
307 | ||
308 | static int __maybe_unused ceva_ahci_resume(struct device *dev) | |
309 | { | |
26bf3b66 AKV |
310 | struct ata_host *host = dev_get_drvdata(dev); |
311 | struct ahci_host_priv *hpriv = host->private_data; | |
312 | int rc; | |
313 | ||
314 | rc = ahci_platform_enable_resources(hpriv); | |
315 | if (rc) | |
316 | return rc; | |
317 | ||
318 | /* Configure CEVA specific config before resuming HBA */ | |
319 | ahci_ceva_setup(hpriv); | |
320 | ||
321 | rc = ahci_platform_resume_host(dev); | |
322 | if (rc) | |
323 | goto disable_resources; | |
324 | ||
325 | /* We resumed so update PM runtime state */ | |
326 | pm_runtime_disable(dev); | |
327 | pm_runtime_set_active(dev); | |
328 | pm_runtime_enable(dev); | |
329 | ||
330 | return 0; | |
331 | ||
332 | disable_resources: | |
333 | ahci_platform_disable_resources(hpriv); | |
334 | ||
335 | return rc; | |
a73ed350 SG |
336 | } |
337 | ||
338 | static SIMPLE_DEV_PM_OPS(ahci_ceva_pm_ops, ceva_ahci_suspend, ceva_ahci_resume); | |
339 | ||
340 | static const struct of_device_id ceva_ahci_of_match[] = { | |
341 | { .compatible = "ceva,ahci-1v84" }, | |
342 | {}, | |
343 | }; | |
344 | MODULE_DEVICE_TABLE(of, ceva_ahci_of_match); | |
345 | ||
346 | static struct platform_driver ceva_ahci_driver = { | |
347 | .probe = ceva_ahci_probe, | |
348 | .remove = ata_platform_remove_one, | |
349 | .driver = { | |
350 | .name = DRV_NAME, | |
351 | .of_match_table = ceva_ahci_of_match, | |
352 | .pm = &ahci_ceva_pm_ops, | |
353 | }, | |
354 | }; | |
355 | module_platform_driver(ceva_ahci_driver); | |
356 | ||
357 | MODULE_DESCRIPTION("CEVA AHCI SATA platform driver"); | |
358 | MODULE_AUTHOR("Xilinx Inc."); | |
359 | MODULE_LICENSE("GPL v2"); |