mirror of
https://github.com/torvalds/linux.git
synced 2024-12-03 09:31:26 +00:00
ec336b2841
As the DDR/IO and MMDC setting are different on LPDDR2 and DDR3, we used cpu type to decide how to do these settings in suspend before which is NOT flexible, take i.MX6SL for example, although it has LPDDR2 on EVK board, but users can also use DDR3 on other boards, so it is better to read the DDR type from MMDC then decide how to do related settings. Signed-off-by: Anson Huang <b20788@freescale.com> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
90 lines
2.0 KiB
C
90 lines
2.0 KiB
C
/*
|
|
* Copyright 2011 Freescale Semiconductor, Inc.
|
|
* Copyright 2011 Linaro Ltd.
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/io.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/of_device.h>
|
|
|
|
#define MMDC_MAPSR 0x404
|
|
#define BP_MMDC_MAPSR_PSD 0
|
|
#define BP_MMDC_MAPSR_PSS 4
|
|
|
|
#define MMDC_MDMISC 0x18
|
|
#define BM_MMDC_MDMISC_DDR_TYPE 0x18
|
|
#define BP_MMDC_MDMISC_DDR_TYPE 0x3
|
|
|
|
static int ddr_type;
|
|
|
|
static int imx_mmdc_probe(struct platform_device *pdev)
|
|
{
|
|
struct device_node *np = pdev->dev.of_node;
|
|
void __iomem *mmdc_base, *reg;
|
|
u32 val;
|
|
int timeout = 0x400;
|
|
|
|
mmdc_base = of_iomap(np, 0);
|
|
WARN_ON(!mmdc_base);
|
|
|
|
reg = mmdc_base + MMDC_MDMISC;
|
|
/* Get ddr type */
|
|
val = readl_relaxed(reg);
|
|
ddr_type = (val & BM_MMDC_MDMISC_DDR_TYPE) >>
|
|
BP_MMDC_MDMISC_DDR_TYPE;
|
|
|
|
reg = mmdc_base + MMDC_MAPSR;
|
|
|
|
/* Enable automatic power saving */
|
|
val = readl_relaxed(reg);
|
|
val &= ~(1 << BP_MMDC_MAPSR_PSD);
|
|
writel_relaxed(val, reg);
|
|
|
|
/* Ensure it's successfully enabled */
|
|
while (!(readl_relaxed(reg) & 1 << BP_MMDC_MAPSR_PSS) && --timeout)
|
|
cpu_relax();
|
|
|
|
if (unlikely(!timeout)) {
|
|
pr_warn("%s: failed to enable automatic power saving\n",
|
|
__func__);
|
|
return -EBUSY;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int imx_mmdc_get_ddr_type(void)
|
|
{
|
|
return ddr_type;
|
|
}
|
|
|
|
static struct of_device_id imx_mmdc_dt_ids[] = {
|
|
{ .compatible = "fsl,imx6q-mmdc", },
|
|
{ /* sentinel */ }
|
|
};
|
|
|
|
static struct platform_driver imx_mmdc_driver = {
|
|
.driver = {
|
|
.name = "imx-mmdc",
|
|
.owner = THIS_MODULE,
|
|
.of_match_table = imx_mmdc_dt_ids,
|
|
},
|
|
.probe = imx_mmdc_probe,
|
|
};
|
|
|
|
static int __init imx_mmdc_init(void)
|
|
{
|
|
return platform_driver_register(&imx_mmdc_driver);
|
|
}
|
|
postcore_initcall(imx_mmdc_init);
|