summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-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
4 files changed, 84 insertions, 1 deletions
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__ */