11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * i2c-au1550.c: SMBus (i2c) adapter for Alchemy PSC interface
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2004 Embedded Edge, LLC <dan@embeddededge.com>
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2.6 port by Matt Porter <mporter@kernel.crashing.org>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The documentation describes this as an SMBus controller, but it doesn't
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * understand any of the SMBus protocol in hardware.  It's really an I2C
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controller that could emulate most of the SMBus in software.
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is just a skeleton adapter to use with the Au1550 PSC
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * algorithm.  It was developed for the Pb1550, but will work with
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * any Au1550 board that has a similar PSC configuration.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as published by the Free Software Foundation; either version 2
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the License, or (at your option) any later version.
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful,
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details.
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
338b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss#include <linux/platform_device.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c.h>
378b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss#include <linux/slab.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3950d5676ebac57c187ac347bae24290f0dc16fdbeManuel Lauss#include <asm/mach-au1x00/au1000.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/mach-au1x00/au1xxx_psc.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss#define PSC_SEL		0x00
43c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss#define PSC_CTRL	0x04
44c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss#define PSC_SMBCFG	0x08
45c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss#define PSC_SMBMSK	0x0C
46c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss#define PSC_SMBPCR	0x10
47c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss#define PSC_SMBSTAT	0x14
48c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss#define PSC_SMBEVNT	0x18
49c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss#define PSC_SMBTXRX	0x1C
50c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss#define PSC_SMBTMR	0x20
51c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss
528b798c4d16b762d15f4055597ff8d87f73b35552Manuel Laussstruct i2c_au1550_data {
53c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	void __iomem *psc_base;
548b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	int	xfer_timeout;
558b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	struct i2c_adapter adap;
568b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	struct resource *ioarea;
578b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss};
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Laussstatic inline void WR(struct i2c_au1550_data *a, int r, unsigned long v)
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
61c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	__raw_writel(v, a->psc_base + r);
62c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	wmb();
63c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss}
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
65c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Laussstatic inline unsigned long RD(struct i2c_au1550_data *a, int r)
66c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss{
67c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	return __raw_readl(a->psc_base + r);
68c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss}
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
70c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Laussstatic int wait_xfer_done(struct i2c_au1550_data *adap)
71c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss{
72c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	int i;
73c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss
74c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	/* Wait for Tx Buffer Empty */
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < adap->xfer_timeout; i++) {
76c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		if (RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_TE)
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
78a202707e71ff16d5e3a92f40eeaa41f3099dd8c5Chris David
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(1);
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ETIMEDOUT;
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
85c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Laussstatic int wait_ack(struct i2c_au1550_data *adap)
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
87c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	unsigned long stat;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (wait_xfer_done(adap))
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ETIMEDOUT;
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
92c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	stat = RD(adap, PSC_SMBEVNT);
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((stat & (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | PSC_SMBEVNT_AL)) != 0)
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ETIMEDOUT;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
99c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Laussstatic int wait_master_done(struct i2c_au1550_data *adap)
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
101c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	int i;
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
103c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	/* Wait for Master Done. */
10484785f120f4d64c5fa8cf4bab1cf07c2507d434fManuel Lauss	for (i = 0; i < 2 * adap->xfer_timeout; i++) {
105c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		if ((RD(adap, PSC_SMBEVNT) & PSC_SMBEVNT_MD) != 0)
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(1);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ETIMEDOUT;
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
11491f27958d686da713c3b0a1dc205288898e44124Manuel Laussdo_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
116c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	unsigned long stat;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
118c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	/* Reset the FIFOs, clear events. */
119c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	stat = RD(adap, PSC_SMBSTAT);
120c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(adap, PSC_SMBEVNT, PSC_SMBEVNT_ALLCLR);
1218859942ede8154c1e90e3b0d1b60aecf0cfaa169Domen Puncer
1228859942ede8154c1e90e3b0d1b60aecf0cfaa169Domen Puncer	if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
123c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		WR(adap, PSC_SMBPCR, PSC_SMBPCR_DC);
124c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		while ((RD(adap, PSC_SMBPCR) & PSC_SMBPCR_DC) != 0)
125c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss			cpu_relax();
1268859942ede8154c1e90e3b0d1b60aecf0cfaa169Domen Puncer		udelay(50);
1278859942ede8154c1e90e3b0d1b60aecf0cfaa169Domen Puncer	}
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
129c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	/* Write out the i2c chip address and specify operation */
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	addr <<= 1;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rd)
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		addr |= 1;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13491f27958d686da713c3b0a1dc205288898e44124Manuel Lauss	/* zero-byte xfers stop immediately */
13591f27958d686da713c3b0a1dc205288898e44124Manuel Lauss	if (q)
13691f27958d686da713c3b0a1dc205288898e44124Manuel Lauss		addr |= PSC_SMBTXRX_STP;
13791f27958d686da713c3b0a1dc205288898e44124Manuel Lauss
138c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	/* Put byte into fifo, start up master. */
139c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(adap, PSC_SMBTXRX, addr);
140c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(adap, PSC_SMBPCR, PSC_SMBPCR_MS);
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (wait_ack(adap))
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EIO;
14391f27958d686da713c3b0a1dc205288898e44124Manuel Lauss	return (q) ? wait_master_done(adap) : 0;
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
146c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Laussstatic int wait_for_rx_byte(struct i2c_au1550_data *adap, unsigned char *out)
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
148c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	int j;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (wait_xfer_done(adap))
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EIO;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	j =  adap->xfer_timeout * 100;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		j--;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (j <= 0)
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EIO;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
159c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		if ((RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_RE) == 0)
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			j = 0;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			udelay(1);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (j > 0);
164c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss
165c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	*out = RD(adap, PSC_SMBTXRX);
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
170c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Laussstatic int i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    unsigned int len)
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
173c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	int i;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len == 0)
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* A read is performed by stuffing the transmit fifo with
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * zero bytes for timing, waiting for bytes to appear in the
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * receive fifo, then reading the bytes.
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = 0;
183c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	while (i < (len - 1)) {
184c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		WR(adap, PSC_SMBTXRX, 0);
185c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		if (wait_for_rx_byte(adap, &buf[i]))
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EIO;
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i++;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
191c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	/* The last byte has to indicate transfer done. */
192c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(adap, PSC_SMBTXRX, PSC_SMBTXRX_STP);
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (wait_master_done(adap))
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EIO;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
196c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	buf[i] = (unsigned char)(RD(adap, PSC_SMBTXRX) & 0xff);
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
200c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Laussstatic int i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     unsigned int len)
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
203c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	int i;
204c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	unsigned long data;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len == 0)
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = 0;
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (i < (len-1)) {
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data = buf[i];
212c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		WR(adap, PSC_SMBTXRX, data);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (wait_ack(adap))
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EIO;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i++;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
218c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	/* The last byte has to indicate transfer done. */
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data = buf[i];
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data |= PSC_SMBTXRX_STP;
221c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(adap, PSC_SMBTXRX, data);
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (wait_master_done(adap))
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EIO;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsau1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_au1550_data *adap = i2c_adap->algo_data;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_msg *p;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, err = 0;
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
234c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(adap, PSC_CTRL, PSC_CTRL_ENABLE);
235f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; !err && i < num; i++) {
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p = &msgs[i];
23891f27958d686da713c3b0a1dc205288898e44124Manuel Lauss		err = do_address(adap, p->addr, p->flags & I2C_M_RD,
23991f27958d686da713c3b0a1dc205288898e44124Manuel Lauss				 (p->len == 0));
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (err || !p->len)
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (p->flags & I2C_M_RD)
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = i2c_read(adap, p->buf, p->len);
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = i2c_write(adap, p->buf, p->len);
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Return the number of messages processed, or the error code.
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err == 0)
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = num;
252f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss
253c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(adap, PSC_CTRL, PSC_CTRL_SUSPEND);
254f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
258c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Laussstatic u32 au1550_func(struct i2c_adapter *adap)
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2606ed07134792655db12fddaafbf870425331a21f6Domen Puncer	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2638f9082c5ce0e2c2f7ad0211b0c089f680d2efc11Jean Delvarestatic const struct i2c_algorithm au1550_algo = {
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.master_xfer	= au1550_xfer,
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.functionality	= au1550_func,
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
268f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Laussstatic void i2c_au1550_setup(struct i2c_au1550_data *priv)
269f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss{
270c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	unsigned long cfg;
271f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss
272c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
273c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(priv, PSC_SEL, PSC_SEL_PS_SMBUSMODE);
274c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(priv, PSC_SMBCFG, 0);
275c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(priv, PSC_CTRL, PSC_CTRL_ENABLE);
276c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
277c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		cpu_relax();
278c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss
279c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	cfg = PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | PSC_SMBCFG_DD_DISABLE;
280c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(priv, PSC_SMBCFG, cfg);
281f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss
282f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss	/* Divide by 8 to get a 6.25 MHz clock.  The later protocol
283f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss	 * timings are based on this clock.
284f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss	 */
285c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	cfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
286c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(priv, PSC_SMBCFG, cfg);
287c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(priv, PSC_SMBMSK, PSC_SMBMSK_ALLMASK);
288f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss
289f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss	/* Set the protocol timer values.  See Table 71 in the
290f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss	 * Au1550 Data Book for standard timing values.
291f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss	 */
292c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
293f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss		PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \
294f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss		PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \
295c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		PSC_SMBTMR_SET_CH(15));
296f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss
297c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	cfg |= PSC_SMBCFG_DE_ENABLE;
298c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(priv, PSC_SMBCFG, cfg);
299c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
300c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		cpu_relax();
301f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss
302c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(priv, PSC_CTRL, PSC_CTRL_SUSPEND);
303f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss}
304f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss
305f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Laussstatic void i2c_au1550_disable(struct i2c_au1550_data *priv)
306f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss{
307c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(priv, PSC_SMBCFG, 0);
308c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
309f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss}
310f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registering functions to load algorithms at runtime
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Prior to calling us, the 50MHz clock frequency and routing
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * must have been set up for the PSC indicated by the adapter.
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3168b798c4d16b762d15f4055597ff8d87f73b35552Manuel Laussstatic int __devinit
3178b798c4d16b762d15f4055597ff8d87f73b35552Manuel Laussi2c_au1550_probe(struct platform_device *pdev)
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3198b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	struct i2c_au1550_data *priv;
3208b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	struct resource *r;
3218b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	int ret;
3228b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss
3238b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3248b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	if (!r) {
3258b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss		ret = -ENODEV;
3268b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss		goto out;
3278b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	}
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3298b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	priv = kzalloc(sizeof(struct i2c_au1550_data), GFP_KERNEL);
3308b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	if (!priv) {
3318b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss		ret = -ENOMEM;
3328b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss		goto out;
3338b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	}
3348b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss
335c6ffddea36dd576b70dfbd10eb5d2b287b786dcaLinus Walleij	priv->ioarea = request_mem_region(r->start, resource_size(r),
3368b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss					  pdev->name);
3378b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	if (!priv->ioarea) {
3388b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss		ret = -EBUSY;
3398b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss		goto out_mem;
3408b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	}
3418b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss
342c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	priv->psc_base = ioremap(r->start, resource_size(r));
343c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	if (!priv->psc_base) {
344c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		ret = -EIO;
345c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss		goto out_map;
346c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	}
3478b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	priv->xfer_timeout = 200;
3488b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss
3498b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	priv->adap.nr = pdev->id;
3508b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	priv->adap.algo = &au1550_algo;
3518b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	priv->adap.algo_data = priv;
3528b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	priv->adap.dev.parent = &pdev->dev;
3538b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
355c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	/* Now, set up the PSC for SMBus PIO mode. */
356f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss	i2c_au1550_setup(priv);
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3588b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	ret = i2c_add_numbered_adapter(&priv->adap);
3598b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	if (ret == 0) {
3608b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss		platform_set_drvdata(pdev, priv);
3618b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss		return 0;
3628b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	}
3638b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss
364f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss	i2c_au1550_disable(priv);
365c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	iounmap(priv->psc_base);
366c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Laussout_map:
3678b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	release_resource(priv->ioarea);
3688b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	kfree(priv->ioarea);
3698b798c4d16b762d15f4055597ff8d87f73b35552Manuel Laussout_mem:
3708b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	kfree(priv);
3718b798c4d16b762d15f4055597ff8d87f73b35552Manuel Laussout:
3728b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	return ret;
3738b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss}
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
375c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Laussstatic int __devexit i2c_au1550_remove(struct platform_device *pdev)
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3778b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
3788b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss
3798b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	platform_set_drvdata(pdev, NULL);
3808b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	i2c_del_adapter(&priv->adap);
381f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss	i2c_au1550_disable(priv);
382c5de6467d2a54eb81b139f29b217d0394e8a790cManuel Lauss	iounmap(priv->psc_base);
3838b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	release_resource(priv->ioarea);
3848b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	kfree(priv->ioarea);
3858b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	kfree(priv);
3868b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	return 0;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
389f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss#ifdef CONFIG_PM
39046f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Laussstatic int i2c_au1550_suspend(struct device *dev)
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
39246f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Lauss	struct i2c_au1550_data *priv = dev_get_drvdata(dev);
3938b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss
394f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss	i2c_au1550_disable(priv);
395f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39946f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Laussstatic int i2c_au1550_resume(struct device *dev)
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
40146f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Lauss	struct i2c_au1550_data *priv = dev_get_drvdata(dev);
4028b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss
403f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss	i2c_au1550_setup(priv);
404f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
40746f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Lauss
40846f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Laussstatic const struct dev_pm_ops i2c_au1550_pmops = {
40946f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Lauss	.suspend	= i2c_au1550_suspend,
41046f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Lauss	.resume		= i2c_au1550_resume,
41146f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Lauss};
41246f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Lauss
41346f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Lauss#define AU1XPSC_SMBUS_PMOPS (&i2c_au1550_pmops)
41446f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Lauss
415f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss#else
41646f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Lauss#define AU1XPSC_SMBUS_PMOPS NULL
417f09f71b24e77a2f2b4e5c98311c8804fc61ad8bcManuel Lauss#endif
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4198b798c4d16b762d15f4055597ff8d87f73b35552Manuel Laussstatic struct platform_driver au1xpsc_smbus_driver = {
4208b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	.driver = {
4218b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss		.name	= "au1xpsc_smbus",
4228b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss		.owner	= THIS_MODULE,
42346f344e2a0844d9b068bffa38cb48b52f4bd2d4aManuel Lauss		.pm	= AU1XPSC_SMBUS_PMOPS,
4248b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	},
4258b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	.probe		= i2c_au1550_probe,
4268b798c4d16b762d15f4055597ff8d87f73b35552Manuel Lauss	.remove		= __devexit_p(i2c_au1550_remove),
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
429a3664b51c783aaa0dde1c95334d1a670d6d54590Axel Linmodule_platform_driver(au1xpsc_smbus_driver);
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("SMBus adapter Alchemy pb1550");
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
434add8eda7f2be781af0224241e870715cf0cfd75aKay SieversMODULE_ALIAS("platform:au1xpsc_smbus");
435