Esempio n. 1
0
/**
 * zynq_pm_remap_ocm() - Remap OCM
 * Returns a pointer to the mapped memory or NULL.
 *
 * Remap the OCM.
 */
static void __iomem *zynq_pm_remap_ocm(void)
{
	struct device_node *np;
	const char *comp = "xlnx,zynq-ocmc-1.0";
	void __iomem *base = NULL;

	np = of_find_compatible_node(NULL, NULL, comp);
	if (np) {
		struct device *dev;
		unsigned long pool_addr;
		unsigned long pool_addr_virt;
		struct gen_pool *pool;

		of_node_put(np);

		dev = &(of_find_device_by_node(np)->dev);

		/* Get OCM pool from device tree or platform data */
		pool = dev_get_gen_pool(dev);
		if (!pool) {
			pr_warn("%s: OCM pool is not available\n", __func__);
			return NULL;
		}

		pool_addr_virt = gen_pool_alloc(pool, zynq_sys_suspend_sz);
		if (!pool_addr_virt) {
			pr_warn("%s: Can't get OCM poll\n", __func__);
			return NULL;
		}
		pool_addr = gen_pool_virt_to_phys(pool, pool_addr_virt);
		if (!pool_addr) {
			pr_warn("%s: Can't get physical address of OCM pool\n",
				__func__);
			return NULL;
		}
		base = __arm_ioremap(pool_addr, zynq_sys_suspend_sz,
				     MT_MEMORY_RWX);
		if (!base) {
			pr_warn("%s: IOremap OCM pool failed\n", __func__);
			return NULL;
		}
		pr_debug("%s: Remap OCM %s from %lx to %lx\n", __func__, comp,
			 pool_addr_virt, (unsigned long)base);
	} else {
		pr_warn("%s: no compatible node found for '%s'\n", __func__,
				comp);
	}

	return base;
}
Esempio n. 2
0
int init_mmdc_lpddr2_settings(struct platform_device *busfreq_pdev)
{
	struct platform_device *ocram_dev;
	unsigned int iram_paddr;
	struct device_node *node;
	struct gen_pool *iram_pool;

	busfreq_dev = &busfreq_pdev->dev;
	node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-mmdc");
	if (!node) {
		printk(KERN_ERR "failed to find imx6sl-mmdc device tree data!\n");
		return -EINVAL;
	}
	mmdc_base = of_iomap(node, 0);
	WARN(!mmdc_base, "unable to map mmdc registers\n");

	node = NULL;
	node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-ccm");
	if (!node) {
		printk(KERN_ERR "failed to find imx6sl-ccm device tree data!\n");
		return -EINVAL;
	}
	ccm_base = of_iomap(node, 0);
	WARN(!ccm_base, "unable to map ccm registers\n");

	node = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
	if (!node) {
		printk(KERN_ERR "failed to find imx6sl-pl310-cache device tree data!\n");
		return -EINVAL;
	}
	l2_base = of_iomap(node, 0);
	WARN(!l2_base, "unable to map PL310 registers\n");

	node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-anatop");
	if (!node) {
		printk(KERN_ERR "failed to find imx6sl-pl310-cache device tree data!\n");
		return -EINVAL;
	}
	anatop_base = of_iomap(node, 0);
	WARN(!anatop_base, "unable to map anatop registers\n");

	node = NULL;
	node = of_find_compatible_node(NULL, NULL, "mmio-sram");
	if (!node) {
		dev_err(busfreq_dev, "%s: failed to find ocram node\n",
			__func__);
		return -EINVAL;
	}

	ocram_dev = of_find_device_by_node(node);
	if (!ocram_dev) {
		dev_err(busfreq_dev, "failed to find ocram device!\n");
		return -EINVAL;
	}

	iram_pool = dev_get_gen_pool(&ocram_dev->dev);
	if (!iram_pool) {
		dev_err(busfreq_dev, "iram pool unavailable!\n");
		return -EINVAL;
	}

	reg_addrs[0] = (unsigned long)anatop_base;
	reg_addrs[1] = (unsigned long)ccm_base;
	reg_addrs[2] = (unsigned long)mmdc_base;
	reg_addrs[3] = (unsigned long)l2_base;

	ddr_freq_change_iram_base = (void *)gen_pool_alloc(iram_pool,
						LPDDR2_FREQ_CHANGE_SIZE);
	if (!ddr_freq_change_iram_base) {
		dev_err(busfreq_dev,
			"Cannot alloc iram for ddr freq change code!\n");
		return -ENOMEM;
	}

	iram_paddr = gen_pool_virt_to_phys(iram_pool,
				(unsigned long)ddr_freq_change_iram_base);
	/*
	 * Need to remap the area here since we want
	 * the memory region to be executable.
	 */
	ddr_freq_change_iram_base = __arm_ioremap(iram_paddr,
						LPDDR2_FREQ_CHANGE_SIZE,
						MT_MEMORY_NONCACHED);
	mx6_change_lpddr2_freq = (void *)fncpy(ddr_freq_change_iram_base,
		&mx6_lpddr2_freq_change, LPDDR2_FREQ_CHANGE_SIZE);

	curr_ddr_rate = ddr_normal_rate;

	return 0;
}
Esempio n. 3
0
int init_mmdc_settings(struct platform_device *busfreq_pdev)
{
	struct device *dev = &busfreq_pdev->dev;
	struct platform_device *ocram_dev;
	unsigned int iram_paddr;
	int i, err;
	u32 cpu;
	struct device_node *node;
	struct gen_pool *iram_pool;

	node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mmdc-combine");
	if (!node) {
		printk(KERN_ERR "failed to find imx6q-mmdc device tree data!\n");
		return -EINVAL;
	}
	mmdc_base = of_iomap(node, 0);
	WARN(!mmdc_base, "unable to map mmdc registers\n");

	node = NULL;
	if (cpu_is_imx6q())
		node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-iomuxc");
	if (cpu_is_imx6dl())
		node = of_find_compatible_node(NULL, NULL,
			"fsl,imx6dl-iomuxc");
	if (!node) {
		printk(KERN_ERR "failed to find imx6q-iomux device tree data!\n");
		return -EINVAL;
	}
	iomux_base = of_iomap(node, 0);
	WARN(!iomux_base, "unable to map iomux registers\n");

	node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ccm");
	if (!node) {
		printk(KERN_ERR "failed to find imx6q-ccm device tree data!\n");
		return -EINVAL;
	}
	ccm_base = of_iomap(node, 0);
	WARN(!mmdc_base, "unable to map mmdc registers\n");

	node = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
	if (!node) {
		printk(KERN_ERR "failed to find imx6q-pl310-cache device tree data!\n");
		return -EINVAL;
	}
	l2_base = of_iomap(node, 0);
	WARN(!mmdc_base, "unable to map mmdc registers\n");

	node = NULL;
	node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic");
	if (!node) {
		printk(KERN_ERR "failed to find imx6q-a9-gic device tree data!\n");
		return -EINVAL;
	}
	gic_dist_base = of_iomap(node, 0);
	WARN(!gic_dist_base, "unable to map gic dist registers\n");

	if (cpu_is_imx6q())
		ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6q) +
			ARRAY_SIZE(ddr3_calibration);
	if (cpu_is_imx6dl())
		ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6dl) +
			ARRAY_SIZE(ddr3_calibration);

	normal_mmdc_settings = kmalloc((ddr_settings_size * 8), GFP_KERNEL);
	if (cpu_is_imx6q()) {
		memcpy(normal_mmdc_settings, ddr3_dll_mx6q,
			sizeof(ddr3_dll_mx6q));
		memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6q)),
			ddr3_calibration, sizeof(ddr3_calibration));
	}
	if (cpu_is_imx6dl()) {
		memcpy(normal_mmdc_settings, ddr3_dll_mx6dl,
			sizeof(ddr3_dll_mx6dl));
		memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6dl)),
			ddr3_calibration, sizeof(ddr3_calibration));
	}
	/* store the original DDR settings at boot. */
	for (i = 0; i < ddr_settings_size; i++) {
		/*
		 * writes via command mode register cannot be read back.
		 * hence hardcode them in the initial static array.
		 * this may require modification on a per customer basis.
		 */
		if (normal_mmdc_settings[i][0] != 0x1C)
			normal_mmdc_settings[i][1] =
				readl_relaxed(mmdc_base
				+ normal_mmdc_settings[i][0]);
	}

	irqs_used = devm_kzalloc(dev, sizeof(u32) * num_present_cpus(),
					GFP_KERNEL);

	for_each_present_cpu(cpu) {
		int irq;

		/*
		 * set up a reserved interrupt to get all
		 * the active cores into a WFE state
		 * before changing the DDR frequency.
		 */
		irq = platform_get_irq(busfreq_pdev, cpu);
		err = request_irq(irq, wait_in_wfe_irq,
			IRQF_PERCPU, "mmdc_1", NULL);
		if (err) {
			dev_err(dev,
				"Busfreq:request_irq failed %d, err = %d\n",
				irq, err);
			return err;
		}
		err = irq_set_affinity(irq, cpumask_of(cpu));
		if (err) {
			dev_err(dev,
				"Busfreq: Cannot set irq affinity irq=%d,\n",
				irq);
			return err;
		}
		irqs_used[cpu] = irq;
	}

	node = NULL;
	node = of_find_compatible_node(NULL, NULL, "mmio-sram");
	if (!node) {
		dev_err(dev, "%s: failed to find ocram node\n",
			__func__);
		return -EINVAL;
	}

	ocram_dev = of_find_device_by_node(node);
	if (!ocram_dev) {
		dev_err(dev, "failed to find ocram device!\n");
		return -EINVAL;
	}

	iram_pool = dev_get_gen_pool(&ocram_dev->dev);
	if (!iram_pool) {
		dev_err(dev, "iram pool unavailable!\n");
		return -EINVAL;
	}

	iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6q);
	iram_iomux_settings = gen_pool_alloc(iram_pool,
						(iomux_settings_size * 8) + 8);
	if (!iram_iomux_settings) {
		dev_err(dev, "unable to alloc iram for IOMUX settings!\n");
		return -ENOMEM;
	}

	/*
	  * Allocate extra space to store the number of entries in the
	  * ddr_settings plus 4 extra regsiter information that needs
	  * to be passed to the frequency change code.
	  * sizeof(iram_ddr_settings) = sizeof(ddr_settings) +
	  *					entries in ddr_settings + 16.
	  * The last 4 enties store the addresses of the registers:
	  * CCM_BASE_ADDR
	  * MMDC_BASE_ADDR
	  * IOMUX_BASE_ADDR
	  * L2X0_BASE_ADDR
	  */
	iram_ddr_settings = gen_pool_alloc(iram_pool,
					(ddr_settings_size * 8) + 8 + 32);
	if (!iram_ddr_settings) {
		dev_err(dev, "unable to alloc iram for ddr settings!\n");
		return -ENOMEM;
	}
	i = ddr_settings_size + 1;
	iram_ddr_settings[i][0] = (unsigned long)mmdc_base;
	iram_ddr_settings[i+1][0] = (unsigned long)ccm_base;
	iram_ddr_settings[i+2][0] = (unsigned long)iomux_base;
	iram_ddr_settings[i+3][0] = (unsigned long)l2_base;

	if (cpu_is_imx6q()) {
		/* store the IOMUX settings at boot. */
		for (i = 0; i < iomux_settings_size; i++) {
			iomux_offsets_mx6q[i][1] =
				readl_relaxed(iomux_base +
					iomux_offsets_mx6q[i][0]);
			iram_iomux_settings[i+1][0] = iomux_offsets_mx6q[i][0];
			iram_iomux_settings[i+1][1] = iomux_offsets_mx6q[i][1];
		}
	}

	if (cpu_is_imx6dl()) {
		for (i = 0; i < iomux_settings_size; i++) {
			iomux_offsets_mx6dl[i][1] =
				readl_relaxed(iomux_base +
					iomux_offsets_mx6dl[i][0]);
			iram_iomux_settings[i+1][0] = iomux_offsets_mx6dl[i][0];
			iram_iomux_settings[i+1][1] = iomux_offsets_mx6dl[i][1];
		}
	}

	ddr_freq_change_iram_base = gen_pool_alloc(iram_pool,
						DDR_FREQ_CHANGE_SIZE);
	if (!ddr_freq_change_iram_base) {
		dev_err(dev, "Cannot alloc iram for ddr freq change code!\n");
		return -ENOMEM;
	}

	iram_paddr = gen_pool_virt_to_phys(iram_pool,
				(unsigned long)ddr_freq_change_iram_base);
	/*
	 * need to remap the area here since we want
	 * the memory region to be executable.
	 */
	ddr_freq_change_iram_base = __arm_ioremap(iram_paddr,
						DDR_FREQ_CHANGE_SIZE,
						MT_MEMORY_RWX_NONCACHED);
	mx6_change_ddr_freq = (void *)fncpy(ddr_freq_change_iram_base,
		&mx6_ddr3_freq_change, DDR_FREQ_CHANGE_SIZE);

	curr_ddr_rate = ddr_normal_rate;

	return 0;
}