genode/repos/os/src/drivers/sd_card/spec/imx/driver.h

300 lines
8.7 KiB
C
Raw Normal View History

/*
* \brief Secured Digital Host Controller
* \author Martin Stein
* \date 2015-02-05
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DRIVER_H_
#define _DRIVER_H_
/* Genode includes */
#include <timer_session/connection.h>
#include <irq_session/connection.h>
#include <os/attached_mmio.h>
/* local includes */
#include <driver_base.h>
#include <adma2.h>
namespace Sd_card { class Driver; }
class Sd_card::Driver : public Driver_base,
private Attached_mmio
{
private:
enum Bus_width { BUS_WIDTH_1, BUS_WIDTH_4 };
enum Clock { CLOCK_INITIAL, CLOCK_OPERATIONAL };
enum Clock_divider { CLOCK_DIV_4, CLOCK_DIV_8, CLOCK_DIV_512 };
/********************
** MMIO structure **
********************/
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> { };
template <off_t OFFSET>
struct Xfertyp_base : Register<OFFSET, 32>
{
struct Dmaen : Register<OFFSET, 32>::template Bitfield<0, 1> { };
struct Bcen : Register<OFFSET, 32>::template Bitfield<1, 1> { };
struct Ac12en : Register<OFFSET, 32>::template Bitfield<2, 1> { };
struct Dtdsel : Register<OFFSET, 32>::template Bitfield<4, 1>
{
enum { WRITE = 0, READ = 1, };
};
struct Msbsel : Register<OFFSET, 32>::template Bitfield<5, 1> { };
};
struct Mixctrl : Xfertyp_base<0x48>
{
struct Ddren : Bitfield<3, 1> { };
struct Nibblepos : Bitfield<6, 1> { };
struct Ac23en : Bitfield<7, 1> { };
struct Always_ones : Bitfield<31, 1> { };
};
struct Xfertyp : Xfertyp_base<0xc>
{
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 Cihb : Bitfield<0, 1> { };
struct Cdihb : Bitfield<1, 1> { };
struct Dla : Bitfield<2, 1> { };
struct Sdstb : Bitfield<3, 1> { };
};
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_28 = 0xf,
SDCLK_TIMES_2_POW_27 = 0xe,
SDCLK_TIMES_2_POW_13 = 0x0,
};
};
struct Ipp_rst_n : Bitfield<23, 1> { };
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> { };
};
struct Vendspec : Register<0xc0, 32>
{
struct Frc_sdclk_on : Bitfield<8, 1> { };
};
/************************
** Utility structures **
************************/
struct Timer_delayer : Timer::Connection, Mmio::Delayer
{
Timer_delayer(Genode::Env &env) : Timer::Connection(env) { }
void usleep(uint64_t us) override { Timer::Connection::usleep(us); }
};
struct Block_transfer
{
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Block::Packet_descriptor packet { };
bool pending = false;
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
bool read = false;
};
Env &_env;
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Block_transfer _block_transfer { };
Timer_delayer _delayer { _env };
Signal_handler<Driver> _irq_handler { _env.ep(), *this,
&Driver::_handle_irq };
2017-06-21 12:15:54 +02:00
Irq_connection _irq;
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Card_info _card_info { _init() };
Adma2::Table _adma2_table { _env.ram(), _env.rm() };
static bool _supported_host_version(Hostver::access_t hostver);
static void _watermark_level(Wml::access_t &wml);
void _handle_irq();
void _detect_err(char const * const err);
void _disable_irqs();
void _enable_irqs();
void _bus_width(Bus_width bus_width);
void _disable_clock();
void _disable_clock_preparation();
void _enable_clock(Clock_divider divider);
void _enable_clock_finish();
void _clock(Clock clock);
void _clock_finish(Clock clock);
int _reset();
void _reset_amendments();
int _wait_for_cmd_allowed();
int _wait_for_cmd_complete();
int _wait_for_card_ready_mbw();
int _stop_transmission();
void _stop_transmission_finish_xfertyp(Xfertyp::access_t &xfertyp);
int _wait_for_cmd_complete_mb_finish(bool const reading);
int _prepare_dma_mb(Block::Packet_descriptor packet,
bool reading,
size_t blk_cnt,
addr_t buf_phys);
bool _issue_cmd_finish_xfertyp(Xfertyp::access_t &xfertyp,
bool const transfer,
bool const multiblock,
bool const reading);
Card_info _init();
/*********************
** Host_controller **
*********************/
Cid _read_cid() override;
Csd _read_csd() override;
unsigned _read_rca() override;
bool _issue_command(Command_base const & cmd) override;
Card_info card_info() const override { return _card_info; }
public:
using Block::Driver::read;
using Block::Driver::write;
Driver(Env &env);
/*******************
** Block::Driver **
*******************/
void read_dma(Block::sector_t block_number,
size_t block_count,
addr_t phys,
Block::Packet_descriptor &packet) override;
void write_dma(Block::sector_t block_number,
size_t block_count,
addr_t phys,
Block::Packet_descriptor &packet) override;
bool dma_enabled() override { return true; }
Ram_dataspace_capability alloc_dma_buffer(size_t size) override {
return _env.ram().alloc(size, UNCACHED); }
};
#endif /* _DRIVER_H_ */