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

247 lines
6.9 KiB
C
Raw Normal View History

/*
* \brief Exynos5-specific implementation of the Block::Driver interface
* \author Sebastian Sumpf
* \author Martin Stein
* \date 2013-03-22
*/
2013-03-22 15:31:16 +01:00
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
2013-03-22 15:31:16 +01:00
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
2013-03-22 15:31:16 +01:00
*/
#ifndef _DRIVER_H_
#define _DRIVER_H_
/* Genode includes */
#include <os/attached_mmio.h>
#include <timer_session/connection.h>
#include <drivers/defs/exynos5.h>
#include <regulator_session/connection.h>
#include <irq_session/connection.h>
#include <base/attached_ram_dataspace.h>
/* local includes */
#include <driver_base.h>
namespace Sd_card { class Driver; }
class Sd_card::Driver : public Driver_base,
private Attached_mmio
{
private:
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
/*
* Noncopyable
*/
Driver(Driver const &);
Driver &operator = (Driver const &);
enum {
HOST_FREQ = 52000000,
CLK_FREQ = 400000000,
CLK_DIV_52Mhz = 4,
CLK_DIV_400Khz = 0xff,
MSH_BASE = 0x12200000,
MSH_SIZE = 0x10000,
IDMAC_DESC_MAX_ENTRIES = 1024
};
enum Bus_width {
BUS_WIDTH_1 = 0,
BUS_WIDTH_4 = 1,
BUS_WIDTH_8 = 1 << 16,
};
template <off_t OFFSET, bool STRICT_WRITE = false>
struct Register : Mmio::Register<OFFSET, 32, STRICT_WRITE> { };
struct Ctrl : Register<0x0>
{
struct Reset : Bitfield<0, 3> { };
struct Global_interrupt : Bitfield<4, 1> { };
struct Dma_enable : Bitfield<5, 1> { };
struct Use_internal_dmac : Bitfield<25, 1> { };
};
struct Pwren : Register<0x4> { };
struct Clkdiv : Register<0x8> { };
struct Clkena : Register<0x10> { };
struct Tmout : Register<0x14> { };
struct Ctype : Register<0x18, true> { };
struct Blksize : Register<0x1c> { };
struct Bytcnt : Register<0x20> { };
struct Intmask : Register<0x24> { };
struct Cmdarg : Register<0x28> { };
struct Cmd : Register<0x2c>
{
struct Index : Bitfield<0, 6> { };
struct Rsp_type : Bitfield<6, 3>
{
enum Response { RESPONSE_NONE = 0,
RESPONSE_48_BIT = 1,
RESPONSE_48_BIT_WITH_BUSY = 5,
RESPONSE_136_BIT = 7,
};
};
struct Data_expected : Bitfield<9, 1> { };
struct Write : Bitfield<10, 1> { };
struct Wait_prvdata_complete : Bitfield<13, 1> { };
struct Init_sequence : Bitfield<15, 1> { };
struct Update_clock_registers_only : Bitfield<21, 1> { };
struct Use_hold_reg : Bitfield<29, 1> { };
struct Start_cmd : Bitfield<31, 1> { };
};
struct Rsp0 : Register<0x30> { };
struct Rsp1 : Register<0x34> { };
struct Rsp2 : Register<0x38> { };
struct Rsp3 : Register<0x3c> { };
struct Mintsts : Register<0x40> { };
struct Rintsts : Register<0x44, true>
{
struct Response_error : Bitfield<1, 1> { };
struct Data_transfer_over : Bitfield<3, 1> { };
struct Command_done : Bitfield<2, 1> { };
struct Data_crc_error : Bitfield<7, 1> { };
struct Response_timeout : Bitfield<8, 1> { };
struct Data_read_timeout : Bitfield<9, 1> { };
};
struct Status : Register<0x48>
{
struct Data_busy : Bitfield<9, 1> { };
};
struct Fifoth : Register<0x4c> { };
struct Bmod : Register<0x80, true>
{
struct Fixed_burst : Bitfield<1, 1> { };
struct Idmac_enable : Bitfield<7, 1> { };
};
struct Pldmnd : Register<0x84> { };
struct Idsts : Register<0x8c> { };
struct Idinten : Register<0x90, true> { };
struct Dbaddr : Register<0x88> { };
struct Clksel : Register<0x9c> { };
struct Emmc_ddr_req : Register<0x10c, true> { };
struct Idmac_desc
{
enum Flags {
NONE = 0,
DIC = 1 << 1,
LD = 1 << 2,
FS = 1 << 3,
CH = 1 << 4,
ER = 1 << 5,
OWN = 1 << 31,
};
unsigned flags;
unsigned bytes;
unsigned addr;
unsigned next;
size_t set(size_t block_count,
size_t block_size,
addr_t phys_addr,
Flags flag);
};
struct Clock_regulator
{
Regulator::Connection regulator;
Clock_regulator(Env &env) : regulator(env, Regulator::CLK_MMC0) {
regulator.state(true); }
};
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;
};
Env &_env;
Timer_delayer _delayer { _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 { };
Clock_regulator _clock_regulator { _env };
Signal_handler<Driver> _irq_handler { _env.ep(), *this, &Driver::_handle_irq };
Irq_connection _irq { _env, Exynos5::SDMMC0_IRQ };
Attached_ram_dataspace _idmac_desc_ds { _env.ram(), _env.rm(),
IDMAC_DESC_MAX_ENTRIES * sizeof(Idmac_desc),
UNCACHED };
Idmac_desc *const _idmac_desc { _idmac_desc_ds.local_addr<Idmac_desc>() };
addr_t const _idmac_desc_phys { Dataspace_client(_idmac_desc_ds.cap())
.phys_addr() };
Card_info _card_info { _init() };
bool _reset();
void _reset_fifo();
void _disable_irq();
bool _update_clock_registers();
bool _setup_bus(unsigned clock_div);
void _handle_irq();
Card_info _init();
bool _setup_idmac_descriptor_table(size_t block_count,
addr_t phys_addr);
/*********************
** Host_controller **
*********************/
bool _issue_command(Command_base const &command) override;
Cid _read_cid() override ;
Csd _read_csd() override ;
size_t _read_ext_csd() override;
unsigned _read_rca() override { return 0; }
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 buf_phys,
Block::Packet_descriptor &pkt) override;
void write_dma(Block::sector_t block_number,
size_t block_count,
addr_t buf_phys,
Block::Packet_descriptor &pkt) 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_ */