Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/ahci/ahci_fsl_fdt.c
39507 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2020 Alstom Group
5
* Copyright (c) 2020 Semihalf
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*/
28
29
/* AHCI controller driver for NXP QorIQ Layerscape SoCs. */
30
31
#include <sys/cdefs.h>
32
#include <sys/stdint.h>
33
#include <sys/stddef.h>
34
#include <sys/param.h>
35
#include <sys/systm.h>
36
#include <sys/kernel.h>
37
#include <sys/bus.h>
38
#include <sys/module.h>
39
#include <sys/sysctl.h>
40
#include <sys/rman.h>
41
#include <sys/unistd.h>
42
43
#include <machine/bus.h>
44
#include <machine/resource.h>
45
46
#include <dev/ofw/ofw_bus.h>
47
#include <dev/ofw/ofw_bus_subr.h>
48
49
#include <dev/ahci/ahci.h>
50
51
#include <dev/clk/clk.h>
52
53
#define AHCI_FSL_REG_PHY1 0xa8
54
#define AHCI_FSL_REG_PHY2 0xac
55
#define AHCI_FSL_REG_PHY3 0xb0
56
#define AHCI_FSL_REG_PHY4 0xb4
57
#define AHCI_FSL_REG_PHY5 0xb8
58
#define AHCI_FSL_REG_AXICC 0xbc
59
#define AHCI_FSL_REG_PTC 0xc8
60
61
#define AHCI_FSL_LS1021A_AXICC 0xc0
62
63
#define AHCI_FSL_REG_PHY1_TTA_MASK 0x0001ffff
64
#define AHCI_FSL_REG_PHY1_SNM (1 << 17)
65
#define AHCI_FSL_REG_PHY1_SNR (1 << 18)
66
#define AHCI_FSL_REG_PHY1_FPR (1 << 20)
67
#define AHCI_FSL_REG_PHY1_PBPS_LBP 0
68
#define AHCI_FSL_REG_PHY1_PBPS_LFTP (0x01 << 21)
69
#define AHCI_FSL_REG_PHY1_PBPS_MFTP (0x02 << 21)
70
#define AHCI_FSL_REG_PHY1_PBPS_HFTP (0x03 << 21)
71
#define AHCI_FSL_REG_PHY1_PBPS_PRBS (0x04 << 21)
72
#define AHCI_FSL_REG_PHY1_PBPS_BIST (0x05 << 21)
73
#define AHCI_FSL_REG_PHY1_PBPE (1 << 24)
74
#define AHCI_FSL_REG_PHY1_PBCE (1 << 25)
75
#define AHCI_FSL_REG_PHY1_PBPNA (1 << 26)
76
#define AHCI_FSL_REG_PHY1_STB (1 << 27)
77
#define AHCI_FSL_REG_PHY1_PSSO (1 << 28)
78
#define AHCI_FSL_REG_PHY1_PSS (1 << 29)
79
#define AHCI_FSL_REG_PHY1_ERSN (1 << 30)
80
#define AHCI_FSL_REG_PHY1_ESDF (1 << 31)
81
82
#define AHCI_FSL_REG_PHY_MASK 0xff
83
84
#define AHCI_FSL_PHY2_CIBGMN_SHIFT 0
85
#define AHCI_FSL_PHY2_CIBGMX_SHIFT 8
86
#define AHCI_FSL_PHY2_CIBGN_SHIFT 16
87
#define AHCI_FSL_PHY2_CINMP_SHIFT 24
88
89
90
#define AHCI_FSL_PHY3_CWBGMN_SHIFT 0
91
#define AHCI_FSL_PHY3_CWBGMX_SHIFT 8
92
#define AHCI_FSL_PHY3_CWBGN_SHIFT 16
93
#define AHCI_FSL_PHY3_CWNMP_SHIFT 24
94
95
/* Only in LS1021A */
96
#define AHCI_FSL_PHY4_BMX_SHIFT 0
97
#define AHCI_FSL_PHY4_BNM_SHIFT 8
98
#define AHCI_FSL_PHY4_SFD_SHIFT 16
99
#define AHCI_FSL_PHY4_PTST_SHIFT 24
100
101
/* Only in LS1021A */
102
#define AHCI_FSL_PHY5_RIT_SHIFT 0
103
#define AHCI_FSL_PHY5_RCT_SHIFT 20
104
105
#define AHCI_FSL_REG_PTC_RXWM_MASK 0x0000007f
106
#define AHCI_FSL_REG_PTC_ENBD (1 << 8)
107
#define AHCI_FSL_REG_PTC_ITM (1 << 9)
108
109
#define AHCI_FSL_REG_PHY1_CFG \
110
((0x1fffe & AHCI_FSL_REG_PHY1_TTA_MASK) | \
111
AHCI_FSL_REG_PHY1_SNM | AHCI_FSL_REG_PHY1_PSS | AHCI_FSL_REG_PHY1_ESDF)
112
113
#define AHCI_FSL_REG_PHY2_CFG \
114
((0x1f << AHCI_FSL_PHY2_CIBGMN_SHIFT) | \
115
(0x4d << AHCI_FSL_PHY2_CIBGMX_SHIFT) | \
116
(0x18 << AHCI_FSL_PHY2_CIBGN_SHIFT) | \
117
(0x28 << AHCI_FSL_PHY2_CINMP_SHIFT))
118
119
#define AHCI_FSL_REG_PHY2_CFG_LS1021A \
120
((0x14 << AHCI_FSL_PHY2_CIBGMN_SHIFT) | \
121
(0x34 << AHCI_FSL_PHY2_CIBGMX_SHIFT) | \
122
(0x18 << AHCI_FSL_PHY2_CIBGN_SHIFT) | \
123
(0x28 << AHCI_FSL_PHY2_CINMP_SHIFT))
124
125
#define AHCI_FSL_REG_PHY3_CFG \
126
((0x09 << AHCI_FSL_PHY3_CWBGMN_SHIFT) | \
127
(0x15 << AHCI_FSL_PHY3_CWBGMX_SHIFT) | \
128
(0x08 << AHCI_FSL_PHY3_CWBGN_SHIFT) | \
129
(0x0e << AHCI_FSL_PHY3_CWNMP_SHIFT))
130
131
#define AHCI_FSL_REG_PHY3_CFG_LS1021A \
132
((0x06 << AHCI_FSL_PHY3_CWBGMN_SHIFT) | \
133
(0x0e << AHCI_FSL_PHY3_CWBGMX_SHIFT) | \
134
(0x08 << AHCI_FSL_PHY3_CWBGN_SHIFT) | \
135
(0x0e << AHCI_FSL_PHY3_CWNMP_SHIFT))
136
137
#define AHCI_FSL_REG_PHY4_CFG_LS1021A \
138
((0x0b << AHCI_FSL_PHY4_BMX_SHIFT) | \
139
(0x08 << AHCI_FSL_PHY4_BNM_SHIFT) | \
140
(0x4a << AHCI_FSL_PHY4_SFD_SHIFT) | \
141
(0x06 << AHCI_FSL_PHY4_PTST_SHIFT))
142
143
#define AHCI_FSL_REG_PHY5_CFG_LS1021A \
144
((0x86470 << AHCI_FSL_PHY5_RIT_SHIFT) | \
145
(0x2aa << AHCI_FSL_PHY5_RCT_SHIFT))
146
147
/* Bit 27 enabled so value of reserved bits remains as in documentation. */
148
#define AHCI_FSL_REG_PTC_CFG \
149
((0x29 & AHCI_FSL_REG_PTC_RXWM_MASK) | (1 << 27))
150
151
#define AHCI_FSL_REG_AXICC_CFG 0x3fffffff
152
153
154
#define AHCI_FSL_REG_ECC 0x0
155
#define AHCI_FSL_REG_ECC_LS1021A 0x00020000
156
#define AHCI_FSL_REG_ECC_LS1043A 0x80000000
157
#define AHCI_FSL_REG_ECC_LS1028A 0x40000000
158
159
160
#define QORIQ_AHCI_LS1021A 1
161
#define QORIQ_AHCI_LS1028A 2
162
#define QORIQ_AHCI_LS1043A 3
163
#define QORIQ_AHCI_LS2080A 4
164
#define QORIQ_AHCI_LS1046A 5
165
#define QORIQ_AHCI_LS1088A 6
166
#define QORIQ_AHCI_LS2088A 7
167
#define QORIQ_AHCI_LX2160A 8
168
169
struct ahci_fsl_fdt_controller {
170
struct ahci_controller ctlr; /* Must be the first field. */
171
int soc_type;
172
struct resource *r_ecc;
173
int r_ecc_rid;
174
};
175
176
static const struct ofw_compat_data ahci_fsl_fdt_compat_data[] = {
177
{"fsl,ls1021a-ahci", QORIQ_AHCI_LS1021A},
178
{"fsl,ls1028a-ahci", QORIQ_AHCI_LS1028A},
179
{"fsl,ls1043a-ahci", QORIQ_AHCI_LS1043A},
180
{"fsl,ls2080a-ahci", QORIQ_AHCI_LS2080A},
181
{"fsl,ls1046a-ahci", QORIQ_AHCI_LS1046A},
182
{"fsl,ls1088a-ahci", QORIQ_AHCI_LS1088A},
183
{"fsl,ls2088a-ahci", QORIQ_AHCI_LS2088A},
184
{"fsl,lx2160a-ahci", QORIQ_AHCI_LX2160A},
185
{NULL, 0}
186
};
187
188
static bool ecc_inited;
189
190
static int
191
ahci_fsl_fdt_ecc_init(struct ahci_fsl_fdt_controller *ctrl)
192
{
193
uint32_t val;
194
195
switch (ctrl->soc_type) {
196
case QORIQ_AHCI_LS2080A:
197
case QORIQ_AHCI_LS2088A:
198
return (0);
199
200
case QORIQ_AHCI_LS1021A:
201
if (!ecc_inited && ctrl->r_ecc == NULL)
202
return (ENXIO);
203
if (!ecc_inited)
204
ATA_OUTL(ctrl->r_ecc, AHCI_FSL_REG_ECC,
205
AHCI_FSL_REG_ECC_LS1021A);
206
break;
207
208
case QORIQ_AHCI_LS1043A:
209
case QORIQ_AHCI_LS1046A:
210
if (!ecc_inited && ctrl->r_ecc == NULL)
211
return (ENXIO);
212
if (!ecc_inited) {
213
val = ATA_INL(ctrl->r_ecc, AHCI_FSL_REG_ECC);
214
val = AHCI_FSL_REG_ECC_LS1043A;
215
ATA_OUTL(ctrl->r_ecc, AHCI_FSL_REG_ECC, val);
216
}
217
break;
218
219
case QORIQ_AHCI_LS1028A:
220
case QORIQ_AHCI_LS1088A:
221
case QORIQ_AHCI_LX2160A:
222
if (!ecc_inited && ctrl->r_ecc == NULL)
223
return (ENXIO);
224
if (!ecc_inited) {
225
226
val = ATA_INL(ctrl->r_ecc, AHCI_FSL_REG_ECC);
227
val |= AHCI_FSL_REG_ECC_LS1028A;
228
ATA_OUTL(ctrl->r_ecc, AHCI_FSL_REG_ECC, val);
229
}
230
break;
231
232
default:
233
panic("Unimplemented SOC type: %d", ctrl->soc_type);
234
}
235
236
ecc_inited = true;
237
return (0);
238
}
239
240
static void
241
ahci_fsl_fdt_phy_init(struct ahci_fsl_fdt_controller *ctrl)
242
{
243
struct ahci_controller *ahci;
244
245
ahci = &ctrl->ctlr;
246
if (ctrl->soc_type == QORIQ_AHCI_LS1021A) {
247
ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY1,
248
AHCI_FSL_REG_PHY1_CFG);
249
ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY2,
250
AHCI_FSL_REG_PHY2_CFG_LS1021A);
251
ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY3,
252
AHCI_FSL_REG_PHY3_CFG_LS1021A);
253
ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY4,
254
AHCI_FSL_REG_PHY4_CFG_LS1021A);
255
ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY5,
256
AHCI_FSL_REG_PHY5_CFG_LS1021A);
257
ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PTC,
258
AHCI_FSL_REG_PTC_CFG);
259
260
if (ctrl->ctlr.dma_coherent)
261
ATA_OUTL(ahci->r_mem, AHCI_FSL_LS1021A_AXICC,
262
AHCI_FSL_REG_AXICC_CFG);
263
} else {
264
ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY1,
265
AHCI_FSL_REG_PHY1_CFG);
266
ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY2,
267
AHCI_FSL_REG_PHY2_CFG);
268
ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY3,
269
AHCI_FSL_REG_PHY3_CFG);
270
ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PTC,
271
AHCI_FSL_REG_PTC_CFG);
272
273
if (ctrl->ctlr.dma_coherent)
274
ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_AXICC,
275
AHCI_FSL_REG_AXICC_CFG);
276
}
277
}
278
279
static int
280
ahci_fsl_fdt_probe(device_t dev)
281
{
282
if (!ofw_bus_status_okay(dev))
283
return (ENXIO);
284
285
if (!ofw_bus_search_compatible(dev, ahci_fsl_fdt_compat_data)->ocd_data)
286
return (ENXIO);
287
288
device_set_desc(dev, "NXP QorIQ Layerscape AHCI controller");
289
return (BUS_PROBE_DEFAULT);
290
}
291
292
static int
293
ahci_fsl_fdt_attach(device_t dev)
294
{
295
struct ahci_fsl_fdt_controller *ctlr;
296
struct ahci_controller *ahci;
297
phandle_t node;
298
clk_t clock;
299
int ret;
300
301
node = ofw_bus_get_node(dev);
302
ctlr = device_get_softc(dev);
303
ctlr->soc_type =
304
ofw_bus_search_compatible(dev, ahci_fsl_fdt_compat_data)->ocd_data;
305
ahci = &ctlr->ctlr;
306
ahci->dev = dev;
307
ahci->r_rid = 0;
308
ahci->quirks = AHCI_Q_NOPMP;
309
310
ahci->dma_coherent = OF_hasprop(node, "dma-coherent");
311
312
ret = clk_get_by_ofw_index(dev, node, 0, &clock);
313
if (ret != 0) {
314
device_printf(dev, "No clock found.\n");
315
return (ENXIO);
316
}
317
318
ret = clk_enable(clock);
319
if (ret !=0) {
320
device_printf(dev, "Could not enable clock.\n");
321
return (ENXIO);
322
}
323
324
if (OF_hasprop(node, "reg-names") && ofw_bus_find_string_index(node,
325
"reg-names", "ahci", &ahci->r_rid)) {
326
device_printf(dev, "Could not locate 'ahci' string in the "
327
"'reg-names' property");
328
return (ENOENT);
329
}
330
331
ahci->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
332
&ahci->r_rid, RF_ACTIVE);
333
if (!ahci->r_mem) {
334
device_printf(dev,
335
"Could not allocate resources for controller\n");
336
return (ENOMEM);
337
}
338
339
ret = ofw_bus_find_string_index(node, "reg-names", "sata-ecc",
340
&ctlr->r_ecc_rid);
341
if (ret == 0) {
342
ctlr->r_ecc = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
343
&ctlr->r_ecc_rid, RF_ACTIVE| RF_SHAREABLE);
344
if (!ctlr->r_ecc) {
345
device_printf(dev,
346
"Could not allocate resources for controller\n");
347
ret = ENOMEM;
348
goto err_free_mem;
349
}
350
} else if (ret != ENOENT) {
351
device_printf(dev, "Could not locate 'sata-ecc' string in "
352
"the 'reg-names' property");
353
goto err_free_mem;
354
}
355
356
ret = ahci_fsl_fdt_ecc_init(ctlr);
357
if (ret != 0) {
358
device_printf(dev, "Could not initialize 'ecc' registers");
359
goto err_free_mem;
360
}
361
362
/* Setup controller defaults. */
363
ahci->numirqs = 1;
364
ahci_fsl_fdt_phy_init(ctlr);
365
366
/* Reset controller. */
367
ret = ahci_ctlr_reset(dev);
368
if (ret)
369
goto err_free_mem;
370
371
ret = ahci_attach(dev);
372
if (ret) {
373
device_printf(dev,
374
"Could not initialize AHCI, with error: %d\n", ret);
375
goto err_free_ecc;
376
}
377
return (0);
378
379
err_free_mem:
380
bus_free_resource(dev, SYS_RES_MEMORY, ahci->r_mem);
381
err_free_ecc:
382
if (ctlr->r_ecc)
383
bus_free_resource(dev, SYS_RES_MEMORY, ctlr->r_ecc);
384
return (ret);
385
}
386
387
static int
388
ahci_fsl_fdt_detach(device_t dev)
389
{
390
struct ahci_fsl_fdt_controller *ctlr;
391
392
ctlr = device_get_softc(dev);
393
if (ctlr->r_ecc)
394
bus_free_resource(dev, SYS_RES_MEMORY, ctlr->r_ecc);
395
return ahci_detach(dev);
396
}
397
398
static const device_method_t ahci_fsl_fdt_methods[] = {
399
DEVMETHOD(device_probe, ahci_fsl_fdt_probe),
400
DEVMETHOD(device_attach, ahci_fsl_fdt_attach),
401
DEVMETHOD(device_detach, ahci_fsl_fdt_detach),
402
DEVMETHOD(bus_alloc_resource, ahci_alloc_resource),
403
DEVMETHOD(bus_release_resource, ahci_release_resource),
404
DEVMETHOD(bus_setup_intr, ahci_setup_intr),
405
DEVMETHOD(bus_teardown_intr, ahci_teardown_intr),
406
DEVMETHOD(bus_print_child, ahci_print_child),
407
DEVMETHOD(bus_child_location, ahci_child_location),
408
DEVMETHOD(bus_get_dma_tag, ahci_get_dma_tag),
409
DEVMETHOD_END
410
};
411
412
static driver_t ahci_fsl_fdt_driver = {
413
"ahci",
414
ahci_fsl_fdt_methods,
415
sizeof(struct ahci_fsl_fdt_controller),
416
};
417
418
DRIVER_MODULE(ahci_fsl, simplebus, ahci_fsl_fdt_driver, NULL, NULL);
419
DRIVER_MODULE(ahci_fsl, ofwbus, ahci_fsl_fdt_driver, NULL, NULL);
420
421