diff --git a/repos/os/src/driver/sd_card/imx/driver.cc b/repos/os/src/driver/sd_card/imx/driver.cc deleted file mode 100644 index fefa5bc4c5..0000000000 --- a/repos/os/src/driver/sd_card/imx/driver.cc +++ /dev/null @@ -1,536 +0,0 @@ -/* - * \brief Secured Digital Host Controller - * \author Martin Stein - * \date 2015-02-05 - */ - -/* - * Copyright (C) 2015-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. - */ - -/* local includes */ -#include - -using namespace Sd_card; -using namespace Genode; - - -int Driver::_wait_for_card_ready_mbw() -{ - /* - * Poll card status - * - * The maximum number of attempts and the delay between two attempts are - * freely chosen. - */ - unsigned attempts = 5; - uint64_t constexpr attempts_delay_us = 100000; - while (1) { - if (!attempts) { - error("Reading card status after multiblock write failed"); - return -1; - } - /* assemble argument register value */ - Send_status::Arg::access_t cmdarg = 0; - Send_status::Arg::Rca::set(cmdarg, _card_info.rca()); - - /* assemble command register value */ - Xfertyp::access_t xfertyp = 0; - Xfertyp::Cmdinx::set(xfertyp, Send_status::INDEX); - Xfertyp::Cicen::set(xfertyp, 1); - Xfertyp::Cccen::set(xfertyp, 1); - Xfertyp::Rsptyp::set(xfertyp, Xfertyp::Rsptyp::_48BIT); - Xfertyp::Msbsel::set(xfertyp, 1); - Xfertyp::Bcen::set(xfertyp, 1); - Xfertyp::Dmaen::set(xfertyp, 1); - - /* send command as soon as the host allows it */ - if (_wait_for_cmd_allowed()) { return -1; } - Mmio::write(cmdarg); - Mmio::write(xfertyp); - - /* wait for command completion */ - if (_wait_for_cmd_complete()) { return -1; } - - /* check for errors */ - R1_response_0::access_t const resp = Mmio::read(); - if (R1_response_0::Error::get(resp)) { - error("Reading card status after multiblock write failed"); - return -1; - } - /* if card is in a ready state, return success, retry otherwise */ - if (R1_response_0::card_ready(resp)) { break; } - _delayer.usleep(attempts_delay_us); - } - return 0; -} - - -int Driver::_stop_transmission() -{ - /* write argument register */ - Mmio::write(0); - - /* write command register */ - Xfertyp::access_t xfertyp = 0; - Xfertyp::Cmdinx::set(xfertyp, Stop_transmission::INDEX); - Xfertyp::Cmdtyp::set(xfertyp, Xfertyp::Cmdtyp::ABORT_CMD12); - Xfertyp::Cccen::set(xfertyp, 1); - Xfertyp::Cicen::set(xfertyp, 1); - Xfertyp::Rsptyp::set(xfertyp, Xfertyp::Rsptyp::_48BIT_BUSY); - _stop_transmission_finish_xfertyp(xfertyp); - Mmio::write(xfertyp); - - /* wait for command completion */ - if (_wait_for_cmd_complete()) { return -1; } - return 0; -} - - -void Driver::_handle_irq() -{ - _irq.ack(); - - /* the handler is only for block transfers, on other commands we poll */ - if (!_block_transfer.pending) { - return; } - - /* - * The host signals on multi-block transfers seem to be broken. - * Synchronizing to "Transfer Complete" before returning from transfers - * and to "Command Inhibit" before sending further commands - as it is - * done with other controllers - isn't sufficient. Instead, both "Transfer - * Complete" and "Command Complete" must be gathered. - */ - try { - wait_for(Attempts(1000), Microseconds(1000), _delayer, - Irqstat::Cc::Equal(1), Irqstat::Tc::Equal(1)); } - catch (Polling_timeout) { - error("Completion host signal timed out"); - throw -1; - } - /* acknowledge completion signals */ - Irqstat::access_t irqstat = 0; - Irqstat::Cc::set(irqstat, 1); - Irqstat::Tc::set(irqstat, 1); - Mmio::write(irqstat); - - if (_wait_for_cmd_complete_mb_finish(_block_transfer.read)) { - throw -1; } - - _block_transfer.pending = false; - ack_packet(_block_transfer.packet, true); -} - - -int Driver::_wait_for_cmd_complete() -{ - try { wait_for(Attempts(200), Microseconds(5000), _delayer, - Irqstat::Cc::Equal(1)); } - catch (Polling_timeout) { - error("command timed out"); - return -1; - } - Mmio::write(Irqstat::Cc::reg_mask()); - return 0; -} - - -bool Driver::_issue_command(Command_base const & command) -{ - /* get command characteristics */ - bool const transfer = command.transfer != TRANSFER_NONE; - bool const reading = command.transfer == TRANSFER_READ; - bool const multiblock = - command.index == Read_multiple_block::INDEX || - command.index == Write_multiple_block::INDEX; - - /* set command index */ - Xfertyp::access_t xfertyp = 0; - Xfertyp::Cmdinx::set(xfertyp, command.index); - - /* select response type */ - typedef Xfertyp::Rsptyp Rsptyp; - Xfertyp::access_t rsptyp = 0; - switch (command.rsp_type) { - case RESPONSE_NONE: rsptyp = Rsptyp::_0BIT; break; - case RESPONSE_136_BIT: rsptyp = Rsptyp::_136BIT; break; - case RESPONSE_48_BIT: rsptyp = Rsptyp::_48BIT; break; - case RESPONSE_48_BIT_WITH_BUSY: rsptyp = Rsptyp::_48BIT_BUSY; break; - } - Xfertyp::Rsptyp::set(xfertyp, rsptyp); - - /* generic transfer settings */ - if (command.transfer != TRANSFER_NONE) { - Xfertyp::Dpsel::set(xfertyp); - if (multiblock) { - Xfertyp::Cicen::set(xfertyp, 1); - Xfertyp::Cccen::set(xfertyp, 1); - } - } - /* version-dependent transfer settings and issue command */ - _issue_cmd_finish_xfertyp(xfertyp, transfer, multiblock, reading); - Mmio::write(command.arg); - Mmio::write(xfertyp); - - /* for block transfers there's a signal handler, on other commands poll */ - return transfer ? true : !_wait_for_cmd_complete(); -} - - -Cid Driver::_read_cid() -{ - Cid cid; - cid.raw_0 = Mmio::read(); - cid.raw_1 = Mmio::read(); - cid.raw_2 = Mmio::read(); - cid.raw_3 = Mmio::read(); - return cid; -} - - -Csd Driver::_read_csd() -{ - Csd csd; - csd.csd0 = Mmio::read(); - csd.csd1 = Mmio::read(); - csd.csd2 = Mmio::read(); - csd.csd3 = Mmio::read(); - return csd; -} - - -unsigned Driver::_read_rca() -{ - Cmdrsp0::access_t const rsp0 = Mmio::read(); - return Send_relative_addr::Response::Rca::get(rsp0); -} - - -void Driver::read_dma(Block::sector_t blk_nr, - size_t blk_cnt, - addr_t buf_phys, - Block::Packet_descriptor &packet) -{ - if (_prepare_dma_mb(packet, true, blk_cnt, buf_phys)) { - throw Io_error(); } - - if (!issue_command(Read_multiple_block((unsigned long)blk_nr))) { - throw Io_error(); } -} - - -void Driver::write_dma(Block::sector_t blk_nr, - size_t blk_cnt, - addr_t buf_phys, - Block::Packet_descriptor &packet) -{ - if (_prepare_dma_mb(packet, false, blk_cnt, buf_phys)) { - throw Io_error(); } - - if (!issue_command(Write_multiple_block((unsigned long)blk_nr))) { - throw Io_error(); } -} - - -int Driver::_prepare_dma_mb(Block::Packet_descriptor packet, - bool reading, - size_t blk_cnt, - addr_t buf_phys) -{ - if (_block_transfer.pending) { - throw Request_congestion(); } - - - /* write ADMA2 table to DMA */ - size_t const req_size = blk_cnt * _block_size(); - if (_adma2_table.setup_request(req_size, buf_phys)) { return -1; } - - /* configure DMA at host */ - Mmio::write(_adma2_table.base_dma()); - Mmio::write(_block_size()); - Mmio::write(blk_cnt); - - _block_transfer.read = reading; - _block_transfer.packet = packet; - _block_transfer.pending = true; - return 0; -} - - -int Driver::_wait_for_cmd_allowed() -{ - /* - * At least after multi-block writes on i.MX53 with the fix for the broken - * "Auto Command 12", waiting only for "Command Inhibit" isn't sufficient - * as "Data Line Active" and "Data Inhibit" may also be active. - */ - try { wait_for(_delayer, Prsstat::Dla::Equal(0), - Prsstat::Sdstb::Equal(1), - Prsstat::Cihb::Equal(0), - Prsstat::Cdihb::Equal(0)); } - catch (Polling_timeout) { - error("wait till issuing a new command is allowed timed out"); - return -1; - } - return 0; -} - - -Card_info Driver::_init() -{ - /* install IRQ signal */ - _irq.sigh(_irq_handler); - - /* configure host for initialization stage */ - if (_reset()) { - _detect_err("Host reset failed"); } - _disable_irqs(); - - if (!_supported_host_version(Mmio::read())) { - error("host version not supported"); - throw Detection_failed(); - } - - /* - * We should check host capabilities at this point if we want to - * support other versions of the SDHC. For the already supported - * versions we know that the capabilities fit our requirements. - */ - - /* configure IRQs, bus width, and clock for initialization */ - _enable_irqs(); - _bus_width(BUS_WIDTH_1); - _delayer.usleep(10000); - _clock(CLOCK_INITIAL); - - /* - * Initialize card - */ - - /* - * At this point we should do an SDIO card reset if we later want - * to detect the unwanted case of an SDIO card beeing inserted. - * The reset would be done via 2 differently configured - * Io_rw_direct commands. - */ - - _delayer.usleep(1000); - if (!issue_command(Go_idle_state())) { - _detect_err("Go_idle_state command failed"); } - - _delayer.usleep(2000); - if (!issue_command(Send_if_cond())) { - _detect_err("Send_if_cond command failed"); } - - if (Mmio::read() != 0x1aa) { - _detect_err("Unexpected response of Send_if_cond command"); } - - /* - * At this point we could detect the unwanted case of an SDIO card - * beeing inserted by issuing 4 Io_send_op_cond commands at an - * interval of 10 ms (they should time out on SD). - */ - - if (!issue_command(Sd_send_op_cond(0, false))) { - _detect_err("Sd_send_op_cond command failed"); } - - _delayer.usleep(1000); - if (!issue_command(Go_idle_state())) { - _detect_err("Go_idle_state command failed"); } - - _delayer.usleep(2000); - if (!issue_command(Send_if_cond())) { - _detect_err("Send_if_cond failed"); } - - if (Mmio::read() != 0x1aa) { - _detect_err("Unexpected response of Send_if_cond command"); } - - /* - * Power on card - * - * We need to issue the same Sd_send_op_cond command multiple - * times. The first time, we receive the status information. On - * subsequent attempts, the response tells us that the card is - * busy. Usually, the command is issued twice. We give up if the - * card is not reaching busy state after one second. - */ - int i = 1000; - for (; i > 0; --i) { - if (!issue_command(Sd_send_op_cond(0x200000, true))) { - _detect_err("Sd_send_op_cond command failed"); } - - if (Ocr::Busy::get(Mmio::read())) { break; } - _delayer.usleep(1000); - } - if (!i) { _detect_err("Could not power-on SD card"); } - - /* get basic information about the card */ - Card_info card_info = _detect(); - - /* - * Configure working clock of host - * - * Host and card may be driven with a higher clock rate but - * checks (maybe read SSR/SCR, read switch, try frequencies) are - * necessary for that. - */ - _clock(CLOCK_OPERATIONAL); - - /* - * Configure card and host to use 4 data signals - * - * Host and card may be driven with a higher bus width but - * further checks (read SCR) are necessary for that. - */ - if (!issue_command(Set_bus_width(Set_bus_width::Arg::Bus_width::FOUR_BITS), - card_info.rca())) - { - _detect_err("Set_bus_width(FOUR_BITS) command failed"); - } - _bus_width(BUS_WIDTH_4); - _delayer.usleep(10000); - - /* configure card to use given block size */ - if (!issue_command(Set_blocklen(_block_size()))) { - _detect_err("Set_blocklen command failed"); } - - /* configure host buffer */ - Wml::access_t wml = Mmio::read(); - _watermark_level(wml); - Mmio::write(wml); - - /* configure ADMA */ - Mmio::write(Proctl::Dmas::ADMA2); - - /* configure interrupts for operational mode */ - _disable_irqs(); - Mmio::write(~0); - _enable_irqs(); - return card_info; -} - - -void Driver::_detect_err(char const * const err) -{ - error(err); - throw Detection_failed(); -} - - -int Driver::_reset() -{ - /* start reset */ - Mmio::write(1); - _reset_amendments(); - - /* wait for reset completion */ - try { wait_for(_delayer, Sysctl::Rsta::Equal(0)); } - catch (Polling_timeout) { - error("Reset timed out"); - return -1; - } - return 0; -} - - -void Driver::_disable_irqs() -{ - Mmio::write(0); - Mmio::write(0); -} - - -void Driver::_enable_irqs() -{ - Irq::access_t irq = 0; - Irq::Cc::set(irq, 1); - Irq::Tc::set(irq, 1); - Irq::Dint::set(irq, 1); - Irq::Ctoe::set(irq, 1); - Irq::Cce::set(irq, 1); - Irq::Cebe::set(irq, 1); - Irq::Cie::set(irq, 1); - Irq::Dtoe::set(irq, 1); - Irq::Dce::set(irq, 1); - Irq::Debe::set(irq, 1); - Irq::Ac12e::set(irq, 1); - Irq::Dmae::set(irq, 1); - Mmio::write(irq); - Mmio::write(irq); -} - - -void Driver::_bus_width(Bus_width bus_width) -{ - switch (bus_width) { - case BUS_WIDTH_1: Mmio::write(Proctl::Dtw::_1BIT); break; - case BUS_WIDTH_4: Mmio::write(Proctl::Dtw::_4BIT); break; - } -} - - -void Driver::_disable_clock() -{ - _disable_clock_preparation(); - Sysctl::access_t sysctl = Mmio::read(); - Sysctl::Ipgen::set(sysctl, 0); - Sysctl::Hcken::set(sysctl, 0); - Sysctl::Peren::set(sysctl, 0); - Sysctl::Dvs::set(sysctl, Sysctl::Dvs::DIV1); - Sysctl::Sdclkfs::set(sysctl, Sysctl::Sdclkfs::DIV1); - Mmio::write(sysctl); -} - - -void Driver::_enable_clock(Clock_divider divider) -{ - Sysctl::access_t sysctl = Mmio::read(); - Sysctl::Ipgen::set(sysctl, 1); - Sysctl::Hcken::set(sysctl, 1); - Sysctl::Peren::set(sysctl, 1); - switch (divider) { - case CLOCK_DIV_4: - Sysctl::Dvs::set(sysctl, Sysctl::Dvs::DIV4); - Sysctl::Sdclkfs::set(sysctl, Sysctl::Sdclkfs::DIV1); - break; - case CLOCK_DIV_8: - Sysctl::Dvs::set(sysctl, Sysctl::Dvs::DIV4); - Sysctl::Sdclkfs::set(sysctl, Sysctl::Sdclkfs::DIV2); - break; - case CLOCK_DIV_512: - Sysctl::Dvs::set(sysctl, Sysctl::Dvs::DIV16); - Sysctl::Sdclkfs::set(sysctl, Sysctl::Sdclkfs::DIV32); - break; - } - Mmio::write(sysctl); - _enable_clock_finish(); - _delayer.usleep(1000); -} - - -void Driver::_clock(Clock clock) -{ - wait_for(_delayer, Prsstat::Sdstb::Equal(1)); - _disable_clock(); - _clock_finish(clock); -} - - -Driver::Driver(Env & env, Platform::Connection & platform) -: - Driver_base(env.ram()), - Platform::Device(platform), - Platform::Device::Mmio(*static_cast(this)), - _env(env), - _platform(platform) -{ - log("SD card detected"); - log("capacity: ", card_info().capacity_mb(), " MiB"); -} - - -Driver::~Driver() { } diff --git a/repos/os/src/driver/sd_card/imx/driver.h b/repos/os/src/driver/sd_card/imx/driver.h deleted file mode 100644 index 7004b55b1b..0000000000 --- a/repos/os/src/driver/sd_card/imx/driver.h +++ /dev/null @@ -1,310 +0,0 @@ -/* - * \brief Secured Digital Host Controller - * \author Martin Stein - * \date 2015-02-05 - */ - -/* - * Copyright (C) 2015-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 _SRC__DRIVERS__SD_CARD__SPEC__IMX__DRIVER_H_ -#define _SRC__DRIVERS__SD_CARD__SPEC__IMX__DRIVER_H_ - -/* Genode includes */ -#include -#include - -/* local includes */ -#include -#include - -namespace Sd_card { class Driver; } - - -class Sd_card::Driver : public Driver_base, - private Platform::Device, - private Platform::Device::Mmio<0x100> -{ - using Mmio = Genode::Mmio; - - private: - - enum Bus_width { BUS_WIDTH_1, BUS_WIDTH_4 }; - - enum Clock { CLOCK_INITIAL, CLOCK_OPERATIONAL }; - - enum Clock_divider { CLOCK_DIV_4, CLOCK_DIV_8, CLOCK_DIV_512 }; - - - /******************** - ** MMIO structure ** - ********************/ - - struct Blkattr : Register<0x4, 32> - { - struct Blksize : Bitfield<0, 13> { }; - struct Blkcnt : Bitfield<16, 16> { }; - }; - template - struct Cmdrsp_tpl : Register - { - struct Rsp136_8_24 : Register::template Bitfield<0, 24> { }; - struct Rsp136_0_8 : Register::template Bitfield<24, 8> { }; - }; - - struct Cmdarg : Register<0x8, 32> { }; - struct Cmdrsp0 : Cmdrsp_tpl<0x10> { }; - struct Cmdrsp1 : Cmdrsp_tpl<0x14> { }; - struct Cmdrsp2 : Cmdrsp_tpl<0x18> { }; - struct Cmdrsp3 : Cmdrsp_tpl<0x1c> { }; - struct Rsp136_0 : Bitset_2 { }; - struct Rsp136_1 : Bitset_2 { }; - struct Rsp136_2 : Bitset_2 { }; - struct Rsp136_3 : Bitset_2 { }; - - template - struct Xfertyp_base : Register - { - struct Dmaen : Register::template Bitfield<0, 1> { }; - struct Bcen : Register::template Bitfield<1, 1> { }; - struct Ac12en : Register::template Bitfield<2, 1> { }; - struct Dtdsel : Register::template Bitfield<4, 1> - { - enum { WRITE = 0, READ = 1, }; - }; - struct Msbsel : Register::template Bitfield<5, 1> { }; - }; - - struct Mixctrl : Xfertyp_base<0x48> - { - struct Ddren : Bitfield<3, 1> { }; - struct Nibblepos : Bitfield<6, 1> { }; - struct Ac23en : Bitfield<7, 1> { }; - struct Always_ones : Bitfield<31, 1> { }; - }; - - struct Xfertyp : Xfertyp_base<0xc> - { - struct Rsptyp : Bitfield<16, 2> - { - enum { - _0BIT = 0, - _136BIT = 1, - _48BIT = 2, - _48BIT_BUSY = 3, - }; - }; - struct Cccen : Bitfield<19, 1> { }; - struct Cicen : Bitfield<20, 1> { }; - struct Dpsel : Bitfield<21, 1> { }; - struct Cmdtyp : Bitfield<22, 2> - { - enum { ABORT_CMD12 = 3 }; - }; - struct Cmdinx : Bitfield<24, 6> { }; - }; - - struct Prsstat : Register<0x24, 32> - { - struct Cihb : Bitfield<0, 1> { }; - struct Cdihb : Bitfield<1, 1> { }; - struct Dla : Bitfield<2, 1> { }; - struct Sdstb : Bitfield<3, 1> { }; - }; - - struct Proctl : Register<0x28, 32> - { - struct Dtw : Bitfield<1, 2> - { - enum { _1BIT = 0, _4BIT = 1 }; - }; - struct Dmas : Bitfield<8, 2> { enum { ADMA2 = 2 }; }; - }; - - struct Sysctl : Register<0x2c, 32> - { - struct Ipgen : Bitfield<0, 1> { }; - struct Hcken : Bitfield<1, 1> { }; - struct Peren : Bitfield<2, 1> { }; - struct Dvs : Bitfield<4, 4> - { - enum { DIV1 = 0x0, DIV4 = 0x3, DIV16 = 0xf, }; - }; - struct Sdclkfs : Bitfield<8, 8> - { - enum { DIV1 = 0x00, DIV2 = 0x01, DIV32 = 0x10, }; - }; - struct Dtocv : Bitfield<16, 4> - { - enum { - SDCLK_TIMES_2_POW_28 = 0xf, - SDCLK_TIMES_2_POW_27 = 0xe, - SDCLK_TIMES_2_POW_13 = 0x0, - }; - }; - struct Ipp_rst_n : Bitfield<23, 1> { }; - struct Rsta : Bitfield<24, 1> { }; - struct Rstc : Bitfield<25, 1> { }; - struct Rstd : Bitfield<26, 1> { }; - }; - - template - struct Irq_tpl : Register - { - struct Cc : Register::template Bitfield<0, 1> { }; - struct Tc : Register::template Bitfield<1, 1> { }; - struct Dint : Register::template Bitfield<3, 1> { }; - struct Ctoe : Register::template Bitfield<16, 1> { }; - struct Cce : Register::template Bitfield<17, 1> { }; - struct Cebe : Register::template Bitfield<18, 1> { }; - struct Cie : Register::template Bitfield<19, 1> { }; - struct Dtoe : Register::template Bitfield<20, 1> { }; - struct Dce : Register::template Bitfield<21, 1> { }; - struct Debe : Register::template Bitfield<22, 1> { }; - struct Ac12e : Register::template Bitfield<24, 1> { }; - struct Dmae : Register::template Bitfield<28, 1> { }; - }; - - struct Irq : Irq_tpl<0> { }; - struct Irqstat : Irq_tpl<0x30> { }; - struct Irqstaten : Irq_tpl<0x34> { }; - struct Irqsigen : Irq_tpl<0x38> { }; - struct Maxcurrent : Register<0x48, 32> { }; - struct Adsaddr : Register<0x58, 32> { }; - - struct Hostver : Register<0xfc, 32> - { - struct Svn : Bitfield<0, 8> { }; - struct Vvn : Bitfield<8, 8> { }; - }; - - struct Wml : Register<0x44, 32> - { - struct Rd_wml : Bitfield<0, 8> { }; - struct Rd_brst_len : Bitfield<8, 5> { }; - struct Wr_wml : Bitfield<16, 8> { }; - struct Wr_brst_len : Bitfield<24, 5> { }; - }; - - struct Vendspec : Register<0xc0, 32> - { - struct Frc_sdclk_on : Bitfield<8, 1> { }; - }; - - - /************************ - ** Utility structures ** - ************************/ - - 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 - { - Block::Packet_descriptor packet { }; - bool pending = false; - bool read = false; - }; - - Env & _env; - Platform::Connection & _platform; - Block_transfer _block_transfer { }; - Timer_delayer _delayer { _env }; - Signal_handler _irq_handler { _env.ep(), *this, - &Driver::_handle_irq }; - Platform::Device::Irq _irq { *this }; - Card_info _card_info { _init() }; - Adma2::Table _adma2_table { _platform }; - - static bool _supported_host_version(Hostver::access_t hostver); - static void _watermark_level(Wml::access_t &wml); - - void _handle_irq(); - void _detect_err(char const * const err); - void _disable_irqs(); - void _enable_irqs(); - void _bus_width(Bus_width bus_width); - void _disable_clock(); - void _disable_clock_preparation(); - void _enable_clock(Clock_divider divider); - void _enable_clock_finish(); - void _clock(Clock clock); - void _clock_finish(Clock clock); - int _reset(); - void _reset_amendments(); - int _wait_for_cmd_allowed(); - int _wait_for_cmd_complete(); - int _wait_for_card_ready_mbw(); - int _stop_transmission(); - void _stop_transmission_finish_xfertyp(Xfertyp::access_t &xfertyp); - int _wait_for_cmd_complete_mb_finish(bool const reading); - - int _prepare_dma_mb(Block::Packet_descriptor packet, - bool reading, - size_t blk_cnt, - addr_t buf_phys); - - bool _issue_cmd_finish_xfertyp(Xfertyp::access_t &xfertyp, - bool const transfer, - bool const multiblock, - bool const reading); - - Card_info _init(); - - - /********************* - ** Host_controller ** - *********************/ - - Cid _read_cid() override; - Csd _read_csd() override; - unsigned _read_rca() override; - bool _issue_command(Command_base const & cmd) override; - - Card_info card_info() const override { return _card_info; } - - public: - - using Block::Driver::read; - using Block::Driver::write; - - Driver(Env &env, Platform::Connection & platform); - ~Driver(); - - - /******************* - ** Block::Driver ** - *******************/ - - void read_dma(Block::sector_t block_number, - size_t block_count, - addr_t phys, - Block::Packet_descriptor &packet) override; - - void write_dma(Block::sector_t block_number, - size_t block_count, - addr_t phys, - Block::Packet_descriptor &packet) override; - - bool dma_enabled() override { return true; } - - Dma_buffer alloc_dma_buffer(size_t size, Cache cache) override - { - Ram_dataspace_capability ds = - _platform.retry_with_upgrade(Ram_quota{4096}, Cap_quota{2}, - [&] () { return _platform.alloc_dma_buffer(size, cache); }); - - return { .ds = ds, - .dma_addr = _platform.dma_addr(ds) }; - } -}; - -#endif /* _SRC__DRIVERS__SD_CARD__SPEC__IMX__DRIVER_H_ */ diff --git a/repos/os/src/driver/sd_card/imx53/driver.cc b/repos/os/src/driver/sd_card/imx53/driver.cc deleted file mode 100644 index 3efef6a9b2..0000000000 --- a/repos/os/src/driver/sd_card/imx53/driver.cc +++ /dev/null @@ -1,119 +0,0 @@ -/* - * \brief Secured Digital Host Controller - * \author Martin Stein - * \date 2016-12-13 - */ - -/* - * Copyright (C) 2016-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. - */ - -/* local includes */ -#include - -using namespace Sd_card; -using namespace Genode; - - -void Driver::_stop_transmission_finish_xfertyp(Xfertyp::access_t &xfertyp) -{ - Xfertyp::Msbsel::set(xfertyp, 1); - Xfertyp::Bcen::set(xfertyp, 1); - Xfertyp::Dmaen::set(xfertyp, 1); -} - - -int Driver::_wait_for_cmd_complete_mb_finish(bool const reading) -{ - if (reading) { return 0; } - - /* - * The "Auto Command 12" feature of the ESDHC seems to be - * broken for multi-block writes as it causes command- - * timeout errors sometimes. Thus, we stop such transfers - * manually. - */ - if (_stop_transmission()) { return -1; } - - /* - * The manual termination of multi-block writes seems to leave - * the card in a busy state sometimes. This causes - * errors on subsequent commands. Thus, we have to synchronize - * manually with the card-internal state. - */ - return _wait_for_card_ready_mbw() ? -1 : 0; -} - - -bool Driver::_issue_cmd_finish_xfertyp(Xfertyp::access_t &xfertyp, - bool const transfer, - bool const multiblock, - bool const reading) -{ - if (transfer) { - Xfertyp::Bcen::set(xfertyp, 1); - Xfertyp::Msbsel::set(xfertyp, 1); - if (multiblock) { - /* - * The "Auto Command 12" feature of the ESDHC seems to be - * broken for multi-block writes as it causes command- - * timeout errors sometimes. - */ - if (reading) { - Xfertyp::Ac12en::set(xfertyp, 1); } - - Xfertyp::Dmaen::set(xfertyp, 1); - } - Xfertyp::Dtdsel::set(xfertyp, - reading ? Xfertyp::Dtdsel::READ : Xfertyp::Dtdsel::WRITE); - } - return _wait_for_cmd_allowed() ? false : true; -} - - -bool Driver::_supported_host_version(Hostver::access_t hostver) -{ - return Hostver::Vvn::get(hostver) == 18 && - Hostver::Svn::get(hostver) == 1; -} - - -void Driver::_watermark_level(Wml::access_t &wml) -{ - Wml::Wr_wml::set(wml, 16); - Wml::Wr_brst_len::set(wml, 8); -} - - -void Driver::_reset_amendments() -{ - /* - * The SDHC specification says that a software reset shouldn't - * have an effect on the the card detection circuit. The ESDHC - * clears Sysctl::Ipgen, Sysctl::Hcken, and Sysctl::Peren - * nonetheless which disables clocks that card detection relies - * on. - */ - Sysctl::access_t sysctl = Mmio::read(); - Sysctl::Ipgen::set(sysctl, 1); - Sysctl::Hcken::set(sysctl, 1); - Sysctl::Peren::set(sysctl, 1); - Mmio::write(sysctl); -} - - -void Driver::_clock_finish(Clock clock) -{ - Mmio::write(Sysctl::Dtocv::SDCLK_TIMES_2_POW_27); - switch (clock) { - case CLOCK_INITIAL: _enable_clock(CLOCK_DIV_512); break; - case CLOCK_OPERATIONAL: _enable_clock(CLOCK_DIV_8); break; } - Mmio::write(Sysctl::Dtocv::SDCLK_TIMES_2_POW_27); -} - - -void Driver::_disable_clock_preparation() { } -void Driver::_enable_clock_finish() { } diff --git a/repos/os/src/driver/sd_card/imx53/target.mk b/repos/os/src/driver/sd_card/imx53/target.mk deleted file mode 100644 index 42f50ee970..0000000000 --- a/repos/os/src/driver/sd_card/imx53/target.mk +++ /dev/null @@ -1,6 +0,0 @@ -TARGET = imx53_sd_card -REQUIRES = arm_v7 -SRC_CC = adma2.cc imx/driver.cc -INC_DIR = $(REP_DIR)/src/driver/sd_card/imx - -include $(REP_DIR)/src/driver/sd_card/target.inc diff --git a/repos/os/src/driver/sd_card/imx6/driver.cc b/repos/os/src/driver/sd_card/imx6/driver.cc deleted file mode 100644 index c75b078c6c..0000000000 --- a/repos/os/src/driver/sd_card/imx6/driver.cc +++ /dev/null @@ -1,120 +0,0 @@ -/* - * \brief Secured Digital Host Controller - * \author Martin Stein - * \date 2016-12-13 - */ - -/* - * Copyright (C) 2016-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. - */ - -/* local includes */ -#include - -using namespace Sd_card; -using namespace Genode; - - -void Driver::_stop_transmission_finish_xfertyp(Xfertyp::access_t &) -{ - Mixctrl::access_t mixctrl = Mmio::read(); - Mixctrl::Dmaen::set(mixctrl, 1); - Mixctrl::Bcen::set(mixctrl, 1); - Mixctrl::Ac12en::set(mixctrl, 0); - Mixctrl::Ddren::set(mixctrl, 0); - Mixctrl::Dtdsel::set(mixctrl, Mixctrl::Dtdsel::READ); - Mixctrl::Msbsel::set(mixctrl, 1); - Mixctrl::Nibblepos::set(mixctrl, 0); - Mixctrl::Ac23en::set(mixctrl, 0); - Mmio::write(mixctrl); -} - - -int Driver::_wait_for_cmd_complete_mb_finish(bool) -{ - /* we can't use the "Auto Command 12" feature as it does not work */ - return _stop_transmission() ? -1 : 0; -} - - -bool Driver::_issue_cmd_finish_xfertyp(Xfertyp::access_t &, - bool const transfer, - bool const multiblock, - bool const reading) -{ - Mixctrl::access_t mixctrl = Mmio::read(); - Mixctrl::Dmaen ::set(mixctrl, transfer && multiblock); - Mixctrl::Bcen ::set(mixctrl, transfer); - Mixctrl::Ac12en ::set(mixctrl, 0); - Mixctrl::Msbsel ::set(mixctrl, transfer); - Mixctrl::Ddren ::set(mixctrl, 0); - Mixctrl::Nibblepos::set(mixctrl, 0); - Mixctrl::Ac23en ::set(mixctrl, 0); - Mixctrl::Dtdsel ::set(mixctrl, reading ? Mixctrl::Dtdsel::READ : - Mixctrl::Dtdsel::WRITE); - - if (_wait_for_cmd_allowed()) { - return false; } - - Mmio::write(mixctrl); - return true; -} - - -bool Driver::_supported_host_version(Hostver::access_t) -{ - /* - * on i.MX6 there exist board-specific (tested) drivers only, - * therefore we do not need to differentiate in between controller versions - */ - return true; -} - - -void Driver::_watermark_level(Wml::access_t &wml) -{ - Wml::Wr_wml::set(wml, 64); - Wml::Wr_brst_len::set(wml, 16); -} - - -void Driver::_reset_amendments() -{ - /* the USDHC doesn't reset the Mixer Control register automatically */ - Mixctrl::access_t mixctrl = Mmio::read(); - Mixctrl::Dmaen::set(mixctrl, 0); - Mixctrl::Bcen::set(mixctrl, 0); - Mixctrl::Ac12en::set(mixctrl, 0); - Mixctrl::Ddren::set(mixctrl, 0); - Mixctrl::Dtdsel::set(mixctrl, 0); - Mixctrl::Msbsel::set(mixctrl, 0); - Mixctrl::Nibblepos::set(mixctrl, 0); - Mixctrl::Ac23en::set(mixctrl, 0); - Mixctrl::Always_ones::set(mixctrl, 1); - Mmio::write(mixctrl); -} - - -void Driver::_clock_finish(Clock clock) -{ - switch (clock) { - case CLOCK_INITIAL: - Mmio::write(Sysctl::Dtocv::SDCLK_TIMES_2_POW_13); - _enable_clock(CLOCK_DIV_512); - break; - case CLOCK_OPERATIONAL: - Mmio::write(Sysctl::Dtocv::SDCLK_TIMES_2_POW_28); - Mmio::write(0); - _enable_clock(CLOCK_DIV_4); - break; - } -} - - -void Driver::_disable_clock_preparation() { - Mmio::write(0); } - -void Driver::_enable_clock_finish() { Mmio::write(0); } diff --git a/repos/os/src/driver/sd_card/imx6/target.mk b/repos/os/src/driver/sd_card/imx6/target.mk deleted file mode 100644 index 005ee5eaee..0000000000 --- a/repos/os/src/driver/sd_card/imx6/target.mk +++ /dev/null @@ -1,6 +0,0 @@ -TARGET = imx6_sd_card -SRC_CC = adma2.cc imx/driver.cc -INC_DIR = $(REP_DIR)/src/driver/sd_card/imx -REQUIRES = arm_v7a - -include $(REP_DIR)/src/driver/sd_card/target.inc