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