18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  i2c_adap_pxa.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  I2C adapter for the PXA I2C bus access.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci *  Copyright (C) 2002 Intrinsyc Software Inc.
88c2ecf20Sopenharmony_ci *  Copyright (C) 2004-2005 Deep Blue Solutions Ltd.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci *  History:
118c2ecf20Sopenharmony_ci *    Apr 2002: Initial version [CS]
128c2ecf20Sopenharmony_ci *    Jun 2002: Properly separated algo/adap [FB]
138c2ecf20Sopenharmony_ci *    Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem]
148c2ecf20Sopenharmony_ci *    Jan 2003: added limited signal handling [Kai-Uwe Bloem]
158c2ecf20Sopenharmony_ci *    Sep 2004: Major rework to ensure efficient bus handling [RMK]
168c2ecf20Sopenharmony_ci *    Dec 2004: Added support for PXA27x and slave device probing [Liam Girdwood]
178c2ecf20Sopenharmony_ci *    Feb 2005: Rework slave mode handling [RMK]
188c2ecf20Sopenharmony_ci */
198c2ecf20Sopenharmony_ci#include <linux/clk.h>
208c2ecf20Sopenharmony_ci#include <linux/delay.h>
218c2ecf20Sopenharmony_ci#include <linux/err.h>
228c2ecf20Sopenharmony_ci#include <linux/errno.h>
238c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h>
248c2ecf20Sopenharmony_ci#include <linux/i2c.h>
258c2ecf20Sopenharmony_ci#include <linux/init.h>
268c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
278c2ecf20Sopenharmony_ci#include <linux/io.h>
288c2ecf20Sopenharmony_ci#include <linux/kernel.h>
298c2ecf20Sopenharmony_ci#include <linux/module.h>
308c2ecf20Sopenharmony_ci#include <linux/of.h>
318c2ecf20Sopenharmony_ci#include <linux/of_device.h>
328c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h>
338c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
348c2ecf20Sopenharmony_ci#include <linux/platform_data/i2c-pxa.h>
358c2ecf20Sopenharmony_ci#include <linux/slab.h>
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/* I2C register field definitions */
388c2ecf20Sopenharmony_ci#define IBMR_SDAS	(1 << 0)
398c2ecf20Sopenharmony_ci#define IBMR_SCLS	(1 << 1)
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define ICR_START	(1 << 0)	   /* start bit */
428c2ecf20Sopenharmony_ci#define ICR_STOP	(1 << 1)	   /* stop bit */
438c2ecf20Sopenharmony_ci#define ICR_ACKNAK	(1 << 2)	   /* send ACK(0) or NAK(1) */
448c2ecf20Sopenharmony_ci#define ICR_TB		(1 << 3)	   /* transfer byte bit */
458c2ecf20Sopenharmony_ci#define ICR_MA		(1 << 4)	   /* master abort */
468c2ecf20Sopenharmony_ci#define ICR_SCLE	(1 << 5)	   /* master clock enable */
478c2ecf20Sopenharmony_ci#define ICR_IUE		(1 << 6)	   /* unit enable */
488c2ecf20Sopenharmony_ci#define ICR_GCD		(1 << 7)	   /* general call disable */
498c2ecf20Sopenharmony_ci#define ICR_ITEIE	(1 << 8)	   /* enable tx interrupts */
508c2ecf20Sopenharmony_ci#define ICR_IRFIE	(1 << 9)	   /* enable rx interrupts */
518c2ecf20Sopenharmony_ci#define ICR_BEIE	(1 << 10)	   /* enable bus error ints */
528c2ecf20Sopenharmony_ci#define ICR_SSDIE	(1 << 11)	   /* slave STOP detected int enable */
538c2ecf20Sopenharmony_ci#define ICR_ALDIE	(1 << 12)	   /* enable arbitration interrupt */
548c2ecf20Sopenharmony_ci#define ICR_SADIE	(1 << 13)	   /* slave address detected int enable */
558c2ecf20Sopenharmony_ci#define ICR_UR		(1 << 14)	   /* unit reset */
568c2ecf20Sopenharmony_ci#define ICR_FM		(1 << 15)	   /* fast mode */
578c2ecf20Sopenharmony_ci#define ICR_HS		(1 << 16)	   /* High Speed mode */
588c2ecf20Sopenharmony_ci#define ICR_A3700_FM	(1 << 16)	   /* fast mode for armada-3700 */
598c2ecf20Sopenharmony_ci#define ICR_A3700_HS	(1 << 17)	   /* high speed mode for armada-3700 */
608c2ecf20Sopenharmony_ci#define ICR_GPIOEN	(1 << 19)	   /* enable GPIO mode for SCL in HS */
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#define ISR_RWM		(1 << 0)	   /* read/write mode */
638c2ecf20Sopenharmony_ci#define ISR_ACKNAK	(1 << 1)	   /* ack/nak status */
648c2ecf20Sopenharmony_ci#define ISR_UB		(1 << 2)	   /* unit busy */
658c2ecf20Sopenharmony_ci#define ISR_IBB		(1 << 3)	   /* bus busy */
668c2ecf20Sopenharmony_ci#define ISR_SSD		(1 << 4)	   /* slave stop detected */
678c2ecf20Sopenharmony_ci#define ISR_ALD		(1 << 5)	   /* arbitration loss detected */
688c2ecf20Sopenharmony_ci#define ISR_ITE		(1 << 6)	   /* tx buffer empty */
698c2ecf20Sopenharmony_ci#define ISR_IRF		(1 << 7)	   /* rx buffer full */
708c2ecf20Sopenharmony_ci#define ISR_GCAD	(1 << 8)	   /* general call address detected */
718c2ecf20Sopenharmony_ci#define ISR_SAD		(1 << 9)	   /* slave address detected */
728c2ecf20Sopenharmony_ci#define ISR_BED		(1 << 10)	   /* bus error no ACK/NAK */
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci#define ILCR_SLV_SHIFT		0
758c2ecf20Sopenharmony_ci#define ILCR_SLV_MASK		(0x1FF << ILCR_SLV_SHIFT)
768c2ecf20Sopenharmony_ci#define ILCR_FLV_SHIFT		9
778c2ecf20Sopenharmony_ci#define ILCR_FLV_MASK		(0x1FF << ILCR_FLV_SHIFT)
788c2ecf20Sopenharmony_ci#define ILCR_HLVL_SHIFT		18
798c2ecf20Sopenharmony_ci#define ILCR_HLVL_MASK		(0x1FF << ILCR_HLVL_SHIFT)
808c2ecf20Sopenharmony_ci#define ILCR_HLVH_SHIFT		27
818c2ecf20Sopenharmony_ci#define ILCR_HLVH_MASK		(0x1F << ILCR_HLVH_SHIFT)
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci#define IWCR_CNT_SHIFT		0
848c2ecf20Sopenharmony_ci#define IWCR_CNT_MASK		(0x1F << IWCR_CNT_SHIFT)
858c2ecf20Sopenharmony_ci#define IWCR_HS_CNT1_SHIFT	5
868c2ecf20Sopenharmony_ci#define IWCR_HS_CNT1_MASK	(0x1F << IWCR_HS_CNT1_SHIFT)
878c2ecf20Sopenharmony_ci#define IWCR_HS_CNT2_SHIFT	10
888c2ecf20Sopenharmony_ci#define IWCR_HS_CNT2_MASK	(0x1F << IWCR_HS_CNT2_SHIFT)
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci/* need a longer timeout if we're dealing with the fact we may well be
918c2ecf20Sopenharmony_ci * looking at a multi-master environment
928c2ecf20Sopenharmony_ci */
938c2ecf20Sopenharmony_ci#define DEF_TIMEOUT             32
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci#define NO_SLAVE		(-ENXIO)
968c2ecf20Sopenharmony_ci#define BUS_ERROR               (-EREMOTEIO)
978c2ecf20Sopenharmony_ci#define XFER_NAKED              (-ECONNREFUSED)
988c2ecf20Sopenharmony_ci#define I2C_RETRY               (-2000) /* an error has occurred retry transmit */
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci/* ICR initialize bit values
1018c2ecf20Sopenharmony_ci *
1028c2ecf20Sopenharmony_ci * 15 FM     0 (100 kHz operation)
1038c2ecf20Sopenharmony_ci * 14 UR     0 (No unit reset)
1048c2ecf20Sopenharmony_ci * 13 SADIE  0 (Disables the unit from interrupting on slave addresses
1058c2ecf20Sopenharmony_ci *              matching its slave address)
1068c2ecf20Sopenharmony_ci * 12 ALDIE  0 (Disables the unit from interrupt when it loses arbitration
1078c2ecf20Sopenharmony_ci *              in master mode)
1088c2ecf20Sopenharmony_ci * 11 SSDIE  0 (Disables interrupts from a slave stop detected, in slave mode)
1098c2ecf20Sopenharmony_ci * 10 BEIE   1 (Enable interrupts from detected bus errors, no ACK sent)
1108c2ecf20Sopenharmony_ci *  9 IRFIE  1 (Enable interrupts from full buffer received)
1118c2ecf20Sopenharmony_ci *  8 ITEIE  1 (Enables the I2C unit to interrupt when transmit buffer empty)
1128c2ecf20Sopenharmony_ci *  7 GCD    1 (Disables i2c unit response to general call messages as a slave)
1138c2ecf20Sopenharmony_ci *  6 IUE    0 (Disable unit until we change settings)
1148c2ecf20Sopenharmony_ci *  5 SCLE   1 (Enables the i2c clock output for master mode (drives SCL)
1158c2ecf20Sopenharmony_ci *  4 MA     0 (Only send stop with the ICR stop bit)
1168c2ecf20Sopenharmony_ci *  3 TB     0 (We are not transmitting a byte initially)
1178c2ecf20Sopenharmony_ci *  2 ACKNAK 0 (Send an ACK after the unit receives a byte)
1188c2ecf20Sopenharmony_ci *  1 STOP   0 (Do not send a STOP)
1198c2ecf20Sopenharmony_ci *  0 START  0 (Do not send a START)
1208c2ecf20Sopenharmony_ci */
1218c2ecf20Sopenharmony_ci#define I2C_ICR_INIT	(ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE)
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci/* I2C status register init values
1248c2ecf20Sopenharmony_ci *
1258c2ecf20Sopenharmony_ci * 10 BED    1 (Clear bus error detected)
1268c2ecf20Sopenharmony_ci *  9 SAD    1 (Clear slave address detected)
1278c2ecf20Sopenharmony_ci *  7 IRF    1 (Clear IDBR Receive Full)
1288c2ecf20Sopenharmony_ci *  6 ITE    1 (Clear IDBR Transmit Empty)
1298c2ecf20Sopenharmony_ci *  5 ALD    1 (Clear Arbitration Loss Detected)
1308c2ecf20Sopenharmony_ci *  4 SSD    1 (Clear Slave Stop Detected)
1318c2ecf20Sopenharmony_ci */
1328c2ecf20Sopenharmony_ci#define I2C_ISR_INIT	0x7FF  /* status register init */
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistruct pxa_reg_layout {
1358c2ecf20Sopenharmony_ci	u32 ibmr;
1368c2ecf20Sopenharmony_ci	u32 idbr;
1378c2ecf20Sopenharmony_ci	u32 icr;
1388c2ecf20Sopenharmony_ci	u32 isr;
1398c2ecf20Sopenharmony_ci	u32 isar;
1408c2ecf20Sopenharmony_ci	u32 ilcr;
1418c2ecf20Sopenharmony_ci	u32 iwcr;
1428c2ecf20Sopenharmony_ci	u32 fm;
1438c2ecf20Sopenharmony_ci	u32 hs;
1448c2ecf20Sopenharmony_ci};
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cienum pxa_i2c_types {
1478c2ecf20Sopenharmony_ci	REGS_PXA2XX,
1488c2ecf20Sopenharmony_ci	REGS_PXA3XX,
1498c2ecf20Sopenharmony_ci	REGS_CE4100,
1508c2ecf20Sopenharmony_ci	REGS_PXA910,
1518c2ecf20Sopenharmony_ci	REGS_A3700,
1528c2ecf20Sopenharmony_ci};
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci/* I2C register layout definitions */
1558c2ecf20Sopenharmony_cistatic struct pxa_reg_layout pxa_reg_layout[] = {
1568c2ecf20Sopenharmony_ci	[REGS_PXA2XX] = {
1578c2ecf20Sopenharmony_ci		.ibmr =	0x00,
1588c2ecf20Sopenharmony_ci		.idbr =	0x08,
1598c2ecf20Sopenharmony_ci		.icr =	0x10,
1608c2ecf20Sopenharmony_ci		.isr =	0x18,
1618c2ecf20Sopenharmony_ci		.isar =	0x20,
1628c2ecf20Sopenharmony_ci		.fm = ICR_FM,
1638c2ecf20Sopenharmony_ci		.hs = ICR_HS,
1648c2ecf20Sopenharmony_ci	},
1658c2ecf20Sopenharmony_ci	[REGS_PXA3XX] = {
1668c2ecf20Sopenharmony_ci		.ibmr =	0x00,
1678c2ecf20Sopenharmony_ci		.idbr =	0x04,
1688c2ecf20Sopenharmony_ci		.icr =	0x08,
1698c2ecf20Sopenharmony_ci		.isr =	0x0c,
1708c2ecf20Sopenharmony_ci		.isar =	0x10,
1718c2ecf20Sopenharmony_ci		.fm = ICR_FM,
1728c2ecf20Sopenharmony_ci		.hs = ICR_HS,
1738c2ecf20Sopenharmony_ci	},
1748c2ecf20Sopenharmony_ci	[REGS_CE4100] = {
1758c2ecf20Sopenharmony_ci		.ibmr =	0x14,
1768c2ecf20Sopenharmony_ci		.idbr =	0x0c,
1778c2ecf20Sopenharmony_ci		.icr =	0x00,
1788c2ecf20Sopenharmony_ci		.isr =	0x04,
1798c2ecf20Sopenharmony_ci		/* no isar register */
1808c2ecf20Sopenharmony_ci		.fm = ICR_FM,
1818c2ecf20Sopenharmony_ci		.hs = ICR_HS,
1828c2ecf20Sopenharmony_ci	},
1838c2ecf20Sopenharmony_ci	[REGS_PXA910] = {
1848c2ecf20Sopenharmony_ci		.ibmr = 0x00,
1858c2ecf20Sopenharmony_ci		.idbr = 0x08,
1868c2ecf20Sopenharmony_ci		.icr =	0x10,
1878c2ecf20Sopenharmony_ci		.isr =	0x18,
1888c2ecf20Sopenharmony_ci		.isar = 0x20,
1898c2ecf20Sopenharmony_ci		.ilcr = 0x28,
1908c2ecf20Sopenharmony_ci		.iwcr = 0x30,
1918c2ecf20Sopenharmony_ci		.fm = ICR_FM,
1928c2ecf20Sopenharmony_ci		.hs = ICR_HS,
1938c2ecf20Sopenharmony_ci	},
1948c2ecf20Sopenharmony_ci	[REGS_A3700] = {
1958c2ecf20Sopenharmony_ci		.ibmr =	0x00,
1968c2ecf20Sopenharmony_ci		.idbr =	0x04,
1978c2ecf20Sopenharmony_ci		.icr =	0x08,
1988c2ecf20Sopenharmony_ci		.isr =	0x0c,
1998c2ecf20Sopenharmony_ci		.isar =	0x10,
2008c2ecf20Sopenharmony_ci		.fm = ICR_A3700_FM,
2018c2ecf20Sopenharmony_ci		.hs = ICR_A3700_HS,
2028c2ecf20Sopenharmony_ci	},
2038c2ecf20Sopenharmony_ci};
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_cistatic const struct of_device_id i2c_pxa_dt_ids[] = {
2068c2ecf20Sopenharmony_ci	{ .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX },
2078c2ecf20Sopenharmony_ci	{ .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX },
2088c2ecf20Sopenharmony_ci	{ .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA910 },
2098c2ecf20Sopenharmony_ci	{ .compatible = "marvell,armada-3700-i2c", .data = (void *)REGS_A3700 },
2108c2ecf20Sopenharmony_ci	{}
2118c2ecf20Sopenharmony_ci};
2128c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_cistatic const struct platform_device_id i2c_pxa_id_table[] = {
2158c2ecf20Sopenharmony_ci	{ "pxa2xx-i2c",		REGS_PXA2XX },
2168c2ecf20Sopenharmony_ci	{ "pxa3xx-pwri2c",	REGS_PXA3XX },
2178c2ecf20Sopenharmony_ci	{ "ce4100-i2c",		REGS_CE4100 },
2188c2ecf20Sopenharmony_ci	{ "pxa910-i2c",		REGS_PXA910 },
2198c2ecf20Sopenharmony_ci	{ "armada-3700-i2c",	REGS_A3700  },
2208c2ecf20Sopenharmony_ci	{ },
2218c2ecf20Sopenharmony_ci};
2228c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cistruct pxa_i2c {
2258c2ecf20Sopenharmony_ci	spinlock_t		lock;
2268c2ecf20Sopenharmony_ci	wait_queue_head_t	wait;
2278c2ecf20Sopenharmony_ci	struct i2c_msg		*msg;
2288c2ecf20Sopenharmony_ci	unsigned int		msg_num;
2298c2ecf20Sopenharmony_ci	unsigned int		msg_idx;
2308c2ecf20Sopenharmony_ci	unsigned int		msg_ptr;
2318c2ecf20Sopenharmony_ci	unsigned int		slave_addr;
2328c2ecf20Sopenharmony_ci	unsigned int		req_slave_addr;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	struct i2c_adapter	adap;
2358c2ecf20Sopenharmony_ci	struct clk		*clk;
2368c2ecf20Sopenharmony_ci#ifdef CONFIG_I2C_PXA_SLAVE
2378c2ecf20Sopenharmony_ci	struct i2c_client	*slave;
2388c2ecf20Sopenharmony_ci#endif
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	unsigned int		irqlogidx;
2418c2ecf20Sopenharmony_ci	u32			isrlog[32];
2428c2ecf20Sopenharmony_ci	u32			icrlog[32];
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	void __iomem		*reg_base;
2458c2ecf20Sopenharmony_ci	void __iomem		*reg_ibmr;
2468c2ecf20Sopenharmony_ci	void __iomem		*reg_idbr;
2478c2ecf20Sopenharmony_ci	void __iomem		*reg_icr;
2488c2ecf20Sopenharmony_ci	void __iomem		*reg_isr;
2498c2ecf20Sopenharmony_ci	void __iomem		*reg_isar;
2508c2ecf20Sopenharmony_ci	void __iomem		*reg_ilcr;
2518c2ecf20Sopenharmony_ci	void __iomem		*reg_iwcr;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	unsigned long		iobase;
2548c2ecf20Sopenharmony_ci	unsigned long		iosize;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	int			irq;
2578c2ecf20Sopenharmony_ci	unsigned int		use_pio :1;
2588c2ecf20Sopenharmony_ci	unsigned int		fast_mode :1;
2598c2ecf20Sopenharmony_ci	unsigned int		high_mode:1;
2608c2ecf20Sopenharmony_ci	unsigned char		master_code;
2618c2ecf20Sopenharmony_ci	unsigned long		rate;
2628c2ecf20Sopenharmony_ci	bool			highmode_enter;
2638c2ecf20Sopenharmony_ci	u32			fm_mask;
2648c2ecf20Sopenharmony_ci	u32			hs_mask;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	struct i2c_bus_recovery_info recovery;
2678c2ecf20Sopenharmony_ci	struct pinctrl		*pinctrl;
2688c2ecf20Sopenharmony_ci	struct pinctrl_state	*pinctrl_default;
2698c2ecf20Sopenharmony_ci	struct pinctrl_state	*pinctrl_recovery;
2708c2ecf20Sopenharmony_ci};
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci#define _IBMR(i2c)	((i2c)->reg_ibmr)
2738c2ecf20Sopenharmony_ci#define _IDBR(i2c)	((i2c)->reg_idbr)
2748c2ecf20Sopenharmony_ci#define _ICR(i2c)	((i2c)->reg_icr)
2758c2ecf20Sopenharmony_ci#define _ISR(i2c)	((i2c)->reg_isr)
2768c2ecf20Sopenharmony_ci#define _ISAR(i2c)	((i2c)->reg_isar)
2778c2ecf20Sopenharmony_ci#define _ILCR(i2c)	((i2c)->reg_ilcr)
2788c2ecf20Sopenharmony_ci#define _IWCR(i2c)	((i2c)->reg_iwcr)
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci/*
2818c2ecf20Sopenharmony_ci * I2C Slave mode address
2828c2ecf20Sopenharmony_ci */
2838c2ecf20Sopenharmony_ci#define I2C_PXA_SLAVE_ADDR      0x1
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci#ifdef DEBUG
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_cistruct bits {
2888c2ecf20Sopenharmony_ci	u32	mask;
2898c2ecf20Sopenharmony_ci	const char *set;
2908c2ecf20Sopenharmony_ci	const char *unset;
2918c2ecf20Sopenharmony_ci};
2928c2ecf20Sopenharmony_ci#define PXA_BIT(m, s, u)	{ .mask = m, .set = s, .unset = u }
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_cistatic inline void
2958c2ecf20Sopenharmony_cidecode_bits(const char *prefix, const struct bits *bits, int num, u32 val)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	printk("%s %08x:", prefix, val);
2988c2ecf20Sopenharmony_ci	while (num--) {
2998c2ecf20Sopenharmony_ci		const char *str = val & bits->mask ? bits->set : bits->unset;
3008c2ecf20Sopenharmony_ci		if (str)
3018c2ecf20Sopenharmony_ci			pr_cont(" %s", str);
3028c2ecf20Sopenharmony_ci		bits++;
3038c2ecf20Sopenharmony_ci	}
3048c2ecf20Sopenharmony_ci	pr_cont("\n");
3058c2ecf20Sopenharmony_ci}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_cistatic const struct bits isr_bits[] = {
3088c2ecf20Sopenharmony_ci	PXA_BIT(ISR_RWM,	"RX",		"TX"),
3098c2ecf20Sopenharmony_ci	PXA_BIT(ISR_ACKNAK,	"NAK",		"ACK"),
3108c2ecf20Sopenharmony_ci	PXA_BIT(ISR_UB,		"Bsy",		"Rdy"),
3118c2ecf20Sopenharmony_ci	PXA_BIT(ISR_IBB,	"BusBsy",	"BusRdy"),
3128c2ecf20Sopenharmony_ci	PXA_BIT(ISR_SSD,	"SlaveStop",	NULL),
3138c2ecf20Sopenharmony_ci	PXA_BIT(ISR_ALD,	"ALD",		NULL),
3148c2ecf20Sopenharmony_ci	PXA_BIT(ISR_ITE,	"TxEmpty",	NULL),
3158c2ecf20Sopenharmony_ci	PXA_BIT(ISR_IRF,	"RxFull",	NULL),
3168c2ecf20Sopenharmony_ci	PXA_BIT(ISR_GCAD,	"GenCall",	NULL),
3178c2ecf20Sopenharmony_ci	PXA_BIT(ISR_SAD,	"SlaveAddr",	NULL),
3188c2ecf20Sopenharmony_ci	PXA_BIT(ISR_BED,	"BusErr",	NULL),
3198c2ecf20Sopenharmony_ci};
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic void decode_ISR(unsigned int val)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	decode_bits(KERN_DEBUG "ISR", isr_bits, ARRAY_SIZE(isr_bits), val);
3248c2ecf20Sopenharmony_ci}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cistatic const struct bits icr_bits[] = {
3278c2ecf20Sopenharmony_ci	PXA_BIT(ICR_START,  "START",	NULL),
3288c2ecf20Sopenharmony_ci	PXA_BIT(ICR_STOP,   "STOP",	NULL),
3298c2ecf20Sopenharmony_ci	PXA_BIT(ICR_ACKNAK, "ACKNAK",	NULL),
3308c2ecf20Sopenharmony_ci	PXA_BIT(ICR_TB,     "TB",	NULL),
3318c2ecf20Sopenharmony_ci	PXA_BIT(ICR_MA,     "MA",	NULL),
3328c2ecf20Sopenharmony_ci	PXA_BIT(ICR_SCLE,   "SCLE",	"scle"),
3338c2ecf20Sopenharmony_ci	PXA_BIT(ICR_IUE,    "IUE",	"iue"),
3348c2ecf20Sopenharmony_ci	PXA_BIT(ICR_GCD,    "GCD",	NULL),
3358c2ecf20Sopenharmony_ci	PXA_BIT(ICR_ITEIE,  "ITEIE",	NULL),
3368c2ecf20Sopenharmony_ci	PXA_BIT(ICR_IRFIE,  "IRFIE",	NULL),
3378c2ecf20Sopenharmony_ci	PXA_BIT(ICR_BEIE,   "BEIE",	NULL),
3388c2ecf20Sopenharmony_ci	PXA_BIT(ICR_SSDIE,  "SSDIE",	NULL),
3398c2ecf20Sopenharmony_ci	PXA_BIT(ICR_ALDIE,  "ALDIE",	NULL),
3408c2ecf20Sopenharmony_ci	PXA_BIT(ICR_SADIE,  "SADIE",	NULL),
3418c2ecf20Sopenharmony_ci	PXA_BIT(ICR_UR,     "UR",		"ur"),
3428c2ecf20Sopenharmony_ci};
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci#ifdef CONFIG_I2C_PXA_SLAVE
3458c2ecf20Sopenharmony_cistatic void decode_ICR(unsigned int val)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	decode_bits(KERN_DEBUG "ICR", icr_bits, ARRAY_SIZE(icr_bits), val);
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ci#endif
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_cistatic unsigned int i2c_debug = DEBUG;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_cistatic void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno,
3568c2ecf20Sopenharmony_ci		readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
3578c2ecf20Sopenharmony_ci}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __func__)
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cistatic void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	unsigned int i;
3648c2ecf20Sopenharmony_ci	struct device *dev = &i2c->adap.dev;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	dev_err(dev, "slave_0x%x error: %s\n",
3678c2ecf20Sopenharmony_ci		i2c->req_slave_addr >> 1, why);
3688c2ecf20Sopenharmony_ci	dev_err(dev, "msg_num: %d msg_idx: %d msg_ptr: %d\n",
3698c2ecf20Sopenharmony_ci		i2c->msg_num, i2c->msg_idx, i2c->msg_ptr);
3708c2ecf20Sopenharmony_ci	dev_err(dev, "IBMR: %08x IDBR: %08x ICR: %08x ISR: %08x\n",
3718c2ecf20Sopenharmony_ci		readl(_IBMR(i2c)), readl(_IDBR(i2c)), readl(_ICR(i2c)),
3728c2ecf20Sopenharmony_ci		readl(_ISR(i2c)));
3738c2ecf20Sopenharmony_ci	dev_err(dev, "log:");
3748c2ecf20Sopenharmony_ci	for (i = 0; i < i2c->irqlogidx; i++)
3758c2ecf20Sopenharmony_ci		pr_cont(" [%03x:%05x]", i2c->isrlog[i], i2c->icrlog[i]);
3768c2ecf20Sopenharmony_ci	pr_cont("\n");
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci#else /* ifdef DEBUG */
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci#define i2c_debug	0
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci#define show_state(i2c) do { } while (0)
3848c2ecf20Sopenharmony_ci#define decode_ISR(val) do { } while (0)
3858c2ecf20Sopenharmony_ci#define decode_ICR(val) do { } while (0)
3868c2ecf20Sopenharmony_ci#define i2c_pxa_scream_blue_murder(i2c, why) do { } while (0)
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci#endif /* ifdef DEBUG / else */
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_cistatic void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_cistatic inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
3938c2ecf20Sopenharmony_ci{
3948c2ecf20Sopenharmony_ci	return !(readl(_ICR(i2c)) & ICR_SCLE);
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_cistatic void i2c_pxa_abort(struct pxa_i2c *i2c)
3988c2ecf20Sopenharmony_ci{
3998c2ecf20Sopenharmony_ci	int i = 250;
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	if (i2c_pxa_is_slavemode(i2c)) {
4028c2ecf20Sopenharmony_ci		dev_dbg(&i2c->adap.dev, "%s: called in slave mode\n", __func__);
4038c2ecf20Sopenharmony_ci		return;
4048c2ecf20Sopenharmony_ci	}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	while ((i > 0) && (readl(_IBMR(i2c)) & IBMR_SDAS) == 0) {
4078c2ecf20Sopenharmony_ci		unsigned long icr = readl(_ICR(i2c));
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci		icr &= ~ICR_START;
4108c2ecf20Sopenharmony_ci		icr |= ICR_ACKNAK | ICR_STOP | ICR_TB;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci		writel(icr, _ICR(i2c));
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci		show_state(i2c);
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci		mdelay(1);
4178c2ecf20Sopenharmony_ci		i --;
4188c2ecf20Sopenharmony_ci	}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) & ~(ICR_MA | ICR_START | ICR_STOP),
4218c2ecf20Sopenharmony_ci	       _ICR(i2c));
4228c2ecf20Sopenharmony_ci}
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_cistatic int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
4258c2ecf20Sopenharmony_ci{
4268c2ecf20Sopenharmony_ci	int timeout = DEF_TIMEOUT;
4278c2ecf20Sopenharmony_ci	u32 isr;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	while (1) {
4308c2ecf20Sopenharmony_ci		isr = readl(_ISR(i2c));
4318c2ecf20Sopenharmony_ci		if (!(isr & (ISR_IBB | ISR_UB)))
4328c2ecf20Sopenharmony_ci			return 0;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci		if (isr & ISR_SAD)
4358c2ecf20Sopenharmony_ci			timeout += 4;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci		if (!timeout--)
4388c2ecf20Sopenharmony_ci			break;
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci		msleep(2);
4418c2ecf20Sopenharmony_ci		show_state(i2c);
4428c2ecf20Sopenharmony_ci	}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	show_state(i2c);
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	return I2C_RETRY;
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_cistatic int i2c_pxa_wait_master(struct pxa_i2c *i2c)
4508c2ecf20Sopenharmony_ci{
4518c2ecf20Sopenharmony_ci	unsigned long timeout = jiffies + HZ*4;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	while (time_before(jiffies, timeout)) {
4548c2ecf20Sopenharmony_ci		if (i2c_debug > 1)
4558c2ecf20Sopenharmony_ci			dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
4568c2ecf20Sopenharmony_ci				__func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci		if (readl(_ISR(i2c)) & ISR_SAD) {
4598c2ecf20Sopenharmony_ci			if (i2c_debug > 0)
4608c2ecf20Sopenharmony_ci				dev_dbg(&i2c->adap.dev, "%s: Slave detected\n", __func__);
4618c2ecf20Sopenharmony_ci			goto out;
4628c2ecf20Sopenharmony_ci		}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci		/* wait for unit and bus being not busy, and we also do a
4658c2ecf20Sopenharmony_ci		 * quick check of the i2c lines themselves to ensure they've
4668c2ecf20Sopenharmony_ci		 * gone high...
4678c2ecf20Sopenharmony_ci		 */
4688c2ecf20Sopenharmony_ci		if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) == 0 &&
4698c2ecf20Sopenharmony_ci		    readl(_IBMR(i2c)) == (IBMR_SCLS | IBMR_SDAS)) {
4708c2ecf20Sopenharmony_ci			if (i2c_debug > 0)
4718c2ecf20Sopenharmony_ci				dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
4728c2ecf20Sopenharmony_ci			return 1;
4738c2ecf20Sopenharmony_ci		}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci		msleep(1);
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	if (i2c_debug > 0)
4798c2ecf20Sopenharmony_ci		dev_dbg(&i2c->adap.dev, "%s: did not free\n", __func__);
4808c2ecf20Sopenharmony_ci out:
4818c2ecf20Sopenharmony_ci	return 0;
4828c2ecf20Sopenharmony_ci}
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_cistatic int i2c_pxa_set_master(struct pxa_i2c *i2c)
4858c2ecf20Sopenharmony_ci{
4868c2ecf20Sopenharmony_ci	if (i2c_debug)
4878c2ecf20Sopenharmony_ci		dev_dbg(&i2c->adap.dev, "setting to bus master\n");
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) != 0) {
4908c2ecf20Sopenharmony_ci		dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__);
4918c2ecf20Sopenharmony_ci		if (!i2c_pxa_wait_master(i2c)) {
4928c2ecf20Sopenharmony_ci			dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__);
4938c2ecf20Sopenharmony_ci			return I2C_RETRY;
4948c2ecf20Sopenharmony_ci		}
4958c2ecf20Sopenharmony_ci	}
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c));
4988c2ecf20Sopenharmony_ci	return 0;
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci#ifdef CONFIG_I2C_PXA_SLAVE
5028c2ecf20Sopenharmony_cistatic int i2c_pxa_wait_slave(struct pxa_i2c *i2c)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	unsigned long timeout = jiffies + HZ*1;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	/* wait for stop */
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	show_state(i2c);
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	while (time_before(jiffies, timeout)) {
5118c2ecf20Sopenharmony_ci		if (i2c_debug > 1)
5128c2ecf20Sopenharmony_ci			dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
5138c2ecf20Sopenharmony_ci				__func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci		if ((readl(_ISR(i2c)) & (ISR_UB|ISR_IBB)) == 0 ||
5168c2ecf20Sopenharmony_ci		    (readl(_ISR(i2c)) & ISR_SAD) != 0 ||
5178c2ecf20Sopenharmony_ci		    (readl(_ICR(i2c)) & ICR_SCLE) == 0) {
5188c2ecf20Sopenharmony_ci			if (i2c_debug > 1)
5198c2ecf20Sopenharmony_ci				dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
5208c2ecf20Sopenharmony_ci			return 1;
5218c2ecf20Sopenharmony_ci		}
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci		msleep(1);
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	if (i2c_debug > 0)
5278c2ecf20Sopenharmony_ci		dev_dbg(&i2c->adap.dev, "%s: did not free\n", __func__);
5288c2ecf20Sopenharmony_ci	return 0;
5298c2ecf20Sopenharmony_ci}
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci/*
5328c2ecf20Sopenharmony_ci * clear the hold on the bus, and take of anything else
5338c2ecf20Sopenharmony_ci * that has been configured
5348c2ecf20Sopenharmony_ci */
5358c2ecf20Sopenharmony_cistatic void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode)
5368c2ecf20Sopenharmony_ci{
5378c2ecf20Sopenharmony_ci	show_state(i2c);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	if (errcode < 0) {
5408c2ecf20Sopenharmony_ci		udelay(100);   /* simple delay */
5418c2ecf20Sopenharmony_ci	} else {
5428c2ecf20Sopenharmony_ci		/* we need to wait for the stop condition to end */
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci		/* if we where in stop, then clear... */
5458c2ecf20Sopenharmony_ci		if (readl(_ICR(i2c)) & ICR_STOP) {
5468c2ecf20Sopenharmony_ci			udelay(100);
5478c2ecf20Sopenharmony_ci			writel(readl(_ICR(i2c)) & ~ICR_STOP, _ICR(i2c));
5488c2ecf20Sopenharmony_ci		}
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci		if (!i2c_pxa_wait_slave(i2c)) {
5518c2ecf20Sopenharmony_ci			dev_err(&i2c->adap.dev, "%s: wait timedout\n",
5528c2ecf20Sopenharmony_ci				__func__);
5538c2ecf20Sopenharmony_ci			return;
5548c2ecf20Sopenharmony_ci		}
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) & ~(ICR_STOP|ICR_ACKNAK|ICR_MA), _ICR(i2c));
5588c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	if (i2c_debug) {
5618c2ecf20Sopenharmony_ci		dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", readl(_ICR(i2c)), readl(_ISR(i2c)));
5628c2ecf20Sopenharmony_ci		decode_ICR(readl(_ICR(i2c)));
5638c2ecf20Sopenharmony_ci	}
5648c2ecf20Sopenharmony_ci}
5658c2ecf20Sopenharmony_ci#else
5668c2ecf20Sopenharmony_ci#define i2c_pxa_set_slave(i2c, err)	do { } while (0)
5678c2ecf20Sopenharmony_ci#endif
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_cistatic void i2c_pxa_do_reset(struct pxa_i2c *i2c)
5708c2ecf20Sopenharmony_ci{
5718c2ecf20Sopenharmony_ci	/* reset according to 9.8 */
5728c2ecf20Sopenharmony_ci	writel(ICR_UR, _ICR(i2c));
5738c2ecf20Sopenharmony_ci	writel(I2C_ISR_INIT, _ISR(i2c));
5748c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c));
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	if (i2c->reg_isar && IS_ENABLED(CONFIG_I2C_PXA_SLAVE))
5778c2ecf20Sopenharmony_ci		writel(i2c->slave_addr, _ISAR(i2c));
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	/* set control register values */
5808c2ecf20Sopenharmony_ci	writel(I2C_ICR_INIT | (i2c->fast_mode ? i2c->fm_mask : 0), _ICR(i2c));
5818c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) | (i2c->high_mode ? i2c->hs_mask : 0), _ICR(i2c));
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci#ifdef CONFIG_I2C_PXA_SLAVE
5848c2ecf20Sopenharmony_ci	dev_info(&i2c->adap.dev, "Enabling slave mode\n");
5858c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) | ICR_SADIE | ICR_ALDIE | ICR_SSDIE, _ICR(i2c));
5868c2ecf20Sopenharmony_ci#endif
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	i2c_pxa_set_slave(i2c, 0);
5898c2ecf20Sopenharmony_ci}
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_cistatic void i2c_pxa_enable(struct pxa_i2c *i2c)
5928c2ecf20Sopenharmony_ci{
5938c2ecf20Sopenharmony_ci	/* enable unit */
5948c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
5958c2ecf20Sopenharmony_ci	udelay(100);
5968c2ecf20Sopenharmony_ci}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cistatic void i2c_pxa_reset(struct pxa_i2c *i2c)
5998c2ecf20Sopenharmony_ci{
6008c2ecf20Sopenharmony_ci	pr_debug("Resetting I2C Controller Unit\n");
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	/* abort any transfer currently under way */
6038c2ecf20Sopenharmony_ci	i2c_pxa_abort(i2c);
6048c2ecf20Sopenharmony_ci	i2c_pxa_do_reset(i2c);
6058c2ecf20Sopenharmony_ci	i2c_pxa_enable(i2c);
6068c2ecf20Sopenharmony_ci}
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci#ifdef CONFIG_I2C_PXA_SLAVE
6108c2ecf20Sopenharmony_ci/*
6118c2ecf20Sopenharmony_ci * PXA I2C Slave mode
6128c2ecf20Sopenharmony_ci */
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_cistatic void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr)
6158c2ecf20Sopenharmony_ci{
6168c2ecf20Sopenharmony_ci	if (isr & ISR_BED) {
6178c2ecf20Sopenharmony_ci		/* what should we do here? */
6188c2ecf20Sopenharmony_ci	} else {
6198c2ecf20Sopenharmony_ci		u8 byte = 0;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci		if (i2c->slave != NULL)
6228c2ecf20Sopenharmony_ci			i2c_slave_event(i2c->slave, I2C_SLAVE_READ_PROCESSED,
6238c2ecf20Sopenharmony_ci					&byte);
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci		writel(byte, _IDBR(i2c));
6268c2ecf20Sopenharmony_ci		writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));   /* allow next byte */
6278c2ecf20Sopenharmony_ci	}
6288c2ecf20Sopenharmony_ci}
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_cistatic void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
6318c2ecf20Sopenharmony_ci{
6328c2ecf20Sopenharmony_ci	u8 byte = readl(_IDBR(i2c));
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	if (i2c->slave != NULL)
6358c2ecf20Sopenharmony_ci		i2c_slave_event(i2c->slave, I2C_SLAVE_WRITE_RECEIVED, &byte);
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
6388c2ecf20Sopenharmony_ci}
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_cistatic void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
6418c2ecf20Sopenharmony_ci{
6428c2ecf20Sopenharmony_ci	int timeout;
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	if (i2c_debug > 0)
6458c2ecf20Sopenharmony_ci		dev_dbg(&i2c->adap.dev, "SAD, mode is slave-%cx\n",
6468c2ecf20Sopenharmony_ci		       (isr & ISR_RWM) ? 'r' : 't');
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	if (i2c->slave != NULL) {
6498c2ecf20Sopenharmony_ci		if (isr & ISR_RWM) {
6508c2ecf20Sopenharmony_ci			u8 byte = 0;
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci			i2c_slave_event(i2c->slave, I2C_SLAVE_READ_REQUESTED,
6538c2ecf20Sopenharmony_ci					&byte);
6548c2ecf20Sopenharmony_ci			writel(byte, _IDBR(i2c));
6558c2ecf20Sopenharmony_ci		} else {
6568c2ecf20Sopenharmony_ci			i2c_slave_event(i2c->slave, I2C_SLAVE_WRITE_REQUESTED,
6578c2ecf20Sopenharmony_ci					NULL);
6588c2ecf20Sopenharmony_ci		}
6598c2ecf20Sopenharmony_ci	}
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	/*
6628c2ecf20Sopenharmony_ci	 * slave could interrupt in the middle of us generating a
6638c2ecf20Sopenharmony_ci	 * start condition... if this happens, we'd better back off
6648c2ecf20Sopenharmony_ci	 * and stop holding the poor thing up
6658c2ecf20Sopenharmony_ci	 */
6668c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c));
6678c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	timeout = 0x10000;
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_ci	while (1) {
6728c2ecf20Sopenharmony_ci		if ((readl(_IBMR(i2c)) & IBMR_SCLS) == IBMR_SCLS)
6738c2ecf20Sopenharmony_ci			break;
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci		timeout--;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci		if (timeout <= 0) {
6788c2ecf20Sopenharmony_ci			dev_err(&i2c->adap.dev, "timeout waiting for SCL high\n");
6798c2ecf20Sopenharmony_ci			break;
6808c2ecf20Sopenharmony_ci		}
6818c2ecf20Sopenharmony_ci	}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
6848c2ecf20Sopenharmony_ci}
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_cistatic void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	if (i2c_debug > 2)
6898c2ecf20Sopenharmony_ci		dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop)\n");
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	if (i2c->slave != NULL)
6928c2ecf20Sopenharmony_ci		i2c_slave_event(i2c->slave, I2C_SLAVE_STOP, NULL);
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	if (i2c_debug > 2)
6958c2ecf20Sopenharmony_ci		dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop) acked\n");
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	/*
6988c2ecf20Sopenharmony_ci	 * If we have a master-mode message waiting,
6998c2ecf20Sopenharmony_ci	 * kick it off now that the slave has completed.
7008c2ecf20Sopenharmony_ci	 */
7018c2ecf20Sopenharmony_ci	if (i2c->msg)
7028c2ecf20Sopenharmony_ci		i2c_pxa_master_complete(i2c, I2C_RETRY);
7038c2ecf20Sopenharmony_ci}
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_cistatic int i2c_pxa_slave_reg(struct i2c_client *slave)
7068c2ecf20Sopenharmony_ci{
7078c2ecf20Sopenharmony_ci	struct pxa_i2c *i2c = slave->adapter->algo_data;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	if (i2c->slave)
7108c2ecf20Sopenharmony_ci		return -EBUSY;
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci	if (!i2c->reg_isar)
7138c2ecf20Sopenharmony_ci		return -EAFNOSUPPORT;
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	i2c->slave = slave;
7168c2ecf20Sopenharmony_ci	i2c->slave_addr = slave->addr;
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	writel(i2c->slave_addr, _ISAR(i2c));
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	return 0;
7218c2ecf20Sopenharmony_ci}
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_cistatic int i2c_pxa_slave_unreg(struct i2c_client *slave)
7248c2ecf20Sopenharmony_ci{
7258c2ecf20Sopenharmony_ci	struct pxa_i2c *i2c = slave->adapter->algo_data;
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	WARN_ON(!i2c->slave);
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	i2c->slave_addr = I2C_PXA_SLAVE_ADDR;
7308c2ecf20Sopenharmony_ci	writel(i2c->slave_addr, _ISAR(i2c));
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	i2c->slave = NULL;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	return 0;
7358c2ecf20Sopenharmony_ci}
7368c2ecf20Sopenharmony_ci#else
7378c2ecf20Sopenharmony_cistatic void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr)
7388c2ecf20Sopenharmony_ci{
7398c2ecf20Sopenharmony_ci	if (isr & ISR_BED) {
7408c2ecf20Sopenharmony_ci		/* what should we do here? */
7418c2ecf20Sopenharmony_ci	} else {
7428c2ecf20Sopenharmony_ci		writel(0, _IDBR(i2c));
7438c2ecf20Sopenharmony_ci		writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
7448c2ecf20Sopenharmony_ci	}
7458c2ecf20Sopenharmony_ci}
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_cistatic void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
7488c2ecf20Sopenharmony_ci{
7498c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c));
7508c2ecf20Sopenharmony_ci}
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_cistatic void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
7538c2ecf20Sopenharmony_ci{
7548c2ecf20Sopenharmony_ci	int timeout;
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	/*
7578c2ecf20Sopenharmony_ci	 * slave could interrupt in the middle of us generating a
7588c2ecf20Sopenharmony_ci	 * start condition... if this happens, we'd better back off
7598c2ecf20Sopenharmony_ci	 * and stop holding the poor thing up
7608c2ecf20Sopenharmony_ci	 */
7618c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c));
7628c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c));
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	timeout = 0x10000;
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	while (1) {
7678c2ecf20Sopenharmony_ci		if ((readl(_IBMR(i2c)) & IBMR_SCLS) == IBMR_SCLS)
7688c2ecf20Sopenharmony_ci			break;
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci		timeout--;
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci		if (timeout <= 0) {
7738c2ecf20Sopenharmony_ci			dev_err(&i2c->adap.dev, "timeout waiting for SCL high\n");
7748c2ecf20Sopenharmony_ci			break;
7758c2ecf20Sopenharmony_ci		}
7768c2ecf20Sopenharmony_ci	}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
7798c2ecf20Sopenharmony_ci}
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_cistatic void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
7828c2ecf20Sopenharmony_ci{
7838c2ecf20Sopenharmony_ci	if (i2c->msg)
7848c2ecf20Sopenharmony_ci		i2c_pxa_master_complete(i2c, I2C_RETRY);
7858c2ecf20Sopenharmony_ci}
7868c2ecf20Sopenharmony_ci#endif
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci/*
7898c2ecf20Sopenharmony_ci * PXA I2C Master mode
7908c2ecf20Sopenharmony_ci */
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_cistatic inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
7938c2ecf20Sopenharmony_ci{
7948c2ecf20Sopenharmony_ci	u32 icr;
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	/*
7978c2ecf20Sopenharmony_ci	 * Step 1: target slave address into IDBR
7988c2ecf20Sopenharmony_ci	 */
7998c2ecf20Sopenharmony_ci	i2c->req_slave_addr = i2c_8bit_addr_from_msg(i2c->msg);
8008c2ecf20Sopenharmony_ci	writel(i2c->req_slave_addr, _IDBR(i2c));
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci	/*
8038c2ecf20Sopenharmony_ci	 * Step 2: initiate the write.
8048c2ecf20Sopenharmony_ci	 */
8058c2ecf20Sopenharmony_ci	icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE);
8068c2ecf20Sopenharmony_ci	writel(icr | ICR_START | ICR_TB, _ICR(i2c));
8078c2ecf20Sopenharmony_ci}
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_cistatic inline void i2c_pxa_stop_message(struct pxa_i2c *i2c)
8108c2ecf20Sopenharmony_ci{
8118c2ecf20Sopenharmony_ci	u32 icr;
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	/* Clear the START, STOP, ACK, TB and MA flags */
8148c2ecf20Sopenharmony_ci	icr = readl(_ICR(i2c));
8158c2ecf20Sopenharmony_ci	icr &= ~(ICR_START | ICR_STOP | ICR_ACKNAK | ICR_TB | ICR_MA);
8168c2ecf20Sopenharmony_ci	writel(icr, _ICR(i2c));
8178c2ecf20Sopenharmony_ci}
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci/*
8208c2ecf20Sopenharmony_ci * PXA I2C send master code
8218c2ecf20Sopenharmony_ci * 1. Load master code to IDBR and send it.
8228c2ecf20Sopenharmony_ci *    Note for HS mode, set ICR [GPIOEN].
8238c2ecf20Sopenharmony_ci * 2. Wait until win arbitration.
8248c2ecf20Sopenharmony_ci */
8258c2ecf20Sopenharmony_cistatic int i2c_pxa_send_mastercode(struct pxa_i2c *i2c)
8268c2ecf20Sopenharmony_ci{
8278c2ecf20Sopenharmony_ci	u32 icr;
8288c2ecf20Sopenharmony_ci	long timeout;
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	spin_lock_irq(&i2c->lock);
8318c2ecf20Sopenharmony_ci	i2c->highmode_enter = true;
8328c2ecf20Sopenharmony_ci	writel(i2c->master_code, _IDBR(i2c));
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE);
8358c2ecf20Sopenharmony_ci	icr |= ICR_GPIOEN | ICR_START | ICR_TB | ICR_ITEIE;
8368c2ecf20Sopenharmony_ci	writel(icr, _ICR(i2c));
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	spin_unlock_irq(&i2c->lock);
8398c2ecf20Sopenharmony_ci	timeout = wait_event_timeout(i2c->wait,
8408c2ecf20Sopenharmony_ci			i2c->highmode_enter == false, HZ * 1);
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	i2c->highmode_enter = false;
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	return (timeout == 0) ? I2C_RETRY : 0;
8458c2ecf20Sopenharmony_ci}
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci/*
8488c2ecf20Sopenharmony_ci * i2c_pxa_master_complete - complete the message and wake up.
8498c2ecf20Sopenharmony_ci */
8508c2ecf20Sopenharmony_cistatic void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret)
8518c2ecf20Sopenharmony_ci{
8528c2ecf20Sopenharmony_ci	i2c->msg_ptr = 0;
8538c2ecf20Sopenharmony_ci	i2c->msg = NULL;
8548c2ecf20Sopenharmony_ci	i2c->msg_idx ++;
8558c2ecf20Sopenharmony_ci	i2c->msg_num = 0;
8568c2ecf20Sopenharmony_ci	if (ret)
8578c2ecf20Sopenharmony_ci		i2c->msg_idx = ret;
8588c2ecf20Sopenharmony_ci	if (!i2c->use_pio)
8598c2ecf20Sopenharmony_ci		wake_up(&i2c->wait);
8608c2ecf20Sopenharmony_ci}
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_cistatic void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
8638c2ecf20Sopenharmony_ci{
8648c2ecf20Sopenharmony_ci	u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci again:
8678c2ecf20Sopenharmony_ci	/*
8688c2ecf20Sopenharmony_ci	 * If ISR_ALD is set, we lost arbitration.
8698c2ecf20Sopenharmony_ci	 */
8708c2ecf20Sopenharmony_ci	if (isr & ISR_ALD) {
8718c2ecf20Sopenharmony_ci		/*
8728c2ecf20Sopenharmony_ci		 * Do we need to do anything here?  The PXA docs
8738c2ecf20Sopenharmony_ci		 * are vague about what happens.
8748c2ecf20Sopenharmony_ci		 */
8758c2ecf20Sopenharmony_ci		i2c_pxa_scream_blue_murder(i2c, "ALD set");
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci		/*
8788c2ecf20Sopenharmony_ci		 * We ignore this error.  We seem to see spurious ALDs
8798c2ecf20Sopenharmony_ci		 * for seemingly no reason.  If we handle them as I think
8808c2ecf20Sopenharmony_ci		 * they should, we end up causing an I2C error, which
8818c2ecf20Sopenharmony_ci		 * is painful for some systems.
8828c2ecf20Sopenharmony_ci		 */
8838c2ecf20Sopenharmony_ci		return; /* ignore */
8848c2ecf20Sopenharmony_ci	}
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	if ((isr & ISR_BED) &&
8878c2ecf20Sopenharmony_ci		(!((i2c->msg->flags & I2C_M_IGNORE_NAK) &&
8888c2ecf20Sopenharmony_ci			(isr & ISR_ACKNAK)))) {
8898c2ecf20Sopenharmony_ci		int ret = BUS_ERROR;
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci		/*
8928c2ecf20Sopenharmony_ci		 * I2C bus error - either the device NAK'd us, or
8938c2ecf20Sopenharmony_ci		 * something more serious happened.  If we were NAK'd
8948c2ecf20Sopenharmony_ci		 * on the initial address phase, we can retry.
8958c2ecf20Sopenharmony_ci		 */
8968c2ecf20Sopenharmony_ci		if (isr & ISR_ACKNAK) {
8978c2ecf20Sopenharmony_ci			if (i2c->msg_ptr == 0 && i2c->msg_idx == 0)
8988c2ecf20Sopenharmony_ci				ret = NO_SLAVE;
8998c2ecf20Sopenharmony_ci			else
9008c2ecf20Sopenharmony_ci				ret = XFER_NAKED;
9018c2ecf20Sopenharmony_ci		}
9028c2ecf20Sopenharmony_ci		i2c_pxa_master_complete(i2c, ret);
9038c2ecf20Sopenharmony_ci	} else if (isr & ISR_RWM) {
9048c2ecf20Sopenharmony_ci		/*
9058c2ecf20Sopenharmony_ci		 * Read mode.  We have just sent the address byte, and
9068c2ecf20Sopenharmony_ci		 * now we must initiate the transfer.
9078c2ecf20Sopenharmony_ci		 */
9088c2ecf20Sopenharmony_ci		if (i2c->msg_ptr == i2c->msg->len - 1 &&
9098c2ecf20Sopenharmony_ci		    i2c->msg_idx == i2c->msg_num - 1)
9108c2ecf20Sopenharmony_ci			icr |= ICR_STOP | ICR_ACKNAK;
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci		icr |= ICR_ALDIE | ICR_TB;
9138c2ecf20Sopenharmony_ci	} else if (i2c->msg_ptr < i2c->msg->len) {
9148c2ecf20Sopenharmony_ci		/*
9158c2ecf20Sopenharmony_ci		 * Write mode.  Write the next data byte.
9168c2ecf20Sopenharmony_ci		 */
9178c2ecf20Sopenharmony_ci		writel(i2c->msg->buf[i2c->msg_ptr++], _IDBR(i2c));
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci		icr |= ICR_ALDIE | ICR_TB;
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci		/*
9228c2ecf20Sopenharmony_ci		 * If this is the last byte of the last message or last byte
9238c2ecf20Sopenharmony_ci		 * of any message with I2C_M_STOP (e.g. SCCB), send a STOP.
9248c2ecf20Sopenharmony_ci		 */
9258c2ecf20Sopenharmony_ci		if ((i2c->msg_ptr == i2c->msg->len) &&
9268c2ecf20Sopenharmony_ci			((i2c->msg->flags & I2C_M_STOP) ||
9278c2ecf20Sopenharmony_ci			(i2c->msg_idx == i2c->msg_num - 1)))
9288c2ecf20Sopenharmony_ci				icr |= ICR_STOP;
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci	} else if (i2c->msg_idx < i2c->msg_num - 1) {
9318c2ecf20Sopenharmony_ci		/*
9328c2ecf20Sopenharmony_ci		 * Next segment of the message.
9338c2ecf20Sopenharmony_ci		 */
9348c2ecf20Sopenharmony_ci		i2c->msg_ptr = 0;
9358c2ecf20Sopenharmony_ci		i2c->msg_idx ++;
9368c2ecf20Sopenharmony_ci		i2c->msg++;
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci		/*
9398c2ecf20Sopenharmony_ci		 * If we aren't doing a repeated start and address,
9408c2ecf20Sopenharmony_ci		 * go back and try to send the next byte.  Note that
9418c2ecf20Sopenharmony_ci		 * we do not support switching the R/W direction here.
9428c2ecf20Sopenharmony_ci		 */
9438c2ecf20Sopenharmony_ci		if (i2c->msg->flags & I2C_M_NOSTART)
9448c2ecf20Sopenharmony_ci			goto again;
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci		/*
9478c2ecf20Sopenharmony_ci		 * Write the next address.
9488c2ecf20Sopenharmony_ci		 */
9498c2ecf20Sopenharmony_ci		i2c->req_slave_addr = i2c_8bit_addr_from_msg(i2c->msg);
9508c2ecf20Sopenharmony_ci		writel(i2c->req_slave_addr, _IDBR(i2c));
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci		/*
9538c2ecf20Sopenharmony_ci		 * And trigger a repeated start, and send the byte.
9548c2ecf20Sopenharmony_ci		 */
9558c2ecf20Sopenharmony_ci		icr &= ~ICR_ALDIE;
9568c2ecf20Sopenharmony_ci		icr |= ICR_START | ICR_TB;
9578c2ecf20Sopenharmony_ci	} else {
9588c2ecf20Sopenharmony_ci		if (i2c->msg->len == 0)
9598c2ecf20Sopenharmony_ci			icr |= ICR_MA;
9608c2ecf20Sopenharmony_ci		i2c_pxa_master_complete(i2c, 0);
9618c2ecf20Sopenharmony_ci	}
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	i2c->icrlog[i2c->irqlogidx-1] = icr;
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci	writel(icr, _ICR(i2c));
9668c2ecf20Sopenharmony_ci	show_state(i2c);
9678c2ecf20Sopenharmony_ci}
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_cistatic void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
9708c2ecf20Sopenharmony_ci{
9718c2ecf20Sopenharmony_ci	u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	/*
9748c2ecf20Sopenharmony_ci	 * Read the byte.
9758c2ecf20Sopenharmony_ci	 */
9768c2ecf20Sopenharmony_ci	i2c->msg->buf[i2c->msg_ptr++] = readl(_IDBR(i2c));
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci	if (i2c->msg_ptr < i2c->msg->len) {
9798c2ecf20Sopenharmony_ci		/*
9808c2ecf20Sopenharmony_ci		 * If this is the last byte of the last
9818c2ecf20Sopenharmony_ci		 * message, send a STOP.
9828c2ecf20Sopenharmony_ci		 */
9838c2ecf20Sopenharmony_ci		if (i2c->msg_ptr == i2c->msg->len - 1)
9848c2ecf20Sopenharmony_ci			icr |= ICR_STOP | ICR_ACKNAK;
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci		icr |= ICR_ALDIE | ICR_TB;
9878c2ecf20Sopenharmony_ci	} else {
9888c2ecf20Sopenharmony_ci		i2c_pxa_master_complete(i2c, 0);
9898c2ecf20Sopenharmony_ci	}
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	i2c->icrlog[i2c->irqlogidx-1] = icr;
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci	writel(icr, _ICR(i2c));
9948c2ecf20Sopenharmony_ci}
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci#define VALID_INT_SOURCE	(ISR_SSD | ISR_ALD | ISR_ITE | ISR_IRF | \
9978c2ecf20Sopenharmony_ci				ISR_SAD | ISR_BED)
9988c2ecf20Sopenharmony_cistatic irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
9998c2ecf20Sopenharmony_ci{
10008c2ecf20Sopenharmony_ci	struct pxa_i2c *i2c = dev_id;
10018c2ecf20Sopenharmony_ci	u32 isr = readl(_ISR(i2c));
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	if (!(isr & VALID_INT_SOURCE))
10048c2ecf20Sopenharmony_ci		return IRQ_NONE;
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci	if (i2c_debug > 2 && 0) {
10078c2ecf20Sopenharmony_ci		dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n",
10088c2ecf20Sopenharmony_ci			__func__, isr, readl(_ICR(i2c)), readl(_IBMR(i2c)));
10098c2ecf20Sopenharmony_ci		decode_ISR(isr);
10108c2ecf20Sopenharmony_ci	}
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	if (i2c->irqlogidx < ARRAY_SIZE(i2c->isrlog))
10138c2ecf20Sopenharmony_ci		i2c->isrlog[i2c->irqlogidx++] = isr;
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_ci	show_state(i2c);
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	/*
10188c2ecf20Sopenharmony_ci	 * Always clear all pending IRQs.
10198c2ecf20Sopenharmony_ci	 */
10208c2ecf20Sopenharmony_ci	writel(isr & VALID_INT_SOURCE, _ISR(i2c));
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	if (isr & ISR_SAD)
10238c2ecf20Sopenharmony_ci		i2c_pxa_slave_start(i2c, isr);
10248c2ecf20Sopenharmony_ci	if (isr & ISR_SSD)
10258c2ecf20Sopenharmony_ci		i2c_pxa_slave_stop(i2c);
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	if (i2c_pxa_is_slavemode(i2c)) {
10288c2ecf20Sopenharmony_ci		if (isr & ISR_ITE)
10298c2ecf20Sopenharmony_ci			i2c_pxa_slave_txempty(i2c, isr);
10308c2ecf20Sopenharmony_ci		if (isr & ISR_IRF)
10318c2ecf20Sopenharmony_ci			i2c_pxa_slave_rxfull(i2c, isr);
10328c2ecf20Sopenharmony_ci	} else if (i2c->msg && (!i2c->highmode_enter)) {
10338c2ecf20Sopenharmony_ci		if (isr & ISR_ITE)
10348c2ecf20Sopenharmony_ci			i2c_pxa_irq_txempty(i2c, isr);
10358c2ecf20Sopenharmony_ci		if (isr & ISR_IRF)
10368c2ecf20Sopenharmony_ci			i2c_pxa_irq_rxfull(i2c, isr);
10378c2ecf20Sopenharmony_ci	} else if ((isr & ISR_ITE) && i2c->highmode_enter) {
10388c2ecf20Sopenharmony_ci		i2c->highmode_enter = false;
10398c2ecf20Sopenharmony_ci		wake_up(&i2c->wait);
10408c2ecf20Sopenharmony_ci	} else {
10418c2ecf20Sopenharmony_ci		i2c_pxa_scream_blue_murder(i2c, "spurious irq");
10428c2ecf20Sopenharmony_ci	}
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
10458c2ecf20Sopenharmony_ci}
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci/*
10488c2ecf20Sopenharmony_ci * We are protected by the adapter bus mutex.
10498c2ecf20Sopenharmony_ci */
10508c2ecf20Sopenharmony_cistatic int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
10518c2ecf20Sopenharmony_ci{
10528c2ecf20Sopenharmony_ci	long timeout;
10538c2ecf20Sopenharmony_ci	int ret;
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci	/*
10568c2ecf20Sopenharmony_ci	 * Wait for the bus to become free.
10578c2ecf20Sopenharmony_ci	 */
10588c2ecf20Sopenharmony_ci	ret = i2c_pxa_wait_bus_not_busy(i2c);
10598c2ecf20Sopenharmony_ci	if (ret) {
10608c2ecf20Sopenharmony_ci		dev_err(&i2c->adap.dev, "i2c_pxa: timeout waiting for bus free\n");
10618c2ecf20Sopenharmony_ci		i2c_recover_bus(&i2c->adap);
10628c2ecf20Sopenharmony_ci		goto out;
10638c2ecf20Sopenharmony_ci	}
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci	/*
10668c2ecf20Sopenharmony_ci	 * Set master mode.
10678c2ecf20Sopenharmony_ci	 */
10688c2ecf20Sopenharmony_ci	ret = i2c_pxa_set_master(i2c);
10698c2ecf20Sopenharmony_ci	if (ret) {
10708c2ecf20Sopenharmony_ci		dev_err(&i2c->adap.dev, "i2c_pxa_set_master: error %d\n", ret);
10718c2ecf20Sopenharmony_ci		goto out;
10728c2ecf20Sopenharmony_ci	}
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	if (i2c->high_mode) {
10758c2ecf20Sopenharmony_ci		ret = i2c_pxa_send_mastercode(i2c);
10768c2ecf20Sopenharmony_ci		if (ret) {
10778c2ecf20Sopenharmony_ci			dev_err(&i2c->adap.dev, "i2c_pxa_send_mastercode timeout\n");
10788c2ecf20Sopenharmony_ci			goto out;
10798c2ecf20Sopenharmony_ci			}
10808c2ecf20Sopenharmony_ci	}
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	spin_lock_irq(&i2c->lock);
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	i2c->msg = msg;
10858c2ecf20Sopenharmony_ci	i2c->msg_num = num;
10868c2ecf20Sopenharmony_ci	i2c->msg_idx = 0;
10878c2ecf20Sopenharmony_ci	i2c->msg_ptr = 0;
10888c2ecf20Sopenharmony_ci	i2c->irqlogidx = 0;
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci	i2c_pxa_start_message(i2c);
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	spin_unlock_irq(&i2c->lock);
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci	/*
10958c2ecf20Sopenharmony_ci	 * The rest of the processing occurs in the interrupt handler.
10968c2ecf20Sopenharmony_ci	 */
10978c2ecf20Sopenharmony_ci	timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
10988c2ecf20Sopenharmony_ci	i2c_pxa_stop_message(i2c);
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	/*
11018c2ecf20Sopenharmony_ci	 * We place the return code in i2c->msg_idx.
11028c2ecf20Sopenharmony_ci	 */
11038c2ecf20Sopenharmony_ci	ret = i2c->msg_idx;
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	if (!timeout && i2c->msg_num) {
11068c2ecf20Sopenharmony_ci		i2c_pxa_scream_blue_murder(i2c, "timeout with active message");
11078c2ecf20Sopenharmony_ci		i2c_recover_bus(&i2c->adap);
11088c2ecf20Sopenharmony_ci		ret = I2C_RETRY;
11098c2ecf20Sopenharmony_ci	}
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci out:
11128c2ecf20Sopenharmony_ci	return ret;
11138c2ecf20Sopenharmony_ci}
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_cistatic int i2c_pxa_internal_xfer(struct pxa_i2c *i2c,
11168c2ecf20Sopenharmony_ci				 struct i2c_msg *msgs, int num,
11178c2ecf20Sopenharmony_ci				 int (*xfer)(struct pxa_i2c *,
11188c2ecf20Sopenharmony_ci					     struct i2c_msg *, int num))
11198c2ecf20Sopenharmony_ci{
11208c2ecf20Sopenharmony_ci	int ret, i;
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	for (i = 0; ; ) {
11238c2ecf20Sopenharmony_ci		ret = xfer(i2c, msgs, num);
11248c2ecf20Sopenharmony_ci		if (ret != I2C_RETRY && ret != NO_SLAVE)
11258c2ecf20Sopenharmony_ci			goto out;
11268c2ecf20Sopenharmony_ci		if (++i >= i2c->adap.retries)
11278c2ecf20Sopenharmony_ci			break;
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci		if (i2c_debug)
11308c2ecf20Sopenharmony_ci			dev_dbg(&i2c->adap.dev, "Retrying transmission\n");
11318c2ecf20Sopenharmony_ci		udelay(100);
11328c2ecf20Sopenharmony_ci	}
11338c2ecf20Sopenharmony_ci	if (ret != NO_SLAVE)
11348c2ecf20Sopenharmony_ci		i2c_pxa_scream_blue_murder(i2c, "exhausted retries");
11358c2ecf20Sopenharmony_ci	ret = -EREMOTEIO;
11368c2ecf20Sopenharmony_ci out:
11378c2ecf20Sopenharmony_ci	i2c_pxa_set_slave(i2c, ret);
11388c2ecf20Sopenharmony_ci	return ret;
11398c2ecf20Sopenharmony_ci}
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_cistatic int i2c_pxa_xfer(struct i2c_adapter *adap,
11428c2ecf20Sopenharmony_ci			struct i2c_msg msgs[], int num)
11438c2ecf20Sopenharmony_ci{
11448c2ecf20Sopenharmony_ci	struct pxa_i2c *i2c = adap->algo_data;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	return i2c_pxa_internal_xfer(i2c, msgs, num, i2c_pxa_do_xfer);
11478c2ecf20Sopenharmony_ci}
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_cistatic u32 i2c_pxa_functionality(struct i2c_adapter *adap)
11508c2ecf20Sopenharmony_ci{
11518c2ecf20Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
11528c2ecf20Sopenharmony_ci		I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_NOSTART;
11538c2ecf20Sopenharmony_ci}
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_cistatic const struct i2c_algorithm i2c_pxa_algorithm = {
11568c2ecf20Sopenharmony_ci	.master_xfer	= i2c_pxa_xfer,
11578c2ecf20Sopenharmony_ci	.functionality	= i2c_pxa_functionality,
11588c2ecf20Sopenharmony_ci#ifdef CONFIG_I2C_PXA_SLAVE
11598c2ecf20Sopenharmony_ci	.reg_slave	= i2c_pxa_slave_reg,
11608c2ecf20Sopenharmony_ci	.unreg_slave	= i2c_pxa_slave_unreg,
11618c2ecf20Sopenharmony_ci#endif
11628c2ecf20Sopenharmony_ci};
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci/* Non-interrupt mode support */
11658c2ecf20Sopenharmony_cistatic int i2c_pxa_pio_set_master(struct pxa_i2c *i2c)
11668c2ecf20Sopenharmony_ci{
11678c2ecf20Sopenharmony_ci	/* make timeout the same as for interrupt based functions */
11688c2ecf20Sopenharmony_ci	long timeout = 2 * DEF_TIMEOUT;
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci	/*
11718c2ecf20Sopenharmony_ci	 * Wait for the bus to become free.
11728c2ecf20Sopenharmony_ci	 */
11738c2ecf20Sopenharmony_ci	while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB))
11748c2ecf20Sopenharmony_ci		udelay(1000);
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci	if (timeout < 0) {
11778c2ecf20Sopenharmony_ci		show_state(i2c);
11788c2ecf20Sopenharmony_ci		dev_err(&i2c->adap.dev,
11798c2ecf20Sopenharmony_ci			"i2c_pxa: timeout waiting for bus free (set_master)\n");
11808c2ecf20Sopenharmony_ci		return I2C_RETRY;
11818c2ecf20Sopenharmony_ci	}
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	/*
11848c2ecf20Sopenharmony_ci	 * Set master mode.
11858c2ecf20Sopenharmony_ci	 */
11868c2ecf20Sopenharmony_ci	writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c));
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	return 0;
11898c2ecf20Sopenharmony_ci}
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_cistatic int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
11928c2ecf20Sopenharmony_ci			       struct i2c_msg *msg, int num)
11938c2ecf20Sopenharmony_ci{
11948c2ecf20Sopenharmony_ci	unsigned long timeout = 500000; /* 5 seconds */
11958c2ecf20Sopenharmony_ci	int ret = 0;
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci	ret = i2c_pxa_pio_set_master(i2c);
11988c2ecf20Sopenharmony_ci	if (ret)
11998c2ecf20Sopenharmony_ci		goto out;
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	i2c->msg = msg;
12028c2ecf20Sopenharmony_ci	i2c->msg_num = num;
12038c2ecf20Sopenharmony_ci	i2c->msg_idx = 0;
12048c2ecf20Sopenharmony_ci	i2c->msg_ptr = 0;
12058c2ecf20Sopenharmony_ci	i2c->irqlogidx = 0;
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci	i2c_pxa_start_message(i2c);
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	while (i2c->msg_num > 0 && --timeout) {
12108c2ecf20Sopenharmony_ci		i2c_pxa_handler(0, i2c);
12118c2ecf20Sopenharmony_ci		udelay(10);
12128c2ecf20Sopenharmony_ci	}
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	i2c_pxa_stop_message(i2c);
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	/*
12178c2ecf20Sopenharmony_ci	 * We place the return code in i2c->msg_idx.
12188c2ecf20Sopenharmony_ci	 */
12198c2ecf20Sopenharmony_ci	ret = i2c->msg_idx;
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ciout:
12228c2ecf20Sopenharmony_ci	if (timeout == 0) {
12238c2ecf20Sopenharmony_ci		i2c_pxa_scream_blue_murder(i2c, "timeout (do_pio_xfer)");
12248c2ecf20Sopenharmony_ci		ret = I2C_RETRY;
12258c2ecf20Sopenharmony_ci	}
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	return ret;
12288c2ecf20Sopenharmony_ci}
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_cistatic int i2c_pxa_pio_xfer(struct i2c_adapter *adap,
12318c2ecf20Sopenharmony_ci			    struct i2c_msg msgs[], int num)
12328c2ecf20Sopenharmony_ci{
12338c2ecf20Sopenharmony_ci	struct pxa_i2c *i2c = adap->algo_data;
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_ci	/* If the I2C controller is disabled we need to reset it
12368c2ecf20Sopenharmony_ci	  (probably due to a suspend/resume destroying state). We do
12378c2ecf20Sopenharmony_ci	  this here as we can then avoid worrying about resuming the
12388c2ecf20Sopenharmony_ci	  controller before its users. */
12398c2ecf20Sopenharmony_ci	if (!(readl(_ICR(i2c)) & ICR_IUE))
12408c2ecf20Sopenharmony_ci		i2c_pxa_reset(i2c);
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci	return i2c_pxa_internal_xfer(i2c, msgs, num, i2c_pxa_do_pio_xfer);
12438c2ecf20Sopenharmony_ci}
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_cistatic const struct i2c_algorithm i2c_pxa_pio_algorithm = {
12468c2ecf20Sopenharmony_ci	.master_xfer	= i2c_pxa_pio_xfer,
12478c2ecf20Sopenharmony_ci	.functionality	= i2c_pxa_functionality,
12488c2ecf20Sopenharmony_ci#ifdef CONFIG_I2C_PXA_SLAVE
12498c2ecf20Sopenharmony_ci	.reg_slave	= i2c_pxa_slave_reg,
12508c2ecf20Sopenharmony_ci	.unreg_slave	= i2c_pxa_slave_unreg,
12518c2ecf20Sopenharmony_ci#endif
12528c2ecf20Sopenharmony_ci};
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_cistatic int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
12558c2ecf20Sopenharmony_ci			    enum pxa_i2c_types *i2c_types)
12568c2ecf20Sopenharmony_ci{
12578c2ecf20Sopenharmony_ci	struct device_node *np = pdev->dev.of_node;
12588c2ecf20Sopenharmony_ci	const struct of_device_id *of_id =
12598c2ecf20Sopenharmony_ci			of_match_device(i2c_pxa_dt_ids, &pdev->dev);
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	if (!of_id)
12628c2ecf20Sopenharmony_ci		return 1;
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	/* For device tree we always use the dynamic or alias-assigned ID */
12658c2ecf20Sopenharmony_ci	i2c->adap.nr = -1;
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci	if (of_get_property(np, "mrvl,i2c-polling", NULL))
12688c2ecf20Sopenharmony_ci		i2c->use_pio = 1;
12698c2ecf20Sopenharmony_ci	if (of_get_property(np, "mrvl,i2c-fast-mode", NULL))
12708c2ecf20Sopenharmony_ci		i2c->fast_mode = 1;
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ci	*i2c_types = (enum pxa_i2c_types)(of_id->data);
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	return 0;
12758c2ecf20Sopenharmony_ci}
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_cistatic int i2c_pxa_probe_pdata(struct platform_device *pdev,
12788c2ecf20Sopenharmony_ci			       struct pxa_i2c *i2c,
12798c2ecf20Sopenharmony_ci			       enum pxa_i2c_types *i2c_types)
12808c2ecf20Sopenharmony_ci{
12818c2ecf20Sopenharmony_ci	struct i2c_pxa_platform_data *plat = dev_get_platdata(&pdev->dev);
12828c2ecf20Sopenharmony_ci	const struct platform_device_id *id = platform_get_device_id(pdev);
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci	*i2c_types = id->driver_data;
12858c2ecf20Sopenharmony_ci	if (plat) {
12868c2ecf20Sopenharmony_ci		i2c->use_pio = plat->use_pio;
12878c2ecf20Sopenharmony_ci		i2c->fast_mode = plat->fast_mode;
12888c2ecf20Sopenharmony_ci		i2c->high_mode = plat->high_mode;
12898c2ecf20Sopenharmony_ci		i2c->master_code = plat->master_code;
12908c2ecf20Sopenharmony_ci		if (!i2c->master_code)
12918c2ecf20Sopenharmony_ci			i2c->master_code = 0xe;
12928c2ecf20Sopenharmony_ci		i2c->rate = plat->rate;
12938c2ecf20Sopenharmony_ci	}
12948c2ecf20Sopenharmony_ci	return 0;
12958c2ecf20Sopenharmony_ci}
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_cistatic void i2c_pxa_prepare_recovery(struct i2c_adapter *adap)
12988c2ecf20Sopenharmony_ci{
12998c2ecf20Sopenharmony_ci	struct pxa_i2c *i2c = adap->algo_data;
13008c2ecf20Sopenharmony_ci	u32 ibmr = readl(_IBMR(i2c));
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	/*
13038c2ecf20Sopenharmony_ci	 * Program the GPIOs to reflect the current I2C bus state while
13048c2ecf20Sopenharmony_ci	 * we transition to recovery; this avoids glitching the bus.
13058c2ecf20Sopenharmony_ci	 */
13068c2ecf20Sopenharmony_ci	gpiod_set_value(i2c->recovery.scl_gpiod, ibmr & IBMR_SCLS);
13078c2ecf20Sopenharmony_ci	gpiod_set_value(i2c->recovery.sda_gpiod, ibmr & IBMR_SDAS);
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci	WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery));
13108c2ecf20Sopenharmony_ci}
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_cistatic void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
13138c2ecf20Sopenharmony_ci{
13148c2ecf20Sopenharmony_ci	struct pxa_i2c *i2c = adap->algo_data;
13158c2ecf20Sopenharmony_ci	u32 isr;
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_ci	/*
13188c2ecf20Sopenharmony_ci	 * The bus should now be free. Clear up the I2C controller before
13198c2ecf20Sopenharmony_ci	 * handing control of the bus back to avoid the bus changing state.
13208c2ecf20Sopenharmony_ci	 */
13218c2ecf20Sopenharmony_ci	isr = readl(_ISR(i2c));
13228c2ecf20Sopenharmony_ci	if (isr & (ISR_UB | ISR_IBB)) {
13238c2ecf20Sopenharmony_ci		dev_dbg(&i2c->adap.dev,
13248c2ecf20Sopenharmony_ci			"recovery: resetting controller, ISR=0x%08x\n", isr);
13258c2ecf20Sopenharmony_ci		i2c_pxa_do_reset(i2c);
13268c2ecf20Sopenharmony_ci	}
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci	WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default));
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	dev_dbg(&i2c->adap.dev, "recovery: IBMR 0x%08x ISR 0x%08x\n",
13318c2ecf20Sopenharmony_ci	        readl(_IBMR(i2c)), readl(_ISR(i2c)));
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	i2c_pxa_enable(i2c);
13348c2ecf20Sopenharmony_ci}
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_cistatic int i2c_pxa_init_recovery(struct pxa_i2c *i2c)
13378c2ecf20Sopenharmony_ci{
13388c2ecf20Sopenharmony_ci	struct i2c_bus_recovery_info *bri = &i2c->recovery;
13398c2ecf20Sopenharmony_ci	struct device *dev = i2c->adap.dev.parent;
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_ci	/*
13428c2ecf20Sopenharmony_ci	 * When slave mode is enabled, we are not the only master on the bus.
13438c2ecf20Sopenharmony_ci	 * Bus recovery can only be performed when we are the master, which
13448c2ecf20Sopenharmony_ci	 * we can't be certain of. Therefore, when slave mode is enabled, do
13458c2ecf20Sopenharmony_ci	 * not configure bus recovery.
13468c2ecf20Sopenharmony_ci	 */
13478c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_I2C_PXA_SLAVE))
13488c2ecf20Sopenharmony_ci		return 0;
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	i2c->pinctrl = devm_pinctrl_get(dev);
13518c2ecf20Sopenharmony_ci	if (PTR_ERR(i2c->pinctrl) == -ENODEV)
13528c2ecf20Sopenharmony_ci		i2c->pinctrl = NULL;
13538c2ecf20Sopenharmony_ci	if (IS_ERR(i2c->pinctrl))
13548c2ecf20Sopenharmony_ci		return PTR_ERR(i2c->pinctrl);
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	if (!i2c->pinctrl)
13578c2ecf20Sopenharmony_ci		return 0;
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ci	i2c->pinctrl_default = pinctrl_lookup_state(i2c->pinctrl,
13608c2ecf20Sopenharmony_ci						    PINCTRL_STATE_DEFAULT);
13618c2ecf20Sopenharmony_ci	i2c->pinctrl_recovery = pinctrl_lookup_state(i2c->pinctrl, "recovery");
13628c2ecf20Sopenharmony_ci
13638c2ecf20Sopenharmony_ci	if (IS_ERR(i2c->pinctrl_default) || IS_ERR(i2c->pinctrl_recovery)) {
13648c2ecf20Sopenharmony_ci		dev_info(dev, "missing pinmux recovery information: %ld %ld\n",
13658c2ecf20Sopenharmony_ci			 PTR_ERR(i2c->pinctrl_default),
13668c2ecf20Sopenharmony_ci			 PTR_ERR(i2c->pinctrl_recovery));
13678c2ecf20Sopenharmony_ci		return 0;
13688c2ecf20Sopenharmony_ci	}
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_ci	/*
13718c2ecf20Sopenharmony_ci	 * Claiming GPIOs can influence the pinmux state, and may glitch the
13728c2ecf20Sopenharmony_ci	 * I2C bus. Do this carefully.
13738c2ecf20Sopenharmony_ci	 */
13748c2ecf20Sopenharmony_ci	bri->scl_gpiod = devm_gpiod_get(dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
13758c2ecf20Sopenharmony_ci	if (bri->scl_gpiod == ERR_PTR(-EPROBE_DEFER))
13768c2ecf20Sopenharmony_ci		return -EPROBE_DEFER;
13778c2ecf20Sopenharmony_ci	if (IS_ERR(bri->scl_gpiod)) {
13788c2ecf20Sopenharmony_ci		dev_info(dev, "missing scl gpio recovery information: %pe\n",
13798c2ecf20Sopenharmony_ci			 bri->scl_gpiod);
13808c2ecf20Sopenharmony_ci		return 0;
13818c2ecf20Sopenharmony_ci	}
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci	/*
13848c2ecf20Sopenharmony_ci	 * We have SCL. Pull SCL low and wait a bit so that SDA glitches
13858c2ecf20Sopenharmony_ci	 * have no effect.
13868c2ecf20Sopenharmony_ci	 */
13878c2ecf20Sopenharmony_ci	gpiod_direction_output(bri->scl_gpiod, 0);
13888c2ecf20Sopenharmony_ci	udelay(10);
13898c2ecf20Sopenharmony_ci	bri->sda_gpiod = devm_gpiod_get(dev, "sda", GPIOD_OUT_HIGH_OPEN_DRAIN);
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci	/* Wait a bit in case of a SDA glitch, and then release SCL. */
13928c2ecf20Sopenharmony_ci	udelay(10);
13938c2ecf20Sopenharmony_ci	gpiod_direction_output(bri->scl_gpiod, 1);
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	if (bri->sda_gpiod == ERR_PTR(-EPROBE_DEFER))
13968c2ecf20Sopenharmony_ci		return -EPROBE_DEFER;
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci	if (IS_ERR(bri->sda_gpiod)) {
13998c2ecf20Sopenharmony_ci		dev_info(dev, "missing sda gpio recovery information: %pe\n",
14008c2ecf20Sopenharmony_ci			 bri->sda_gpiod);
14018c2ecf20Sopenharmony_ci		return 0;
14028c2ecf20Sopenharmony_ci	}
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	bri->prepare_recovery = i2c_pxa_prepare_recovery;
14058c2ecf20Sopenharmony_ci	bri->unprepare_recovery = i2c_pxa_unprepare_recovery;
14068c2ecf20Sopenharmony_ci	bri->recover_bus = i2c_generic_scl_recovery;
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_ci	i2c->adap.bus_recovery_info = bri;
14098c2ecf20Sopenharmony_ci
14108c2ecf20Sopenharmony_ci	/*
14118c2ecf20Sopenharmony_ci	 * Claiming GPIOs can change the pinmux state, which confuses the
14128c2ecf20Sopenharmony_ci	 * pinctrl since pinctrl's idea of the current setting is unaffected
14138c2ecf20Sopenharmony_ci	 * by the pinmux change caused by claiming the GPIO. Work around that
14148c2ecf20Sopenharmony_ci	 * by switching pinctrl to the GPIO state here. We do it this way to
14158c2ecf20Sopenharmony_ci	 * avoid glitching the I2C bus.
14168c2ecf20Sopenharmony_ci	 */
14178c2ecf20Sopenharmony_ci	pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery);
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	return pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default);
14208c2ecf20Sopenharmony_ci}
14218c2ecf20Sopenharmony_ci
14228c2ecf20Sopenharmony_cistatic int i2c_pxa_probe(struct platform_device *dev)
14238c2ecf20Sopenharmony_ci{
14248c2ecf20Sopenharmony_ci	struct i2c_pxa_platform_data *plat = dev_get_platdata(&dev->dev);
14258c2ecf20Sopenharmony_ci	enum pxa_i2c_types i2c_type;
14268c2ecf20Sopenharmony_ci	struct pxa_i2c *i2c;
14278c2ecf20Sopenharmony_ci	struct resource *res = NULL;
14288c2ecf20Sopenharmony_ci	int ret, irq;
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	i2c = devm_kzalloc(&dev->dev, sizeof(struct pxa_i2c), GFP_KERNEL);
14318c2ecf20Sopenharmony_ci	if (!i2c)
14328c2ecf20Sopenharmony_ci		return -ENOMEM;
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci	/* Default adapter num to device id; i2c_pxa_probe_dt can override. */
14358c2ecf20Sopenharmony_ci	i2c->adap.nr = dev->id;
14368c2ecf20Sopenharmony_ci	i2c->adap.owner   = THIS_MODULE;
14378c2ecf20Sopenharmony_ci	i2c->adap.retries = 5;
14388c2ecf20Sopenharmony_ci	i2c->adap.algo_data = i2c;
14398c2ecf20Sopenharmony_ci	i2c->adap.dev.parent = &dev->dev;
14408c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
14418c2ecf20Sopenharmony_ci	i2c->adap.dev.of_node = dev->dev.of_node;
14428c2ecf20Sopenharmony_ci#endif
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
14458c2ecf20Sopenharmony_ci	i2c->reg_base = devm_ioremap_resource(&dev->dev, res);
14468c2ecf20Sopenharmony_ci	if (IS_ERR(i2c->reg_base))
14478c2ecf20Sopenharmony_ci		return PTR_ERR(i2c->reg_base);
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci	irq = platform_get_irq(dev, 0);
14508c2ecf20Sopenharmony_ci	if (irq < 0)
14518c2ecf20Sopenharmony_ci		return irq;
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	ret = i2c_pxa_init_recovery(i2c);
14548c2ecf20Sopenharmony_ci	if (ret)
14558c2ecf20Sopenharmony_ci		return ret;
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci	ret = i2c_pxa_probe_dt(dev, i2c, &i2c_type);
14588c2ecf20Sopenharmony_ci	if (ret > 0)
14598c2ecf20Sopenharmony_ci		ret = i2c_pxa_probe_pdata(dev, i2c, &i2c_type);
14608c2ecf20Sopenharmony_ci	if (ret < 0)
14618c2ecf20Sopenharmony_ci		return ret;
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_ci	spin_lock_init(&i2c->lock);
14648c2ecf20Sopenharmony_ci	init_waitqueue_head(&i2c->wait);
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci	strlcpy(i2c->adap.name, "pxa_i2c-i2c", sizeof(i2c->adap.name));
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_ci	i2c->clk = devm_clk_get(&dev->dev, NULL);
14698c2ecf20Sopenharmony_ci	if (IS_ERR(i2c->clk)) {
14708c2ecf20Sopenharmony_ci		dev_err(&dev->dev, "failed to get the clk: %ld\n", PTR_ERR(i2c->clk));
14718c2ecf20Sopenharmony_ci		return PTR_ERR(i2c->clk);
14728c2ecf20Sopenharmony_ci	}
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci	i2c->reg_ibmr = i2c->reg_base + pxa_reg_layout[i2c_type].ibmr;
14758c2ecf20Sopenharmony_ci	i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr;
14768c2ecf20Sopenharmony_ci	i2c->reg_icr = i2c->reg_base + pxa_reg_layout[i2c_type].icr;
14778c2ecf20Sopenharmony_ci	i2c->reg_isr = i2c->reg_base + pxa_reg_layout[i2c_type].isr;
14788c2ecf20Sopenharmony_ci	i2c->fm_mask = pxa_reg_layout[i2c_type].fm;
14798c2ecf20Sopenharmony_ci	i2c->hs_mask = pxa_reg_layout[i2c_type].hs;
14808c2ecf20Sopenharmony_ci
14818c2ecf20Sopenharmony_ci	if (i2c_type != REGS_CE4100)
14828c2ecf20Sopenharmony_ci		i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci	if (i2c_type == REGS_PXA910) {
14858c2ecf20Sopenharmony_ci		i2c->reg_ilcr = i2c->reg_base + pxa_reg_layout[i2c_type].ilcr;
14868c2ecf20Sopenharmony_ci		i2c->reg_iwcr = i2c->reg_base + pxa_reg_layout[i2c_type].iwcr;
14878c2ecf20Sopenharmony_ci	}
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_ci	i2c->iobase = res->start;
14908c2ecf20Sopenharmony_ci	i2c->iosize = resource_size(res);
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci	i2c->irq = irq;
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci	i2c->slave_addr = I2C_PXA_SLAVE_ADDR;
14958c2ecf20Sopenharmony_ci	i2c->highmode_enter = false;
14968c2ecf20Sopenharmony_ci
14978c2ecf20Sopenharmony_ci	if (plat) {
14988c2ecf20Sopenharmony_ci		i2c->adap.class = plat->class;
14998c2ecf20Sopenharmony_ci	}
15008c2ecf20Sopenharmony_ci
15018c2ecf20Sopenharmony_ci	if (i2c->high_mode) {
15028c2ecf20Sopenharmony_ci		if (i2c->rate) {
15038c2ecf20Sopenharmony_ci			clk_set_rate(i2c->clk, i2c->rate);
15048c2ecf20Sopenharmony_ci			pr_info("i2c: <%s> set rate to %ld\n",
15058c2ecf20Sopenharmony_ci				i2c->adap.name, clk_get_rate(i2c->clk));
15068c2ecf20Sopenharmony_ci		} else
15078c2ecf20Sopenharmony_ci			pr_warn("i2c: <%s> clock rate not set\n",
15088c2ecf20Sopenharmony_ci				i2c->adap.name);
15098c2ecf20Sopenharmony_ci	}
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci	clk_prepare_enable(i2c->clk);
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci	if (i2c->use_pio) {
15148c2ecf20Sopenharmony_ci		i2c->adap.algo = &i2c_pxa_pio_algorithm;
15158c2ecf20Sopenharmony_ci	} else {
15168c2ecf20Sopenharmony_ci		i2c->adap.algo = &i2c_pxa_algorithm;
15178c2ecf20Sopenharmony_ci		ret = devm_request_irq(&dev->dev, irq, i2c_pxa_handler,
15188c2ecf20Sopenharmony_ci				IRQF_SHARED | IRQF_NO_SUSPEND,
15198c2ecf20Sopenharmony_ci				dev_name(&dev->dev), i2c);
15208c2ecf20Sopenharmony_ci		if (ret) {
15218c2ecf20Sopenharmony_ci			dev_err(&dev->dev, "failed to request irq: %d\n", ret);
15228c2ecf20Sopenharmony_ci			goto ereqirq;
15238c2ecf20Sopenharmony_ci		}
15248c2ecf20Sopenharmony_ci	}
15258c2ecf20Sopenharmony_ci
15268c2ecf20Sopenharmony_ci	i2c_pxa_reset(i2c);
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_ci	ret = i2c_add_numbered_adapter(&i2c->adap);
15298c2ecf20Sopenharmony_ci	if (ret < 0)
15308c2ecf20Sopenharmony_ci		goto ereqirq;
15318c2ecf20Sopenharmony_ci
15328c2ecf20Sopenharmony_ci	platform_set_drvdata(dev, i2c);
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_ci#ifdef CONFIG_I2C_PXA_SLAVE
15358c2ecf20Sopenharmony_ci	dev_info(&i2c->adap.dev, " PXA I2C adapter, slave address %d\n",
15368c2ecf20Sopenharmony_ci		i2c->slave_addr);
15378c2ecf20Sopenharmony_ci#else
15388c2ecf20Sopenharmony_ci	dev_info(&i2c->adap.dev, " PXA I2C adapter\n");
15398c2ecf20Sopenharmony_ci#endif
15408c2ecf20Sopenharmony_ci	return 0;
15418c2ecf20Sopenharmony_ci
15428c2ecf20Sopenharmony_ciereqirq:
15438c2ecf20Sopenharmony_ci	clk_disable_unprepare(i2c->clk);
15448c2ecf20Sopenharmony_ci	return ret;
15458c2ecf20Sopenharmony_ci}
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_cistatic int i2c_pxa_remove(struct platform_device *dev)
15488c2ecf20Sopenharmony_ci{
15498c2ecf20Sopenharmony_ci	struct pxa_i2c *i2c = platform_get_drvdata(dev);
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	i2c_del_adapter(&i2c->adap);
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_ci	clk_disable_unprepare(i2c->clk);
15548c2ecf20Sopenharmony_ci
15558c2ecf20Sopenharmony_ci	return 0;
15568c2ecf20Sopenharmony_ci}
15578c2ecf20Sopenharmony_ci
15588c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
15598c2ecf20Sopenharmony_cistatic int i2c_pxa_suspend_noirq(struct device *dev)
15608c2ecf20Sopenharmony_ci{
15618c2ecf20Sopenharmony_ci	struct pxa_i2c *i2c = dev_get_drvdata(dev);
15628c2ecf20Sopenharmony_ci
15638c2ecf20Sopenharmony_ci	clk_disable(i2c->clk);
15648c2ecf20Sopenharmony_ci
15658c2ecf20Sopenharmony_ci	return 0;
15668c2ecf20Sopenharmony_ci}
15678c2ecf20Sopenharmony_ci
15688c2ecf20Sopenharmony_cistatic int i2c_pxa_resume_noirq(struct device *dev)
15698c2ecf20Sopenharmony_ci{
15708c2ecf20Sopenharmony_ci	struct pxa_i2c *i2c = dev_get_drvdata(dev);
15718c2ecf20Sopenharmony_ci
15728c2ecf20Sopenharmony_ci	clk_enable(i2c->clk);
15738c2ecf20Sopenharmony_ci	i2c_pxa_reset(i2c);
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci	return 0;
15768c2ecf20Sopenharmony_ci}
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_cistatic const struct dev_pm_ops i2c_pxa_dev_pm_ops = {
15798c2ecf20Sopenharmony_ci	.suspend_noirq = i2c_pxa_suspend_noirq,
15808c2ecf20Sopenharmony_ci	.resume_noirq = i2c_pxa_resume_noirq,
15818c2ecf20Sopenharmony_ci};
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci#define I2C_PXA_DEV_PM_OPS (&i2c_pxa_dev_pm_ops)
15848c2ecf20Sopenharmony_ci#else
15858c2ecf20Sopenharmony_ci#define I2C_PXA_DEV_PM_OPS NULL
15868c2ecf20Sopenharmony_ci#endif
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_cistatic struct platform_driver i2c_pxa_driver = {
15898c2ecf20Sopenharmony_ci	.probe		= i2c_pxa_probe,
15908c2ecf20Sopenharmony_ci	.remove		= i2c_pxa_remove,
15918c2ecf20Sopenharmony_ci	.driver		= {
15928c2ecf20Sopenharmony_ci		.name	= "pxa2xx-i2c",
15938c2ecf20Sopenharmony_ci		.pm	= I2C_PXA_DEV_PM_OPS,
15948c2ecf20Sopenharmony_ci		.of_match_table = i2c_pxa_dt_ids,
15958c2ecf20Sopenharmony_ci	},
15968c2ecf20Sopenharmony_ci	.id_table	= i2c_pxa_id_table,
15978c2ecf20Sopenharmony_ci};
15988c2ecf20Sopenharmony_ci
15998c2ecf20Sopenharmony_cistatic int __init i2c_adap_pxa_init(void)
16008c2ecf20Sopenharmony_ci{
16018c2ecf20Sopenharmony_ci	return platform_driver_register(&i2c_pxa_driver);
16028c2ecf20Sopenharmony_ci}
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_cistatic void __exit i2c_adap_pxa_exit(void)
16058c2ecf20Sopenharmony_ci{
16068c2ecf20Sopenharmony_ci	platform_driver_unregister(&i2c_pxa_driver);
16078c2ecf20Sopenharmony_ci}
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
16108c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:pxa2xx-i2c");
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_cisubsys_initcall(i2c_adap_pxa_init);
16138c2ecf20Sopenharmony_cimodule_exit(i2c_adap_pxa_exit);
1614