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; }