MAINTAINERS: Add Yuchi and Vasiliy for Intel Atom Snow Ridge SoC
[coreboot.git] / src / soc / qualcomm / ipq806x / i2c.c
blobcce7ed94c7629f6d0370a649dbfab426e8b655b5
1 /* SPDX-License-Identifier: BSD-3-Clause */
3 #include <console/console.h>
4 #include <device/i2c_simple.h>
5 #include <string.h>
6 #include <soc/gsbi.h>
7 #include <soc/qup.h>
9 static qup_config_t gsbi1_qup_config = {
10 QUP_MINICORE_I2C_MASTER,
11 100000,
12 24000000,
13 QUP_MODE_FIFO,
17 static qup_config_t gsbi4_qup_config = {
18 QUP_MINICORE_I2C_MASTER,
19 100000,
20 24000000,
21 QUP_MODE_FIFO,
25 static qup_config_t gsbi7_qup_config = {
26 QUP_MINICORE_I2C_MASTER,
27 100000,
28 24000000,
29 QUP_MODE_FIFO,
33 static int i2c_read(uint32_t gsbi_id, uint8_t slave,
34 uint8_t *data, int data_len)
36 qup_data_t obj;
37 qup_return_t qup_ret = 0;
39 memset(&obj, 0, sizeof(obj));
40 obj.protocol = QUP_MINICORE_I2C_MASTER;
41 obj.p.iic.addr = slave;
42 obj.p.iic.data_len = data_len;
43 obj.p.iic.data = data;
44 qup_ret = qup_recv_data(gsbi_id, &obj);
46 if (QUP_SUCCESS != qup_ret)
47 return 1;
48 else
49 return 0;
52 static int i2c_write(uint32_t gsbi_id, uint8_t slave,
53 uint8_t *data, int data_len, uint8_t stop_seq)
55 qup_data_t obj;
56 qup_return_t qup_ret = 0;
58 memset(&obj, 0, sizeof(obj));
59 obj.protocol = QUP_MINICORE_I2C_MASTER;
60 obj.p.iic.addr = slave;
61 obj.p.iic.data_len = data_len;
62 obj.p.iic.data = data;
63 qup_ret = qup_send_data(gsbi_id, &obj, stop_seq);
65 if (QUP_SUCCESS != qup_ret)
66 return 1;
67 else
68 return 0;
71 static int i2c_init(unsigned int bus)
73 unsigned int gsbi_id = bus;
74 qup_config_t *qup_config;
76 switch (gsbi_id) {
77 case GSBI_ID_1:
78 qup_config = &gsbi1_qup_config;
79 break;
80 case GSBI_ID_4:
81 qup_config = &gsbi4_qup_config;
82 break;
83 case GSBI_ID_7:
84 qup_config = &gsbi7_qup_config;
85 break;
86 default:
87 printk(BIOS_ERR, "QUP configuration not defined for GSBI%d.\n",
88 gsbi_id);
89 return 1;
92 if (qup_config->initialized)
93 return 0;
95 if (gsbi_init(gsbi_id, GSBI_PROTO_I2C_ONLY)) {
96 printk(BIOS_ERR, "failed to initialize gsbi\n");
97 return 1;
100 if (qup_init(gsbi_id, qup_config)) {
101 printk(BIOS_ERR, "failed to initialize qup\n");
102 return 1;
105 if (qup_reset_i2c_master_status(gsbi_id)) {
106 printk(BIOS_ERR, "failed to reset i2c master status\n");
107 return 1;
110 qup_config->initialized = 1;
111 return 0;
114 int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments,
115 int seg_count)
117 struct i2c_msg *seg = segments;
118 int ret = 0;
120 if (i2c_init(bus))
121 return 1;
123 while (!ret && seg_count--) {
124 if (seg->flags & I2C_M_RD)
125 ret = i2c_read(bus, seg->slave, seg->buf, seg->len);
126 else
127 ret = i2c_write(bus, seg->slave, seg->buf, seg->len,
128 (seg_count ? 0 : 1));
129 seg++;
132 if (ret) {
133 qup_set_state(bus, QUP_STATE_RESET);
134 return 1;
137 return 0;