Commit | Line | Data |
---|---|---|
81dee67e SM |
1 | /******************************************************************* |
2 | * | |
3 | * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) | |
4 | * | |
5 | * All rights are reserved. Reproduction or in part is prohibited | |
6 | * without the written consent of the copyright owner. | |
7 | * | |
8 | * swi2c.c --- SM750/SM718 DDK | |
9 | * This file contains the source code for I2C using software | |
10 | * implementation. | |
11 | * | |
12 | *******************************************************************/ | |
13 | #include "ddk750_help.h" | |
14 | #include "ddk750_reg.h" | |
15 | #include "ddk750_swi2c.h" | |
16 | #include "ddk750_power.h" | |
17 | ||
81dee67e SM |
18 | /******************************************************************* |
19 | * I2C Software Master Driver: | |
20 | * =========================== | |
21 | * Each i2c cycle is split into 4 sections. Each of these section marks | |
22 | * a point in time where the SCL or SDA may be changed. | |
23 | * | |
24 | * 1 Cycle == | Section I. | Section 2. | Section 3. | Section 4. | | |
25 | * +-------------+-------------+-------------+-------------+ | |
26 | * | SCL set LOW |SCL no change| SCL set HIGH|SCL no change| | |
27 | * | |
28 | * ____________ _____________ | |
29 | * SCL == XXXX _____________ ____________ / | |
30 | * | |
31 | * I.e. the SCL may only be changed in section 1. and section 3. while | |
32 | * the SDA may only be changed in section 2. and section 4. The table | |
33 | * below gives the changes for these 2 lines in the varios sections. | |
34 | * | |
35 | * Section changes Table: | |
36 | * ====================== | |
37 | * blank = no change, L = set bit LOW, H = set bit HIGH | |
38 | * | |
39 | * | 1.| 2.| 3.| 4.| | |
40 | * ---------------+---+---+---+---+ | |
41 | * Tx Start SDA | | H | | L | | |
42 | * SCL | L | | H | | | |
43 | * ---------------+---+---+---+---+ | |
44 | * Tx Stop SDA | | L | | H | | |
45 | * SCL | L | | H | | | |
46 | * ---------------+---+---+---+---+ | |
47 | * Tx bit H SDA | | H | | | | |
48 | * SCL | L | | H | | | |
49 | * ---------------+---+---+---+---+ | |
50 | * Tx bit L SDA | | L | | | | |
51 | * SCL | L | | H | | | |
52 | * ---------------+---+---+---+---+ | |
53 | * | |
54 | ******************************************************************/ | |
55 | ||
56 | /* GPIO pins used for this I2C. It ranges from 0 to 63. */ | |
53bc6b6e MR |
57 | static unsigned char sw_i2c_clk_gpio = DEFAULT_I2C_SCL; |
58 | static unsigned char sw_i2c_data_gpio = DEFAULT_I2C_SDA; | |
81dee67e SM |
59 | |
60 | /* | |
61 | * Below is the variable declaration for the GPIO pin register usage | |
62 | * for the i2c Clock and i2c Data. | |
63 | * | |
64 | * Note: | |
65 | * Notice that the GPIO usage for the i2c clock and i2c Data are | |
66 | * separated. This is to make this code flexible enough when | |
67 | * two separate GPIO pins for the clock and data are located | |
68 | * in two different GPIO register set (worst case). | |
69 | */ | |
70 | ||
71 | /* i2c Clock GPIO Register usage */ | |
53bc6b6e MR |
72 | static unsigned long sw_i2c_clk_gpio_mux_reg = GPIO_MUX; |
73 | static unsigned long sw_i2c_clk_gpio_data_reg = GPIO_DATA; | |
74 | static unsigned long sw_i2c_clk_gpio_data_dir_reg = GPIO_DATA_DIRECTION; | |
81dee67e SM |
75 | |
76 | /* i2c Data GPIO Register usage */ | |
53bc6b6e MR |
77 | static unsigned long sw_i2c_data_gpio_mux_reg = GPIO_MUX; |
78 | static unsigned long sw_i2c_data_gpio_data_reg = GPIO_DATA; | |
79 | static unsigned long sw_i2c_data_gpio_data_dir_reg = GPIO_DATA_DIRECTION; | |
81dee67e | 80 | |
81dee67e SM |
81 | /* |
82 | * This function puts a delay between command | |
83 | */ | |
6c78f4ce | 84 | static void sw_i2c_wait(void) |
81dee67e SM |
85 | { |
86 | /* find a bug: | |
87 | * peekIO method works well before suspend/resume | |
88 | * but after suspend, peekIO(0x3ce,0x61) & 0x10 | |
89 | * always be non-zero,which makes the while loop | |
90 | * never finish. | |
91 | * use non-ultimate for loop below is safe | |
92 | * */ | |
1282bade | 93 | |
81dee67e SM |
94 | /* Change wait algorithm to use PCI bus clock, |
95 | it's more reliable than counter loop .. | |
96 | write 0x61 to 0x3ce and read from 0x3cf | |
97 | */ | |
fe820044 | 98 | int i, tmp; |
81dee67e | 99 | |
6bdee8bd | 100 | for (i = 0; i < 600; i++) { |
fe820044 MR |
101 | tmp = i; |
102 | tmp += i; | |
7ef803a9 | 103 | } |
81dee67e SM |
104 | } |
105 | ||
106 | /* | |
107 | * This function set/reset the SCL GPIO pin | |
108 | * | |
109 | * Parameters: | |
110 | * value - Bit value to set to the SCL or SDA (0 = low, 1 = high) | |
111 | * | |
112 | * Notes: | |
113 | * When setting SCL to high, just set the GPIO as input where the pull up | |
114 | * resistor will pull the signal up. Do not use software to pull up the | |
115 | * signal because the i2c will fail when other device try to drive the | |
116 | * signal due to SM50x will drive the signal to always high. | |
117 | */ | |
6c78f4ce | 118 | static void sw_i2c_scl(unsigned char value) |
81dee67e | 119 | { |
fe820044 MR |
120 | unsigned long gpio_data; |
121 | unsigned long gpio_dir; | |
7ef803a9 | 122 | |
fe820044 | 123 | gpio_dir = PEEK32(sw_i2c_clk_gpio_data_dir_reg); |
d3f431d0 | 124 | if (value) { /* High */ |
9137f812 MR |
125 | /* |
126 | * Set direction as input. This will automatically | |
127 | * pull the signal up. | |
128 | */ | |
fe820044 MR |
129 | gpio_dir &= ~(1 << sw_i2c_clk_gpio); |
130 | POKE32(sw_i2c_clk_gpio_data_dir_reg, gpio_dir); | |
d3f431d0 | 131 | } else { /* Low */ |
7ef803a9 | 132 | /* Set the signal down */ |
fe820044 MR |
133 | gpio_data = PEEK32(sw_i2c_clk_gpio_data_reg); |
134 | gpio_data &= ~(1 << sw_i2c_clk_gpio); | |
135 | POKE32(sw_i2c_clk_gpio_data_reg, gpio_data); | |
7ef803a9 IA |
136 | |
137 | /* Set direction as output */ | |
fe820044 MR |
138 | gpio_dir |= (1 << sw_i2c_clk_gpio); |
139 | POKE32(sw_i2c_clk_gpio_data_dir_reg, gpio_dir); | |
7ef803a9 | 140 | } |
81dee67e SM |
141 | } |
142 | ||
143 | /* | |
144 | * This function set/reset the SDA GPIO pin | |
145 | * | |
146 | * Parameters: | |
147 | * value - Bit value to set to the SCL or SDA (0 = low, 1 = high) | |
148 | * | |
149 | * Notes: | |
150 | * When setting SCL to high, just set the GPIO as input where the pull up | |
151 | * resistor will pull the signal up. Do not use software to pull up the | |
152 | * signal because the i2c will fail when other device try to drive the | |
153 | * signal due to SM50x will drive the signal to always high. | |
154 | */ | |
6c78f4ce | 155 | static void sw_i2c_sda(unsigned char value) |
81dee67e | 156 | { |
fe820044 MR |
157 | unsigned long gpio_data; |
158 | unsigned long gpio_dir; | |
7ef803a9 | 159 | |
fe820044 | 160 | gpio_dir = PEEK32(sw_i2c_data_gpio_data_dir_reg); |
d3f431d0 | 161 | if (value) { /* High */ |
9137f812 MR |
162 | /* |
163 | * Set direction as input. This will automatically | |
164 | * pull the signal up. | |
165 | */ | |
fe820044 MR |
166 | gpio_dir &= ~(1 << sw_i2c_data_gpio); |
167 | POKE32(sw_i2c_data_gpio_data_dir_reg, gpio_dir); | |
d3f431d0 | 168 | } else { /* Low */ |
7ef803a9 | 169 | /* Set the signal down */ |
fe820044 MR |
170 | gpio_data = PEEK32(sw_i2c_data_gpio_data_reg); |
171 | gpio_data &= ~(1 << sw_i2c_data_gpio); | |
172 | POKE32(sw_i2c_data_gpio_data_reg, gpio_data); | |
7ef803a9 IA |
173 | |
174 | /* Set direction as output */ | |
fe820044 MR |
175 | gpio_dir |= (1 << sw_i2c_data_gpio); |
176 | POKE32(sw_i2c_data_gpio_data_dir_reg, gpio_dir); | |
7ef803a9 | 177 | } |
81dee67e SM |
178 | } |
179 | ||
180 | /* | |
181 | * This function read the data from the SDA GPIO pin | |
182 | * | |
183 | * Return Value: | |
184 | * The SDA data bit sent by the Slave | |
185 | */ | |
6c78f4ce | 186 | static unsigned char sw_i2c_read_sda(void) |
81dee67e | 187 | { |
fe820044 MR |
188 | unsigned long gpio_dir; |
189 | unsigned long gpio_data; | |
9137f812 | 190 | unsigned long dir_mask = 1 << sw_i2c_data_gpio; |
7ef803a9 IA |
191 | |
192 | /* Make sure that the direction is input (High) */ | |
fe820044 | 193 | gpio_dir = PEEK32(sw_i2c_data_gpio_data_dir_reg); |
9137f812 | 194 | if ((gpio_dir & dir_mask) != ~dir_mask) { |
fe820044 MR |
195 | gpio_dir &= ~(1 << sw_i2c_data_gpio); |
196 | POKE32(sw_i2c_data_gpio_data_dir_reg, gpio_dir); | |
7ef803a9 IA |
197 | } |
198 | ||
199 | /* Now read the SDA line */ | |
fe820044 MR |
200 | gpio_data = PEEK32(sw_i2c_data_gpio_data_reg); |
201 | if (gpio_data & (1 << sw_i2c_data_gpio)) | |
7ef803a9 IA |
202 | return 1; |
203 | else | |
204 | return 0; | |
81dee67e SM |
205 | } |
206 | ||
81dee67e SM |
207 | /* |
208 | * This function sends ACK signal | |
209 | */ | |
6c78f4ce | 210 | static void sw_i2c_ack(void) |
81dee67e | 211 | { |
7ef803a9 | 212 | return; /* Single byte read is ok without it. */ |
81dee67e SM |
213 | } |
214 | ||
215 | /* | |
216 | * This function sends the start command to the slave device | |
217 | */ | |
6c78f4ce | 218 | static void sw_i2c_start(void) |
81dee67e | 219 | { |
7ef803a9 | 220 | /* Start I2C */ |
6c78f4ce MR |
221 | sw_i2c_sda(1); |
222 | sw_i2c_scl(1); | |
223 | sw_i2c_sda(0); | |
81dee67e SM |
224 | } |
225 | ||
226 | /* | |
227 | * This function sends the stop command to the slave device | |
228 | */ | |
6c78f4ce | 229 | static void sw_i2c_stop(void) |
81dee67e | 230 | { |
7ef803a9 | 231 | /* Stop the I2C */ |
6c78f4ce MR |
232 | sw_i2c_scl(1); |
233 | sw_i2c_sda(0); | |
234 | sw_i2c_sda(1); | |
81dee67e SM |
235 | } |
236 | ||
237 | /* | |
238 | * This function writes one byte to the slave device | |
239 | * | |
240 | * Parameters: | |
241 | * data - Data to be write to the slave device | |
242 | * | |
243 | * Return Value: | |
244 | * 0 - Success | |
245 | * -1 - Fail to write byte | |
246 | */ | |
6c78f4ce | 247 | static long sw_i2c_write_byte(unsigned char data) |
81dee67e | 248 | { |
7ef803a9 IA |
249 | unsigned char value = data; |
250 | int i; | |
251 | ||
252 | /* Sending the data bit by bit */ | |
d3f431d0 | 253 | for (i = 0; i < 8; i++) { |
7ef803a9 | 254 | /* Set SCL to low */ |
6c78f4ce | 255 | sw_i2c_scl(0); |
7ef803a9 IA |
256 | |
257 | /* Send data bit */ | |
258 | if ((value & 0x80) != 0) | |
6c78f4ce | 259 | sw_i2c_sda(1); |
7ef803a9 | 260 | else |
6c78f4ce | 261 | sw_i2c_sda(0); |
7ef803a9 | 262 | |
6c78f4ce | 263 | sw_i2c_wait(); |
7ef803a9 IA |
264 | |
265 | /* Toggle clk line to one */ | |
6c78f4ce MR |
266 | sw_i2c_scl(1); |
267 | sw_i2c_wait(); | |
7ef803a9 IA |
268 | |
269 | /* Shift byte to be sent */ | |
270 | value = value << 1; | |
271 | } | |
272 | ||
273 | /* Set the SCL Low and SDA High (prepare to get input) */ | |
6c78f4ce MR |
274 | sw_i2c_scl(0); |
275 | sw_i2c_sda(1); | |
7ef803a9 IA |
276 | |
277 | /* Set the SCL High for ack */ | |
6c78f4ce MR |
278 | sw_i2c_wait(); |
279 | sw_i2c_scl(1); | |
280 | sw_i2c_wait(); | |
7ef803a9 IA |
281 | |
282 | /* Read SDA, until SDA==0 */ | |
6bdee8bd | 283 | for (i = 0; i < 0xff; i++) { |
6c78f4ce | 284 | if (!sw_i2c_read_sda()) |
7ef803a9 IA |
285 | break; |
286 | ||
6c78f4ce MR |
287 | sw_i2c_scl(0); |
288 | sw_i2c_wait(); | |
289 | sw_i2c_scl(1); | |
290 | sw_i2c_wait(); | |
7ef803a9 IA |
291 | } |
292 | ||
293 | /* Set the SCL Low and SDA High */ | |
6c78f4ce MR |
294 | sw_i2c_scl(0); |
295 | sw_i2c_sda(1); | |
7ef803a9 | 296 | |
6d43b0f4 | 297 | if (i < 0xff) |
7ef803a9 IA |
298 | return 0; |
299 | else | |
300 | return -1; | |
81dee67e SM |
301 | } |
302 | ||
303 | /* | |
304 | * This function reads one byte from the slave device | |
305 | * | |
306 | * Parameters: | |
307 | * ack - Flag to indicate either to send the acknowledge | |
308 | * message to the slave device or not | |
309 | * | |
310 | * Return Value: | |
311 | * One byte data read from the Slave device | |
312 | */ | |
6c78f4ce | 313 | static unsigned char sw_i2c_read_byte(unsigned char ack) |
81dee67e | 314 | { |
7ef803a9 IA |
315 | int i; |
316 | unsigned char data = 0; | |
81dee67e | 317 | |
6bdee8bd | 318 | for (i = 7; i >= 0; i--) { |
7ef803a9 | 319 | /* Set the SCL to Low and SDA to High (Input) */ |
6c78f4ce MR |
320 | sw_i2c_scl(0); |
321 | sw_i2c_sda(1); | |
322 | sw_i2c_wait(); | |
81dee67e | 323 | |
7ef803a9 | 324 | /* Set the SCL High */ |
6c78f4ce MR |
325 | sw_i2c_scl(1); |
326 | sw_i2c_wait(); | |
81dee67e | 327 | |
7ef803a9 | 328 | /* Read data bits from SDA */ |
6c78f4ce | 329 | data |= (sw_i2c_read_sda() << i); |
7ef803a9 | 330 | } |
81dee67e | 331 | |
7ef803a9 | 332 | if (ack) |
6c78f4ce | 333 | sw_i2c_ack(); |
81dee67e | 334 | |
7ef803a9 | 335 | /* Set the SCL Low and SDA High */ |
6c78f4ce MR |
336 | sw_i2c_scl(0); |
337 | sw_i2c_sda(1); | |
81dee67e | 338 | |
7ef803a9 | 339 | return data; |
81dee67e | 340 | } |
81dee67e SM |
341 | |
342 | /* | |
343 | * This function initializes GPIO port for SW I2C communication. | |
344 | * | |
345 | * Parameters: | |
fe820044 MR |
346 | * clk_gpio - The GPIO pin to be used as i2c SCL |
347 | * data_gpio - The GPIO pin to be used as i2c SDA | |
81dee67e SM |
348 | * |
349 | * Return Value: | |
350 | * -1 - Fail to initialize the i2c | |
351 | * 0 - Success | |
352 | */ | |
fe820044 MR |
353 | static long sm750le_i2c_init(unsigned char clk_gpio, |
354 | unsigned char data_gpio) | |
81dee67e | 355 | { |
7ef803a9 | 356 | int i; |
81dee67e | 357 | |
7ef803a9 | 358 | /* Initialize the GPIO pin for the i2c Clock Register */ |
53bc6b6e MR |
359 | sw_i2c_clk_gpio_data_reg = GPIO_DATA_SM750LE; |
360 | sw_i2c_clk_gpio_data_dir_reg = GPIO_DATA_DIRECTION_SM750LE; | |
81dee67e | 361 | |
7ef803a9 | 362 | /* Initialize the Clock GPIO Offset */ |
fe820044 | 363 | sw_i2c_clk_gpio = clk_gpio; |
81dee67e | 364 | |
7ef803a9 | 365 | /* Initialize the GPIO pin for the i2c Data Register */ |
53bc6b6e MR |
366 | sw_i2c_data_gpio_data_reg = GPIO_DATA_SM750LE; |
367 | sw_i2c_data_gpio_data_dir_reg = GPIO_DATA_DIRECTION_SM750LE; | |
81dee67e | 368 | |
7ef803a9 | 369 | /* Initialize the Data GPIO Offset */ |
fe820044 | 370 | sw_i2c_data_gpio = data_gpio; |
81dee67e | 371 | |
7ef803a9 | 372 | /* Note that SM750LE don't have GPIO MUX and power is always on */ |
81dee67e | 373 | |
7ef803a9 | 374 | /* Clear the i2c lines. */ |
6bdee8bd | 375 | for (i = 0; i < 9; i++) |
6c78f4ce | 376 | sw_i2c_stop(); |
81dee67e | 377 | |
7ef803a9 | 378 | return 0; |
81dee67e SM |
379 | } |
380 | ||
381 | /* | |
382 | * This function initializes the i2c attributes and bus | |
383 | * | |
384 | * Parameters: | |
fe820044 MR |
385 | * clk_gpio - The GPIO pin to be used as i2c SCL |
386 | * data_gpio - The GPIO pin to be used as i2c SDA | |
81dee67e SM |
387 | * |
388 | * Return Value: | |
389 | * -1 - Fail to initialize the i2c | |
390 | * 0 - Success | |
391 | */ | |
f2ea7733 | 392 | long sm750_sw_i2c_init( |
fe820044 MR |
393 | unsigned char clk_gpio, |
394 | unsigned char data_gpio | |
81dee67e SM |
395 | ) |
396 | { | |
7ef803a9 | 397 | int i; |
81dee67e | 398 | |
9137f812 MR |
399 | /* |
400 | * Return 0 if the GPIO pins to be used is out of range. The | |
401 | * range is only from [0..63] | |
402 | */ | |
fe820044 | 403 | if ((clk_gpio > 31) || (data_gpio > 31)) |
7ef803a9 | 404 | return -1; |
81dee67e | 405 | |
06a4f429 | 406 | if (sm750_get_chip_type() == SM750LE) |
fe820044 | 407 | return sm750le_i2c_init(clk_gpio, data_gpio); |
81dee67e | 408 | |
7ef803a9 | 409 | /* Initialize the GPIO pin for the i2c Clock Register */ |
53bc6b6e MR |
410 | sw_i2c_clk_gpio_mux_reg = GPIO_MUX; |
411 | sw_i2c_clk_gpio_data_reg = GPIO_DATA; | |
412 | sw_i2c_clk_gpio_data_dir_reg = GPIO_DATA_DIRECTION; | |
81dee67e | 413 | |
7ef803a9 | 414 | /* Initialize the Clock GPIO Offset */ |
fe820044 | 415 | sw_i2c_clk_gpio = clk_gpio; |
81dee67e | 416 | |
7ef803a9 | 417 | /* Initialize the GPIO pin for the i2c Data Register */ |
53bc6b6e MR |
418 | sw_i2c_data_gpio_mux_reg = GPIO_MUX; |
419 | sw_i2c_data_gpio_data_reg = GPIO_DATA; | |
420 | sw_i2c_data_gpio_data_dir_reg = GPIO_DATA_DIRECTION; | |
81dee67e | 421 | |
7ef803a9 | 422 | /* Initialize the Data GPIO Offset */ |
fe820044 | 423 | sw_i2c_data_gpio = data_gpio; |
81dee67e | 424 | |
7ef803a9 | 425 | /* Enable the GPIO pins for the i2c Clock and Data (GPIO MUX) */ |
53bc6b6e | 426 | POKE32(sw_i2c_clk_gpio_mux_reg, |
9137f812 | 427 | PEEK32(sw_i2c_clk_gpio_mux_reg) & ~(1 << sw_i2c_clk_gpio)); |
53bc6b6e | 428 | POKE32(sw_i2c_data_gpio_mux_reg, |
9137f812 | 429 | PEEK32(sw_i2c_data_gpio_mux_reg) & ~(1 << sw_i2c_data_gpio)); |
81dee67e | 430 | |
7ef803a9 IA |
431 | /* Enable GPIO power */ |
432 | enableGPIO(1); | |
81dee67e | 433 | |
7ef803a9 | 434 | /* Clear the i2c lines. */ |
6bdee8bd | 435 | for (i = 0; i < 9; i++) |
6c78f4ce | 436 | sw_i2c_stop(); |
81dee67e | 437 | |
7ef803a9 | 438 | return 0; |
81dee67e SM |
439 | } |
440 | ||
441 | /* | |
442 | * This function reads the slave device's register | |
443 | * | |
444 | * Parameters: | |
fe820044 | 445 | * addr - i2c Slave device address which register |
81dee67e | 446 | * to be read from |
fe820044 | 447 | * reg - Slave device's register to be read |
81dee67e SM |
448 | * |
449 | * Return Value: | |
450 | * Register value | |
451 | */ | |
288836b6 | 452 | unsigned char sm750_sw_i2c_read_reg( |
fe820044 MR |
453 | unsigned char addr, |
454 | unsigned char reg | |
81dee67e SM |
455 | ) |
456 | { | |
7ef803a9 | 457 | unsigned char data; |
81dee67e | 458 | |
7ef803a9 | 459 | /* Send the Start signal */ |
6c78f4ce | 460 | sw_i2c_start(); |
81dee67e | 461 | |
7ef803a9 | 462 | /* Send the device address */ |
fe820044 | 463 | sw_i2c_write_byte(addr); |
81dee67e | 464 | |
7ef803a9 | 465 | /* Send the register index */ |
fe820044 | 466 | sw_i2c_write_byte(reg); |
81dee67e | 467 | |
7ef803a9 | 468 | /* Get the bus again and get the data from the device read address */ |
6c78f4ce | 469 | sw_i2c_start(); |
fe820044 | 470 | sw_i2c_write_byte(addr + 1); |
6c78f4ce | 471 | data = sw_i2c_read_byte(1); |
81dee67e | 472 | |
7ef803a9 | 473 | /* Stop swI2C and release the bus */ |
6c78f4ce | 474 | sw_i2c_stop(); |
81dee67e | 475 | |
7ef803a9 | 476 | return data; |
81dee67e SM |
477 | } |
478 | ||
479 | /* | |
480 | * This function writes a value to the slave device's register | |
481 | * | |
482 | * Parameters: | |
fe820044 | 483 | * addr - i2c Slave device address which register |
81dee67e | 484 | * to be written |
fe820044 | 485 | * reg - Slave device's register to be written |
81dee67e SM |
486 | * data - Data to be written to the register |
487 | * | |
488 | * Result: | |
489 | * 0 - Success | |
490 | * -1 - Fail | |
491 | */ | |
d33b4204 | 492 | long sm750_sw_i2c_write_reg( |
fe820044 MR |
493 | unsigned char addr, |
494 | unsigned char reg, | |
7ef803a9 | 495 | unsigned char data |
81dee67e SM |
496 | ) |
497 | { | |
fe820044 | 498 | long ret = 0; |
81dee67e | 499 | |
7ef803a9 | 500 | /* Send the Start signal */ |
6c78f4ce | 501 | sw_i2c_start(); |
81dee67e | 502 | |
7ef803a9 IA |
503 | /* Send the device address and read the data. All should return success |
504 | in order for the writing processed to be successful | |
505 | */ | |
fe820044 MR |
506 | if ((sw_i2c_write_byte(addr) != 0) || |
507 | (sw_i2c_write_byte(reg) != 0) || | |
6c78f4ce | 508 | (sw_i2c_write_byte(data) != 0)) { |
fe820044 | 509 | ret = -1; |
7ef803a9 | 510 | } |
81dee67e | 511 | |
7ef803a9 | 512 | /* Stop i2c and release the bus */ |
6c78f4ce | 513 | sw_i2c_stop(); |
81dee67e | 514 | |
fe820044 | 515 | return ret; |
81dee67e | 516 | } |