blob: 70b027c9037d809a57aae0208ce91ee2209ab641 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * i2c-au1550.c: SMBus (i2c) adapter for Alchemy PSC interface
3 * Copyright (C) 2004 Embedded Edge, LLC <dan@embeddededge.com>
4 *
5 * 2.6 port by Matt Porter <mporter@kernel.crashing.org>
6 *
7 * The documentation describes this as an SMBus controller, but it doesn't
8 * understand any of the SMBus protocol in hardware. It's really an I2C
9 * controller that could emulate most of the SMBus in software.
10 *
11 * This is just a skeleton adapter to use with the Au1550 PSC
12 * algorithm. It was developed for the Pb1550, but will work with
13 * any Au1550 board that has a similar PSC configuration.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 */
29
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/delay.h>
31#include <linux/kernel.h>
32#include <linux/module.h>
Manuel Lauss8b798c42008-01-27 18:14:52 +010033#include <linux/platform_device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/init.h>
35#include <linux/errno.h>
36#include <linux/i2c.h>
Manuel Lauss8b798c42008-01-27 18:14:52 +010037#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
Domen Puncera294de42006-08-13 23:37:13 +020039#include <asm/mach-au1x00/au1xxx.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <asm/mach-au1x00/au1xxx_psc.h>
41
Manuel Laussc5de6462011-10-22 13:34:36 +020042#define PSC_SEL 0x00
43#define PSC_CTRL 0x04
44#define PSC_SMBCFG 0x08
45#define PSC_SMBMSK 0x0C
46#define PSC_SMBPCR 0x10
47#define PSC_SMBSTAT 0x14
48#define PSC_SMBEVNT 0x18
49#define PSC_SMBTXRX 0x1C
50#define PSC_SMBTMR 0x20
51
Manuel Lauss8b798c42008-01-27 18:14:52 +010052struct i2c_au1550_data {
Manuel Laussc5de6462011-10-22 13:34:36 +020053 void __iomem *psc_base;
Manuel Lauss8b798c42008-01-27 18:14:52 +010054 int xfer_timeout;
55 int ack_timeout;
56 struct i2c_adapter adap;
57 struct resource *ioarea;
58};
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Manuel Laussc5de6462011-10-22 13:34:36 +020060static inline void WR(struct i2c_au1550_data *a, int r, unsigned long v)
Linus Torvalds1da177e2005-04-16 15:20:36 -070061{
Manuel Laussc5de6462011-10-22 13:34:36 +020062 __raw_writel(v, a->psc_base + r);
63 wmb();
64}
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
Manuel Laussc5de6462011-10-22 13:34:36 +020066static inline unsigned long RD(struct i2c_au1550_data *a, int r)
67{
68 return __raw_readl(a->psc_base + r);
69}
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Manuel Laussc5de6462011-10-22 13:34:36 +020071static int wait_xfer_done(struct i2c_au1550_data *adap)
72{
73 int i;
74
75 /* Wait for Tx Buffer Empty */
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 for (i = 0; i < adap->xfer_timeout; i++) {
Manuel Laussc5de6462011-10-22 13:34:36 +020077 if (RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_TE)
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 return 0;
Chris Davida2027072007-10-13 23:56:33 +020079
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 udelay(1);
81 }
82
83 return -ETIMEDOUT;
84}
85
Manuel Laussc5de6462011-10-22 13:34:36 +020086static int wait_ack(struct i2c_au1550_data *adap)
Linus Torvalds1da177e2005-04-16 15:20:36 -070087{
Manuel Laussc5de6462011-10-22 13:34:36 +020088 unsigned long stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
90 if (wait_xfer_done(adap))
91 return -ETIMEDOUT;
92
Manuel Laussc5de6462011-10-22 13:34:36 +020093 stat = RD(adap, PSC_SMBEVNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 if ((stat & (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | PSC_SMBEVNT_AL)) != 0)
95 return -ETIMEDOUT;
96
97 return 0;
98}
99
Manuel Laussc5de6462011-10-22 13:34:36 +0200100static int wait_master_done(struct i2c_au1550_data *adap)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101{
Manuel Laussc5de6462011-10-22 13:34:36 +0200102 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Manuel Laussc5de6462011-10-22 13:34:36 +0200104 /* Wait for Master Done. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 for (i = 0; i < adap->xfer_timeout; i++) {
Manuel Laussc5de6462011-10-22 13:34:36 +0200106 if ((RD(adap, PSC_SMBEVNT) & PSC_SMBEVNT_MD) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 return 0;
108 udelay(1);
109 }
110
111 return -ETIMEDOUT;
112}
113
114static int
Manuel Lauss91f27952008-01-27 18:14:52 +0100115do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116{
Manuel Laussc5de6462011-10-22 13:34:36 +0200117 unsigned long stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
Manuel Laussc5de6462011-10-22 13:34:36 +0200119 /* Reset the FIFOs, clear events. */
120 stat = RD(adap, PSC_SMBSTAT);
121 WR(adap, PSC_SMBEVNT, PSC_SMBEVNT_ALLCLR);
Domen Puncer88599422006-08-13 23:35:40 +0200122
123 if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
Manuel Laussc5de6462011-10-22 13:34:36 +0200124 WR(adap, PSC_SMBPCR, PSC_SMBPCR_DC);
125 while ((RD(adap, PSC_SMBPCR) & PSC_SMBPCR_DC) != 0)
126 cpu_relax();
Domen Puncer88599422006-08-13 23:35:40 +0200127 udelay(50);
128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
Manuel Laussc5de6462011-10-22 13:34:36 +0200130 /* Write out the i2c chip address and specify operation */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 addr <<= 1;
132 if (rd)
133 addr |= 1;
134
Manuel Lauss91f27952008-01-27 18:14:52 +0100135 /* zero-byte xfers stop immediately */
136 if (q)
137 addr |= PSC_SMBTXRX_STP;
138
Manuel Laussc5de6462011-10-22 13:34:36 +0200139 /* Put byte into fifo, start up master. */
140 WR(adap, PSC_SMBTXRX, addr);
141 WR(adap, PSC_SMBPCR, PSC_SMBPCR_MS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 if (wait_ack(adap))
143 return -EIO;
Manuel Lauss91f27952008-01-27 18:14:52 +0100144 return (q) ? wait_master_done(adap) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145}
146
Manuel Laussc5de6462011-10-22 13:34:36 +0200147static int wait_for_rx_byte(struct i2c_au1550_data *adap, unsigned char *out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148{
Manuel Laussc5de6462011-10-22 13:34:36 +0200149 int j;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
151 if (wait_xfer_done(adap))
152 return -EIO;
153
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 j = adap->xfer_timeout * 100;
155 do {
156 j--;
157 if (j <= 0)
158 return -EIO;
159
Manuel Laussc5de6462011-10-22 13:34:36 +0200160 if ((RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_RE) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 j = 0;
162 else
163 udelay(1);
164 } while (j > 0);
Manuel Laussc5de6462011-10-22 13:34:36 +0200165
166 *out = RD(adap, PSC_SMBTXRX);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
168 return 0;
169}
170
Manuel Laussc5de6462011-10-22 13:34:36 +0200171static int i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 unsigned int len)
173{
Manuel Laussc5de6462011-10-22 13:34:36 +0200174 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
176 if (len == 0)
177 return 0;
178
179 /* A read is performed by stuffing the transmit fifo with
180 * zero bytes for timing, waiting for bytes to appear in the
181 * receive fifo, then reading the bytes.
182 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 i = 0;
Manuel Laussc5de6462011-10-22 13:34:36 +0200184 while (i < (len - 1)) {
185 WR(adap, PSC_SMBTXRX, 0);
186 if (wait_for_rx_byte(adap, &buf[i]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 return -EIO;
188
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 i++;
190 }
191
Manuel Laussc5de6462011-10-22 13:34:36 +0200192 /* The last byte has to indicate transfer done. */
193 WR(adap, PSC_SMBTXRX, PSC_SMBTXRX_STP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 if (wait_master_done(adap))
195 return -EIO;
196
Manuel Laussc5de6462011-10-22 13:34:36 +0200197 buf[i] = (unsigned char)(RD(adap, PSC_SMBTXRX) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 return 0;
199}
200
Manuel Laussc5de6462011-10-22 13:34:36 +0200201static int i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 unsigned int len)
203{
Manuel Laussc5de6462011-10-22 13:34:36 +0200204 int i;
205 unsigned long data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
207 if (len == 0)
208 return 0;
209
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 i = 0;
211 while (i < (len-1)) {
212 data = buf[i];
Manuel Laussc5de6462011-10-22 13:34:36 +0200213 WR(adap, PSC_SMBTXRX, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 if (wait_ack(adap))
215 return -EIO;
216 i++;
217 }
218
Manuel Laussc5de6462011-10-22 13:34:36 +0200219 /* The last byte has to indicate transfer done. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 data = buf[i];
221 data |= PSC_SMBTXRX_STP;
Manuel Laussc5de6462011-10-22 13:34:36 +0200222 WR(adap, PSC_SMBTXRX, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 if (wait_master_done(adap))
224 return -EIO;
225 return 0;
226}
227
228static int
229au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
230{
231 struct i2c_au1550_data *adap = i2c_adap->algo_data;
232 struct i2c_msg *p;
233 int i, err = 0;
234
Manuel Laussc5de6462011-10-22 13:34:36 +0200235 WR(adap, PSC_CTRL, PSC_CTRL_ENABLE);
Manuel Laussf09f71b2008-07-14 22:38:34 +0200236
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 for (i = 0; !err && i < num; i++) {
238 p = &msgs[i];
Manuel Lauss91f27952008-01-27 18:14:52 +0100239 err = do_address(adap, p->addr, p->flags & I2C_M_RD,
240 (p->len == 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 if (err || !p->len)
242 continue;
243 if (p->flags & I2C_M_RD)
244 err = i2c_read(adap, p->buf, p->len);
245 else
246 err = i2c_write(adap, p->buf, p->len);
247 }
248
249 /* Return the number of messages processed, or the error code.
250 */
251 if (err == 0)
252 err = num;
Manuel Laussf09f71b2008-07-14 22:38:34 +0200253
Manuel Laussc5de6462011-10-22 13:34:36 +0200254 WR(adap, PSC_CTRL, PSC_CTRL_SUSPEND);
Manuel Laussf09f71b2008-07-14 22:38:34 +0200255
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 return err;
257}
258
Manuel Laussc5de6462011-10-22 13:34:36 +0200259static u32 au1550_func(struct i2c_adapter *adap)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260{
Domen Puncer6ed07132006-08-13 23:36:27 +0200261 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262}
263
Jean Delvare8f9082c2006-09-03 22:39:46 +0200264static const struct i2c_algorithm au1550_algo = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 .master_xfer = au1550_xfer,
266 .functionality = au1550_func,
267};
268
Manuel Laussf09f71b2008-07-14 22:38:34 +0200269static void i2c_au1550_setup(struct i2c_au1550_data *priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270{
Manuel Laussc5de6462011-10-22 13:34:36 +0200271 unsigned long cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272
Manuel Laussc5de6462011-10-22 13:34:36 +0200273 WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
274 WR(priv, PSC_SEL, PSC_SEL_PS_SMBUSMODE);
275 WR(priv, PSC_SMBCFG, 0);
276 WR(priv, PSC_CTRL, PSC_CTRL_ENABLE);
277 while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
278 cpu_relax();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Manuel Laussc5de6462011-10-22 13:34:36 +0200280 cfg = PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | PSC_SMBCFG_DD_DISABLE;
281 WR(priv, PSC_SMBCFG, cfg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
283 /* Divide by 8 to get a 6.25 MHz clock. The later protocol
284 * timings are based on this clock.
285 */
Manuel Laussc5de6462011-10-22 13:34:36 +0200286 cfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
287 WR(priv, PSC_SMBCFG, cfg);
288 WR(priv, PSC_SMBMSK, PSC_SMBMSK_ALLMASK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
290 /* Set the protocol timer values. See Table 71 in the
291 * Au1550 Data Book for standard timing values.
292 */
Manuel Laussc5de6462011-10-22 13:34:36 +0200293 WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \
295 PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \
Manuel Laussc5de6462011-10-22 13:34:36 +0200296 PSC_SMBTMR_SET_CH(15));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297
Manuel Laussc5de6462011-10-22 13:34:36 +0200298 cfg |= PSC_SMBCFG_DE_ENABLE;
299 WR(priv, PSC_SMBCFG, cfg);
300 while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
301 cpu_relax();
Manuel Laussf09f71b2008-07-14 22:38:34 +0200302
Manuel Laussc5de6462011-10-22 13:34:36 +0200303 WR(priv, PSC_CTRL, PSC_CTRL_SUSPEND);
Manuel Laussf09f71b2008-07-14 22:38:34 +0200304}
305
306static void i2c_au1550_disable(struct i2c_au1550_data *priv)
307{
Manuel Laussc5de6462011-10-22 13:34:36 +0200308 WR(priv, PSC_SMBCFG, 0);
309 WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
Manuel Laussf09f71b2008-07-14 22:38:34 +0200310}
311
312/*
313 * registering functions to load algorithms at runtime
314 * Prior to calling us, the 50MHz clock frequency and routing
315 * must have been set up for the PSC indicated by the adapter.
316 */
317static int __devinit
318i2c_au1550_probe(struct platform_device *pdev)
319{
320 struct i2c_au1550_data *priv;
321 struct resource *r;
322 int ret;
323
324 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
325 if (!r) {
326 ret = -ENODEV;
327 goto out;
328 }
329
330 priv = kzalloc(sizeof(struct i2c_au1550_data), GFP_KERNEL);
331 if (!priv) {
332 ret = -ENOMEM;
333 goto out;
334 }
335
Linus Walleijc6ffdde2009-06-14 00:20:36 +0200336 priv->ioarea = request_mem_region(r->start, resource_size(r),
Manuel Laussf09f71b2008-07-14 22:38:34 +0200337 pdev->name);
338 if (!priv->ioarea) {
339 ret = -EBUSY;
340 goto out_mem;
341 }
342
Manuel Laussc5de6462011-10-22 13:34:36 +0200343 priv->psc_base = ioremap(r->start, resource_size(r));
344 if (!priv->psc_base) {
345 ret = -EIO;
346 goto out_map;
347 }
Manuel Laussf09f71b2008-07-14 22:38:34 +0200348 priv->xfer_timeout = 200;
349 priv->ack_timeout = 200;
350
Manuel Laussf09f71b2008-07-14 22:38:34 +0200351 priv->adap.nr = pdev->id;
352 priv->adap.algo = &au1550_algo;
353 priv->adap.algo_data = priv;
354 priv->adap.dev.parent = &pdev->dev;
355 strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
356
Manuel Laussc5de6462011-10-22 13:34:36 +0200357 /* Now, set up the PSC for SMBus PIO mode. */
Manuel Laussf09f71b2008-07-14 22:38:34 +0200358 i2c_au1550_setup(priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Manuel Lauss8b798c42008-01-27 18:14:52 +0100360 ret = i2c_add_numbered_adapter(&priv->adap);
361 if (ret == 0) {
362 platform_set_drvdata(pdev, priv);
363 return 0;
364 }
365
Manuel Laussf09f71b2008-07-14 22:38:34 +0200366 i2c_au1550_disable(priv);
Manuel Laussc5de6462011-10-22 13:34:36 +0200367 iounmap(priv->psc_base);
368out_map:
Manuel Lauss8b798c42008-01-27 18:14:52 +0100369 release_resource(priv->ioarea);
370 kfree(priv->ioarea);
371out_mem:
372 kfree(priv);
373out:
374 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375}
376
Manuel Laussc5de6462011-10-22 13:34:36 +0200377static int __devexit i2c_au1550_remove(struct platform_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378{
Manuel Lauss8b798c42008-01-27 18:14:52 +0100379 struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
Manuel Lauss8b798c42008-01-27 18:14:52 +0100381 platform_set_drvdata(pdev, NULL);
382 i2c_del_adapter(&priv->adap);
Manuel Laussf09f71b2008-07-14 22:38:34 +0200383 i2c_au1550_disable(priv);
Manuel Laussc5de6462011-10-22 13:34:36 +0200384 iounmap(priv->psc_base);
Manuel Lauss8b798c42008-01-27 18:14:52 +0100385 release_resource(priv->ioarea);
386 kfree(priv->ioarea);
387 kfree(priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 return 0;
389}
390
Manuel Laussf09f71b2008-07-14 22:38:34 +0200391#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392static int
Manuel Lauss8b798c42008-01-27 18:14:52 +0100393i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394{
Manuel Lauss8b798c42008-01-27 18:14:52 +0100395 struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
Manuel Lauss8b798c42008-01-27 18:14:52 +0100396
Manuel Laussf09f71b2008-07-14 22:38:34 +0200397 i2c_au1550_disable(priv);
398
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 return 0;
400}
401
Manuel Lauss8b798c42008-01-27 18:14:52 +0100402static int
403i2c_au1550_resume(struct platform_device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404{
Manuel Lauss8b798c42008-01-27 18:14:52 +0100405 struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
Manuel Laussf09f71b2008-07-14 22:38:34 +0200407 i2c_au1550_setup(priv);
408
Manuel Lauss8b798c42008-01-27 18:14:52 +0100409 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410}
Manuel Laussf09f71b2008-07-14 22:38:34 +0200411#else
412#define i2c_au1550_suspend NULL
413#define i2c_au1550_resume NULL
414#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Manuel Lauss8b798c42008-01-27 18:14:52 +0100416static struct platform_driver au1xpsc_smbus_driver = {
417 .driver = {
418 .name = "au1xpsc_smbus",
419 .owner = THIS_MODULE,
420 },
421 .probe = i2c_au1550_probe,
422 .remove = __devexit_p(i2c_au1550_remove),
423 .suspend = i2c_au1550_suspend,
424 .resume = i2c_au1550_resume,
425};
426
Manuel Laussc5de6462011-10-22 13:34:36 +0200427static int __init i2c_au1550_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428{
Manuel Lauss8b798c42008-01-27 18:14:52 +0100429 return platform_driver_register(&au1xpsc_smbus_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430}
431
Manuel Laussc5de6462011-10-22 13:34:36 +0200432static void __exit i2c_au1550_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433{
Manuel Lauss8b798c42008-01-27 18:14:52 +0100434 platform_driver_unregister(&au1xpsc_smbus_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435}
436
437MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
438MODULE_DESCRIPTION("SMBus adapter Alchemy pb1550");
439MODULE_LICENSE("GPL");
Kay Sieversadd8eda2008-04-22 22:16:49 +0200440MODULE_ALIAS("platform:au1xpsc_smbus");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
442module_init (i2c_au1550_init);
443module_exit (i2c_au1550_exit);