91 lines
3.5 KiB
C++
91 lines
3.5 KiB
C++
#ifndef _DRV_OMAP35X_SDMMC_HH_
|
|
#define _DRV_OMAP35X_SDMMC_HH_
|
|
|
|
#include <cstdint>
|
|
|
|
#include "interfaces.hh"
|
|
#include "exceptions.hh"
|
|
#include "mmio.hh"
|
|
#include "util.hh"
|
|
#include "scheduler.hh"
|
|
|
|
class OMAP35x_SDMMC : public IBlockDevice {
|
|
public:
|
|
OMAP35x_SDMMC(uintptr_t base, unsigned irq, unsigned drq_rx, unsigned drq_tx);
|
|
|
|
~OMAP35x_SDMMC();
|
|
|
|
// Get the (logical) block size of the device
|
|
virtual unsigned getBlockSize() const;
|
|
|
|
// Write getBlockSize()*'count' bytes of data from 'data' to the device starting at block 'pos'
|
|
/* Throw an ex::error on error, containing the errno describing the error. The contents of the
|
|
block device from 'pos' to 'pos'+'count' are undefined after an exception */
|
|
virtual void write(unsigned pos, char const* data, unsigned count);
|
|
// Read getBlockSize()*'count' bytes of data from the device starting at block 'pos' to 'data'
|
|
/* Throw an ex::error on error, containing the errno describing the error. The contents of 'data'
|
|
are undefined after an exception */
|
|
virtual void read(unsigned pos, char *data, unsigned count);
|
|
|
|
private:
|
|
void command(unsigned cmd, uint32_t arg);
|
|
uint32_t command_r1(unsigned cmd, uint32_t arg);
|
|
uint32_t command_r1b(unsigned cmd, uint32_t arg);
|
|
std::array<uint32_t, 4> command_r2(unsigned cmd, uint32_t arg);
|
|
|
|
void int_handler();
|
|
|
|
void test_data(unsigned block);
|
|
|
|
void acmd();
|
|
void cmd_reset();
|
|
void dat_reset();
|
|
void changeClock(unsigned cdiv);
|
|
|
|
enum class CardType {
|
|
sdxc,
|
|
sdhc,
|
|
sdv2,
|
|
sdv1,
|
|
mmc
|
|
};
|
|
|
|
char const* cardTypeToString() const;
|
|
|
|
MMIO_alloc base_;
|
|
unsigned irq_, drq_rx_, drq_tx_;
|
|
CardType cardType_;
|
|
unsigned blockSize_, sectorSize_, cardBlocks_;
|
|
unsigned rca_;
|
|
unsigned readTimeout_, writeTimeout_;
|
|
Scheduler::Semaphore intSem_;
|
|
uint32_t intStat_;
|
|
|
|
uint32_t volatile& r_sysconfig() { return _reg32(base_.get_virt(), 0x10); }
|
|
uint32_t volatile& r_sysstatus() { return _reg32(base_.get_virt(), 0x14); }
|
|
uint32_t volatile& r_csre() { return _reg32(base_.get_virt(), 0x24); }
|
|
uint32_t volatile& r_systest() { return _reg32(base_.get_virt(), 0x28); }
|
|
uint32_t volatile& r_con() { return _reg32(base_.get_virt(), 0x2c); }
|
|
uint32_t volatile& r_pwcnt() { return _reg32(base_.get_virt(), 0x30); }
|
|
uint32_t volatile& r_blk() { return _reg32(base_.get_virt(), 0x104); }
|
|
uint32_t volatile& r_arg() { return _reg32(base_.get_virt(), 0x108); }
|
|
uint32_t volatile& r_cmd() { return _reg32(base_.get_virt(), 0x10c); }
|
|
uint32_t volatile& r_rsp10() { return _reg32(base_.get_virt(), 0x110); }
|
|
uint32_t volatile& r_rsp32() { return _reg32(base_.get_virt(), 0x114); }
|
|
uint32_t volatile& r_rsp54() { return _reg32(base_.get_virt(), 0x118); }
|
|
uint32_t volatile& r_rsp76() { return _reg32(base_.get_virt(), 0x11c); }
|
|
uint32_t volatile& r_data() { return _reg32(base_.get_virt(), 0x120); }
|
|
uint32_t volatile& r_pstate() { return _reg32(base_.get_virt(), 0x124); }
|
|
uint32_t volatile& r_hctl() { return _reg32(base_.get_virt(), 0x128); }
|
|
uint32_t volatile& r_sysctl() { return _reg32(base_.get_virt(), 0x12c); }
|
|
uint32_t volatile& r_stat() { return _reg32(base_.get_virt(), 0x130); }
|
|
uint32_t volatile& r_ie() { return _reg32(base_.get_virt(), 0x134); }
|
|
uint32_t volatile& r_ise() { return _reg32(base_.get_virt(), 0x138); }
|
|
uint32_t volatile& r_ac12() { return _reg32(base_.get_virt(), 0x13c); }
|
|
uint32_t volatile& r_capa() { return _reg32(base_.get_virt(), 0x140); }
|
|
uint32_t volatile& r_cur_capa() { return _reg32(base_.get_virt(), 0x148); }
|
|
uint32_t volatile& r_rev() { return _reg32(base_.get_virt(), 0x1fc); }
|
|
};
|
|
|
|
#endif
|