示例#1
0
文件: pm.c 项目: boseji/kernel_imx
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;
}
示例#2
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;
}
示例#3
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;
}
示例#4
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;
	}
}
示例#5
0
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;
}