Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2006-2007 PA Semi, Inc
0004  *
0005  * SMBus host driver for PA Semi PWRficient
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/pci.h>
0010 #include <linux/kernel.h>
0011 #include <linux/stddef.h>
0012 #include <linux/sched.h>
0013 #include <linux/i2c.h>
0014 #include <linux/delay.h>
0015 #include <linux/slab.h>
0016 #include <linux/io.h>
0017 
0018 #include "i2c-pasemi-core.h"
0019 
0020 /* Register offsets */
0021 #define REG_MTXFIFO 0x00
0022 #define REG_MRXFIFO 0x04
0023 #define REG_SMSTA   0x14
0024 #define REG_CTL     0x1c
0025 #define REG_REV     0x28
0026 
0027 /* Register defs */
0028 #define MTXFIFO_READ    0x00000400
0029 #define MTXFIFO_STOP    0x00000200
0030 #define MTXFIFO_START   0x00000100
0031 #define MTXFIFO_DATA_M  0x000000ff
0032 
0033 #define MRXFIFO_EMPTY   0x00000100
0034 #define MRXFIFO_DATA_M  0x000000ff
0035 
0036 #define SMSTA_XEN   0x08000000
0037 #define SMSTA_MTN   0x00200000
0038 
0039 #define CTL_MRR     0x00000400
0040 #define CTL_MTR     0x00000200
0041 #define CTL_EN      0x00000800
0042 #define CTL_CLK_M   0x000000ff
0043 
0044 static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
0045 {
0046     dev_dbg(smbus->dev, "smbus write reg %x val %08x\n", reg, val);
0047     iowrite32(val, smbus->ioaddr + reg);
0048 }
0049 
0050 static inline int reg_read(struct pasemi_smbus *smbus, int reg)
0051 {
0052     int ret;
0053     ret = ioread32(smbus->ioaddr + reg);
0054     dev_dbg(smbus->dev, "smbus read reg %x val %08x\n", reg, ret);
0055     return ret;
0056 }
0057 
0058 #define TXFIFO_WR(smbus, reg)   reg_write((smbus), REG_MTXFIFO, (reg))
0059 #define RXFIFO_RD(smbus)    reg_read((smbus), REG_MRXFIFO)
0060 
0061 static void pasemi_reset(struct pasemi_smbus *smbus)
0062 {
0063     u32 val = (CTL_MTR | CTL_MRR | (smbus->clk_div & CTL_CLK_M));
0064 
0065     if (smbus->hw_rev >= 6)
0066         val |= CTL_EN;
0067 
0068     reg_write(smbus, REG_CTL, val);
0069 }
0070 
0071 static void pasemi_smb_clear(struct pasemi_smbus *smbus)
0072 {
0073     unsigned int status;
0074 
0075     status = reg_read(smbus, REG_SMSTA);
0076     reg_write(smbus, REG_SMSTA, status);
0077 }
0078 
0079 static int pasemi_smb_waitready(struct pasemi_smbus *smbus)
0080 {
0081     int timeout = 10;
0082     unsigned int status;
0083 
0084     status = reg_read(smbus, REG_SMSTA);
0085 
0086     while (!(status & SMSTA_XEN) && timeout--) {
0087         msleep(1);
0088         status = reg_read(smbus, REG_SMSTA);
0089     }
0090 
0091     /* Got NACK? */
0092     if (status & SMSTA_MTN)
0093         return -ENXIO;
0094 
0095     if (timeout < 0) {
0096         dev_warn(smbus->dev, "Timeout, status 0x%08x\n", status);
0097         reg_write(smbus, REG_SMSTA, status);
0098         return -ETIME;
0099     }
0100 
0101     /* Clear XEN */
0102     reg_write(smbus, REG_SMSTA, SMSTA_XEN);
0103 
0104     return 0;
0105 }
0106 
0107 static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter,
0108                    struct i2c_msg *msg, int stop)
0109 {
0110     struct pasemi_smbus *smbus = adapter->algo_data;
0111     int read, i, err;
0112     u32 rd;
0113 
0114     read = msg->flags & I2C_M_RD ? 1 : 0;
0115 
0116     TXFIFO_WR(smbus, MTXFIFO_START | i2c_8bit_addr_from_msg(msg));
0117 
0118     if (read) {
0119         TXFIFO_WR(smbus, msg->len | MTXFIFO_READ |
0120                  (stop ? MTXFIFO_STOP : 0));
0121 
0122         err = pasemi_smb_waitready(smbus);
0123         if (err)
0124             goto reset_out;
0125 
0126         for (i = 0; i < msg->len; i++) {
0127             rd = RXFIFO_RD(smbus);
0128             if (rd & MRXFIFO_EMPTY) {
0129                 err = -ENODATA;
0130                 goto reset_out;
0131             }
0132             msg->buf[i] = rd & MRXFIFO_DATA_M;
0133         }
0134     } else {
0135         for (i = 0; i < msg->len - 1; i++)
0136             TXFIFO_WR(smbus, msg->buf[i]);
0137 
0138         TXFIFO_WR(smbus, msg->buf[msg->len-1] |
0139               (stop ? MTXFIFO_STOP : 0));
0140 
0141         if (stop) {
0142             err = pasemi_smb_waitready(smbus);
0143             if (err)
0144                 goto reset_out;
0145         }
0146     }
0147 
0148     return 0;
0149 
0150  reset_out:
0151     pasemi_reset(smbus);
0152     return err;
0153 }
0154 
0155 static int pasemi_i2c_xfer(struct i2c_adapter *adapter,
0156                struct i2c_msg *msgs, int num)
0157 {
0158     struct pasemi_smbus *smbus = adapter->algo_data;
0159     int ret, i;
0160 
0161     pasemi_smb_clear(smbus);
0162 
0163     ret = 0;
0164 
0165     for (i = 0; i < num && !ret; i++)
0166         ret = pasemi_i2c_xfer_msg(adapter, &msgs[i], (i == (num - 1)));
0167 
0168     return ret ? ret : num;
0169 }
0170 
0171 static int pasemi_smb_xfer(struct i2c_adapter *adapter,
0172         u16 addr, unsigned short flags, char read_write, u8 command,
0173         int size, union i2c_smbus_data *data)
0174 {
0175     struct pasemi_smbus *smbus = adapter->algo_data;
0176     unsigned int rd;
0177     int read_flag, err;
0178     int len = 0, i;
0179 
0180     /* All our ops take 8-bit shifted addresses */
0181     addr <<= 1;
0182     read_flag = read_write == I2C_SMBUS_READ;
0183 
0184     pasemi_smb_clear(smbus);
0185 
0186     switch (size) {
0187     case I2C_SMBUS_QUICK:
0188         TXFIFO_WR(smbus, addr | read_flag | MTXFIFO_START |
0189               MTXFIFO_STOP);
0190         break;
0191     case I2C_SMBUS_BYTE:
0192         TXFIFO_WR(smbus, addr | read_flag | MTXFIFO_START);
0193         if (read_write)
0194             TXFIFO_WR(smbus, 1 | MTXFIFO_STOP | MTXFIFO_READ);
0195         else
0196             TXFIFO_WR(smbus, MTXFIFO_STOP | command);
0197         break;
0198     case I2C_SMBUS_BYTE_DATA:
0199         TXFIFO_WR(smbus, addr | MTXFIFO_START);
0200         TXFIFO_WR(smbus, command);
0201         if (read_write) {
0202             TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
0203             TXFIFO_WR(smbus, 1 | MTXFIFO_READ | MTXFIFO_STOP);
0204         } else {
0205             TXFIFO_WR(smbus, MTXFIFO_STOP | data->byte);
0206         }
0207         break;
0208     case I2C_SMBUS_WORD_DATA:
0209         TXFIFO_WR(smbus, addr | MTXFIFO_START);
0210         TXFIFO_WR(smbus, command);
0211         if (read_write) {
0212             TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
0213             TXFIFO_WR(smbus, 2 | MTXFIFO_READ | MTXFIFO_STOP);
0214         } else {
0215             TXFIFO_WR(smbus, data->word & MTXFIFO_DATA_M);
0216             TXFIFO_WR(smbus, MTXFIFO_STOP | (data->word >> 8));
0217         }
0218         break;
0219     case I2C_SMBUS_BLOCK_DATA:
0220         TXFIFO_WR(smbus, addr | MTXFIFO_START);
0221         TXFIFO_WR(smbus, command);
0222         if (read_write) {
0223             TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
0224             TXFIFO_WR(smbus, 1 | MTXFIFO_READ);
0225             rd = RXFIFO_RD(smbus);
0226             len = min_t(u8, (rd & MRXFIFO_DATA_M),
0227                     I2C_SMBUS_BLOCK_MAX);
0228             TXFIFO_WR(smbus, len | MTXFIFO_READ |
0229                      MTXFIFO_STOP);
0230         } else {
0231             len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX);
0232             TXFIFO_WR(smbus, len);
0233             for (i = 1; i < len; i++)
0234                 TXFIFO_WR(smbus, data->block[i]);
0235             TXFIFO_WR(smbus, data->block[len] | MTXFIFO_STOP);
0236         }
0237         break;
0238     case I2C_SMBUS_PROC_CALL:
0239         read_write = I2C_SMBUS_READ;
0240         TXFIFO_WR(smbus, addr | MTXFIFO_START);
0241         TXFIFO_WR(smbus, command);
0242         TXFIFO_WR(smbus, data->word & MTXFIFO_DATA_M);
0243         TXFIFO_WR(smbus, (data->word >> 8) & MTXFIFO_DATA_M);
0244         TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
0245         TXFIFO_WR(smbus, 2 | MTXFIFO_STOP | MTXFIFO_READ);
0246         break;
0247     case I2C_SMBUS_BLOCK_PROC_CALL:
0248         len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX - 1);
0249         read_write = I2C_SMBUS_READ;
0250         TXFIFO_WR(smbus, addr | MTXFIFO_START);
0251         TXFIFO_WR(smbus, command);
0252         TXFIFO_WR(smbus, len);
0253         for (i = 1; i <= len; i++)
0254             TXFIFO_WR(smbus, data->block[i]);
0255         TXFIFO_WR(smbus, addr | I2C_SMBUS_READ);
0256         TXFIFO_WR(smbus, MTXFIFO_READ | 1);
0257         rd = RXFIFO_RD(smbus);
0258         len = min_t(u8, (rd & MRXFIFO_DATA_M),
0259                 I2C_SMBUS_BLOCK_MAX - len);
0260         TXFIFO_WR(smbus, len | MTXFIFO_READ | MTXFIFO_STOP);
0261         break;
0262 
0263     default:
0264         dev_warn(&adapter->dev, "Unsupported transaction %d\n", size);
0265         return -EINVAL;
0266     }
0267 
0268     err = pasemi_smb_waitready(smbus);
0269     if (err)
0270         goto reset_out;
0271 
0272     if (read_write == I2C_SMBUS_WRITE)
0273         return 0;
0274 
0275     switch (size) {
0276     case I2C_SMBUS_BYTE:
0277     case I2C_SMBUS_BYTE_DATA:
0278         rd = RXFIFO_RD(smbus);
0279         if (rd & MRXFIFO_EMPTY) {
0280             err = -ENODATA;
0281             goto reset_out;
0282         }
0283         data->byte = rd & MRXFIFO_DATA_M;
0284         break;
0285     case I2C_SMBUS_WORD_DATA:
0286     case I2C_SMBUS_PROC_CALL:
0287         rd = RXFIFO_RD(smbus);
0288         if (rd & MRXFIFO_EMPTY) {
0289             err = -ENODATA;
0290             goto reset_out;
0291         }
0292         data->word = rd & MRXFIFO_DATA_M;
0293         rd = RXFIFO_RD(smbus);
0294         if (rd & MRXFIFO_EMPTY) {
0295             err = -ENODATA;
0296             goto reset_out;
0297         }
0298         data->word |= (rd & MRXFIFO_DATA_M) << 8;
0299         break;
0300     case I2C_SMBUS_BLOCK_DATA:
0301     case I2C_SMBUS_BLOCK_PROC_CALL:
0302         data->block[0] = len;
0303         for (i = 1; i <= len; i ++) {
0304             rd = RXFIFO_RD(smbus);
0305             if (rd & MRXFIFO_EMPTY) {
0306                 err = -ENODATA;
0307                 goto reset_out;
0308             }
0309             data->block[i] = rd & MRXFIFO_DATA_M;
0310         }
0311         break;
0312     }
0313 
0314     return 0;
0315 
0316  reset_out:
0317     pasemi_reset(smbus);
0318     return err;
0319 }
0320 
0321 static u32 pasemi_smb_func(struct i2c_adapter *adapter)
0322 {
0323     return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
0324            I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
0325            I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL |
0326            I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_I2C;
0327 }
0328 
0329 static const struct i2c_algorithm smbus_algorithm = {
0330     .master_xfer    = pasemi_i2c_xfer,
0331     .smbus_xfer = pasemi_smb_xfer,
0332     .functionality  = pasemi_smb_func,
0333 };
0334 
0335 int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
0336 {
0337     int error;
0338 
0339     smbus->adapter.owner = THIS_MODULE;
0340     snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
0341          "PA Semi SMBus adapter (%s)", dev_name(smbus->dev));
0342     smbus->adapter.algo = &smbus_algorithm;
0343     smbus->adapter.algo_data = smbus;
0344 
0345     /* set up the sysfs linkage to our parent device */
0346     smbus->adapter.dev.parent = smbus->dev;
0347 
0348     if (smbus->hw_rev != PASEMI_HW_REV_PCI)
0349         smbus->hw_rev = reg_read(smbus, REG_REV);
0350 
0351     pasemi_reset(smbus);
0352 
0353     error = devm_i2c_add_adapter(smbus->dev, &smbus->adapter);
0354     if (error)
0355         return error;
0356 
0357     return 0;
0358 }