ec/kontron/kempld: add option to configure I2C frequency
Allows to change the I2C bus frequency by overriding i2c_frequency option from the board devicetree. Thus, the I2C controller can use Fast-mode (Fm), with a bit rate up to 400 kbit/s and Fast-mode Plus (Fm+), with a bit rate up to 1 Mbit/s [1]. Tested on Kontron mAL10 COMe module with T10-TNI carrierboard [2]. [1] I2C-bus specification and user manual, doc #UM10204, Rev. 6, 4 April 2014. [2] https://review.coreboot.org/c/coreboot/+/39133 Change-Id: If0eb477af10d00eb4f17f9c01209f170b746ad3d Signed-off-by: Maxim Polyakov <max.senia.poliak@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/44476 Reviewed-by: Angel Pons <th3fanbus@gmail.com> Reviewed-by: Nico Huber <nico.h@gmx.de> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
0af1926353
commit
aa99830c06
2 changed files with 25 additions and 6 deletions
|
@ -12,6 +12,13 @@ enum kempld_uart_io {
|
||||||
KEMPLD_UART_2E8 = 3,
|
KEMPLD_UART_2E8 = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum kempld_i2c_frequency {
|
||||||
|
KEMPLD_I2C_FREQ_STANDARD_MODE_100KHZ = 100,
|
||||||
|
KEMPLD_I2C_FREQ_FAST_MODE_400KHZ = 400,
|
||||||
|
KEMPLD_I2C_FREQ_FAST_PLUS_MODE_1MHZ = 1000,
|
||||||
|
KEMPLD_I2C_FREQ_MAX = 2700,
|
||||||
|
};
|
||||||
|
|
||||||
struct kempld_uart {
|
struct kempld_uart {
|
||||||
enum kempld_uart_io io;
|
enum kempld_uart_io io;
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
|
@ -19,6 +26,7 @@ struct kempld_uart {
|
||||||
|
|
||||||
struct ec_kontron_kempld_config {
|
struct ec_kontron_kempld_config {
|
||||||
struct kempld_uart uart[KEMPLD_NUM_UARTS];
|
struct kempld_uart uart[KEMPLD_NUM_UARTS];
|
||||||
|
unsigned short i2c_frequency;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EC_KONTRON_KEMPLD_CHIP_H */
|
#endif /* EC_KONTRON_KEMPLD_CHIP_H */
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
#include <delay.h>
|
#include <delay.h>
|
||||||
|
|
||||||
|
#include "chip.h"
|
||||||
#include "kempld.h"
|
#include "kempld.h"
|
||||||
#include "kempld_internal.h"
|
#include "kempld_internal.h"
|
||||||
|
|
||||||
|
@ -40,9 +41,6 @@
|
||||||
#define I2C_CMD_READ_NACK 0x29
|
#define I2C_CMD_READ_NACK 0x29
|
||||||
#define I2C_CMD_IACK 0x01
|
#define I2C_CMD_IACK 0x01
|
||||||
|
|
||||||
#define KEMPLD_I2C_FREQ_MAX 2700 /* 2.7 mHz */
|
|
||||||
#define KEMPLD_I2C_FREQ_STD 100 /* 100 kHz */
|
|
||||||
|
|
||||||
#define EIO 5
|
#define EIO 5
|
||||||
#define ENXIO 6
|
#define ENXIO 6
|
||||||
#define EAGAIN 11
|
#define EAGAIN 11
|
||||||
|
@ -230,7 +228,8 @@ static struct device_operations kempld_i2c_dev_ops = {
|
||||||
|
|
||||||
void kempld_i2c_device_init(struct device *const dev)
|
void kempld_i2c_device_init(struct device *const dev)
|
||||||
{
|
{
|
||||||
u16 prescale_corr;
|
const struct ec_kontron_kempld_config *const config = dev->chip_info;
|
||||||
|
u16 prescale_corr, frequency;
|
||||||
long prescale;
|
long prescale;
|
||||||
u8 ctrl;
|
u8 ctrl;
|
||||||
u8 stat;
|
u8 stat;
|
||||||
|
@ -244,11 +243,23 @@ void kempld_i2c_device_init(struct device *const dev)
|
||||||
ctrl &= ~(I2C_CTRL_EN | I2C_CTRL_IEN);
|
ctrl &= ~(I2C_CTRL_EN | I2C_CTRL_IEN);
|
||||||
kempld_write8(KEMPLD_I2C_CTRL, ctrl);
|
kempld_write8(KEMPLD_I2C_CTRL, ctrl);
|
||||||
|
|
||||||
|
frequency = KEMPLD_I2C_FREQ_STANDARD_MODE_100KHZ;
|
||||||
|
if (config && config->i2c_frequency) {
|
||||||
|
if (config->i2c_frequency <= KEMPLD_I2C_FREQ_MAX) {
|
||||||
|
frequency = config->i2c_frequency;
|
||||||
|
} else {
|
||||||
|
printk(BIOS_NOTICE,
|
||||||
|
"kempld_i2c: %d kHz is too high!\n",
|
||||||
|
config->i2c_frequency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printk(BIOS_INFO, "kempld_i2c: Use frequency %d\n", frequency);
|
||||||
|
|
||||||
const u8 spec_major = KEMPLD_SPEC_GET_MAJOR(kempld_read8(KEMPLD_SPEC));
|
const u8 spec_major = KEMPLD_SPEC_GET_MAJOR(kempld_read8(KEMPLD_SPEC));
|
||||||
if (spec_major == 1)
|
if (spec_major == 1)
|
||||||
prescale = KEMPLD_CLK / (KEMPLD_I2C_FREQ_STD * 5) - 1000;
|
prescale = KEMPLD_CLK / (frequency * 5) - 1000;
|
||||||
else
|
else
|
||||||
prescale = KEMPLD_CLK / (KEMPLD_I2C_FREQ_STD * 4) - 3000;
|
prescale = KEMPLD_CLK / (frequency * 4) - 3000;
|
||||||
|
|
||||||
if (prescale < 0)
|
if (prescale < 0)
|
||||||
prescale = 0;
|
prescale = 0;
|
||||||
|
|
Loading…
Reference in a new issue