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