xref: /OK3568_Linux_fs/kernel/drivers/i2c/busses/i2c-au1550.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * i2c-au1550.c: SMBus (i2c) adapter for Alchemy PSC interface
4*4882a593Smuzhiyun  * Copyright (C) 2004 Embedded Edge, LLC <dan@embeddededge.com>
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * 2.6 port by Matt Porter <mporter@kernel.crashing.org>
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * The documentation describes this as an SMBus controller, but it doesn't
9*4882a593Smuzhiyun  * understand any of the SMBus protocol in hardware.  It's really an I2C
10*4882a593Smuzhiyun  * controller that could emulate most of the SMBus in software.
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * This is just a skeleton adapter to use with the Au1550 PSC
13*4882a593Smuzhiyun  * algorithm.  It was developed for the Pb1550, but will work with
14*4882a593Smuzhiyun  * any Au1550 board that has a similar PSC configuration.
15*4882a593Smuzhiyun  */
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <linux/delay.h>
18*4882a593Smuzhiyun #include <linux/kernel.h>
19*4882a593Smuzhiyun #include <linux/module.h>
20*4882a593Smuzhiyun #include <linux/platform_device.h>
21*4882a593Smuzhiyun #include <linux/errno.h>
22*4882a593Smuzhiyun #include <linux/i2c.h>
23*4882a593Smuzhiyun #include <linux/slab.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #include <asm/mach-au1x00/au1000.h>
26*4882a593Smuzhiyun #include <asm/mach-au1x00/au1xxx_psc.h>
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define PSC_SEL		0x00
29*4882a593Smuzhiyun #define PSC_CTRL	0x04
30*4882a593Smuzhiyun #define PSC_SMBCFG	0x08
31*4882a593Smuzhiyun #define PSC_SMBMSK	0x0C
32*4882a593Smuzhiyun #define PSC_SMBPCR	0x10
33*4882a593Smuzhiyun #define PSC_SMBSTAT	0x14
34*4882a593Smuzhiyun #define PSC_SMBEVNT	0x18
35*4882a593Smuzhiyun #define PSC_SMBTXRX	0x1C
36*4882a593Smuzhiyun #define PSC_SMBTMR	0x20
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun struct i2c_au1550_data {
39*4882a593Smuzhiyun 	void __iomem *psc_base;
40*4882a593Smuzhiyun 	int	xfer_timeout;
41*4882a593Smuzhiyun 	struct i2c_adapter adap;
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
WR(struct i2c_au1550_data * a,int r,unsigned long v)44*4882a593Smuzhiyun static inline void WR(struct i2c_au1550_data *a, int r, unsigned long v)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	__raw_writel(v, a->psc_base + r);
47*4882a593Smuzhiyun 	wmb();
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun 
RD(struct i2c_au1550_data * a,int r)50*4882a593Smuzhiyun static inline unsigned long RD(struct i2c_au1550_data *a, int r)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun 	return __raw_readl(a->psc_base + r);
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
wait_xfer_done(struct i2c_au1550_data * adap)55*4882a593Smuzhiyun static int wait_xfer_done(struct i2c_au1550_data *adap)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	int i;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	/* Wait for Tx Buffer Empty */
60*4882a593Smuzhiyun 	for (i = 0; i < adap->xfer_timeout; i++) {
61*4882a593Smuzhiyun 		if (RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_TE)
62*4882a593Smuzhiyun 			return 0;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 		udelay(1);
65*4882a593Smuzhiyun 	}
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	return -ETIMEDOUT;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun 
wait_ack(struct i2c_au1550_data * adap)70*4882a593Smuzhiyun static int wait_ack(struct i2c_au1550_data *adap)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun 	unsigned long stat;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	if (wait_xfer_done(adap))
75*4882a593Smuzhiyun 		return -ETIMEDOUT;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	stat = RD(adap, PSC_SMBEVNT);
78*4882a593Smuzhiyun 	if ((stat & (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | PSC_SMBEVNT_AL)) != 0)
79*4882a593Smuzhiyun 		return -ETIMEDOUT;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	return 0;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun 
wait_master_done(struct i2c_au1550_data * adap)84*4882a593Smuzhiyun static int wait_master_done(struct i2c_au1550_data *adap)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	int i;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	/* Wait for Master Done. */
89*4882a593Smuzhiyun 	for (i = 0; i < 2 * adap->xfer_timeout; i++) {
90*4882a593Smuzhiyun 		if ((RD(adap, PSC_SMBEVNT) & PSC_SMBEVNT_MD) != 0)
91*4882a593Smuzhiyun 			return 0;
92*4882a593Smuzhiyun 		udelay(1);
93*4882a593Smuzhiyun 	}
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	return -ETIMEDOUT;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun static int
do_address(struct i2c_au1550_data * adap,unsigned int addr,int rd,int q)99*4882a593Smuzhiyun do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	unsigned long stat;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	/* Reset the FIFOs, clear events. */
104*4882a593Smuzhiyun 	stat = RD(adap, PSC_SMBSTAT);
105*4882a593Smuzhiyun 	WR(adap, PSC_SMBEVNT, PSC_SMBEVNT_ALLCLR);
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
108*4882a593Smuzhiyun 		WR(adap, PSC_SMBPCR, PSC_SMBPCR_DC);
109*4882a593Smuzhiyun 		while ((RD(adap, PSC_SMBPCR) & PSC_SMBPCR_DC) != 0)
110*4882a593Smuzhiyun 			cpu_relax();
111*4882a593Smuzhiyun 		udelay(50);
112*4882a593Smuzhiyun 	}
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	/* Write out the i2c chip address and specify operation */
115*4882a593Smuzhiyun 	addr <<= 1;
116*4882a593Smuzhiyun 	if (rd)
117*4882a593Smuzhiyun 		addr |= 1;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	/* zero-byte xfers stop immediately */
120*4882a593Smuzhiyun 	if (q)
121*4882a593Smuzhiyun 		addr |= PSC_SMBTXRX_STP;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	/* Put byte into fifo, start up master. */
124*4882a593Smuzhiyun 	WR(adap, PSC_SMBTXRX, addr);
125*4882a593Smuzhiyun 	WR(adap, PSC_SMBPCR, PSC_SMBPCR_MS);
126*4882a593Smuzhiyun 	if (wait_ack(adap))
127*4882a593Smuzhiyun 		return -EIO;
128*4882a593Smuzhiyun 	return (q) ? wait_master_done(adap) : 0;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
wait_for_rx_byte(struct i2c_au1550_data * adap,unsigned char * out)131*4882a593Smuzhiyun static int wait_for_rx_byte(struct i2c_au1550_data *adap, unsigned char *out)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	int j;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	if (wait_xfer_done(adap))
136*4882a593Smuzhiyun 		return -EIO;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	j =  adap->xfer_timeout * 100;
139*4882a593Smuzhiyun 	do {
140*4882a593Smuzhiyun 		j--;
141*4882a593Smuzhiyun 		if (j <= 0)
142*4882a593Smuzhiyun 			return -EIO;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 		if ((RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_RE) == 0)
145*4882a593Smuzhiyun 			j = 0;
146*4882a593Smuzhiyun 		else
147*4882a593Smuzhiyun 			udelay(1);
148*4882a593Smuzhiyun 	} while (j > 0);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	*out = RD(adap, PSC_SMBTXRX);
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	return 0;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun 
i2c_read(struct i2c_au1550_data * adap,unsigned char * buf,unsigned int len)155*4882a593Smuzhiyun static int i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
156*4882a593Smuzhiyun 		    unsigned int len)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	int i;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	if (len == 0)
161*4882a593Smuzhiyun 		return 0;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	/* A read is performed by stuffing the transmit fifo with
164*4882a593Smuzhiyun 	 * zero bytes for timing, waiting for bytes to appear in the
165*4882a593Smuzhiyun 	 * receive fifo, then reading the bytes.
166*4882a593Smuzhiyun 	 */
167*4882a593Smuzhiyun 	i = 0;
168*4882a593Smuzhiyun 	while (i < (len - 1)) {
169*4882a593Smuzhiyun 		WR(adap, PSC_SMBTXRX, 0);
170*4882a593Smuzhiyun 		if (wait_for_rx_byte(adap, &buf[i]))
171*4882a593Smuzhiyun 			return -EIO;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 		i++;
174*4882a593Smuzhiyun 	}
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	/* The last byte has to indicate transfer done. */
177*4882a593Smuzhiyun 	WR(adap, PSC_SMBTXRX, PSC_SMBTXRX_STP);
178*4882a593Smuzhiyun 	if (wait_master_done(adap))
179*4882a593Smuzhiyun 		return -EIO;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	buf[i] = (unsigned char)(RD(adap, PSC_SMBTXRX) & 0xff);
182*4882a593Smuzhiyun 	return 0;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
i2c_write(struct i2c_au1550_data * adap,unsigned char * buf,unsigned int len)185*4882a593Smuzhiyun static int i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
186*4882a593Smuzhiyun 		     unsigned int len)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	int i;
189*4882a593Smuzhiyun 	unsigned long data;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	if (len == 0)
192*4882a593Smuzhiyun 		return 0;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	i = 0;
195*4882a593Smuzhiyun 	while (i < (len-1)) {
196*4882a593Smuzhiyun 		data = buf[i];
197*4882a593Smuzhiyun 		WR(adap, PSC_SMBTXRX, data);
198*4882a593Smuzhiyun 		if (wait_ack(adap))
199*4882a593Smuzhiyun 			return -EIO;
200*4882a593Smuzhiyun 		i++;
201*4882a593Smuzhiyun 	}
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	/* The last byte has to indicate transfer done. */
204*4882a593Smuzhiyun 	data = buf[i];
205*4882a593Smuzhiyun 	data |= PSC_SMBTXRX_STP;
206*4882a593Smuzhiyun 	WR(adap, PSC_SMBTXRX, data);
207*4882a593Smuzhiyun 	if (wait_master_done(adap))
208*4882a593Smuzhiyun 		return -EIO;
209*4882a593Smuzhiyun 	return 0;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun static int
au1550_xfer(struct i2c_adapter * i2c_adap,struct i2c_msg * msgs,int num)213*4882a593Smuzhiyun au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun 	struct i2c_au1550_data *adap = i2c_adap->algo_data;
216*4882a593Smuzhiyun 	struct i2c_msg *p;
217*4882a593Smuzhiyun 	int i, err = 0;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	WR(adap, PSC_CTRL, PSC_CTRL_ENABLE);
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	for (i = 0; !err && i < num; i++) {
222*4882a593Smuzhiyun 		p = &msgs[i];
223*4882a593Smuzhiyun 		err = do_address(adap, p->addr, p->flags & I2C_M_RD,
224*4882a593Smuzhiyun 				 (p->len == 0));
225*4882a593Smuzhiyun 		if (err || !p->len)
226*4882a593Smuzhiyun 			continue;
227*4882a593Smuzhiyun 		if (p->flags & I2C_M_RD)
228*4882a593Smuzhiyun 			err = i2c_read(adap, p->buf, p->len);
229*4882a593Smuzhiyun 		else
230*4882a593Smuzhiyun 			err = i2c_write(adap, p->buf, p->len);
231*4882a593Smuzhiyun 	}
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	/* Return the number of messages processed, or the error code.
234*4882a593Smuzhiyun 	*/
235*4882a593Smuzhiyun 	if (err == 0)
236*4882a593Smuzhiyun 		err = num;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	WR(adap, PSC_CTRL, PSC_CTRL_SUSPEND);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	return err;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun 
au1550_func(struct i2c_adapter * adap)243*4882a593Smuzhiyun static u32 au1550_func(struct i2c_adapter *adap)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun static const struct i2c_algorithm au1550_algo = {
249*4882a593Smuzhiyun 	.master_xfer	= au1550_xfer,
250*4882a593Smuzhiyun 	.functionality	= au1550_func,
251*4882a593Smuzhiyun };
252*4882a593Smuzhiyun 
i2c_au1550_setup(struct i2c_au1550_data * priv)253*4882a593Smuzhiyun static void i2c_au1550_setup(struct i2c_au1550_data *priv)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun 	unsigned long cfg;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
258*4882a593Smuzhiyun 	WR(priv, PSC_SEL, PSC_SEL_PS_SMBUSMODE);
259*4882a593Smuzhiyun 	WR(priv, PSC_SMBCFG, 0);
260*4882a593Smuzhiyun 	WR(priv, PSC_CTRL, PSC_CTRL_ENABLE);
261*4882a593Smuzhiyun 	while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
262*4882a593Smuzhiyun 		cpu_relax();
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	cfg = PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | PSC_SMBCFG_DD_DISABLE;
265*4882a593Smuzhiyun 	WR(priv, PSC_SMBCFG, cfg);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	/* Divide by 8 to get a 6.25 MHz clock.  The later protocol
268*4882a593Smuzhiyun 	 * timings are based on this clock.
269*4882a593Smuzhiyun 	 */
270*4882a593Smuzhiyun 	cfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
271*4882a593Smuzhiyun 	WR(priv, PSC_SMBCFG, cfg);
272*4882a593Smuzhiyun 	WR(priv, PSC_SMBMSK, PSC_SMBMSK_ALLMASK);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	/* Set the protocol timer values.  See Table 71 in the
275*4882a593Smuzhiyun 	 * Au1550 Data Book for standard timing values.
276*4882a593Smuzhiyun 	 */
277*4882a593Smuzhiyun 	WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(20) | \
278*4882a593Smuzhiyun 		PSC_SMBTMR_SET_PU(20) | PSC_SMBTMR_SET_SH(20) | \
279*4882a593Smuzhiyun 		PSC_SMBTMR_SET_SU(20) | PSC_SMBTMR_SET_CL(20) | \
280*4882a593Smuzhiyun 		PSC_SMBTMR_SET_CH(20));
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	cfg |= PSC_SMBCFG_DE_ENABLE;
283*4882a593Smuzhiyun 	WR(priv, PSC_SMBCFG, cfg);
284*4882a593Smuzhiyun 	while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
285*4882a593Smuzhiyun 		cpu_relax();
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	WR(priv, PSC_CTRL, PSC_CTRL_SUSPEND);
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun 
i2c_au1550_disable(struct i2c_au1550_data * priv)290*4882a593Smuzhiyun static void i2c_au1550_disable(struct i2c_au1550_data *priv)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun 	WR(priv, PSC_SMBCFG, 0);
293*4882a593Smuzhiyun 	WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun /*
297*4882a593Smuzhiyun  * registering functions to load algorithms at runtime
298*4882a593Smuzhiyun  * Prior to calling us, the 50MHz clock frequency and routing
299*4882a593Smuzhiyun  * must have been set up for the PSC indicated by the adapter.
300*4882a593Smuzhiyun  */
301*4882a593Smuzhiyun static int
i2c_au1550_probe(struct platform_device * pdev)302*4882a593Smuzhiyun i2c_au1550_probe(struct platform_device *pdev)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	struct i2c_au1550_data *priv;
305*4882a593Smuzhiyun 	struct resource *r;
306*4882a593Smuzhiyun 	int ret;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	priv = devm_kzalloc(&pdev->dev, sizeof(struct i2c_au1550_data),
309*4882a593Smuzhiyun 			    GFP_KERNEL);
310*4882a593Smuzhiyun 	if (!priv)
311*4882a593Smuzhiyun 		return -ENOMEM;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
314*4882a593Smuzhiyun 	priv->psc_base = devm_ioremap_resource(&pdev->dev, r);
315*4882a593Smuzhiyun 	if (IS_ERR(priv->psc_base))
316*4882a593Smuzhiyun 		return PTR_ERR(priv->psc_base);
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	priv->xfer_timeout = 200;
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	priv->adap.nr = pdev->id;
321*4882a593Smuzhiyun 	priv->adap.algo = &au1550_algo;
322*4882a593Smuzhiyun 	priv->adap.algo_data = priv;
323*4882a593Smuzhiyun 	priv->adap.dev.parent = &pdev->dev;
324*4882a593Smuzhiyun 	strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	/* Now, set up the PSC for SMBus PIO mode. */
327*4882a593Smuzhiyun 	i2c_au1550_setup(priv);
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	ret = i2c_add_numbered_adapter(&priv->adap);
330*4882a593Smuzhiyun 	if (ret) {
331*4882a593Smuzhiyun 		i2c_au1550_disable(priv);
332*4882a593Smuzhiyun 		return ret;
333*4882a593Smuzhiyun 	}
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	platform_set_drvdata(pdev, priv);
336*4882a593Smuzhiyun 	return 0;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun 
i2c_au1550_remove(struct platform_device * pdev)339*4882a593Smuzhiyun static int i2c_au1550_remove(struct platform_device *pdev)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun 	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	i2c_del_adapter(&priv->adap);
344*4882a593Smuzhiyun 	i2c_au1550_disable(priv);
345*4882a593Smuzhiyun 	return 0;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun #ifdef CONFIG_PM
i2c_au1550_suspend(struct device * dev)349*4882a593Smuzhiyun static int i2c_au1550_suspend(struct device *dev)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun 	struct i2c_au1550_data *priv = dev_get_drvdata(dev);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	i2c_au1550_disable(priv);
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	return 0;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun 
i2c_au1550_resume(struct device * dev)358*4882a593Smuzhiyun static int i2c_au1550_resume(struct device *dev)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun 	struct i2c_au1550_data *priv = dev_get_drvdata(dev);
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	i2c_au1550_setup(priv);
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	return 0;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun static const struct dev_pm_ops i2c_au1550_pmops = {
368*4882a593Smuzhiyun 	.suspend	= i2c_au1550_suspend,
369*4882a593Smuzhiyun 	.resume		= i2c_au1550_resume,
370*4882a593Smuzhiyun };
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun #define AU1XPSC_SMBUS_PMOPS (&i2c_au1550_pmops)
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun #else
375*4882a593Smuzhiyun #define AU1XPSC_SMBUS_PMOPS NULL
376*4882a593Smuzhiyun #endif
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun static struct platform_driver au1xpsc_smbus_driver = {
379*4882a593Smuzhiyun 	.driver = {
380*4882a593Smuzhiyun 		.name	= "au1xpsc_smbus",
381*4882a593Smuzhiyun 		.pm	= AU1XPSC_SMBUS_PMOPS,
382*4882a593Smuzhiyun 	},
383*4882a593Smuzhiyun 	.probe		= i2c_au1550_probe,
384*4882a593Smuzhiyun 	.remove		= i2c_au1550_remove,
385*4882a593Smuzhiyun };
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun module_platform_driver(au1xpsc_smbus_driver);
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
390*4882a593Smuzhiyun MODULE_DESCRIPTION("SMBus adapter Alchemy pb1550");
391*4882a593Smuzhiyun MODULE_LICENSE("GPL");
392*4882a593Smuzhiyun MODULE_ALIAS("platform:au1xpsc_smbus");
393