sdhci: Support SDHCI devices on PCI

Support for PCI devices following the "SD Host Controller Simplified
Specification Version 2.00" spec.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Kevin O'Connor 2014-12-08 18:10:33 -05:00 committed by Paolo Bonzini
parent ece5e5bfa1
commit 224d10ff5a
3 changed files with 54 additions and 1 deletions

View File

@ -30,3 +30,5 @@ CONFIG_IPACK=y
CONFIG_WDT_IB6300ESB=y CONFIG_WDT_IB6300ESB=y
CONFIG_PCI_TESTDEV=y CONFIG_PCI_TESTDEV=y
CONFIG_NVME_PCI=y CONFIG_NVME_PCI=y
CONFIG_SD=y
CONFIG_SDHCI=y

View File

@ -1220,6 +1220,49 @@ static Property sdhci_properties[] = {
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}; };
static int sdhci_pci_init(PCIDevice *dev)
{
SDHCIState *s = PCI_SDHCI(dev);
dev->config[PCI_CLASS_PROG] = 0x01; /* Standard Host supported DMA */
dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
sdhci_initfn(s);
s->buf_maxsz = sdhci_get_fifolen(s);
s->fifo_buffer = g_malloc0(s->buf_maxsz);
s->irq = pci_allocate_irq(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci",
SDHC_REGISTERS_MAP_SIZE);
pci_register_bar(dev, 0, 0, &s->iomem);
return 0;
}
static void sdhci_pci_exit(PCIDevice *dev)
{
SDHCIState *s = PCI_SDHCI(dev);
sdhci_uninitfn(s);
}
static void sdhci_pci_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->init = sdhci_pci_init;
k->exit = sdhci_pci_exit;
k->vendor_id = PCI_VENDOR_ID_REDHAT;
k->device_id = PCI_DEVICE_ID_REDHAT_SDHCI;
k->class_id = PCI_CLASS_SYSTEM_SDHCI;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->vmsd = &sdhci_vmstate;
dc->props = sdhci_properties;
}
static const TypeInfo sdhci_pci_info = {
.name = TYPE_PCI_SDHCI,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(SDHCIState),
.class_init = sdhci_pci_class_init,
};
static void sdhci_sysbus_init(Object *obj) static void sdhci_sysbus_init(Object *obj)
{ {
SDHCIState *s = SYSBUS_SDHCI(obj); SDHCIState *s = SYSBUS_SDHCI(obj);
@ -1265,6 +1308,7 @@ static const TypeInfo sdhci_sysbus_info = {
static void sdhci_register_types(void) static void sdhci_register_types(void)
{ {
type_register_static(&sdhci_pci_info);
type_register_static(&sdhci_sysbus_info); type_register_static(&sdhci_sysbus_info);
} }

View File

@ -26,6 +26,7 @@
#define SDHCI_H #define SDHCI_H
#include "qemu-common.h" #include "qemu-common.h"
#include "hw/pci/pci.h"
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "hw/sd.h" #include "hw/sd.h"
@ -232,7 +233,10 @@ enum {
/* SD/MMC host controller state */ /* SD/MMC host controller state */
typedef struct SDHCIState { typedef struct SDHCIState {
union {
PCIDevice pcidev;
SysBusDevice busdev; SysBusDevice busdev;
};
SDState *card; SDState *card;
MemoryRegion iomem; MemoryRegion iomem;
@ -281,6 +285,9 @@ typedef struct SDHCIState {
extern const VMStateDescription sdhci_vmstate; extern const VMStateDescription sdhci_vmstate;
#define TYPE_PCI_SDHCI "sdhci-pci"
#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI)
#define TYPE_SYSBUS_SDHCI "generic-sdhci" #define TYPE_SYSBUS_SDHCI "generic-sdhci"
#define SYSBUS_SDHCI(obj) \ #define SYSBUS_SDHCI(obj) \
OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI) OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI)