Esempio n. 1
0
/*
 * blow one u32 to indexed fuse
 */
int imx_otp_blow_one_u32(u32 index, u32 data, u32 *pfused_value)
{
	u32 ctrl_reg = 0;
	int ret = 0;

	if (otp_clk_enable()) {
		ret = -1;
		goto exit_nop;
	}

	if (otp_blow_prep()) {
		ret = -1;
		printf("ERROR: blow preparation failed\n");
		goto exit_cleanup;
	}
	if (fuse_blow_addr(index, data)) {
		ret = -1;
		printf("ERROR: blow fuse failed\n");
		goto exit_cleanup;
	}
	if (otp_blow_post()) {
		ret = -1;
		printf("ERROR: blow post operation failed\n");
		goto exit_cleanup;
	}

	ctrl_reg = readl(IMX_OTP_BASE + HW_OCOTP_CTRL);
	if (ctrl_reg & BM_OCOTP_CTRL_ERROR) {
		ret = -1;
		goto exit_cleanup;
	}

	if (imx_otp_read_one_u32(index, pfused_value)) {
		ret = -1;
		goto exit_cleanup;
	}

exit_cleanup:
	otp_clk_disable();
exit_nop:
	return ret;
}
Esempio n. 2
0
int do_imxotp(cmd_tbl_t *cmd_tbl, int flag, int argc, char *  const argv[])
{
	u32 addr, value_read;
#ifdef IMX_OTPWRITE_ENABLED
	u32 fused_value, value_to_fuse;
	int force_to_fuse = 0;
#endif

	if (argc < 3) {
usage:
		cmd_usage(cmd_tbl);
		return 1;
	}

	if (!strcmp(argv[1], "read")) {
		switch (argc) {
		case 3:
			addr = simple_strtoul(argv[2], NULL, 16);
			if ((addr == 0) &&
				validate_zero_from_simple_strtoul(argv[2]))
				goto usage;
			break;
		default:
			goto usage;
		}
		printf("Reading fuse at index 0x%X\n", addr);
		if (imx_otp_read_one_u32(addr, &value_read))
			return -1;
		printf("Fuse at index 0x%X has the value: 0x%08X\n", addr, value_read);
#ifdef IMX_OTPWRITE_ENABLED
	} else if (!strcmp(argv[1], "blow")) {
		if (argc < 4 || argc > 5)
			goto usage;

		if (!strcmp(argv[2], "--force")) {
			force_to_fuse = 1;
			addr = simple_strtoul(argv[3], NULL, 16);
			if ((addr == 0)
				  && validate_zero_from_simple_strtoul(argv[3]))
				goto usage;
			value_to_fuse = simple_strtoul(argv[4], NULL, 16);
			if ((value_to_fuse == 0)
				  && validate_zero_from_simple_strtoul(argv[4]))
				goto usage;
		} else {
			addr = simple_strtoul(argv[2], NULL, 16);
			if ((addr == 0)
				  && validate_zero_from_simple_strtoul(argv[2]))
				goto usage;
			value_to_fuse = simple_strtoul(argv[3], NULL, 16);
			if ((value_to_fuse == 0)
				  && validate_zero_from_simple_strtoul(argv[3]))
				goto usage;
		}

		/* show the current value of specified address (fuse index) */
		if (imx_otp_read_one_u32(addr, &value_read))
			return -1;
		printf("Current fuse at index 0x%X has the value: 0x%08X\n",
				addr, value_read);

		if ((value_to_fuse & value_read) == value_to_fuse)
			printf("!! Fuse blow skipped:"
					" the bits have been already set.\n");
		else if (force_to_fuse) {
			printf("Blowing fuse at index 0x%X, value: 0x%08X\n",
					addr, value_to_fuse);
			if (imx_otp_blow_one_u32(addr,
					value_to_fuse, &fused_value)) {
				printf("ERROR: failed to blow fuse"
					  " at 0x%X with value of 0x%08X\n",
						addr, value_to_fuse);
			} else {
				printf("Operation %s fuse"
					  " at index 0x%X value: 0x%08X\n",
					((fused_value & value_to_fuse) ==
					value_to_fuse) ? "succeeded" : "failed",
					addr, fused_value);
			}
		} else {
			printf("!! Fuse blow aborted."
				" if you do want to blow it."
				" Please use the command:\n"
				"%s blow --force %X %X\n",
				argv[0], addr, value_to_fuse);
		}
#endif
	} else
		goto usage;

	return 0;
}