From 934fcfb6a0d39c6ec9c64ecac6c2273b5fca4911 Mon Sep 17 00:00:00 2001 From: "ot_ryanw.wang" Date: Thu, 19 Dec 2024 10:07:47 +0800 Subject: [PATCH] soc/mediatek/mt8189: Add I2C driver support Add I2C controller driver. BUG=b:379008996 BRANCH=none TEST=build passed Signed-off-by: ot_ryanw.wang Change-Id: I4baa291a83ecce60eb2d41e329c2182f3ea273b7 Reviewed-on: https://review.coreboot.org/c/coreboot/+/87338 Tested-by: build bot (Jenkins) Reviewed-by: Yu-Ping Wu Reviewed-by: Yidi Lin --- src/soc/mediatek/mt8189/Makefile.mk | 1 + src/soc/mediatek/mt8189/i2c.c | 114 ++++++++++++++++++ .../mediatek/mt8189/include/soc/addressmap.h | 18 +++ src/soc/mediatek/mt8189/include/soc/i2c.h | 81 +++++++++++++ 4 files changed, 214 insertions(+) create mode 100644 src/soc/mediatek/mt8189/i2c.c create mode 100644 src/soc/mediatek/mt8189/include/soc/i2c.h diff --git a/src/soc/mediatek/mt8189/Makefile.mk b/src/soc/mediatek/mt8189/Makefile.mk index feba664bec..56a7033eb3 100644 --- a/src/soc/mediatek/mt8189/Makefile.mk +++ b/src/soc/mediatek/mt8189/Makefile.mk @@ -4,6 +4,7 @@ ifeq ($(CONFIG_SOC_MEDIATEK_MT8189),y) all-y += ../common/flash_controller.c all-y += ../common/gpio.c ../common/gpio_op.c ../common/gpio_eint_v2.c gpio.c gpio_eint.c +all-y += ../common/i2c.c ../common/i2c_common.c i2c.c all-$(CONFIG_SPI_FLASH) += spi.c all-y += ../common/timer_prepare.c timer.c all-y += ../common/uart.c diff --git a/src/soc/mediatek/mt8189/i2c.c b/src/soc/mediatek/mt8189/i2c.c new file mode 100644 index 0000000000..4f73d608ac --- /dev/null +++ b/src/soc/mediatek/mt8189/i2c.c @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +/* + * This file is created based on MT8189 Functional Specification + * Chapter number: 9.10 + */ + +#include +#include +#include +#include +#include +#include + +struct mtk_i2c mtk_i2c_bus_controller[] = { + [0] = { + .i2c_regs = (void *)I2C0_BASE, + .i2c_dma_regs = (void *)I2C0_DMA_BASE, + .mt_i2c_flag = I2C_APDMA_ASYNC, + }, + [1] = { + .i2c_regs = (void *)I2C1_BASE, + .i2c_dma_regs = (void *)I2C1_DMA_BASE, + .mt_i2c_flag = I2C_APDMA_ASYNC, + }, + [2] = { + .i2c_regs = (void *)I2C2_BASE, + .i2c_dma_regs = (void *)I2C2_DMA_BASE, + .mt_i2c_flag = I2C_APDMA_ASYNC, + }, + [3] = { + .i2c_regs = (void *)I2C3_BASE, + .i2c_dma_regs = (void *)I2C3_DMA_BASE, + .mt_i2c_flag = I2C_APDMA_ASYNC, + }, + [4] = { + .i2c_regs = (void *)I2C4_BASE, + .i2c_dma_regs = (void *)I2C4_DMA_BASE, + .mt_i2c_flag = I2C_APDMA_ASYNC, + }, + [5] = { + .i2c_regs = (void *)I2C5_BASE, + .i2c_dma_regs = (void *)I2C5_DMA_BASE, + .mt_i2c_flag = I2C_APDMA_ASYNC, + }, + [6] = { + .i2c_regs = (void *)I2C6_BASE, + .i2c_dma_regs = (void *)I2C6_DMA_BASE, + .mt_i2c_flag = I2C_APDMA_ASYNC, + }, + [7] = { + .i2c_regs = (void *)I2C7_BASE, + .i2c_dma_regs = (void *)I2C7_DMA_BASE, + .mt_i2c_flag = I2C_APDMA_ASYNC, + }, + [8] = { + .i2c_regs = (void *)I2C8_BASE, + .i2c_dma_regs = (void *)I2C8_DMA_BASE, + .mt_i2c_flag = I2C_APDMA_ASYNC, + }, +}; + +_Static_assert(ARRAY_SIZE(mtk_i2c_bus_controller) == I2C_BUS_NUMBER, + "Wrong size of mtk_i2c_bus_controller"); + +static const struct pad_func i2c_funcs[I2C_BUS_NUMBER][2] = { + [0] = { + PAD_FUNC_UP(SCP_SDA0, SDA0), + PAD_FUNC_UP(SCP_SCL0, SCL0), + }, + [1] = { + PAD_FUNC_UP(SCP_SDA1, SDA1), + PAD_FUNC_UP(SCP_SCL1, SCL1), + }, + [2] = { + PAD_FUNC_UP(SDA2, SDA2), + PAD_FUNC_UP(SCL2, SCL2), + }, + [3] = { + PAD_FUNC_UP(SDA3, SDA3), + PAD_FUNC_UP(SCL3, SCL3), + }, + [4] = { + PAD_FUNC_UP(SDA4, SDA4), + PAD_FUNC_UP(SCL4, SCL4), + }, + [5] = { + PAD_FUNC_UP(SDA5, SDA5), + PAD_FUNC_UP(SCL5, SCL5), + }, + [6] = { + PAD_FUNC_UP(SDA6, SDA6), + PAD_FUNC_UP(SCL6, SCL6), + }, + [7] = { + PAD_FUNC_UP(SDA7, SDA7), + PAD_FUNC_UP(SCL7, SCL7), + }, + [8] = { + PAD_FUNC_UP(SDA8, SDA8), + PAD_FUNC_UP(SCL8, SCL8), + }, +}; + +void mtk_i2c_set_gpio_pinmux(uint8_t bus) +{ + assert(bus < I2C_BUS_NUMBER); + + const struct pad_func *ptr = i2c_funcs[bus]; + for (size_t i = 0; i < 2; i++) { + gpio_set_mode(ptr[i].gpio, ptr[i].func); + gpio_set_pull(ptr[i].gpio, GPIO_PULL_DISABLE, ptr[i].select); + } +} diff --git a/src/soc/mediatek/mt8189/include/soc/addressmap.h b/src/soc/mediatek/mt8189/include/soc/addressmap.h index 3d559a9294..84006623a4 100644 --- a/src/soc/mediatek/mt8189/include/soc/addressmap.h +++ b/src/soc/mediatek/mt8189/include/soc/addressmap.h @@ -40,10 +40,28 @@ enum { DEVAPC_PERI_PAR_AO_BASE = IO_PHYS + 0x0103C000, SSUSB_IPPC_BASE = IO_PHYS + 0x01263E00, UFSHCI_BASE = IO_PHYS + 0x012B0000, + I2C0_DMA_BASE = IO_PHYS + 0x01300200, + I2C1_DMA_BASE = IO_PHYS + 0x01300300, + I2C2_DMA_BASE = IO_PHYS + 0x01300400, + I2C3_DMA_BASE = IO_PHYS + 0x01300500, + I2C4_DMA_BASE = IO_PHYS + 0x01300600, + I2C5_DMA_BASE = IO_PHYS + 0x01300700, + I2C6_DMA_BASE = IO_PHYS + 0x01300800, + I2C7_DMA_BASE = IO_PHYS + 0x01300900, + I2C8_DMA_BASE = IO_PHYS + 0x01300A00, SSUSB_SIF_BASE = IO_PHYS + 0x01B00300, + I2C2_BASE = IO_PHYS + 0x01B20000, MIPITX0_BASE = IO_PHYS + 0x01B40000, IOCFG_LM_BASE = IO_PHYS + 0x01B50000, EDP_BASE = IO_PHYS + 0x01B70000, + I2C0_BASE = IO_PHYS + 0x01C20000, + I2C1_BASE = IO_PHYS + 0x01C21000, + I2C3_BASE = IO_PHYS + 0x01D70000, + I2C4_BASE = IO_PHYS + 0x01D71000, + I2C5_BASE = IO_PHYS + 0x01D72000, + I2C6_BASE = IO_PHYS + 0x01D73000, + I2C7_BASE = IO_PHYS + 0x01F30000, + I2C8_BASE = IO_PHYS + 0x01F31000, IOCFG_RB0_BASE = IO_PHYS + 0x01C50000, IOCFG_RB1_BASE = IO_PHYS + 0x01C60000, IOCFG_BM0_BASE = IO_PHYS + 0x01D20000, diff --git a/src/soc/mediatek/mt8189/include/soc/i2c.h b/src/soc/mediatek/mt8189/include/soc/i2c.h new file mode 100644 index 0000000000..b39c0d734d --- /dev/null +++ b/src/soc/mediatek/mt8189/include/soc/i2c.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +/* + * This file is created based on MT8189 Functional Specification + * Chapter number: 9.10 + */ + +#ifndef __SOC_MEDIATEK_MT8189_INCLUDE_SOC_I2C_H__ +#define __SOC_MEDIATEK_MT8189_INCLUDE_SOC_I2C_H__ + +#include + +/* I2C Register */ +struct mt_i2c_regs { + uint32_t data_port; + uint32_t reserved0[1]; + uint32_t intr_mask; + uint32_t intr_stat; + uint32_t control; + uint32_t transfer_len; + uint32_t transac_len; + uint32_t delay_len; + uint32_t timing; + uint32_t start; + uint32_t ext_conf; + uint32_t ltiming; + uint32_t hs; + uint32_t io_config; + uint32_t fifo_addr_clr; + uint32_t reserved1[2]; + uint32_t transfer_aux_len; + uint32_t clock_div; + uint32_t time_out; + uint32_t softreset; + uint32_t reserved2[16]; + uint32_t slave_addr; + uint32_t reserved3[19]; + uint32_t debug_stat; + uint32_t debug_ctrl; + uint32_t reserved4[2]; + uint32_t fifo_stat; + uint32_t fifo_thresh; + uint32_t reserved5[897]; + uint32_t sec_control; + uint32_t reserved6[31]; + uint32_t channel_lock; + uint32_t channel_sec; + uint32_t hw_cg_en; + uint32_t reserved7[1]; + uint32_t dma_req; + uint32_t dma_nreq; +}; + +check_member(mt_i2c_regs, intr_mask, 0x08); +check_member(mt_i2c_regs, transfer_aux_len, 0x44); +check_member(mt_i2c_regs, slave_addr, 0x94); +check_member(mt_i2c_regs, debug_stat, 0xE4); +check_member(mt_i2c_regs, fifo_stat, 0xF4); +check_member(mt_i2c_regs, sec_control, 0xF00); +check_member(mt_i2c_regs, channel_lock, 0xF80); +check_member(mt_i2c_regs, dma_req, 0xF90); +check_member(mt_i2c_regs, dma_nreq, 0xF94); + +/* I2C ID Number*/ +enum { + I2C0, + I2C1, + I2C2, + I2C3, + I2C4, + I2C5, + I2C6, + I2C7, + I2C8, +}; + +#define I2C_BUS_NUMBER 9 +#define MAX_CLOCK_DIV 32 +#define I2C_CLK_HZ 124800000 + +#endif /* __SOC_MEDIATEK_MT8189_INCLUDE_SOC_I2C_H__ */