summaryrefslogtreecommitdiff
path: root/src/soc/marvell/armada38x/i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/marvell/armada38x/i2c.c')
-rw-r--r--src/soc/marvell/armada38x/i2c.c1251
1 files changed, 0 insertions, 1251 deletions
diff --git a/src/soc/marvell/armada38x/i2c.c b/src/soc/marvell/armada38x/i2c.c
deleted file mode 100644
index 723d3b4b1d..0000000000
--- a/src/soc/marvell/armada38x/i2c.c
+++ /dev/null
@@ -1,1251 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2015 Marvell Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <arch/io.h>
-#include <arch/cpu.h>
-#include <console/console.h>
-#include <delay.h>
-#include <device/i2c.h>
-#include <soc/common.h>
-#include <soc/i2c.h>
-#include <soc/clock.h>
-#include <helpers.h>
-
-#undef MV_DEBUG
-//#define MV_DEBUG
-#ifdef MV_DEBUG
-#define DB(x) x
-#else
-#define DB(x)
-#endif
-#define mv_os_printf(args...) printk(BIOS_INFO, args)
-
-/* The TWSI interface supports both 7-bit and 10-bit addressing. */
-/* This enumerator describes addressing type. */
-typedef enum _mv_twsi_addr_type {
- ADDR7_BIT, /* 7 bit address */
- ADDR10_BIT /* 10 bit address */
-} MV_TWSI_ADDR_TYPE;
-
-/* This structure describes TWSI address. */
-typedef struct _mv_twsi_addr {
- uint32_t address; /* address */
- MV_TWSI_ADDR_TYPE type; /* Address type */
-} MV_TWSI_ADDR;
-
-/* This structure describes a TWSI slave. */
-typedef struct _mv_twsi_slave {
- MV_TWSI_ADDR slave_addr;
- int valid_offset; /* whether the slave has offset (i.e. Eeprom etc.) */
- uint32_t offset; /* offset in the slave. */
- int more_than256; /* whether the ofset is bigger then 256 */
-} MV_TWSI_SLAVE;
-
-/* This enumerator describes TWSI protocol commands. */
-typedef enum _mv_twsi_cmd {
- MV_TWSI_WRITE, /* TWSI write command - 0 according to spec */
- MV_TWSI_READ /* TWSI read command - 1 according to spec */
-} MV_TWSI_CMD;
-
-static void twsi_int_flg_clr(uint8_t chan_num);
-static uint8_t twsi_main_int_get(uint8_t chan_num);
-static void twsi_ack_bit_set(uint8_t chan_num);
-static uint32_t twsi_sts_get(uint8_t chan_num);
-static void twsi_reset(uint8_t chan_num);
-static int twsi_addr7_bit_set(uint8_t chan_num,
- uint32_t device_address,
- MV_TWSI_CMD command);
-static int twsi_addr10_bit_set(uint8_t chan_num,
- uint32_t device_address,
- MV_TWSI_CMD command);
-static int twsi_data_transmit(uint8_t chan_num,
- uint8_t *p_block,
- uint32_t block_size);
-static int twsi_data_receive(uint8_t chan_num,
- uint8_t *p_block,
- uint32_t block_size);
-static int twsi_target_offs_set(uint8_t chan_num,
- uint32_t offset,
- uint8_t more_than256);
-static int mv_twsi_start_bit_set(uint8_t chan_num);
-static int mv_twsi_stop_bit_set(uint8_t chan_num);
-static int mv_twsi_addr_set(uint8_t chan_num,
- MV_TWSI_ADDR *twsi_addr,
- MV_TWSI_CMD command);
-static uint32_t mv_twsi_init(uint8_t chan_num,
- uint32_t frequency,
- uint32_t Tclk,
- MV_TWSI_ADDR *twsi_addr,
- uint8_t general_call_enable);
-static int mv_twsi_read(uint8_t chan_num,
- MV_TWSI_SLAVE *twsi_slave,
- uint8_t *p_block,
- uint32_t block_size);
-static int mv_twsi_write(uint8_t chan_num,
- MV_TWSI_SLAVE *twsi_slave,
- uint8_t *p_block,
- uint32_t block_size);
-static uint32_t who_am_i(void);
-static int i2c_init(unsigned bus);
-static void i2c_reset(unsigned bus);
-
-static int m_initialized[MAX_I2C_NUM] = {0, 0};
-
-static uint8_t twsi_timeout_chk(uint32_t timeout, const char *p_string)
-{
- if (timeout >= TWSI_TIMEOUT_VALUE) {
- DB(mv_os_printf("%s", p_string));
- return MV_TRUE;
- }
- return MV_FALSE;
-}
-
-/*******************************************************************************
-* mv_twsi_start_bit_set - Set start bit on the bus
-*
-* DESCRIPTION:
-* This routine sets the start bit on the TWSI bus.
-* The routine first checks for interrupt flag condition, then it sets
-* the start bit in the TWSI Control register.
-* If the interrupt flag condition check previously was set, the function
-* will clear it.
-* The function then wait for the start bit to be cleared by the HW.
-* Then it waits for the interrupt flag to be set and eventually, the
-* TWSI status is checked to be 0x8 or 0x10(repeated start bit).
-*
-* INPUT:
-* chan_num - TWSI channel.
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* MV_OK if start bit was set successfuly on the bus.
-* MV_FAIL if start_bit not set or status does not indicate start
-* condition trasmitted.
-*
-*******************************************************************************/
-static int mv_twsi_start_bit_set(uint8_t chan_num)
-{
- uint8_t is_int_flag = MV_FALSE;
- uint32_t timeout, temp;
-
- DB(mv_os_printf("TWSI: mv_twsi_start_bit_set\n"));
- /* check Int flag */
- if (twsi_main_int_get(chan_num))
- is_int_flag = MV_TRUE;
- /* set start Bit */
- mrvl_reg_bit_set(TWSI_CONTROL_REG(chan_num), TWSI_CONTROL_START_BIT);
-
- /* in case that the int flag was set before i.e. repeated start bit */
- if (is_int_flag) {
- DB(mv_os_printf(
- "TWSI: mv_twsi_start_bit_set repeated start Bit\n"));
- twsi_int_flg_clr(chan_num);
- }
-
- /* wait for interrupt */
- timeout = 0;
- while (!twsi_main_int_get(chan_num) && (timeout++ < TWSI_TIMEOUT_VALUE))
- ;
-
- /* check for timeout */
- if (MV_TRUE ==
- twsi_timeout_chk(timeout,
- (const char *)"TWSI: Start Clear bit time_out.\n"))
- return MV_TIMEOUT;
-
- /* check that start bit went down */
- if ((mrvl_reg_read(TWSI_CONTROL_REG(chan_num)) &
- TWSI_CONTROL_START_BIT) != 0) {
- mv_os_printf("TWSI: start bit didn't go down\n");
- return MV_FAIL;
- }
-
- /* check the status */
- temp = twsi_sts_get(chan_num);
- if ((TWSI_M_LOST_ARB_DUR_AD_OR_DATA_TRA == temp) ||
- (TWSI_M_LOST_ARB_DUR_AD_TRA_GNL_CALL_AD_REC_ACK_TRA == temp)) {
- DB(mv_os_printf("TWSI: Lost Arb, status %x\n", temp));
- return MV_RETRY;
- } else if ((temp != TWSI_START_CON_TRA) &&
- (temp != TWSI_REPEATED_START_CON_TRA)) {
- mv_os_printf("TWSI: status %x after Set Start Bit.\n", temp);
- return MV_FAIL;
- }
-
- return MV_OK;
-}
-
-/*******************************************************************************
-* mv_twsi_stop_bit_set - Set stop bit on the bus
-*
-* DESCRIPTION:
-* This routine set the stop bit on the TWSI bus.
-* The function then wait for the stop bit to be cleared by the HW.
-* Finally the function checks for status of 0xF8.
-*
-* INPUT:
-* chan_num - TWSI channel
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* MV_TRUE is stop bit was set successfuly on the bus.
-*
-*******************************************************************************/
-static int mv_twsi_stop_bit_set(uint8_t chan_num)
-{
- uint32_t timeout, temp;
-
- /* Generate stop bit */
- mrvl_reg_bit_set(TWSI_CONTROL_REG(chan_num), TWSI_CONTROL_STOP_BIT);
-
- twsi_int_flg_clr(chan_num);
-
- /* wait for stop bit to come down */
- timeout = 0;
- while (((mrvl_reg_read(TWSI_CONTROL_REG(chan_num)) &
- TWSI_CONTROL_STOP_BIT) != 0) &&
- (timeout++ < TWSI_TIMEOUT_VALUE))
- ;
-
- /* check for timeout */
- if (MV_TRUE ==
- twsi_timeout_chk(timeout,
- (const char *)"TWSI: ERROR - Stop bit timeout\n"))
- return MV_TIMEOUT;
-
- /* check that the stop bit went down */
- if ((mrvl_reg_read(TWSI_CONTROL_REG(chan_num)) &
- TWSI_CONTROL_STOP_BIT) != 0) {
- mv_os_printf(
- "TWSI: ERROR - stop bit not went down\n");
- return MV_FAIL;
- }
-
- /* check the status */
- temp = twsi_sts_get(chan_num);
- if ((TWSI_M_LOST_ARB_DUR_AD_OR_DATA_TRA == temp) ||
- (TWSI_M_LOST_ARB_DUR_AD_TRA_GNL_CALL_AD_REC_ACK_TRA == temp)) {
- DB(mv_os_printf("TWSI: Lost Arb, status %x\n", temp));
- return MV_RETRY;
- } else if (temp != TWSI_NO_REL_STS_INT_FLAG_IS_KEPT_0) {
- mv_os_printf(
- "TWSI: ERROR - status %x after Stop Bit\n",
- temp);
- return MV_FAIL;
- }
-
- return MV_OK;
-}
-
-/*******************************************************************************
-* twsi_main_int_get - Get twsi bit from main Interrupt cause.
-*
-* DESCRIPTION:
-* This routine returns the twsi interrupt flag value.
-*
-* INPUT:
-* None.
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* MV_TRUE is interrupt flag is set, MV_FALSE otherwise.
-*
-*******************************************************************************/
-static uint32_t who_am_i(void)
-{
- return (read_mpidr() & 0x1);
-}
-
-static uint8_t twsi_main_int_get(uint8_t chan_num)
-{
- uint32_t temp;
-
- /* get the int flag bit */
- temp = mrvl_reg_read(MV_TWSI_CPU_MAIN_INT_CAUSE(chan_num, who_am_i()));
- if (temp & (1 << CPU_MAIN_INT_TWSI_OFFS(chan_num)))
- return MV_TRUE;
-
- return MV_FALSE;
-}
-
-/*******************************************************************************
-* twsi_int_flg_clr - Clear Interrupt flag.
-*
-* DESCRIPTION:
-* This routine clears the interrupt flag. It does NOT poll the interrupt
-* to make sure the clear. After clearing the interrupt, it waits for at
-* least 1 miliseconds.
-*
-* INPUT:
-* chan_num - TWSI channel
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* None.
-*
-*******************************************************************************/
-static void twsi_int_flg_clr(uint8_t chan_num)
-{
- /* wait for 1ms to prevent TWSI register write after write problems */
- mdelay(1);
- /* clear the int flag bit */
- mrvl_reg_bit_reset(
- TWSI_CONTROL_REG(chan_num), TWSI_CONTROL_INT_FLAG_SET);
- /* wait for 1 mili sec for the clear to take effect */
- mdelay(1);
-}
-
-/*******************************************************************************
-* twsi_ack_bit_set - Set acknowledge bit on the bus
-*
-* DESCRIPTION:
-* This routine set the acknowledge bit on the TWSI bus.
-*
-* INPUT:
-* None.
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* None.
-*
-*******************************************************************************/
-static void twsi_ack_bit_set(uint8_t chan_num)
-{
- /*Set the Ack bit */
- mrvl_reg_bit_set(TWSI_CONTROL_REG(chan_num), TWSI_CONTROL_ACK);
- /* Add delay of 1ms */
- mdelay(1);
-}
-
-/*******************************************************************************
-* twsi_init - Initialize TWSI interface
-*
-* DESCRIPTION:
-* This routine:
-* -Reset the TWSI.
-* -Initialize the TWSI clock baud rate according to given frequency
-* parameter based on Tclk frequency and enables TWSI slave.
-* -Set the ack bit.
-* -Assign the TWSI slave address according to the TWSI address Type.
-*
-* INPUT:
-* chan_num - TWSI channel
-* frequency - TWSI frequency in KHz. (up to 100_kHZ)
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* Actual frequency.
-*
-*******************************************************************************/
-static uint32_t mv_twsi_init(uint8_t chan_num,
- uint32_t frequency,
- uint32_t Tclk,
- MV_TWSI_ADDR *p_twsi_addr,
- uint8_t general_call_enable)
-{
- uint32_t n, m, freq, margin, min_margin = 0xffffffff;
- uint32_t power;
- uint32_t actual_freq = 0, actual_n = 0, actual_m = 0, val;
-
- if (frequency > 100000)
- die("TWSI frequency is too high!");
-
- DB(mv_os_printf("TWSI: mv_twsi_init - Tclk = %d freq = %d\n", Tclk,
- frequency));
- /* Calucalte N and M for the TWSI clock baud rate */
- for (n = 0; n < 8; n++) {
- for (m = 0; m < 16; m++) {
- power = 2 << n; /* power = 2^(n+1) */
- freq = Tclk / (10 * (m + 1) * power);
- margin = ABS(frequency - freq);
-
- if ((freq <= frequency) && (margin < min_margin)) {
- min_margin = margin;
- actual_freq = freq;
- actual_n = n;
- actual_m = m;
- }
- }
- }
- DB(mv_os_printf("TWSI: mv_twsi_init - act_n %u act_m %u act_freq %u\n",
- actual_n, actual_m, actual_freq));
- /* Reset the TWSI logic */
- twsi_reset(chan_num);
-
- /* Set the baud rate */
- val = ((actual_m << TWSI_BAUD_RATE_M_OFFS) |
- actual_n << TWSI_BAUD_RATE_N_OFFS);
- mrvl_reg_write(TWSI_STATUS_BAUDE_RATE_REG(chan_num), val);
-
- /* Enable the TWSI and slave */
- mrvl_reg_write(TWSI_CONTROL_REG(chan_num),
- TWSI_CONTROL_ENA | TWSI_CONTROL_ACK);
-
- /* set the TWSI slave address */
- if (p_twsi_addr->type == ADDR10_BIT) {
- /* writing the 2 most significant bits of the 10 bit address */
- val = ((p_twsi_addr->address & TWSI_SLAVE_ADDR_10_BIT_MASK) >>
- TWSI_SLAVE_ADDR_10_BIT_OFFS);
- /* bits 7:3 must be 0x11110 */
- val |= TWSI_SLAVE_ADDR_10_BIT_CONST;
- /* set GCE bit */
- if (general_call_enable)
- val |= TWSI_SLAVE_ADDR_GCE_ENA;
- /* write slave address */
- mrvl_reg_write(TWSI_SLAVE_ADDR_REG(chan_num), val);
-
- /* writing the 8 least significant bits of the 10 bit address */
- val = (p_twsi_addr->address << TWSI_EXTENDED_SLAVE_OFFS) &
- TWSI_EXTENDED_SLAVE_MASK;
- mrvl_reg_write(TWSI_EXTENDED_SLAVE_ADDR_REG(chan_num), val);
- } else {
- /* set the 7 Bits address */
- mrvl_reg_write(TWSI_EXTENDED_SLAVE_ADDR_REG(chan_num), 0x0);
- val = (p_twsi_addr->address << TWSI_SLAVE_ADDR_7_BIT_OFFS) &
- TWSI_SLAVE_ADDR_7_BIT_MASK;
- mrvl_reg_write(TWSI_SLAVE_ADDR_REG(chan_num), val);
- }
-
- /* unmask twsi int */
- mrvl_reg_bit_set(TWSI_CONTROL_REG(chan_num), TWSI_CONTROL_INT_ENA);
-
- /* unmask twsi int in Interrupt source control register */
- mrvl_reg_bit_set(CPU_INT_SOURCE_CONTROL_REG(
- CPU_MAIN_INT_CAUSE_TWSI(chan_num)), (
- 1 << CPU_INT_SOURCE_CONTROL_IRQ_OFFS));
-
- /* Add delay of 1ms */
- mdelay(1);
-
- return actual_freq;
-}
-
-/*******************************************************************************
-* twsi_sts_get - Get the TWSI status value.
-*
-* DESCRIPTION:
-* This routine returns the TWSI status value.
-*
-* INPUT:
-* chan_num - TWSI channel
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* uint32_t - the TWSI status.
-*
-*******************************************************************************/
-static uint32_t twsi_sts_get(uint8_t chan_num)
-{
- return mrvl_reg_read(TWSI_STATUS_BAUDE_RATE_REG(chan_num));
-}
-
-/*******************************************************************************
-* twsi_reset - Reset the TWSI.
-*
-* DESCRIPTION:
-* Resets the TWSI logic and sets all TWSI registers to their reset values.
-*
-* INPUT:
-* chan_num - TWSI channel
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* None
-*
-*******************************************************************************/
-static void twsi_reset(uint8_t chan_num)
-{
- /* Reset the TWSI logic */
- mrvl_reg_write(TWSI_SOFT_RESET_REG(chan_num), 0);
-
- /* wait for 2 mili sec */
- mdelay(2);
-}
-
-/*******************************************************************************
-* mv_twsi_addr_set - Set address on TWSI bus.
-*
-* DESCRIPTION:
-* This function Set address (7 or 10 Bit address) on the Twsi Bus.
-*
-* INPUT:
-* chan_num - TWSI channel
-* p_twsi_addr - twsi address.
-* command - read / write .
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* MV_OK - if setting the address completed successfully.
-* MV_FAIL otherwmise.
-*
-*******************************************************************************/
-static int mv_twsi_addr_set(uint8_t chan_num,
- MV_TWSI_ADDR *p_twsi_addr,
- MV_TWSI_CMD command)
-{
- DB(mv_os_printf(
- "TWSI: mv_twsi_addr7_bit_set addr %x , type %d, cmd is %s\n",
- p_twsi_addr->address, p_twsi_addr->type,
- ((command == MV_TWSI_WRITE) ? "Write" : "Read")));
- /* 10 Bit address */
- if (p_twsi_addr->type == ADDR10_BIT)
- return twsi_addr10_bit_set(chan_num, p_twsi_addr->address,
- command);
- /* 7 Bit address */
- else
- return twsi_addr7_bit_set(chan_num, p_twsi_addr->address,
- command);
-}
-
-/*******************************************************************************
-* twsi_addr10_bit_set - Set 10 Bit address on TWSI bus.
-*
-* DESCRIPTION:
-* There are two address phases:
-* 1) Write '11110' to data register bits [7:3] and 10-bit address MSB
-* (bits [9:8]) to data register bits [2:1] plus a write(0) or read(1)
-*bit
-* to the Data register. Then it clears interrupt flag which drive
-* the address on the TWSI bus. The function then waits for interrupt
-* flag to be active and status 0x18 (write) or 0x40 (read) to be set.
-* 2) write the rest of 10-bit address to data register and clears
-* interrupt flag which drive the address on the TWSI bus. The
-* function then waits for interrupt flag to be active and status
-* 0xD0 (write) or 0xE0 (read) to be set.
-*
-* INPUT:
-* chan_num - TWSI channel
-* device_address - twsi address.
-* command - read / write .
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* MV_OK - if setting the address completed successfully.
-* MV_FAIL otherwmise.
-*
-*******************************************************************************/
-static int twsi_addr10_bit_set(uint8_t chan_num,
- uint32_t device_address,
- MV_TWSI_CMD command)
-{
- uint32_t val, timeout;
-
- /* writing the 2 most significant bits of the 10 bit address */
- val = ((device_address & TWSI_DATA_ADDR_10_BIT_MASK) >>
- TWSI_DATA_ADDR_10_BIT_OFFS);
- /* bits 7:3 must be 0x11110 */
- val |= TWSI_DATA_ADDR_10_BIT_CONST;
- /* set command */
- val |= command;
- mrvl_reg_write(TWSI_DATA_REG(chan_num), val);
- /* WA add a delay */
- mdelay(1);
-
- /* clear Int flag */
- twsi_int_flg_clr(chan_num);
-
- /* wait for Int to be Set */
- timeout = 0;
- while (!twsi_main_int_get(chan_num) && (timeout++ < TWSI_TIMEOUT_VALUE))
- ;
-
- /* check for timeout */
- if (MV_TRUE ==
- twsi_timeout_chk(
- timeout, (const char *)"TWSI: addr (10_bit) Int time_out.\n"))
- return MV_TIMEOUT;
-
- /* check the status */
- val = twsi_sts_get(chan_num);
- if ((TWSI_M_LOST_ARB_DUR_AD_OR_DATA_TRA == val) ||
- (TWSI_M_LOST_ARB_DUR_AD_TRA_GNL_CALL_AD_REC_ACK_TRA == val)) {
- DB(mv_os_printf("TWSI: Lost Arb, status %x\n", val));
- return MV_RETRY;
- } else if (((val != TWSI_AD_PLS_RD_BIT_TRA_ACK_REC) &&
- (command == MV_TWSI_READ)) ||
- ((val != TWSI_AD_PLS_WR_BIT_TRA_ACK_REC) &&
- (command == MV_TWSI_WRITE))) {
- mv_os_printf("TWSI: status %x 1st addr (10 Bit) in %s mode.\n",
- val,
- ((command == MV_TWSI_WRITE) ? "Write" : "Read"));
- return MV_FAIL;
- }
-
- /* set 8 LSB of the address */
- val = (device_address << TWSI_DATA_ADDR_7_BIT_OFFS) &
- TWSI_DATA_ADDR_7_BIT_MASK;
- mrvl_reg_write(TWSI_DATA_REG(chan_num), val);
-
- /* clear Int flag */
- twsi_int_flg_clr(chan_num);
-
- /* wait for Int to be Set */
- timeout = 0;
- while (!twsi_main_int_get(chan_num) && (timeout++ < TWSI_TIMEOUT_VALUE))
- ;
-
- /* check for timeout */
- if (MV_TRUE ==
- twsi_timeout_chk(timeout,
- (const char *)"TWSI: 2nd (10 Bit) Int tim_out.\n"))
- return MV_TIMEOUT;
-
- /* check the status */
- val = twsi_sts_get(chan_num);
- if ((TWSI_M_LOST_ARB_DUR_AD_OR_DATA_TRA == val) ||
- (TWSI_M_LOST_ARB_DUR_AD_TRA_GNL_CALL_AD_REC_ACK_TRA == val)) {
- DB(mv_os_printf("TWSI: Lost Arb, status %x\n", val));
- return MV_RETRY;
- } else if (((val != TWSI_SEC_AD_PLS_RD_BIT_TRA_ACK_REC) &&
- (command == MV_TWSI_READ)) ||
- ((val != TWSI_SEC_AD_PLS_WR_BIT_TRA_ACK_REC) &&
- (command == MV_TWSI_WRITE))) {
- mv_os_printf("TWSI: status %x 2nd addr(10 Bit) in %s mode.\n",
- val,
- ((command == MV_TWSI_WRITE) ? "Write" : "Read"));
- return MV_FAIL;
- }
-
- return MV_OK;
-}
-
-/*******************************************************************************
-* twsi_addr7_bit_set - Set 7 Bit address on TWSI bus.
-*
-* DESCRIPTION:
-* This function writes 7 bit address plus a write or read bit to the
-* Data register. Then it clears interrupt flag which drive the address on
-* the TWSI bus. The function then waits for interrupt flag to be active
-* and status 0x18 (write) or 0x40 (read) to be set.
-*
-* INPUT:
-* chan_num - TWSI channel
-* device_address - twsi address.
-* command - read / write .
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* MV_OK - if setting the address completed successfully.
-* MV_FAIL otherwmise.
-*
-*******************************************************************************/
-static int twsi_addr7_bit_set(uint8_t chan_num,
- uint32_t device_address,
- MV_TWSI_CMD command)
-{
- uint32_t val, timeout;
-
- /* set the address */
- val = (device_address << TWSI_DATA_ADDR_7_BIT_OFFS) &
- TWSI_DATA_ADDR_7_BIT_MASK;
- /* set command */
- val |= command;
- mrvl_reg_write(TWSI_DATA_REG(chan_num), val);
- /* WA add a delay */
- mdelay(1);
-
- /* clear Int flag */
- twsi_int_flg_clr(chan_num);
-
- /* wait for Int to be Set */
- timeout = 0;
- while (!twsi_main_int_get(chan_num) && (timeout++ < TWSI_TIMEOUT_VALUE))
- ;
-
- /* check for timeout */
- if (MV_TRUE ==
- twsi_timeout_chk(
- timeout, (const char *)"TWSI: Addr (7 Bit) int time_out.\n"))
- return MV_TIMEOUT;
-
- /* check the status */
- val = twsi_sts_get(chan_num);
- if ((TWSI_M_LOST_ARB_DUR_AD_OR_DATA_TRA == val) ||
- (TWSI_M_LOST_ARB_DUR_AD_TRA_GNL_CALL_AD_REC_ACK_TRA == val)) {
- DB(mv_os_printf("TWSI: Lost Arb, status %x\n", val));
- return MV_RETRY;
- } else if (((val != TWSI_AD_PLS_RD_BIT_TRA_ACK_REC) &&
- (command == MV_TWSI_READ)) ||
- ((val != TWSI_AD_PLS_WR_BIT_TRA_ACK_REC) &&
- (command == MV_TWSI_WRITE))) {
- /* only in debug, since in boot we try to read the SPD of both
- DRAM, and we don't
- want error messeges in case DIMM doesn't exist. */
- DB(mv_os_printf(
- "TWSI: status %x addr (7 Bit) in %s mode.\n", val,
- ((command == MV_TWSI_WRITE) ? "Write" : "Read")));
- return MV_FAIL;
- }
-
- return MV_OK;
-}
-
-/*******************************************************************************
-* twsi_data_write - Trnasmit a data block over TWSI bus.
-*
-* DESCRIPTION:
-* This function writes a given data block to TWSI bus in 8 bit
-* granularity.
-* first The function waits for interrupt flag to be active then
-* For each 8-bit data:
-* The function writes data to data register. It then clears
-* interrupt flag which drives the data on the TWSI bus.
-* The function then waits for interrupt flag to be active and status
-* 0x28 to be set.
-*
-*
-* INPUT:
-* chan_num - TWSI channel
-* p_block - Data block.
-* block_size - number of chars in p_block.
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* MV_OK - if transmiting the block completed successfully,
-* MV_BAD_PARAM - if p_block is NULL,
-* MV_FAIL otherwmise.
-*
-*******************************************************************************/
-static int twsi_data_transmit(uint8_t chan_num,
- uint8_t *p_block,
- uint32_t block_size)
-{
- uint32_t timeout, temp, block_size_wr = block_size;
-
- if (NULL == p_block)
- return MV_BAD_PARAM;
-
- /* wait for Int to be Set */
- timeout = 0;
- while (!twsi_main_int_get(chan_num) && (timeout++ < TWSI_TIMEOUT_VALUE))
- ;
-
- /* check for timeout */
- if (MV_TRUE ==
- twsi_timeout_chk(timeout,
- (const char *)"TWSI: Read Data Int time_out.\n"))
- return MV_TIMEOUT;
-
- while (block_size_wr) {
- /* write the data */
- mrvl_reg_write(TWSI_DATA_REG(chan_num), (uint32_t)*p_block);
- DB(mv_os_printf(
- "TWSI: twsi_data_transmit place = %d write %x\n",
- block_size - block_size_wr, *p_block));
- p_block++;
- block_size_wr--;
-
- twsi_int_flg_clr(chan_num);
-
- /* wait for Int to be Set */
- timeout = 0;
- while (!twsi_main_int_get(chan_num) &&
- (timeout++ < TWSI_TIMEOUT_VALUE))
- ;
-
- /* check for timeout */
- if (MV_TRUE == twsi_timeout_chk(
- timeout, (const char *)"TWSI: time_out.\n"))
- return MV_TIMEOUT;
-
- /* check the status */
- temp = twsi_sts_get(chan_num);
- if ((TWSI_M_LOST_ARB_DUR_AD_OR_DATA_TRA == temp) ||
- (TWSI_M_LOST_ARB_DUR_AD_TRA_GNL_CALL_AD_REC_ACK_TRA ==
- temp)) {
- DB(mv_os_printf("TWSI: Lost Arb, status %x\n", temp));
- return MV_RETRY;
- } else if (temp != TWSI_M_TRAN_DATA_BYTE_ACK_REC) {
- mv_os_printf("TWSI: status %x in write trans\n", temp);
- return MV_FAIL;
- }
- }
-
- return MV_OK;
-}
-
-/*******************************************************************************
-* twsi_data_receive - Receive data block from TWSI bus.
-*
-* DESCRIPTION:
-* This function receive data block from TWSI bus in 8bit granularity
-* into p_block buffer.
-* first The function waits for interrupt flag to be active then
-* For each 8-bit data:
-* It clears the interrupt flag which allows the next data to be
-* received from TWSI bus.
-* The function waits for interrupt flag to be active,
-* and status reg is 0x50.
-* Then the function reads data from data register, and copies it to
-* the given buffer.
-*
-* INPUT:
-* chan_num - TWSI channel
-* block_size - number of bytes to read.
-*
-* OUTPUT:
-* p_block - Data block.
-*
-* RETURN:
-* MV_OK - if receive transaction completed successfully,
-* MV_BAD_PARAM - if p_block is NULL,
-* MV_FAIL otherwmise.
-*
-*******************************************************************************/
-static int twsi_data_receive(uint8_t chan_num,
- uint8_t *p_block,
- uint32_t block_size)
-{
- uint32_t timeout, temp, block_size_rd = block_size;
-
- if (NULL == p_block)
- return MV_BAD_PARAM;
-
- /* wait for Int to be Set */
- timeout = 0;
- while (!twsi_main_int_get(chan_num) && (timeout++ < TWSI_TIMEOUT_VALUE))
- ;
-
- /* check for timeout */
- if (MV_TRUE ==
- twsi_timeout_chk(timeout,
- (const char *)"TWSI: Read Data int Time out .\n"))
- return MV_TIMEOUT;
-
- while (block_size_rd) {
- if (block_size_rd == 1)
- /* clear ack and Int flag */
- mrvl_reg_bit_reset(
- TWSI_CONTROL_REG(chan_num), TWSI_CONTROL_ACK);
-
- twsi_int_flg_clr(chan_num);
- /* wait for Int to be Set */
- timeout = 0;
- while ((!twsi_main_int_get(chan_num)) &&
- (timeout++ < TWSI_TIMEOUT_VALUE))
- ;
-
- /* check for timeout */
- if (MV_TRUE ==
- twsi_timeout_chk(timeout, (const char *)"TWSI: Timeout.\n"))
- return MV_TIMEOUT;
-
- /* check the status */
- temp = twsi_sts_get(chan_num);
- if ((TWSI_M_LOST_ARB_DUR_AD_OR_DATA_TRA == temp) ||
- (TWSI_M_LOST_ARB_DUR_AD_TRA_GNL_CALL_AD_REC_ACK_TRA ==
- temp)) {
- DB(mv_os_printf("TWSI: Lost Arb, status %x\n", temp));
- return MV_RETRY;
- } else if ((temp != TWSI_M_REC_RD_DATA_ACK_TRA) &&
- (block_size_rd != 1)) {
- mv_os_printf("TWSI: status %x in read trans\n", temp);
- return MV_FAIL;
- } else if ((temp != TWSI_M_REC_RD_DATA_ACK_NOT_TRA) &&
- (block_size_rd == 1)) {
- mv_os_printf("TWSI: status %x in Rd Terminate\n", temp);
- return MV_FAIL;
- }
-
- /* read the data */
- *p_block = (uint8_t)mrvl_reg_read(TWSI_DATA_REG(chan_num));
- DB(mv_os_printf("TWSI: twsi_data_receive place %d read %x\n",
- block_size - block_size_rd, *p_block));
- p_block++;
- block_size_rd--;
- }
-
- return MV_OK;
-}
-
-/*******************************************************************************
-* twsi_target_offs_set - Set TWST target offset on TWSI bus.
-*
-* DESCRIPTION:
-* The function support TWSI targets that have inside address space (for
-* example EEPROMs). The function:
-* 1) Convert the given offset into p_block and size.
-* in case the offset should be set to a TWSI slave which support
-* more then 256 bytes offset, the offset setting will be done
-* in 2 transactions.
-* 2) Use twsi_data_transmit to place those on the bus.
-*
-* INPUT:
-* chan_num - TWSI channel
-* offset - offset to be set on the EEPROM device.
-* more_than256 - whether the EEPROM device support more then 256 byte
-*offset.
-*
-* OUTPUT:
-* None.
-*
-* RETURN:
-* MV_OK - if setting the offset completed successfully.
-* MV_FAIL otherwmise.
-*
-*******************************************************************************/
-static int twsi_target_offs_set(uint8_t chan_num,
- uint32_t offset,
- uint8_t more_than256)
-{
- uint8_t off_block[2];
- uint32_t off_size;
-
- if (more_than256 == MV_TRUE) {
- off_block[0] = (offset >> 8) & 0xff;
- off_block[1] = offset & 0xff;
- off_size = 2;
- } else {
- off_block[0] = offset & 0xff;
- off_size = 1;
- }
- DB(mv_os_printf(
- "TWSI: twsi_target_offs_set off_size = %x addr1 = %x addr2 = %x\n",
- off_size, off_block[0], off_block[1]));
- return twsi_data_transmit(chan_num, off_block, off_size);
-}
-
-/*******************************************************************************
-* mv_twsi_read - Read data block from a TWSI Slave.
-*
-* DESCRIPTION:
-* The function calls the following functions:
-* -) mv_twsi_start_bit_set();
-* if (EEPROM device)
-* -) mv_twsi_addr_set(w);
-* -) twsi_target_offs_set();
-* -) mv_twsi_start_bit_set();
-* -) mv_twsi_addr_set(r);
-* -) twsi_data_receive();
-* -) mv_twsi_stop_bit_set();
-*
-* INPUT:
-* chan_num - TWSI channel
-* p_twsi_slave - Twsi Slave structure.
-* block_size - number of bytes to read.
-*
-* OUTPUT:
-* p_block - Data block.
-*
-* RETURN:
-* MV_OK - if EEPROM read transaction completed successfully,
-* MV_BAD_PARAM - if p_block is NULL,
-* MV_FAIL otherwmise.
-*
-*******************************************************************************/
-static int mv_twsi_read(uint8_t chan_num,
- MV_TWSI_SLAVE *p_twsi_slave,
- uint8_t *p_block,
- uint32_t block_size)
-{
- int rc;
- int ret = MV_FAIL;
- uint32_t counter = 0;
-
- if ((NULL == p_block) || (NULL == p_twsi_slave))
- return MV_BAD_PARAM;
-
- do {
- /* wait for 1 mili sec for the clear to take effect */
- if (counter > 0)
- mdelay(1);
- ret = mv_twsi_start_bit_set(chan_num);
-
- if (MV_RETRY == ret)
- continue;
- else if (MV_OK != ret) {
- mv_twsi_stop_bit_set(chan_num);
- DB(mv_os_printf(
- "mv_twsi_read:mv_twsi_start_bit_set failed\n"));
- return MV_FAIL;
- }
-
- DB(mv_os_printf(
- "TWSI: mv_twsi_eeprom_read after mv_twsi_start_bit_set\n"));
-
- /* in case offset exsist (i.e. eeprom ) */
- if (MV_TRUE == p_twsi_slave->valid_offset) {
- rc = mv_twsi_addr_set(chan_num,
- &(p_twsi_slave->slave_addr),
- MV_TWSI_WRITE);
- if (MV_RETRY == rc)
- continue;
- else if (MV_OK != rc) {
- mv_twsi_stop_bit_set(chan_num);
- DB(mv_os_printf(
- "mv_twsi_addr_set(%d,0x%x,%d) rc=%d\n",
- chan_num,
- (uint32_t) &(p_twsi_slave->slave_addr),
- MV_TWSI_WRITE, rc));
- return MV_FAIL;
- }
-
- ret =
- twsi_target_offs_set(chan_num, p_twsi_slave->offset,
- p_twsi_slave->more_than256);
- if (MV_RETRY == ret)
- continue;
- else if (MV_OK != ret) {
- mv_twsi_stop_bit_set(chan_num);
- DB(mv_os_printf(
- "TWSI: twsi_target_offs_set Failed\n"));
- return MV_FAIL;
- }
- DB(mv_os_printf("TWSI: after twsi_target_offs_set\n"));
- ret = mv_twsi_start_bit_set(chan_num);
- if (MV_RETRY == ret)
- continue;
- else if (MV_OK != ret) {
- mv_twsi_stop_bit_set(chan_num);
- DB(mv_os_printf(
- "TWSI: mv_twsi_start_bit_set failed\n"));
- return MV_FAIL;
- }
- DB(mv_os_printf("TWSI: after mv_twsi_start_bit_set\n"));
- }
- ret = mv_twsi_addr_set(chan_num, &(p_twsi_slave->slave_addr),
- MV_TWSI_READ);
- if (MV_RETRY == ret)
- continue;
- else if (MV_OK != ret) {
- mv_twsi_stop_bit_set(chan_num);
- DB(mv_os_printf(
- "mv_twsi_read: mv_twsi_addr_set 2 Failed\n"));
- return MV_FAIL;
- }
- DB(mv_os_printf(
- "TWSI: mv_twsi_eeprom_read after mv_twsi_addr_set\n"));
-
- ret = twsi_data_receive(chan_num, p_block, block_size);
- if (MV_RETRY == ret)
- continue;
- else if (MV_OK != ret) {
- mv_twsi_stop_bit_set(chan_num);
- DB(mv_os_printf(
- "mv_twsi_read: twsi_data_receive Failed\n"));
- return MV_FAIL;
- }
- DB(mv_os_printf(
- "TWSI: mv_twsi_eeprom_read after twsi_data_receive\n"));
-
- ret = mv_twsi_stop_bit_set(chan_num);
- if (MV_RETRY == ret)
- continue;
- else if (MV_OK != ret) {
- DB(mv_os_printf(
- "mv_twsi_read: mv_twsi_stop_bit_set 3 Failed\n"));
- return MV_FAIL;
- }
- counter++;
- } while ((MV_RETRY == ret) && (counter < MAX_RETRY_CNT));
-
- if (counter == MAX_RETRY_CNT)
- DB(mv_os_printf("mv_twsi_write: Retry Expire\n"));
-
- twsi_ack_bit_set(chan_num);
-
- DB(mv_os_printf(
- "TWSI: mv_twsi_eeprom_read after mv_twsi_stop_bit_set\n"));
-
- return MV_OK;
-}
-
-/*******************************************************************************
-* mv_twsi_write - Write data block to a TWSI Slave.
-*
-* DESCRIPTION:
-* The function calls the following functions:
-* -) mv_twsi_start_bit_set();
-* -) mv_twsi_addr_set();
-* -)if (EEPROM device)
-* -) twsi_target_offs_set();
-* -) twsi_data_transmit();
-* -) mv_twsi_stop_bit_set();
-*
-* INPUT:
-* chan_num - TWSI channel
-* eeprom_address - eeprom address.
-* block_size - number of bytes to write.
-* p_block - Data block.
-*
-* OUTPUT:
-* None
-*
-* RETURN:
-* MV_OK - if EEPROM read transaction completed successfully.
-* MV_BAD_PARAM - if p_block is NULL,
-* MV_FAIL otherwmise.
-*
-* NOTE: Part of the EEPROM, required that the offset will be aligned to the
-* max write burst supported.
-*******************************************************************************/
-static int mv_twsi_write(uint8_t chan_num,
- MV_TWSI_SLAVE *p_twsi_slave,
- uint8_t *p_block,
- uint32_t block_size)
-{
- int ret = MV_FAIL;
- uint32_t counter = 0;
-
- if ((NULL == p_block) || (NULL == p_twsi_slave))
- return MV_BAD_PARAM;
-
- do {
- if (counter >
- 0) /* wait for 1 mili sec for the clear to take effect */
- mdelay(1);
- ret = mv_twsi_start_bit_set(chan_num);
-
- if (MV_RETRY == ret)
- continue;
-
- else if (MV_OK != ret) {
- mv_twsi_stop_bit_set(chan_num);
- DB(mv_os_printf(
- "mv_twsi_write: mv_twsi_start_bit_set failed\n"));
- return MV_FAIL;
- }
-
- ret = mv_twsi_addr_set(chan_num, &(p_twsi_slave->slave_addr),
- MV_TWSI_WRITE);
- if (MV_RETRY == ret)
- continue;
- else if (MV_OK != ret) {
- mv_twsi_stop_bit_set(chan_num);
- DB(mv_os_printf(
- "mv_twsi_write: mv_twsi_addr_set failed\n"));
- return MV_FAIL;
- }
-
- /* in case offset exsist (i.e. eeprom ) */
- if (MV_TRUE == p_twsi_slave->valid_offset) {
- ret =
- twsi_target_offs_set(chan_num, p_twsi_slave->offset,
- p_twsi_slave->more_than256);
- if (MV_RETRY == ret)
- continue;
- else if (MV_OK != ret) {
- mv_twsi_stop_bit_set(chan_num);
- DB(mv_os_printf(
- "TWSI: twsi_target_offs_set failed\n"));
- return MV_FAIL;
- }
- }
-
- ret = twsi_data_transmit(chan_num, p_block, block_size);
- if (MV_RETRY == ret)
- continue;
- else if (MV_OK != ret) {
- mv_twsi_stop_bit_set(chan_num);
- DB(mv_os_printf(
- "mv_twsi_write: twsi_data_transmit failed\n"));
- return MV_FAIL;
- }
- ret = mv_twsi_stop_bit_set(chan_num);
- if (MV_RETRY == ret)
- continue;
- else if (MV_OK != ret) {
- DB(mv_os_printf(
- "mv_twsi_write: failed to set stopbit\n"));
- return MV_FAIL;
- }
- counter++;
- } while ((MV_RETRY == ret) && (counter < MAX_RETRY_CNT));
-
- if (counter == MAX_RETRY_CNT)
- DB(mv_os_printf("mv_twsi_write: Retry Expire\n"));
-
- return MV_OK;
-}
-
-static int i2c_init(unsigned bus)
-{
- if (bus >= MAX_I2C_NUM)
- return 1;
-
- if (!m_initialized[bus]) {
- /* TWSI init */
- MV_TWSI_ADDR slave;
-
- slave.type = ADDR7_BIT;
- slave.address = 0;
- mv_twsi_init(bus, TWSI_SPEED, mv_tclk_get(), &slave, 0);
- m_initialized[bus] = 1;
- }
-
- return 0;
-}
-
-static void i2c_reset(unsigned bus)
-{
- if (bus < MAX_I2C_NUM)
- m_initialized[bus] = 0;
-}
-
-int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int seg_count)
-{
- struct i2c_seg *seg = segments;
- int ret = 0;
- MV_TWSI_SLAVE twsi_slave;
-
- if (i2c_init(bus))
- return 1;
-
- while (!ret && seg_count--) {
- twsi_slave.slave_addr.address = seg->chip;
- twsi_slave.slave_addr.type = ADDR7_BIT;
- twsi_slave.more_than256 = MV_FALSE;
- twsi_slave.valid_offset = MV_FALSE;
- if (seg->read)
- ret =
- mv_twsi_read(bus, &twsi_slave, seg->buf, seg->len);
- else
- ret =
- mv_twsi_write(bus, &twsi_slave, seg->buf, seg->len);
- seg++;
- }
-
- if (ret) {
- i2c_reset(bus);
- DB(mv_os_printf("mv_twsi_read/mv_twsi_write failed\n"));
- return 1;
- }
-
- return 0;
-}