summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Schmitt <B43082@freescale.com>2014-11-06 17:33:48 (GMT)
committerMatthew Weigel <Matthew.Weigel@freescale.com>2014-12-11 18:40:23 (GMT)
commitfe66d670380dabdacbc74d67a24b5cbc89acabfb (patch)
tree645b2b422feca723bba4c7cbddc588971006f188
parentcc3516a4dfcf877e98c06183ea4cdc1408cdc6c8 (diff)
parent7b9ae59617188d40735351e2401202ae70d629cd (diff)
downloadlinux-fsl-qoriq-fe66d670380dabdacbc74d67a24b5cbc89acabfb.tar.xz
Merge remote-tracking branch 'linux-pm/sdk-v1.6.x'
-rw-r--r--arch/powerpc/platforms/85xx/deepsleep.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/85xx/deepsleep.c b/arch/powerpc/platforms/85xx/deepsleep.c
index cbd0c2a..454c070 100644
--- a/arch/powerpc/platforms/85xx/deepsleep.c
+++ b/arch/powerpc/platforms/85xx/deepsleep.c
@@ -41,6 +41,15 @@
#define CSTTACR0 0xb00
#define CG1CR0 0x31c
+#define CCSR_LAW_BASE 0xC00
+#define DCFG_BRR 0xE4 /* boot release register */
+#define LCC_BSTRH 0x20 /* Boot space translation register high */
+#define LCC_BSTRL 0x24 /* Boot space translation register low */
+#define LCC_BSTAR 0x28 /* Boot space translation attribute register */
+#define RCPM_PCTBENR 0x1A0 /* Physical Core Timebase Enable Register */
+#define RCPM_BASE 0xE2000
+#define DCFG_BASE 0xE0000
+
/* 128 bytes buffer for restoring data broke by DDR training initialization */
#define DDR_BUF_SIZE 128
static u8 ddr_buff[DDR_BUF_SIZE] __aligned(64);
@@ -48,6 +57,26 @@ static u8 ddr_buff[DDR_BUF_SIZE] __aligned(64);
static void *dcsr_base, *ccsr_base, *pld_base;
static int pld_flag;
+/* for law */
+struct fsl_law {
+ u32 lawbarh; /* LAWn base address high */
+ u32 lawbarl; /* LAWn base address low */
+ u32 lawar; /* LAWn attributes */
+ u32 reserved;
+};
+
+struct fsl_law *saved_law;
+static u32 num_laws;
+
+/* for nonboot cpu */
+struct fsl_bstr {
+ u32 bstrh;
+ u32 bstrl;
+ u32 bstar;
+ u32 cpu_mask;
+};
+static struct fsl_bstr saved_bstr;
+
int fsl_dp_iomap(void)
{
struct device_node *np;
@@ -95,6 +124,25 @@ int fsl_dp_iomap(void)
pld_base = of_iomap(np, 0);
of_node_put(np);
+ np = of_find_compatible_node(NULL, NULL, "fsl,corenet-law");
+ if (!np) {
+ pr_err("%s: Can't find the node of \"law\"\n", __func__);
+ ret = -EINVAL;
+ goto pld_err;
+ }
+ ret = of_property_read_u32(np, "fsl,num-laws", &num_laws);
+ if (ret) {
+ ret = -EINVAL;
+ goto pld_err;
+ }
+
+ saved_law = kzalloc(sizeof(*saved_law) * num_laws, GFP_KERNEL);
+ if (!saved_law) {
+ ret = -ENOMEM;
+ goto pld_err;
+ }
+ of_node_put(np);
+
return 0;
pld_err:
@@ -148,6 +196,67 @@ static void fsl_dp_ddr_save(void *ccsr_base)
out_be32(ccsr_base + CCSR_SCFG_SPARECR3, ddr_buff_addr);
}
+static void fsl_dp_mp_save(void *ccsr)
+{
+ struct fsl_bstr *dst = &saved_bstr;
+
+ dst->bstrh = in_be32(ccsr + LCC_BSTRH);
+ dst->bstrl = in_be32(ccsr + LCC_BSTRL);
+ dst->bstar = in_be32(ccsr + LCC_BSTAR);
+ dst->cpu_mask = in_be32(ccsr + DCFG_BASE + DCFG_BRR);
+}
+
+static void fsl_dp_mp_restore(void *ccsr)
+{
+ struct fsl_bstr *src = &saved_bstr;
+
+ out_be32(ccsr + LCC_BSTRH, src->bstrh);
+ out_be32(ccsr + LCC_BSTRL, src->bstrl);
+ out_be32(ccsr + LCC_BSTAR, src->bstar);
+
+ /* release the nonboot cpus */
+ out_be32(ccsr + DCFG_BASE + DCFG_BRR, src->cpu_mask);
+
+ /* enable the time base */
+ out_be32(ccsr + RCPM_BASE + RCPM_PCTBENR, src->cpu_mask);
+ /* read back to sync write */
+ in_be32(ccsr + RCPM_BASE + RCPM_PCTBENR);
+}
+
+static void fsl_dp_law_save(void *ccsr)
+{
+ int i;
+ struct fsl_law *dst = saved_law;
+ struct fsl_law *src = (void *)(ccsr + CCSR_LAW_BASE);
+
+ for (i = 0; i < num_laws; i++) {
+ dst->lawbarh = in_be32(&src->lawbarh);
+ dst->lawbarl = in_be32(&src->lawbarl);
+ dst->lawar = in_be32(&src->lawar);
+ dst++;
+ src++;
+ }
+}
+
+static void fsl_dp_law_restore(void *ccsr)
+{
+ int i;
+ struct fsl_law *src = saved_law;
+ struct fsl_law *dst = (void *)(ccsr + CCSR_LAW_BASE);
+
+ for (i = 0; i < num_laws - 1; i++) {
+ out_be32(&dst->lawar, 0);
+ out_be32(&dst->lawbarl, src->lawbarl);
+ out_be32(&dst->lawbarh, src->lawbarh);
+ out_be32(&dst->lawar, src->lawar);
+
+ /* Read back so that we sync the writes */
+ in_be32(&dst->lawar);
+ src++;
+ dst++;
+ }
+}
+
static void fsl_dp_set_resume_pointer(void *ccsr_base)
{
u32 resume_addr;
@@ -171,6 +280,8 @@ int fsl_enter_epu_deepsleep(void)
fsl_dp_set_resume_pointer(ccsr_base);
+ fsl_dp_mp_save(ccsr_base);
+ fsl_dp_law_save(ccsr_base);
/* enable Warm Device Reset request. */
setbits32(ccsr_base + CCSR_SCFG_DPSLPCR, CCSR_SCFG_DPSLPCR_WDRR_EN);
@@ -193,6 +304,9 @@ int fsl_enter_epu_deepsleep(void)
fsl_dp_enter_low(ccsr_base, dcsr_base, pld_base, pld_flag);
+ fsl_dp_law_restore(ccsr_base);
+ fsl_dp_mp_restore(ccsr_base);
+
/* disable Warm Device Reset request */
clrbits32(ccsr_base + CCSR_SCFG_DPSLPCR, CCSR_SCFG_DPSLPCR_WDRR_EN);