Blame view

drivers/i2c/busses/i2c-eg20t.c 24.5 KB
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
1
  /*
8956dc102   Tomoya MORINAGA   i2c-eg20t: Change...
2
   * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
3
4
5
6
7
8
9
10
11
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; version 2 of the License.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
12
13
14
15
16
   */
  
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/delay.h>
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
17
18
19
20
21
22
23
24
25
26
  #include <linux/errno.h>
  #include <linux/i2c.h>
  #include <linux/fs.h>
  #include <linux/io.h>
  #include <linux/types.h>
  #include <linux/interrupt.h>
  #include <linux/jiffies.h>
  #include <linux/pci.h>
  #include <linux/mutex.h>
  #include <linux/ktime.h>
6dbc2f35a   Wolfram Sang   i2c-eg20t: includ...
27
  #include <linux/slab.h>
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  
  #define PCH_EVENT_SET	0	/* I2C Interrupt Event Set Status */
  #define PCH_EVENT_NONE	1	/* I2C Interrupt Event Clear Status */
  #define PCH_MAX_CLK		100000	/* Maximum Clock speed in MHz */
  #define PCH_BUFFER_MODE_ENABLE	0x0002	/* flag for Buffer mode enable */
  #define PCH_EEPROM_SW_RST_MODE_ENABLE	0x0008	/* EEPROM SW RST enable flag */
  
  #define PCH_I2CSADR	0x00	/* I2C slave address register */
  #define PCH_I2CCTL	0x04	/* I2C control register */
  #define PCH_I2CSR	0x08	/* I2C status register */
  #define PCH_I2CDR	0x0C	/* I2C data register */
  #define PCH_I2CMON	0x10	/* I2C bus monitor register */
  #define PCH_I2CBC	0x14	/* I2C bus transfer rate setup counter */
  #define PCH_I2CMOD	0x18	/* I2C mode register */
  #define PCH_I2CBUFSLV	0x1C	/* I2C buffer mode slave address register */
  #define PCH_I2CBUFSUB	0x20	/* I2C buffer mode subaddress register */
  #define PCH_I2CBUFFOR	0x24	/* I2C buffer mode format register */
  #define PCH_I2CBUFCTL	0x28	/* I2C buffer mode control register */
  #define PCH_I2CBUFMSK	0x2C	/* I2C buffer mode interrupt mask register */
  #define PCH_I2CBUFSTA	0x30	/* I2C buffer mode status register */
  #define PCH_I2CBUFLEV	0x34	/* I2C buffer mode level register */
  #define PCH_I2CESRFOR	0x38	/* EEPROM software reset mode format register */
  #define PCH_I2CESRCTL	0x3C	/* EEPROM software reset mode ctrl register */
  #define PCH_I2CESRMSK	0x40	/* EEPROM software reset mode */
  #define PCH_I2CESRSTA	0x44	/* EEPROM software reset mode status register */
  #define PCH_I2CTMR	0x48	/* I2C timer register */
  #define PCH_I2CSRST	0xFC	/* I2C reset register */
  #define PCH_I2CNF	0xF8	/* I2C noise filter register */
  
  #define BUS_IDLE_TIMEOUT	20
  #define PCH_I2CCTL_I2CMEN	0x0080
  #define TEN_BIT_ADDR_DEFAULT	0xF000
  #define TEN_BIT_ADDR_MASK	0xF0
  #define PCH_START		0x0020
c249ac207   Tomoya MORINAGA   i2c-eg20t: Fix 10...
62
  #define PCH_RESTART		0x0004
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  #define PCH_ESR_START		0x0001
  #define PCH_BUFF_START		0x1
  #define PCH_REPSTART		0x0004
  #define PCH_ACK			0x0008
  #define PCH_GETACK		0x0001
  #define CLR_REG			0x0
  #define I2C_RD			0x1
  #define I2CMCF_BIT		0x0080
  #define I2CMIF_BIT		0x0002
  #define I2CMAL_BIT		0x0010
  #define I2CBMFI_BIT		0x0001
  #define I2CBMAL_BIT		0x0002
  #define I2CBMNA_BIT		0x0004
  #define I2CBMTO_BIT		0x0008
  #define I2CBMIS_BIT		0x0010
  #define I2CESRFI_BIT		0X0001
  #define I2CESRTO_BIT		0x0002
  #define I2CESRFIIE_BIT		0x1
  #define I2CESRTOIE_BIT		0x2
  #define I2CBMDZ_BIT		0x0040
  #define I2CBMAG_BIT		0x0020
  #define I2CMBB_BIT		0x0020
  #define BUFFER_MODE_MASK	(I2CBMFI_BIT | I2CBMAL_BIT | I2CBMNA_BIT | \
  				I2CBMTO_BIT | I2CBMIS_BIT)
  #define I2C_ADDR_MSK		0xFF
  #define I2C_MSB_2B_MSK		0x300
  #define FAST_MODE_CLK		400
  #define FAST_MODE_EN		0x0001
  #define SUB_ADDR_LEN_MAX	4
  #define BUF_LEN_MAX		32
  #define PCH_BUFFER_MODE		0x1
  #define EEPROM_SW_RST_MODE	0x0002
  #define NORMAL_INTR_ENBL	0x0300
  #define EEPROM_RST_INTR_ENBL	(I2CESRFIIE_BIT | I2CESRTOIE_BIT)
  #define EEPROM_RST_INTR_DISBL	0x0
  #define BUFFER_MODE_INTR_ENBL	0x001F
  #define BUFFER_MODE_INTR_DISBL	0x0
  #define NORMAL_MODE		0x0
  #define BUFFER_MODE		0x1
  #define EEPROM_SR_MODE		0x2
  #define I2C_TX_MODE		0x0010
  #define PCH_BUF_TX		0xFFF7
  #define PCH_BUF_RD		0x0008
  #define I2C_ERROR_MASK	(I2CESRTO_EVENT | I2CBMIS_EVENT | I2CBMTO_EVENT | \
  			I2CBMNA_EVENT | I2CBMAL_EVENT | I2CMAL_EVENT)
  #define I2CMAL_EVENT		0x0001
  #define I2CMCF_EVENT		0x0002
  #define I2CBMFI_EVENT		0x0004
  #define I2CBMAL_EVENT		0x0008
  #define I2CBMNA_EVENT		0x0010
  #define I2CBMTO_EVENT		0x0020
  #define I2CBMIS_EVENT		0x0040
  #define I2CESRFI_EVENT		0x0080
  #define I2CESRTO_EVENT		0x0100
  #define PCI_DEVICE_ID_PCH_I2C	0x8817
  
  #define pch_dbg(adap, fmt, arg...)  \
  	dev_dbg(adap->pch_adapter.dev.parent, "%s :" fmt, __func__, ##arg)
  
  #define pch_err(adap, fmt, arg...)  \
  	dev_err(adap->pch_adapter.dev.parent, "%s :" fmt, __func__, ##arg)
  
  #define pch_pci_err(pdev, fmt, arg...)  \
  	dev_err(&pdev->dev, "%s :" fmt, __func__, ##arg)
  
  #define pch_pci_dbg(pdev, fmt, arg...)  \
  	dev_dbg(&pdev->dev, "%s :" fmt, __func__, ##arg)
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
130
131
132
  /*
  Set the number of I2C instance max
  Intel EG20T PCH :		1ch
8956dc102   Tomoya MORINAGA   i2c-eg20t: Change...
133
134
  LAPIS Semiconductor ML7213 IOH :	2ch
  LAPIS Semiconductor ML7831 IOH :	1ch
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
135
136
  */
  #define PCH_I2C_MAX_DEV			2
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  /**
   * struct i2c_algo_pch_data - for I2C driver functionalities
   * @pch_adapter:		stores the reference to i2c_adapter structure
   * @p_adapter_info:		stores the reference to adapter_info structure
   * @pch_base_address:		specifies the remapped base address
   * @pch_buff_mode_en:		specifies if buffer mode is enabled
   * @pch_event_flag:		specifies occurrence of interrupt events
   * @pch_i2c_xfer_in_progress:	specifies whether the transfer is completed
   */
  struct i2c_algo_pch_data {
  	struct i2c_adapter pch_adapter;
  	struct adapter_info *p_adapter_info;
  	void __iomem *pch_base_address;
  	int pch_buff_mode_en;
  	u32 pch_event_flag;
  	bool pch_i2c_xfer_in_progress;
  };
  
  /**
   * struct adapter_info - This structure holds the adapter information for the
  			 PCH i2c controller
   * @pch_data:		stores a list of i2c_algo_pch_data
   * @pch_i2c_suspended:	specifies whether the system is suspended or not
   *			perhaps with more lines and words.
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
161
   * @ch_num:		specifies the number of i2c instance
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
162
163
164
165
   *
   * pch_data has as many elements as maximum I2C channels
   */
  struct adapter_info {
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
166
  	struct i2c_algo_pch_data pch_data[PCH_I2C_MAX_DEV];
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
167
  	bool pch_i2c_suspended;
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
168
  	int ch_num;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
169
170
171
172
173
174
175
  };
  
  
  static int pch_i2c_speed = 100; /* I2C bus speed in Kbps */
  static int pch_clk = 50000;	/* specifies I2C clock speed in KHz */
  static wait_queue_head_t pch_event;
  static DEFINE_MUTEX(pch_mutex);
8956dc102   Tomoya MORINAGA   i2c-eg20t: Change...
176
  /* Definition for ML7213 by LAPIS Semiconductor */
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
177
178
  #define PCI_VENDOR_ID_ROHM		0x10DB
  #define PCI_DEVICE_ID_ML7213_I2C	0x802D
efbe0f27c   Tomoya MORINAGA   i2c-eg20t: Suppor...
179
  #define PCI_DEVICE_ID_ML7223_I2C	0x8010
c3f4661f5   Tomoya MORINAGA   i2c-eg20t: Suppor...
180
  #define PCI_DEVICE_ID_ML7831_I2C	0x8817
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
181

392debf11   Jingoo Han   i2c: remove DEFIN...
182
  static const struct pci_device_id pch_pcidev_id[] = {
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
183
184
  	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_I2C),   1, },
  	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_I2C), 2, },
efbe0f27c   Tomoya MORINAGA   i2c-eg20t: Suppor...
185
  	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_I2C), 1, },
c3f4661f5   Tomoya MORINAGA   i2c-eg20t: Suppor...
186
  	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_I2C), 1, },
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  	{0,}
  };
  
  static irqreturn_t pch_i2c_handler(int irq, void *pData);
  
  static inline void pch_setbit(void __iomem *addr, u32 offset, u32 bitmask)
  {
  	u32 val;
  	val = ioread32(addr + offset);
  	val |= bitmask;
  	iowrite32(val, addr + offset);
  }
  
  static inline void pch_clrbit(void __iomem *addr, u32 offset, u32 bitmask)
  {
  	u32 val;
  	val = ioread32(addr + offset);
  	val &= (~bitmask);
  	iowrite32(val, addr + offset);
  }
  
  /**
   * pch_i2c_init() - hardware initialization of I2C module
   * @adap:	Pointer to struct i2c_algo_pch_data.
   */
  static void pch_i2c_init(struct i2c_algo_pch_data *adap)
  {
  	void __iomem *p = adap->pch_base_address;
  	u32 pch_i2cbc;
  	u32 pch_i2ctmr;
  	u32 reg_value;
  
  	/* reset I2C controller */
  	iowrite32(0x01, p + PCH_I2CSRST);
  	msleep(20);
  	iowrite32(0x0, p + PCH_I2CSRST);
  
  	/* Initialize I2C registers */
  	iowrite32(0x21, p + PCH_I2CNF);
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
226
  	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_I2CCTL_I2CMEN);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
227
228
229
230
231
232
233
234
235
236
237
238
239
  
  	if (pch_i2c_speed != 400)
  		pch_i2c_speed = 100;
  
  	reg_value = PCH_I2CCTL_I2CMEN;
  	if (pch_i2c_speed == FAST_MODE_CLK) {
  		reg_value |= FAST_MODE_EN;
  		pch_dbg(adap, "Fast mode enabled
  ");
  	}
  
  	if (pch_clk > PCH_MAX_CLK)
  		pch_clk = 62500;
ff35e8b18   Toshiharu Okada   i2c-eg20t: modifi...
240
  	pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / (pch_i2c_speed * 8);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
  	/* Set transfer speed in I2CBC */
  	iowrite32(pch_i2cbc, p + PCH_I2CBC);
  
  	pch_i2ctmr = (pch_clk) / 8;
  	iowrite32(pch_i2ctmr, p + PCH_I2CTMR);
  
  	reg_value |= NORMAL_INTR_ENBL;	/* Enable interrupts in normal mode */
  	iowrite32(reg_value, p + PCH_I2CCTL);
  
  	pch_dbg(adap,
  		"I2CCTL=%x pch_i2cbc=%x pch_i2ctmr=%x Enable interrupts
  ",
  		ioread32(p + PCH_I2CCTL), pch_i2cbc, pch_i2ctmr);
  
  	init_waitqueue_head(&pch_event);
  }
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
257
258
259
  /**
   * pch_i2c_wait_for_bus_idle() - check the status of bus.
   * @adap:	Pointer to struct i2c_algo_pch_data.
0836c8090   Alexander Stein   i2c-eg20t: Rework...
260
   * @timeout:	waiting time counter (ms).
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
261
262
   */
  static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap,
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
263
  				     s32 timeout)
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
264
265
  {
  	void __iomem *p = adap->pch_base_address;
0836c8090   Alexander Stein   i2c-eg20t: Rework...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
  	int schedule = 0;
  	unsigned long end = jiffies + msecs_to_jiffies(timeout);
  
  	while (ioread32(p + PCH_I2CSR) & I2CMBB_BIT) {
  		if (time_after(jiffies, end)) {
  			pch_dbg(adap, "I2CSR = %x
  ", ioread32(p + PCH_I2CSR));
  			pch_err(adap, "%s: Timeout Error.return%d
  ",
  					__func__, -ETIME);
  			pch_i2c_init(adap);
  
  			return -ETIME;
  		}
  
  		if (!schedule)
  			/* Retry after some usecs */
  			udelay(5);
  		else
  			/* Wait a bit more without consuming CPU */
  			usleep_range(20, 1000);
  
  		schedule = 1;
  	}
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
290

0836c8090   Alexander Stein   i2c-eg20t: Rework...
291
  	return 0;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  }
  
  /**
   * pch_i2c_start() - Generate I2C start condition in normal mode.
   * @adap:	Pointer to struct i2c_algo_pch_data.
   *
   * Generate I2C start condition in normal mode by setting I2CCTL.I2CMSTA to 1.
   */
  static void pch_i2c_start(struct i2c_algo_pch_data *adap)
  {
  	void __iomem *p = adap->pch_base_address;
  	pch_dbg(adap, "I2CCTL = %x
  ", ioread32(p + PCH_I2CCTL));
  	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_START);
  }
  
  /**
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
309
310
311
312
313
314
315
316
317
318
319
   * pch_i2c_stop() - generate stop condition in normal mode.
   * @adap:	Pointer to struct i2c_algo_pch_data.
   */
  static void pch_i2c_stop(struct i2c_algo_pch_data *adap)
  {
  	void __iomem *p = adap->pch_base_address;
  	pch_dbg(adap, "I2CCTL = %x
  ", ioread32(p + PCH_I2CCTL));
  	/* clear the start bit */
  	pch_clrbit(adap->pch_base_address, PCH_I2CCTL, PCH_START);
  }
5cc056327   Tomoya MORINAGA   i2c-eg20t: add he...
320
321
  static int pch_i2c_wait_for_check_xfer(struct i2c_algo_pch_data *adap)
  {
199bca2a7   Tomoya MORINAGA   i2c-eg20t: Merge ...
322
  	long ret;
5e47eec00   Andreas Werner   i2c: i2c-eg20t: d...
323
  	void __iomem *p = adap->pch_base_address;
199bca2a7   Tomoya MORINAGA   i2c-eg20t: Merge ...
324
325
326
327
328
329
330
331
332
333
334
335
336
  
  	ret = wait_event_timeout(pch_event,
  			(adap->pch_event_flag != 0), msecs_to_jiffies(1000));
  	if (!ret) {
  		pch_err(adap, "%s:wait-event timeout
  ", __func__);
  		adap->pch_event_flag = 0;
  		pch_i2c_stop(adap);
  		pch_i2c_init(adap);
  		return -ETIMEDOUT;
  	}
  
  	if (adap->pch_event_flag & I2C_ERROR_MASK) {
5cc056327   Tomoya MORINAGA   i2c-eg20t: add he...
337
338
  		pch_err(adap, "Lost Arbitration
  ");
199bca2a7   Tomoya MORINAGA   i2c-eg20t: Merge ...
339
  		adap->pch_event_flag = 0;
5cc056327   Tomoya MORINAGA   i2c-eg20t: add he...
340
341
342
343
  		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
  		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
  		pch_i2c_init(adap);
  		return -EAGAIN;
199bca2a7   Tomoya MORINAGA   i2c-eg20t: Merge ...
344
345
346
  	}
  
  	adap->pch_event_flag = 0;
5e47eec00   Andreas Werner   i2c: i2c-eg20t: d...
347
348
349
350
  	if (ioread32(p + PCH_I2CSR) & PCH_GETACK) {
  		pch_dbg(adap, "Receive NACK for slave address setting
  ");
  		return -ENXIO;
5cc056327   Tomoya MORINAGA   i2c-eg20t: add he...
351
352
353
354
  	}
  
  	return 0;
  }
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
  /**
   * pch_i2c_repstart() - generate repeated start condition in normal mode
   * @adap:	Pointer to struct i2c_algo_pch_data.
   */
  static void pch_i2c_repstart(struct i2c_algo_pch_data *adap)
  {
  	void __iomem *p = adap->pch_base_address;
  	pch_dbg(adap, "I2CCTL = %x
  ", ioread32(p + PCH_I2CCTL));
  	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_REPSTART);
  }
  
  /**
   * pch_i2c_writebytes() - write data to I2C bus in normal mode
   * @i2c_adap:	Pointer to the struct i2c_adapter.
   * @last:	specifies whether last message or not.
   *		In the case of compound mode it will be 1 for last message,
   *		otherwise 0.
   * @first:	specifies whether first message or not.
   *		1 for first message otherwise 0.
   */
  static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
  			      struct i2c_msg *msgs, u32 last, u32 first)
  {
  	struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
  	u8 *buf;
  	u32 length;
  	u32 addr;
  	u32 addr_2_msb;
  	u32 addr_8_lsb;
  	s32 wrcount;
12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
386
  	s32 rtn;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
  	void __iomem *p = adap->pch_base_address;
  
  	length = msgs->len;
  	buf = msgs->buf;
  	addr = msgs->addr;
  
  	/* enable master tx */
  	pch_setbit(adap->pch_base_address, PCH_I2CCTL, I2C_TX_MODE);
  
  	pch_dbg(adap, "I2CCTL = %x msgs->len = %d
  ", ioread32(p + PCH_I2CCTL),
  		length);
  
  	if (first) {
  		if (pch_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) == -ETIME)
  			return -ETIME;
  	}
  
  	if (msgs->flags & I2C_M_TEN) {
c249ac207   Tomoya MORINAGA   i2c-eg20t: Fix 10...
406
  		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7) & 0x06;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
407
408
409
  		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
  		if (first)
  			pch_i2c_start(adap);
12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
410

5cc056327   Tomoya MORINAGA   i2c-eg20t: add he...
411
412
413
414
415
416
  		rtn = pch_i2c_wait_for_check_xfer(adap);
  		if (rtn)
  			return rtn;
  
  		addr_8_lsb = (addr & I2C_ADDR_MSK);
  		iowrite32(addr_8_lsb, p + PCH_I2CDR);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
417
418
419
420
421
422
  	} else {
  		/* set 7 bit slave address and R/W bit as 0 */
  		iowrite32(addr << 1, p + PCH_I2CDR);
  		if (first)
  			pch_i2c_start(adap);
  	}
5cc056327   Tomoya MORINAGA   i2c-eg20t: add he...
423
424
425
  	rtn = pch_i2c_wait_for_check_xfer(adap);
  	if (rtn)
  		return rtn;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
426

12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
427
428
429
430
431
  	for (wrcount = 0; wrcount < length; ++wrcount) {
  		/* write buffer value to I2C data register */
  		iowrite32(buf[wrcount], p + PCH_I2CDR);
  		pch_dbg(adap, "writing %x to Data register
  ", buf[wrcount]);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
432

5cc056327   Tomoya MORINAGA   i2c-eg20t: add he...
433
434
435
436
437
438
  		rtn = pch_i2c_wait_for_check_xfer(adap);
  		if (rtn)
  			return rtn;
  
  		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMCF_BIT);
  		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
439
  	}
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
440

12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
441
442
  	/* check if this is the last message */
  	if (last)
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
443
  		pch_i2c_stop(adap);
12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
444
445
  	else
  		pch_i2c_repstart(adap);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
  
  	pch_dbg(adap, "return=%d
  ", wrcount);
  
  	return wrcount;
  }
  
  /**
   * pch_i2c_sendack() - send ACK
   * @adap:	Pointer to struct i2c_algo_pch_data.
   */
  static void pch_i2c_sendack(struct i2c_algo_pch_data *adap)
  {
  	void __iomem *p = adap->pch_base_address;
  	pch_dbg(adap, "I2CCTL = %x
  ", ioread32(p + PCH_I2CCTL));
  	pch_clrbit(adap->pch_base_address, PCH_I2CCTL, PCH_ACK);
  }
  
  /**
   * pch_i2c_sendnack() - send NACK
   * @adap:	Pointer to struct i2c_algo_pch_data.
   */
  static void pch_i2c_sendnack(struct i2c_algo_pch_data *adap)
  {
  	void __iomem *p = adap->pch_base_address;
  	pch_dbg(adap, "I2CCTL = %x
  ", ioread32(p + PCH_I2CCTL));
  	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_ACK);
  }
  
  /**
c249ac207   Tomoya MORINAGA   i2c-eg20t: Fix 10...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
   * pch_i2c_restart() - Generate I2C restart condition in normal mode.
   * @adap:	Pointer to struct i2c_algo_pch_data.
   *
   * Generate I2C restart condition in normal mode by setting I2CCTL.I2CRSTA.
   */
  static void pch_i2c_restart(struct i2c_algo_pch_data *adap)
  {
  	void __iomem *p = adap->pch_base_address;
  	pch_dbg(adap, "I2CCTL = %x
  ", ioread32(p + PCH_I2CCTL));
  	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_RESTART);
  }
  
  /**
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
492
493
494
495
496
497
   * pch_i2c_readbytes() - read data  from I2C bus in normal mode.
   * @i2c_adap:	Pointer to the struct i2c_adapter.
   * @msgs:	Pointer to i2c_msg structure.
   * @last:	specifies whether last message or not.
   * @first:	specifies whether first message or not.
   */
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
498
499
  static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
  			     u32 last, u32 first)
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
500
501
502
503
504
505
506
507
  {
  	struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
  
  	u8 *buf;
  	u32 count;
  	u32 length;
  	u32 addr;
  	u32 addr_2_msb;
c249ac207   Tomoya MORINAGA   i2c-eg20t: Fix 10...
508
  	u32 addr_8_lsb;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
509
  	void __iomem *p = adap->pch_base_address;
12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
510
  	s32 rtn;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
511
512
513
514
515
516
517
518
519
520
521
522
523
524
  
  	length = msgs->len;
  	buf = msgs->buf;
  	addr = msgs->addr;
  
  	/* enable master reception */
  	pch_clrbit(adap->pch_base_address, PCH_I2CCTL, I2C_TX_MODE);
  
  	if (first) {
  		if (pch_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) == -ETIME)
  			return -ETIME;
  	}
  
  	if (msgs->flags & I2C_M_TEN) {
c249ac207   Tomoya MORINAGA   i2c-eg20t: Fix 10...
525
  		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
526
  		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
c249ac207   Tomoya MORINAGA   i2c-eg20t: Fix 10...
527
528
  		if (first)
  			pch_i2c_start(adap);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
529

5cc056327   Tomoya MORINAGA   i2c-eg20t: add he...
530
531
532
533
534
535
  		rtn = pch_i2c_wait_for_check_xfer(adap);
  		if (rtn)
  			return rtn;
  
  		addr_8_lsb = (addr & I2C_ADDR_MSK);
  		iowrite32(addr_8_lsb, p + PCH_I2CDR);
c249ac207   Tomoya MORINAGA   i2c-eg20t: Fix 10...
536
  		pch_i2c_restart(adap);
5cc056327   Tomoya MORINAGA   i2c-eg20t: add he...
537
538
539
540
541
542
543
  
  		rtn = pch_i2c_wait_for_check_xfer(adap);
  		if (rtn)
  			return rtn;
  
  		addr_2_msb |= I2C_RD;
  		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
544
545
546
547
548
549
550
551
552
  	} else {
  		/* 7 address bits + R/W bit */
  		addr = (((addr) << 1) | (I2C_RD));
  		iowrite32(addr, p + PCH_I2CDR);
  	}
  
  	/* check if it is the first message */
  	if (first)
  		pch_i2c_start(adap);
5cc056327   Tomoya MORINAGA   i2c-eg20t: add he...
553
554
555
  	rtn = pch_i2c_wait_for_check_xfer(adap);
  	if (rtn)
  		return rtn;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
556

12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
557
558
559
  	if (length == 0) {
  		pch_i2c_stop(adap);
  		ioread32(p + PCH_I2CDR); /* Dummy read needs */
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
560

12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
561
562
563
564
565
  		count = length;
  	} else {
  		int read_index;
  		int loop;
  		pch_i2c_sendack(adap);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
566

12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
567
568
569
  		/* Dummy read */
  		for (loop = 1, read_index = 0; loop < length; loop++) {
  			buf[read_index] = ioread32(p + PCH_I2CDR);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
570

12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
571
572
  			if (loop != 1)
  				read_index++;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
573

5cc056327   Tomoya MORINAGA   i2c-eg20t: add he...
574
575
576
  			rtn = pch_i2c_wait_for_check_xfer(adap);
  			if (rtn)
  				return rtn;
12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
577
  		}	/* end for */
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
578

12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
579
  		pch_i2c_sendnack(adap);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
580

12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
581
  		buf[read_index] = ioread32(p + PCH_I2CDR); /* Read final - 1 */
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
582

12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
583
584
  		if (length != 1)
  			read_index++;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
585

5cc056327   Tomoya MORINAGA   i2c-eg20t: add he...
586
587
588
  		rtn = pch_i2c_wait_for_check_xfer(adap);
  		if (rtn)
  			return rtn;
12bd31465   Tomoya MORINAGA   i2c-eg20t: Separa...
589
590
591
592
593
594
595
596
  
  		if (last)
  			pch_i2c_stop(adap);
  		else
  			pch_i2c_repstart(adap);
  
  		buf[read_index++] = ioread32(p + PCH_I2CDR); /* Read Final */
  		count = read_index;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
597
598
599
600
601
602
  	}
  
  	return count;
  }
  
  /**
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
603
   * pch_i2c_cb() - Interrupt handler Call back function
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
604
605
   * @adap:	Pointer to struct i2c_algo_pch_data.
   */
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
606
  static void pch_i2c_cb(struct i2c_algo_pch_data *adap)
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
  {
  	u32 sts;
  	void __iomem *p = adap->pch_base_address;
  
  	sts = ioread32(p + PCH_I2CSR);
  	sts &= (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT);
  	if (sts & I2CMAL_BIT)
  		adap->pch_event_flag |= I2CMAL_EVENT;
  
  	if (sts & I2CMCF_BIT)
  		adap->pch_event_flag |= I2CMCF_EVENT;
  
  	/* clear the applicable bits */
  	pch_clrbit(adap->pch_base_address, PCH_I2CSR, sts);
  
  	pch_dbg(adap, "PCH_I2CSR = %x
  ", ioread32(p + PCH_I2CSR));
  
  	wake_up(&pch_event);
  }
  
  /**
   * pch_i2c_handler() - interrupt handler for the PCH I2C controller
   * @irq:	irq number.
   * @pData:	cookie passed back to the handler function.
   */
  static irqreturn_t pch_i2c_handler(int irq, void *pData)
  {
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
  	u32 reg_val;
  	int flag;
  	int i;
  	struct adapter_info *adap_info = pData;
  	void __iomem *p;
  	u32 mode;
  
  	for (i = 0, flag = 0; i < adap_info->ch_num; i++) {
  		p = adap_info->pch_data[i].pch_base_address;
  		mode = ioread32(p + PCH_I2CMOD);
  		mode &= BUFFER_MODE | EEPROM_SR_MODE;
  		if (mode != NORMAL_MODE) {
  			pch_err(adap_info->pch_data,
  				"I2C-%d mode(%d) is not supported
  ", mode, i);
  			continue;
  		}
  		reg_val = ioread32(p + PCH_I2CSR);
  		if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT)) {
  			pch_i2c_cb(&adap_info->pch_data[i]);
  			flag = 1;
  		}
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
657
  	}
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
658
  	return flag ? IRQ_HANDLED : IRQ_NONE;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
659
660
661
662
663
664
665
666
667
  }
  
  /**
   * pch_i2c_xfer() - Reading adnd writing data through I2C bus
   * @i2c_adap:	Pointer to the struct i2c_adapter.
   * @msgs:	Pointer to i2c_msg structure.
   * @num:	number of messages.
   */
  static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
668
  			struct i2c_msg *msgs, s32 num)
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
669
670
671
672
  {
  	struct i2c_msg *pmsg;
  	u32 i = 0;
  	u32 status;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
673
674
675
676
677
678
  	s32 ret;
  
  	struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
  
  	ret = mutex_lock_interruptible(&pch_mutex);
  	if (ret)
772ae99c5   Wolfram Sang   i2c: eg20t: pass ...
679
  		return ret;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
680
681
682
683
684
685
686
687
688
689
690
  
  	if (adap->p_adapter_info->pch_i2c_suspended) {
  		mutex_unlock(&pch_mutex);
  		return -EBUSY;
  	}
  
  	pch_dbg(adap, "adap->p_adapter_info->pch_i2c_suspended is %d
  ",
  		adap->p_adapter_info->pch_i2c_suspended);
  	/* transfer not completed */
  	adap->pch_i2c_xfer_in_progress = true;
07e729ce8   Tomoya MORINAGA   i2c-eg20t : Fix t...
691
  	for (i = 0; i < num && ret >= 0; i++) {
7a9c42ccc   Tomoya MORINAGA   i2c-eg20t : Suppo...
692
693
694
695
696
697
  		pmsg = &msgs[i];
  		pmsg->flags |= adap->pch_buff_mode_en;
  		status = pmsg->flags;
  		pch_dbg(adap,
  			"After invoking I2C_MODE_SEL :flag= 0x%x
  ", status);
7a9c42ccc   Tomoya MORINAGA   i2c-eg20t : Suppo...
698
699
700
701
702
703
704
705
  
  		if ((status & (I2C_M_RD)) != false) {
  			ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num),
  						(i == 0));
  		} else {
  			ret = pch_i2c_writebytes(i2c_adap, pmsg, (i + 1 == num),
  						 (i == 0));
  		}
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
706
707
708
709
710
  	}
  
  	adap->pch_i2c_xfer_in_progress = false;	/* transfer completed */
  
  	mutex_unlock(&pch_mutex);
07e729ce8   Tomoya MORINAGA   i2c-eg20t : Fix t...
711
  	return (ret < 0) ? ret : num;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
  }
  
  /**
   * pch_i2c_func() - return the functionality of the I2C driver
   * @adap:	Pointer to struct i2c_algo_pch_data.
   */
  static u32 pch_i2c_func(struct i2c_adapter *adap)
  {
  	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
  }
  
  static struct i2c_algorithm pch_algorithm = {
  	.master_xfer = pch_i2c_xfer,
  	.functionality = pch_i2c_func
  };
  
  /**
   * pch_i2c_disbl_int() - Disable PCH I2C interrupts
   * @adap:	Pointer to struct i2c_algo_pch_data.
   */
  static void pch_i2c_disbl_int(struct i2c_algo_pch_data *adap)
  {
  	void __iomem *p = adap->pch_base_address;
  
  	pch_clrbit(adap->pch_base_address, PCH_I2CCTL, NORMAL_INTR_ENBL);
  
  	iowrite32(EEPROM_RST_INTR_DISBL, p + PCH_I2CESRMSK);
  
  	iowrite32(BUFFER_MODE_INTR_DISBL, p + PCH_I2CBUFMSK);
  }
0b255e927   Bill Pemberton   i2c: remove __dev...
742
  static int pch_i2c_probe(struct pci_dev *pdev,
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
743
  				   const struct pci_device_id *id)
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
744
745
  {
  	void __iomem *base_addr;
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
746
747
  	int ret;
  	int i, j;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
748
  	struct adapter_info *adap_info;
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
749
  	struct i2c_adapter *pch_adap;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
750
751
752
753
754
  
  	pch_pci_dbg(pdev, "Entered.
  ");
  
  	adap_info = kzalloc((sizeof(struct adapter_info)), GFP_KERNEL);
46797a2ad   Jingoo Han   i2c: remove unnec...
755
  	if (adap_info == NULL)
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
756
  		return -ENOMEM;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
  
  	ret = pci_enable_device(pdev);
  	if (ret) {
  		pch_pci_err(pdev, "pci_enable_device FAILED
  ");
  		goto err_pci_enable;
  	}
  
  	ret = pci_request_regions(pdev, KBUILD_MODNAME);
  	if (ret) {
  		pch_pci_err(pdev, "pci_request_regions FAILED
  ");
  		goto err_pci_req;
  	}
  
  	base_addr = pci_iomap(pdev, 1, 0);
  
  	if (base_addr == NULL) {
  		pch_pci_err(pdev, "pci_iomap FAILED
  ");
  		ret = -ENOMEM;
  		goto err_pci_iomap;
  	}
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
780
781
  	/* Set the number of I2C channel instance */
  	adap_info->ch_num = id->driver_data;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
782

0d5fb5ea7   Feng Tang   i2c-eg20t: correc...
783
784
785
786
787
788
789
  	ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
  		  KBUILD_MODNAME, adap_info);
  	if (ret) {
  		pch_pci_err(pdev, "request_irq FAILED
  ");
  		goto err_request_irq;
  	}
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
790
791
792
  	for (i = 0; i < adap_info->ch_num; i++) {
  		pch_adap = &adap_info->pch_data[i].pch_adapter;
  		adap_info->pch_i2c_suspended = false;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
793

173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
794
  		adap_info->pch_data[i].p_adapter_info = adap_info;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
795

173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
796
797
  		pch_adap->owner = THIS_MODULE;
  		pch_adap->class = I2C_CLASS_HWMON;
6188a3768   Wolfram Sang   i2c: eg20t: don't...
798
  		strlcpy(pch_adap->name, KBUILD_MODNAME, sizeof(pch_adap->name));
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
799
800
  		pch_adap->algo = &pch_algorithm;
  		pch_adap->algo_data = &adap_info->pch_data[i];
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
801

173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
802
803
  		/* base_addr + offset; */
  		adap_info->pch_data[i].pch_base_address = base_addr + 0x100 * i;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
804

173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
805
  		pch_adap->dev.parent = &pdev->dev;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
806

0d5fb5ea7   Feng Tang   i2c-eg20t: correc...
807
  		pch_i2c_init(&adap_info->pch_data[i]);
07e8a51ff   Feng Tang   i2c-eg20t: use i2...
808
809
810
  
  		pch_adap->nr = i;
  		ret = i2c_add_numbered_adapter(pch_adap);
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
811
812
813
  		if (ret) {
  			pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED
  ", i);
0d5fb5ea7   Feng Tang   i2c-eg20t: correc...
814
  			goto err_add_adapter;
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
815
  		}
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
816
817
818
819
820
821
  	}
  
  	pci_set_drvdata(pdev, adap_info);
  	pch_pci_dbg(pdev, "returns %d.
  ", ret);
  	return 0;
0d5fb5ea7   Feng Tang   i2c-eg20t: correc...
822
  err_add_adapter:
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
823
824
  	for (j = 0; j < i; j++)
  		i2c_del_adapter(&adap_info->pch_data[j].pch_adapter);
0d5fb5ea7   Feng Tang   i2c-eg20t: correc...
825
826
  	free_irq(pdev->irq, adap_info);
  err_request_irq:
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
827
828
829
830
831
832
833
834
835
  	pci_iounmap(pdev, base_addr);
  err_pci_iomap:
  	pci_release_regions(pdev);
  err_pci_req:
  	pci_disable_device(pdev);
  err_pci_enable:
  	kfree(adap_info);
  	return ret;
  }
0b255e927   Bill Pemberton   i2c: remove __dev...
836
  static void pch_i2c_remove(struct pci_dev *pdev)
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
837
  {
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
838
  	int i;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
839
  	struct adapter_info *adap_info = pci_get_drvdata(pdev);
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
840
  	free_irq(pdev->irq, adap_info);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
841

173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
842
843
844
  	for (i = 0; i < adap_info->ch_num; i++) {
  		pch_i2c_disbl_int(&adap_info->pch_data[i]);
  		i2c_del_adapter(&adap_info->pch_data[i].pch_adapter);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
845
  	}
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
846
847
848
849
  	if (adap_info->pch_data[0].pch_base_address)
  		pci_iounmap(pdev, adap_info->pch_data[0].pch_base_address);
  
  	for (i = 0; i < adap_info->ch_num; i++)
75fb1f25d   Wolfram Sang   i2c: eg20t: use N...
850
  		adap_info->pch_data[i].pch_base_address = NULL;
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
851

e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
852
853
854
855
856
857
858
859
860
861
  	pci_release_regions(pdev);
  
  	pci_disable_device(pdev);
  	kfree(adap_info);
  }
  
  #ifdef CONFIG_PM
  static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state)
  {
  	int ret;
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
862
  	int i;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
863
  	struct adapter_info *adap_info = pci_get_drvdata(pdev);
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
864
  	void __iomem *p = adap_info->pch_data[0].pch_base_address;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
865
866
  
  	adap_info->pch_i2c_suspended = true;
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
867
868
869
870
871
  	for (i = 0; i < adap_info->ch_num; i++) {
  		while ((adap_info->pch_data[i].pch_i2c_xfer_in_progress)) {
  			/* Wait until all channel transfers are completed */
  			msleep(20);
  		}
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
872
  	}
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
873

e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
874
  	/* Disable the i2c interrupts */
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
875
876
  	for (i = 0; i < adap_info->ch_num; i++)
  		pch_i2c_disbl_int(&adap_info->pch_data[i]);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
  
  	pch_pci_dbg(pdev, "I2CSR = %x I2CBUFSTA = %x I2CESRSTA = %x "
  		"invoked function pch_i2c_disbl_int successfully
  ",
  		ioread32(p + PCH_I2CSR), ioread32(p + PCH_I2CBUFSTA),
  		ioread32(p + PCH_I2CESRSTA));
  
  	ret = pci_save_state(pdev);
  
  	if (ret) {
  		pch_pci_err(pdev, "pci_save_state
  ");
  		return ret;
  	}
  
  	pci_enable_wake(pdev, PCI_D3hot, 0);
  	pci_disable_device(pdev);
  	pci_set_power_state(pdev, pci_choose_state(pdev, state));
  
  	return 0;
  }
  
  static int pch_i2c_resume(struct pci_dev *pdev)
  {
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
901
  	int i;
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
902
903
904
905
906
907
908
909
910
911
912
913
  	struct adapter_info *adap_info = pci_get_drvdata(pdev);
  
  	pci_set_power_state(pdev, PCI_D0);
  	pci_restore_state(pdev);
  
  	if (pci_enable_device(pdev) < 0) {
  		pch_pci_err(pdev, "pch_i2c_resume:pci_enable_device FAILED
  ");
  		return -EIO;
  	}
  
  	pci_enable_wake(pdev, PCI_D3hot, 0);
173442f27   Tomoya MORINAGA   i2c-eg20t: suppor...
914
915
  	for (i = 0; i < adap_info->ch_num; i++)
  		pch_i2c_init(&adap_info->pch_data[i]);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
916
917
918
919
920
921
922
923
924
925
926
927
928
929
  
  	adap_info->pch_i2c_suspended = false;
  
  	return 0;
  }
  #else
  #define pch_i2c_suspend NULL
  #define pch_i2c_resume NULL
  #endif
  
  static struct pci_driver pch_pcidriver = {
  	.name = KBUILD_MODNAME,
  	.id_table = pch_pcidev_id,
  	.probe = pch_i2c_probe,
0b255e927   Bill Pemberton   i2c: remove __dev...
930
  	.remove = pch_i2c_remove,
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
931
932
933
  	.suspend = pch_i2c_suspend,
  	.resume = pch_i2c_resume
  };
56f217889   Axel Lin   i2c/busses: Use m...
934
  module_pci_driver(pch_pcidriver);
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
935

8956dc102   Tomoya MORINAGA   i2c-eg20t: Change...
936
  MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semico ML7213/ML7223/ML7831 IOH I2C");
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
937
  MODULE_LICENSE("GPL");
096407136   Tomoya MORINAGA   i2c-eg20t: Modify...
938
  MODULE_AUTHOR("Tomoya MORINAGA. <tomoya.rohm@gmail.com>");
e9bc8fa5d   Tomoya MORINAGA   i2c-eg20t: add dr...
939
940
  module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR));
  module_param(pch_clk, int, (S_IRUSR | S_IWUSR));