Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions components/drivers/ata/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions components/drivers/ata/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -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']

Expand Down
172 changes: 172 additions & 0 deletions components/drivers/ata/ahci-dw.c
Original file line number Diff line number Diff line change
@@ -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 <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>

#define DBG_TAG "ahci.dwc"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

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);
Loading