diff --git a/repos/base/include/spec/rpi/drivers/board_base.h b/repos/base/include/spec/rpi/drivers/board_base.h
index a20d385c4..24b653ffd 100644
--- a/repos/base/include/spec/rpi/drivers/board_base.h
+++ b/repos/base/include/spec/rpi/drivers/board_base.h
@@ -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,
diff --git a/repos/os/src/drivers/sd_card/spec/rpi/driver.h b/repos/os/src/drivers/sd_card/spec/rpi/driver.h
index 9037ebdfb..f65277dd9 100644
--- a/repos/os/src/drivers/sd_card/spec/rpi/driver.h
+++ b/repos/os/src/drivers/sd_card/spec/rpi/driver.h
@@ -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
#include
#include
+#include
/* local includes */
#include
@@ -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(),
- _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()
{
diff --git a/repos/os/src/drivers/sd_card/spec/rpi/sdhci.h b/repos/os/src/drivers/sd_card/spec/rpi/sdhci.h
index 565caff03..64a4e86f2 100644
--- a/repos/os/src/drivers/sd_card/spec/rpi/sdhci.h
+++ b/repos/os/src/drivers/sd_card/spec/rpi/sdhci.h
@@ -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(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(), read()+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::Power::bits(1)
+ | Host_ctrl::Voltage::bits(Host_ctrl::Voltage::V33));
+ }
+
/* enable interrupt status reporting */
write(~0UL);
write(~0UL);
@@ -277,7 +317,7 @@ struct Sdhci_controller : private Sdhci, public Sd_card::Host_controller
*/
Blksizecnt::access_t v = read();
Blksizecnt::Blkcnt::set(v, block_count);
- Blksizecnt::Blksize::set(v, 0x200);
+ Blksizecnt::Blksize::set(v, Block_size);
write(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());
}
+ 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());
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());
return false;
}