xref: /optee_os/core/drivers/imx_i2c.c (revision 5729b44e26c145c1d4bc3616519ca25f10b7b60b)
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)
27c29c5388SDevendra Devadiga #if defined(CFG_MX8MM) || defined(CFG_MX8MQ)
28e2cf992dSJorge Ramirez-Ortiz /* IOMUX */
29e2cf992dSJorge Ramirez-Ortiz #define I2C_INP_SCL(__x)	0 /* Not implemented */
30e2cf992dSJorge Ramirez-Ortiz #define I2C_INP_SDA(__x)	0 /* Not implemented */
31e2cf992dSJorge Ramirez-Ortiz #define I2C_INP_VAL(__x)	0 /* Not implemented */
32e2cf992dSJorge Ramirez-Ortiz #define I2C_MUX_VAL(__x)	0x010
33e2cf992dSJorge Ramirez-Ortiz #define I2C_CFG_VAL(__x)	0x1c3
34e2cf992dSJorge Ramirez-Ortiz /* Clock */
35e2cf992dSJorge Ramirez-Ortiz #define I2C_CLK_CGRBM(__x)	0 /* Not implemented */
36*5729b44eSDevendra Devadiga #define I2C_CLK_CGR6BM(__x)	0
37e2cf992dSJorge Ramirez-Ortiz #define I2C_CLK_CGR(__x)	CCM_CCRG_I2C##__x
38e2cf992dSJorge Ramirez-Ortiz #elif defined(CFG_MX6ULL)
39e2cf992dSJorge Ramirez-Ortiz /* IOMUX */
40e2cf992dSJorge Ramirez-Ortiz #define I2C_INP_SCL(__x)	(IOMUXC_I2C1_SCL_INP_OFF + ((__x) - 1) * 0x8)
41e2cf992dSJorge Ramirez-Ortiz #define I2C_INP_SDA(__x)	(IOMUXC_I2C1_SDA_INP_OFF + ((__x) - 1) * 0x8)
42e2cf992dSJorge Ramirez-Ortiz #define I2C_INP_VAL(__x)	(((__x) == 1) ? 0x1 : 0x2)
43e2cf992dSJorge Ramirez-Ortiz #define I2C_MUX_VAL(__x)	0x012
44e2cf992dSJorge Ramirez-Ortiz #define I2C_CFG_VAL(__x)	0x1b8b0
45e2cf992dSJorge Ramirez-Ortiz /* Clock */
46e2cf992dSJorge Ramirez-Ortiz #define I2C_CLK_CGRBM(__x)	BM_CCM_CCGR2_I2C##__x##_SERIAL
47*5729b44eSDevendra Devadiga #define I2C_CLK_CGR6BM(__x)	BM_CCM_CCGR6_I2C##__x##_SERIAL
48*5729b44eSDevendra Devadiga #define I2C_CLK_CGR(__x)	(((__x) == 4) ? CCM_CCGR6 : CCM_CCGR2)
49e2cf992dSJorge Ramirez-Ortiz #else
50e2cf992dSJorge Ramirez-Ortiz #error IMX_I2C driver not supported on this platform
51d156989aSJorge Ramirez-Ortiz #endif
52d156989aSJorge Ramirez-Ortiz 
53*5729b44eSDevendra Devadiga static struct io_pa_va i2c_bus[4] = {
54f8cb9adeSJorge Ramirez-Ortiz #if !defined(CFG_DT) || defined(CFG_EXTERNAL_DTB_OVERLAY)
558e58c34aSJorge Ramirez-Ortiz #if defined(I2C1_BASE)
568e58c34aSJorge Ramirez-Ortiz 	[0] = { .pa = I2C1_BASE, },
578e58c34aSJorge Ramirez-Ortiz #endif
588e58c34aSJorge Ramirez-Ortiz #if defined(I2C2_BASE)
598e58c34aSJorge Ramirez-Ortiz 	[1] = { .pa = I2C2_BASE, },
608e58c34aSJorge Ramirez-Ortiz #endif
618e58c34aSJorge Ramirez-Ortiz #if defined(I2C3_BASE)
628e58c34aSJorge Ramirez-Ortiz 	[2] = { .pa = I2C3_BASE, },
638e58c34aSJorge Ramirez-Ortiz #endif
64*5729b44eSDevendra Devadiga #if defined(I2C4_BASE)
65*5729b44eSDevendra Devadiga 	[3] = { .pa = I2C4_BASE, },
66*5729b44eSDevendra Devadiga #endif
676923dd89SJorge Ramirez-Ortiz #endif
6878b3ea9cSJorge Ramirez-Ortiz };
6978b3ea9cSJorge Ramirez-Ortiz 
7078b3ea9cSJorge Ramirez-Ortiz static struct imx_i2c_clk {
7178b3ea9cSJorge Ramirez-Ortiz 	struct io_pa_va base;
7278b3ea9cSJorge Ramirez-Ortiz 	uint32_t i2c[ARRAY_SIZE(i2c_bus)];
73d156989aSJorge Ramirez-Ortiz 	uint32_t cgrbm[ARRAY_SIZE(i2c_bus)];
7478b3ea9cSJorge Ramirez-Ortiz } i2c_clk = {
7578b3ea9cSJorge Ramirez-Ortiz 	.base.pa = CCM_BASE,
76*5729b44eSDevendra Devadiga 	.i2c = { I2C_CLK_CGR(1), I2C_CLK_CGR(2), I2C_CLK_CGR(3), I2C_CLK_CGR(4), },
77*5729b44eSDevendra Devadiga 	.cgrbm = { I2C_CLK_CGRBM(1), I2C_CLK_CGRBM(2), I2C_CLK_CGRBM(3), I2C_CLK_CGR6BM(4),},
7878b3ea9cSJorge Ramirez-Ortiz };
7978b3ea9cSJorge Ramirez-Ortiz 
8078b3ea9cSJorge Ramirez-Ortiz static struct imx_i2c_mux {
8178b3ea9cSJorge Ramirez-Ortiz 	struct io_pa_va base;
8278b3ea9cSJorge Ramirez-Ortiz 	struct imx_i2c_mux_regs {
8378b3ea9cSJorge Ramirez-Ortiz 		uint32_t scl_mux;
8478b3ea9cSJorge Ramirez-Ortiz 		uint32_t scl_cfg;
85d156989aSJorge Ramirez-Ortiz 		uint32_t scl_inp;
8678b3ea9cSJorge Ramirez-Ortiz 		uint32_t sda_mux;
8778b3ea9cSJorge Ramirez-Ortiz 		uint32_t sda_cfg;
88d156989aSJorge Ramirez-Ortiz 		uint32_t sda_inp;
8978b3ea9cSJorge Ramirez-Ortiz 	} i2c[ARRAY_SIZE(i2c_bus)];
9078b3ea9cSJorge Ramirez-Ortiz } i2c_mux = {
9178b3ea9cSJorge Ramirez-Ortiz 	.base.pa = IOMUXC_BASE,
9278b3ea9cSJorge Ramirez-Ortiz 	.i2c = {{ .scl_mux = I2C_MUX_SCL(1), .scl_cfg = I2C_CFG_SCL(1),
93d156989aSJorge Ramirez-Ortiz 		.scl_inp = I2C_INP_SCL(1), .sda_mux = I2C_MUX_SDA(1),
94d156989aSJorge Ramirez-Ortiz 		.sda_cfg = I2C_CFG_SDA(1), .sda_inp = I2C_INP_SDA(1), },
9578b3ea9cSJorge Ramirez-Ortiz 		{ .scl_mux = I2C_MUX_SCL(2), .scl_cfg = I2C_CFG_SCL(2),
96d156989aSJorge Ramirez-Ortiz 		.scl_inp = I2C_INP_SCL(2), .sda_mux = I2C_MUX_SDA(2),
97d156989aSJorge Ramirez-Ortiz 		.sda_cfg = I2C_CFG_SDA(2), .sda_inp = I2C_INP_SDA(2), },
9878b3ea9cSJorge Ramirez-Ortiz 		{ .scl_mux = I2C_MUX_SCL(3), .scl_cfg = I2C_CFG_SCL(3),
99d156989aSJorge Ramirez-Ortiz 		.scl_inp = I2C_INP_SCL(3), .sda_mux = I2C_MUX_SDA(3),
100*5729b44eSDevendra Devadiga 		.sda_cfg = I2C_CFG_SDA(3), .sda_inp = I2C_INP_SDA(3), },
101*5729b44eSDevendra Devadiga 		{ .scl_mux = I2C_MUX_SCL(4), .scl_cfg = I2C_CFG_SCL(4),
102*5729b44eSDevendra Devadiga 		.scl_inp = I2C_INP_SCL(4), .sda_mux = I2C_MUX_SDA(4),
103*5729b44eSDevendra Devadiga 		.sda_cfg = I2C_CFG_SDA(4), .sda_inp = I2C_INP_SDA(4), },},
10478b3ea9cSJorge Ramirez-Ortiz };
10578b3ea9cSJorge Ramirez-Ortiz 
10678b3ea9cSJorge Ramirez-Ortiz #define I2DR				0x10
10778b3ea9cSJorge Ramirez-Ortiz #define I2SR				0x0C
10878b3ea9cSJorge Ramirez-Ortiz #define I2CR				0x08
10978b3ea9cSJorge Ramirez-Ortiz #define IFDR				0x04
11078b3ea9cSJorge Ramirez-Ortiz 
11178b3ea9cSJorge Ramirez-Ortiz #define I2CR_IEN			BIT(7)
11278b3ea9cSJorge Ramirez-Ortiz #define I2CR_IIEN			BIT(6)
11378b3ea9cSJorge Ramirez-Ortiz #define I2CR_MSTA			BIT(5)
11478b3ea9cSJorge Ramirez-Ortiz #define I2CR_MTX			BIT(4)
11578b3ea9cSJorge Ramirez-Ortiz #define I2CR_TX_NO_AK			BIT(3)
11678b3ea9cSJorge Ramirez-Ortiz #define I2CR_RSTA			BIT(2)
11778b3ea9cSJorge Ramirez-Ortiz 
11878b3ea9cSJorge Ramirez-Ortiz #define I2SR_ICF			BIT(7)
11978b3ea9cSJorge Ramirez-Ortiz #define I2SR_IBB			BIT(5)
12078b3ea9cSJorge Ramirez-Ortiz #define I2SR_IAL			BIT(4)
12178b3ea9cSJorge Ramirez-Ortiz #define I2SR_IIF			BIT(1)
12278b3ea9cSJorge Ramirez-Ortiz #define I2SR_RX_NO_AK			BIT(0)
12378b3ea9cSJorge Ramirez-Ortiz 
12478b3ea9cSJorge Ramirez-Ortiz static uint8_t i2c_io_read8(uint8_t bid, uint32_t address)
12578b3ea9cSJorge Ramirez-Ortiz {
12678b3ea9cSJorge Ramirez-Ortiz 	return io_read8(i2c_bus[bid].va + address);
12778b3ea9cSJorge Ramirez-Ortiz }
12878b3ea9cSJorge Ramirez-Ortiz 
12978b3ea9cSJorge Ramirez-Ortiz static void i2c_io_write8(uint8_t bid, uint32_t address, uint8_t data)
13078b3ea9cSJorge Ramirez-Ortiz {
13178b3ea9cSJorge Ramirez-Ortiz 	return io_write8(i2c_bus[bid].va + address, data);
13278b3ea9cSJorge Ramirez-Ortiz }
13378b3ea9cSJorge Ramirez-Ortiz 
13478b3ea9cSJorge Ramirez-Ortiz static bool bus_is_idle(uint32_t sr)
13578b3ea9cSJorge Ramirez-Ortiz {
13678b3ea9cSJorge Ramirez-Ortiz 	return (sr & I2SR_IBB) == 0;
13778b3ea9cSJorge Ramirez-Ortiz }
13878b3ea9cSJorge Ramirez-Ortiz 
13978b3ea9cSJorge Ramirez-Ortiz static bool bus_is_busy(uint32_t sr)
14078b3ea9cSJorge Ramirez-Ortiz {
14178b3ea9cSJorge Ramirez-Ortiz 	return !bus_is_idle(sr);
14278b3ea9cSJorge Ramirez-Ortiz }
14378b3ea9cSJorge Ramirez-Ortiz 
14478b3ea9cSJorge Ramirez-Ortiz static bool isr_active(uint32_t sr)
14578b3ea9cSJorge Ramirez-Ortiz {
14678b3ea9cSJorge Ramirez-Ortiz 	return (sr & I2SR_IIF) == I2SR_IIF;
14778b3ea9cSJorge Ramirez-Ortiz }
14878b3ea9cSJorge Ramirez-Ortiz 
14978b3ea9cSJorge Ramirez-Ortiz static struct ifdr_pair {
15078b3ea9cSJorge Ramirez-Ortiz 	uint32_t divider;
15178b3ea9cSJorge Ramirez-Ortiz 	uint8_t prescaler;
15278b3ea9cSJorge Ramirez-Ortiz } ifdr_table[] = {
15378b3ea9cSJorge Ramirez-Ortiz 	{ 22,	0x20 }, { 24,	0x21 }, { 26,	0x22 }, { 28,	0x23 },
15478b3ea9cSJorge Ramirez-Ortiz 	{ 30,	0x00 }, { 32,	0x24 }, { 36,	0x25 }, { 40,	0x26 },
15578b3ea9cSJorge Ramirez-Ortiz 	{ 42,	0x03 }, { 44,	0x27 }, { 48,	0x28 }, { 52,	0x05 },
15678b3ea9cSJorge Ramirez-Ortiz 	{ 56,	0x29 }, { 60,	0x06 }, { 64,	0x2A }, { 72,	0x2B },
15778b3ea9cSJorge Ramirez-Ortiz 	{ 80,	0x2C }, { 88,	0x09 }, { 96,	0x2D }, { 104,	0x0A },
15878b3ea9cSJorge Ramirez-Ortiz 	{ 112,	0x2E }, { 128,	0x2F }, { 144,	0x0C }, { 160,	0x30 },
15978b3ea9cSJorge Ramirez-Ortiz 	{ 192,	0x31 }, { 224,	0x32 }, { 240,	0x0F }, { 256,	0x33 },
16078b3ea9cSJorge Ramirez-Ortiz 	{ 288,	0x10 }, { 320,	0x34 }, { 384,	0x35 }, { 448,	0x36 },
16178b3ea9cSJorge Ramirez-Ortiz 	{ 480,	0x13 }, { 512,	0x37 }, { 576,	0x14 }, { 640,	0x38 },
16278b3ea9cSJorge Ramirez-Ortiz 	{ 768,	0x39 }, { 896,	0x3A }, { 960,	0x17 }, { 1024,	0x3B },
16378b3ea9cSJorge Ramirez-Ortiz 	{ 1152,	0x18 }, { 1280,	0x3C }, { 1536,	0x3D }, { 1792,	0x3E },
16478b3ea9cSJorge Ramirez-Ortiz 	{ 1920,	0x1B }, { 2048,	0x3F }, { 2304,	0x1C }, { 2560,	0x1D },
16578b3ea9cSJorge Ramirez-Ortiz 	{ 3072,	0x1E }, { 3840,	0x1F }
16678b3ea9cSJorge Ramirez-Ortiz };
16778b3ea9cSJorge Ramirez-Ortiz 
16878b3ea9cSJorge Ramirez-Ortiz static void i2c_set_prescaler(uint8_t bid, uint32_t bps)
16978b3ea9cSJorge Ramirez-Ortiz {
17078b3ea9cSJorge Ramirez-Ortiz 	struct ifdr_pair *p = ifdr_table;
17178b3ea9cSJorge Ramirez-Ortiz 	struct ifdr_pair *q = p + ARRAY_SIZE(ifdr_table) - 1;
17278b3ea9cSJorge Ramirez-Ortiz 	uint32_t div = (I2C_CLK_RATE + bps - 1) / bps;
17378b3ea9cSJorge Ramirez-Ortiz 
17478b3ea9cSJorge Ramirez-Ortiz 	if (div < p->divider)
17578b3ea9cSJorge Ramirez-Ortiz 		q = p;
17678b3ea9cSJorge Ramirez-Ortiz 	else if (div > q->divider)
17778b3ea9cSJorge Ramirez-Ortiz 		p = q;
17878b3ea9cSJorge Ramirez-Ortiz 
17978b3ea9cSJorge Ramirez-Ortiz 	while (p != q) {
18078b3ea9cSJorge Ramirez-Ortiz 		if (div <= p->divider)
18178b3ea9cSJorge Ramirez-Ortiz 			break;
18278b3ea9cSJorge Ramirez-Ortiz 		p++;
18378b3ea9cSJorge Ramirez-Ortiz 	}
18478b3ea9cSJorge Ramirez-Ortiz 
18578b3ea9cSJorge Ramirez-Ortiz 	i2c_io_write8(bid, IFDR, p->prescaler);
18678b3ea9cSJorge Ramirez-Ortiz }
18778b3ea9cSJorge Ramirez-Ortiz 
18878b3ea9cSJorge Ramirez-Ortiz static void i2c_set_bus_speed(uint8_t bid, int bps)
18978b3ea9cSJorge Ramirez-Ortiz {
190d156989aSJorge Ramirez-Ortiz 	vaddr_t addr = i2c_clk.base.va;
191d156989aSJorge Ramirez-Ortiz 	uint32_t val = 0;
19278b3ea9cSJorge Ramirez-Ortiz 
193581b1e23SDavid Griego #if defined(CFG_MX8MM) || defined(CFG_MX8MQ)
194d156989aSJorge Ramirez-Ortiz 	addr += CCM_CCGRx_SET(i2c_clk.i2c[bid]);
195d156989aSJorge Ramirez-Ortiz 	val = CCM_CCGRx_ALWAYS_ON(0);
196d156989aSJorge Ramirez-Ortiz #elif defined(CFG_MX6ULL)
197d156989aSJorge Ramirez-Ortiz 	addr += i2c_clk.i2c[bid];
198d156989aSJorge Ramirez-Ortiz 	val = i2c_clk.cgrbm[bid] | io_read32(addr);
199e2cf992dSJorge Ramirez-Ortiz #else
200e2cf992dSJorge Ramirez-Ortiz #error IMX_I2C driver not supported on this platform
201d156989aSJorge Ramirez-Ortiz #endif
202d156989aSJorge Ramirez-Ortiz 	io_write32(addr, val);
20378b3ea9cSJorge Ramirez-Ortiz 	i2c_set_prescaler(bid, bps);
20478b3ea9cSJorge Ramirez-Ortiz }
20578b3ea9cSJorge Ramirez-Ortiz 
20678b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_sync_bus(uint8_t bid, bool (*match)(uint32_t),
20778b3ea9cSJorge Ramirez-Ortiz 			       uint32_t *status)
20878b3ea9cSJorge Ramirez-Ortiz {
20978b3ea9cSJorge Ramirez-Ortiz 	uint64_t tref = timeout_init_us(100000);
21078b3ea9cSJorge Ramirez-Ortiz 	uint32_t sr = 0;
21178b3ea9cSJorge Ramirez-Ortiz 
21278b3ea9cSJorge Ramirez-Ortiz 	while (!timeout_elapsed(tref)) {
21378b3ea9cSJorge Ramirez-Ortiz 		sr = i2c_io_read8(bid, I2SR);
21478b3ea9cSJorge Ramirez-Ortiz 		if (sr & I2SR_IAL) {
21578b3ea9cSJorge Ramirez-Ortiz 			EMSG("bus arbitration lost");
21678b3ea9cSJorge Ramirez-Ortiz 			i2c_io_write8(bid, I2SR, sr & ~I2SR_IAL);
21778b3ea9cSJorge Ramirez-Ortiz 			return TEE_ERROR_COMMUNICATION;
21878b3ea9cSJorge Ramirez-Ortiz 		}
21978b3ea9cSJorge Ramirez-Ortiz 		if ((*match)(sr)) {
22078b3ea9cSJorge Ramirez-Ortiz 			if (status)
22178b3ea9cSJorge Ramirez-Ortiz 				*status = sr;
22278b3ea9cSJorge Ramirez-Ortiz 			return TEE_SUCCESS;
22378b3ea9cSJorge Ramirez-Ortiz 		}
22478b3ea9cSJorge Ramirez-Ortiz 	}
22578b3ea9cSJorge Ramirez-Ortiz 
22678b3ea9cSJorge Ramirez-Ortiz 	return TEE_ERROR_BUSY;
22778b3ea9cSJorge Ramirez-Ortiz }
22878b3ea9cSJorge Ramirez-Ortiz 
22978b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_idle_bus(uint8_t bid)
23078b3ea9cSJorge Ramirez-Ortiz {
23178b3ea9cSJorge Ramirez-Ortiz 	uint8_t tmp = i2c_io_read8(bid, I2CR) & ~I2CR_MSTA;
23278b3ea9cSJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
23378b3ea9cSJorge Ramirez-Ortiz 
23478b3ea9cSJorge Ramirez-Ortiz 	i2c_io_write8(bid, I2CR, tmp);
23578b3ea9cSJorge Ramirez-Ortiz 	ret = i2c_sync_bus(bid, &bus_is_idle, NULL);
23678b3ea9cSJorge Ramirez-Ortiz 	i2c_io_write8(bid, I2SR, 0);
23778b3ea9cSJorge Ramirez-Ortiz 
23878b3ea9cSJorge Ramirez-Ortiz 	return ret;
23978b3ea9cSJorge Ramirez-Ortiz }
24078b3ea9cSJorge Ramirez-Ortiz 
24178b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_write_byte(uint8_t bid, uint8_t byte)
24278b3ea9cSJorge Ramirez-Ortiz {
24378b3ea9cSJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
24478b3ea9cSJorge Ramirez-Ortiz 	uint32_t status = 0;
24578b3ea9cSJorge Ramirez-Ortiz 
24678b3ea9cSJorge Ramirez-Ortiz 	i2c_io_write8(bid, I2DR, byte);
24778b3ea9cSJorge Ramirez-Ortiz 	ret = i2c_sync_bus(bid, &isr_active, &status);
24878b3ea9cSJorge Ramirez-Ortiz 	i2c_io_write8(bid, I2SR, 0);
24978b3ea9cSJorge Ramirez-Ortiz 
25014371509SJorge Ramirez-Ortiz 	if (!ret && (status & I2SR_RX_NO_AK))
25178b3ea9cSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_STATE;
25278b3ea9cSJorge Ramirez-Ortiz 
25378b3ea9cSJorge Ramirez-Ortiz 	return ret;
25478b3ea9cSJorge Ramirez-Ortiz }
25578b3ea9cSJorge Ramirez-Ortiz 
25678b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_read_byte(uint8_t bid, uint8_t *p)
25778b3ea9cSJorge Ramirez-Ortiz {
25878b3ea9cSJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
25978b3ea9cSJorge Ramirez-Ortiz 
26078b3ea9cSJorge Ramirez-Ortiz 	*p = i2c_io_read8(bid, I2DR);
26178b3ea9cSJorge Ramirez-Ortiz 	ret = i2c_sync_bus(bid, &isr_active, NULL);
26278b3ea9cSJorge Ramirez-Ortiz 	i2c_io_write8(bid, I2SR, 0);
26378b3ea9cSJorge Ramirez-Ortiz 
26478b3ea9cSJorge Ramirez-Ortiz 	return ret;
26578b3ea9cSJorge Ramirez-Ortiz }
26678b3ea9cSJorge Ramirez-Ortiz 
26778b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_write_data(uint8_t bid, const uint8_t *buf, int len)
26878b3ea9cSJorge Ramirez-Ortiz {
26978b3ea9cSJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
27078b3ea9cSJorge Ramirez-Ortiz 	uint32_t tmp = 0;
27178b3ea9cSJorge Ramirez-Ortiz 
27278b3ea9cSJorge Ramirez-Ortiz 	if (!len)
27378b3ea9cSJorge Ramirez-Ortiz 		return TEE_SUCCESS;
27478b3ea9cSJorge Ramirez-Ortiz 
27578b3ea9cSJorge Ramirez-Ortiz 	tmp = i2c_io_read8(bid, I2CR) | I2CR_MTX | I2CR_TX_NO_AK;
27678b3ea9cSJorge Ramirez-Ortiz 	i2c_io_write8(bid, I2CR, tmp);
27778b3ea9cSJorge Ramirez-Ortiz 
27878b3ea9cSJorge Ramirez-Ortiz 	while (len--) {
27978b3ea9cSJorge Ramirez-Ortiz 		ret = i2c_write_byte(bid, *buf++);
28014371509SJorge Ramirez-Ortiz 		if (ret)
28178b3ea9cSJorge Ramirez-Ortiz 			return ret;
28278b3ea9cSJorge Ramirez-Ortiz 	}
28378b3ea9cSJorge Ramirez-Ortiz 
28478b3ea9cSJorge Ramirez-Ortiz 	return ret;
28578b3ea9cSJorge Ramirez-Ortiz }
28678b3ea9cSJorge Ramirez-Ortiz 
28778b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_read_data(uint8_t bid, uint8_t *buf, int len)
28878b3ea9cSJorge Ramirez-Ortiz {
28978b3ea9cSJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
29078b3ea9cSJorge Ramirez-Ortiz 	uint8_t dummy = 0;
29178b3ea9cSJorge Ramirez-Ortiz 	uint32_t tmp = 0;
29278b3ea9cSJorge Ramirez-Ortiz 
29378b3ea9cSJorge Ramirez-Ortiz 	if (!len)
29478b3ea9cSJorge Ramirez-Ortiz 		return TEE_SUCCESS;
29578b3ea9cSJorge Ramirez-Ortiz 
29678b3ea9cSJorge Ramirez-Ortiz 	tmp = i2c_io_read8(bid, I2CR) & ~I2CR_MTX;
29778b3ea9cSJorge Ramirez-Ortiz 	tmp = (len == 1) ? tmp | I2CR_TX_NO_AK : tmp & ~I2CR_TX_NO_AK;
29878b3ea9cSJorge Ramirez-Ortiz 	i2c_io_write8(bid, I2CR, tmp);
29978b3ea9cSJorge Ramirez-Ortiz 	i2c_io_read8(bid, I2DR);
30078b3ea9cSJorge Ramirez-Ortiz 
30178b3ea9cSJorge Ramirez-Ortiz 	ret = i2c_read_byte(bid, &dummy);
30214371509SJorge Ramirez-Ortiz 	if (ret)
30378b3ea9cSJorge Ramirez-Ortiz 		return ret;
30478b3ea9cSJorge Ramirez-Ortiz 
30578b3ea9cSJorge Ramirez-Ortiz 	/*
30678b3ea9cSJorge Ramirez-Ortiz 	 * A data transfer ends when the master signals a stop; for a master
30778b3ea9cSJorge Ramirez-Ortiz 	 * receiver to terminate a transfer it must inform the slave transmiter
30878b3ea9cSJorge Ramirez-Ortiz 	 * by not acknowledging the last data byte. This is done by setting the
30978b3ea9cSJorge Ramirez-Ortiz 	 * transmit acknowledge bit before reading the next-to-last byte.
31078b3ea9cSJorge Ramirez-Ortiz 	 */
31178b3ea9cSJorge Ramirez-Ortiz 	do {
31278b3ea9cSJorge Ramirez-Ortiz 		if (len == 2) {
31378b3ea9cSJorge Ramirez-Ortiz 			tmp = i2c_io_read8(bid, I2CR) | I2CR_TX_NO_AK;
31478b3ea9cSJorge Ramirez-Ortiz 			i2c_io_write8(bid, I2CR, tmp);
31578b3ea9cSJorge Ramirez-Ortiz 		}
31678b3ea9cSJorge Ramirez-Ortiz 
31778b3ea9cSJorge Ramirez-Ortiz 		ret = i2c_read_byte(bid, buf++);
31814371509SJorge Ramirez-Ortiz 		if (ret)
31978b3ea9cSJorge Ramirez-Ortiz 			return ret;
32078b3ea9cSJorge Ramirez-Ortiz 	} while (len--);
32178b3ea9cSJorge Ramirez-Ortiz 
32278b3ea9cSJorge Ramirez-Ortiz 	return ret;
32378b3ea9cSJorge Ramirez-Ortiz }
32478b3ea9cSJorge Ramirez-Ortiz 
32578b3ea9cSJorge Ramirez-Ortiz static TEE_Result i2c_init_transfer(uint8_t bid, uint8_t chip)
32678b3ea9cSJorge Ramirez-Ortiz {
32778b3ea9cSJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
32878b3ea9cSJorge Ramirez-Ortiz 	uint32_t tmp = 0;
32978b3ea9cSJorge Ramirez-Ortiz 
33078b3ea9cSJorge Ramirez-Ortiz 	ret = i2c_idle_bus(bid);
33114371509SJorge Ramirez-Ortiz 	if (ret)
33278b3ea9cSJorge Ramirez-Ortiz 		return ret;
33378b3ea9cSJorge Ramirez-Ortiz 
33478b3ea9cSJorge Ramirez-Ortiz 	/* Enable the interface */
33578b3ea9cSJorge Ramirez-Ortiz 	i2c_io_write8(bid, I2CR, I2CR_IEN);
33678b3ea9cSJorge Ramirez-Ortiz 
33778b3ea9cSJorge Ramirez-Ortiz 	tmp = i2c_io_read8(bid, I2CR) | I2CR_MSTA;
33878b3ea9cSJorge Ramirez-Ortiz 	i2c_io_write8(bid, I2CR, tmp);
33978b3ea9cSJorge Ramirez-Ortiz 
34078b3ea9cSJorge Ramirez-Ortiz 	/* Wait until the bus is active */
34178b3ea9cSJorge Ramirez-Ortiz 	ret = i2c_sync_bus(bid, &bus_is_busy, NULL);
34214371509SJorge Ramirez-Ortiz 	if (ret)
34378b3ea9cSJorge Ramirez-Ortiz 		return ret;
34478b3ea9cSJorge Ramirez-Ortiz 
34578b3ea9cSJorge Ramirez-Ortiz 	/* Slave address on the bus */
34678b3ea9cSJorge Ramirez-Ortiz 	return i2c_write_data(bid, &chip, 1);
34778b3ea9cSJorge Ramirez-Ortiz }
34878b3ea9cSJorge Ramirez-Ortiz 
34978b3ea9cSJorge Ramirez-Ortiz TEE_Result imx_i2c_read(uint8_t bid, uint8_t chip, uint8_t *buf, int len)
35078b3ea9cSJorge Ramirez-Ortiz {
35178b3ea9cSJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
35278b3ea9cSJorge Ramirez-Ortiz 
35378b3ea9cSJorge Ramirez-Ortiz 	if (bid >= ARRAY_SIZE(i2c_bus))
35478b3ea9cSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
35578b3ea9cSJorge Ramirez-Ortiz 
35678b3ea9cSJorge Ramirez-Ortiz 	if ((len && !buf) || chip > 0x7F)
35778b3ea9cSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
35878b3ea9cSJorge Ramirez-Ortiz 
3598e58c34aSJorge Ramirez-Ortiz 	if (!i2c_bus[bid].va)
3608e58c34aSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
3618e58c34aSJorge Ramirez-Ortiz 
36278b3ea9cSJorge Ramirez-Ortiz 	ret = i2c_init_transfer(bid, chip << 1 | BIT(0));
36314371509SJorge Ramirez-Ortiz 	if (!ret)
36478b3ea9cSJorge Ramirez-Ortiz 		ret = i2c_read_data(bid, buf, len);
36578b3ea9cSJorge Ramirez-Ortiz 
36614371509SJorge Ramirez-Ortiz 	if (i2c_idle_bus(bid))
36778b3ea9cSJorge Ramirez-Ortiz 		IMSG("bus not idle");
36878b3ea9cSJorge Ramirez-Ortiz 
36978b3ea9cSJorge Ramirez-Ortiz 	return ret;
37078b3ea9cSJorge Ramirez-Ortiz }
37178b3ea9cSJorge Ramirez-Ortiz 
37278b3ea9cSJorge Ramirez-Ortiz TEE_Result imx_i2c_write(uint8_t bid, uint8_t chip, const uint8_t *buf, int len)
37378b3ea9cSJorge Ramirez-Ortiz {
37478b3ea9cSJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
37578b3ea9cSJorge Ramirez-Ortiz 
37678b3ea9cSJorge Ramirez-Ortiz 	if (bid >= ARRAY_SIZE(i2c_bus))
37778b3ea9cSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
37878b3ea9cSJorge Ramirez-Ortiz 
37978b3ea9cSJorge Ramirez-Ortiz 	if ((len && !buf) || chip > 0x7F)
38078b3ea9cSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
38178b3ea9cSJorge Ramirez-Ortiz 
3828e58c34aSJorge Ramirez-Ortiz 	if (!i2c_bus[bid].va)
3838e58c34aSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
3848e58c34aSJorge Ramirez-Ortiz 
38578b3ea9cSJorge Ramirez-Ortiz 	ret = i2c_init_transfer(bid, chip << 1);
38614371509SJorge Ramirez-Ortiz 	if (!ret)
38778b3ea9cSJorge Ramirez-Ortiz 		ret = i2c_write_data(bid, buf, len);
38878b3ea9cSJorge Ramirez-Ortiz 
38914371509SJorge Ramirez-Ortiz 	if (i2c_idle_bus(bid))
39078b3ea9cSJorge Ramirez-Ortiz 		IMSG("bus not idle");
39178b3ea9cSJorge Ramirez-Ortiz 
39278b3ea9cSJorge Ramirez-Ortiz 	return ret;
39378b3ea9cSJorge Ramirez-Ortiz }
39478b3ea9cSJorge Ramirez-Ortiz 
39578b3ea9cSJorge Ramirez-Ortiz TEE_Result imx_i2c_probe(uint8_t bid, uint8_t chip)
39678b3ea9cSJorge Ramirez-Ortiz {
39778b3ea9cSJorge Ramirez-Ortiz 	if (bid >= ARRAY_SIZE(i2c_bus))
39878b3ea9cSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
39978b3ea9cSJorge Ramirez-Ortiz 
4008e58c34aSJorge Ramirez-Ortiz 	if (!i2c_bus[bid].va)
4018e58c34aSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
4028e58c34aSJorge Ramirez-Ortiz 
40378b3ea9cSJorge Ramirez-Ortiz 	if (chip > 0x7F)
40478b3ea9cSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
40578b3ea9cSJorge Ramirez-Ortiz 
40678b3ea9cSJorge Ramirez-Ortiz 	return imx_i2c_write(bid, chip, NULL, 0);
40778b3ea9cSJorge Ramirez-Ortiz }
40878b3ea9cSJorge Ramirez-Ortiz 
40978b3ea9cSJorge Ramirez-Ortiz /*
41078b3ea9cSJorge Ramirez-Ortiz  * I2C bus initialization: configure the IOMUX and enable the clock.
411*5729b44eSDevendra Devadiga  * @bid: Bus ID: (0=I2C1), (1=I2C2), (2=I2C3), (3=I2C4).
41278b3ea9cSJorge Ramirez-Ortiz  * @bps: Bus baud rate, in bits per second.
41378b3ea9cSJorge Ramirez-Ortiz  */
41478b3ea9cSJorge Ramirez-Ortiz TEE_Result imx_i2c_init(uint8_t bid, int bps)
41578b3ea9cSJorge Ramirez-Ortiz {
41678b3ea9cSJorge Ramirez-Ortiz 	struct imx_i2c_mux *mux = &i2c_mux;
41778b3ea9cSJorge Ramirez-Ortiz 
41878b3ea9cSJorge Ramirez-Ortiz 	if (bid >= ARRAY_SIZE(i2c_bus))
41978b3ea9cSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
42078b3ea9cSJorge Ramirez-Ortiz 
42178b3ea9cSJorge Ramirez-Ortiz 	if (!bps)
42278b3ea9cSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
42378b3ea9cSJorge Ramirez-Ortiz 
4248e58c34aSJorge Ramirez-Ortiz 	if (!i2c_bus[bid].va)
4258e58c34aSJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
4268e58c34aSJorge Ramirez-Ortiz 
42778b3ea9cSJorge Ramirez-Ortiz 	io_write32(mux->base.va + mux->i2c[bid].scl_mux, I2C_MUX_VAL(bid));
42878b3ea9cSJorge Ramirez-Ortiz 	io_write32(mux->base.va + mux->i2c[bid].scl_cfg, I2C_CFG_VAL(bid));
429d156989aSJorge Ramirez-Ortiz 	if (mux->i2c[bid].scl_inp)
430d156989aSJorge Ramirez-Ortiz 		io_write32(mux->base.va + mux->i2c[bid].scl_inp,
431e2cf992dSJorge Ramirez-Ortiz 			   I2C_INP_VAL(bid + 1));
432d156989aSJorge Ramirez-Ortiz 
43378b3ea9cSJorge Ramirez-Ortiz 	io_write32(mux->base.va + mux->i2c[bid].sda_mux, I2C_MUX_VAL(bid));
43478b3ea9cSJorge Ramirez-Ortiz 	io_write32(mux->base.va + mux->i2c[bid].sda_cfg, I2C_CFG_VAL(bid));
435d156989aSJorge Ramirez-Ortiz 	if (mux->i2c[bid].sda_inp)
436d156989aSJorge Ramirez-Ortiz 		io_write32(mux->base.va + mux->i2c[bid].sda_inp,
437e2cf992dSJorge Ramirez-Ortiz 			   I2C_INP_VAL(bid + 1));
43878b3ea9cSJorge Ramirez-Ortiz 
43978b3ea9cSJorge Ramirez-Ortiz 	/* Baud rate in bits per second */
44078b3ea9cSJorge Ramirez-Ortiz 	i2c_set_bus_speed(bid, bps);
44178b3ea9cSJorge Ramirez-Ortiz 
44278b3ea9cSJorge Ramirez-Ortiz 	return TEE_SUCCESS;
44378b3ea9cSJorge Ramirez-Ortiz }
44478b3ea9cSJorge Ramirez-Ortiz 
44578b3ea9cSJorge Ramirez-Ortiz static TEE_Result get_va(paddr_t pa, vaddr_t *va)
44678b3ea9cSJorge Ramirez-Ortiz {
447bc9618c0SAnton Rybakov 	*va = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, pa, 0x10000);
448bc9618c0SAnton Rybakov 	if (!*va)
44978b3ea9cSJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
45078b3ea9cSJorge Ramirez-Ortiz 
45178b3ea9cSJorge Ramirez-Ortiz 	return TEE_SUCCESS;
45278b3ea9cSJorge Ramirez-Ortiz }
45378b3ea9cSJorge Ramirez-Ortiz 
454f8cb9adeSJorge Ramirez-Ortiz #if defined(CFG_DT) && !defined(CFG_EXTERNAL_DTB_OVERLAY)
4556923dd89SJorge Ramirez-Ortiz static const char *const dt_i2c_match_table[] = {
4566923dd89SJorge Ramirez-Ortiz 	"fsl,imx21-i2c",
4576923dd89SJorge Ramirez-Ortiz };
4586923dd89SJorge Ramirez-Ortiz 
4596923dd89SJorge Ramirez-Ortiz static TEE_Result i2c_mapped(const char *i2c_match)
46078b3ea9cSJorge Ramirez-Ortiz {
4616923dd89SJorge Ramirez-Ortiz 	TEE_Result ret = TEE_ERROR_GENERIC;
4626923dd89SJorge Ramirez-Ortiz 	void *fdt = get_dt();
4636923dd89SJorge Ramirez-Ortiz 	size_t size = 0;
4646923dd89SJorge Ramirez-Ortiz 	size_t i = 0;
4656923dd89SJorge Ramirez-Ortiz 	int off = 0;
4666923dd89SJorge Ramirez-Ortiz 
4676923dd89SJorge Ramirez-Ortiz 	if (!fdt)
4686923dd89SJorge Ramirez-Ortiz 		return TEE_ERROR_NOT_SUPPORTED;
4696923dd89SJorge Ramirez-Ortiz 
4706923dd89SJorge Ramirez-Ortiz 	for (i = 0; i < ARRAY_SIZE(i2c_bus); i++) {
4716923dd89SJorge Ramirez-Ortiz 		off = fdt_node_offset_by_compatible(fdt, off, i2c_match);
4726923dd89SJorge Ramirez-Ortiz 		if (off < 0)
4736923dd89SJorge Ramirez-Ortiz 			break;
4746923dd89SJorge Ramirez-Ortiz 
4756923dd89SJorge Ramirez-Ortiz 		if (!(_fdt_get_status(fdt, off) & DT_STATUS_OK_SEC)) {
4766923dd89SJorge Ramirez-Ortiz 			EMSG("i2c%zu not enabled", i + 1);
4776923dd89SJorge Ramirez-Ortiz 			continue;
4786923dd89SJorge Ramirez-Ortiz 		}
4796923dd89SJorge Ramirez-Ortiz 
4806923dd89SJorge Ramirez-Ortiz 		if (dt_map_dev(fdt, off, &i2c_bus[i].va, &size) < 0) {
4816923dd89SJorge Ramirez-Ortiz 			EMSG("i2c%zu not enabled", i + 1);
4826923dd89SJorge Ramirez-Ortiz 			continue;
4836923dd89SJorge Ramirez-Ortiz 		}
4846923dd89SJorge Ramirez-Ortiz 
4856923dd89SJorge Ramirez-Ortiz 		i2c_bus[i].pa = virt_to_phys((void *)i2c_bus[i].va);
4866923dd89SJorge Ramirez-Ortiz 		ret = TEE_SUCCESS;
4876923dd89SJorge Ramirez-Ortiz 	}
4886923dd89SJorge Ramirez-Ortiz 
4896923dd89SJorge Ramirez-Ortiz 	return ret;
4906923dd89SJorge Ramirez-Ortiz }
4916923dd89SJorge Ramirez-Ortiz 
4926923dd89SJorge Ramirez-Ortiz static TEE_Result i2c_map_controller(void)
4936923dd89SJorge Ramirez-Ortiz {
4946923dd89SJorge Ramirez-Ortiz 	TEE_Result ret = TEE_ERROR_GENERIC;
4956923dd89SJorge Ramirez-Ortiz 	size_t i = 0;
4966923dd89SJorge Ramirez-Ortiz 
4976923dd89SJorge Ramirez-Ortiz 	for (i = 0; i < ARRAY_SIZE(dt_i2c_match_table); i++) {
4986923dd89SJorge Ramirez-Ortiz 		ret = i2c_mapped(dt_i2c_match_table[i]);
4996923dd89SJorge Ramirez-Ortiz 		if (!ret || ret == TEE_ERROR_NOT_SUPPORTED)
5006923dd89SJorge Ramirez-Ortiz 			return ret;
5016923dd89SJorge Ramirez-Ortiz 	}
5026923dd89SJorge Ramirez-Ortiz 
5036923dd89SJorge Ramirez-Ortiz 	return ret;
5046923dd89SJorge Ramirez-Ortiz }
5056923dd89SJorge Ramirez-Ortiz #else
5066923dd89SJorge Ramirez-Ortiz static TEE_Result i2c_map_controller(void)
5076923dd89SJorge Ramirez-Ortiz {
5086923dd89SJorge Ramirez-Ortiz 	TEE_Result ret = TEE_ERROR_GENERIC;
50978b3ea9cSJorge Ramirez-Ortiz 	size_t n = 0;
51078b3ea9cSJorge Ramirez-Ortiz 
5116923dd89SJorge Ramirez-Ortiz 	for (n = 0; n < ARRAY_SIZE(i2c_bus); n++) {
5126923dd89SJorge Ramirez-Ortiz 		if (i2c_bus[n].pa) {
5136923dd89SJorge Ramirez-Ortiz 			if (get_va(i2c_bus[n].pa, &i2c_bus[n].va))
5146923dd89SJorge Ramirez-Ortiz 				EMSG("i2c%zu not enabled", n + 1);
5156923dd89SJorge Ramirez-Ortiz 			else
5166923dd89SJorge Ramirez-Ortiz 				ret = TEE_SUCCESS;
5176923dd89SJorge Ramirez-Ortiz 		} else {
5186923dd89SJorge Ramirez-Ortiz 			IMSG("i2c%zu not enabled", n + 1);
5196923dd89SJorge Ramirez-Ortiz 		}
5206923dd89SJorge Ramirez-Ortiz 	}
5216923dd89SJorge Ramirez-Ortiz 
5226923dd89SJorge Ramirez-Ortiz 	return ret;
5236923dd89SJorge Ramirez-Ortiz }
524f8cb9adeSJorge Ramirez-Ortiz #endif
5256923dd89SJorge Ramirez-Ortiz 
5266923dd89SJorge Ramirez-Ortiz static TEE_Result i2c_init(void)
5276923dd89SJorge Ramirez-Ortiz {
52814371509SJorge Ramirez-Ortiz 	if (get_va(i2c_clk.base.pa, &i2c_clk.base.va))
52978b3ea9cSJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
53078b3ea9cSJorge Ramirez-Ortiz 
53114371509SJorge Ramirez-Ortiz 	if (get_va(i2c_mux.base.pa, &i2c_mux.base.va))
53278b3ea9cSJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
53378b3ea9cSJorge Ramirez-Ortiz 
5346923dd89SJorge Ramirez-Ortiz 	return i2c_map_controller();
53578b3ea9cSJorge Ramirez-Ortiz }
53678b3ea9cSJorge Ramirez-Ortiz 
537db0683faSJorge Ramirez-Ortiz early_init(i2c_init);
538