/** * 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; }
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; }
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; }