//---------------------------------------------------------------------------------------- // Procedure: e100_eeprom_size // // Description: This routine determines the size of the EEPROM. This value should be // checked for validity - ie. is it too big or too small. The size returned // is then passed to the read/write functions. // // Returns: // Size of the eeprom, or zero if an error occured //---------------------------------------------------------------------------------------- u16 e100_eeprom_size(struct e100_private *adapter) { u16 x, size = 1; // must be one to accumulate a product // if we've already stored this data, read from memory if (adapter->eeprom_size) { return adapter->eeprom_size; } // otherwise, read from the eeprom // Set EEPROM semaphore. if (adapter->rev_id >= D102_REV_ID) { if (!eeprom_set_semaphore(adapter)) return 0; } // enable the eeprom by setting EECS. x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); x &= ~(EEDI | EEDO | EESK); x |= EECS; writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); // write the read opcode shift_out_bits(adapter, EEPROM_READ_OPCODE, 3); // experiment to discover the size of the eeprom. request register zero // and wait for the eeprom to tell us it has accepted the entire address. x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); do { size *= 2; // each bit of address doubles eeprom size x |= EEDO; // set bit to detect "dummy zero" x &= ~EEDI; // address consists of all zeros writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); udelay(EEPROM_STALL_TIME); raise_clock(adapter, &x); lower_clock(adapter, &x); // check for "dummy zero" x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); if (size > EEPROM_MAX_WORD_SIZE) { size = 0; break; } } while (x & EEDO); // read in the value requested (void) shift_in_bits(adapter); e100_eeprom_cleanup(adapter); // Clear EEPROM Semaphore. if (adapter->rev_id >= D102_REV_ID) { eeprom_reset_semaphore(adapter); } return size; }
u16 e100_eeprom_read(struct e100_private *adapter, u16 reg) { u16 x, data, bits; // Set EEPROM semaphore. if (adapter->rev_id >= D102_REV_ID) { if (!eeprom_set_semaphore(adapter)) return 0; } // eeprom size is initialized to zero if (!adapter->eeprom_size) adapter->eeprom_size = e100_eeprom_size(adapter); bits = eeprom_address_size(adapter->eeprom_size); // select EEPROM, reset bits, set EECS x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); x &= ~(EEDI | EEDO | EESK); x |= EECS; writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); // write the read opcode and register number in that order // The opcode is 3bits in length, reg is 'bits' bits long shift_out_bits(adapter, EEPROM_READ_OPCODE, 3); shift_out_bits(adapter, reg, bits); // Now read the data (16 bits) in from the selected EEPROM word data = shift_in_bits(adapter); e100_eeprom_cleanup(adapter); // Clear EEPROM Semaphore. if (adapter->rev_id >= D102_REV_ID) { eeprom_reset_semaphore(adapter); } return data; }
u16 r8712_eeprom_read16(struct _adapter *padapter, u16 reg) /*ReadEEprom*/ { u16 x; u16 data = 0; u8 tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new; tmp8_ori = r8712_read8(padapter, 0x102502f1); tmp8_new = tmp8_ori & 0xf7; if (tmp8_ori != tmp8_new) r8712_write8(padapter, 0x102502f1, tmp8_new); tmp8_clk_ori = r8712_read8(padapter, 0x10250003); tmp8_clk_new = tmp8_clk_ori | 0x20; if (tmp8_clk_new != tmp8_clk_ori) r8712_write8(padapter, 0x10250003, tmp8_clk_new); if (padapter->bSurpriseRemoved == true) goto out; /* select EEPROM, reset bits, set _EECS */ x = r8712_read8(padapter, EE_9346CR); if (padapter->bSurpriseRemoved == true) goto out; x &= ~(_EEDI | _EEDO | _EESK | _EEM0); x |= _EEM1 | _EECS; r8712_write8(padapter, EE_9346CR, (unsigned char)x); /* write the read opcode and register number in that order * The opcode is 3bits in length, reg is 6 bits long */ shift_out_bits(padapter, EEPROM_READ_OPCODE, 3); shift_out_bits(padapter, reg, padapter->EepromAddressSize); /* Now read the data (16 bits) in from the selected EEPROM word */ data = shift_in_bits(padapter); eeprom_clean(padapter); out: if (tmp8_clk_new != tmp8_clk_ori) r8712_write8(padapter, 0x10250003, tmp8_clk_ori); if (tmp8_new != tmp8_ori) r8712_write8(padapter, 0x102502f1, tmp8_ori); return data; }
void r8712_eeprom_write16(struct _adapter *padapter, u16 reg, u16 data) { u8 x; u8 tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new; tmp8_ori = r8712_read8(padapter, 0x102502f1); tmp8_new = tmp8_ori & 0xf7; if (tmp8_ori != tmp8_new) r8712_write8(padapter, 0x102502f1, tmp8_new); tmp8_clk_ori = r8712_read8(padapter, 0x10250003); tmp8_clk_new = tmp8_clk_ori | 0x20; if (tmp8_clk_new != tmp8_clk_ori) r8712_write8(padapter, 0x10250003, tmp8_clk_new); x = r8712_read8(padapter, EE_9346CR); x &= ~(_EEDI | _EEDO | _EESK | _EEM0); x |= _EEM1 | _EECS; r8712_write8(padapter, EE_9346CR, x); shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5); if (padapter->EepromAddressSize == 8) /*CF+ and SDIO*/ shift_out_bits(padapter, 0, 6); else /* USB */ shift_out_bits(padapter, 0, 4); standby(padapter); /* Erase this particular word. Write the erase opcode and register * number in that order. The opcode is 3bits in length; reg is 6 * bits long. */ standby(padapter); /* write the new word to the EEPROM * send the write opcode the EEPORM */ shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3); /* select which word in the EEPROM that we are writing to. */ shift_out_bits(padapter, reg, padapter->EepromAddressSize); /* write the data to the selected EEPROM word. */ shift_out_bits(padapter, data, 16); if (wait_eeprom_cmd_done(padapter)) { standby(padapter); shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5); shift_out_bits(padapter, reg, 4); eeprom_clean(padapter); } if (tmp8_clk_new != tmp8_clk_ori) r8712_write8(padapter, 0x10250003, tmp8_clk_ori); if (tmp8_new != tmp8_ori) r8712_write8(padapter, 0x102502f1, tmp8_ori); }
//---------------------------------------------------------------------------------------- // 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 void e100_eeprom_write_word(struct e100_private *adapter, u16 reg, u16 data) { u16 x; u16 bits; bits = eeprom_address_size(adapter->eeprom_size); /* select EEPROM, mask off ASIC and reset bits, set EECS */ x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); x &= ~(EEDI | EEDO | EESK); writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); readw(&(adapter->scb->scb_status)); /* flush command to card */ udelay(EEPROM_STALL_TIME); x |= EECS; writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); shift_out_bits(adapter, EEPROM_EWEN_OPCODE, 5); shift_out_bits(adapter, reg, (u16) (bits - 2)); if (!eeprom_wait_cmd_done(adapter)) return; /* write the new word to the EEPROM & send the write opcode the EEPORM */ shift_out_bits(adapter, EEPROM_WRITE_OPCODE, 3); /* select which word in the EEPROM that we are writing to */ shift_out_bits(adapter, reg, bits); /* write the data to the selected EEPROM word */ shift_out_bits(adapter, data, 16); if (!eeprom_wait_cmd_done(adapter)) return; shift_out_bits(adapter, EEPROM_EWDS_OPCODE, 5); shift_out_bits(adapter, reg, (u16) (bits - 2)); if (!eeprom_wait_cmd_done(adapter)) return; e100_eeprom_cleanup(adapter); }