/*
 * Below is portion of IBA7220-specific bringup_serdes() that actually
 * deals with registers and memory within the SerDes itself.
 * Post IB uC code version 1.32.17, was_reset being 1 is not really
 * informative, so we double-check.
 */
int qib_sd7220_init(struct qib_devdata *dd)
{
	const struct firmware *fw;
	int ret = 1; /* default to failure */
	int first_reset, was_reset;

	/* SERDES MPU reset recorded in D0 */
	was_reset = (qib_read_kreg64(dd, kr_ibserdesctrl) & 1);
	if (!was_reset) {
		/* entered with reset not asserted, we need to do it */
		qib_ibsd_reset(dd, 1);
		qib_sd_trimdone_monitor(dd, "Driver-reload");
	}

	ret = request_firmware(&fw, SD7220_FW_NAME, &dd->pcidev->dev);
	if (ret)
		goto done;

	/* Substitute our deduced value for was_reset */
	ret = qib_ibsd_ucode_loaded(dd->pport, fw);
	if (ret < 0)
		goto bail;

	first_reset = !ret; /* First reset if IBSD uCode not yet loaded */
	/*
	 * Alter some regs per vendor latest doc, reset-defaults
	 * are not right for IB.
	 */
	ret = qib_sd_early(dd);
	if (ret < 0) {
		qib_dev_err(dd, "Failed to set IB SERDES early defaults\n");
		goto bail;
	}
	/*
	 * Set DAC manual trim IB.
	 * We only do this once after chip has been reset (usually
	 * same as once per system boot).
	 */
	if (first_reset) {
		ret = qib_sd_dactrim(dd);
		if (ret < 0) {
			qib_dev_err(dd, "Failed IB SERDES DAC trim\n");
			goto bail;
		}
	}
	/*
	 * Set various registers (DDS and RXEQ) that will be
	 * controlled by IBC (in 1.2 mode) to reasonable preset values
	 * Calling the "internal" version avoids the "check for needed"
	 * and "trimdone monitor" that might be counter-productive.
	 */
	ret = qib_internal_presets(dd);
	if (ret < 0) {
		qib_dev_err(dd, "Failed to set IB SERDES presets\n");
		goto bail;
	}
	ret = qib_sd_trimself(dd, 0x80);
	if (ret < 0) {
		qib_dev_err(dd, "Failed to set IB SERDES TRIMSELF\n");
		goto bail;
	}

	/* Load image, then try to verify */
	ret = 0;        /* Assume success */
	if (first_reset) {
		int vfy;
		int trim_done;

		ret = qib_sd7220_ib_load(dd, fw);
		if (ret < 0) {
			qib_dev_err(dd, "Failed to load IB SERDES image\n");
			goto bail;
		} else {
			/* Loaded image, try to verify */
			vfy = qib_sd7220_ib_vfy(dd, fw);
			if (vfy != ret) {
				qib_dev_err(dd, "SERDES PRAM VFY failed\n");
				goto bail;
			} /* end if verified */
		} /* end if loaded */

		/*
		 * Loaded and verified. Almost good...
		 * hold "success" in ret
		 */
		ret = 0;
		/*
		 * Prev steps all worked, continue bringup
		 * De-assert RESET to uC, only in first reset, to allow
		 * trimming.
		 *
		 * Since our default setup sets START_EQ1 to
		 * PRESET, we need to clear that for this very first run.
		 */
		ret = ibsd_mod_allchnls(dd, START_EQ1(0), 0, 0x38);
		if (ret < 0) {
			qib_dev_err(dd, "Failed clearing START_EQ1\n");
			goto bail;
		}

		qib_ibsd_reset(dd, 0);
		/*
		 * If this is not the first reset, trimdone should be set
		 * already. We may need to check about this.
		 */
		trim_done = qib_sd_trimdone_poll(dd);
		/*
		 * Whether or not trimdone succeeded, we need to put the
		 * uC back into reset to avoid a possible fight with the
		 * IBC state-machine.
		 */
		qib_ibsd_reset(dd, 1);

		if (!trim_done) {
			qib_dev_err(dd, "No TRIMDONE seen\n");
			goto bail;
		}
		/*
		 * DEBUG: check each time we reset if trimdone bits have
		 * gotten cleared, and re-set them.
		 */
		qib_sd_trimdone_monitor(dd, "First-reset");
		/* Remember so we do not re-do the load, dactrim, etc. */
		dd->cspec->serdes_first_init_done = 1;
	}
	/*
	 * setup for channel training and load values for
	 * RxEq and DDS in tables used by IBC in IB1.2 mode
	 */
	ret = 0;
	if (qib_sd_setvals(dd) >= 0)
		goto done;
bail:
	ret = 1;
done:
	/* start relock timer regardless, but start at 1 second */
	set_7220_relock_poll(dd, -1);

	release_firmware(fw);
	return ret;
}
int qib_sd7220_init(struct qib_devdata *dd)
{
	const struct firmware *fw;
	int ret = 1; 
	int first_reset, was_reset;

	
	was_reset = (qib_read_kreg64(dd, kr_ibserdesctrl) & 1);
	if (!was_reset) {
		
		qib_ibsd_reset(dd, 1);
		qib_sd_trimdone_monitor(dd, "Driver-reload");
	}

	ret = request_firmware(&fw, SD7220_FW_NAME, &dd->pcidev->dev);
	if (ret) {
		qib_dev_err(dd, "Failed to load IB SERDES image\n");
		goto done;
	}

	
	ret = qib_ibsd_ucode_loaded(dd->pport, fw);
	if (ret < 0)
		goto bail;

	first_reset = !ret; 
	ret = qib_sd_early(dd);
	if (ret < 0) {
		qib_dev_err(dd, "Failed to set IB SERDES early defaults\n");
		goto bail;
	}
	if (first_reset) {
		ret = qib_sd_dactrim(dd);
		if (ret < 0) {
			qib_dev_err(dd, "Failed IB SERDES DAC trim\n");
			goto bail;
		}
	}
	ret = qib_internal_presets(dd);
	if (ret < 0) {
		qib_dev_err(dd, "Failed to set IB SERDES presets\n");
		goto bail;
	}
	ret = qib_sd_trimself(dd, 0x80);
	if (ret < 0) {
		qib_dev_err(dd, "Failed to set IB SERDES TRIMSELF\n");
		goto bail;
	}

	
	ret = 0;        
	if (first_reset) {
		int vfy;
		int trim_done;

		ret = qib_sd7220_ib_load(dd, fw);
		if (ret < 0) {
			qib_dev_err(dd, "Failed to load IB SERDES image\n");
			goto bail;
		} else {
			
			vfy = qib_sd7220_ib_vfy(dd, fw);
			if (vfy != ret) {
				qib_dev_err(dd, "SERDES PRAM VFY failed\n");
				goto bail;
			} 
		} 

		ret = 0;
		ret = ibsd_mod_allchnls(dd, START_EQ1(0), 0, 0x38);
		if (ret < 0) {
			qib_dev_err(dd, "Failed clearing START_EQ1\n");
			goto bail;
		}

		qib_ibsd_reset(dd, 0);
		trim_done = qib_sd_trimdone_poll(dd);
		qib_ibsd_reset(dd, 1);

		if (!trim_done) {
			qib_dev_err(dd, "No TRIMDONE seen\n");
			goto bail;
		}
		qib_sd_trimdone_monitor(dd, "First-reset");
		
		dd->cspec->serdes_first_init_done = 1;
	}
	ret = 0;
	if (qib_sd_setvals(dd) >= 0)
		goto done;
bail:
	ret = 1;
done:
	
	set_7220_relock_poll(dd, -1);

	release_firmware(fw);
	return ret;
}