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:
Pirmin Duss 2024-01-25 09:46:05 +01:00 committed by Christian Helmuth
parent 40c8e76f49
commit 55007f5bd9
5 changed files with 31 additions and 7 deletions

View File

@ -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
*/

View File

@ -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));

View File

@ -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:

View File

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

View File

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