From 534f502c6cc4a8b59c6ec98f4e3321e4194b7d02 Mon Sep 17 00:00:00 2001 From: GuEe-GUI <2991707448@qq.com> Date: Wed, 22 Jul 2026 22:19:39 +0800 Subject: [PATCH] [dm][ata] support DW AHCI Signed-off-by: GuEe-GUI <2991707448@qq.com> --- components/drivers/ata/Kconfig | 7 ++ components/drivers/ata/SConscript | 3 + components/drivers/ata/ahci-dw.c | 172 ++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100755 components/drivers/ata/ahci-dw.c diff --git a/components/drivers/ata/Kconfig b/components/drivers/ata/Kconfig index 4b5cee5627c..1cd836e684e 100644 --- a/components/drivers/ata/Kconfig +++ b/components/drivers/ata/Kconfig @@ -11,6 +11,13 @@ config RT_ATA_AHCI depends on RT_USING_SCSI default y +config RT_ATA_AHCI_DW + bool "AHCI support on Synopsys DWC" + depends on RT_ATA_AHCI + depends on RT_USING_CLK + depends on RT_USING_PHYE + default n + config RT_ATA_AHCI_PCI bool "AHCI support on PCI bus" depends on RT_ATA_AHCI diff --git a/components/drivers/ata/SConscript b/components/drivers/ata/SConscript index f4a0922a84d..4c2c6e137f8 100644 --- a/components/drivers/ata/SConscript +++ b/components/drivers/ata/SConscript @@ -13,6 +13,9 @@ src = [] if GetDepend(['RT_ATA_AHCI']): src += ['ahci.c'] + if GetDepend(['RT_ATA_AHCI_DW']): + src += ['ahci-dw.c'] + if GetDepend(['RT_ATA_AHCI_PCI']): src += ['ahci-pci.c'] diff --git a/components/drivers/ata/ahci-dw.c b/components/drivers/ata/ahci-dw.c new file mode 100755 index 00000000000..c3d35af92b1 --- /dev/null +++ b/components/drivers/ata/ahci-dw.c @@ -0,0 +1,172 @@ +/* + * 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 +#include +#include + +#define DBG_TAG "ahci.dwc" +#define DBG_LVL DBG_INFO +#include + +struct dwc_ahci_host +{ + struct rt_ahci_host parent; + + struct rt_clk_array *clk_arr; + struct rt_phye *sata_phy; +}; + +static const struct rt_ahci_ops dwc_ahci_ops = +{ +}; + +static void dwc_ahci_free(struct dwc_ahci_host *dwc_ahci) +{ + if (!rt_is_err_or_null(dwc_ahci->sata_phy)) + { + rt_phye_put(dwc_ahci->sata_phy); + } + + if (dwc_ahci->parent.regs) + { + rt_iounmap(dwc_ahci->parent.regs); + } + + rt_free(dwc_ahci); +} + +static rt_err_t dwc_ahci_probe(struct rt_platform_device *pdev) +{ + rt_err_t err; + struct rt_ahci_host *ahci; + struct rt_device *dev = &pdev->parent; + struct dwc_ahci_host *dwc_ahci = rt_calloc(1, sizeof(*dwc_ahci)); + + if (!dwc_ahci) + { + return -RT_ENOMEM; + } + + ahci = &dwc_ahci->parent; + ahci->parent.dev = dev; + + ahci->regs = rt_dm_dev_iomap(dev, 0); + + if (!ahci->regs) + { + err = -RT_EIO; + goto _fail; + } + + ahci->irq = rt_dm_dev_get_irq(dev, 0); + + if (ahci->irq < 0) + { + err = ahci->irq; + goto _fail; + } + + dwc_ahci->clk_arr = rt_clk_get_array(dev); + + if (rt_is_err(dwc_ahci->clk_arr)) + { + LOG_E("Missing CLK"); + err = rt_ptr_err(dwc_ahci->clk_arr); + + goto _fail; + } + + dwc_ahci->sata_phy = rt_phye_get_by_name(dev, "sata-phy"); + + if (rt_is_err(dwc_ahci->sata_phy)) + { + LOG_E("Missing PHY"); + err = rt_ptr_err(dwc_ahci->sata_phy); + + goto _fail; + } + + if ((err = rt_clk_array_prepare_enable(dwc_ahci->clk_arr))) + { + goto _fail; + } + + if ((err = rt_phye_init(dwc_ahci->sata_phy))) + { + goto _disable_clk; + } + + if ((err = rt_phye_power_on(dwc_ahci->sata_phy))) + { + goto _phy_exit; + } + + ahci->ops = &dwc_ahci_ops; + + if ((err = rt_ahci_host_register(ahci))) + { + goto _phy_power_off; + } + + dev->user_data = dwc_ahci; + + return RT_EOK; + +_phy_power_off: + rt_phye_power_off(dwc_ahci->sata_phy); + +_phy_exit: + rt_phye_exit(dwc_ahci->sata_phy); + +_disable_clk: + rt_clk_array_disable_unprepare(dwc_ahci->clk_arr); + +_fail: + dwc_ahci_free(dwc_ahci); + + return err; +} + +static rt_err_t dwc_ahci_remove(struct rt_platform_device *pdev) +{ + struct dwc_ahci_host *dwc_ahci = pdev->parent.user_data; + + rt_phye_exit(dwc_ahci->sata_phy); + rt_phye_power_off(dwc_ahci->sata_phy); + + rt_clk_array_disable_unprepare(dwc_ahci->clk_arr); + + dwc_ahci_free(dwc_ahci); + + return RT_EOK; +} + +static rt_err_t dwc_ahci_shutdown(struct rt_platform_device *pdev) +{ + return dwc_ahci_remove(pdev); +} + +static const struct rt_ofw_node_id dwc_ahci_ofw_ids[] = +{ + { .compatible = "snps,dwc-ahci" }, + { /* sentinel */ } +}; + +static struct rt_platform_driver ahci_dwc_driver = +{ + .name = "ahci-dwc", + .ids = dwc_ahci_ofw_ids, + + .probe = dwc_ahci_probe, + .remove = dwc_ahci_remove, + .shutdown = dwc_ahci_shutdown, +}; +RT_PLATFORM_DRIVER_EXPORT(ahci_dwc_driver);