// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2014 MediaTek Inc.
* Author: Xudong Chen <xudong.chen@mediatek.com>
*/
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/scatterlist.h>
#include <linux/sched.h>
#include <linux/slab.h>
#define I2C_RS_TRANSFER (1 << 4)
#define I2C_ARB_LOST (1 << 3)
#define I2C_HS_NACKERR (1 << 2)
#define I2C_ACKERR (1 << 1)
#define I2C_TRANSAC_COMP (1 << 0)
#define I2C_TRANSAC_START (1 << 0)
#define I2C_RS_MUL_CNFG (1 << 15)
#define I2C_RS_MUL_TRIG (1 << 14)
#define I2C_DCM_DISABLE 0x0000
#define I2C_IO_CONFIG_OPEN_DRAIN 0x0003
#define I2C_IO_CONFIG_PUSH_PULL 0x0000
#define I2C_SOFT_RST 0x0001
#define I2C_FIFO_ADDR_CLR 0x0001
#define I2C_DELAY_LEN 0x0002
#define I2C_TIME_CLR_VALUE 0x0000
#define I2C_TIME_DEFAULT_VALUE 0x0003
#define I2C_WRRD_TRANAC_VALUE 0x0002
#define I2C_RD_TRANAC_VALUE 0x0001
#define I2C_SCL_MIS_COMP_VALUE 0x0000
#define I2C_DMA_CON_TX 0x0000
#define I2C_DMA_CON_RX 0x0001
#define I2C_DMA_START_EN 0x0001
#define I2C_DMA_INT_FLAG_NONE 0x0000
#define I2C_DMA_CLR_FLAG 0x0000
#define I2C_DMA_HARD_RST 0x0002
#define I2C_DMA_4G_MODE 0x0001
#define MAX_SAMPLE_CNT_DIV 8
#define MAX_STEP_CNT_DIV 64
#define MAX_CLOCK_DIV 256
#define MAX_HS_STEP_CNT_DIV 8
#define I2C_STANDARD_MODE_BUFFER (1000 / 2)
#define I2C_FAST_MODE_BUFFER (300 / 2)
#define I2C_FAST_MODE_PLUS_BUFFER (20 / 2)
#define I2C_CONTROL_RS (0x1 << 1)
#define I2C_CONTROL_DMA_EN (0x1 << 2)
#define I2C_CONTROL_CLK_EXT_EN (0x1 << 3)
#define I2C_CONTROL_DIR_CHANGE (0x1 << 4)
#define I2C_CONTROL_ACKERR_DET_EN (0x1 << 5)
#define I2C_CONTROL_TRANSFER_LEN_CHANGE (0x1 << 6)
#define I2C_CONTROL_DMAACK_EN (0x1 << 8)
#define I2C_CONTROL_ASYNC_MODE (0x1 << 9)
#define I2C_CONTROL_WRAPPER (0x1 << 0)
#define I2C_DRV_NAME "i2c-mt65xx"
enum DMA_REGS_OFFSET {
OFFSET_INT_FLAG = 0x0,
OFFSET_INT_EN = 0x04,
OFFSET_EN = 0x08,
OFFSET_RST = 0x0c,
OFFSET_CON = 0x18,
OFFSET_TX_MEM_ADDR = 0x1c,
OFFSET_RX_MEM_ADDR = 0x20,
OFFSET_TX_LEN = 0x24,
OFFSET_RX_LEN = 0x28,
OFFSET_TX_4G_MODE = 0x54,
OFFSET_RX_4G_MODE = 0x58,
};
enum i2c_trans_st_rs {
I2C_TRANS_STOP = 0,
I2C_TRANS_REPEATED_START,
};
enum mtk_trans_op {
I2C_MASTER_WR = 1,
I2C_MASTER_RD,
I2C_MASTER_WRRD,
};
enum I2C_REGS_OFFSET {
OFFSET_DATA_PORT,
OFFSET_SLAVE_ADDR,
OFFSET_INTR_MASK,
OFFSET_INTR_STAT,
OFFSET_CONTROL,
OFFSET_TRANSFER_LEN,
OFFSET_TRANSAC_LEN,
OFFSET_DELAY_LEN,
OFFSET_TIMING,
OFFSET_START,
OFFSET_EXT_CONF,
OFFSET_FIFO_STAT,
OFFSET_FIFO_THRESH,
OFFSET_FIFO_ADDR_CLR,
OFFSET_IO_CONFIG,
OFFSET_RSV_DEBUG,
OFFSET_HS,
OFFSET_SOFTRESET,
OFFSET_DCM_EN,
OFFSET_PATH_DIR,
OFFSET_DEBUGSTAT,
OFFSET_DEBUGCTRL,
OFFSET_TRANSFER_LEN_AUX,
OFFSET_CLOCK_DIV,
OFFSET_LTIMING,
OFFSET_SCL_HIGH_LOW_RATIO,
OFFSET_HS_SCL_HIGH_LOW_RATIO,
OFFSET_SCL_MIS_COMP_POINT,
OFFSET_STA_STO_AC_TIMING,
OFFSET_HS_STA_STO_AC_TIMING,
OFFSET_SDA_TIMING,
};
static const u16