18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * (C) Copyright 2003-2004
38c2ecf20Sopenharmony_ci * Humboldt Solutions Ltd, adrian@humboldt.co.uk.
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci * This is a combined i2c adapter and algorithm driver for the
68c2ecf20Sopenharmony_ci * MPC107/Tsi107 PowerPC northbridge and processors that include
78c2ecf20Sopenharmony_ci * the same I2C unit (8240, 8245, 85xx).
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Release 0.8
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * This file is licensed under the terms of the GNU General Public
128c2ecf20Sopenharmony_ci * License version 2. This program is licensed "as is" without any
138c2ecf20Sopenharmony_ci * warranty of any kind, whether express or implied.
148c2ecf20Sopenharmony_ci */
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <linux/kernel.h>
178c2ecf20Sopenharmony_ci#include <linux/module.h>
188c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
198c2ecf20Sopenharmony_ci#include <linux/of_address.h>
208c2ecf20Sopenharmony_ci#include <linux/of_irq.h>
218c2ecf20Sopenharmony_ci#include <linux/of_platform.h>
228c2ecf20Sopenharmony_ci#include <linux/slab.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include <linux/clk.h>
258c2ecf20Sopenharmony_ci#include <linux/io.h>
268c2ecf20Sopenharmony_ci#include <linux/iopoll.h>
278c2ecf20Sopenharmony_ci#include <linux/fsl_devices.h>
288c2ecf20Sopenharmony_ci#include <linux/i2c.h>
298c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
308c2ecf20Sopenharmony_ci#include <linux/delay.h>
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#include <asm/mpc52xx.h>
338c2ecf20Sopenharmony_ci#include <asm/mpc85xx.h>
348c2ecf20Sopenharmony_ci#include <sysdev/fsl_soc.h>
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define DRV_NAME "mpc-i2c"
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define MPC_I2C_CLOCK_LEGACY   0
398c2ecf20Sopenharmony_ci#define MPC_I2C_CLOCK_PRESERVE (~0U)
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define MPC_I2C_FDR   0x04
428c2ecf20Sopenharmony_ci#define MPC_I2C_CR    0x08
438c2ecf20Sopenharmony_ci#define MPC_I2C_SR    0x0c
448c2ecf20Sopenharmony_ci#define MPC_I2C_DR    0x10
458c2ecf20Sopenharmony_ci#define MPC_I2C_DFSRR 0x14
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define CCR_MEN  0x80
488c2ecf20Sopenharmony_ci#define CCR_MIEN 0x40
498c2ecf20Sopenharmony_ci#define CCR_MSTA 0x20
508c2ecf20Sopenharmony_ci#define CCR_MTX  0x10
518c2ecf20Sopenharmony_ci#define CCR_TXAK 0x08
528c2ecf20Sopenharmony_ci#define CCR_RSTA 0x04
538c2ecf20Sopenharmony_ci#define CCR_RSVD 0x02
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define CSR_MCF  0x80
568c2ecf20Sopenharmony_ci#define CSR_MAAS 0x40
578c2ecf20Sopenharmony_ci#define CSR_MBB  0x20
588c2ecf20Sopenharmony_ci#define CSR_MAL  0x10
598c2ecf20Sopenharmony_ci#define CSR_SRW  0x04
608c2ecf20Sopenharmony_ci#define CSR_MIF  0x02
618c2ecf20Sopenharmony_ci#define CSR_RXAK 0x01
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistruct mpc_i2c {
648c2ecf20Sopenharmony_ci	struct device *dev;
658c2ecf20Sopenharmony_ci	void __iomem *base;
668c2ecf20Sopenharmony_ci	u32 interrupt;
678c2ecf20Sopenharmony_ci	wait_queue_head_t queue;
688c2ecf20Sopenharmony_ci	struct i2c_adapter adap;
698c2ecf20Sopenharmony_ci	int irq;
708c2ecf20Sopenharmony_ci	u32 real_clk;
718c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
728c2ecf20Sopenharmony_ci	u8 fdr, dfsrr;
738c2ecf20Sopenharmony_ci#endif
748c2ecf20Sopenharmony_ci	struct clk *clk_per;
758c2ecf20Sopenharmony_ci	bool has_errata_A004447;
768c2ecf20Sopenharmony_ci};
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistruct mpc_i2c_divider {
798c2ecf20Sopenharmony_ci	u16 divider;
808c2ecf20Sopenharmony_ci	u16 fdr;	/* including dfsrr */
818c2ecf20Sopenharmony_ci};
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_cistruct mpc_i2c_data {
848c2ecf20Sopenharmony_ci	void (*setup)(struct device_node *node, struct mpc_i2c *i2c, u32 clock);
858c2ecf20Sopenharmony_ci};
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cistatic inline void writeccr(struct mpc_i2c *i2c, u32 x)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	writeb(x, i2c->base + MPC_I2C_CR);
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistatic irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	struct mpc_i2c *i2c = dev_id;
958c2ecf20Sopenharmony_ci	if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) {
968c2ecf20Sopenharmony_ci		/* Read again to allow register to stabilise */
978c2ecf20Sopenharmony_ci		i2c->interrupt = readb(i2c->base + MPC_I2C_SR);
988c2ecf20Sopenharmony_ci		writeb(0, i2c->base + MPC_I2C_SR);
998c2ecf20Sopenharmony_ci		wake_up(&i2c->queue);
1008c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
1018c2ecf20Sopenharmony_ci	}
1028c2ecf20Sopenharmony_ci	return IRQ_NONE;
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/* Sometimes 9th clock pulse isn't generated, and slave doesn't release
1068c2ecf20Sopenharmony_ci * the bus, because it wants to send ACK.
1078c2ecf20Sopenharmony_ci * Following sequence of enabling/disabling and sending start/stop generates
1088c2ecf20Sopenharmony_ci * the 9 pulses, each with a START then ending with STOP, so it's all OK.
1098c2ecf20Sopenharmony_ci */
1108c2ecf20Sopenharmony_cistatic void mpc_i2c_fixup(struct mpc_i2c *i2c)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	int k;
1138c2ecf20Sopenharmony_ci	unsigned long flags;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	for (k = 9; k; k--) {
1168c2ecf20Sopenharmony_ci		writeccr(i2c, 0);
1178c2ecf20Sopenharmony_ci		writeb(0, i2c->base + MPC_I2C_SR); /* clear any status bits */
1188c2ecf20Sopenharmony_ci		writeccr(i2c, CCR_MEN | CCR_MSTA); /* START */
1198c2ecf20Sopenharmony_ci		readb(i2c->base + MPC_I2C_DR); /* init xfer */
1208c2ecf20Sopenharmony_ci		udelay(15); /* let it hit the bus */
1218c2ecf20Sopenharmony_ci		local_irq_save(flags); /* should not be delayed further */
1228c2ecf20Sopenharmony_ci		writeccr(i2c, CCR_MEN | CCR_MSTA | CCR_RSTA); /* delay SDA */
1238c2ecf20Sopenharmony_ci		readb(i2c->base + MPC_I2C_DR);
1248c2ecf20Sopenharmony_ci		if (k != 1)
1258c2ecf20Sopenharmony_ci			udelay(5);
1268c2ecf20Sopenharmony_ci		local_irq_restore(flags);
1278c2ecf20Sopenharmony_ci	}
1288c2ecf20Sopenharmony_ci	writeccr(i2c, CCR_MEN); /* Initiate STOP */
1298c2ecf20Sopenharmony_ci	readb(i2c->base + MPC_I2C_DR);
1308c2ecf20Sopenharmony_ci	udelay(15); /* Let STOP propagate */
1318c2ecf20Sopenharmony_ci	writeccr(i2c, 0);
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistatic int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	unsigned long orig_jiffies = jiffies;
1378c2ecf20Sopenharmony_ci	u32 cmd_err;
1388c2ecf20Sopenharmony_ci	int result = 0;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	if (!i2c->irq) {
1418c2ecf20Sopenharmony_ci		while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) {
1428c2ecf20Sopenharmony_ci			schedule();
1438c2ecf20Sopenharmony_ci			if (time_after(jiffies, orig_jiffies + timeout)) {
1448c2ecf20Sopenharmony_ci				dev_dbg(i2c->dev, "timeout\n");
1458c2ecf20Sopenharmony_ci				writeccr(i2c, 0);
1468c2ecf20Sopenharmony_ci				result = -ETIMEDOUT;
1478c2ecf20Sopenharmony_ci				break;
1488c2ecf20Sopenharmony_ci			}
1498c2ecf20Sopenharmony_ci		}
1508c2ecf20Sopenharmony_ci		cmd_err = readb(i2c->base + MPC_I2C_SR);
1518c2ecf20Sopenharmony_ci		writeb(0, i2c->base + MPC_I2C_SR);
1528c2ecf20Sopenharmony_ci	} else {
1538c2ecf20Sopenharmony_ci		/* Interrupt mode */
1548c2ecf20Sopenharmony_ci		result = wait_event_timeout(i2c->queue,
1558c2ecf20Sopenharmony_ci			(i2c->interrupt & CSR_MIF), timeout);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci		if (unlikely(!(i2c->interrupt & CSR_MIF))) {
1588c2ecf20Sopenharmony_ci			dev_dbg(i2c->dev, "wait timeout\n");
1598c2ecf20Sopenharmony_ci			writeccr(i2c, 0);
1608c2ecf20Sopenharmony_ci			result = -ETIMEDOUT;
1618c2ecf20Sopenharmony_ci		}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci		cmd_err = i2c->interrupt;
1648c2ecf20Sopenharmony_ci		i2c->interrupt = 0;
1658c2ecf20Sopenharmony_ci	}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	if (result < 0)
1688c2ecf20Sopenharmony_ci		return result;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	if (!(cmd_err & CSR_MCF)) {
1718c2ecf20Sopenharmony_ci		dev_dbg(i2c->dev, "unfinished\n");
1728c2ecf20Sopenharmony_ci		return -EIO;
1738c2ecf20Sopenharmony_ci	}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	if (cmd_err & CSR_MAL) {
1768c2ecf20Sopenharmony_ci		dev_dbg(i2c->dev, "MAL\n");
1778c2ecf20Sopenharmony_ci		return -EAGAIN;
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	if (writing && (cmd_err & CSR_RXAK)) {
1818c2ecf20Sopenharmony_ci		dev_dbg(i2c->dev, "No RXAK\n");
1828c2ecf20Sopenharmony_ci		/* generate stop */
1838c2ecf20Sopenharmony_ci		writeccr(i2c, CCR_MEN);
1848c2ecf20Sopenharmony_ci		return -ENXIO;
1858c2ecf20Sopenharmony_ci	}
1868c2ecf20Sopenharmony_ci	return 0;
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_cistatic int i2c_mpc_wait_sr(struct mpc_i2c *i2c, int mask)
1908c2ecf20Sopenharmony_ci{
1918c2ecf20Sopenharmony_ci	void __iomem *addr = i2c->base + MPC_I2C_SR;
1928c2ecf20Sopenharmony_ci	u8 val;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	return readb_poll_timeout(addr, val, val & mask, 0, 100);
1958c2ecf20Sopenharmony_ci}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci/*
1988c2ecf20Sopenharmony_ci * Workaround for Erratum A004447. From the P2040CE Rev Q
1998c2ecf20Sopenharmony_ci *
2008c2ecf20Sopenharmony_ci * 1.  Set up the frequency divider and sampling rate.
2018c2ecf20Sopenharmony_ci * 2.  I2CCR - a0h
2028c2ecf20Sopenharmony_ci * 3.  Poll for I2CSR[MBB] to get set.
2038c2ecf20Sopenharmony_ci * 4.  If I2CSR[MAL] is set (an indication that SDA is stuck low), then go to
2048c2ecf20Sopenharmony_ci *     step 5. If MAL is not set, then go to step 13.
2058c2ecf20Sopenharmony_ci * 5.  I2CCR - 00h
2068c2ecf20Sopenharmony_ci * 6.  I2CCR - 22h
2078c2ecf20Sopenharmony_ci * 7.  I2CCR - a2h
2088c2ecf20Sopenharmony_ci * 8.  Poll for I2CSR[MBB] to get set.
2098c2ecf20Sopenharmony_ci * 9.  Issue read to I2CDR.
2108c2ecf20Sopenharmony_ci * 10. Poll for I2CSR[MIF] to be set.
2118c2ecf20Sopenharmony_ci * 11. I2CCR - 82h
2128c2ecf20Sopenharmony_ci * 12. Workaround complete. Skip the next steps.
2138c2ecf20Sopenharmony_ci * 13. Issue read to I2CDR.
2148c2ecf20Sopenharmony_ci * 14. Poll for I2CSR[MIF] to be set.
2158c2ecf20Sopenharmony_ci * 15. I2CCR - 80h
2168c2ecf20Sopenharmony_ci */
2178c2ecf20Sopenharmony_cistatic void mpc_i2c_fixup_A004447(struct mpc_i2c *i2c)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	int ret;
2208c2ecf20Sopenharmony_ci	u32 val;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	writeccr(i2c, CCR_MEN | CCR_MSTA);
2238c2ecf20Sopenharmony_ci	ret = i2c_mpc_wait_sr(i2c, CSR_MBB);
2248c2ecf20Sopenharmony_ci	if (ret) {
2258c2ecf20Sopenharmony_ci		dev_err(i2c->dev, "timeout waiting for CSR_MBB\n");
2268c2ecf20Sopenharmony_ci		return;
2278c2ecf20Sopenharmony_ci	}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	val = readb(i2c->base + MPC_I2C_SR);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	if (val & CSR_MAL) {
2328c2ecf20Sopenharmony_ci		writeccr(i2c, 0x00);
2338c2ecf20Sopenharmony_ci		writeccr(i2c, CCR_MSTA | CCR_RSVD);
2348c2ecf20Sopenharmony_ci		writeccr(i2c, CCR_MEN | CCR_MSTA | CCR_RSVD);
2358c2ecf20Sopenharmony_ci		ret = i2c_mpc_wait_sr(i2c, CSR_MBB);
2368c2ecf20Sopenharmony_ci		if (ret) {
2378c2ecf20Sopenharmony_ci			dev_err(i2c->dev, "timeout waiting for CSR_MBB\n");
2388c2ecf20Sopenharmony_ci			return;
2398c2ecf20Sopenharmony_ci		}
2408c2ecf20Sopenharmony_ci		val = readb(i2c->base + MPC_I2C_DR);
2418c2ecf20Sopenharmony_ci		ret = i2c_mpc_wait_sr(i2c, CSR_MIF);
2428c2ecf20Sopenharmony_ci		if (ret) {
2438c2ecf20Sopenharmony_ci			dev_err(i2c->dev, "timeout waiting for CSR_MIF\n");
2448c2ecf20Sopenharmony_ci			return;
2458c2ecf20Sopenharmony_ci		}
2468c2ecf20Sopenharmony_ci		writeccr(i2c, CCR_MEN | CCR_RSVD);
2478c2ecf20Sopenharmony_ci	} else {
2488c2ecf20Sopenharmony_ci		val = readb(i2c->base + MPC_I2C_DR);
2498c2ecf20Sopenharmony_ci		ret = i2c_mpc_wait_sr(i2c, CSR_MIF);
2508c2ecf20Sopenharmony_ci		if (ret) {
2518c2ecf20Sopenharmony_ci			dev_err(i2c->dev, "timeout waiting for CSR_MIF\n");
2528c2ecf20Sopenharmony_ci			return;
2538c2ecf20Sopenharmony_ci		}
2548c2ecf20Sopenharmony_ci		writeccr(i2c, CCR_MEN);
2558c2ecf20Sopenharmony_ci	}
2568c2ecf20Sopenharmony_ci}
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC_MPC52xx) || defined(CONFIG_PPC_MPC512x)
2598c2ecf20Sopenharmony_cistatic const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = {
2608c2ecf20Sopenharmony_ci	{20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23},
2618c2ecf20Sopenharmony_ci	{28, 0x24}, {30, 0x01}, {32, 0x25}, {34, 0x02},
2628c2ecf20Sopenharmony_ci	{36, 0x26}, {40, 0x27}, {44, 0x04}, {48, 0x28},
2638c2ecf20Sopenharmony_ci	{52, 0x63}, {56, 0x29}, {60, 0x41}, {64, 0x2a},
2648c2ecf20Sopenharmony_ci	{68, 0x07}, {72, 0x2b}, {80, 0x2c}, {88, 0x09},
2658c2ecf20Sopenharmony_ci	{96, 0x2d}, {104, 0x0a}, {112, 0x2e}, {120, 0x81},
2668c2ecf20Sopenharmony_ci	{128, 0x2f}, {136, 0x47}, {144, 0x0c}, {160, 0x30},
2678c2ecf20Sopenharmony_ci	{176, 0x49}, {192, 0x31}, {208, 0x4a}, {224, 0x32},
2688c2ecf20Sopenharmony_ci	{240, 0x0f}, {256, 0x33}, {272, 0x87}, {288, 0x10},
2698c2ecf20Sopenharmony_ci	{320, 0x34}, {352, 0x89}, {384, 0x35}, {416, 0x8a},
2708c2ecf20Sopenharmony_ci	{448, 0x36}, {480, 0x13}, {512, 0x37}, {576, 0x14},
2718c2ecf20Sopenharmony_ci	{640, 0x38}, {768, 0x39}, {896, 0x3a}, {960, 0x17},
2728c2ecf20Sopenharmony_ci	{1024, 0x3b}, {1152, 0x18}, {1280, 0x3c}, {1536, 0x3d},
2738c2ecf20Sopenharmony_ci	{1792, 0x3e}, {1920, 0x1b}, {2048, 0x3f}, {2304, 0x1c},
2748c2ecf20Sopenharmony_ci	{2560, 0x1d}, {3072, 0x1e}, {3584, 0x7e}, {3840, 0x1f},
2758c2ecf20Sopenharmony_ci	{4096, 0x7f}, {4608, 0x5c}, {5120, 0x5d}, {6144, 0x5e},
2768c2ecf20Sopenharmony_ci	{7168, 0xbe}, {7680, 0x5f}, {8192, 0xbf}, {9216, 0x9c},
2778c2ecf20Sopenharmony_ci	{10240, 0x9d}, {12288, 0x9e}, {15360, 0x9f}
2788c2ecf20Sopenharmony_ci};
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistatic int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,
2818c2ecf20Sopenharmony_ci					  u32 *real_clk)
2828c2ecf20Sopenharmony_ci{
2838c2ecf20Sopenharmony_ci	const struct mpc_i2c_divider *div = NULL;
2848c2ecf20Sopenharmony_ci	unsigned int pvr = mfspr(SPRN_PVR);
2858c2ecf20Sopenharmony_ci	u32 divider;
2868c2ecf20Sopenharmony_ci	int i;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	if (clock == MPC_I2C_CLOCK_LEGACY) {
2898c2ecf20Sopenharmony_ci		/* see below - default fdr = 0x3f -> div = 2048 */
2908c2ecf20Sopenharmony_ci		*real_clk = mpc5xxx_get_bus_frequency(node) / 2048;
2918c2ecf20Sopenharmony_ci		return -EINVAL;
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	/* Determine divider value */
2958c2ecf20Sopenharmony_ci	divider = mpc5xxx_get_bus_frequency(node) / clock;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	/*
2988c2ecf20Sopenharmony_ci	 * We want to choose an FDR/DFSR that generates an I2C bus speed that
2998c2ecf20Sopenharmony_ci	 * is equal to or lower than the requested speed.
3008c2ecf20Sopenharmony_ci	 */
3018c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(mpc_i2c_dividers_52xx); i++) {
3028c2ecf20Sopenharmony_ci		div = &mpc_i2c_dividers_52xx[i];
3038c2ecf20Sopenharmony_ci		/* Old MPC5200 rev A CPUs do not support the high bits */
3048c2ecf20Sopenharmony_ci		if (div->fdr & 0xc0 && pvr == 0x80822011)
3058c2ecf20Sopenharmony_ci			continue;
3068c2ecf20Sopenharmony_ci		if (div->divider >= divider)
3078c2ecf20Sopenharmony_ci			break;
3088c2ecf20Sopenharmony_ci	}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	*real_clk = mpc5xxx_get_bus_frequency(node) / div->divider;
3118c2ecf20Sopenharmony_ci	return (int)div->fdr;
3128c2ecf20Sopenharmony_ci}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_cistatic void mpc_i2c_setup_52xx(struct device_node *node,
3158c2ecf20Sopenharmony_ci					 struct mpc_i2c *i2c,
3168c2ecf20Sopenharmony_ci					 u32 clock)
3178c2ecf20Sopenharmony_ci{
3188c2ecf20Sopenharmony_ci	int ret, fdr;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	if (clock == MPC_I2C_CLOCK_PRESERVE) {
3218c2ecf20Sopenharmony_ci		dev_dbg(i2c->dev, "using fdr %d\n",
3228c2ecf20Sopenharmony_ci			readb(i2c->base + MPC_I2C_FDR));
3238c2ecf20Sopenharmony_ci		return;
3248c2ecf20Sopenharmony_ci	}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	ret = mpc_i2c_get_fdr_52xx(node, clock, &i2c->real_clk);
3278c2ecf20Sopenharmony_ci	fdr = (ret >= 0) ? ret : 0x3f; /* backward compatibility */
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	writeb(fdr & 0xff, i2c->base + MPC_I2C_FDR);
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	if (ret >= 0)
3328c2ecf20Sopenharmony_ci		dev_info(i2c->dev, "clock %u Hz (fdr=%d)\n", i2c->real_clk,
3338c2ecf20Sopenharmony_ci			 fdr);
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci#else /* !(CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x) */
3368c2ecf20Sopenharmony_cistatic void mpc_i2c_setup_52xx(struct device_node *node,
3378c2ecf20Sopenharmony_ci					 struct mpc_i2c *i2c,
3388c2ecf20Sopenharmony_ci					 u32 clock)
3398c2ecf20Sopenharmony_ci{
3408c2ecf20Sopenharmony_ci}
3418c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x */
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_MPC512x
3448c2ecf20Sopenharmony_cistatic void mpc_i2c_setup_512x(struct device_node *node,
3458c2ecf20Sopenharmony_ci					 struct mpc_i2c *i2c,
3468c2ecf20Sopenharmony_ci					 u32 clock)
3478c2ecf20Sopenharmony_ci{
3488c2ecf20Sopenharmony_ci	struct device_node *node_ctrl;
3498c2ecf20Sopenharmony_ci	void __iomem *ctrl;
3508c2ecf20Sopenharmony_ci	const u32 *pval;
3518c2ecf20Sopenharmony_ci	u32 idx;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	/* Enable I2C interrupts for mpc5121 */
3548c2ecf20Sopenharmony_ci	node_ctrl = of_find_compatible_node(NULL, NULL,
3558c2ecf20Sopenharmony_ci					    "fsl,mpc5121-i2c-ctrl");
3568c2ecf20Sopenharmony_ci	if (node_ctrl) {
3578c2ecf20Sopenharmony_ci		ctrl = of_iomap(node_ctrl, 0);
3588c2ecf20Sopenharmony_ci		if (ctrl) {
3598c2ecf20Sopenharmony_ci			/* Interrupt enable bits for i2c-0/1/2: bit 24/26/28 */
3608c2ecf20Sopenharmony_ci			pval = of_get_property(node, "reg", NULL);
3618c2ecf20Sopenharmony_ci			idx = (*pval & 0xff) / 0x20;
3628c2ecf20Sopenharmony_ci			setbits32(ctrl, 1 << (24 + idx * 2));
3638c2ecf20Sopenharmony_ci			iounmap(ctrl);
3648c2ecf20Sopenharmony_ci		}
3658c2ecf20Sopenharmony_ci		of_node_put(node_ctrl);
3668c2ecf20Sopenharmony_ci	}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	/* The clock setup for the 52xx works also fine for the 512x */
3698c2ecf20Sopenharmony_ci	mpc_i2c_setup_52xx(node, i2c, clock);
3708c2ecf20Sopenharmony_ci}
3718c2ecf20Sopenharmony_ci#else /* CONFIG_PPC_MPC512x */
3728c2ecf20Sopenharmony_cistatic void mpc_i2c_setup_512x(struct device_node *node,
3738c2ecf20Sopenharmony_ci					 struct mpc_i2c *i2c,
3748c2ecf20Sopenharmony_ci					 u32 clock)
3758c2ecf20Sopenharmony_ci{
3768c2ecf20Sopenharmony_ci}
3778c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_MPC512x */
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_SOC
3808c2ecf20Sopenharmony_cistatic const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = {
3818c2ecf20Sopenharmony_ci	{160, 0x0120}, {192, 0x0121}, {224, 0x0122}, {256, 0x0123},
3828c2ecf20Sopenharmony_ci	{288, 0x0100}, {320, 0x0101}, {352, 0x0601}, {384, 0x0102},
3838c2ecf20Sopenharmony_ci	{416, 0x0602}, {448, 0x0126}, {480, 0x0103}, {512, 0x0127},
3848c2ecf20Sopenharmony_ci	{544, 0x0b03}, {576, 0x0104}, {608, 0x1603}, {640, 0x0105},
3858c2ecf20Sopenharmony_ci	{672, 0x2003}, {704, 0x0b05}, {736, 0x2b03}, {768, 0x0106},
3868c2ecf20Sopenharmony_ci	{800, 0x3603}, {832, 0x0b06}, {896, 0x012a}, {960, 0x0107},
3878c2ecf20Sopenharmony_ci	{1024, 0x012b}, {1088, 0x1607}, {1152, 0x0108}, {1216, 0x2b07},
3888c2ecf20Sopenharmony_ci	{1280, 0x0109}, {1408, 0x1609}, {1536, 0x010a}, {1664, 0x160a},
3898c2ecf20Sopenharmony_ci	{1792, 0x012e}, {1920, 0x010b}, {2048, 0x012f}, {2176, 0x2b0b},
3908c2ecf20Sopenharmony_ci	{2304, 0x010c}, {2560, 0x010d}, {2816, 0x2b0d}, {3072, 0x010e},
3918c2ecf20Sopenharmony_ci	{3328, 0x2b0e}, {3584, 0x0132}, {3840, 0x010f}, {4096, 0x0133},
3928c2ecf20Sopenharmony_ci	{4608, 0x0110}, {5120, 0x0111}, {6144, 0x0112}, {7168, 0x0136},
3938c2ecf20Sopenharmony_ci	{7680, 0x0113}, {8192, 0x0137}, {9216, 0x0114}, {10240, 0x0115},
3948c2ecf20Sopenharmony_ci	{12288, 0x0116}, {14336, 0x013a}, {15360, 0x0117}, {16384, 0x013b},
3958c2ecf20Sopenharmony_ci	{18432, 0x0118}, {20480, 0x0119}, {24576, 0x011a}, {28672, 0x013e},
3968c2ecf20Sopenharmony_ci	{30720, 0x011b}, {32768, 0x013f}, {36864, 0x011c}, {40960, 0x011d},
3978c2ecf20Sopenharmony_ci	{49152, 0x011e}, {61440, 0x011f}
3988c2ecf20Sopenharmony_ci};
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_cistatic u32 mpc_i2c_get_sec_cfg_8xxx(void)
4018c2ecf20Sopenharmony_ci{
4028c2ecf20Sopenharmony_ci	struct device_node *node;
4038c2ecf20Sopenharmony_ci	u32 __iomem *reg;
4048c2ecf20Sopenharmony_ci	u32 val = 0;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	node = of_find_node_by_name(NULL, "global-utilities");
4078c2ecf20Sopenharmony_ci	if (node) {
4088c2ecf20Sopenharmony_ci		const u32 *prop = of_get_property(node, "reg", NULL);
4098c2ecf20Sopenharmony_ci		if (prop) {
4108c2ecf20Sopenharmony_ci			/*
4118c2ecf20Sopenharmony_ci			 * Map and check POR Device Status Register 2
4128c2ecf20Sopenharmony_ci			 * (PORDEVSR2) at 0xE0014. Note than while MPC8533
4138c2ecf20Sopenharmony_ci			 * and MPC8544 indicate SEC frequency ratio
4148c2ecf20Sopenharmony_ci			 * configuration as bit 26 in PORDEVSR2, other MPC8xxx
4158c2ecf20Sopenharmony_ci			 * parts may store it differently or may not have it
4168c2ecf20Sopenharmony_ci			 * at all.
4178c2ecf20Sopenharmony_ci			 */
4188c2ecf20Sopenharmony_ci			reg = ioremap(get_immrbase() + *prop + 0x14, 0x4);
4198c2ecf20Sopenharmony_ci			if (!reg)
4208c2ecf20Sopenharmony_ci				printk(KERN_ERR
4218c2ecf20Sopenharmony_ci				       "Error: couldn't map PORDEVSR2\n");
4228c2ecf20Sopenharmony_ci			else
4238c2ecf20Sopenharmony_ci				val = in_be32(reg) & 0x00000020; /* sec-cfg */
4248c2ecf20Sopenharmony_ci			iounmap(reg);
4258c2ecf20Sopenharmony_ci		}
4268c2ecf20Sopenharmony_ci	}
4278c2ecf20Sopenharmony_ci	of_node_put(node);
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	return val;
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistatic u32 mpc_i2c_get_prescaler_8xxx(void)
4338c2ecf20Sopenharmony_ci{
4348c2ecf20Sopenharmony_ci	/*
4358c2ecf20Sopenharmony_ci	 * According to the AN2919 all MPC824x have prescaler 1, while MPC83xx
4368c2ecf20Sopenharmony_ci	 * may have prescaler 1, 2, or 3, depending on the power-on
4378c2ecf20Sopenharmony_ci	 * configuration.
4388c2ecf20Sopenharmony_ci	 */
4398c2ecf20Sopenharmony_ci	u32 prescaler = 1;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	/* mpc85xx */
4428c2ecf20Sopenharmony_ci	if (pvr_version_is(PVR_VER_E500V1) || pvr_version_is(PVR_VER_E500V2)
4438c2ecf20Sopenharmony_ci		|| pvr_version_is(PVR_VER_E500MC)
4448c2ecf20Sopenharmony_ci		|| pvr_version_is(PVR_VER_E5500)
4458c2ecf20Sopenharmony_ci		|| pvr_version_is(PVR_VER_E6500)) {
4468c2ecf20Sopenharmony_ci		unsigned int svr = mfspr(SPRN_SVR);
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci		if ((SVR_SOC_VER(svr) == SVR_8540)
4498c2ecf20Sopenharmony_ci			|| (SVR_SOC_VER(svr) == SVR_8541)
4508c2ecf20Sopenharmony_ci			|| (SVR_SOC_VER(svr) == SVR_8560)
4518c2ecf20Sopenharmony_ci			|| (SVR_SOC_VER(svr) == SVR_8555)
4528c2ecf20Sopenharmony_ci			|| (SVR_SOC_VER(svr) == SVR_8610))
4538c2ecf20Sopenharmony_ci			/* the above 85xx SoCs have prescaler 1 */
4548c2ecf20Sopenharmony_ci			prescaler = 1;
4558c2ecf20Sopenharmony_ci		else if ((SVR_SOC_VER(svr) == SVR_8533)
4568c2ecf20Sopenharmony_ci			|| (SVR_SOC_VER(svr) == SVR_8544))
4578c2ecf20Sopenharmony_ci			/* the above 85xx SoCs have prescaler 3 or 2 */
4588c2ecf20Sopenharmony_ci			prescaler = mpc_i2c_get_sec_cfg_8xxx() ? 3 : 2;
4598c2ecf20Sopenharmony_ci		else
4608c2ecf20Sopenharmony_ci			/* all the other 85xx have prescaler 2 */
4618c2ecf20Sopenharmony_ci			prescaler = 2;
4628c2ecf20Sopenharmony_ci	}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	return prescaler;
4658c2ecf20Sopenharmony_ci}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_cistatic int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
4688c2ecf20Sopenharmony_ci					  u32 *real_clk)
4698c2ecf20Sopenharmony_ci{
4708c2ecf20Sopenharmony_ci	const struct mpc_i2c_divider *div = NULL;
4718c2ecf20Sopenharmony_ci	u32 prescaler = mpc_i2c_get_prescaler_8xxx();
4728c2ecf20Sopenharmony_ci	u32 divider;
4738c2ecf20Sopenharmony_ci	int i;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	if (clock == MPC_I2C_CLOCK_LEGACY) {
4768c2ecf20Sopenharmony_ci		/* see below - default fdr = 0x1031 -> div = 16 * 3072 */
4778c2ecf20Sopenharmony_ci		*real_clk = fsl_get_sys_freq() / prescaler / (16 * 3072);
4788c2ecf20Sopenharmony_ci		return -EINVAL;
4798c2ecf20Sopenharmony_ci	}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	divider = fsl_get_sys_freq() / clock / prescaler;
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	pr_debug("I2C: src_clock=%d clock=%d divider=%d\n",
4848c2ecf20Sopenharmony_ci		 fsl_get_sys_freq(), clock, divider);
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	/*
4878c2ecf20Sopenharmony_ci	 * We want to choose an FDR/DFSR that generates an I2C bus speed that
4888c2ecf20Sopenharmony_ci	 * is equal to or lower than the requested speed.
4898c2ecf20Sopenharmony_ci	 */
4908c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(mpc_i2c_dividers_8xxx); i++) {
4918c2ecf20Sopenharmony_ci		div = &mpc_i2c_dividers_8xxx[i];
4928c2ecf20Sopenharmony_ci		if (div->divider >= divider)
4938c2ecf20Sopenharmony_ci			break;
4948c2ecf20Sopenharmony_ci	}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	*real_clk = fsl_get_sys_freq() / prescaler / div->divider;
4978c2ecf20Sopenharmony_ci	return div ? (int)div->fdr : -EINVAL;
4988c2ecf20Sopenharmony_ci}
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_cistatic void mpc_i2c_setup_8xxx(struct device_node *node,
5018c2ecf20Sopenharmony_ci					 struct mpc_i2c *i2c,
5028c2ecf20Sopenharmony_ci					 u32 clock)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	int ret, fdr;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	if (clock == MPC_I2C_CLOCK_PRESERVE) {
5078c2ecf20Sopenharmony_ci		dev_dbg(i2c->dev, "using dfsrr %d, fdr %d\n",
5088c2ecf20Sopenharmony_ci			readb(i2c->base + MPC_I2C_DFSRR),
5098c2ecf20Sopenharmony_ci			readb(i2c->base + MPC_I2C_FDR));
5108c2ecf20Sopenharmony_ci		return;
5118c2ecf20Sopenharmony_ci	}
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	ret = mpc_i2c_get_fdr_8xxx(node, clock, &i2c->real_clk);
5148c2ecf20Sopenharmony_ci	fdr = (ret >= 0) ? ret : 0x1031; /* backward compatibility */
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	writeb(fdr & 0xff, i2c->base + MPC_I2C_FDR);
5178c2ecf20Sopenharmony_ci	writeb((fdr >> 8) & 0xff, i2c->base + MPC_I2C_DFSRR);
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	if (ret >= 0)
5208c2ecf20Sopenharmony_ci		dev_info(i2c->dev, "clock %d Hz (dfsrr=%d fdr=%d)\n",
5218c2ecf20Sopenharmony_ci			 i2c->real_clk, fdr >> 8, fdr & 0xff);
5228c2ecf20Sopenharmony_ci}
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci#else /* !CONFIG_FSL_SOC */
5258c2ecf20Sopenharmony_cistatic void mpc_i2c_setup_8xxx(struct device_node *node,
5268c2ecf20Sopenharmony_ci					 struct mpc_i2c *i2c,
5278c2ecf20Sopenharmony_ci					 u32 clock)
5288c2ecf20Sopenharmony_ci{
5298c2ecf20Sopenharmony_ci}
5308c2ecf20Sopenharmony_ci#endif /* CONFIG_FSL_SOC */
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_cistatic void mpc_i2c_start(struct mpc_i2c *i2c)
5338c2ecf20Sopenharmony_ci{
5348c2ecf20Sopenharmony_ci	/* Clear arbitration */
5358c2ecf20Sopenharmony_ci	writeb(0, i2c->base + MPC_I2C_SR);
5368c2ecf20Sopenharmony_ci	/* Start with MEN */
5378c2ecf20Sopenharmony_ci	writeccr(i2c, CCR_MEN);
5388c2ecf20Sopenharmony_ci}
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_cistatic void mpc_i2c_stop(struct mpc_i2c *i2c)
5418c2ecf20Sopenharmony_ci{
5428c2ecf20Sopenharmony_ci	writeccr(i2c, CCR_MEN);
5438c2ecf20Sopenharmony_ci}
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_cistatic int mpc_write(struct mpc_i2c *i2c, int target,
5468c2ecf20Sopenharmony_ci		     const u8 *data, int length, int restart)
5478c2ecf20Sopenharmony_ci{
5488c2ecf20Sopenharmony_ci	int i, result;
5498c2ecf20Sopenharmony_ci	unsigned timeout = i2c->adap.timeout;
5508c2ecf20Sopenharmony_ci	u32 flags = restart ? CCR_RSTA : 0;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	/* Start as master */
5538c2ecf20Sopenharmony_ci	writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
5548c2ecf20Sopenharmony_ci	/* Write target byte */
5558c2ecf20Sopenharmony_ci	writeb((target << 1), i2c->base + MPC_I2C_DR);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	result = i2c_wait(i2c, timeout, 1);
5588c2ecf20Sopenharmony_ci	if (result < 0)
5598c2ecf20Sopenharmony_ci		return result;
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	for (i = 0; i < length; i++) {
5628c2ecf20Sopenharmony_ci		/* Write data byte */
5638c2ecf20Sopenharmony_ci		writeb(data[i], i2c->base + MPC_I2C_DR);
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci		result = i2c_wait(i2c, timeout, 1);
5668c2ecf20Sopenharmony_ci		if (result < 0)
5678c2ecf20Sopenharmony_ci			return result;
5688c2ecf20Sopenharmony_ci	}
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	return 0;
5718c2ecf20Sopenharmony_ci}
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_cistatic int mpc_read(struct mpc_i2c *i2c, int target,
5748c2ecf20Sopenharmony_ci		    u8 *data, int length, int restart, bool recv_len)
5758c2ecf20Sopenharmony_ci{
5768c2ecf20Sopenharmony_ci	unsigned timeout = i2c->adap.timeout;
5778c2ecf20Sopenharmony_ci	int i, result;
5788c2ecf20Sopenharmony_ci	u32 flags = restart ? CCR_RSTA : 0;
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	/* Switch to read - restart */
5818c2ecf20Sopenharmony_ci	writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
5828c2ecf20Sopenharmony_ci	/* Write target address byte - this time with the read flag set */
5838c2ecf20Sopenharmony_ci	writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	result = i2c_wait(i2c, timeout, 1);
5868c2ecf20Sopenharmony_ci	if (result < 0)
5878c2ecf20Sopenharmony_ci		return result;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	if (length) {
5908c2ecf20Sopenharmony_ci		if (length == 1 && !recv_len)
5918c2ecf20Sopenharmony_ci			writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
5928c2ecf20Sopenharmony_ci		else
5938c2ecf20Sopenharmony_ci			writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA);
5948c2ecf20Sopenharmony_ci		/* Dummy read */
5958c2ecf20Sopenharmony_ci		readb(i2c->base + MPC_I2C_DR);
5968c2ecf20Sopenharmony_ci	}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	for (i = 0; i < length; i++) {
5998c2ecf20Sopenharmony_ci		u8 byte;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci		result = i2c_wait(i2c, timeout, 0);
6028c2ecf20Sopenharmony_ci		if (result < 0)
6038c2ecf20Sopenharmony_ci			return result;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci		/*
6068c2ecf20Sopenharmony_ci		 * For block reads, we have to know the total length (1st byte)
6078c2ecf20Sopenharmony_ci		 * before we can determine if we are done.
6088c2ecf20Sopenharmony_ci		 */
6098c2ecf20Sopenharmony_ci		if (i || !recv_len) {
6108c2ecf20Sopenharmony_ci			/* Generate txack on next to last byte */
6118c2ecf20Sopenharmony_ci			if (i == length - 2)
6128c2ecf20Sopenharmony_ci				writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
6138c2ecf20Sopenharmony_ci					 | CCR_TXAK);
6148c2ecf20Sopenharmony_ci			/* Do not generate stop on last byte */
6158c2ecf20Sopenharmony_ci			if (i == length - 1)
6168c2ecf20Sopenharmony_ci				writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
6178c2ecf20Sopenharmony_ci					 | CCR_MTX);
6188c2ecf20Sopenharmony_ci		}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci		byte = readb(i2c->base + MPC_I2C_DR);
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci		/*
6238c2ecf20Sopenharmony_ci		 * Adjust length if first received byte is length.
6248c2ecf20Sopenharmony_ci		 * The length is 1 length byte plus actually data length
6258c2ecf20Sopenharmony_ci		 */
6268c2ecf20Sopenharmony_ci		if (i == 0 && recv_len) {
6278c2ecf20Sopenharmony_ci			if (byte == 0 || byte > I2C_SMBUS_BLOCK_MAX)
6288c2ecf20Sopenharmony_ci				return -EPROTO;
6298c2ecf20Sopenharmony_ci			length += byte;
6308c2ecf20Sopenharmony_ci			/*
6318c2ecf20Sopenharmony_ci			 * For block reads, generate txack here if data length
6328c2ecf20Sopenharmony_ci			 * is 1 byte (total length is 2 bytes).
6338c2ecf20Sopenharmony_ci			 */
6348c2ecf20Sopenharmony_ci			if (length == 2)
6358c2ecf20Sopenharmony_ci				writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
6368c2ecf20Sopenharmony_ci					 | CCR_TXAK);
6378c2ecf20Sopenharmony_ci		}
6388c2ecf20Sopenharmony_ci		data[i] = byte;
6398c2ecf20Sopenharmony_ci	}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	return length;
6428c2ecf20Sopenharmony_ci}
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_cistatic int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
6458c2ecf20Sopenharmony_ci{
6468c2ecf20Sopenharmony_ci	struct i2c_msg *pmsg;
6478c2ecf20Sopenharmony_ci	int i;
6488c2ecf20Sopenharmony_ci	int ret = 0;
6498c2ecf20Sopenharmony_ci	unsigned long orig_jiffies = jiffies;
6508c2ecf20Sopenharmony_ci	struct mpc_i2c *i2c = i2c_get_adapdata(adap);
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	mpc_i2c_start(i2c);
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	/* Allow bus up to 1s to become not busy */
6558c2ecf20Sopenharmony_ci	while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) {
6568c2ecf20Sopenharmony_ci		if (signal_pending(current)) {
6578c2ecf20Sopenharmony_ci			dev_dbg(i2c->dev, "Interrupted\n");
6588c2ecf20Sopenharmony_ci			writeccr(i2c, 0);
6598c2ecf20Sopenharmony_ci			return -EINTR;
6608c2ecf20Sopenharmony_ci		}
6618c2ecf20Sopenharmony_ci		if (time_after(jiffies, orig_jiffies + HZ)) {
6628c2ecf20Sopenharmony_ci			u8 status = readb(i2c->base + MPC_I2C_SR);
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci			dev_dbg(i2c->dev, "timeout\n");
6658c2ecf20Sopenharmony_ci			if ((status & (CSR_MCF | CSR_MBB | CSR_RXAK)) != 0) {
6668c2ecf20Sopenharmony_ci				writeb(status & ~CSR_MAL,
6678c2ecf20Sopenharmony_ci				       i2c->base + MPC_I2C_SR);
6688c2ecf20Sopenharmony_ci				i2c_recover_bus(&i2c->adap);
6698c2ecf20Sopenharmony_ci			}
6708c2ecf20Sopenharmony_ci			return -EIO;
6718c2ecf20Sopenharmony_ci		}
6728c2ecf20Sopenharmony_ci		schedule();
6738c2ecf20Sopenharmony_ci	}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	for (i = 0; ret >= 0 && i < num; i++) {
6768c2ecf20Sopenharmony_ci		pmsg = &msgs[i];
6778c2ecf20Sopenharmony_ci		dev_dbg(i2c->dev,
6788c2ecf20Sopenharmony_ci			"Doing %s %d bytes to 0x%02x - %d of %d messages\n",
6798c2ecf20Sopenharmony_ci			pmsg->flags & I2C_M_RD ? "read" : "write",
6808c2ecf20Sopenharmony_ci			pmsg->len, pmsg->addr, i + 1, num);
6818c2ecf20Sopenharmony_ci		if (pmsg->flags & I2C_M_RD) {
6828c2ecf20Sopenharmony_ci			bool recv_len = pmsg->flags & I2C_M_RECV_LEN;
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci			ret = mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i,
6858c2ecf20Sopenharmony_ci				       recv_len);
6868c2ecf20Sopenharmony_ci			if (recv_len && ret > 0)
6878c2ecf20Sopenharmony_ci				pmsg->len = ret;
6888c2ecf20Sopenharmony_ci		} else {
6898c2ecf20Sopenharmony_ci			ret =
6908c2ecf20Sopenharmony_ci			    mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
6918c2ecf20Sopenharmony_ci		}
6928c2ecf20Sopenharmony_ci	}
6938c2ecf20Sopenharmony_ci	mpc_i2c_stop(i2c); /* Initiate STOP */
6948c2ecf20Sopenharmony_ci	orig_jiffies = jiffies;
6958c2ecf20Sopenharmony_ci	/* Wait until STOP is seen, allow up to 1 s */
6968c2ecf20Sopenharmony_ci	while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) {
6978c2ecf20Sopenharmony_ci		if (time_after(jiffies, orig_jiffies + HZ)) {
6988c2ecf20Sopenharmony_ci			u8 status = readb(i2c->base + MPC_I2C_SR);
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci			dev_dbg(i2c->dev, "timeout\n");
7018c2ecf20Sopenharmony_ci			if ((status & (CSR_MCF | CSR_MBB | CSR_RXAK)) != 0) {
7028c2ecf20Sopenharmony_ci				writeb(status & ~CSR_MAL,
7038c2ecf20Sopenharmony_ci				       i2c->base + MPC_I2C_SR);
7048c2ecf20Sopenharmony_ci				i2c_recover_bus(&i2c->adap);
7058c2ecf20Sopenharmony_ci			}
7068c2ecf20Sopenharmony_ci			return -EIO;
7078c2ecf20Sopenharmony_ci		}
7088c2ecf20Sopenharmony_ci		cond_resched();
7098c2ecf20Sopenharmony_ci	}
7108c2ecf20Sopenharmony_ci	return (ret < 0) ? ret : num;
7118c2ecf20Sopenharmony_ci}
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_cistatic u32 mpc_functionality(struct i2c_adapter *adap)
7148c2ecf20Sopenharmony_ci{
7158c2ecf20Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
7168c2ecf20Sopenharmony_ci	  | I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
7178c2ecf20Sopenharmony_ci}
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_cistatic int fsl_i2c_bus_recovery(struct i2c_adapter *adap)
7208c2ecf20Sopenharmony_ci{
7218c2ecf20Sopenharmony_ci	struct mpc_i2c *i2c = i2c_get_adapdata(adap);
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	if (i2c->has_errata_A004447)
7248c2ecf20Sopenharmony_ci		mpc_i2c_fixup_A004447(i2c);
7258c2ecf20Sopenharmony_ci	else
7268c2ecf20Sopenharmony_ci		mpc_i2c_fixup(i2c);
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	return 0;
7298c2ecf20Sopenharmony_ci}
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_cistatic const struct i2c_algorithm mpc_algo = {
7328c2ecf20Sopenharmony_ci	.master_xfer = mpc_xfer,
7338c2ecf20Sopenharmony_ci	.functionality = mpc_functionality,
7348c2ecf20Sopenharmony_ci};
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_cistatic struct i2c_adapter mpc_ops = {
7378c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
7388c2ecf20Sopenharmony_ci	.algo = &mpc_algo,
7398c2ecf20Sopenharmony_ci	.timeout = HZ,
7408c2ecf20Sopenharmony_ci};
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_cistatic struct i2c_bus_recovery_info fsl_i2c_recovery_info = {
7438c2ecf20Sopenharmony_ci	.recover_bus = fsl_i2c_bus_recovery,
7448c2ecf20Sopenharmony_ci};
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_cistatic const struct of_device_id mpc_i2c_of_match[];
7478c2ecf20Sopenharmony_cistatic int fsl_i2c_probe(struct platform_device *op)
7488c2ecf20Sopenharmony_ci{
7498c2ecf20Sopenharmony_ci	const struct of_device_id *match;
7508c2ecf20Sopenharmony_ci	struct mpc_i2c *i2c;
7518c2ecf20Sopenharmony_ci	const u32 *prop;
7528c2ecf20Sopenharmony_ci	u32 clock = MPC_I2C_CLOCK_LEGACY;
7538c2ecf20Sopenharmony_ci	int result = 0;
7548c2ecf20Sopenharmony_ci	int plen;
7558c2ecf20Sopenharmony_ci	struct resource res;
7568c2ecf20Sopenharmony_ci	struct clk *clk;
7578c2ecf20Sopenharmony_ci	int err;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	match = of_match_device(mpc_i2c_of_match, &op->dev);
7608c2ecf20Sopenharmony_ci	if (!match)
7618c2ecf20Sopenharmony_ci		return -EINVAL;
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci	i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
7648c2ecf20Sopenharmony_ci	if (!i2c)
7658c2ecf20Sopenharmony_ci		return -ENOMEM;
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	i2c->dev = &op->dev; /* for debug and error output */
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	init_waitqueue_head(&i2c->queue);
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	i2c->base = of_iomap(op->dev.of_node, 0);
7728c2ecf20Sopenharmony_ci	if (!i2c->base) {
7738c2ecf20Sopenharmony_ci		dev_err(i2c->dev, "failed to map controller\n");
7748c2ecf20Sopenharmony_ci		result = -ENOMEM;
7758c2ecf20Sopenharmony_ci		goto fail_map;
7768c2ecf20Sopenharmony_ci	}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	i2c->irq = irq_of_parse_and_map(op->dev.of_node, 0);
7798c2ecf20Sopenharmony_ci	if (i2c->irq) { /* no i2c->irq implies polling */
7808c2ecf20Sopenharmony_ci		result = request_irq(i2c->irq, mpc_i2c_isr,
7818c2ecf20Sopenharmony_ci				     IRQF_SHARED, "i2c-mpc", i2c);
7828c2ecf20Sopenharmony_ci		if (result < 0) {
7838c2ecf20Sopenharmony_ci			dev_err(i2c->dev, "failed to attach interrupt\n");
7848c2ecf20Sopenharmony_ci			goto fail_request;
7858c2ecf20Sopenharmony_ci		}
7868c2ecf20Sopenharmony_ci	}
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	/*
7898c2ecf20Sopenharmony_ci	 * enable clock for the I2C peripheral (non fatal),
7908c2ecf20Sopenharmony_ci	 * keep a reference upon successful allocation
7918c2ecf20Sopenharmony_ci	 */
7928c2ecf20Sopenharmony_ci	clk = devm_clk_get(&op->dev, NULL);
7938c2ecf20Sopenharmony_ci	if (!IS_ERR(clk)) {
7948c2ecf20Sopenharmony_ci		err = clk_prepare_enable(clk);
7958c2ecf20Sopenharmony_ci		if (err) {
7968c2ecf20Sopenharmony_ci			dev_err(&op->dev, "failed to enable clock\n");
7978c2ecf20Sopenharmony_ci			goto fail_request;
7988c2ecf20Sopenharmony_ci		} else {
7998c2ecf20Sopenharmony_ci			i2c->clk_per = clk;
8008c2ecf20Sopenharmony_ci		}
8018c2ecf20Sopenharmony_ci	}
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	if (of_property_read_bool(op->dev.of_node, "fsl,preserve-clocking")) {
8048c2ecf20Sopenharmony_ci		clock = MPC_I2C_CLOCK_PRESERVE;
8058c2ecf20Sopenharmony_ci	} else {
8068c2ecf20Sopenharmony_ci		prop = of_get_property(op->dev.of_node, "clock-frequency",
8078c2ecf20Sopenharmony_ci					&plen);
8088c2ecf20Sopenharmony_ci		if (prop && plen == sizeof(u32))
8098c2ecf20Sopenharmony_ci			clock = *prop;
8108c2ecf20Sopenharmony_ci	}
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	if (match->data) {
8138c2ecf20Sopenharmony_ci		const struct mpc_i2c_data *data = match->data;
8148c2ecf20Sopenharmony_ci		data->setup(op->dev.of_node, i2c, clock);
8158c2ecf20Sopenharmony_ci	} else {
8168c2ecf20Sopenharmony_ci		/* Backwards compatibility */
8178c2ecf20Sopenharmony_ci		if (of_get_property(op->dev.of_node, "dfsrr", NULL))
8188c2ecf20Sopenharmony_ci			mpc_i2c_setup_8xxx(op->dev.of_node, i2c, clock);
8198c2ecf20Sopenharmony_ci	}
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	prop = of_get_property(op->dev.of_node, "fsl,timeout", &plen);
8228c2ecf20Sopenharmony_ci	if (prop && plen == sizeof(u32)) {
8238c2ecf20Sopenharmony_ci		mpc_ops.timeout = *prop * HZ / 1000000;
8248c2ecf20Sopenharmony_ci		if (mpc_ops.timeout < 5)
8258c2ecf20Sopenharmony_ci			mpc_ops.timeout = 5;
8268c2ecf20Sopenharmony_ci	}
8278c2ecf20Sopenharmony_ci	dev_info(i2c->dev, "timeout %u us\n", mpc_ops.timeout * 1000000 / HZ);
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	platform_set_drvdata(op, i2c);
8308c2ecf20Sopenharmony_ci	if (of_property_read_bool(op->dev.of_node, "fsl,i2c-erratum-a004447"))
8318c2ecf20Sopenharmony_ci		i2c->has_errata_A004447 = true;
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	i2c->adap = mpc_ops;
8348c2ecf20Sopenharmony_ci	of_address_to_resource(op->dev.of_node, 0, &res);
8358c2ecf20Sopenharmony_ci	scnprintf(i2c->adap.name, sizeof(i2c->adap.name),
8368c2ecf20Sopenharmony_ci		  "MPC adapter at 0x%llx", (unsigned long long)res.start);
8378c2ecf20Sopenharmony_ci	i2c_set_adapdata(&i2c->adap, i2c);
8388c2ecf20Sopenharmony_ci	i2c->adap.dev.parent = &op->dev;
8398c2ecf20Sopenharmony_ci	i2c->adap.dev.of_node = of_node_get(op->dev.of_node);
8408c2ecf20Sopenharmony_ci	i2c->adap.bus_recovery_info = &fsl_i2c_recovery_info;
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	result = i2c_add_adapter(&i2c->adap);
8438c2ecf20Sopenharmony_ci	if (result < 0)
8448c2ecf20Sopenharmony_ci		goto fail_add;
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	return result;
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci fail_add:
8498c2ecf20Sopenharmony_ci	if (i2c->clk_per)
8508c2ecf20Sopenharmony_ci		clk_disable_unprepare(i2c->clk_per);
8518c2ecf20Sopenharmony_ci	free_irq(i2c->irq, i2c);
8528c2ecf20Sopenharmony_ci fail_request:
8538c2ecf20Sopenharmony_ci	irq_dispose_mapping(i2c->irq);
8548c2ecf20Sopenharmony_ci	iounmap(i2c->base);
8558c2ecf20Sopenharmony_ci fail_map:
8568c2ecf20Sopenharmony_ci	kfree(i2c);
8578c2ecf20Sopenharmony_ci	return result;
8588c2ecf20Sopenharmony_ci};
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_cistatic int fsl_i2c_remove(struct platform_device *op)
8618c2ecf20Sopenharmony_ci{
8628c2ecf20Sopenharmony_ci	struct mpc_i2c *i2c = platform_get_drvdata(op);
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	i2c_del_adapter(&i2c->adap);
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	if (i2c->clk_per)
8678c2ecf20Sopenharmony_ci		clk_disable_unprepare(i2c->clk_per);
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	if (i2c->irq)
8708c2ecf20Sopenharmony_ci		free_irq(i2c->irq, i2c);
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	irq_dispose_mapping(i2c->irq);
8738c2ecf20Sopenharmony_ci	iounmap(i2c->base);
8748c2ecf20Sopenharmony_ci	kfree(i2c);
8758c2ecf20Sopenharmony_ci	return 0;
8768c2ecf20Sopenharmony_ci};
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
8798c2ecf20Sopenharmony_cistatic int mpc_i2c_suspend(struct device *dev)
8808c2ecf20Sopenharmony_ci{
8818c2ecf20Sopenharmony_ci	struct mpc_i2c *i2c = dev_get_drvdata(dev);
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	i2c->fdr = readb(i2c->base + MPC_I2C_FDR);
8848c2ecf20Sopenharmony_ci	i2c->dfsrr = readb(i2c->base + MPC_I2C_DFSRR);
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	return 0;
8878c2ecf20Sopenharmony_ci}
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_cistatic int mpc_i2c_resume(struct device *dev)
8908c2ecf20Sopenharmony_ci{
8918c2ecf20Sopenharmony_ci	struct mpc_i2c *i2c = dev_get_drvdata(dev);
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	writeb(i2c->fdr, i2c->base + MPC_I2C_FDR);
8948c2ecf20Sopenharmony_ci	writeb(i2c->dfsrr, i2c->base + MPC_I2C_DFSRR);
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	return 0;
8978c2ecf20Sopenharmony_ci}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume);
9008c2ecf20Sopenharmony_ci#define MPC_I2C_PM_OPS	(&mpc_i2c_pm_ops)
9018c2ecf20Sopenharmony_ci#else
9028c2ecf20Sopenharmony_ci#define MPC_I2C_PM_OPS	NULL
9038c2ecf20Sopenharmony_ci#endif
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_cistatic const struct mpc_i2c_data mpc_i2c_data_512x = {
9068c2ecf20Sopenharmony_ci	.setup = mpc_i2c_setup_512x,
9078c2ecf20Sopenharmony_ci};
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_cistatic const struct mpc_i2c_data mpc_i2c_data_52xx = {
9108c2ecf20Sopenharmony_ci	.setup = mpc_i2c_setup_52xx,
9118c2ecf20Sopenharmony_ci};
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_cistatic const struct mpc_i2c_data mpc_i2c_data_8313 = {
9148c2ecf20Sopenharmony_ci	.setup = mpc_i2c_setup_8xxx,
9158c2ecf20Sopenharmony_ci};
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_cistatic const struct mpc_i2c_data mpc_i2c_data_8543 = {
9188c2ecf20Sopenharmony_ci	.setup = mpc_i2c_setup_8xxx,
9198c2ecf20Sopenharmony_ci};
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_cistatic const struct mpc_i2c_data mpc_i2c_data_8544 = {
9228c2ecf20Sopenharmony_ci	.setup = mpc_i2c_setup_8xxx,
9238c2ecf20Sopenharmony_ci};
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_cistatic const struct of_device_id mpc_i2c_of_match[] = {
9268c2ecf20Sopenharmony_ci	{.compatible = "mpc5200-i2c", .data = &mpc_i2c_data_52xx, },
9278c2ecf20Sopenharmony_ci	{.compatible = "fsl,mpc5200b-i2c", .data = &mpc_i2c_data_52xx, },
9288c2ecf20Sopenharmony_ci	{.compatible = "fsl,mpc5200-i2c", .data = &mpc_i2c_data_52xx, },
9298c2ecf20Sopenharmony_ci	{.compatible = "fsl,mpc5121-i2c", .data = &mpc_i2c_data_512x, },
9308c2ecf20Sopenharmony_ci	{.compatible = "fsl,mpc8313-i2c", .data = &mpc_i2c_data_8313, },
9318c2ecf20Sopenharmony_ci	{.compatible = "fsl,mpc8543-i2c", .data = &mpc_i2c_data_8543, },
9328c2ecf20Sopenharmony_ci	{.compatible = "fsl,mpc8544-i2c", .data = &mpc_i2c_data_8544, },
9338c2ecf20Sopenharmony_ci	/* Backward compatibility */
9348c2ecf20Sopenharmony_ci	{.compatible = "fsl-i2c", },
9358c2ecf20Sopenharmony_ci	{},
9368c2ecf20Sopenharmony_ci};
9378c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci/* Structure for a device driver */
9408c2ecf20Sopenharmony_cistatic struct platform_driver mpc_i2c_driver = {
9418c2ecf20Sopenharmony_ci	.probe		= fsl_i2c_probe,
9428c2ecf20Sopenharmony_ci	.remove		= fsl_i2c_remove,
9438c2ecf20Sopenharmony_ci	.driver = {
9448c2ecf20Sopenharmony_ci		.name = DRV_NAME,
9458c2ecf20Sopenharmony_ci		.of_match_table = mpc_i2c_of_match,
9468c2ecf20Sopenharmony_ci		.pm = MPC_I2C_PM_OPS,
9478c2ecf20Sopenharmony_ci	},
9488c2ecf20Sopenharmony_ci};
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_cimodule_platform_driver(mpc_i2c_driver);
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ciMODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
9538c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("I2C-Bus adapter for MPC107 bridge and "
9548c2ecf20Sopenharmony_ci		   "MPC824x/83xx/85xx/86xx/512x/52xx processors");
9558c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
956