static int __init pm_init(void) { scu_base = IO_ADDRESS(SCU_BASE_ADDR); gpc_base = IO_ADDRESS(GPC_BASE_ADDR); src_base = IO_ADDRESS(SRC_BASE_ADDR); gic_dist_base = IO_ADDRESS(IC_DISTRIBUTOR_BASE_ADDR); gic_cpu_base = IO_ADDRESS(IC_INTERFACES_BASE_ADDR); local_twd_base = IO_ADDRESS(LOCAL_TWD_ADDR); anatop_base = IO_ADDRESS(ANATOP_BASE_ADDR); pr_info("Static Power Management for Freescale i.MX6\n"); if (platform_driver_register(&mx6_pm_driver) != 0) { printk(KERN_ERR "mx6_pm_driver register failed\n"); return -ENODEV; } suspend_set_ops(&mx6_suspend_ops); /* Move suspend routine into iRAM */ cpaddr = (unsigned long)iram_alloc(SZ_4K, &iram_paddr); /* Need to remap the area here since we want the memory region to be executable. */ suspend_iram_base = __arm_ioremap(iram_paddr, SZ_4K, MT_MEMORY_NONCACHED); pr_info("cpaddr = %x suspend_iram_base=%x\n", (unsigned int)cpaddr, (unsigned int)suspend_iram_base); /* * Need to run the suspend code from IRAM as the DDR needs * to be put into low power mode manually. */ memcpy((void *)cpaddr, mx6q_suspend, SZ_4K); suspend_in_iram = (void *)suspend_iram_base; cpu_clk = clk_get(NULL, "cpu_clk"); if (IS_ERR(cpu_clk)) { printk(KERN_DEBUG "%s: failed to get cpu_clk\n", __func__); return PTR_ERR(cpu_clk); } printk(KERN_INFO "PM driver module loaded\n"); return 0; }
static int __init pm_init(void) { int ret = 0; scu_base = IO_ADDRESS(SCU_BASE_ADDR); gpc_base = IO_ADDRESS(GPC_BASE_ADDR); src_base = IO_ADDRESS(SRC_BASE_ADDR); gic_dist_base = IO_ADDRESS(IC_DISTRIBUTOR_BASE_ADDR); gic_cpu_base = IO_ADDRESS(IC_INTERFACES_BASE_ADDR); local_twd_base = IO_ADDRESS(LOCAL_TWD_ADDR); anatop_base = IO_ADDRESS(ANATOP_BASE_ADDR); pr_info("Static Power Management for Freescale i.MX6\n"); pr_info("wait mode is %s for i.MX6\n", enable_wait_mode ? "enabled" : "disabled"); if (platform_driver_register(&mx6_pm_driver) != 0) { printk(KERN_ERR "mx6_pm_driver register failed\n"); return -ENODEV; } suspend_set_ops(&mx6_suspend_ops); /* Move suspend routine into iRAM */ cpaddr = (unsigned long)iram_alloc(SZ_8K, &iram_paddr); /* Need to remap the area here since we want the memory region to be executable. */ suspend_iram_base = __arm_ioremap(iram_paddr, SZ_8K, MT_MEMORY_NONCACHED); pr_info("cpaddr = %x suspend_iram_base=%x\n", (unsigned int)cpaddr, (unsigned int)suspend_iram_base); /* * Need to run the suspend code from IRAM as the DDR needs * to be put into low power mode manually. */ memcpy((void *)cpaddr, mx6_suspend, SZ_8K); suspend_in_iram = (void *)suspend_iram_base; cpu_clk = clk_get(NULL, "cpu_clk"); if (IS_ERR(cpu_clk)) { printk(KERN_DEBUG "%s: failed to get cpu_clk\n", __func__); return PTR_ERR(cpu_clk); } axi_clk = clk_get(NULL, "axi_clk"); if (IS_ERR(axi_clk)) { printk(KERN_DEBUG "%s: failed to get axi_clk\n", __func__); return PTR_ERR(axi_clk); } periph_clk = clk_get(NULL, "periph_clk"); if (IS_ERR(periph_clk)) { printk(KERN_DEBUG "%s: failed to get periph_clk\n", __func__); return PTR_ERR(periph_clk); } pll3_usb_otg_main_clk = clk_get(NULL, "pll3_main_clk"); if (IS_ERR(pll3_usb_otg_main_clk)) { printk(KERN_DEBUG "%s: failed to get pll3_main_clk\n", __func__); return PTR_ERR(pll3_usb_otg_main_clk); } vdd3p0_regulator = regulator_get(NULL, "cpu_vdd3p0"); if (IS_ERR(vdd3p0_regulator)) { printk(KERN_ERR "%s: failed to get 3p0 regulator Err: %d\n", __func__, ret); return PTR_ERR(vdd3p0_regulator); } ret = regulator_set_voltage(vdd3p0_regulator, VDD3P0_VOLTAGE, VDD3P0_VOLTAGE); if (ret) { printk(KERN_ERR "%s: failed to set 3p0 regulator voltage Err: %d\n", __func__, ret); } ret = regulator_enable(vdd3p0_regulator); if (ret) { printk(KERN_ERR "%s: failed to enable 3p0 regulator Err: %d\n", __func__, ret); } printk(KERN_INFO "PM driver module loaded\n"); return 0; }
static int __devinit busfreq_probe(struct platform_device *pdev) { u32 err; busfreq_dev = &pdev->dev; pll2_400 = clk_get(NULL, "pll2_pfd_400M"); if (IS_ERR(pll2_400)) { printk(KERN_DEBUG "%s: failed to get pll2_pfd_400M\n", __func__); return PTR_ERR(pll2_400); } pll2_200 = clk_get(NULL, "pll2_200M"); if (IS_ERR(pll2_200)) { printk(KERN_DEBUG "%s: failed to get pll2_200M\n", __func__); return PTR_ERR(pll2_200); } pll2 = clk_get(NULL, "pll2"); if (IS_ERR(pll2)) { printk(KERN_DEBUG "%s: failed to get pll2\n", __func__); return PTR_ERR(pll2); } pll1 = clk_get(NULL, "pll1_main_clk"); if (IS_ERR(pll1)) { printk(KERN_DEBUG "%s: failed to get pll1\n", __func__); return PTR_ERR(pll1); } pll1_sw_clk = clk_get(NULL, "pll1_sw_clk"); if (IS_ERR(pll1_sw_clk)) { printk(KERN_DEBUG "%s: failed to get pll1_sw_clk\n", __func__); return PTR_ERR(pll1_sw_clk); } if (IS_ERR(pll2)) { printk(KERN_DEBUG "%s: failed to get pll2\n", __func__); return PTR_ERR(pll2); } cpu_clk = clk_get(NULL, "cpu_clk"); if (IS_ERR(cpu_clk)) { printk(KERN_DEBUG "%s: failed to get cpu_clk\n", __func__); return PTR_ERR(cpu_clk); } pll3 = clk_get(NULL, "pll3_main_clk"); if (IS_ERR(pll3)) { printk(KERN_DEBUG "%s: failed to get pll3\n", __func__); return PTR_ERR(pll3); } pll3_540 = clk_get(NULL, "pll3_pfd_540M"); if (IS_ERR(pll3_540)) { printk(KERN_DEBUG "%s: failed to get periph_clk\n", __func__); return PTR_ERR(pll3_540); } pll3_sw_clk = clk_get(NULL, "pll3_sw_clk"); if (IS_ERR(pll3_sw_clk)) { printk(KERN_DEBUG "%s: failed to get pll3_sw_clk\n", __func__); return PTR_ERR(pll3_sw_clk); } axi_clk = clk_get(NULL, "axi_clk"); if (IS_ERR(axi_clk)) { printk(KERN_DEBUG "%s: failed to get axi_clk\n", __func__); return PTR_ERR(axi_clk); } ahb_clk = clk_get(NULL, "ahb"); if (IS_ERR(ahb_clk)) { printk(KERN_DEBUG "%s: failed to get ahb_clk\n", __func__); return PTR_ERR(ahb_clk); } periph_clk = clk_get(NULL, "periph_clk"); if (IS_ERR(periph_clk)) { printk(KERN_DEBUG "%s: failed to get periph_clk\n", __func__); return PTR_ERR(periph_clk); } osc_clk = clk_get(NULL, "osc"); if (IS_ERR(osc_clk)) { printk(KERN_DEBUG "%s: failed to get osc_clk\n", __func__); return PTR_ERR(osc_clk); } mmdc_ch0_axi = clk_get(NULL, "mmdc_ch0_axi"); if (IS_ERR(mmdc_ch0_axi)) { printk(KERN_DEBUG "%s: failed to get mmdc_ch0_axi\n", __func__); return PTR_ERR(mmdc_ch0_axi); } err = sysfs_create_file(&busfreq_dev->kobj, &dev_attr_enable.attr); if (err) { printk(KERN_ERR "Unable to register sysdev entry for BUSFREQ"); return err; } cpu_op_tbl = get_cpu_op(&cpu_op_nr); low_bus_freq_mode = 0; if (cpu_is_mx6dl()) { high_bus_freq_mode = 0; med_bus_freq_mode = 1; /* To make pll2_400 use count right, as when system enter 24M, it will disable pll2_400 */ clk_enable(pll2_400); } else if (cpu_is_mx6sl()) { /* Set med_bus_freq_mode to 1 since med_bus_freq_mode is not supported as yet for MX6SL */ high_bus_freq_mode = 1; med_bus_freq_mode = 1; } else { high_bus_freq_mode = 1; med_bus_freq_mode = 0; } bus_freq_scaling_is_active = 0; bus_freq_scaling_initialized = 1; if (cpu_is_mx6q()) { ddr_low_rate = LPAPM_CLK; ddr_med_rate = DDR_MED_CLK; ddr_normal_rate = DDR3_NORMAL_CLK; } if (cpu_is_mx6dl() || cpu_is_mx6sl()) { ddr_low_rate = LPAPM_CLK; ddr_normal_rate = ddr_med_rate = DDR_MED_CLK; } INIT_DELAYED_WORK(&low_bus_freq_handler, reduce_bus_freq_handler); register_pm_notifier(&imx_bus_freq_pm_notifier); if (!cpu_is_mx6sl()) init_mmdc_settings(); else { unsigned long iram_paddr; /* Allocate IRAM for WFI code when system is * in low freq mode. */ iram_alloc(SZ_4K, &iram_paddr); /* Need to remap the area here since we want * the memory region to be executable. */ mx6sl_wfi_iram_base = __arm_ioremap(iram_paddr, SZ_4K, MT_MEMORY_NONCACHED); memcpy(mx6sl_wfi_iram_base, mx6sl_wait, SZ_4K); mx6sl_wfi_iram = (void *)mx6sl_wfi_iram_base; /* Allocate IRAM for WFI code when system is *in low freq mode. */ iram_alloc(SZ_4K, &iram_paddr); /* Need to remap the area here since we want the memory region to be executable. */ mx6sl_ddr_freq_base = __arm_ioremap(iram_paddr, SZ_4K, MT_MEMORY_NONCACHED); memcpy(mx6sl_ddr_freq_base, mx6sl_ddr_iram, SZ_4K); mx6sl_ddr_freq_change_iram = (void *)mx6sl_ddr_freq_base; } return 0; }
void init_ddr_settings(void) { unsigned long iram_paddr; unsigned int reg; int i; struct clk *ddr_clk = clk_get(NULL, "ddr_clk"); databahn_base = ioremap(MX50_DATABAHN_BASE_ADDR, SZ_16K); /* Find the memory type, LPDDR2 or mddr. */ mx50_ddr_type = __raw_readl(databahn_base) & 0xF00; if (mx50_ddr_type == MX50_LPDDR2) { normal_databahn_settings = lpddr2_databhan_regs_offsets; ddr_settings_size = ARRAY_SIZE(lpddr2_databhan_regs_offsets); } else if (mx50_ddr_type == MX50_MDDR) { normal_databahn_settings = mddr_databhan_regs_offsets; ddr_settings_size = ARRAY_SIZE(mddr_databhan_regs_offsets); } else if (mx50_ddr_type == MX50_DDR2) { normal_databahn_settings = ddr2_databhan_regs_offsets; ddr_settings_size = ARRAY_SIZE(ddr2_databhan_regs_offsets); } else { printk(KERN_DEBUG "%s: Unsupported memory type\n", __func__); return; } /* Copy the databhan settings into the iram location. */ for (i = 0; i < ddr_settings_size; i++) { normal_databahn_settings[i][1] = __raw_readl(databahn_base + normal_databahn_settings[i][0]); } /* Store the size of the array in iRAM also, * increase the size by 8 bytes. */ iram_ddr_settings = iram_alloc(ddr_settings_size + 8, &iram_paddr); if (iram_ddr_settings == NULL) { printk(KERN_DEBUG "%s: failed to allocate iRAM memory for ddr settings\n", __func__); return; } /* Allocate IRAM for the DDR freq change code. */ iram_alloc(SZ_8K, &iram_paddr); /* Need to remap the area here since we want the memory region to be executable. */ ddr_freq_change_iram_base = __arm_ioremap(iram_paddr, SZ_8K, MT_HIGH_VECTORS); memcpy(ddr_freq_change_iram_base, mx50_ddr_freq_change, SZ_8K); change_ddr_freq = (void *)ddr_freq_change_iram_base; qosc_base = ioremap(QOSC_BASE_ADDR, SZ_4K); /* Enable the QoSC */ reg = __raw_readl(qosc_base); reg &= ~0xC0000000; __raw_writel(reg, qosc_base); /* Allocate IRAM to run the WFI code from iram, since * we can turn off the DDR clocks when ARM is in WFI. */ iram_alloc(SZ_4K, &iram_paddr); /* Need to remap the area here since we want the memory region to be executable. */ wait_in_iram_base = __arm_ioremap(iram_paddr, SZ_4K, MT_HIGH_VECTORS); memcpy(wait_in_iram_base, mx50_wait, SZ_4K); wait_in_iram = (void *)wait_in_iram_base; clk_enable(ddr_clk); /* Set the DDR to enter automatic self-refresh. */ /* Set the DDR to automatically enter lower power mode 4. */ reg = __raw_readl(databahn_base + DATABAHN_CTL_REG22); reg &= ~LOWPOWER_AUTOENABLE_MASK; reg |= 1 << 1; __raw_writel(reg, databahn_base + DATABAHN_CTL_REG22); /* set the counter for entering mode 4. */ reg = __raw_readl(databahn_base + DATABAHN_CTL_REG21); reg &= ~LOWPOWER_EXTERNAL_CNT_MASK; reg = 128 << LOWPOWER_EXTERNAL_CNT_OFFSET; __raw_writel(reg, databahn_base + DATABAHN_CTL_REG21); /* Enable low power mode 4 */ reg = __raw_readl(databahn_base + DATABAHN_CTL_REG20); reg &= ~LOWPOWER_CONTROL_MASK; reg |= 1 << 1; __raw_writel(reg, databahn_base + DATABAHN_CTL_REG20); clk_disable(ddr_clk); epdc_clk = clk_get(NULL, "epdc_axi"); if (IS_ERR(epdc_clk)) { printk(KERN_DEBUG "%s: failed to get epdc_axi_clk\n", __func__); return; } }
static int __init post_cpu_init(void) { unsigned int reg; void __iomem *base; unsigned long iram_paddr, cpaddr; iram_init(MX6Q_IRAM_BASE_ADDR, MX6Q_IRAM_SIZE); base = ioremap(AIPS1_ON_BASE_ADDR, PAGE_SIZE); __raw_writel(0x0, base + 0x40); __raw_writel(0x0, base + 0x44); __raw_writel(0x0, base + 0x48); __raw_writel(0x0, base + 0x4C); reg = __raw_readl(base + 0x50) & 0x00FFFFFF; __raw_writel(reg, base + 0x50); iounmap(base); base = ioremap(AIPS2_ON_BASE_ADDR, PAGE_SIZE); __raw_writel(0x0, base + 0x40); __raw_writel(0x0, base + 0x44); __raw_writel(0x0, base + 0x48); __raw_writel(0x0, base + 0x4C); reg = __raw_readl(base + 0x50) & 0x00FFFFFF; __raw_writel(reg, base + 0x50); iounmap(base); if (enable_wait_mode) { /* Allow SCU_CLK to be disabled when all cores are in WFI*/ base = IO_ADDRESS(SCU_BASE_ADDR); reg = __raw_readl(base); reg |= 0x20; __raw_writel(reg, base); } /* Disable SRC warm reset to work aound system reboot issue */ base = IO_ADDRESS(SRC_BASE_ADDR); reg = __raw_readl(base); reg &= ~0x1; __raw_writel(reg, base); /* Allocate IRAM for WAIT code. */ /* Move wait routine into iRAM */ cpaddr = (unsigned long)iram_alloc(SZ_4K, &iram_paddr); /* Need to remap the area here since we want the memory region to be executable. */ mx6_wait_in_iram_base = __arm_ioremap(iram_paddr, SZ_4K, MT_MEMORY_NONCACHED); pr_info("cpaddr = %x wait_iram_base=%x\n", (unsigned int)cpaddr, (unsigned int)mx6_wait_in_iram_base); /* * Need to run the suspend code from IRAM as the DDR needs * to be put into low power mode manually. */ memcpy((void *)cpaddr, mx6_wait, SZ_4K); mx6_wait_in_iram = (void *)mx6_wait_in_iram_base; gpc_base = MX6_IO_ADDRESS(GPC_BASE_ADDR); ccm_base = MX6_IO_ADDRESS(CCM_BASE_ADDR); return 0; }