162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Freescale CPM1/CPM2 I2C interface.
462306a36Sopenharmony_ci * Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * moved into proper i2c interface;
762306a36Sopenharmony_ci * Brad Parker (brad@heeltoe.com)
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Parts from dbox2_i2c.c (cvs.tuxbox.org)
1062306a36Sopenharmony_ci * (C) 2000-2001 Felix Domke (tmbinc@gmx.net), Gillem (htoa@gmx.net)
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * (C) 2007 Montavista Software, Inc.
1362306a36Sopenharmony_ci * Vitaly Bordug <vitb@kernel.crashing.org>
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * Converted to of_platform_device. Renamed to i2c-cpm.c.
1662306a36Sopenharmony_ci * (C) 2007,2008 Jochen Friedrich <jochen@scram.de>
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <linux/kernel.h>
2062306a36Sopenharmony_ci#include <linux/module.h>
2162306a36Sopenharmony_ci#include <linux/delay.h>
2262306a36Sopenharmony_ci#include <linux/slab.h>
2362306a36Sopenharmony_ci#include <linux/interrupt.h>
2462306a36Sopenharmony_ci#include <linux/errno.h>
2562306a36Sopenharmony_ci#include <linux/stddef.h>
2662306a36Sopenharmony_ci#include <linux/i2c.h>
2762306a36Sopenharmony_ci#include <linux/io.h>
2862306a36Sopenharmony_ci#include <linux/dma-mapping.h>
2962306a36Sopenharmony_ci#include <linux/of.h>
3062306a36Sopenharmony_ci#include <linux/of_address.h>
3162306a36Sopenharmony_ci#include <linux/of_irq.h>
3262306a36Sopenharmony_ci#include <linux/platform_device.h>
3362306a36Sopenharmony_ci#include <sysdev/fsl_soc.h>
3462306a36Sopenharmony_ci#include <asm/cpm.h>
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci/* Try to define this if you have an older CPU (earlier than rev D4) */
3762306a36Sopenharmony_ci/* However, better use a GPIO based bitbang driver in this case :/   */
3862306a36Sopenharmony_ci#undef	I2C_CHIP_ERRATA
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define CPM_MAX_READ    513
4162306a36Sopenharmony_ci#define CPM_MAXBD       4
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#define I2C_EB			(0x10) /* Big endian mode */
4462306a36Sopenharmony_ci#define I2C_EB_CPM2		(0x30) /* Big endian mode, memory snoop */
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#define DPRAM_BASE		((u8 __iomem __force *)cpm_muram_addr(0))
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/* I2C parameter RAM. */
4962306a36Sopenharmony_cistruct i2c_ram {
5062306a36Sopenharmony_ci	ushort  rbase;		/* Rx Buffer descriptor base address */
5162306a36Sopenharmony_ci	ushort  tbase;		/* Tx Buffer descriptor base address */
5262306a36Sopenharmony_ci	u_char  rfcr;		/* Rx function code */
5362306a36Sopenharmony_ci	u_char  tfcr;		/* Tx function code */
5462306a36Sopenharmony_ci	ushort  mrblr;		/* Max receive buffer length */
5562306a36Sopenharmony_ci	uint    rstate;		/* Internal */
5662306a36Sopenharmony_ci	uint    rdp;		/* Internal */
5762306a36Sopenharmony_ci	ushort  rbptr;		/* Rx Buffer descriptor pointer */
5862306a36Sopenharmony_ci	ushort  rbc;		/* Internal */
5962306a36Sopenharmony_ci	uint    rxtmp;		/* Internal */
6062306a36Sopenharmony_ci	uint    tstate;		/* Internal */
6162306a36Sopenharmony_ci	uint    tdp;		/* Internal */
6262306a36Sopenharmony_ci	ushort  tbptr;		/* Tx Buffer descriptor pointer */
6362306a36Sopenharmony_ci	ushort  tbc;		/* Internal */
6462306a36Sopenharmony_ci	uint    txtmp;		/* Internal */
6562306a36Sopenharmony_ci	char    res1[4];	/* Reserved */
6662306a36Sopenharmony_ci	ushort  rpbase;		/* Relocation pointer */
6762306a36Sopenharmony_ci	char    res2[2];	/* Reserved */
6862306a36Sopenharmony_ci	/* The following elements are only for CPM2 */
6962306a36Sopenharmony_ci	char    res3[4];	/* Reserved */
7062306a36Sopenharmony_ci	uint    sdmatmp;	/* Internal */
7162306a36Sopenharmony_ci};
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define I2COM_START	0x80
7462306a36Sopenharmony_ci#define I2COM_MASTER	0x01
7562306a36Sopenharmony_ci#define I2CER_TXE	0x10
7662306a36Sopenharmony_ci#define I2CER_BUSY	0x04
7762306a36Sopenharmony_ci#define I2CER_TXB	0x02
7862306a36Sopenharmony_ci#define I2CER_RXB	0x01
7962306a36Sopenharmony_ci#define I2MOD_EN	0x01
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci/* I2C Registers */
8262306a36Sopenharmony_cistruct i2c_reg {
8362306a36Sopenharmony_ci	u8	i2mod;
8462306a36Sopenharmony_ci	u8	res1[3];
8562306a36Sopenharmony_ci	u8	i2add;
8662306a36Sopenharmony_ci	u8	res2[3];
8762306a36Sopenharmony_ci	u8	i2brg;
8862306a36Sopenharmony_ci	u8	res3[3];
8962306a36Sopenharmony_ci	u8	i2com;
9062306a36Sopenharmony_ci	u8	res4[3];
9162306a36Sopenharmony_ci	u8	i2cer;
9262306a36Sopenharmony_ci	u8	res5[3];
9362306a36Sopenharmony_ci	u8	i2cmr;
9462306a36Sopenharmony_ci};
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistruct cpm_i2c {
9762306a36Sopenharmony_ci	char *base;
9862306a36Sopenharmony_ci	struct platform_device *ofdev;
9962306a36Sopenharmony_ci	struct i2c_adapter adap;
10062306a36Sopenharmony_ci	uint dp_addr;
10162306a36Sopenharmony_ci	int version; /* CPM1=1, CPM2=2 */
10262306a36Sopenharmony_ci	int irq;
10362306a36Sopenharmony_ci	int cp_command;
10462306a36Sopenharmony_ci	int freq;
10562306a36Sopenharmony_ci	struct i2c_reg __iomem *i2c_reg;
10662306a36Sopenharmony_ci	struct i2c_ram __iomem *i2c_ram;
10762306a36Sopenharmony_ci	u16 i2c_addr;
10862306a36Sopenharmony_ci	wait_queue_head_t i2c_wait;
10962306a36Sopenharmony_ci	cbd_t __iomem *tbase;
11062306a36Sopenharmony_ci	cbd_t __iomem *rbase;
11162306a36Sopenharmony_ci	u_char *txbuf[CPM_MAXBD];
11262306a36Sopenharmony_ci	u_char *rxbuf[CPM_MAXBD];
11362306a36Sopenharmony_ci	dma_addr_t txdma[CPM_MAXBD];
11462306a36Sopenharmony_ci	dma_addr_t rxdma[CPM_MAXBD];
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic irqreturn_t cpm_i2c_interrupt(int irq, void *dev_id)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	struct cpm_i2c *cpm;
12062306a36Sopenharmony_ci	struct i2c_reg __iomem *i2c_reg;
12162306a36Sopenharmony_ci	struct i2c_adapter *adap = dev_id;
12262306a36Sopenharmony_ci	int i;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	cpm = i2c_get_adapdata(dev_id);
12562306a36Sopenharmony_ci	i2c_reg = cpm->i2c_reg;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	/* Clear interrupt. */
12862306a36Sopenharmony_ci	i = in_8(&i2c_reg->i2cer);
12962306a36Sopenharmony_ci	out_8(&i2c_reg->i2cer, i);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	dev_dbg(&adap->dev, "Interrupt: %x\n", i);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	wake_up(&cpm->i2c_wait);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	return i ? IRQ_HANDLED : IRQ_NONE;
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic void cpm_reset_i2c_params(struct cpm_i2c *cpm)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	/* Set up the I2C parameters in the parameter ram. */
14362306a36Sopenharmony_ci	out_be16(&i2c_ram->tbase, (u8 __iomem *)cpm->tbase - DPRAM_BASE);
14462306a36Sopenharmony_ci	out_be16(&i2c_ram->rbase, (u8 __iomem *)cpm->rbase - DPRAM_BASE);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	if (cpm->version == 1) {
14762306a36Sopenharmony_ci		out_8(&i2c_ram->tfcr, I2C_EB);
14862306a36Sopenharmony_ci		out_8(&i2c_ram->rfcr, I2C_EB);
14962306a36Sopenharmony_ci	} else {
15062306a36Sopenharmony_ci		out_8(&i2c_ram->tfcr, I2C_EB_CPM2);
15162306a36Sopenharmony_ci		out_8(&i2c_ram->rfcr, I2C_EB_CPM2);
15262306a36Sopenharmony_ci	}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	out_be16(&i2c_ram->mrblr, CPM_MAX_READ);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	out_be32(&i2c_ram->rstate, 0);
15762306a36Sopenharmony_ci	out_be32(&i2c_ram->rdp, 0);
15862306a36Sopenharmony_ci	out_be16(&i2c_ram->rbptr, 0);
15962306a36Sopenharmony_ci	out_be16(&i2c_ram->rbc, 0);
16062306a36Sopenharmony_ci	out_be32(&i2c_ram->rxtmp, 0);
16162306a36Sopenharmony_ci	out_be32(&i2c_ram->tstate, 0);
16262306a36Sopenharmony_ci	out_be32(&i2c_ram->tdp, 0);
16362306a36Sopenharmony_ci	out_be16(&i2c_ram->tbptr, 0);
16462306a36Sopenharmony_ci	out_be16(&i2c_ram->tbc, 0);
16562306a36Sopenharmony_ci	out_be32(&i2c_ram->txtmp, 0);
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic void cpm_i2c_force_close(struct i2c_adapter *adap)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	struct cpm_i2c *cpm = i2c_get_adapdata(adap);
17162306a36Sopenharmony_ci	struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	dev_dbg(&adap->dev, "cpm_i2c_force_close()\n");
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	cpm_command(cpm->cp_command, CPM_CR_CLOSE_RX_BD);
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	out_8(&i2c_reg->i2cmr, 0x00);	/* Disable all interrupts */
17862306a36Sopenharmony_ci	out_8(&i2c_reg->i2cer, 0xff);
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistatic void cpm_i2c_parse_message(struct i2c_adapter *adap,
18262306a36Sopenharmony_ci	struct i2c_msg *pmsg, int num, int tx, int rx)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	cbd_t __iomem *tbdf;
18562306a36Sopenharmony_ci	cbd_t __iomem *rbdf;
18662306a36Sopenharmony_ci	u_char addr;
18762306a36Sopenharmony_ci	u_char *tb;
18862306a36Sopenharmony_ci	u_char *rb;
18962306a36Sopenharmony_ci	struct cpm_i2c *cpm = i2c_get_adapdata(adap);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	tbdf = cpm->tbase + tx;
19262306a36Sopenharmony_ci	rbdf = cpm->rbase + rx;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	addr = i2c_8bit_addr_from_msg(pmsg);
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	tb = cpm->txbuf[tx];
19762306a36Sopenharmony_ci	rb = cpm->rxbuf[rx];
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	/* Align read buffer */
20062306a36Sopenharmony_ci	rb = (u_char *) (((ulong) rb + 1) & ~1);
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	tb[0] = addr;		/* Device address byte w/rw flag */
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	out_be16(&tbdf->cbd_datlen, pmsg->len + 1);
20562306a36Sopenharmony_ci	out_be16(&tbdf->cbd_sc, 0);
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	if (!(pmsg->flags & I2C_M_NOSTART))
20862306a36Sopenharmony_ci		setbits16(&tbdf->cbd_sc, BD_I2C_START);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	if (tx + 1 == num)
21162306a36Sopenharmony_ci		setbits16(&tbdf->cbd_sc, BD_SC_LAST | BD_SC_WRAP);
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	if (pmsg->flags & I2C_M_RD) {
21462306a36Sopenharmony_ci		/*
21562306a36Sopenharmony_ci		 * To read, we need an empty buffer of the proper length.
21662306a36Sopenharmony_ci		 * All that is used is the first byte for address, the remainder
21762306a36Sopenharmony_ci		 * is just used for timing (and doesn't really have to exist).
21862306a36Sopenharmony_ci		 */
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci		dev_dbg(&adap->dev, "cpm_i2c_read(abyte=0x%x)\n", addr);
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci		out_be16(&rbdf->cbd_datlen, 0);
22362306a36Sopenharmony_ci		out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci		if (rx + 1 == CPM_MAXBD)
22662306a36Sopenharmony_ci			setbits16(&rbdf->cbd_sc, BD_SC_WRAP);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci		eieio();
22962306a36Sopenharmony_ci		setbits16(&tbdf->cbd_sc, BD_SC_READY);
23062306a36Sopenharmony_ci	} else {
23162306a36Sopenharmony_ci		dev_dbg(&adap->dev, "cpm_i2c_write(abyte=0x%x)\n", addr);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci		memcpy(tb+1, pmsg->buf, pmsg->len);
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci		eieio();
23662306a36Sopenharmony_ci		setbits16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_INTRPT);
23762306a36Sopenharmony_ci	}
23862306a36Sopenharmony_ci}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cistatic int cpm_i2c_check_message(struct i2c_adapter *adap,
24162306a36Sopenharmony_ci	struct i2c_msg *pmsg, int tx, int rx)
24262306a36Sopenharmony_ci{
24362306a36Sopenharmony_ci	cbd_t __iomem *tbdf;
24462306a36Sopenharmony_ci	cbd_t __iomem *rbdf;
24562306a36Sopenharmony_ci	u_char *tb;
24662306a36Sopenharmony_ci	u_char *rb;
24762306a36Sopenharmony_ci	struct cpm_i2c *cpm = i2c_get_adapdata(adap);
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	tbdf = cpm->tbase + tx;
25062306a36Sopenharmony_ci	rbdf = cpm->rbase + rx;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	tb = cpm->txbuf[tx];
25362306a36Sopenharmony_ci	rb = cpm->rxbuf[rx];
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	/* Align read buffer */
25662306a36Sopenharmony_ci	rb = (u_char *) (((uint) rb + 1) & ~1);
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	eieio();
25962306a36Sopenharmony_ci	if (pmsg->flags & I2C_M_RD) {
26062306a36Sopenharmony_ci		dev_dbg(&adap->dev, "tx sc 0x%04x, rx sc 0x%04x\n",
26162306a36Sopenharmony_ci			in_be16(&tbdf->cbd_sc), in_be16(&rbdf->cbd_sc));
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci		if (in_be16(&tbdf->cbd_sc) & BD_SC_NAK) {
26462306a36Sopenharmony_ci			dev_dbg(&adap->dev, "I2C read; No ack\n");
26562306a36Sopenharmony_ci			return -ENXIO;
26662306a36Sopenharmony_ci		}
26762306a36Sopenharmony_ci		if (in_be16(&rbdf->cbd_sc) & BD_SC_EMPTY) {
26862306a36Sopenharmony_ci			dev_err(&adap->dev,
26962306a36Sopenharmony_ci				"I2C read; complete but rbuf empty\n");
27062306a36Sopenharmony_ci			return -EREMOTEIO;
27162306a36Sopenharmony_ci		}
27262306a36Sopenharmony_ci		if (in_be16(&rbdf->cbd_sc) & BD_SC_OV) {
27362306a36Sopenharmony_ci			dev_err(&adap->dev, "I2C read; Overrun\n");
27462306a36Sopenharmony_ci			return -EREMOTEIO;
27562306a36Sopenharmony_ci		}
27662306a36Sopenharmony_ci		memcpy(pmsg->buf, rb, pmsg->len);
27762306a36Sopenharmony_ci	} else {
27862306a36Sopenharmony_ci		dev_dbg(&adap->dev, "tx sc %d 0x%04x\n", tx,
27962306a36Sopenharmony_ci			in_be16(&tbdf->cbd_sc));
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci		if (in_be16(&tbdf->cbd_sc) & BD_SC_NAK) {
28262306a36Sopenharmony_ci			dev_dbg(&adap->dev, "I2C write; No ack\n");
28362306a36Sopenharmony_ci			return -ENXIO;
28462306a36Sopenharmony_ci		}
28562306a36Sopenharmony_ci		if (in_be16(&tbdf->cbd_sc) & BD_SC_UN) {
28662306a36Sopenharmony_ci			dev_err(&adap->dev, "I2C write; Underrun\n");
28762306a36Sopenharmony_ci			return -EIO;
28862306a36Sopenharmony_ci		}
28962306a36Sopenharmony_ci		if (in_be16(&tbdf->cbd_sc) & BD_SC_CL) {
29062306a36Sopenharmony_ci			dev_err(&adap->dev, "I2C write; Collision\n");
29162306a36Sopenharmony_ci			return -EIO;
29262306a36Sopenharmony_ci		}
29362306a36Sopenharmony_ci	}
29462306a36Sopenharmony_ci	return 0;
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_cistatic int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
29862306a36Sopenharmony_ci{
29962306a36Sopenharmony_ci	struct cpm_i2c *cpm = i2c_get_adapdata(adap);
30062306a36Sopenharmony_ci	struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg;
30162306a36Sopenharmony_ci	struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram;
30262306a36Sopenharmony_ci	struct i2c_msg *pmsg;
30362306a36Sopenharmony_ci	int ret;
30462306a36Sopenharmony_ci	int tptr;
30562306a36Sopenharmony_ci	int rptr;
30662306a36Sopenharmony_ci	cbd_t __iomem *tbdf;
30762306a36Sopenharmony_ci	cbd_t __iomem *rbdf;
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	/* Reset to use first buffer */
31062306a36Sopenharmony_ci	out_be16(&i2c_ram->rbptr, in_be16(&i2c_ram->rbase));
31162306a36Sopenharmony_ci	out_be16(&i2c_ram->tbptr, in_be16(&i2c_ram->tbase));
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	tbdf = cpm->tbase;
31462306a36Sopenharmony_ci	rbdf = cpm->rbase;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	tptr = 0;
31762306a36Sopenharmony_ci	rptr = 0;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	/*
32062306a36Sopenharmony_ci	 * If there was a collision in the last i2c transaction,
32162306a36Sopenharmony_ci	 * Set I2COM_MASTER as it was cleared during collision.
32262306a36Sopenharmony_ci	 */
32362306a36Sopenharmony_ci	if (in_be16(&tbdf->cbd_sc) & BD_SC_CL) {
32462306a36Sopenharmony_ci		out_8(&cpm->i2c_reg->i2com, I2COM_MASTER);
32562306a36Sopenharmony_ci	}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	while (tptr < num) {
32862306a36Sopenharmony_ci		pmsg = &msgs[tptr];
32962306a36Sopenharmony_ci		dev_dbg(&adap->dev, "R: %d T: %d\n", rptr, tptr);
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci		cpm_i2c_parse_message(adap, pmsg, num, tptr, rptr);
33262306a36Sopenharmony_ci		if (pmsg->flags & I2C_M_RD)
33362306a36Sopenharmony_ci			rptr++;
33462306a36Sopenharmony_ci		tptr++;
33562306a36Sopenharmony_ci	}
33662306a36Sopenharmony_ci	/* Start transfer now */
33762306a36Sopenharmony_ci	/* Enable RX/TX/Error interupts */
33862306a36Sopenharmony_ci	out_8(&i2c_reg->i2cmr, I2CER_TXE | I2CER_TXB | I2CER_RXB);
33962306a36Sopenharmony_ci	out_8(&i2c_reg->i2cer, 0xff);	/* Clear interrupt status */
34062306a36Sopenharmony_ci	/* Chip bug, set enable here */
34162306a36Sopenharmony_ci	setbits8(&i2c_reg->i2mod, I2MOD_EN);	/* Enable */
34262306a36Sopenharmony_ci	/* Begin transmission */
34362306a36Sopenharmony_ci	setbits8(&i2c_reg->i2com, I2COM_START);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	tptr = 0;
34662306a36Sopenharmony_ci	rptr = 0;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	while (tptr < num) {
34962306a36Sopenharmony_ci		/* Check for outstanding messages */
35062306a36Sopenharmony_ci		dev_dbg(&adap->dev, "test ready.\n");
35162306a36Sopenharmony_ci		pmsg = &msgs[tptr];
35262306a36Sopenharmony_ci		if (pmsg->flags & I2C_M_RD)
35362306a36Sopenharmony_ci			ret = wait_event_timeout(cpm->i2c_wait,
35462306a36Sopenharmony_ci				(in_be16(&tbdf[tptr].cbd_sc) & BD_SC_NAK) ||
35562306a36Sopenharmony_ci				!(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY),
35662306a36Sopenharmony_ci				1 * HZ);
35762306a36Sopenharmony_ci		else
35862306a36Sopenharmony_ci			ret = wait_event_timeout(cpm->i2c_wait,
35962306a36Sopenharmony_ci				!(in_be16(&tbdf[tptr].cbd_sc) & BD_SC_READY),
36062306a36Sopenharmony_ci				1 * HZ);
36162306a36Sopenharmony_ci		if (ret == 0) {
36262306a36Sopenharmony_ci			ret = -EREMOTEIO;
36362306a36Sopenharmony_ci			dev_err(&adap->dev, "I2C transfer: timeout\n");
36462306a36Sopenharmony_ci			goto out_err;
36562306a36Sopenharmony_ci		}
36662306a36Sopenharmony_ci		if (ret > 0) {
36762306a36Sopenharmony_ci			dev_dbg(&adap->dev, "ready.\n");
36862306a36Sopenharmony_ci			ret = cpm_i2c_check_message(adap, pmsg, tptr, rptr);
36962306a36Sopenharmony_ci			tptr++;
37062306a36Sopenharmony_ci			if (pmsg->flags & I2C_M_RD)
37162306a36Sopenharmony_ci				rptr++;
37262306a36Sopenharmony_ci			if (ret)
37362306a36Sopenharmony_ci				goto out_err;
37462306a36Sopenharmony_ci		}
37562306a36Sopenharmony_ci	}
37662306a36Sopenharmony_ci#ifdef I2C_CHIP_ERRATA
37762306a36Sopenharmony_ci	/*
37862306a36Sopenharmony_ci	 * Chip errata, clear enable. This is not needed on rev D4 CPUs.
37962306a36Sopenharmony_ci	 * Disabling I2C too early may cause too short stop condition
38062306a36Sopenharmony_ci	 */
38162306a36Sopenharmony_ci	udelay(4);
38262306a36Sopenharmony_ci	clrbits8(&i2c_reg->i2mod, I2MOD_EN);
38362306a36Sopenharmony_ci#endif
38462306a36Sopenharmony_ci	return (num);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ciout_err:
38762306a36Sopenharmony_ci	cpm_i2c_force_close(adap);
38862306a36Sopenharmony_ci#ifdef I2C_CHIP_ERRATA
38962306a36Sopenharmony_ci	/*
39062306a36Sopenharmony_ci	 * Chip errata, clear enable. This is not needed on rev D4 CPUs.
39162306a36Sopenharmony_ci	 */
39262306a36Sopenharmony_ci	clrbits8(&i2c_reg->i2mod, I2MOD_EN);
39362306a36Sopenharmony_ci#endif
39462306a36Sopenharmony_ci	return ret;
39562306a36Sopenharmony_ci}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_cistatic u32 cpm_i2c_func(struct i2c_adapter *adap)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
40062306a36Sopenharmony_ci}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci/* -----exported algorithm data: -------------------------------------	*/
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cistatic const struct i2c_algorithm cpm_i2c_algo = {
40562306a36Sopenharmony_ci	.master_xfer = cpm_i2c_xfer,
40662306a36Sopenharmony_ci	.functionality = cpm_i2c_func,
40762306a36Sopenharmony_ci};
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci/* CPM_MAX_READ is also limiting writes according to the code! */
41062306a36Sopenharmony_cistatic const struct i2c_adapter_quirks cpm_i2c_quirks = {
41162306a36Sopenharmony_ci	.max_num_msgs = CPM_MAXBD,
41262306a36Sopenharmony_ci	.max_read_len = CPM_MAX_READ,
41362306a36Sopenharmony_ci	.max_write_len = CPM_MAX_READ,
41462306a36Sopenharmony_ci};
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistatic const struct i2c_adapter cpm_ops = {
41762306a36Sopenharmony_ci	.owner		= THIS_MODULE,
41862306a36Sopenharmony_ci	.name		= "i2c-cpm",
41962306a36Sopenharmony_ci	.algo		= &cpm_i2c_algo,
42062306a36Sopenharmony_ci	.quirks		= &cpm_i2c_quirks,
42162306a36Sopenharmony_ci};
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_cistatic int cpm_i2c_setup(struct cpm_i2c *cpm)
42462306a36Sopenharmony_ci{
42562306a36Sopenharmony_ci	struct platform_device *ofdev = cpm->ofdev;
42662306a36Sopenharmony_ci	const u32 *data;
42762306a36Sopenharmony_ci	int len, ret, i;
42862306a36Sopenharmony_ci	void __iomem *i2c_base;
42962306a36Sopenharmony_ci	cbd_t __iomem *tbdf;
43062306a36Sopenharmony_ci	cbd_t __iomem *rbdf;
43162306a36Sopenharmony_ci	unsigned char brg;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	dev_dbg(&cpm->ofdev->dev, "cpm_i2c_setup()\n");
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	init_waitqueue_head(&cpm->i2c_wait);
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	cpm->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
43862306a36Sopenharmony_ci	if (!cpm->irq)
43962306a36Sopenharmony_ci		return -EINVAL;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	/* Install interrupt handler. */
44262306a36Sopenharmony_ci	ret = request_irq(cpm->irq, cpm_i2c_interrupt, 0, "cpm_i2c",
44362306a36Sopenharmony_ci			  &cpm->adap);
44462306a36Sopenharmony_ci	if (ret)
44562306a36Sopenharmony_ci		return ret;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	/* I2C parameter RAM */
44862306a36Sopenharmony_ci	i2c_base = of_iomap(ofdev->dev.of_node, 1);
44962306a36Sopenharmony_ci	if (i2c_base == NULL) {
45062306a36Sopenharmony_ci		ret = -EINVAL;
45162306a36Sopenharmony_ci		goto out_irq;
45262306a36Sopenharmony_ci	}
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,cpm1-i2c")) {
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci		/* Check for and use a microcode relocation patch. */
45762306a36Sopenharmony_ci		cpm->i2c_ram = i2c_base;
45862306a36Sopenharmony_ci		cpm->i2c_addr = in_be16(&cpm->i2c_ram->rpbase);
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci		/*
46162306a36Sopenharmony_ci		 * Maybe should use cpm_muram_alloc instead of hardcoding
46262306a36Sopenharmony_ci		 * this in micropatch.c
46362306a36Sopenharmony_ci		 */
46462306a36Sopenharmony_ci		if (cpm->i2c_addr) {
46562306a36Sopenharmony_ci			cpm->i2c_ram = cpm_muram_addr(cpm->i2c_addr);
46662306a36Sopenharmony_ci			iounmap(i2c_base);
46762306a36Sopenharmony_ci		}
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci		cpm->version = 1;
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	} else if (of_device_is_compatible(ofdev->dev.of_node, "fsl,cpm2-i2c")) {
47262306a36Sopenharmony_ci		cpm->i2c_addr = cpm_muram_alloc(sizeof(struct i2c_ram), 64);
47362306a36Sopenharmony_ci		cpm->i2c_ram = cpm_muram_addr(cpm->i2c_addr);
47462306a36Sopenharmony_ci		out_be16(i2c_base, cpm->i2c_addr);
47562306a36Sopenharmony_ci		iounmap(i2c_base);
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci		cpm->version = 2;
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	} else {
48062306a36Sopenharmony_ci		iounmap(i2c_base);
48162306a36Sopenharmony_ci		ret = -EINVAL;
48262306a36Sopenharmony_ci		goto out_irq;
48362306a36Sopenharmony_ci	}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	/* I2C control/status registers */
48662306a36Sopenharmony_ci	cpm->i2c_reg = of_iomap(ofdev->dev.of_node, 0);
48762306a36Sopenharmony_ci	if (cpm->i2c_reg == NULL) {
48862306a36Sopenharmony_ci		ret = -EINVAL;
48962306a36Sopenharmony_ci		goto out_ram;
49062306a36Sopenharmony_ci	}
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	data = of_get_property(ofdev->dev.of_node, "fsl,cpm-command", &len);
49362306a36Sopenharmony_ci	if (!data || len != 4) {
49462306a36Sopenharmony_ci		ret = -EINVAL;
49562306a36Sopenharmony_ci		goto out_reg;
49662306a36Sopenharmony_ci	}
49762306a36Sopenharmony_ci	cpm->cp_command = *data;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	data = of_get_property(ofdev->dev.of_node, "linux,i2c-class", &len);
50062306a36Sopenharmony_ci	if (data && len == 4)
50162306a36Sopenharmony_ci		cpm->adap.class = *data;
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	data = of_get_property(ofdev->dev.of_node, "clock-frequency", &len);
50462306a36Sopenharmony_ci	if (data && len == 4)
50562306a36Sopenharmony_ci		cpm->freq = *data;
50662306a36Sopenharmony_ci	else
50762306a36Sopenharmony_ci		cpm->freq = 60000; /* use 60kHz i2c clock by default */
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	/*
51062306a36Sopenharmony_ci	 * Allocate space for CPM_MAXBD transmit and receive buffer
51162306a36Sopenharmony_ci	 * descriptors in the DP ram.
51262306a36Sopenharmony_ci	 */
51362306a36Sopenharmony_ci	cpm->dp_addr = cpm_muram_alloc(sizeof(cbd_t) * 2 * CPM_MAXBD, 8);
51462306a36Sopenharmony_ci	if (!cpm->dp_addr) {
51562306a36Sopenharmony_ci		ret = -ENOMEM;
51662306a36Sopenharmony_ci		goto out_reg;
51762306a36Sopenharmony_ci	}
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	cpm->tbase = cpm_muram_addr(cpm->dp_addr);
52062306a36Sopenharmony_ci	cpm->rbase = cpm_muram_addr(cpm->dp_addr + sizeof(cbd_t) * CPM_MAXBD);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	/* Allocate TX and RX buffers */
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	tbdf = cpm->tbase;
52562306a36Sopenharmony_ci	rbdf = cpm->rbase;
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	for (i = 0; i < CPM_MAXBD; i++) {
52862306a36Sopenharmony_ci		cpm->rxbuf[i] = dma_alloc_coherent(&cpm->ofdev->dev,
52962306a36Sopenharmony_ci						   CPM_MAX_READ + 1,
53062306a36Sopenharmony_ci						   &cpm->rxdma[i], GFP_KERNEL);
53162306a36Sopenharmony_ci		if (!cpm->rxbuf[i]) {
53262306a36Sopenharmony_ci			ret = -ENOMEM;
53362306a36Sopenharmony_ci			goto out_muram;
53462306a36Sopenharmony_ci		}
53562306a36Sopenharmony_ci		out_be32(&rbdf[i].cbd_bufaddr, ((cpm->rxdma[i] + 1) & ~1));
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci		cpm->txbuf[i] = dma_alloc_coherent(&cpm->ofdev->dev,
53862306a36Sopenharmony_ci						   CPM_MAX_READ + 1,
53962306a36Sopenharmony_ci						   &cpm->txdma[i], GFP_KERNEL);
54062306a36Sopenharmony_ci		if (!cpm->txbuf[i]) {
54162306a36Sopenharmony_ci			ret = -ENOMEM;
54262306a36Sopenharmony_ci			goto out_muram;
54362306a36Sopenharmony_ci		}
54462306a36Sopenharmony_ci		out_be32(&tbdf[i].cbd_bufaddr, cpm->txdma[i]);
54562306a36Sopenharmony_ci	}
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	/* Initialize Tx/Rx parameters. */
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	cpm_reset_i2c_params(cpm);
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	dev_dbg(&cpm->ofdev->dev, "i2c_ram 0x%p, i2c_addr 0x%04x, freq %d\n",
55262306a36Sopenharmony_ci		cpm->i2c_ram, cpm->i2c_addr, cpm->freq);
55362306a36Sopenharmony_ci	dev_dbg(&cpm->ofdev->dev, "tbase 0x%04x, rbase 0x%04x\n",
55462306a36Sopenharmony_ci		(u8 __iomem *)cpm->tbase - DPRAM_BASE,
55562306a36Sopenharmony_ci		(u8 __iomem *)cpm->rbase - DPRAM_BASE);
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	cpm_command(cpm->cp_command, CPM_CR_INIT_TRX);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	/*
56062306a36Sopenharmony_ci	 * Select an invalid address. Just make sure we don't use loopback mode
56162306a36Sopenharmony_ci	 */
56262306a36Sopenharmony_ci	out_8(&cpm->i2c_reg->i2add, 0x7f << 1);
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	/*
56562306a36Sopenharmony_ci	 * PDIV is set to 00 in i2mod, so brgclk/32 is used as input to the
56662306a36Sopenharmony_ci	 * i2c baud rate generator. This is divided by 2 x (DIV + 3) to get
56762306a36Sopenharmony_ci	 * the actual i2c bus frequency.
56862306a36Sopenharmony_ci	 */
56962306a36Sopenharmony_ci	brg = get_brgfreq() / (32 * 2 * cpm->freq) - 3;
57062306a36Sopenharmony_ci	out_8(&cpm->i2c_reg->i2brg, brg);
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	out_8(&cpm->i2c_reg->i2mod, 0x00);
57362306a36Sopenharmony_ci	out_8(&cpm->i2c_reg->i2com, I2COM_MASTER);	/* Master mode */
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	/* Disable interrupts. */
57662306a36Sopenharmony_ci	out_8(&cpm->i2c_reg->i2cmr, 0);
57762306a36Sopenharmony_ci	out_8(&cpm->i2c_reg->i2cer, 0xff);
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	return 0;
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ciout_muram:
58262306a36Sopenharmony_ci	for (i = 0; i < CPM_MAXBD; i++) {
58362306a36Sopenharmony_ci		if (cpm->rxbuf[i])
58462306a36Sopenharmony_ci			dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1,
58562306a36Sopenharmony_ci				cpm->rxbuf[i], cpm->rxdma[i]);
58662306a36Sopenharmony_ci		if (cpm->txbuf[i])
58762306a36Sopenharmony_ci			dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1,
58862306a36Sopenharmony_ci				cpm->txbuf[i], cpm->txdma[i]);
58962306a36Sopenharmony_ci	}
59062306a36Sopenharmony_ci	cpm_muram_free(cpm->dp_addr);
59162306a36Sopenharmony_ciout_reg:
59262306a36Sopenharmony_ci	iounmap(cpm->i2c_reg);
59362306a36Sopenharmony_ciout_ram:
59462306a36Sopenharmony_ci	if ((cpm->version == 1) && (!cpm->i2c_addr))
59562306a36Sopenharmony_ci		iounmap(cpm->i2c_ram);
59662306a36Sopenharmony_ci	if (cpm->version == 2)
59762306a36Sopenharmony_ci		cpm_muram_free(cpm->i2c_addr);
59862306a36Sopenharmony_ciout_irq:
59962306a36Sopenharmony_ci	free_irq(cpm->irq, &cpm->adap);
60062306a36Sopenharmony_ci	return ret;
60162306a36Sopenharmony_ci}
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_cistatic void cpm_i2c_shutdown(struct cpm_i2c *cpm)
60462306a36Sopenharmony_ci{
60562306a36Sopenharmony_ci	int i;
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	/* Shut down I2C. */
60862306a36Sopenharmony_ci	clrbits8(&cpm->i2c_reg->i2mod, I2MOD_EN);
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	/* Disable interrupts */
61162306a36Sopenharmony_ci	out_8(&cpm->i2c_reg->i2cmr, 0);
61262306a36Sopenharmony_ci	out_8(&cpm->i2c_reg->i2cer, 0xff);
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	free_irq(cpm->irq, &cpm->adap);
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	/* Free all memory */
61762306a36Sopenharmony_ci	for (i = 0; i < CPM_MAXBD; i++) {
61862306a36Sopenharmony_ci		dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1,
61962306a36Sopenharmony_ci			cpm->rxbuf[i], cpm->rxdma[i]);
62062306a36Sopenharmony_ci		dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1,
62162306a36Sopenharmony_ci			cpm->txbuf[i], cpm->txdma[i]);
62262306a36Sopenharmony_ci	}
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	cpm_muram_free(cpm->dp_addr);
62562306a36Sopenharmony_ci	iounmap(cpm->i2c_reg);
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	if ((cpm->version == 1) && (!cpm->i2c_addr))
62862306a36Sopenharmony_ci		iounmap(cpm->i2c_ram);
62962306a36Sopenharmony_ci	if (cpm->version == 2)
63062306a36Sopenharmony_ci		cpm_muram_free(cpm->i2c_addr);
63162306a36Sopenharmony_ci}
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_cistatic int cpm_i2c_probe(struct platform_device *ofdev)
63462306a36Sopenharmony_ci{
63562306a36Sopenharmony_ci	int result, len;
63662306a36Sopenharmony_ci	struct cpm_i2c *cpm;
63762306a36Sopenharmony_ci	const u32 *data;
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	cpm = kzalloc(sizeof(struct cpm_i2c), GFP_KERNEL);
64062306a36Sopenharmony_ci	if (!cpm)
64162306a36Sopenharmony_ci		return -ENOMEM;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	cpm->ofdev = ofdev;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	platform_set_drvdata(ofdev, cpm);
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	cpm->adap = cpm_ops;
64862306a36Sopenharmony_ci	i2c_set_adapdata(&cpm->adap, cpm);
64962306a36Sopenharmony_ci	cpm->adap.dev.parent = &ofdev->dev;
65062306a36Sopenharmony_ci	cpm->adap.dev.of_node = of_node_get(ofdev->dev.of_node);
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	result = cpm_i2c_setup(cpm);
65362306a36Sopenharmony_ci	if (result) {
65462306a36Sopenharmony_ci		dev_err(&ofdev->dev, "Unable to init hardware\n");
65562306a36Sopenharmony_ci		goto out_free;
65662306a36Sopenharmony_ci	}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	/* register new adapter to i2c module... */
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	data = of_get_property(ofdev->dev.of_node, "linux,i2c-index", &len);
66162306a36Sopenharmony_ci	cpm->adap.nr = (data && len == 4) ? be32_to_cpup(data) : -1;
66262306a36Sopenharmony_ci	result = i2c_add_numbered_adapter(&cpm->adap);
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	if (result < 0)
66562306a36Sopenharmony_ci		goto out_shut;
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
66862306a36Sopenharmony_ci		cpm->adap.name);
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	return 0;
67162306a36Sopenharmony_ciout_shut:
67262306a36Sopenharmony_ci	cpm_i2c_shutdown(cpm);
67362306a36Sopenharmony_ciout_free:
67462306a36Sopenharmony_ci	kfree(cpm);
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	return result;
67762306a36Sopenharmony_ci}
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_cistatic void cpm_i2c_remove(struct platform_device *ofdev)
68062306a36Sopenharmony_ci{
68162306a36Sopenharmony_ci	struct cpm_i2c *cpm = platform_get_drvdata(ofdev);
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	i2c_del_adapter(&cpm->adap);
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	cpm_i2c_shutdown(cpm);
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	kfree(cpm);
68862306a36Sopenharmony_ci}
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_cistatic const struct of_device_id cpm_i2c_match[] = {
69162306a36Sopenharmony_ci	{
69262306a36Sopenharmony_ci		.compatible = "fsl,cpm1-i2c",
69362306a36Sopenharmony_ci	},
69462306a36Sopenharmony_ci	{
69562306a36Sopenharmony_ci		.compatible = "fsl,cpm2-i2c",
69662306a36Sopenharmony_ci	},
69762306a36Sopenharmony_ci	{},
69862306a36Sopenharmony_ci};
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, cpm_i2c_match);
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_cistatic struct platform_driver cpm_i2c_driver = {
70362306a36Sopenharmony_ci	.probe		= cpm_i2c_probe,
70462306a36Sopenharmony_ci	.remove_new	= cpm_i2c_remove,
70562306a36Sopenharmony_ci	.driver = {
70662306a36Sopenharmony_ci		.name = "fsl-i2c-cpm",
70762306a36Sopenharmony_ci		.of_match_table = cpm_i2c_match,
70862306a36Sopenharmony_ci	},
70962306a36Sopenharmony_ci};
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_cimodule_platform_driver(cpm_i2c_driver);
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ciMODULE_AUTHOR("Jochen Friedrich <jochen@scram.de>");
71462306a36Sopenharmony_ciMODULE_DESCRIPTION("I2C-Bus adapter routines for CPM boards");
71562306a36Sopenharmony_ciMODULE_LICENSE("GPL");
716