blob: 85af6e4a856fc807179745c54711d7396d9f87fb [file] [log] [blame]
Patrick Georgi70517072020-05-10 18:47:05 +02001/* SPDX-License-Identifier: BSD-3-Clause */
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +05302
3#include <assert.h>
4#include <console/console.h>
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +05305#include <device/i2c_simple.h>
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +05306#include <string.h>
7#include <soc/blsp.h>
8#include <soc/qup.h>
9#include <soc/gpio.h>
10
11static qup_config_t blsp1_qup0_config = {
12 QUP_MINICORE_I2C_MASTER,
13 400000,
14 19200000,
15 QUP_MODE_BLOCK,
16 0
17};
18
19static qup_config_t blsp1_qup1_config = {
20 QUP_MINICORE_I2C_MASTER,
21 400000,
22 19200000,
23 QUP_MODE_BLOCK,
24 0
25};
26
27static qup_config_t blsp1_qup2_config = {
28 QUP_MINICORE_I2C_MASTER,
29 400000,
30 19200000,
31 QUP_MODE_BLOCK,
32 0
33};
34
35static qup_config_t blsp1_qup3_config = {
36 QUP_MINICORE_I2C_MASTER,
37 400000,
38 19200000,
39 QUP_MODE_BLOCK,
40 0
41};
42
43static int i2c_read(uint32_t gsbi_id, uint8_t slave,
44 uint8_t *data, int data_len)
45{
46 qup_data_t obj;
47 qup_return_t qup_ret = 0;
48
49 memset(&obj, 0, sizeof(obj));
50 obj.protocol = QUP_MINICORE_I2C_MASTER;
51 obj.p.iic.addr = slave;
52 obj.p.iic.data_len = data_len;
53 obj.p.iic.data = data;
54 qup_ret = qup_recv_data(gsbi_id, &obj);
55
56 if (qup_ret != QUP_SUCCESS)
57 return 1;
58 else
59 return 0;
60}
61
62static int i2c_write(uint32_t gsbi_id, uint8_t slave,
63 uint8_t *data, int data_len, uint8_t stop_seq)
64{
65 qup_data_t obj;
66 qup_return_t qup_ret = 0;
67
68 memset(&obj, 0, sizeof(obj));
69 obj.protocol = QUP_MINICORE_I2C_MASTER;
70 obj.p.iic.addr = slave;
71 obj.p.iic.data_len = data_len;
72 obj.p.iic.data = data;
73 qup_ret = qup_send_data(gsbi_id, &obj, stop_seq);
74
75 if (qup_ret != QUP_SUCCESS)
76 return 1;
77 else
78 return 0;
79}
80
81static int i2c_init(blsp_qup_id_t id)
82{
83 qup_config_t *qup_config;
84
85 switch (id) {
86 case BLSP_QUP_ID_0:
87 qup_config = &blsp1_qup0_config;
88 break;
89 case BLSP_QUP_ID_1:
90 qup_config = &blsp1_qup1_config;
91 break;
92 case BLSP_QUP_ID_2:
93 qup_config = &blsp1_qup2_config;
94 break;
95 case BLSP_QUP_ID_3:
96 qup_config = &blsp1_qup3_config;
97 break;
98 default:
99 printk(BIOS_ERR, "QUP configuration not defined for BLSP%d.\n",
100 id);
101 return 1;
102 }
103
104 if (qup_config->initialized)
105 return 0;
106
107 if (blsp_i2c_init(id)) {
108 printk(BIOS_ERR, "failed to initialize blsp\n");
109 return 1;
110 }
111
112 if (qup_init(id, qup_config)) {
113 printk(BIOS_ERR, "failed to initialize qup\n");
114 return 1;
115 }
116
117 if (qup_reset_i2c_master_status(id)) {
118 printk(BIOS_ERR, "failed to reset i2c master status\n");
119 return 1;
120 }
121
122 qup_config->initialized = 1;
123 return 0;
124}
125
126int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments,
127 int seg_count)
128{
129 struct i2c_msg *seg = segments;
130 int ret = 0;
131
132 if (i2c_init(bus))
133 return 1;
134
135 while (!ret && seg_count--) {
136 if (seg->flags & I2C_M_RD)
137 ret = i2c_read(bus, seg->slave, seg->buf, seg->len);
138 else
139 ret = i2c_write(bus, seg->slave, seg->buf, seg->len,
140 (seg_count ? 0 : 1));
141 seg++;
142 }
143
144 if (ret) {
145 qup_set_state(bus, QUP_STATE_RESET);
146 return 1;
147 }
148
149 return 0;
150}