Skip to content

Commit 6e435c5

Browse files
committed
[DM/FEATURE] Support ATA AHCI
Add ACHI drivers to support some old platform driver such as SATA. Signed-off-by: GuEe-GUI <[email protected]>
1 parent fed7c9a commit 6e435c5

File tree

7 files changed

+1549
-0
lines changed

7 files changed

+1549
-0
lines changed

components/drivers/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ rsource "graphic/Kconfig"
2222
rsource "hwcrypto/Kconfig"
2323
rsource "wlan/Kconfig"
2424
rsource "virtio/Kconfig"
25+
rsource "ata/Kconfig"
2526
rsource "ofw/Kconfig"
2627
rsource "pci/Kconfig"
2728
rsource "pic/Kconfig"

components/drivers/ata/Kconfig

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
menuconfig RT_USING_ATA
2+
bool "Using Advanced Technology Attachment (ATA) device drivers"
3+
depends on RT_USING_DM
4+
depends on RT_USING_BLK
5+
depends on RT_USING_DMA
6+
default n
7+
8+
config RT_ATA_AHCI
9+
bool "Advanced Host Controller Interface (AHCI)"
10+
depends on RT_USING_ATA
11+
depends on RT_USING_SCSI
12+
default y
13+
14+
config RT_ATA_AHCI_PCI
15+
bool "AHCI support on PCI bus"
16+
depends on RT_ATA_AHCI
17+
depends on RT_USING_PCI
18+
default n
19+
20+
if RT_USING_ATA
21+
osource "$(SOC_DM_ATA_DIR)/Kconfig"
22+
endif

components/drivers/ata/SConscript

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from building import *
2+
3+
group = []
4+
5+
if not GetDepend(['RT_USING_ATA']):
6+
Return('group')
7+
8+
cwd = GetCurrentDir()
9+
CPPPATH = [cwd + '/../include']
10+
11+
src = []
12+
13+
if GetDepend(['RT_ATA_AHCI']):
14+
src += ['ahci.c']
15+
16+
if GetDepend(['RT_ATA_AHCI_PCI']):
17+
src += ['ahci-pci.c']
18+
19+
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
20+
21+
Return('group')

components/drivers/ata/ahci-pci.c

+206
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/*
2+
* Copyright (c) 2006-2023, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2023-02-25 GuEe-GUI the first version
9+
*/
10+
11+
#include <rtthread.h>
12+
#include <rtdevice.h>
13+
14+
#define AHCI_REG_BAR 5
15+
16+
struct pci_ahci_quirk
17+
{
18+
int bar_idx;
19+
rt_bool_t bar_offset;
20+
21+
const struct rt_ahci_ops *ops;
22+
};
23+
24+
struct pci_ahci_host
25+
{
26+
struct rt_ahci_host parent;
27+
const struct pci_ahci_quirk *quirk;
28+
29+
rt_bool_t is_msi;
30+
};
31+
32+
#define raw_to_pci_ahci_host(raw) rt_container_of(raw, struct pci_ahci_host, parent)
33+
34+
static rt_err_t pci_ahci_init(struct rt_ahci_host *host)
35+
{
36+
struct rt_pci_device *pdev;
37+
38+
pdev = rt_container_of(host->parent.dev, struct rt_pci_device, parent);
39+
40+
if (pdev->vendor == PCI_VENDOR_ID_JMICRON)
41+
{
42+
rt_pci_write_config_u8(pdev, 0x41, 0xa1);
43+
}
44+
45+
return RT_EOK;
46+
}
47+
48+
static const struct rt_ahci_ops pci_ahci_ops =
49+
{
50+
.host_init = pci_ahci_init,
51+
};
52+
53+
static rt_err_t pci_ahci_intel_init(struct rt_ahci_host *host)
54+
{
55+
rt_uint16_t val;
56+
struct rt_pci_device *pdev;
57+
58+
pdev = rt_container_of(host->parent.dev, struct rt_pci_device, parent);
59+
60+
rt_pci_read_config_u16(pdev, 0x92, &val);
61+
rt_pci_write_config_u16(pdev, 0x92, val & ~0xf);
62+
63+
rt_thread_mdelay(10);
64+
rt_pci_write_config_u16(pdev, 0x92, val | 0xf);
65+
66+
return RT_EOK;
67+
}
68+
69+
static const struct rt_ahci_ops pci_ahci_intel_ops =
70+
{
71+
.host_init = pci_ahci_intel_init,
72+
};
73+
74+
static rt_err_t pci_ahci_probe(struct rt_pci_device *pdev)
75+
{
76+
rt_err_t err;
77+
int bar_idx;
78+
struct rt_ahci_host *ahci;
79+
struct pci_ahci_host *pci_ahci = rt_calloc(1, sizeof(*pci_ahci));
80+
const struct pci_ahci_quirk *quirk = pdev->id->data;
81+
82+
if (!pci_ahci)
83+
{
84+
return -RT_ENOMEM;
85+
}
86+
87+
pci_ahci->quirk = quirk;
88+
ahci = &pci_ahci->parent;
89+
ahci->parent.dev = &pdev->parent;
90+
91+
bar_idx = quirk && quirk->bar_offset ? quirk->bar_idx : AHCI_REG_BAR;
92+
93+
ahci->regs = rt_pci_iomap(pdev, bar_idx);
94+
95+
if (!ahci->regs)
96+
{
97+
err = -RT_EIO;
98+
goto _fail;
99+
}
100+
101+
ahci->ops = quirk && quirk->ops ? quirk->ops : &pci_ahci_ops;
102+
103+
if (rt_pci_msi_enable(pdev) > 0)
104+
{
105+
pci_ahci->is_msi = RT_TRUE;
106+
}
107+
else
108+
{
109+
rt_pci_irq_unmask(pdev);
110+
}
111+
ahci->irq = pdev->irq;
112+
113+
rt_pci_set_master(pdev);
114+
115+
if ((err = rt_ahci_host_register(ahci)))
116+
{
117+
goto _disable;
118+
}
119+
120+
pdev->parent.user_data = pci_ahci;
121+
122+
return RT_EOK;
123+
124+
_disable:
125+
if (pci_ahci->is_msi)
126+
{
127+
rt_pci_msix_disable(pdev);
128+
}
129+
else
130+
{
131+
rt_pci_irq_mask(pdev);
132+
}
133+
rt_pci_clear_master(pdev);
134+
rt_iounmap(ahci->regs);
135+
136+
_fail:
137+
rt_free(pci_ahci);
138+
139+
return err;
140+
}
141+
142+
static rt_err_t pci_ahci_remove(struct rt_pci_device *pdev)
143+
{
144+
struct rt_ahci_host *ahci;
145+
struct pci_ahci_host *pci_ahci = pdev->parent.user_data;
146+
147+
ahci = &pci_ahci->parent;
148+
149+
rt_ahci_host_unregister(ahci);
150+
151+
if (pci_ahci->is_msi)
152+
{
153+
rt_pci_msi_disable(pdev);
154+
}
155+
else
156+
{
157+
/* INTx is shared, don't mask all */
158+
rt_hw_interrupt_umask(pdev->irq);
159+
rt_pci_irq_mask(pdev);
160+
}
161+
162+
rt_pci_clear_master(pdev);
163+
164+
rt_iounmap(ahci->regs);
165+
rt_free(pci_ahci);
166+
167+
return RT_EOK;
168+
}
169+
170+
static rt_err_t pci_ahci_shutdown(struct rt_pci_device *pdev)
171+
{
172+
return pci_ahci_remove(pdev);
173+
}
174+
175+
static struct pci_ahci_quirk intel_quirk =
176+
{
177+
.ops = &pci_ahci_intel_ops,
178+
};
179+
180+
static struct pci_ahci_quirk cavium_sata_quirk =
181+
{
182+
.bar_idx = 0,
183+
.bar_offset = RT_TRUE,
184+
};
185+
186+
static const struct rt_pci_device_id pci_ahci_ids[] =
187+
{
188+
{ RT_PCI_DEVICE_ID(PCI_VENDOR_ID_INTEL, 0x2922), .data = &intel_quirk },
189+
{ RT_PCI_DEVICE_ID(PCI_VENDOR_ID_ASMEDIA, 0x0611) },
190+
{ RT_PCI_DEVICE_ID(PCI_VENDOR_ID_MARVELL, 0x6121) },
191+
{ RT_PCI_DEVICE_ID(PCI_VENDOR_ID_MARVELL, 0x6145) },
192+
{ RT_PCI_DEVICE_ID(PCI_VENDOR_ID_CAVIUM, 0xa01c), .data = &cavium_sata_quirk },
193+
{ RT_PCI_DEVICE_CLASS(PCIS_STORAGE_SATA_AHCI, ~0) },
194+
{ /* sentinel */ }
195+
};
196+
197+
static struct rt_pci_driver pci_ahci_driver =
198+
{
199+
.name = "ahci-pci",
200+
201+
.ids = pci_ahci_ids,
202+
.probe = pci_ahci_probe,
203+
.remove = pci_ahci_remove,
204+
.shutdown = pci_ahci_shutdown,
205+
};
206+
RT_PCI_DRIVER_EXPORT(pci_ahci_driver);

0 commit comments

Comments
 (0)