From 849369d6c66d3054688672f97d31fceb8e8230fb Mon Sep 17 00:00:00 2001 From: root Date: Fri, 25 Dec 2015 04:40:36 +0000 Subject: initial_commit --- arch/arm/mach-mx5/sdram_autogating.c | 201 +++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100755 arch/arm/mach-mx5/sdram_autogating.c (limited to 'arch/arm/mach-mx5/sdram_autogating.c') diff --git a/arch/arm/mach-mx5/sdram_autogating.c b/arch/arm/mach-mx5/sdram_autogating.c new file mode 100755 index 00000000..ca75739e --- /dev/null +++ b/arch/arm/mach-mx5/sdram_autogating.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/*! + * @file sdram_autogating.c + * + * @brief Enable auto clock gating of the EMI_FAST clock using M4IF. + * + * The APIs are for enabling and disabling automatic clock gating of EMI_FAST. + * + * @ingroup PM + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crm_regs.h" + +static struct device *sdram_autogating_dev; +#define M4IF_CNTL_REG0 0x8c +#define M4IF_CNTL_REG1 0x90 + +/* Flag used to indicate if SDRAM M4IF autoclock gating feature is active. */ +static int sdram_autogating_is_active; +static int sdram_autogating_paused; +static void __iomem *m4if_base; + +void start_sdram_autogating(void); +void stop_sdram_autogating(void); +int sdram_autogating_active(void); + +static void enable(void) +{ + u32 reg; + + /* Set the Fast arbitration Power saving timer */ + reg = __raw_readl(m4if_base + M4IF_CNTL_REG1); + reg &= ~0xFF; + reg |= 0x09; + __raw_writel(reg, m4if_base + M4IF_CNTL_REG1); + /*Allow for automatic gating of the EMI internal clock. + * If this is done, emi_intr CCGR bits should be set to 11. + */ + reg = __raw_readl(m4if_base + M4IF_CNTL_REG0); + reg &= ~0x5; + __raw_writel(reg, m4if_base + M4IF_CNTL_REG0); + + sdram_autogating_is_active = 1; +} + +static void disable(void) +{ + u32 reg; + + reg = __raw_readl(m4if_base + M4IF_CNTL_REG0); + reg |= 0x4; + __raw_writel(reg, m4if_base + M4IF_CNTL_REG0); + sdram_autogating_is_active = 0; +} + +int sdram_autogating_active() +{ + return sdram_autogating_is_active; +} + +void start_sdram_autogating() +{ + if (cpu_is_mx50()) + return; + if (sdram_autogating_paused) { + enable(); + sdram_autogating_paused = 0; + } +} + +void stop_sdram_autogating() +{ + if (cpu_is_mx50()) + return; + + if (sdram_autogating_is_active) { + sdram_autogating_paused = 1; + disable(); + } +} + +static ssize_t sdram_autogating_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if (sdram_autogating_is_active) + return sprintf(buf, + "M4IF autoclock gating for EMI_FAST enabled\n"); + else + return sprintf(buf, + "M4IF autoclock gating for EMI_FAST disabled\n"); +} + +static ssize_t sdram_autogating_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + if (strstr(buf, "1") != NULL) + enable(); + else if (strstr(buf, "0") != NULL) { + if (sdram_autogating_is_active) + disable(); + } + return size; +} + +static DEVICE_ATTR(enable, 0644, sdram_autogating_enable_show, + sdram_autogating_enable_store); + +/*! + * This is the probe routine for the auto clockgating of sdram driver. + * + * @param pdev The platform device structure + * + * @return The function returns 0 on success + * + */ +static int __devinit sdram_autogating_probe(struct platform_device *pdev) +{ + struct resource *res; + int err = 0; + + sdram_autogating_dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + return -ENOMEM; + } + m4if_base = ioremap(res->start, res->end - res->start + 1); + + err = sysfs_create_file(&sdram_autogating_dev->kobj, + &dev_attr_enable.attr); + if (err) { + printk(KERN_ERR + "Unable to register sysdev entry for sdram_autogating"); + return err; + } + + sdram_autogating_is_active = 0; + + return 0; +} + +static struct platform_driver sdram_autogating_driver = { + .driver = { + .name = "sdram_autogating", + }, + .probe = sdram_autogating_probe, +}; + +/*! + * Initialise the sdram_autogating_driver. + * + * @return The function always returns 0. + */ + +static int __init sdram_autogating_init(void) +{ + if (platform_driver_register(&sdram_autogating_driver) != 0) { + printk(KERN_ERR "sdram_autogating_driver register failed\n"); + return -ENODEV; + } + + printk(KERN_INFO "sdram autogating driver module loaded\n"); + return 0; +} + +static void __exit sdram_autogating_cleanup(void) +{ + sysfs_remove_file(&sdram_autogating_dev->kobj, &dev_attr_enable.attr); + + /* Unregister the device structure */ + platform_driver_unregister(&sdram_autogating_driver); +} + +module_init(sdram_autogating_init); +module_exit(sdram_autogating_cleanup); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("sdram_autogating driver"); +MODULE_LICENSE("GPL"); + -- cgit v1.2.3