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 181 182 183 184 185 186 187 188 | /* 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_ntfy_req {
#define NVKM_I2C_PLUG 0x01
#define NVKM_I2C_UNPLUG 0x02
#define NVKM_I2C_IRQ 0x04
#define NVKM_I2C_DONE 0x08
#define NVKM_I2C_ANY 0x0f
u8 mask;
u8 port;
};
struct nvkm_i2c_ntfy_rep {
u8 mask;
};
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) + 0x100)
#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) + 0x100)
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;
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 *, int, struct nvkm_i2c **);
int nv4e_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **);
int nv50_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **);
int g94_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **);
int gf117_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **);
int gf119_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **);
int gk104_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **);
int gm200_i2c_new(struct nvkm_device *, int, 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
|