-
Notifications
You must be signed in to change notification settings - Fork 5.4k
[dm][ufs] support Universal Flash Storage (UFS) #11302
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| menuconfig RT_USING_UFS | ||
| bool "Using Universal Flash Storage (UFS) device drivers" | ||
| depends on RT_USING_DM | ||
| depends on RT_USING_DMA | ||
| depends on RT_SCSI_SD | ||
| default n | ||
|
|
||
| config RT_UFS_PCI | ||
| bool "UFS support on PCI bus" | ||
| depends on RT_USING_UFS | ||
| depends on RT_USING_PCI | ||
| default n | ||
|
|
||
| if RT_USING_UFS | ||
| osource "$(SOC_DM_UFS_DIR)/Kconfig" | ||
| endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| from building import * | ||
|
|
||
| group = [] | ||
|
|
||
| if not GetDepend(['RT_USING_UFS']): | ||
| Return('group') | ||
|
|
||
| cwd = GetCurrentDir() | ||
| CPPPATH = [cwd + '/../include'] | ||
|
|
||
| src = ['ufs.c', 'ufs_pm.c'] | ||
|
|
||
| if GetDepend(['RT_UFS_PCI']): | ||
| src += ['ufs-pci.c'] | ||
|
|
||
| group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) | ||
|
|
||
| Return('group') |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,116 @@ | ||||||||||||||||||
| /* | ||||||||||||||||||
| * Copyright (c) 2006-2023, RT-Thread Development Team | ||||||||||||||||||
| * | ||||||||||||||||||
| * SPDX-License-Identifier: Apache-2.0 | ||||||||||||||||||
| * | ||||||||||||||||||
| * Change Logs: | ||||||||||||||||||
| * Date Author Notes | ||||||||||||||||||
| * 2023-02-25 GuEe-GUI the first version | ||||||||||||||||||
| */ | ||||||||||||||||||
|
|
||||||||||||||||||
| #include <rtthread.h> | ||||||||||||||||||
| #include <rtdevice.h> | ||||||||||||||||||
|
|
||||||||||||||||||
| #define UFS_REG_BAR 0 | ||||||||||||||||||
|
|
||||||||||||||||||
| struct pci_ufs_quirk | ||||||||||||||||||
| { | ||||||||||||||||||
| const struct rt_ufs_ops *ops; | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| struct pci_ufs_host | ||||||||||||||||||
| { | ||||||||||||||||||
| struct rt_ufs_host parent; | ||||||||||||||||||
| const struct pci_ufs_quirk *quirk; | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| static const struct rt_ufs_ops pci_ufs_std_ops = | ||||||||||||||||||
| { | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| static rt_err_t pci_ufs_probe(struct rt_pci_device *pdev) | ||||||||||||||||||
| { | ||||||||||||||||||
| rt_err_t err; | ||||||||||||||||||
| struct rt_ufs_host *ufs; | ||||||||||||||||||
| struct pci_ufs_host *pci_ufs = rt_calloc(1, sizeof(*pci_ufs)); | ||||||||||||||||||
| const struct pci_ufs_quirk *quirk = pdev->id->data; | ||||||||||||||||||
|
|
||||||||||||||||||
| if (!pci_ufs) | ||||||||||||||||||
| { | ||||||||||||||||||
| return -RT_ENOMEM; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| pci_ufs->quirk = quirk; | ||||||||||||||||||
| ufs = &pci_ufs->parent; | ||||||||||||||||||
| ufs->parent.dev = &pdev->parent; | ||||||||||||||||||
| ufs->regs = rt_pci_iomap(pdev, UFS_REG_BAR); | ||||||||||||||||||
| ufs->irq = pdev->irq; | ||||||||||||||||||
|
|
||||||||||||||||||
| if (!ufs->regs) | ||||||||||||||||||
| { | ||||||||||||||||||
| err = -RT_EIO; | ||||||||||||||||||
| goto _fail; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| ufs->ops = quirk ? quirk->ops : &pci_ufs_std_ops; | ||||||||||||||||||
|
|
||||||||||||||||||
| rt_pci_irq_unmask(pdev); | ||||||||||||||||||
| rt_pci_set_master(pdev); | ||||||||||||||||||
|
|
||||||||||||||||||
| if ((err = rt_ufs_host_register(ufs))) | ||||||||||||||||||
| { | ||||||||||||||||||
| goto _fail; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| pdev->parent.user_data = pci_ufs; | ||||||||||||||||||
|
|
||||||||||||||||||
| return RT_EOK; | ||||||||||||||||||
|
|
||||||||||||||||||
| _fail: | ||||||||||||||||||
|
||||||||||||||||||
| _fail: | |
| _fail: | |
| if (ufs->regs) | |
| { | |
| rt_pci_irq_mask(pdev); | |
| rt_pci_clear_master(pdev); | |
| rt_iounmap(ufs->regs); | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[bug/缺陷]: pci_ufs_probe() chooses ufs->ops as
quirk ? quirk->ops : &pci_ufs_std_ops, which can set ops to NULL when quirk exists but quirk->ops is not provided.English: Please match the pattern used by AHCI/NVMe PCI drivers:
ufs->ops = (quirk && quirk->ops) ? quirk->ops : &pci_ufs_std_ops;to avoid rt_ufs_host_register() failing/crashing.中文:pci_ufs_probe() 使用
quirk ? quirk->ops : &pci_ufs_std_ops选择 ops,当 quirk 存在但 quirk->ops 未设置时会把 ops 置为 NULL,导致后续注册失败/潜在崩溃。建议参考 AHCI/NVMe PCI 驱动的写法:(quirk && quirk->ops) ? quirk->ops : &pci_ufs_std_ops。