Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/ata/ahci_ceva.c
26278 views
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
};
92
93
static unsigned int ceva_ahci_read_id(struct ata_device *dev,
94
struct ata_taskfile *tf, __le16 *id)
95
{
96
u32 err_mask;
97
98
err_mask = ata_do_dev_read_id(dev, tf, id);
99
if (err_mask)
100
return err_mask;
101
/*
102
* Since CEVA controller does not support device sleep feature, we
103
* need to clear DEVSLP (bit 8) in word78 of the IDENTIFY DEVICE data.
104
*/
105
id[ATA_ID_FEATURE_SUPP] &= cpu_to_le16(~(1 << 8));
106
107
return 0;
108
}
109
110
static struct ata_port_operations ahci_ceva_ops = {
111
.inherits = &ahci_platform_ops,
112
.read_id = ceva_ahci_read_id,
113
};
114
115
static const struct ata_port_info ahci_ceva_port_info = {
116
.flags = AHCI_FLAG_COMMON,
117
.pio_mask = ATA_PIO4,
118
.udma_mask = ATA_UDMA6,
119
.port_ops = &ahci_ceva_ops,
120
};
121
122
static void ahci_ceva_setup(struct ahci_host_priv *hpriv)
123
{
124
void __iomem *mmio = hpriv->mmio;
125
struct ceva_ahci_priv *cevapriv = hpriv->plat_data;
126
u32 tmp;
127
int i;
128
129
/* Set AHCI Enable */
130
tmp = readl(mmio + HOST_CTL);
131
tmp |= HOST_AHCI_EN;
132
writel(tmp, mmio + HOST_CTL);
133
134
for (i = 0; i < NR_PORTS; i++) {
135
/* TPSS TPRS scalars, CISE and Port Addr */
136
tmp = PCFG_TPSS_VAL | PCFG_TPRS_VAL | (PCFG_PAD_VAL + i);
137
writel(tmp, mmio + AHCI_VEND_PCFG);
138
139
/*
140
* AXI Data bus width to 64
141
* Set Mem Addr Read, Write ID for data transfers
142
* Set Mem Addr Read ID, Write ID for non-data transfers
143
* Transfer limit to 72 DWord
144
*/
145
tmp = PAXIC_ADBW_BW64 | PAXIC_MAWIDD(i) | PAXIC_MARIDD(i) |
146
PAXIC_MAWID(i) | PAXIC_MARID(i) | PAXIC_OTL;
147
writel(tmp, mmio + AHCI_VEND_PAXIC);
148
149
/* Set AXI cache control register if CCi is enabled */
150
if (cevapriv->is_cci_enabled) {
151
tmp = readl(mmio + AHCI_VEND_AXICC);
152
tmp |= AXICC_ARCA_VAL | AXICC_ARCF_VAL |
153
AXICC_ARCH_VAL | AXICC_ARCP_VAL |
154
AXICC_AWCFD_VAL | AXICC_AWCD_VAL |
155
AXICC_AWCF_VAL;
156
writel(tmp, mmio + AHCI_VEND_AXICC);
157
}
158
159
/* Port Phy Cfg register enables */
160
tmp = PPCFG_TTA | PPCFG_PSS_EN | PPCFG_ESDF_EN;
161
writel(tmp, mmio + AHCI_VEND_PPCFG);
162
163
/* Phy Control OOB timing parameters COMINIT */
164
writel(cevapriv->pp2c[i], mmio + AHCI_VEND_PP2C);
165
166
/* Phy Control OOB timing parameters COMWAKE */
167
writel(cevapriv->pp3c[i], mmio + AHCI_VEND_PP3C);
168
169
/* Phy Control Burst timing setting */
170
writel(cevapriv->pp4c[i], mmio + AHCI_VEND_PP4C);
171
172
/* Rate Change Timer and Retry Interval Timer setting */
173
writel(cevapriv->pp5c[i], mmio + AHCI_VEND_PP5C);
174
175
/* Rx Watermark setting */
176
tmp = rx_watermark | PTC_RSVD;
177
writel(tmp, mmio + AHCI_VEND_PTC);
178
179
/* Default to Gen 3 Speed and Gen 1 if Gen2 is broken */
180
tmp = PORT_SCTL_SPD_GEN3 | PORT_SCTL_IPM;
181
if (cevapriv->flags & CEVA_FLAG_BROKEN_GEN2)
182
tmp = PORT_SCTL_SPD_GEN1 | PORT_SCTL_IPM;
183
writel(tmp, mmio + PORT_SCR_CTL + PORT_BASE + PORT_OFFSET * i);
184
}
185
}
186
187
static const struct scsi_host_template ahci_platform_sht = {
188
AHCI_SHT(DRV_NAME),
189
};
190
191
static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
192
{
193
int rc, i;
194
195
rc = ahci_platform_enable_regulators(hpriv);
196
if (rc)
197
return rc;
198
199
rc = ahci_platform_enable_clks(hpriv);
200
if (rc)
201
goto disable_regulator;
202
203
/* Assert the controller reset */
204
rc = ahci_platform_assert_rsts(hpriv);
205
if (rc)
206
goto disable_clks;
207
208
for (i = 0; i < hpriv->nports; i++) {
209
if (ahci_ignore_port(hpriv, i))
210
continue;
211
212
rc = phy_init(hpriv->phys[i]);
213
if (rc)
214
goto disable_rsts;
215
}
216
217
/* De-assert the controller reset */
218
ahci_platform_deassert_rsts(hpriv);
219
220
for (i = 0; i < hpriv->nports; i++) {
221
if (ahci_ignore_port(hpriv, i))
222
continue;
223
224
rc = phy_power_on(hpriv->phys[i]);
225
if (rc) {
226
phy_exit(hpriv->phys[i]);
227
goto disable_phys;
228
}
229
}
230
231
return 0;
232
233
disable_rsts:
234
ahci_platform_deassert_rsts(hpriv);
235
236
disable_phys:
237
while (--i >= 0) {
238
phy_power_off(hpriv->phys[i]);
239
phy_exit(hpriv->phys[i]);
240
}
241
242
disable_clks:
243
ahci_platform_disable_clks(hpriv);
244
245
disable_regulator:
246
ahci_platform_disable_regulators(hpriv);
247
248
return rc;
249
}
250
251
static int ceva_ahci_probe(struct platform_device *pdev)
252
{
253
struct device_node *np = pdev->dev.of_node;
254
struct device *dev = &pdev->dev;
255
struct ahci_host_priv *hpriv;
256
struct ceva_ahci_priv *cevapriv;
257
enum dev_dma_attr attr;
258
int rc;
259
260
cevapriv = devm_kzalloc(dev, sizeof(*cevapriv), GFP_KERNEL);
261
if (!cevapriv)
262
return -ENOMEM;
263
264
cevapriv->ahci_pdev = pdev;
265
hpriv = ahci_platform_get_resources(pdev, 0);
266
if (IS_ERR(hpriv))
267
return PTR_ERR(hpriv);
268
269
hpriv->rsts = devm_reset_control_get_optional_exclusive(&pdev->dev,
270
NULL);
271
if (IS_ERR(hpriv->rsts))
272
return dev_err_probe(&pdev->dev, PTR_ERR(hpriv->rsts),
273
"failed to get reset\n");
274
275
rc = ceva_ahci_platform_enable_resources(hpriv);
276
if (rc)
277
return rc;
278
279
if (of_property_read_bool(np, "ceva,broken-gen2"))
280
cevapriv->flags = CEVA_FLAG_BROKEN_GEN2;
281
282
/* Read OOB timing value for COMINIT from device-tree */
283
if (of_property_read_u8_array(np, "ceva,p0-cominit-params",
284
(u8 *)&cevapriv->pp2c[0], 4) < 0) {
285
dev_warn(dev, "ceva,p0-cominit-params property not defined\n");
286
rc = -EINVAL;
287
goto disable_resources;
288
}
289
290
if (of_property_read_u8_array(np, "ceva,p1-cominit-params",
291
(u8 *)&cevapriv->pp2c[1], 4) < 0) {
292
dev_warn(dev, "ceva,p1-cominit-params property not defined\n");
293
rc = -EINVAL;
294
goto disable_resources;
295
}
296
297
/* Read OOB timing value for COMWAKE from device-tree*/
298
if (of_property_read_u8_array(np, "ceva,p0-comwake-params",
299
(u8 *)&cevapriv->pp3c[0], 4) < 0) {
300
dev_warn(dev, "ceva,p0-comwake-params property not defined\n");
301
rc = -EINVAL;
302
goto disable_resources;
303
}
304
305
if (of_property_read_u8_array(np, "ceva,p1-comwake-params",
306
(u8 *)&cevapriv->pp3c[1], 4) < 0) {
307
dev_warn(dev, "ceva,p1-comwake-params property not defined\n");
308
rc = -EINVAL;
309
goto disable_resources;
310
}
311
312
/* Read phy BURST timing value from device-tree */
313
if (of_property_read_u8_array(np, "ceva,p0-burst-params",
314
(u8 *)&cevapriv->pp4c[0], 4) < 0) {
315
dev_warn(dev, "ceva,p0-burst-params property not defined\n");
316
rc = -EINVAL;
317
goto disable_resources;
318
}
319
320
if (of_property_read_u8_array(np, "ceva,p1-burst-params",
321
(u8 *)&cevapriv->pp4c[1], 4) < 0) {
322
dev_warn(dev, "ceva,p1-burst-params property not defined\n");
323
rc = -EINVAL;
324
goto disable_resources;
325
}
326
327
/* Read phy RETRY interval timing value from device-tree */
328
if (of_property_read_u16_array(np, "ceva,p0-retry-params",
329
(u16 *)&cevapriv->pp5c[0], 2) < 0) {
330
dev_warn(dev, "ceva,p0-retry-params property not defined\n");
331
rc = -EINVAL;
332
goto disable_resources;
333
}
334
335
if (of_property_read_u16_array(np, "ceva,p1-retry-params",
336
(u16 *)&cevapriv->pp5c[1], 2) < 0) {
337
dev_warn(dev, "ceva,p1-retry-params property not defined\n");
338
rc = -EINVAL;
339
goto disable_resources;
340
}
341
342
/*
343
* Check if CCI is enabled for SATA. The DEV_DMA_COHERENT is returned
344
* if CCI is enabled, so check for DEV_DMA_COHERENT.
345
*/
346
attr = device_get_dma_attr(dev);
347
cevapriv->is_cci_enabled = (attr == DEV_DMA_COHERENT);
348
349
hpriv->plat_data = cevapriv;
350
351
/* CEVA specific initialization */
352
ahci_ceva_setup(hpriv);
353
354
rc = ahci_platform_init_host(pdev, hpriv, &ahci_ceva_port_info,
355
&ahci_platform_sht);
356
if (rc)
357
goto disable_resources;
358
359
return 0;
360
361
disable_resources:
362
ahci_platform_disable_resources(hpriv);
363
return rc;
364
}
365
366
static int __maybe_unused ceva_ahci_suspend(struct device *dev)
367
{
368
return ahci_platform_suspend(dev);
369
}
370
371
static int __maybe_unused ceva_ahci_resume(struct device *dev)
372
{
373
struct ata_host *host = dev_get_drvdata(dev);
374
struct ahci_host_priv *hpriv = host->private_data;
375
int rc;
376
377
rc = ceva_ahci_platform_enable_resources(hpriv);
378
if (rc)
379
return rc;
380
381
/* Configure CEVA specific config before resuming HBA */
382
ahci_ceva_setup(hpriv);
383
384
rc = ahci_platform_resume_host(dev);
385
if (rc)
386
goto disable_resources;
387
388
/* We resumed so update PM runtime state */
389
pm_runtime_disable(dev);
390
pm_runtime_set_active(dev);
391
pm_runtime_enable(dev);
392
393
return 0;
394
395
disable_resources:
396
ahci_platform_disable_resources(hpriv);
397
398
return rc;
399
}
400
401
static SIMPLE_DEV_PM_OPS(ahci_ceva_pm_ops, ceva_ahci_suspend, ceva_ahci_resume);
402
403
static const struct of_device_id ceva_ahci_of_match[] = {
404
{ .compatible = "ceva,ahci-1v84" },
405
{ /* sentinel */ }
406
};
407
MODULE_DEVICE_TABLE(of, ceva_ahci_of_match);
408
409
static struct platform_driver ceva_ahci_driver = {
410
.probe = ceva_ahci_probe,
411
.remove = ata_platform_remove_one,
412
.driver = {
413
.name = DRV_NAME,
414
.of_match_table = ceva_ahci_of_match,
415
.pm = &ahci_ceva_pm_ops,
416
},
417
};
418
module_platform_driver(ceva_ahci_driver);
419
420
MODULE_DESCRIPTION("CEVA AHCI SATA platform driver");
421
MODULE_AUTHOR("Xilinx Inc.");
422
MODULE_LICENSE("GPL v2");
423
424