static int idtcm_load_firmware()

in ptp_clockmatrix.c [1233:1305]


static int idtcm_load_firmware(struct idtcm *idtcm,
			       struct device *dev)
{
	u16 scratch = IDTCM_FW_REG(idtcm->fw_ver, V520, SCRATCH);
	char fname[128] = FW_FILENAME;
	const struct firmware *fw;
	struct idtcm_fwrc *rec;
	u32 regaddr;
	int err;
	s32 len;
	u8 val;
	u8 loaddr;

	if (firmware) /* module parameter */
		snprintf(fname, sizeof(fname), "%s", firmware);

	dev_info(idtcm->dev, "requesting firmware '%s'", fname);

	err = request_firmware(&fw, fname, dev);
	if (err) {
		dev_err(idtcm->dev,
			"Failed at line %d in %s!", __LINE__, __func__);
		return err;
	}

	dev_dbg(idtcm->dev, "firmware size %zu bytes", fw->size);

	rec = (struct idtcm_fwrc *) fw->data;

	if (contains_full_configuration(idtcm, fw))
		idtcm_state_machine_reset(idtcm);

	for (len = fw->size; len > 0; len -= sizeof(*rec)) {
		if (rec->reserved) {
			dev_err(idtcm->dev,
				"bad firmware, reserved field non-zero");
			err = -EINVAL;
		} else {
			regaddr = rec->hiaddr << 8;
			regaddr |= rec->loaddr;

			val = rec->value;
			loaddr = rec->loaddr;

			rec++;

			err = check_and_set_masks(idtcm, regaddr, val);
		}

		if (err != -EINVAL) {
			err = 0;

			/* Top (status registers) and bottom are read-only */
			if (regaddr < GPIO_USER_CONTROL || regaddr >= scratch)
				continue;

			/* Page size 128, last 4 bytes of page skipped */
			if ((loaddr > 0x7b && loaddr <= 0x7f) || loaddr > 0xfb)
				continue;

			err = idtcm_write(idtcm, regaddr, 0, &val, sizeof(val));
		}

		if (err)
			goto out;
	}

	display_pll_and_masks(idtcm);

out:
	release_firmware(fw);
	return err;
}