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
i2c_io_read8(uint8_t bid,uint32_t address)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
i2c_io_write8(uint8_t bid,uint32_t address,uint8_t data)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
bus_is_idle(uint32_t sr)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
bus_is_busy(uint32_t sr)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
isr_active(uint32_t sr)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
i2c_set_prescaler(uint8_t bid,uint32_t bps)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
i2c_set_bus_speed(uint8_t bid,int bps)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
i2c_sync_bus(uint8_t bid,bool (* match)(uint32_t),uint32_t * status)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
i2c_idle_bus(uint8_t bid)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
i2c_write_byte(uint8_t bid,uint8_t byte)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
i2c_read_byte(uint8_t bid,uint8_t * p)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
i2c_write_data(uint8_t bid,const uint8_t * buf,int len)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
i2c_read_data(uint8_t bid,uint8_t * buf,int len)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
i2c_init_transfer(uint8_t bid,uint8_t chip)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
imx_i2c_read(uint8_t bid,uint8_t chip,uint8_t * buf,int len)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
imx_i2c_write(uint8_t bid,uint8_t chip,const uint8_t * buf,int len)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
imx_i2c_probe(uint8_t bid,uint8_t chip)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 */
imx_i2c_init(uint8_t bid,int bps)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
get_va(paddr_t pa,vaddr_t * va)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
i2c_mapped(const char * i2c_match)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
508*f354a5d8SGatien Chevallier 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
513a5d5bbc8SVesa Jääskeläinen if (dt_map_dev(fdt, off, &i2c_bus[i].va, &size,
514a5d5bbc8SVesa 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
i2c_map_controller(void)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
i2c_map_controller(void)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
i2c_init(void)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