genode/repos/os/src/drivers/sd_card/spec/imx53/esdhcv2.h

244 lines
6.9 KiB
C++

/*
* \brief Freescale Enhanced Secured Digital Host Controller Version 2
* \author Martin Stein
* \date 2015-02-05
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _ESDHCV2_H_
#define _ESDHCV2_H_
/* Genode includes */
#include <util/mmio.h>
#include <irq_session/connection.h>
#include <base/sleep.h>
/* local includes */
#include <sd_card.h>
#include <adma2.h>
namespace Genode
{
struct Esdhcv2;
class Esdhcv2_controller;
}
/**
* MMIO structure of a Freescale ESDHCv2
*/
struct Genode::Esdhcv2 : Mmio
{
struct Blkattr : Register<0x4, 32>
{
struct Blksize : Bitfield<0, 13> { };
struct Blkcnt : Bitfield<16, 16> { };
};
template <off_t OFFSET>
struct Cmdrsp_tpl : Register<OFFSET, 32>
{
struct Rsp136_8_24 : Register<OFFSET, 32>::template Bitfield<0, 24> { };
struct Rsp136_0_8 : Register<OFFSET, 32>::template Bitfield<24, 8> { };
};
struct Cmdarg : Register<0x8, 32> { };
struct Cmdrsp0 : Cmdrsp_tpl<0x10> { };
struct Cmdrsp1 : Cmdrsp_tpl<0x14> { };
struct Cmdrsp2 : Cmdrsp_tpl<0x18> { };
struct Cmdrsp3 : Cmdrsp_tpl<0x1c> { };
struct Rsp136_0 : Bitset_2<Cmdrsp3::Rsp136_0_8, Cmdrsp0::Rsp136_8_24> { };
struct Rsp136_1 : Bitset_2<Cmdrsp0::Rsp136_0_8, Cmdrsp1::Rsp136_8_24> { };
struct Rsp136_2 : Bitset_2<Cmdrsp1::Rsp136_0_8, Cmdrsp2::Rsp136_8_24> { };
struct Rsp136_3 : Bitset_2<Cmdrsp2::Rsp136_0_8, Cmdrsp3::Rsp136_8_24> { };
struct Xfertyp : Register<0xc, 32>
{
struct Dmaen : Bitfield<0, 1> { };
struct Bcen : Bitfield<1, 1> { };
struct Ac12en : Bitfield<2, 1> { };
struct Dtdsel : Bitfield<4, 1>
{
enum { WRITE = 0, READ = 1, };
};
struct Msbsel : Bitfield<5, 1> { };
struct Rsptyp : Bitfield<16, 2>
{
enum {
_0BIT = 0,
_136BIT = 1,
_48BIT = 2,
_48BIT_BUSY = 3,
};
};
struct Cccen : Bitfield<19, 1> { };
struct Cicen : Bitfield<20, 1> { };
struct Dpsel : Bitfield<21, 1> { };
struct Cmdtyp : Bitfield<22, 2>
{
enum { ABORT_CMD12 = 3 };
};
struct Cmdinx : Bitfield<24, 6> { };
};
struct Prsstat : Register<0x24, 32> { };
struct Prsstat_lhw : Register<0x24, 16>
{
struct Sdstb : Bitfield<3, 1> { };
static constexpr access_t cmd_allowed() { return Sdstb::reg_mask(); }
};
struct Proctl : Register<0x28, 32>
{
struct Dtw : Bitfield<1, 2>
{
enum { _1BIT = 0, _4BIT = 1 };
};
struct Dmas : Bitfield<8, 2> { enum { ADMA2 = 2 }; };
};
struct Sysctl : Register<0x2c, 32>
{
struct Ipgen : Bitfield<0, 1> { };
struct Hcken : Bitfield<1, 1> { };
struct Peren : Bitfield<2, 1> { };
struct Dvs : Bitfield<4, 4>
{
enum { DIV1 = 0x0, DIV4 = 0x3, DIV16 = 0xf, };
};
struct Sdclkfs : Bitfield<8, 8>
{
enum { DIV1 = 0x00, DIV2 = 0x01, DIV32 = 0x10, };
};
struct Dtocv : Bitfield<16, 4>
{
enum { SDCLK_TIMES_2_POW_27 = 0xe };
};
struct Rsta : Bitfield<24, 1> { };
struct Rstc : Bitfield<25, 1> { };
struct Rstd : Bitfield<26, 1> { };
};
template <off_t OFFSET>
struct Irq_tpl : Register<OFFSET, 32>
{
struct Cc : Register<OFFSET, 32>::template Bitfield<0, 1> { };
struct Tc : Register<OFFSET, 32>::template Bitfield<1, 1> { };
struct Dint : Register<OFFSET, 32>::template Bitfield<3, 1> { };
struct Ctoe : Register<OFFSET, 32>::template Bitfield<16, 1> { };
struct Cce : Register<OFFSET, 32>::template Bitfield<17, 1> { };
struct Cebe : Register<OFFSET, 32>::template Bitfield<18, 1> { };
struct Cie : Register<OFFSET, 32>::template Bitfield<19, 1> { };
struct Dtoe : Register<OFFSET, 32>::template Bitfield<20, 1> { };
struct Dce : Register<OFFSET, 32>::template Bitfield<21, 1> { };
struct Debe : Register<OFFSET, 32>::template Bitfield<22, 1> { };
struct Ac12e : Register<OFFSET, 32>::template Bitfield<24, 1> { };
struct Dmae : Register<OFFSET, 32>::template Bitfield<28, 1> { };
};
struct Irq : Irq_tpl<0> { };
struct Irqstat : Irq_tpl<0x30> { };
struct Irqstaten : Irq_tpl<0x34> { };
struct Irqsigen : Irq_tpl<0x38> { };
struct Maxcurrent : Register<0x48, 32> { };
struct Adsaddr : Register<0x58, 32> { };
struct Hostver : Register<0xfc, 32>
{
struct Svn : Bitfield<0, 8> { };
struct Vvn : Bitfield<8, 8> { };
};
struct Wml : Register<0x44, 32>
{
struct Rd_wml : Bitfield<0, 8> { };
struct Rd_brst_len : Bitfield<8, 5> { };
struct Wr_wml : Bitfield<16, 8> { };
struct Wr_brst_len : Bitfield<24, 5> { };
};
Esdhcv2(addr_t const mmio_base) : Mmio(mmio_base) { }
};
/**
* Implementation of the SD host-controller interface for the ESDHCv2
*/
struct Genode::Esdhcv2_controller
:
private Esdhcv2, public Sd_card::Host_controller
{
private:
enum {
BLOCK_SIZE = 512,
WATERMARK_WORDS = 16,
BURST_WORDS = 8,
};
enum Bus_width { BUS_WIDTH_1, BUS_WIDTH_4 };
enum Clock_divider { CLOCK_DIV_8, CLOCK_DIV_512 };
Irq_connection _irq;
Signal_receiver _irq_rec;
Signal_context _irq_ctx;
Delayer & _delayer;
Sd_card::Card_info _card_info;
bool const _use_dma;
Adma2::Table _adma2_table;
void _detect_err(char const * const err);
void _disable_irqs();
void _enable_irqs();
void _bus_width(Bus_width bus_width);
void _disable_clock();
void _enable_clock(Clock_divider divider, Delayer &delayer);
void _clock(enum Clock_divider divider, Delayer &delayer);
void _wait_for_irq();
int _reset(Delayer & delayer);
int _wait_for_cmd_allowed();
int _wait_for_cmd_complete();
int _wait_for_card_ready_mbw();
int _stop_transmission_mbw();
int _wait_for_cmd_complete_mb(bool const r);
int _prepare_dma_mb(size_t blk_cnt, addr_t buf_phys);
Sd_card::Card_info _init();
/****************************************
** Sd_card::Host_controller interface **
****************************************/
Sd_card::Cid _read_cid();
Sd_card::Csd _read_csd();
unsigned _read_rca();
bool _issue_command(Sd_card::Command_base const & command);
public:
/**
* Constructor
*
* \param base local base address of MMIO registers
* \param irq host-interrupt ID
* \param delayer delayer timing of MMIO accesses
* \param use_dma wether to use DMA or direct IO for transfers
*/
Esdhcv2_controller(addr_t const base, unsigned const irq,
Delayer & delayer, bool const use_dma);
~Esdhcv2_controller() { _irq_rec.dissolve(&_irq_ctx); }
/****************************************
** Sd_card::Host_controller interface **
****************************************/
bool read_blocks(size_t, size_t, char *);
bool write_blocks(size_t, size_t, char const *);
bool read_blocks_dma(size_t blk_nr, size_t blk_cnt, addr_t buf_phys);
bool write_blocks_dma(size_t blk_nr, size_t blk_cnt, addr_t buf_phys);
Sd_card::Card_info card_info() const { return _card_info; }
};
#endif /* _ESDHCV2_H_ */