summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/console/Kconfig15
-rw-r--r--src/drivers/smbus/Makefile.inc5
-rw-r--r--src/drivers/smbus/i2c_smbus_console.c7
-rw-r--r--src/drivers/smbus/sc16is7xx_init.c62
-rw-r--r--src/drivers/smbus/sc16is7xx_init.h11
5 files changed, 99 insertions, 1 deletions
diff --git a/src/console/Kconfig b/src/console/Kconfig
index 9b8e9f87c8..c6aec18b09 100644
--- a/src/console/Kconfig
+++ b/src/console/Kconfig
@@ -311,14 +311,29 @@ if CONSOLE_I2C_SMBUS
config CONSOLE_I2C_SMBUS_SLAVE_ADDRESS
hex "I2C slave address of the logging device"
+ default 0x48 if SC16IS7XX_INIT
help
I2C address of the device which logs the data.
config CONSOLE_I2C_SMBUS_SLAVE_DATA_REGISTER
hex "Data register address of the I2C logging device"
+ default 0x00 if SC16IS7XX_INIT
help
This an 8-bit data register.
+config SC16IS7XX_INIT
+ bool "Initialize SC16IS7XX I2C to UART converter chip"
+ help
+ SC16IS7XX is a slave I2C to UART converter chip. Enabling
+ this option will initialize the chip.
+
+ The default I2C slave address value 0x48 is the address of
+ SC16IS7XX I2C to UART converter chip when the A1 and A0 pins
+ are set to Vcc.
+
+ The default data register address value 0x00 is the data
+ register address of SC16IS7XX I2C to UART converter chip.
+
endif # CONSOLE_I2C_SMBUS
config CONSOLE_QEMU_DEBUGCON
diff --git a/src/drivers/smbus/Makefile.inc b/src/drivers/smbus/Makefile.inc
index e14d59c3e3..d478889b66 100644
--- a/src/drivers/smbus/Makefile.inc
+++ b/src/drivers/smbus/Makefile.inc
@@ -1,3 +1,8 @@
+ifeq ($(CONFIG_SC16IS7XX_INIT),y)
+bootblock-y += sc16is7xx_init.c
+romstage-y += sc16is7xx_init.c
+endif
+
ifeq ($(CONFIG_CONSOLE_I2C_SMBUS),y)
all-y += i2c_smbus_console.c
endif
diff --git a/src/drivers/smbus/i2c_smbus_console.c b/src/drivers/smbus/i2c_smbus_console.c
index c223028a18..d651790694 100644
--- a/src/drivers/smbus/i2c_smbus_console.c
+++ b/src/drivers/smbus/i2c_smbus_console.c
@@ -3,8 +3,13 @@
#include <console/i2c_smbus.h>
#include <device/smbus_host.h>
#include <southbridge/intel/bd82x6x/pch.h>
+#include "sc16is7xx_init.h"
-void i2c_smbus_console_init(void) {}
+void i2c_smbus_console_init(void)
+{
+ if (CONFIG(SC16IS7XX_INIT))
+ sc16is7xx_init();
+}
void i2c_smbus_console_tx_byte(unsigned char c)
{
diff --git a/src/drivers/smbus/sc16is7xx_init.c b/src/drivers/smbus/sc16is7xx_init.c
new file mode 100644
index 0000000000..c350b252a3
--- /dev/null
+++ b/src/drivers/smbus/sc16is7xx_init.c
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/i2c_smbus.h>
+#include <device/i2c.h>
+#include <device/smbus_host.h>
+#include <southbridge/intel/bd82x6x/pch.h>
+#include "sc16is7xx_init.h"
+
+/*
+ * Datasheet - SC16IS740/750/760, Rev. 7 - 9 June 2011
+ * https://web.archive.org/web/20210612105830/https://www.nxp.com/docs/en/data-sheet/SC16IS740_750_760.pdf
+ */
+
+// Bits [6:3] of the subaddress is to address device internal registers
+#define INTERNAL_REG_SUB_ADDR_SHIFT 3
+
+#define REG_THR 0x00 // Transmit Holding Register
+#define REG_LCR 0x03 // Line Control Register
+
+// Special Register Set is accessible only when LCR[7] is logic 1
+#define REG_DLL 0x00 // divisor latch LSB
+#define REG_DLH 0x01 // divisor latch MSB
+
+#define LCR_WORD_LEN_BIT_0 BIT(0)
+#define LCR_WORD_LEN_BIT_1 BIT(1)
+#define LCR_STOP_BIT BIT(2)
+#define LCR_PARITY_BIT_0 BIT(3)
+#define LCR_PARITY_BIT_1 BIT(4)
+#define LCR_PARITY_BIT_2 BIT(5)
+#define LCR_BREAK_CTL_BIT BIT(6)
+#define LCR_SPEC_REG_SET_EN BIT(7)
+
+#define UART_8_N_1 (LCR_WORD_LEN_BIT_0 | LCR_WORD_LEN_BIT_1)
+
+/*
+ * UART configuration: 8 bit word length, No parity, 1 stop bit (8-N-1)
+ * Divisor value set here is calculated for 115200 baud rate
+ * in 14.7MHz clock input to chip.
+ */
+
+#define BAUD_115200_DLL 0x08
+#define BAUD_115200_DLH 0x00
+
+void sc16is7xx_write_byte(uint8_t reg, unsigned char c)
+{
+ do_smbus_write_byte(CONFIG_FIXED_SMBUS_IO_BASE,
+ CONFIG_CONSOLE_I2C_SMBUS_SLAVE_ADDRESS, reg, c);
+}
+
+void sc16is7xx_init(void)
+{
+ // Configure 8-N-1 and enable special register set
+ sc16is7xx_write_byte(REG_LCR << INTERNAL_REG_SUB_ADDR_SHIFT,
+ (UART_8_N_1 | LCR_SPEC_REG_SET_EN));
+
+ sc16is7xx_write_byte(REG_DLL << INTERNAL_REG_SUB_ADDR_SHIFT, BAUD_115200_DLL);
+ sc16is7xx_write_byte(REG_DLH << INTERNAL_REG_SUB_ADDR_SHIFT, BAUD_115200_DLH);
+
+ // Disable special register set
+ sc16is7xx_write_byte(REG_LCR << INTERNAL_REG_SUB_ADDR_SHIFT,
+ (UART_8_N_1 & ~LCR_SPEC_REG_SET_EN));
+}
diff --git a/src/drivers/smbus/sc16is7xx_init.h b/src/drivers/smbus/sc16is7xx_init.h
new file mode 100644
index 0000000000..f57c82ac5a
--- /dev/null
+++ b/src/drivers/smbus/sc16is7xx_init.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __DRIVERS_SMBUS_SC16IS7XX_INIT__
+#define __DRIVERS_SMBUS_SC16IS7XX_INIT__
+
+#include <types.h>
+
+void sc16is7xx_write_byte(uint8_t reg, unsigned char c);
+void sc16is7xx_init(void);
+
+#endif /* __DRIVERS_SMBUS_SC16IS7XX_INIT__ */