📄 rtl_e100_eeprom.c
字号:
//----------------------------------------------------------------------------------------static voidshift_out_bits( u16 data, u16 count){ u16 x, mask; mask = 1 << (count - 1); x = readw(&CSR_EEPROM_CONTROL_FIELD()); x &= ~(EEDO | EEDI); do { x &= ~EEDI; if (data & mask) x |= EEDI; writew(x, &CSR_EEPROM_CONTROL_FIELD()); readw(&(private_data.scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME); raise_clock( &x); lower_clock( &x); mask = mask >> 1; } while (mask); x &= ~EEDI; writew(x, &CSR_EEPROM_CONTROL_FIELD());}//----------------------------------------------------------------------------------------// Procedure: raise_clock//// Description: This routine raises the EEPROM's clock input (EESK)//// Arguments:// x - Ptr to the EEPROM control register's current value//// Returns: (none)//----------------------------------------------------------------------------------------voidraise_clock( u16 *x){ *x = *x | EESK; writew(*x, &CSR_EEPROM_CONTROL_FIELD()); readw(&(private_data.scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME);}//----------------------------------------------------------------------------------------// Procedure: lower_clock//// Description: This routine lower's the EEPROM's clock input (EESK)//// Arguments:// x - Ptr to the EEPROM control register's current value//// Returns: (none)//----------------------------------------------------------------------------------------voidlower_clock( u16 *x){ *x = *x & ~EESK; writew(*x, &CSR_EEPROM_CONTROL_FIELD()); readw(&(private_data.scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME);}//----------------------------------------------------------------------------------------// Procedure: shift_in_bits//// Description: This routine shifts data bits in from the EEPROM.//// Arguments://// Returns:// The contents of that particular EEPROM word//----------------------------------------------------------------------------------------static u16shift_in_bits(){ u16 x, d, i; x = readw(&CSR_EEPROM_CONTROL_FIELD()); x &= ~(EEDO | EEDI); d = 0; for (i = 0; i < 16; i++) { d <<= 1; raise_clock( &x); x = readw(&CSR_EEPROM_CONTROL_FIELD()); x &= ~EEDI; if (x & EEDO) d |= 1; lower_clock( &x); } return d;}//----------------------------------------------------------------------------------------// Procedure: e100_eeprom_cleanup//// Description: This routine returns the EEPROM to an idle state//----------------------------------------------------------------------------------------void e100_eeprom_cleanup(void){ u16 x; x = readw(&CSR_EEPROM_CONTROL_FIELD()); x &= ~(EECS | EEDI); writew(x, &CSR_EEPROM_CONTROL_FIELD()); raise_clock( &x); lower_clock( &x);}//**********************************************************************************// Procedure: e100_eeprom_update_chksum//// Description: Calculates the checksum and writes it to the EEProm. // It calculates the checksum accroding to the formula: // Checksum = 0xBABA - (sum of first 63 words).////-----------------------------------------------------------------------------------u16e100_eeprom_calculate_chksum(){ u16 idx, xsum_index, checksum = 0; // eeprom size is initialized to zero if (!private_data.eeprom_size) private_data.eeprom_size = e100_eeprom_size(); xsum_index = private_data.eeprom_size - 1; for (idx = 0; idx < xsum_index; idx++) checksum += e100_eeprom_read( idx); checksum = EEPROM_CHECKSUM - checksum; return checksum;}//----------------------------------------------------------------------------------------// Procedure: e100_eeprom_write_word//// Description: This routine writes a word to a specific EEPROM location without.// taking EEPROM semaphore and updating checksum. // Use e100_eeprom_write_block for the EEPROM update// Arguments: reg - The EEPROM word that we are going to write to.// data - The data (word) that we are going to write to the EEPROM.//----------------------------------------------------------------------------------------static voide100_eeprom_write_word( u16 reg, u16 data){ u16 x; u16 bits; bits = eeprom_address_size(private_data.eeprom_size); /* select EEPROM, mask off ASIC and reset bits, set EECS */ x = readw(&CSR_EEPROM_CONTROL_FIELD()); x &= ~(EEDI | EEDO | EESK); writew(x, &CSR_EEPROM_CONTROL_FIELD()); readw(&(private_data.scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME); x |= EECS; writew(x, &CSR_EEPROM_CONTROL_FIELD()); shift_out_bits( EEPROM_EWEN_OPCODE, 5); shift_out_bits( reg, (u16) (bits - 2)); if (!eeprom_wait_cmd_done()) return; /* write the new word to the EEPROM & send the write opcode the EEPORM */ shift_out_bits( EEPROM_WRITE_OPCODE, 3); /* select which word in the EEPROM that we are writing to */ shift_out_bits( reg, bits); /* write the data to the selected EEPROM word */ shift_out_bits( data, 16); if (!eeprom_wait_cmd_done()) return; shift_out_bits( EEPROM_EWDS_OPCODE, 5); shift_out_bits( reg, (u16) (bits - 2)); if (!eeprom_wait_cmd_done()) return; e100_eeprom_cleanup();}//----------------------------------------------------------------------------------------// Procedure: e100_eeprom_write_block//// Description: This routine writes a block of words starting from specified EEPROM // location and updates checksum// Arguments: reg - The EEPROM word that we are going to write to.// data - The data (word) that we are going to write to the EEPROM.//----------------------------------------------------------------------------------------voide100_eeprom_write_block( u16 start, u16 *data, u16 size){ u16 checksum; u16 i; if (!private_data.eeprom_size) private_data.eeprom_size = e100_eeprom_size(); // Set EEPROM semaphore. if (private_data.rev_id >= D102_REV_ID) { if (!eeprom_set_semaphore()) return; } for (i = 0; i < size; i++) { e100_eeprom_write_word( start + i, data[i]); } //Update checksum checksum = e100_eeprom_calculate_chksum(); e100_eeprom_write_word( (private_data.eeprom_size - 1), checksum); // Clear EEPROM Semaphore. if (private_data.rev_id >= D102_REV_ID) { eeprom_reset_semaphore(); }}//----------------------------------------------------------------------------------------// Procedure: eeprom_wait_cmd_done//// Description: This routine waits for the the EEPROM to finish its command. // Specifically, it waits for EEDO (data out) to go high.// Returns: true - If the command finished// false - If the command never finished (EEDO stayed low)//----------------------------------------------------------------------------------------static u16eeprom_wait_cmd_done(){ u16 x; unsigned long expiration_time = jiffies + HZ / 100 + 1; eeprom_stand_by(); do { rmb(); x = readw(&CSR_EEPROM_CONTROL_FIELD()); if (x & EEDO) return true; if (time_before(jiffies, expiration_time)) yield(); else return false; } while (true);}//----------------------------------------------------------------------------------------// Procedure: eeprom_stand_by//// Description: This routine lowers the EEPROM chip select (EECS) for a few microseconds.//----------------------------------------------------------------------------------------static voideeprom_stand_by(){ u16 x; x = readw(&CSR_EEPROM_CONTROL_FIELD()); x &= ~(EECS | EESK); writew(x, &CSR_EEPROM_CONTROL_FIELD()); readw(&(private_data.scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME); x |= EECS; writew(x, &CSR_EEPROM_CONTROL_FIELD()); readw(&(private_data.scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -