162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *	Copyright (C) 2002 Motorola GSG-China
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Author:
662306a36Sopenharmony_ci *	Darius Augulis, Teltonika Inc.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Desc.:
962306a36Sopenharmony_ci *	Implementation of I2C Adapter/Algorithm Driver
1062306a36Sopenharmony_ci *	for I2C Bus integrated in Freescale i.MX/MXC processors
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci *	Derived from Motorola GSG China I2C example driver
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci *	Copyright (C) 2005 Torsten Koschorrek <koschorrek at synertronixx.de
1562306a36Sopenharmony_ci *	Copyright (C) 2005 Matthias Blaschke <blaschke at synertronixx.de
1662306a36Sopenharmony_ci *	Copyright (C) 2007 RightHand Technologies, Inc.
1762306a36Sopenharmony_ci *	Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt>
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci *	Copyright 2013 Freescale Semiconductor, Inc.
2062306a36Sopenharmony_ci *	Copyright 2020 NXP
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include <linux/acpi.h>
2562306a36Sopenharmony_ci#include <linux/clk.h>
2662306a36Sopenharmony_ci#include <linux/completion.h>
2762306a36Sopenharmony_ci#include <linux/delay.h>
2862306a36Sopenharmony_ci#include <linux/dma-mapping.h>
2962306a36Sopenharmony_ci#include <linux/dmaengine.h>
3062306a36Sopenharmony_ci#include <linux/dmapool.h>
3162306a36Sopenharmony_ci#include <linux/err.h>
3262306a36Sopenharmony_ci#include <linux/errno.h>
3362306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
3462306a36Sopenharmony_ci#include <linux/i2c.h>
3562306a36Sopenharmony_ci#include <linux/init.h>
3662306a36Sopenharmony_ci#include <linux/interrupt.h>
3762306a36Sopenharmony_ci#include <linux/io.h>
3862306a36Sopenharmony_ci#include <linux/iopoll.h>
3962306a36Sopenharmony_ci#include <linux/kernel.h>
4062306a36Sopenharmony_ci#include <linux/spinlock.h>
4162306a36Sopenharmony_ci#include <linux/hrtimer.h>
4262306a36Sopenharmony_ci#include <linux/module.h>
4362306a36Sopenharmony_ci#include <linux/of.h>
4462306a36Sopenharmony_ci#include <linux/of_dma.h>
4562306a36Sopenharmony_ci#include <linux/pinctrl/consumer.h>
4662306a36Sopenharmony_ci#include <linux/platform_data/i2c-imx.h>
4762306a36Sopenharmony_ci#include <linux/platform_device.h>
4862306a36Sopenharmony_ci#include <linux/pm_runtime.h>
4962306a36Sopenharmony_ci#include <linux/sched.h>
5062306a36Sopenharmony_ci#include <linux/slab.h>
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/* This will be the driver name the kernel reports */
5362306a36Sopenharmony_ci#define DRIVER_NAME "imx-i2c"
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define I2C_IMX_CHECK_DELAY 30000 /* Time to check for bus idle, in NS */
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/*
5862306a36Sopenharmony_ci * Enable DMA if transfer byte size is bigger than this threshold.
5962306a36Sopenharmony_ci * As the hardware request, it must bigger than 4 bytes.\
6062306a36Sopenharmony_ci * I have set '16' here, maybe it's not the best but I think it's
6162306a36Sopenharmony_ci * the appropriate.
6262306a36Sopenharmony_ci */
6362306a36Sopenharmony_ci#define DMA_THRESHOLD	16
6462306a36Sopenharmony_ci#define DMA_TIMEOUT	1000
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci/* IMX I2C registers:
6762306a36Sopenharmony_ci * the I2C register offset is different between SoCs,
6862306a36Sopenharmony_ci * to provide support for all these chips, split the
6962306a36Sopenharmony_ci * register offset into a fixed base address and a
7062306a36Sopenharmony_ci * variable shift value, then the full register offset
7162306a36Sopenharmony_ci * will be calculated by
7262306a36Sopenharmony_ci * reg_off = ( reg_base_addr << reg_shift)
7362306a36Sopenharmony_ci */
7462306a36Sopenharmony_ci#define IMX_I2C_IADR	0x00	/* i2c slave address */
7562306a36Sopenharmony_ci#define IMX_I2C_IFDR	0x01	/* i2c frequency divider */
7662306a36Sopenharmony_ci#define IMX_I2C_I2CR	0x02	/* i2c control */
7762306a36Sopenharmony_ci#define IMX_I2C_I2SR	0x03	/* i2c status */
7862306a36Sopenharmony_ci#define IMX_I2C_I2DR	0x04	/* i2c transfer data */
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci/*
8162306a36Sopenharmony_ci * All of the layerscape series SoCs support IBIC register.
8262306a36Sopenharmony_ci */
8362306a36Sopenharmony_ci#define IMX_I2C_IBIC	0x05    /* i2c bus interrupt config */
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci#define IMX_I2C_REGSHIFT	2
8662306a36Sopenharmony_ci#define VF610_I2C_REGSHIFT	0
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci/* Bits of IMX I2C registers */
8962306a36Sopenharmony_ci#define I2SR_RXAK	0x01
9062306a36Sopenharmony_ci#define I2SR_IIF	0x02
9162306a36Sopenharmony_ci#define I2SR_SRW	0x04
9262306a36Sopenharmony_ci#define I2SR_IAL	0x10
9362306a36Sopenharmony_ci#define I2SR_IBB	0x20
9462306a36Sopenharmony_ci#define I2SR_IAAS	0x40
9562306a36Sopenharmony_ci#define I2SR_ICF	0x80
9662306a36Sopenharmony_ci#define I2CR_DMAEN	0x02
9762306a36Sopenharmony_ci#define I2CR_RSTA	0x04
9862306a36Sopenharmony_ci#define I2CR_TXAK	0x08
9962306a36Sopenharmony_ci#define I2CR_MTX	0x10
10062306a36Sopenharmony_ci#define I2CR_MSTA	0x20
10162306a36Sopenharmony_ci#define I2CR_IIEN	0x40
10262306a36Sopenharmony_ci#define I2CR_IEN	0x80
10362306a36Sopenharmony_ci#define IBIC_BIIE	0x80 /* Bus idle interrupt enable */
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/* register bits different operating codes definition:
10662306a36Sopenharmony_ci * 1) I2SR: Interrupt flags clear operation differ between SoCs:
10762306a36Sopenharmony_ci * - write zero to clear(w0c) INT flag on i.MX,
10862306a36Sopenharmony_ci * - but write one to clear(w1c) INT flag on Vybrid.
10962306a36Sopenharmony_ci * 2) I2CR: I2C module enable operation also differ between SoCs:
11062306a36Sopenharmony_ci * - set I2CR_IEN bit enable the module on i.MX,
11162306a36Sopenharmony_ci * - but clear I2CR_IEN bit enable the module on Vybrid.
11262306a36Sopenharmony_ci */
11362306a36Sopenharmony_ci#define I2SR_CLR_OPCODE_W0C	0x0
11462306a36Sopenharmony_ci#define I2SR_CLR_OPCODE_W1C	(I2SR_IAL | I2SR_IIF)
11562306a36Sopenharmony_ci#define I2CR_IEN_OPCODE_0	0x0
11662306a36Sopenharmony_ci#define I2CR_IEN_OPCODE_1	I2CR_IEN
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci#define I2C_PM_TIMEOUT		10 /* ms */
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci/*
12162306a36Sopenharmony_ci * sorted list of clock divider, register value pairs
12262306a36Sopenharmony_ci * taken from table 26-5, p.26-9, Freescale i.MX
12362306a36Sopenharmony_ci * Integrated Portable System Processor Reference Manual
12462306a36Sopenharmony_ci * Document Number: MC9328MXLRM, Rev. 5.1, 06/2007
12562306a36Sopenharmony_ci *
12662306a36Sopenharmony_ci * Duplicated divider values removed from list
12762306a36Sopenharmony_ci */
12862306a36Sopenharmony_cistruct imx_i2c_clk_pair {
12962306a36Sopenharmony_ci	u16	div;
13062306a36Sopenharmony_ci	u16	val;
13162306a36Sopenharmony_ci};
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic struct imx_i2c_clk_pair imx_i2c_clk_div[] = {
13462306a36Sopenharmony_ci	{ 22,	0x20 }, { 24,	0x21 }, { 26,	0x22 }, { 28,	0x23 },
13562306a36Sopenharmony_ci	{ 30,	0x00 },	{ 32,	0x24 }, { 36,	0x25 }, { 40,	0x26 },
13662306a36Sopenharmony_ci	{ 42,	0x03 }, { 44,	0x27 },	{ 48,	0x28 }, { 52,	0x05 },
13762306a36Sopenharmony_ci	{ 56,	0x29 }, { 60,	0x06 }, { 64,	0x2A },	{ 72,	0x2B },
13862306a36Sopenharmony_ci	{ 80,	0x2C }, { 88,	0x09 }, { 96,	0x2D }, { 104,	0x0A },
13962306a36Sopenharmony_ci	{ 112,	0x2E }, { 128,	0x2F }, { 144,	0x0C }, { 160,	0x30 },
14062306a36Sopenharmony_ci	{ 192,	0x31 },	{ 224,	0x32 }, { 240,	0x0F }, { 256,	0x33 },
14162306a36Sopenharmony_ci	{ 288,	0x10 }, { 320,	0x34 },	{ 384,	0x35 }, { 448,	0x36 },
14262306a36Sopenharmony_ci	{ 480,	0x13 }, { 512,	0x37 }, { 576,	0x14 },	{ 640,	0x38 },
14362306a36Sopenharmony_ci	{ 768,	0x39 }, { 896,	0x3A }, { 960,	0x17 }, { 1024,	0x3B },
14462306a36Sopenharmony_ci	{ 1152,	0x18 }, { 1280,	0x3C }, { 1536,	0x3D }, { 1792,	0x3E },
14562306a36Sopenharmony_ci	{ 1920,	0x1B },	{ 2048,	0x3F }, { 2304,	0x1C }, { 2560,	0x1D },
14662306a36Sopenharmony_ci	{ 3072,	0x1E }, { 3840,	0x1F }
14762306a36Sopenharmony_ci};
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci/* Vybrid VF610 clock divider, register value pairs */
15062306a36Sopenharmony_cistatic struct imx_i2c_clk_pair vf610_i2c_clk_div[] = {
15162306a36Sopenharmony_ci	{ 20,   0x00 }, { 22,   0x01 }, { 24,   0x02 }, { 26,   0x03 },
15262306a36Sopenharmony_ci	{ 28,   0x04 }, { 30,   0x05 }, { 32,   0x09 }, { 34,   0x06 },
15362306a36Sopenharmony_ci	{ 36,   0x0A }, { 40,   0x07 }, { 44,   0x0C }, { 48,   0x0D },
15462306a36Sopenharmony_ci	{ 52,   0x43 }, { 56,   0x0E }, { 60,   0x45 }, { 64,   0x12 },
15562306a36Sopenharmony_ci	{ 68,   0x0F }, { 72,   0x13 }, { 80,   0x14 }, { 88,   0x15 },
15662306a36Sopenharmony_ci	{ 96,   0x19 }, { 104,  0x16 }, { 112,  0x1A }, { 128,  0x17 },
15762306a36Sopenharmony_ci	{ 136,  0x4F }, { 144,  0x1C }, { 160,  0x1D }, { 176,  0x55 },
15862306a36Sopenharmony_ci	{ 192,  0x1E }, { 208,  0x56 }, { 224,  0x22 }, { 228,  0x24 },
15962306a36Sopenharmony_ci	{ 240,  0x1F }, { 256,  0x23 }, { 288,  0x5C }, { 320,  0x25 },
16062306a36Sopenharmony_ci	{ 384,  0x26 }, { 448,  0x2A }, { 480,  0x27 }, { 512,  0x2B },
16162306a36Sopenharmony_ci	{ 576,  0x2C }, { 640,  0x2D }, { 768,  0x31 }, { 896,  0x32 },
16262306a36Sopenharmony_ci	{ 960,  0x2F }, { 1024, 0x33 }, { 1152, 0x34 }, { 1280, 0x35 },
16362306a36Sopenharmony_ci	{ 1536, 0x36 }, { 1792, 0x3A }, { 1920, 0x37 }, { 2048, 0x3B },
16462306a36Sopenharmony_ci	{ 2304, 0x3C }, { 2560, 0x3D }, { 3072, 0x3E }, { 3584, 0x7A },
16562306a36Sopenharmony_ci	{ 3840, 0x3F }, { 4096, 0x7B }, { 5120, 0x7D }, { 6144, 0x7E },
16662306a36Sopenharmony_ci};
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cienum imx_i2c_type {
16962306a36Sopenharmony_ci	IMX1_I2C,
17062306a36Sopenharmony_ci	IMX21_I2C,
17162306a36Sopenharmony_ci	VF610_I2C,
17262306a36Sopenharmony_ci};
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistruct imx_i2c_hwdata {
17562306a36Sopenharmony_ci	enum imx_i2c_type	devtype;
17662306a36Sopenharmony_ci	unsigned int		regshift;
17762306a36Sopenharmony_ci	struct imx_i2c_clk_pair	*clk_div;
17862306a36Sopenharmony_ci	unsigned int		ndivs;
17962306a36Sopenharmony_ci	unsigned int		i2sr_clr_opcode;
18062306a36Sopenharmony_ci	unsigned int		i2cr_ien_opcode;
18162306a36Sopenharmony_ci	/*
18262306a36Sopenharmony_ci	 * Errata ERR007805 or e7805:
18362306a36Sopenharmony_ci	 * I2C: When the I2C clock speed is configured for 400 kHz,
18462306a36Sopenharmony_ci	 * the SCL low period violates the I2C spec of 1.3 uS min.
18562306a36Sopenharmony_ci	 */
18662306a36Sopenharmony_ci	bool			has_err007805;
18762306a36Sopenharmony_ci};
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistruct imx_i2c_dma {
19062306a36Sopenharmony_ci	struct dma_chan		*chan_tx;
19162306a36Sopenharmony_ci	struct dma_chan		*chan_rx;
19262306a36Sopenharmony_ci	struct dma_chan		*chan_using;
19362306a36Sopenharmony_ci	struct completion	cmd_complete;
19462306a36Sopenharmony_ci	dma_addr_t		dma_buf;
19562306a36Sopenharmony_ci	unsigned int		dma_len;
19662306a36Sopenharmony_ci	enum dma_transfer_direction dma_transfer_dir;
19762306a36Sopenharmony_ci	enum dma_data_direction dma_data_dir;
19862306a36Sopenharmony_ci};
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_cistruct imx_i2c_struct {
20162306a36Sopenharmony_ci	struct i2c_adapter	adapter;
20262306a36Sopenharmony_ci	struct clk		*clk;
20362306a36Sopenharmony_ci	struct notifier_block	clk_change_nb;
20462306a36Sopenharmony_ci	void __iomem		*base;
20562306a36Sopenharmony_ci	wait_queue_head_t	queue;
20662306a36Sopenharmony_ci	unsigned long		i2csr;
20762306a36Sopenharmony_ci	unsigned int		disable_delay;
20862306a36Sopenharmony_ci	int			stopped;
20962306a36Sopenharmony_ci	unsigned int		ifdr; /* IMX_I2C_IFDR */
21062306a36Sopenharmony_ci	unsigned int		cur_clk;
21162306a36Sopenharmony_ci	unsigned int		bitrate;
21262306a36Sopenharmony_ci	const struct imx_i2c_hwdata	*hwdata;
21362306a36Sopenharmony_ci	struct i2c_bus_recovery_info rinfo;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	struct pinctrl *pinctrl;
21662306a36Sopenharmony_ci	struct pinctrl_state *pinctrl_pins_default;
21762306a36Sopenharmony_ci	struct pinctrl_state *pinctrl_pins_gpio;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	struct imx_i2c_dma	*dma;
22062306a36Sopenharmony_ci	struct i2c_client	*slave;
22162306a36Sopenharmony_ci	enum i2c_slave_event last_slave_event;
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	/* For checking slave events. */
22462306a36Sopenharmony_ci	spinlock_t     slave_lock;
22562306a36Sopenharmony_ci	struct hrtimer slave_timer;
22662306a36Sopenharmony_ci};
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistatic const struct imx_i2c_hwdata imx1_i2c_hwdata = {
22962306a36Sopenharmony_ci	.devtype		= IMX1_I2C,
23062306a36Sopenharmony_ci	.regshift		= IMX_I2C_REGSHIFT,
23162306a36Sopenharmony_ci	.clk_div		= imx_i2c_clk_div,
23262306a36Sopenharmony_ci	.ndivs			= ARRAY_SIZE(imx_i2c_clk_div),
23362306a36Sopenharmony_ci	.i2sr_clr_opcode	= I2SR_CLR_OPCODE_W0C,
23462306a36Sopenharmony_ci	.i2cr_ien_opcode	= I2CR_IEN_OPCODE_1,
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci};
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic const struct imx_i2c_hwdata imx21_i2c_hwdata = {
23962306a36Sopenharmony_ci	.devtype		= IMX21_I2C,
24062306a36Sopenharmony_ci	.regshift		= IMX_I2C_REGSHIFT,
24162306a36Sopenharmony_ci	.clk_div		= imx_i2c_clk_div,
24262306a36Sopenharmony_ci	.ndivs			= ARRAY_SIZE(imx_i2c_clk_div),
24362306a36Sopenharmony_ci	.i2sr_clr_opcode	= I2SR_CLR_OPCODE_W0C,
24462306a36Sopenharmony_ci	.i2cr_ien_opcode	= I2CR_IEN_OPCODE_1,
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci};
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistatic const struct imx_i2c_hwdata imx6_i2c_hwdata = {
24962306a36Sopenharmony_ci	.devtype		= IMX21_I2C,
25062306a36Sopenharmony_ci	.regshift		= IMX_I2C_REGSHIFT,
25162306a36Sopenharmony_ci	.clk_div		= imx_i2c_clk_div,
25262306a36Sopenharmony_ci	.ndivs			= ARRAY_SIZE(imx_i2c_clk_div),
25362306a36Sopenharmony_ci	.i2sr_clr_opcode	= I2SR_CLR_OPCODE_W0C,
25462306a36Sopenharmony_ci	.i2cr_ien_opcode	= I2CR_IEN_OPCODE_1,
25562306a36Sopenharmony_ci	.has_err007805		= true,
25662306a36Sopenharmony_ci};
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic struct imx_i2c_hwdata vf610_i2c_hwdata = {
25962306a36Sopenharmony_ci	.devtype		= VF610_I2C,
26062306a36Sopenharmony_ci	.regshift		= VF610_I2C_REGSHIFT,
26162306a36Sopenharmony_ci	.clk_div		= vf610_i2c_clk_div,
26262306a36Sopenharmony_ci	.ndivs			= ARRAY_SIZE(vf610_i2c_clk_div),
26362306a36Sopenharmony_ci	.i2sr_clr_opcode	= I2SR_CLR_OPCODE_W1C,
26462306a36Sopenharmony_ci	.i2cr_ien_opcode	= I2CR_IEN_OPCODE_0,
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci};
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_cistatic const struct platform_device_id imx_i2c_devtype[] = {
26962306a36Sopenharmony_ci	{
27062306a36Sopenharmony_ci		.name = "imx1-i2c",
27162306a36Sopenharmony_ci		.driver_data = (kernel_ulong_t)&imx1_i2c_hwdata,
27262306a36Sopenharmony_ci	}, {
27362306a36Sopenharmony_ci		.name = "imx21-i2c",
27462306a36Sopenharmony_ci		.driver_data = (kernel_ulong_t)&imx21_i2c_hwdata,
27562306a36Sopenharmony_ci	}, {
27662306a36Sopenharmony_ci		/* sentinel */
27762306a36Sopenharmony_ci	}
27862306a36Sopenharmony_ci};
27962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(platform, imx_i2c_devtype);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_cistatic const struct of_device_id i2c_imx_dt_ids[] = {
28262306a36Sopenharmony_ci	{ .compatible = "fsl,imx1-i2c", .data = &imx1_i2c_hwdata, },
28362306a36Sopenharmony_ci	{ .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, },
28462306a36Sopenharmony_ci	{ .compatible = "fsl,imx6q-i2c", .data = &imx6_i2c_hwdata, },
28562306a36Sopenharmony_ci	{ .compatible = "fsl,imx6sl-i2c", .data = &imx6_i2c_hwdata, },
28662306a36Sopenharmony_ci	{ .compatible = "fsl,imx6sll-i2c", .data = &imx6_i2c_hwdata, },
28762306a36Sopenharmony_ci	{ .compatible = "fsl,imx6sx-i2c", .data = &imx6_i2c_hwdata, },
28862306a36Sopenharmony_ci	{ .compatible = "fsl,imx6ul-i2c", .data = &imx6_i2c_hwdata, },
28962306a36Sopenharmony_ci	{ .compatible = "fsl,imx7s-i2c", .data = &imx6_i2c_hwdata, },
29062306a36Sopenharmony_ci	{ .compatible = "fsl,imx8mm-i2c", .data = &imx6_i2c_hwdata, },
29162306a36Sopenharmony_ci	{ .compatible = "fsl,imx8mn-i2c", .data = &imx6_i2c_hwdata, },
29262306a36Sopenharmony_ci	{ .compatible = "fsl,imx8mp-i2c", .data = &imx6_i2c_hwdata, },
29362306a36Sopenharmony_ci	{ .compatible = "fsl,imx8mq-i2c", .data = &imx6_i2c_hwdata, },
29462306a36Sopenharmony_ci	{ .compatible = "fsl,vf610-i2c", .data = &vf610_i2c_hwdata, },
29562306a36Sopenharmony_ci	{ /* sentinel */ }
29662306a36Sopenharmony_ci};
29762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, i2c_imx_dt_ids);
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic const struct acpi_device_id i2c_imx_acpi_ids[] = {
30062306a36Sopenharmony_ci	{"NXP0001", .driver_data = (kernel_ulong_t)&vf610_i2c_hwdata},
30162306a36Sopenharmony_ci	{ }
30262306a36Sopenharmony_ci};
30362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, i2c_imx_acpi_ids);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_cistatic inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci	return i2c_imx->hwdata->devtype == IMX1_I2C;
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_cistatic inline int is_vf610_i2c(struct imx_i2c_struct *i2c_imx)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	return i2c_imx->hwdata->devtype == VF610_I2C;
31362306a36Sopenharmony_ci}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic inline void imx_i2c_write_reg(unsigned int val,
31662306a36Sopenharmony_ci		struct imx_i2c_struct *i2c_imx, unsigned int reg)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	writeb(val, i2c_imx->base + (reg << i2c_imx->hwdata->regshift));
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,
32262306a36Sopenharmony_ci		unsigned int reg)
32362306a36Sopenharmony_ci{
32462306a36Sopenharmony_ci	return readb(i2c_imx->base + (reg << i2c_imx->hwdata->regshift));
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cistatic void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	unsigned int temp;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	/*
33262306a36Sopenharmony_ci	 * i2sr_clr_opcode is the value to clear all interrupts. Here we want to
33362306a36Sopenharmony_ci	 * clear only <bits>, so we write ~i2sr_clr_opcode with just <bits>
33462306a36Sopenharmony_ci	 * toggled. This is required because i.MX needs W0C and Vybrid uses W1C.
33562306a36Sopenharmony_ci	 */
33662306a36Sopenharmony_ci	temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits;
33762306a36Sopenharmony_ci	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci/* Set up i2c controller register and i2c status register to default value. */
34162306a36Sopenharmony_cistatic void i2c_imx_reset_regs(struct imx_i2c_struct *i2c_imx)
34262306a36Sopenharmony_ci{
34362306a36Sopenharmony_ci	imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
34462306a36Sopenharmony_ci			  i2c_imx, IMX_I2C_I2CR);
34562306a36Sopenharmony_ci	i2c_imx_clear_irq(i2c_imx, I2SR_IIF | I2SR_IAL);
34662306a36Sopenharmony_ci}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci/* Functions for DMA support */
34962306a36Sopenharmony_cistatic void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
35062306a36Sopenharmony_ci						dma_addr_t phy_addr)
35162306a36Sopenharmony_ci{
35262306a36Sopenharmony_ci	struct imx_i2c_dma *dma;
35362306a36Sopenharmony_ci	struct dma_slave_config dma_sconfig;
35462306a36Sopenharmony_ci	struct device *dev = &i2c_imx->adapter.dev;
35562306a36Sopenharmony_ci	int ret;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
35862306a36Sopenharmony_ci	if (!dma)
35962306a36Sopenharmony_ci		return;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	dma->chan_tx = dma_request_chan(dev, "tx");
36262306a36Sopenharmony_ci	if (IS_ERR(dma->chan_tx)) {
36362306a36Sopenharmony_ci		ret = PTR_ERR(dma->chan_tx);
36462306a36Sopenharmony_ci		if (ret != -ENODEV && ret != -EPROBE_DEFER)
36562306a36Sopenharmony_ci			dev_err(dev, "can't request DMA tx channel (%d)\n", ret);
36662306a36Sopenharmony_ci		goto fail_al;
36762306a36Sopenharmony_ci	}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	dma_sconfig.dst_addr = phy_addr +
37062306a36Sopenharmony_ci				(IMX_I2C_I2DR << i2c_imx->hwdata->regshift);
37162306a36Sopenharmony_ci	dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
37262306a36Sopenharmony_ci	dma_sconfig.dst_maxburst = 1;
37362306a36Sopenharmony_ci	dma_sconfig.direction = DMA_MEM_TO_DEV;
37462306a36Sopenharmony_ci	ret = dmaengine_slave_config(dma->chan_tx, &dma_sconfig);
37562306a36Sopenharmony_ci	if (ret < 0) {
37662306a36Sopenharmony_ci		dev_err(dev, "can't configure tx channel (%d)\n", ret);
37762306a36Sopenharmony_ci		goto fail_tx;
37862306a36Sopenharmony_ci	}
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	dma->chan_rx = dma_request_chan(dev, "rx");
38162306a36Sopenharmony_ci	if (IS_ERR(dma->chan_rx)) {
38262306a36Sopenharmony_ci		ret = PTR_ERR(dma->chan_rx);
38362306a36Sopenharmony_ci		if (ret != -ENODEV && ret != -EPROBE_DEFER)
38462306a36Sopenharmony_ci			dev_err(dev, "can't request DMA rx channel (%d)\n", ret);
38562306a36Sopenharmony_ci		goto fail_tx;
38662306a36Sopenharmony_ci	}
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	dma_sconfig.src_addr = phy_addr +
38962306a36Sopenharmony_ci				(IMX_I2C_I2DR << i2c_imx->hwdata->regshift);
39062306a36Sopenharmony_ci	dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
39162306a36Sopenharmony_ci	dma_sconfig.src_maxburst = 1;
39262306a36Sopenharmony_ci	dma_sconfig.direction = DMA_DEV_TO_MEM;
39362306a36Sopenharmony_ci	ret = dmaengine_slave_config(dma->chan_rx, &dma_sconfig);
39462306a36Sopenharmony_ci	if (ret < 0) {
39562306a36Sopenharmony_ci		dev_err(dev, "can't configure rx channel (%d)\n", ret);
39662306a36Sopenharmony_ci		goto fail_rx;
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	i2c_imx->dma = dma;
40062306a36Sopenharmony_ci	init_completion(&dma->cmd_complete);
40162306a36Sopenharmony_ci	dev_info(dev, "using %s (tx) and %s (rx) for DMA transfers\n",
40262306a36Sopenharmony_ci		dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	return;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_cifail_rx:
40762306a36Sopenharmony_ci	dma_release_channel(dma->chan_rx);
40862306a36Sopenharmony_cifail_tx:
40962306a36Sopenharmony_ci	dma_release_channel(dma->chan_tx);
41062306a36Sopenharmony_cifail_al:
41162306a36Sopenharmony_ci	devm_kfree(dev, dma);
41262306a36Sopenharmony_ci}
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_cistatic void i2c_imx_dma_callback(void *arg)
41562306a36Sopenharmony_ci{
41662306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx = (struct imx_i2c_struct *)arg;
41762306a36Sopenharmony_ci	struct imx_i2c_dma *dma = i2c_imx->dma;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	dma_unmap_single(dma->chan_using->device->dev, dma->dma_buf,
42062306a36Sopenharmony_ci			dma->dma_len, dma->dma_data_dir);
42162306a36Sopenharmony_ci	complete(&dma->cmd_complete);
42262306a36Sopenharmony_ci}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_cistatic int i2c_imx_dma_xfer(struct imx_i2c_struct *i2c_imx,
42562306a36Sopenharmony_ci					struct i2c_msg *msgs)
42662306a36Sopenharmony_ci{
42762306a36Sopenharmony_ci	struct imx_i2c_dma *dma = i2c_imx->dma;
42862306a36Sopenharmony_ci	struct dma_async_tx_descriptor *txdesc;
42962306a36Sopenharmony_ci	struct device *dev = &i2c_imx->adapter.dev;
43062306a36Sopenharmony_ci	struct device *chan_dev = dma->chan_using->device->dev;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	dma->dma_buf = dma_map_single(chan_dev, msgs->buf,
43362306a36Sopenharmony_ci					dma->dma_len, dma->dma_data_dir);
43462306a36Sopenharmony_ci	if (dma_mapping_error(chan_dev, dma->dma_buf)) {
43562306a36Sopenharmony_ci		dev_err(dev, "DMA mapping failed\n");
43662306a36Sopenharmony_ci		goto err_map;
43762306a36Sopenharmony_ci	}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	txdesc = dmaengine_prep_slave_single(dma->chan_using, dma->dma_buf,
44062306a36Sopenharmony_ci					dma->dma_len, dma->dma_transfer_dir,
44162306a36Sopenharmony_ci					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
44262306a36Sopenharmony_ci	if (!txdesc) {
44362306a36Sopenharmony_ci		dev_err(dev, "Not able to get desc for DMA xfer\n");
44462306a36Sopenharmony_ci		goto err_desc;
44562306a36Sopenharmony_ci	}
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	reinit_completion(&dma->cmd_complete);
44862306a36Sopenharmony_ci	txdesc->callback = i2c_imx_dma_callback;
44962306a36Sopenharmony_ci	txdesc->callback_param = i2c_imx;
45062306a36Sopenharmony_ci	if (dma_submit_error(dmaengine_submit(txdesc))) {
45162306a36Sopenharmony_ci		dev_err(dev, "DMA submit failed\n");
45262306a36Sopenharmony_ci		goto err_submit;
45362306a36Sopenharmony_ci	}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	dma_async_issue_pending(dma->chan_using);
45662306a36Sopenharmony_ci	return 0;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_cierr_submit:
45962306a36Sopenharmony_ci	dmaengine_terminate_sync(dma->chan_using);
46062306a36Sopenharmony_cierr_desc:
46162306a36Sopenharmony_ci	dma_unmap_single(chan_dev, dma->dma_buf,
46262306a36Sopenharmony_ci			dma->dma_len, dma->dma_data_dir);
46362306a36Sopenharmony_cierr_map:
46462306a36Sopenharmony_ci	return -EINVAL;
46562306a36Sopenharmony_ci}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_cistatic void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
46862306a36Sopenharmony_ci{
46962306a36Sopenharmony_ci	struct imx_i2c_dma *dma = i2c_imx->dma;
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	dma->dma_buf = 0;
47262306a36Sopenharmony_ci	dma->dma_len = 0;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	dma_release_channel(dma->chan_tx);
47562306a36Sopenharmony_ci	dma->chan_tx = NULL;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	dma_release_channel(dma->chan_rx);
47862306a36Sopenharmony_ci	dma->chan_rx = NULL;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	dma->chan_using = NULL;
48162306a36Sopenharmony_ci}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic)
48462306a36Sopenharmony_ci{
48562306a36Sopenharmony_ci	unsigned long orig_jiffies = jiffies;
48662306a36Sopenharmony_ci	unsigned int temp;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	while (1) {
48962306a36Sopenharmony_ci		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci		/* check for arbitration lost */
49262306a36Sopenharmony_ci		if (temp & I2SR_IAL) {
49362306a36Sopenharmony_ci			i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
49462306a36Sopenharmony_ci			return -EAGAIN;
49562306a36Sopenharmony_ci		}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci		if (for_busy && (temp & I2SR_IBB)) {
49862306a36Sopenharmony_ci			i2c_imx->stopped = 0;
49962306a36Sopenharmony_ci			break;
50062306a36Sopenharmony_ci		}
50162306a36Sopenharmony_ci		if (!for_busy && !(temp & I2SR_IBB)) {
50262306a36Sopenharmony_ci			i2c_imx->stopped = 1;
50362306a36Sopenharmony_ci			break;
50462306a36Sopenharmony_ci		}
50562306a36Sopenharmony_ci		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
50662306a36Sopenharmony_ci			dev_dbg(&i2c_imx->adapter.dev,
50762306a36Sopenharmony_ci				"<%s> I2C bus is busy\n", __func__);
50862306a36Sopenharmony_ci			return -ETIMEDOUT;
50962306a36Sopenharmony_ci		}
51062306a36Sopenharmony_ci		if (atomic)
51162306a36Sopenharmony_ci			udelay(100);
51262306a36Sopenharmony_ci		else
51362306a36Sopenharmony_ci			schedule();
51462306a36Sopenharmony_ci	}
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	return 0;
51762306a36Sopenharmony_ci}
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_cistatic int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)
52062306a36Sopenharmony_ci{
52162306a36Sopenharmony_ci	if (atomic) {
52262306a36Sopenharmony_ci		void __iomem *addr = i2c_imx->base + (IMX_I2C_I2SR << i2c_imx->hwdata->regshift);
52362306a36Sopenharmony_ci		unsigned int regval;
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci		/*
52662306a36Sopenharmony_ci		 * The formula for the poll timeout is documented in the RM
52762306a36Sopenharmony_ci		 * Rev.5 on page 1878:
52862306a36Sopenharmony_ci		 *     T_min = 10/F_scl
52962306a36Sopenharmony_ci		 * Set the value hard as it is done for the non-atomic use-case.
53062306a36Sopenharmony_ci		 * Use 10 kHz for the calculation since this is the minimum
53162306a36Sopenharmony_ci		 * allowed SMBus frequency. Also add an offset of 100us since it
53262306a36Sopenharmony_ci		 * turned out that the I2SR_IIF bit isn't set correctly within
53362306a36Sopenharmony_ci		 * the minimum timeout in polling mode.
53462306a36Sopenharmony_ci		 */
53562306a36Sopenharmony_ci		readb_poll_timeout_atomic(addr, regval, regval & I2SR_IIF, 5, 1000 + 100);
53662306a36Sopenharmony_ci		i2c_imx->i2csr = regval;
53762306a36Sopenharmony_ci		i2c_imx_clear_irq(i2c_imx, I2SR_IIF | I2SR_IAL);
53862306a36Sopenharmony_ci	} else {
53962306a36Sopenharmony_ci		wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
54062306a36Sopenharmony_ci	}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
54362306a36Sopenharmony_ci		dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
54462306a36Sopenharmony_ci		return -ETIMEDOUT;
54562306a36Sopenharmony_ci	}
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	/* check for arbitration lost */
54862306a36Sopenharmony_ci	if (i2c_imx->i2csr & I2SR_IAL) {
54962306a36Sopenharmony_ci		dev_dbg(&i2c_imx->adapter.dev, "<%s> Arbitration lost\n", __func__);
55062306a36Sopenharmony_ci		i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci		i2c_imx->i2csr = 0;
55362306a36Sopenharmony_ci		return -EAGAIN;
55462306a36Sopenharmony_ci	}
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__);
55762306a36Sopenharmony_ci	i2c_imx->i2csr = 0;
55862306a36Sopenharmony_ci	return 0;
55962306a36Sopenharmony_ci}
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_cistatic int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
56262306a36Sopenharmony_ci{
56362306a36Sopenharmony_ci	if (imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR) & I2SR_RXAK) {
56462306a36Sopenharmony_ci		dev_dbg(&i2c_imx->adapter.dev, "<%s> No ACK\n", __func__);
56562306a36Sopenharmony_ci		return -ENXIO;  /* No ACK */
56662306a36Sopenharmony_ci	}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "<%s> ACK received\n", __func__);
56962306a36Sopenharmony_ci	return 0;
57062306a36Sopenharmony_ci}
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_cistatic void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
57362306a36Sopenharmony_ci			    unsigned int i2c_clk_rate)
57462306a36Sopenharmony_ci{
57562306a36Sopenharmony_ci	struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
57662306a36Sopenharmony_ci	unsigned int div;
57762306a36Sopenharmony_ci	int i;
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	if (i2c_imx->hwdata->has_err007805 && i2c_imx->bitrate > 384000) {
58062306a36Sopenharmony_ci		dev_dbg(&i2c_imx->adapter.dev,
58162306a36Sopenharmony_ci			"SoC errata ERR007805 or e7805 applies, bus frequency limited from %d Hz to 384000 Hz.\n",
58262306a36Sopenharmony_ci			i2c_imx->bitrate);
58362306a36Sopenharmony_ci		i2c_imx->bitrate = 384000;
58462306a36Sopenharmony_ci	}
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	/* Divider value calculation */
58762306a36Sopenharmony_ci	if (i2c_imx->cur_clk == i2c_clk_rate)
58862306a36Sopenharmony_ci		return;
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	i2c_imx->cur_clk = i2c_clk_rate;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	div = DIV_ROUND_UP(i2c_clk_rate, i2c_imx->bitrate);
59362306a36Sopenharmony_ci	if (div < i2c_clk_div[0].div)
59462306a36Sopenharmony_ci		i = 0;
59562306a36Sopenharmony_ci	else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div)
59662306a36Sopenharmony_ci		i = i2c_imx->hwdata->ndivs - 1;
59762306a36Sopenharmony_ci	else
59862306a36Sopenharmony_ci		for (i = 0; i2c_clk_div[i].div < div; i++)
59962306a36Sopenharmony_ci			;
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	/* Store divider value */
60262306a36Sopenharmony_ci	i2c_imx->ifdr = i2c_clk_div[i].val;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	/*
60562306a36Sopenharmony_ci	 * There dummy delay is calculated.
60662306a36Sopenharmony_ci	 * It should be about one I2C clock period long.
60762306a36Sopenharmony_ci	 * This delay is used in I2C bus disable function
60862306a36Sopenharmony_ci	 * to fix chip hardware bug.
60962306a36Sopenharmony_ci	 */
61062306a36Sopenharmony_ci	i2c_imx->disable_delay = DIV_ROUND_UP(500000U * i2c_clk_div[i].div,
61162306a36Sopenharmony_ci					      i2c_clk_rate / 2);
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci#ifdef CONFIG_I2C_DEBUG_BUS
61462306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "I2C_CLK=%d, REQ DIV=%d\n",
61562306a36Sopenharmony_ci		i2c_clk_rate, div);
61662306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "IFDR[IC]=0x%x, REAL DIV=%d\n",
61762306a36Sopenharmony_ci		i2c_clk_div[i].val, i2c_clk_div[i].div);
61862306a36Sopenharmony_ci#endif
61962306a36Sopenharmony_ci}
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_cistatic int i2c_imx_clk_notifier_call(struct notifier_block *nb,
62262306a36Sopenharmony_ci				     unsigned long action, void *data)
62362306a36Sopenharmony_ci{
62462306a36Sopenharmony_ci	struct clk_notifier_data *ndata = data;
62562306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx = container_of(nb,
62662306a36Sopenharmony_ci						      struct imx_i2c_struct,
62762306a36Sopenharmony_ci						      clk_change_nb);
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	if (action & POST_RATE_CHANGE)
63062306a36Sopenharmony_ci		i2c_imx_set_clk(i2c_imx, ndata->new_rate);
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	return NOTIFY_OK;
63362306a36Sopenharmony_ci}
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_cistatic int i2c_imx_start(struct imx_i2c_struct *i2c_imx, bool atomic)
63662306a36Sopenharmony_ci{
63762306a36Sopenharmony_ci	unsigned int temp = 0;
63862306a36Sopenharmony_ci	int result;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR);
64162306a36Sopenharmony_ci	/* Enable I2C controller */
64262306a36Sopenharmony_ci	imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
64362306a36Sopenharmony_ci	imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode, i2c_imx, IMX_I2C_I2CR);
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	/* Wait controller to be stable */
64662306a36Sopenharmony_ci	if (atomic)
64762306a36Sopenharmony_ci		udelay(50);
64862306a36Sopenharmony_ci	else
64962306a36Sopenharmony_ci		usleep_range(50, 150);
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	/* Start I2C transaction */
65262306a36Sopenharmony_ci	temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
65362306a36Sopenharmony_ci	temp |= I2CR_MSTA;
65462306a36Sopenharmony_ci	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
65562306a36Sopenharmony_ci	result = i2c_imx_bus_busy(i2c_imx, 1, atomic);
65662306a36Sopenharmony_ci	if (result)
65762306a36Sopenharmony_ci		return result;
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
66062306a36Sopenharmony_ci	if (atomic)
66162306a36Sopenharmony_ci		temp &= ~I2CR_IIEN; /* Disable interrupt */
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	temp &= ~I2CR_DMAEN;
66462306a36Sopenharmony_ci	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
66562306a36Sopenharmony_ci	return result;
66662306a36Sopenharmony_ci}
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_cistatic void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic)
66962306a36Sopenharmony_ci{
67062306a36Sopenharmony_ci	unsigned int temp = 0;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	if (!i2c_imx->stopped) {
67362306a36Sopenharmony_ci		/* Stop I2C transaction */
67462306a36Sopenharmony_ci		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
67562306a36Sopenharmony_ci		if (!(temp & I2CR_MSTA))
67662306a36Sopenharmony_ci			i2c_imx->stopped = 1;
67762306a36Sopenharmony_ci		temp &= ~(I2CR_MSTA | I2CR_MTX);
67862306a36Sopenharmony_ci		if (i2c_imx->dma)
67962306a36Sopenharmony_ci			temp &= ~I2CR_DMAEN;
68062306a36Sopenharmony_ci		imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
68162306a36Sopenharmony_ci	}
68262306a36Sopenharmony_ci	if (is_imx1_i2c(i2c_imx)) {
68362306a36Sopenharmony_ci		/*
68462306a36Sopenharmony_ci		 * This delay caused by an i.MXL hardware bug.
68562306a36Sopenharmony_ci		 * If no (or too short) delay, no "STOP" bit will be generated.
68662306a36Sopenharmony_ci		 */
68762306a36Sopenharmony_ci		udelay(i2c_imx->disable_delay);
68862306a36Sopenharmony_ci	}
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	if (!i2c_imx->stopped)
69162306a36Sopenharmony_ci		i2c_imx_bus_busy(i2c_imx, 0, atomic);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	/* Disable I2C controller */
69462306a36Sopenharmony_ci	temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
69562306a36Sopenharmony_ci	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
69662306a36Sopenharmony_ci}
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci/*
69962306a36Sopenharmony_ci * Enable bus idle interrupts
70062306a36Sopenharmony_ci * Note: IBIC register will be cleared after disabled i2c module.
70162306a36Sopenharmony_ci * All of layerscape series SoCs support IBIC register.
70262306a36Sopenharmony_ci */
70362306a36Sopenharmony_cistatic void i2c_imx_enable_bus_idle(struct imx_i2c_struct *i2c_imx)
70462306a36Sopenharmony_ci{
70562306a36Sopenharmony_ci	if (is_vf610_i2c(i2c_imx)) {
70662306a36Sopenharmony_ci		unsigned int temp;
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_IBIC);
70962306a36Sopenharmony_ci		temp |= IBIC_BIIE;
71062306a36Sopenharmony_ci		imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_IBIC);
71162306a36Sopenharmony_ci	}
71262306a36Sopenharmony_ci}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_cistatic void i2c_imx_slave_event(struct imx_i2c_struct *i2c_imx,
71562306a36Sopenharmony_ci				enum i2c_slave_event event, u8 *val)
71662306a36Sopenharmony_ci{
71762306a36Sopenharmony_ci	i2c_slave_event(i2c_imx->slave, event, val);
71862306a36Sopenharmony_ci	i2c_imx->last_slave_event = event;
71962306a36Sopenharmony_ci}
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_cistatic void i2c_imx_slave_finish_op(struct imx_i2c_struct *i2c_imx)
72262306a36Sopenharmony_ci{
72362306a36Sopenharmony_ci	u8 val = 0;
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	while (i2c_imx->last_slave_event != I2C_SLAVE_STOP) {
72662306a36Sopenharmony_ci		switch (i2c_imx->last_slave_event) {
72762306a36Sopenharmony_ci		case I2C_SLAVE_READ_REQUESTED:
72862306a36Sopenharmony_ci			i2c_imx_slave_event(i2c_imx, I2C_SLAVE_READ_PROCESSED,
72962306a36Sopenharmony_ci					    &val);
73062306a36Sopenharmony_ci			break;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci		case I2C_SLAVE_WRITE_REQUESTED:
73362306a36Sopenharmony_ci		case I2C_SLAVE_READ_PROCESSED:
73462306a36Sopenharmony_ci		case I2C_SLAVE_WRITE_RECEIVED:
73562306a36Sopenharmony_ci			i2c_imx_slave_event(i2c_imx, I2C_SLAVE_STOP, &val);
73662306a36Sopenharmony_ci			break;
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci		case I2C_SLAVE_STOP:
73962306a36Sopenharmony_ci			break;
74062306a36Sopenharmony_ci		}
74162306a36Sopenharmony_ci	}
74262306a36Sopenharmony_ci}
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci/* Returns true if the timer should be restarted, false if not. */
74562306a36Sopenharmony_cistatic irqreturn_t i2c_imx_slave_handle(struct imx_i2c_struct *i2c_imx,
74662306a36Sopenharmony_ci					unsigned int status, unsigned int ctl)
74762306a36Sopenharmony_ci{
74862306a36Sopenharmony_ci	u8 value = 0;
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_ci	if (status & I2SR_IAL) { /* Arbitration lost */
75162306a36Sopenharmony_ci		i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
75262306a36Sopenharmony_ci		if (!(status & I2SR_IAAS))
75362306a36Sopenharmony_ci			return IRQ_HANDLED;
75462306a36Sopenharmony_ci	}
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	if (!(status & I2SR_IBB)) {
75762306a36Sopenharmony_ci		/* No master on the bus, that could mean a stop condition. */
75862306a36Sopenharmony_ci		i2c_imx_slave_finish_op(i2c_imx);
75962306a36Sopenharmony_ci		return IRQ_HANDLED;
76062306a36Sopenharmony_ci	}
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	if (!(status & I2SR_ICF))
76362306a36Sopenharmony_ci		/* Data transfer still in progress, ignore this. */
76462306a36Sopenharmony_ci		goto out;
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci	if (status & I2SR_IAAS) { /* Addressed as a slave */
76762306a36Sopenharmony_ci		i2c_imx_slave_finish_op(i2c_imx);
76862306a36Sopenharmony_ci		if (status & I2SR_SRW) { /* Master wants to read from us*/
76962306a36Sopenharmony_ci			dev_dbg(&i2c_imx->adapter.dev, "read requested");
77062306a36Sopenharmony_ci			i2c_imx_slave_event(i2c_imx,
77162306a36Sopenharmony_ci					    I2C_SLAVE_READ_REQUESTED, &value);
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci			/* Slave transmit */
77462306a36Sopenharmony_ci			ctl |= I2CR_MTX;
77562306a36Sopenharmony_ci			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci			/* Send data */
77862306a36Sopenharmony_ci			imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
77962306a36Sopenharmony_ci		} else { /* Master wants to write to us */
78062306a36Sopenharmony_ci			dev_dbg(&i2c_imx->adapter.dev, "write requested");
78162306a36Sopenharmony_ci			i2c_imx_slave_event(i2c_imx,
78262306a36Sopenharmony_ci					    I2C_SLAVE_WRITE_REQUESTED, &value);
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_ci			/* Slave receive */
78562306a36Sopenharmony_ci			ctl &= ~I2CR_MTX;
78662306a36Sopenharmony_ci			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
78762306a36Sopenharmony_ci			/* Dummy read */
78862306a36Sopenharmony_ci			imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
78962306a36Sopenharmony_ci		}
79062306a36Sopenharmony_ci	} else if (!(ctl & I2CR_MTX)) { /* Receive mode */
79162306a36Sopenharmony_ci		value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
79262306a36Sopenharmony_ci		i2c_imx_slave_event(i2c_imx,
79362306a36Sopenharmony_ci				    I2C_SLAVE_WRITE_RECEIVED, &value);
79462306a36Sopenharmony_ci	} else if (!(status & I2SR_RXAK)) { /* Transmit mode received ACK */
79562306a36Sopenharmony_ci		ctl |= I2CR_MTX;
79662306a36Sopenharmony_ci		imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci		i2c_imx_slave_event(i2c_imx,
79962306a36Sopenharmony_ci				    I2C_SLAVE_READ_PROCESSED, &value);
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci		imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
80262306a36Sopenharmony_ci	} else { /* Transmit mode received NAK, operation is done */
80362306a36Sopenharmony_ci		ctl &= ~I2CR_MTX;
80462306a36Sopenharmony_ci		imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
80562306a36Sopenharmony_ci		imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci		/* flag the last byte as processed */
80862306a36Sopenharmony_ci		i2c_imx_slave_event(i2c_imx,
80962306a36Sopenharmony_ci				    I2C_SLAVE_READ_PROCESSED, &value);
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci		i2c_imx_slave_finish_op(i2c_imx);
81262306a36Sopenharmony_ci		return IRQ_HANDLED;
81362306a36Sopenharmony_ci	}
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ciout:
81662306a36Sopenharmony_ci	/*
81762306a36Sopenharmony_ci	 * No need to check the return value here.  If it returns 0 or
81862306a36Sopenharmony_ci	 * 1, then everything is fine.  If it returns -1, then the
81962306a36Sopenharmony_ci	 * timer is running in the handler.  This will still work,
82062306a36Sopenharmony_ci	 * though it may be redone (or already have been done) by the
82162306a36Sopenharmony_ci	 * timer function.
82262306a36Sopenharmony_ci	 */
82362306a36Sopenharmony_ci	hrtimer_try_to_cancel(&i2c_imx->slave_timer);
82462306a36Sopenharmony_ci	hrtimer_forward_now(&i2c_imx->slave_timer, I2C_IMX_CHECK_DELAY);
82562306a36Sopenharmony_ci	hrtimer_restart(&i2c_imx->slave_timer);
82662306a36Sopenharmony_ci	return IRQ_HANDLED;
82762306a36Sopenharmony_ci}
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_cistatic enum hrtimer_restart i2c_imx_slave_timeout(struct hrtimer *t)
83062306a36Sopenharmony_ci{
83162306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx = container_of(t, struct imx_i2c_struct,
83262306a36Sopenharmony_ci						      slave_timer);
83362306a36Sopenharmony_ci	unsigned int ctl, status;
83462306a36Sopenharmony_ci	unsigned long flags;
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	spin_lock_irqsave(&i2c_imx->slave_lock, flags);
83762306a36Sopenharmony_ci	status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
83862306a36Sopenharmony_ci	ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
83962306a36Sopenharmony_ci	i2c_imx_slave_handle(i2c_imx, status, ctl);
84062306a36Sopenharmony_ci	spin_unlock_irqrestore(&i2c_imx->slave_lock, flags);
84162306a36Sopenharmony_ci	return HRTIMER_NORESTART;
84262306a36Sopenharmony_ci}
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_cistatic void i2c_imx_slave_init(struct imx_i2c_struct *i2c_imx)
84562306a36Sopenharmony_ci{
84662306a36Sopenharmony_ci	int temp;
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	/* Set slave addr. */
84962306a36Sopenharmony_ci	imx_i2c_write_reg((i2c_imx->slave->addr << 1), i2c_imx, IMX_I2C_IADR);
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	i2c_imx_reset_regs(i2c_imx);
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	/* Enable module */
85462306a36Sopenharmony_ci	temp = i2c_imx->hwdata->i2cr_ien_opcode;
85562306a36Sopenharmony_ci	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	/* Enable interrupt from i2c module */
85862306a36Sopenharmony_ci	temp |= I2CR_IIEN;
85962306a36Sopenharmony_ci	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci	i2c_imx_enable_bus_idle(i2c_imx);
86262306a36Sopenharmony_ci}
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_cistatic int i2c_imx_reg_slave(struct i2c_client *client)
86562306a36Sopenharmony_ci{
86662306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
86762306a36Sopenharmony_ci	int ret;
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	if (i2c_imx->slave)
87062306a36Sopenharmony_ci		return -EBUSY;
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	i2c_imx->slave = client;
87362306a36Sopenharmony_ci	i2c_imx->last_slave_event = I2C_SLAVE_STOP;
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	/* Resume */
87662306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(i2c_imx->adapter.dev.parent);
87762306a36Sopenharmony_ci	if (ret < 0) {
87862306a36Sopenharmony_ci		dev_err(&i2c_imx->adapter.dev, "failed to resume i2c controller");
87962306a36Sopenharmony_ci		return ret;
88062306a36Sopenharmony_ci	}
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	i2c_imx_slave_init(i2c_imx);
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci	return 0;
88562306a36Sopenharmony_ci}
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_cistatic int i2c_imx_unreg_slave(struct i2c_client *client)
88862306a36Sopenharmony_ci{
88962306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
89062306a36Sopenharmony_ci	int ret;
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	if (!i2c_imx->slave)
89362306a36Sopenharmony_ci		return -EINVAL;
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	/* Reset slave address. */
89662306a36Sopenharmony_ci	imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR);
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	i2c_imx_reset_regs(i2c_imx);
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	i2c_imx->slave = NULL;
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	/* Suspend */
90362306a36Sopenharmony_ci	ret = pm_runtime_put_sync(i2c_imx->adapter.dev.parent);
90462306a36Sopenharmony_ci	if (ret < 0)
90562306a36Sopenharmony_ci		dev_err(&i2c_imx->adapter.dev, "failed to suspend i2c controller");
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	return ret;
90862306a36Sopenharmony_ci}
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_cistatic irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned int status)
91162306a36Sopenharmony_ci{
91262306a36Sopenharmony_ci	/* save status register */
91362306a36Sopenharmony_ci	i2c_imx->i2csr = status;
91462306a36Sopenharmony_ci	wake_up(&i2c_imx->queue);
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	return IRQ_HANDLED;
91762306a36Sopenharmony_ci}
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_cistatic irqreturn_t i2c_imx_isr(int irq, void *dev_id)
92062306a36Sopenharmony_ci{
92162306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx = dev_id;
92262306a36Sopenharmony_ci	unsigned int ctl, status;
92362306a36Sopenharmony_ci	unsigned long flags;
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	spin_lock_irqsave(&i2c_imx->slave_lock, flags);
92662306a36Sopenharmony_ci	status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
92762306a36Sopenharmony_ci	ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	if (status & I2SR_IIF) {
93062306a36Sopenharmony_ci		i2c_imx_clear_irq(i2c_imx, I2SR_IIF);
93162306a36Sopenharmony_ci		if (i2c_imx->slave) {
93262306a36Sopenharmony_ci			if (!(ctl & I2CR_MSTA)) {
93362306a36Sopenharmony_ci				irqreturn_t ret;
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci				ret = i2c_imx_slave_handle(i2c_imx,
93662306a36Sopenharmony_ci							   status, ctl);
93762306a36Sopenharmony_ci				spin_unlock_irqrestore(&i2c_imx->slave_lock,
93862306a36Sopenharmony_ci						       flags);
93962306a36Sopenharmony_ci				return ret;
94062306a36Sopenharmony_ci			}
94162306a36Sopenharmony_ci			i2c_imx_slave_finish_op(i2c_imx);
94262306a36Sopenharmony_ci		}
94362306a36Sopenharmony_ci		spin_unlock_irqrestore(&i2c_imx->slave_lock, flags);
94462306a36Sopenharmony_ci		return i2c_imx_master_isr(i2c_imx, status);
94562306a36Sopenharmony_ci	}
94662306a36Sopenharmony_ci	spin_unlock_irqrestore(&i2c_imx->slave_lock, flags);
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	return IRQ_NONE;
94962306a36Sopenharmony_ci}
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_cistatic int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
95262306a36Sopenharmony_ci					struct i2c_msg *msgs)
95362306a36Sopenharmony_ci{
95462306a36Sopenharmony_ci	int result;
95562306a36Sopenharmony_ci	unsigned long time_left;
95662306a36Sopenharmony_ci	unsigned int temp = 0;
95762306a36Sopenharmony_ci	unsigned long orig_jiffies = jiffies;
95862306a36Sopenharmony_ci	struct imx_i2c_dma *dma = i2c_imx->dma;
95962306a36Sopenharmony_ci	struct device *dev = &i2c_imx->adapter.dev;
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	dma->chan_using = dma->chan_tx;
96262306a36Sopenharmony_ci	dma->dma_transfer_dir = DMA_MEM_TO_DEV;
96362306a36Sopenharmony_ci	dma->dma_data_dir = DMA_TO_DEVICE;
96462306a36Sopenharmony_ci	dma->dma_len = msgs->len - 1;
96562306a36Sopenharmony_ci	result = i2c_imx_dma_xfer(i2c_imx, msgs);
96662306a36Sopenharmony_ci	if (result)
96762306a36Sopenharmony_ci		return result;
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
97062306a36Sopenharmony_ci	temp |= I2CR_DMAEN;
97162306a36Sopenharmony_ci	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	/*
97462306a36Sopenharmony_ci	 * Write slave address.
97562306a36Sopenharmony_ci	 * The first byte must be transmitted by the CPU.
97662306a36Sopenharmony_ci	 */
97762306a36Sopenharmony_ci	imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
97862306a36Sopenharmony_ci	time_left = wait_for_completion_timeout(
97962306a36Sopenharmony_ci				&i2c_imx->dma->cmd_complete,
98062306a36Sopenharmony_ci				msecs_to_jiffies(DMA_TIMEOUT));
98162306a36Sopenharmony_ci	if (time_left == 0) {
98262306a36Sopenharmony_ci		dmaengine_terminate_sync(dma->chan_using);
98362306a36Sopenharmony_ci		return -ETIMEDOUT;
98462306a36Sopenharmony_ci	}
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	/* Waiting for transfer complete. */
98762306a36Sopenharmony_ci	while (1) {
98862306a36Sopenharmony_ci		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
98962306a36Sopenharmony_ci		if (temp & I2SR_ICF)
99062306a36Sopenharmony_ci			break;
99162306a36Sopenharmony_ci		if (time_after(jiffies, orig_jiffies +
99262306a36Sopenharmony_ci				msecs_to_jiffies(DMA_TIMEOUT))) {
99362306a36Sopenharmony_ci			dev_dbg(dev, "<%s> Timeout\n", __func__);
99462306a36Sopenharmony_ci			return -ETIMEDOUT;
99562306a36Sopenharmony_ci		}
99662306a36Sopenharmony_ci		schedule();
99762306a36Sopenharmony_ci	}
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci	temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
100062306a36Sopenharmony_ci	temp &= ~I2CR_DMAEN;
100162306a36Sopenharmony_ci	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_ci	/* The last data byte must be transferred by the CPU. */
100462306a36Sopenharmony_ci	imx_i2c_write_reg(msgs->buf[msgs->len-1],
100562306a36Sopenharmony_ci				i2c_imx, IMX_I2C_I2DR);
100662306a36Sopenharmony_ci	result = i2c_imx_trx_complete(i2c_imx, false);
100762306a36Sopenharmony_ci	if (result)
100862306a36Sopenharmony_ci		return result;
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	return i2c_imx_acked(i2c_imx);
101162306a36Sopenharmony_ci}
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_cistatic int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
101462306a36Sopenharmony_ci			struct i2c_msg *msgs, bool is_lastmsg)
101562306a36Sopenharmony_ci{
101662306a36Sopenharmony_ci	int result;
101762306a36Sopenharmony_ci	unsigned long time_left;
101862306a36Sopenharmony_ci	unsigned int temp;
101962306a36Sopenharmony_ci	unsigned long orig_jiffies = jiffies;
102062306a36Sopenharmony_ci	struct imx_i2c_dma *dma = i2c_imx->dma;
102162306a36Sopenharmony_ci	struct device *dev = &i2c_imx->adapter.dev;
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	dma->chan_using = dma->chan_rx;
102562306a36Sopenharmony_ci	dma->dma_transfer_dir = DMA_DEV_TO_MEM;
102662306a36Sopenharmony_ci	dma->dma_data_dir = DMA_FROM_DEVICE;
102762306a36Sopenharmony_ci	/* The last two data bytes must be transferred by the CPU. */
102862306a36Sopenharmony_ci	dma->dma_len = msgs->len - 2;
102962306a36Sopenharmony_ci	result = i2c_imx_dma_xfer(i2c_imx, msgs);
103062306a36Sopenharmony_ci	if (result)
103162306a36Sopenharmony_ci		return result;
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci	time_left = wait_for_completion_timeout(
103462306a36Sopenharmony_ci				&i2c_imx->dma->cmd_complete,
103562306a36Sopenharmony_ci				msecs_to_jiffies(DMA_TIMEOUT));
103662306a36Sopenharmony_ci	if (time_left == 0) {
103762306a36Sopenharmony_ci		dmaengine_terminate_sync(dma->chan_using);
103862306a36Sopenharmony_ci		return -ETIMEDOUT;
103962306a36Sopenharmony_ci	}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	/* waiting for transfer complete. */
104262306a36Sopenharmony_ci	while (1) {
104362306a36Sopenharmony_ci		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
104462306a36Sopenharmony_ci		if (temp & I2SR_ICF)
104562306a36Sopenharmony_ci			break;
104662306a36Sopenharmony_ci		if (time_after(jiffies, orig_jiffies +
104762306a36Sopenharmony_ci				msecs_to_jiffies(DMA_TIMEOUT))) {
104862306a36Sopenharmony_ci			dev_dbg(dev, "<%s> Timeout\n", __func__);
104962306a36Sopenharmony_ci			return -ETIMEDOUT;
105062306a36Sopenharmony_ci		}
105162306a36Sopenharmony_ci		schedule();
105262306a36Sopenharmony_ci	}
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
105562306a36Sopenharmony_ci	temp &= ~I2CR_DMAEN;
105662306a36Sopenharmony_ci	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci	/* read n-1 byte data */
105962306a36Sopenharmony_ci	temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
106062306a36Sopenharmony_ci	temp |= I2CR_TXAK;
106162306a36Sopenharmony_ci	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	msgs->buf[msgs->len-2] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
106462306a36Sopenharmony_ci	/* read n byte data */
106562306a36Sopenharmony_ci	result = i2c_imx_trx_complete(i2c_imx, false);
106662306a36Sopenharmony_ci	if (result)
106762306a36Sopenharmony_ci		return result;
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	if (is_lastmsg) {
107062306a36Sopenharmony_ci		/*
107162306a36Sopenharmony_ci		 * It must generate STOP before read I2DR to prevent
107262306a36Sopenharmony_ci		 * controller from generating another clock cycle
107362306a36Sopenharmony_ci		 */
107462306a36Sopenharmony_ci		dev_dbg(dev, "<%s> clear MSTA\n", __func__);
107562306a36Sopenharmony_ci		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
107662306a36Sopenharmony_ci		if (!(temp & I2CR_MSTA))
107762306a36Sopenharmony_ci			i2c_imx->stopped = 1;
107862306a36Sopenharmony_ci		temp &= ~(I2CR_MSTA | I2CR_MTX);
107962306a36Sopenharmony_ci		imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
108062306a36Sopenharmony_ci		if (!i2c_imx->stopped)
108162306a36Sopenharmony_ci			i2c_imx_bus_busy(i2c_imx, 0, false);
108262306a36Sopenharmony_ci	} else {
108362306a36Sopenharmony_ci		/*
108462306a36Sopenharmony_ci		 * For i2c master receiver repeat restart operation like:
108562306a36Sopenharmony_ci		 * read -> repeat MSTA -> read/write
108662306a36Sopenharmony_ci		 * The controller must set MTX before read the last byte in
108762306a36Sopenharmony_ci		 * the first read operation, otherwise the first read cost
108862306a36Sopenharmony_ci		 * one extra clock cycle.
108962306a36Sopenharmony_ci		 */
109062306a36Sopenharmony_ci		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
109162306a36Sopenharmony_ci		temp |= I2CR_MTX;
109262306a36Sopenharmony_ci		imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
109362306a36Sopenharmony_ci	}
109462306a36Sopenharmony_ci	msgs->buf[msgs->len-1] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	return 0;
109762306a36Sopenharmony_ci}
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_cistatic int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
110062306a36Sopenharmony_ci			 bool atomic)
110162306a36Sopenharmony_ci{
110262306a36Sopenharmony_ci	int i, result;
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "<%s> write slave address: addr=0x%x\n",
110562306a36Sopenharmony_ci		__func__, i2c_8bit_addr_from_msg(msgs));
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	/* write slave address */
110862306a36Sopenharmony_ci	imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
110962306a36Sopenharmony_ci	result = i2c_imx_trx_complete(i2c_imx, atomic);
111062306a36Sopenharmony_ci	if (result)
111162306a36Sopenharmony_ci		return result;
111262306a36Sopenharmony_ci	result = i2c_imx_acked(i2c_imx);
111362306a36Sopenharmony_ci	if (result)
111462306a36Sopenharmony_ci		return result;
111562306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "<%s> write data\n", __func__);
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci	/* write data */
111862306a36Sopenharmony_ci	for (i = 0; i < msgs->len; i++) {
111962306a36Sopenharmony_ci		dev_dbg(&i2c_imx->adapter.dev,
112062306a36Sopenharmony_ci			"<%s> write byte: B%d=0x%X\n",
112162306a36Sopenharmony_ci			__func__, i, msgs->buf[i]);
112262306a36Sopenharmony_ci		imx_i2c_write_reg(msgs->buf[i], i2c_imx, IMX_I2C_I2DR);
112362306a36Sopenharmony_ci		result = i2c_imx_trx_complete(i2c_imx, atomic);
112462306a36Sopenharmony_ci		if (result)
112562306a36Sopenharmony_ci			return result;
112662306a36Sopenharmony_ci		result = i2c_imx_acked(i2c_imx);
112762306a36Sopenharmony_ci		if (result)
112862306a36Sopenharmony_ci			return result;
112962306a36Sopenharmony_ci	}
113062306a36Sopenharmony_ci	return 0;
113162306a36Sopenharmony_ci}
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_cistatic int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
113462306a36Sopenharmony_ci			bool is_lastmsg, bool atomic)
113562306a36Sopenharmony_ci{
113662306a36Sopenharmony_ci	int i, result;
113762306a36Sopenharmony_ci	unsigned int temp;
113862306a36Sopenharmony_ci	int block_data = msgs->flags & I2C_M_RECV_LEN;
113962306a36Sopenharmony_ci	int use_dma = i2c_imx->dma && msgs->flags & I2C_M_DMA_SAFE &&
114062306a36Sopenharmony_ci		msgs->len >= DMA_THRESHOLD && !block_data;
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev,
114362306a36Sopenharmony_ci		"<%s> write slave address: addr=0x%x\n",
114462306a36Sopenharmony_ci		__func__, i2c_8bit_addr_from_msg(msgs));
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	/* write slave address */
114762306a36Sopenharmony_ci	imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
114862306a36Sopenharmony_ci	result = i2c_imx_trx_complete(i2c_imx, atomic);
114962306a36Sopenharmony_ci	if (result)
115062306a36Sopenharmony_ci		return result;
115162306a36Sopenharmony_ci	result = i2c_imx_acked(i2c_imx);
115262306a36Sopenharmony_ci	if (result)
115362306a36Sopenharmony_ci		return result;
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "<%s> setup bus\n", __func__);
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	/* setup bus to read data */
115862306a36Sopenharmony_ci	temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
115962306a36Sopenharmony_ci	temp &= ~I2CR_MTX;
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci	/*
116262306a36Sopenharmony_ci	 * Reset the I2CR_TXAK flag initially for SMBus block read since the
116362306a36Sopenharmony_ci	 * length is unknown
116462306a36Sopenharmony_ci	 */
116562306a36Sopenharmony_ci	if ((msgs->len - 1) || block_data)
116662306a36Sopenharmony_ci		temp &= ~I2CR_TXAK;
116762306a36Sopenharmony_ci	if (use_dma)
116862306a36Sopenharmony_ci		temp |= I2CR_DMAEN;
116962306a36Sopenharmony_ci	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
117062306a36Sopenharmony_ci	imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__);
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_ci	if (use_dma)
117562306a36Sopenharmony_ci		return i2c_imx_dma_read(i2c_imx, msgs, is_lastmsg);
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_ci	/* read data */
117862306a36Sopenharmony_ci	for (i = 0; i < msgs->len; i++) {
117962306a36Sopenharmony_ci		u8 len = 0;
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci		result = i2c_imx_trx_complete(i2c_imx, atomic);
118262306a36Sopenharmony_ci		if (result)
118362306a36Sopenharmony_ci			return result;
118462306a36Sopenharmony_ci		/*
118562306a36Sopenharmony_ci		 * First byte is the length of remaining packet
118662306a36Sopenharmony_ci		 * in the SMBus block data read. Add it to
118762306a36Sopenharmony_ci		 * msgs->len.
118862306a36Sopenharmony_ci		 */
118962306a36Sopenharmony_ci		if ((!i) && block_data) {
119062306a36Sopenharmony_ci			len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
119162306a36Sopenharmony_ci			if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX))
119262306a36Sopenharmony_ci				return -EPROTO;
119362306a36Sopenharmony_ci			dev_dbg(&i2c_imx->adapter.dev,
119462306a36Sopenharmony_ci				"<%s> read length: 0x%X\n",
119562306a36Sopenharmony_ci				__func__, len);
119662306a36Sopenharmony_ci			msgs->len += len;
119762306a36Sopenharmony_ci		}
119862306a36Sopenharmony_ci		if (i == (msgs->len - 1)) {
119962306a36Sopenharmony_ci			if (is_lastmsg) {
120062306a36Sopenharmony_ci				/*
120162306a36Sopenharmony_ci				 * It must generate STOP before read I2DR to prevent
120262306a36Sopenharmony_ci				 * controller from generating another clock cycle
120362306a36Sopenharmony_ci				 */
120462306a36Sopenharmony_ci				dev_dbg(&i2c_imx->adapter.dev,
120562306a36Sopenharmony_ci					"<%s> clear MSTA\n", __func__);
120662306a36Sopenharmony_ci				temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
120762306a36Sopenharmony_ci				if (!(temp & I2CR_MSTA))
120862306a36Sopenharmony_ci					i2c_imx->stopped =  1;
120962306a36Sopenharmony_ci				temp &= ~(I2CR_MSTA | I2CR_MTX);
121062306a36Sopenharmony_ci				imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
121162306a36Sopenharmony_ci				if (!i2c_imx->stopped)
121262306a36Sopenharmony_ci					i2c_imx_bus_busy(i2c_imx, 0, atomic);
121362306a36Sopenharmony_ci			} else {
121462306a36Sopenharmony_ci				/*
121562306a36Sopenharmony_ci				 * For i2c master receiver repeat restart operation like:
121662306a36Sopenharmony_ci				 * read -> repeat MSTA -> read/write
121762306a36Sopenharmony_ci				 * The controller must set MTX before read the last byte in
121862306a36Sopenharmony_ci				 * the first read operation, otherwise the first read cost
121962306a36Sopenharmony_ci				 * one extra clock cycle.
122062306a36Sopenharmony_ci				 */
122162306a36Sopenharmony_ci				temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
122262306a36Sopenharmony_ci				temp |= I2CR_MTX;
122362306a36Sopenharmony_ci				imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
122462306a36Sopenharmony_ci			}
122562306a36Sopenharmony_ci		} else if (i == (msgs->len - 2)) {
122662306a36Sopenharmony_ci			dev_dbg(&i2c_imx->adapter.dev,
122762306a36Sopenharmony_ci				"<%s> set TXAK\n", __func__);
122862306a36Sopenharmony_ci			temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
122962306a36Sopenharmony_ci			temp |= I2CR_TXAK;
123062306a36Sopenharmony_ci			imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
123162306a36Sopenharmony_ci		}
123262306a36Sopenharmony_ci		if ((!i) && block_data)
123362306a36Sopenharmony_ci			msgs->buf[0] = len;
123462306a36Sopenharmony_ci		else
123562306a36Sopenharmony_ci			msgs->buf[i] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
123662306a36Sopenharmony_ci		dev_dbg(&i2c_imx->adapter.dev,
123762306a36Sopenharmony_ci			"<%s> read byte: B%d=0x%X\n",
123862306a36Sopenharmony_ci			__func__, i, msgs->buf[i]);
123962306a36Sopenharmony_ci	}
124062306a36Sopenharmony_ci	return 0;
124162306a36Sopenharmony_ci}
124262306a36Sopenharmony_ci
124362306a36Sopenharmony_cistatic int i2c_imx_xfer_common(struct i2c_adapter *adapter,
124462306a36Sopenharmony_ci			       struct i2c_msg *msgs, int num, bool atomic)
124562306a36Sopenharmony_ci{
124662306a36Sopenharmony_ci	unsigned int i, temp;
124762306a36Sopenharmony_ci	int result;
124862306a36Sopenharmony_ci	bool is_lastmsg = false;
124962306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter);
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci	/* Start I2C transfer */
125262306a36Sopenharmony_ci	result = i2c_imx_start(i2c_imx, atomic);
125362306a36Sopenharmony_ci	if (result) {
125462306a36Sopenharmony_ci		/*
125562306a36Sopenharmony_ci		 * Bus recovery uses gpiod_get_value_cansleep() which is not
125662306a36Sopenharmony_ci		 * allowed within atomic context.
125762306a36Sopenharmony_ci		 */
125862306a36Sopenharmony_ci		if (!atomic && i2c_imx->adapter.bus_recovery_info) {
125962306a36Sopenharmony_ci			i2c_recover_bus(&i2c_imx->adapter);
126062306a36Sopenharmony_ci			result = i2c_imx_start(i2c_imx, atomic);
126162306a36Sopenharmony_ci		}
126262306a36Sopenharmony_ci	}
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci	if (result)
126562306a36Sopenharmony_ci		goto fail0;
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci	/* read/write data */
126862306a36Sopenharmony_ci	for (i = 0; i < num; i++) {
126962306a36Sopenharmony_ci		if (i == num - 1)
127062306a36Sopenharmony_ci			is_lastmsg = true;
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci		if (i) {
127362306a36Sopenharmony_ci			dev_dbg(&i2c_imx->adapter.dev,
127462306a36Sopenharmony_ci				"<%s> repeated start\n", __func__);
127562306a36Sopenharmony_ci			temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
127662306a36Sopenharmony_ci			temp |= I2CR_RSTA;
127762306a36Sopenharmony_ci			imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
127862306a36Sopenharmony_ci			result = i2c_imx_bus_busy(i2c_imx, 1, atomic);
127962306a36Sopenharmony_ci			if (result)
128062306a36Sopenharmony_ci				goto fail0;
128162306a36Sopenharmony_ci		}
128262306a36Sopenharmony_ci		dev_dbg(&i2c_imx->adapter.dev,
128362306a36Sopenharmony_ci			"<%s> transfer message: %d\n", __func__, i);
128462306a36Sopenharmony_ci		/* write/read data */
128562306a36Sopenharmony_ci#ifdef CONFIG_I2C_DEBUG_BUS
128662306a36Sopenharmony_ci		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
128762306a36Sopenharmony_ci		dev_dbg(&i2c_imx->adapter.dev,
128862306a36Sopenharmony_ci			"<%s> CONTROL: IEN=%d, IIEN=%d, MSTA=%d, MTX=%d, TXAK=%d, RSTA=%d\n",
128962306a36Sopenharmony_ci			__func__,
129062306a36Sopenharmony_ci			(temp & I2CR_IEN ? 1 : 0), (temp & I2CR_IIEN ? 1 : 0),
129162306a36Sopenharmony_ci			(temp & I2CR_MSTA ? 1 : 0), (temp & I2CR_MTX ? 1 : 0),
129262306a36Sopenharmony_ci			(temp & I2CR_TXAK ? 1 : 0), (temp & I2CR_RSTA ? 1 : 0));
129362306a36Sopenharmony_ci		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
129462306a36Sopenharmony_ci		dev_dbg(&i2c_imx->adapter.dev,
129562306a36Sopenharmony_ci			"<%s> STATUS: ICF=%d, IAAS=%d, IBB=%d, IAL=%d, SRW=%d, IIF=%d, RXAK=%d\n",
129662306a36Sopenharmony_ci			__func__,
129762306a36Sopenharmony_ci			(temp & I2SR_ICF ? 1 : 0), (temp & I2SR_IAAS ? 1 : 0),
129862306a36Sopenharmony_ci			(temp & I2SR_IBB ? 1 : 0), (temp & I2SR_IAL ? 1 : 0),
129962306a36Sopenharmony_ci			(temp & I2SR_SRW ? 1 : 0), (temp & I2SR_IIF ? 1 : 0),
130062306a36Sopenharmony_ci			(temp & I2SR_RXAK ? 1 : 0));
130162306a36Sopenharmony_ci#endif
130262306a36Sopenharmony_ci		if (msgs[i].flags & I2C_M_RD) {
130362306a36Sopenharmony_ci			result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg, atomic);
130462306a36Sopenharmony_ci		} else {
130562306a36Sopenharmony_ci			if (!atomic &&
130662306a36Sopenharmony_ci			    i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD &&
130762306a36Sopenharmony_ci				msgs[i].flags & I2C_M_DMA_SAFE)
130862306a36Sopenharmony_ci				result = i2c_imx_dma_write(i2c_imx, &msgs[i]);
130962306a36Sopenharmony_ci			else
131062306a36Sopenharmony_ci				result = i2c_imx_write(i2c_imx, &msgs[i], atomic);
131162306a36Sopenharmony_ci		}
131262306a36Sopenharmony_ci		if (result)
131362306a36Sopenharmony_ci			goto fail0;
131462306a36Sopenharmony_ci	}
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_cifail0:
131762306a36Sopenharmony_ci	/* Stop I2C transfer */
131862306a36Sopenharmony_ci	i2c_imx_stop(i2c_imx, atomic);
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
132162306a36Sopenharmony_ci		(result < 0) ? "error" : "success msg",
132262306a36Sopenharmony_ci			(result < 0) ? result : num);
132362306a36Sopenharmony_ci	/* After data is transferred, switch to slave mode(as a receiver) */
132462306a36Sopenharmony_ci	if (i2c_imx->slave)
132562306a36Sopenharmony_ci		i2c_imx_slave_init(i2c_imx);
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci	return (result < 0) ? result : num;
132862306a36Sopenharmony_ci}
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_cistatic int i2c_imx_xfer(struct i2c_adapter *adapter,
133162306a36Sopenharmony_ci			struct i2c_msg *msgs, int num)
133262306a36Sopenharmony_ci{
133362306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter);
133462306a36Sopenharmony_ci	int result;
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	result = pm_runtime_resume_and_get(i2c_imx->adapter.dev.parent);
133762306a36Sopenharmony_ci	if (result < 0)
133862306a36Sopenharmony_ci		return result;
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	result = i2c_imx_xfer_common(adapter, msgs, num, false);
134162306a36Sopenharmony_ci
134262306a36Sopenharmony_ci	pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent);
134362306a36Sopenharmony_ci	pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent);
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	return result;
134662306a36Sopenharmony_ci}
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_cistatic int i2c_imx_xfer_atomic(struct i2c_adapter *adapter,
134962306a36Sopenharmony_ci			       struct i2c_msg *msgs, int num)
135062306a36Sopenharmony_ci{
135162306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter);
135262306a36Sopenharmony_ci	int result;
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_ci	result = clk_enable(i2c_imx->clk);
135562306a36Sopenharmony_ci	if (result)
135662306a36Sopenharmony_ci		return result;
135762306a36Sopenharmony_ci
135862306a36Sopenharmony_ci	result = i2c_imx_xfer_common(adapter, msgs, num, true);
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	clk_disable(i2c_imx->clk);
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci	return result;
136362306a36Sopenharmony_ci}
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_cistatic void i2c_imx_prepare_recovery(struct i2c_adapter *adap)
136662306a36Sopenharmony_ci{
136762306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx;
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci	i2c_imx = container_of(adap, struct imx_i2c_struct, adapter);
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci	pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_gpio);
137262306a36Sopenharmony_ci}
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_cistatic void i2c_imx_unprepare_recovery(struct i2c_adapter *adap)
137562306a36Sopenharmony_ci{
137662306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx;
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	i2c_imx = container_of(adap, struct imx_i2c_struct, adapter);
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_default);
138162306a36Sopenharmony_ci}
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci/*
138462306a36Sopenharmony_ci * We switch SCL and SDA to their GPIO function and do some bitbanging
138562306a36Sopenharmony_ci * for bus recovery. These alternative pinmux settings can be
138662306a36Sopenharmony_ci * described in the device tree by a separate pinctrl state "gpio". If
138762306a36Sopenharmony_ci * this is missing this is not a big problem, the only implication is
138862306a36Sopenharmony_ci * that we can't do bus recovery.
138962306a36Sopenharmony_ci */
139062306a36Sopenharmony_cistatic int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
139162306a36Sopenharmony_ci		struct platform_device *pdev)
139262306a36Sopenharmony_ci{
139362306a36Sopenharmony_ci	struct i2c_bus_recovery_info *rinfo = &i2c_imx->rinfo;
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci	i2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev);
139662306a36Sopenharmony_ci	if (!i2c_imx->pinctrl) {
139762306a36Sopenharmony_ci		dev_info(&pdev->dev, "pinctrl unavailable, bus recovery not supported\n");
139862306a36Sopenharmony_ci		return 0;
139962306a36Sopenharmony_ci	}
140062306a36Sopenharmony_ci	if (IS_ERR(i2c_imx->pinctrl)) {
140162306a36Sopenharmony_ci		dev_info(&pdev->dev, "can't get pinctrl, bus recovery not supported\n");
140262306a36Sopenharmony_ci		return PTR_ERR(i2c_imx->pinctrl);
140362306a36Sopenharmony_ci	}
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci	i2c_imx->pinctrl_pins_default = pinctrl_lookup_state(i2c_imx->pinctrl,
140662306a36Sopenharmony_ci			PINCTRL_STATE_DEFAULT);
140762306a36Sopenharmony_ci	i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
140862306a36Sopenharmony_ci			"gpio");
140962306a36Sopenharmony_ci	rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
141062306a36Sopenharmony_ci	rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ci	if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER ||
141362306a36Sopenharmony_ci	    PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER) {
141462306a36Sopenharmony_ci		return -EPROBE_DEFER;
141562306a36Sopenharmony_ci	} else if (IS_ERR(rinfo->sda_gpiod) ||
141662306a36Sopenharmony_ci		   IS_ERR(rinfo->scl_gpiod) ||
141762306a36Sopenharmony_ci		   IS_ERR(i2c_imx->pinctrl_pins_default) ||
141862306a36Sopenharmony_ci		   IS_ERR(i2c_imx->pinctrl_pins_gpio)) {
141962306a36Sopenharmony_ci		dev_dbg(&pdev->dev, "recovery information incomplete\n");
142062306a36Sopenharmony_ci		return 0;
142162306a36Sopenharmony_ci	}
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	dev_dbg(&pdev->dev, "using scl%s for recovery\n",
142462306a36Sopenharmony_ci		rinfo->sda_gpiod ? ",sda" : "");
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci	rinfo->prepare_recovery = i2c_imx_prepare_recovery;
142762306a36Sopenharmony_ci	rinfo->unprepare_recovery = i2c_imx_unprepare_recovery;
142862306a36Sopenharmony_ci	rinfo->recover_bus = i2c_generic_scl_recovery;
142962306a36Sopenharmony_ci	i2c_imx->adapter.bus_recovery_info = rinfo;
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci	return 0;
143262306a36Sopenharmony_ci}
143362306a36Sopenharmony_ci
143462306a36Sopenharmony_cistatic u32 i2c_imx_func(struct i2c_adapter *adapter)
143562306a36Sopenharmony_ci{
143662306a36Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
143762306a36Sopenharmony_ci		| I2C_FUNC_SMBUS_READ_BLOCK_DATA;
143862306a36Sopenharmony_ci}
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_cistatic const struct i2c_algorithm i2c_imx_algo = {
144162306a36Sopenharmony_ci	.master_xfer = i2c_imx_xfer,
144262306a36Sopenharmony_ci	.master_xfer_atomic = i2c_imx_xfer_atomic,
144362306a36Sopenharmony_ci	.functionality = i2c_imx_func,
144462306a36Sopenharmony_ci	.reg_slave	= i2c_imx_reg_slave,
144562306a36Sopenharmony_ci	.unreg_slave	= i2c_imx_unreg_slave,
144662306a36Sopenharmony_ci};
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_cistatic int i2c_imx_probe(struct platform_device *pdev)
144962306a36Sopenharmony_ci{
145062306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx;
145162306a36Sopenharmony_ci	struct resource *res;
145262306a36Sopenharmony_ci	struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
145362306a36Sopenharmony_ci	void __iomem *base;
145462306a36Sopenharmony_ci	int irq, ret;
145562306a36Sopenharmony_ci	dma_addr_t phy_addr;
145662306a36Sopenharmony_ci	const struct imx_i2c_hwdata *match;
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
145962306a36Sopenharmony_ci	if (irq < 0)
146062306a36Sopenharmony_ci		return irq;
146162306a36Sopenharmony_ci
146262306a36Sopenharmony_ci	base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
146362306a36Sopenharmony_ci	if (IS_ERR(base))
146462306a36Sopenharmony_ci		return PTR_ERR(base);
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	phy_addr = (dma_addr_t)res->start;
146762306a36Sopenharmony_ci	i2c_imx = devm_kzalloc(&pdev->dev, sizeof(*i2c_imx), GFP_KERNEL);
146862306a36Sopenharmony_ci	if (!i2c_imx)
146962306a36Sopenharmony_ci		return -ENOMEM;
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci	spin_lock_init(&i2c_imx->slave_lock);
147262306a36Sopenharmony_ci	hrtimer_init(&i2c_imx->slave_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
147362306a36Sopenharmony_ci	i2c_imx->slave_timer.function = i2c_imx_slave_timeout;
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci	match = device_get_match_data(&pdev->dev);
147662306a36Sopenharmony_ci	if (match)
147762306a36Sopenharmony_ci		i2c_imx->hwdata = match;
147862306a36Sopenharmony_ci	else
147962306a36Sopenharmony_ci		i2c_imx->hwdata = (struct imx_i2c_hwdata *)
148062306a36Sopenharmony_ci				platform_get_device_id(pdev)->driver_data;
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci	/* Setup i2c_imx driver structure */
148362306a36Sopenharmony_ci	strscpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name));
148462306a36Sopenharmony_ci	i2c_imx->adapter.owner		= THIS_MODULE;
148562306a36Sopenharmony_ci	i2c_imx->adapter.algo		= &i2c_imx_algo;
148662306a36Sopenharmony_ci	i2c_imx->adapter.dev.parent	= &pdev->dev;
148762306a36Sopenharmony_ci	i2c_imx->adapter.nr		= pdev->id;
148862306a36Sopenharmony_ci	i2c_imx->adapter.dev.of_node	= pdev->dev.of_node;
148962306a36Sopenharmony_ci	i2c_imx->base			= base;
149062306a36Sopenharmony_ci	ACPI_COMPANION_SET(&i2c_imx->adapter.dev, ACPI_COMPANION(&pdev->dev));
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	/* Get I2C clock */
149362306a36Sopenharmony_ci	i2c_imx->clk = devm_clk_get_enabled(&pdev->dev, NULL);
149462306a36Sopenharmony_ci	if (IS_ERR(i2c_imx->clk))
149562306a36Sopenharmony_ci		return dev_err_probe(&pdev->dev, PTR_ERR(i2c_imx->clk),
149662306a36Sopenharmony_ci				     "can't get I2C clock\n");
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci	/* Init queue */
149962306a36Sopenharmony_ci	init_waitqueue_head(&i2c_imx->queue);
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ci	/* Set up adapter data */
150262306a36Sopenharmony_ci	i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
150362306a36Sopenharmony_ci
150462306a36Sopenharmony_ci	/* Set up platform driver data */
150562306a36Sopenharmony_ci	platform_set_drvdata(pdev, i2c_imx);
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
150862306a36Sopenharmony_ci	pm_runtime_use_autosuspend(&pdev->dev);
150962306a36Sopenharmony_ci	pm_runtime_set_active(&pdev->dev);
151062306a36Sopenharmony_ci	pm_runtime_enable(&pdev->dev);
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	ret = pm_runtime_get_sync(&pdev->dev);
151362306a36Sopenharmony_ci	if (ret < 0)
151462306a36Sopenharmony_ci		goto rpm_disable;
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci	/* Request IRQ */
151762306a36Sopenharmony_ci	ret = request_irq(irq, i2c_imx_isr, IRQF_SHARED, pdev->name, i2c_imx);
151862306a36Sopenharmony_ci	if (ret) {
151962306a36Sopenharmony_ci		dev_err(&pdev->dev, "can't claim irq %d\n", irq);
152062306a36Sopenharmony_ci		goto rpm_disable;
152162306a36Sopenharmony_ci	}
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci	/* Set up clock divider */
152462306a36Sopenharmony_ci	i2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ;
152562306a36Sopenharmony_ci	ret = of_property_read_u32(pdev->dev.of_node,
152662306a36Sopenharmony_ci				   "clock-frequency", &i2c_imx->bitrate);
152762306a36Sopenharmony_ci	if (ret < 0 && pdata && pdata->bitrate)
152862306a36Sopenharmony_ci		i2c_imx->bitrate = pdata->bitrate;
152962306a36Sopenharmony_ci	i2c_imx->clk_change_nb.notifier_call = i2c_imx_clk_notifier_call;
153062306a36Sopenharmony_ci	clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb);
153162306a36Sopenharmony_ci	i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk));
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci	i2c_imx_reset_regs(i2c_imx);
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	/* Init optional bus recovery function */
153662306a36Sopenharmony_ci	ret = i2c_imx_init_recovery_info(i2c_imx, pdev);
153762306a36Sopenharmony_ci	/* Give it another chance if pinctrl used is not ready yet */
153862306a36Sopenharmony_ci	if (ret == -EPROBE_DEFER)
153962306a36Sopenharmony_ci		goto clk_notifier_unregister;
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci	/* Add I2C adapter */
154262306a36Sopenharmony_ci	ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
154362306a36Sopenharmony_ci	if (ret < 0)
154462306a36Sopenharmony_ci		goto clk_notifier_unregister;
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	pm_runtime_mark_last_busy(&pdev->dev);
154762306a36Sopenharmony_ci	pm_runtime_put_autosuspend(&pdev->dev);
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq);
155062306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res);
155162306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",
155262306a36Sopenharmony_ci		i2c_imx->adapter.name);
155362306a36Sopenharmony_ci	dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci	/* Init DMA config if supported */
155662306a36Sopenharmony_ci	i2c_imx_dma_request(i2c_imx, phy_addr);
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci	return 0;   /* Return OK */
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_ciclk_notifier_unregister:
156162306a36Sopenharmony_ci	clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
156262306a36Sopenharmony_ci	free_irq(irq, i2c_imx);
156362306a36Sopenharmony_cirpm_disable:
156462306a36Sopenharmony_ci	pm_runtime_put_noidle(&pdev->dev);
156562306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
156662306a36Sopenharmony_ci	pm_runtime_set_suspended(&pdev->dev);
156762306a36Sopenharmony_ci	pm_runtime_dont_use_autosuspend(&pdev->dev);
156862306a36Sopenharmony_ci	return ret;
156962306a36Sopenharmony_ci}
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_cistatic void i2c_imx_remove(struct platform_device *pdev)
157262306a36Sopenharmony_ci{
157362306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
157462306a36Sopenharmony_ci	int irq, ret;
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	ret = pm_runtime_get_sync(&pdev->dev);
157762306a36Sopenharmony_ci
157862306a36Sopenharmony_ci	hrtimer_cancel(&i2c_imx->slave_timer);
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci	/* remove adapter */
158162306a36Sopenharmony_ci	dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n");
158262306a36Sopenharmony_ci	i2c_del_adapter(&i2c_imx->adapter);
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	if (i2c_imx->dma)
158562306a36Sopenharmony_ci		i2c_imx_dma_free(i2c_imx);
158662306a36Sopenharmony_ci
158762306a36Sopenharmony_ci	if (ret >= 0) {
158862306a36Sopenharmony_ci		/* setup chip registers to defaults */
158962306a36Sopenharmony_ci		imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR);
159062306a36Sopenharmony_ci		imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IFDR);
159162306a36Sopenharmony_ci		imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR);
159262306a36Sopenharmony_ci		imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
159362306a36Sopenharmony_ci	}
159462306a36Sopenharmony_ci
159562306a36Sopenharmony_ci	clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
159662306a36Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
159762306a36Sopenharmony_ci	if (irq >= 0)
159862306a36Sopenharmony_ci		free_irq(irq, i2c_imx);
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	pm_runtime_put_noidle(&pdev->dev);
160162306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
160262306a36Sopenharmony_ci}
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_cistatic int __maybe_unused i2c_imx_runtime_suspend(struct device *dev)
160562306a36Sopenharmony_ci{
160662306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci	clk_disable(i2c_imx->clk);
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	return 0;
161162306a36Sopenharmony_ci}
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_cistatic int __maybe_unused i2c_imx_runtime_resume(struct device *dev)
161462306a36Sopenharmony_ci{
161562306a36Sopenharmony_ci	struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
161662306a36Sopenharmony_ci	int ret;
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci	ret = clk_enable(i2c_imx->clk);
161962306a36Sopenharmony_ci	if (ret)
162062306a36Sopenharmony_ci		dev_err(dev, "can't enable I2C clock, ret=%d\n", ret);
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci	return ret;
162362306a36Sopenharmony_ci}
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_cistatic const struct dev_pm_ops i2c_imx_pm_ops = {
162662306a36Sopenharmony_ci	SET_RUNTIME_PM_OPS(i2c_imx_runtime_suspend,
162762306a36Sopenharmony_ci			   i2c_imx_runtime_resume, NULL)
162862306a36Sopenharmony_ci};
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_cistatic struct platform_driver i2c_imx_driver = {
163162306a36Sopenharmony_ci	.probe = i2c_imx_probe,
163262306a36Sopenharmony_ci	.remove_new = i2c_imx_remove,
163362306a36Sopenharmony_ci	.driver = {
163462306a36Sopenharmony_ci		.name = DRIVER_NAME,
163562306a36Sopenharmony_ci		.pm = &i2c_imx_pm_ops,
163662306a36Sopenharmony_ci		.of_match_table = i2c_imx_dt_ids,
163762306a36Sopenharmony_ci		.acpi_match_table = i2c_imx_acpi_ids,
163862306a36Sopenharmony_ci	},
163962306a36Sopenharmony_ci	.id_table = imx_i2c_devtype,
164062306a36Sopenharmony_ci};
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_cistatic int __init i2c_adap_imx_init(void)
164362306a36Sopenharmony_ci{
164462306a36Sopenharmony_ci	return platform_driver_register(&i2c_imx_driver);
164562306a36Sopenharmony_ci}
164662306a36Sopenharmony_cisubsys_initcall(i2c_adap_imx_init);
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_cistatic void __exit i2c_adap_imx_exit(void)
164962306a36Sopenharmony_ci{
165062306a36Sopenharmony_ci	platform_driver_unregister(&i2c_imx_driver);
165162306a36Sopenharmony_ci}
165262306a36Sopenharmony_cimodule_exit(i2c_adap_imx_exit);
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ciMODULE_LICENSE("GPL");
165562306a36Sopenharmony_ciMODULE_AUTHOR("Darius Augulis");
165662306a36Sopenharmony_ciMODULE_DESCRIPTION("I2C adapter driver for IMX I2C bus");
165762306a36Sopenharmony_ciMODULE_ALIAS("platform:" DRIVER_NAME);
1658