178b3ea9cSJorge Ramirez-Ortiz // SPDX-License-Identifier: BSD-2-Clause 278b3ea9cSJorge Ramirez-Ortiz /* 378b3ea9cSJorge Ramirez-Ortiz * (c) 2020 Jorge Ramirez <jorge@foundries.io>, Foundries Ltd. 478b3ea9cSJorge Ramirez-Ortiz */ 578b3ea9cSJorge Ramirez-Ortiz #include <arm.h> 678b3ea9cSJorge Ramirez-Ortiz #include <drivers/imx_i2c.h> 778b3ea9cSJorge Ramirez-Ortiz #include <initcall.h> 878b3ea9cSJorge Ramirez-Ortiz #include <io.h> 96923dd89SJorge Ramirez-Ortiz #include <kernel/boot.h> 1078b3ea9cSJorge Ramirez-Ortiz #include <kernel/delay.h> 116923dd89SJorge Ramirez-Ortiz #include <kernel/dt.h> 126923dd89SJorge Ramirez-Ortiz #include <libfdt.h> 1378b3ea9cSJorge Ramirez-Ortiz #include <mm/core_memprot.h> 1478b3ea9cSJorge Ramirez-Ortiz #include <mm/core_mmu.h> 1578b3ea9cSJorge Ramirez-Ortiz #include <platform_config.h> 1678b3ea9cSJorge Ramirez-Ortiz #include <stdlib.h> 1778b3ea9cSJorge Ramirez-Ortiz #include <trace.h> 1878b3ea9cSJorge Ramirez-Ortiz #include <util.h> 1978b3ea9cSJorge Ramirez-Ortiz 2078b3ea9cSJorge Ramirez-Ortiz #define I2C_CLK_RATE 24000000 /* Bits per second */ 2178b3ea9cSJorge Ramirez-Ortiz 22e2cf992dSJorge Ramirez-Ortiz /* Utility macros (__x identifies the bus [1 .. 3]) */ 23e2cf992dSJorge Ramirez-Ortiz #define I2C_CFG_SCL(__x) (IOMUXC_I2C1_SCL_CFG_OFF + ((__x) - 1) * 0x8) 24e2cf992dSJorge Ramirez-Ortiz #define I2C_CFG_SDA(__x) (IOMUXC_I2C1_SDA_CFG_OFF + ((__x) - 1) * 0x8) 25e2cf992dSJorge Ramirez-Ortiz #define I2C_MUX_SCL(__x) (IOMUXC_I2C1_SCL_MUX_OFF + ((__x) - 1) * 0x8) 26e2cf992dSJorge Ramirez-Ortiz #define I2C_MUX_SDA(__x) (IOMUXC_I2C1_SDA_MUX_OFF + ((__x) - 1) * 0x8) 27830dc5c6SGerard Koskamp #if defined(CFG_MX8MM) || defined(CFG_MX8MQ) || defined(CFG_MX8MP) || \ 28830dc5c6SGerard Koskamp defined(CFG_MX8MN) 29e2cf992dSJorge Ramirez-Ortiz /* IOMUX */ 30e2cf992dSJorge Ramirez-Ortiz #define I2C_INP_SCL(__x) 0 /* Not implemented */ 31e2cf992dSJorge Ramirez-Ortiz #define I2C_INP_SDA(__x) 0 /* Not implemented */ 32e2cf992dSJorge Ramirez-Ortiz #define I2C_INP_VAL(__x) 0 /* Not implemented */ 33e2cf992dSJorge Ramirez-Ortiz #define I2C_MUX_VAL(__x) 0x010 34e2cf992dSJorge Ramirez-Ortiz #define I2C_CFG_VAL(__x) 0x1c3 35e2cf992dSJorge Ramirez-Ortiz /* Clock */ 36e2cf992dSJorge Ramirez-Ortiz #define I2C_CLK_CGRBM(__x) 0 /* Not implemented */ 375729b44eSDevendra Devadiga #define I2C_CLK_CGR6BM(__x) 0 38e2cf992dSJorge Ramirez-Ortiz #define I2C_CLK_CGR(__x) CCM_CCRG_I2C##__x 39e2cf992dSJorge Ramirez-Ortiz #elif defined(CFG_MX6ULL) 40e2cf992dSJorge Ramirez-Ortiz /* IOMUX */ 41e2cf992dSJorge Ramirez-Ortiz #define I2C_INP_SCL(__x) (IOMUXC_I2C1_SCL_INP_OFF + ((__x) - 1) * 0x8) 42e2cf992dSJorge Ramirez-Ortiz #define I2C_INP_SDA(__x) (IOMUXC_I2C1_SDA_INP_OFF + ((__x) - 1) * 0x8) 43e2cf992dSJorge Ramirez-Ortiz #define I2C_INP_VAL(__x) (((__x) == 1) ? 0x1 : 0x2) 44e2cf992dSJorge Ramirez-Ortiz #define I2C_MUX_VAL(__x) 0x012 45e2cf992dSJorge Ramirez-Ortiz #define I2C_CFG_VAL(__x) 0x1b8b0 46e2cf992dSJorge Ramirez-Ortiz /* Clock */ 47e2cf992dSJorge Ramirez-Ortiz #define I2C_CLK_CGRBM(__x) BM_CCM_CCGR2_I2C##__x##_SERIAL 485729b44eSDevendra Devadiga #define I2C_CLK_CGR6BM(__x) BM_CCM_CCGR6_I2C##__x##_SERIAL 495729b44eSDevendra Devadiga #define I2C_CLK_CGR(__x) (((__x) == 4) ? CCM_CCGR6 : CCM_CCGR2) 50e2cf992dSJorge Ramirez-Ortiz #else 51e2cf992dSJorge Ramirez-Ortiz #error IMX_I2C driver not supported on this platform 52d156989aSJorge Ramirez-Ortiz #endif 53d156989aSJorge Ramirez-Ortiz 54a9edcef3SVanessa Maegima #if !defined(CFG_MX8MP) 555729b44eSDevendra Devadiga static struct io_pa_va i2c_bus[4] = { 56f8cb9adeSJorge Ramirez-Ortiz #if !defined(CFG_DT) || defined(CFG_EXTERNAL_DTB_OVERLAY) 578e58c34aSJorge Ramirez-Ortiz #if defined(I2C1_BASE) 588e58c34aSJorge Ramirez-Ortiz [0] = { .pa = I2C1_BASE, }, 598e58c34aSJorge Ramirez-Ortiz #endif 608e58c34aSJorge Ramirez-Ortiz #if defined(I2C2_BASE) 618e58c34aSJorge Ramirez-Ortiz [1] = { .pa = I2C2_BASE, }, 628e58c34aSJorge Ramirez-Ortiz #endif 638e58c34aSJorge Ramirez-Ortiz #if defined(I2C3_BASE) 648e58c34aSJorge Ramirez-Ortiz [2] = { .pa = I2C3_BASE, }, 658e58c34aSJorge Ramirez-Ortiz #endif 665729b44eSDevendra Devadiga #if defined(I2C4_BASE) 675729b44eSDevendra Devadiga [3] = { .pa = I2C4_BASE, }, 685729b44eSDevendra Devadiga #endif 696923dd89SJorge Ramirez-Ortiz #endif 7078b3ea9cSJorge Ramirez-Ortiz }; 71a9edcef3SVanessa Maegima #else 72a9edcef3SVanessa Maegima static struct io_pa_va i2c_bus[6] = { 73a9edcef3SVanessa Maegima #if !defined(CFG_DT) || defined(CFG_EXTERNAL_DTB_OVERLAY) 74a9edcef3SVanessa Maegima #if defined(I2C1_BASE) 75a9edcef3SVanessa Maegima [0] = { .pa = I2C1_BASE, }, 76a9edcef3SVanessa Maegima #endif 77a9edcef3SVanessa Maegima #if defined(I2C2_BASE) 78a9edcef3SVanessa Maegima [1] = { .pa = I2C2_BASE, }, 79a9edcef3SVanessa Maegima #endif 80a9edcef3SVanessa Maegima #if defined(I2C3_BASE) 81a9edcef3SVanessa Maegima [2] = { .pa = I2C3_BASE, }, 82a9edcef3SVanessa Maegima #endif 83a9edcef3SVanessa Maegima #if defined(I2C4_BASE) 84a9edcef3SVanessa Maegima [3] = { .pa = I2C4_BASE, }, 85a9edcef3SVanessa Maegima #endif 86a9edcef3SVanessa Maegima #if defined(I2C5_BASE) 87a9edcef3SVanessa Maegima [4] = { .pa = I2C5_BASE, }, 88a9edcef3SVanessa Maegima #endif 89a9edcef3SVanessa Maegima #if defined(I2C6_BASE) 90a9edcef3SVanessa Maegima [5] = { .pa = I2C6_BASE, }, 91a9edcef3SVanessa Maegima #endif 92a9edcef3SVanessa Maegima 93a9edcef3SVanessa Maegima #endif 94a9edcef3SVanessa Maegima }; 95a9edcef3SVanessa Maegima #endif 9678b3ea9cSJorge Ramirez-Ortiz 9778b3ea9cSJorge Ramirez-Ortiz static struct imx_i2c_clk { 9878b3ea9cSJorge Ramirez-Ortiz struct io_pa_va base; 9978b3ea9cSJorge Ramirez-Ortiz uint32_t i2c[ARRAY_SIZE(i2c_bus)]; 100d156989aSJorge Ramirez-Ortiz uint32_t cgrbm[ARRAY_SIZE(i2c_bus)]; 10178b3ea9cSJorge Ramirez-Ortiz } i2c_clk = { 10278b3ea9cSJorge Ramirez-Ortiz .base.pa = CCM_BASE, 1035729b44eSDevendra Devadiga .i2c = { I2C_CLK_CGR(1), I2C_CLK_CGR(2), I2C_CLK_CGR(3), I2C_CLK_CGR(4), }, 1045729b44eSDevendra Devadiga .cgrbm = { I2C_CLK_CGRBM(1), I2C_CLK_CGRBM(2), I2C_CLK_CGRBM(3), I2C_CLK_CGR6BM(4),}, 10578b3ea9cSJorge Ramirez-Ortiz }; 10678b3ea9cSJorge Ramirez-Ortiz 10778b3ea9cSJorge Ramirez-Ortiz static struct imx_i2c_mux { 10878b3ea9cSJorge Ramirez-Ortiz struct io_pa_va base; 10978b3ea9cSJorge Ramirez-Ortiz struct imx_i2c_mux_regs { 11078b3ea9cSJorge Ramirez-Ortiz uint32_t scl_mux; 11178b3ea9cSJorge Ramirez-Ortiz uint32_t scl_cfg; 112d156989aSJorge Ramirez-Ortiz uint32_t scl_inp; 11378b3ea9cSJorge Ramirez-Ortiz uint32_t sda_mux; 11478b3ea9cSJorge Ramirez-Ortiz uint32_t sda_cfg; 115d156989aSJorge Ramirez-Ortiz uint32_t sda_inp; 11678b3ea9cSJorge Ramirez-Ortiz } i2c[ARRAY_SIZE(i2c_bus)]; 11778b3ea9cSJorge Ramirez-Ortiz } i2c_mux = { 11878b3ea9cSJorge Ramirez-Ortiz .base.pa = IOMUXC_BASE, 11978b3ea9cSJorge Ramirez-Ortiz .i2c = {{ .scl_mux = I2C_MUX_SCL(1), .scl_cfg = I2C_CFG_SCL(1), 120d156989aSJorge Ramirez-Ortiz .scl_inp = I2C_INP_SCL(1), .sda_mux = I2C_MUX_SDA(1), 121d156989aSJorge Ramirez-Ortiz .sda_cfg = I2C_CFG_SDA(1), .sda_inp = I2C_INP_SDA(1), }, 12278b3ea9cSJorge Ramirez-Ortiz { .scl_mux = I2C_MUX_SCL(2), .scl_cfg = I2C_CFG_SCL(2), 123d156989aSJorge Ramirez-Ortiz .scl_inp = I2C_INP_SCL(2), .sda_mux = I2C_MUX_SDA(2), 124d156989aSJorge Ramirez-Ortiz .sda_cfg = I2C_CFG_SDA(2), .sda_inp = I2C_INP_SDA(2), }, 12578b3ea9cSJorge Ramirez-Ortiz { .scl_mux = I2C_MUX_SCL(3), .scl_cfg = I2C_CFG_SCL(3), 126d156989aSJorge Ramirez-Ortiz .scl_inp = I2C_INP_SCL(3), .sda_mux = I2C_MUX_SDA(3), 1275729b44eSDevendra Devadiga .sda_cfg = I2C_CFG_SDA(3), .sda_inp = I2C_INP_SDA(3), }, 1285729b44eSDevendra Devadiga { .scl_mux = I2C_MUX_SCL(4), .scl_cfg = I2C_CFG_SCL(4), 1295729b44eSDevendra Devadiga .scl_inp = I2C_INP_SCL(4), .sda_mux = I2C_MUX_SDA(4), 1305729b44eSDevendra Devadiga .sda_cfg = I2C_CFG_SDA(4), .sda_inp = I2C_INP_SDA(4), },}, 13178b3ea9cSJorge Ramirez-Ortiz }; 13278b3ea9cSJorge Ramirez-Ortiz 13378b3ea9cSJorge Ramirez-Ortiz #define I2DR 0x10 13478b3ea9cSJorge Ramirez-Ortiz #define I2SR 0x0C 13578b3ea9cSJorge Ramirez-Ortiz #define I2CR 0x08 13678b3ea9cSJorge Ramirez-Ortiz #define IFDR 0x04 13778b3ea9cSJorge Ramirez-Ortiz 13878b3ea9cSJorge Ramirez-Ortiz #define I2CR_IEN BIT(7) 13978b3ea9cSJorge Ramirez-Ortiz #define I2CR_IIEN BIT(6) 14078b3ea9cSJorge Ramirez-Ortiz #define I2CR_MSTA BIT(5) 14178b3ea9cSJorge Ramirez-Ortiz #define I2CR_MTX BIT(4) 14278b3ea9cSJorge Ramirez-Ortiz #define I2CR_TX_NO_AK BIT(3) 14378b3ea9cSJorge Ramirez-Ortiz #define I2CR_RSTA BIT(2) 14478b3ea9cSJorge Ramirez-Ortiz 14578b3ea9cSJorge Ramirez-Ortiz #define I2SR_ICF BIT(7) 14678b3ea9cSJorge Ramirez-Ortiz #define I2SR_IBB BIT(5) 14778b3ea9cSJorge Ramirez-Ortiz #define I2SR_IAL BIT(4) 14878b3ea9cSJorge Ramirez-Ortiz #define I2SR_IIF BIT(1) 14978b3ea9cSJorge Ramirez-Ortiz #define I2SR_RX_NO_AK BIT(0) 15078b3ea9cSJorge Ramirez-Ortiz 15178b3ea9cSJorge Ramirez-Ortiz static uint8_t i2c_io_read8(uint8_t bid, uint32_t address) 15278b3ea9cSJorge Ramirez-Ortiz { 15378b3ea9cSJorge Ramirez-Ortiz return io_read8(i2c_bus[bid].va + address); 15478b3ea9cSJorge Ramirez-Ortiz } 15578b3ea9cSJorge Ramirez-Ortiz 15678b3ea9cSJorge Ramirez-Ortiz static void i2c_io_write8(uint8_t bid, uint32_t address, uint8_t data) 15778b3ea9cSJorge Ramirez-Ortiz { 15878b3ea9cSJorge Ramirez-Ortiz return io_write8(i2c_bus[bid].va + address, data); 15978b3ea9cSJorge Ramirez-Ortiz } 16078b3ea9cSJorge Ramirez-Ortiz 16178b3ea9cSJorge Ramirez-Ortiz static bool bus_is_idle(uint32_t sr) 16278b3ea9cSJorge Ramirez-Ortiz { 16378b3ea9cSJorge Ramirez-Ortiz return (sr & I2SR_IBB) == 0; 16478b3ea9cSJorge Ramirez-Ortiz } 16578b3ea9cSJorge Ramirez-Ortiz 16678b3ea9cSJorge Ramirez-Ortiz static bool bus_is_busy(uint32_t sr) 16778b3ea9cSJorge Ramirez-Ortiz { 16878b3ea9cSJorge Ramirez-Ortiz return !bus_is_idle(sr); 16978b3ea9cSJorge Ramirez-Ortiz } 17078b3ea9cSJorge Ramirez-Ortiz 17178b3ea9cSJorge Ramirez-Ortiz static bool isr_active(uint32_t sr) 17278b3ea9cSJorge Ramirez-Ortiz { 17378b3ea9cSJorge Ramirez-Ortiz return (sr & I2SR_IIF) == I2SR_IIF; 17478b3ea9cSJorge Ramirez-Ortiz } 17578b3ea9cSJorge Ramirez-Ortiz 17678b3ea9cSJorge Ramirez-Ortiz static struct ifdr_pair { 17778b3ea9cSJorge Ramirez-Ortiz uint32_t divider; 17878b3ea9cSJorge Ramirez-Ortiz uint8_t prescaler; 17978b3ea9cSJorge Ramirez-Ortiz } ifdr_table[] = { 18078b3ea9cSJorge Ramirez-Ortiz { 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 }, { 28, 0x23 }, 18178b3ea9cSJorge Ramirez-Ortiz { 30, 0x00 }, { 32, 0x24 }, { 36, 0x25 }, { 40, 0x26 }, 18278b3ea9cSJorge Ramirez-Ortiz { 42, 0x03 }, { 44, 0x27 }, { 48, 0x28 }, { 52, 0x05 }, 18378b3ea9cSJorge Ramirez-Ortiz { 56, 0x29 }, { 60, 0x06 }, { 64, 0x2A }, { 72, 0x2B }, 18478b3ea9cSJorge Ramirez-Ortiz { 80, 0x2C }, { 88, 0x09 }, { 96, 0x2D }, { 104, 0x0A }, 18578b3ea9cSJorge Ramirez-Ortiz { 112, 0x2E }, { 128, 0x2F }, { 144, 0x0C }, { 160, 0x30 }, 18678b3ea9cSJorge Ramirez-Ortiz { 192, 0x31 }, { 224, 0x32 }, { 240, 0x0F }, { 256, 0x33 }, 18778b3ea9cSJorge Ramirez-Ortiz { 288, 0x10 }, { 320, 0x34 }, { 384, 0x35 }, { 448, 0x36 }, 18878b3ea9cSJorge Ramirez-Ortiz { 480, 0x13 }, { 512, 0x37 }, { 576, 0x14 }, { 640, 0x38 }, 18978b3ea9cSJorge Ramirez-Ortiz { 768, 0x39 }, { 896, 0x3A }, { 960, 0x17 }, { 1024, 0x3B }, 19078b3ea9cSJorge Ramirez-Ortiz { 1152, 0x18 }, { 1280, 0x3C }, { 1536, 0x3D }, { 1792, 0x3E }, 19178b3ea9cSJorge Ramirez-Ortiz { 1920, 0x1B }, { 2048, 0x3F }, { 2304, 0x1C }, { 2560, 0x1D }, 19278b3ea9cSJorge Ramirez-Ortiz { 3072, 0x1E }, { 3840, 0x1F } 19378b3ea9cSJorge Ramirez-Ortiz }; 19478b3ea9cSJorge Ramirez-Ortiz 19578b3ea9cSJorge Ramirez-Ortiz static void i2c_set_prescaler(uint8_t bid, uint32_t bps) 19678b3ea9cSJorge Ramirez-Ortiz { 19778b3ea9cSJorge Ramirez-Ortiz struct ifdr_pair *p = ifdr_table; 19878b3ea9cSJorge Ramirez-Ortiz struct ifdr_pair *q = p + ARRAY_SIZE(ifdr_table) - 1; 19978b3ea9cSJorge Ramirez-Ortiz uint32_t div = (I2C_CLK_RATE + bps - 1) / bps; 20078b3ea9cSJorge Ramirez-Ortiz 20178b3ea9cSJorge Ramirez-Ortiz if (div < p->divider) 20278b3ea9cSJorge Ramirez-Ortiz q = p; 20378b3ea9cSJorge Ramirez-Ortiz else if (div > q->divider) 20478b3ea9cSJorge Ramirez-Ortiz p = q; 20578b3ea9cSJorge Ramirez-Ortiz 20678b3ea9cSJorge Ramirez-Ortiz while (p != q) { 20778b3ea9cSJorge Ramirez-Ortiz if (div <= p->divider) 20878b3ea9cSJorge Ramirez-Ortiz break; 20978b3ea9cSJorge Ramirez-Ortiz p++; 21078b3ea9cSJorge Ramirez-Ortiz } 21178b3ea9cSJorge Ramirez-Ortiz 21278b3ea9cSJorge Ramirez-Ortiz i2c_io_write8(bid, IFDR, p->prescaler); 21378b3ea9cSJorge Ramirez-Ortiz } 21478b3ea9cSJorge Ramirez-Ortiz 21578b3ea9cSJorge Ramirez-Ortiz static void i2c_set_bus_speed(uint8_t bid, int bps) 21678b3ea9cSJorge Ramirez-Ortiz { 217d156989aSJorge Ramirez-Ortiz vaddr_t addr = i2c_clk.base.va; 218d156989aSJorge Ramirez-Ortiz uint32_t val = 0; 21978b3ea9cSJorge Ramirez-Ortiz 220830dc5c6SGerard Koskamp #if defined(CFG_MX8MM) || defined(CFG_MX8MQ) || defined(CFG_MX8MP) || \ 221830dc5c6SGerard Koskamp defined(CFG_MX8MN) 222d156989aSJorge Ramirez-Ortiz addr += CCM_CCGRx_SET(i2c_clk.i2c[bid]); 223d156989aSJorge Ramirez-Ortiz val = CCM_CCGRx_ALWAYS_ON(0); 224d156989aSJorge Ramirez-Ortiz #elif defined(CFG_MX6ULL) 225d156989aSJorge Ramirez-Ortiz addr += i2c_clk.i2c[bid]; 226d156989aSJorge Ramirez-Ortiz val = i2c_clk.cgrbm[bid] | io_read32(addr); 227e2cf992dSJorge Ramirez-Ortiz #else 228e2cf992dSJorge Ramirez-Ortiz #error IMX_I2C driver not supported on this platform 229d156989aSJorge Ramirez-Ortiz #endif 230d156989aSJorge Ramirez-Ortiz io_write32(addr, val); 23178b3ea9cSJorge Ramirez-Ortiz i2c_set_prescaler(bid, bps); 23278b3ea9cSJorge Ramirez-Ortiz } 23378b3ea9cSJorge Ramirez-Ortiz 23478b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_sync_bus(uint8_t bid, bool (*match)(uint32_t), 23578b3ea9cSJorge Ramirez-Ortiz uint32_t *status) 23678b3ea9cSJorge Ramirez-Ortiz { 23778b3ea9cSJorge Ramirez-Ortiz uint64_t tref = timeout_init_us(100000); 23878b3ea9cSJorge Ramirez-Ortiz uint32_t sr = 0; 23978b3ea9cSJorge Ramirez-Ortiz 24078b3ea9cSJorge Ramirez-Ortiz while (!timeout_elapsed(tref)) { 24178b3ea9cSJorge Ramirez-Ortiz sr = i2c_io_read8(bid, I2SR); 24278b3ea9cSJorge Ramirez-Ortiz if (sr & I2SR_IAL) { 24378b3ea9cSJorge Ramirez-Ortiz EMSG("bus arbitration lost"); 24478b3ea9cSJorge Ramirez-Ortiz i2c_io_write8(bid, I2SR, sr & ~I2SR_IAL); 24578b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_COMMUNICATION; 24678b3ea9cSJorge Ramirez-Ortiz } 24778b3ea9cSJorge Ramirez-Ortiz if ((*match)(sr)) { 24878b3ea9cSJorge Ramirez-Ortiz if (status) 24978b3ea9cSJorge Ramirez-Ortiz *status = sr; 25078b3ea9cSJorge Ramirez-Ortiz return TEE_SUCCESS; 25178b3ea9cSJorge Ramirez-Ortiz } 25278b3ea9cSJorge Ramirez-Ortiz } 25378b3ea9cSJorge Ramirez-Ortiz 25478b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_BUSY; 25578b3ea9cSJorge Ramirez-Ortiz } 25678b3ea9cSJorge Ramirez-Ortiz 25778b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_idle_bus(uint8_t bid) 25878b3ea9cSJorge Ramirez-Ortiz { 25978b3ea9cSJorge Ramirez-Ortiz uint8_t tmp = i2c_io_read8(bid, I2CR) & ~I2CR_MSTA; 26078b3ea9cSJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS; 26178b3ea9cSJorge Ramirez-Ortiz 26278b3ea9cSJorge Ramirez-Ortiz i2c_io_write8(bid, I2CR, tmp); 26378b3ea9cSJorge Ramirez-Ortiz ret = i2c_sync_bus(bid, &bus_is_idle, NULL); 26478b3ea9cSJorge Ramirez-Ortiz i2c_io_write8(bid, I2SR, 0); 26578b3ea9cSJorge Ramirez-Ortiz 26678b3ea9cSJorge Ramirez-Ortiz return ret; 26778b3ea9cSJorge Ramirez-Ortiz } 26878b3ea9cSJorge Ramirez-Ortiz 26978b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_write_byte(uint8_t bid, uint8_t byte) 27078b3ea9cSJorge Ramirez-Ortiz { 27178b3ea9cSJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS; 27278b3ea9cSJorge Ramirez-Ortiz uint32_t status = 0; 27378b3ea9cSJorge Ramirez-Ortiz 27478b3ea9cSJorge Ramirez-Ortiz i2c_io_write8(bid, I2DR, byte); 27578b3ea9cSJorge Ramirez-Ortiz ret = i2c_sync_bus(bid, &isr_active, &status); 27678b3ea9cSJorge Ramirez-Ortiz i2c_io_write8(bid, I2SR, 0); 27778b3ea9cSJorge Ramirez-Ortiz 27814371509SJorge Ramirez-Ortiz if (!ret && (status & I2SR_RX_NO_AK)) 27978b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_BAD_STATE; 28078b3ea9cSJorge Ramirez-Ortiz 28178b3ea9cSJorge Ramirez-Ortiz return ret; 28278b3ea9cSJorge Ramirez-Ortiz } 28378b3ea9cSJorge Ramirez-Ortiz 28478b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_read_byte(uint8_t bid, uint8_t *p) 28578b3ea9cSJorge Ramirez-Ortiz { 28678b3ea9cSJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS; 28778b3ea9cSJorge Ramirez-Ortiz 28878b3ea9cSJorge Ramirez-Ortiz *p = i2c_io_read8(bid, I2DR); 28978b3ea9cSJorge Ramirez-Ortiz ret = i2c_sync_bus(bid, &isr_active, NULL); 29078b3ea9cSJorge Ramirez-Ortiz i2c_io_write8(bid, I2SR, 0); 29178b3ea9cSJorge Ramirez-Ortiz 29278b3ea9cSJorge Ramirez-Ortiz return ret; 29378b3ea9cSJorge Ramirez-Ortiz } 29478b3ea9cSJorge Ramirez-Ortiz 29578b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_write_data(uint8_t bid, const uint8_t *buf, int len) 29678b3ea9cSJorge Ramirez-Ortiz { 29778b3ea9cSJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS; 29878b3ea9cSJorge Ramirez-Ortiz uint32_t tmp = 0; 29978b3ea9cSJorge Ramirez-Ortiz 30078b3ea9cSJorge Ramirez-Ortiz if (!len) 30178b3ea9cSJorge Ramirez-Ortiz return TEE_SUCCESS; 30278b3ea9cSJorge Ramirez-Ortiz 30378b3ea9cSJorge Ramirez-Ortiz tmp = i2c_io_read8(bid, I2CR) | I2CR_MTX | I2CR_TX_NO_AK; 30478b3ea9cSJorge Ramirez-Ortiz i2c_io_write8(bid, I2CR, tmp); 30578b3ea9cSJorge Ramirez-Ortiz 30678b3ea9cSJorge Ramirez-Ortiz while (len--) { 30778b3ea9cSJorge Ramirez-Ortiz ret = i2c_write_byte(bid, *buf++); 30814371509SJorge Ramirez-Ortiz if (ret) 30978b3ea9cSJorge Ramirez-Ortiz return ret; 31078b3ea9cSJorge Ramirez-Ortiz } 31178b3ea9cSJorge Ramirez-Ortiz 31278b3ea9cSJorge Ramirez-Ortiz return ret; 31378b3ea9cSJorge Ramirez-Ortiz } 31478b3ea9cSJorge Ramirez-Ortiz 31578b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_read_data(uint8_t bid, uint8_t *buf, int len) 31678b3ea9cSJorge Ramirez-Ortiz { 31778b3ea9cSJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS; 31878b3ea9cSJorge Ramirez-Ortiz uint8_t dummy = 0; 31978b3ea9cSJorge Ramirez-Ortiz uint32_t tmp = 0; 32078b3ea9cSJorge Ramirez-Ortiz 32178b3ea9cSJorge Ramirez-Ortiz if (!len) 32278b3ea9cSJorge Ramirez-Ortiz return TEE_SUCCESS; 32378b3ea9cSJorge Ramirez-Ortiz 32478b3ea9cSJorge Ramirez-Ortiz tmp = i2c_io_read8(bid, I2CR) & ~I2CR_MTX; 32578b3ea9cSJorge Ramirez-Ortiz tmp = (len == 1) ? tmp | I2CR_TX_NO_AK : tmp & ~I2CR_TX_NO_AK; 32678b3ea9cSJorge Ramirez-Ortiz i2c_io_write8(bid, I2CR, tmp); 32778b3ea9cSJorge Ramirez-Ortiz i2c_io_read8(bid, I2DR); 32878b3ea9cSJorge Ramirez-Ortiz 32978b3ea9cSJorge Ramirez-Ortiz ret = i2c_read_byte(bid, &dummy); 33014371509SJorge Ramirez-Ortiz if (ret) 33178b3ea9cSJorge Ramirez-Ortiz return ret; 33278b3ea9cSJorge Ramirez-Ortiz 33378b3ea9cSJorge Ramirez-Ortiz /* 33478b3ea9cSJorge Ramirez-Ortiz * A data transfer ends when the master signals a stop; for a master 33578b3ea9cSJorge Ramirez-Ortiz * receiver to terminate a transfer it must inform the slave transmiter 33678b3ea9cSJorge Ramirez-Ortiz * by not acknowledging the last data byte. This is done by setting the 33778b3ea9cSJorge Ramirez-Ortiz * transmit acknowledge bit before reading the next-to-last byte. 33878b3ea9cSJorge Ramirez-Ortiz */ 33978b3ea9cSJorge Ramirez-Ortiz do { 34078b3ea9cSJorge Ramirez-Ortiz if (len == 2) { 34178b3ea9cSJorge Ramirez-Ortiz tmp = i2c_io_read8(bid, I2CR) | I2CR_TX_NO_AK; 34278b3ea9cSJorge Ramirez-Ortiz i2c_io_write8(bid, I2CR, tmp); 34378b3ea9cSJorge Ramirez-Ortiz } 34478b3ea9cSJorge Ramirez-Ortiz 34578b3ea9cSJorge Ramirez-Ortiz ret = i2c_read_byte(bid, buf++); 34614371509SJorge Ramirez-Ortiz if (ret) 34778b3ea9cSJorge Ramirez-Ortiz return ret; 34878b3ea9cSJorge Ramirez-Ortiz } while (len--); 34978b3ea9cSJorge Ramirez-Ortiz 35078b3ea9cSJorge Ramirez-Ortiz return ret; 35178b3ea9cSJorge Ramirez-Ortiz } 35278b3ea9cSJorge Ramirez-Ortiz 35378b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_init_transfer(uint8_t bid, uint8_t chip) 35478b3ea9cSJorge Ramirez-Ortiz { 35578b3ea9cSJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS; 35678b3ea9cSJorge Ramirez-Ortiz uint32_t tmp = 0; 35778b3ea9cSJorge Ramirez-Ortiz 35878b3ea9cSJorge Ramirez-Ortiz ret = i2c_idle_bus(bid); 35914371509SJorge Ramirez-Ortiz if (ret) 36078b3ea9cSJorge Ramirez-Ortiz return ret; 36178b3ea9cSJorge Ramirez-Ortiz 36278b3ea9cSJorge Ramirez-Ortiz /* Enable the interface */ 363460dc361STim Anderson tmp = !(i2c_io_read8(bid, I2CR) & I2CR_IEN); 364460dc361STim Anderson if (tmp) { 36578b3ea9cSJorge Ramirez-Ortiz i2c_io_write8(bid, I2CR, I2CR_IEN); 366460dc361STim Anderson udelay(50); 367460dc361STim Anderson } 368460dc361STim Anderson i2c_io_write8(bid, I2SR, 0); 36978b3ea9cSJorge Ramirez-Ortiz 37078b3ea9cSJorge Ramirez-Ortiz tmp = i2c_io_read8(bid, I2CR) | I2CR_MSTA; 37178b3ea9cSJorge Ramirez-Ortiz i2c_io_write8(bid, I2CR, tmp); 37278b3ea9cSJorge Ramirez-Ortiz 37378b3ea9cSJorge Ramirez-Ortiz /* Wait until the bus is active */ 37478b3ea9cSJorge Ramirez-Ortiz ret = i2c_sync_bus(bid, &bus_is_busy, NULL); 37514371509SJorge Ramirez-Ortiz if (ret) 37678b3ea9cSJorge Ramirez-Ortiz return ret; 37778b3ea9cSJorge Ramirez-Ortiz 37878b3ea9cSJorge Ramirez-Ortiz /* Slave address on the bus */ 37978b3ea9cSJorge Ramirez-Ortiz return i2c_write_data(bid, &chip, 1); 38078b3ea9cSJorge Ramirez-Ortiz } 38178b3ea9cSJorge Ramirez-Ortiz 38278b3ea9cSJorge Ramirez-Ortiz TEE_Result imx_i2c_read(uint8_t bid, uint8_t chip, uint8_t *buf, int len) 38378b3ea9cSJorge Ramirez-Ortiz { 38478b3ea9cSJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS; 38578b3ea9cSJorge Ramirez-Ortiz 38678b3ea9cSJorge Ramirez-Ortiz if (bid >= ARRAY_SIZE(i2c_bus)) 38778b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 38878b3ea9cSJorge Ramirez-Ortiz 38978b3ea9cSJorge Ramirez-Ortiz if ((len && !buf) || chip > 0x7F) 39078b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 39178b3ea9cSJorge Ramirez-Ortiz 3928e58c34aSJorge Ramirez-Ortiz if (!i2c_bus[bid].va) 3938e58c34aSJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 3948e58c34aSJorge Ramirez-Ortiz 39578b3ea9cSJorge Ramirez-Ortiz ret = i2c_init_transfer(bid, chip << 1 | BIT(0)); 39614371509SJorge Ramirez-Ortiz if (!ret) 39778b3ea9cSJorge Ramirez-Ortiz ret = i2c_read_data(bid, buf, len); 39878b3ea9cSJorge Ramirez-Ortiz 39914371509SJorge Ramirez-Ortiz if (i2c_idle_bus(bid)) 40078b3ea9cSJorge Ramirez-Ortiz IMSG("bus not idle"); 40178b3ea9cSJorge Ramirez-Ortiz 40278b3ea9cSJorge Ramirez-Ortiz return ret; 40378b3ea9cSJorge Ramirez-Ortiz } 40478b3ea9cSJorge Ramirez-Ortiz 40578b3ea9cSJorge Ramirez-Ortiz TEE_Result imx_i2c_write(uint8_t bid, uint8_t chip, const uint8_t *buf, int len) 40678b3ea9cSJorge Ramirez-Ortiz { 40778b3ea9cSJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS; 40878b3ea9cSJorge Ramirez-Ortiz 40978b3ea9cSJorge Ramirez-Ortiz if (bid >= ARRAY_SIZE(i2c_bus)) 41078b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 41178b3ea9cSJorge Ramirez-Ortiz 41278b3ea9cSJorge Ramirez-Ortiz if ((len && !buf) || chip > 0x7F) 41378b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 41478b3ea9cSJorge Ramirez-Ortiz 4158e58c34aSJorge Ramirez-Ortiz if (!i2c_bus[bid].va) 4168e58c34aSJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 4178e58c34aSJorge Ramirez-Ortiz 41878b3ea9cSJorge Ramirez-Ortiz ret = i2c_init_transfer(bid, chip << 1); 41914371509SJorge Ramirez-Ortiz if (!ret) 42078b3ea9cSJorge Ramirez-Ortiz ret = i2c_write_data(bid, buf, len); 42178b3ea9cSJorge Ramirez-Ortiz 42214371509SJorge Ramirez-Ortiz if (i2c_idle_bus(bid)) 42378b3ea9cSJorge Ramirez-Ortiz IMSG("bus not idle"); 42478b3ea9cSJorge Ramirez-Ortiz 42578b3ea9cSJorge Ramirez-Ortiz return ret; 42678b3ea9cSJorge Ramirez-Ortiz } 42778b3ea9cSJorge Ramirez-Ortiz 42878b3ea9cSJorge Ramirez-Ortiz TEE_Result imx_i2c_probe(uint8_t bid, uint8_t chip) 42978b3ea9cSJorge Ramirez-Ortiz { 43078b3ea9cSJorge Ramirez-Ortiz if (bid >= ARRAY_SIZE(i2c_bus)) 43178b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 43278b3ea9cSJorge Ramirez-Ortiz 4338e58c34aSJorge Ramirez-Ortiz if (!i2c_bus[bid].va) 4348e58c34aSJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 4358e58c34aSJorge Ramirez-Ortiz 43678b3ea9cSJorge Ramirez-Ortiz if (chip > 0x7F) 43778b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 43878b3ea9cSJorge Ramirez-Ortiz 43978b3ea9cSJorge Ramirez-Ortiz return imx_i2c_write(bid, chip, NULL, 0); 44078b3ea9cSJorge Ramirez-Ortiz } 44178b3ea9cSJorge Ramirez-Ortiz 44278b3ea9cSJorge Ramirez-Ortiz /* 44378b3ea9cSJorge Ramirez-Ortiz * I2C bus initialization: configure the IOMUX and enable the clock. 4445729b44eSDevendra Devadiga * @bid: Bus ID: (0=I2C1), (1=I2C2), (2=I2C3), (3=I2C4). 44578b3ea9cSJorge Ramirez-Ortiz * @bps: Bus baud rate, in bits per second. 44678b3ea9cSJorge Ramirez-Ortiz */ 44778b3ea9cSJorge Ramirez-Ortiz TEE_Result imx_i2c_init(uint8_t bid, int bps) 44878b3ea9cSJorge Ramirez-Ortiz { 44978b3ea9cSJorge Ramirez-Ortiz struct imx_i2c_mux *mux = &i2c_mux; 45078b3ea9cSJorge Ramirez-Ortiz 45178b3ea9cSJorge Ramirez-Ortiz if (bid >= ARRAY_SIZE(i2c_bus)) 45278b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 45378b3ea9cSJorge Ramirez-Ortiz 45478b3ea9cSJorge Ramirez-Ortiz if (!bps) 45578b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 45678b3ea9cSJorge Ramirez-Ortiz 4578e58c34aSJorge Ramirez-Ortiz if (!i2c_bus[bid].va) 4588e58c34aSJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS; 4598e58c34aSJorge Ramirez-Ortiz 46078b3ea9cSJorge Ramirez-Ortiz io_write32(mux->base.va + mux->i2c[bid].scl_mux, I2C_MUX_VAL(bid)); 46178b3ea9cSJorge Ramirez-Ortiz io_write32(mux->base.va + mux->i2c[bid].scl_cfg, I2C_CFG_VAL(bid)); 462d156989aSJorge Ramirez-Ortiz if (mux->i2c[bid].scl_inp) 463d156989aSJorge Ramirez-Ortiz io_write32(mux->base.va + mux->i2c[bid].scl_inp, 464e2cf992dSJorge Ramirez-Ortiz I2C_INP_VAL(bid + 1)); 465d156989aSJorge Ramirez-Ortiz 46678b3ea9cSJorge Ramirez-Ortiz io_write32(mux->base.va + mux->i2c[bid].sda_mux, I2C_MUX_VAL(bid)); 46778b3ea9cSJorge Ramirez-Ortiz io_write32(mux->base.va + mux->i2c[bid].sda_cfg, I2C_CFG_VAL(bid)); 468d156989aSJorge Ramirez-Ortiz if (mux->i2c[bid].sda_inp) 469d156989aSJorge Ramirez-Ortiz io_write32(mux->base.va + mux->i2c[bid].sda_inp, 470961785fbSTim Anderson I2C_INP_VAL(bid + 2)); 47178b3ea9cSJorge Ramirez-Ortiz 47278b3ea9cSJorge Ramirez-Ortiz /* Baud rate in bits per second */ 47378b3ea9cSJorge Ramirez-Ortiz i2c_set_bus_speed(bid, bps); 47478b3ea9cSJorge Ramirez-Ortiz 47578b3ea9cSJorge Ramirez-Ortiz return TEE_SUCCESS; 47678b3ea9cSJorge Ramirez-Ortiz } 47778b3ea9cSJorge Ramirez-Ortiz 47878b3ea9cSJorge Ramirez-Ortiz static TEE_Result get_va(paddr_t pa, vaddr_t *va) 47978b3ea9cSJorge Ramirez-Ortiz { 480bc9618c0SAnton Rybakov *va = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, pa, 0x10000); 481bc9618c0SAnton Rybakov if (!*va) 48278b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 48378b3ea9cSJorge Ramirez-Ortiz 48478b3ea9cSJorge Ramirez-Ortiz return TEE_SUCCESS; 48578b3ea9cSJorge Ramirez-Ortiz } 48678b3ea9cSJorge Ramirez-Ortiz 487f8cb9adeSJorge Ramirez-Ortiz #if defined(CFG_DT) && !defined(CFG_EXTERNAL_DTB_OVERLAY) 4886923dd89SJorge Ramirez-Ortiz static const char *const dt_i2c_match_table[] = { 4896923dd89SJorge Ramirez-Ortiz "fsl,imx21-i2c", 4906923dd89SJorge Ramirez-Ortiz }; 4916923dd89SJorge Ramirez-Ortiz 4926923dd89SJorge Ramirez-Ortiz static TEE_Result i2c_mapped(const char *i2c_match) 49378b3ea9cSJorge Ramirez-Ortiz { 4946923dd89SJorge Ramirez-Ortiz TEE_Result ret = TEE_ERROR_GENERIC; 4956923dd89SJorge Ramirez-Ortiz void *fdt = get_dt(); 4966923dd89SJorge Ramirez-Ortiz size_t size = 0; 4976923dd89SJorge Ramirez-Ortiz size_t i = 0; 4986923dd89SJorge Ramirez-Ortiz int off = 0; 4996923dd89SJorge Ramirez-Ortiz 5006923dd89SJorge Ramirez-Ortiz if (!fdt) 5016923dd89SJorge Ramirez-Ortiz return TEE_ERROR_NOT_SUPPORTED; 5026923dd89SJorge Ramirez-Ortiz 5036923dd89SJorge Ramirez-Ortiz for (i = 0; i < ARRAY_SIZE(i2c_bus); i++) { 5046923dd89SJorge Ramirez-Ortiz off = fdt_node_offset_by_compatible(fdt, off, i2c_match); 5056923dd89SJorge Ramirez-Ortiz if (off < 0) 5066923dd89SJorge Ramirez-Ortiz break; 5076923dd89SJorge Ramirez-Ortiz 5086923dd89SJorge Ramirez-Ortiz if (!(_fdt_get_status(fdt, off) & DT_STATUS_OK_SEC)) { 5096923dd89SJorge Ramirez-Ortiz EMSG("i2c%zu not enabled", i + 1); 5106923dd89SJorge Ramirez-Ortiz continue; 5116923dd89SJorge Ramirez-Ortiz } 5126923dd89SJorge Ramirez-Ortiz 513*a5d5bbc8SVesa Jääskeläinen if (dt_map_dev(fdt, off, &i2c_bus[i].va, &size, 514*a5d5bbc8SVesa Jääskeläinen DT_MAP_AUTO) < 0) { 5156923dd89SJorge Ramirez-Ortiz EMSG("i2c%zu not enabled", i + 1); 5166923dd89SJorge Ramirez-Ortiz continue; 5176923dd89SJorge Ramirez-Ortiz } 5186923dd89SJorge Ramirez-Ortiz 5196923dd89SJorge Ramirez-Ortiz i2c_bus[i].pa = virt_to_phys((void *)i2c_bus[i].va); 5206923dd89SJorge Ramirez-Ortiz ret = TEE_SUCCESS; 5216923dd89SJorge Ramirez-Ortiz } 5226923dd89SJorge Ramirez-Ortiz 5236923dd89SJorge Ramirez-Ortiz return ret; 5246923dd89SJorge Ramirez-Ortiz } 5256923dd89SJorge Ramirez-Ortiz 5266923dd89SJorge Ramirez-Ortiz static TEE_Result i2c_map_controller(void) 5276923dd89SJorge Ramirez-Ortiz { 5286923dd89SJorge Ramirez-Ortiz TEE_Result ret = TEE_ERROR_GENERIC; 5296923dd89SJorge Ramirez-Ortiz size_t i = 0; 5306923dd89SJorge Ramirez-Ortiz 5316923dd89SJorge Ramirez-Ortiz for (i = 0; i < ARRAY_SIZE(dt_i2c_match_table); i++) { 5326923dd89SJorge Ramirez-Ortiz ret = i2c_mapped(dt_i2c_match_table[i]); 5336923dd89SJorge Ramirez-Ortiz if (!ret || ret == TEE_ERROR_NOT_SUPPORTED) 5346923dd89SJorge Ramirez-Ortiz return ret; 5356923dd89SJorge Ramirez-Ortiz } 5366923dd89SJorge Ramirez-Ortiz 5376923dd89SJorge Ramirez-Ortiz return ret; 5386923dd89SJorge Ramirez-Ortiz } 5396923dd89SJorge Ramirez-Ortiz #else 5406923dd89SJorge Ramirez-Ortiz static TEE_Result i2c_map_controller(void) 5416923dd89SJorge Ramirez-Ortiz { 5426923dd89SJorge Ramirez-Ortiz TEE_Result ret = TEE_ERROR_GENERIC; 54378b3ea9cSJorge Ramirez-Ortiz size_t n = 0; 54478b3ea9cSJorge Ramirez-Ortiz 5456923dd89SJorge Ramirez-Ortiz for (n = 0; n < ARRAY_SIZE(i2c_bus); n++) { 5466923dd89SJorge Ramirez-Ortiz if (i2c_bus[n].pa) { 5476923dd89SJorge Ramirez-Ortiz if (get_va(i2c_bus[n].pa, &i2c_bus[n].va)) 5486923dd89SJorge Ramirez-Ortiz EMSG("i2c%zu not enabled", n + 1); 5496923dd89SJorge Ramirez-Ortiz else 5506923dd89SJorge Ramirez-Ortiz ret = TEE_SUCCESS; 5516923dd89SJorge Ramirez-Ortiz } else { 5526923dd89SJorge Ramirez-Ortiz IMSG("i2c%zu not enabled", n + 1); 5536923dd89SJorge Ramirez-Ortiz } 5546923dd89SJorge Ramirez-Ortiz } 5556923dd89SJorge Ramirez-Ortiz 5566923dd89SJorge Ramirez-Ortiz return ret; 5576923dd89SJorge Ramirez-Ortiz } 558f8cb9adeSJorge Ramirez-Ortiz #endif 5596923dd89SJorge Ramirez-Ortiz 5606923dd89SJorge Ramirez-Ortiz static TEE_Result i2c_init(void) 5616923dd89SJorge Ramirez-Ortiz { 56214371509SJorge Ramirez-Ortiz if (get_va(i2c_clk.base.pa, &i2c_clk.base.va)) 56378b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 56478b3ea9cSJorge Ramirez-Ortiz 56514371509SJorge Ramirez-Ortiz if (get_va(i2c_mux.base.pa, &i2c_mux.base.va)) 56678b3ea9cSJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 56778b3ea9cSJorge Ramirez-Ortiz 5686923dd89SJorge Ramirez-Ortiz return i2c_map_controller(); 56978b3ea9cSJorge Ramirez-Ortiz } 57078b3ea9cSJorge Ramirez-Ortiz 571db0683faSJorge Ramirez-Ortiz early_init(i2c_init); 572