mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 20:05:54 +00:00
Operate SD card in 4-bit data mode
This commit is contained in:
parent
b37a28578c
commit
eac9055c92
@ -326,7 +326,7 @@ struct Mmchs : Genode::Mmio
|
||||
write<Stat>(~0);
|
||||
}
|
||||
|
||||
enum Bus_width { BUS_WIDTH_1, BUS_WIDTH_8 };
|
||||
enum Bus_width { BUS_WIDTH_1, BUS_WIDTH_4 };
|
||||
|
||||
void bus_width(Bus_width bus_width)
|
||||
{
|
||||
@ -336,8 +336,9 @@ struct Mmchs : Genode::Mmio
|
||||
write<Hctl::Dtw>(Hctl::Dtw::ONE_BIT);
|
||||
break;
|
||||
|
||||
case BUS_WIDTH_8:
|
||||
write<Con::Dw8>(1);
|
||||
case BUS_WIDTH_4:
|
||||
write<Con::Dw8>(0);
|
||||
write<Hctl::Dtw>(Hctl::Dtw::FOUR_BITS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -510,13 +511,30 @@ struct Omap4_hsmmc_controller : private Mmchs, public Sd_card::Host_controller
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
PERR("Sd_send_op_cond timed out, could no power on SD card");
|
||||
PERR("Sd_send_op_cond timed out, could no power-on SD card");
|
||||
throw Detection_failed();
|
||||
}
|
||||
|
||||
Card_info card_info = _detect();
|
||||
|
||||
write<Sysctl::Clkd>(0);
|
||||
/*
|
||||
* Switch card to use 4 data signals
|
||||
*/
|
||||
if (!issue_command(Set_bus_width(Set_bus_width::Arg::Bus_width::FOUR_BITS),
|
||||
card_info.rca())) {
|
||||
PWRN("Set_bus_width(FOUR_BITS) command failed");
|
||||
throw Detection_failed();
|
||||
}
|
||||
|
||||
bus_width(BUS_WIDTH_4);
|
||||
|
||||
_delayer.usleep(10*1000);
|
||||
|
||||
stop_clock();
|
||||
if (!set_and_enable_clock(CLOCK_DIV_0, _delayer)) {
|
||||
PERR("set_clock failed");
|
||||
throw Detection_failed();
|
||||
}
|
||||
|
||||
return card_info;
|
||||
}
|
||||
@ -555,16 +573,18 @@ struct Omap4_hsmmc_controller : private Mmchs, public Sd_card::Host_controller
|
||||
/* assemble command register */
|
||||
Cmd::access_t cmd = 0;
|
||||
Cmd::Index::set(cmd, command.index);
|
||||
if (command.index == Sd_card::Read_multiple_block::INDEX
|
||||
|| command.index == Sd_card::Write_multiple_block::INDEX) {
|
||||
if (command.transfer != Sd_card::TRANSFER_NONE) {
|
||||
|
||||
Cmd::Dp::set(cmd);
|
||||
Cmd::Bce::set(cmd);
|
||||
Cmd::Msbs::set(cmd);
|
||||
Cmd::Acen::set(cmd);
|
||||
|
||||
if (command.index == Sd_card::Read_multiple_block::INDEX
|
||||
|| command.index == Sd_card::Write_multiple_block::INDEX)
|
||||
Cmd::Acen::set(cmd);
|
||||
|
||||
/* set data-direction bit depending on the command */
|
||||
bool const read = command.index == Sd_card::Read_multiple_block::INDEX;
|
||||
bool const read = command.transfer == Sd_card::TRANSFER_READ;
|
||||
Cmd::Ddir::set(cmd, read ? Cmd::Ddir::READ : Cmd::Ddir::WRITE);
|
||||
}
|
||||
|
||||
|
@ -72,29 +72,32 @@ namespace Sd_card {
|
||||
RESPONSE_48_BIT,
|
||||
RESPONSE_48_BIT_WITH_BUSY };
|
||||
|
||||
enum Transfer { TRANSFER_NONE, TRANSFER_READ, TRANSFER_WRITE };
|
||||
|
||||
struct Command_base
|
||||
{
|
||||
unsigned index; /* command opcode */
|
||||
Arg::access_t arg; /* argument */
|
||||
Response rsp_type; /* response type */
|
||||
Transfer transfer; /* data transfer type */
|
||||
|
||||
Command_base(unsigned op, Response rsp_type)
|
||||
Command_base(unsigned op, Response rsp_type, Transfer transfer)
|
||||
:
|
||||
index(op), arg(0), rsp_type(rsp_type)
|
||||
index(op), arg(0), rsp_type(rsp_type), transfer(transfer)
|
||||
{ }
|
||||
};
|
||||
|
||||
template <unsigned _INDEX, Response RSP_TYPE>
|
||||
template <unsigned _INDEX, Response RSP_TYPE, Transfer TRANSFER = TRANSFER_NONE>
|
||||
struct Command : Command_base
|
||||
{
|
||||
enum { INDEX = _INDEX };
|
||||
Command() : Command_base(_INDEX, RSP_TYPE) { }
|
||||
Command() : Command_base(_INDEX, RSP_TYPE, TRANSFER) { }
|
||||
};
|
||||
|
||||
template <unsigned INDEX, Response RSP_TYPE>
|
||||
template <unsigned INDEX, Response RSP_TYPE, Transfer TRANSFER = TRANSFER_NONE>
|
||||
struct Prefixed_command : private Command_base
|
||||
{
|
||||
Prefixed_command() : Command_base(INDEX, RSP_TYPE) { }
|
||||
Prefixed_command() : Command_base(INDEX, RSP_TYPE, TRANSFER) { }
|
||||
|
||||
using Command_base::arg;
|
||||
|
||||
@ -165,7 +168,7 @@ namespace Sd_card {
|
||||
};
|
||||
};
|
||||
|
||||
struct Read_multiple_block : Command<18, RESPONSE_48_BIT>
|
||||
struct Read_multiple_block : Command<18, RESPONSE_48_BIT, TRANSFER_READ>
|
||||
{
|
||||
Read_multiple_block(unsigned long addr)
|
||||
{
|
||||
@ -173,7 +176,7 @@ namespace Sd_card {
|
||||
}
|
||||
};
|
||||
|
||||
struct Write_multiple_block : Command<25, RESPONSE_48_BIT>
|
||||
struct Write_multiple_block : Command<25, RESPONSE_48_BIT, TRANSFER_WRITE>
|
||||
{
|
||||
Write_multiple_block(unsigned long addr)
|
||||
{
|
||||
@ -181,6 +184,22 @@ namespace Sd_card {
|
||||
}
|
||||
};
|
||||
|
||||
struct Set_bus_width : Prefixed_command<6, RESPONSE_48_BIT>
|
||||
{
|
||||
struct Arg : Sd_card::Arg
|
||||
{
|
||||
struct Bus_width : Bitfield<0, 2>
|
||||
{
|
||||
enum Width { ONE_BIT = 0, FOUR_BITS = 2 };
|
||||
};
|
||||
};
|
||||
|
||||
Set_bus_width(Arg::Bus_width::Width width)
|
||||
{
|
||||
Arg::Bus_width::set(arg, width);
|
||||
}
|
||||
};
|
||||
|
||||
struct Sd_send_op_cond : Prefixed_command<41, RESPONSE_48_BIT>
|
||||
{
|
||||
struct Arg : Sd_card::Arg
|
||||
@ -203,8 +222,18 @@ namespace Sd_card {
|
||||
}
|
||||
};
|
||||
|
||||
struct Acmd_prefix : Command<55, RESPONSE_48_BIT> { };
|
||||
struct Acmd_prefix : Command<55, RESPONSE_48_BIT>
|
||||
{
|
||||
struct Arg : Sd_card::Arg
|
||||
{
|
||||
struct Rca : Bitfield<16, 16> { };
|
||||
};
|
||||
|
||||
Acmd_prefix(unsigned rca)
|
||||
{
|
||||
Arg::Rca::set(arg, rca);
|
||||
}
|
||||
};
|
||||
|
||||
class Card_info
|
||||
{
|
||||
@ -268,12 +297,15 @@ namespace Sd_card {
|
||||
* This overload is selected if the supplied command type has
|
||||
* 'Prefixed_command' as its base class. In this case, we need to
|
||||
* issue a CMD55 as command prefix followed by the actual command.
|
||||
*
|
||||
* \param prefix_rca argument to CMD55 prefix command
|
||||
*/
|
||||
template <unsigned INDEX, Response RSP_TYPE>
|
||||
bool issue_command(Prefixed_command<INDEX, RSP_TYPE> const &command)
|
||||
template <unsigned INDEX, Response RSP_TYPE, Transfer TRANSFER>
|
||||
bool issue_command(Prefixed_command<INDEX, RSP_TYPE, TRANSFER> const &command,
|
||||
unsigned prefix_rca = 0)
|
||||
{
|
||||
/* send CMD55 prefix */
|
||||
if (!_issue_command(Acmd_prefix())) {
|
||||
if (!_issue_command(Acmd_prefix(prefix_rca))) {
|
||||
PERR("prefix command timed out");
|
||||
return false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user