1*cfad6425SSerge Semin /* 2*cfad6425SSerge Semin * This file is provided under a GPLv2 license. When using or 3*cfad6425SSerge Semin * redistributing this file, you may do so under that license. 4*cfad6425SSerge Semin * 5*cfad6425SSerge Semin * GPL LICENSE SUMMARY 6*cfad6425SSerge Semin * 7*cfad6425SSerge Semin * Copyright (C) 2016 T-Platforms. All Rights Reserved. 8*cfad6425SSerge Semin * 9*cfad6425SSerge Semin * This program is free software; you can redistribute it and/or modify it 10*cfad6425SSerge Semin * under the terms and conditions of the GNU General Public License, 11*cfad6425SSerge Semin * version 2, as published by the Free Software Foundation. 12*cfad6425SSerge Semin * 13*cfad6425SSerge Semin * This program is distributed in the hope that it will be useful, but WITHOUT 14*cfad6425SSerge Semin * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15*cfad6425SSerge Semin * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 16*cfad6425SSerge Semin * more details. 17*cfad6425SSerge Semin * 18*cfad6425SSerge Semin * You should have received a copy of the GNU General Public License along 19*cfad6425SSerge Semin * with this program; if not, it can be found <http://www.gnu.org/licenses/>. 20*cfad6425SSerge Semin * 21*cfad6425SSerge Semin * The full GNU General Public License is included in this distribution in 22*cfad6425SSerge Semin * the file called "COPYING". 23*cfad6425SSerge Semin * 24*cfad6425SSerge Semin * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25*cfad6425SSerge Semin * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26*cfad6425SSerge Semin * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27*cfad6425SSerge Semin * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28*cfad6425SSerge Semin * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29*cfad6425SSerge Semin * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30*cfad6425SSerge Semin * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31*cfad6425SSerge Semin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32*cfad6425SSerge Semin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33*cfad6425SSerge Semin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34*cfad6425SSerge Semin * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35*cfad6425SSerge Semin * 36*cfad6425SSerge Semin * IDT PCIe-switch NTB Linux driver 37*cfad6425SSerge Semin * 38*cfad6425SSerge Semin * Contact Information: 39*cfad6425SSerge Semin * Serge Semin <fancer.lancer@gmail.com>, <Sergey.Semin@t-platforms.ru> 40*cfad6425SSerge Semin */ 41*cfad6425SSerge Semin /* 42*cfad6425SSerge Semin * NOTE of the IDT 89HPESx SMBus-slave interface driver 43*cfad6425SSerge Semin * This driver primarily is developed to have an access to EEPROM device of 44*cfad6425SSerge Semin * IDT PCIe-switches. IDT provides a simple SMBus interface to perform IO- 45*cfad6425SSerge Semin * operations from/to EEPROM, which is located at private (so called Master) 46*cfad6425SSerge Semin * SMBus of switches. Using that interface this the driver creates a simple 47*cfad6425SSerge Semin * binary sysfs-file in the device directory: 48*cfad6425SSerge Semin * /sys/bus/i2c/devices/<bus>-<devaddr>/eeprom 49*cfad6425SSerge Semin * In case if read-only flag is specified in the dts-node of device desription, 50*cfad6425SSerge Semin * User-space applications won't be able to write to the EEPROM sysfs-node. 51*cfad6425SSerge Semin * Additionally IDT 89HPESx SMBus interface has an ability to write/read 52*cfad6425SSerge Semin * data of device CSRs. This driver exposes debugf-file to perform simple IO 53*cfad6425SSerge Semin * operations using that ability for just basic debug purpose. Particularly 54*cfad6425SSerge Semin * next file is created in the specific debugfs-directory: 55*cfad6425SSerge Semin * /sys/kernel/debug/idt_csr/ 56*cfad6425SSerge Semin * Format of the debugfs-node is: 57*cfad6425SSerge Semin * $ cat /sys/kernel/debug/idt_csr/<bus>-<devaddr>/<devname>; 58*cfad6425SSerge Semin * <CSR address>:<CSR value> 59*cfad6425SSerge Semin * So reading the content of the file gives current CSR address and it value. 60*cfad6425SSerge Semin * If User-space application wishes to change current CSR address, 61*cfad6425SSerge Semin * it can just write a proper value to the sysfs-file: 62*cfad6425SSerge Semin * $ echo "<CSR address>" > /sys/kernel/debug/idt_csr/<bus>-<devaddr>/<devname> 63*cfad6425SSerge Semin * If it wants to change the CSR value as well, the format of the write 64*cfad6425SSerge Semin * operation is: 65*cfad6425SSerge Semin * $ echo "<CSR address>:<CSR value>" > \ 66*cfad6425SSerge Semin * /sys/kernel/debug/idt_csr/<bus>-<devaddr>/<devname>; 67*cfad6425SSerge Semin * CSR address and value can be any of hexadecimal, decimal or octal format. 68*cfad6425SSerge Semin */ 69*cfad6425SSerge Semin 70*cfad6425SSerge Semin #include <linux/kernel.h> 71*cfad6425SSerge Semin #include <linux/init.h> 72*cfad6425SSerge Semin #include <linux/module.h> 73*cfad6425SSerge Semin #include <linux/types.h> 74*cfad6425SSerge Semin #include <linux/sizes.h> 75*cfad6425SSerge Semin #include <linux/slab.h> 76*cfad6425SSerge Semin #include <linux/mutex.h> 77*cfad6425SSerge Semin #include <linux/sysfs.h> 78*cfad6425SSerge Semin #include <linux/debugfs.h> 79*cfad6425SSerge Semin #include <linux/mod_devicetable.h> 80*cfad6425SSerge Semin #include <linux/of.h> 81*cfad6425SSerge Semin #include <linux/i2c.h> 82*cfad6425SSerge Semin #include <linux/pci_ids.h> 83*cfad6425SSerge Semin #include <linux/delay.h> 84*cfad6425SSerge Semin 85*cfad6425SSerge Semin #define IDT_NAME "89hpesx" 86*cfad6425SSerge Semin #define IDT_89HPESX_DESC "IDT 89HPESx SMBus-slave interface driver" 87*cfad6425SSerge Semin #define IDT_89HPESX_VER "1.0" 88*cfad6425SSerge Semin 89*cfad6425SSerge Semin MODULE_DESCRIPTION(IDT_89HPESX_DESC); 90*cfad6425SSerge Semin MODULE_VERSION(IDT_89HPESX_VER); 91*cfad6425SSerge Semin MODULE_LICENSE("GPL v2"); 92*cfad6425SSerge Semin MODULE_AUTHOR("T-platforms"); 93*cfad6425SSerge Semin 94*cfad6425SSerge Semin /* 95*cfad6425SSerge Semin * csr_dbgdir - CSR read/write operations Debugfs directory 96*cfad6425SSerge Semin */ 97*cfad6425SSerge Semin static struct dentry *csr_dbgdir; 98*cfad6425SSerge Semin 99*cfad6425SSerge Semin /* 100*cfad6425SSerge Semin * struct idt_89hpesx_dev - IDT 89HPESx device data structure 101*cfad6425SSerge Semin * @eesize: Size of EEPROM in bytes (calculated from "idt,eecompatible") 102*cfad6425SSerge Semin * @eero: EEPROM Read-only flag 103*cfad6425SSerge Semin * @eeaddr: EEPROM custom address 104*cfad6425SSerge Semin * 105*cfad6425SSerge Semin * @inieecmd: Initial cmd value for EEPROM read/write operations 106*cfad6425SSerge Semin * @inicsrcmd: Initial cmd value for CSR read/write operations 107*cfad6425SSerge Semin * @iniccode: Initialial command code value for IO-operations 108*cfad6425SSerge Semin * 109*cfad6425SSerge Semin * @csr: CSR address to perform read operation 110*cfad6425SSerge Semin * 111*cfad6425SSerge Semin * @smb_write: SMBus write method 112*cfad6425SSerge Semin * @smb_read: SMBus read method 113*cfad6425SSerge Semin * @smb_mtx: SMBus mutex 114*cfad6425SSerge Semin * 115*cfad6425SSerge Semin * @client: i2c client used to perform IO operations 116*cfad6425SSerge Semin * 117*cfad6425SSerge Semin * @ee_file: EEPROM read/write sysfs-file 118*cfad6425SSerge Semin * @csr_file: CSR read/write debugfs-node 119*cfad6425SSerge Semin */ 120*cfad6425SSerge Semin struct idt_smb_seq; 121*cfad6425SSerge Semin struct idt_89hpesx_dev { 122*cfad6425SSerge Semin u32 eesize; 123*cfad6425SSerge Semin bool eero; 124*cfad6425SSerge Semin u8 eeaddr; 125*cfad6425SSerge Semin 126*cfad6425SSerge Semin u8 inieecmd; 127*cfad6425SSerge Semin u8 inicsrcmd; 128*cfad6425SSerge Semin u8 iniccode; 129*cfad6425SSerge Semin 130*cfad6425SSerge Semin u16 csr; 131*cfad6425SSerge Semin 132*cfad6425SSerge Semin int (*smb_write)(struct idt_89hpesx_dev *, const struct idt_smb_seq *); 133*cfad6425SSerge Semin int (*smb_read)(struct idt_89hpesx_dev *, struct idt_smb_seq *); 134*cfad6425SSerge Semin struct mutex smb_mtx; 135*cfad6425SSerge Semin 136*cfad6425SSerge Semin struct i2c_client *client; 137*cfad6425SSerge Semin 138*cfad6425SSerge Semin struct bin_attribute *ee_file; 139*cfad6425SSerge Semin struct dentry *csr_dir; 140*cfad6425SSerge Semin struct dentry *csr_file; 141*cfad6425SSerge Semin }; 142*cfad6425SSerge Semin 143*cfad6425SSerge Semin /* 144*cfad6425SSerge Semin * struct idt_smb_seq - sequence of data to be read/written from/to IDT 89HPESx 145*cfad6425SSerge Semin * @ccode: SMBus command code 146*cfad6425SSerge Semin * @bytecnt: Byte count of operation 147*cfad6425SSerge Semin * @data: Data to by written 148*cfad6425SSerge Semin */ 149*cfad6425SSerge Semin struct idt_smb_seq { 150*cfad6425SSerge Semin u8 ccode; 151*cfad6425SSerge Semin u8 bytecnt; 152*cfad6425SSerge Semin u8 *data; 153*cfad6425SSerge Semin }; 154*cfad6425SSerge Semin 155*cfad6425SSerge Semin /* 156*cfad6425SSerge Semin * struct idt_eeprom_seq - sequence of data to be read/written from/to EEPROM 157*cfad6425SSerge Semin * @cmd: Transaction CMD 158*cfad6425SSerge Semin * @eeaddr: EEPROM custom address 159*cfad6425SSerge Semin * @memaddr: Internal memory address of EEPROM 160*cfad6425SSerge Semin * @data: Data to be written at the memory address 161*cfad6425SSerge Semin */ 162*cfad6425SSerge Semin struct idt_eeprom_seq { 163*cfad6425SSerge Semin u8 cmd; 164*cfad6425SSerge Semin u8 eeaddr; 165*cfad6425SSerge Semin u16 memaddr; 166*cfad6425SSerge Semin u8 data; 167*cfad6425SSerge Semin } __packed; 168*cfad6425SSerge Semin 169*cfad6425SSerge Semin /* 170*cfad6425SSerge Semin * struct idt_csr_seq - sequence of data to be read/written from/to CSR 171*cfad6425SSerge Semin * @cmd: Transaction CMD 172*cfad6425SSerge Semin * @csraddr: Internal IDT device CSR address 173*cfad6425SSerge Semin * @data: Data to be read/written from/to the CSR address 174*cfad6425SSerge Semin */ 175*cfad6425SSerge Semin struct idt_csr_seq { 176*cfad6425SSerge Semin u8 cmd; 177*cfad6425SSerge Semin u16 csraddr; 178*cfad6425SSerge Semin u32 data; 179*cfad6425SSerge Semin } __packed; 180*cfad6425SSerge Semin 181*cfad6425SSerge Semin /* 182*cfad6425SSerge Semin * SMBus command code macros 183*cfad6425SSerge Semin * @CCODE_END: Indicates the end of transaction 184*cfad6425SSerge Semin * @CCODE_START: Indicates the start of transaction 185*cfad6425SSerge Semin * @CCODE_CSR: CSR read/write transaction 186*cfad6425SSerge Semin * @CCODE_EEPROM: EEPROM read/write transaction 187*cfad6425SSerge Semin * @CCODE_BYTE: Supplied data has BYTE length 188*cfad6425SSerge Semin * @CCODE_WORD: Supplied data has WORD length 189*cfad6425SSerge Semin * @CCODE_BLOCK: Supplied data has variable length passed in bytecnt 190*cfad6425SSerge Semin * byte right following CCODE byte 191*cfad6425SSerge Semin */ 192*cfad6425SSerge Semin #define CCODE_END ((u8)0x01) 193*cfad6425SSerge Semin #define CCODE_START ((u8)0x02) 194*cfad6425SSerge Semin #define CCODE_CSR ((u8)0x00) 195*cfad6425SSerge Semin #define CCODE_EEPROM ((u8)0x04) 196*cfad6425SSerge Semin #define CCODE_BYTE ((u8)0x00) 197*cfad6425SSerge Semin #define CCODE_WORD ((u8)0x20) 198*cfad6425SSerge Semin #define CCODE_BLOCK ((u8)0x40) 199*cfad6425SSerge Semin #define CCODE_PEC ((u8)0x80) 200*cfad6425SSerge Semin 201*cfad6425SSerge Semin /* 202*cfad6425SSerge Semin * EEPROM command macros 203*cfad6425SSerge Semin * @EEPROM_OP_WRITE: EEPROM write operation 204*cfad6425SSerge Semin * @EEPROM_OP_READ: EEPROM read operation 205*cfad6425SSerge Semin * @EEPROM_USA: Use specified address of EEPROM 206*cfad6425SSerge Semin * @EEPROM_NAERR: EEPROM device is not ready to respond 207*cfad6425SSerge Semin * @EEPROM_LAERR: EEPROM arbitration loss error 208*cfad6425SSerge Semin * @EEPROM_MSS: EEPROM misplace start & stop bits error 209*cfad6425SSerge Semin * @EEPROM_WR_CNT: Bytes count to perform write operation 210*cfad6425SSerge Semin * @EEPROM_WRRD_CNT: Bytes count to write before reading 211*cfad6425SSerge Semin * @EEPROM_RD_CNT: Bytes count to perform read operation 212*cfad6425SSerge Semin * @EEPROM_DEF_SIZE: Fall back size of EEPROM 213*cfad6425SSerge Semin * @EEPROM_DEF_ADDR: Defatul EEPROM address 214*cfad6425SSerge Semin * @EEPROM_TOUT: Timeout before retry read operation if eeprom is busy 215*cfad6425SSerge Semin */ 216*cfad6425SSerge Semin #define EEPROM_OP_WRITE ((u8)0x00) 217*cfad6425SSerge Semin #define EEPROM_OP_READ ((u8)0x01) 218*cfad6425SSerge Semin #define EEPROM_USA ((u8)0x02) 219*cfad6425SSerge Semin #define EEPROM_NAERR ((u8)0x08) 220*cfad6425SSerge Semin #define EEPROM_LAERR ((u8)0x10) 221*cfad6425SSerge Semin #define EEPROM_MSS ((u8)0x20) 222*cfad6425SSerge Semin #define EEPROM_WR_CNT ((u8)5) 223*cfad6425SSerge Semin #define EEPROM_WRRD_CNT ((u8)4) 224*cfad6425SSerge Semin #define EEPROM_RD_CNT ((u8)5) 225*cfad6425SSerge Semin #define EEPROM_DEF_SIZE ((u16)4096) 226*cfad6425SSerge Semin #define EEPROM_DEF_ADDR ((u8)0x50) 227*cfad6425SSerge Semin #define EEPROM_TOUT (100) 228*cfad6425SSerge Semin 229*cfad6425SSerge Semin /* 230*cfad6425SSerge Semin * CSR command macros 231*cfad6425SSerge Semin * @CSR_DWE: Enable all four bytes of the operation 232*cfad6425SSerge Semin * @CSR_OP_WRITE: CSR write operation 233*cfad6425SSerge Semin * @CSR_OP_READ: CSR read operation 234*cfad6425SSerge Semin * @CSR_RERR: Read operation error 235*cfad6425SSerge Semin * @CSR_WERR: Write operation error 236*cfad6425SSerge Semin * @CSR_WR_CNT: Bytes count to perform write operation 237*cfad6425SSerge Semin * @CSR_WRRD_CNT: Bytes count to write before reading 238*cfad6425SSerge Semin * @CSR_RD_CNT: Bytes count to perform read operation 239*cfad6425SSerge Semin * @CSR_MAX: Maximum CSR address 240*cfad6425SSerge Semin * @CSR_DEF: Default CSR address 241*cfad6425SSerge Semin * @CSR_REAL_ADDR: CSR real unshifted address 242*cfad6425SSerge Semin */ 243*cfad6425SSerge Semin #define CSR_DWE ((u8)0x0F) 244*cfad6425SSerge Semin #define CSR_OP_WRITE ((u8)0x00) 245*cfad6425SSerge Semin #define CSR_OP_READ ((u8)0x10) 246*cfad6425SSerge Semin #define CSR_RERR ((u8)0x40) 247*cfad6425SSerge Semin #define CSR_WERR ((u8)0x80) 248*cfad6425SSerge Semin #define CSR_WR_CNT ((u8)7) 249*cfad6425SSerge Semin #define CSR_WRRD_CNT ((u8)3) 250*cfad6425SSerge Semin #define CSR_RD_CNT ((u8)7) 251*cfad6425SSerge Semin #define CSR_MAX ((u32)0x3FFFF) 252*cfad6425SSerge Semin #define CSR_DEF ((u16)0x0000) 253*cfad6425SSerge Semin #define CSR_REAL_ADDR(val) ((unsigned int)val << 2) 254*cfad6425SSerge Semin 255*cfad6425SSerge Semin /* 256*cfad6425SSerge Semin * IDT 89HPESx basic register 257*cfad6425SSerge Semin * @IDT_VIDDID_CSR: PCIe VID and DID of IDT 89HPESx 258*cfad6425SSerge Semin * @IDT_VID_MASK: Mask of VID 259*cfad6425SSerge Semin */ 260*cfad6425SSerge Semin #define IDT_VIDDID_CSR ((u32)0x0000) 261*cfad6425SSerge Semin #define IDT_VID_MASK ((u32)0xFFFF) 262*cfad6425SSerge Semin 263*cfad6425SSerge Semin /* 264*cfad6425SSerge Semin * IDT 89HPESx can send NACK when new command is sent before previous one 265*cfad6425SSerge Semin * fininshed execution. In this case driver retries operation 266*cfad6425SSerge Semin * certain times. 267*cfad6425SSerge Semin * @RETRY_CNT: Number of retries before giving up and fail 268*cfad6425SSerge Semin * @idt_smb_safe: Generate a retry loop on corresponding SMBus method 269*cfad6425SSerge Semin */ 270*cfad6425SSerge Semin #define RETRY_CNT (128) 271*cfad6425SSerge Semin #define idt_smb_safe(ops, args...) ({ \ 272*cfad6425SSerge Semin int __retry = RETRY_CNT; \ 273*cfad6425SSerge Semin s32 __sts; \ 274*cfad6425SSerge Semin do { \ 275*cfad6425SSerge Semin __sts = i2c_smbus_ ## ops ## _data(args); \ 276*cfad6425SSerge Semin } while (__retry-- && __sts < 0); \ 277*cfad6425SSerge Semin __sts; \ 278*cfad6425SSerge Semin }) 279*cfad6425SSerge Semin 280*cfad6425SSerge Semin /*=========================================================================== 281*cfad6425SSerge Semin * i2c bus level IO-operations 282*cfad6425SSerge Semin *=========================================================================== 283*cfad6425SSerge Semin */ 284*cfad6425SSerge Semin 285*cfad6425SSerge Semin /* 286*cfad6425SSerge Semin * idt_smb_write_byte() - SMBus write method when I2C_SMBUS_BYTE_DATA operation 287*cfad6425SSerge Semin * is only available 288*cfad6425SSerge Semin * @pdev: Pointer to the driver data 289*cfad6425SSerge Semin * @seq: Sequence of data to be written 290*cfad6425SSerge Semin */ 291*cfad6425SSerge Semin static int idt_smb_write_byte(struct idt_89hpesx_dev *pdev, 292*cfad6425SSerge Semin const struct idt_smb_seq *seq) 293*cfad6425SSerge Semin { 294*cfad6425SSerge Semin s32 sts; 295*cfad6425SSerge Semin u8 ccode; 296*cfad6425SSerge Semin int idx; 297*cfad6425SSerge Semin 298*cfad6425SSerge Semin /* Loop over the supplied data sending byte one-by-one */ 299*cfad6425SSerge Semin for (idx = 0; idx < seq->bytecnt; idx++) { 300*cfad6425SSerge Semin /* Collect the command code byte */ 301*cfad6425SSerge Semin ccode = seq->ccode | CCODE_BYTE; 302*cfad6425SSerge Semin if (idx == 0) 303*cfad6425SSerge Semin ccode |= CCODE_START; 304*cfad6425SSerge Semin if (idx == seq->bytecnt - 1) 305*cfad6425SSerge Semin ccode |= CCODE_END; 306*cfad6425SSerge Semin 307*cfad6425SSerge Semin /* Send data to the device */ 308*cfad6425SSerge Semin sts = idt_smb_safe(write_byte, pdev->client, ccode, 309*cfad6425SSerge Semin seq->data[idx]); 310*cfad6425SSerge Semin if (sts != 0) 311*cfad6425SSerge Semin return (int)sts; 312*cfad6425SSerge Semin } 313*cfad6425SSerge Semin 314*cfad6425SSerge Semin return 0; 315*cfad6425SSerge Semin } 316*cfad6425SSerge Semin 317*cfad6425SSerge Semin /* 318*cfad6425SSerge Semin * idt_smb_read_byte() - SMBus read method when I2C_SMBUS_BYTE_DATA operation 319*cfad6425SSerge Semin * is only available 320*cfad6425SSerge Semin * @pdev: Pointer to the driver data 321*cfad6425SSerge Semin * @seq: Buffer to read data to 322*cfad6425SSerge Semin */ 323*cfad6425SSerge Semin static int idt_smb_read_byte(struct idt_89hpesx_dev *pdev, 324*cfad6425SSerge Semin struct idt_smb_seq *seq) 325*cfad6425SSerge Semin { 326*cfad6425SSerge Semin s32 sts; 327*cfad6425SSerge Semin u8 ccode; 328*cfad6425SSerge Semin int idx; 329*cfad6425SSerge Semin 330*cfad6425SSerge Semin /* Loop over the supplied buffer receiving byte one-by-one */ 331*cfad6425SSerge Semin for (idx = 0; idx < seq->bytecnt; idx++) { 332*cfad6425SSerge Semin /* Collect the command code byte */ 333*cfad6425SSerge Semin ccode = seq->ccode | CCODE_BYTE; 334*cfad6425SSerge Semin if (idx == 0) 335*cfad6425SSerge Semin ccode |= CCODE_START; 336*cfad6425SSerge Semin if (idx == seq->bytecnt - 1) 337*cfad6425SSerge Semin ccode |= CCODE_END; 338*cfad6425SSerge Semin 339*cfad6425SSerge Semin /* Read data from the device */ 340*cfad6425SSerge Semin sts = idt_smb_safe(read_byte, pdev->client, ccode); 341*cfad6425SSerge Semin if (sts < 0) 342*cfad6425SSerge Semin return (int)sts; 343*cfad6425SSerge Semin 344*cfad6425SSerge Semin seq->data[idx] = (u8)sts; 345*cfad6425SSerge Semin } 346*cfad6425SSerge Semin 347*cfad6425SSerge Semin return 0; 348*cfad6425SSerge Semin } 349*cfad6425SSerge Semin 350*cfad6425SSerge Semin /* 351*cfad6425SSerge Semin * idt_smb_write_word() - SMBus write method when I2C_SMBUS_BYTE_DATA and 352*cfad6425SSerge Semin * I2C_FUNC_SMBUS_WORD_DATA operations are available 353*cfad6425SSerge Semin * @pdev: Pointer to the driver data 354*cfad6425SSerge Semin * @seq: Sequence of data to be written 355*cfad6425SSerge Semin */ 356*cfad6425SSerge Semin static int idt_smb_write_word(struct idt_89hpesx_dev *pdev, 357*cfad6425SSerge Semin const struct idt_smb_seq *seq) 358*cfad6425SSerge Semin { 359*cfad6425SSerge Semin s32 sts; 360*cfad6425SSerge Semin u8 ccode; 361*cfad6425SSerge Semin int idx, evencnt; 362*cfad6425SSerge Semin 363*cfad6425SSerge Semin /* Calculate the even count of data to send */ 364*cfad6425SSerge Semin evencnt = seq->bytecnt - (seq->bytecnt % 2); 365*cfad6425SSerge Semin 366*cfad6425SSerge Semin /* Loop over the supplied data sending two bytes at a time */ 367*cfad6425SSerge Semin for (idx = 0; idx < evencnt; idx += 2) { 368*cfad6425SSerge Semin /* Collect the command code byte */ 369*cfad6425SSerge Semin ccode = seq->ccode | CCODE_WORD; 370*cfad6425SSerge Semin if (idx == 0) 371*cfad6425SSerge Semin ccode |= CCODE_START; 372*cfad6425SSerge Semin if (idx == evencnt - 2) 373*cfad6425SSerge Semin ccode |= CCODE_END; 374*cfad6425SSerge Semin 375*cfad6425SSerge Semin /* Send word data to the device */ 376*cfad6425SSerge Semin sts = idt_smb_safe(write_word, pdev->client, ccode, 377*cfad6425SSerge Semin *(u16 *)&seq->data[idx]); 378*cfad6425SSerge Semin if (sts != 0) 379*cfad6425SSerge Semin return (int)sts; 380*cfad6425SSerge Semin } 381*cfad6425SSerge Semin 382*cfad6425SSerge Semin /* If there is odd number of bytes then send just one last byte */ 383*cfad6425SSerge Semin if (seq->bytecnt != evencnt) { 384*cfad6425SSerge Semin /* Collect the command code byte */ 385*cfad6425SSerge Semin ccode = seq->ccode | CCODE_BYTE | CCODE_END; 386*cfad6425SSerge Semin if (idx == 0) 387*cfad6425SSerge Semin ccode |= CCODE_START; 388*cfad6425SSerge Semin 389*cfad6425SSerge Semin /* Send byte data to the device */ 390*cfad6425SSerge Semin sts = idt_smb_safe(write_byte, pdev->client, ccode, 391*cfad6425SSerge Semin seq->data[idx]); 392*cfad6425SSerge Semin if (sts != 0) 393*cfad6425SSerge Semin return (int)sts; 394*cfad6425SSerge Semin } 395*cfad6425SSerge Semin 396*cfad6425SSerge Semin return 0; 397*cfad6425SSerge Semin } 398*cfad6425SSerge Semin 399*cfad6425SSerge Semin /* 400*cfad6425SSerge Semin * idt_smb_read_word() - SMBus read method when I2C_SMBUS_BYTE_DATA and 401*cfad6425SSerge Semin * I2C_FUNC_SMBUS_WORD_DATA operations are available 402*cfad6425SSerge Semin * @pdev: Pointer to the driver data 403*cfad6425SSerge Semin * @seq: Buffer to read data to 404*cfad6425SSerge Semin */ 405*cfad6425SSerge Semin static int idt_smb_read_word(struct idt_89hpesx_dev *pdev, 406*cfad6425SSerge Semin struct idt_smb_seq *seq) 407*cfad6425SSerge Semin { 408*cfad6425SSerge Semin s32 sts; 409*cfad6425SSerge Semin u8 ccode; 410*cfad6425SSerge Semin int idx, evencnt; 411*cfad6425SSerge Semin 412*cfad6425SSerge Semin /* Calculate the even count of data to send */ 413*cfad6425SSerge Semin evencnt = seq->bytecnt - (seq->bytecnt % 2); 414*cfad6425SSerge Semin 415*cfad6425SSerge Semin /* Loop over the supplied data reading two bytes at a time */ 416*cfad6425SSerge Semin for (idx = 0; idx < evencnt; idx += 2) { 417*cfad6425SSerge Semin /* Collect the command code byte */ 418*cfad6425SSerge Semin ccode = seq->ccode | CCODE_WORD; 419*cfad6425SSerge Semin if (idx == 0) 420*cfad6425SSerge Semin ccode |= CCODE_START; 421*cfad6425SSerge Semin if (idx == evencnt - 2) 422*cfad6425SSerge Semin ccode |= CCODE_END; 423*cfad6425SSerge Semin 424*cfad6425SSerge Semin /* Read word data from the device */ 425*cfad6425SSerge Semin sts = idt_smb_safe(read_word, pdev->client, ccode); 426*cfad6425SSerge Semin if (sts < 0) 427*cfad6425SSerge Semin return (int)sts; 428*cfad6425SSerge Semin 429*cfad6425SSerge Semin *(u16 *)&seq->data[idx] = (u16)sts; 430*cfad6425SSerge Semin } 431*cfad6425SSerge Semin 432*cfad6425SSerge Semin /* If there is odd number of bytes then receive just one last byte */ 433*cfad6425SSerge Semin if (seq->bytecnt != evencnt) { 434*cfad6425SSerge Semin /* Collect the command code byte */ 435*cfad6425SSerge Semin ccode = seq->ccode | CCODE_BYTE | CCODE_END; 436*cfad6425SSerge Semin if (idx == 0) 437*cfad6425SSerge Semin ccode |= CCODE_START; 438*cfad6425SSerge Semin 439*cfad6425SSerge Semin /* Read last data byte from the device */ 440*cfad6425SSerge Semin sts = idt_smb_safe(read_byte, pdev->client, ccode); 441*cfad6425SSerge Semin if (sts < 0) 442*cfad6425SSerge Semin return (int)sts; 443*cfad6425SSerge Semin 444*cfad6425SSerge Semin seq->data[idx] = (u8)sts; 445*cfad6425SSerge Semin } 446*cfad6425SSerge Semin 447*cfad6425SSerge Semin return 0; 448*cfad6425SSerge Semin } 449*cfad6425SSerge Semin 450*cfad6425SSerge Semin /* 451*cfad6425SSerge Semin * idt_smb_write_block() - SMBus write method when I2C_SMBUS_BLOCK_DATA 452*cfad6425SSerge Semin * operation is available 453*cfad6425SSerge Semin * @pdev: Pointer to the driver data 454*cfad6425SSerge Semin * @seq: Sequence of data to be written 455*cfad6425SSerge Semin */ 456*cfad6425SSerge Semin static int idt_smb_write_block(struct idt_89hpesx_dev *pdev, 457*cfad6425SSerge Semin const struct idt_smb_seq *seq) 458*cfad6425SSerge Semin { 459*cfad6425SSerge Semin u8 ccode; 460*cfad6425SSerge Semin 461*cfad6425SSerge Semin /* Return error if too much data passed to send */ 462*cfad6425SSerge Semin if (seq->bytecnt > I2C_SMBUS_BLOCK_MAX) 463*cfad6425SSerge Semin return -EINVAL; 464*cfad6425SSerge Semin 465*cfad6425SSerge Semin /* Collect the command code byte */ 466*cfad6425SSerge Semin ccode = seq->ccode | CCODE_BLOCK | CCODE_START | CCODE_END; 467*cfad6425SSerge Semin 468*cfad6425SSerge Semin /* Send block of data to the device */ 469*cfad6425SSerge Semin return idt_smb_safe(write_block, pdev->client, ccode, seq->bytecnt, 470*cfad6425SSerge Semin seq->data); 471*cfad6425SSerge Semin } 472*cfad6425SSerge Semin 473*cfad6425SSerge Semin /* 474*cfad6425SSerge Semin * idt_smb_read_block() - SMBus read method when I2C_SMBUS_BLOCK_DATA 475*cfad6425SSerge Semin * operation is available 476*cfad6425SSerge Semin * @pdev: Pointer to the driver data 477*cfad6425SSerge Semin * @seq: Buffer to read data to 478*cfad6425SSerge Semin */ 479*cfad6425SSerge Semin static int idt_smb_read_block(struct idt_89hpesx_dev *pdev, 480*cfad6425SSerge Semin struct idt_smb_seq *seq) 481*cfad6425SSerge Semin { 482*cfad6425SSerge Semin s32 sts; 483*cfad6425SSerge Semin u8 ccode; 484*cfad6425SSerge Semin 485*cfad6425SSerge Semin /* Return error if too much data passed to send */ 486*cfad6425SSerge Semin if (seq->bytecnt > I2C_SMBUS_BLOCK_MAX) 487*cfad6425SSerge Semin return -EINVAL; 488*cfad6425SSerge Semin 489*cfad6425SSerge Semin /* Collect the command code byte */ 490*cfad6425SSerge Semin ccode = seq->ccode | CCODE_BLOCK | CCODE_START | CCODE_END; 491*cfad6425SSerge Semin 492*cfad6425SSerge Semin /* Read block of data from the device */ 493*cfad6425SSerge Semin sts = idt_smb_safe(read_block, pdev->client, ccode, seq->data); 494*cfad6425SSerge Semin if (sts != seq->bytecnt) 495*cfad6425SSerge Semin return (sts < 0 ? sts : -ENODATA); 496*cfad6425SSerge Semin 497*cfad6425SSerge Semin return 0; 498*cfad6425SSerge Semin } 499*cfad6425SSerge Semin 500*cfad6425SSerge Semin /* 501*cfad6425SSerge Semin * idt_smb_write_i2c_block() - SMBus write method when I2C_SMBUS_I2C_BLOCK_DATA 502*cfad6425SSerge Semin * operation is available 503*cfad6425SSerge Semin * @pdev: Pointer to the driver data 504*cfad6425SSerge Semin * @seq: Sequence of data to be written 505*cfad6425SSerge Semin * 506*cfad6425SSerge Semin * NOTE It's usual SMBus write block operation, except the actual data length is 507*cfad6425SSerge Semin * sent as first byte of data 508*cfad6425SSerge Semin */ 509*cfad6425SSerge Semin static int idt_smb_write_i2c_block(struct idt_89hpesx_dev *pdev, 510*cfad6425SSerge Semin const struct idt_smb_seq *seq) 511*cfad6425SSerge Semin { 512*cfad6425SSerge Semin u8 ccode, buf[I2C_SMBUS_BLOCK_MAX + 1]; 513*cfad6425SSerge Semin 514*cfad6425SSerge Semin /* Return error if too much data passed to send */ 515*cfad6425SSerge Semin if (seq->bytecnt > I2C_SMBUS_BLOCK_MAX) 516*cfad6425SSerge Semin return -EINVAL; 517*cfad6425SSerge Semin 518*cfad6425SSerge Semin /* Collect the data to send. Length byte must be added prior the data */ 519*cfad6425SSerge Semin buf[0] = seq->bytecnt; 520*cfad6425SSerge Semin memcpy(&buf[1], seq->data, seq->bytecnt); 521*cfad6425SSerge Semin 522*cfad6425SSerge Semin /* Collect the command code byte */ 523*cfad6425SSerge Semin ccode = seq->ccode | CCODE_BLOCK | CCODE_START | CCODE_END; 524*cfad6425SSerge Semin 525*cfad6425SSerge Semin /* Send length and block of data to the device */ 526*cfad6425SSerge Semin return idt_smb_safe(write_i2c_block, pdev->client, ccode, 527*cfad6425SSerge Semin seq->bytecnt + 1, buf); 528*cfad6425SSerge Semin } 529*cfad6425SSerge Semin 530*cfad6425SSerge Semin /* 531*cfad6425SSerge Semin * idt_smb_read_i2c_block() - SMBus read method when I2C_SMBUS_I2C_BLOCK_DATA 532*cfad6425SSerge Semin * operation is available 533*cfad6425SSerge Semin * @pdev: Pointer to the driver data 534*cfad6425SSerge Semin * @seq: Buffer to read data to 535*cfad6425SSerge Semin * 536*cfad6425SSerge Semin * NOTE It's usual SMBus read block operation, except the actual data length is 537*cfad6425SSerge Semin * retrieved as first byte of data 538*cfad6425SSerge Semin */ 539*cfad6425SSerge Semin static int idt_smb_read_i2c_block(struct idt_89hpesx_dev *pdev, 540*cfad6425SSerge Semin struct idt_smb_seq *seq) 541*cfad6425SSerge Semin { 542*cfad6425SSerge Semin u8 ccode, buf[I2C_SMBUS_BLOCK_MAX + 1]; 543*cfad6425SSerge Semin s32 sts; 544*cfad6425SSerge Semin 545*cfad6425SSerge Semin /* Return error if too much data passed to send */ 546*cfad6425SSerge Semin if (seq->bytecnt > I2C_SMBUS_BLOCK_MAX) 547*cfad6425SSerge Semin return -EINVAL; 548*cfad6425SSerge Semin 549*cfad6425SSerge Semin /* Collect the command code byte */ 550*cfad6425SSerge Semin ccode = seq->ccode | CCODE_BLOCK | CCODE_START | CCODE_END; 551*cfad6425SSerge Semin 552*cfad6425SSerge Semin /* Read length and block of data from the device */ 553*cfad6425SSerge Semin sts = idt_smb_safe(read_i2c_block, pdev->client, ccode, 554*cfad6425SSerge Semin seq->bytecnt + 1, buf); 555*cfad6425SSerge Semin if (sts != seq->bytecnt + 1) 556*cfad6425SSerge Semin return (sts < 0 ? sts : -ENODATA); 557*cfad6425SSerge Semin if (buf[0] != seq->bytecnt) 558*cfad6425SSerge Semin return -ENODATA; 559*cfad6425SSerge Semin 560*cfad6425SSerge Semin /* Copy retrieved data to the output data buffer */ 561*cfad6425SSerge Semin memcpy(seq->data, &buf[1], seq->bytecnt); 562*cfad6425SSerge Semin 563*cfad6425SSerge Semin return 0; 564*cfad6425SSerge Semin } 565*cfad6425SSerge Semin 566*cfad6425SSerge Semin /*=========================================================================== 567*cfad6425SSerge Semin * EEPROM IO-operations 568*cfad6425SSerge Semin *=========================================================================== 569*cfad6425SSerge Semin */ 570*cfad6425SSerge Semin 571*cfad6425SSerge Semin /* 572*cfad6425SSerge Semin * idt_eeprom_read_byte() - read just one byte from EEPROM 573*cfad6425SSerge Semin * @pdev: Pointer to the driver data 574*cfad6425SSerge Semin * @memaddr: Start EEPROM memory address 575*cfad6425SSerge Semin * @data: Data to be written to EEPROM 576*cfad6425SSerge Semin */ 577*cfad6425SSerge Semin static int idt_eeprom_read_byte(struct idt_89hpesx_dev *pdev, u16 memaddr, 578*cfad6425SSerge Semin u8 *data) 579*cfad6425SSerge Semin { 580*cfad6425SSerge Semin struct device *dev = &pdev->client->dev; 581*cfad6425SSerge Semin struct idt_eeprom_seq eeseq; 582*cfad6425SSerge Semin struct idt_smb_seq smbseq; 583*cfad6425SSerge Semin int ret, retry; 584*cfad6425SSerge Semin 585*cfad6425SSerge Semin /* Initialize SMBus sequence fields */ 586*cfad6425SSerge Semin smbseq.ccode = pdev->iniccode | CCODE_EEPROM; 587*cfad6425SSerge Semin smbseq.data = (u8 *)&eeseq; 588*cfad6425SSerge Semin 589*cfad6425SSerge Semin /* 590*cfad6425SSerge Semin * Sometimes EEPROM may respond with NACK if it's busy with previous 591*cfad6425SSerge Semin * operation, so we need to perform a few attempts of read cycle 592*cfad6425SSerge Semin */ 593*cfad6425SSerge Semin retry = RETRY_CNT; 594*cfad6425SSerge Semin do { 595*cfad6425SSerge Semin /* Send EEPROM memory address to read data from */ 596*cfad6425SSerge Semin smbseq.bytecnt = EEPROM_WRRD_CNT; 597*cfad6425SSerge Semin eeseq.cmd = pdev->inieecmd | EEPROM_OP_READ; 598*cfad6425SSerge Semin eeseq.eeaddr = pdev->eeaddr; 599*cfad6425SSerge Semin eeseq.memaddr = cpu_to_le16(memaddr); 600*cfad6425SSerge Semin ret = pdev->smb_write(pdev, &smbseq); 601*cfad6425SSerge Semin if (ret != 0) { 602*cfad6425SSerge Semin dev_err(dev, "Failed to init eeprom addr 0x%02hhx", 603*cfad6425SSerge Semin memaddr); 604*cfad6425SSerge Semin break; 605*cfad6425SSerge Semin } 606*cfad6425SSerge Semin 607*cfad6425SSerge Semin /* Perform read operation */ 608*cfad6425SSerge Semin smbseq.bytecnt = EEPROM_RD_CNT; 609*cfad6425SSerge Semin ret = pdev->smb_read(pdev, &smbseq); 610*cfad6425SSerge Semin if (ret != 0) { 611*cfad6425SSerge Semin dev_err(dev, "Failed to read eeprom data 0x%02hhx", 612*cfad6425SSerge Semin memaddr); 613*cfad6425SSerge Semin break; 614*cfad6425SSerge Semin } 615*cfad6425SSerge Semin 616*cfad6425SSerge Semin /* Restart read operation if the device is busy */ 617*cfad6425SSerge Semin if (retry && (eeseq.cmd & EEPROM_NAERR)) { 618*cfad6425SSerge Semin dev_dbg(dev, "EEPROM busy, retry reading after %d ms", 619*cfad6425SSerge Semin EEPROM_TOUT); 620*cfad6425SSerge Semin msleep(EEPROM_TOUT); 621*cfad6425SSerge Semin continue; 622*cfad6425SSerge Semin } 623*cfad6425SSerge Semin 624*cfad6425SSerge Semin /* Check whether IDT successfully read data from EEPROM */ 625*cfad6425SSerge Semin if (eeseq.cmd & (EEPROM_NAERR | EEPROM_LAERR | EEPROM_MSS)) { 626*cfad6425SSerge Semin dev_err(dev, 627*cfad6425SSerge Semin "Communication with eeprom failed, cmd 0x%hhx", 628*cfad6425SSerge Semin eeseq.cmd); 629*cfad6425SSerge Semin ret = -EREMOTEIO; 630*cfad6425SSerge Semin break; 631*cfad6425SSerge Semin } 632*cfad6425SSerge Semin 633*cfad6425SSerge Semin /* Save retrieved data and exit the loop */ 634*cfad6425SSerge Semin *data = eeseq.data; 635*cfad6425SSerge Semin break; 636*cfad6425SSerge Semin } while (retry--); 637*cfad6425SSerge Semin 638*cfad6425SSerge Semin /* Return the status of operation */ 639*cfad6425SSerge Semin return ret; 640*cfad6425SSerge Semin } 641*cfad6425SSerge Semin 642*cfad6425SSerge Semin /* 643*cfad6425SSerge Semin * idt_eeprom_write() - EEPROM write operation 644*cfad6425SSerge Semin * @pdev: Pointer to the driver data 645*cfad6425SSerge Semin * @memaddr: Start EEPROM memory address 646*cfad6425SSerge Semin * @len: Length of data to be written 647*cfad6425SSerge Semin * @data: Data to be written to EEPROM 648*cfad6425SSerge Semin */ 649*cfad6425SSerge Semin static int idt_eeprom_write(struct idt_89hpesx_dev *pdev, u16 memaddr, u16 len, 650*cfad6425SSerge Semin const u8 *data) 651*cfad6425SSerge Semin { 652*cfad6425SSerge Semin struct device *dev = &pdev->client->dev; 653*cfad6425SSerge Semin struct idt_eeprom_seq eeseq; 654*cfad6425SSerge Semin struct idt_smb_seq smbseq; 655*cfad6425SSerge Semin int ret; 656*cfad6425SSerge Semin u16 idx; 657*cfad6425SSerge Semin 658*cfad6425SSerge Semin /* Initialize SMBus sequence fields */ 659*cfad6425SSerge Semin smbseq.ccode = pdev->iniccode | CCODE_EEPROM; 660*cfad6425SSerge Semin smbseq.data = (u8 *)&eeseq; 661*cfad6425SSerge Semin 662*cfad6425SSerge Semin /* Send data byte-by-byte, checking if it is successfully written */ 663*cfad6425SSerge Semin for (idx = 0; idx < len; idx++, memaddr++) { 664*cfad6425SSerge Semin /* Lock IDT SMBus device */ 665*cfad6425SSerge Semin mutex_lock(&pdev->smb_mtx); 666*cfad6425SSerge Semin 667*cfad6425SSerge Semin /* Perform write operation */ 668*cfad6425SSerge Semin smbseq.bytecnt = EEPROM_WR_CNT; 669*cfad6425SSerge Semin eeseq.cmd = pdev->inieecmd | EEPROM_OP_WRITE; 670*cfad6425SSerge Semin eeseq.eeaddr = pdev->eeaddr; 671*cfad6425SSerge Semin eeseq.memaddr = cpu_to_le16(memaddr); 672*cfad6425SSerge Semin eeseq.data = data[idx]; 673*cfad6425SSerge Semin ret = pdev->smb_write(pdev, &smbseq); 674*cfad6425SSerge Semin if (ret != 0) { 675*cfad6425SSerge Semin dev_err(dev, 676*cfad6425SSerge Semin "Failed to write 0x%04hx:0x%02hhx to eeprom", 677*cfad6425SSerge Semin memaddr, data[idx]); 678*cfad6425SSerge Semin goto err_mutex_unlock; 679*cfad6425SSerge Semin } 680*cfad6425SSerge Semin 681*cfad6425SSerge Semin /* 682*cfad6425SSerge Semin * Check whether the data is successfully written by reading 683*cfad6425SSerge Semin * from the same EEPROM memory address. 684*cfad6425SSerge Semin */ 685*cfad6425SSerge Semin eeseq.data = ~data[idx]; 686*cfad6425SSerge Semin ret = idt_eeprom_read_byte(pdev, memaddr, &eeseq.data); 687*cfad6425SSerge Semin if (ret != 0) 688*cfad6425SSerge Semin goto err_mutex_unlock; 689*cfad6425SSerge Semin 690*cfad6425SSerge Semin /* Check whether the read byte is the same as written one */ 691*cfad6425SSerge Semin if (eeseq.data != data[idx]) { 692*cfad6425SSerge Semin dev_err(dev, "Values don't match 0x%02hhx != 0x%02hhx", 693*cfad6425SSerge Semin eeseq.data, data[idx]); 694*cfad6425SSerge Semin ret = -EREMOTEIO; 695*cfad6425SSerge Semin goto err_mutex_unlock; 696*cfad6425SSerge Semin } 697*cfad6425SSerge Semin 698*cfad6425SSerge Semin /* Unlock IDT SMBus device */ 699*cfad6425SSerge Semin err_mutex_unlock: 700*cfad6425SSerge Semin mutex_unlock(&pdev->smb_mtx); 701*cfad6425SSerge Semin if (ret != 0) 702*cfad6425SSerge Semin return ret; 703*cfad6425SSerge Semin } 704*cfad6425SSerge Semin 705*cfad6425SSerge Semin return 0; 706*cfad6425SSerge Semin } 707*cfad6425SSerge Semin 708*cfad6425SSerge Semin /* 709*cfad6425SSerge Semin * idt_eeprom_read() - EEPROM read operation 710*cfad6425SSerge Semin * @pdev: Pointer to the driver data 711*cfad6425SSerge Semin * @memaddr: Start EEPROM memory address 712*cfad6425SSerge Semin * @len: Length of data to read 713*cfad6425SSerge Semin * @buf: Buffer to read data to 714*cfad6425SSerge Semin */ 715*cfad6425SSerge Semin static int idt_eeprom_read(struct idt_89hpesx_dev *pdev, u16 memaddr, u16 len, 716*cfad6425SSerge Semin u8 *buf) 717*cfad6425SSerge Semin { 718*cfad6425SSerge Semin int ret; 719*cfad6425SSerge Semin u16 idx; 720*cfad6425SSerge Semin 721*cfad6425SSerge Semin /* Read data byte-by-byte, retrying if it wasn't successful */ 722*cfad6425SSerge Semin for (idx = 0; idx < len; idx++, memaddr++) { 723*cfad6425SSerge Semin /* Lock IDT SMBus device */ 724*cfad6425SSerge Semin mutex_lock(&pdev->smb_mtx); 725*cfad6425SSerge Semin 726*cfad6425SSerge Semin /* Just read the byte to the buffer */ 727*cfad6425SSerge Semin ret = idt_eeprom_read_byte(pdev, memaddr, &buf[idx]); 728*cfad6425SSerge Semin 729*cfad6425SSerge Semin /* Unlock IDT SMBus device */ 730*cfad6425SSerge Semin mutex_unlock(&pdev->smb_mtx); 731*cfad6425SSerge Semin 732*cfad6425SSerge Semin /* Return error if read operation failed */ 733*cfad6425SSerge Semin if (ret != 0) 734*cfad6425SSerge Semin return ret; 735*cfad6425SSerge Semin } 736*cfad6425SSerge Semin 737*cfad6425SSerge Semin return 0; 738*cfad6425SSerge Semin } 739*cfad6425SSerge Semin 740*cfad6425SSerge Semin /*=========================================================================== 741*cfad6425SSerge Semin * CSR IO-operations 742*cfad6425SSerge Semin *=========================================================================== 743*cfad6425SSerge Semin */ 744*cfad6425SSerge Semin 745*cfad6425SSerge Semin /* 746*cfad6425SSerge Semin * idt_csr_write() - CSR write operation 747*cfad6425SSerge Semin * @pdev: Pointer to the driver data 748*cfad6425SSerge Semin * @csraddr: CSR address (with no two LS bits) 749*cfad6425SSerge Semin * @data: Data to be written to CSR 750*cfad6425SSerge Semin */ 751*cfad6425SSerge Semin static int idt_csr_write(struct idt_89hpesx_dev *pdev, u16 csraddr, 752*cfad6425SSerge Semin const u32 data) 753*cfad6425SSerge Semin { 754*cfad6425SSerge Semin struct device *dev = &pdev->client->dev; 755*cfad6425SSerge Semin struct idt_csr_seq csrseq; 756*cfad6425SSerge Semin struct idt_smb_seq smbseq; 757*cfad6425SSerge Semin int ret; 758*cfad6425SSerge Semin 759*cfad6425SSerge Semin /* Initialize SMBus sequence fields */ 760*cfad6425SSerge Semin smbseq.ccode = pdev->iniccode | CCODE_CSR; 761*cfad6425SSerge Semin smbseq.data = (u8 *)&csrseq; 762*cfad6425SSerge Semin 763*cfad6425SSerge Semin /* Lock IDT SMBus device */ 764*cfad6425SSerge Semin mutex_lock(&pdev->smb_mtx); 765*cfad6425SSerge Semin 766*cfad6425SSerge Semin /* Perform write operation */ 767*cfad6425SSerge Semin smbseq.bytecnt = CSR_WR_CNT; 768*cfad6425SSerge Semin csrseq.cmd = pdev->inicsrcmd | CSR_OP_WRITE; 769*cfad6425SSerge Semin csrseq.csraddr = cpu_to_le16(csraddr); 770*cfad6425SSerge Semin csrseq.data = cpu_to_le32(data); 771*cfad6425SSerge Semin ret = pdev->smb_write(pdev, &smbseq); 772*cfad6425SSerge Semin if (ret != 0) { 773*cfad6425SSerge Semin dev_err(dev, "Failed to write 0x%04x: 0x%04x to csr", 774*cfad6425SSerge Semin CSR_REAL_ADDR(csraddr), data); 775*cfad6425SSerge Semin goto err_mutex_unlock; 776*cfad6425SSerge Semin } 777*cfad6425SSerge Semin 778*cfad6425SSerge Semin /* Send CSR address to read data from */ 779*cfad6425SSerge Semin smbseq.bytecnt = CSR_WRRD_CNT; 780*cfad6425SSerge Semin csrseq.cmd = pdev->inicsrcmd | CSR_OP_READ; 781*cfad6425SSerge Semin ret = pdev->smb_write(pdev, &smbseq); 782*cfad6425SSerge Semin if (ret != 0) { 783*cfad6425SSerge Semin dev_err(dev, "Failed to init csr address 0x%04x", 784*cfad6425SSerge Semin CSR_REAL_ADDR(csraddr)); 785*cfad6425SSerge Semin goto err_mutex_unlock; 786*cfad6425SSerge Semin } 787*cfad6425SSerge Semin 788*cfad6425SSerge Semin /* Perform read operation */ 789*cfad6425SSerge Semin smbseq.bytecnt = CSR_RD_CNT; 790*cfad6425SSerge Semin ret = pdev->smb_read(pdev, &smbseq); 791*cfad6425SSerge Semin if (ret != 0) { 792*cfad6425SSerge Semin dev_err(dev, "Failed to read csr 0x%04x", 793*cfad6425SSerge Semin CSR_REAL_ADDR(csraddr)); 794*cfad6425SSerge Semin goto err_mutex_unlock; 795*cfad6425SSerge Semin } 796*cfad6425SSerge Semin 797*cfad6425SSerge Semin /* Check whether IDT successfully retrieved CSR data */ 798*cfad6425SSerge Semin if (csrseq.cmd & (CSR_RERR | CSR_WERR)) { 799*cfad6425SSerge Semin dev_err(dev, "IDT failed to perform CSR r/w"); 800*cfad6425SSerge Semin ret = -EREMOTEIO; 801*cfad6425SSerge Semin goto err_mutex_unlock; 802*cfad6425SSerge Semin } 803*cfad6425SSerge Semin 804*cfad6425SSerge Semin /* Unlock IDT SMBus device */ 805*cfad6425SSerge Semin err_mutex_unlock: 806*cfad6425SSerge Semin mutex_unlock(&pdev->smb_mtx); 807*cfad6425SSerge Semin 808*cfad6425SSerge Semin return ret; 809*cfad6425SSerge Semin } 810*cfad6425SSerge Semin 811*cfad6425SSerge Semin /* 812*cfad6425SSerge Semin * idt_csr_read() - CSR read operation 813*cfad6425SSerge Semin * @pdev: Pointer to the driver data 814*cfad6425SSerge Semin * @csraddr: CSR address (with no two LS bits) 815*cfad6425SSerge Semin * @data: Data to be written to CSR 816*cfad6425SSerge Semin */ 817*cfad6425SSerge Semin static int idt_csr_read(struct idt_89hpesx_dev *pdev, u16 csraddr, u32 *data) 818*cfad6425SSerge Semin { 819*cfad6425SSerge Semin struct device *dev = &pdev->client->dev; 820*cfad6425SSerge Semin struct idt_csr_seq csrseq; 821*cfad6425SSerge Semin struct idt_smb_seq smbseq; 822*cfad6425SSerge Semin int ret; 823*cfad6425SSerge Semin 824*cfad6425SSerge Semin /* Initialize SMBus sequence fields */ 825*cfad6425SSerge Semin smbseq.ccode = pdev->iniccode | CCODE_CSR; 826*cfad6425SSerge Semin smbseq.data = (u8 *)&csrseq; 827*cfad6425SSerge Semin 828*cfad6425SSerge Semin /* Lock IDT SMBus device */ 829*cfad6425SSerge Semin mutex_lock(&pdev->smb_mtx); 830*cfad6425SSerge Semin 831*cfad6425SSerge Semin /* Send CSR register address before reading it */ 832*cfad6425SSerge Semin smbseq.bytecnt = CSR_WRRD_CNT; 833*cfad6425SSerge Semin csrseq.cmd = pdev->inicsrcmd | CSR_OP_READ; 834*cfad6425SSerge Semin csrseq.csraddr = cpu_to_le16(csraddr); 835*cfad6425SSerge Semin ret = pdev->smb_write(pdev, &smbseq); 836*cfad6425SSerge Semin if (ret != 0) { 837*cfad6425SSerge Semin dev_err(dev, "Failed to init csr address 0x%04x", 838*cfad6425SSerge Semin CSR_REAL_ADDR(csraddr)); 839*cfad6425SSerge Semin goto err_mutex_unlock; 840*cfad6425SSerge Semin } 841*cfad6425SSerge Semin 842*cfad6425SSerge Semin /* Perform read operation */ 843*cfad6425SSerge Semin smbseq.bytecnt = CSR_RD_CNT; 844*cfad6425SSerge Semin ret = pdev->smb_read(pdev, &smbseq); 845*cfad6425SSerge Semin if (ret != 0) { 846*cfad6425SSerge Semin dev_err(dev, "Failed to read csr 0x%04hx", 847*cfad6425SSerge Semin CSR_REAL_ADDR(csraddr)); 848*cfad6425SSerge Semin goto err_mutex_unlock; 849*cfad6425SSerge Semin } 850*cfad6425SSerge Semin 851*cfad6425SSerge Semin /* Check whether IDT successfully retrieved CSR data */ 852*cfad6425SSerge Semin if (csrseq.cmd & (CSR_RERR | CSR_WERR)) { 853*cfad6425SSerge Semin dev_err(dev, "IDT failed to perform CSR r/w"); 854*cfad6425SSerge Semin ret = -EREMOTEIO; 855*cfad6425SSerge Semin goto err_mutex_unlock; 856*cfad6425SSerge Semin } 857*cfad6425SSerge Semin 858*cfad6425SSerge Semin /* Save data retrieved from IDT */ 859*cfad6425SSerge Semin *data = le32_to_cpu(csrseq.data); 860*cfad6425SSerge Semin 861*cfad6425SSerge Semin /* Unlock IDT SMBus device */ 862*cfad6425SSerge Semin err_mutex_unlock: 863*cfad6425SSerge Semin mutex_unlock(&pdev->smb_mtx); 864*cfad6425SSerge Semin 865*cfad6425SSerge Semin return ret; 866*cfad6425SSerge Semin } 867*cfad6425SSerge Semin 868*cfad6425SSerge Semin /*=========================================================================== 869*cfad6425SSerge Semin * Sysfs/debugfs-nodes IO-operations 870*cfad6425SSerge Semin *=========================================================================== 871*cfad6425SSerge Semin */ 872*cfad6425SSerge Semin 873*cfad6425SSerge Semin /* 874*cfad6425SSerge Semin * eeprom_write() - EEPROM sysfs-node write callback 875*cfad6425SSerge Semin * @filep: Pointer to the file system node 876*cfad6425SSerge Semin * @kobj: Pointer to the kernel object related to the sysfs-node 877*cfad6425SSerge Semin * @attr: Attributes of the file 878*cfad6425SSerge Semin * @buf: Buffer to write data to 879*cfad6425SSerge Semin * @off: Offset at which data should be written to 880*cfad6425SSerge Semin * @count: Number of bytes to write 881*cfad6425SSerge Semin */ 882*cfad6425SSerge Semin static ssize_t eeprom_write(struct file *filp, struct kobject *kobj, 883*cfad6425SSerge Semin struct bin_attribute *attr, 884*cfad6425SSerge Semin char *buf, loff_t off, size_t count) 885*cfad6425SSerge Semin { 886*cfad6425SSerge Semin struct idt_89hpesx_dev *pdev; 887*cfad6425SSerge Semin int ret; 888*cfad6425SSerge Semin 889*cfad6425SSerge Semin /* Retrieve driver data */ 890*cfad6425SSerge Semin pdev = dev_get_drvdata(kobj_to_dev(kobj)); 891*cfad6425SSerge Semin 892*cfad6425SSerge Semin /* Perform EEPROM write operation */ 893*cfad6425SSerge Semin ret = idt_eeprom_write(pdev, (u16)off, (u16)count, (u8 *)buf); 894*cfad6425SSerge Semin return (ret != 0 ? ret : count); 895*cfad6425SSerge Semin } 896*cfad6425SSerge Semin 897*cfad6425SSerge Semin /* 898*cfad6425SSerge Semin * eeprom_read() - EEPROM sysfs-node read callback 899*cfad6425SSerge Semin * @filep: Pointer to the file system node 900*cfad6425SSerge Semin * @kobj: Pointer to the kernel object related to the sysfs-node 901*cfad6425SSerge Semin * @attr: Attributes of the file 902*cfad6425SSerge Semin * @buf: Buffer to write data to 903*cfad6425SSerge Semin * @off: Offset at which data should be written to 904*cfad6425SSerge Semin * @count: Number of bytes to write 905*cfad6425SSerge Semin */ 906*cfad6425SSerge Semin static ssize_t eeprom_read(struct file *filp, struct kobject *kobj, 907*cfad6425SSerge Semin struct bin_attribute *attr, 908*cfad6425SSerge Semin char *buf, loff_t off, size_t count) 909*cfad6425SSerge Semin { 910*cfad6425SSerge Semin struct idt_89hpesx_dev *pdev; 911*cfad6425SSerge Semin int ret; 912*cfad6425SSerge Semin 913*cfad6425SSerge Semin /* Retrieve driver data */ 914*cfad6425SSerge Semin pdev = dev_get_drvdata(kobj_to_dev(kobj)); 915*cfad6425SSerge Semin 916*cfad6425SSerge Semin /* Perform EEPROM read operation */ 917*cfad6425SSerge Semin ret = idt_eeprom_read(pdev, (u16)off, (u16)count, (u8 *)buf); 918*cfad6425SSerge Semin return (ret != 0 ? ret : count); 919*cfad6425SSerge Semin } 920*cfad6425SSerge Semin 921*cfad6425SSerge Semin /* 922*cfad6425SSerge Semin * idt_dbgfs_csr_write() - CSR debugfs-node write callback 923*cfad6425SSerge Semin * @filep: Pointer to the file system file descriptor 924*cfad6425SSerge Semin * @buf: Buffer to read data from 925*cfad6425SSerge Semin * @count: Size of the buffer 926*cfad6425SSerge Semin * @offp: Offset within the file 927*cfad6425SSerge Semin * 928*cfad6425SSerge Semin * It accepts either "0x<reg addr>:0x<value>" for saving register address 929*cfad6425SSerge Semin * and writing value to specified DWORD register or "0x<reg addr>" for 930*cfad6425SSerge Semin * just saving register address in order to perform next read operation. 931*cfad6425SSerge Semin * 932*cfad6425SSerge Semin * WARNING No spaces are allowed. Incoming string must be strictly formated as: 933*cfad6425SSerge Semin * "<reg addr>:<value>". Register address must be aligned within 4 bytes 934*cfad6425SSerge Semin * (one DWORD). 935*cfad6425SSerge Semin */ 936*cfad6425SSerge Semin static ssize_t idt_dbgfs_csr_write(struct file *filep, const char __user *ubuf, 937*cfad6425SSerge Semin size_t count, loff_t *offp) 938*cfad6425SSerge Semin { 939*cfad6425SSerge Semin struct idt_89hpesx_dev *pdev = filep->private_data; 940*cfad6425SSerge Semin char *colon_ch, *csraddr_str, *csrval_str; 941*cfad6425SSerge Semin int ret, csraddr_len, csrval_len; 942*cfad6425SSerge Semin u32 csraddr, csrval; 943*cfad6425SSerge Semin char *buf; 944*cfad6425SSerge Semin 945*cfad6425SSerge Semin /* Copy data from User-space */ 946*cfad6425SSerge Semin buf = kmalloc(count + 1, GFP_KERNEL); 947*cfad6425SSerge Semin if (!buf) 948*cfad6425SSerge Semin return -ENOMEM; 949*cfad6425SSerge Semin 950*cfad6425SSerge Semin ret = simple_write_to_buffer(buf, count, offp, ubuf, count); 951*cfad6425SSerge Semin if (ret < 0) 952*cfad6425SSerge Semin goto free_buf; 953*cfad6425SSerge Semin buf[count] = 0; 954*cfad6425SSerge Semin 955*cfad6425SSerge Semin /* Find position of colon in the buffer */ 956*cfad6425SSerge Semin colon_ch = strnchr(buf, count, ':'); 957*cfad6425SSerge Semin 958*cfad6425SSerge Semin /* 959*cfad6425SSerge Semin * If there is colon passed then new CSR value should be parsed as 960*cfad6425SSerge Semin * well, so allocate buffer for CSR address substring. 961*cfad6425SSerge Semin * If no colon is found, then string must have just one number with 962*cfad6425SSerge Semin * no new CSR value 963*cfad6425SSerge Semin */ 964*cfad6425SSerge Semin if (colon_ch != NULL) { 965*cfad6425SSerge Semin csraddr_len = colon_ch - buf; 966*cfad6425SSerge Semin csraddr_str = 967*cfad6425SSerge Semin kmalloc(sizeof(char)*(csraddr_len + 1), GFP_KERNEL); 968*cfad6425SSerge Semin if (csraddr_str == NULL) 969*cfad6425SSerge Semin return -ENOMEM; 970*cfad6425SSerge Semin /* Copy the register address to the substring buffer */ 971*cfad6425SSerge Semin strncpy(csraddr_str, buf, csraddr_len); 972*cfad6425SSerge Semin csraddr_str[csraddr_len] = '\0'; 973*cfad6425SSerge Semin /* Register value must follow the colon */ 974*cfad6425SSerge Semin csrval_str = colon_ch + 1; 975*cfad6425SSerge Semin csrval_len = strnlen(csrval_str, count - csraddr_len); 976*cfad6425SSerge Semin } else /* if (str_colon == NULL) */ { 977*cfad6425SSerge Semin csraddr_str = (char *)buf; /* Just to shut warning up */ 978*cfad6425SSerge Semin csraddr_len = strnlen(csraddr_str, count); 979*cfad6425SSerge Semin csrval_str = NULL; 980*cfad6425SSerge Semin csrval_len = 0; 981*cfad6425SSerge Semin } 982*cfad6425SSerge Semin 983*cfad6425SSerge Semin /* Convert CSR address to u32 value */ 984*cfad6425SSerge Semin ret = kstrtou32(csraddr_str, 0, &csraddr); 985*cfad6425SSerge Semin if (ret != 0) 986*cfad6425SSerge Semin goto free_csraddr_str; 987*cfad6425SSerge Semin 988*cfad6425SSerge Semin /* Check whether passed register address is valid */ 989*cfad6425SSerge Semin if (csraddr > CSR_MAX || !IS_ALIGNED(csraddr, SZ_4)) { 990*cfad6425SSerge Semin ret = -EINVAL; 991*cfad6425SSerge Semin goto free_csraddr_str; 992*cfad6425SSerge Semin } 993*cfad6425SSerge Semin 994*cfad6425SSerge Semin /* Shift register address to the right so to have u16 address */ 995*cfad6425SSerge Semin pdev->csr = (csraddr >> 2); 996*cfad6425SSerge Semin 997*cfad6425SSerge Semin /* Parse new CSR value and send it to IDT, if colon has been found */ 998*cfad6425SSerge Semin if (colon_ch != NULL) { 999*cfad6425SSerge Semin ret = kstrtou32(csrval_str, 0, &csrval); 1000*cfad6425SSerge Semin if (ret != 0) 1001*cfad6425SSerge Semin goto free_csraddr_str; 1002*cfad6425SSerge Semin 1003*cfad6425SSerge Semin ret = idt_csr_write(pdev, pdev->csr, csrval); 1004*cfad6425SSerge Semin if (ret != 0) 1005*cfad6425SSerge Semin goto free_csraddr_str; 1006*cfad6425SSerge Semin } 1007*cfad6425SSerge Semin 1008*cfad6425SSerge Semin /* Free memory only if colon has been found */ 1009*cfad6425SSerge Semin free_csraddr_str: 1010*cfad6425SSerge Semin if (colon_ch != NULL) 1011*cfad6425SSerge Semin kfree(csraddr_str); 1012*cfad6425SSerge Semin 1013*cfad6425SSerge Semin /* Free buffer allocated for data retrieved from User-space */ 1014*cfad6425SSerge Semin free_buf: 1015*cfad6425SSerge Semin kfree(buf); 1016*cfad6425SSerge Semin 1017*cfad6425SSerge Semin return (ret != 0 ? ret : count); 1018*cfad6425SSerge Semin } 1019*cfad6425SSerge Semin 1020*cfad6425SSerge Semin /* 1021*cfad6425SSerge Semin * idt_dbgfs_csr_read() - CSR debugfs-node read callback 1022*cfad6425SSerge Semin * @filep: Pointer to the file system file descriptor 1023*cfad6425SSerge Semin * @buf: Buffer to write data to 1024*cfad6425SSerge Semin * @count: Size of the buffer 1025*cfad6425SSerge Semin * @offp: Offset within the file 1026*cfad6425SSerge Semin * 1027*cfad6425SSerge Semin * It just prints the pair "0x<reg addr>:0x<value>" to passed buffer. 1028*cfad6425SSerge Semin */ 1029*cfad6425SSerge Semin #define CSRBUF_SIZE ((size_t)32) 1030*cfad6425SSerge Semin static ssize_t idt_dbgfs_csr_read(struct file *filep, char __user *ubuf, 1031*cfad6425SSerge Semin size_t count, loff_t *offp) 1032*cfad6425SSerge Semin { 1033*cfad6425SSerge Semin struct idt_89hpesx_dev *pdev = filep->private_data; 1034*cfad6425SSerge Semin u32 csraddr, csrval; 1035*cfad6425SSerge Semin char buf[CSRBUF_SIZE]; 1036*cfad6425SSerge Semin int ret, size; 1037*cfad6425SSerge Semin 1038*cfad6425SSerge Semin /* Perform CSR read operation */ 1039*cfad6425SSerge Semin ret = idt_csr_read(pdev, pdev->csr, &csrval); 1040*cfad6425SSerge Semin if (ret != 0) 1041*cfad6425SSerge Semin return ret; 1042*cfad6425SSerge Semin 1043*cfad6425SSerge Semin /* Shift register address to the left so to have real address */ 1044*cfad6425SSerge Semin csraddr = ((u32)pdev->csr << 2); 1045*cfad6425SSerge Semin 1046*cfad6425SSerge Semin /* Print the "0x<reg addr>:0x<value>" to buffer */ 1047*cfad6425SSerge Semin size = snprintf(buf, CSRBUF_SIZE, "0x%05x:0x%08x\n", 1048*cfad6425SSerge Semin (unsigned int)csraddr, (unsigned int)csrval); 1049*cfad6425SSerge Semin 1050*cfad6425SSerge Semin /* Copy data to User-space */ 1051*cfad6425SSerge Semin return simple_read_from_buffer(ubuf, count, offp, buf, size); 1052*cfad6425SSerge Semin } 1053*cfad6425SSerge Semin 1054*cfad6425SSerge Semin /* 1055*cfad6425SSerge Semin * eeprom_attribute - EEPROM sysfs-node attributes 1056*cfad6425SSerge Semin * 1057*cfad6425SSerge Semin * NOTE Size will be changed in compliance with OF node. EEPROM attribute will 1058*cfad6425SSerge Semin * be read-only as well if the corresponding flag is specified in OF node. 1059*cfad6425SSerge Semin */ 1060*cfad6425SSerge Semin static BIN_ATTR_RW(eeprom, EEPROM_DEF_SIZE); 1061*cfad6425SSerge Semin 1062*cfad6425SSerge Semin /* 1063*cfad6425SSerge Semin * csr_dbgfs_ops - CSR debugfs-node read/write operations 1064*cfad6425SSerge Semin */ 1065*cfad6425SSerge Semin static const struct file_operations csr_dbgfs_ops = { 1066*cfad6425SSerge Semin .owner = THIS_MODULE, 1067*cfad6425SSerge Semin .open = simple_open, 1068*cfad6425SSerge Semin .write = idt_dbgfs_csr_write, 1069*cfad6425SSerge Semin .read = idt_dbgfs_csr_read 1070*cfad6425SSerge Semin }; 1071*cfad6425SSerge Semin 1072*cfad6425SSerge Semin /*=========================================================================== 1073*cfad6425SSerge Semin * Driver init/deinit methods 1074*cfad6425SSerge Semin *=========================================================================== 1075*cfad6425SSerge Semin */ 1076*cfad6425SSerge Semin 1077*cfad6425SSerge Semin /* 1078*cfad6425SSerge Semin * idt_set_defval() - disable EEPROM access by default 1079*cfad6425SSerge Semin * @pdev: Pointer to the driver data 1080*cfad6425SSerge Semin */ 1081*cfad6425SSerge Semin static void idt_set_defval(struct idt_89hpesx_dev *pdev) 1082*cfad6425SSerge Semin { 1083*cfad6425SSerge Semin /* If OF info is missing then use next values */ 1084*cfad6425SSerge Semin pdev->eesize = 0; 1085*cfad6425SSerge Semin pdev->eero = true; 1086*cfad6425SSerge Semin pdev->inieecmd = 0; 1087*cfad6425SSerge Semin pdev->eeaddr = 0; 1088*cfad6425SSerge Semin } 1089*cfad6425SSerge Semin 1090*cfad6425SSerge Semin #ifdef CONFIG_OF 1091*cfad6425SSerge Semin static const struct i2c_device_id ee_ids[]; 1092*cfad6425SSerge Semin /* 1093*cfad6425SSerge Semin * idt_ee_match_id() - check whether the node belongs to compatible EEPROMs 1094*cfad6425SSerge Semin */ 1095*cfad6425SSerge Semin static const struct i2c_device_id *idt_ee_match_id(struct device_node *node) 1096*cfad6425SSerge Semin { 1097*cfad6425SSerge Semin const struct i2c_device_id *id = ee_ids; 1098*cfad6425SSerge Semin char devname[I2C_NAME_SIZE]; 1099*cfad6425SSerge Semin 1100*cfad6425SSerge Semin /* Retrieve the device name without manufacturer name */ 1101*cfad6425SSerge Semin if (of_modalias_node(node, devname, sizeof(devname))) 1102*cfad6425SSerge Semin return NULL; 1103*cfad6425SSerge Semin 1104*cfad6425SSerge Semin /* Search through the device name */ 1105*cfad6425SSerge Semin while (id->name[0]) { 1106*cfad6425SSerge Semin if (strcmp(devname, id->name) == 0) 1107*cfad6425SSerge Semin return id; 1108*cfad6425SSerge Semin id++; 1109*cfad6425SSerge Semin } 1110*cfad6425SSerge Semin return NULL; 1111*cfad6425SSerge Semin } 1112*cfad6425SSerge Semin 1113*cfad6425SSerge Semin /* 1114*cfad6425SSerge Semin * idt_get_ofdata() - get IDT i2c-device parameters from device tree 1115*cfad6425SSerge Semin * @pdev: Pointer to the driver data 1116*cfad6425SSerge Semin */ 1117*cfad6425SSerge Semin static void idt_get_ofdata(struct idt_89hpesx_dev *pdev) 1118*cfad6425SSerge Semin { 1119*cfad6425SSerge Semin const struct device_node *node = pdev->client->dev.of_node; 1120*cfad6425SSerge Semin struct device *dev = &pdev->client->dev; 1121*cfad6425SSerge Semin 1122*cfad6425SSerge Semin /* Read dts node parameters */ 1123*cfad6425SSerge Semin if (node) { 1124*cfad6425SSerge Semin const struct i2c_device_id *ee_id = NULL; 1125*cfad6425SSerge Semin struct device_node *child; 1126*cfad6425SSerge Semin const __be32 *addr_be; 1127*cfad6425SSerge Semin int len; 1128*cfad6425SSerge Semin 1129*cfad6425SSerge Semin /* Walk through all child nodes looking for compatible one */ 1130*cfad6425SSerge Semin for_each_available_child_of_node(node, child) { 1131*cfad6425SSerge Semin ee_id = idt_ee_match_id(child); 1132*cfad6425SSerge Semin if (IS_ERR_OR_NULL(ee_id)) { 1133*cfad6425SSerge Semin dev_warn(dev, "Skip unsupported child node %s", 1134*cfad6425SSerge Semin child->full_name); 1135*cfad6425SSerge Semin continue; 1136*cfad6425SSerge Semin } else 1137*cfad6425SSerge Semin break; 1138*cfad6425SSerge Semin } 1139*cfad6425SSerge Semin 1140*cfad6425SSerge Semin /* If there is no child EEPROM device, then set zero size */ 1141*cfad6425SSerge Semin if (!ee_id) { 1142*cfad6425SSerge Semin idt_set_defval(pdev); 1143*cfad6425SSerge Semin return; 1144*cfad6425SSerge Semin } 1145*cfad6425SSerge Semin 1146*cfad6425SSerge Semin /* Retrieve EEPROM size */ 1147*cfad6425SSerge Semin pdev->eesize = (u32)ee_id->driver_data; 1148*cfad6425SSerge Semin 1149*cfad6425SSerge Semin /* Get custom EEPROM address from 'reg' attribute */ 1150*cfad6425SSerge Semin addr_be = of_get_property(child, "reg", &len); 1151*cfad6425SSerge Semin if (!addr_be || (len < sizeof(*addr_be))) { 1152*cfad6425SSerge Semin dev_warn(dev, "No reg on %s, use default address %d", 1153*cfad6425SSerge Semin child->full_name, EEPROM_DEF_ADDR); 1154*cfad6425SSerge Semin pdev->inieecmd = 0; 1155*cfad6425SSerge Semin pdev->eeaddr = EEPROM_DEF_ADDR << 1; 1156*cfad6425SSerge Semin } else { 1157*cfad6425SSerge Semin pdev->inieecmd = EEPROM_USA; 1158*cfad6425SSerge Semin pdev->eeaddr = be32_to_cpup(addr_be) << 1; 1159*cfad6425SSerge Semin } 1160*cfad6425SSerge Semin 1161*cfad6425SSerge Semin /* Check EEPROM 'read-only' flag */ 1162*cfad6425SSerge Semin if (of_get_property(child, "read-only", NULL)) 1163*cfad6425SSerge Semin pdev->eero = true; 1164*cfad6425SSerge Semin else /* if (!of_get_property(node, "read-only", NULL)) */ 1165*cfad6425SSerge Semin pdev->eero = false; 1166*cfad6425SSerge Semin 1167*cfad6425SSerge Semin dev_dbg(dev, "EEPROM of %u bytes found by %hhu", 1168*cfad6425SSerge Semin pdev->eesize, pdev->eeaddr); 1169*cfad6425SSerge Semin } else { 1170*cfad6425SSerge Semin dev_warn(dev, "No dts node, EEPROM access disabled"); 1171*cfad6425SSerge Semin idt_set_defval(pdev); 1172*cfad6425SSerge Semin } 1173*cfad6425SSerge Semin } 1174*cfad6425SSerge Semin #else 1175*cfad6425SSerge Semin static void idt_get_ofdata(struct idt_89hpesx_dev *pdev) 1176*cfad6425SSerge Semin { 1177*cfad6425SSerge Semin struct device *dev = &pdev->client->dev; 1178*cfad6425SSerge Semin 1179*cfad6425SSerge Semin dev_warn(dev, "OF table is unsupported, EEPROM access disabled"); 1180*cfad6425SSerge Semin 1181*cfad6425SSerge Semin /* Nothing we can do, just set the default values */ 1182*cfad6425SSerge Semin idt_set_defval(pdev); 1183*cfad6425SSerge Semin } 1184*cfad6425SSerge Semin #endif /* CONFIG_OF */ 1185*cfad6425SSerge Semin 1186*cfad6425SSerge Semin /* 1187*cfad6425SSerge Semin * idt_create_pdev() - create and init data structure of the driver 1188*cfad6425SSerge Semin * @client: i2c client of IDT PCIe-switch device 1189*cfad6425SSerge Semin */ 1190*cfad6425SSerge Semin static struct idt_89hpesx_dev *idt_create_pdev(struct i2c_client *client) 1191*cfad6425SSerge Semin { 1192*cfad6425SSerge Semin struct idt_89hpesx_dev *pdev; 1193*cfad6425SSerge Semin 1194*cfad6425SSerge Semin /* Allocate memory for driver data */ 1195*cfad6425SSerge Semin pdev = devm_kmalloc(&client->dev, sizeof(struct idt_89hpesx_dev), 1196*cfad6425SSerge Semin GFP_KERNEL); 1197*cfad6425SSerge Semin if (pdev == NULL) 1198*cfad6425SSerge Semin return ERR_PTR(-ENOMEM); 1199*cfad6425SSerge Semin 1200*cfad6425SSerge Semin /* Initialize basic fields of the data */ 1201*cfad6425SSerge Semin pdev->client = client; 1202*cfad6425SSerge Semin i2c_set_clientdata(client, pdev); 1203*cfad6425SSerge Semin 1204*cfad6425SSerge Semin /* Read OF nodes information */ 1205*cfad6425SSerge Semin idt_get_ofdata(pdev); 1206*cfad6425SSerge Semin 1207*cfad6425SSerge Semin /* Initialize basic CSR CMD field - use full DWORD-sized r/w ops */ 1208*cfad6425SSerge Semin pdev->inicsrcmd = CSR_DWE; 1209*cfad6425SSerge Semin pdev->csr = CSR_DEF; 1210*cfad6425SSerge Semin 1211*cfad6425SSerge Semin /* Enable Packet Error Checking if it's supported by adapter */ 1212*cfad6425SSerge Semin if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_PEC)) { 1213*cfad6425SSerge Semin pdev->iniccode = CCODE_PEC; 1214*cfad6425SSerge Semin client->flags |= I2C_CLIENT_PEC; 1215*cfad6425SSerge Semin } else /* PEC is unsupported */ { 1216*cfad6425SSerge Semin pdev->iniccode = 0; 1217*cfad6425SSerge Semin } 1218*cfad6425SSerge Semin 1219*cfad6425SSerge Semin return pdev; 1220*cfad6425SSerge Semin } 1221*cfad6425SSerge Semin 1222*cfad6425SSerge Semin /* 1223*cfad6425SSerge Semin * idt_free_pdev() - free data structure of the driver 1224*cfad6425SSerge Semin * @pdev: Pointer to the driver data 1225*cfad6425SSerge Semin */ 1226*cfad6425SSerge Semin static void idt_free_pdev(struct idt_89hpesx_dev *pdev) 1227*cfad6425SSerge Semin { 1228*cfad6425SSerge Semin /* Clear driver data from device private field */ 1229*cfad6425SSerge Semin i2c_set_clientdata(pdev->client, NULL); 1230*cfad6425SSerge Semin 1231*cfad6425SSerge Semin /* Just free memory allocated for data */ 1232*cfad6425SSerge Semin devm_kfree(&pdev->client->dev, pdev); 1233*cfad6425SSerge Semin } 1234*cfad6425SSerge Semin 1235*cfad6425SSerge Semin /* 1236*cfad6425SSerge Semin * idt_set_smbus_ops() - set supported SMBus operations 1237*cfad6425SSerge Semin * @pdev: Pointer to the driver data 1238*cfad6425SSerge Semin * Return status of smbus check operations 1239*cfad6425SSerge Semin */ 1240*cfad6425SSerge Semin static int idt_set_smbus_ops(struct idt_89hpesx_dev *pdev) 1241*cfad6425SSerge Semin { 1242*cfad6425SSerge Semin struct i2c_adapter *adapter = pdev->client->adapter; 1243*cfad6425SSerge Semin struct device *dev = &pdev->client->dev; 1244*cfad6425SSerge Semin 1245*cfad6425SSerge Semin /* Check i2c adapter read functionality */ 1246*cfad6425SSerge Semin if (i2c_check_functionality(adapter, 1247*cfad6425SSerge Semin I2C_FUNC_SMBUS_READ_BLOCK_DATA)) { 1248*cfad6425SSerge Semin pdev->smb_read = idt_smb_read_block; 1249*cfad6425SSerge Semin dev_dbg(dev, "SMBus block-read op chosen"); 1250*cfad6425SSerge Semin } else if (i2c_check_functionality(adapter, 1251*cfad6425SSerge Semin I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { 1252*cfad6425SSerge Semin pdev->smb_read = idt_smb_read_i2c_block; 1253*cfad6425SSerge Semin dev_dbg(dev, "SMBus i2c-block-read op chosen"); 1254*cfad6425SSerge Semin } else if (i2c_check_functionality(adapter, 1255*cfad6425SSerge Semin I2C_FUNC_SMBUS_READ_WORD_DATA) && 1256*cfad6425SSerge Semin i2c_check_functionality(adapter, 1257*cfad6425SSerge Semin I2C_FUNC_SMBUS_READ_BYTE_DATA)) { 1258*cfad6425SSerge Semin pdev->smb_read = idt_smb_read_word; 1259*cfad6425SSerge Semin dev_warn(dev, "Use slow word/byte SMBus read ops"); 1260*cfad6425SSerge Semin } else if (i2c_check_functionality(adapter, 1261*cfad6425SSerge Semin I2C_FUNC_SMBUS_READ_BYTE_DATA)) { 1262*cfad6425SSerge Semin pdev->smb_read = idt_smb_read_byte; 1263*cfad6425SSerge Semin dev_warn(dev, "Use slow byte SMBus read op"); 1264*cfad6425SSerge Semin } else /* no supported smbus read operations */ { 1265*cfad6425SSerge Semin dev_err(dev, "No supported SMBus read op"); 1266*cfad6425SSerge Semin return -EPFNOSUPPORT; 1267*cfad6425SSerge Semin } 1268*cfad6425SSerge Semin 1269*cfad6425SSerge Semin /* Check i2c adapter write functionality */ 1270*cfad6425SSerge Semin if (i2c_check_functionality(adapter, 1271*cfad6425SSerge Semin I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)) { 1272*cfad6425SSerge Semin pdev->smb_write = idt_smb_write_block; 1273*cfad6425SSerge Semin dev_dbg(dev, "SMBus block-write op chosen"); 1274*cfad6425SSerge Semin } else if (i2c_check_functionality(adapter, 1275*cfad6425SSerge Semin I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { 1276*cfad6425SSerge Semin pdev->smb_write = idt_smb_write_i2c_block; 1277*cfad6425SSerge Semin dev_dbg(dev, "SMBus i2c-block-write op chosen"); 1278*cfad6425SSerge Semin } else if (i2c_check_functionality(adapter, 1279*cfad6425SSerge Semin I2C_FUNC_SMBUS_WRITE_WORD_DATA) && 1280*cfad6425SSerge Semin i2c_check_functionality(adapter, 1281*cfad6425SSerge Semin I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { 1282*cfad6425SSerge Semin pdev->smb_write = idt_smb_write_word; 1283*cfad6425SSerge Semin dev_warn(dev, "Use slow word/byte SMBus write op"); 1284*cfad6425SSerge Semin } else if (i2c_check_functionality(adapter, 1285*cfad6425SSerge Semin I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { 1286*cfad6425SSerge Semin pdev->smb_write = idt_smb_write_byte; 1287*cfad6425SSerge Semin dev_warn(dev, "Use slow byte SMBus write op"); 1288*cfad6425SSerge Semin } else /* no supported smbus write operations */ { 1289*cfad6425SSerge Semin dev_err(dev, "No supported SMBus write op"); 1290*cfad6425SSerge Semin return -EPFNOSUPPORT; 1291*cfad6425SSerge Semin } 1292*cfad6425SSerge Semin 1293*cfad6425SSerge Semin /* Initialize IDT SMBus slave interface mutex */ 1294*cfad6425SSerge Semin mutex_init(&pdev->smb_mtx); 1295*cfad6425SSerge Semin 1296*cfad6425SSerge Semin return 0; 1297*cfad6425SSerge Semin } 1298*cfad6425SSerge Semin 1299*cfad6425SSerge Semin /* 1300*cfad6425SSerge Semin * idt_check_dev() - check whether it's really IDT 89HPESx device 1301*cfad6425SSerge Semin * @pdev: Pointer to the driver data 1302*cfad6425SSerge Semin * Return status of i2c adapter check operation 1303*cfad6425SSerge Semin */ 1304*cfad6425SSerge Semin static int idt_check_dev(struct idt_89hpesx_dev *pdev) 1305*cfad6425SSerge Semin { 1306*cfad6425SSerge Semin struct device *dev = &pdev->client->dev; 1307*cfad6425SSerge Semin u32 viddid; 1308*cfad6425SSerge Semin int ret; 1309*cfad6425SSerge Semin 1310*cfad6425SSerge Semin /* Read VID and DID directly from IDT memory space */ 1311*cfad6425SSerge Semin ret = idt_csr_read(pdev, IDT_VIDDID_CSR, &viddid); 1312*cfad6425SSerge Semin if (ret != 0) { 1313*cfad6425SSerge Semin dev_err(dev, "Failed to read VID/DID"); 1314*cfad6425SSerge Semin return ret; 1315*cfad6425SSerge Semin } 1316*cfad6425SSerge Semin 1317*cfad6425SSerge Semin /* Check whether it's IDT device */ 1318*cfad6425SSerge Semin if ((viddid & IDT_VID_MASK) != PCI_VENDOR_ID_IDT) { 1319*cfad6425SSerge Semin dev_err(dev, "Got unsupported VID/DID: 0x%08x", viddid); 1320*cfad6425SSerge Semin return -ENODEV; 1321*cfad6425SSerge Semin } 1322*cfad6425SSerge Semin 1323*cfad6425SSerge Semin dev_info(dev, "Found IDT 89HPES device VID:0x%04x, DID:0x%04x", 1324*cfad6425SSerge Semin (viddid & IDT_VID_MASK), (viddid >> 16)); 1325*cfad6425SSerge Semin 1326*cfad6425SSerge Semin return 0; 1327*cfad6425SSerge Semin } 1328*cfad6425SSerge Semin 1329*cfad6425SSerge Semin /* 1330*cfad6425SSerge Semin * idt_create_sysfs_files() - create sysfs attribute files 1331*cfad6425SSerge Semin * @pdev: Pointer to the driver data 1332*cfad6425SSerge Semin * Return status of operation 1333*cfad6425SSerge Semin */ 1334*cfad6425SSerge Semin static int idt_create_sysfs_files(struct idt_89hpesx_dev *pdev) 1335*cfad6425SSerge Semin { 1336*cfad6425SSerge Semin struct device *dev = &pdev->client->dev; 1337*cfad6425SSerge Semin int ret; 1338*cfad6425SSerge Semin 1339*cfad6425SSerge Semin /* Don't do anything if EEPROM isn't accessible */ 1340*cfad6425SSerge Semin if (pdev->eesize == 0) { 1341*cfad6425SSerge Semin dev_dbg(dev, "Skip creating sysfs-files"); 1342*cfad6425SSerge Semin return 0; 1343*cfad6425SSerge Semin } 1344*cfad6425SSerge Semin 1345*cfad6425SSerge Semin /* Allocate memory for attribute file */ 1346*cfad6425SSerge Semin pdev->ee_file = devm_kmalloc(dev, sizeof(*pdev->ee_file), GFP_KERNEL); 1347*cfad6425SSerge Semin if (!pdev->ee_file) 1348*cfad6425SSerge Semin return -ENOMEM; 1349*cfad6425SSerge Semin 1350*cfad6425SSerge Semin /* Copy the declared EEPROM attr structure to change some of fields */ 1351*cfad6425SSerge Semin memcpy(pdev->ee_file, &bin_attr_eeprom, sizeof(*pdev->ee_file)); 1352*cfad6425SSerge Semin 1353*cfad6425SSerge Semin /* In case of read-only EEPROM get rid of write ability */ 1354*cfad6425SSerge Semin if (pdev->eero) { 1355*cfad6425SSerge Semin pdev->ee_file->attr.mode &= ~0200; 1356*cfad6425SSerge Semin pdev->ee_file->write = NULL; 1357*cfad6425SSerge Semin } 1358*cfad6425SSerge Semin /* Create EEPROM sysfs file */ 1359*cfad6425SSerge Semin pdev->ee_file->size = pdev->eesize; 1360*cfad6425SSerge Semin ret = sysfs_create_bin_file(&dev->kobj, pdev->ee_file); 1361*cfad6425SSerge Semin if (ret != 0) { 1362*cfad6425SSerge Semin kfree(pdev->ee_file); 1363*cfad6425SSerge Semin dev_err(dev, "Failed to create EEPROM sysfs-node"); 1364*cfad6425SSerge Semin return ret; 1365*cfad6425SSerge Semin } 1366*cfad6425SSerge Semin 1367*cfad6425SSerge Semin return 0; 1368*cfad6425SSerge Semin } 1369*cfad6425SSerge Semin 1370*cfad6425SSerge Semin /* 1371*cfad6425SSerge Semin * idt_remove_sysfs_files() - remove sysfs attribute files 1372*cfad6425SSerge Semin * @pdev: Pointer to the driver data 1373*cfad6425SSerge Semin */ 1374*cfad6425SSerge Semin static void idt_remove_sysfs_files(struct idt_89hpesx_dev *pdev) 1375*cfad6425SSerge Semin { 1376*cfad6425SSerge Semin struct device *dev = &pdev->client->dev; 1377*cfad6425SSerge Semin 1378*cfad6425SSerge Semin /* Don't do anything if EEPROM wasn't accessible */ 1379*cfad6425SSerge Semin if (pdev->eesize == 0) 1380*cfad6425SSerge Semin return; 1381*cfad6425SSerge Semin 1382*cfad6425SSerge Semin /* Remove EEPROM sysfs file */ 1383*cfad6425SSerge Semin sysfs_remove_bin_file(&dev->kobj, pdev->ee_file); 1384*cfad6425SSerge Semin 1385*cfad6425SSerge Semin /* Free memory allocated for bin_attribute structure */ 1386*cfad6425SSerge Semin kfree(pdev->ee_file); 1387*cfad6425SSerge Semin } 1388*cfad6425SSerge Semin 1389*cfad6425SSerge Semin /* 1390*cfad6425SSerge Semin * idt_create_dbgfs_files() - create debugfs files 1391*cfad6425SSerge Semin * @pdev: Pointer to the driver data 1392*cfad6425SSerge Semin */ 1393*cfad6425SSerge Semin #define CSRNAME_LEN ((size_t)32) 1394*cfad6425SSerge Semin static void idt_create_dbgfs_files(struct idt_89hpesx_dev *pdev) 1395*cfad6425SSerge Semin { 1396*cfad6425SSerge Semin struct i2c_client *cli = pdev->client; 1397*cfad6425SSerge Semin char fname[CSRNAME_LEN]; 1398*cfad6425SSerge Semin 1399*cfad6425SSerge Semin /* Create Debugfs directory for CSR file */ 1400*cfad6425SSerge Semin snprintf(fname, CSRNAME_LEN, "%d-%04hx", cli->adapter->nr, cli->addr); 1401*cfad6425SSerge Semin pdev->csr_dir = debugfs_create_dir(fname, csr_dbgdir); 1402*cfad6425SSerge Semin 1403*cfad6425SSerge Semin /* Create Debugfs file for CSR read/write operations */ 1404*cfad6425SSerge Semin pdev->csr_file = debugfs_create_file(cli->name, 0600, 1405*cfad6425SSerge Semin pdev->csr_dir, pdev, &csr_dbgfs_ops); 1406*cfad6425SSerge Semin } 1407*cfad6425SSerge Semin 1408*cfad6425SSerge Semin /* 1409*cfad6425SSerge Semin * idt_remove_dbgfs_files() - remove debugfs files 1410*cfad6425SSerge Semin * @pdev: Pointer to the driver data 1411*cfad6425SSerge Semin */ 1412*cfad6425SSerge Semin static void idt_remove_dbgfs_files(struct idt_89hpesx_dev *pdev) 1413*cfad6425SSerge Semin { 1414*cfad6425SSerge Semin /* Remove CSR directory and it sysfs-node */ 1415*cfad6425SSerge Semin debugfs_remove_recursive(pdev->csr_dir); 1416*cfad6425SSerge Semin } 1417*cfad6425SSerge Semin 1418*cfad6425SSerge Semin /* 1419*cfad6425SSerge Semin * idt_probe() - IDT 89HPESx driver probe() callback method 1420*cfad6425SSerge Semin */ 1421*cfad6425SSerge Semin static int idt_probe(struct i2c_client *client, const struct i2c_device_id *id) 1422*cfad6425SSerge Semin { 1423*cfad6425SSerge Semin struct idt_89hpesx_dev *pdev; 1424*cfad6425SSerge Semin int ret; 1425*cfad6425SSerge Semin 1426*cfad6425SSerge Semin /* Create driver data */ 1427*cfad6425SSerge Semin pdev = idt_create_pdev(client); 1428*cfad6425SSerge Semin if (IS_ERR(pdev)) 1429*cfad6425SSerge Semin return PTR_ERR(pdev); 1430*cfad6425SSerge Semin 1431*cfad6425SSerge Semin /* Set SMBus operations */ 1432*cfad6425SSerge Semin ret = idt_set_smbus_ops(pdev); 1433*cfad6425SSerge Semin if (ret != 0) 1434*cfad6425SSerge Semin goto err_free_pdev; 1435*cfad6425SSerge Semin 1436*cfad6425SSerge Semin /* Check whether it is truly IDT 89HPESx device */ 1437*cfad6425SSerge Semin ret = idt_check_dev(pdev); 1438*cfad6425SSerge Semin if (ret != 0) 1439*cfad6425SSerge Semin goto err_free_pdev; 1440*cfad6425SSerge Semin 1441*cfad6425SSerge Semin /* Create sysfs files */ 1442*cfad6425SSerge Semin ret = idt_create_sysfs_files(pdev); 1443*cfad6425SSerge Semin if (ret != 0) 1444*cfad6425SSerge Semin goto err_free_pdev; 1445*cfad6425SSerge Semin 1446*cfad6425SSerge Semin /* Create debugfs files */ 1447*cfad6425SSerge Semin idt_create_dbgfs_files(pdev); 1448*cfad6425SSerge Semin 1449*cfad6425SSerge Semin return 0; 1450*cfad6425SSerge Semin 1451*cfad6425SSerge Semin err_free_pdev: 1452*cfad6425SSerge Semin idt_free_pdev(pdev); 1453*cfad6425SSerge Semin 1454*cfad6425SSerge Semin return ret; 1455*cfad6425SSerge Semin } 1456*cfad6425SSerge Semin 1457*cfad6425SSerge Semin /* 1458*cfad6425SSerge Semin * idt_remove() - IDT 89HPESx driver remove() callback method 1459*cfad6425SSerge Semin */ 1460*cfad6425SSerge Semin static int idt_remove(struct i2c_client *client) 1461*cfad6425SSerge Semin { 1462*cfad6425SSerge Semin struct idt_89hpesx_dev *pdev = i2c_get_clientdata(client); 1463*cfad6425SSerge Semin 1464*cfad6425SSerge Semin /* Remove debugfs files first */ 1465*cfad6425SSerge Semin idt_remove_dbgfs_files(pdev); 1466*cfad6425SSerge Semin 1467*cfad6425SSerge Semin /* Remove sysfs files */ 1468*cfad6425SSerge Semin idt_remove_sysfs_files(pdev); 1469*cfad6425SSerge Semin 1470*cfad6425SSerge Semin /* Discard driver data structure */ 1471*cfad6425SSerge Semin idt_free_pdev(pdev); 1472*cfad6425SSerge Semin 1473*cfad6425SSerge Semin return 0; 1474*cfad6425SSerge Semin } 1475*cfad6425SSerge Semin 1476*cfad6425SSerge Semin /* 1477*cfad6425SSerge Semin * ee_ids - array of supported EEPROMs 1478*cfad6425SSerge Semin */ 1479*cfad6425SSerge Semin static const struct i2c_device_id ee_ids[] = { 1480*cfad6425SSerge Semin { "24c32", 4096}, 1481*cfad6425SSerge Semin { "24c64", 8192}, 1482*cfad6425SSerge Semin { "24c128", 16384}, 1483*cfad6425SSerge Semin { "24c256", 32768}, 1484*cfad6425SSerge Semin { "24c512", 65536}, 1485*cfad6425SSerge Semin {} 1486*cfad6425SSerge Semin }; 1487*cfad6425SSerge Semin MODULE_DEVICE_TABLE(i2c, ee_ids); 1488*cfad6425SSerge Semin 1489*cfad6425SSerge Semin /* 1490*cfad6425SSerge Semin * idt_ids - supported IDT 89HPESx devices 1491*cfad6425SSerge Semin */ 1492*cfad6425SSerge Semin static const struct i2c_device_id idt_ids[] = { 1493*cfad6425SSerge Semin { "89hpes8nt2", 0 }, 1494*cfad6425SSerge Semin { "89hpes12nt3", 0 }, 1495*cfad6425SSerge Semin 1496*cfad6425SSerge Semin { "89hpes24nt6ag2", 0 }, 1497*cfad6425SSerge Semin { "89hpes32nt8ag2", 0 }, 1498*cfad6425SSerge Semin { "89hpes32nt8bg2", 0 }, 1499*cfad6425SSerge Semin { "89hpes12nt12g2", 0 }, 1500*cfad6425SSerge Semin { "89hpes16nt16g2", 0 }, 1501*cfad6425SSerge Semin { "89hpes24nt24g2", 0 }, 1502*cfad6425SSerge Semin { "89hpes32nt24ag2", 0 }, 1503*cfad6425SSerge Semin { "89hpes32nt24bg2", 0 }, 1504*cfad6425SSerge Semin 1505*cfad6425SSerge Semin { "89hpes12n3", 0 }, 1506*cfad6425SSerge Semin { "89hpes12n3a", 0 }, 1507*cfad6425SSerge Semin { "89hpes24n3", 0 }, 1508*cfad6425SSerge Semin { "89hpes24n3a", 0 }, 1509*cfad6425SSerge Semin 1510*cfad6425SSerge Semin { "89hpes32h8", 0 }, 1511*cfad6425SSerge Semin { "89hpes32h8g2", 0 }, 1512*cfad6425SSerge Semin { "89hpes48h12", 0 }, 1513*cfad6425SSerge Semin { "89hpes48h12g2", 0 }, 1514*cfad6425SSerge Semin { "89hpes48h12ag2", 0 }, 1515*cfad6425SSerge Semin { "89hpes16h16", 0 }, 1516*cfad6425SSerge Semin { "89hpes22h16", 0 }, 1517*cfad6425SSerge Semin { "89hpes22h16g2", 0 }, 1518*cfad6425SSerge Semin { "89hpes34h16", 0 }, 1519*cfad6425SSerge Semin { "89hpes34h16g2", 0 }, 1520*cfad6425SSerge Semin { "89hpes64h16", 0 }, 1521*cfad6425SSerge Semin { "89hpes64h16g2", 0 }, 1522*cfad6425SSerge Semin { "89hpes64h16ag2", 0 }, 1523*cfad6425SSerge Semin 1524*cfad6425SSerge Semin /* { "89hpes3t3", 0 }, // No SMBus-slave iface */ 1525*cfad6425SSerge Semin { "89hpes12t3g2", 0 }, 1526*cfad6425SSerge Semin { "89hpes24t3g2", 0 }, 1527*cfad6425SSerge Semin /* { "89hpes4t4", 0 }, // No SMBus-slave iface */ 1528*cfad6425SSerge Semin { "89hpes16t4", 0 }, 1529*cfad6425SSerge Semin { "89hpes4t4g2", 0 }, 1530*cfad6425SSerge Semin { "89hpes10t4g2", 0 }, 1531*cfad6425SSerge Semin { "89hpes16t4g2", 0 }, 1532*cfad6425SSerge Semin { "89hpes16t4ag2", 0 }, 1533*cfad6425SSerge Semin { "89hpes5t5", 0 }, 1534*cfad6425SSerge Semin { "89hpes6t5", 0 }, 1535*cfad6425SSerge Semin { "89hpes8t5", 0 }, 1536*cfad6425SSerge Semin { "89hpes8t5a", 0 }, 1537*cfad6425SSerge Semin { "89hpes24t6", 0 }, 1538*cfad6425SSerge Semin { "89hpes6t6g2", 0 }, 1539*cfad6425SSerge Semin { "89hpes24t6g2", 0 }, 1540*cfad6425SSerge Semin { "89hpes16t7", 0 }, 1541*cfad6425SSerge Semin { "89hpes32t8", 0 }, 1542*cfad6425SSerge Semin { "89hpes32t8g2", 0 }, 1543*cfad6425SSerge Semin { "89hpes48t12", 0 }, 1544*cfad6425SSerge Semin { "89hpes48t12g2", 0 }, 1545*cfad6425SSerge Semin { /* END OF LIST */ } 1546*cfad6425SSerge Semin }; 1547*cfad6425SSerge Semin MODULE_DEVICE_TABLE(i2c, idt_ids); 1548*cfad6425SSerge Semin 1549*cfad6425SSerge Semin /* 1550*cfad6425SSerge Semin * idt_driver - IDT 89HPESx driver structure 1551*cfad6425SSerge Semin */ 1552*cfad6425SSerge Semin static struct i2c_driver idt_driver = { 1553*cfad6425SSerge Semin .driver = { 1554*cfad6425SSerge Semin .name = IDT_NAME, 1555*cfad6425SSerge Semin .owner = THIS_MODULE, 1556*cfad6425SSerge Semin }, 1557*cfad6425SSerge Semin .probe = idt_probe, 1558*cfad6425SSerge Semin .remove = idt_remove, 1559*cfad6425SSerge Semin .id_table = idt_ids, 1560*cfad6425SSerge Semin }; 1561*cfad6425SSerge Semin 1562*cfad6425SSerge Semin /* 1563*cfad6425SSerge Semin * idt_init() - IDT 89HPESx driver init() callback method 1564*cfad6425SSerge Semin */ 1565*cfad6425SSerge Semin static int __init idt_init(void) 1566*cfad6425SSerge Semin { 1567*cfad6425SSerge Semin /* Create Debugfs directory first */ 1568*cfad6425SSerge Semin if (debugfs_initialized()) 1569*cfad6425SSerge Semin csr_dbgdir = debugfs_create_dir("idt_csr", NULL); 1570*cfad6425SSerge Semin 1571*cfad6425SSerge Semin /* Add new i2c-device driver */ 1572*cfad6425SSerge Semin return i2c_add_driver(&idt_driver); 1573*cfad6425SSerge Semin } 1574*cfad6425SSerge Semin module_init(idt_init); 1575*cfad6425SSerge Semin 1576*cfad6425SSerge Semin /* 1577*cfad6425SSerge Semin * idt_exit() - IDT 89HPESx driver exit() callback method 1578*cfad6425SSerge Semin */ 1579*cfad6425SSerge Semin static void __exit idt_exit(void) 1580*cfad6425SSerge Semin { 1581*cfad6425SSerge Semin /* Discard debugfs directory and all files if any */ 1582*cfad6425SSerge Semin debugfs_remove_recursive(csr_dbgdir); 1583*cfad6425SSerge Semin 1584*cfad6425SSerge Semin /* Unregister i2c-device driver */ 1585*cfad6425SSerge Semin i2c_del_driver(&idt_driver); 1586*cfad6425SSerge Semin } 1587*cfad6425SSerge Semin module_exit(idt_exit); 1588