cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pm-arm.c (19766B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * ARM-specific support for Broadcom STB S2/S3/S5 power management
      4 *
      5 * S2: clock gate CPUs and as many peripherals as possible
      6 * S3: power off all of the chip except the Always ON (AON) island; keep DDR is
      7 *     self-refresh
      8 * S5: (a.k.a. S3 cold boot) much like S3, except DDR is powered down, so we
      9 *     treat this mode like a soft power-off, with wakeup allowed from AON
     10 *
     11 * Copyright © 2014-2017 Broadcom
     12 */
     13
     14#define pr_fmt(fmt) "brcmstb-pm: " fmt
     15
     16#include <linux/bitops.h>
     17#include <linux/compiler.h>
     18#include <linux/delay.h>
     19#include <linux/dma-mapping.h>
     20#include <linux/err.h>
     21#include <linux/init.h>
     22#include <linux/io.h>
     23#include <linux/ioport.h>
     24#include <linux/kconfig.h>
     25#include <linux/kernel.h>
     26#include <linux/memblock.h>
     27#include <linux/module.h>
     28#include <linux/notifier.h>
     29#include <linux/of.h>
     30#include <linux/of_address.h>
     31#include <linux/panic_notifier.h>
     32#include <linux/platform_device.h>
     33#include <linux/pm.h>
     34#include <linux/printk.h>
     35#include <linux/proc_fs.h>
     36#include <linux/sizes.h>
     37#include <linux/slab.h>
     38#include <linux/sort.h>
     39#include <linux/suspend.h>
     40#include <linux/types.h>
     41#include <linux/uaccess.h>
     42#include <linux/soc/brcmstb/brcmstb.h>
     43
     44#include <asm/fncpy.h>
     45#include <asm/setup.h>
     46#include <asm/suspend.h>
     47
     48#include "pm.h"
     49#include "aon_defs.h"
     50
     51#define SHIMPHY_DDR_PAD_CNTRL		0x8c
     52
     53/* Method #0 */
     54#define SHIMPHY_PAD_PLL_SEQUENCE	BIT(8)
     55#define SHIMPHY_PAD_GATE_PLL_S3		BIT(9)
     56
     57/* Method #1 */
     58#define PWRDWN_SEQ_NO_SEQUENCING	0
     59#define PWRDWN_SEQ_HOLD_CHANNEL		1
     60#define	PWRDWN_SEQ_RESET_PLL		2
     61#define PWRDWN_SEQ_POWERDOWN_PLL	3
     62
     63#define SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK	0x00f00000
     64#define SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT	20
     65
     66#define	DDR_FORCE_CKE_RST_N		BIT(3)
     67#define	DDR_PHY_RST_N			BIT(2)
     68#define	DDR_PHY_CKE			BIT(1)
     69
     70#define	DDR_PHY_NO_CHANNEL		0xffffffff
     71
     72#define MAX_NUM_MEMC			3
     73
     74struct brcmstb_memc {
     75	void __iomem *ddr_phy_base;
     76	void __iomem *ddr_shimphy_base;
     77	void __iomem *ddr_ctrl;
     78};
     79
     80struct brcmstb_pm_control {
     81	void __iomem *aon_ctrl_base;
     82	void __iomem *aon_sram;
     83	struct brcmstb_memc memcs[MAX_NUM_MEMC];
     84
     85	void __iomem *boot_sram;
     86	size_t boot_sram_len;
     87
     88	bool support_warm_boot;
     89	size_t pll_status_offset;
     90	int num_memc;
     91
     92	struct brcmstb_s3_params *s3_params;
     93	dma_addr_t s3_params_pa;
     94	int s3entry_method;
     95	u32 warm_boot_offset;
     96	u32 phy_a_standby_ctrl_offs;
     97	u32 phy_b_standby_ctrl_offs;
     98	bool needs_ddr_pad;
     99	struct platform_device *pdev;
    100};
    101
    102enum bsp_initiate_command {
    103	BSP_CLOCK_STOP		= 0x00,
    104	BSP_GEN_RANDOM_KEY	= 0x4A,
    105	BSP_RESTORE_RANDOM_KEY	= 0x55,
    106	BSP_GEN_FIXED_KEY	= 0x63,
    107};
    108
    109#define PM_INITIATE		0x01
    110#define PM_INITIATE_SUCCESS	0x00
    111#define PM_INITIATE_FAIL	0xfe
    112
    113static struct brcmstb_pm_control ctrl;
    114
    115noinline int brcmstb_pm_s3_finish(void);
    116
    117static int (*brcmstb_pm_do_s2_sram)(void __iomem *aon_ctrl_base,
    118		void __iomem *ddr_phy_pll_status);
    119
    120static int brcmstb_init_sram(struct device_node *dn)
    121{
    122	void __iomem *sram;
    123	struct resource res;
    124	int ret;
    125
    126	ret = of_address_to_resource(dn, 0, &res);
    127	if (ret)
    128		return ret;
    129
    130	/* Uncached, executable remapping of SRAM */
    131	sram = __arm_ioremap_exec(res.start, resource_size(&res), false);
    132	if (!sram)
    133		return -ENOMEM;
    134
    135	ctrl.boot_sram = sram;
    136	ctrl.boot_sram_len = resource_size(&res);
    137
    138	return 0;
    139}
    140
    141static const struct of_device_id sram_dt_ids[] = {
    142	{ .compatible = "mmio-sram" },
    143	{ /* sentinel */ }
    144};
    145
    146static int do_bsp_initiate_command(enum bsp_initiate_command cmd)
    147{
    148	void __iomem *base = ctrl.aon_ctrl_base;
    149	int ret;
    150	int timeo = 1000 * 1000; /* 1 second */
    151
    152	writel_relaxed(0, base + AON_CTRL_PM_INITIATE);
    153	(void)readl_relaxed(base + AON_CTRL_PM_INITIATE);
    154
    155	/* Go! */
    156	writel_relaxed((cmd << 1) | PM_INITIATE, base + AON_CTRL_PM_INITIATE);
    157
    158	/*
    159	 * If firmware doesn't support the 'ack', then just assume it's done
    160	 * after 10ms. Note that this only works for command 0, BSP_CLOCK_STOP
    161	 */
    162	if (of_machine_is_compatible("brcm,bcm74371a0")) {
    163		(void)readl_relaxed(base + AON_CTRL_PM_INITIATE);
    164		mdelay(10);
    165		return 0;
    166	}
    167
    168	for (;;) {
    169		ret = readl_relaxed(base + AON_CTRL_PM_INITIATE);
    170		if (!(ret & PM_INITIATE))
    171			break;
    172		if (timeo <= 0) {
    173			pr_err("error: timeout waiting for BSP (%x)\n", ret);
    174			break;
    175		}
    176		timeo -= 50;
    177		udelay(50);
    178	}
    179
    180	return (ret & 0xff) != PM_INITIATE_SUCCESS;
    181}
    182
    183static int brcmstb_pm_handshake(void)
    184{
    185	void __iomem *base = ctrl.aon_ctrl_base;
    186	u32 tmp;
    187	int ret;
    188
    189	/* BSP power handshake, v1 */
    190	tmp = readl_relaxed(base + AON_CTRL_HOST_MISC_CMDS);
    191	tmp &= ~1UL;
    192	writel_relaxed(tmp, base + AON_CTRL_HOST_MISC_CMDS);
    193	(void)readl_relaxed(base + AON_CTRL_HOST_MISC_CMDS);
    194
    195	ret = do_bsp_initiate_command(BSP_CLOCK_STOP);
    196	if (ret)
    197		pr_err("BSP handshake failed\n");
    198
    199	/*
    200	 * HACK: BSP may have internal race on the CLOCK_STOP command.
    201	 * Avoid touching the BSP for a few milliseconds.
    202	 */
    203	mdelay(3);
    204
    205	return ret;
    206}
    207
    208static inline void shimphy_set(u32 value, u32 mask)
    209{
    210	int i;
    211
    212	if (!ctrl.needs_ddr_pad)
    213		return;
    214
    215	for (i = 0; i < ctrl.num_memc; i++) {
    216		u32 tmp;
    217
    218		tmp = readl_relaxed(ctrl.memcs[i].ddr_shimphy_base +
    219			SHIMPHY_DDR_PAD_CNTRL);
    220		tmp = value | (tmp & mask);
    221		writel_relaxed(tmp, ctrl.memcs[i].ddr_shimphy_base +
    222			SHIMPHY_DDR_PAD_CNTRL);
    223	}
    224	wmb(); /* Complete sequence in order. */
    225}
    226
    227static inline void ddr_ctrl_set(bool warmboot)
    228{
    229	int i;
    230
    231	for (i = 0; i < ctrl.num_memc; i++) {
    232		u32 tmp;
    233
    234		tmp = readl_relaxed(ctrl.memcs[i].ddr_ctrl +
    235				ctrl.warm_boot_offset);
    236		if (warmboot)
    237			tmp |= 1;
    238		else
    239			tmp &= ~1; /* Cold boot */
    240		writel_relaxed(tmp, ctrl.memcs[i].ddr_ctrl +
    241				ctrl.warm_boot_offset);
    242	}
    243	/* Complete sequence in order */
    244	wmb();
    245}
    246
    247static inline void s3entry_method0(void)
    248{
    249	shimphy_set(SHIMPHY_PAD_GATE_PLL_S3 | SHIMPHY_PAD_PLL_SEQUENCE,
    250		    0xffffffff);
    251}
    252
    253static inline void s3entry_method1(void)
    254{
    255	/*
    256	 * S3 Entry Sequence
    257	 * -----------------
    258	 * Step 1: SHIMPHY_ADDR_CNTL_0_DDR_PAD_CNTRL [ S3_PWRDWN_SEQ ] = 3
    259	 * Step 2: MEMC_DDR_0_WARM_BOOT [ WARM_BOOT ] = 1
    260	 */
    261	shimphy_set((PWRDWN_SEQ_POWERDOWN_PLL <<
    262		    SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT),
    263		    ~SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK);
    264
    265	ddr_ctrl_set(true);
    266}
    267
    268static inline void s5entry_method1(void)
    269{
    270	int i;
    271
    272	/*
    273	 * S5 Entry Sequence
    274	 * -----------------
    275	 * Step 1: SHIMPHY_ADDR_CNTL_0_DDR_PAD_CNTRL [ S3_PWRDWN_SEQ ] = 3
    276	 * Step 2: MEMC_DDR_0_WARM_BOOT [ WARM_BOOT ] = 0
    277	 * Step 3: DDR_PHY_CONTROL_REGS_[AB]_0_STANDBY_CONTROL[ CKE ] = 0
    278	 *	   DDR_PHY_CONTROL_REGS_[AB]_0_STANDBY_CONTROL[ RST_N ] = 0
    279	 */
    280	shimphy_set((PWRDWN_SEQ_POWERDOWN_PLL <<
    281		    SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT),
    282		    ~SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK);
    283
    284	ddr_ctrl_set(false);
    285
    286	for (i = 0; i < ctrl.num_memc; i++) {
    287		u32 tmp;
    288
    289		/* Step 3: Channel A (RST_N = CKE = 0) */
    290		tmp = readl_relaxed(ctrl.memcs[i].ddr_phy_base +
    291				  ctrl.phy_a_standby_ctrl_offs);
    292		tmp &= ~(DDR_PHY_RST_N | DDR_PHY_RST_N);
    293		writel_relaxed(tmp, ctrl.memcs[i].ddr_phy_base +
    294			     ctrl.phy_a_standby_ctrl_offs);
    295
    296		/* Step 3: Channel B? */
    297		if (ctrl.phy_b_standby_ctrl_offs != DDR_PHY_NO_CHANNEL) {
    298			tmp = readl_relaxed(ctrl.memcs[i].ddr_phy_base +
    299					  ctrl.phy_b_standby_ctrl_offs);
    300			tmp &= ~(DDR_PHY_RST_N | DDR_PHY_RST_N);
    301			writel_relaxed(tmp, ctrl.memcs[i].ddr_phy_base +
    302				     ctrl.phy_b_standby_ctrl_offs);
    303		}
    304	}
    305	/* Must complete */
    306	wmb();
    307}
    308
    309/*
    310 * Run a Power Management State Machine (PMSM) shutdown command and put the CPU
    311 * into a low-power mode
    312 */
    313static void brcmstb_do_pmsm_power_down(unsigned long base_cmd, bool onewrite)
    314{
    315	void __iomem *base = ctrl.aon_ctrl_base;
    316
    317	if ((ctrl.s3entry_method == 1) && (base_cmd == PM_COLD_CONFIG))
    318		s5entry_method1();
    319
    320	/* pm_start_pwrdn transition 0->1 */
    321	writel_relaxed(base_cmd, base + AON_CTRL_PM_CTRL);
    322
    323	if (!onewrite) {
    324		(void)readl_relaxed(base + AON_CTRL_PM_CTRL);
    325
    326		writel_relaxed(base_cmd | PM_PWR_DOWN, base + AON_CTRL_PM_CTRL);
    327		(void)readl_relaxed(base + AON_CTRL_PM_CTRL);
    328	}
    329	wfi();
    330}
    331
    332/* Support S5 cold boot out of "poweroff" */
    333static void brcmstb_pm_poweroff(void)
    334{
    335	brcmstb_pm_handshake();
    336
    337	/* Clear magic S3 warm-boot value */
    338	writel_relaxed(0, ctrl.aon_sram + AON_REG_MAGIC_FLAGS);
    339	(void)readl_relaxed(ctrl.aon_sram + AON_REG_MAGIC_FLAGS);
    340
    341	/* Skip wait-for-interrupt signal; just use a countdown */
    342	writel_relaxed(0x10, ctrl.aon_ctrl_base + AON_CTRL_PM_CPU_WAIT_COUNT);
    343	(void)readl_relaxed(ctrl.aon_ctrl_base + AON_CTRL_PM_CPU_WAIT_COUNT);
    344
    345	if (ctrl.s3entry_method == 1) {
    346		shimphy_set((PWRDWN_SEQ_POWERDOWN_PLL <<
    347			     SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT),
    348			     ~SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK);
    349		ddr_ctrl_set(false);
    350		brcmstb_do_pmsm_power_down(M1_PM_COLD_CONFIG, true);
    351		return; /* We should never actually get here */
    352	}
    353
    354	brcmstb_do_pmsm_power_down(PM_COLD_CONFIG, false);
    355}
    356
    357static void *brcmstb_pm_copy_to_sram(void *fn, size_t len)
    358{
    359	unsigned int size = ALIGN(len, FNCPY_ALIGN);
    360
    361	if (ctrl.boot_sram_len < size) {
    362		pr_err("standby code will not fit in SRAM\n");
    363		return NULL;
    364	}
    365
    366	return fncpy(ctrl.boot_sram, fn, size);
    367}
    368
    369/*
    370 * S2 suspend/resume picks up where we left off, so we must execute carefully
    371 * from SRAM, in order to allow DDR to come back up safely before we continue.
    372 */
    373static int brcmstb_pm_s2(void)
    374{
    375	/* A previous S3 can set a value hazardous to S2, so make sure. */
    376	if (ctrl.s3entry_method == 1) {
    377		shimphy_set((PWRDWN_SEQ_NO_SEQUENCING <<
    378			    SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT),
    379			    ~SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK);
    380		ddr_ctrl_set(false);
    381	}
    382
    383	brcmstb_pm_do_s2_sram = brcmstb_pm_copy_to_sram(&brcmstb_pm_do_s2,
    384			brcmstb_pm_do_s2_sz);
    385	if (!brcmstb_pm_do_s2_sram)
    386		return -EINVAL;
    387
    388	return brcmstb_pm_do_s2_sram(ctrl.aon_ctrl_base,
    389			ctrl.memcs[0].ddr_phy_base +
    390			ctrl.pll_status_offset);
    391}
    392
    393/*
    394 * This function is called on a new stack, so don't allow inlining (which will
    395 * generate stack references on the old stack). It cannot be made static because
    396 * it is referenced from brcmstb_pm_s3()
    397 */
    398noinline int brcmstb_pm_s3_finish(void)
    399{
    400	struct brcmstb_s3_params *params = ctrl.s3_params;
    401	dma_addr_t params_pa = ctrl.s3_params_pa;
    402	phys_addr_t reentry = virt_to_phys(&cpu_resume_arm);
    403	enum bsp_initiate_command cmd;
    404	u32 flags;
    405
    406	/*
    407	 * Clear parameter structure, but not DTU area, which has already been
    408	 * filled in. We know DTU is a the end, so we can just subtract its
    409	 * size.
    410	 */
    411	memset(params, 0, sizeof(*params) - sizeof(params->dtu));
    412
    413	flags = readl_relaxed(ctrl.aon_sram + AON_REG_MAGIC_FLAGS);
    414
    415	flags &= S3_BOOTLOADER_RESERVED;
    416	flags |= S3_FLAG_NO_MEM_VERIFY;
    417	flags |= S3_FLAG_LOAD_RANDKEY;
    418
    419	/* Load random / fixed key */
    420	if (flags & S3_FLAG_LOAD_RANDKEY)
    421		cmd = BSP_GEN_RANDOM_KEY;
    422	else
    423		cmd = BSP_GEN_FIXED_KEY;
    424	if (do_bsp_initiate_command(cmd)) {
    425		pr_info("key loading failed\n");
    426		return -EIO;
    427	}
    428
    429	params->magic = BRCMSTB_S3_MAGIC;
    430	params->reentry = reentry;
    431
    432	/* No more writes to DRAM */
    433	flush_cache_all();
    434
    435	flags |= BRCMSTB_S3_MAGIC_SHORT;
    436
    437	writel_relaxed(flags, ctrl.aon_sram + AON_REG_MAGIC_FLAGS);
    438	writel_relaxed(lower_32_bits(params_pa),
    439		       ctrl.aon_sram + AON_REG_CONTROL_LOW);
    440	writel_relaxed(upper_32_bits(params_pa),
    441		       ctrl.aon_sram + AON_REG_CONTROL_HIGH);
    442
    443	switch (ctrl.s3entry_method) {
    444	case 0:
    445		s3entry_method0();
    446		brcmstb_do_pmsm_power_down(PM_WARM_CONFIG, false);
    447		break;
    448	case 1:
    449		s3entry_method1();
    450		brcmstb_do_pmsm_power_down(M1_PM_WARM_CONFIG, true);
    451		break;
    452	default:
    453		return -EINVAL;
    454	}
    455
    456	/* Must have been interrupted from wfi()? */
    457	return -EINTR;
    458}
    459
    460static int brcmstb_pm_do_s3(unsigned long sp)
    461{
    462	unsigned long save_sp;
    463	int ret;
    464
    465	asm volatile (
    466		"mov	%[save], sp\n"
    467		"mov	sp, %[new]\n"
    468		"bl	brcmstb_pm_s3_finish\n"
    469		"mov	%[ret], r0\n"
    470		"mov	%[new], sp\n"
    471		"mov	sp, %[save]\n"
    472		: [save] "=&r" (save_sp), [ret] "=&r" (ret)
    473		: [new] "r" (sp)
    474	);
    475
    476	return ret;
    477}
    478
    479static int brcmstb_pm_s3(void)
    480{
    481	void __iomem *sp = ctrl.boot_sram + ctrl.boot_sram_len;
    482
    483	return cpu_suspend((unsigned long)sp, brcmstb_pm_do_s3);
    484}
    485
    486static int brcmstb_pm_standby(bool deep_standby)
    487{
    488	int ret;
    489
    490	if (brcmstb_pm_handshake())
    491		return -EIO;
    492
    493	if (deep_standby)
    494		ret = brcmstb_pm_s3();
    495	else
    496		ret = brcmstb_pm_s2();
    497	if (ret)
    498		pr_err("%s: standby failed\n", __func__);
    499
    500	return ret;
    501}
    502
    503static int brcmstb_pm_enter(suspend_state_t state)
    504{
    505	int ret = -EINVAL;
    506
    507	switch (state) {
    508	case PM_SUSPEND_STANDBY:
    509		ret = brcmstb_pm_standby(false);
    510		break;
    511	case PM_SUSPEND_MEM:
    512		ret = brcmstb_pm_standby(true);
    513		break;
    514	}
    515
    516	return ret;
    517}
    518
    519static int brcmstb_pm_valid(suspend_state_t state)
    520{
    521	switch (state) {
    522	case PM_SUSPEND_STANDBY:
    523		return true;
    524	case PM_SUSPEND_MEM:
    525		return ctrl.support_warm_boot;
    526	default:
    527		return false;
    528	}
    529}
    530
    531static const struct platform_suspend_ops brcmstb_pm_ops = {
    532	.enter		= brcmstb_pm_enter,
    533	.valid		= brcmstb_pm_valid,
    534};
    535
    536static const struct of_device_id aon_ctrl_dt_ids[] = {
    537	{ .compatible = "brcm,brcmstb-aon-ctrl" },
    538	{}
    539};
    540
    541struct ddr_phy_ofdata {
    542	bool supports_warm_boot;
    543	size_t pll_status_offset;
    544	int s3entry_method;
    545	u32 warm_boot_offset;
    546	u32 phy_a_standby_ctrl_offs;
    547	u32 phy_b_standby_ctrl_offs;
    548};
    549
    550static struct ddr_phy_ofdata ddr_phy_71_1 = {
    551	.supports_warm_boot = true,
    552	.pll_status_offset = 0x0c,
    553	.s3entry_method = 1,
    554	.warm_boot_offset = 0x2c,
    555	.phy_a_standby_ctrl_offs = 0x198,
    556	.phy_b_standby_ctrl_offs = DDR_PHY_NO_CHANNEL
    557};
    558
    559static struct ddr_phy_ofdata ddr_phy_72_0 = {
    560	.supports_warm_boot = true,
    561	.pll_status_offset = 0x10,
    562	.s3entry_method = 1,
    563	.warm_boot_offset = 0x40,
    564	.phy_a_standby_ctrl_offs = 0x2a4,
    565	.phy_b_standby_ctrl_offs = 0x8a4
    566};
    567
    568static struct ddr_phy_ofdata ddr_phy_225_1 = {
    569	.supports_warm_boot = false,
    570	.pll_status_offset = 0x4,
    571	.s3entry_method = 0
    572};
    573
    574static struct ddr_phy_ofdata ddr_phy_240_1 = {
    575	.supports_warm_boot = true,
    576	.pll_status_offset = 0x4,
    577	.s3entry_method = 0
    578};
    579
    580static const struct of_device_id ddr_phy_dt_ids[] = {
    581	{
    582		.compatible = "brcm,brcmstb-ddr-phy-v71.1",
    583		.data = &ddr_phy_71_1,
    584	},
    585	{
    586		.compatible = "brcm,brcmstb-ddr-phy-v72.0",
    587		.data = &ddr_phy_72_0,
    588	},
    589	{
    590		.compatible = "brcm,brcmstb-ddr-phy-v225.1",
    591		.data = &ddr_phy_225_1,
    592	},
    593	{
    594		.compatible = "brcm,brcmstb-ddr-phy-v240.1",
    595		.data = &ddr_phy_240_1,
    596	},
    597	{
    598		/* Same as v240.1, for the registers we care about */
    599		.compatible = "brcm,brcmstb-ddr-phy-v240.2",
    600		.data = &ddr_phy_240_1,
    601	},
    602	{}
    603};
    604
    605struct ddr_seq_ofdata {
    606	bool needs_ddr_pad;
    607	u32 warm_boot_offset;
    608};
    609
    610static const struct ddr_seq_ofdata ddr_seq_b22 = {
    611	.needs_ddr_pad = false,
    612	.warm_boot_offset = 0x2c,
    613};
    614
    615static const struct ddr_seq_ofdata ddr_seq = {
    616	.needs_ddr_pad = true,
    617};
    618
    619static const struct of_device_id ddr_shimphy_dt_ids[] = {
    620	{ .compatible = "brcm,brcmstb-ddr-shimphy-v1.0" },
    621	{}
    622};
    623
    624static const struct of_device_id brcmstb_memc_of_match[] = {
    625	{
    626		.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.1",
    627		.data = &ddr_seq,
    628	},
    629	{
    630		.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.2",
    631		.data = &ddr_seq_b22,
    632	},
    633	{
    634		.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.3",
    635		.data = &ddr_seq_b22,
    636	},
    637	{
    638		.compatible = "brcm,brcmstb-memc-ddr-rev-b.3.0",
    639		.data = &ddr_seq_b22,
    640	},
    641	{
    642		.compatible = "brcm,brcmstb-memc-ddr-rev-b.3.1",
    643		.data = &ddr_seq_b22,
    644	},
    645	{
    646		.compatible = "brcm,brcmstb-memc-ddr",
    647		.data = &ddr_seq,
    648	},
    649	{},
    650};
    651
    652static void __iomem *brcmstb_ioremap_match(const struct of_device_id *matches,
    653					   int index, const void **ofdata)
    654{
    655	struct device_node *dn;
    656	const struct of_device_id *match;
    657
    658	dn = of_find_matching_node_and_match(NULL, matches, &match);
    659	if (!dn)
    660		return ERR_PTR(-EINVAL);
    661
    662	if (ofdata)
    663		*ofdata = match->data;
    664
    665	return of_io_request_and_map(dn, index, dn->full_name);
    666}
    667
    668static int brcmstb_pm_panic_notify(struct notifier_block *nb,
    669		unsigned long action, void *data)
    670{
    671	writel_relaxed(BRCMSTB_PANIC_MAGIC, ctrl.aon_sram + AON_REG_PANIC);
    672
    673	return NOTIFY_DONE;
    674}
    675
    676static struct notifier_block brcmstb_pm_panic_nb = {
    677	.notifier_call = brcmstb_pm_panic_notify,
    678};
    679
    680static int brcmstb_pm_probe(struct platform_device *pdev)
    681{
    682	const struct ddr_phy_ofdata *ddr_phy_data;
    683	const struct ddr_seq_ofdata *ddr_seq_data;
    684	const struct of_device_id *of_id = NULL;
    685	struct device_node *dn;
    686	void __iomem *base;
    687	int ret, i;
    688
    689	/* AON ctrl registers */
    690	base = brcmstb_ioremap_match(aon_ctrl_dt_ids, 0, NULL);
    691	if (IS_ERR(base)) {
    692		pr_err("error mapping AON_CTRL\n");
    693		return PTR_ERR(base);
    694	}
    695	ctrl.aon_ctrl_base = base;
    696
    697	/* AON SRAM registers */
    698	base = brcmstb_ioremap_match(aon_ctrl_dt_ids, 1, NULL);
    699	if (IS_ERR(base)) {
    700		/* Assume standard offset */
    701		ctrl.aon_sram = ctrl.aon_ctrl_base +
    702				     AON_CTRL_SYSTEM_DATA_RAM_OFS;
    703	} else {
    704		ctrl.aon_sram = base;
    705	}
    706
    707	writel_relaxed(0, ctrl.aon_sram + AON_REG_PANIC);
    708
    709	/* DDR PHY registers */
    710	base = brcmstb_ioremap_match(ddr_phy_dt_ids, 0,
    711				     (const void **)&ddr_phy_data);
    712	if (IS_ERR(base)) {
    713		pr_err("error mapping DDR PHY\n");
    714		return PTR_ERR(base);
    715	}
    716	ctrl.support_warm_boot = ddr_phy_data->supports_warm_boot;
    717	ctrl.pll_status_offset = ddr_phy_data->pll_status_offset;
    718	/* Only need DDR PHY 0 for now? */
    719	ctrl.memcs[0].ddr_phy_base = base;
    720	ctrl.s3entry_method = ddr_phy_data->s3entry_method;
    721	ctrl.phy_a_standby_ctrl_offs = ddr_phy_data->phy_a_standby_ctrl_offs;
    722	ctrl.phy_b_standby_ctrl_offs = ddr_phy_data->phy_b_standby_ctrl_offs;
    723	/*
    724	 * Slightly grosss to use the phy ver to get a memc,
    725	 * offset but that is the only versioned things so far
    726	 * we can test for.
    727	 */
    728	ctrl.warm_boot_offset = ddr_phy_data->warm_boot_offset;
    729
    730	/* DDR SHIM-PHY registers */
    731	for_each_matching_node(dn, ddr_shimphy_dt_ids) {
    732		i = ctrl.num_memc;
    733		if (i >= MAX_NUM_MEMC) {
    734			pr_warn("too many MEMCs (max %d)\n", MAX_NUM_MEMC);
    735			break;
    736		}
    737
    738		base = of_io_request_and_map(dn, 0, dn->full_name);
    739		if (IS_ERR(base)) {
    740			if (!ctrl.support_warm_boot)
    741				break;
    742
    743			pr_err("error mapping DDR SHIMPHY %d\n", i);
    744			return PTR_ERR(base);
    745		}
    746		ctrl.memcs[i].ddr_shimphy_base = base;
    747		ctrl.num_memc++;
    748	}
    749
    750	/* Sequencer DRAM Param and Control Registers */
    751	i = 0;
    752	for_each_matching_node(dn, brcmstb_memc_of_match) {
    753		base = of_iomap(dn, 0);
    754		if (!base) {
    755			pr_err("error mapping DDR Sequencer %d\n", i);
    756			return -ENOMEM;
    757		}
    758
    759		of_id = of_match_node(brcmstb_memc_of_match, dn);
    760		if (!of_id) {
    761			iounmap(base);
    762			return -EINVAL;
    763		}
    764
    765		ddr_seq_data = of_id->data;
    766		ctrl.needs_ddr_pad = ddr_seq_data->needs_ddr_pad;
    767		/* Adjust warm boot offset based on the DDR sequencer */
    768		if (ddr_seq_data->warm_boot_offset)
    769			ctrl.warm_boot_offset = ddr_seq_data->warm_boot_offset;
    770
    771		ctrl.memcs[i].ddr_ctrl = base;
    772		i++;
    773	}
    774
    775	pr_debug("PM: supports warm boot:%d, method:%d, wboffs:%x\n",
    776		ctrl.support_warm_boot, ctrl.s3entry_method,
    777		ctrl.warm_boot_offset);
    778
    779	dn = of_find_matching_node(NULL, sram_dt_ids);
    780	if (!dn) {
    781		pr_err("SRAM not found\n");
    782		return -EINVAL;
    783	}
    784
    785	ret = brcmstb_init_sram(dn);
    786	of_node_put(dn);
    787	if (ret) {
    788		pr_err("error setting up SRAM for PM\n");
    789		return ret;
    790	}
    791
    792	ctrl.pdev = pdev;
    793
    794	ctrl.s3_params = kmalloc(sizeof(*ctrl.s3_params), GFP_KERNEL);
    795	if (!ctrl.s3_params)
    796		return -ENOMEM;
    797	ctrl.s3_params_pa = dma_map_single(&pdev->dev, ctrl.s3_params,
    798					   sizeof(*ctrl.s3_params),
    799					   DMA_TO_DEVICE);
    800	if (dma_mapping_error(&pdev->dev, ctrl.s3_params_pa)) {
    801		pr_err("error mapping DMA memory\n");
    802		ret = -ENOMEM;
    803		goto out;
    804	}
    805
    806	atomic_notifier_chain_register(&panic_notifier_list,
    807				       &brcmstb_pm_panic_nb);
    808
    809	pm_power_off = brcmstb_pm_poweroff;
    810	suspend_set_ops(&brcmstb_pm_ops);
    811
    812	return 0;
    813
    814out:
    815	kfree(ctrl.s3_params);
    816
    817	pr_warn("PM: initialization failed with code %d\n", ret);
    818
    819	return ret;
    820}
    821
    822static struct platform_driver brcmstb_pm_driver = {
    823	.driver = {
    824		.name	= "brcmstb-pm",
    825		.of_match_table = aon_ctrl_dt_ids,
    826	},
    827};
    828
    829static int __init brcmstb_pm_init(void)
    830{
    831	return platform_driver_probe(&brcmstb_pm_driver,
    832				     brcmstb_pm_probe);
    833}
    834module_init(brcmstb_pm_init);