summaryrefslogtreecommitdiff
path: root/components/drivers/sdio/host/sdhci-pci.c
blob: 704b1b701b2e3f42f596eb4321b5d285167aa5d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*
 * Copyright (c) 2006-2022, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-02-25     GuEe-GUI     the first version
 */

#define SDHCI_REG_BAR 0

#include "../dev_sdio_dm.h"

struct pci_sdhci_host
{
    struct rt_sdhci_host parent;
};

static const struct rt_sdhci_ops pci_sdhci_ops =
{
    .set_clock = rt_sdhci_set_clock,
    .set_bus_width = rt_sdhci_set_bus_width,
    .reset = rt_sdhci_reset,
};

static rt_err_t pci_sdhci_probe(struct rt_pci_device *pdev)
{
    rt_err_t err;
    struct rt_sdhci_host *host;
    struct pci_sdhci_host *pci_host;

    host = rt_sdhci_alloc_host(&pdev->parent, sizeof(struct pci_sdhci_host));

    if (!host)
    {
        return -RT_ENOMEM;
    }
    pci_host = rt_container_of(host, struct pci_sdhci_host, parent);

    host->ioaddr = rt_pci_iomap(pdev, SDHCI_REG_BAR);

    if (!host->ioaddr)
    {
        err = -RT_EIO;
        goto _fail;
    }

    host->irq = pdev->irq;
    host->ops = &pci_sdhci_ops;

    rt_pci_irq_unmask(pdev);
    rt_pci_set_master(pdev);

    if ((err = rt_sdhci_set_and_add_host(host)))
    {
        goto _fail;
    }

    pdev->parent.user_data = pci_host;

    return RT_EOK;

_fail:
    if (host->ioaddr)
    {
        rt_iounmap(host->ioaddr);
    }

    rt_sdhci_free_host(host);

    return err;
}

static rt_err_t pci_sdhci_remove(struct rt_pci_device *pdev)
{
    rt_bool_t dead;
    struct rt_sdhci_host *host;
    struct pci_sdhci_host *pci_host = pdev->parent.user_data;

    host = &pci_host->parent;

    /* INTx is shared, don't mask all */
    rt_hw_interrupt_umask(pdev->irq);
    rt_pci_irq_mask(pdev);
    rt_pci_clear_master(pdev);

    dead = (HWREG32(host->ioaddr + RT_SDHCI_INT_STATUS) == 0xffffffff);

    rt_sdhci_uninit_host(host, dead);

    rt_iounmap(host->ioaddr);
    rt_sdhci_free_host(host);

    return RT_EOK;
}

static const struct rt_pci_device_id pci_sdhci_pci_ids[] =
{
    { RT_PCI_DEVICE_ID(PCI_VENDOR_ID_REDHAT, 0x0007), },
    { RT_PCI_DEVICE_CLASS(PCIS_SYSTEM_SDHCI, ~0) },
    { /* sentinel */ }
};

static struct rt_pci_driver pci_sdhci_driver =
{
    .name = "sdhci-pci",

    .ids = pci_sdhci_pci_ids,
    .probe = pci_sdhci_probe,
    .remove = pci_sdhci_remove,
};
RT_PCI_DRIVER_EXPORT(pci_sdhci_driver);