rjw | 6c1fd8f | 2022-11-30 14:33:01 +0800 | [diff] [blame] | 1 | /***************************************************************************** |
| 2 | * Copyright Statement: |
| 3 | * -------------------- |
| 4 | * This software is protected by Copyright and the information contained |
| 5 | * herein is confidential. The software may not be copied and the information |
| 6 | * contained herein may not be used or disclosed except with the written |
| 7 | * permission of MediaTek Inc. (C) 2005 |
| 8 | * |
| 9 | * BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES |
| 10 | * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") |
| 11 | * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON |
| 12 | * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, |
| 13 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF |
| 14 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. |
| 15 | * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE |
| 16 | * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR |
| 17 | * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH |
| 18 | * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO |
| 19 | * NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S |
| 20 | * SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. |
| 21 | * |
| 22 | * BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE |
| 23 | * LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, |
| 24 | * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, |
| 25 | * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO |
| 26 | * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. |
| 27 | * |
| 28 | * THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE |
| 29 | * WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF |
| 30 | * LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND |
| 31 | * RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER |
| 32 | * THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). |
| 33 | * |
| 34 | *****************************************************************************/ |
| 35 | |
| 36 | /***************************************************************************** |
| 37 | * |
| 38 | * Filename: |
| 39 | * --------- |
| 40 | * drv_i2c.c |
| 41 | * |
| 42 | * |
| 43 | * Description: |
| 44 | * ------------ |
| 45 | * I2C Driver |
| 46 | * |
| 47 | * Author: |
| 48 | * ------- |
| 49 | * ------- |
| 50 | * |
| 51 | *============================================================================ |
| 52 | * HISTORY |
| 53 | * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! |
| 54 | *------------------------------------------------------------------------------ |
| 55 | * removed! |
| 56 | * removed! |
| 57 | * removed! |
| 58 | * |
| 59 | * removed! |
| 60 | * removed! |
| 61 | * removed! |
| 62 | * |
| 63 | * removed! |
| 64 | * removed! |
| 65 | * removed! |
| 66 | * |
| 67 | * removed! |
| 68 | * removed! |
| 69 | * removed! |
| 70 | * |
| 71 | * removed! |
| 72 | * removed! |
| 73 | * removed! |
| 74 | * removed! |
| 75 | *------------------------------------------------------------------------------ |
| 76 | * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! |
| 77 | *============================================================================ |
| 78 | *****************************************************************************/ |
| 79 | #include "drv_comm.h" |
| 80 | #include "reg_base.h" |
| 81 | #include "drv_i2c.h" //*/ the new sccb_v2.h should be named i2c.h /*// |
| 82 | #include "drvpdn.h" |
| 83 | |
| 84 | #include "dcl_i2c_owner.h" |
| 85 | #include "kal_general_types.h" |
| 86 | #include "kal_public_api.h" |
| 87 | #include "drvpdn_inline.h" |
| 88 | #include <ex_item.h> |
| 89 | #include <ex_public.h> |
| 90 | |
| 91 | #if (!defined(DRV_I2C_OFF)) |
| 92 | #if defined(__MD95__) |
| 93 | #define I2C_POWER_OFF() do{PDN_SET(PDN_I2C_BCLK);}while(0) /* Power off I2C */ |
| 94 | #define I2C_POWER_ON() do{PDN_CLR(PDN_I2C_BCLK);}while(0) /* Power on I2C */ |
| 95 | #else |
| 96 | #define I2C_POWER_OFF() |
| 97 | #define I2C_POWER_ON() |
| 98 | #endif |
| 99 | /// I2C internal global variables |
| 100 | i2c_handle_struct i2c_handle[DCL_I2C_NUM_OF_OWNER]; |
| 101 | i2c_status_struct dcl_i2c_status; |
| 102 | kal_bool i2c_lock_status = KAL_FALSE; |
| 103 | kal_spinlockid i2c_lock_id = 0; |
| 104 | |
| 105 | |
| 106 | //*/ abstract the HW register config API /*// |
| 107 | //called in i2c_write -> dcl_i2c_hw_cfg (owner, I2C_TRANSACTION_WRITE, para, datalen, NULL, 0, 1); |
| 108 | //called in i2c_read -> dcl_i2c_hw_cfg (owner, I2C_TRANSACTION_READ, NULL, 0, para, datalen, 1); |
| 109 | //called in i2c_cont_write -> dcl_i2c_hw_cfg (owner, I2C_TRANSACTION_CONT_WRITE, para, datalen_in_transfer, NULL, 0, transfer_num); |
| 110 | //called in i2c_cont_read -> dcl_i2c_hw_cfg (owner, I2C_TRANSACTION_CONT_READ, NULL, 0, para, datalen_in_transfer, transfer_num); |
| 111 | //called in i2c_write_and_read -> dcl_i2c_hw_cfg (owner, I2C_TRANSACTION_WRITE_AND_READ, write_buffer, write_len, read_buffer, read_len, 2); |
| 112 | void dcl_i2c_hw_cfg (DCL_I2C_OWNER owner, I2C_TRANSACTION_TYPE type, kal_uint8* write_buffer, kal_uint32 write_len, kal_uint8* read_buffer, kal_uint32 read_len, kal_uint32 transfer_num) |
| 113 | { |
| 114 | i2c_handle_struct* handle=&i2c_handle[owner]; |
| 115 | i2c_config_struct* config=&handle->i2c_config; |
| 116 | kal_uint32 count_write, count_read, i; |
| 117 | |
| 118 | if (read_len>DRV_I2C_FIFO_DEPTH || write_len>DRV_I2C_FIFO_DEPTH) //if u want a transcation with len>8, please enable DMA. |
| 119 | { |
| 120 | ASSERT(0); |
| 121 | } |
| 122 | count_write = write_len*transfer_num; |
| 123 | count_read = read_len*transfer_num; |
| 124 | |
| 125 | CLEAR_I2C_FIFO; |
| 126 | CLEAR_I2C_STA; |
| 127 | DISABLE_I2C_INT; |
| 128 | |
| 129 | SET_I2C_STEP_CNT_DIV(handle->fs_step_cnt_div); |
| 130 | SET_I2C_SAMPLE_CNT_DIV(handle->fs_sample_cnt_div); |
| 131 | |
| 132 | SET_I2C_TRANSACTION_LENGTH(transfer_num); |
| 133 | |
| 134 | if (handle->i2c_config.transaction_mode == I2C_TRANSACTION_FAST_MODE) |
| 135 | { |
| 136 | SET_I2C_FAST_MODE; |
| 137 | SET_I2C_ST_BETWEEN_TRANSFER; |
| 138 | if (config->delay_len>0) |
| 139 | { |
| 140 | SET_I2C_DELAY_LENGTH(config->delay_len-1); |
| 141 | } |
| 142 | if ((config->delay_len == 0)&&((type == I2C_TRANSACTION_CONT_WRITE)||(type == I2C_TRANSACTION_CONT_READ))) |
| 143 | { |
| 144 | SET_I2C_RS_BETWEEN_TRANSFER; |
| 145 | } |
| 146 | } |
| 147 | else if (handle->i2c_config.transaction_mode == I2C_TRANSACTION_HIGH_SPEED_MODE) |
| 148 | { |
| 149 | SET_I2C_HS_STEP_CNT_DIV(handle->hs_step_cnt_div); |
| 150 | SET_I2C_HS_SAMPLE_CNT_DIV(handle->hs_sample_cnt_div); |
| 151 | SET_I2C_HS_MODE; |
| 152 | SET_I2C_RS_BETWEEN_TRANSFER; |
| 153 | } |
| 154 | |
| 155 | DISABLE_I2C_DIR_CHANGE; |
| 156 | DISABLE_I2C_DMA_TRANSFER; |
| 157 | |
| 158 | if ((type == I2C_TRANSACTION_WRITE)||(type == I2C_TRANSACTION_CONT_WRITE)) |
| 159 | { |
| 160 | SET_I2C_SLAVE_ADDRESS(config->slave_address,I2C_WRITE_BIT); |
| 161 | SET_I2C_TRANSFER_LENGTH(write_len); |
| 162 | dcl_i2c_status.number_of_read=0; |
| 163 | |
| 164 | for (i=0;i<count_write;i++) |
| 165 | { |
| 166 | DRV_I2C_WriteReg16(REG_I2C_DATA_PORT, *(write_buffer+i)); |
| 167 | } |
| 168 | } |
| 169 | else if ((type == I2C_TRANSACTION_READ)||(type == I2C_TRANSACTION_CONT_READ)) |
| 170 | { |
| 171 | SET_I2C_SLAVE_ADDRESS(config->slave_address,I2C_READ_BIT); |
| 172 | SET_I2C_TRANSFER_LENGTH(read_len); |
| 173 | dcl_i2c_status.number_of_read = count_read; |
| 174 | dcl_i2c_status.read_buffer=read_buffer; |
| 175 | } |
| 176 | else if (type == I2C_TRANSACTION_WRITE_AND_READ) |
| 177 | { |
| 178 | SET_I2C_SLAVE_ADDRESS(config->slave_address,I2C_WRITE_BIT); |
| 179 | SET_I2C_TRANSFER_LENGTH(write_len); |
| 180 | SET_I2C_AUX_TRANSFER_LENGTH(read_len); |
| 181 | ENABLE_I2C_DIR_CHANGE; |
| 182 | SET_I2C_RS_BETWEEN_TRANSFER; |
| 183 | |
| 184 | dcl_i2c_status.number_of_read = read_len; |
| 185 | dcl_i2c_status.read_buffer=read_buffer; |
| 186 | for (i=0;i<write_len;i++) |
| 187 | { |
| 188 | DRV_I2C_WriteReg16(REG_I2C_DATA_PORT, (*(write_buffer+i))); |
| 189 | } |
| 190 | } |
| 191 | START_I2C_TRANSACTION; |
| 192 | } |
| 193 | |
| 194 | |
| 195 | void _dcl_i2c_status_handler(kal_uint32 sta) |
| 196 | { |
| 197 | kal_uint32 i; |
| 198 | kal_uint8* read_buffer=dcl_i2c_status.read_buffer; |
| 199 | kal_uint32 number_of_read=dcl_i2c_status.number_of_read; |
| 200 | i2c_handle_struct* handle=&i2c_handle[dcl_i2c_status.owner]; |
| 201 | |
| 202 | if (sta == I2C_TRANSAC_COMPLETE) //This transaction is done now |
| 203 | { |
| 204 | for (i=0;i<number_of_read;i++) |
| 205 | { |
| 206 | read_buffer[i]=(DRV_I2C_ReadReg16(REG_I2C_DATA_PORT) & 0xff); //copy the read data to the previous transcation owner |
| 207 | } |
| 208 | handle->transaction_result = I2C_TRANSACTION_COMPLETE; |
| 209 | } |
| 210 | else |
| 211 | { |
| 212 | if (sta & I2C_TRANSAC_ACK_ERR) |
| 213 | handle->transaction_result = I2C_TRANSACTION_ACKERR; |
| 214 | else if (sta & I2C_HS_NACK_ERR) |
| 215 | handle->transaction_result = I2C_TRANSACTION_HS_NACKERR; |
| 216 | else //if got this, check register INTR_STAT to debug |
| 217 | handle->transaction_result = I2C_TRANSACTION_FAIL; |
| 218 | } |
| 219 | dcl_i2c_status.state=I2C_READY_STATE; |
| 220 | } |
| 221 | |
| 222 | void _dcl_i2c_lisr(kal_uint32 vector) |
| 223 | { |
| 224 | kal_uint32 savedMask; |
| 225 | kal_uint32 sta; |
| 226 | //test lisr executive time |
| 227 | //kal_uint32 start_qbit,end_qbit;// |
| 228 | |
| 229 | //start_qbit = HW_TDMA_GET_TQCNT();// |
| 230 | |
| 231 | savedMask = SaveAndSetIRQMask(); |
| 232 | |
| 233 | sta = DRV_I2C_ReadReg16(REG_I2C_INT_STA); //sta=REG_I2C_INT_STA; |
| 234 | |
| 235 | { |
| 236 | _dcl_i2c_status_handler(sta); |
| 237 | } |
| 238 | |
| 239 | RestoreIRQMask(savedMask); |
| 240 | //end_qbit = HW_TDMA_GET_TQCNT();// |
| 241 | } |
| 242 | |
| 243 | |
| 244 | void dcl_i2c_init(void) |
| 245 | { |
| 246 | if(dcl_i2c_status.state != I2C_IDLE_STATE) |
| 247 | { |
| 248 | return; |
| 249 | } |
| 250 | |
| 251 | dcl_i2c_status.state=I2C_READY_STATE; |
| 252 | I2C_POWER_ON(); |
| 253 | |
| 254 | SET_I2C_HW_MODE; |
| 255 | ENABLE_I2C_ACK_ERR_DET; //Always enable ack error detection |
| 256 | ENABLE_I2C_NAKERR_DET; //Always enable nack error detection |
| 257 | |
| 258 | // create mutex |
| 259 | if(i2c_lock_status == KAL_FALSE && !INT_QueryExceptionStatus()) |
| 260 | { |
| 261 | i2c_lock_id = kal_create_spinlock("DRV_I2C"); |
| 262 | i2c_lock_status = KAL_TRUE; |
| 263 | } |
| 264 | MD_TRC(I2C_INIT_MSG,__FUNCTION__); |
| 265 | } |
| 266 | |
| 267 | void dcl_i2c_deinit(void) |
| 268 | { |
| 269 | RESET_I2C; |
| 270 | kal_mem_set(&dcl_i2c_status,0, sizeof(i2c_status_struct)); |
| 271 | MD_TRC(I2C_DEINIT_MSG,__FUNCTION__); |
| 272 | I2C_POWER_OFF(); |
| 273 | } |
| 274 | |
| 275 | |
| 276 | //----------------------------I2C internal arbiteration------------------------------ |
| 277 | //--When return from this function, I bit is turned off!!-- |
| 278 | kal_uint32 dcl_i2c_wait_transaction_complete_and_lock(DCL_I2C_OWNER owner) |
| 279 | { |
| 280 | if (!(kal_if_lisr())) |
| 281 | { |
| 282 | while(1) |
| 283 | { |
| 284 | if (dcl_i2c_status.state==I2C_READY_STATE) |
| 285 | { |
| 286 | kal_take_spinlock(i2c_lock_id, KAL_INFINITE_WAIT); |
| 287 | dcl_i2c_status.state=I2C_BUSY_STATE; //Lock it |
| 288 | dcl_i2c_status.owner=owner; |
| 289 | kal_give_spinlock(i2c_lock_id); |
| 290 | return 0;//will restore it at: dcl_i2c_wait_transaction_complete |
| 291 | } |
| 292 | else if (i2c_handle[owner].i2c_config.get_handle_wait==KAL_FALSE) |
| 293 | { |
| 294 | return 0; |
| 295 | } |
| 296 | |
| 297 | }//end of while |
| 298 | } |
| 299 | else |
| 300 | { |
| 301 | if (dcl_i2c_status.state!=I2C_READY_STATE) |
| 302 | { |
| 303 | ASSERT(0); |
| 304 | } |
| 305 | |
| 306 | dcl_i2c_status.state=I2C_BUSY_STATE; //Lock it |
| 307 | dcl_i2c_status.owner=owner; |
| 308 | } |
| 309 | |
| 310 | return 0; |
| 311 | } |
| 312 | |
| 313 | |
| 314 | |
| 315 | void dcl_i2c_wait_transaction_complete(kal_uint32 savedMask) |
| 316 | { |
| 317 | kal_uint32 sta=0,timer=0; |
| 318 | kal_uint32 i=0; |
| 319 | kal_uint8* read_buffer=dcl_i2c_status.read_buffer; |
| 320 | kal_uint32 number_of_read=dcl_i2c_status.number_of_read; |
| 321 | i2c_handle_struct* handle=&i2c_handle[dcl_i2c_status.owner]; |
| 322 | |
| 323 | timer = 10000; |
| 324 | do |
| 325 | { |
| 326 | sta = DRV_I2C_ReadReg16(REG_I2C_INT_STA); |
| 327 | timer--; |
| 328 | } while((!(sta & I2C_TRANSAC_COMPLETE)) && (timer!=0)); |
| 329 | |
| 330 | if(timer == 0){ |
| 331 | MD_TRC(I2C_TRANSACTION_TIMETOUT_MSG,); |
| 332 | handle->transaction_result = I2C_TRANSACTION_FAIL; |
| 333 | return; |
| 334 | } |
| 335 | |
| 336 | if (sta == I2C_TRANSAC_COMPLETE) //This transaction is done now |
| 337 | { |
| 338 | for (i=0;i<number_of_read;i++) |
| 339 | { |
| 340 | read_buffer[i]=(DRV_I2C_ReadReg16(REG_I2C_DATA_PORT) & 0xff); //copy the read data to the previous transcation owner |
| 341 | } |
| 342 | handle->transaction_result = I2C_TRANSACTION_COMPLETE; |
| 343 | MD_TRC(I2C_TRANSACTION_COMPLETE_MSG,); |
| 344 | } |
| 345 | else |
| 346 | { |
| 347 | MD_TRC(I2C_TRANSACTION_ERROR_MSG,sta); |
| 348 | if (sta & I2C_TRANSAC_ACK_ERR) |
| 349 | handle->transaction_result = I2C_TRANSACTION_ACKERR; |
| 350 | else if (sta & I2C_HS_NACK_ERR) |
| 351 | handle->transaction_result = I2C_TRANSACTION_HS_NACKERR; |
| 352 | else //if got this, check register INTR_STAT to debug |
| 353 | handle->transaction_result = I2C_TRANSACTION_FAIL; |
| 354 | |
| 355 | } |
| 356 | kal_take_spinlock(i2c_lock_id, KAL_INFINITE_WAIT); |
| 357 | dcl_i2c_status.state=I2C_READY_STATE; |
| 358 | kal_give_spinlock(i2c_lock_id); |
| 359 | |
| 360 | } |
| 361 | |
| 362 | |
| 363 | |
| 364 | //----------------------------I2C Configuration APIs------------------------------- |
| 365 | void dcl_i2c_set_transaction_speed(DCL_I2C_OWNER owner,I2C_TRANSACTION_MODE mode,kal_uint16* Fast_Mode_Speed,kal_uint16* HS_Mode_Speed) |
| 366 | { |
| 367 | kal_uint32 step_cnt_div; |
| 368 | kal_uint32 sample_cnt_div; |
| 369 | kal_uint32 temp; |
| 370 | |
| 371 | //Fast Mode Speed |
| 372 | for (sample_cnt_div=1;sample_cnt_div<=8;sample_cnt_div++) |
| 373 | { |
| 374 | if (NULL != Fast_Mode_Speed) |
| 375 | { |
| 376 | temp=((*Fast_Mode_Speed)*2*sample_cnt_div); |
| 377 | } |
| 378 | else |
| 379 | { |
| 380 | temp = 1*2*sample_cnt_div; |
| 381 | } |
| 382 | step_cnt_div=(I2C_CLOCK_RATE+temp-1)/temp; //cast the <1 part |
| 383 | |
| 384 | if (step_cnt_div<=64) |
| 385 | { |
| 386 | break; |
| 387 | } |
| 388 | } |
| 389 | if (step_cnt_div>64 && sample_cnt_div>8) |
| 390 | { |
| 391 | step_cnt_div=64; |
| 392 | sample_cnt_div=8; |
| 393 | } |
| 394 | |
| 395 | |
| 396 | |
| 397 | if (NULL != Fast_Mode_Speed) |
| 398 | { |
| 399 | *Fast_Mode_Speed = I2C_CLOCK_RATE/2/sample_cnt_div/step_cnt_div; |
| 400 | i2c_handle[owner].fs_sample_cnt_div=sample_cnt_div-1; |
| 401 | i2c_handle[owner].fs_step_cnt_div=step_cnt_div-1; |
| 402 | i2c_handle[owner].i2c_config.transaction_mode=I2C_TRANSACTION_FAST_MODE; |
| 403 | |
| 404 | } |
| 405 | |
| 406 | //HS Mode Speed |
| 407 | if (mode==I2C_TRANSACTION_HIGH_SPEED_MODE) |
| 408 | { |
| 409 | for (sample_cnt_div=1;sample_cnt_div<=8;sample_cnt_div++) |
| 410 | { |
| 411 | if (NULL != HS_Mode_Speed) |
| 412 | { |
| 413 | temp=((*HS_Mode_Speed)*2*sample_cnt_div); |
| 414 | } |
| 415 | else |
| 416 | { |
| 417 | temp=(1*2*sample_cnt_div); |
| 418 | } |
| 419 | step_cnt_div=(I2C_CLOCK_RATE+temp-1)/temp; |
| 420 | if (step_cnt_div<=8) |
| 421 | { |
| 422 | break; |
| 423 | } |
| 424 | } |
| 425 | if (NULL != HS_Mode_Speed) |
| 426 | { |
| 427 | *HS_Mode_Speed=I2C_CLOCK_RATE/2/sample_cnt_div/step_cnt_div; |
| 428 | i2c_handle[owner].hs_sample_cnt_div=sample_cnt_div-1; |
| 429 | i2c_handle[owner].hs_step_cnt_div=step_cnt_div-1; |
| 430 | i2c_handle[owner].i2c_config.transaction_mode=I2C_TRANSACTION_HIGH_SPEED_MODE; |
| 431 | } |
| 432 | } |
| 433 | } |
| 434 | |
| 435 | |
| 436 | #endif |
| 437 | |
| 438 | |