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

// SPDX-License-Identifier: GPL-2.0+
/*
 *	Copyright (C) 2002 Motorola GSG-China
 *
 * Author:
 *	Darius Augulis, Teltonika Inc.
 *
 * Desc.:
 *	Implementation of I2C Adapter/Algorithm Driver
 *	for I2C Bus integrated in Freescale i.MX/MXC processors
 *
 *	Derived from Motorola GSG China I2C example driver
 *
 *	Copyright (C) 2005 Torsten Koschorrek <koschorrek at synertronixx.de
 *	Copyright (C) 2005 Matthias Blaschke <blaschke at synertronixx.de
 *	Copyright (C) 2007 RightHand Technologies, Inc.
 *	Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt>
 *
 *	Copyright 2013 Freescale Semiconductor, Inc.
 *	Copyright 2020 NXP
 *
 */

#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/dmapool.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/hrtimer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_dma.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_data/i2c-imx.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/sched.h>
#include <linux/slab.h>

/* This will be the driver name the kernel reports */
#define DRIVER_NAME

#define I2C_IMX_CHECK_DELAY

/*
 * Enable DMA if transfer byte size is bigger than this threshold.
 * As the hardware request, it must bigger than 4 bytes.\
 * I have set '16' here, maybe it's not the best but I think it's
 * the appropriate.
 */
#define DMA_THRESHOLD
#define DMA_TIMEOUT

/* IMX I2C registers:
 * the I2C register offset is different between SoCs,
 * to provide support for all these chips, split the
 * register offset into a fixed base address and a
 * variable shift value, then the full register offset
 * will be calculated by
 * reg_off = ( reg_base_addr << reg_shift)
 */
#define IMX_I2C_IADR
#define IMX_I2C_IFDR
#define IMX_I2C_I2CR
#define IMX_I2C_I2SR
#define IMX_I2C_I2DR

/*
 * All of the layerscape series SoCs support IBIC register.
 */
#define IMX_I2C_IBIC

#define IMX_I2C_REGSHIFT
#define VF610_I2C_REGSHIFT

/* Bits of IMX I2C registers */
#define I2SR_RXAK
#define I2SR_IIF
#define I2SR_SRW
#define I2SR_IAL
#define I2SR_IBB
#define I2SR_IAAS
#define I2SR_ICF
#define I2CR_DMAEN
#define I2CR_RSTA
#define I2CR_TXAK
#define I2CR_MTX
#define I2CR_MSTA
#define I2CR_IIEN
#define I2CR_IEN
#define IBIC_BIIE

/* register bits different operating codes definition:
 * 1) I2SR: Interrupt flags clear operation differ between SoCs:
 * - write zero to clear(w0c) INT flag on i.MX,
 * - but write one to clear(w1c) INT flag on Vybrid.
 * 2) I2CR: I2C module enable operation also differ between SoCs:
 * - set I2CR_IEN bit enable the module on i.MX,
 * - but clear I2CR_IEN bit enable the module on Vybrid.
 */
#define I2SR_CLR_OPCODE_W0C
#define I2SR_CLR_OPCODE_W1C
#define I2CR_IEN_OPCODE_0
#define I2CR_IEN_OPCODE_1

#define I2C_PM_TIMEOUT

/*
 * sorted list of clock divider, register value pairs
 * taken from table 26-5, p.26-9, Freescale i.MX
 * Integrated Portable System Processor Reference Manual
 * Document Number: MC9328MXLRM, Rev. 5.1, 06/2007
 *
 * Duplicated divider values removed from list
 */
struct imx_i2c_clk_pair {};

static struct imx_i2c_clk_pair imx_i2c_clk_div[] =;

/* Vybrid VF610 clock divider, register value pairs */
static struct imx_i2c_clk_pair vf610_i2c_clk_div[] =;

enum imx_i2c_type {};

struct imx_i2c_hwdata {};

struct imx_i2c_dma {};

struct imx_i2c_struct {};

static const struct imx_i2c_hwdata imx1_i2c_hwdata =;

static const struct imx_i2c_hwdata imx21_i2c_hwdata =;

static const struct imx_i2c_hwdata imx6_i2c_hwdata =;

static struct imx_i2c_hwdata vf610_i2c_hwdata =;

static const struct platform_device_id imx_i2c_devtype[] =;
MODULE_DEVICE_TABLE(platform, imx_i2c_devtype);

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

static const struct acpi_device_id i2c_imx_acpi_ids[] =;
MODULE_DEVICE_TABLE(acpi, i2c_imx_acpi_ids);

static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx)
{}

static inline int is_vf610_i2c(struct imx_i2c_struct *i2c_imx)
{}

static inline void imx_i2c_write_reg(unsigned int val,
		struct imx_i2c_struct *i2c_imx, unsigned int reg)
{}

static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,
		unsigned int reg)
{}

static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits)
{}

/* Set up i2c controller register and i2c status register to default value. */
static void i2c_imx_reset_regs(struct imx_i2c_struct *i2c_imx)
{}

/* Functions for DMA support */
static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
						dma_addr_t phy_addr)
{}

static void i2c_imx_dma_callback(void *arg)
{}

static int i2c_imx_dma_xfer(struct imx_i2c_struct *i2c_imx,
					struct i2c_msg *msgs)
{}

static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
{}

static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic)
{}

static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)
{}

static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
{}

static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
			    unsigned int i2c_clk_rate)
{}

static int i2c_imx_clk_notifier_call(struct notifier_block *nb,
				     unsigned long action, void *data)
{}

static int i2c_imx_start(struct imx_i2c_struct *i2c_imx, bool atomic)
{}

static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic)
{}

/*
 * Enable bus idle interrupts
 * Note: IBIC register will be cleared after disabled i2c module.
 * All of layerscape series SoCs support IBIC register.
 */
static void i2c_imx_enable_bus_idle(struct imx_i2c_struct *i2c_imx)
{}

static void i2c_imx_slave_event(struct imx_i2c_struct *i2c_imx,
				enum i2c_slave_event event, u8 *val)
{}

static void i2c_imx_slave_finish_op(struct imx_i2c_struct *i2c_imx)
{}

/* Returns true if the timer should be restarted, false if not. */
static irqreturn_t i2c_imx_slave_handle(struct imx_i2c_struct *i2c_imx,
					unsigned int status, unsigned int ctl)
{}

static enum hrtimer_restart i2c_imx_slave_timeout(struct hrtimer *t)
{}

static void i2c_imx_slave_init(struct imx_i2c_struct *i2c_imx)
{}

static int i2c_imx_reg_slave(struct i2c_client *client)
{}

static int i2c_imx_unreg_slave(struct i2c_client *client)
{}

static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned int status)
{}

static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
{}

static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
					struct i2c_msg *msgs)
{}

static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
			struct i2c_msg *msgs, bool is_lastmsg)
{}

static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
			 bool atomic)
{}

static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
			bool is_lastmsg, bool atomic)
{}

static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
			       struct i2c_msg *msgs, int num, bool atomic)
{}

static int i2c_imx_xfer(struct i2c_adapter *adapter,
			struct i2c_msg *msgs, int num)
{}

static int i2c_imx_xfer_atomic(struct i2c_adapter *adapter,
			       struct i2c_msg *msgs, int num)
{}

/*
 * We switch SCL and SDA to their GPIO function and do some bitbanging
 * for bus recovery. These alternative pinmux settings can be
 * described in the device tree by a separate pinctrl state "gpio". If
 * this is missing this is not a big problem, the only implication is
 * that we can't do bus recovery.
 */
static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
		struct platform_device *pdev)
{}

static u32 i2c_imx_func(struct i2c_adapter *adapter)
{}

static const struct i2c_algorithm i2c_imx_algo =;

static int i2c_imx_probe(struct platform_device *pdev)
{}

static void i2c_imx_remove(struct platform_device *pdev)
{}

static int __maybe_unused i2c_imx_runtime_suspend(struct device *dev)
{}

static int __maybe_unused i2c_imx_runtime_resume(struct device *dev)
{}

static const struct dev_pm_ops i2c_imx_pm_ops =;

static struct platform_driver i2c_imx_driver =;

static int __init i2c_adap_imx_init(void)
{}
subsys_initcall(i2c_adap_imx_init);

static void __exit i2c_adap_imx_exit(void)
{}
module_exit(i2c_adap_imx_exit);

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