void imx_dump_clocks(void)
{
	printf("mpll:    %10u kHz\n", imx_get_mpllclk() / 1000);
	printf("arm:     %10u kHz\n", imx_get_armclk() / 1000);
	printf("ioclk0:  %10u kHz\n", imx_get_ioclk(0) / 1000);
	printf("ioclk1:  %10u kHz\n", imx_get_ioclk(1) / 1000);
	printf("emiclk:  %10u kHz\n", imx_get_emiclk() / 1000);
	printf("hclk:    %10u kHz\n", imx_get_hclk() / 1000);
	printf("xclk:    %10u kHz\n", imx_get_xclk() / 1000);
	printf("ssp0:    %10u kHz\n", imx_get_sspclk(0) / 1000);
	printf("ssp1:    %10u kHz\n", imx_get_sspclk(1) / 1000);
	printf("ssp2:    %10u kHz\n", imx_get_sspclk(2) / 1000);
	printf("ssp3:    %10u kHz\n", imx_get_sspclk(3) / 1000);
}
unsigned imx_set_hclk(unsigned nc)
{
	unsigned root_rate = imx_get_armclk();
	unsigned reg, div;

	div = DIV_ROUND_UP(root_rate, nc);
	if ((div == 0) || (div >= 32))
		return 0;

	if ((root_rate < nc) && (root_rate == 64000000))
		div = 3;

	reg = readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & ~0x3f;
	writel(reg | div, IMX_CCM_BASE + HW_CLKCTRL_HBUS);

	while (readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & (1 << 31))
		;

	return imx_get_hclk();
}
unsigned imx_get_fecclk(void)
{
	return imx_get_hclk();
}
Exemple #4
0
static ssize_t mxs_ocotp_cdev_write(struct cdev *cdev, const void *buf, size_t count,
		loff_t offset, ulong flags)
{
	struct ocotp_priv *priv = cdev->priv;
	void __iomem *base = priv->base;
	const char *write_param;
	unsigned int write_enabled = 0;
	unsigned long old_hclk, aligned_offset;
	int old_vddio, num_words, num_bytes, i, ret = 0;
	u8 *work_buf;
	u32 reg;

	write_param = dev_get_param(cdev->dev, "permanent_write_enable");
	if (write_param)
		write_enabled = simple_strtoul(write_param, NULL, 0);

	if (!write_param || !write_enabled)
		return -EPERM;

	/* we can only work on u32, so calc some helpers */
	aligned_offset = offset & ~3UL;
	num_words = DIV_ROUND_UP(offset - aligned_offset + count, 4);
	num_bytes = num_words << 2;

	/* read in all words which will be modified */
	work_buf = xmalloc(num_bytes);

	i = mxs_ocotp_cdev_read(cdev, work_buf, num_bytes, aligned_offset, 0);
	if (i != num_bytes) {
		ret = -ENXIO;
		goto free_mem;
	}

	/* modify read words with to be written data */
	for (i = 0; i < count; i++)
		work_buf[offset - aligned_offset + i] |= ((u8 *)buf)[i];

	/* prepare system for OTP write */
	old_hclk = imx_get_hclk();
	old_vddio = imx_get_vddio();

	imx_set_hclk(24000000);
	imx_set_vddio(2800000);

	writel(OCOTP_CTRL_RD_BANK_OPEN, base + OCOTP_CTRL + BIT_CLR);

	if (mxs_ocotp_wait_busy(priv)) {
		ret = -ETIMEDOUT;
		goto restore_system;
	}

	/* write word for word via data register */
	for (i = 0; i < num_words; i++) {
		reg = readl(base + OCOTP_CTRL) & ~OCOTP_CTRL_ADDR_MASK;
		reg |= OCOTP_CTRL_WR_UNLOCK | ((aligned_offset >> 2) + i);
		writel(reg, base + OCOTP_CTRL);

		writel(((u32 *)work_buf)[i], base + OCOTP_DATA);

		if (mxs_ocotp_wait_busy(priv)) {
			ret = -ETIMEDOUT;
			goto restore_system;
		}

		mdelay(2);
	}

restore_system:
	imx_set_vddio(old_vddio);
	imx_set_hclk(old_hclk);
free_mem:
	free(work_buf);

	return ret;
}