1/* 2 * Copyright 2013 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Ben Skeggs 23 */ 24 25#define T_TIMEOUT 2200000 26#define T_RISEFALL 1000 27#define T_HOLD 5000 28 29#ifdef INCLUDE_PROC 30process(PROC_I2C_, #i2c_init, #i2c_recv) 31#endif 32 33/****************************************************************************** 34 * I2C_ data segment 35 *****************************************************************************/ 36#ifdef INCLUDE_DATA 37i2c_scl_map: 38.b32 NV_PPWR_OUTPUT_I2C_0_SCL 39.b32 NV_PPWR_OUTPUT_I2C_1_SCL 40.b32 NV_PPWR_OUTPUT_I2C_2_SCL 41.b32 NV_PPWR_OUTPUT_I2C_3_SCL 42.b32 NV_PPWR_OUTPUT_I2C_4_SCL 43.b32 NV_PPWR_OUTPUT_I2C_5_SCL 44.b32 NV_PPWR_OUTPUT_I2C_6_SCL 45.b32 NV_PPWR_OUTPUT_I2C_7_SCL 46.b32 NV_PPWR_OUTPUT_I2C_8_SCL 47.b32 NV_PPWR_OUTPUT_I2C_9_SCL 48i2c_sda_map: 49.b32 NV_PPWR_OUTPUT_I2C_0_SDA 50.b32 NV_PPWR_OUTPUT_I2C_1_SDA 51.b32 NV_PPWR_OUTPUT_I2C_2_SDA 52.b32 NV_PPWR_OUTPUT_I2C_3_SDA 53.b32 NV_PPWR_OUTPUT_I2C_4_SDA 54.b32 NV_PPWR_OUTPUT_I2C_5_SDA 55.b32 NV_PPWR_OUTPUT_I2C_6_SDA 56.b32 NV_PPWR_OUTPUT_I2C_7_SDA 57.b32 NV_PPWR_OUTPUT_I2C_8_SDA 58.b32 NV_PPWR_OUTPUT_I2C_9_SDA 59#if NVKM_PPWR_CHIPSET < GF119 60i2c_ctrl: 61.b32 0x00e138 62.b32 0x00e150 63.b32 0x00e168 64.b32 0x00e180 65.b32 0x00e254 66.b32 0x00e274 67.b32 0x00e764 68.b32 0x00e780 69.b32 0x00e79c 70.b32 0x00e7b8 71#endif 72#endif 73 74/****************************************************************************** 75 * I2C_ code segment 76 *****************************************************************************/ 77#ifdef INCLUDE_CODE 78 79// $r3 - value 80// $r2 - sda line 81// $r1 - scl line 82// $r0 - zero 83i2c_drive_scl: 84 cmp b32 $r3 0 85 bra e #i2c_drive_scl_lo 86 nv_iowr(NV_PPWR_OUTPUT_SET, $r1) 87 ret 88 i2c_drive_scl_lo: 89 nv_iowr(NV_PPWR_OUTPUT_CLR, $r1) 90 ret 91 92i2c_drive_sda: 93 cmp b32 $r3 0 94 bra e #i2c_drive_sda_lo 95 nv_iowr(NV_PPWR_OUTPUT_SET, $r2) 96 ret 97 i2c_drive_sda_lo: 98 nv_iowr(NV_PPWR_OUTPUT_CLR, $r2) 99 ret 100 101i2c_sense_scl: 102 bclr $flags $p1 103 nv_iord($r3, NV_PPWR_INPUT) 104 and $r3 $r1 105 bra z #i2c_sense_scl_done 106 bset $flags $p1 107 i2c_sense_scl_done: 108 ret 109 110i2c_sense_sda: 111 bclr $flags $p1 112 nv_iord($r3, NV_PPWR_INPUT) 113 and $r3 $r2 114 bra z #i2c_sense_sda_done 115 bset $flags $p1 116 i2c_sense_sda_done: 117 ret 118 119#define i2c_drive_scl(v) /* 120*/ mov $r3 (v) /* 121*/ call(i2c_drive_scl) 122#define i2c_drive_sda(v) /* 123*/ mov $r3 (v) /* 124*/ call(i2c_drive_sda) 125#define i2c_sense_scl() /* 126*/ call(i2c_sense_scl) 127#define i2c_sense_sda() /* 128*/ call(i2c_sense_sda) 129#define i2c_delay(v) /* 130*/ mov $r14 (v) /* 131*/ call(nsec) 132 133#define i2c_trace_init() /* 134*/ imm32($r6, 0x10000000) /* 135*/ sub b32 $r7 $r6 1 /* 136*/ 137#define i2c_trace_down() /* 138*/ shr b32 $r6 4 /* 139*/ push $r5 /* 140*/ shl b32 $r5 $r6 4 /* 141*/ sub b32 $r5 $r6 /* 142*/ not b32 $r5 /* 143*/ and $r7 $r5 /* 144*/ pop $r5 /* 145*/ 146#define i2c_trace_exit() /* 147*/ shl b32 $r6 4 /* 148*/ 149#define i2c_trace_next() /* 150*/ add b32 $r7 $r6 /* 151*/ 152#define i2c_trace_call(func) /* 153*/ i2c_trace_next() /* 154*/ i2c_trace_down() /* 155*/ call(func) /* 156*/ i2c_trace_exit() /* 157*/ 158 159i2c_raise_scl: 160 push $r4 161 mov $r4 (T_TIMEOUT / T_RISEFALL) 162 i2c_drive_scl(1) 163 i2c_raise_scl_wait: 164 i2c_delay(T_RISEFALL) 165 i2c_sense_scl() 166 bra $p1 #i2c_raise_scl_done 167 sub b32 $r4 1 168 bra nz #i2c_raise_scl_wait 169 i2c_raise_scl_done: 170 pop $r4 171 ret 172 173i2c_start: 174 i2c_sense_scl() 175 bra not $p1 #i2c_start_rep 176 i2c_sense_sda() 177 bra not $p1 #i2c_start_rep 178 bra #i2c_start_send 179 i2c_start_rep: 180 i2c_drive_scl(0) 181 i2c_drive_sda(1) 182 i2c_trace_call(i2c_raise_scl) 183 bra not $p1 #i2c_start_out 184 i2c_start_send: 185 i2c_drive_sda(0) 186 i2c_delay(T_HOLD) 187 i2c_drive_scl(0) 188 i2c_delay(T_HOLD) 189 i2c_start_out: 190 ret 191 192i2c_stop: 193 i2c_drive_scl(0) 194 i2c_drive_sda(0) 195 i2c_delay(T_RISEFALL) 196 i2c_drive_scl(1) 197 i2c_delay(T_HOLD) 198 i2c_drive_sda(1) 199 i2c_delay(T_HOLD) 200 ret 201 202// $r3 - value 203// $r2 - sda line 204// $r1 - scl line 205// $r0 - zero 206i2c_bitw: 207 call(i2c_drive_sda) 208 i2c_delay(T_RISEFALL) 209 i2c_trace_call(i2c_raise_scl) 210 bra not $p1 #i2c_bitw_out 211 i2c_delay(T_HOLD) 212 i2c_drive_scl(0) 213 i2c_delay(T_HOLD) 214 i2c_bitw_out: 215 ret 216 217// $r3 - value (out) 218// $r2 - sda line 219// $r1 - scl line 220// $r0 - zero 221i2c_bitr: 222 i2c_drive_sda(1) 223 i2c_delay(T_RISEFALL) 224 i2c_trace_call(i2c_raise_scl) 225 bra not $p1 #i2c_bitr_done 226 i2c_sense_sda() 227 i2c_drive_scl(0) 228 i2c_delay(T_HOLD) 229 xbit $r3 $flags $p1 230 bset $flags $p1 231 i2c_bitr_done: 232 ret 233 234i2c_get_byte: 235 mov $r5 0 236 mov $r4 8 237 i2c_get_byte_next: 238 shl b32 $r5 1 239 i2c_trace_call(i2c_bitr) 240 bra not $p1 #i2c_get_byte_done 241 or $r5 $r3 242 sub b32 $r4 1 243 bra nz #i2c_get_byte_next 244 mov $r3 1 245 i2c_trace_call(i2c_bitw) 246 i2c_get_byte_done: 247 ret 248 249i2c_put_byte: 250 mov $r4 8 251 i2c_put_byte_next: 252 sub b32 $r4 1 253 xbit $r3 $r5 $r4 254 i2c_trace_call(i2c_bitw) 255 bra not $p1 #i2c_put_byte_done 256 cmp b32 $r4 0 257 bra ne #i2c_put_byte_next 258 i2c_trace_call(i2c_bitr) 259 bra not $p1 #i2c_put_byte_done 260 i2c_trace_next() 261 cmp b32 $r3 1 262 bra ne #i2c_put_byte_done 263 bclr $flags $p1 // nack 264 i2c_put_byte_done: 265 ret 266 267i2c_addr: 268 i2c_trace_call(i2c_start) 269 bra not $p1 #i2c_addr_done 270 extr $r3 $r12 I2C__MSG_DATA0_ADDR 271 shl b32 $r3 1 272 or $r5 $r3 273 i2c_trace_call(i2c_put_byte) 274 i2c_addr_done: 275 ret 276 277i2c_acquire_addr: 278 extr $r14 $r12 I2C__MSG_DATA0_PORT 279#if NVKM_PPWR_CHIPSET < GF119 280 shl b32 $r14 2 281 add b32 $r14 #i2c_ctrl 282 ld b32 $r14 D[$r14] 283#else 284 shl b32 $r14 5 285 add b32 $r14 0x00d014 286#endif 287 ret 288 289i2c_acquire: 290 call(i2c_acquire_addr) 291 call(rd32) 292 bset $r13 3 293 call(wr32) 294 ret 295 296i2c_release: 297 call(i2c_acquire_addr) 298 call(rd32) 299 bclr $r13 3 300 call(wr32) 301 ret 302 303// description 304// 305// $r15 - current (i2c) 306// $r14 - sender process name 307// $r13 - message 308// $r12 - data0 309// $r11 - data1 310// $r0 - zero 311i2c_recv: 312 bclr $flags $p1 313 extr $r1 $r12 I2C__MSG_DATA0_PORT 314 shl b32 $r1 2 315 cmp b32 $r1 (#i2c_sda_map - #i2c_scl_map) 316 bra ge #i2c_recv_done 317 add b32 $r3 $r1 #i2c_sda_map 318 ld b32 $r2 D[$r3] 319 add b32 $r3 $r1 #i2c_scl_map 320 ld b32 $r1 D[$r3] 321 322 bset $flags $p2 323 push $r13 324 push $r14 325 326 push $r13 327 i2c_trace_init() 328 i2c_trace_call(i2c_acquire) 329 pop $r13 330 331 cmp b32 $r13 I2C__MSG_RD08 332 bra ne #i2c_recv_not_rd08 333 mov $r5 0 334 i2c_trace_call(i2c_addr) 335 bra not $p1 #i2c_recv_done 336 extr $r5 $r12 I2C__MSG_DATA0_RD08_REG 337 i2c_trace_call(i2c_put_byte) 338 bra not $p1 #i2c_recv_done 339 mov $r5 1 340 i2c_trace_call(i2c_addr) 341 bra not $p1 #i2c_recv_done 342 i2c_trace_call(i2c_get_byte) 343 bra not $p1 #i2c_recv_done 344 ins $r11 $r5 I2C__MSG_DATA1_RD08_VAL 345 i2c_trace_call(i2c_stop) 346 mov b32 $r11 $r5 347 clear b32 $r7 348 bra #i2c_recv_done 349 350 i2c_recv_not_rd08: 351 cmp b32 $r13 I2C__MSG_WR08 352 bra ne #i2c_recv_not_wr08 353 mov $r5 0 354 call(i2c_addr) 355 bra not $p1 #i2c_recv_done 356 extr $r5 $r12 I2C__MSG_DATA0_WR08_REG 357 call(i2c_put_byte) 358 bra not $p1 #i2c_recv_done 359 mov $r5 0 360 call(i2c_addr) 361 bra not $p1 #i2c_recv_done 362 extr $r5 $r11 I2C__MSG_DATA1_WR08_VAL 363 call(i2c_put_byte) 364 bra not $p1 #i2c_recv_done 365 call(i2c_stop) 366 clear b32 $r7 367 extr $r5 $r12 I2C__MSG_DATA0_WR08_SYNC 368 bra nz #i2c_recv_done 369 bclr $flags $p2 370 bra #i2c_recv_done 371 372 i2c_recv_not_wr08: 373 374 i2c_recv_done: 375 extr $r14 $r12 I2C__MSG_DATA0_PORT 376 call(i2c_release) 377 378 pop $r14 379 pop $r13 380 bra not $p2 #i2c_recv_exit 381 mov b32 $r12 $r7 382 call(send) 383 384 i2c_recv_exit: 385 ret 386 387// description 388// 389// $r15 - current (i2c) 390// $r0 - zero 391i2c_init: 392 ret 393#endif 394