Added Ricoh 5U822/5U823 SD/MMC Controller support.
This commit is contained in:
parent
583c0ba939
commit
5a4d57175c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sdhc_pci.c,v 1.6 2012/02/02 22:49:17 nonaka Exp $ */
|
||||
/* $NetBSD: sdhc_pci.c,v 1.7 2012/03/02 18:20:33 nonaka Exp $ */
|
||||
/* $OpenBSD: sdhc_pci.c,v 1.7 2007/10/30 18:13:45 chl Exp $ */
|
||||
|
||||
/*
|
||||
@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sdhc_pci.c,v 1.6 2012/02/02 22:49:17 nonaka Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sdhc_pci.c,v 1.7 2012/03/02 18:20:33 nonaka Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_sdmmc.h"
|
||||
@ -79,9 +79,10 @@ static const struct sdhc_pci_quirk {
|
||||
u_int function;
|
||||
|
||||
uint32_t flags;
|
||||
#define SDHC_PCI_QUIRK_FORCE_DMA (1U << 0)
|
||||
#define SDHC_PCI_QUIRK_TI_HACK (1U << 1)
|
||||
#define SDHC_PCI_QUIRK_NO_PWR0 (1U << 2)
|
||||
#define SDHC_PCI_QUIRK_FORCE_DMA (1U << 0)
|
||||
#define SDHC_PCI_QUIRK_TI_HACK (1U << 1)
|
||||
#define SDHC_PCI_QUIRK_NO_PWR0 (1U << 2)
|
||||
#define SDHC_PCI_QUIRK_RICOH_LOWER_FREQ_HACK (1U << 3)
|
||||
} sdhc_pci_quirk_table[] = {
|
||||
{
|
||||
PCI_VENDOR_TI,
|
||||
@ -109,9 +110,19 @@ static const struct sdhc_pci_quirk {
|
||||
0,
|
||||
SDHC_PCI_QUIRK_NO_PWR0
|
||||
},
|
||||
|
||||
{
|
||||
PCI_VENDOR_RICOH,
|
||||
PCI_PRODUCT_RICOH_Rx5U823,
|
||||
0xffff,
|
||||
0xffff,
|
||||
0,
|
||||
SDHC_PCI_QUIRK_RICOH_LOWER_FREQ_HACK
|
||||
},
|
||||
};
|
||||
|
||||
static void sdhc_pci_quirk_ti_hack(struct pci_attach_args *);
|
||||
static void sdhc_pci_quirk_ricoh_lower_freq_hack(struct pci_attach_args *);
|
||||
|
||||
static uint32_t
|
||||
sdhc_pci_lookup_quirk_flags(struct pci_attach_args *pa)
|
||||
@ -133,7 +144,7 @@ sdhc_pci_lookup_quirk_flags(struct pci_attach_args *pa)
|
||||
|
||||
if ((q->subvendor == 0xffff)
|
||||
&& (q->subproduct == 0xffff))
|
||||
return q->flags;
|
||||
return (q->flags);
|
||||
|
||||
id = pci_conf_read(pa->pa_pc, pa->pa_tag,
|
||||
PCI_SUBSYS_ID_REG);
|
||||
@ -144,18 +155,17 @@ sdhc_pci_lookup_quirk_flags(struct pci_attach_args *pa)
|
||||
&& (q->subproduct != 0xffff)) {
|
||||
if ((vendor == q->subvendor)
|
||||
&& (product == q->subproduct))
|
||||
return q->flags;
|
||||
return (q->flags);
|
||||
} else if (q->subvendor != 0xffff) {
|
||||
if (product == q->subproduct)
|
||||
return q->flags;
|
||||
return (q->flags);
|
||||
} else {
|
||||
if (vendor == q->subvendor)
|
||||
return q->flags;
|
||||
return (q->flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -165,9 +175,12 @@ sdhc_pci_match(device_t parent, cfdata_t cf, void *aux)
|
||||
|
||||
if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SYSTEM &&
|
||||
PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SYSTEM_SDHC)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return (1);
|
||||
if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH &&
|
||||
(PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_Rx5U822 ||
|
||||
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_Rx5U823))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -203,6 +216,8 @@ sdhc_pci_attach(device_t parent, device_t self, void *aux)
|
||||
SET(sc->sc.sc_flags, SDHC_FLAG_FORCE_DMA);
|
||||
if (ISSET(flags, SDHC_PCI_QUIRK_NO_PWR0))
|
||||
SET(sc->sc.sc_flags, SDHC_FLAG_NO_PWR0);
|
||||
if (ISSET(flags, SDHC_PCI_QUIRK_RICOH_LOWER_FREQ_HACK))
|
||||
sdhc_pci_quirk_ricoh_lower_freq_hack(pa);
|
||||
|
||||
/*
|
||||
* Map and attach all hosts supported by the host controller.
|
||||
@ -276,6 +291,17 @@ err:
|
||||
free(sc->sc.sc_host, M_DEVBUF);
|
||||
}
|
||||
|
||||
static void
|
||||
sdhc_pci_conf_write(struct pci_attach_args *pa, int reg, uint8_t val)
|
||||
{
|
||||
pcireg_t r;
|
||||
|
||||
r = pci_conf_read(pa->pa_pc, pa->pa_tag, reg & ~0x3);
|
||||
r &= ~(0xff << ((reg & 0x3) * 8));
|
||||
r |= (val << ((reg & 0x3) * 8));
|
||||
pci_conf_write(pa->pa_pc, pa->pa_tag, reg & ~0x3, r);
|
||||
}
|
||||
|
||||
/* TI specific register */
|
||||
#define SDHC_PCI_GENERAL_CTL 0x4c
|
||||
#define MMC_SD_DIS 0x02
|
||||
@ -309,3 +335,29 @@ sdhc_pci_quirk_ti_hack(struct pci_attach_args *pa)
|
||||
reg |= MMC_SD_DIS;
|
||||
pci_conf_write(pc, tag, SDHC_PCI_GENERAL_CTL, reg);
|
||||
}
|
||||
|
||||
/* Ricoh specific register */
|
||||
#define SDHC_PCI_MODE_KEY 0xf9
|
||||
#define SDHC_PCI_MODE 0x150
|
||||
#define SDHC_PCI_MODE_SD20 0x10
|
||||
#define SDHC_PCI_BASE_FREQ_KEY 0xfc
|
||||
#define SDHC_PCI_BASE_FREQ 0xe1
|
||||
|
||||
/* Some RICOH controllers need to be bumped into the right mode. */
|
||||
static void
|
||||
sdhc_pci_quirk_ricoh_lower_freq_hack(struct pci_attach_args *pa)
|
||||
{
|
||||
|
||||
/* Enable SD2.0 mode. */
|
||||
sdhc_pci_conf_write(pa, SDHC_PCI_MODE_KEY, 0xfc);
|
||||
sdhc_pci_conf_write(pa, SDHC_PCI_MODE, SDHC_PCI_MODE_SD20);
|
||||
sdhc_pci_conf_write(pa, SDHC_PCI_MODE_KEY, 0x00);
|
||||
|
||||
/*
|
||||
* Some SD/MMC cards don't work with the default base
|
||||
* clock frequency of 200MHz. Lower it to 50Hz.
|
||||
*/
|
||||
sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ_KEY, 0x01);
|
||||
sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ, 50);
|
||||
sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ_KEY, 0x00);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sdhc.c,v 1.11 2012/02/23 21:06:21 matt Exp $ */
|
||||
/* $NetBSD: sdhc.c,v 1.12 2012/03/02 18:20:33 nonaka Exp $ */
|
||||
/* $OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $ */
|
||||
|
||||
/*
|
||||
@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.11 2012/02/23 21:06:21 matt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.12 2012/03/02 18:20:33 nonaka Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_sdmmc.h"
|
||||
@ -79,6 +79,8 @@ struct sdhc_host {
|
||||
struct kmutex intr_mtx;
|
||||
struct kcondvar intr_cv;
|
||||
|
||||
int specver; /* spec. version */
|
||||
|
||||
uint32_t flags; /* flags for this host */
|
||||
#define SHF_USE_DMA 0x0001
|
||||
#define SHF_USE_4BIT_MODE 0x0002
|
||||
@ -90,18 +92,18 @@ struct sdhc_host {
|
||||
static uint8_t
|
||||
hread1(struct sdhc_host *hp, bus_size_t reg)
|
||||
{
|
||||
|
||||
if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS))
|
||||
return bus_space_read_1(hp->iot, hp->ioh, reg);
|
||||
|
||||
return bus_space_read_4(hp->iot, hp->ioh, reg & -4) >> (8 * (reg & 3));
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
hread2(struct sdhc_host *hp, bus_size_t reg)
|
||||
{
|
||||
|
||||
if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS))
|
||||
return bus_space_read_2(hp->iot, hp->ioh, reg);
|
||||
|
||||
return bus_space_read_4(hp->iot, hp->ioh, reg & -4) >> (8 * (reg & 2));
|
||||
}
|
||||
|
||||
@ -114,6 +116,7 @@ hread2(struct sdhc_host *hp, bus_size_t reg)
|
||||
static void
|
||||
hwrite1(struct sdhc_host *hp, bus_size_t o, uint8_t val)
|
||||
{
|
||||
|
||||
if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
|
||||
bus_space_write_1(hp->iot, hp->ioh, o, val);
|
||||
} else {
|
||||
@ -128,6 +131,7 @@ hwrite1(struct sdhc_host *hp, bus_size_t o, uint8_t val)
|
||||
static void
|
||||
hwrite2(struct sdhc_host *hp, bus_size_t o, uint16_t val)
|
||||
{
|
||||
|
||||
if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
|
||||
bus_space_write_2(hp->iot, hp->ioh, o, val);
|
||||
} else {
|
||||
@ -223,25 +227,29 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
|
||||
struct sdmmcbus_attach_args saa;
|
||||
struct sdhc_host *hp;
|
||||
uint32_t caps;
|
||||
#ifdef SDHC_DEBUG
|
||||
uint16_t sdhcver;
|
||||
|
||||
sdhcver = bus_space_read_2(iot, ioh, SDHC_HOST_CTL_VERSION);
|
||||
aprint_normal_dev(sc->sc_dev, "SD Host Specification/Vendor Version ");
|
||||
aprint_normal_dev(sc->sc_dev, "SD Host Specification ");
|
||||
switch (SDHC_SPEC_VERSION(sdhcver)) {
|
||||
case 0x00:
|
||||
aprint_normal("1.0/%u\n", SDHC_VENDOR_VERSION(sdhcver));
|
||||
case SDHC_SPEC_VERS_100:
|
||||
aprint_normal("1.0");
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
aprint_normal("2.0/%u\n", SDHC_VENDOR_VERSION(sdhcver));
|
||||
case SDHC_SPEC_VERS_200:
|
||||
aprint_normal("2.0");
|
||||
break;
|
||||
|
||||
case SDHC_SPEC_VERS_300:
|
||||
aprint_normal("3.0");
|
||||
break;
|
||||
|
||||
default:
|
||||
aprint_normal(">2.0/%u\n", SDHC_VENDOR_VERSION(sdhcver));
|
||||
aprint_normal("unknown version(0x%x)",
|
||||
SDHC_SPEC_VERSION(sdhcver));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
aprint_normal(", rev.%u\n", SDHC_VENDOR_VERSION(sdhcver));
|
||||
|
||||
/* Allocate one more host structure. */
|
||||
hp = malloc(sizeof(struct sdhc_host), M_DEVBUF, M_WAITOK|M_ZERO);
|
||||
@ -257,6 +265,7 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
|
||||
hp->iot = iot;
|
||||
hp->ioh = ioh;
|
||||
hp->dmat = sc->sc_dmat;
|
||||
hp->specver = SDHC_SPEC_VERSION(sdhcver);
|
||||
|
||||
mutex_init(&hp->host_mtx, MUTEX_DEFAULT, IPL_SDMMC);
|
||||
mutex_init(&hp->intr_mtx, MUTEX_DEFAULT, IPL_SDMMC);
|
||||
@ -285,12 +294,12 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
|
||||
/*
|
||||
* Determine the base clock frequency. (2.2.24)
|
||||
*/
|
||||
if (SDHC_BASE_FREQ_KHZ(caps) != 0)
|
||||
hp->clkbase = SDHC_BASE_FREQ_KHZ(caps);
|
||||
hp->clkbase = SDHC_BASE_FREQ_KHZ(caps);
|
||||
if (hp->clkbase == 0) {
|
||||
if (sc->sc_clkbase == 0) {
|
||||
/* The attachment driver must tell us. */
|
||||
aprint_error_dev(sc->sc_dev,"unknown base clock frequency\n");
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"unknown base clock frequency\n");
|
||||
goto err;
|
||||
}
|
||||
hp->clkbase = sc->sc_clkbase;
|
||||
@ -419,6 +428,7 @@ sdhc_suspend(device_t dev, const pmf_qual_t *qual)
|
||||
{
|
||||
struct sdhc_softc *sc = device_private(dev);
|
||||
struct sdhc_host *hp;
|
||||
size_t i;
|
||||
|
||||
/* XXX poll for command completion or suspend command
|
||||
* in progress */
|
||||
@ -427,15 +437,15 @@ sdhc_suspend(device_t dev, const pmf_qual_t *qual)
|
||||
for (size_t n = 0; n < sc->sc_nhosts; n++) {
|
||||
hp = sc->sc_host[n];
|
||||
if (ISSET(sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
|
||||
for (size_t i = 0; i < sizeof hp->regs; i += 4) {
|
||||
for (i = 0; i < sizeof hp->regs; i += 4) {
|
||||
uint32_t v = HREAD4(hp, i);
|
||||
hp->regs[i+0] = (v >> 0);
|
||||
hp->regs[i+1] = (v >> 8);
|
||||
hp->regs[i+2] = (v >> 16);
|
||||
hp->regs[i+3] = (v >> 24);
|
||||
hp->regs[i + 0] = (v >> 0);
|
||||
hp->regs[i + 1] = (v >> 8);
|
||||
hp->regs[i + 2] = (v >> 16);
|
||||
hp->regs[i + 3] = (v >> 24);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < sizeof hp->regs; i++) {
|
||||
for (i = 0; i < sizeof hp->regs; i++) {
|
||||
hp->regs[i] = HREAD1(hp, i);
|
||||
}
|
||||
}
|
||||
@ -448,21 +458,22 @@ sdhc_resume(device_t dev, const pmf_qual_t *qual)
|
||||
{
|
||||
struct sdhc_softc *sc = device_private(dev);
|
||||
struct sdhc_host *hp;
|
||||
size_t i;
|
||||
|
||||
/* Restore the host controller state. */
|
||||
for (size_t n = 0; n < sc->sc_nhosts; n++) {
|
||||
hp = sc->sc_host[n];
|
||||
(void)sdhc_host_reset(hp);
|
||||
if (ISSET(sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)) {
|
||||
for (size_t i = 0; i < sizeof hp->regs; i += 4) {
|
||||
for (i = 0; i < sizeof hp->regs; i += 4) {
|
||||
HWRITE4(hp, i,
|
||||
(hp->regs[i+0] << 0)
|
||||
|(hp->regs[i+1] << 8)
|
||||
|(hp->regs[i+2] << 16)
|
||||
|(hp->regs[i+3] << 24));
|
||||
(hp->regs[i + 0] << 0)
|
||||
| (hp->regs[i + 1] << 8)
|
||||
| (hp->regs[i + 2] << 16)
|
||||
| (hp->regs[i + 3] << 24));
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < sizeof hp->regs; i++) {
|
||||
for (i = 0; i < sizeof hp->regs; i++) {
|
||||
HWRITE1(hp, i, hp->regs[i]);
|
||||
}
|
||||
}
|
||||
@ -601,9 +612,7 @@ sdhc_write_protect(sdmmc_chipset_handle_t sch)
|
||||
r = ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_WRITE_PROTECT_SWITCH);
|
||||
mutex_exit(&hp->host_mtx);
|
||||
|
||||
if (!r)
|
||||
return 1;
|
||||
return 0;
|
||||
return r ? 0 : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -722,7 +731,6 @@ sdhc_clock_divisor(struct sdhc_host *hp, u_int freq, u_int *divp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No divisor found. */
|
||||
return false;
|
||||
}
|
||||
@ -739,18 +747,17 @@ sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
|
||||
u_int timo;
|
||||
int error = 0;
|
||||
#ifdef DIAGNOSTIC
|
||||
bool ispresent;
|
||||
#endif
|
||||
bool present;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
mutex_enter(&hp->host_mtx);
|
||||
ispresent = ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CMD_INHIBIT_MASK);
|
||||
present = ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CMD_INHIBIT_MASK);
|
||||
mutex_exit(&hp->host_mtx);
|
||||
|
||||
/* Must not stop the clock if commands are in progress. */
|
||||
if (ispresent && sdhc_card_detect(hp))
|
||||
if (present && sdhc_card_detect(hp)) {
|
||||
printf("%s: sdhc_sdclk_frequency_select: command in progress\n",
|
||||
device_xname(hp->sc->sc_dev));
|
||||
}
|
||||
#endif
|
||||
|
||||
mutex_enter(&hp->host_mtx);
|
||||
@ -790,11 +797,13 @@ sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
|
||||
*/
|
||||
if (ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
|
||||
sdmmc_delay(10000);
|
||||
HSET4(hp, SDHC_CLOCK_CTL, 8|SDHC_INTCLK_ENABLE|SDHC_INTCLK_STABLE);
|
||||
HSET4(hp, SDHC_CLOCK_CTL,
|
||||
8 | SDHC_INTCLK_ENABLE | SDHC_INTCLK_STABLE);
|
||||
} else {
|
||||
HSET2(hp, SDHC_CLOCK_CTL, SDHC_INTCLK_ENABLE);
|
||||
for (timo = 1000; timo > 0; timo--) {
|
||||
if (ISSET(HREAD2(hp, SDHC_CLOCK_CTL), SDHC_INTCLK_STABLE))
|
||||
if (ISSET(HREAD2(hp, SDHC_CLOCK_CTL),
|
||||
SDHC_INTCLK_STABLE))
|
||||
break;
|
||||
sdmmc_delay(10);
|
||||
}
|
||||
@ -819,6 +828,7 @@ sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
|
||||
sdmmc_delay(10);
|
||||
}
|
||||
DPRINTF(2,("%s: %u init spins\n", __func__, 10 - timo));
|
||||
|
||||
/*
|
||||
* Enable SD clock.
|
||||
*/
|
||||
@ -865,11 +875,11 @@ sdhc_bus_width(sdmmc_chipset_handle_t sch, int width)
|
||||
mutex_enter(&hp->host_mtx);
|
||||
reg = HREAD1(hp, SDHC_HOST_CTL);
|
||||
if (ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
|
||||
reg &= ~(SDHC_4BIT_MODE|SDHC_8BIT_MODE);
|
||||
reg &= ~(SDHC_4BIT_MODE|SDHC_ESDHC_8BIT_MODE);
|
||||
if (width == 4)
|
||||
reg |= SDHC_4BIT_MODE;
|
||||
else if (width == 8)
|
||||
reg |= SDHC_8BIT_MODE;
|
||||
reg |= SDHC_ESDHC_8BIT_MODE;
|
||||
} else {
|
||||
reg &= ~SDHC_4BIT_MODE;
|
||||
if (width == 4)
|
||||
@ -1086,8 +1096,7 @@ sdhc_start_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
|
||||
/*
|
||||
* Prepare command register value. (2.2.6)
|
||||
*/
|
||||
command =
|
||||
(cmd->c_opcode & SDHC_COMMAND_INDEX_MASK) << SDHC_COMMAND_INDEX_SHIFT;
|
||||
command = (cmd->c_opcode & SDHC_COMMAND_INDEX_MASK) << SDHC_COMMAND_INDEX_SHIFT;
|
||||
|
||||
if (ISSET(cmd->c_flags, SCF_RSP_CRC))
|
||||
command |= SDHC_CRC_CHECK_ENABLE;
|
||||
@ -1224,11 +1233,11 @@ static int
|
||||
sdhc_transfer_data_pio(struct sdhc_host *hp, struct sdmmc_command *cmd)
|
||||
{
|
||||
uint8_t *data = cmd->c_data;
|
||||
void (*pio_func)(struct sdhc_host *, uint8_t *, u_int);
|
||||
u_int len, datalen;
|
||||
u_int imask;
|
||||
u_int pmask;
|
||||
int error = 0;
|
||||
void (*pio_func)(struct sdhc_host *, uint8_t *, u_int);
|
||||
|
||||
if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
|
||||
imask = SDHC_BUFFER_READ_READY;
|
||||
@ -1366,22 +1375,22 @@ sdhc_write_data_pio(struct sdhc_host *hp, uint8_t *data, u_int datalen)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
esdhc_read_data_pio(struct sdhc_host *hp, uint8_t *data, u_int datalen)
|
||||
{
|
||||
uint16_t status = HREAD2(hp, SDHC_NINTR_STATUS);
|
||||
uint32_t v;
|
||||
|
||||
while (datalen > 3 && !ISSET(status, SDHC_TRANSFER_COMPLETE)) {
|
||||
uint32_t v = HREAD4(hp, SDHC_DATA);
|
||||
v = HREAD4(hp, SDHC_DATA);
|
||||
v = le32toh(v);
|
||||
*(uint32_t *)data = v;
|
||||
data += 4;
|
||||
datalen -= 4;
|
||||
status = HREAD2(hp, SDHC_NINTR_STATUS);
|
||||
}
|
||||
|
||||
if (datalen > 0 && !ISSET(status, SDHC_TRANSFER_COMPLETE)) {
|
||||
uint32_t v = HREAD4(hp, SDHC_DATA);
|
||||
v = HREAD4(hp, SDHC_DATA);
|
||||
v = le32toh(v);
|
||||
do {
|
||||
*data++ = v;
|
||||
@ -1394,8 +1403,10 @@ static void
|
||||
esdhc_write_data_pio(struct sdhc_host *hp, uint8_t *data, u_int datalen)
|
||||
{
|
||||
uint16_t status = HREAD2(hp, SDHC_NINTR_STATUS);
|
||||
uint32_t v;
|
||||
|
||||
while (datalen > 3 && !ISSET(status, SDHC_TRANSFER_COMPLETE)) {
|
||||
uint32_t v = *(uint32_t *)data;
|
||||
v = *(uint32_t *)data;
|
||||
v = htole32(v);
|
||||
HWRITE4(hp, SDHC_DATA, v);
|
||||
data += 4;
|
||||
@ -1403,7 +1414,7 @@ esdhc_write_data_pio(struct sdhc_host *hp, uint8_t *data, u_int datalen)
|
||||
status = HREAD2(hp, SDHC_NINTR_STATUS);
|
||||
}
|
||||
if (datalen > 0 && !ISSET(status, SDHC_TRANSFER_COMPLETE)) {
|
||||
uint32_t v = *(uint32_t *)data;
|
||||
v = *(uint32_t *)data;
|
||||
v = htole32(v);
|
||||
HWRITE4(hp, SDHC_DATA, v);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sdhcreg.h,v 1.5 2012/02/01 22:53:19 matt Exp $ */
|
||||
/* $NetBSD: sdhcreg.h,v 1.6 2012/03/02 18:20:34 nonaka Exp $ */
|
||||
/* $OpenBSD: sdhcreg.h,v 1.4 2006/07/30 17:20:40 fgsch Exp $ */
|
||||
|
||||
/*
|
||||
@ -73,7 +73,7 @@
|
||||
#define SDHC_CMD_INHIBIT_MASK 0x0003
|
||||
#define SDHC_HOST_CTL 0x28
|
||||
#define SDHC_HIGH_SPEED (1<<2)
|
||||
#define SDHC_8BIT_MODE (1<<2) /* ESDHC */
|
||||
#define SDHC_ESDHC_8BIT_MODE (1<<2) /* eSDHC */
|
||||
#define SDHC_4BIT_MODE (1<<1)
|
||||
#define SDHC_LED_ON (1<<0)
|
||||
#define SDHC_POWER_CTL 0x29
|
||||
@ -167,6 +167,11 @@
|
||||
#define SDHC_DMA_CTL 0x40c /* eSDHC */
|
||||
#define SDHC_DMA_SNOOP 0x40
|
||||
|
||||
/* SDHC_SPEC_VERS */
|
||||
#define SDHC_SPEC_VERS_100 0x00
|
||||
#define SDHC_SPEC_VERS_200 0x01
|
||||
#define SDHC_SPEC_VERS_300 0x02
|
||||
|
||||
/* SDHC_CAPABILITIES decoding */
|
||||
#define SDHC_BASE_FREQ_KHZ(cap) \
|
||||
((((cap) >> SDHC_BASE_FREQ_SHIFT) & SDHC_BASE_FREQ_MASK) * 1000)
|
||||
|
Loading…
Reference in New Issue
Block a user