mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 21:27:56 +00:00
i2c: bus speed configuration node
I2C EEPROMs of the type at24xxx are really slow (ca. 10 kHZ). This adds the `bus_speed_khz` attribute to the config of the driver and adapts the i.MX8 driver to support the feature. Issue gapfruit#1996 Fixes genodelabs#5090
This commit is contained in:
parent
40c8e76f49
commit
55007f5bd9
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief I2C driver base class to be implemented by platform specific
|
||||
* \brief I2C driver base class to be implemented by platform specific
|
||||
* \author Jean-Adrien Domage <jean-adrien.domage@gapfruit.com>
|
||||
* \date 2021-02-08
|
||||
*/
|
||||
|
@ -17,6 +17,27 @@
|
||||
#include "driver.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
Genode::uint8_t _bus_speed_to_divider(Genode::uint16_t bus_speed_khz)
|
||||
{
|
||||
/* the table can be found:
|
||||
* IMX8MMRM.pdf on 5233
|
||||
*
|
||||
* The bus base frequency is 25MHz.
|
||||
*/
|
||||
|
||||
if (bus_speed_khz >= 400) return 0x2a; /* divide by 64 maximal speed supported */
|
||||
if (bus_speed_khz >= 200) return 0x2f; /* divide by 128 */
|
||||
if (bus_speed_khz >= 100) return 0x33; /* divide by 256 */
|
||||
if (bus_speed_khz >= 50) return 0x37; /* divide by 512 */
|
||||
if (bus_speed_khz >= 25) return 0x3B; /* divide by 1024 */
|
||||
|
||||
return 0x3F; /* divide by 2048 minimal speed */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void I2c::Driver::_wait_for_irq()
|
||||
{
|
||||
_sem_cnt++;
|
||||
@ -58,8 +79,8 @@ void I2c::Driver::_bus_reset()
|
||||
|
||||
void I2c::Driver::_bus_start()
|
||||
{
|
||||
/* input root 90 is 25Mhz target is 400Khz, divide by 64 */
|
||||
_mmio.write<Mmio::Freq_divider>(0x2a);
|
||||
/* input root 90 is 25Mhz select divisor to approximate desired bus speed */
|
||||
_mmio.write<Mmio::Freq_divider>(_bus_speed_to_divider(_args.bus_speed_khz));
|
||||
_mmio.write<Mmio::Status>(0);
|
||||
_mmio.write<Mmio::Control>(Mmio::Control::Enable::bits(1));
|
||||
|
||||
|
@ -43,6 +43,7 @@ class I2c::Driver: public I2c::Driver_base
|
||||
bool verbose;
|
||||
unsigned bus_no;
|
||||
Device_name device_name;
|
||||
uint16_t bus_speed_khz;
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -29,7 +29,7 @@ struct I2c::Mmio: Platform::Device::Mmio
|
||||
struct Freq_divider : Mmio::Register<0x4, 16> {};
|
||||
|
||||
struct Control : Mmio::Register<0x8, 16> {
|
||||
struct Repeat_start : Mmio::Register<0x8, 16>::Bitfield<2, 1> {};
|
||||
struct Repeat_start : Mmio::Register<0x8, 16>::Bitfield<2, 1> {};
|
||||
struct Tx_ack_enable : Mmio::Register<0x8, 16>::Bitfield<3, 1> {};
|
||||
struct Tx_rx_select : Mmio::Register<0x8, 16>::Bitfield<4, 1> {};
|
||||
struct Master_slave_select : Mmio::Register<0x8, 16>::Bitfield<5, 1> {};
|
||||
|
@ -37,10 +37,12 @@ struct I2c::Main
|
||||
|
||||
static I2c::Driver::Args _driver_args_from_config(Xml_node config)
|
||||
{
|
||||
constexpr uint16_t const default_bus_speed_khz { 400 };
|
||||
return {
|
||||
.verbose = config.attribute_value("verbose", false),
|
||||
.bus_no = config.attribute_value("bus_no", 0u),
|
||||
.device_name = config.attribute_value("device_name", Device_name())
|
||||
.verbose = config.attribute_value("verbose", false),
|
||||
.bus_no = config.attribute_value("bus_no", 0u),
|
||||
.device_name = config.attribute_value("device_name", Device_name()),
|
||||
.bus_speed_khz = config.attribute_value("bus_speed_khz", default_bus_speed_khz)
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user