File Index
Files and directories
Sign in
FILE

ddk750_swi2c.c

File preview with syntax highlighting.

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