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