18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Freescale MXS I2C bus driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2012-2013 Marek Vasut <marex@denx.de>
68c2ecf20Sopenharmony_ci * Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * based on a (non-working) driver which was:
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/slab.h>
148c2ecf20Sopenharmony_ci#include <linux/device.h>
158c2ecf20Sopenharmony_ci#include <linux/module.h>
168c2ecf20Sopenharmony_ci#include <linux/i2c.h>
178c2ecf20Sopenharmony_ci#include <linux/err.h>
188c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
198c2ecf20Sopenharmony_ci#include <linux/completion.h>
208c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
218c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
228c2ecf20Sopenharmony_ci#include <linux/io.h>
238c2ecf20Sopenharmony_ci#include <linux/stmp_device.h>
248c2ecf20Sopenharmony_ci#include <linux/of.h>
258c2ecf20Sopenharmony_ci#include <linux/of_device.h>
268c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
278c2ecf20Sopenharmony_ci#include <linux/dmaengine.h>
288c2ecf20Sopenharmony_ci#include <linux/dma/mxs-dma.h>
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define DRIVER_NAME "mxs-i2c"
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0		(0x00)
338c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0_SET	(0x04)
348c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0_CLR	(0x08)
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0_SFTRST			0x80000000
378c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0_RUN			0x20000000
388c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0_SEND_NAK_ON_LAST		0x02000000
398c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0_PIO_MODE			0x01000000
408c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0_RETAIN_CLOCK		0x00200000
418c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0_POST_SEND_STOP		0x00100000
428c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0_PRE_SEND_START		0x00080000
438c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0_MASTER_MODE		0x00020000
448c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0_DIRECTION			0x00010000
458c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL0_XFER_COUNT(v)		((v) & 0x0000FFFF)
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define MXS_I2C_TIMING0		(0x10)
488c2ecf20Sopenharmony_ci#define MXS_I2C_TIMING1		(0x20)
498c2ecf20Sopenharmony_ci#define MXS_I2C_TIMING2		(0x30)
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL1		(0x40)
528c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL1_SET	(0x44)
538c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL1_CLR	(0x48)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL1_CLR_GOT_A_NAK		0x10000000
568c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL1_BUS_FREE_IRQ		0x80
578c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ	0x40
588c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ		0x20
598c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ	0x10
608c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL1_EARLY_TERM_IRQ		0x08
618c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL1_MASTER_LOSS_IRQ		0x04
628c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL1_SLAVE_STOP_IRQ		0x02
638c2ecf20Sopenharmony_ci#define MXS_I2C_CTRL1_SLAVE_IRQ			0x01
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci#define MXS_I2C_STAT		(0x50)
668c2ecf20Sopenharmony_ci#define MXS_I2C_STAT_GOT_A_NAK			0x10000000
678c2ecf20Sopenharmony_ci#define MXS_I2C_STAT_BUS_BUSY			0x00000800
688c2ecf20Sopenharmony_ci#define MXS_I2C_STAT_CLK_GEN_BUSY		0x00000400
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci#define MXS_I2C_DATA(i2c)	((i2c->dev_type == MXS_I2C_V1) ? 0x60 : 0xa0)
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#define MXS_I2C_DEBUG0_CLR(i2c)	((i2c->dev_type == MXS_I2C_V1) ? 0x78 : 0xb8)
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci#define MXS_I2C_DEBUG0_DMAREQ	0x80000000
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci#define MXS_I2C_IRQ_MASK	(MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | \
778c2ecf20Sopenharmony_ci				 MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ | \
788c2ecf20Sopenharmony_ci				 MXS_I2C_CTRL1_EARLY_TERM_IRQ | \
798c2ecf20Sopenharmony_ci				 MXS_I2C_CTRL1_MASTER_LOSS_IRQ | \
808c2ecf20Sopenharmony_ci				 MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \
818c2ecf20Sopenharmony_ci				 MXS_I2C_CTRL1_SLAVE_IRQ)
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci#define MXS_CMD_I2C_SELECT	(MXS_I2C_CTRL0_RETAIN_CLOCK |	\
858c2ecf20Sopenharmony_ci				 MXS_I2C_CTRL0_PRE_SEND_START |	\
868c2ecf20Sopenharmony_ci				 MXS_I2C_CTRL0_MASTER_MODE |	\
878c2ecf20Sopenharmony_ci				 MXS_I2C_CTRL0_DIRECTION |	\
888c2ecf20Sopenharmony_ci				 MXS_I2C_CTRL0_XFER_COUNT(1))
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci#define MXS_CMD_I2C_WRITE	(MXS_I2C_CTRL0_PRE_SEND_START |	\
918c2ecf20Sopenharmony_ci				 MXS_I2C_CTRL0_MASTER_MODE |	\
928c2ecf20Sopenharmony_ci				 MXS_I2C_CTRL0_DIRECTION)
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci#define MXS_CMD_I2C_READ	(MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
958c2ecf20Sopenharmony_ci				 MXS_I2C_CTRL0_MASTER_MODE)
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cienum mxs_i2c_devtype {
988c2ecf20Sopenharmony_ci	MXS_I2C_UNKNOWN = 0,
998c2ecf20Sopenharmony_ci	MXS_I2C_V1,
1008c2ecf20Sopenharmony_ci	MXS_I2C_V2,
1018c2ecf20Sopenharmony_ci};
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci/**
1048c2ecf20Sopenharmony_ci * struct mxs_i2c_dev - per device, private MXS-I2C data
1058c2ecf20Sopenharmony_ci *
1068c2ecf20Sopenharmony_ci * @dev: driver model device node
1078c2ecf20Sopenharmony_ci * @dev_type: distinguish i.MX23/i.MX28 features
1088c2ecf20Sopenharmony_ci * @regs: IO registers pointer
1098c2ecf20Sopenharmony_ci * @cmd_complete: completion object for transaction wait
1108c2ecf20Sopenharmony_ci * @cmd_err: error code for last transaction
1118c2ecf20Sopenharmony_ci * @adapter: i2c subsystem adapter node
1128c2ecf20Sopenharmony_ci */
1138c2ecf20Sopenharmony_cistruct mxs_i2c_dev {
1148c2ecf20Sopenharmony_ci	struct device *dev;
1158c2ecf20Sopenharmony_ci	enum mxs_i2c_devtype dev_type;
1168c2ecf20Sopenharmony_ci	void __iomem *regs;
1178c2ecf20Sopenharmony_ci	struct completion cmd_complete;
1188c2ecf20Sopenharmony_ci	int cmd_err;
1198c2ecf20Sopenharmony_ci	struct i2c_adapter adapter;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	uint32_t timing0;
1228c2ecf20Sopenharmony_ci	uint32_t timing1;
1238c2ecf20Sopenharmony_ci	uint32_t timing2;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	/* DMA support components */
1268c2ecf20Sopenharmony_ci	struct dma_chan			*dmach;
1278c2ecf20Sopenharmony_ci	uint32_t			pio_data[2];
1288c2ecf20Sopenharmony_ci	uint32_t			addr_data;
1298c2ecf20Sopenharmony_ci	struct scatterlist		sg_io[2];
1308c2ecf20Sopenharmony_ci	bool				dma_read;
1318c2ecf20Sopenharmony_ci};
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic int mxs_i2c_reset(struct mxs_i2c_dev *i2c)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	int ret = stmp_reset_block(i2c->regs);
1368c2ecf20Sopenharmony_ci	if (ret)
1378c2ecf20Sopenharmony_ci		return ret;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	/*
1408c2ecf20Sopenharmony_ci	 * Configure timing for the I2C block. The I2C TIMING2 register has to
1418c2ecf20Sopenharmony_ci	 * be programmed with this particular magic number. The rest is derived
1428c2ecf20Sopenharmony_ci	 * from the XTAL speed and requested I2C speed.
1438c2ecf20Sopenharmony_ci	 *
1448c2ecf20Sopenharmony_ci	 * For details, see i.MX233 [25.4.2 - 25.4.4] and i.MX28 [27.5.2 - 27.5.4].
1458c2ecf20Sopenharmony_ci	 */
1468c2ecf20Sopenharmony_ci	writel(i2c->timing0, i2c->regs + MXS_I2C_TIMING0);
1478c2ecf20Sopenharmony_ci	writel(i2c->timing1, i2c->regs + MXS_I2C_TIMING1);
1488c2ecf20Sopenharmony_ci	writel(i2c->timing2, i2c->regs + MXS_I2C_TIMING2);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	return 0;
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_cistatic void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	if (i2c->dma_read) {
1588c2ecf20Sopenharmony_ci		dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
1598c2ecf20Sopenharmony_ci		dma_unmap_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
1608c2ecf20Sopenharmony_ci	} else {
1618c2ecf20Sopenharmony_ci		dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
1628c2ecf20Sopenharmony_ci	}
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_cistatic void mxs_i2c_dma_irq_callback(void *param)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	struct mxs_i2c_dev *i2c = param;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	complete(&i2c->cmd_complete);
1708c2ecf20Sopenharmony_ci	mxs_i2c_dma_finish(i2c);
1718c2ecf20Sopenharmony_ci}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_cistatic int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
1748c2ecf20Sopenharmony_ci			struct i2c_msg *msg, uint32_t flags)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	struct dma_async_tx_descriptor *desc;
1778c2ecf20Sopenharmony_ci	struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	i2c->addr_data = i2c_8bit_addr_from_msg(msg);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	if (msg->flags & I2C_M_RD) {
1828c2ecf20Sopenharmony_ci		i2c->dma_read = true;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci		/*
1858c2ecf20Sopenharmony_ci		 * SELECT command.
1868c2ecf20Sopenharmony_ci		 */
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci		/* Queue the PIO register write transfer. */
1898c2ecf20Sopenharmony_ci		i2c->pio_data[0] = MXS_CMD_I2C_SELECT;
1908c2ecf20Sopenharmony_ci		desc = dmaengine_prep_slave_sg(i2c->dmach,
1918c2ecf20Sopenharmony_ci					(struct scatterlist *)&i2c->pio_data[0],
1928c2ecf20Sopenharmony_ci					1, DMA_TRANS_NONE, 0);
1938c2ecf20Sopenharmony_ci		if (!desc) {
1948c2ecf20Sopenharmony_ci			dev_err(i2c->dev,
1958c2ecf20Sopenharmony_ci				"Failed to get PIO reg. write descriptor.\n");
1968c2ecf20Sopenharmony_ci			goto select_init_pio_fail;
1978c2ecf20Sopenharmony_ci		}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci		/* Queue the DMA data transfer. */
2008c2ecf20Sopenharmony_ci		sg_init_one(&i2c->sg_io[0], &i2c->addr_data, 1);
2018c2ecf20Sopenharmony_ci		dma_map_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
2028c2ecf20Sopenharmony_ci		desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[0], 1,
2038c2ecf20Sopenharmony_ci					DMA_MEM_TO_DEV,
2048c2ecf20Sopenharmony_ci					DMA_PREP_INTERRUPT |
2058c2ecf20Sopenharmony_ci					MXS_DMA_CTRL_WAIT4END);
2068c2ecf20Sopenharmony_ci		if (!desc) {
2078c2ecf20Sopenharmony_ci			dev_err(i2c->dev,
2088c2ecf20Sopenharmony_ci				"Failed to get DMA data write descriptor.\n");
2098c2ecf20Sopenharmony_ci			goto select_init_dma_fail;
2108c2ecf20Sopenharmony_ci		}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci		/*
2138c2ecf20Sopenharmony_ci		 * READ command.
2148c2ecf20Sopenharmony_ci		 */
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci		/* Queue the PIO register write transfer. */
2178c2ecf20Sopenharmony_ci		i2c->pio_data[1] = flags | MXS_CMD_I2C_READ |
2188c2ecf20Sopenharmony_ci				MXS_I2C_CTRL0_XFER_COUNT(msg->len);
2198c2ecf20Sopenharmony_ci		desc = dmaengine_prep_slave_sg(i2c->dmach,
2208c2ecf20Sopenharmony_ci					(struct scatterlist *)&i2c->pio_data[1],
2218c2ecf20Sopenharmony_ci					1, DMA_TRANS_NONE, DMA_PREP_INTERRUPT);
2228c2ecf20Sopenharmony_ci		if (!desc) {
2238c2ecf20Sopenharmony_ci			dev_err(i2c->dev,
2248c2ecf20Sopenharmony_ci				"Failed to get PIO reg. write descriptor.\n");
2258c2ecf20Sopenharmony_ci			goto select_init_dma_fail;
2268c2ecf20Sopenharmony_ci		}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci		/* Queue the DMA data transfer. */
2298c2ecf20Sopenharmony_ci		sg_init_one(&i2c->sg_io[1], msg->buf, msg->len);
2308c2ecf20Sopenharmony_ci		dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
2318c2ecf20Sopenharmony_ci		desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1,
2328c2ecf20Sopenharmony_ci					DMA_DEV_TO_MEM,
2338c2ecf20Sopenharmony_ci					DMA_PREP_INTERRUPT |
2348c2ecf20Sopenharmony_ci					MXS_DMA_CTRL_WAIT4END);
2358c2ecf20Sopenharmony_ci		if (!desc) {
2368c2ecf20Sopenharmony_ci			dev_err(i2c->dev,
2378c2ecf20Sopenharmony_ci				"Failed to get DMA data write descriptor.\n");
2388c2ecf20Sopenharmony_ci			goto read_init_dma_fail;
2398c2ecf20Sopenharmony_ci		}
2408c2ecf20Sopenharmony_ci	} else {
2418c2ecf20Sopenharmony_ci		i2c->dma_read = false;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci		/*
2448c2ecf20Sopenharmony_ci		 * WRITE command.
2458c2ecf20Sopenharmony_ci		 */
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci		/* Queue the PIO register write transfer. */
2488c2ecf20Sopenharmony_ci		i2c->pio_data[0] = flags | MXS_CMD_I2C_WRITE |
2498c2ecf20Sopenharmony_ci				MXS_I2C_CTRL0_XFER_COUNT(msg->len + 1);
2508c2ecf20Sopenharmony_ci		desc = dmaengine_prep_slave_sg(i2c->dmach,
2518c2ecf20Sopenharmony_ci					(struct scatterlist *)&i2c->pio_data[0],
2528c2ecf20Sopenharmony_ci					1, DMA_TRANS_NONE, 0);
2538c2ecf20Sopenharmony_ci		if (!desc) {
2548c2ecf20Sopenharmony_ci			dev_err(i2c->dev,
2558c2ecf20Sopenharmony_ci				"Failed to get PIO reg. write descriptor.\n");
2568c2ecf20Sopenharmony_ci			goto write_init_pio_fail;
2578c2ecf20Sopenharmony_ci		}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci		/* Queue the DMA data transfer. */
2608c2ecf20Sopenharmony_ci		sg_init_table(i2c->sg_io, 2);
2618c2ecf20Sopenharmony_ci		sg_set_buf(&i2c->sg_io[0], &i2c->addr_data, 1);
2628c2ecf20Sopenharmony_ci		sg_set_buf(&i2c->sg_io[1], msg->buf, msg->len);
2638c2ecf20Sopenharmony_ci		dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
2648c2ecf20Sopenharmony_ci		desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2,
2658c2ecf20Sopenharmony_ci					DMA_MEM_TO_DEV,
2668c2ecf20Sopenharmony_ci					DMA_PREP_INTERRUPT |
2678c2ecf20Sopenharmony_ci					MXS_DMA_CTRL_WAIT4END);
2688c2ecf20Sopenharmony_ci		if (!desc) {
2698c2ecf20Sopenharmony_ci			dev_err(i2c->dev,
2708c2ecf20Sopenharmony_ci				"Failed to get DMA data write descriptor.\n");
2718c2ecf20Sopenharmony_ci			goto write_init_dma_fail;
2728c2ecf20Sopenharmony_ci		}
2738c2ecf20Sopenharmony_ci	}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	/*
2768c2ecf20Sopenharmony_ci	 * The last descriptor must have this callback,
2778c2ecf20Sopenharmony_ci	 * to finish the DMA transaction.
2788c2ecf20Sopenharmony_ci	 */
2798c2ecf20Sopenharmony_ci	desc->callback = mxs_i2c_dma_irq_callback;
2808c2ecf20Sopenharmony_ci	desc->callback_param = i2c;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	/* Start the transfer. */
2838c2ecf20Sopenharmony_ci	dmaengine_submit(desc);
2848c2ecf20Sopenharmony_ci	dma_async_issue_pending(i2c->dmach);
2858c2ecf20Sopenharmony_ci	return 0;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci/* Read failpath. */
2888c2ecf20Sopenharmony_ciread_init_dma_fail:
2898c2ecf20Sopenharmony_ci	dma_unmap_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
2908c2ecf20Sopenharmony_ciselect_init_dma_fail:
2918c2ecf20Sopenharmony_ci	dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
2928c2ecf20Sopenharmony_ciselect_init_pio_fail:
2938c2ecf20Sopenharmony_ci	dmaengine_terminate_all(i2c->dmach);
2948c2ecf20Sopenharmony_ci	return -EINVAL;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci/* Write failpath. */
2978c2ecf20Sopenharmony_ciwrite_init_dma_fail:
2988c2ecf20Sopenharmony_ci	dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
2998c2ecf20Sopenharmony_ciwrite_init_pio_fail:
3008c2ecf20Sopenharmony_ci	dmaengine_terminate_all(i2c->dmach);
3018c2ecf20Sopenharmony_ci	return -EINVAL;
3028c2ecf20Sopenharmony_ci}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_cistatic int mxs_i2c_pio_wait_xfer_end(struct mxs_i2c_dev *i2c)
3058c2ecf20Sopenharmony_ci{
3068c2ecf20Sopenharmony_ci	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	while (readl(i2c->regs + MXS_I2C_CTRL0) & MXS_I2C_CTRL0_RUN) {
3098c2ecf20Sopenharmony_ci		if (readl(i2c->regs + MXS_I2C_CTRL1) &
3108c2ecf20Sopenharmony_ci				MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ)
3118c2ecf20Sopenharmony_ci			return -ENXIO;
3128c2ecf20Sopenharmony_ci		if (time_after(jiffies, timeout))
3138c2ecf20Sopenharmony_ci			return -ETIMEDOUT;
3148c2ecf20Sopenharmony_ci		cond_resched();
3158c2ecf20Sopenharmony_ci	}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	return 0;
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic int mxs_i2c_pio_check_error_state(struct mxs_i2c_dev *i2c)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	u32 state;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	state = readl(i2c->regs + MXS_I2C_CTRL1_CLR) & MXS_I2C_IRQ_MASK;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	if (state & MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ)
3278c2ecf20Sopenharmony_ci		i2c->cmd_err = -ENXIO;
3288c2ecf20Sopenharmony_ci	else if (state & (MXS_I2C_CTRL1_EARLY_TERM_IRQ |
3298c2ecf20Sopenharmony_ci			  MXS_I2C_CTRL1_MASTER_LOSS_IRQ |
3308c2ecf20Sopenharmony_ci			  MXS_I2C_CTRL1_SLAVE_STOP_IRQ |
3318c2ecf20Sopenharmony_ci			  MXS_I2C_CTRL1_SLAVE_IRQ))
3328c2ecf20Sopenharmony_ci		i2c->cmd_err = -EIO;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	return i2c->cmd_err;
3358c2ecf20Sopenharmony_ci}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_cistatic void mxs_i2c_pio_trigger_cmd(struct mxs_i2c_dev *i2c, u32 cmd)
3388c2ecf20Sopenharmony_ci{
3398c2ecf20Sopenharmony_ci	u32 reg;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	writel(cmd, i2c->regs + MXS_I2C_CTRL0);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	/* readback makes sure the write is latched into hardware */
3448c2ecf20Sopenharmony_ci	reg = readl(i2c->regs + MXS_I2C_CTRL0);
3458c2ecf20Sopenharmony_ci	reg |= MXS_I2C_CTRL0_RUN;
3468c2ecf20Sopenharmony_ci	writel(reg, i2c->regs + MXS_I2C_CTRL0);
3478c2ecf20Sopenharmony_ci}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci/*
3508c2ecf20Sopenharmony_ci * Start WRITE transaction on the I2C bus. By studying i.MX23 datasheet,
3518c2ecf20Sopenharmony_ci * CTRL0::PIO_MODE bit description clarifies the order in which the registers
3528c2ecf20Sopenharmony_ci * must be written during PIO mode operation. First, the CTRL0 register has
3538c2ecf20Sopenharmony_ci * to be programmed with all the necessary bits but the RUN bit. Then the
3548c2ecf20Sopenharmony_ci * payload has to be written into the DATA register. Finally, the transmission
3558c2ecf20Sopenharmony_ci * is executed by setting the RUN bit in CTRL0.
3568c2ecf20Sopenharmony_ci */
3578c2ecf20Sopenharmony_cistatic void mxs_i2c_pio_trigger_write_cmd(struct mxs_i2c_dev *i2c, u32 cmd,
3588c2ecf20Sopenharmony_ci					  u32 data)
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	writel(cmd, i2c->regs + MXS_I2C_CTRL0);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	if (i2c->dev_type == MXS_I2C_V1)
3638c2ecf20Sopenharmony_ci		writel(MXS_I2C_CTRL0_PIO_MODE, i2c->regs + MXS_I2C_CTRL0_SET);
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	writel(data, i2c->regs + MXS_I2C_DATA(i2c));
3668c2ecf20Sopenharmony_ci	writel(MXS_I2C_CTRL0_RUN, i2c->regs + MXS_I2C_CTRL0_SET);
3678c2ecf20Sopenharmony_ci}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_cistatic int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
3708c2ecf20Sopenharmony_ci			struct i2c_msg *msg, uint32_t flags)
3718c2ecf20Sopenharmony_ci{
3728c2ecf20Sopenharmony_ci	struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
3738c2ecf20Sopenharmony_ci	uint32_t addr_data = i2c_8bit_addr_from_msg(msg);
3748c2ecf20Sopenharmony_ci	uint32_t data = 0;
3758c2ecf20Sopenharmony_ci	int i, ret, xlen = 0, xmit = 0;
3768c2ecf20Sopenharmony_ci	uint32_t start;
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	/* Mute IRQs coming from this block. */
3798c2ecf20Sopenharmony_ci	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_CLR);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	/*
3828c2ecf20Sopenharmony_ci	 * MX23 idea:
3838c2ecf20Sopenharmony_ci	 * - Enable CTRL0::PIO_MODE (1 << 24)
3848c2ecf20Sopenharmony_ci	 * - Enable CTRL1::ACK_MODE (1 << 27)
3858c2ecf20Sopenharmony_ci	 *
3868c2ecf20Sopenharmony_ci	 * WARNING! The MX23 is broken in some way, even if it claims
3878c2ecf20Sopenharmony_ci	 * to support PIO, when we try to transfer any amount of data
3888c2ecf20Sopenharmony_ci	 * that is not aligned to 4 bytes, the DMA engine will have
3898c2ecf20Sopenharmony_ci	 * bits in DEBUG1::DMA_BYTES_ENABLES still set even after the
3908c2ecf20Sopenharmony_ci	 * transfer. This in turn will mess up the next transfer as
3918c2ecf20Sopenharmony_ci	 * the block it emit one byte write onto the bus terminated
3928c2ecf20Sopenharmony_ci	 * with a NAK+STOP. A possible workaround is to reset the IP
3938c2ecf20Sopenharmony_ci	 * block after every PIO transmission, which might just work.
3948c2ecf20Sopenharmony_ci	 *
3958c2ecf20Sopenharmony_ci	 * NOTE: The CTRL0::PIO_MODE description is important, since
3968c2ecf20Sopenharmony_ci	 * it outlines how the PIO mode is really supposed to work.
3978c2ecf20Sopenharmony_ci	 */
3988c2ecf20Sopenharmony_ci	if (msg->flags & I2C_M_RD) {
3998c2ecf20Sopenharmony_ci		/*
4008c2ecf20Sopenharmony_ci		 * PIO READ transfer:
4018c2ecf20Sopenharmony_ci		 *
4028c2ecf20Sopenharmony_ci		 * This transfer MUST be limited to 4 bytes maximum. It is not
4038c2ecf20Sopenharmony_ci		 * possible to transfer more than four bytes via PIO, since we
4048c2ecf20Sopenharmony_ci		 * can not in any way make sure we can read the data from the
4058c2ecf20Sopenharmony_ci		 * DATA register fast enough. Besides, the RX FIFO is only four
4068c2ecf20Sopenharmony_ci		 * bytes deep, thus we can only really read up to four bytes at
4078c2ecf20Sopenharmony_ci		 * time. Finally, there is no bit indicating us that new data
4088c2ecf20Sopenharmony_ci		 * arrived at the FIFO and can thus be fetched from the DATA
4098c2ecf20Sopenharmony_ci		 * register.
4108c2ecf20Sopenharmony_ci		 */
4118c2ecf20Sopenharmony_ci		BUG_ON(msg->len > 4);
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci		/* SELECT command. */
4148c2ecf20Sopenharmony_ci		mxs_i2c_pio_trigger_write_cmd(i2c, MXS_CMD_I2C_SELECT,
4158c2ecf20Sopenharmony_ci					      addr_data);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci		ret = mxs_i2c_pio_wait_xfer_end(i2c);
4188c2ecf20Sopenharmony_ci		if (ret) {
4198c2ecf20Sopenharmony_ci			dev_dbg(i2c->dev,
4208c2ecf20Sopenharmony_ci				"PIO: Failed to send SELECT command!\n");
4218c2ecf20Sopenharmony_ci			goto cleanup;
4228c2ecf20Sopenharmony_ci		}
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci		/* READ command. */
4258c2ecf20Sopenharmony_ci		mxs_i2c_pio_trigger_cmd(i2c,
4268c2ecf20Sopenharmony_ci					MXS_CMD_I2C_READ | flags |
4278c2ecf20Sopenharmony_ci					MXS_I2C_CTRL0_XFER_COUNT(msg->len));
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci		ret = mxs_i2c_pio_wait_xfer_end(i2c);
4308c2ecf20Sopenharmony_ci		if (ret) {
4318c2ecf20Sopenharmony_ci			dev_dbg(i2c->dev,
4328c2ecf20Sopenharmony_ci				"PIO: Failed to send READ command!\n");
4338c2ecf20Sopenharmony_ci			goto cleanup;
4348c2ecf20Sopenharmony_ci		}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci		data = readl(i2c->regs + MXS_I2C_DATA(i2c));
4378c2ecf20Sopenharmony_ci		for (i = 0; i < msg->len; i++) {
4388c2ecf20Sopenharmony_ci			msg->buf[i] = data & 0xff;
4398c2ecf20Sopenharmony_ci			data >>= 8;
4408c2ecf20Sopenharmony_ci		}
4418c2ecf20Sopenharmony_ci	} else {
4428c2ecf20Sopenharmony_ci		/*
4438c2ecf20Sopenharmony_ci		 * PIO WRITE transfer:
4448c2ecf20Sopenharmony_ci		 *
4458c2ecf20Sopenharmony_ci		 * The code below implements clock stretching to circumvent
4468c2ecf20Sopenharmony_ci		 * the possibility of kernel not being able to supply data
4478c2ecf20Sopenharmony_ci		 * fast enough. It is possible to transfer arbitrary amount
4488c2ecf20Sopenharmony_ci		 * of data using PIO write.
4498c2ecf20Sopenharmony_ci		 */
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci		/*
4528c2ecf20Sopenharmony_ci		 * The LSB of data buffer is the first byte blasted across
4538c2ecf20Sopenharmony_ci		 * the bus. Higher order bytes follow. Thus the following
4548c2ecf20Sopenharmony_ci		 * filling schematic.
4558c2ecf20Sopenharmony_ci		 */
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci		data = addr_data << 24;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci		/* Start the transfer with START condition. */
4608c2ecf20Sopenharmony_ci		start = MXS_I2C_CTRL0_PRE_SEND_START;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci		/* If the transfer is long, use clock stretching. */
4638c2ecf20Sopenharmony_ci		if (msg->len > 3)
4648c2ecf20Sopenharmony_ci			start |= MXS_I2C_CTRL0_RETAIN_CLOCK;
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci		for (i = 0; i < msg->len; i++) {
4678c2ecf20Sopenharmony_ci			data >>= 8;
4688c2ecf20Sopenharmony_ci			data |= (msg->buf[i] << 24);
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci			xmit = 0;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci			/* This is the last transfer of the message. */
4738c2ecf20Sopenharmony_ci			if (i + 1 == msg->len) {
4748c2ecf20Sopenharmony_ci				/* Add optional STOP flag. */
4758c2ecf20Sopenharmony_ci				start |= flags;
4768c2ecf20Sopenharmony_ci				/* Remove RETAIN_CLOCK bit. */
4778c2ecf20Sopenharmony_ci				start &= ~MXS_I2C_CTRL0_RETAIN_CLOCK;
4788c2ecf20Sopenharmony_ci				xmit = 1;
4798c2ecf20Sopenharmony_ci			}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci			/* Four bytes are ready in the "data" variable. */
4828c2ecf20Sopenharmony_ci			if ((i & 3) == 2)
4838c2ecf20Sopenharmony_ci				xmit = 1;
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci			/* Nothing interesting happened, continue stuffing. */
4868c2ecf20Sopenharmony_ci			if (!xmit)
4878c2ecf20Sopenharmony_ci				continue;
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci			/*
4908c2ecf20Sopenharmony_ci			 * Compute the size of the transfer and shift the
4918c2ecf20Sopenharmony_ci			 * data accordingly.
4928c2ecf20Sopenharmony_ci			 *
4938c2ecf20Sopenharmony_ci			 * i = (4k + 0) .... xlen = 2
4948c2ecf20Sopenharmony_ci			 * i = (4k + 1) .... xlen = 3
4958c2ecf20Sopenharmony_ci			 * i = (4k + 2) .... xlen = 4
4968c2ecf20Sopenharmony_ci			 * i = (4k + 3) .... xlen = 1
4978c2ecf20Sopenharmony_ci			 */
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci			if ((i % 4) == 3)
5008c2ecf20Sopenharmony_ci				xlen = 1;
5018c2ecf20Sopenharmony_ci			else
5028c2ecf20Sopenharmony_ci				xlen = (i % 4) + 2;
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci			data >>= (4 - xlen) * 8;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci			dev_dbg(i2c->dev,
5078c2ecf20Sopenharmony_ci				"PIO: len=%i pos=%i total=%i [W%s%s%s]\n",
5088c2ecf20Sopenharmony_ci				xlen, i, msg->len,
5098c2ecf20Sopenharmony_ci				start & MXS_I2C_CTRL0_PRE_SEND_START ? "S" : "",
5108c2ecf20Sopenharmony_ci				start & MXS_I2C_CTRL0_POST_SEND_STOP ? "E" : "",
5118c2ecf20Sopenharmony_ci				start & MXS_I2C_CTRL0_RETAIN_CLOCK ? "C" : "");
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci			writel(MXS_I2C_DEBUG0_DMAREQ,
5148c2ecf20Sopenharmony_ci			       i2c->regs + MXS_I2C_DEBUG0_CLR(i2c));
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci			mxs_i2c_pio_trigger_write_cmd(i2c,
5178c2ecf20Sopenharmony_ci				start | MXS_I2C_CTRL0_MASTER_MODE |
5188c2ecf20Sopenharmony_ci				MXS_I2C_CTRL0_DIRECTION |
5198c2ecf20Sopenharmony_ci				MXS_I2C_CTRL0_XFER_COUNT(xlen), data);
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci			/* The START condition is sent only once. */
5228c2ecf20Sopenharmony_ci			start &= ~MXS_I2C_CTRL0_PRE_SEND_START;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci			/* Wait for the end of the transfer. */
5258c2ecf20Sopenharmony_ci			ret = mxs_i2c_pio_wait_xfer_end(i2c);
5268c2ecf20Sopenharmony_ci			if (ret) {
5278c2ecf20Sopenharmony_ci				dev_dbg(i2c->dev,
5288c2ecf20Sopenharmony_ci					"PIO: Failed to finish WRITE cmd!\n");
5298c2ecf20Sopenharmony_ci				break;
5308c2ecf20Sopenharmony_ci			}
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci			/* Check NAK here. */
5338c2ecf20Sopenharmony_ci			ret = readl(i2c->regs + MXS_I2C_STAT) &
5348c2ecf20Sopenharmony_ci				    MXS_I2C_STAT_GOT_A_NAK;
5358c2ecf20Sopenharmony_ci			if (ret) {
5368c2ecf20Sopenharmony_ci				ret = -ENXIO;
5378c2ecf20Sopenharmony_ci				goto cleanup;
5388c2ecf20Sopenharmony_ci			}
5398c2ecf20Sopenharmony_ci		}
5408c2ecf20Sopenharmony_ci	}
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	/* make sure we capture any occurred error into cmd_err */
5438c2ecf20Sopenharmony_ci	ret = mxs_i2c_pio_check_error_state(i2c);
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_cicleanup:
5468c2ecf20Sopenharmony_ci	/* Clear any dangling IRQs and re-enable interrupts. */
5478c2ecf20Sopenharmony_ci	writel(MXS_I2C_IRQ_MASK, i2c->regs + MXS_I2C_CTRL1_CLR);
5488c2ecf20Sopenharmony_ci	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	/* Clear the PIO_MODE on i.MX23 */
5518c2ecf20Sopenharmony_ci	if (i2c->dev_type == MXS_I2C_V1)
5528c2ecf20Sopenharmony_ci		writel(MXS_I2C_CTRL0_PIO_MODE, i2c->regs + MXS_I2C_CTRL0_CLR);
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	return ret;
5558c2ecf20Sopenharmony_ci}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci/*
5588c2ecf20Sopenharmony_ci * Low level master read/write transaction.
5598c2ecf20Sopenharmony_ci */
5608c2ecf20Sopenharmony_cistatic int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
5618c2ecf20Sopenharmony_ci				int stop)
5628c2ecf20Sopenharmony_ci{
5638c2ecf20Sopenharmony_ci	struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
5648c2ecf20Sopenharmony_ci	int ret;
5658c2ecf20Sopenharmony_ci	int flags;
5668c2ecf20Sopenharmony_ci	int use_pio = 0;
5678c2ecf20Sopenharmony_ci	unsigned long time_left;
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
5728c2ecf20Sopenharmony_ci		msg->addr, msg->len, msg->flags, stop);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	/*
5758c2ecf20Sopenharmony_ci	 * The MX28 I2C IP block can only do PIO READ for transfer of to up
5768c2ecf20Sopenharmony_ci	 * 4 bytes of length. The write transfer is not limited as it can use
5778c2ecf20Sopenharmony_ci	 * clock stretching to avoid FIFO underruns.
5788c2ecf20Sopenharmony_ci	 */
5798c2ecf20Sopenharmony_ci	if ((msg->flags & I2C_M_RD) && (msg->len <= 4))
5808c2ecf20Sopenharmony_ci		use_pio = 1;
5818c2ecf20Sopenharmony_ci	if (!(msg->flags & I2C_M_RD) && (msg->len < 7))
5828c2ecf20Sopenharmony_ci		use_pio = 1;
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	i2c->cmd_err = 0;
5858c2ecf20Sopenharmony_ci	if (use_pio) {
5868c2ecf20Sopenharmony_ci		ret = mxs_i2c_pio_setup_xfer(adap, msg, flags);
5878c2ecf20Sopenharmony_ci		/* No need to reset the block if NAK was received. */
5888c2ecf20Sopenharmony_ci		if (ret && (ret != -ENXIO))
5898c2ecf20Sopenharmony_ci			mxs_i2c_reset(i2c);
5908c2ecf20Sopenharmony_ci	} else {
5918c2ecf20Sopenharmony_ci		reinit_completion(&i2c->cmd_complete);
5928c2ecf20Sopenharmony_ci		ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
5938c2ecf20Sopenharmony_ci		if (ret)
5948c2ecf20Sopenharmony_ci			return ret;
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci		time_left = wait_for_completion_timeout(&i2c->cmd_complete,
5978c2ecf20Sopenharmony_ci						msecs_to_jiffies(1000));
5988c2ecf20Sopenharmony_ci		if (!time_left)
5998c2ecf20Sopenharmony_ci			goto timeout;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci		ret = i2c->cmd_err;
6028c2ecf20Sopenharmony_ci	}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	if (ret == -ENXIO) {
6058c2ecf20Sopenharmony_ci		/*
6068c2ecf20Sopenharmony_ci		 * If the transfer fails with a NAK from the slave the
6078c2ecf20Sopenharmony_ci		 * controller halts until it gets told to return to idle state.
6088c2ecf20Sopenharmony_ci		 */
6098c2ecf20Sopenharmony_ci		writel(MXS_I2C_CTRL1_CLR_GOT_A_NAK,
6108c2ecf20Sopenharmony_ci		       i2c->regs + MXS_I2C_CTRL1_SET);
6118c2ecf20Sopenharmony_ci	}
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	/*
6148c2ecf20Sopenharmony_ci	 * WARNING!
6158c2ecf20Sopenharmony_ci	 * The i.MX23 is strange. After each and every operation, it's I2C IP
6168c2ecf20Sopenharmony_ci	 * block must be reset, otherwise the IP block will misbehave. This can
6178c2ecf20Sopenharmony_ci	 * be observed on the bus by the block sending out one single byte onto
6188c2ecf20Sopenharmony_ci	 * the bus. In case such an error happens, bit 27 will be set in the
6198c2ecf20Sopenharmony_ci	 * DEBUG0 register. This bit is not documented in the i.MX23 datasheet
6208c2ecf20Sopenharmony_ci	 * and is marked as "TBD" instead. To reset this bit to a correct state,
6218c2ecf20Sopenharmony_ci	 * reset the whole block. Since the block reset does not take long, do
6228c2ecf20Sopenharmony_ci	 * reset the block after every transfer to play safe.
6238c2ecf20Sopenharmony_ci	 */
6248c2ecf20Sopenharmony_ci	if (i2c->dev_type == MXS_I2C_V1)
6258c2ecf20Sopenharmony_ci		mxs_i2c_reset(i2c);
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	dev_dbg(i2c->dev, "Done with err=%d\n", ret);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	return ret;
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_citimeout:
6328c2ecf20Sopenharmony_ci	dev_dbg(i2c->dev, "Timeout!\n");
6338c2ecf20Sopenharmony_ci	mxs_i2c_dma_finish(i2c);
6348c2ecf20Sopenharmony_ci	ret = mxs_i2c_reset(i2c);
6358c2ecf20Sopenharmony_ci	if (ret)
6368c2ecf20Sopenharmony_ci		return ret;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	return -ETIMEDOUT;
6398c2ecf20Sopenharmony_ci}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_cistatic int mxs_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
6428c2ecf20Sopenharmony_ci			int num)
6438c2ecf20Sopenharmony_ci{
6448c2ecf20Sopenharmony_ci	int i;
6458c2ecf20Sopenharmony_ci	int err;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	for (i = 0; i < num; i++) {
6488c2ecf20Sopenharmony_ci		err = mxs_i2c_xfer_msg(adap, &msgs[i], i == (num - 1));
6498c2ecf20Sopenharmony_ci		if (err)
6508c2ecf20Sopenharmony_ci			return err;
6518c2ecf20Sopenharmony_ci	}
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	return num;
6548c2ecf20Sopenharmony_ci}
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_cistatic u32 mxs_i2c_func(struct i2c_adapter *adap)
6578c2ecf20Sopenharmony_ci{
6588c2ecf20Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
6598c2ecf20Sopenharmony_ci}
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_cistatic irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
6628c2ecf20Sopenharmony_ci{
6638c2ecf20Sopenharmony_ci	struct mxs_i2c_dev *i2c = dev_id;
6648c2ecf20Sopenharmony_ci	u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	if (!stat)
6678c2ecf20Sopenharmony_ci		return IRQ_NONE;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	if (stat & MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ)
6708c2ecf20Sopenharmony_ci		i2c->cmd_err = -ENXIO;
6718c2ecf20Sopenharmony_ci	else if (stat & (MXS_I2C_CTRL1_EARLY_TERM_IRQ |
6728c2ecf20Sopenharmony_ci		    MXS_I2C_CTRL1_MASTER_LOSS_IRQ |
6738c2ecf20Sopenharmony_ci		    MXS_I2C_CTRL1_SLAVE_STOP_IRQ | MXS_I2C_CTRL1_SLAVE_IRQ))
6748c2ecf20Sopenharmony_ci		/* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
6758c2ecf20Sopenharmony_ci		i2c->cmd_err = -EIO;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
6808c2ecf20Sopenharmony_ci}
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_cistatic const struct i2c_algorithm mxs_i2c_algo = {
6838c2ecf20Sopenharmony_ci	.master_xfer = mxs_i2c_xfer,
6848c2ecf20Sopenharmony_ci	.functionality = mxs_i2c_func,
6858c2ecf20Sopenharmony_ci};
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_cistatic const struct i2c_adapter_quirks mxs_i2c_quirks = {
6888c2ecf20Sopenharmony_ci	.flags = I2C_AQ_NO_ZERO_LEN,
6898c2ecf20Sopenharmony_ci};
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_cistatic void mxs_i2c_derive_timing(struct mxs_i2c_dev *i2c, uint32_t speed)
6928c2ecf20Sopenharmony_ci{
6938c2ecf20Sopenharmony_ci	/* The I2C block clock runs at 24MHz */
6948c2ecf20Sopenharmony_ci	const uint32_t clk = 24000000;
6958c2ecf20Sopenharmony_ci	uint32_t divider;
6968c2ecf20Sopenharmony_ci	uint16_t high_count, low_count, rcv_count, xmit_count;
6978c2ecf20Sopenharmony_ci	uint32_t bus_free, leadin;
6988c2ecf20Sopenharmony_ci	struct device *dev = i2c->dev;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	divider = DIV_ROUND_UP(clk, speed);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	if (divider < 25) {
7038c2ecf20Sopenharmony_ci		/*
7048c2ecf20Sopenharmony_ci		 * limit the divider, so that min(low_count, high_count)
7058c2ecf20Sopenharmony_ci		 * is >= 1
7068c2ecf20Sopenharmony_ci		 */
7078c2ecf20Sopenharmony_ci		divider = 25;
7088c2ecf20Sopenharmony_ci		dev_warn(dev,
7098c2ecf20Sopenharmony_ci			"Speed too high (%u.%03u kHz), using %u.%03u kHz\n",
7108c2ecf20Sopenharmony_ci			speed / 1000, speed % 1000,
7118c2ecf20Sopenharmony_ci			clk / divider / 1000, clk / divider % 1000);
7128c2ecf20Sopenharmony_ci	} else if (divider > 1897) {
7138c2ecf20Sopenharmony_ci		/*
7148c2ecf20Sopenharmony_ci		 * limit the divider, so that max(low_count, high_count)
7158c2ecf20Sopenharmony_ci		 * cannot exceed 1023
7168c2ecf20Sopenharmony_ci		 */
7178c2ecf20Sopenharmony_ci		divider = 1897;
7188c2ecf20Sopenharmony_ci		dev_warn(dev,
7198c2ecf20Sopenharmony_ci			"Speed too low (%u.%03u kHz), using %u.%03u kHz\n",
7208c2ecf20Sopenharmony_ci			speed / 1000, speed % 1000,
7218c2ecf20Sopenharmony_ci			clk / divider / 1000, clk / divider % 1000);
7228c2ecf20Sopenharmony_ci	}
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	/*
7258c2ecf20Sopenharmony_ci	 * The I2C spec specifies the following timing data:
7268c2ecf20Sopenharmony_ci	 *                          standard mode  fast mode Bitfield name
7278c2ecf20Sopenharmony_ci	 * tLOW (SCL LOW period)     4700 ns        1300 ns
7288c2ecf20Sopenharmony_ci	 * tHIGH (SCL HIGH period)   4000 ns         600 ns
7298c2ecf20Sopenharmony_ci	 * tSU;DAT (data setup time)  250 ns         100 ns
7308c2ecf20Sopenharmony_ci	 * tHD;STA (START hold time) 4000 ns         600 ns
7318c2ecf20Sopenharmony_ci	 * tBUF (bus free time)      4700 ns        1300 ns
7328c2ecf20Sopenharmony_ci	 *
7338c2ecf20Sopenharmony_ci	 * The hardware (of the i.MX28 at least) seems to add 2 additional
7348c2ecf20Sopenharmony_ci	 * clock cycles to the low_count and 7 cycles to the high_count.
7358c2ecf20Sopenharmony_ci	 * This is compensated for by subtracting the respective constants
7368c2ecf20Sopenharmony_ci	 * from the values written to the timing registers.
7378c2ecf20Sopenharmony_ci	 */
7388c2ecf20Sopenharmony_ci	if (speed > I2C_MAX_STANDARD_MODE_FREQ) {
7398c2ecf20Sopenharmony_ci		/* fast mode */
7408c2ecf20Sopenharmony_ci		low_count = DIV_ROUND_CLOSEST(divider * 13, (13 + 6));
7418c2ecf20Sopenharmony_ci		high_count = DIV_ROUND_CLOSEST(divider * 6, (13 + 6));
7428c2ecf20Sopenharmony_ci		leadin = DIV_ROUND_UP(600 * (clk / 1000000), 1000);
7438c2ecf20Sopenharmony_ci		bus_free = DIV_ROUND_UP(1300 * (clk / 1000000), 1000);
7448c2ecf20Sopenharmony_ci	} else {
7458c2ecf20Sopenharmony_ci		/* normal mode */
7468c2ecf20Sopenharmony_ci		low_count = DIV_ROUND_CLOSEST(divider * 47, (47 + 40));
7478c2ecf20Sopenharmony_ci		high_count = DIV_ROUND_CLOSEST(divider * 40, (47 + 40));
7488c2ecf20Sopenharmony_ci		leadin = DIV_ROUND_UP(4700 * (clk / 1000000), 1000);
7498c2ecf20Sopenharmony_ci		bus_free = DIV_ROUND_UP(4700 * (clk / 1000000), 1000);
7508c2ecf20Sopenharmony_ci	}
7518c2ecf20Sopenharmony_ci	rcv_count = high_count * 3 / 8;
7528c2ecf20Sopenharmony_ci	xmit_count = low_count * 3 / 8;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	dev_dbg(dev,
7558c2ecf20Sopenharmony_ci		"speed=%u(actual %u) divider=%u low=%u high=%u xmit=%u rcv=%u leadin=%u bus_free=%u\n",
7568c2ecf20Sopenharmony_ci		speed, clk / divider, divider, low_count, high_count,
7578c2ecf20Sopenharmony_ci		xmit_count, rcv_count, leadin, bus_free);
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	low_count -= 2;
7608c2ecf20Sopenharmony_ci	high_count -= 7;
7618c2ecf20Sopenharmony_ci	i2c->timing0 = (high_count << 16) | rcv_count;
7628c2ecf20Sopenharmony_ci	i2c->timing1 = (low_count << 16) | xmit_count;
7638c2ecf20Sopenharmony_ci	i2c->timing2 = (bus_free << 16 | leadin);
7648c2ecf20Sopenharmony_ci}
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_cistatic int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
7678c2ecf20Sopenharmony_ci{
7688c2ecf20Sopenharmony_ci	uint32_t speed;
7698c2ecf20Sopenharmony_ci	struct device *dev = i2c->dev;
7708c2ecf20Sopenharmony_ci	struct device_node *node = dev->of_node;
7718c2ecf20Sopenharmony_ci	int ret;
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	ret = of_property_read_u32(node, "clock-frequency", &speed);
7748c2ecf20Sopenharmony_ci	if (ret) {
7758c2ecf20Sopenharmony_ci		dev_warn(dev, "No I2C speed selected, using 100kHz\n");
7768c2ecf20Sopenharmony_ci		speed = I2C_MAX_STANDARD_MODE_FREQ;
7778c2ecf20Sopenharmony_ci	}
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	mxs_i2c_derive_timing(i2c, speed);
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	return 0;
7828c2ecf20Sopenharmony_ci}
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_cistatic const struct platform_device_id mxs_i2c_devtype[] = {
7858c2ecf20Sopenharmony_ci	{
7868c2ecf20Sopenharmony_ci		.name = "imx23-i2c",
7878c2ecf20Sopenharmony_ci		.driver_data = MXS_I2C_V1,
7888c2ecf20Sopenharmony_ci	}, {
7898c2ecf20Sopenharmony_ci		.name = "imx28-i2c",
7908c2ecf20Sopenharmony_ci		.driver_data = MXS_I2C_V2,
7918c2ecf20Sopenharmony_ci	}, { /* sentinel */ }
7928c2ecf20Sopenharmony_ci};
7938c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(platform, mxs_i2c_devtype);
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_cistatic const struct of_device_id mxs_i2c_dt_ids[] = {
7968c2ecf20Sopenharmony_ci	{ .compatible = "fsl,imx23-i2c", .data = &mxs_i2c_devtype[0], },
7978c2ecf20Sopenharmony_ci	{ .compatible = "fsl,imx28-i2c", .data = &mxs_i2c_devtype[1], },
7988c2ecf20Sopenharmony_ci	{ /* sentinel */ }
7998c2ecf20Sopenharmony_ci};
8008c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, mxs_i2c_dt_ids);
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_cistatic int mxs_i2c_probe(struct platform_device *pdev)
8038c2ecf20Sopenharmony_ci{
8048c2ecf20Sopenharmony_ci	const struct of_device_id *of_id =
8058c2ecf20Sopenharmony_ci				of_match_device(mxs_i2c_dt_ids, &pdev->dev);
8068c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
8078c2ecf20Sopenharmony_ci	struct mxs_i2c_dev *i2c;
8088c2ecf20Sopenharmony_ci	struct i2c_adapter *adap;
8098c2ecf20Sopenharmony_ci	int err, irq;
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci	i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
8128c2ecf20Sopenharmony_ci	if (!i2c)
8138c2ecf20Sopenharmony_ci		return -ENOMEM;
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	if (of_id) {
8168c2ecf20Sopenharmony_ci		const struct platform_device_id *device_id = of_id->data;
8178c2ecf20Sopenharmony_ci		i2c->dev_type = device_id->driver_data;
8188c2ecf20Sopenharmony_ci	}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	i2c->regs = devm_platform_ioremap_resource(pdev, 0);
8218c2ecf20Sopenharmony_ci	if (IS_ERR(i2c->regs))
8228c2ecf20Sopenharmony_ci		return PTR_ERR(i2c->regs);
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
8258c2ecf20Sopenharmony_ci	if (irq < 0)
8268c2ecf20Sopenharmony_ci		return irq;
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	err = devm_request_irq(dev, irq, mxs_i2c_isr, 0, dev_name(dev), i2c);
8298c2ecf20Sopenharmony_ci	if (err)
8308c2ecf20Sopenharmony_ci		return err;
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci	i2c->dev = dev;
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	init_completion(&i2c->cmd_complete);
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	if (dev->of_node) {
8378c2ecf20Sopenharmony_ci		err = mxs_i2c_get_ofdata(i2c);
8388c2ecf20Sopenharmony_ci		if (err)
8398c2ecf20Sopenharmony_ci			return err;
8408c2ecf20Sopenharmony_ci	}
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	/* Setup the DMA */
8438c2ecf20Sopenharmony_ci	i2c->dmach = dma_request_chan(dev, "rx-tx");
8448c2ecf20Sopenharmony_ci	if (IS_ERR(i2c->dmach)) {
8458c2ecf20Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(i2c->dmach),
8468c2ecf20Sopenharmony_ci				     "Failed to request dma\n");
8478c2ecf20Sopenharmony_ci	}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, i2c);
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	/* Do reset to enforce correct startup after pinmuxing */
8528c2ecf20Sopenharmony_ci	err = mxs_i2c_reset(i2c);
8538c2ecf20Sopenharmony_ci	if (err)
8548c2ecf20Sopenharmony_ci		return err;
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	adap = &i2c->adapter;
8578c2ecf20Sopenharmony_ci	strlcpy(adap->name, "MXS I2C adapter", sizeof(adap->name));
8588c2ecf20Sopenharmony_ci	adap->owner = THIS_MODULE;
8598c2ecf20Sopenharmony_ci	adap->algo = &mxs_i2c_algo;
8608c2ecf20Sopenharmony_ci	adap->quirks = &mxs_i2c_quirks;
8618c2ecf20Sopenharmony_ci	adap->dev.parent = dev;
8628c2ecf20Sopenharmony_ci	adap->nr = pdev->id;
8638c2ecf20Sopenharmony_ci	adap->dev.of_node = pdev->dev.of_node;
8648c2ecf20Sopenharmony_ci	i2c_set_adapdata(adap, i2c);
8658c2ecf20Sopenharmony_ci	err = i2c_add_numbered_adapter(adap);
8668c2ecf20Sopenharmony_ci	if (err) {
8678c2ecf20Sopenharmony_ci		writel(MXS_I2C_CTRL0_SFTRST,
8688c2ecf20Sopenharmony_ci				i2c->regs + MXS_I2C_CTRL0_SET);
8698c2ecf20Sopenharmony_ci		return err;
8708c2ecf20Sopenharmony_ci	}
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	return 0;
8738c2ecf20Sopenharmony_ci}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_cistatic int mxs_i2c_remove(struct platform_device *pdev)
8768c2ecf20Sopenharmony_ci{
8778c2ecf20Sopenharmony_ci	struct mxs_i2c_dev *i2c = platform_get_drvdata(pdev);
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	i2c_del_adapter(&i2c->adapter);
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci	if (i2c->dmach)
8828c2ecf20Sopenharmony_ci		dma_release_channel(i2c->dmach);
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_ci	writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET);
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	return 0;
8878c2ecf20Sopenharmony_ci}
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_cistatic struct platform_driver mxs_i2c_driver = {
8908c2ecf20Sopenharmony_ci	.driver = {
8918c2ecf20Sopenharmony_ci		   .name = DRIVER_NAME,
8928c2ecf20Sopenharmony_ci		   .of_match_table = mxs_i2c_dt_ids,
8938c2ecf20Sopenharmony_ci		   },
8948c2ecf20Sopenharmony_ci	.probe = mxs_i2c_probe,
8958c2ecf20Sopenharmony_ci	.remove = mxs_i2c_remove,
8968c2ecf20Sopenharmony_ci};
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_cistatic int __init mxs_i2c_init(void)
8998c2ecf20Sopenharmony_ci{
9008c2ecf20Sopenharmony_ci	return platform_driver_register(&mxs_i2c_driver);
9018c2ecf20Sopenharmony_ci}
9028c2ecf20Sopenharmony_cisubsys_initcall(mxs_i2c_init);
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_cistatic void __exit mxs_i2c_exit(void)
9058c2ecf20Sopenharmony_ci{
9068c2ecf20Sopenharmony_ci	platform_driver_unregister(&mxs_i2c_driver);
9078c2ecf20Sopenharmony_ci}
9088c2ecf20Sopenharmony_cimodule_exit(mxs_i2c_exit);
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ciMODULE_AUTHOR("Marek Vasut <marex@denx.de>");
9118c2ecf20Sopenharmony_ciMODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
9128c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("MXS I2C Bus Driver");
9138c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
9148c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:" DRIVER_NAME);
915