394 lines · plain
1/*2 * Copyright 2013 Red Hat Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: Ben Skeggs23 */24 25#define T_TIMEOUT 220000026#define T_RISEFALL 100027#define T_HOLD 500028 29#ifdef INCLUDE_PROC30process(PROC_I2C_, #i2c_init, #i2c_recv)31#endif32 33/******************************************************************************34 * I2C_ data segment35 *****************************************************************************/36#ifdef INCLUDE_DATA37i2c_scl_map:38.b32 NV_PPWR_OUTPUT_I2C_0_SCL39.b32 NV_PPWR_OUTPUT_I2C_1_SCL40.b32 NV_PPWR_OUTPUT_I2C_2_SCL41.b32 NV_PPWR_OUTPUT_I2C_3_SCL42.b32 NV_PPWR_OUTPUT_I2C_4_SCL43.b32 NV_PPWR_OUTPUT_I2C_5_SCL44.b32 NV_PPWR_OUTPUT_I2C_6_SCL45.b32 NV_PPWR_OUTPUT_I2C_7_SCL46.b32 NV_PPWR_OUTPUT_I2C_8_SCL47.b32 NV_PPWR_OUTPUT_I2C_9_SCL48i2c_sda_map:49.b32 NV_PPWR_OUTPUT_I2C_0_SDA50.b32 NV_PPWR_OUTPUT_I2C_1_SDA51.b32 NV_PPWR_OUTPUT_I2C_2_SDA52.b32 NV_PPWR_OUTPUT_I2C_3_SDA53.b32 NV_PPWR_OUTPUT_I2C_4_SDA54.b32 NV_PPWR_OUTPUT_I2C_5_SDA55.b32 NV_PPWR_OUTPUT_I2C_6_SDA56.b32 NV_PPWR_OUTPUT_I2C_7_SDA57.b32 NV_PPWR_OUTPUT_I2C_8_SDA58.b32 NV_PPWR_OUTPUT_I2C_9_SDA59#if NVKM_PPWR_CHIPSET < GF11960i2c_ctrl:61.b32 0x00e13862.b32 0x00e15063.b32 0x00e16864.b32 0x00e18065.b32 0x00e25466.b32 0x00e27467.b32 0x00e76468.b32 0x00e78069.b32 0x00e79c70.b32 0x00e7b871#endif72#endif73 74/******************************************************************************75 * I2C_ code segment76 *****************************************************************************/77#ifdef INCLUDE_CODE78 79// $r3 - value80// $r2 - sda line81// $r1 - scl line82// $r0 - zero83i2c_drive_scl:84 cmp b32 $r3 085 bra e #i2c_drive_scl_lo86 nv_iowr(NV_PPWR_OUTPUT_SET, $r1)87 ret88 i2c_drive_scl_lo:89 nv_iowr(NV_PPWR_OUTPUT_CLR, $r1)90 ret91 92i2c_drive_sda:93 cmp b32 $r3 094 bra e #i2c_drive_sda_lo95 nv_iowr(NV_PPWR_OUTPUT_SET, $r2)96 ret97 i2c_drive_sda_lo:98 nv_iowr(NV_PPWR_OUTPUT_CLR, $r2)99 ret100 101i2c_sense_scl:102 bclr $flags $p1103 nv_iord($r3, NV_PPWR_INPUT)104 and $r3 $r1105 bra z #i2c_sense_scl_done106 bset $flags $p1107 i2c_sense_scl_done:108 ret109 110i2c_sense_sda:111 bclr $flags $p1112 nv_iord($r3, NV_PPWR_INPUT)113 and $r3 $r2114 bra z #i2c_sense_sda_done115 bset $flags $p1116 i2c_sense_sda_done:117 ret118 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 $r4161 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_done167 sub b32 $r4 1168 bra nz #i2c_raise_scl_wait169 i2c_raise_scl_done:170 pop $r4171 ret172 173i2c_start:174 i2c_sense_scl()175 bra not $p1 #i2c_start_rep176 i2c_sense_sda()177 bra not $p1 #i2c_start_rep178 bra #i2c_start_send179 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_out184 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 ret191 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 ret201 202// $r3 - value203// $r2 - sda line204// $r1 - scl line205// $r0 - zero206i2c_bitw:207 call(i2c_drive_sda)208 i2c_delay(T_RISEFALL)209 i2c_trace_call(i2c_raise_scl)210 bra not $p1 #i2c_bitw_out211 i2c_delay(T_HOLD)212 i2c_drive_scl(0)213 i2c_delay(T_HOLD)214 i2c_bitw_out:215 ret216 217// $r3 - value (out)218// $r2 - sda line219// $r1 - scl line220// $r0 - zero221i2c_bitr:222 i2c_drive_sda(1)223 i2c_delay(T_RISEFALL)224 i2c_trace_call(i2c_raise_scl)225 bra not $p1 #i2c_bitr_done226 i2c_sense_sda()227 i2c_drive_scl(0)228 i2c_delay(T_HOLD)229 xbit $r3 $flags $p1230 bset $flags $p1231 i2c_bitr_done:232 ret233 234i2c_get_byte:235 mov $r5 0236 mov $r4 8237 i2c_get_byte_next:238 shl b32 $r5 1239 i2c_trace_call(i2c_bitr)240 bra not $p1 #i2c_get_byte_done241 or $r5 $r3242 sub b32 $r4 1243 bra nz #i2c_get_byte_next244 mov $r3 1245 i2c_trace_call(i2c_bitw)246 i2c_get_byte_done:247 ret248 249i2c_put_byte:250 mov $r4 8251 i2c_put_byte_next:252 sub b32 $r4 1253 xbit $r3 $r5 $r4254 i2c_trace_call(i2c_bitw)255 bra not $p1 #i2c_put_byte_done256 cmp b32 $r4 0257 bra ne #i2c_put_byte_next258 i2c_trace_call(i2c_bitr)259 bra not $p1 #i2c_put_byte_done260 i2c_trace_next()261 cmp b32 $r3 1262 bra ne #i2c_put_byte_done263 bclr $flags $p1 // nack264 i2c_put_byte_done:265 ret266 267i2c_addr:268 i2c_trace_call(i2c_start)269 bra not $p1 #i2c_addr_done270 extr $r3 $r12 I2C__MSG_DATA0_ADDR271 shl b32 $r3 1272 or $r5 $r3273 i2c_trace_call(i2c_put_byte)274 i2c_addr_done:275 ret276 277i2c_acquire_addr:278 extr $r14 $r12 I2C__MSG_DATA0_PORT279#if NVKM_PPWR_CHIPSET < GF119280 shl b32 $r14 2281 add b32 $r14 #i2c_ctrl282 ld b32 $r14 D[$r14]283#else284 shl b32 $r14 5285 add b32 $r14 0x00d014286#endif287 ret288 289i2c_acquire:290 call(i2c_acquire_addr)291 call(rd32)292 bset $r13 3293 call(wr32)294 ret295 296i2c_release:297 call(i2c_acquire_addr)298 call(rd32)299 bclr $r13 3300 call(wr32)301 ret302 303// description304//305// $r15 - current (i2c)306// $r14 - sender process name307// $r13 - message308// $r12 - data0309// $r11 - data1310// $r0 - zero311i2c_recv:312 bclr $flags $p1313 extr $r1 $r12 I2C__MSG_DATA0_PORT314 shl b32 $r1 2315 cmp b32 $r1 (#i2c_sda_map - #i2c_scl_map)316 bra ge #i2c_recv_done317 add b32 $r3 $r1 #i2c_sda_map318 ld b32 $r2 D[$r3]319 add b32 $r3 $r1 #i2c_scl_map320 ld b32 $r1 D[$r3]321 322 bset $flags $p2323 push $r13324 push $r14325 326 push $r13327 i2c_trace_init()328 i2c_trace_call(i2c_acquire)329 pop $r13330 331 cmp b32 $r13 I2C__MSG_RD08332 bra ne #i2c_recv_not_rd08333 mov $r5 0334 i2c_trace_call(i2c_addr)335 bra not $p1 #i2c_recv_done336 extr $r5 $r12 I2C__MSG_DATA0_RD08_REG337 i2c_trace_call(i2c_put_byte)338 bra not $p1 #i2c_recv_done339 mov $r5 1340 i2c_trace_call(i2c_addr)341 bra not $p1 #i2c_recv_done342 i2c_trace_call(i2c_get_byte)343 bra not $p1 #i2c_recv_done344 ins $r11 $r5 I2C__MSG_DATA1_RD08_VAL345 i2c_trace_call(i2c_stop)346 mov b32 $r11 $r5347 clear b32 $r7348 bra #i2c_recv_done349 350 i2c_recv_not_rd08:351 cmp b32 $r13 I2C__MSG_WR08352 bra ne #i2c_recv_not_wr08353 mov $r5 0354 call(i2c_addr)355 bra not $p1 #i2c_recv_done356 extr $r5 $r12 I2C__MSG_DATA0_WR08_REG357 call(i2c_put_byte)358 bra not $p1 #i2c_recv_done359 mov $r5 0360 call(i2c_addr)361 bra not $p1 #i2c_recv_done362 extr $r5 $r11 I2C__MSG_DATA1_WR08_VAL363 call(i2c_put_byte)364 bra not $p1 #i2c_recv_done365 call(i2c_stop)366 clear b32 $r7367 extr $r5 $r12 I2C__MSG_DATA0_WR08_SYNC368 bra nz #i2c_recv_done369 bclr $flags $p2370 bra #i2c_recv_done371 372 i2c_recv_not_wr08:373 374 i2c_recv_done:375 extr $r14 $r12 I2C__MSG_DATA0_PORT376 call(i2c_release)377 378 pop $r14379 pop $r13380 bra not $p2 #i2c_recv_exit381 mov b32 $r12 $r7382 call(send)383 384 i2c_recv_exit:385 ret386 387// description388//389// $r15 - current (i2c)390// $r0 - zero391i2c_init:392 ret393#endif394