Message ID | 20220915152520.21948-11-shentey@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | ppc/e500: Add support for two types of flash, cleanup | expand |
On Thu, Sep 15, 2022 at 11:30 PM Bernhard Beschow <shentey@gmail.com> wrote: > > Will allow e500 boards to access SD cards using just their own devices. > > Signed-off-by: Bernhard Beschow <shentey@gmail.com> > --- > hw/sd/sdhci.c | 147 +++++++++++++++++++++++++++++++++++++++++- > include/hw/sd/sdhci.h | 3 + > 2 files changed, 149 insertions(+), 1 deletion(-) > > diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c > index 7a5996caad..09285ccfa1 100644 > --- a/hw/sd/sdhci.c > +++ b/hw/sd/sdhci.c > @@ -1369,6 +1369,7 @@ void sdhci_initfn(SDHCIState *s) > s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, s); > > s->io_ops = &sdhci_mmio_ops; > + s->io_registers_map_size = SDHC_REGISTERS_MAP_SIZE; > } > > void sdhci_uninitfn(SDHCIState *s) > @@ -1392,7 +1393,7 @@ void sdhci_common_realize(SDHCIState *s, Error **errp) > s->fifo_buffer = g_malloc0(s->buf_maxsz); > > memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci", > - SDHC_REGISTERS_MAP_SIZE); > + s->io_registers_map_size); > } > > void sdhci_common_unrealize(SDHCIState *s) > @@ -1575,6 +1576,149 @@ static const TypeInfo sdhci_bus_info = { > .class_init = sdhci_bus_class_init, > }; > > +/* --- qdev Freescale eSDHC --- */ > + > +/* Host Controller Capabilities Register 2 */ > +#define ESDHC_CAPABILITIES_1 0x114 > + > +/* Control Register for DMA transfer */ > +#define ESDHC_DMA_SYSCTL 0x40c > +#define ESDHC_PERIPHERAL_CLK_SEL 0x00080000 > +#define ESDHC_FLUSH_ASYNC_FIFO 0x00040000 > +#define ESDHC_DMA_SNOOP 0x00000040 It looks the above 3 bit fields are not used? > + > +#define ESDHC_REGISTERS_MAP_SIZE 0x410 > + > +static uint64_t esdhci_read(void *opaque, hwaddr offset, unsigned size) > +{ > + uint64_t ret; > + > + if (size != 4) { > + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC rd_%ub @0x%02" HWADDR_PRIx > + " wrong size\n", size, offset); > + return 0; > + } > + > + if (offset & 0x3) { > + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC rd_%ub @0x%02" HWADDR_PRIx > + " unaligned\n", size, offset); > + return 0; > + } > + > + switch (offset) { > + case SDHC_SYSAD: > + case SDHC_BLKSIZE: > + case SDHC_ARGUMENT: > + case SDHC_TRNMOD: > + case SDHC_RSPREG0: > + case SDHC_RSPREG1: > + case SDHC_RSPREG2: > + case SDHC_RSPREG3: > + case SDHC_BDATA: > + case SDHC_PRNSTS: > + case SDHC_HOSTCTL: > + case SDHC_CLKCON: > + case SDHC_NORINTSTS: > + case SDHC_NORINTSTSEN: > + case SDHC_NORINTSIGEN: > + case SDHC_ACMD12ERRSTS: > + case SDHC_CAPAB: > + case SDHC_SLOT_INT_STATUS: > + ret = sdhci_read(opaque, offset, size); > + break; > + > + case ESDHC_DMA_SYSCTL: > + case 0x44: Can we define a macro for this offset? > + ret = 0; > + qemu_log_mask(LOG_UNIMP, "ESDHC rd_%ub @0x%02" HWADDR_PRIx > + " not implemented\n", size, offset); > + break; > + > + default: > + ret = 0; > + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC rd_%ub @0x%02" HWADDR_PRIx > + " unknown offset\n", size, offset); > + break; > + } > + > + return ret; > +} > + > +static void esdhci_write(void *opaque, hwaddr offset, uint64_t val, > + unsigned size) > +{ > + if (size != 4) { > + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC wr_%ub @0x%02" HWADDR_PRIx > + " <- 0x%08lx wrong size\n", size, offset, val); > + return; > + } > + > + if (offset & 0x3) { > + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC wr_%ub @0x%02" HWADDR_PRIx > + " <- 0x%08lx unaligned\n", size, offset, val); > + return; > + } > + > + switch (offset) { > + case SDHC_SYSAD: > + case SDHC_BLKSIZE: > + case SDHC_ARGUMENT: > + case SDHC_TRNMOD: > + case SDHC_BDATA: > + case SDHC_HOSTCTL: > + case SDHC_CLKCON: > + case SDHC_NORINTSTS: > + case SDHC_NORINTSTSEN: > + case SDHC_NORINTSIGEN: > + case SDHC_FEAER: > + sdhci_write(opaque, offset, val, size); > + break; > + > + case ESDHC_DMA_SYSCTL: > + case 0x44: ditto > + qemu_log_mask(LOG_UNIMP, "ESDHC wr_%ub @0x%02" HWADDR_PRIx " <- 0x%08lx " > + "not implemented\n", size, offset, val); > + break; > + > + default: > + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC wr_%ub @0x%02" HWADDR_PRIx > + " <- 0x%08lx unknown offset\n", size, offset, val); > + break; > + } > +} > + > +static const MemoryRegionOps esdhc_mmio_ops = { > + .read = esdhci_read, > + .write = esdhci_write, > + .valid = { > + .min_access_size = 1, > + .max_access_size = 4, > + .unaligned = false > + }, > + .endianness = DEVICE_BIG_ENDIAN, > +}; > + > +static void esdhci_init(Object *obj) > +{ > + DeviceState *dev = DEVICE(obj); > + SDHCIState *s = SYSBUS_SDHCI(obj); > + > + s->io_ops = &esdhc_mmio_ops; > + s->io_registers_map_size = ESDHC_REGISTERS_MAP_SIZE; > + > + /* > + * Compatible with: > + * - SD Host Controller Specification Version 2.0 Part A2 > + */ > + qdev_prop_set_uint8(dev, "sd-spec-version", 2); > +} > + > +static const TypeInfo esdhc_info = { > + .name = TYPE_FSL_ESDHC, > + .parent = TYPE_SYSBUS_SDHCI, > + .instance_init = esdhci_init, > +}; > + > /* --- qdev i.MX eSDHC --- */ > > #define USDHC_MIX_CTRL 0x48 > @@ -1907,6 +2051,7 @@ static void sdhci_register_types(void) > { > type_register_static(&sdhci_sysbus_info); > type_register_static(&sdhci_bus_info); > + type_register_static(&esdhc_info); > type_register_static(&imx_usdhc_info); > type_register_static(&sdhci_s3c_info); > } > diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h > index 01a64c5442..5b32e83eee 100644 > --- a/include/hw/sd/sdhci.h > +++ b/include/hw/sd/sdhci.h > @@ -45,6 +45,7 @@ struct SDHCIState { > AddressSpace *dma_as; > MemoryRegion *dma_mr; > const MemoryRegionOps *io_ops; > + uint64_t io_registers_map_size; > > QEMUTimer *insert_timer; /* timer for 'changing' sd card. */ > QEMUTimer *transfer_timer; > @@ -122,6 +123,8 @@ DECLARE_INSTANCE_CHECKER(SDHCIState, PCI_SDHCI, > DECLARE_INSTANCE_CHECKER(SDHCIState, SYSBUS_SDHCI, > TYPE_SYSBUS_SDHCI) > > +#define TYPE_FSL_ESDHC "fsl-esdhc" > + > #define TYPE_IMX_USDHC "imx-usdhc" > > #define TYPE_S3C_SDHCI "s3c-sdhci" > -- Regards, Bin
Am 16. September 2022 15:15:03 UTC schrieb Bin Meng <bmeng.cn@gmail.com>: >On Thu, Sep 15, 2022 at 11:30 PM Bernhard Beschow <shentey@gmail.com> wrote: >> >> Will allow e500 boards to access SD cards using just their own devices. >> >> Signed-off-by: Bernhard Beschow <shentey@gmail.com> >> --- >> hw/sd/sdhci.c | 147 +++++++++++++++++++++++++++++++++++++++++- >> include/hw/sd/sdhci.h | 3 + >> 2 files changed, 149 insertions(+), 1 deletion(-) >> >> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c >> index 7a5996caad..09285ccfa1 100644 >> --- a/hw/sd/sdhci.c >> +++ b/hw/sd/sdhci.c >> @@ -1369,6 +1369,7 @@ void sdhci_initfn(SDHCIState *s) >> s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, s); >> >> s->io_ops = &sdhci_mmio_ops; >> + s->io_registers_map_size = SDHC_REGISTERS_MAP_SIZE; >> } >> >> void sdhci_uninitfn(SDHCIState *s) >> @@ -1392,7 +1393,7 @@ void sdhci_common_realize(SDHCIState *s, Error **errp) >> s->fifo_buffer = g_malloc0(s->buf_maxsz); >> >> memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci", >> - SDHC_REGISTERS_MAP_SIZE); >> + s->io_registers_map_size); >> } >> >> void sdhci_common_unrealize(SDHCIState *s) >> @@ -1575,6 +1576,149 @@ static const TypeInfo sdhci_bus_info = { >> .class_init = sdhci_bus_class_init, >> }; >> >> +/* --- qdev Freescale eSDHC --- */ >> + >> +/* Host Controller Capabilities Register 2 */ >> +#define ESDHC_CAPABILITIES_1 0x114 >> + >> +/* Control Register for DMA transfer */ >> +#define ESDHC_DMA_SYSCTL 0x40c >> +#define ESDHC_PERIPHERAL_CLK_SEL 0x00080000 >> +#define ESDHC_FLUSH_ASYNC_FIFO 0x00040000 >> +#define ESDHC_DMA_SNOOP 0x00000040 > >It looks the above 3 bit fields are not used? Yes, possibly. I'll check for more unused stuff. >> + >> +#define ESDHC_REGISTERS_MAP_SIZE 0x410 >> + >> +static uint64_t esdhci_read(void *opaque, hwaddr offset, unsigned size) >> +{ >> + uint64_t ret; >> + >> + if (size != 4) { >> + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC rd_%ub @0x%02" HWADDR_PRIx >> + " wrong size\n", size, offset); >> + return 0; >> + } >> + >> + if (offset & 0x3) { >> + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC rd_%ub @0x%02" HWADDR_PRIx >> + " unaligned\n", size, offset); >> + return 0; >> + } >> + >> + switch (offset) { >> + case SDHC_SYSAD: >> + case SDHC_BLKSIZE: >> + case SDHC_ARGUMENT: >> + case SDHC_TRNMOD: >> + case SDHC_RSPREG0: >> + case SDHC_RSPREG1: >> + case SDHC_RSPREG2: >> + case SDHC_RSPREG3: >> + case SDHC_BDATA: >> + case SDHC_PRNSTS: >> + case SDHC_HOSTCTL: >> + case SDHC_CLKCON: >> + case SDHC_NORINTSTS: >> + case SDHC_NORINTSTSEN: >> + case SDHC_NORINTSIGEN: >> + case SDHC_ACMD12ERRSTS: >> + case SDHC_CAPAB: >> + case SDHC_SLOT_INT_STATUS: >> + ret = sdhci_read(opaque, offset, size); >> + break; >> + >> + case ESDHC_DMA_SYSCTL: >> + case 0x44: > >Can we define a macro for this offset? Sure. Not sure why I didn't. >> + ret = 0; >> + qemu_log_mask(LOG_UNIMP, "ESDHC rd_%ub @0x%02" HWADDR_PRIx >> + " not implemented\n", size, offset); >> + break; >> + >> + default: >> + ret = 0; >> + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC rd_%ub @0x%02" HWADDR_PRIx >> + " unknown offset\n", size, offset); >> + break; >> + } >> + >> + return ret; >> +} >> + >> +static void esdhci_write(void *opaque, hwaddr offset, uint64_t val, >> + unsigned size) >> +{ >> + if (size != 4) { >> + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC wr_%ub @0x%02" HWADDR_PRIx >> + " <- 0x%08lx wrong size\n", size, offset, val); >> + return; >> + } >> + >> + if (offset & 0x3) { >> + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC wr_%ub @0x%02" HWADDR_PRIx >> + " <- 0x%08lx unaligned\n", size, offset, val); >> + return; >> + } >> + >> + switch (offset) { >> + case SDHC_SYSAD: >> + case SDHC_BLKSIZE: >> + case SDHC_ARGUMENT: >> + case SDHC_TRNMOD: >> + case SDHC_BDATA: >> + case SDHC_HOSTCTL: >> + case SDHC_CLKCON: >> + case SDHC_NORINTSTS: >> + case SDHC_NORINTSTSEN: >> + case SDHC_NORINTSIGEN: >> + case SDHC_FEAER: >> + sdhci_write(opaque, offset, val, size); >> + break; >> + >> + case ESDHC_DMA_SYSCTL: >> + case 0x44: > >ditto Ack. Best regards, Bernhard > >> + qemu_log_mask(LOG_UNIMP, "ESDHC wr_%ub @0x%02" HWADDR_PRIx " <- 0x%08lx " >> + "not implemented\n", size, offset, val); >> + break; >> + >> + default: >> + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC wr_%ub @0x%02" HWADDR_PRIx >> + " <- 0x%08lx unknown offset\n", size, offset, val); >> + break; >> + } >> +} >> + >> +static const MemoryRegionOps esdhc_mmio_ops = { >> + .read = esdhci_read, >> + .write = esdhci_write, >> + .valid = { >> + .min_access_size = 1, >> + .max_access_size = 4, >> + .unaligned = false >> + }, >> + .endianness = DEVICE_BIG_ENDIAN, >> +}; >> + >> +static void esdhci_init(Object *obj) >> +{ >> + DeviceState *dev = DEVICE(obj); >> + SDHCIState *s = SYSBUS_SDHCI(obj); >> + >> + s->io_ops = &esdhc_mmio_ops; >> + s->io_registers_map_size = ESDHC_REGISTERS_MAP_SIZE; >> + >> + /* >> + * Compatible with: >> + * - SD Host Controller Specification Version 2.0 Part A2 >> + */ >> + qdev_prop_set_uint8(dev, "sd-spec-version", 2); >> +} >> + >> +static const TypeInfo esdhc_info = { >> + .name = TYPE_FSL_ESDHC, >> + .parent = TYPE_SYSBUS_SDHCI, >> + .instance_init = esdhci_init, >> +}; >> + >> /* --- qdev i.MX eSDHC --- */ >> >> #define USDHC_MIX_CTRL 0x48 >> @@ -1907,6 +2051,7 @@ static void sdhci_register_types(void) >> { >> type_register_static(&sdhci_sysbus_info); >> type_register_static(&sdhci_bus_info); >> + type_register_static(&esdhc_info); >> type_register_static(&imx_usdhc_info); >> type_register_static(&sdhci_s3c_info); >> } >> diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h >> index 01a64c5442..5b32e83eee 100644 >> --- a/include/hw/sd/sdhci.h >> +++ b/include/hw/sd/sdhci.h >> @@ -45,6 +45,7 @@ struct SDHCIState { >> AddressSpace *dma_as; >> MemoryRegion *dma_mr; >> const MemoryRegionOps *io_ops; >> + uint64_t io_registers_map_size; >> >> QEMUTimer *insert_timer; /* timer for 'changing' sd card. */ >> QEMUTimer *transfer_timer; >> @@ -122,6 +123,8 @@ DECLARE_INSTANCE_CHECKER(SDHCIState, PCI_SDHCI, >> DECLARE_INSTANCE_CHECKER(SDHCIState, SYSBUS_SDHCI, >> TYPE_SYSBUS_SDHCI) >> >> +#define TYPE_FSL_ESDHC "fsl-esdhc" >> + >> #define TYPE_IMX_USDHC "imx-usdhc" >> >> #define TYPE_S3C_SDHCI "s3c-sdhci" >> -- > >Regards, >Bin
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 7a5996caad..09285ccfa1 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1369,6 +1369,7 @@ void sdhci_initfn(SDHCIState *s) s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, s); s->io_ops = &sdhci_mmio_ops; + s->io_registers_map_size = SDHC_REGISTERS_MAP_SIZE; } void sdhci_uninitfn(SDHCIState *s) @@ -1392,7 +1393,7 @@ void sdhci_common_realize(SDHCIState *s, Error **errp) s->fifo_buffer = g_malloc0(s->buf_maxsz); memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci", - SDHC_REGISTERS_MAP_SIZE); + s->io_registers_map_size); } void sdhci_common_unrealize(SDHCIState *s) @@ -1575,6 +1576,149 @@ static const TypeInfo sdhci_bus_info = { .class_init = sdhci_bus_class_init, }; +/* --- qdev Freescale eSDHC --- */ + +/* Host Controller Capabilities Register 2 */ +#define ESDHC_CAPABILITIES_1 0x114 + +/* Control Register for DMA transfer */ +#define ESDHC_DMA_SYSCTL 0x40c +#define ESDHC_PERIPHERAL_CLK_SEL 0x00080000 +#define ESDHC_FLUSH_ASYNC_FIFO 0x00040000 +#define ESDHC_DMA_SNOOP 0x00000040 + +#define ESDHC_REGISTERS_MAP_SIZE 0x410 + +static uint64_t esdhci_read(void *opaque, hwaddr offset, unsigned size) +{ + uint64_t ret; + + if (size != 4) { + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC rd_%ub @0x%02" HWADDR_PRIx + " wrong size\n", size, offset); + return 0; + } + + if (offset & 0x3) { + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC rd_%ub @0x%02" HWADDR_PRIx + " unaligned\n", size, offset); + return 0; + } + + switch (offset) { + case SDHC_SYSAD: + case SDHC_BLKSIZE: + case SDHC_ARGUMENT: + case SDHC_TRNMOD: + case SDHC_RSPREG0: + case SDHC_RSPREG1: + case SDHC_RSPREG2: + case SDHC_RSPREG3: + case SDHC_BDATA: + case SDHC_PRNSTS: + case SDHC_HOSTCTL: + case SDHC_CLKCON: + case SDHC_NORINTSTS: + case SDHC_NORINTSTSEN: + case SDHC_NORINTSIGEN: + case SDHC_ACMD12ERRSTS: + case SDHC_CAPAB: + case SDHC_SLOT_INT_STATUS: + ret = sdhci_read(opaque, offset, size); + break; + + case ESDHC_DMA_SYSCTL: + case 0x44: + ret = 0; + qemu_log_mask(LOG_UNIMP, "ESDHC rd_%ub @0x%02" HWADDR_PRIx + " not implemented\n", size, offset); + break; + + default: + ret = 0; + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC rd_%ub @0x%02" HWADDR_PRIx + " unknown offset\n", size, offset); + break; + } + + return ret; +} + +static void esdhci_write(void *opaque, hwaddr offset, uint64_t val, + unsigned size) +{ + if (size != 4) { + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC wr_%ub @0x%02" HWADDR_PRIx + " <- 0x%08lx wrong size\n", size, offset, val); + return; + } + + if (offset & 0x3) { + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC wr_%ub @0x%02" HWADDR_PRIx + " <- 0x%08lx unaligned\n", size, offset, val); + return; + } + + switch (offset) { + case SDHC_SYSAD: + case SDHC_BLKSIZE: + case SDHC_ARGUMENT: + case SDHC_TRNMOD: + case SDHC_BDATA: + case SDHC_HOSTCTL: + case SDHC_CLKCON: + case SDHC_NORINTSTS: + case SDHC_NORINTSTSEN: + case SDHC_NORINTSIGEN: + case SDHC_FEAER: + sdhci_write(opaque, offset, val, size); + break; + + case ESDHC_DMA_SYSCTL: + case 0x44: + qemu_log_mask(LOG_UNIMP, "ESDHC wr_%ub @0x%02" HWADDR_PRIx " <- 0x%08lx " + "not implemented\n", size, offset, val); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "ESDHC wr_%ub @0x%02" HWADDR_PRIx + " <- 0x%08lx unknown offset\n", size, offset, val); + break; + } +} + +static const MemoryRegionOps esdhc_mmio_ops = { + .read = esdhci_read, + .write = esdhci_write, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + .unaligned = false + }, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void esdhci_init(Object *obj) +{ + DeviceState *dev = DEVICE(obj); + SDHCIState *s = SYSBUS_SDHCI(obj); + + s->io_ops = &esdhc_mmio_ops; + s->io_registers_map_size = ESDHC_REGISTERS_MAP_SIZE; + + /* + * Compatible with: + * - SD Host Controller Specification Version 2.0 Part A2 + */ + qdev_prop_set_uint8(dev, "sd-spec-version", 2); +} + +static const TypeInfo esdhc_info = { + .name = TYPE_FSL_ESDHC, + .parent = TYPE_SYSBUS_SDHCI, + .instance_init = esdhci_init, +}; + /* --- qdev i.MX eSDHC --- */ #define USDHC_MIX_CTRL 0x48 @@ -1907,6 +2051,7 @@ static void sdhci_register_types(void) { type_register_static(&sdhci_sysbus_info); type_register_static(&sdhci_bus_info); + type_register_static(&esdhc_info); type_register_static(&imx_usdhc_info); type_register_static(&sdhci_s3c_info); } diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h index 01a64c5442..5b32e83eee 100644 --- a/include/hw/sd/sdhci.h +++ b/include/hw/sd/sdhci.h @@ -45,6 +45,7 @@ struct SDHCIState { AddressSpace *dma_as; MemoryRegion *dma_mr; const MemoryRegionOps *io_ops; + uint64_t io_registers_map_size; QEMUTimer *insert_timer; /* timer for 'changing' sd card. */ QEMUTimer *transfer_timer; @@ -122,6 +123,8 @@ DECLARE_INSTANCE_CHECKER(SDHCIState, PCI_SDHCI, DECLARE_INSTANCE_CHECKER(SDHCIState, SYSBUS_SDHCI, TYPE_SYSBUS_SDHCI) +#define TYPE_FSL_ESDHC "fsl-esdhc" + #define TYPE_IMX_USDHC "imx-usdhc" #define TYPE_S3C_SDHCI "s3c-sdhci"
Will allow e500 boards to access SD cards using just their own devices. Signed-off-by: Bernhard Beschow <shentey@gmail.com> --- hw/sd/sdhci.c | 147 +++++++++++++++++++++++++++++++++++++++++- include/hw/sd/sdhci.h | 3 + 2 files changed, 149 insertions(+), 1 deletion(-)