0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "bus.h"
0025
0026 #ifdef CONFIG_NOUVEAU_I2C_INTERNAL
0027 #define T_TIMEOUT 2200000
0028 #define T_RISEFALL 1000
0029 #define T_HOLD 5000
0030
0031 static inline void
0032 nvkm_i2c_drive_scl(struct nvkm_i2c_bus *bus, int state)
0033 {
0034 bus->func->drive_scl(bus, state);
0035 }
0036
0037 static inline void
0038 nvkm_i2c_drive_sda(struct nvkm_i2c_bus *bus, int state)
0039 {
0040 bus->func->drive_sda(bus, state);
0041 }
0042
0043 static inline int
0044 nvkm_i2c_sense_scl(struct nvkm_i2c_bus *bus)
0045 {
0046 return bus->func->sense_scl(bus);
0047 }
0048
0049 static inline int
0050 nvkm_i2c_sense_sda(struct nvkm_i2c_bus *bus)
0051 {
0052 return bus->func->sense_sda(bus);
0053 }
0054
0055 static void
0056 nvkm_i2c_delay(struct nvkm_i2c_bus *bus, u32 nsec)
0057 {
0058 udelay((nsec + 500) / 1000);
0059 }
0060
0061 static bool
0062 nvkm_i2c_raise_scl(struct nvkm_i2c_bus *bus)
0063 {
0064 u32 timeout = T_TIMEOUT / T_RISEFALL;
0065
0066 nvkm_i2c_drive_scl(bus, 1);
0067 do {
0068 nvkm_i2c_delay(bus, T_RISEFALL);
0069 } while (!nvkm_i2c_sense_scl(bus) && --timeout);
0070
0071 return timeout != 0;
0072 }
0073
0074 static int
0075 i2c_start(struct nvkm_i2c_bus *bus)
0076 {
0077 int ret = 0;
0078
0079 if (!nvkm_i2c_sense_scl(bus) ||
0080 !nvkm_i2c_sense_sda(bus)) {
0081 nvkm_i2c_drive_scl(bus, 0);
0082 nvkm_i2c_drive_sda(bus, 1);
0083 if (!nvkm_i2c_raise_scl(bus))
0084 ret = -EBUSY;
0085 }
0086
0087 nvkm_i2c_drive_sda(bus, 0);
0088 nvkm_i2c_delay(bus, T_HOLD);
0089 nvkm_i2c_drive_scl(bus, 0);
0090 nvkm_i2c_delay(bus, T_HOLD);
0091 return ret;
0092 }
0093
0094 static void
0095 i2c_stop(struct nvkm_i2c_bus *bus)
0096 {
0097 nvkm_i2c_drive_scl(bus, 0);
0098 nvkm_i2c_drive_sda(bus, 0);
0099 nvkm_i2c_delay(bus, T_RISEFALL);
0100
0101 nvkm_i2c_drive_scl(bus, 1);
0102 nvkm_i2c_delay(bus, T_HOLD);
0103 nvkm_i2c_drive_sda(bus, 1);
0104 nvkm_i2c_delay(bus, T_HOLD);
0105 }
0106
0107 static int
0108 i2c_bitw(struct nvkm_i2c_bus *bus, int sda)
0109 {
0110 nvkm_i2c_drive_sda(bus, sda);
0111 nvkm_i2c_delay(bus, T_RISEFALL);
0112
0113 if (!nvkm_i2c_raise_scl(bus))
0114 return -ETIMEDOUT;
0115 nvkm_i2c_delay(bus, T_HOLD);
0116
0117 nvkm_i2c_drive_scl(bus, 0);
0118 nvkm_i2c_delay(bus, T_HOLD);
0119 return 0;
0120 }
0121
0122 static int
0123 i2c_bitr(struct nvkm_i2c_bus *bus)
0124 {
0125 int sda;
0126
0127 nvkm_i2c_drive_sda(bus, 1);
0128 nvkm_i2c_delay(bus, T_RISEFALL);
0129
0130 if (!nvkm_i2c_raise_scl(bus))
0131 return -ETIMEDOUT;
0132 nvkm_i2c_delay(bus, T_HOLD);
0133
0134 sda = nvkm_i2c_sense_sda(bus);
0135
0136 nvkm_i2c_drive_scl(bus, 0);
0137 nvkm_i2c_delay(bus, T_HOLD);
0138 return sda;
0139 }
0140
0141 static int
0142 nvkm_i2c_get_byte(struct nvkm_i2c_bus *bus, u8 *byte, bool last)
0143 {
0144 int i, bit;
0145
0146 *byte = 0;
0147 for (i = 7; i >= 0; i--) {
0148 bit = i2c_bitr(bus);
0149 if (bit < 0)
0150 return bit;
0151 *byte |= bit << i;
0152 }
0153
0154 return i2c_bitw(bus, last ? 1 : 0);
0155 }
0156
0157 static int
0158 nvkm_i2c_put_byte(struct nvkm_i2c_bus *bus, u8 byte)
0159 {
0160 int i, ret;
0161 for (i = 7; i >= 0; i--) {
0162 ret = i2c_bitw(bus, !!(byte & (1 << i)));
0163 if (ret < 0)
0164 return ret;
0165 }
0166
0167 ret = i2c_bitr(bus);
0168 if (ret == 1)
0169 ret = -EIO;
0170 return ret;
0171 }
0172
0173 static int
0174 i2c_addr(struct nvkm_i2c_bus *bus, struct i2c_msg *msg)
0175 {
0176 u32 addr = msg->addr << 1;
0177 if (msg->flags & I2C_M_RD)
0178 addr |= 1;
0179 return nvkm_i2c_put_byte(bus, addr);
0180 }
0181
0182 int
0183 nvkm_i2c_bit_xfer(struct nvkm_i2c_bus *bus, struct i2c_msg *msgs, int num)
0184 {
0185 struct i2c_msg *msg = msgs;
0186 int ret = 0, mcnt = num;
0187
0188 while (!ret && mcnt--) {
0189 u8 remaining = msg->len;
0190 u8 *ptr = msg->buf;
0191
0192 ret = i2c_start(bus);
0193 if (ret == 0)
0194 ret = i2c_addr(bus, msg);
0195
0196 if (msg->flags & I2C_M_RD) {
0197 while (!ret && remaining--)
0198 ret = nvkm_i2c_get_byte(bus, ptr++, !remaining);
0199 } else {
0200 while (!ret && remaining--)
0201 ret = nvkm_i2c_put_byte(bus, *ptr++);
0202 }
0203
0204 msg++;
0205 }
0206
0207 i2c_stop(bus);
0208 return (ret < 0) ? ret : num;
0209 }
0210 #else
0211 int
0212 nvkm_i2c_bit_xfer(struct nvkm_i2c_bus *bus, struct i2c_msg *msgs, int num)
0213 {
0214 return -ENODEV;
0215 }
0216 #endif