root/drivers/i2c/busses/i2c-sibyte.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. smbus_xfer
  2. bit_func
  3. i2c_sibyte_add_bus
  4. i2c_sibyte_init
  5. i2c_sibyte_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (C) 2004 Steven J. Hill
   4  * Copyright (C) 2001,2002,2003 Broadcom Corporation
   5  * Copyright (C) 1995-2000 Simon G. Vogl
   6  */
   7 
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/init.h>
  11 #include <linux/i2c.h>
  12 #include <linux/io.h>
  13 #include <asm/sibyte/sb1250_regs.h>
  14 #include <asm/sibyte/sb1250_smbus.h>
  15 
  16 
  17 struct i2c_algo_sibyte_data {
  18         void *data;             /* private data */
  19         int   bus;              /* which bus */
  20         void *reg_base;         /* CSR base */
  21 };
  22 
  23 /* ----- global defines ----------------------------------------------- */
  24 #define SMB_CSR(a,r) ((long)(a->reg_base + r))
  25 
  26 
  27 static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
  28                       unsigned short flags, char read_write,
  29                       u8 command, int size, union i2c_smbus_data * data)
  30 {
  31         struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
  32         int data_bytes = 0;
  33         int error;
  34 
  35         while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
  36                 ;
  37 
  38         switch (size) {
  39         case I2C_SMBUS_QUICK:
  40                 csr_out32((V_SMB_ADDR(addr) |
  41                            (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) |
  42                            V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START));
  43                 break;
  44         case I2C_SMBUS_BYTE:
  45                 if (read_write == I2C_SMBUS_READ) {
  46                         csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE),
  47                                   SMB_CSR(adap, R_SMB_START));
  48                         data_bytes = 1;
  49                 } else {
  50                         csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
  51                         csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE),
  52                                   SMB_CSR(adap, R_SMB_START));
  53                 }
  54                 break;
  55         case I2C_SMBUS_BYTE_DATA:
  56                 csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
  57                 if (read_write == I2C_SMBUS_READ) {
  58                         csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE),
  59                                   SMB_CSR(adap, R_SMB_START));
  60                         data_bytes = 1;
  61                 } else {
  62                         csr_out32(V_SMB_LB(data->byte),
  63                                   SMB_CSR(adap, R_SMB_DATA));
  64                         csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
  65                                   SMB_CSR(adap, R_SMB_START));
  66                 }
  67                 break;
  68         case I2C_SMBUS_WORD_DATA:
  69                 csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
  70                 if (read_write == I2C_SMBUS_READ) {
  71                         csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE),
  72                                   SMB_CSR(adap, R_SMB_START));
  73                         data_bytes = 2;
  74                 } else {
  75                         csr_out32(V_SMB_LB(data->word & 0xff),
  76                                   SMB_CSR(adap, R_SMB_DATA));
  77                         csr_out32(V_SMB_MB(data->word >> 8),
  78                                   SMB_CSR(adap, R_SMB_DATA));
  79                         csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
  80                                   SMB_CSR(adap, R_SMB_START));
  81                 }
  82                 break;
  83         default:
  84                 return -EOPNOTSUPP;
  85         }
  86 
  87         while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
  88                 ;
  89 
  90         error = csr_in32(SMB_CSR(adap, R_SMB_STATUS));
  91         if (error & M_SMB_ERROR) {
  92                 /* Clear error bit by writing a 1 */
  93                 csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
  94                 return (error & M_SMB_ERROR_TYPE) ? -EIO : -ENXIO;
  95         }
  96 
  97         if (data_bytes == 1)
  98                 data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff;
  99         if (data_bytes == 2)
 100                 data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff;
 101 
 102         return 0;
 103 }
 104 
 105 static u32 bit_func(struct i2c_adapter *adap)
 106 {
 107         return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
 108                 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA);
 109 }
 110 
 111 
 112 /* -----exported algorithm data: -------------------------------------  */
 113 
 114 static const struct i2c_algorithm i2c_sibyte_algo = {
 115         .smbus_xfer     = smbus_xfer,
 116         .functionality  = bit_func,
 117 };
 118 
 119 /*
 120  * registering functions to load algorithms at runtime
 121  */
 122 static int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
 123 {
 124         struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
 125 
 126         /* Register new adapter to i2c module... */
 127         i2c_adap->algo = &i2c_sibyte_algo;
 128 
 129         /* Set the requested frequency. */
 130         csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
 131         csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
 132 
 133         return i2c_add_numbered_adapter(i2c_adap);
 134 }
 135 
 136 
 137 static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
 138         { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) },
 139         { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) }
 140 };
 141 
 142 static struct i2c_adapter sibyte_board_adapter[2] = {
 143         {
 144                 .owner          = THIS_MODULE,
 145                 .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
 146                 .algo           = NULL,
 147                 .algo_data      = &sibyte_board_data[0],
 148                 .nr             = 0,
 149                 .name           = "SiByte SMBus 0",
 150         },
 151         {
 152                 .owner          = THIS_MODULE,
 153                 .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
 154                 .algo           = NULL,
 155                 .algo_data      = &sibyte_board_data[1],
 156                 .nr             = 1,
 157                 .name           = "SiByte SMBus 1",
 158         },
 159 };
 160 
 161 static int __init i2c_sibyte_init(void)
 162 {
 163         pr_info("i2c-sibyte: i2c SMBus adapter module for SiByte board\n");
 164         if (i2c_sibyte_add_bus(&sibyte_board_adapter[0], K_SMB_FREQ_100KHZ) < 0)
 165                 return -ENODEV;
 166         if (i2c_sibyte_add_bus(&sibyte_board_adapter[1],
 167                                K_SMB_FREQ_400KHZ) < 0) {
 168                 i2c_del_adapter(&sibyte_board_adapter[0]);
 169                 return -ENODEV;
 170         }
 171         return 0;
 172 }
 173 
 174 static void __exit i2c_sibyte_exit(void)
 175 {
 176         i2c_del_adapter(&sibyte_board_adapter[0]);
 177         i2c_del_adapter(&sibyte_board_adapter[1]);
 178 }
 179 
 180 module_init(i2c_sibyte_init);
 181 module_exit(i2c_sibyte_exit);
 182 
 183 MODULE_AUTHOR("Kip Walker (Broadcom Corp.), Steven J. Hill <sjhill@realitydiluted.com>");
 184 MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards");
 185 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */