linux/drivers/i2c/busses/i2c-exynos5.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * i2c-exynos5.c - Samsung Exynos5 I2C Controller Driver
 *
 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
*/

#include <linux/kernel.h>
#include <linux/module.h>

#include <linux/i2c.h>
#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/spinlock.h>

/*
 * HSI2C controller from Samsung supports 2 modes of operation
 * 1. Auto mode: Where in master automatically controls the whole transaction
 * 2. Manual mode: Software controls the transaction by issuing commands
 *    START, READ, WRITE, STOP, RESTART in I2C_MANUAL_CMD register.
 *
 * Operation mode can be selected by setting AUTO_MODE bit in I2C_CONF register
 *
 * Special bits are available for both modes of operation to set commands
 * and for checking transfer status
 */

/* Register Map */
#define HSI2C_CTL
#define HSI2C_FIFO_CTL
#define HSI2C_TRAILIG_CTL
#define HSI2C_CLK_CTL
#define HSI2C_CLK_SLOT
#define HSI2C_INT_ENABLE
#define HSI2C_INT_STATUS
#define HSI2C_ERR_STATUS
#define HSI2C_FIFO_STATUS
#define HSI2C_TX_DATA
#define HSI2C_RX_DATA
#define HSI2C_CONF
#define HSI2C_AUTO_CONF
#define HSI2C_TIMEOUT
#define HSI2C_MANUAL_CMD
#define HSI2C_TRANS_STATUS
#define HSI2C_TIMING_HS1
#define HSI2C_TIMING_HS2
#define HSI2C_TIMING_HS3
#define HSI2C_TIMING_FS1
#define HSI2C_TIMING_FS2
#define HSI2C_TIMING_FS3
#define HSI2C_TIMING_SLA
#define HSI2C_ADDR

/* I2C_CTL Register bits */
#define HSI2C_FUNC_MODE_I2C
#define HSI2C_MASTER
#define HSI2C_RXCHON
#define HSI2C_TXCHON
#define HSI2C_SW_RST

/* I2C_FIFO_CTL Register bits */
#define HSI2C_RXFIFO_EN
#define HSI2C_TXFIFO_EN
#define HSI2C_RXFIFO_TRIGGER_LEVEL(x)
#define HSI2C_TXFIFO_TRIGGER_LEVEL(x)

/* I2C_TRAILING_CTL Register bits */
#define HSI2C_TRAILING_COUNT

/* I2C_INT_EN Register bits */
#define HSI2C_INT_TX_ALMOSTEMPTY_EN
#define HSI2C_INT_RX_ALMOSTFULL_EN
#define HSI2C_INT_TRAILING_EN

/* I2C_INT_STAT Register bits */
#define HSI2C_INT_TX_ALMOSTEMPTY
#define HSI2C_INT_RX_ALMOSTFULL
#define HSI2C_INT_TX_UNDERRUN
#define HSI2C_INT_TX_OVERRUN
#define HSI2C_INT_RX_UNDERRUN
#define HSI2C_INT_RX_OVERRUN
#define HSI2C_INT_TRAILING
#define HSI2C_INT_I2C

#define HSI2C_INT_TRANS_DONE
#define HSI2C_INT_TRANS_ABORT
#define HSI2C_INT_NO_DEV_ACK
#define HSI2C_INT_NO_DEV
#define HSI2C_INT_TIMEOUT
#define HSI2C_INT_I2C_TRANS

/* I2C_FIFO_STAT Register bits */
#define HSI2C_RX_FIFO_EMPTY
#define HSI2C_RX_FIFO_FULL
#define HSI2C_RX_FIFO_LVL(x)
#define HSI2C_TX_FIFO_EMPTY
#define HSI2C_TX_FIFO_FULL
#define HSI2C_TX_FIFO_LVL(x)

/* I2C_CONF Register bits */
#define HSI2C_AUTO_MODE
#define HSI2C_10BIT_ADDR_MODE
#define HSI2C_HS_MODE

/* I2C_AUTO_CONF Register bits */
#define HSI2C_READ_WRITE
#define HSI2C_STOP_AFTER_TRANS
#define HSI2C_MASTER_RUN

/* I2C_TIMEOUT Register bits */
#define HSI2C_TIMEOUT_EN
#define HSI2C_TIMEOUT_MASK

/* I2C_MANUAL_CMD register bits */
#define HSI2C_CMD_READ_DATA
#define HSI2C_CMD_SEND_STOP

/* I2C_TRANS_STATUS register bits */
#define HSI2C_MASTER_BUSY
#define HSI2C_SLAVE_BUSY

/* I2C_TRANS_STATUS register bits for Exynos5 variant */
#define HSI2C_TIMEOUT_AUTO
#define HSI2C_NO_DEV
#define HSI2C_NO_DEV_ACK
#define HSI2C_TRANS_ABORT
#define HSI2C_TRANS_DONE

/* I2C_TRANS_STATUS register bits for Exynos7 variant */
#define HSI2C_MASTER_ST_MASK
#define HSI2C_MASTER_ST_IDLE
#define HSI2C_MASTER_ST_START
#define HSI2C_MASTER_ST_RESTART
#define HSI2C_MASTER_ST_STOP
#define HSI2C_MASTER_ST_MASTER_ID
#define HSI2C_MASTER_ST_ADDR0
#define HSI2C_MASTER_ST_ADDR1
#define HSI2C_MASTER_ST_ADDR2
#define HSI2C_MASTER_ST_ADDR_SR
#define HSI2C_MASTER_ST_READ
#define HSI2C_MASTER_ST_WRITE
#define HSI2C_MASTER_ST_NO_ACK
#define HSI2C_MASTER_ST_LOSE
#define HSI2C_MASTER_ST_WAIT
#define HSI2C_MASTER_ST_WAIT_CMD

/* I2C_ADDR register bits */
#define HSI2C_SLV_ADDR_SLV(x)
#define HSI2C_SLV_ADDR_MAS(x)
#define HSI2C_MASTER_ID(x)
#define MASTER_ID(x)

#define EXYNOS5_I2C_TIMEOUT

enum i2c_type_exynos {};

struct exynos5_i2c {};

/**
 * struct exynos_hsi2c_variant - platform specific HSI2C driver data
 * @fifo_depth: the fifo depth supported by the HSI2C module
 * @hw: the hardware variant of Exynos I2C controller
 *
 * Specifies platform specific configuration of HSI2C module.
 * Note: A structure for driver specific platform data is used for future
 * expansion of its usage.
 */
struct exynos_hsi2c_variant {};

static const struct exynos_hsi2c_variant exynos5250_hsi2c_data =;

static const struct exynos_hsi2c_variant exynos5260_hsi2c_data =;

static const struct exynos_hsi2c_variant exynos7_hsi2c_data =;

static const struct exynos_hsi2c_variant exynosautov9_hsi2c_data =;

static const struct of_device_id exynos5_i2c_match[] =;
MODULE_DEVICE_TABLE(of, exynos5_i2c_match);

static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c)
{}

/*
 * exynos5_i2c_set_timing: updates the registers with appropriate
 * timing values calculated
 *
 * Timing values for operation are calculated against 100kHz, 400kHz
 * or 1MHz controller operating frequency.
 *
 * Returns 0 on success, -EINVAL if the cycle length cannot
 * be calculated.
 */
static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
{}

static int exynos5_hsi2c_clock_setup(struct exynos5_i2c *i2c)
{}

/*
 * exynos5_i2c_init: configures the controller for I2C functionality
 * Programs I2C controller for Master mode operation
 */
static void exynos5_i2c_init(struct exynos5_i2c *i2c)
{}

static void exynos5_i2c_reset(struct exynos5_i2c *i2c)
{}

/*
 * exynos5_i2c_irq: top level IRQ servicing routine
 *
 * INT_STATUS registers gives the interrupt details. Further,
 * FIFO_STATUS or TRANS_STATUS registers are to be check for detailed
 * state of the bus.
 */
static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
{}

/*
 * exynos5_i2c_wait_bus_idle
 *
 * Wait for the bus to go idle, indicated by the MASTER_BUSY bit being
 * cleared.
 *
 * Returns -EBUSY if the bus cannot be bought to idle
 */
static int exynos5_i2c_wait_bus_idle(struct exynos5_i2c *i2c)
{}

static void exynos5_i2c_bus_recover(struct exynos5_i2c *i2c)
{}

static void exynos5_i2c_bus_check(struct exynos5_i2c *i2c)
{}

/*
 * exynos5_i2c_message_start: Configures the bus and starts the xfer
 * i2c: struct exynos5_i2c pointer for the current bus
 * stop: Enables stop after transfer if set. Set for last transfer of
 *       in the list of messages.
 *
 * Configures the bus for read/write function
 * Sets chip address to talk to, message length to be sent.
 * Enables appropriate interrupts and sends start xfer command.
 */
static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
{}

static bool exynos5_i2c_poll_irqs_timeout(struct exynos5_i2c *i2c,
					  unsigned long timeout)
{}

static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c,
			      struct i2c_msg *msgs, int stop)
{}

static int exynos5_i2c_xfer(struct i2c_adapter *adap,
			struct i2c_msg *msgs, int num)
{}

static int exynos5_i2c_xfer_atomic(struct i2c_adapter *adap,
				   struct i2c_msg *msgs, int num)
{}

static u32 exynos5_i2c_func(struct i2c_adapter *adap)
{}

static const struct i2c_algorithm exynos5_i2c_algorithm =;

static int exynos5_i2c_probe(struct platform_device *pdev)
{}

static void exynos5_i2c_remove(struct platform_device *pdev)
{}

static int exynos5_i2c_suspend_noirq(struct device *dev)
{}

static int exynos5_i2c_resume_noirq(struct device *dev)
{}

static const struct dev_pm_ops exynos5_i2c_dev_pm_ops =;

static struct platform_driver exynos5_i2c_driver =;

module_platform_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_LICENSE();