Skip to content
Snippets Groups Projects
Select Git revision
  • 80b9abf973462499c1a0110df47f62cc90361e2c
  • seco_lf-6.6.52-2.2.1 default protected
  • integrate/gitlab-ci/use-board-only-instead-codename-and-board-in-the-configuration/into/seco_lf-6.6.52-2.2.1
  • seco_lf-6.6.52-2.2.1-tr8mp-dtb
  • seco_lf-6.6.52-2.2.1-tr8mp-mcu
  • integrate/gitlab-ci/use-board-only-instead-codename-and-board-in-the-configuration/into/seco_lf-5.10.y
  • seco_lf-6.6.23-2.0.0_e39-e83-p4-devicetree
  • integrate/gitlab-ci/cleaos-894-rename-distros-into-build-tergets/into/seco_lf-5.10.y
  • integrate/gitlab-ci/cleaos-894-rename-distros-into-build-tergets/into/seco_lf-6.6.52-2.2.1
  • seco_lf-5.10.y protected
  • seco_lf-6.6.52-2.2.1_e88-dev
  • seco_lf-6.6.52-2.2.1_ov5640-mx95-dev
  • seco_lf-6.6.52-2.2.1-tr8mp-rgb-defconfig
  • seco_lf-6.6.52-2.2.1-tr8mp-dev
  • seco_lf-6.6.52-2.2.1-tr8mp-dtbo
  • seco_lf-6.6.52-2.2.1-tr8mp-rv3028
  • seco_lf-6.6.52-2.2.1-tr8mp-fpga
  • seco_lf-6.6.52-2.2.1_stm32g0-dev
  • seco_lf-6.6.52-2.2.1_remove-mwifiex_d18
  • seco_lf-6.6.52-2.2.1_e88-dbg-uart-dev
  • seco_lf_v2024.04_6.6.52_2.2.x-e39-e83-devicetrees
  • lf-6.6.52-2.2.1
  • lf-6.1.55-2.2.1
  • lf-6.6.3-1.0.0
  • lf-6.6.3-imx95-er2
  • lf-6.1.55-2.2.0
  • lf-6.6.y-imx95-er1
  • lf-5.15.71-2.2.2
  • lf-6.1.36-2.1.0
  • lf-5.15.71-2.2.1
  • lf-6.1.22-2.0.0
  • lf-6.1.1-1.0.1
  • rel_imx_5.4.24_2.1.4
  • rel_imx_4.9.88_2.0.13
  • rel_imx_4.14.98_2.3.5
  • lf-6.1.1-1.0.0
  • rel_imx_5.4.3_2.0.2
  • lf-5.15.71-2.2.0
  • lf-5.10.72-2.2.3
  • lf-5.15.52-2.1.0
  • imx_5.15.52_imx8ulp_er1
41 results

pm.c

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    pm.c 3.77 KiB
    /*
     * DaVinci Power Management Routines
     *
     * Copyright (C) 2009 Texas Instruments, Inc. http://www.ti.com/
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     */
    
    #include <linux/pm.h>
    #include <linux/suspend.h>
    #include <linux/module.h>
    #include <linux/platform_device.h>
    #include <linux/clk.h>
    #include <linux/spinlock.h>
    
    #include <asm/cacheflush.h>
    #include <asm/delay.h>
    #include <asm/io.h>
    
    #include <mach/da8xx.h>
    #include <mach/sram.h>
    #include <mach/pm.h>
    
    #include "clock.h"
    
    #define DEEPSLEEP_SLEEPCOUNT_MASK	0xFFFF
    
    static void (*davinci_sram_suspend) (struct davinci_pm_config *);
    static struct davinci_pm_config *pdata;
    
    static void davinci_sram_push(void *dest, void *src, unsigned int size)
    {
    	memcpy(dest, src, size);
    	flush_icache_range((unsigned long)dest, (unsigned long)(dest + size));
    }
    
    static void davinci_pm_suspend(void)
    {
    	unsigned val;
    
    	if (pdata->cpupll_reg_base != pdata->ddrpll_reg_base) {
    
    		/* Switch CPU PLL to bypass mode */
    		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
    		val &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
    		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
    
    		udelay(PLL_BYPASS_TIME);
    
    		/* Powerdown CPU PLL */
    		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
    		val |= PLLCTL_PLLPWRDN;
    		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
    	}
    
    	/* Configure sleep count in deep sleep register */
    	val = __raw_readl(pdata->deepsleep_reg);
    	val &= ~DEEPSLEEP_SLEEPCOUNT_MASK,
    	val |= pdata->sleepcount;
    	__raw_writel(val, pdata->deepsleep_reg);
    
    	/* System goes to sleep in this call */
    	davinci_sram_suspend(pdata);
    
    	if (pdata->cpupll_reg_base != pdata->ddrpll_reg_base) {
    
    		/* put CPU PLL in reset */
    		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
    		val &= ~PLLCTL_PLLRST;
    		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
    
    		/* put CPU PLL in power down */
    		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
    		val &= ~PLLCTL_PLLPWRDN;
    		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
    
    		/* wait for CPU PLL reset */
    		udelay(PLL_RESET_TIME);
    
    		/* bring CPU PLL out of reset */
    		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
    		val |= PLLCTL_PLLRST;
    		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
    
    		/* Wait for CPU PLL to lock */
    		udelay(PLL_LOCK_TIME);
    
    		/* Remove CPU PLL from bypass mode */
    		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
    		val &= ~PLLCTL_PLLENSRC;
    		val |= PLLCTL_PLLEN;
    		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
    	}
    }
    
    static int davinci_pm_enter(suspend_state_t state)
    {
    	int ret = 0;
    
    	switch (state) {
    	case PM_SUSPEND_STANDBY:
    	case PM_SUSPEND_MEM:
    		davinci_pm_suspend();
    		break;
    	default:
    		ret = -EINVAL;
    	}
    
    	return ret;
    }
    
    static const struct platform_suspend_ops davinci_pm_ops = {
    	.enter		= davinci_pm_enter,
    	.valid		= suspend_valid_only_mem,
    };
    
    static int __init davinci_pm_probe(struct platform_device *pdev)
    {
    	pdata = pdev->dev.platform_data;
    	if (!pdata) {
    		dev_err(&pdev->dev, "cannot get platform data\n");
    		return -ENOENT;
    	}
    
    	davinci_sram_suspend = sram_alloc(davinci_cpu_suspend_sz, NULL);
    	if (!davinci_sram_suspend) {
    		dev_err(&pdev->dev, "cannot allocate SRAM memory\n");
    		return -ENOMEM;
    	}
    
    	davinci_sram_push(davinci_sram_suspend, davinci_cpu_suspend,
    						davinci_cpu_suspend_sz);
    
    	suspend_set_ops(&davinci_pm_ops);
    
    	return 0;
    }
    
    static int __exit davinci_pm_remove(struct platform_device *pdev)
    {
    	sram_free(davinci_sram_suspend, davinci_cpu_suspend_sz);
    	return 0;
    }
    
    static struct platform_driver davinci_pm_driver = {
    	.driver = {
    		.name	 = "pm-davinci",
    		.owner	 = THIS_MODULE,
    	},
    	.remove = __exit_p(davinci_pm_remove),
    };
    
    int __init davinci_pm_init(void)
    {
    	return platform_driver_probe(&davinci_pm_driver, davinci_pm_probe);
    }