mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
sd_card: generalise RPi sd card driver
This enables to reuse the driver for zynq (and other platforms) in the future. Fixes #1925
This commit is contained in:
parent
036f3b5702
commit
3e1fa54c61
@ -65,6 +65,11 @@ struct Genode::Board_base
|
||||
|
||||
/* CPU cache */
|
||||
CACHE_LINE_SIZE_LOG2 = 5,
|
||||
|
||||
/* SD card */
|
||||
SDHCI_BASE = MMIO_0_BASE + 0x300000,
|
||||
SDHCI_SIZE = 0x100,
|
||||
SDHCI_IRQ = 62,
|
||||
};
|
||||
|
||||
enum Videocore_cache_policy { NON_COHERENT = 0,
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* \brief Raspberry Pi implementation of the Block::Driver interface
|
||||
* \author Norman Feske
|
||||
* \author Timo Wischer
|
||||
* \date 2014-09-21
|
||||
*/
|
||||
|
||||
@ -19,6 +20,7 @@
|
||||
#include <base/printf.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <block/component.h>
|
||||
#include <drivers/board_base.h>
|
||||
|
||||
/* local includes */
|
||||
#include <sdhci.h>
|
||||
@ -42,15 +44,8 @@ class Block::Sdhci_driver : public Block::Driver
|
||||
|
||||
} _delayer;
|
||||
|
||||
/* memory map */
|
||||
enum {
|
||||
SDHCI_BASE = 0x20300000,
|
||||
SDHCI_SIZE = 0x100,
|
||||
SDHCI_IRQ = 62,
|
||||
};
|
||||
|
||||
/* display sub system registers */
|
||||
Attached_io_mem_dataspace _sdhci_mmio { SDHCI_BASE, SDHCI_SIZE };
|
||||
Attached_io_mem_dataspace _sdhci_mmio { Board_base::SDHCI_BASE, Board_base::SDHCI_SIZE };
|
||||
|
||||
/* host-controller instance */
|
||||
Sdhci_controller _controller;
|
||||
@ -59,10 +54,10 @@ class Block::Sdhci_driver : public Block::Driver
|
||||
|
||||
public:
|
||||
|
||||
Sdhci_driver(bool use_dma)
|
||||
Sdhci_driver(bool use_dma, const bool set_voltage = false)
|
||||
:
|
||||
_controller((addr_t)_sdhci_mmio.local_addr<void>(),
|
||||
_delayer, SDHCI_IRQ, use_dma),
|
||||
_delayer, Board_base::SDHCI_IRQ, use_dma, set_voltage),
|
||||
_use_dma(use_dma)
|
||||
{
|
||||
Sd_card::Card_info const card_info = _controller.card_info();
|
||||
@ -76,7 +71,7 @@ class Block::Sdhci_driver : public Block::Driver
|
||||
** Block::Driver interface **
|
||||
*****************************/
|
||||
|
||||
Genode::size_t block_size() { return 512; }
|
||||
Genode::size_t block_size() { return Sdhci_controller::Block_size; }
|
||||
|
||||
virtual Block::sector_t block_count()
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
* \brief SDHCI controller driver
|
||||
* \author Norman Feske
|
||||
* \author Christian Helmuth
|
||||
* \author Timo Wischer
|
||||
* \date 2014-09-21
|
||||
*/
|
||||
|
||||
@ -91,6 +92,18 @@ struct Sdhci : Genode::Mmio
|
||||
struct Bre : Bitfield<11, 1> { };
|
||||
};
|
||||
|
||||
struct Host_ctrl : Register<0x28, 32>
|
||||
{
|
||||
struct Voltage : Bitfield<9, 3> {
|
||||
enum {
|
||||
V18 = 0b101,
|
||||
V30 = 0b110,
|
||||
V33 = 0b111,
|
||||
};
|
||||
};
|
||||
struct Power : Bitfield<8, 1> { };
|
||||
};
|
||||
|
||||
struct Arg1 : Register<0x8, 32> { };
|
||||
|
||||
struct Cmdtm : Register<0xc, 32>
|
||||
@ -125,12 +138,22 @@ struct Sdhci : Genode::Mmio
|
||||
struct Irpt_mask : Register<0x34, 32> { };
|
||||
struct Irpt_en : Register<0x38, 32> { };
|
||||
|
||||
struct Capabilities : Register<0x40, 32> { };
|
||||
|
||||
struct Host_version : Register<0xFE, 16>
|
||||
{
|
||||
struct Spec : Bitfield<0, 8> { };
|
||||
struct Vendor : Bitfield<8, 8> { };
|
||||
};
|
||||
|
||||
Sdhci(Genode::addr_t const mmio_base) : Genode::Mmio(mmio_base) { }
|
||||
};
|
||||
|
||||
|
||||
struct Sdhci_controller : private Sdhci, public Sd_card::Host_controller
|
||||
{
|
||||
enum { Block_size = 0x200 };
|
||||
|
||||
private:
|
||||
|
||||
Delayer &_delayer;
|
||||
@ -160,7 +183,7 @@ struct Sdhci_controller : private Sdhci, public Sd_card::Host_controller
|
||||
write<Control1::Data_tounit>(0xe);
|
||||
}
|
||||
|
||||
Sd_card::Card_info _init()
|
||||
Sd_card::Card_info _init(const bool set_voltage)
|
||||
{
|
||||
using namespace Sd_card;
|
||||
|
||||
@ -177,6 +200,23 @@ struct Sdhci_controller : private Sdhci, public Sd_card::Host_controller
|
||||
throw Detection_failed();
|
||||
}
|
||||
|
||||
PLOG("SDHCI version: %u (specification %u.0)",
|
||||
read<Host_version::Vendor>(), read<Host_version::Spec>()+1);
|
||||
|
||||
|
||||
/*
|
||||
* Raspberry Pi (BCM2835) does not need to
|
||||
* set the sd card voltage and
|
||||
* power up the host controller.
|
||||
* This registers are reserved and
|
||||
* always have to be written to 0.
|
||||
*/
|
||||
if (set_voltage) {
|
||||
/* Enable sd card power */
|
||||
write<Host_ctrl>(Host_ctrl::Power::bits(1)
|
||||
| Host_ctrl::Voltage::bits(Host_ctrl::Voltage::V33));
|
||||
}
|
||||
|
||||
/* enable interrupt status reporting */
|
||||
write<Irpt_mask>(~0UL);
|
||||
write<Irpt_en>(~0UL);
|
||||
@ -277,7 +317,7 @@ struct Sdhci_controller : private Sdhci, public Sd_card::Host_controller
|
||||
*/
|
||||
Blksizecnt::access_t v = read<Blksizecnt>();
|
||||
Blksizecnt::Blkcnt::set(v, block_count);
|
||||
Blksizecnt::Blksize::set(v, 0x200);
|
||||
Blksizecnt::Blksize::set(v, Block_size);
|
||||
write<Blksizecnt>(v);
|
||||
}
|
||||
|
||||
@ -300,9 +340,9 @@ struct Sdhci_controller : private Sdhci, public Sd_card::Host_controller
|
||||
* \param mmio_base local base address of MMIO registers
|
||||
*/
|
||||
Sdhci_controller(Genode::addr_t const mmio_base, Delayer &delayer,
|
||||
unsigned irq, bool use_dma)
|
||||
unsigned irq, bool use_dma, const bool set_voltage = false)
|
||||
:
|
||||
Sdhci(mmio_base), _delayer(delayer), _card_info(_init()), _irq(irq)
|
||||
Sdhci(mmio_base), _delayer(delayer), _card_info(_init(set_voltage)), _irq(irq)
|
||||
{ }
|
||||
|
||||
|
||||
@ -397,6 +437,16 @@ struct Sdhci_controller : private Sdhci, public Sd_card::Host_controller
|
||||
return Sd_card::Send_relative_addr::Response::Rca::get(read<Resp0>());
|
||||
}
|
||||
|
||||
size_t _block_to_command_address(const size_t block_number)
|
||||
{
|
||||
/* use byte position for addressing with standard cards */
|
||||
if (_card_info.version() == Sd_card::Csd3::Version::STANDARD_CAPACITY) {
|
||||
return block_number * Block_size;
|
||||
}
|
||||
|
||||
return block_number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read data blocks from SD card
|
||||
*
|
||||
@ -408,7 +458,7 @@ struct Sdhci_controller : private Sdhci, public Sd_card::Host_controller
|
||||
|
||||
_set_block_count(block_count);
|
||||
|
||||
if (!issue_command(Read_multiple_block(block_number))) {
|
||||
if (!issue_command(Read_multiple_block(_block_to_command_address(block_number)))) {
|
||||
PERR("Read_multiple_block failed, Status: 0x%08x", read<Status>());
|
||||
return false;
|
||||
}
|
||||
@ -454,7 +504,7 @@ struct Sdhci_controller : private Sdhci, public Sd_card::Host_controller
|
||||
|
||||
_set_block_count(block_count);
|
||||
|
||||
if (!issue_command(Write_multiple_block(block_number))) {
|
||||
if (!issue_command(Write_multiple_block(_block_to_command_address(block_number)))) {
|
||||
PERR("Write_multiple_block failed, Status: 0x%08x", read<Status>());
|
||||
return false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user