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