aboutsummaryrefslogtreecommitdiff
path: root/hw/sd
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2014-12-08 18:10:33 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2014-12-15 17:34:44 +0100
commit224d10ff5aea9e74a1792fc21188bc9752c43ee9 (patch)
treea0e209524110f7ccce1348f80e0a1c3655c6127c /hw/sd
parentece5e5bfa1377546d5f94e1bb04298e48ce60c1c (diff)
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>
Diffstat (limited to 'hw/sd')
-rw-r--r--hw/sd/sdhci.c44
-rw-r--r--hw/sd/sdhci.h9
2 files changed, 52 insertions, 1 deletions
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index d7ca0c057c..15064d3ec2 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1220,6 +1220,49 @@ static Property sdhci_properties[] = {
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)
{
SDHCIState *s = SYSBUS_SDHCI(obj);
@@ -1265,6 +1308,7 @@ static const TypeInfo sdhci_sysbus_info = {
static void sdhci_register_types(void)
{
+ type_register_static(&sdhci_pci_info);
type_register_static(&sdhci_sysbus_info);
}
diff --git a/hw/sd/sdhci.h b/hw/sd/sdhci.h
index 9fbf682935..3352d23d68 100644
--- a/hw/sd/sdhci.h
+++ b/hw/sd/sdhci.h
@@ -26,6 +26,7 @@
#define SDHCI_H
#include "qemu-common.h"
+#include "hw/pci/pci.h"
#include "hw/sysbus.h"
#include "hw/sd.h"
@@ -232,7 +233,10 @@ enum {
/* SD/MMC host controller state */
typedef struct SDHCIState {
- SysBusDevice busdev;
+ union {
+ PCIDevice pcidev;
+ SysBusDevice busdev;
+ };
SDState *card;
MemoryRegion iomem;
@@ -281,6 +285,9 @@ typedef struct SDHCIState {
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 SYSBUS_SDHCI(obj) \
OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI)