From aa99830c067036015b6ce45c01063b4482bf05b9 Mon Sep 17 00:00:00 2001 From: Maxim Polyakov Date: Sat, 20 Jun 2020 17:26:21 +0300 Subject: 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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/44476 Reviewed-by: Angel Pons Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- src/ec/kontron/kempld/chip.h | 8 ++++++++ src/ec/kontron/kempld/kempld_i2c.c | 23 +++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) (limited to 'src/ec/kontron/kempld') diff --git a/src/ec/kontron/kempld/chip.h b/src/ec/kontron/kempld/chip.h index 8ca8d246e9..30f40fe097 100644 --- a/src/ec/kontron/kempld/chip.h +++ b/src/ec/kontron/kempld/chip.h @@ -12,6 +12,13 @@ enum kempld_uart_io { 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 { enum kempld_uart_io io; unsigned int irq; @@ -19,6 +26,7 @@ struct kempld_uart { struct ec_kontron_kempld_config { struct kempld_uart uart[KEMPLD_NUM_UARTS]; + unsigned short i2c_frequency; }; #endif /* EC_KONTRON_KEMPLD_CHIP_H */ diff --git a/src/ec/kontron/kempld/kempld_i2c.c b/src/ec/kontron/kempld/kempld_i2c.c index 296cf76ddd..8abbb4b856 100644 --- a/src/ec/kontron/kempld/kempld_i2c.c +++ b/src/ec/kontron/kempld/kempld_i2c.c @@ -13,6 +13,7 @@ #include #include +#include "chip.h" #include "kempld.h" #include "kempld_internal.h" @@ -40,9 +41,6 @@ #define I2C_CMD_READ_NACK 0x29 #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 ENXIO 6 #define EAGAIN 11 @@ -230,7 +228,8 @@ static struct device_operations kempld_i2c_dev_ops = { 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; u8 ctrl; u8 stat; @@ -244,11 +243,23 @@ void kempld_i2c_device_init(struct device *const dev) ctrl &= ~(I2C_CTRL_EN | I2C_CTRL_IEN); 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)); if (spec_major == 1) - prescale = KEMPLD_CLK / (KEMPLD_I2C_FREQ_STD * 5) - 1000; + prescale = KEMPLD_CLK / (frequency * 5) - 1000; else - prescale = KEMPLD_CLK / (KEMPLD_I2C_FREQ_STD * 4) - 3000; + prescale = KEMPLD_CLK / (frequency * 4) - 3000; if (prescale < 0) prescale = 0; -- cgit v1.2.3