rockbox/firmware/target/mips/ingenic_x1000/msc-x1000.h

183 lines
5.1 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2021 Aidan MacDonald
*
* 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; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __MSC_X1000_H__
#define __MSC_X1000_H__
#include "kernel.h"
#include "sdmmc.h"
#include <stdbool.h>
/* Number of MSC controllers */
#define MSC_COUNT 2
/* Media types */
#define MSC_TYPE_SD 0
#define MSC_TYPE_MMC 1
#define MSC_TYPE_ATA 2
#define MSC_TYPE_ANY 3
/* Clock modes */
#define MSC_CLK_MANUAL 0
#define MSC_CLK_AUTOMATIC 1
/* Clock status bits */
#define MSC_CLKST_ENABLE (1 << 0)
#define MSC_CLKST_AUTO (1 << 1)
/* Driver flags */
#define MSC_DF_ERRSTATE (1 << 0)
#define MSC_DF_READY (1 << 1)
#define MSC_DF_HCS_CARD (1 << 2)
#define MSC_DF_V2_CARD (1 << 3)
/* Request status codes */
#define MSC_REQ_SUCCESS 0
#define MSC_REQ_CRC_ERR 1
#define MSC_REQ_CARD_ERR 2
#define MSC_REQ_TIMEOUT 3
#define MSC_REQ_EXTRACTED 4
#define MSC_REQ_LOCKUP 5
#define MSC_REQ_ERROR 6
#define MSC_REQ_INCOMPLETE (-1)
/* Response types */
#define MSC_RESP_NONE 0
#define MSC_RESP_BUSY (1 << 7)
#define MSC_RESP_R1 1
#define MSC_RESP_R1B (MSC_RESP_R1|MSC_RESP_BUSY)
#define MSC_RESP_R2 2
#define MSC_RESP_R3 3
#define MSC_RESP_R6 6
#define MSC_RESP_R7 7
/* Request flags */
#define MSC_RF_INIT (1 << 0)
#define MSC_RF_ERR_CMD12 (1 << 1)
#define MSC_RF_AUTO_CMD12 (1 << 2)
#define MSC_RF_PROG (1 << 3)
#define MSC_RF_DATA (1 << 4)
#define MSC_RF_WRITE (1 << 5)
#define MSC_RF_ABORT (1 << 6)
/* Clock speeds */
#define MSC_SPEED_INIT 400000
#define MSC_SPEED_FAST 25000000
#define MSC_SPEED_HIGH 50000000
typedef struct msc_config {
int msc_nr;
int msc_type;
int bus_width;
const char* label;
int cd_gpio;
int cd_active_level;
} msc_config;
typedef struct msc_req {
/* Filled by caller */
int command;
unsigned argument;
int resptype;
int flags;
void* data;
unsigned nr_blocks;
unsigned block_len;
/* Filled by driver */
volatile unsigned response[4];
volatile int status;
} msc_req;
struct sd_dma_desc {
unsigned nda;
unsigned mem;
unsigned len;
unsigned cmd;
} __attribute__((aligned(16)));
typedef struct msc_drv {
int msc_nr;
int drive_nr;
const msc_config* config;
int driver_flags;
int clk_status;
unsigned cmdat_def;
msc_req* req;
unsigned iflag_done;
volatile int req_running;
volatile int card_present; /* Debounced status */
volatile int card_present_last; /* Status when we last polled it */
struct mutex lock;
struct semaphore cmd_done;
struct timeout cmd_tmo;
struct timeout cd_tmo;
struct sd_dma_desc dma_desc;
tCardInfo cardinfo;
} msc_drv;
/* Driver initialization, etc */
extern void msc_init(void);
extern msc_drv* msc_get(int type, int index);
extern msc_drv* msc_get_by_drive(int drive_nr);
extern void msc_lock(msc_drv* d);
extern void msc_unlock(msc_drv* d);
extern void msc_full_reset(msc_drv* d);
extern bool msc_card_detect(msc_drv* d);
/* Controller API */
extern void msc_ctl_reset(msc_drv* d);
extern void msc_set_clock_mode(msc_drv* d, int mode);
extern void msc_enable_clock(msc_drv* d, bool enable);
extern void msc_set_speed(msc_drv* d, int rate);
extern void msc_set_width(msc_drv* d, int width);
/* Request API */
extern void msc_async_start(msc_drv* d, msc_req* r);
extern void msc_async_abort(msc_drv* d, int status);
extern int msc_async_wait(msc_drv* d, int timeout);
extern int msc_request(msc_drv* d, msc_req* r);
/* Command helpers; note these are written with SD in mind
* and should be reviewed before using them for MMC / CE-ATA
*/
extern int msc_cmd_exec(msc_drv* d, msc_req* r);
extern int msc_app_cmd_exec(msc_drv* d, msc_req* r);
extern int msc_cmd_go_idle_state(msc_drv* d);
extern int msc_cmd_send_if_cond(msc_drv* d);
extern int msc_cmd_app_op_cond(msc_drv* d);
extern int msc_cmd_all_send_cid(msc_drv* d);
extern int msc_cmd_send_rca(msc_drv* d);
extern int msc_cmd_send_csd(msc_drv* d);
extern int msc_cmd_select_card(msc_drv* d);
extern int msc_cmd_set_bus_width(msc_drv* d, int width);
extern int msc_cmd_set_clr_card_detect(msc_drv* d, int arg);
extern int msc_cmd_switch_freq(msc_drv* d);
extern int msc_cmd_send_status(msc_drv* d);
extern int msc_cmd_set_block_len(msc_drv* d, unsigned len);
#endif /* __MSC_X1000_H__ */