1e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/*
28956dc102ca26357850830f1d26132719c1ce6eeTomoya MORINAGA * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
3e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA *
4e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * This program is free software; you can redistribute it and/or modify
5e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * it under the terms of the GNU General Public License as published by
6e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * the Free Software Foundation; version 2 of the License.
7e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA *
8e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * This program is distributed in the hope that it will be useful,
9e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * but WITHOUT ANY WARRANTY; without even the implied warranty of
10e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * GNU General Public License for more details.
12e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA *
13e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * You should have received a copy of the GNU General Public License
14e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * along with this program; if not, write to the Free Software
15e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
16e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
17e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
18e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/module.h>
19e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/kernel.h>
20e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/delay.h>
21e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/init.h>
22e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/errno.h>
23e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/i2c.h>
24e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/fs.h>
25e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/io.h>
26e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/types.h>
27e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/interrupt.h>
28e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/jiffies.h>
29e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/pci.h>
30e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/mutex.h>
31e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#include <linux/ktime.h>
326dbc2f35ab457770d121d119788fc89c79124734Wolfram Sang#include <linux/slab.h>
33e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
34e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_EVENT_SET	0	/* I2C Interrupt Event Set Status */
35e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_EVENT_NONE	1	/* I2C Interrupt Event Clear Status */
36e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_MAX_CLK		100000	/* Maximum Clock speed in MHz */
37e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_BUFFER_MODE_ENABLE	0x0002	/* flag for Buffer mode enable */
38e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_EEPROM_SW_RST_MODE_ENABLE	0x0008	/* EEPROM SW RST enable flag */
39e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
40e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CSADR	0x00	/* I2C slave address register */
41e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CCTL	0x04	/* I2C control register */
42e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CSR	0x08	/* I2C status register */
43e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CDR	0x0C	/* I2C data register */
44e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CMON	0x10	/* I2C bus monitor register */
45e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CBC	0x14	/* I2C bus transfer rate setup counter */
46e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CMOD	0x18	/* I2C mode register */
47e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CBUFSLV	0x1C	/* I2C buffer mode slave address register */
48e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CBUFSUB	0x20	/* I2C buffer mode subaddress register */
49e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CBUFFOR	0x24	/* I2C buffer mode format register */
50e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CBUFCTL	0x28	/* I2C buffer mode control register */
51e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CBUFMSK	0x2C	/* I2C buffer mode interrupt mask register */
52e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CBUFSTA	0x30	/* I2C buffer mode status register */
53e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CBUFLEV	0x34	/* I2C buffer mode level register */
54e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CESRFOR	0x38	/* EEPROM software reset mode format register */
55e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CESRCTL	0x3C	/* EEPROM software reset mode ctrl register */
56e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CESRMSK	0x40	/* EEPROM software reset mode */
57e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CESRSTA	0x44	/* EEPROM software reset mode status register */
58e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CTMR	0x48	/* I2C timer register */
59e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CSRST	0xFC	/* I2C reset register */
60e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CNF	0xF8	/* I2C noise filter register */
61e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
62e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define BUS_IDLE_TIMEOUT	20
63e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_I2CCTL_I2CMEN	0x0080
64e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define TEN_BIT_ADDR_DEFAULT	0xF000
65e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define TEN_BIT_ADDR_MASK	0xF0
66e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_START		0x0020
67c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA#define PCH_RESTART		0x0004
68e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_ESR_START		0x0001
69e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_BUFF_START		0x1
70e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_REPSTART		0x0004
71e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_ACK			0x0008
72e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_GETACK		0x0001
73e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define CLR_REG			0x0
74e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2C_RD			0x1
75e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CMCF_BIT		0x0080
76e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CMIF_BIT		0x0002
77e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CMAL_BIT		0x0010
78e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CBMFI_BIT		0x0001
79e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CBMAL_BIT		0x0002
80e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CBMNA_BIT		0x0004
81e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CBMTO_BIT		0x0008
82e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CBMIS_BIT		0x0010
83e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CESRFI_BIT		0X0001
84e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CESRTO_BIT		0x0002
85e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CESRFIIE_BIT		0x1
86e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CESRTOIE_BIT		0x2
87e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CBMDZ_BIT		0x0040
88e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CBMAG_BIT		0x0020
89e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CMBB_BIT		0x0020
90e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define BUFFER_MODE_MASK	(I2CBMFI_BIT | I2CBMAL_BIT | I2CBMNA_BIT | \
91e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA				I2CBMTO_BIT | I2CBMIS_BIT)
92e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2C_ADDR_MSK		0xFF
93e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2C_MSB_2B_MSK		0x300
94e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define FAST_MODE_CLK		400
95e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define FAST_MODE_EN		0x0001
96e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define SUB_ADDR_LEN_MAX	4
97e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define BUF_LEN_MAX		32
98e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_BUFFER_MODE		0x1
99e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define EEPROM_SW_RST_MODE	0x0002
100e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define NORMAL_INTR_ENBL	0x0300
101e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define EEPROM_RST_INTR_ENBL	(I2CESRFIIE_BIT | I2CESRTOIE_BIT)
102e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define EEPROM_RST_INTR_DISBL	0x0
103e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define BUFFER_MODE_INTR_ENBL	0x001F
104e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define BUFFER_MODE_INTR_DISBL	0x0
105e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define NORMAL_MODE		0x0
106e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define BUFFER_MODE		0x1
107e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define EEPROM_SR_MODE		0x2
108e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2C_TX_MODE		0x0010
109e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_BUF_TX		0xFFF7
110e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCH_BUF_RD		0x0008
111e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2C_ERROR_MASK	(I2CESRTO_EVENT | I2CBMIS_EVENT | I2CBMTO_EVENT | \
112e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA			I2CBMNA_EVENT | I2CBMAL_EVENT | I2CMAL_EVENT)
113e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CMAL_EVENT		0x0001
114e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CMCF_EVENT		0x0002
115e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CBMFI_EVENT		0x0004
116e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CBMAL_EVENT		0x0008
117e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CBMNA_EVENT		0x0010
118e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CBMTO_EVENT		0x0020
119e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CBMIS_EVENT		0x0040
120e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CESRFI_EVENT		0x0080
121e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define I2CESRTO_EVENT		0x0100
122e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define PCI_DEVICE_ID_PCH_I2C	0x8817
123e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
124e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define pch_dbg(adap, fmt, arg...)  \
125e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	dev_dbg(adap->pch_adapter.dev.parent, "%s :" fmt, __func__, ##arg)
126e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
127e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define pch_err(adap, fmt, arg...)  \
128e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	dev_err(adap->pch_adapter.dev.parent, "%s :" fmt, __func__, ##arg)
129e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
130e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define pch_pci_err(pdev, fmt, arg...)  \
131e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	dev_err(&pdev->dev, "%s :" fmt, __func__, ##arg)
132e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
133e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define pch_pci_dbg(pdev, fmt, arg...)  \
134e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	dev_dbg(&pdev->dev, "%s :" fmt, __func__, ##arg)
135e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
136173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA/*
137173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGASet the number of I2C instance max
138173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGAIntel EG20T PCH :		1ch
1398956dc102ca26357850830f1d26132719c1ce6eeTomoya MORINAGALAPIS Semiconductor ML7213 IOH :	2ch
1408956dc102ca26357850830f1d26132719c1ce6eeTomoya MORINAGALAPIS Semiconductor ML7831 IOH :	1ch
141173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA*/
142173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA#define PCH_I2C_MAX_DEV			2
143173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA
144e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
145e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * struct i2c_algo_pch_data - for I2C driver functionalities
146e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @pch_adapter:		stores the reference to i2c_adapter structure
147e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @p_adapter_info:		stores the reference to adapter_info structure
148e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @pch_base_address:		specifies the remapped base address
149e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @pch_buff_mode_en:		specifies if buffer mode is enabled
150e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @pch_event_flag:		specifies occurrence of interrupt events
151e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @pch_i2c_xfer_in_progress:	specifies whether the transfer is completed
152e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
153e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstruct i2c_algo_pch_data {
154e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	struct i2c_adapter pch_adapter;
155e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	struct adapter_info *p_adapter_info;
156e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *pch_base_address;
157e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	int pch_buff_mode_en;
158e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 pch_event_flag;
159e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	bool pch_i2c_xfer_in_progress;
160e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA};
161e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
162e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
163e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * struct adapter_info - This structure holds the adapter information for the
164e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA			 PCH i2c controller
165e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @pch_data:		stores a list of i2c_algo_pch_data
166e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @pch_i2c_suspended:	specifies whether the system is suspended or not
167e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA *			perhaps with more lines and words.
168173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA * @ch_num:		specifies the number of i2c instance
169e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA *
170e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_data has as many elements as maximum I2C channels
171e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
172e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstruct adapter_info {
173173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	struct i2c_algo_pch_data pch_data[PCH_I2C_MAX_DEV];
174e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	bool pch_i2c_suspended;
175173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	int ch_num;
176e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA};
177e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
178e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
179e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic int pch_i2c_speed = 100; /* I2C bus speed in Kbps */
180e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic int pch_clk = 50000;	/* specifies I2C clock speed in KHz */
181e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic wait_queue_head_t pch_event;
182e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic DEFINE_MUTEX(pch_mutex);
183e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1848956dc102ca26357850830f1d26132719c1ce6eeTomoya MORINAGA/* Definition for ML7213 by LAPIS Semiconductor */
185173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA#define PCI_VENDOR_ID_ROHM		0x10DB
186173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA#define PCI_DEVICE_ID_ML7213_I2C	0x802D
187efbe0f27ccfa7237c5524b10e8ccc91f97002f16Tomoya MORINAGA#define PCI_DEVICE_ID_ML7223_I2C	0x8010
188c3f4661f55f86b541d23c66dbb53ce7b0a34e777Tomoya MORINAGA#define PCI_DEVICE_ID_ML7831_I2C	0x8817
189173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA
1903527bd5045aacb4e4072f9cacb8eb9a433fbad39Axel Linstatic DEFINE_PCI_DEVICE_TABLE(pch_pcidev_id) = {
191173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_I2C),   1, },
192173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_I2C), 2, },
193efbe0f27ccfa7237c5524b10e8ccc91f97002f16Tomoya MORINAGA	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_I2C), 1, },
194c3f4661f55f86b541d23c66dbb53ce7b0a34e777Tomoya MORINAGA	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_I2C), 1, },
195e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	{0,}
196e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA};
197e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
198e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic irqreturn_t pch_i2c_handler(int irq, void *pData);
199e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
200e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic inline void pch_setbit(void __iomem *addr, u32 offset, u32 bitmask)
201e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
202e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 val;
203e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	val = ioread32(addr + offset);
204e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	val |= bitmask;
205e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	iowrite32(val, addr + offset);
206e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
207e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
208e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic inline void pch_clrbit(void __iomem *addr, u32 offset, u32 bitmask)
209e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
210e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 val;
211e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	val = ioread32(addr + offset);
212e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	val &= (~bitmask);
213e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	iowrite32(val, addr + offset);
214e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
215e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
216e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
217e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_init() - hardware initialization of I2C module
218e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
219e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
220e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic void pch_i2c_init(struct i2c_algo_pch_data *adap)
221e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
222e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
223e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 pch_i2cbc;
224e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 pch_i2ctmr;
225e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 reg_value;
226e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
227e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	/* reset I2C controller */
228e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	iowrite32(0x01, p + PCH_I2CSRST);
229e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	msleep(20);
230e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	iowrite32(0x0, p + PCH_I2CSRST);
231e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
232e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	/* Initialize I2C registers */
233e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	iowrite32(0x21, p + PCH_I2CNF);
234e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
235173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_I2CCTL_I2CMEN);
236e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
237e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (pch_i2c_speed != 400)
238e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_i2c_speed = 100;
239e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
240e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	reg_value = PCH_I2CCTL_I2CMEN;
241e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (pch_i2c_speed == FAST_MODE_CLK) {
242e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		reg_value |= FAST_MODE_EN;
243e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_dbg(adap, "Fast mode enabled\n");
244e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
245e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
246e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (pch_clk > PCH_MAX_CLK)
247e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_clk = 62500;
248e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
249ff35e8b18984ad2a82cbd259fc07f0be4b34b1aaToshiharu Okada	pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / (pch_i2c_speed * 8);
250e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	/* Set transfer speed in I2CBC */
251e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	iowrite32(pch_i2cbc, p + PCH_I2CBC);
252e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
253e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_i2ctmr = (pch_clk) / 8;
254e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	iowrite32(pch_i2ctmr, p + PCH_I2CTMR);
255e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
256e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	reg_value |= NORMAL_INTR_ENBL;	/* Enable interrupts in normal mode */
257e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	iowrite32(reg_value, p + PCH_I2CCTL);
258e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
259e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_dbg(adap,
260e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		"I2CCTL=%x pch_i2cbc=%x pch_i2ctmr=%x Enable interrupts\n",
261e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		ioread32(p + PCH_I2CCTL), pch_i2cbc, pch_i2ctmr);
262e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
263e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	init_waitqueue_head(&pch_event);
264e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
265e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
266e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic inline bool ktime_lt(const ktime_t cmp1, const ktime_t cmp2)
267e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
268e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	return cmp1.tv64 < cmp2.tv64;
269e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
270e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
271e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
272e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_wait_for_bus_idle() - check the status of bus.
273e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
2740836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein * @timeout:	waiting time counter (ms).
275e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
276e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap,
277173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA				     s32 timeout)
278e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
279e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
2800836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein	int schedule = 0;
2810836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein	unsigned long end = jiffies + msecs_to_jiffies(timeout);
2820836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein
2830836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein	while (ioread32(p + PCH_I2CSR) & I2CMBB_BIT) {
2840836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein		if (time_after(jiffies, end)) {
2850836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein			pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR));
2860836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein			pch_err(adap, "%s: Timeout Error.return%d\n",
2870836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein					__func__, -ETIME);
2880836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein			pch_i2c_init(adap);
2890836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein
2900836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein			return -ETIME;
2910836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein		}
2920836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein
2930836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein		if (!schedule)
2940836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein			/* Retry after some usecs */
2950836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein			udelay(5);
2960836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein		else
2970836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein			/* Wait a bit more without consuming CPU */
2980836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein			usleep_range(20, 1000);
2990836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein
3000836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein		schedule = 1;
3010836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein	}
302e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
3030836c80901565e8549e17cbad6933ab7e48ef6b2Alexander Stein	return 0;
304e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
305e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
306e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
307e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_start() - Generate I2C start condition in normal mode.
308e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
309e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA *
310e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * Generate I2C start condition in normal mode by setting I2CCTL.I2CMSTA to 1.
311e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
312e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic void pch_i2c_start(struct i2c_algo_pch_data *adap)
313e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
314e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
315e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
316e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_START);
317e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
318e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
319e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
320e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_wait_for_xfer_complete() - initiates a wait for the tx complete event
321e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
322e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
323e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic s32 pch_i2c_wait_for_xfer_complete(struct i2c_algo_pch_data *adap)
324e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
325c7b41f3affc63644f398b5faa170b1f531b406a8Tomoya MORINAGA	long ret;
326e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	ret = wait_event_timeout(pch_event,
3278a52f9f347da721b199b7f9dcc0168bbe7d0baaeTomoya MORINAGA			(adap->pch_event_flag != 0), msecs_to_jiffies(1000));
328e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
329e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (ret == 0) {
330e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
331cb59f5253a5313d62e8e345fcd5dd5a44a73e0d6Tomoya MORINAGA		adap->pch_event_flag = 0;
332e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		return -ETIMEDOUT;
333e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
334e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
335e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (adap->pch_event_flag & I2C_ERROR_MASK) {
336e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_err(adap, "error bits set: %x\n", adap->pch_event_flag);
337cb59f5253a5313d62e8e345fcd5dd5a44a73e0d6Tomoya MORINAGA		adap->pch_event_flag = 0;
338e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		return -EIO;
339e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
340e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
341e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	adap->pch_event_flag = 0;
342e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
343e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	return 0;
344e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
345e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
346e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
347e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_getack() - to confirm ACK/NACK
348e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
349e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
350e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic s32 pch_i2c_getack(struct i2c_algo_pch_data *adap)
351e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
352e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 reg_val;
353e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
354e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	reg_val = ioread32(p + PCH_I2CSR) & PCH_GETACK;
355e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
356e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (reg_val != 0) {
357e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_err(adap, "return%d\n", -EPROTO);
358e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		return -EPROTO;
359e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
360e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
361e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	return 0;
362e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
363e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
364e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
365e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_stop() - generate stop condition in normal mode.
366e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
367e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
368e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic void pch_i2c_stop(struct i2c_algo_pch_data *adap)
369e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
370e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
371e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
372e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	/* clear the start bit */
373e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_clrbit(adap->pch_base_address, PCH_I2CCTL, PCH_START);
374e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
375e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
376e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
377e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_repstart() - generate repeated start condition in normal mode
378e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
379e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
380e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic void pch_i2c_repstart(struct i2c_algo_pch_data *adap)
381e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
382e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
383e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
384e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_REPSTART);
385e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
386e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
387e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
388e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_writebytes() - write data to I2C bus in normal mode
389e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @i2c_adap:	Pointer to the struct i2c_adapter.
390e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @last:	specifies whether last message or not.
391e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA *		In the case of compound mode it will be 1 for last message,
392e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA *		otherwise 0.
393e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @first:	specifies whether first message or not.
394e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA *		1 for first message otherwise 0.
395e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
396e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
397e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA			      struct i2c_msg *msgs, u32 last, u32 first)
398e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
399e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
400e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u8 *buf;
401e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 length;
402e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 addr;
403e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 addr_2_msb;
404e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 addr_8_lsb;
405e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	s32 wrcount;
40612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	s32 rtn;
407e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
408e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
409e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	length = msgs->len;
410e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	buf = msgs->buf;
411e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	addr = msgs->addr;
412e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
413e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	/* enable master tx */
414e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_setbit(adap->pch_base_address, PCH_I2CCTL, I2C_TX_MODE);
415e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
416e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_dbg(adap, "I2CCTL = %x msgs->len = %d\n", ioread32(p + PCH_I2CCTL),
417e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		length);
418e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
419e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (first) {
420e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		if (pch_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) == -ETIME)
421e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA			return -ETIME;
422e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
423e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
424e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (msgs->flags & I2C_M_TEN) {
425c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7) & 0x06;
426e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
427e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		if (first)
428e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA			pch_i2c_start(adap);
42912bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA
43012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		rtn = pch_i2c_wait_for_xfer_complete(adap);
43112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		if (rtn == 0) {
43212bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			if (pch_i2c_getack(adap)) {
43312bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				pch_dbg(adap, "Receive NACK for slave address"
43412bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA					"setting\n");
43512bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				return -EIO;
43612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			}
437e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA			addr_8_lsb = (addr & I2C_ADDR_MSK);
438e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA			iowrite32(addr_8_lsb, p + PCH_I2CDR);
43912bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		} else if (rtn == -EIO) { /* Arbitration Lost */
44012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			pch_err(adap, "Lost Arbitration\n");
44112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
44212bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				   I2CMAL_BIT);
44312bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
44412bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				   I2CMIF_BIT);
44512bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			pch_i2c_init(adap);
44612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			return -EAGAIN;
44712bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		} else { /* wait-event timeout */
448e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA			pch_i2c_stop(adap);
449e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA			return -ETIME;
450e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		}
451e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	} else {
452e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		/* set 7 bit slave address and R/W bit as 0 */
453e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		iowrite32(addr << 1, p + PCH_I2CDR);
454e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		if (first)
455e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA			pch_i2c_start(adap);
456e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
457e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
45812bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	rtn = pch_i2c_wait_for_xfer_complete(adap);
45912bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	if (rtn == 0) {
46012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		if (pch_i2c_getack(adap)) {
46112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			pch_dbg(adap, "Receive NACK for slave address"
46212bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				"setting\n");
46312bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			return -EIO;
46412bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		}
46512bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	} else if (rtn == -EIO) { /* Arbitration Lost */
46612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		pch_err(adap, "Lost Arbitration\n");
46712bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
46812bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
46924597bf8012cf3fa5703c38e1bb13df3118d7588Tomoya MORINAGA		pch_i2c_init(adap);
47012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		return -EAGAIN;
47112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	} else { /* wait-event timeout */
4723cf21a7c48389c167065bffd61db39a9bd201f07Tomoya MORINAGA		pch_i2c_stop(adap);
47312bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		return -ETIME;
47412bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	}
475e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
47612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	for (wrcount = 0; wrcount < length; ++wrcount) {
47712bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		/* write buffer value to I2C data register */
47812bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		iowrite32(buf[wrcount], p + PCH_I2CDR);
47912bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		pch_dbg(adap, "writing %x to Data register\n", buf[wrcount]);
480e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
48112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		rtn = pch_i2c_wait_for_xfer_complete(adap);
48212bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		if (rtn == 0) {
48312bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			if (pch_i2c_getack(adap)) {
48412bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				pch_dbg(adap, "Receive NACK for slave address"
48512bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA					"setting\n");
486e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA				return -EIO;
48712bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			}
48812bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
48912bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				   I2CMCF_BIT);
49012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
49112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				   I2CMIF_BIT);
49212bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		} else { /* wait-event timeout */
4933cf21a7c48389c167065bffd61db39a9bd201f07Tomoya MORINAGA			pch_i2c_stop(adap);
49412bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			return -ETIME;
495e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		}
49612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	}
497e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
49812bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	/* check if this is the last message */
49912bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	if (last)
500e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_i2c_stop(adap);
50112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	else
50212bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		pch_i2c_repstart(adap);
503e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
504e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_dbg(adap, "return=%d\n", wrcount);
505e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
506e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	return wrcount;
507e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
508e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
509e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
510e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_sendack() - send ACK
511e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
512e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
513e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic void pch_i2c_sendack(struct i2c_algo_pch_data *adap)
514e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
515e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
516e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
517e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_clrbit(adap->pch_base_address, PCH_I2CCTL, PCH_ACK);
518e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
519e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
520e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
521e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_sendnack() - send NACK
522e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
523e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
524e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic void pch_i2c_sendnack(struct i2c_algo_pch_data *adap)
525e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
526e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
527e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
528e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_ACK);
529e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
530e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
531e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
532c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA * pch_i2c_restart() - Generate I2C restart condition in normal mode.
533c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
534c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA *
535c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA * Generate I2C restart condition in normal mode by setting I2CCTL.I2CRSTA.
536c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA */
537c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGAstatic void pch_i2c_restart(struct i2c_algo_pch_data *adap)
538c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA{
539c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
540c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA	pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
541c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_RESTART);
542c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA}
543c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA
544c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA/**
545e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_readbytes() - read data  from I2C bus in normal mode.
546e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @i2c_adap:	Pointer to the struct i2c_adapter.
547e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @msgs:	Pointer to i2c_msg structure.
548e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @last:	specifies whether last message or not.
549e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @first:	specifies whether first message or not.
550e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
551173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGAstatic s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
552173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA			     u32 last, u32 first)
553e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
554e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
555e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
556e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u8 *buf;
557e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 count;
558e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 length;
559e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 addr;
560e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 addr_2_msb;
561c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA	u32 addr_8_lsb;
562e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
56312bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	s32 rtn;
564e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
565e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	length = msgs->len;
566e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	buf = msgs->buf;
567e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	addr = msgs->addr;
568e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
569e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	/* enable master reception */
570e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_clrbit(adap->pch_base_address, PCH_I2CCTL, I2C_TX_MODE);
571e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
572e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (first) {
573e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		if (pch_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) == -ETIME)
574e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA			return -ETIME;
575e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
576e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
577e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (msgs->flags & I2C_M_TEN) {
578c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
579e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
580c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		if (first)
581c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			pch_i2c_start(adap);
582e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
583c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		rtn = pch_i2c_wait_for_xfer_complete(adap);
584c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		if (rtn == 0) {
585c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			if (pch_i2c_getack(adap)) {
586c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA				pch_dbg(adap, "Receive NACK for slave address"
587c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA					"setting\n");
588c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA				return -EIO;
589c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			}
590c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			addr_8_lsb = (addr & I2C_ADDR_MSK);
591c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			iowrite32(addr_8_lsb, p + PCH_I2CDR);
592c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		} else if (rtn == -EIO) { /* Arbitration Lost */
593c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			pch_err(adap, "Lost Arbitration\n");
594c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
595c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA				   I2CMAL_BIT);
596c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
597c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA				   I2CMIF_BIT);
598c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			pch_i2c_init(adap);
599c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			return -EAGAIN;
600c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		} else { /* wait-event timeout */
601c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			pch_i2c_stop(adap);
602c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			return -ETIME;
603c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		}
604c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		pch_i2c_restart(adap);
605c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		rtn = pch_i2c_wait_for_xfer_complete(adap);
606c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		if (rtn == 0) {
607c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			if (pch_i2c_getack(adap)) {
608c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA				pch_dbg(adap, "Receive NACK for slave address"
609c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA					"setting\n");
610c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA				return -EIO;
611c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			}
612c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			addr_2_msb |= I2C_RD;
613c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK,
614c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA				  p + PCH_I2CDR);
615c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		} else if (rtn == -EIO) { /* Arbitration Lost */
616c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			pch_err(adap, "Lost Arbitration\n");
617c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
618c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA				   I2CMAL_BIT);
619c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
620c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA				   I2CMIF_BIT);
621c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			pch_i2c_init(adap);
622c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			return -EAGAIN;
623c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		} else { /* wait-event timeout */
624c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			pch_i2c_stop(adap);
625c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA			return -ETIME;
626c249ac207f2cedb49f2c9442afbaac35bfcfcd25Tomoya MORINAGA		}
627e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	} else {
628e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		/* 7 address bits + R/W bit */
629e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		addr = (((addr) << 1) | (I2C_RD));
630e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		iowrite32(addr, p + PCH_I2CDR);
631e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
632e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
633e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	/* check if it is the first message */
634e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (first)
635e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_i2c_start(adap);
636e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
63712bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	rtn = pch_i2c_wait_for_xfer_complete(adap);
63812bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	if (rtn == 0) {
63912bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		if (pch_i2c_getack(adap)) {
64012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			pch_dbg(adap, "Receive NACK for slave address"
64112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				"setting\n");
64212bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			return -EIO;
64312bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		}
64412bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	} else if (rtn == -EIO) { /* Arbitration Lost */
64512bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		pch_err(adap, "Lost Arbitration\n");
64612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
64712bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
64824597bf8012cf3fa5703c38e1bb13df3118d7588Tomoya MORINAGA		pch_i2c_init(adap);
64912bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		return -EAGAIN;
65012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	} else { /* wait-event timeout */
6513cf21a7c48389c167065bffd61db39a9bd201f07Tomoya MORINAGA		pch_i2c_stop(adap);
65212bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		return -ETIME;
65312bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	}
654e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
65512bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	if (length == 0) {
65612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		pch_i2c_stop(adap);
65712bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		ioread32(p + PCH_I2CDR); /* Dummy read needs */
658e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
65912bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		count = length;
66012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA	} else {
66112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		int read_index;
66212bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		int loop;
66312bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		pch_i2c_sendack(adap);
664e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
66512bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		/* Dummy read */
66612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		for (loop = 1, read_index = 0; loop < length; loop++) {
66712bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			buf[read_index] = ioread32(p + PCH_I2CDR);
668e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
66912bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			if (loop != 1)
67012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				read_index++;
671e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
67212bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			rtn = pch_i2c_wait_for_xfer_complete(adap);
67312bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			if (rtn == 0) {
67412bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				if (pch_i2c_getack(adap)) {
67512bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA					pch_dbg(adap, "Receive NACK for slave"
67612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA						"address setting\n");
67712bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA					return -EIO;
678e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA				}
67912bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			} else { /* wait-event timeout */
68012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				pch_i2c_stop(adap);
68112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				return -ETIME;
68212bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			}
683e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
68412bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		}	/* end for */
685e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
68612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		pch_i2c_sendnack(adap);
687e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
68812bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		buf[read_index] = ioread32(p + PCH_I2CDR); /* Read final - 1 */
689e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
69012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		if (length != 1)
69112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			read_index++;
692e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
69312bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		rtn = pch_i2c_wait_for_xfer_complete(adap);
69412bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		if (rtn == 0) {
69512bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			if (pch_i2c_getack(adap)) {
69612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				pch_dbg(adap, "Receive NACK for slave"
69712bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA					"address setting\n");
69812bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA				return -EIO;
699e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA			}
70012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		} else { /* wait-event timeout */
70112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			pch_i2c_stop(adap);
70212bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			return -ETIME;
703e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		}
70412bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA
70512bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		if (last)
70612bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			pch_i2c_stop(adap);
70712bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		else
70812bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA			pch_i2c_repstart(adap);
70912bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA
71012bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		buf[read_index++] = ioread32(p + PCH_I2CDR); /* Read Final */
71112bd3146518ab984c1eb234a0f81756ddc5e3683Tomoya MORINAGA		count = read_index;
712e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
713e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
714e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	return count;
715e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
716e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
717e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
718173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA * pch_i2c_cb() - Interrupt handler Call back function
719e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
720e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
721173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGAstatic void pch_i2c_cb(struct i2c_algo_pch_data *adap)
722e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
723e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 sts;
724e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
725e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
726e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	sts = ioread32(p + PCH_I2CSR);
727e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	sts &= (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT);
728e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (sts & I2CMAL_BIT)
729e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		adap->pch_event_flag |= I2CMAL_EVENT;
730e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
731e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (sts & I2CMCF_BIT)
732e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		adap->pch_event_flag |= I2CMCF_EVENT;
733e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
734e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	/* clear the applicable bits */
735e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_clrbit(adap->pch_base_address, PCH_I2CSR, sts);
736e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
737e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_dbg(adap, "PCH_I2CSR = %x\n", ioread32(p + PCH_I2CSR));
738e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
739e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	wake_up(&pch_event);
740e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
741e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
742e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
743e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_handler() - interrupt handler for the PCH I2C controller
744e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @irq:	irq number.
745e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @pData:	cookie passed back to the handler function.
746e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
747e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic irqreturn_t pch_i2c_handler(int irq, void *pData)
748e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
749173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	u32 reg_val;
750173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	int flag;
751173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	int i;
752173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	struct adapter_info *adap_info = pData;
753173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	void __iomem *p;
754173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	u32 mode;
755173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA
756173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	for (i = 0, flag = 0; i < adap_info->ch_num; i++) {
757173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		p = adap_info->pch_data[i].pch_base_address;
758173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		mode = ioread32(p + PCH_I2CMOD);
759173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		mode &= BUFFER_MODE | EEPROM_SR_MODE;
760173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		if (mode != NORMAL_MODE) {
761173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA			pch_err(adap_info->pch_data,
762173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA				"I2C-%d mode(%d) is not supported\n", mode, i);
763173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA			continue;
764173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		}
765173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		reg_val = ioread32(p + PCH_I2CSR);
766173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT)) {
767173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA			pch_i2c_cb(&adap_info->pch_data[i]);
768173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA			flag = 1;
769173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		}
770e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
771e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
772173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	return flag ? IRQ_HANDLED : IRQ_NONE;
773e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
774e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
775e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
776e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_xfer() - Reading adnd writing data through I2C bus
777e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @i2c_adap:	Pointer to the struct i2c_adapter.
778e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @msgs:	Pointer to i2c_msg structure.
779e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @num:	number of messages.
780e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
781e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
782173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA			struct i2c_msg *msgs, s32 num)
783e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
784e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	struct i2c_msg *pmsg;
785e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 i = 0;
786e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	u32 status;
787e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	s32 ret;
788e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
789e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
790e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
791e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	ret = mutex_lock_interruptible(&pch_mutex);
792e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (ret)
793e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		return -ERESTARTSYS;
794e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
795e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (adap->p_adapter_info->pch_i2c_suspended) {
796e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		mutex_unlock(&pch_mutex);
797e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		return -EBUSY;
798e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
799e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
800e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_dbg(adap, "adap->p_adapter_info->pch_i2c_suspended is %d\n",
801e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		adap->p_adapter_info->pch_i2c_suspended);
802e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	/* transfer not completed */
803e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	adap->pch_i2c_xfer_in_progress = true;
804e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
80507e729ce894487e92405d3b221cffe587420a376Tomoya MORINAGA	for (i = 0; i < num && ret >= 0; i++) {
8067a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA		pmsg = &msgs[i];
8077a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA		pmsg->flags |= adap->pch_buff_mode_en;
8087a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA		status = pmsg->flags;
8097a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA		pch_dbg(adap,
8107a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA			"After invoking I2C_MODE_SEL :flag= 0x%x\n", status);
8117a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA
8127a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA		if ((status & (I2C_M_RD)) != false) {
8137a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA			ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num),
8147a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA						(i == 0));
8157a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA		} else {
8167a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA			ret = pch_i2c_writebytes(i2c_adap, pmsg, (i + 1 == num),
8177a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA						 (i == 0));
8187a9c42ccc9fd4317383e55209f825f974e64aa99Tomoya MORINAGA		}
819e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
820e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
821e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	adap->pch_i2c_xfer_in_progress = false;	/* transfer completed */
822e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
823e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	mutex_unlock(&pch_mutex);
824e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
82507e729ce894487e92405d3b221cffe587420a376Tomoya MORINAGA	return (ret < 0) ? ret : num;
826e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
827e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
828e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
829e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_func() - return the functionality of the I2C driver
830e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
831e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
832e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic u32 pch_i2c_func(struct i2c_adapter *adap)
833e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
834e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
835e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
836e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
837e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic struct i2c_algorithm pch_algorithm = {
838e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	.master_xfer = pch_i2c_xfer,
839e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	.functionality = pch_i2c_func
840e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA};
841e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
842e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA/**
843e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * pch_i2c_disbl_int() - Disable PCH I2C interrupts
844e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA * @adap:	Pointer to struct i2c_algo_pch_data.
845e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA */
846e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic void pch_i2c_disbl_int(struct i2c_algo_pch_data *adap)
847e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
848e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *p = adap->pch_base_address;
849e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
850e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_clrbit(adap->pch_base_address, PCH_I2CCTL, NORMAL_INTR_ENBL);
851e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
852e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	iowrite32(EEPROM_RST_INTR_DISBL, p + PCH_I2CESRMSK);
853e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
854e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	iowrite32(BUFFER_MODE_INTR_DISBL, p + PCH_I2CBUFMSK);
855e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
856e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
857e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic int __devinit pch_i2c_probe(struct pci_dev *pdev,
858173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA				   const struct pci_device_id *id)
859e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
860e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	void __iomem *base_addr;
861173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	int ret;
862173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	int i, j;
863e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	struct adapter_info *adap_info;
864173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	struct i2c_adapter *pch_adap;
865e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
866e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_pci_dbg(pdev, "Entered.\n");
867e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
868e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	adap_info = kzalloc((sizeof(struct adapter_info)), GFP_KERNEL);
869e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (adap_info == NULL) {
870e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_pci_err(pdev, "Memory allocation FAILED\n");
871e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		return -ENOMEM;
872e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
873e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
874e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	ret = pci_enable_device(pdev);
875e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (ret) {
876e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_pci_err(pdev, "pci_enable_device FAILED\n");
877e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		goto err_pci_enable;
878e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
879e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
880e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	ret = pci_request_regions(pdev, KBUILD_MODNAME);
881e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (ret) {
882e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_pci_err(pdev, "pci_request_regions FAILED\n");
883e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		goto err_pci_req;
884e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
885e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
886e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	base_addr = pci_iomap(pdev, 1, 0);
887e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
888e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (base_addr == NULL) {
889e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_pci_err(pdev, "pci_iomap FAILED\n");
890e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		ret = -ENOMEM;
891e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		goto err_pci_iomap;
892e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
893e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
894173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	/* Set the number of I2C channel instance */
895173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	adap_info->ch_num = id->driver_data;
896e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
8970d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43deFeng Tang	ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
8980d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43deFeng Tang		  KBUILD_MODNAME, adap_info);
8990d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43deFeng Tang	if (ret) {
9000d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43deFeng Tang		pch_pci_err(pdev, "request_irq FAILED\n");
9010d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43deFeng Tang		goto err_request_irq;
9020d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43deFeng Tang	}
9030d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43deFeng Tang
904173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	for (i = 0; i < adap_info->ch_num; i++) {
905173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		pch_adap = &adap_info->pch_data[i].pch_adapter;
906173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		adap_info->pch_i2c_suspended = false;
907e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
908173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		adap_info->pch_data[i].p_adapter_info = adap_info;
909e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
910173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		pch_adap->owner = THIS_MODULE;
911173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		pch_adap->class = I2C_CLASS_HWMON;
912173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		strcpy(pch_adap->name, KBUILD_MODNAME);
913173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		pch_adap->algo = &pch_algorithm;
914173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		pch_adap->algo_data = &adap_info->pch_data[i];
915e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
916173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		/* base_addr + offset; */
917173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		adap_info->pch_data[i].pch_base_address = base_addr + 0x100 * i;
918e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
919173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		pch_adap->dev.parent = &pdev->dev;
920e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
9210d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43deFeng Tang		pch_i2c_init(&adap_info->pch_data[i]);
92207e8a51ff68353e01d795cceafbac9f54c49132bFeng Tang
92307e8a51ff68353e01d795cceafbac9f54c49132bFeng Tang		pch_adap->nr = i;
92407e8a51ff68353e01d795cceafbac9f54c49132bFeng Tang		ret = i2c_add_numbered_adapter(pch_adap);
925173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		if (ret) {
926173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA			pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i);
9270d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43deFeng Tang			goto err_add_adapter;
928173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		}
929e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
930e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
931e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_set_drvdata(pdev, adap_info);
932e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_pci_dbg(pdev, "returns %d.\n", ret);
933e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	return 0;
934e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
9350d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43deFeng Tangerr_add_adapter:
936173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	for (j = 0; j < i; j++)
937173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		i2c_del_adapter(&adap_info->pch_data[j].pch_adapter);
9380d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43deFeng Tang	free_irq(pdev->irq, adap_info);
9390d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43deFeng Tangerr_request_irq:
940e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_iounmap(pdev, base_addr);
941e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAerr_pci_iomap:
942e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_release_regions(pdev);
943e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAerr_pci_req:
944e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_disable_device(pdev);
945e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAerr_pci_enable:
946e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	kfree(adap_info);
947e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	return ret;
948e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
949e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
950e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic void __devexit pch_i2c_remove(struct pci_dev *pdev)
951e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
952173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	int i;
953e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	struct adapter_info *adap_info = pci_get_drvdata(pdev);
954e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
955173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	free_irq(pdev->irq, adap_info);
956e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
957173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	for (i = 0; i < adap_info->ch_num; i++) {
958173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		pch_i2c_disbl_int(&adap_info->pch_data[i]);
959173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		i2c_del_adapter(&adap_info->pch_data[i].pch_adapter);
960e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
961e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
962173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	if (adap_info->pch_data[0].pch_base_address)
963173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		pci_iounmap(pdev, adap_info->pch_data[0].pch_base_address);
964173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA
965173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	for (i = 0; i < adap_info->ch_num; i++)
966173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		adap_info->pch_data[i].pch_base_address = 0;
967173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA
968e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_set_drvdata(pdev, NULL);
969e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
970e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_release_regions(pdev);
971e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
972e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_disable_device(pdev);
973e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	kfree(adap_info);
974e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
975e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
976e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#ifdef CONFIG_PM
977e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state)
978e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
979e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	int ret;
980173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	int i;
981e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	struct adapter_info *adap_info = pci_get_drvdata(pdev);
982173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	void __iomem *p = adap_info->pch_data[0].pch_base_address;
983e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
984e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	adap_info->pch_i2c_suspended = true;
985e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
986173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	for (i = 0; i < adap_info->ch_num; i++) {
987173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		while ((adap_info->pch_data[i].pch_i2c_xfer_in_progress)) {
988173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA			/* Wait until all channel transfers are completed */
989173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA			msleep(20);
990173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		}
991e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
992173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA
993e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	/* Disable the i2c interrupts */
994173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	for (i = 0; i < adap_info->ch_num; i++)
995173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		pch_i2c_disbl_int(&adap_info->pch_data[i]);
996e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
997e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pch_pci_dbg(pdev, "I2CSR = %x I2CBUFSTA = %x I2CESRSTA = %x "
998e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		"invoked function pch_i2c_disbl_int successfully\n",
999e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		ioread32(p + PCH_I2CSR), ioread32(p + PCH_I2CBUFSTA),
1000e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		ioread32(p + PCH_I2CESRSTA));
1001e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1002e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	ret = pci_save_state(pdev);
1003e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1004e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (ret) {
1005e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_pci_err(pdev, "pci_save_state\n");
1006e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		return ret;
1007e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
1008e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1009e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_enable_wake(pdev, PCI_D3hot, 0);
1010e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_disable_device(pdev);
1011e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_set_power_state(pdev, pci_choose_state(pdev, state));
1012e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1013e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	return 0;
1014e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
1015e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1016e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic int pch_i2c_resume(struct pci_dev *pdev)
1017e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
1018173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	int i;
1019e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	struct adapter_info *adap_info = pci_get_drvdata(pdev);
1020e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1021e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_set_power_state(pdev, PCI_D0);
1022e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_restore_state(pdev);
1023e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1024e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	if (pci_enable_device(pdev) < 0) {
1025e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		pch_pci_err(pdev, "pch_i2c_resume:pci_enable_device FAILED\n");
1026e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA		return -EIO;
1027e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	}
1028e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1029e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_enable_wake(pdev, PCI_D3hot, 0);
1030e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1031173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA	for (i = 0; i < adap_info->ch_num; i++)
1032173442f2787c88e1ed1bb62aaeb6fd9127720559Tomoya MORINAGA		pch_i2c_init(&adap_info->pch_data[i]);
1033e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1034e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	adap_info->pch_i2c_suspended = false;
1035e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1036e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	return 0;
1037e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
1038e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#else
1039e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define pch_i2c_suspend NULL
1040e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#define pch_i2c_resume NULL
1041e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA#endif
1042e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1043e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic struct pci_driver pch_pcidriver = {
1044e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	.name = KBUILD_MODNAME,
1045e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	.id_table = pch_pcidev_id,
1046e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	.probe = pch_i2c_probe,
1047e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	.remove = __devexit_p(pch_i2c_remove),
1048e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	.suspend = pch_i2c_suspend,
1049e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	.resume = pch_i2c_resume
1050e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA};
1051e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1052e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic int __init pch_pci_init(void)
1053e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
1054e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	return pci_register_driver(&pch_pcidriver);
1055e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
1056e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAmodule_init(pch_pci_init);
1057e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
1058e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAstatic void __exit pch_pci_exit(void)
1059e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA{
1060e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA	pci_unregister_driver(&pch_pcidriver);
1061e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA}
1062e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAmodule_exit(pch_pci_exit);
1063e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGA
10648956dc102ca26357850830f1d26132719c1ce6eeTomoya MORINAGAMODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semico ML7213/ML7223/ML7831 IOH I2C");
1065e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAMODULE_LICENSE("GPL");
1066096407136769ec10690abe1baba092abcb763662Tomoya MORINAGAMODULE_AUTHOR("Tomoya MORINAGA. <tomoya.rohm@gmail.com>");
1067e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAmodule_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR));
1068e9bc8fa5df1c398890e0963afe07425d994240b7Tomoya MORINAGAmodule_param(pch_clk, int, (S_IRUSR | S_IWUSR));
1069