// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) * * swi2c.c --- SM750/SM718 DDK * This file contains the source code for I2C using software * implementation. */ #include "ddk750_chip.h" #include "ddk750_reg.h" #include "ddk750_swi2c.h" #include "ddk750_power.h" /* * I2C Software Master Driver: * =========================== * Each i2c cycle is split into 4 sections. Each of these section marks * a point in time where the SCL or SDA may be changed. * * 1 Cycle == | Section I. | Section 2. | Section 3. | Section 4. | * +-------------+-------------+-------------+-------------+ * | SCL set LOW |SCL no change| SCL set HIGH|SCL no change| * * ____________ _____________ * SCL == XXXX _____________ ____________ / * * I.e. the SCL may only be changed in section 1. and section 3. while * the SDA may only be changed in section 2. and section 4. The table * below gives the changes for these 2 lines in the varios sections. * * Section changes Table: * ====================== * blank = no change, L = set bit LOW, H = set bit HIGH * * | 1.| 2.| 3.| 4.| * ---------------+---+---+---+---+ * Tx Start SDA | | H | | L | * SCL | L | | H | | * ---------------+---+---+---+---+ * Tx Stop SDA | | L | | H | * SCL | L | | H | | * ---------------+---+---+---+---+ * Tx bit H SDA | | H | | | * SCL | L | | H | | * ---------------+---+---+---+---+ * Tx bit L SDA | | L | | | * SCL | L | | H | | * ---------------+---+---+---+---+ * */ /* GPIO pins used for this I2C. It ranges from 0 to 63. */ static unsigned char sw_i2c_clk_gpio = …; static unsigned char sw_i2c_data_gpio = …; /* * Below is the variable declaration for the GPIO pin register usage * for the i2c Clock and i2c Data. * * Note: * Notice that the GPIO usage for the i2c clock and i2c Data are * separated. This is to make this code flexible enough when * two separate GPIO pins for the clock and data are located * in two different GPIO register set (worst case). */ /* i2c Clock GPIO Register usage */ static unsigned long sw_i2c_clk_gpio_mux_reg = …; static unsigned long sw_i2c_clk_gpio_data_reg = …; static unsigned long sw_i2c_clk_gpio_data_dir_reg = …; /* i2c Data GPIO Register usage */ static unsigned long sw_i2c_data_gpio_mux_reg = …; static unsigned long sw_i2c_data_gpio_data_reg = …; static unsigned long sw_i2c_data_gpio_data_dir_reg = …; /* * This function puts a delay between command */ static void sw_i2c_wait(void) { … } /* * This function set/reset the SCL GPIO pin * * Parameters: * value - Bit value to set to the SCL or SDA (0 = low, 1 = high) * * Notes: * When setting SCL to high, just set the GPIO as input where the pull up * resistor will pull the signal up. Do not use software to pull up the * signal because the i2c will fail when other device try to drive the * signal due to SM50x will drive the signal to always high. */ static void sw_i2c_scl(unsigned char value) { … } /* * This function set/reset the SDA GPIO pin * * Parameters: * value - Bit value to set to the SCL or SDA (0 = low, 1 = high) * * Notes: * When setting SCL to high, just set the GPIO as input where the pull up * resistor will pull the signal up. Do not use software to pull up the * signal because the i2c will fail when other device try to drive the * signal due to SM50x will drive the signal to always high. */ static void sw_i2c_sda(unsigned char value) { … } /* * This function read the data from the SDA GPIO pin * * Return Value: * The SDA data bit sent by the Slave */ static unsigned char sw_i2c_read_sda(void) { … } /* * This function sends ACK signal */ static void sw_i2c_ack(void) { … } /* * This function sends the start command to the slave device */ static void sw_i2c_start(void) { … } /* * This function sends the stop command to the slave device */ static void sw_i2c_stop(void) { … } /* * This function writes one byte to the slave device * * Parameters: * data - Data to be write to the slave device * * Return Value: * 0 - Success * -1 - Fail to write byte */ static long sw_i2c_write_byte(unsigned char data) { … } /* * This function reads one byte from the slave device * * Parameters: * ack - Flag to indicate either to send the acknowledge * message to the slave device or not * * Return Value: * One byte data read from the Slave device */ static unsigned char sw_i2c_read_byte(unsigned char ack) { … } /* * This function initializes GPIO port for SW I2C communication. * * Parameters: * clk_gpio - The GPIO pin to be used as i2c SCL * data_gpio - The GPIO pin to be used as i2c SDA * * Return Value: * -1 - Fail to initialize the i2c * 0 - Success */ static long sm750le_i2c_init(unsigned char clk_gpio, unsigned char data_gpio) { … } /* * This function initializes the i2c attributes and bus * * Parameters: * clk_gpio - The GPIO pin to be used as i2c SCL * data_gpio - The GPIO pin to be used as i2c SDA * * Return Value: * -1 - Fail to initialize the i2c * 0 - Success */ long sm750_sw_i2c_init(unsigned char clk_gpio, unsigned char data_gpio) { … } /* * This function reads the slave device's register * * Parameters: * addr - i2c Slave device address which register * to be read from * reg - Slave device's register to be read * * Return Value: * Register value */ unsigned char sm750_sw_i2c_read_reg(unsigned char addr, unsigned char reg) { … } /* * This function writes a value to the slave device's register * * Parameters: * addr - i2c Slave device address which register * to be written * reg - Slave device's register to be written * data - Data to be written to the register * * Result: * 0 - Success * -1 - Fail */ long sm750_sw_i2c_write_reg(unsigned char addr, unsigned char reg, unsigned char data) { … }