cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ddk750_hwi2c.c (5712B)


      1// SPDX-License-Identifier: GPL-2.0
      2#define USE_HW_I2C
      3#ifdef USE_HW_I2C
      4#include "ddk750_chip.h"
      5#include "ddk750_reg.h"
      6#include "ddk750_hwi2c.h"
      7#include "ddk750_power.h"
      8
      9#define MAX_HWI2C_FIFO                  16
     10#define HWI2C_WAIT_TIMEOUT              0xF0000
     11
     12int sm750_hw_i2c_init(unsigned char bus_speed_mode)
     13{
     14	unsigned int value;
     15
     16	/* Enable GPIO 30 & 31 as IIC clock & data */
     17	value = peek32(GPIO_MUX);
     18
     19	value |= (GPIO_MUX_30 | GPIO_MUX_31);
     20	poke32(GPIO_MUX, value);
     21
     22	/*
     23	 * Enable Hardware I2C power.
     24	 * TODO: Check if we need to enable GPIO power?
     25	 */
     26	sm750_enable_i2c(1);
     27
     28	/* Enable the I2C Controller and set the bus speed mode */
     29	value = peek32(I2C_CTRL) & ~(I2C_CTRL_MODE | I2C_CTRL_EN);
     30	if (bus_speed_mode)
     31		value |= I2C_CTRL_MODE;
     32	value |= I2C_CTRL_EN;
     33	poke32(I2C_CTRL, value);
     34
     35	return 0;
     36}
     37
     38void sm750_hw_i2c_close(void)
     39{
     40	unsigned int value;
     41
     42	/* Disable I2C controller */
     43	value = peek32(I2C_CTRL) & ~I2C_CTRL_EN;
     44	poke32(I2C_CTRL, value);
     45
     46	/* Disable I2C Power */
     47	sm750_enable_i2c(0);
     48
     49	/* Set GPIO 30 & 31 back as GPIO pins */
     50	value = peek32(GPIO_MUX);
     51	value &= ~GPIO_MUX_30;
     52	value &= ~GPIO_MUX_31;
     53	poke32(GPIO_MUX, value);
     54}
     55
     56static long hw_i2c_wait_tx_done(void)
     57{
     58	unsigned int timeout;
     59
     60	/* Wait until the transfer is completed. */
     61	timeout = HWI2C_WAIT_TIMEOUT;
     62	while (!(peek32(I2C_STATUS) & I2C_STATUS_TX) && (timeout != 0))
     63		timeout--;
     64
     65	if (timeout == 0)
     66		return -1;
     67
     68	return 0;
     69}
     70
     71/*
     72 *  This function writes data to the i2c slave device registers.
     73 *
     74 *  Parameters:
     75 *      addr            - i2c Slave device address
     76 *      length          - Total number of bytes to be written to the device
     77 *      buf             - The buffer that contains the data to be written to the
     78 *                     i2c device.
     79 *
     80 *  Return Value:
     81 *      Total number of bytes those are actually written.
     82 */
     83static unsigned int hw_i2c_write_data(unsigned char addr,
     84				      unsigned int length,
     85				      unsigned char *buf)
     86{
     87	unsigned char count, i;
     88	unsigned int total_bytes = 0;
     89
     90	/* Set the Device Address */
     91	poke32(I2C_SLAVE_ADDRESS, addr & ~0x01);
     92
     93	/*
     94	 * Write data.
     95	 * Note:
     96	 *      Only 16 byte can be accessed per i2c start instruction.
     97	 */
     98	do {
     99		/*
    100		 * Reset I2C by writing 0 to I2C_RESET register to
    101		 * clear the previous status.
    102		 */
    103		poke32(I2C_RESET, 0);
    104
    105		/* Set the number of bytes to be written */
    106		if (length < MAX_HWI2C_FIFO)
    107			count = length - 1;
    108		else
    109			count = MAX_HWI2C_FIFO - 1;
    110		poke32(I2C_BYTE_COUNT, count);
    111
    112		/* Move the data to the I2C data register */
    113		for (i = 0; i <= count; i++)
    114			poke32(I2C_DATA0 + i, *buf++);
    115
    116		/* Start the I2C */
    117		poke32(I2C_CTRL, peek32(I2C_CTRL) | I2C_CTRL_CTRL);
    118
    119		/* Wait until the transfer is completed. */
    120		if (hw_i2c_wait_tx_done() != 0)
    121			break;
    122
    123		/* Subtract length */
    124		length -= (count + 1);
    125
    126		/* Total byte written */
    127		total_bytes += (count + 1);
    128
    129	} while (length > 0);
    130
    131	return total_bytes;
    132}
    133
    134/*
    135 *  This function reads data from the slave device and stores them
    136 *  in the given buffer
    137 *
    138 *  Parameters:
    139 *      addr            - i2c Slave device address
    140 *      length          - Total number of bytes to be read
    141 *      buf             - Pointer to a buffer to be filled with the data read
    142 *                     from the slave device. It has to be the same size as the
    143 *                     length to make sure that it can keep all the data read.
    144 *
    145 *  Return Value:
    146 *      Total number of actual bytes read from the slave device
    147 */
    148static unsigned int hw_i2c_read_data(unsigned char addr,
    149				     unsigned int length,
    150				     unsigned char *buf)
    151{
    152	unsigned char count, i;
    153	unsigned int total_bytes = 0;
    154
    155	/* Set the Device Address */
    156	poke32(I2C_SLAVE_ADDRESS, addr | 0x01);
    157
    158	/*
    159	 * Read data and save them to the buffer.
    160	 * Note:
    161	 *      Only 16 byte can be accessed per i2c start instruction.
    162	 */
    163	do {
    164		/*
    165		 * Reset I2C by writing 0 to I2C_RESET register to
    166		 * clear all the status.
    167		 */
    168		poke32(I2C_RESET, 0);
    169
    170		/* Set the number of bytes to be read */
    171		if (length <= MAX_HWI2C_FIFO)
    172			count = length - 1;
    173		else
    174			count = MAX_HWI2C_FIFO - 1;
    175		poke32(I2C_BYTE_COUNT, count);
    176
    177		/* Start the I2C */
    178		poke32(I2C_CTRL, peek32(I2C_CTRL) | I2C_CTRL_CTRL);
    179
    180		/* Wait until transaction done. */
    181		if (hw_i2c_wait_tx_done() != 0)
    182			break;
    183
    184		/* Save the data to the given buffer */
    185		for (i = 0; i <= count; i++)
    186			*buf++ = peek32(I2C_DATA0 + i);
    187
    188		/* Subtract length by 16 */
    189		length -= (count + 1);
    190
    191		/* Number of bytes read. */
    192		total_bytes += (count + 1);
    193
    194	} while (length > 0);
    195
    196	return total_bytes;
    197}
    198
    199/*
    200 *  This function reads the slave device's register
    201 *
    202 *  Parameters:
    203 *      deviceAddress   - i2c Slave device address which register
    204 *                        to be read from
    205 *      registerIndex   - Slave device's register to be read
    206 *
    207 *  Return Value:
    208 *      Register value
    209 */
    210unsigned char sm750_hw_i2c_read_reg(unsigned char addr, unsigned char reg)
    211{
    212	unsigned char value = 0xFF;
    213
    214	if (hw_i2c_write_data(addr, 1, &reg) == 1)
    215		hw_i2c_read_data(addr, 1, &value);
    216
    217	return value;
    218}
    219
    220/*
    221 *  This function writes a value to the slave device's register
    222 *
    223 *  Parameters:
    224 *      deviceAddress   - i2c Slave device address which register
    225 *                        to be written
    226 *      registerIndex   - Slave device's register to be written
    227 *      data            - Data to be written to the register
    228 *
    229 *  Result:
    230 *          0   - Success
    231 *         -1   - Fail
    232 */
    233int sm750_hw_i2c_write_reg(unsigned char addr,
    234			   unsigned char reg,
    235			   unsigned char data)
    236{
    237	unsigned char value[2];
    238
    239	value[0] = reg;
    240	value[1] = data;
    241	if (hw_i2c_write_data(addr, 2, value) == 2)
    242		return 0;
    243
    244	return -1;
    245}
    246
    247#endif