Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Coral-P(A)/Lime I2C adapter driver
0004  *
0005  * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
0006  */
0007 
0008 #include <linux/fb.h>
0009 #include <linux/i2c.h>
0010 #include <linux/io.h>
0011 #include <linux/delay.h>
0012 #include <linux/export.h>
0013 
0014 #include "mb862xxfb.h"
0015 #include "mb862xx_reg.h"
0016 
0017 static int mb862xx_i2c_wait_event(struct i2c_adapter *adap)
0018 {
0019     struct mb862xxfb_par *par = adap->algo_data;
0020     u32 reg;
0021 
0022     do {
0023         udelay(10);
0024         reg = inreg(i2c, GC_I2C_BCR);
0025         if (reg & (I2C_INT | I2C_BER))
0026             break;
0027     } while (1);
0028 
0029     return (reg & I2C_BER) ? 0 : 1;
0030 }
0031 
0032 static int mb862xx_i2c_do_address(struct i2c_adapter *adap, int addr)
0033 {
0034     struct mb862xxfb_par *par = adap->algo_data;
0035 
0036     outreg(i2c, GC_I2C_DAR, addr);
0037     outreg(i2c, GC_I2C_CCR, I2C_CLOCK_AND_ENABLE);
0038     outreg(i2c, GC_I2C_BCR, par->i2c_rs ? I2C_REPEATED_START : I2C_START);
0039     if (!mb862xx_i2c_wait_event(adap))
0040         return -EIO;
0041     par->i2c_rs = !(inreg(i2c, GC_I2C_BSR) & I2C_LRB);
0042     return par->i2c_rs;
0043 }
0044 
0045 static int mb862xx_i2c_write_byte(struct i2c_adapter *adap, u8 byte)
0046 {
0047     struct mb862xxfb_par *par = adap->algo_data;
0048 
0049     outreg(i2c, GC_I2C_DAR, byte);
0050     outreg(i2c, GC_I2C_BCR, I2C_START);
0051     if (!mb862xx_i2c_wait_event(adap))
0052         return -EIO;
0053     return !(inreg(i2c, GC_I2C_BSR) & I2C_LRB);
0054 }
0055 
0056 static int mb862xx_i2c_read_byte(struct i2c_adapter *adap, u8 *byte, int last)
0057 {
0058     struct mb862xxfb_par *par = adap->algo_data;
0059 
0060     outreg(i2c, GC_I2C_BCR, I2C_START | (last ? 0 : I2C_ACK));
0061     if (!mb862xx_i2c_wait_event(adap))
0062         return 0;
0063     *byte = inreg(i2c, GC_I2C_DAR);
0064     return 1;
0065 }
0066 
0067 static void mb862xx_i2c_stop(struct i2c_adapter *adap)
0068 {
0069     struct mb862xxfb_par *par = adap->algo_data;
0070 
0071     outreg(i2c, GC_I2C_BCR, I2C_STOP);
0072     outreg(i2c, GC_I2C_CCR, I2C_DISABLE);
0073     par->i2c_rs = 0;
0074 }
0075 
0076 static int mb862xx_i2c_read(struct i2c_adapter *adap, struct i2c_msg *m)
0077 {
0078     int i, ret = 0;
0079     int last = m->len - 1;
0080 
0081     for (i = 0; i < m->len; i++) {
0082         if (!mb862xx_i2c_read_byte(adap, &m->buf[i], i == last)) {
0083             ret = -EIO;
0084             break;
0085         }
0086     }
0087     return ret;
0088 }
0089 
0090 static int mb862xx_i2c_write(struct i2c_adapter *adap, struct i2c_msg *m)
0091 {
0092     int i, ret = 0;
0093 
0094     for (i = 0; i < m->len; i++) {
0095         if (!mb862xx_i2c_write_byte(adap, m->buf[i])) {
0096             ret = -EIO;
0097             break;
0098         }
0099     }
0100     return ret;
0101 }
0102 
0103 static int mb862xx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
0104             int num)
0105 {
0106     struct mb862xxfb_par *par = adap->algo_data;
0107     struct i2c_msg *m;
0108     int addr;
0109     int i = 0, err = 0;
0110 
0111     dev_dbg(par->dev, "%s: %d msgs\n", __func__, num);
0112 
0113     for (i = 0; i < num; i++) {
0114         m = &msgs[i];
0115         if (!m->len) {
0116             dev_dbg(par->dev, "%s: null msgs\n", __func__);
0117             continue;
0118         }
0119         addr = m->addr;
0120         if (m->flags & I2C_M_RD)
0121             addr |= 1;
0122 
0123         err = mb862xx_i2c_do_address(adap, addr);
0124         if (err < 0)
0125             break;
0126         if (m->flags & I2C_M_RD)
0127             err = mb862xx_i2c_read(adap, m);
0128         else
0129             err = mb862xx_i2c_write(adap, m);
0130     }
0131 
0132     if (i)
0133         mb862xx_i2c_stop(adap);
0134 
0135     return (err < 0) ? err : i;
0136 }
0137 
0138 static u32 mb862xx_func(struct i2c_adapter *adap)
0139 {
0140     return I2C_FUNC_SMBUS_BYTE_DATA;
0141 }
0142 
0143 static const struct i2c_algorithm mb862xx_algo = {
0144     .master_xfer    = mb862xx_xfer,
0145     .functionality  = mb862xx_func,
0146 };
0147 
0148 static struct i2c_adapter mb862xx_i2c_adapter = {
0149     .name       = "MB862xx I2C adapter",
0150     .algo       = &mb862xx_algo,
0151     .owner      = THIS_MODULE,
0152 };
0153 
0154 int mb862xx_i2c_init(struct mb862xxfb_par *par)
0155 {
0156     mb862xx_i2c_adapter.algo_data = par;
0157     par->adap = &mb862xx_i2c_adapter;
0158 
0159     return i2c_add_adapter(par->adap);
0160 }
0161 
0162 void mb862xx_i2c_exit(struct mb862xxfb_par *par)
0163 {
0164     if (par->adap) {
0165         i2c_del_adapter(par->adap);
0166         par->adap = NULL;
0167     }
0168 }