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