host-drivers/base-driver/vca/plx87xx/plx_hw.c
enum plx_eep_retval plx_update_eeprom(struct plx_device *xdev, char *eeprom_data,
				      size_t eeprom_size)
{
	u16 offset;
	u16 verify_value_16;
	u32 verify_value_32;
	u32 value_32;
	enum plx_eep_retval ret;
	u32 eep_3rd_addr_byte_reg;

	ret = eeprom_validate(xdev, eeprom_data, eeprom_size);
	if (ret != PLX_EEP_STATUS_OK)
		return ret;

	mutex_lock(&xdev->mmio_lock);

	eep_3rd_addr_byte_reg = plx_mmio_read(&xdev->mmio, PLX_EEP_ADDRESS_BYTE);

	if (eep_3rd_addr_byte_reg & 0x3)
		plx_mmio_write(&xdev->mmio,
			eep_3rd_addr_byte_reg & (PLX_EEP_3RD_ADDRES_BYTE_RSVD_MASK | PLX_EEP_EXPANSION_ROM_BASE_ADDR_MASK),
			PLX_EEP_ADDRESS_BYTE);

	for (offset = 0; offset < eeprom_size; offset += sizeof(u32))
	{
		// if eeprom data is not dword aligned
		if (eeprom_size - offset == 2) {
			value_32 = *(u16*)(eeprom_data + offset);

			ret = eeprom_write16(xdev, offset, value_32);
			if (ret != PLX_EEP_STATUS_OK) {
				dev_err(&xdev->pdev->dev,
					"%s: failed to write value_32 %08x on offset %08x!\n",
					__func__, value_32, offset);
				goto unlock;
			}

			ret = eeprom_read16(xdev, offset, &verify_value_16);
			if (ret != PLX_EEP_STATUS_OK) {
				dev_err(&xdev->pdev->dev,
					"%s: failed to read value_16 from offset %08x !\n",
					__func__, offset);
				goto unlock;
			}

			if ((u16)value_32 != verify_value_16) {
				dev_err(&xdev->pdev->dev, "value_16 into eeprom (%08x) is "
					"different with value_16 in file (%08x) !\n",
					verify_value_16, value_32);
				ret = PLX_EEP_INTERNAL_ERROR;
				goto unlock;
			}
			break;
		}

		value_32 = *(u32*)(eeprom_data + offset);

		ret = eeprom_write32(xdev, offset, value_32);
		if (ret != PLX_EEP_STATUS_OK) {
			dev_err(&xdev->pdev->dev,
				"%s: failed to write value_32 %08x on offset %08x!\n",
				__func__, value_32, offset);
			goto unlock;
		}

		ret = eeprom_read32(xdev, offset, &verify_value_32);
		if (ret != PLX_EEP_STATUS_OK) {
			dev_err(&xdev->pdev->dev,
				"%s: failed to read value_32 %08x on offset %08x!\n",
				__func__, verify_value_32, offset);
			goto unlock;
		}

		if (value_32 != verify_value_32) {
			dev_err(&xdev->pdev->dev, "value_32 into eeprom (%08x) is "
				"different with value_32 in file (%08x) !\n", verify_value_32, value_32);
			ret = PLX_EEP_INTERNAL_ERROR;
			goto unlock;
		}
	}
unlock:
	mutex_unlock(&xdev->mmio_lock);
	return ret;
}
/*
* plx_update_eeprom - write user provided configuration to EEPROM
*
* @xdev - pointer to plx device
* @eeprom_data  - eeprom content in following layout:
*	4B - header:
*		1B - validation_signature
*		1B - flags
*		2B - configuration_size
*	(2B, 4B) x configuration_size - (register address, register value) pairs
*	4B - CRC
* @eeprom_size - configuration_size passed by user
*
* RETURNS: PLX_EEP_STATUS_OK on success,
*	   PLX_EEP_INTERNAL_ERROR or PLX_EEP_TIMEOUT on failure
*/
write user provided configuration to EEPROM
write user provided configuration to EEPROM
enum plx_eep_retval plx_update_eeprom(struct plx_device *xdev, char *eeprom_data,
				      size_t eeprom_size)
{
	u16 offset;
	u16 verify_value_16;
	u32 verify_value_32;
	u32 value_32;
	enum plx_eep_retval ret;
	u32 eep_3rd_addr_byte_reg;
	ret = eeprom_validate(xdev, eeprom_data, eeprom_size);
	if (ret != PLX_EEP_STATUS_OK)
		return ret;
	mutex_lock(&xdev->mmio_lock);
	eep_3rd_addr_byte_reg = plx_mmio_read(&xdev->mmio, PLX_EEP_ADDRESS_BYTE);
	if (eep_3rd_addr_byte_reg & 0x3)
		plx_mmio_write(&xdev->mmio,
			eep_3rd_addr_byte_reg & (PLX_EEP_3RD_ADDRES_BYTE_RSVD_MASK | PLX_EEP_EXPANSION_ROM_BASE_ADDR_MASK),
			PLX_EEP_ADDRESS_BYTE);
	for (offset = 0; offset < eeprom_size; offset += sizeof(u32))
	{
		if (eeprom_size - offset == 2) {
			value_32 = *(u16*)(eeprom_data + offset);
			ret = eeprom_write16(xdev, offset, value_32);
			if (ret != PLX_EEP_STATUS_OK) {
				dev_err(&xdev->pdev->dev,
					"%s: failed to write value_32 %08x on offset %08x!\n",
					__func__, value_32, offset);
				goto unlock;
			}
			ret = eeprom_read16(xdev, offset, &verify_value_16);
			if (ret != PLX_EEP_STATUS_OK) {
				dev_err(&xdev->pdev->dev,
					"%s: failed to read value_16 from offset %08x !\n",
					__func__, offset);
				goto unlock;
			}
			if ((u16)value_32 != verify_value_16) {
				dev_err(&xdev->pdev->dev, "value_16 into eeprom (%08x) is "
					"different with value_16 in file (%08x) !\n",
					verify_value_16, value_32);
				ret = PLX_EEP_INTERNAL_ERROR;
				goto unlock;
			}
			break;
		}
		value_32 = *(u32*)(eeprom_data + offset);
		ret = eeprom_write32(xdev, offset, value_32);
		if (ret != PLX_EEP_STATUS_OK) {
			dev_err(&xdev->pdev->dev,
				"%s: failed to write value_32 %08x on offset %08x!\n",
				__func__, value_32, offset);
			goto unlock;
		}
		ret = eeprom_read32(xdev, offset, &verify_value_32);
		if (ret != PLX_EEP_STATUS_OK) {
			dev_err(&xdev->pdev->dev,
				"%s: failed to read value_32 %08x on offset %08x!\n",
				__func__, verify_value_32, offset);
			goto unlock;
		}
		if (value_32 != verify_value_32) {
			dev_err(&xdev->pdev->dev, "value_32 into eeprom (%08x) is "
				"different with value_32 in file (%08x) !\n", verify_value_32, value_32);
			ret = PLX_EEP_INTERNAL_ERROR;
			goto unlock;
		}
	}
unlock:
	mutex_unlock(&xdev->mmio_lock);
	return ret;
}
enum plx_eep_retval plx_update_eeprom ( struct plx_device * xdev , char * eeprom_data , size_t eeprom_size ) { u16 offset ; u16 verify_value_16 ; u32 verify_value_32 ; u32 value_32 ; enum plx_eep_retval ret ; u32 eep_3rd_addr_byte_reg ; ret = eeprom_validate ( xdev , eeprom_data , eeprom_size ) ; if ( ret != PLX_EEP_STATUS_OK ) return ret ; mutex_lock ( & xdev -> mmio_lock ) ; eep_3rd_addr_byte_reg = plx_mmio_read ( & xdev -> mmio , PLX_EEP_ADDRESS_BYTE ) ; if ( eep_3rd_addr_byte_reg & 0x3 ) plx_mmio_write ( & xdev -> mmio , eep_3rd_addr_byte_reg & ( PLX_EEP_3RD_ADDRES_BYTE_RSVD_MASK | PLX_EEP_EXPANSION_ROM_BASE_ADDR_MASK ) , PLX_EEP_ADDRESS_BYTE ) ; for ( offset = 0 ; offset < eeprom_size ; offset += sizeof ( u32 ) ) { if ( eeprom_size - offset == 2 ) { value_32 = * ( u16 * ) ( eeprom_data + offset ) ; ret = eeprom_write16 ( xdev , offset , value_32 ) ; if ( ret != PLX_EEP_STATUS_OK ) { dev_err ( & xdev -> pdev -> dev , " \n " , __func__ , value_32 , offset ) ; goto unlock ; } ret = eeprom_read16 ( xdev , offset , & verify_value_16 ) ; if ( ret != PLX_EEP_STATUS_OK ) { dev_err ( & xdev -> pdev -> dev , " \n " , __func__ , offset ) ; goto unlock ; } if ( ( u16 ) value_32 != verify_value_16 ) { dev_err ( & xdev -> pdev -> dev , " " " \n " , verify_value_16 , value_32 ) ; ret = PLX_EEP_INTERNAL_ERROR ; goto unlock ; } break ; } value_32 = * ( u32 * ) ( eeprom_data + offset ) ; ret = eeprom_write32 ( xdev , offset , value_32 ) ; if ( ret != PLX_EEP_STATUS_OK ) { dev_err ( & xdev -> pdev -> dev , " \n " , __func__ , value_32 , offset ) ; goto unlock ; } ret = eeprom_read32 ( xdev , offset , & verify_value_32 ) ; if ( ret != PLX_EEP_STATUS_OK ) { dev_err ( & xdev -> pdev -> dev , " \n " , __func__ , verify_value_32 , offset ) ; goto unlock ; } if ( value_32 != verify_value_32 ) { dev_err ( & xdev -> pdev -> dev , " " " \n " , verify_value_32 , value_32 ) ; ret = PLX_EEP_INTERNAL_ERROR ; goto unlock ; } } unlock : mutex_unlock ( & xdev -> mmio_lock ) ; return ret ; }
plx_update_eeprom - write user provided configuration to EEPROM
plx_update_eeprom - write user provided configuration to EEPROM
// if eeprom data is not dword aligned