aboutsummaryrefslogtreecommitdiff
path: root/src/soc/broadcom/cygnus/i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/broadcom/cygnus/i2c.c')
-rw-r--r--src/soc/broadcom/cygnus/i2c.c266
1 files changed, 0 insertions, 266 deletions
diff --git a/src/soc/broadcom/cygnus/i2c.c b/src/soc/broadcom/cygnus/i2c.c
deleted file mode 100644
index ac431e734a..0000000000
--- a/src/soc/broadcom/cygnus/i2c.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2015 Google 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 <assert.h>
-#include <console/console.h>
-#include <delay.h>
-#include <device/i2c_simple.h>
-#include <soc/i2c.h>
-
-struct cygnus_i2c_regs {
- u32 i2c_con;
- u32 i2c_timing_con;
- u32 i2c_addr;
- u32 i2c_fifo_master;
- u32 i2c_fifo_slave;
- u32 i2c_bit_bang;
- u32 reserved0[(0x30 - 0x18) / 4];
- u32 i2c_master_comm;
- u32 i2c_slave_comm;
- u32 i2c_int_en;
- u32 i2c_int_status;
- u32 i2c_master_data_wr;
- u32 i2c_master_data_rd;
- u32 i2c_slave_data_wr;
- u32 i2c_slave_data_rd;
- u32 reserved1[(0xb0 - 0x50) / 4];
- u32 i2c_timing_con2;
-};
-
-static struct cygnus_i2c_regs *i2c_bus[] = {
- (struct cygnus_i2c_regs *)0x18008000,
- (struct cygnus_i2c_regs *)0x1800b000,
-};
-
-#define I2C_TIMEOUT_US 100000 /* 100ms */
-#define I2C_FIFO_MAX_SIZE 64
-
-#define ETIMEDOUT 1
-#define EINVAL 2
-#define EBUSY 3
-
-/* Configuration (0x0) */
-#define I2C_SMB_RESET (1 << 31)
-#define I2C_SMB_EN (1 << 30)
-
-/* Timing configuration (0x4) */
-#define I2C_MODE_400 (1 << 31)
-
-/* Master FIFO control (0xc) */
-#define I2C_MASTER_RX_FIFO_FLUSH (1 << 31)
-#define I2C_MASTER_TX_FIFO_FLUSH (1 << 30)
-
-/* Master command (0x30) */
-#define I2C_MASTER_START_BUSY (1 << 31)
-#define I2C_MASTER_STATUS_SFT 25
-#define I2C_MASTER_STATUS_MASK (0x7 << I2C_MASTER_STATUS_SFT)
-#define I2C_MASTER_PROT_SFT 9
-#define I2C_MASTER_PROT_BLK_WR (0x7 << I2C_MASTER_PROT_SFT)
-#define I2C_MASTER_PROT_BLK_RD (0x8 << I2C_MASTER_PROT_SFT)
-
-/* Master data write (0x40) */
-#define I2C_MASTER_WR_STATUS (1 << 31)
-
-/* Master data read (0x44) */
-#define I2C_MASTER_RD_DATA_MASK 0xff
-
-static unsigned int i2c_bus_busy(struct cygnus_i2c_regs *reg_addr)
-{
- return read32(&reg_addr->i2c_master_comm) & I2C_MASTER_START_BUSY;
-}
-
-static int i2c_wait_bus_busy(struct cygnus_i2c_regs *reg_addr)
-{
- int timeout = I2C_TIMEOUT_US;
- while (timeout--) {
- if (!i2c_bus_busy(reg_addr))
- break;
- udelay(1);
- }
-
- if (timeout <= 0)
- return ETIMEDOUT;
-
- return 0;
-}
-
-static void i2c_flush_fifo(struct cygnus_i2c_regs *reg_addr)
-{
- write32(&reg_addr->i2c_fifo_master,
- I2C_MASTER_RX_FIFO_FLUSH | I2C_MASTER_TX_FIFO_FLUSH);
-}
-
-static int i2c_write(struct cygnus_i2c_regs *reg_addr,
- struct i2c_msg *segment)
-{
- uint8_t *data = segment->buf;
- unsigned int val, status;
- int i, ret;
-
- write32(&reg_addr->i2c_master_data_wr, segment->slave << 1);
-
- for (i = 0; i < segment->len; i++) {
- val = data[i];
-
- /* mark the last byte */
- if (i == segment->len - 1)
- val |= I2C_MASTER_WR_STATUS;
-
- write32(&reg_addr->i2c_master_data_wr, val);
- }
- if (segment->len == 0)
- write32(&reg_addr->i2c_master_data_wr, I2C_MASTER_WR_STATUS);
-
- /*
- * Now we can activate the transfer.
- */
- write32(&reg_addr->i2c_master_comm,
- I2C_MASTER_START_BUSY | I2C_MASTER_PROT_BLK_WR);
-
- ret = i2c_wait_bus_busy(reg_addr);
- if (ret) {
- printk(BIOS_ERR, "I2C bus timeout\n");
- goto flush_fifo;
- }
-
- /* check transaction successful */
- status = read32(&reg_addr->i2c_master_comm);
- ret = (status & I2C_MASTER_STATUS_MASK) >> I2C_MASTER_STATUS_SFT;
- if (ret) {
- printk(BIOS_ERR, "I2C write error %u\n", status);
- goto flush_fifo;
- }
-
- return 0;
-
-flush_fifo:
- i2c_flush_fifo(reg_addr);
- return ret;
-}
-
-static int i2c_read(struct cygnus_i2c_regs *reg_addr, struct i2c_msg *segment)
-{
- uint8_t *data = segment->buf;
- int i, ret;
- unsigned int status;
-
- write32(&reg_addr->i2c_master_data_wr, segment->slave << 1 | 1);
-
- /*
- * Now we can activate the transfer. Specify the number of bytes to read
- */
- write32(&reg_addr->i2c_master_comm,
- I2C_MASTER_START_BUSY | I2C_MASTER_PROT_BLK_RD | segment->len);
-
- ret = i2c_wait_bus_busy(reg_addr);
- if (ret) {
- printk(BIOS_ERR, "I2C bus timeout\n");
- goto flush_fifo;
- }
-
- /* check transaction successful */
- status = read32(&reg_addr->i2c_master_comm);
- ret = (status & I2C_MASTER_STATUS_MASK) >> I2C_MASTER_STATUS_SFT;
- if (ret) {
- printk(BIOS_ERR, "I2C read error %u\n", status);
- goto flush_fifo;
- }
-
- for (i = 0; i < segment->len; i++)
- data[i] = read32(&reg_addr->i2c_master_data_rd) &
- I2C_MASTER_RD_DATA_MASK;
-
- return 0;
-
-flush_fifo:
- i2c_flush_fifo(reg_addr);
- return ret;
-}
-
-static int i2c_do_xfer(struct cygnus_i2c_regs *reg_addr,
- struct i2c_msg *segment)
-{
- int ret;
-
- if (segment->len > I2C_FIFO_MAX_SIZE - 1) {
- printk(BIOS_ERR,
- "I2C transfer error: segment size (%d) is larger than limit (%d)\n",
- segment->len, I2C_FIFO_MAX_SIZE);
- return EINVAL;
- }
-
- if (i2c_bus_busy(reg_addr)) {
- printk(BIOS_WARNING, "I2C transfer error: bus is busy\n");
- return EBUSY;
- }
-
- if (segment->flags & I2C_M_RD)
- ret = i2c_read(reg_addr, segment);
- else
- ret = i2c_write(reg_addr, segment);
-
- return ret;
-}
-
-int platform_i2c_transfer(unsigned bus, struct i2c_msg *segments,
- int seg_count)
-{
- int i;
- int res = 0;
- struct cygnus_i2c_regs *regs = i2c_bus[bus];
- struct i2c_msg *seg = segments;
-
- for (i = 0; i < seg_count; i++, seg++) {
- res = i2c_do_xfer(regs, seg);
- if (res)
- break;
- }
- return res;
-}
-
-void i2c_init(unsigned int bus, unsigned int hz)
-{
- struct cygnus_i2c_regs *regs = i2c_bus[bus];
-
- assert(bus >= 0 && bus <= 1);
-
- setbits_le32(&regs->i2c_con, I2C_SMB_RESET);
- udelay(100); /* wait 100 usec per spec */
- clrbits_le32(&regs->i2c_con, I2C_SMB_RESET);
-
- switch (hz) {
- case 100000:
- clrbits_le32(&regs->i2c_timing_con, I2C_MODE_400);
- break;
- case 400000:
- setbits_le32(&regs->i2c_timing_con, I2C_MODE_400);
- break;
- default:
- printk(BIOS_ERR, "I2C bus does not support frequency %d Hz\n",
- hz);
- break;
- }
-
- i2c_flush_fifo(regs);
-
- /* disable all interrupts */
- write32(&regs->i2c_int_en, 0);
-
- /* clear all pending interrupts */
- write32(&regs->i2c_int_status, 0xffffffff);
-
- write32(&regs->i2c_con, I2C_SMB_EN);
-}