1 /* $NetBSD: i2c.h,v 1.3 2021/12/18 23:45:33 riastradh Exp $ */ 2 3 /* SPDX-License-Identifier: MIT */ 4 #ifndef __NVKM_I2C_H__ 5 #define __NVKM_I2C_H__ 6 #include <core/subdev.h> 7 #include <core/event.h> 8 9 #include <subdev/bios.h> 10 #include <subdev/bios/i2c.h> 11 12 struct nvkm_i2c_ntfy_req { 13 #define NVKM_I2C_PLUG 0x01 14 #define NVKM_I2C_UNPLUG 0x02 15 #define NVKM_I2C_IRQ 0x04 16 #define NVKM_I2C_DONE 0x08 17 #define NVKM_I2C_ANY 0x0f 18 u8 mask; 19 u8 port; 20 }; 21 22 struct nvkm_i2c_ntfy_rep { 23 u8 mask; 24 }; 25 26 struct nvkm_i2c_bus_probe { 27 struct i2c_board_info dev; 28 u8 udelay; /* set to 0 to use the standard delay */ 29 }; 30 31 struct nvkm_i2c_bus { 32 const struct nvkm_i2c_bus_func *func; 33 struct nvkm_i2c_pad *pad; 34 #define NVKM_I2C_BUS_CCB(n) /* 'n' is ccb index */ (n) 35 #define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100) 36 #define NVKM_I2C_BUS_PRI /* ccb primary comm. port */ -1 37 #define NVKM_I2C_BUS_SEC /* ccb secondary comm. port */ -2 38 int id; 39 40 struct mutex mutex; 41 struct list_head head; 42 struct i2c_adapter i2c; 43 u8 enabled; 44 }; 45 46 int nvkm_i2c_bus_acquire(struct nvkm_i2c_bus *); 47 void nvkm_i2c_bus_release(struct nvkm_i2c_bus *); 48 int nvkm_i2c_bus_probe(struct nvkm_i2c_bus *, const char *, 49 struct nvkm_i2c_bus_probe *, 50 bool (*)(struct nvkm_i2c_bus *, 51 struct i2c_board_info *, void *), void *); 52 53 struct nvkm_i2c_aux { 54 const struct nvkm_i2c_aux_func *func; 55 struct nvkm_i2c_pad *pad; 56 #define NVKM_I2C_AUX_CCB(n) /* 'n' is ccb index */ (n) 57 #define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100) 58 int id; 59 60 struct mutex mutex; 61 struct list_head head; 62 struct i2c_adapter i2c; 63 u8 enabled; 64 65 u32 intr; 66 }; 67 68 void nvkm_i2c_aux_monitor(struct nvkm_i2c_aux *, bool monitor); 69 int nvkm_i2c_aux_acquire(struct nvkm_i2c_aux *); 70 void nvkm_i2c_aux_release(struct nvkm_i2c_aux *); 71 int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type, 72 u32 addr, u8 *data, u8 *size); 73 int nvkm_i2c_aux_lnk_ctl(struct nvkm_i2c_aux *, int link_nr, int link_bw, 74 bool enhanced_framing); 75 76 struct nvkm_i2c { 77 const struct nvkm_i2c_func *func; 78 struct nvkm_subdev subdev; 79 80 struct list_head pad; 81 struct list_head bus; 82 struct list_head aux; 83 84 struct nvkm_event event; 85 }; 86 87 struct nvkm_i2c_bus *nvkm_i2c_bus_find(struct nvkm_i2c *, int); 88 struct nvkm_i2c_aux *nvkm_i2c_aux_find(struct nvkm_i2c *, int); 89 90 int nv04_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); 91 int nv4e_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); 92 int nv50_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); 93 int g94_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); 94 int gf117_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); 95 int gf119_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); 96 int gk104_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); 97 int gm200_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **); 98 99 static inline int 100 nvkm_rdi2cr(struct i2c_adapter *adap, u8 addr, u8 reg) 101 { 102 u8 val; 103 struct i2c_msg msgs[] = { 104 { .addr = addr, .flags = 0, .len = 1, .buf = ® }, 105 { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val }, 106 }; 107 108 int ret = i2c_transfer(adap, msgs, ARRAY_SIZE(msgs)); 109 if (ret != 2) 110 return -EIO; 111 112 return val; 113 } 114 115 static inline int 116 nv_rd16i2cr(struct i2c_adapter *adap, u8 addr, u8 reg) 117 { 118 u8 val[2]; 119 struct i2c_msg msgs[] = { 120 { .addr = addr, .flags = 0, .len = 1, .buf = ® }, 121 { .addr = addr, .flags = I2C_M_RD, .len = 2, .buf = val }, 122 }; 123 124 int ret = i2c_transfer(adap, msgs, ARRAY_SIZE(msgs)); 125 if (ret != 2) 126 return -EIO; 127 128 return val[0] << 8 | val[1]; 129 } 130 131 static inline int 132 nvkm_wri2cr(struct i2c_adapter *adap, u8 addr, u8 reg, u8 val) 133 { 134 u8 buf[2] = { reg, val }; 135 struct i2c_msg msgs[] = { 136 { .addr = addr, .flags = 0, .len = 2, .buf = buf }, 137 }; 138 139 int ret = i2c_transfer(adap, msgs, ARRAY_SIZE(msgs)); 140 if (ret != 1) 141 return -EIO; 142 143 return 0; 144 } 145 146 static inline int 147 nv_wr16i2cr(struct i2c_adapter *adap, u8 addr, u8 reg, u16 val) 148 { 149 u8 buf[3] = { reg, val >> 8, val & 0xff}; 150 struct i2c_msg msgs[] = { 151 { .addr = addr, .flags = 0, .len = 3, .buf = buf }, 152 }; 153 154 int ret = i2c_transfer(adap, msgs, ARRAY_SIZE(msgs)); 155 if (ret != 1) 156 return -EIO; 157 158 return 0; 159 } 160 161 static inline bool 162 nvkm_probe_i2c(struct i2c_adapter *adap, u8 addr) 163 { 164 return nvkm_rdi2cr(adap, addr, 0) >= 0; 165 } 166 167 static inline int 168 nvkm_rdaux(struct nvkm_i2c_aux *aux, u32 addr, u8 *data, u8 size) 169 { 170 const u8 xfer = size; 171 int ret = nvkm_i2c_aux_acquire(aux); 172 if (ret == 0) { 173 ret = nvkm_i2c_aux_xfer(aux, true, 9, addr, data, &size); 174 WARN_ON(!ret && size != xfer); 175 nvkm_i2c_aux_release(aux); 176 } 177 return ret; 178 } 179 180 static inline int 181 nvkm_wraux(struct nvkm_i2c_aux *aux, u32 addr, u8 *data, u8 size) 182 { 183 int ret = nvkm_i2c_aux_acquire(aux); 184 if (ret == 0) { 185 ret = nvkm_i2c_aux_xfer(aux, true, 8, addr, data, &size); 186 nvkm_i2c_aux_release(aux); 187 } 188 return ret; 189 } 190 #endif 191