mirror of
https://github.com/fail0verflow/mini.git
synced 2024-11-16 08:29:25 +01:00
some more sd fail.
This commit is contained in:
parent
516d5e8d2f
commit
ca7836a7a6
2
Makefile
2
Makefile
@ -14,7 +14,7 @@ TARGET_BIN = armboot.bin
|
|||||||
OBJS = start.o main.o ipc.o vsprintf.o string.o gecko.o memory.o memory_asm.o \
|
OBJS = start.o main.o ipc.o vsprintf.o string.o gecko.o memory.o memory_asm.o \
|
||||||
utils_asm.o utils.o ff.o diskio.o sdhc.o powerpc_elf.o powerpc.o panic.o \
|
utils_asm.o utils.o ff.o diskio.o sdhc.o powerpc_elf.o powerpc.o panic.o \
|
||||||
irq.o irq_asm.o exception.o exception_asm.o seeprom.o crypto.o nand.o \
|
irq.o irq_asm.o exception.o exception_asm.o seeprom.o crypto.o nand.o \
|
||||||
boot2.o ldhack.o
|
boot2.o ldhack.o sdmmc.o
|
||||||
|
|
||||||
include ../../common.mk
|
include ../../common.mk
|
||||||
|
|
||||||
|
@ -24,6 +24,6 @@ struct device {
|
|||||||
|
|
||||||
#define bzero(mem, size) memset(mem, 0, size)
|
#define bzero(mem, size) memset(mem, 0, size)
|
||||||
|
|
||||||
#define ISSET(var, mask) (((var) & (mask)) == (mask) ? 1 : 0)
|
#define ISSET(var, mask) (((var) & (mask)) ? 1 : 0)
|
||||||
#define SET(var, mask) ((var) |= (mask))
|
#define SET(var, mask) ((var) |= (mask))
|
||||||
#endif
|
#endif
|
||||||
|
21
ipc.c
21
ipc.c
@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
#include "ipc.h"
|
#include "ipc.h"
|
||||||
#include "nand.h"
|
#include "nand.h"
|
||||||
//#include "sdhc.h"
|
#include "sdhcvar.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "boot2.h"
|
#include "boot2.h"
|
||||||
#include "powerpc.h"
|
#include "powerpc.h"
|
||||||
@ -150,7 +150,7 @@ static u32 process_slow(volatile ipc_request *req)
|
|||||||
nand_ipc(req);
|
nand_ipc(req);
|
||||||
break;
|
break;
|
||||||
case IPC_DEV_SD:
|
case IPC_DEV_SD:
|
||||||
// sd_ipc(req);
|
sdhc_ipc(req);
|
||||||
break;
|
break;
|
||||||
case IPC_DEV_KEYS:
|
case IPC_DEV_KEYS:
|
||||||
crypto_ipc(req);
|
crypto_ipc(req);
|
||||||
@ -171,6 +171,16 @@ static u32 process_slow(volatile ipc_request *req)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ipc_add_slow(volatile ipc_request *req)
|
||||||
|
{
|
||||||
|
if(slow_queue_head == ((slow_queue_tail + 1)&(IPC_SLOW_SIZE-1))) {
|
||||||
|
gecko_printf("IPC: Slowqueue overrun\n");
|
||||||
|
panic2(0, PANIC_IPCOVF);
|
||||||
|
}
|
||||||
|
slow_queue[slow_queue_tail] = *req;
|
||||||
|
slow_queue_tail = (slow_queue_tail+1)&(IPC_SLOW_SIZE-1);
|
||||||
|
}
|
||||||
|
|
||||||
static void process_in(void)
|
static void process_in(void)
|
||||||
{
|
{
|
||||||
volatile ipc_request *req = &in_queue[in_head];
|
volatile ipc_request *req = &in_queue[in_head];
|
||||||
@ -245,12 +255,7 @@ static void process_in(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(slow_queue_head == ((slow_queue_tail + 1)&(IPC_SLOW_SIZE-1))) {
|
ipc_add_slow(req);
|
||||||
gecko_printf("IPC: Slowqueue overrun\n");
|
|
||||||
panic2(0, PANIC_IPCOVF);
|
|
||||||
}
|
|
||||||
slow_queue[slow_queue_tail] = *req;
|
|
||||||
slow_queue_tail = (slow_queue_tail+1)&(IPC_SLOW_SIZE-1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
8
ipc.h
8
ipc.h
@ -62,12 +62,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#define IPC_NAND_ERASE 0x0004
|
#define IPC_NAND_ERASE 0x0004
|
||||||
#define IPC_NAND_STATUS 0x0005
|
#define IPC_NAND_STATUS 0x0005
|
||||||
|
|
||||||
#define IPC_SD_MOUNT 0x0000
|
/*#define IPC_SD_MOUNT 0x0000
|
||||||
#define IPC_SD_SELECT 0x0001
|
#define IPC_SD_SELECT 0x0001
|
||||||
#define IPC_SD_GETSTATE 0x0002
|
#define IPC_SD_GETSTATE 0x0002
|
||||||
#define IPC_SD_READ 0x0003
|
#define IPC_SD_READ 0x0003
|
||||||
#define IPC_SD_WRITE 0x0004
|
#define IPC_SD_WRITE 0x0004
|
||||||
#define IPC_SD_GETSIZE 0x0005
|
#define IPC_SD_GETSIZE 0x0005*/
|
||||||
|
|
||||||
#define IPC_KEYS_GETOTP 0x0000
|
#define IPC_KEYS_GETOTP 0x0000
|
||||||
#define IPC_KEYS_GETEEP 0x0001
|
#define IPC_KEYS_GETEEP 0x0001
|
||||||
@ -120,4 +120,8 @@ void ipc_post(u32 code, u32 tag, u32 num_args, ...);
|
|||||||
void ipc_flush(void);
|
void ipc_flush(void);
|
||||||
u32 ipc_process_slow(void);
|
u32 ipc_process_slow(void);
|
||||||
|
|
||||||
|
// add an entry to the slow queue from the arm
|
||||||
|
// (you probably want to use this in irq context)
|
||||||
|
void ipc_add_slow(volatile ipc_request *req);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
2
main.c
2
main.c
@ -187,7 +187,7 @@ u32 _main(void *base)
|
|||||||
|
|
||||||
irq_initialize();
|
irq_initialize();
|
||||||
irq_enable(IRQ_TIMER);
|
irq_enable(IRQ_TIMER);
|
||||||
irq_enable(IRQ_GPIO1B);
|
// irq_enable(IRQ_GPIO1B);
|
||||||
irq_enable(IRQ_GPIO1);
|
irq_enable(IRQ_GPIO1);
|
||||||
irq_enable(IRQ_RESET);
|
irq_enable(IRQ_RESET);
|
||||||
gecko_timer_initialize();
|
gecko_timer_initialize();
|
||||||
|
2
mini.ld
2
mini.ld
@ -5,7 +5,7 @@ EXTERN(__ipc_info)
|
|||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
__stack_size = 0x800;
|
__stack_size = 0x800;
|
||||||
__irqstack_size = 0x100;
|
__irqstack_size = 0x400; /* blame the bsd's sdhc_intr function */
|
||||||
__excstack_size = 0x100;
|
__excstack_size = 0x100;
|
||||||
|
|
||||||
MEMORY {
|
MEMORY {
|
||||||
|
48
sdhc.c
48
sdhc.c
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
|
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
|
||||||
|
* Copyright (c) 2009 Sven Peter <svenpeter@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -37,31 +38,19 @@
|
|||||||
#include "sdmmcchip.h"
|
#include "sdmmcchip.h"
|
||||||
#include "sdmmcreg.h"
|
#include "sdmmcreg.h"
|
||||||
#include "sdmmcvar.h"
|
#include "sdmmcvar.h"
|
||||||
|
#include "sdmmc.h"
|
||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "ipc.h"
|
||||||
|
|
||||||
#define SDHC_DEBUG 1
|
#define SDHC_DEBUG 0
|
||||||
|
|
||||||
#define SDHC_COMMAND_TIMEOUT 0
|
#define SDHC_COMMAND_TIMEOUT 0
|
||||||
#define SDHC_BUFFER_TIMEOUT 0
|
#define SDHC_BUFFER_TIMEOUT 0
|
||||||
#define SDHC_TRANSFER_TIMEOUT 0
|
#define SDHC_TRANSFER_TIMEOUT 0
|
||||||
|
|
||||||
struct sdhc_host {
|
|
||||||
struct sdhc_softc *sc; /* host controller device */
|
|
||||||
struct device *sdmmc; /* generic SD/MMC device */
|
|
||||||
bus_space_tag_t iot; /* host register set tag */
|
|
||||||
bus_space_handle_t ioh; /* host register set handle */
|
|
||||||
u_int clkbase; /* base clock frequency in KHz */
|
|
||||||
int maxblklen; /* maximum block length */
|
|
||||||
int flags; /* flags for this host */
|
|
||||||
u_int32_t ocr; /* OCR value from capabilities */
|
|
||||||
u_int8_t regs[14]; /* host controller state */
|
|
||||||
u_int16_t intr_status; /* soft interrupt status */
|
|
||||||
u_int16_t intr_error_status; /* soft error status */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define HDEVNAME(hp) ((hp)->sc->sc_dev.dv_xname)
|
#define HDEVNAME(hp) ((hp)->sc->sc_dev.dv_xname)
|
||||||
#define sdmmc_delay(t) udelay(t)
|
#define sdmmc_delay(t) udelay(t)
|
||||||
|
|
||||||
@ -119,13 +108,13 @@ static inline void bus_space_write_1(bus_space_tag_t iot, bus_space_handle_t ioh
|
|||||||
|
|
||||||
u32 splbio()
|
u32 splbio()
|
||||||
{
|
{
|
||||||
irq_disable(IRQ_SDHC);
|
// irq_disable(IRQ_SDHC);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void splx(u32 dummy)
|
void splx(u32 dummy)
|
||||||
{
|
{
|
||||||
irq_enable(IRQ_SDHC);
|
// irq_enable(IRQ_SDHC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* flag values */
|
/* flag values */
|
||||||
@ -213,6 +202,8 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
|
|||||||
struct sdhc_host *hp;
|
struct sdhc_host *hp;
|
||||||
u_int32_t caps;
|
u_int32_t caps;
|
||||||
int error = 1;
|
int error = 1;
|
||||||
|
|
||||||
|
strcpy(sc->sc_dev.dv_xname, "sdhc");
|
||||||
#ifdef SDHC_DEBUG
|
#ifdef SDHC_DEBUG
|
||||||
u_int16_t version;
|
u_int16_t version;
|
||||||
|
|
||||||
@ -232,7 +223,7 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
|
|||||||
/* Allocate one more host structure. */
|
/* Allocate one more host structure. */
|
||||||
if (sc->sc_nhosts < SDHC_MAX_HOSTS) {
|
if (sc->sc_nhosts < SDHC_MAX_HOSTS) {
|
||||||
sc->sc_nhosts++;
|
sc->sc_nhosts++;
|
||||||
hp = sc->sc_host[sc->sc_nhosts - 1];
|
hp = &sc->sc_host[sc->sc_nhosts - 1];
|
||||||
memset(hp, 0, sizeof(*hp));
|
memset(hp, 0, sizeof(*hp));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -315,6 +306,7 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
|
|||||||
saa.sct = &sdhc_functions;
|
saa.sct = &sdhc_functions;
|
||||||
saa.sch = hp;
|
saa.sch = hp;
|
||||||
|
|
||||||
|
hp->sdmmc = sdmmc_attach(&sdhc_functions, hp, "sdhc", ioh);
|
||||||
/* hp->sdmmc = config_found(&sc->sc_dev, &saa, NULL);
|
/* hp->sdmmc = config_found(&sc->sc_dev, &saa, NULL);
|
||||||
if (hp->sdmmc == NULL) {
|
if (hp->sdmmc == NULL) {
|
||||||
error = 0;
|
error = 0;
|
||||||
@ -325,7 +317,6 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
// free(hp, M_DEVBUF);
|
// free(hp, M_DEVBUF);
|
||||||
sc->sc_host[sc->sc_nhosts - 1] = NULL;
|
|
||||||
sc->sc_nhosts--;
|
sc->sc_nhosts--;
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -380,7 +371,7 @@ sdhc_shutdown(void *arg)
|
|||||||
|
|
||||||
/* XXX chip locks up if we don't disable it before reboot. */
|
/* XXX chip locks up if we don't disable it before reboot. */
|
||||||
for (i = 0; i < sc->sc_nhosts; i++) {
|
for (i = 0; i < sc->sc_nhosts; i++) {
|
||||||
hp = sc->sc_host[i];
|
hp = &sc->sc_host[i];
|
||||||
(void)sdhc_host_reset(hp);
|
(void)sdhc_host_reset(hp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -967,7 +958,7 @@ sdhc_intr(void *arg)
|
|||||||
|
|
||||||
/* We got an interrupt, but we don't know from which slot. */
|
/* We got an interrupt, but we don't know from which slot. */
|
||||||
for (host = 0; host < sc->sc_nhosts; host++) {
|
for (host = 0; host < sc->sc_nhosts; host++) {
|
||||||
struct sdhc_host *hp = sc->sc_host[host];
|
struct sdhc_host *hp = &sc->sc_host[host];
|
||||||
u_int16_t status;
|
u_int16_t status;
|
||||||
|
|
||||||
if (hp == NULL)
|
if (hp == NULL)
|
||||||
@ -983,6 +974,7 @@ sdhc_intr(void *arg)
|
|||||||
DPRINTF(2,("%s: interrupt status=%d\n", HDEVNAME(hp),
|
DPRINTF(2,("%s: interrupt status=%d\n", HDEVNAME(hp),
|
||||||
status));
|
status));
|
||||||
|
|
||||||
|
|
||||||
/* Claim this interrupt. */
|
/* Claim this interrupt. */
|
||||||
done = 1;
|
done = 1;
|
||||||
|
|
||||||
@ -1008,9 +1000,11 @@ sdhc_intr(void *arg)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Wake up the sdmmc event thread to scan for cards.
|
* Wake up the sdmmc event thread to scan for cards.
|
||||||
|
* TODO: move request to slow queue to make sure that
|
||||||
|
* we're not blocking other IRQs
|
||||||
*/
|
*/
|
||||||
/* if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION))
|
if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION))
|
||||||
sdmmc_needs_discover(hp->sdmmc);*/
|
sdmmc_needs_discover(hp->sdmmc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wake up the blocking process to service command
|
* Wake up the blocking process to service command
|
||||||
@ -1067,13 +1061,21 @@ static struct sdhc_softc __softc;
|
|||||||
|
|
||||||
void sdhc_irq(void)
|
void sdhc_irq(void)
|
||||||
{
|
{
|
||||||
|
ipc_request req;
|
||||||
sdhc_intr(&__softc);
|
sdhc_intr(&__softc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdhc_init(void)
|
void sdhc_init(void)
|
||||||
{
|
{
|
||||||
|
irq_enable(IRQ_SDHC);
|
||||||
memset(&__softc, 0, sizeof(__softc));
|
memset(&__softc, 0, sizeof(__softc));
|
||||||
sdhc_host_found(&__softc, 0, SDHC_REG_BASE, 1);
|
sdhc_host_found(&__softc, 0, SDHC_REG_BASE, 1);
|
||||||
// sdhc_host_found(&__softc, 0, SDHC_REG_BASE + 0x100, 1);
|
// sdhc_host_found(&__softc, 0, SDHC_REG_BASE + 0x100, 1);
|
||||||
// sdhc_host_found(&__softc, 0, 0x0d080000, 1);
|
// sdhc_host_found(&__softc, 0, 0x0d080000, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sdhc_ipc(volatile ipc_request *req)
|
||||||
|
{
|
||||||
|
switch (req->req) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
18
sdhcvar.h
18
sdhcvar.h
@ -21,13 +21,26 @@
|
|||||||
#define _SDHCVAR_H_
|
#define _SDHCVAR_H_
|
||||||
|
|
||||||
#include "bsdtypes.h"
|
#include "bsdtypes.h"
|
||||||
|
#include "ipc.h"
|
||||||
#define SDHC_MAX_HOSTS 4
|
#define SDHC_MAX_HOSTS 4
|
||||||
|
|
||||||
struct sdhc_host;
|
struct sdhc_host {
|
||||||
|
struct sdhc_softc *sc; /* host controller device */
|
||||||
|
struct device *sdmmc; /* generic SD/MMC device */
|
||||||
|
bus_space_tag_t iot; /* host register set tag */
|
||||||
|
bus_space_handle_t ioh; /* host register set handle */
|
||||||
|
u_int clkbase; /* base clock frequency in KHz */
|
||||||
|
int maxblklen; /* maximum block length */
|
||||||
|
int flags; /* flags for this host */
|
||||||
|
u_int32_t ocr; /* OCR value from capabilities */
|
||||||
|
u_int8_t regs[14]; /* host controller state */
|
||||||
|
u_int16_t intr_status; /* soft interrupt status */
|
||||||
|
u_int16_t intr_error_status; /* soft error status */
|
||||||
|
};
|
||||||
|
|
||||||
struct sdhc_softc {
|
struct sdhc_softc {
|
||||||
struct device sc_dev;
|
struct device sc_dev;
|
||||||
struct sdhc_host *sc_host[SDHC_MAX_HOSTS];
|
struct sdhc_host sc_host[SDHC_MAX_HOSTS];
|
||||||
int sc_nhosts;
|
int sc_nhosts;
|
||||||
u_int sc_flags;
|
u_int sc_flags;
|
||||||
};
|
};
|
||||||
@ -41,6 +54,7 @@ void sdhc_shutdown(void *);
|
|||||||
int sdhc_intr(void *);
|
int sdhc_intr(void *);
|
||||||
void sdhc_init(void);
|
void sdhc_init(void);
|
||||||
void sdhc_irq(void);
|
void sdhc_irq(void);
|
||||||
|
void sdhc_ipc(volatile ipc_request *req);
|
||||||
|
|
||||||
/* flag values */
|
/* flag values */
|
||||||
#define SDHC_F_NOPWR0 (1 << 0)
|
#define SDHC_F_NOPWR0 (1 << 0)
|
||||||
|
258
sdmmc.c
Normal file
258
sdmmc.c
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
/*
|
||||||
|
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
|
||||||
|
|
||||||
|
SD/MMC interface
|
||||||
|
|
||||||
|
Copyright (C) 2008, 2009 Sven Peter <svenpeter@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 2.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "bsdtypes.h"
|
||||||
|
#include "sdhcreg.h"
|
||||||
|
#include "sdhcvar.h"
|
||||||
|
#include "sdmmcchip.h"
|
||||||
|
#include "sdmmcreg.h"
|
||||||
|
#include "sdmmcvar.h"
|
||||||
|
#include "sdmmc.h"
|
||||||
|
#include "gecko.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#define SDMMC_DEBUG 1
|
||||||
|
|
||||||
|
#ifdef SDMMC_DEBUG
|
||||||
|
static int sdmmcdebug = 5;
|
||||||
|
#define DPRINTF(n,s) do { if ((n) <= sdmmcdebug) gecko_printf s; } while (0)
|
||||||
|
#else
|
||||||
|
#define DPRINTF(n,s) do {} while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sdmmc_card {
|
||||||
|
struct sdmmc_chip_functions *functions;
|
||||||
|
sdmmc_chipset_handle_t handle;
|
||||||
|
char name[255];
|
||||||
|
int no;
|
||||||
|
int inserted;
|
||||||
|
int sdhc_blockmode;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sdmmc_card cards[SDHC_MAX_HOSTS];
|
||||||
|
static int n_cards = 0;
|
||||||
|
|
||||||
|
static inline int sdmmc_host_reset(struct sdmmc_card *card)
|
||||||
|
{
|
||||||
|
return sdmmc_chip_host_reset(card->functions, card->handle);
|
||||||
|
}
|
||||||
|
static inline int sdmmc_host_card_detect(struct sdmmc_card *card)
|
||||||
|
{
|
||||||
|
return sdmmc_chip_card_detect(card->functions, card->handle);
|
||||||
|
#if 0
|
||||||
|
#define sdmmc_chip_host_maxblklen(tag, handle) \
|
||||||
|
((tag)->host_maxblklen((handle)))
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static inline int sdmmc_host_ocr(struct sdmmc_card *card)
|
||||||
|
{
|
||||||
|
return sdmmc_chip_host_ocr(card->functions, card->handle);
|
||||||
|
}
|
||||||
|
static inline int sdmmc_host_power(struct sdmmc_card *card, int ocr)
|
||||||
|
{
|
||||||
|
return sdmmc_chip_bus_power(card->functions, card->handle, ocr);
|
||||||
|
}
|
||||||
|
static inline int sdmmc_host_clock(struct sdmmc_card *card, int freq)
|
||||||
|
{
|
||||||
|
return sdmmc_chip_bus_clock(card->functions, card->handle, freq);
|
||||||
|
}
|
||||||
|
static inline void sdmmc_host_exec_command(struct sdmmc_card *card, struct
|
||||||
|
sdmmc_command *cmd)
|
||||||
|
{
|
||||||
|
sdmmc_chip_exec_command(card->functions, card->handle, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct device *sdmmc_attach(struct sdmmc_chip_functions *functions,
|
||||||
|
sdmmc_chipset_handle_t handle, const char *name, int no)
|
||||||
|
{
|
||||||
|
struct sdmmc_card *c;
|
||||||
|
|
||||||
|
if (n_cards >= SDHC_MAX_HOSTS) {
|
||||||
|
gecko_printf("n_cards(%d) >= %d!\n", n_cards, SDHC_MAX_HOSTS);
|
||||||
|
gecko_printf("starlet is soo going to crash very soon...\n");
|
||||||
|
|
||||||
|
// HACK
|
||||||
|
return (struct device *)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = &cards[n_cards++];
|
||||||
|
memset(c, 0, sizeof(*c));
|
||||||
|
|
||||||
|
c->functions = functions;
|
||||||
|
c->handle = handle;
|
||||||
|
c->no = no;
|
||||||
|
strncpy(c->name, name, sizeof(c->name));
|
||||||
|
|
||||||
|
DPRINTF(0, ("sdmmc: attached new SD/MMC card %d for host [%s:%d]\n",
|
||||||
|
n_cards-1, c->name, c->no));
|
||||||
|
|
||||||
|
sdmmc_host_reset(c);
|
||||||
|
|
||||||
|
if (sdmmc_host_card_detect(c)) {
|
||||||
|
DPRINTF(1, ("card is inserted. starting init sequence.\n"));
|
||||||
|
sdmmc_needs_discover((struct device *)(n_cards-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK
|
||||||
|
return (struct device *)(n_cards-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdmmc_needs_discover(struct device *dev)
|
||||||
|
{
|
||||||
|
int no = (int)dev;
|
||||||
|
struct sdmmc_card *c = &cards[no];
|
||||||
|
struct sdmmc_command cmd;
|
||||||
|
u32 ocr;
|
||||||
|
|
||||||
|
DPRINTF(0, ("sdmmc: card %d needs discovery.\n", no));
|
||||||
|
|
||||||
|
if (!sdmmc_host_card_detect(c)) {
|
||||||
|
DPRINTF(1, ("sdmmc: card %d (no longer?) inserted.\n", no));
|
||||||
|
c->inserted = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTF(1, ("sdmmc: enabling power for %d\n", no));
|
||||||
|
if (sdmmc_host_power(c, MMC_OCR_3_2V_3_3V|MMC_OCR_3_3V_3_4V) != 0) {
|
||||||
|
gecko_printf("sdmmc: powerup failed for card %d\n", no);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTF(1, ("sdmmc: enabling clock for %d\n", no));
|
||||||
|
if (sdmmc_host_clock(c, SDMMC_DEFAULT_CLOCK) != 0) {
|
||||||
|
gecko_printf("sdmmc: could not enable clock for card %d\n", no);
|
||||||
|
goto out_power;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTF(1, ("sdmmc: sending GO_IDLE_STATE for %d\n", no));
|
||||||
|
|
||||||
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
|
cmd.c_opcode = MMC_GO_IDLE_STATE;
|
||||||
|
cmd.c_flags = SCF_RSP_R0;
|
||||||
|
sdmmc_host_exec_command(c, &cmd);
|
||||||
|
|
||||||
|
if (cmd.c_error) {
|
||||||
|
gecko_printf("sdmmc: GO_IDLE_STATE failed with %d for card %d\n",
|
||||||
|
cmd.c_error, no);
|
||||||
|
goto out_clock;
|
||||||
|
}
|
||||||
|
DPRINTF(2, ("sdmmc: GO_IDLE_STATE response for %d: %x\n", no,
|
||||||
|
MMC_R1(cmd.c_resp)));
|
||||||
|
|
||||||
|
DPRINTF(1, ("sdmmc: sending SEND_IF_COND for %d\n", no));
|
||||||
|
|
||||||
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
|
cmd.c_opcode = SD_SEND_IF_COND;
|
||||||
|
cmd.c_arg = 0x1aa;
|
||||||
|
cmd.c_flags = SCF_RSP_R7;
|
||||||
|
sdmmc_host_exec_command(c, &cmd);
|
||||||
|
|
||||||
|
gecko_printf("response: %08x %08x %08x %08x\n", cmd.c_resp[0],
|
||||||
|
cmd.c_resp[1], cmd.c_resp[2], cmd.c_resp[3]);
|
||||||
|
|
||||||
|
ocr = sdmmc_host_ocr(c);
|
||||||
|
if (cmd.c_error || (cmd.c_resp[0] & 0xff) != 0xaa)
|
||||||
|
ocr &= ~SD_OCR_SDHC_CAP;
|
||||||
|
else
|
||||||
|
ocr |= SD_OCR_SDHC_CAP;
|
||||||
|
gecko_printf("-----> ocr: %x\n", ocr);
|
||||||
|
DPRINTF(2, ("sdmmc: SEND_IF_COND ocr: %x\n", ocr));
|
||||||
|
|
||||||
|
int tries;
|
||||||
|
for (tries = 10; tries > 0; tries--) {
|
||||||
|
udelay(10000);
|
||||||
|
|
||||||
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
|
cmd.c_opcode = MMC_APP_CMD;
|
||||||
|
cmd.c_arg = 0;
|
||||||
|
cmd.c_flags = SCF_RSP_R1;
|
||||||
|
sdmmc_host_exec_command(c, &cmd);
|
||||||
|
|
||||||
|
if (cmd.c_error)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
|
cmd.c_opcode = SD_APP_OP_COND;
|
||||||
|
cmd.c_arg = ocr;
|
||||||
|
cmd.c_flags = SCF_RSP_R3;
|
||||||
|
sdmmc_host_exec_command(c, &cmd);
|
||||||
|
if (cmd.c_error)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
gecko_printf("response: %08x\n", cmd.c_resp[0]);
|
||||||
|
if (ISSET(cmd.c_resp[0], MMC_OCR_MEM_READY))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!ISSET(cmd.c_resp[0], MMC_OCR_MEM_READY)) {
|
||||||
|
gecko_printf("sdmmc: card %d failed to powerup.\n", no);
|
||||||
|
goto out_power;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
out_clock:
|
||||||
|
out_power:
|
||||||
|
sdmmc_host_power(c, 0);
|
||||||
|
out:
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// struct sdmmc_task c_task; /* task queue entry */
|
||||||
|
u_int16_t c_opcode; /* SD or MMC command index */
|
||||||
|
u_int32_t c_arg; /* SD/MMC command argument */
|
||||||
|
sdmmc_response c_resp; /* response buffer */
|
||||||
|
void *c_data; /* buffer to send or read into */
|
||||||
|
int c_datalen; /* length of data buffer */
|
||||||
|
int c_blklen; /* block length */
|
||||||
|
int c_flags; /* see below */
|
||||||
|
#define SCF_ITSDONE 0x0001 /* command is complete */
|
||||||
|
#define SCF_CMD(flags) ((flags) & 0x00f0)
|
||||||
|
#define SCF_CMD_AC 0x0000
|
||||||
|
#define SCF_CMD_ADTC 0x0010
|
||||||
|
#define SCF_CMD_BC 0x0020
|
||||||
|
#define SCF_CMD_BCR 0x0030
|
||||||
|
#define SCF_CMD_READ 0x0040 /* read command (data expected) */
|
||||||
|
#define SCF_RSP_BSY 0x0100
|
||||||
|
#define SCF_RSP_136 0x0200
|
||||||
|
#define SCF_RSP_CRC 0x0400
|
||||||
|
#define SCF_RSP_IDX 0x0800
|
||||||
|
#define SCF_RSP_PRESENT 0x1000
|
||||||
|
/* response types */
|
||||||
|
#define SCF_RSP_R0 0 /* none */
|
||||||
|
#define SCF_RSP_R1 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
||||||
|
#define SCF_RSP_R1B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
|
||||||
|
#define SCF_RSP_R2 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_136)
|
||||||
|
#define SCF_RSP_R3 (SCF_RSP_PRESENT)
|
||||||
|
#define SCF_RSP_R4 (SCF_RSP_PRESENT)
|
||||||
|
#define SCF_RSP_R5 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
||||||
|
#define SCF_RSP_R5B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
|
||||||
|
#define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
||||||
|
#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
||||||
|
int c_error; /* errno value on completion */
|
||||||
|
|
||||||
|
/* Host controller owned fields for data xfer in progress */
|
||||||
|
int c_resid; /* remaining I/O */
|
||||||
|
u_char *c_buf; /* remaining data */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
33
sdmmc.h
Normal file
33
sdmmc.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
|
||||||
|
|
||||||
|
SD/MMC interface
|
||||||
|
|
||||||
|
Copyright (C) 2008, 2009 Sven Peter <svenpeter@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 2.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
#ifndef __SDMMC_H__
|
||||||
|
#define __SDMMC_H__ 1
|
||||||
|
|
||||||
|
#include "sdmmcvar.h"
|
||||||
|
#include "sdmmcchip.h"
|
||||||
|
|
||||||
|
#define SDMMC_DEFAULT_CLOCK 25000
|
||||||
|
|
||||||
|
struct device *sdmmc_attach(struct sdmmc_chip_functions *functions,
|
||||||
|
sdmmc_chipset_handle_t handle, const char *name, int no);
|
||||||
|
void sdmmc_needs_discover(struct device *dev);
|
||||||
|
#endif
|
@ -81,8 +81,10 @@ struct sdmmcbus_attach_args {
|
|||||||
long max_xfer;
|
long max_xfer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
void sdmmc_needs_discover(struct device *);
|
void sdmmc_needs_discover(struct device *);
|
||||||
void sdmmc_card_intr(struct device *);
|
void sdmmc_card_intr(struct device *);
|
||||||
|
#endif
|
||||||
void sdmmc_delay(u_int);
|
void sdmmc_delay(u_int);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -73,7 +73,7 @@ struct sdmmc_task {
|
|||||||
#define sdmmc_task_pending(xtask) ((xtask)->onqueue)
|
#define sdmmc_task_pending(xtask) ((xtask)->onqueue)
|
||||||
|
|
||||||
struct sdmmc_command {
|
struct sdmmc_command {
|
||||||
struct sdmmc_task c_task; /* task queue entry */
|
// struct sdmmc_task c_task; /* task queue entry */
|
||||||
u_int16_t c_opcode; /* SD or MMC command index */
|
u_int16_t c_opcode; /* SD or MMC command index */
|
||||||
u_int32_t c_arg; /* SD/MMC command argument */
|
u_int32_t c_arg; /* SD/MMC command argument */
|
||||||
sdmmc_response c_resp; /* response buffer */
|
sdmmc_response c_resp; /* response buffer */
|
||||||
|
Loading…
Reference in New Issue
Block a user