Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2013 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: Ben Skeggs
0023  */
0024 
0025 #define T_TIMEOUT  2200000
0026 #define T_RISEFALL 1000
0027 #define T_HOLD     5000
0028 
0029 #ifdef INCLUDE_PROC
0030 process(PROC_I2C_, #i2c_init, #i2c_recv)
0031 #endif
0032 
0033 /******************************************************************************
0034  * I2C_ data segment
0035  *****************************************************************************/
0036 #ifdef INCLUDE_DATA
0037 i2c_scl_map:
0038 .b32 NV_PPWR_OUTPUT_I2C_0_SCL
0039 .b32 NV_PPWR_OUTPUT_I2C_1_SCL
0040 .b32 NV_PPWR_OUTPUT_I2C_2_SCL
0041 .b32 NV_PPWR_OUTPUT_I2C_3_SCL
0042 .b32 NV_PPWR_OUTPUT_I2C_4_SCL
0043 .b32 NV_PPWR_OUTPUT_I2C_5_SCL
0044 .b32 NV_PPWR_OUTPUT_I2C_6_SCL
0045 .b32 NV_PPWR_OUTPUT_I2C_7_SCL
0046 .b32 NV_PPWR_OUTPUT_I2C_8_SCL
0047 .b32 NV_PPWR_OUTPUT_I2C_9_SCL
0048 i2c_sda_map:
0049 .b32 NV_PPWR_OUTPUT_I2C_0_SDA
0050 .b32 NV_PPWR_OUTPUT_I2C_1_SDA
0051 .b32 NV_PPWR_OUTPUT_I2C_2_SDA
0052 .b32 NV_PPWR_OUTPUT_I2C_3_SDA
0053 .b32 NV_PPWR_OUTPUT_I2C_4_SDA
0054 .b32 NV_PPWR_OUTPUT_I2C_5_SDA
0055 .b32 NV_PPWR_OUTPUT_I2C_6_SDA
0056 .b32 NV_PPWR_OUTPUT_I2C_7_SDA
0057 .b32 NV_PPWR_OUTPUT_I2C_8_SDA
0058 .b32 NV_PPWR_OUTPUT_I2C_9_SDA
0059 #if NVKM_PPWR_CHIPSET < GF119
0060 i2c_ctrl:
0061 .b32 0x00e138
0062 .b32 0x00e150
0063 .b32 0x00e168
0064 .b32 0x00e180
0065 .b32 0x00e254
0066 .b32 0x00e274
0067 .b32 0x00e764
0068 .b32 0x00e780
0069 .b32 0x00e79c
0070 .b32 0x00e7b8
0071 #endif
0072 #endif
0073 
0074 /******************************************************************************
0075  * I2C_ code segment
0076  *****************************************************************************/
0077 #ifdef INCLUDE_CODE
0078 
0079 // $r3  - value
0080 // $r2  - sda line
0081 // $r1  - scl line
0082 // $r0  - zero
0083 i2c_drive_scl:
0084         cmp b32 $r3 0
0085         bra e #i2c_drive_scl_lo
0086         nv_iowr(NV_PPWR_OUTPUT_SET, $r1)
0087         ret
0088         i2c_drive_scl_lo:
0089         nv_iowr(NV_PPWR_OUTPUT_CLR, $r1)
0090         ret
0091 
0092 i2c_drive_sda:
0093         cmp b32 $r3 0
0094         bra e #i2c_drive_sda_lo
0095         nv_iowr(NV_PPWR_OUTPUT_SET, $r2)
0096         ret
0097         i2c_drive_sda_lo:
0098         nv_iowr(NV_PPWR_OUTPUT_CLR, $r2)
0099         ret
0100 
0101 i2c_sense_scl:
0102         bclr $flags $p1
0103         nv_iord($r3, NV_PPWR_INPUT)
0104         and $r3 $r1
0105         bra z #i2c_sense_scl_done
0106                 bset $flags $p1
0107         i2c_sense_scl_done:
0108         ret
0109 
0110 i2c_sense_sda:
0111         bclr $flags $p1
0112         nv_iord($r3, NV_PPWR_INPUT)
0113         and $r3 $r2
0114         bra z #i2c_sense_sda_done
0115                 bset $flags $p1
0116         i2c_sense_sda_done:
0117         ret
0118 
0119 #define i2c_drive_scl(v) /*
0120 */      mov $r3 (v) /*
0121 */      call(i2c_drive_scl)
0122 #define i2c_drive_sda(v) /*
0123 */      mov $r3 (v) /*
0124 */      call(i2c_drive_sda)
0125 #define i2c_sense_scl() /*
0126 */      call(i2c_sense_scl)
0127 #define i2c_sense_sda() /*
0128 */      call(i2c_sense_sda)
0129 #define i2c_delay(v) /*
0130 */      mov $r14 (v) /*
0131 */      call(nsec)
0132 
0133 #define i2c_trace_init() /*
0134 */      imm32($r6, 0x10000000) /*
0135 */      sub b32 $r7 $r6 1 /*
0136 */
0137 #define i2c_trace_down() /*
0138 */      shr b32 $r6 4 /*
0139 */      push $r5 /*
0140 */      shl b32 $r5 $r6 4 /*
0141 */      sub b32 $r5 $r6 /*
0142 */      not b32 $r5 /*
0143 */      and $r7 $r5 /*
0144 */      pop $r5 /*
0145 */
0146 #define i2c_trace_exit() /*
0147 */      shl b32 $r6 4 /*
0148 */
0149 #define i2c_trace_next() /*
0150 */      add b32 $r7 $r6 /*
0151 */
0152 #define i2c_trace_call(func) /*
0153 */      i2c_trace_next() /*
0154 */      i2c_trace_down() /*
0155 */      call(func) /*
0156 */      i2c_trace_exit() /*
0157 */
0158 
0159 i2c_raise_scl:
0160         push $r4
0161         mov $r4 (T_TIMEOUT / T_RISEFALL)
0162         i2c_drive_scl(1)
0163         i2c_raise_scl_wait:
0164                 i2c_delay(T_RISEFALL)
0165                 i2c_sense_scl()
0166                 bra $p1 #i2c_raise_scl_done
0167                 sub b32 $r4 1
0168                 bra nz #i2c_raise_scl_wait
0169         i2c_raise_scl_done:
0170         pop $r4
0171         ret
0172 
0173 i2c_start:
0174         i2c_sense_scl()
0175         bra not $p1 #i2c_start_rep
0176         i2c_sense_sda()
0177         bra not $p1 #i2c_start_rep
0178         bra #i2c_start_send
0179         i2c_start_rep:
0180                 i2c_drive_scl(0)
0181                 i2c_drive_sda(1)
0182                 i2c_trace_call(i2c_raise_scl)
0183                 bra not $p1 #i2c_start_out
0184         i2c_start_send:
0185         i2c_drive_sda(0)
0186         i2c_delay(T_HOLD)
0187         i2c_drive_scl(0)
0188         i2c_delay(T_HOLD)
0189         i2c_start_out:
0190         ret
0191 
0192 i2c_stop:
0193         i2c_drive_scl(0)
0194         i2c_drive_sda(0)
0195         i2c_delay(T_RISEFALL)
0196         i2c_drive_scl(1)
0197         i2c_delay(T_HOLD)
0198         i2c_drive_sda(1)
0199         i2c_delay(T_HOLD)
0200         ret
0201 
0202 // $r3  - value
0203 // $r2  - sda line
0204 // $r1  - scl line
0205 // $r0  - zero
0206 i2c_bitw:
0207         call(i2c_drive_sda)
0208         i2c_delay(T_RISEFALL)
0209         i2c_trace_call(i2c_raise_scl)
0210         bra not $p1 #i2c_bitw_out
0211         i2c_delay(T_HOLD)
0212         i2c_drive_scl(0)
0213         i2c_delay(T_HOLD)
0214         i2c_bitw_out:
0215         ret
0216 
0217 // $r3  - value (out)
0218 // $r2  - sda line
0219 // $r1  - scl line
0220 // $r0  - zero
0221 i2c_bitr:
0222         i2c_drive_sda(1)
0223         i2c_delay(T_RISEFALL)
0224         i2c_trace_call(i2c_raise_scl)
0225         bra not $p1 #i2c_bitr_done
0226         i2c_sense_sda()
0227         i2c_drive_scl(0)
0228         i2c_delay(T_HOLD)
0229         xbit $r3 $flags $p1
0230         bset $flags $p1
0231         i2c_bitr_done:
0232         ret
0233 
0234 i2c_get_byte:
0235         mov $r5 0
0236         mov $r4 8
0237         i2c_get_byte_next:
0238                 shl b32 $r5 1
0239                 i2c_trace_call(i2c_bitr)
0240                 bra not $p1 #i2c_get_byte_done
0241                 or $r5 $r3
0242                 sub b32 $r4 1
0243                 bra nz #i2c_get_byte_next
0244         mov $r3 1
0245         i2c_trace_call(i2c_bitw)
0246         i2c_get_byte_done:
0247         ret
0248 
0249 i2c_put_byte:
0250         mov $r4 8
0251         i2c_put_byte_next:
0252                 sub b32 $r4 1
0253                 xbit $r3 $r5 $r4
0254                 i2c_trace_call(i2c_bitw)
0255                 bra not $p1 #i2c_put_byte_done
0256                 cmp b32 $r4 0
0257                 bra ne #i2c_put_byte_next
0258         i2c_trace_call(i2c_bitr)
0259         bra not $p1 #i2c_put_byte_done
0260         i2c_trace_next()
0261         cmp b32 $r3 1
0262         bra ne #i2c_put_byte_done
0263         bclr $flags $p1 // nack
0264         i2c_put_byte_done:
0265         ret
0266 
0267 i2c_addr:
0268         i2c_trace_call(i2c_start)
0269         bra not $p1 #i2c_addr_done
0270         extr $r3 $r12 I2C__MSG_DATA0_ADDR
0271         shl b32 $r3 1
0272         or $r5 $r3
0273         i2c_trace_call(i2c_put_byte)
0274         i2c_addr_done:
0275         ret
0276 
0277 i2c_acquire_addr:
0278         extr $r14 $r12 I2C__MSG_DATA0_PORT
0279 #if NVKM_PPWR_CHIPSET < GF119
0280         shl b32 $r14 2
0281         add b32 $r14 #i2c_ctrl
0282         ld b32 $r14 D[$r14]
0283 #else
0284         shl b32 $r14 5
0285         add b32 $r14 0x00d014
0286 #endif
0287         ret
0288 
0289 i2c_acquire:
0290         call(i2c_acquire_addr)
0291         call(rd32)
0292         bset $r13 3
0293         call(wr32)
0294         ret
0295 
0296 i2c_release:
0297         call(i2c_acquire_addr)
0298         call(rd32)
0299         bclr $r13 3
0300         call(wr32)
0301         ret
0302 
0303 // description
0304 //
0305 // $r15 - current (i2c)
0306 // $r14 - sender process name
0307 // $r13 - message
0308 // $r12 - data0
0309 // $r11 - data1
0310 // $r0  - zero
0311 i2c_recv:
0312         bclr $flags $p1
0313         extr $r1 $r12 I2C__MSG_DATA0_PORT
0314         shl b32 $r1 2
0315         cmp b32 $r1 (#i2c_sda_map - #i2c_scl_map)
0316         bra ge #i2c_recv_done
0317         add b32 $r3 $r1 #i2c_sda_map
0318         ld b32 $r2 D[$r3]
0319         add b32 $r3 $r1 #i2c_scl_map
0320         ld b32 $r1 D[$r3]
0321 
0322         bset $flags $p2
0323         push $r13
0324         push $r14
0325 
0326         push $r13
0327         i2c_trace_init()
0328         i2c_trace_call(i2c_acquire)
0329         pop $r13
0330 
0331         cmp b32 $r13 I2C__MSG_RD08
0332         bra ne #i2c_recv_not_rd08
0333                 mov $r5 0
0334                 i2c_trace_call(i2c_addr)
0335                 bra not $p1 #i2c_recv_done
0336                 extr $r5 $r12 I2C__MSG_DATA0_RD08_REG
0337                 i2c_trace_call(i2c_put_byte)
0338                 bra not $p1 #i2c_recv_done
0339                 mov $r5 1
0340                 i2c_trace_call(i2c_addr)
0341                 bra not $p1 #i2c_recv_done
0342                 i2c_trace_call(i2c_get_byte)
0343                 bra not $p1 #i2c_recv_done
0344                 ins $r11 $r5 I2C__MSG_DATA1_RD08_VAL
0345                 i2c_trace_call(i2c_stop)
0346                 mov b32 $r11 $r5
0347                 clear b32 $r7
0348                 bra #i2c_recv_done
0349 
0350         i2c_recv_not_rd08:
0351         cmp b32 $r13 I2C__MSG_WR08
0352         bra ne #i2c_recv_not_wr08
0353                 mov $r5 0
0354                 call(i2c_addr)
0355                 bra not $p1 #i2c_recv_done
0356                 extr $r5 $r12 I2C__MSG_DATA0_WR08_REG
0357                 call(i2c_put_byte)
0358                 bra not $p1 #i2c_recv_done
0359                 mov $r5 0
0360                 call(i2c_addr)
0361                 bra not $p1 #i2c_recv_done
0362                 extr $r5 $r11 I2C__MSG_DATA1_WR08_VAL
0363                 call(i2c_put_byte)
0364                 bra not $p1 #i2c_recv_done
0365                 call(i2c_stop)
0366                 clear b32 $r7
0367                 extr $r5 $r12 I2C__MSG_DATA0_WR08_SYNC
0368                 bra nz #i2c_recv_done
0369                 bclr $flags $p2
0370                 bra #i2c_recv_done
0371 
0372         i2c_recv_not_wr08:
0373 
0374         i2c_recv_done:
0375         extr $r14 $r12 I2C__MSG_DATA0_PORT
0376         call(i2c_release)
0377 
0378         pop $r14
0379         pop $r13
0380         bra not $p2 #i2c_recv_exit
0381         mov b32 $r12 $r7
0382         call(send)
0383 
0384         i2c_recv_exit:
0385         ret
0386 
0387 // description
0388 //
0389 // $r15 - current (i2c)
0390 // $r0  - zero
0391 i2c_init:
0392         ret
0393 #endif