141561f28SVitaly Wool /*
241561f28SVitaly Wool * Provides I2C support for Philips PNX010x/PNX4008 boards.
341561f28SVitaly Wool *
441561f28SVitaly Wool * Authors: Dennis Kovalev <dkovalev@ru.mvista.com>
541561f28SVitaly Wool * Vitaly Wool <vwool@ru.mvista.com>
641561f28SVitaly Wool *
741561f28SVitaly Wool * 2004-2006 (c) MontaVista Software, Inc. This file is licensed under
841561f28SVitaly Wool * the terms of the GNU General Public License version 2. This program
941561f28SVitaly Wool * is licensed "as is" without any warranty of any kind, whether express
1041561f28SVitaly Wool * or implied.
1141561f28SVitaly Wool */
1241561f28SVitaly Wool
1341561f28SVitaly Wool #include <linux/module.h>
1441561f28SVitaly Wool #include <linux/interrupt.h>
1541561f28SVitaly Wool #include <linux/ioport.h>
1641561f28SVitaly Wool #include <linux/delay.h>
1741561f28SVitaly Wool #include <linux/i2c.h>
1841561f28SVitaly Wool #include <linux/completion.h>
1941561f28SVitaly Wool #include <linux/platform_device.h>
20a7d73d8cSKevin Wells #include <linux/io.h>
210321cb83SRussell King #include <linux/err.h>
220321cb83SRussell King #include <linux/clk.h>
235a0e3ad6STejun Heo #include <linux/slab.h>
244edd65e6SSachin Kamat #include <linux/of.h>
250321cb83SRussell King
26b41a216dSRoland Stigge #define I2C_PNX_TIMEOUT_DEFAULT 10 /* msec */
27b41a216dSRoland Stigge #define I2C_PNX_SPEED_KHZ_DEFAULT 100
2841561f28SVitaly Wool #define I2C_PNX_REGION_SIZE 0x100
2941561f28SVitaly Wool
30caaccda1SWolfram Sang struct i2c_pnx_mif {
31caaccda1SWolfram Sang int ret; /* Return value */
32caaccda1SWolfram Sang int mode; /* Interface mode */
33caaccda1SWolfram Sang struct completion complete; /* I/O completion */
34caaccda1SWolfram Sang u8 * buf; /* Data buffer */
35caaccda1SWolfram Sang int len; /* Length of data buffer */
36caaccda1SWolfram Sang int order; /* RX Bytes to order via TX */
37caaccda1SWolfram Sang };
38caaccda1SWolfram Sang
39caaccda1SWolfram Sang struct i2c_pnx_algo_data {
40caaccda1SWolfram Sang void __iomem *ioaddr;
41caaccda1SWolfram Sang struct i2c_pnx_mif mif;
42caaccda1SWolfram Sang int last;
43caaccda1SWolfram Sang struct clk *clk;
44caaccda1SWolfram Sang struct i2c_adapter adapter;
45caaccda1SWolfram Sang int irq;
46caaccda1SWolfram Sang u32 timeout;
47caaccda1SWolfram Sang };
48caaccda1SWolfram Sang
49be460385SRoland Stigge enum {
50be460385SRoland Stigge mstatus_tdi = 0x00000001,
51be460385SRoland Stigge mstatus_afi = 0x00000002,
52be460385SRoland Stigge mstatus_nai = 0x00000004,
53be460385SRoland Stigge mstatus_drmi = 0x00000008,
54be460385SRoland Stigge mstatus_active = 0x00000020,
55be460385SRoland Stigge mstatus_scl = 0x00000040,
56be460385SRoland Stigge mstatus_sda = 0x00000080,
57be460385SRoland Stigge mstatus_rff = 0x00000100,
58be460385SRoland Stigge mstatus_rfe = 0x00000200,
59be460385SRoland Stigge mstatus_tff = 0x00000400,
60be460385SRoland Stigge mstatus_tfe = 0x00000800,
61be460385SRoland Stigge };
62be460385SRoland Stigge
63be460385SRoland Stigge enum {
64be460385SRoland Stigge mcntrl_tdie = 0x00000001,
65be460385SRoland Stigge mcntrl_afie = 0x00000002,
66be460385SRoland Stigge mcntrl_naie = 0x00000004,
67be460385SRoland Stigge mcntrl_drmie = 0x00000008,
68b3aafe80SRoland Stigge mcntrl_drsie = 0x00000010,
69b3aafe80SRoland Stigge mcntrl_rffie = 0x00000020,
70b3aafe80SRoland Stigge mcntrl_daie = 0x00000040,
71be460385SRoland Stigge mcntrl_tffie = 0x00000080,
72be460385SRoland Stigge mcntrl_reset = 0x00000100,
73be460385SRoland Stigge mcntrl_cdbmode = 0x00000400,
74be460385SRoland Stigge };
75be460385SRoland Stigge
76be460385SRoland Stigge enum {
77be460385SRoland Stigge rw_bit = 1 << 0,
78be460385SRoland Stigge start_bit = 1 << 8,
79be460385SRoland Stigge stop_bit = 1 << 9,
80be460385SRoland Stigge };
81be460385SRoland Stigge
82be460385SRoland Stigge #define I2C_REG_RX(a) ((a)->ioaddr) /* Rx FIFO reg (RO) */
83be460385SRoland Stigge #define I2C_REG_TX(a) ((a)->ioaddr) /* Tx FIFO reg (WO) */
84be460385SRoland Stigge #define I2C_REG_STS(a) ((a)->ioaddr + 0x04) /* Status reg (RO) */
85be460385SRoland Stigge #define I2C_REG_CTL(a) ((a)->ioaddr + 0x08) /* Ctl reg */
86be460385SRoland Stigge #define I2C_REG_CKL(a) ((a)->ioaddr + 0x0c) /* Clock divider low */
87be460385SRoland Stigge #define I2C_REG_CKH(a) ((a)->ioaddr + 0x10) /* Clock divider high */
88be460385SRoland Stigge #define I2C_REG_ADR(a) ((a)->ioaddr + 0x14) /* I2C address */
89be460385SRoland Stigge #define I2C_REG_RFL(a) ((a)->ioaddr + 0x18) /* Rx FIFO level (RO) */
90be460385SRoland Stigge #define I2C_REG_TFL(a) ((a)->ioaddr + 0x1c) /* Tx FIFO level (RO) */
91be460385SRoland Stigge #define I2C_REG_RXB(a) ((a)->ioaddr + 0x20) /* Num of bytes Rx-ed (RO) */
92be460385SRoland Stigge #define I2C_REG_TXB(a) ((a)->ioaddr + 0x24) /* Num of bytes Tx-ed (RO) */
93be460385SRoland Stigge #define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */
94be460385SRoland Stigge #define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */
95be460385SRoland Stigge
wait_timeout(struct i2c_pnx_algo_data * data)96b41a216dSRoland Stigge static inline int wait_timeout(struct i2c_pnx_algo_data *data)
9741561f28SVitaly Wool {
98*e4ee7050SVladimir Riabchun long timeout = jiffies_to_msecs(data->timeout);
9941561f28SVitaly Wool while (timeout > 0 &&
10041561f28SVitaly Wool (ioread32(I2C_REG_STS(data)) & mstatus_active)) {
10141561f28SVitaly Wool mdelay(1);
10241561f28SVitaly Wool timeout--;
10341561f28SVitaly Wool }
10441561f28SVitaly Wool return (timeout <= 0);
10541561f28SVitaly Wool }
10641561f28SVitaly Wool
wait_reset(struct i2c_pnx_algo_data * data)107b41a216dSRoland Stigge static inline int wait_reset(struct i2c_pnx_algo_data *data)
10841561f28SVitaly Wool {
109*e4ee7050SVladimir Riabchun long timeout = jiffies_to_msecs(data->timeout);
11041561f28SVitaly Wool while (timeout > 0 &&
11141561f28SVitaly Wool (ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
11241561f28SVitaly Wool mdelay(1);
11341561f28SVitaly Wool timeout--;
11441561f28SVitaly Wool }
11541561f28SVitaly Wool return (timeout <= 0);
11641561f28SVitaly Wool }
11741561f28SVitaly Wool
11841561f28SVitaly Wool /**
11941561f28SVitaly Wool * i2c_pnx_start - start a device
12041561f28SVitaly Wool * @slave_addr: slave address
1213e0f8672SLee Jones * @alg_data: pointer to local driver data structure
12241561f28SVitaly Wool *
12341561f28SVitaly Wool * Generate a START signal in the desired mode.
12441561f28SVitaly Wool */
i2c_pnx_start(unsigned char slave_addr,struct i2c_pnx_algo_data * alg_data)12581d6724aSRussell King static int i2c_pnx_start(unsigned char slave_addr,
12681d6724aSRussell King struct i2c_pnx_algo_data *alg_data)
12741561f28SVitaly Wool {
12881d6724aSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__,
12941561f28SVitaly Wool slave_addr, alg_data->mif.mode);
13041561f28SVitaly Wool
13141561f28SVitaly Wool /* Check for 7 bit slave addresses only */
13241561f28SVitaly Wool if (slave_addr & ~0x7f) {
1334be53dbeSRussell King dev_err(&alg_data->adapter.dev,
1344be53dbeSRussell King "%s: Invalid slave address %x. Only 7-bit addresses are supported\n",
13581d6724aSRussell King alg_data->adapter.name, slave_addr);
13641561f28SVitaly Wool return -EINVAL;
13741561f28SVitaly Wool }
13841561f28SVitaly Wool
13941561f28SVitaly Wool /* First, make sure bus is idle */
140b41a216dSRoland Stigge if (wait_timeout(alg_data)) {
14141561f28SVitaly Wool /* Somebody else is monopolizing the bus */
1424be53dbeSRussell King dev_err(&alg_data->adapter.dev,
1434be53dbeSRussell King "%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
14481d6724aSRussell King alg_data->adapter.name, slave_addr,
14541561f28SVitaly Wool ioread32(I2C_REG_CTL(alg_data)),
14641561f28SVitaly Wool ioread32(I2C_REG_STS(alg_data)));
14741561f28SVitaly Wool return -EBUSY;
14841561f28SVitaly Wool } else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {
14941561f28SVitaly Wool /* Sorry, we lost the bus */
1504be53dbeSRussell King dev_err(&alg_data->adapter.dev,
1514be53dbeSRussell King "%s: Arbitration failure. Slave addr = %02x\n",
1524be53dbeSRussell King alg_data->adapter.name, slave_addr);
15341561f28SVitaly Wool return -EIO;
15441561f28SVitaly Wool }
15541561f28SVitaly Wool
15641561f28SVitaly Wool /*
15741561f28SVitaly Wool * OK, I2C is enabled and we have the bus.
15841561f28SVitaly Wool * Clear the current TDI and AFI status flags.
15941561f28SVitaly Wool */
16041561f28SVitaly Wool iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
16141561f28SVitaly Wool I2C_REG_STS(alg_data));
16241561f28SVitaly Wool
16381d6724aSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__,
16441561f28SVitaly Wool (slave_addr << 1) | start_bit | alg_data->mif.mode);
16541561f28SVitaly Wool
16641561f28SVitaly Wool /* Write the slave address, START bit and R/W bit */
16741561f28SVitaly Wool iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
16841561f28SVitaly Wool I2C_REG_TX(alg_data));
16941561f28SVitaly Wool
17081d6724aSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__);
17141561f28SVitaly Wool
17241561f28SVitaly Wool return 0;
17341561f28SVitaly Wool }
17441561f28SVitaly Wool
17541561f28SVitaly Wool /**
17641561f28SVitaly Wool * i2c_pnx_stop - stop a device
1773e0f8672SLee Jones * @alg_data: pointer to local driver data structure
17841561f28SVitaly Wool *
17941561f28SVitaly Wool * Generate a STOP signal to terminate the master transaction.
18041561f28SVitaly Wool */
i2c_pnx_stop(struct i2c_pnx_algo_data * alg_data)18181d6724aSRussell King static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data)
18241561f28SVitaly Wool {
18341561f28SVitaly Wool /* Only 1 msec max timeout due to interrupt context */
18441561f28SVitaly Wool long timeout = 1000;
18541561f28SVitaly Wool
18681d6724aSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
18708882d20SHarvey Harrison __func__, ioread32(I2C_REG_STS(alg_data)));
18841561f28SVitaly Wool
18941561f28SVitaly Wool /* Write a STOP bit to TX FIFO */
19041561f28SVitaly Wool iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));
19141561f28SVitaly Wool
19241561f28SVitaly Wool /* Wait until the STOP is seen. */
19341561f28SVitaly Wool while (timeout > 0 &&
19441561f28SVitaly Wool (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) {
19541561f28SVitaly Wool /* may be called from interrupt context */
19641561f28SVitaly Wool udelay(1);
19741561f28SVitaly Wool timeout--;
19841561f28SVitaly Wool }
19941561f28SVitaly Wool
20081d6724aSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
20108882d20SHarvey Harrison __func__, ioread32(I2C_REG_STS(alg_data)));
20241561f28SVitaly Wool }
20341561f28SVitaly Wool
20441561f28SVitaly Wool /**
20541561f28SVitaly Wool * i2c_pnx_master_xmit - transmit data to slave
2063e0f8672SLee Jones * @alg_data: pointer to local driver data structure
20741561f28SVitaly Wool *
20841561f28SVitaly Wool * Sends one byte of data to the slave
20941561f28SVitaly Wool */
i2c_pnx_master_xmit(struct i2c_pnx_algo_data * alg_data)21081d6724aSRussell King static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
21141561f28SVitaly Wool {
21241561f28SVitaly Wool u32 val;
21341561f28SVitaly Wool
21481d6724aSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
21508882d20SHarvey Harrison __func__, ioread32(I2C_REG_STS(alg_data)));
21641561f28SVitaly Wool
21741561f28SVitaly Wool if (alg_data->mif.len > 0) {
21841561f28SVitaly Wool /* We still have something to talk about... */
21941561f28SVitaly Wool val = *alg_data->mif.buf++;
22041561f28SVitaly Wool
22128ad3321SKevin Wells if (alg_data->mif.len == 1)
22228ad3321SKevin Wells val |= stop_bit;
22328ad3321SKevin Wells
22441561f28SVitaly Wool alg_data->mif.len--;
22541561f28SVitaly Wool iowrite32(val, I2C_REG_TX(alg_data));
22641561f28SVitaly Wool
2274be53dbeSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n",
2284be53dbeSRussell King __func__, val, alg_data->mif.len + 1);
22941561f28SVitaly Wool
23041561f28SVitaly Wool if (alg_data->mif.len == 0) {
23141561f28SVitaly Wool if (alg_data->last) {
23241561f28SVitaly Wool /* Wait until the STOP is seen. */
233b41a216dSRoland Stigge if (wait_timeout(alg_data))
2344be53dbeSRussell King dev_err(&alg_data->adapter.dev,
2354be53dbeSRussell King "The bus is still active after timeout\n");
23641561f28SVitaly Wool }
23741561f28SVitaly Wool /* Disable master interrupts */
23841561f28SVitaly Wool iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
23941561f28SVitaly Wool ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
24041561f28SVitaly Wool I2C_REG_CTL(alg_data));
24141561f28SVitaly Wool
2424be53dbeSRussell King dev_dbg(&alg_data->adapter.dev,
2434be53dbeSRussell King "%s(): Waking up xfer routine.\n",
24408882d20SHarvey Harrison __func__);
24541561f28SVitaly Wool
24641561f28SVitaly Wool complete(&alg_data->mif.complete);
24741561f28SVitaly Wool }
24841561f28SVitaly Wool } else if (alg_data->mif.len == 0) {
24941561f28SVitaly Wool /* zero-sized transfer */
25081d6724aSRussell King i2c_pnx_stop(alg_data);
25141561f28SVitaly Wool
25241561f28SVitaly Wool /* Disable master interrupts. */
25341561f28SVitaly Wool iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
25441561f28SVitaly Wool ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
25541561f28SVitaly Wool I2C_REG_CTL(alg_data));
25641561f28SVitaly Wool
2574be53dbeSRussell King dev_dbg(&alg_data->adapter.dev,
2584be53dbeSRussell King "%s(): Waking up xfer routine after zero-xfer.\n",
2594be53dbeSRussell King __func__);
26041561f28SVitaly Wool
26141561f28SVitaly Wool complete(&alg_data->mif.complete);
26241561f28SVitaly Wool }
26341561f28SVitaly Wool
26481d6724aSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
26508882d20SHarvey Harrison __func__, ioread32(I2C_REG_STS(alg_data)));
26641561f28SVitaly Wool
26741561f28SVitaly Wool return 0;
26841561f28SVitaly Wool }
26941561f28SVitaly Wool
27041561f28SVitaly Wool /**
27141561f28SVitaly Wool * i2c_pnx_master_rcv - receive data from slave
2723e0f8672SLee Jones * @alg_data: pointer to local driver data structure
27341561f28SVitaly Wool *
27441561f28SVitaly Wool * Reads one byte data from the slave
27541561f28SVitaly Wool */
i2c_pnx_master_rcv(struct i2c_pnx_algo_data * alg_data)27681d6724aSRussell King static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
27741561f28SVitaly Wool {
27841561f28SVitaly Wool unsigned int val = 0;
27941561f28SVitaly Wool u32 ctl = 0;
28041561f28SVitaly Wool
28181d6724aSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
28208882d20SHarvey Harrison __func__, ioread32(I2C_REG_STS(alg_data)));
28341561f28SVitaly Wool
28441561f28SVitaly Wool /* Check, whether there is already data,
28541561f28SVitaly Wool * or we didn't 'ask' for it yet.
28641561f28SVitaly Wool */
28741561f28SVitaly Wool if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
288c076ada4SRoland Stigge /* 'Asking' is done asynchronously, e.g. dummy TX of several
289c076ada4SRoland Stigge * bytes is done before the first actual RX arrives in FIFO.
290c076ada4SRoland Stigge * Therefore, ordered bytes (via TX) are counted separately.
291c076ada4SRoland Stigge */
292c076ada4SRoland Stigge if (alg_data->mif.order) {
2934be53dbeSRussell King dev_dbg(&alg_data->adapter.dev,
2944be53dbeSRussell King "%s(): Write dummy data to fill Rx-fifo...\n",
2954be53dbeSRussell King __func__);
29641561f28SVitaly Wool
297c076ada4SRoland Stigge if (alg_data->mif.order == 1) {
29828ad3321SKevin Wells /* Last byte, do not acknowledge next rcv. */
29928ad3321SKevin Wells val |= stop_bit;
30028ad3321SKevin Wells
30141561f28SVitaly Wool /*
30241561f28SVitaly Wool * Enable interrupt RFDAIE (data in Rx fifo),
30341561f28SVitaly Wool * and disable DRMIE (need data for Tx)
30441561f28SVitaly Wool */
30541561f28SVitaly Wool ctl = ioread32(I2C_REG_CTL(alg_data));
30641561f28SVitaly Wool ctl |= mcntrl_rffie | mcntrl_daie;
30741561f28SVitaly Wool ctl &= ~mcntrl_drmie;
30841561f28SVitaly Wool iowrite32(ctl, I2C_REG_CTL(alg_data));
30941561f28SVitaly Wool }
31041561f28SVitaly Wool
31141561f28SVitaly Wool /*
31241561f28SVitaly Wool * Now we'll 'ask' for data:
31341561f28SVitaly Wool * For each byte we want to receive, we must
31441561f28SVitaly Wool * write a (dummy) byte to the Tx-FIFO.
31541561f28SVitaly Wool */
31641561f28SVitaly Wool iowrite32(val, I2C_REG_TX(alg_data));
317c076ada4SRoland Stigge alg_data->mif.order--;
318c076ada4SRoland Stigge }
31941561f28SVitaly Wool return 0;
32041561f28SVitaly Wool }
32141561f28SVitaly Wool
32241561f28SVitaly Wool /* Handle data. */
32341561f28SVitaly Wool if (alg_data->mif.len > 0) {
32441561f28SVitaly Wool val = ioread32(I2C_REG_RX(alg_data));
32541561f28SVitaly Wool *alg_data->mif.buf++ = (u8) (val & 0xff);
3264be53dbeSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): rcv 0x%x [%d]\n",
3274be53dbeSRussell King __func__, val, alg_data->mif.len);
32841561f28SVitaly Wool
32941561f28SVitaly Wool alg_data->mif.len--;
33041561f28SVitaly Wool if (alg_data->mif.len == 0) {
33141561f28SVitaly Wool if (alg_data->last)
33241561f28SVitaly Wool /* Wait until the STOP is seen. */
333b41a216dSRoland Stigge if (wait_timeout(alg_data))
3344be53dbeSRussell King dev_err(&alg_data->adapter.dev,
3354be53dbeSRussell King "The bus is still active after timeout\n");
33641561f28SVitaly Wool
33741561f28SVitaly Wool /* Disable master interrupts */
33841561f28SVitaly Wool ctl = ioread32(I2C_REG_CTL(alg_data));
33941561f28SVitaly Wool ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
34041561f28SVitaly Wool mcntrl_drmie | mcntrl_daie);
34141561f28SVitaly Wool iowrite32(ctl, I2C_REG_CTL(alg_data));
34241561f28SVitaly Wool
34341561f28SVitaly Wool complete(&alg_data->mif.complete);
34441561f28SVitaly Wool }
34541561f28SVitaly Wool }
34641561f28SVitaly Wool
34781d6724aSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
34808882d20SHarvey Harrison __func__, ioread32(I2C_REG_STS(alg_data)));
34941561f28SVitaly Wool
35041561f28SVitaly Wool return 0;
35141561f28SVitaly Wool }
35241561f28SVitaly Wool
i2c_pnx_interrupt(int irq,void * dev_id)3536c566fb7SVitaly Wool static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
35441561f28SVitaly Wool {
35581d6724aSRussell King struct i2c_pnx_algo_data *alg_data = dev_id;
35641561f28SVitaly Wool u32 stat, ctl;
35741561f28SVitaly Wool
3584be53dbeSRussell King dev_dbg(&alg_data->adapter.dev,
3594be53dbeSRussell King "%s(): mstat = %x mctrl = %x, mode = %d\n",
36008882d20SHarvey Harrison __func__,
36141561f28SVitaly Wool ioread32(I2C_REG_STS(alg_data)),
36241561f28SVitaly Wool ioread32(I2C_REG_CTL(alg_data)),
36341561f28SVitaly Wool alg_data->mif.mode);
36441561f28SVitaly Wool stat = ioread32(I2C_REG_STS(alg_data));
36541561f28SVitaly Wool
36641561f28SVitaly Wool /* let's see what kind of event this is */
36741561f28SVitaly Wool if (stat & mstatus_afi) {
36841561f28SVitaly Wool /* We lost arbitration in the midst of a transfer */
36941561f28SVitaly Wool alg_data->mif.ret = -EIO;
37041561f28SVitaly Wool
37141561f28SVitaly Wool /* Disable master interrupts. */
37241561f28SVitaly Wool ctl = ioread32(I2C_REG_CTL(alg_data));
37341561f28SVitaly Wool ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
37441561f28SVitaly Wool mcntrl_drmie);
37541561f28SVitaly Wool iowrite32(ctl, I2C_REG_CTL(alg_data));
37641561f28SVitaly Wool
37741561f28SVitaly Wool complete(&alg_data->mif.complete);
37841561f28SVitaly Wool } else if (stat & mstatus_nai) {
37941561f28SVitaly Wool /* Slave did not acknowledge, generate a STOP */
3804be53dbeSRussell King dev_dbg(&alg_data->adapter.dev,
3814be53dbeSRussell King "%s(): Slave did not acknowledge, generating a STOP.\n",
38208882d20SHarvey Harrison __func__);
38381d6724aSRussell King i2c_pnx_stop(alg_data);
38441561f28SVitaly Wool
38541561f28SVitaly Wool /* Disable master interrupts. */
38641561f28SVitaly Wool ctl = ioread32(I2C_REG_CTL(alg_data));
38741561f28SVitaly Wool ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
38841561f28SVitaly Wool mcntrl_drmie);
38941561f28SVitaly Wool iowrite32(ctl, I2C_REG_CTL(alg_data));
39041561f28SVitaly Wool
39141561f28SVitaly Wool /* Our return value. */
39241561f28SVitaly Wool alg_data->mif.ret = -EIO;
39341561f28SVitaly Wool
39441561f28SVitaly Wool complete(&alg_data->mif.complete);
39541561f28SVitaly Wool } else {
39641561f28SVitaly Wool /*
39741561f28SVitaly Wool * Two options:
39841561f28SVitaly Wool * - Master Tx needs data.
39941561f28SVitaly Wool * - There is data in the Rx-fifo
40041561f28SVitaly Wool * The latter is only the case if we have requested for data,
40141561f28SVitaly Wool * via a dummy write. (See 'i2c_pnx_master_rcv'.)
40241561f28SVitaly Wool * We therefore check, as a sanity check, whether that interrupt
40341561f28SVitaly Wool * has been enabled.
40441561f28SVitaly Wool */
40541561f28SVitaly Wool if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {
40641561f28SVitaly Wool if (alg_data->mif.mode == I2C_SMBUS_WRITE) {
40781d6724aSRussell King i2c_pnx_master_xmit(alg_data);
40841561f28SVitaly Wool } else if (alg_data->mif.mode == I2C_SMBUS_READ) {
40981d6724aSRussell King i2c_pnx_master_rcv(alg_data);
41041561f28SVitaly Wool }
41141561f28SVitaly Wool }
41241561f28SVitaly Wool }
41341561f28SVitaly Wool
41441561f28SVitaly Wool /* Clear TDI and AFI bits */
41541561f28SVitaly Wool stat = ioread32(I2C_REG_STS(alg_data));
41641561f28SVitaly Wool iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));
41741561f28SVitaly Wool
4184be53dbeSRussell King dev_dbg(&alg_data->adapter.dev,
4194be53dbeSRussell King "%s(): exiting, stat = %x ctrl = %x.\n",
42008882d20SHarvey Harrison __func__, ioread32(I2C_REG_STS(alg_data)),
42141561f28SVitaly Wool ioread32(I2C_REG_CTL(alg_data)));
42241561f28SVitaly Wool
42341561f28SVitaly Wool return IRQ_HANDLED;
42441561f28SVitaly Wool }
42541561f28SVitaly Wool
i2c_pnx_timeout(struct i2c_pnx_algo_data * alg_data)42692e494a7SPiotr Wojtaszczyk static void i2c_pnx_timeout(struct i2c_pnx_algo_data *alg_data)
42741561f28SVitaly Wool {
42841561f28SVitaly Wool u32 ctl;
42941561f28SVitaly Wool
4304be53dbeSRussell King dev_err(&alg_data->adapter.dev,
4314be53dbeSRussell King "Master timed out. stat = %04x, cntrl = %04x. Resetting master...\n",
43241561f28SVitaly Wool ioread32(I2C_REG_STS(alg_data)),
43341561f28SVitaly Wool ioread32(I2C_REG_CTL(alg_data)));
43441561f28SVitaly Wool
43541561f28SVitaly Wool /* Reset master and disable interrupts */
43641561f28SVitaly Wool ctl = ioread32(I2C_REG_CTL(alg_data));
43741561f28SVitaly Wool ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | mcntrl_drmie);
43841561f28SVitaly Wool iowrite32(ctl, I2C_REG_CTL(alg_data));
43941561f28SVitaly Wool
44041561f28SVitaly Wool ctl |= mcntrl_reset;
44141561f28SVitaly Wool iowrite32(ctl, I2C_REG_CTL(alg_data));
442b41a216dSRoland Stigge wait_reset(alg_data);
44341561f28SVitaly Wool alg_data->mif.ret = -EIO;
44441561f28SVitaly Wool }
44541561f28SVitaly Wool
bus_reset_if_active(struct i2c_pnx_algo_data * alg_data)44681d6724aSRussell King static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data)
44741561f28SVitaly Wool {
44841561f28SVitaly Wool u32 stat;
44941561f28SVitaly Wool
45041561f28SVitaly Wool if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) {
45181d6724aSRussell King dev_err(&alg_data->adapter.dev,
45241561f28SVitaly Wool "%s: Bus is still active after xfer. Reset it...\n",
45381d6724aSRussell King alg_data->adapter.name);
45441561f28SVitaly Wool iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
45541561f28SVitaly Wool I2C_REG_CTL(alg_data));
456b41a216dSRoland Stigge wait_reset(alg_data);
45741561f28SVitaly Wool } else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) {
45841561f28SVitaly Wool /* If there is data in the fifo's after transfer,
45941561f28SVitaly Wool * flush fifo's by reset.
46041561f28SVitaly Wool */
46141561f28SVitaly Wool iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
46241561f28SVitaly Wool I2C_REG_CTL(alg_data));
463b41a216dSRoland Stigge wait_reset(alg_data);
46441561f28SVitaly Wool } else if (stat & mstatus_nai) {
46541561f28SVitaly Wool iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
46641561f28SVitaly Wool I2C_REG_CTL(alg_data));
467b41a216dSRoland Stigge wait_reset(alg_data);
46841561f28SVitaly Wool }
46941561f28SVitaly Wool }
47041561f28SVitaly Wool
47141561f28SVitaly Wool /**
47241561f28SVitaly Wool * i2c_pnx_xfer - generic transfer entry point
47341561f28SVitaly Wool * @adap: pointer to I2C adapter structure
47441561f28SVitaly Wool * @msgs: array of messages
47541561f28SVitaly Wool * @num: number of messages
47641561f28SVitaly Wool *
47741561f28SVitaly Wool * Initiates the transfer
47841561f28SVitaly Wool */
47941561f28SVitaly Wool static int
i2c_pnx_xfer(struct i2c_adapter * adap,struct i2c_msg * msgs,int num)48041561f28SVitaly Wool i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
48141561f28SVitaly Wool {
48241561f28SVitaly Wool struct i2c_msg *pmsg;
48341561f28SVitaly Wool int rc = 0, completed = 0, i;
48441561f28SVitaly Wool struct i2c_pnx_algo_data *alg_data = adap->algo_data;
48592e494a7SPiotr Wojtaszczyk unsigned long time_left;
48677133e1cSWolfram Sang u32 stat;
48741561f28SVitaly Wool
4884be53dbeSRussell King dev_dbg(&alg_data->adapter.dev,
4894be53dbeSRussell King "%s(): entering: %d messages, stat = %04x.\n",
49008882d20SHarvey Harrison __func__, num, ioread32(I2C_REG_STS(alg_data)));
49141561f28SVitaly Wool
49281d6724aSRussell King bus_reset_if_active(alg_data);
49341561f28SVitaly Wool
49441561f28SVitaly Wool /* Process transactions in a loop. */
49541561f28SVitaly Wool for (i = 0; rc >= 0 && i < num; i++) {
49641561f28SVitaly Wool u8 addr;
49741561f28SVitaly Wool
49841561f28SVitaly Wool pmsg = &msgs[i];
49941561f28SVitaly Wool addr = pmsg->addr;
50041561f28SVitaly Wool
50141561f28SVitaly Wool if (pmsg->flags & I2C_M_TEN) {
50281d6724aSRussell King dev_err(&alg_data->adapter.dev,
50341561f28SVitaly Wool "%s: 10 bits addr not supported!\n",
50481d6724aSRussell King alg_data->adapter.name);
50541561f28SVitaly Wool rc = -EINVAL;
50641561f28SVitaly Wool break;
50741561f28SVitaly Wool }
50841561f28SVitaly Wool
50941561f28SVitaly Wool alg_data->mif.buf = pmsg->buf;
51041561f28SVitaly Wool alg_data->mif.len = pmsg->len;
511c076ada4SRoland Stigge alg_data->mif.order = pmsg->len;
51241561f28SVitaly Wool alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ?
51341561f28SVitaly Wool I2C_SMBUS_READ : I2C_SMBUS_WRITE;
51441561f28SVitaly Wool alg_data->mif.ret = 0;
51541561f28SVitaly Wool alg_data->last = (i == num - 1);
51641561f28SVitaly Wool
5174be53dbeSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n",
5184be53dbeSRussell King __func__, alg_data->mif.mode, alg_data->mif.len);
51941561f28SVitaly Wool
52041561f28SVitaly Wool
52141561f28SVitaly Wool /* initialize the completion var */
52241561f28SVitaly Wool init_completion(&alg_data->mif.complete);
52341561f28SVitaly Wool
52441561f28SVitaly Wool /* Enable master interrupt */
52541561f28SVitaly Wool iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_afie |
52641561f28SVitaly Wool mcntrl_naie | mcntrl_drmie,
52741561f28SVitaly Wool I2C_REG_CTL(alg_data));
52841561f28SVitaly Wool
52941561f28SVitaly Wool /* Put start-code and slave-address on the bus. */
53081d6724aSRussell King rc = i2c_pnx_start(addr, alg_data);
53141561f28SVitaly Wool if (rc < 0)
53241561f28SVitaly Wool break;
53341561f28SVitaly Wool
53441561f28SVitaly Wool /* Wait for completion */
53592e494a7SPiotr Wojtaszczyk time_left = wait_for_completion_timeout(&alg_data->mif.complete,
53692e494a7SPiotr Wojtaszczyk alg_data->timeout);
53792e494a7SPiotr Wojtaszczyk if (time_left == 0)
53892e494a7SPiotr Wojtaszczyk i2c_pnx_timeout(alg_data);
53941561f28SVitaly Wool
54041561f28SVitaly Wool if (!(rc = alg_data->mif.ret))
54141561f28SVitaly Wool completed++;
5424be53dbeSRussell King dev_dbg(&alg_data->adapter.dev,
5434be53dbeSRussell King "%s(): Complete, return code = %d.\n",
54408882d20SHarvey Harrison __func__, rc);
54541561f28SVitaly Wool
54641561f28SVitaly Wool /* Clear TDI and AFI bits in case they are set. */
54741561f28SVitaly Wool if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) {
54881d6724aSRussell King dev_dbg(&alg_data->adapter.dev,
54941561f28SVitaly Wool "%s: TDI still set... clearing now.\n",
55081d6724aSRussell King alg_data->adapter.name);
55141561f28SVitaly Wool iowrite32(stat, I2C_REG_STS(alg_data));
55241561f28SVitaly Wool }
55341561f28SVitaly Wool if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) {
55481d6724aSRussell King dev_dbg(&alg_data->adapter.dev,
55541561f28SVitaly Wool "%s: AFI still set... clearing now.\n",
55681d6724aSRussell King alg_data->adapter.name);
55741561f28SVitaly Wool iowrite32(stat, I2C_REG_STS(alg_data));
55841561f28SVitaly Wool }
55941561f28SVitaly Wool }
56041561f28SVitaly Wool
56181d6724aSRussell King bus_reset_if_active(alg_data);
56241561f28SVitaly Wool
56341561f28SVitaly Wool /* Cleanup to be sure... */
56441561f28SVitaly Wool alg_data->mif.buf = NULL;
56541561f28SVitaly Wool alg_data->mif.len = 0;
566c076ada4SRoland Stigge alg_data->mif.order = 0;
56741561f28SVitaly Wool
56881d6724aSRussell King dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n",
56908882d20SHarvey Harrison __func__, ioread32(I2C_REG_STS(alg_data)));
57041561f28SVitaly Wool
57141561f28SVitaly Wool if (completed != num)
57241561f28SVitaly Wool return ((rc < 0) ? rc : -EREMOTEIO);
57341561f28SVitaly Wool
57441561f28SVitaly Wool return num;
57541561f28SVitaly Wool }
57641561f28SVitaly Wool
i2c_pnx_func(struct i2c_adapter * adapter)57741561f28SVitaly Wool static u32 i2c_pnx_func(struct i2c_adapter *adapter)
57841561f28SVitaly Wool {
57941561f28SVitaly Wool return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
58041561f28SVitaly Wool }
58141561f28SVitaly Wool
582ad3caf8aSBhumika Goyal static const struct i2c_algorithm pnx_algorithm = {
58341561f28SVitaly Wool .master_xfer = i2c_pnx_xfer,
58441561f28SVitaly Wool .functionality = i2c_pnx_func,
58541561f28SVitaly Wool };
58641561f28SVitaly Wool
i2c_pnx_controller_suspend(struct device * dev)587783414baSRafael J. Wysocki static int i2c_pnx_controller_suspend(struct device *dev)
58841561f28SVitaly Wool {
589783414baSRafael J. Wysocki struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
5900321cb83SRussell King
5915dd32eaeSVladimir Zapolskiy clk_disable_unprepare(alg_data->clk);
5920321cb83SRussell King
5930321cb83SRussell King return 0;
59441561f28SVitaly Wool }
59541561f28SVitaly Wool
i2c_pnx_controller_resume(struct device * dev)596783414baSRafael J. Wysocki static int i2c_pnx_controller_resume(struct device *dev)
59741561f28SVitaly Wool {
598783414baSRafael J. Wysocki struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
5990321cb83SRussell King
6005dd32eaeSVladimir Zapolskiy return clk_prepare_enable(alg_data->clk);
60141561f28SVitaly Wool }
602783414baSRafael J. Wysocki
6036184f92fSPaul Cercueil static DEFINE_SIMPLE_DEV_PM_OPS(i2c_pnx_pm,
6046184f92fSPaul Cercueil i2c_pnx_controller_suspend,
6056184f92fSPaul Cercueil i2c_pnx_controller_resume);
60641561f28SVitaly Wool
i2c_pnx_probe(struct platform_device * pdev)6070b255e92SBill Pemberton static int i2c_pnx_probe(struct platform_device *pdev)
60841561f28SVitaly Wool {
60941561f28SVitaly Wool unsigned long tmp;
61041561f28SVitaly Wool int ret = 0;
61141561f28SVitaly Wool struct i2c_pnx_algo_data *alg_data;
6126fff3da9SRussell King unsigned long freq;
6131451ba3aSRoland Stigge struct resource *res;
614b41a216dSRoland Stigge u32 speed = I2C_PNX_SPEED_KHZ_DEFAULT * 1000;
61541561f28SVitaly Wool
616d1ccc125SJingoo Han alg_data = devm_kzalloc(&pdev->dev, sizeof(*alg_data), GFP_KERNEL);
617d1ccc125SJingoo Han if (!alg_data)
618d1ccc125SJingoo Han return -ENOMEM;
61944c5d739SRussell King
6209d7f7363SRussell King platform_set_drvdata(pdev, alg_data);
62141561f28SVitaly Wool
6229d7f7363SRussell King alg_data->adapter.dev.parent = &pdev->dev;
6239d7f7363SRussell King alg_data->adapter.algo = &pnx_algorithm;
6249d7f7363SRussell King alg_data->adapter.algo_data = alg_data;
6259d7f7363SRussell King alg_data->adapter.nr = pdev->id;
6260321cb83SRussell King
62792e494a7SPiotr Wojtaszczyk alg_data->timeout = msecs_to_jiffies(I2C_PNX_TIMEOUT_DEFAULT);
62892e494a7SPiotr Wojtaszczyk if (alg_data->timeout <= 1)
62992e494a7SPiotr Wojtaszczyk alg_data->timeout = 2;
63092e494a7SPiotr Wojtaszczyk
631b41a216dSRoland Stigge #ifdef CONFIG_OF
632b41a216dSRoland Stigge alg_data->adapter.dev.of_node = of_node_get(pdev->dev.of_node);
633b41a216dSRoland Stigge if (pdev->dev.of_node) {
634b41a216dSRoland Stigge of_property_read_u32(pdev->dev.of_node, "clock-frequency",
635b41a216dSRoland Stigge &speed);
636b41a216dSRoland Stigge /*
637b41a216dSRoland Stigge * At this point, it is planned to add an OF timeout property.
638b41a216dSRoland Stigge * As soon as there is a consensus about how to call and handle
639b41a216dSRoland Stigge * this, sth. like the following can be put here:
640b41a216dSRoland Stigge *
641b41a216dSRoland Stigge * of_property_read_u32(pdev->dev.of_node, "timeout",
642b41a216dSRoland Stigge * &alg_data->timeout);
643b41a216dSRoland Stigge */
644b41a216dSRoland Stigge }
645b41a216dSRoland Stigge #endif
646d1ccc125SJingoo Han alg_data->clk = devm_clk_get(&pdev->dev, NULL);
647d1ccc125SJingoo Han if (IS_ERR(alg_data->clk))
648d1ccc125SJingoo Han return PTR_ERR(alg_data->clk);
6490321cb83SRussell King
6501451ba3aSRoland Stigge snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name),
6511451ba3aSRoland Stigge "%s", pdev->name);
6521451ba3aSRoland Stigge
65341561f28SVitaly Wool /* Register I/O resource */
65408e3351bSYangtao Li alg_data->ioaddr = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
655d1ccc125SJingoo Han if (IS_ERR(alg_data->ioaddr))
656d1ccc125SJingoo Han return PTR_ERR(alg_data->ioaddr);
65741561f28SVitaly Wool
6585dd32eaeSVladimir Zapolskiy ret = clk_prepare_enable(alg_data->clk);
659ebdbbf20SRussell King if (ret)
660d1ccc125SJingoo Han return ret;
66141561f28SVitaly Wool
6626fff3da9SRussell King freq = clk_get_rate(alg_data->clk);
6636fff3da9SRussell King
66441561f28SVitaly Wool /*
66541561f28SVitaly Wool * Clock Divisor High This value is the number of system clocks
66641561f28SVitaly Wool * the serial clock (SCL) will be high.
66741561f28SVitaly Wool * For example, if the system clock period is 50 ns and the maximum
66841561f28SVitaly Wool * desired serial period is 10000 ns (100 kHz), then CLKHI would be
66941561f28SVitaly Wool * set to 0.5*(f_sys/f_i2c)-2=0.5*(20e6/100e3)-2=98. The actual value
67041561f28SVitaly Wool * programmed into CLKHI will vary from this slightly due to
67141561f28SVitaly Wool * variations in the output pad's rise and fall times as well as
67241561f28SVitaly Wool * the deglitching filter length.
67341561f28SVitaly Wool */
67441561f28SVitaly Wool
675b41a216dSRoland Stigge tmp = (freq / speed) / 2 - 2;
676be80dbaaSKevin Wells if (tmp > 0x3FF)
677be80dbaaSKevin Wells tmp = 0x3FF;
67841561f28SVitaly Wool iowrite32(tmp, I2C_REG_CKH(alg_data));
67941561f28SVitaly Wool iowrite32(tmp, I2C_REG_CKL(alg_data));
68041561f28SVitaly Wool
68141561f28SVitaly Wool iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
682b41a216dSRoland Stigge if (wait_reset(alg_data)) {
68341561f28SVitaly Wool ret = -ENODEV;
684ebdbbf20SRussell King goto out_clock;
68541561f28SVitaly Wool }
68641561f28SVitaly Wool init_completion(&alg_data->mif.complete);
68741561f28SVitaly Wool
6881451ba3aSRoland Stigge alg_data->irq = platform_get_irq(pdev, 0);
6891451ba3aSRoland Stigge if (alg_data->irq < 0) {
690498c0146SWei Yongjun ret = alg_data->irq;
691498c0146SWei Yongjun goto out_clock;
6921451ba3aSRoland Stigge }
693d1ccc125SJingoo Han ret = devm_request_irq(&pdev->dev, alg_data->irq, i2c_pnx_interrupt,
69481d6724aSRussell King 0, pdev->name, alg_data);
69541561f28SVitaly Wool if (ret)
69641561f28SVitaly Wool goto out_clock;
69741561f28SVitaly Wool
69841561f28SVitaly Wool /* Register this adapter with the I2C subsystem */
6999d7f7363SRussell King ret = i2c_add_numbered_adapter(&alg_data->adapter);
700ea734404SWolfram Sang if (ret < 0)
701d1ccc125SJingoo Han goto out_clock;
70241561f28SVitaly Wool
70317b3fe8bSKrzysztof Kozlowski dev_dbg(&pdev->dev, "%s: Master at %pap, irq %d.\n",
70417b3fe8bSKrzysztof Kozlowski alg_data->adapter.name, &res->start, alg_data->irq);
70541561f28SVitaly Wool
70641561f28SVitaly Wool return 0;
70741561f28SVitaly Wool
70841561f28SVitaly Wool out_clock:
7095dd32eaeSVladimir Zapolskiy clk_disable_unprepare(alg_data->clk);
71041561f28SVitaly Wool return ret;
71141561f28SVitaly Wool }
71241561f28SVitaly Wool
i2c_pnx_remove(struct platform_device * pdev)713e190a0c3SUwe Kleine-König static void i2c_pnx_remove(struct platform_device *pdev)
71441561f28SVitaly Wool {
7159d7f7363SRussell King struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
71641561f28SVitaly Wool
7179d7f7363SRussell King i2c_del_adapter(&alg_data->adapter);
7185dd32eaeSVladimir Zapolskiy clk_disable_unprepare(alg_data->clk);
71941561f28SVitaly Wool }
72041561f28SVitaly Wool
721b41a216dSRoland Stigge #ifdef CONFIG_OF
722b41a216dSRoland Stigge static const struct of_device_id i2c_pnx_of_match[] = {
723b41a216dSRoland Stigge { .compatible = "nxp,pnx-i2c" },
724b41a216dSRoland Stigge { },
725b41a216dSRoland Stigge };
726b41a216dSRoland Stigge MODULE_DEVICE_TABLE(of, i2c_pnx_of_match);
727b41a216dSRoland Stigge #endif
728b41a216dSRoland Stigge
72941561f28SVitaly Wool static struct platform_driver i2c_pnx_driver = {
73041561f28SVitaly Wool .driver = {
73141561f28SVitaly Wool .name = "pnx-i2c",
732b41a216dSRoland Stigge .of_match_table = of_match_ptr(i2c_pnx_of_match),
7336184f92fSPaul Cercueil .pm = pm_sleep_ptr(&i2c_pnx_pm),
73441561f28SVitaly Wool },
73541561f28SVitaly Wool .probe = i2c_pnx_probe,
736e190a0c3SUwe Kleine-König .remove_new = i2c_pnx_remove,
73741561f28SVitaly Wool };
73841561f28SVitaly Wool
i2c_adap_pnx_init(void)73941561f28SVitaly Wool static int __init i2c_adap_pnx_init(void)
74041561f28SVitaly Wool {
74141561f28SVitaly Wool return platform_driver_register(&i2c_pnx_driver);
74241561f28SVitaly Wool }
74341561f28SVitaly Wool
i2c_adap_pnx_exit(void)74441561f28SVitaly Wool static void __exit i2c_adap_pnx_exit(void)
74541561f28SVitaly Wool {
74641561f28SVitaly Wool platform_driver_unregister(&i2c_pnx_driver);
74741561f28SVitaly Wool }
74841561f28SVitaly Wool
749f80531c8SJarkko Nikula MODULE_AUTHOR("Vitaly Wool");
750f80531c8SJarkko Nikula MODULE_AUTHOR("Dennis Kovalev <source@mvista.com>");
75141561f28SVitaly Wool MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
75241561f28SVitaly Wool MODULE_LICENSE("GPL");
753add8eda7SKay Sievers MODULE_ALIAS("platform:pnx-i2c");
75441561f28SVitaly Wool
75541561f28SVitaly Wool /* We need to make sure I2C is initialized before USB */
75641561f28SVitaly Wool subsys_initcall(i2c_adap_pnx_init);
75741561f28SVitaly Wool module_exit(i2c_adap_pnx_exit);
758