some more sd fail.

This commit is contained in:
Sven Peter 2009-04-11 23:42:53 +02:00 committed by bushing
parent 516d5e8d2f
commit ca7836a7a6
12 changed files with 359 additions and 41 deletions

View File

@ -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 \
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 \
boot2.o ldhack.o
boot2.o ldhack.o sdmmc.o
include ../../common.mk

View File

@ -24,6 +24,6 @@ struct device {
#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))
#endif

21
ipc.c
View File

@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "gecko.h"
#include "ipc.h"
#include "nand.h"
//#include "sdhc.h"
#include "sdhcvar.h"
#include "crypto.h"
#include "boot2.h"
#include "powerpc.h"
@ -150,7 +150,7 @@ static u32 process_slow(volatile ipc_request *req)
nand_ipc(req);
break;
case IPC_DEV_SD:
// sd_ipc(req);
sdhc_ipc(req);
break;
case IPC_DEV_KEYS:
crypto_ipc(req);
@ -171,6 +171,16 @@ static u32 process_slow(volatile ipc_request *req)
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)
{
volatile ipc_request *req = &in_queue[in_head];
@ -245,12 +255,7 @@ static void process_in(void)
break;
}
} else {
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);
ipc_add_slow(req);
}
}

8
ipc.h
View File

@ -62,12 +62,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define IPC_NAND_ERASE 0x0004
#define IPC_NAND_STATUS 0x0005
#define IPC_SD_MOUNT 0x0000
/*#define IPC_SD_MOUNT 0x0000
#define IPC_SD_SELECT 0x0001
#define IPC_SD_GETSTATE 0x0002
#define IPC_SD_READ 0x0003
#define IPC_SD_WRITE 0x0004
#define IPC_SD_GETSIZE 0x0005
#define IPC_SD_GETSIZE 0x0005*/
#define IPC_KEYS_GETOTP 0x0000
#define IPC_KEYS_GETEEP 0x0001
@ -120,4 +120,8 @@ void ipc_post(u32 code, u32 tag, u32 num_args, ...);
void ipc_flush(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

2
main.c
View File

@ -187,7 +187,7 @@ u32 _main(void *base)
irq_initialize();
irq_enable(IRQ_TIMER);
irq_enable(IRQ_GPIO1B);
// irq_enable(IRQ_GPIO1B);
irq_enable(IRQ_GPIO1);
irq_enable(IRQ_RESET);
gecko_timer_initialize();

View File

@ -5,7 +5,7 @@ EXTERN(__ipc_info)
ENTRY(_start)
__stack_size = 0x800;
__irqstack_size = 0x100;
__irqstack_size = 0x400; /* blame the bsd's sdhc_intr function */
__excstack_size = 0x100;
MEMORY {

48
sdhc.c
View File

@ -2,6 +2,7 @@
/*
* 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
* purpose with or without fee is hereby granted, provided that the above
@ -37,31 +38,19 @@
#include "sdmmcchip.h"
#include "sdmmcreg.h"
#include "sdmmcvar.h"
#include "sdmmc.h"
#include "gecko.h"
#include "string.h"
#include "irq.h"
#include "utils.h"
#include "ipc.h"
#define SDHC_DEBUG 1
#define SDHC_DEBUG 0
#define SDHC_COMMAND_TIMEOUT 0
#define SDHC_BUFFER_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 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()
{
irq_disable(IRQ_SDHC);
// irq_disable(IRQ_SDHC);
return 0;
}
void splx(u32 dummy)
{
irq_enable(IRQ_SDHC);
// irq_enable(IRQ_SDHC);
}
/* flag values */
@ -213,6 +202,8 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
struct sdhc_host *hp;
u_int32_t caps;
int error = 1;
strcpy(sc->sc_dev.dv_xname, "sdhc");
#ifdef SDHC_DEBUG
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. */
if (sc->sc_nhosts < SDHC_MAX_HOSTS) {
sc->sc_nhosts++;
hp = sc->sc_host[sc->sc_nhosts - 1];
hp = &sc->sc_host[sc->sc_nhosts - 1];
memset(hp, 0, sizeof(*hp));
}
else
@ -315,6 +306,7 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
saa.sct = &sdhc_functions;
saa.sch = hp;
hp->sdmmc = sdmmc_attach(&sdhc_functions, hp, "sdhc", ioh);
/* hp->sdmmc = config_found(&sc->sc_dev, &saa, NULL);
if (hp->sdmmc == NULL) {
error = 0;
@ -325,7 +317,6 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
err:
// free(hp, M_DEVBUF);
sc->sc_host[sc->sc_nhosts - 1] = NULL;
sc->sc_nhosts--;
return (error);
}
@ -380,7 +371,7 @@ sdhc_shutdown(void *arg)
/* XXX chip locks up if we don't disable it before reboot. */
for (i = 0; i < sc->sc_nhosts; i++) {
hp = sc->sc_host[i];
hp = &sc->sc_host[i];
(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. */
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;
if (hp == NULL)
@ -983,6 +974,7 @@ sdhc_intr(void *arg)
DPRINTF(2,("%s: interrupt status=%d\n", HDEVNAME(hp),
status));
/* Claim this interrupt. */
done = 1;
@ -1008,9 +1000,11 @@ sdhc_intr(void *arg)
/*
* 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))
sdmmc_needs_discover(hp->sdmmc);*/
if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION))
sdmmc_needs_discover(hp->sdmmc);
/*
* Wake up the blocking process to service command
@ -1067,13 +1061,21 @@ static struct sdhc_softc __softc;
void sdhc_irq(void)
{
ipc_request req;
sdhc_intr(&__softc);
}
void sdhc_init(void)
{
irq_enable(IRQ_SDHC);
memset(&__softc, 0, sizeof(__softc));
sdhc_host_found(&__softc, 0, SDHC_REG_BASE, 1);
// sdhc_host_found(&__softc, 0, SDHC_REG_BASE + 0x100, 1);
// sdhc_host_found(&__softc, 0, 0x0d080000, 1);
}
void sdhc_ipc(volatile ipc_request *req)
{
switch (req->req) {
}
}

View File

@ -21,13 +21,26 @@
#define _SDHCVAR_H_
#include "bsdtypes.h"
#include "ipc.h"
#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 device sc_dev;
struct sdhc_host *sc_host[SDHC_MAX_HOSTS];
struct sdhc_host sc_host[SDHC_MAX_HOSTS];
int sc_nhosts;
u_int sc_flags;
};
@ -41,6 +54,7 @@ void sdhc_shutdown(void *);
int sdhc_intr(void *);
void sdhc_init(void);
void sdhc_irq(void);
void sdhc_ipc(volatile ipc_request *req);
/* flag values */
#define SDHC_F_NOPWR0 (1 << 0)

258
sdmmc.c Normal file
View 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
View 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

View File

@ -81,8 +81,10 @@ struct sdmmcbus_attach_args {
long max_xfer;
};
#if 0
void sdmmc_needs_discover(struct device *);
void sdmmc_card_intr(struct device *);
#endif
void sdmmc_delay(u_int);
#endif

View File

@ -73,7 +73,7 @@ struct sdmmc_task {
#define sdmmc_task_pending(xtask) ((xtask)->onqueue)
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_int32_t c_arg; /* SD/MMC command argument */
sdmmc_response c_resp; /* response buffer */