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

224 lines
5.4 KiB
C++

/*
* \brief OMAP4-specific implementation of the Block::Driver interface
* \author Norman Feske
* \date 2012-07-19
*/
/*
* Copyright (C) 2012-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 <os/attached_mmio.h>
#include <drivers/defs/panda.h>
#include <timer_session/connection.h>
#include <irq_session/connection.h>
/* local includes */
#include <driver_base.h>
namespace Sd_card { class Driver; }
class Sd_card::Driver : public Driver_base,
private Attached_mmio
{
private:
enum {
MMCHS1_MMIO_BASE = 0x4809c000,
MMCHS1_MMIO_SIZE = 0x00001000,
};
enum Bus_width { BUS_WIDTH_1, BUS_WIDTH_4 };
enum Clock_divider { CLOCK_DIV_0, CLOCK_DIV_240 };
enum Voltage { VOLTAGE_3_0, VOLTAGE_1_8 };
struct Sysconfig : Register<0x110, 32> { };
struct Con : Register<0x12c, 32>
{
struct Init : Bitfield<1, 1> { };
struct Dw8 : Bitfield<5, 1> { };
};
struct Cmd : Register<0x20c, 32>
{
struct Bce : Bitfield<1, 1> { };
struct Acen : Bitfield<2, 1> { };
struct Msbs : Bitfield<5, 1> { };
struct Index : Bitfield<24, 6> { };
struct Dp : Bitfield<21, 1> { };
struct Rsp_type : Bitfield<16, 2>
{
enum Response { RESPONSE_NONE = 0,
RESPONSE_136_BIT = 1,
RESPONSE_48_BIT = 2,
RESPONSE_48_BIT_WITH_BUSY = 3 };
};
struct Ddir : Bitfield<4, 1>
{
enum { WRITE = 0, READ = 1 };
};
};
struct Blk : Register<0x204, 32>
{
struct Blen : Bitfield<0, 12> { };
struct Nblk : Bitfield<16, 16> { };
};
struct Arg : Register<0x208, 32> { };
struct Rsp10 : Register<0x210, 32> { };
struct Rsp32 : Register<0x214, 32> { };
struct Rsp54 : Register<0x218, 32> { };
struct Rsp76 : Register<0x21c, 32> { };
struct Data : Register<0x220, 32> { };
struct Pstate : Register<0x224, 32>
{
struct Cmdi : Bitfield<0, 1> { };
struct Bwe : Bitfield<10, 1> { };
struct Bre : Bitfield<11, 1> { };
};
struct Hctl : Register<0x228, 32>
{
struct Sdbp : Bitfield<8, 1>
{
enum { POWER_OFF = 0, POWER_ON = 1 };
};
struct Sdvs : Bitfield<9, 3>
{
enum Voltage { VOLTAGE_1_8 = 5,
VOLTAGE_3_0 = 6,
VOLTAGE_3_3 = 7 };
};
struct Dtw : Bitfield<1, 1>
{
enum { ONE_BIT = 0, FOUR_BITS = 1 };
};
};
struct Sysctl : Register<0x22c, 32>
{
struct Ice : Bitfield<0, 1> { };
struct Ics : Bitfield<1, 1> { };
struct Ce : Bitfield<2, 1> { };
struct Clkd : Bitfield<6, 10> { };
struct Src : Bitfield<25, 1> { };
struct Dto : Bitfield<16, 4>
{
enum { TCF_2_POW_27 = 0xe };
};
};
struct Stat : Register<0x230, 32>
{
struct Tc : Bitfield<1, 1> { };
struct Cc : Bitfield<0, 1> { };
struct Erri : Bitfield<15, 1> { };
struct Cto : Bitfield<16, 1> { };
};
struct Ie : Register<0x234, 32>
{
struct Tc_enable : Bitfield<1, 1> { };
struct Cto_enable : Bitfield<16, 1> { };
};
struct Ise : Register<0x238, 32>
{
struct Tc_sigen : Bitfield<1, 1> { };
struct Cto_sigen : Bitfield<16, 1> { };
};
struct Capa : Register<0x240, 32>
{
struct Vs30 : Bitfield<25, 1> { };
struct Vs18 : Bitfield<26, 1> { };
};
struct Block_transfer
{
Block::Packet_descriptor packet { };
bool pending = false;
};
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); }
};
Env &_env;
Block_transfer _block_transfer { };
Timer_delayer _delayer { _env };
Signal_handler<Driver> _irq_handler { _env.ep(), *this, &Driver::_handle_irq };
Irq_connection _irq { _env, Panda::HSMMC_IRQ };
Card_info _card_info { _init() };
Card_info _init();
bool _wait_for_bre();
bool _wait_for_bwe();
void _handle_irq();
bool _reset_cmd_line();
void _disable_irq();
void _bus_width(Bus_width bus_width);
bool _sd_bus_power_on();
bool _set_and_enable_clock(enum Clock_divider divider);
void _set_bus_power(Voltage voltage);
bool _init_stream();
void _stop_clock() { Mmio::write<Sysctl::Ce>(0); }
/*********************
** Host_controller **
*********************/
bool _issue_command(Command_base const &command) override;
Cid _read_cid() override;
Csd _read_csd() override;
Card_info card_info() const override { return _card_info; }
unsigned _read_rca() override {
return Send_relative_addr::Response::Rca::get(Mmio::read<Rsp10>()); }
public:
Driver(Env &env);
/*******************
** Block::Driver **
*******************/
void read(Block::sector_t block_number,
size_t block_count,
char *buffer,
Block::Packet_descriptor &pkt) override;
void write(Block::sector_t block_number,
size_t block_count,
char const *buffer,
Block::Packet_descriptor &pkt) override;
};
#endif /* _DRIVER_H_ */