From 3ec66893e377b088c1284d2d23adb2aeea6d7965 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sat, 27 Feb 2021 22:08:58 +0000 Subject: New port: FiiO M3K on bare metal Change-Id: I7517e7d5459e129dcfc9465c6fbd708619888fbe --- firmware/target/mips/ingenic_x1000/msc-x1000.h | 186 +++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 firmware/target/mips/ingenic_x1000/msc-x1000.h (limited to 'firmware/target/mips/ingenic_x1000/msc-x1000.h') diff --git a/firmware/target/mips/ingenic_x1000/msc-x1000.h b/firmware/target/mips/ingenic_x1000/msc-x1000.h new file mode 100644 index 0000000000..53a5b301f0 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/msc-x1000.h @@ -0,0 +1,186 @@ +/*************************************************************************** + * __________ __ ___. + * 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 + +/* 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_gpio_data { + int port; + int pin; + int active_level; +} msc_gpio_data; + +typedef struct msc_config { + int msc_nr; + int msc_type; + int bus_width; + const char* label; + struct msc_gpio_data cd_gpio; +} 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; + + 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__ */ -- cgit v1.2.3