1#ifndef __NOUVEAU_I2C_H__ 2#define __NOUVEAU_I2C_H__ 3 4#include <core/subdev.h> 5#include <core/device.h> 6 7#include <subdev/bios.h> 8#include <subdev/bios/i2c.h> 9 10#define NV_I2C_PORT(n) (0x00 + (n)) 11#define NV_I2C_DEFAULT(n) (0x80 + (n)) 12 13#define NV_I2C_TYPE_DCBI2C(n) (0x0000 | (n)) 14#define NV_I2C_TYPE_EXTDDC(e) (0x0005 | (e) << 8) 15#define NV_I2C_TYPE_EXTAUX(e) (0x0006 | (e) << 8) 16 17struct nouveau_i2c_port { 18 struct nouveau_object base; 19 struct i2c_adapter adapter; 20 21 struct list_head head; 22 u8 index; 23 24 const struct nouveau_i2c_func *func; 25}; 26 27struct nouveau_i2c_func { 28 void (*acquire)(struct nouveau_i2c_port *); 29 void (*release)(struct nouveau_i2c_port *); 30 31 void (*drive_scl)(struct nouveau_i2c_port *, int); 32 void (*drive_sda)(struct nouveau_i2c_port *, int); 33 int (*sense_scl)(struct nouveau_i2c_port *); 34 int (*sense_sda)(struct nouveau_i2c_port *); 35 36 int (*aux)(struct nouveau_i2c_port *, u8, u32, u8 *, u8); 37 int (*pattern)(struct nouveau_i2c_port *, int pattern); 38 int (*lnk_ctl)(struct nouveau_i2c_port *, int nr, int bw, bool enh); 39 int (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe); 40}; 41 42#define nouveau_i2c_port_create(p,e,o,i,a,d) \ 43 nouveau_i2c_port_create_((p), (e), (o), (i), (a), \ 44 sizeof(**d), (void **)d) 45#define nouveau_i2c_port_destroy(p) ({ \ 46 struct nouveau_i2c_port *port = (p); \ 47 _nouveau_i2c_port_dtor(nv_object(i2c)); \ 48}) 49#define nouveau_i2c_port_init(p) \ 50 nouveau_object_init(&(p)->base) 51#define nouveau_i2c_port_fini(p,s) \ 52 nouveau_object_fini(&(p)->base, (s)) 53 54int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *, 55 struct nouveau_oclass *, u8, 56 const struct i2c_algorithm *, int, void **); 57void _nouveau_i2c_port_dtor(struct nouveau_object *); 58#define _nouveau_i2c_port_init nouveau_object_init 59#define _nouveau_i2c_port_fini nouveau_object_fini 60 61struct nouveau_i2c { 62 struct nouveau_subdev base; 63 64 struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index); 65 struct nouveau_i2c_port *(*find_type)(struct nouveau_i2c *, u16 type); 66 int (*identify)(struct nouveau_i2c *, int index, 67 const char *what, struct i2c_board_info *, 68 bool (*match)(struct nouveau_i2c_port *, 69 struct i2c_board_info *)); 70 struct list_head ports; 71}; 72 73static inline struct nouveau_i2c * 74nouveau_i2c(void *obj) 75{ 76 return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_I2C]; 77} 78 79#define nouveau_i2c_create(p,e,o,s,d) \ 80 nouveau_i2c_create_((p), (e), (o), (s), sizeof(**d), (void **)d) 81#define nouveau_i2c_destroy(p) ({ \ 82 struct nouveau_i2c *i2c = (p); \ 83 _nouveau_i2c_dtor(nv_object(i2c)); \ 84}) 85#define nouveau_i2c_init(p) ({ \ 86 struct nouveau_i2c *i2c = (p); \ 87 _nouveau_i2c_init(nv_object(i2c)); \ 88}) 89#define nouveau_i2c_fini(p,s) ({ \ 90 struct nouveau_i2c *i2c = (p); \ 91 _nouveau_i2c_fini(nv_object(i2c), (s)); \ 92}) 93 94int nouveau_i2c_create_(struct nouveau_object *, struct nouveau_object *, 95 struct nouveau_oclass *, struct nouveau_oclass *, 96 int, void **); 97void _nouveau_i2c_dtor(struct nouveau_object *); 98int _nouveau_i2c_init(struct nouveau_object *); 99int _nouveau_i2c_fini(struct nouveau_object *, bool); 100 101extern struct nouveau_oclass nv04_i2c_oclass; 102extern struct nouveau_oclass nv4e_i2c_oclass; 103extern struct nouveau_oclass nv50_i2c_oclass; 104extern struct nouveau_oclass nv94_i2c_oclass; 105extern struct nouveau_oclass nvd0_i2c_oclass; 106extern struct nouveau_oclass nouveau_anx9805_sclass[]; 107 108extern const struct i2c_algorithm nouveau_i2c_bit_algo; 109extern const struct i2c_algorithm nouveau_i2c_aux_algo; 110 111static inline int 112nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg) 113{ 114 u8 val; 115 struct i2c_msg msgs[] = { 116 { .addr = addr, .flags = 0, .len = 1, .buf = ® }, 117 { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val }, 118 }; 119 120 int ret = i2c_transfer(&port->adapter, msgs, 2); 121 if (ret != 2) 122 return -EIO; 123 124 return val; 125} 126 127static inline int 128nv_wri2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg, u8 val) 129{ 130 u8 buf[2] = { reg, val }; 131 struct i2c_msg msgs[] = { 132 { .addr = addr, .flags = 0, .len = 2, .buf = buf }, 133 }; 134 135 int ret = i2c_transfer(&port->adapter, msgs, 1); 136 if (ret != 1) 137 return -EIO; 138 139 return 0; 140} 141 142static inline bool 143nv_probe_i2c(struct nouveau_i2c_port *port, u8 addr) 144{ 145 return nv_rdi2cr(port, addr, 0) >= 0; 146} 147 148int nv_rdaux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); 149int nv_wraux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); 150 151#endif 152