Merge remote-tracking branch 'origin/arch/qoriq' into arch/next
* origin/arch/qoriq: (17 commits) drivers: soc: fsl: add qixis driver Add APIs to setup HugeTLB mappings for USDPAA powerpc/pm: add sleep and deep sleep on QorIQ SoCs powerpc/cache: add cache flush operation for various e500 powerpc/pm: Fix suspend=n in menuconfig for e500mc platforms. ...5.4-rM2-2.2.x-imx-squashed
commit
7e3b1c91d0
|
@ -85,6 +85,22 @@ extern void __bad_udelay(void);
|
|||
__const_udelay((n) * UDELAY_MULT)) : \
|
||||
__udelay(n))
|
||||
|
||||
#define spin_event_timeout(condition, timeout, delay) \
|
||||
({ \
|
||||
typeof(condition) __ret; \
|
||||
int i = 0; \
|
||||
while (!(__ret = (condition)) && (i++ < timeout)) { \
|
||||
if (delay) \
|
||||
udelay(delay); \
|
||||
else \
|
||||
cpu_relax(); \
|
||||
udelay(1); \
|
||||
} \
|
||||
if (!__ret) \
|
||||
__ret = (condition); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Loop-based definitions for assembly code. */
|
||||
extern void __loop_delay(unsigned long loops);
|
||||
extern void __loop_udelay(unsigned long usecs);
|
||||
|
|
|
@ -123,6 +123,7 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)
|
|||
#define MT_DEVICE_NONSHARED 1
|
||||
#define MT_DEVICE_CACHED 2
|
||||
#define MT_DEVICE_WC 3
|
||||
#define MT_MEMORY_RW_NS 4
|
||||
/*
|
||||
* types 4 onwards can be found in asm/mach/map.h and are undefined
|
||||
* for ioremap
|
||||
|
@ -224,6 +225,34 @@ void __iomem *pci_remap_cfgspace(resource_size_t res_cookie, size_t size);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/* access ports */
|
||||
#define setbits32(_addr, _v) iowrite32be(ioread32be(_addr) | (_v), (_addr))
|
||||
#define clrbits32(_addr, _v) iowrite32be(ioread32be(_addr) & ~(_v), (_addr))
|
||||
|
||||
#define setbits16(_addr, _v) iowrite16be(ioread16be(_addr) | (_v), (_addr))
|
||||
#define clrbits16(_addr, _v) iowrite16be(ioread16be(_addr) & ~(_v), (_addr))
|
||||
|
||||
#define setbits8(_addr, _v) iowrite8(ioread8(_addr) | (_v), (_addr))
|
||||
#define clrbits8(_addr, _v) iowrite8(ioread8(_addr) & ~(_v), (_addr))
|
||||
|
||||
/* Clear and set bits in one shot. These macros can be used to clear and
|
||||
* set multiple bits in a register using a single read-modify-write. These
|
||||
* macros can also be used to set a multiple-bit bit pattern using a mask,
|
||||
* by specifying the mask in the 'clear' parameter and the new bit pattern
|
||||
* in the 'set' parameter.
|
||||
*/
|
||||
|
||||
#define clrsetbits_be32(addr, clear, set) \
|
||||
iowrite32be((ioread32be(addr) & ~(clear)) | (set), (addr))
|
||||
#define clrsetbits_le32(addr, clear, set) \
|
||||
iowrite32le((ioread32le(addr) & ~(clear)) | (set), (addr))
|
||||
#define clrsetbits_be16(addr, clear, set) \
|
||||
iowrite16be((ioread16be(addr) & ~(clear)) | (set), (addr))
|
||||
#define clrsetbits_le16(addr, clear, set) \
|
||||
iowrite16le((ioread16le(addr) & ~(clear)) | (set), (addr))
|
||||
#define clrsetbits_8(addr, clear, set) \
|
||||
iowrite8((ioread8(addr) & ~(clear)) | (set), (addr))
|
||||
|
||||
/*
|
||||
* IO port access primitives
|
||||
* -------------------------
|
||||
|
@ -410,6 +439,8 @@ void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size);
|
|||
#define ioremap_wc ioremap_wc
|
||||
#define ioremap_wt ioremap_wc
|
||||
|
||||
void __iomem *ioremap_cache_ns(resource_size_t res_cookie, size_t size);
|
||||
|
||||
void iounmap(volatile void __iomem *iomem_cookie);
|
||||
#define iounmap iounmap
|
||||
|
||||
|
|
|
@ -18,9 +18,9 @@ struct map_desc {
|
|||
unsigned int type;
|
||||
};
|
||||
|
||||
/* types 0-3 are defined in asm/io.h */
|
||||
/* types 0-4 are defined in asm/io.h */
|
||||
enum {
|
||||
MT_UNCACHED = 4,
|
||||
MT_UNCACHED = 5,
|
||||
MT_CACHECLEAN,
|
||||
MT_MINICLEAN,
|
||||
MT_LOW_VECTORS,
|
||||
|
|
|
@ -116,6 +116,13 @@ extern pgprot_t pgprot_s2_device;
|
|||
#define pgprot_noncached(prot) \
|
||||
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
|
||||
|
||||
#define pgprot_cached(prot) \
|
||||
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_DEV_CACHED)
|
||||
|
||||
#define pgprot_cached_ns(prot) \
|
||||
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_DEV_CACHED | \
|
||||
L_PTE_MT_DEV_NONSHARED)
|
||||
|
||||
#define pgprot_writecombine(prot) \
|
||||
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* reading the RTC at bootup, etc...
|
||||
*/
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/export.h>
|
||||
|
@ -107,5 +108,7 @@ void __init time_init(void)
|
|||
of_clk_init(NULL);
|
||||
#endif
|
||||
timer_probe();
|
||||
|
||||
tick_setup_hrtimer_broadcast();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2320,6 +2320,7 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
|
|||
#endif
|
||||
dev->archdata.dma_ops_setup = true;
|
||||
}
|
||||
EXPORT_SYMBOL(arch_setup_dma_ops);
|
||||
|
||||
void arch_teardown_dma_ops(struct device *dev)
|
||||
{
|
||||
|
|
|
@ -399,6 +399,13 @@ void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size)
|
|||
}
|
||||
EXPORT_SYMBOL(ioremap_wc);
|
||||
|
||||
void __iomem *ioremap_cache_ns(resource_size_t res_cookie, size_t size)
|
||||
{
|
||||
return arch_ioremap_caller(res_cookie, size, MT_MEMORY_RW_NS,
|
||||
__builtin_return_address(0));
|
||||
}
|
||||
EXPORT_SYMBOL(ioremap_cache_ns);
|
||||
|
||||
/*
|
||||
* Remap an arbitrary physical address space into the kernel virtual
|
||||
* address space as memory. Needed when the kernel wants to execute
|
||||
|
|
|
@ -312,6 +312,13 @@ static struct mem_type mem_types[] __ro_after_init = {
|
|||
.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
|
||||
.domain = DOMAIN_KERNEL,
|
||||
},
|
||||
[MT_MEMORY_RW_NS] = {
|
||||
.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
|
||||
L_PTE_XN,
|
||||
.prot_l1 = PMD_TYPE_TABLE,
|
||||
.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_XN,
|
||||
.domain = DOMAIN_KERNEL,
|
||||
},
|
||||
[MT_ROM] = {
|
||||
.prot_sect = PMD_TYPE_SECT,
|
||||
.domain = DOMAIN_KERNEL,
|
||||
|
@ -648,6 +655,7 @@ static void __init build_mem_type_table(void)
|
|||
}
|
||||
kern_pgprot |= PTE_EXT_AF;
|
||||
vecs_pgprot |= PTE_EXT_AF;
|
||||
mem_types[MT_MEMORY_RW_NS].prot_pte |= PTE_EXT_AF | cp->pte;
|
||||
|
||||
/*
|
||||
* Set PXN for user mappings
|
||||
|
@ -676,6 +684,7 @@ static void __init build_mem_type_table(void)
|
|||
mem_types[MT_MEMORY_RWX].prot_pte |= kern_pgprot;
|
||||
mem_types[MT_MEMORY_RW].prot_sect |= ecc_mask | cp->pmd;
|
||||
mem_types[MT_MEMORY_RW].prot_pte |= kern_pgprot;
|
||||
mem_types[MT_MEMORY_RW_NS].prot_sect |= ecc_mask | cp->pmd;
|
||||
mem_types[MT_MEMORY_DMA_READY].prot_pte |= kern_pgprot;
|
||||
mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= ecc_mask;
|
||||
mem_types[MT_ROM].prot_sect |= cp->pmd;
|
||||
|
|
|
@ -170,6 +170,7 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
|
|||
#define ioremap_nocache(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
|
||||
#define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
|
||||
#define ioremap_wt(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
|
||||
#define ioremap_cache_ns(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NS))
|
||||
|
||||
/*
|
||||
* PCI configuration space mapping function.
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC))
|
||||
#define PROT_NORMAL_WT (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT))
|
||||
#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL))
|
||||
#define PROT_NORMAL_NS (PTE_TYPE_PAGE | PTE_AF | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL))
|
||||
|
||||
#define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE))
|
||||
#define PROT_SECT_NORMAL (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL))
|
||||
|
@ -77,6 +78,7 @@
|
|||
})
|
||||
|
||||
#define PAGE_S2 __pgprot(_PROT_DEFAULT | PAGE_S2_MEMATTR(NORMAL) | PTE_S2_RDONLY | PAGE_S2_XN)
|
||||
#define PAGE_S2_NS __pgprot(PAGE_S2_MEMATTR(NORMAL) | PTE_S2_RDWR | PTE_TYPE_PAGE | PTE_AF)
|
||||
#define PAGE_S2_DEVICE __pgprot(_PROT_DEFAULT | PAGE_S2_MEMATTR(DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_S2_XN)
|
||||
|
||||
#define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN)
|
||||
|
|
|
@ -418,6 +418,11 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd)
|
|||
__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN)
|
||||
#define pgprot_writecombine(prot) \
|
||||
__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN)
|
||||
#define pgprot_cached(prot) \
|
||||
__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL) | \
|
||||
PTE_PXN | PTE_UXN)
|
||||
#define pgprot_cached_ns(prot) \
|
||||
__pgprot(pgprot_val(pgprot_cached(prot)) ^ PTE_SHARED)
|
||||
#define pgprot_device(prot) \
|
||||
__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_PXN | PTE_UXN)
|
||||
/*
|
||||
|
|
|
@ -57,3 +57,4 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
|
|||
dev->dma_ops = &xen_swiotlb_dma_ops;
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(arch_setup_dma_ops);
|
||||
|
|
|
@ -322,7 +322,7 @@ config ARCH_HIBERNATION_POSSIBLE
|
|||
config ARCH_SUSPEND_POSSIBLE
|
||||
def_bool y
|
||||
depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
|
||||
(PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \
|
||||
FSL_SOC_BOOKE || PPC_86xx || PPC_PSERIES \
|
||||
|| 44x || 40x
|
||||
|
||||
config ARCH_SUSPEND_NONZERO_CPU
|
||||
|
@ -977,8 +977,6 @@ config FSL_PCI
|
|||
|
||||
config FSL_PMC
|
||||
bool
|
||||
default y
|
||||
depends on SUSPEND && (PPC_85xx || PPC_86xx)
|
||||
help
|
||||
Freescale MPC85xx/MPC86xx power management controller support
|
||||
(suspend/resume). For MPC83xx see platforms/83xx/suspend.c
|
||||
|
|
|
@ -42,6 +42,13 @@ extern void flush_dcache_page(struct page *page);
|
|||
#define flush_dcache_mmap_lock(mapping) do { } while (0)
|
||||
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
||||
|
||||
extern void __flush_disable_L1(void);
|
||||
#ifdef CONFIG_FSL_SOC_BOOKE
|
||||
extern void flush_dcache_L1(void);
|
||||
#else
|
||||
#define flush_dcache_L1() do { } while (0)
|
||||
#endif
|
||||
|
||||
extern void flush_icache_range(unsigned long, unsigned long);
|
||||
extern void flush_icache_user_range(struct vm_area_struct *vma,
|
||||
struct page *page, unsigned long addr,
|
||||
|
|
|
@ -43,6 +43,14 @@ extern int machine_check_e500mc(struct pt_regs *regs);
|
|||
extern int machine_check_e500(struct pt_regs *regs);
|
||||
extern int machine_check_e200(struct pt_regs *regs);
|
||||
extern int machine_check_47x(struct pt_regs *regs);
|
||||
|
||||
#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC)
|
||||
extern void __flush_caches_e500v2(void);
|
||||
extern void __flush_caches_e500mc(void);
|
||||
extern void __flush_caches_e5500(void);
|
||||
extern void __flush_caches_e6500(void);
|
||||
#endif
|
||||
|
||||
int machine_check_8xx(struct pt_regs *regs);
|
||||
int machine_check_83xx(struct pt_regs *regs);
|
||||
|
||||
|
@ -70,6 +78,10 @@ struct cpu_spec {
|
|||
/* flush caches inside the current cpu */
|
||||
void (*cpu_down_flush)(void);
|
||||
|
||||
#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC)
|
||||
/* flush caches of the cpu which is running the function */
|
||||
void (*cpu_flush_caches)(void);
|
||||
#endif
|
||||
/* number of performance monitor counters */
|
||||
unsigned int num_pmcs;
|
||||
enum powerpc_pmc_type pmc_type;
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#ifndef __PPC_FSL_PM_H
|
||||
#define __PPC_FSL_PM_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#define E500_PM_PH10 1
|
||||
#define E500_PM_PH15 2
|
||||
#define E500_PM_PH20 3
|
||||
|
@ -42,6 +45,34 @@ struct fsl_pm_ops {
|
|||
|
||||
extern const struct fsl_pm_ops *qoriq_pm_ops;
|
||||
|
||||
struct fsm_reg_vals {
|
||||
u32 offset;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
void fsl_fsm_setup(void __iomem *base, struct fsm_reg_vals *val);
|
||||
void fsl_epu_setup_default(void __iomem *epu_base);
|
||||
void fsl_npc_setup_default(void __iomem *npc_base);
|
||||
void fsl_fsm_clean(void __iomem *base, struct fsm_reg_vals *val);
|
||||
void fsl_epu_clean_default(void __iomem *epu_base);
|
||||
|
||||
extern int fsl_dp_iomap(void);
|
||||
extern void fsl_dp_iounmap(void);
|
||||
|
||||
extern int fsl_enter_epu_deepsleep(void);
|
||||
extern void fsl_dp_enter_low(void __iomem *ccsr_base, void __iomem *dcsr_base,
|
||||
void __iomem *pld_base, int pld_flag);
|
||||
extern void fsl_booke_deep_sleep_resume(void);
|
||||
|
||||
int __init fsl_rcpm_init(void);
|
||||
|
||||
void set_pm_suspend_state(suspend_state_t state);
|
||||
suspend_state_t pm_suspend_state(void);
|
||||
|
||||
void fsl_set_power_except(struct device *dev, int on);
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#define T1040QDS_TETRA_FLAG 1
|
||||
#define T104xRDB_CPLD_FLAG 2
|
||||
|
||||
#endif /* __PPC_FSL_PM_H */
|
||||
|
|
|
@ -81,6 +81,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
|
|||
ifneq ($(CONFIG_FA_DUMP)$(CONFIG_PRESERVE_FA_DUMP),)
|
||||
obj-y += fadump.o
|
||||
endif
|
||||
obj-$(CONFIG_FSL_SOC) += fsl_pm.o
|
||||
ifdef CONFIG_PPC32
|
||||
obj-$(CONFIG_E500) += idle_e500.o
|
||||
endif
|
||||
|
|
|
@ -365,6 +365,9 @@ int main(void)
|
|||
OFFSET(CPU_SPEC_FEATURES, cpu_spec, cpu_features);
|
||||
OFFSET(CPU_SPEC_SETUP, cpu_spec, cpu_setup);
|
||||
OFFSET(CPU_SPEC_RESTORE, cpu_spec, cpu_restore);
|
||||
#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC)
|
||||
OFFSET(CPU_FLUSH_CACHES, cpu_spec, cpu_flush_caches);
|
||||
#endif
|
||||
|
||||
OFFSET(pbe_address, pbe, address);
|
||||
OFFSET(pbe_orig_address, pbe, orig_address);
|
||||
|
|
|
@ -340,3 +340,84 @@ _GLOBAL(cpu_down_flush_e5500)
|
|||
/* L1 Data Cache of e6500 contains no modified data, no flush is required */
|
||||
_GLOBAL(cpu_down_flush_e6500)
|
||||
blr
|
||||
|
||||
_GLOBAL(__flush_caches_e500v2)
|
||||
mflr r0
|
||||
bl flush_dcache_L1
|
||||
mtlr r0
|
||||
blr
|
||||
|
||||
_GLOBAL(__flush_caches_e500mc)
|
||||
_GLOBAL(__flush_caches_e5500)
|
||||
mflr r0
|
||||
bl flush_dcache_L1
|
||||
bl flush_backside_L2_cache
|
||||
mtlr r0
|
||||
blr
|
||||
|
||||
/* L1 Data Cache of e6500 contains no modified data, no flush is required */
|
||||
_GLOBAL(__flush_caches_e6500)
|
||||
blr
|
||||
|
||||
/* r3 = virtual address of L2 controller, WIMG = 01xx */
|
||||
_GLOBAL(flush_disable_L2)
|
||||
/* It's a write-through cache, so only invalidation is needed. */
|
||||
mbar
|
||||
isync
|
||||
lwz r4, 0(r3)
|
||||
li r5, 1
|
||||
rlwimi r4, r5, 30, 0xc0000000
|
||||
stw r4, 0(r3)
|
||||
|
||||
/* Wait for the invalidate to finish */
|
||||
1: lwz r4, 0(r3)
|
||||
andis. r4, r4, 0x4000
|
||||
bne 1b
|
||||
mbar
|
||||
|
||||
blr
|
||||
|
||||
/* r3 = virtual address of L2 controller, WIMG = 01xx */
|
||||
_GLOBAL(invalidate_enable_L2)
|
||||
mbar
|
||||
isync
|
||||
lwz r4, 0(r3)
|
||||
li r5, 3
|
||||
rlwimi r4, r5, 30, 0xc0000000
|
||||
stw r4, 0(r3)
|
||||
|
||||
/* Wait for the invalidate to finish */
|
||||
1: lwz r4, 0(r3)
|
||||
andis. r4, r4, 0x4000
|
||||
bne 1b
|
||||
mbar
|
||||
|
||||
blr
|
||||
|
||||
/* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
|
||||
_GLOBAL(__flush_disable_L1)
|
||||
mflr r10
|
||||
bl flush_dcache_L1 /* Flush L1 d-cache */
|
||||
mtlr r10
|
||||
|
||||
mfspr r4, SPRN_L1CSR0 /* Invalidate and disable d-cache */
|
||||
li r5, 2
|
||||
rlwimi r4, r5, 0, 3
|
||||
|
||||
msync
|
||||
isync
|
||||
mtspr SPRN_L1CSR0, r4
|
||||
isync
|
||||
|
||||
1: mfspr r4, SPRN_L1CSR0 /* Wait for the invalidate to finish */
|
||||
andi. r4, r4, 2
|
||||
bne 1b
|
||||
|
||||
mfspr r4, SPRN_L1CSR1 /* Invalidate and disable i-cache */
|
||||
li r5, 2
|
||||
rlwimi r4, r5, 0, 3
|
||||
|
||||
mtspr SPRN_L1CSR1, r4
|
||||
isync
|
||||
|
||||
blr
|
||||
|
|
|
@ -2051,6 +2051,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
|||
.machine_check = machine_check_e500,
|
||||
.platform = "ppc8548",
|
||||
.cpu_down_flush = cpu_down_flush_e500v2,
|
||||
.cpu_flush_caches = __flush_caches_e500v2,
|
||||
},
|
||||
#else
|
||||
{ /* e500mc */
|
||||
|
@ -2071,6 +2072,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
|||
.machine_check = machine_check_e500mc,
|
||||
.platform = "ppce500mc",
|
||||
.cpu_down_flush = cpu_down_flush_e500mc,
|
||||
.cpu_flush_caches = __flush_caches_e500mc,
|
||||
},
|
||||
#endif /* CONFIG_PPC_E500MC */
|
||||
#endif /* CONFIG_PPC32 */
|
||||
|
@ -2096,6 +2098,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
|||
.machine_check = machine_check_e500mc,
|
||||
.platform = "ppce5500",
|
||||
.cpu_down_flush = cpu_down_flush_e5500,
|
||||
.cpu_flush_caches = __flush_caches_e5500,
|
||||
},
|
||||
{ /* e6500 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
|
@ -2119,6 +2122,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
|||
.machine_check = machine_check_e500mc,
|
||||
.platform = "ppce6500",
|
||||
.cpu_down_flush = cpu_down_flush_e6500,
|
||||
.cpu_flush_caches = __flush_caches_e6500,
|
||||
},
|
||||
#endif /* CONFIG_PPC_E500MC */
|
||||
#ifdef CONFIG_PPC32
|
||||
|
|
|
@ -174,6 +174,10 @@ skpinv: addi r6,r6,1 /* Increment */
|
|||
lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_NEEDED)@h
|
||||
ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_NEEDED)@l
|
||||
mtspr SPRN_MAS2,r6
|
||||
#ifdef ENTRY_DEEPSLEEP_SETUP
|
||||
LOAD_REG_IMMEDIATE(r8, MEMORY_START)
|
||||
ori r8,r8,(MAS3_SX|MAS3_SW|MAS3_SR)
|
||||
#endif
|
||||
mtspr SPRN_MAS3,r8
|
||||
tlbwe
|
||||
|
||||
|
@ -216,12 +220,18 @@ next_tlb_setup:
|
|||
#error You need to specify the mapping or not use this at all.
|
||||
#endif
|
||||
|
||||
#ifdef ENTRY_DEEPSLEEP_SETUP
|
||||
LOAD_REG_ADDR(r6, 2f)
|
||||
mfmsr r7
|
||||
rlwinm r7,r7,0,~(MSR_IS|MSR_DS)
|
||||
#else
|
||||
lis r7,MSR_KERNEL@h
|
||||
ori r7,r7,MSR_KERNEL@l
|
||||
bl 1f /* Find our address */
|
||||
1: mflr r9
|
||||
rlwimi r6,r9,0,20,31
|
||||
addi r6,r6,(2f - 1b)
|
||||
#endif
|
||||
mtspr SPRN_SRR0,r6
|
||||
mtspr SPRN_SRR1,r7
|
||||
rfi /* start execution out of TLB1[0] entry */
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Freescale General Power Management Implementation
|
||||
*
|
||||
* Copyright 2018 NXP
|
||||
* Author: Wang Dongsheng <dongsheng.wang@freescale.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the above-listed copyright holders nor the
|
||||
* names of any contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation, either version 2 of that License or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <linux/suspend.h>
|
||||
#include <asm/fsl_pm.h>
|
||||
|
||||
static suspend_state_t pm_state;
|
||||
|
||||
void set_pm_suspend_state(suspend_state_t state)
|
||||
{
|
||||
pm_state = state;
|
||||
}
|
||||
|
||||
suspend_state_t pm_suspend_state(void)
|
||||
{
|
||||
return pm_state;
|
||||
}
|
|
@ -860,7 +860,7 @@ _GLOBAL(start_secondary_resume)
|
|||
/*
|
||||
* This subroutine clobbers r11 and r12
|
||||
*/
|
||||
enable_64b_mode:
|
||||
_GLOBAL(enable_64b_mode)
|
||||
mfmsr r11 /* grab the current MSR */
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
oris r11,r11,0x8000 /* CM bit set, we'll set ICM later */
|
||||
|
|
|
@ -89,6 +89,12 @@ void print_system_hash_info(void);
|
|||
|
||||
#endif /* CONFIG_PPC_MMU_NOHASH */
|
||||
|
||||
void settlbcam(int index, unsigned long virt, phys_addr_t phys,
|
||||
unsigned long size, unsigned long flags, unsigned int pid);
|
||||
|
||||
void cleartlbcam(unsigned long virt, unsigned int pid);
|
||||
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
|
||||
void hash_preload(struct mm_struct *mm, unsigned long ea);
|
||||
|
|
|
@ -102,7 +102,7 @@ unsigned long p_block_mapped(phys_addr_t pa)
|
|||
* an unsigned long (for example, 32-bit implementations cannot support a 4GB
|
||||
* size).
|
||||
*/
|
||||
static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
|
||||
void settlbcam(int index, unsigned long virt, phys_addr_t phys,
|
||||
unsigned long size, unsigned long flags, unsigned int pid)
|
||||
{
|
||||
unsigned int tsize;
|
||||
|
@ -140,6 +140,18 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
|
|||
tlbcam_addrs[index].phys = phys;
|
||||
}
|
||||
|
||||
void cleartlbcam(unsigned long virt, unsigned int pid)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < NUM_TLBCAMS; i++) {
|
||||
if (tlbcam_addrs[i].start == virt) {
|
||||
TLBCAM[i].MAS1 = 0;
|
||||
loadcam_entry(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
|
||||
phys_addr_t phys)
|
||||
{
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
#include <soc/fsl/qe/qe.h>
|
||||
#include <soc/fsl/qe/qe_ic.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <soc/fsl/qe/qe_ic.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
||||
|
@ -90,24 +89,9 @@ void __init mpc83xx_ipic_init_IRQ(void)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
void __init mpc83xx_qe_init_IRQ(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
|
||||
if (!np) {
|
||||
np = of_find_node_by_type(NULL, "qeic");
|
||||
if (!np)
|
||||
return;
|
||||
}
|
||||
qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
void __init mpc83xx_ipic_and_qe_init_IRQ(void)
|
||||
{
|
||||
mpc83xx_ipic_init_IRQ();
|
||||
mpc83xx_qe_init_IRQ();
|
||||
}
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
#include <soc/fsl/qe/qe.h>
|
||||
#include <soc/fsl/qe/qe_ic.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <asm/ipic.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <soc/fsl/qe/qe.h>
|
||||
#include <soc/fsl/qe/qe_ic.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include <sysdev/fsl_pci.h>
|
||||
#include <sysdev/simple_gpio.h>
|
||||
#include <soc/fsl/qe/qe.h>
|
||||
#include <soc/fsl/qe/qe_ic.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <asm/ipic.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <soc/fsl/qe/qe.h>
|
||||
#include <soc/fsl/qe/qe_ic.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ menuconfig FSL_SOC_BOOKE
|
|||
select SERIAL_8250_EXTENDED if SERIAL_8250
|
||||
select SERIAL_8250_SHARE_IRQ if SERIAL_8250
|
||||
select FSL_CORENET_RCPM if PPC_E500MC
|
||||
select FSL_QORIQ_PM if SUSPEND && PPC_E500MC
|
||||
select FSL_PMC if SUSPEND && !PPC_E500MC
|
||||
default y
|
||||
|
||||
if FSL_SOC_BOOKE
|
||||
|
@ -292,3 +294,7 @@ endif # FSL_SOC_BOOKE
|
|||
|
||||
config TQM85xx
|
||||
bool
|
||||
|
||||
config FSL_QORIQ_PM
|
||||
bool
|
||||
select FSL_SLEEP_FSM
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
# Makefile for the PowerPC 85xx linux kernel.
|
||||
#
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_SUSPEND) += sleep.o
|
||||
obj-$(CONFIG_FSL_PMC) += mpc85xx_pm_ops.o
|
||||
obj-$(CONFIG_FSL_QORIQ_PM) += qoriq_pm.o deepsleep.o
|
||||
|
||||
obj-y += common.o
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <asm/mpic.h>
|
||||
#include <asm/ehv_pic.h>
|
||||
#include <asm/swiotlb.h>
|
||||
#include <soc/fsl/qe/qe_ic.h>
|
||||
|
||||
#include <linux/of_platform.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
|
@ -38,8 +37,6 @@ void __init corenet_gen_pic_init(void)
|
|||
unsigned int flags = MPIC_BIG_ENDIAN | MPIC_SINGLE_DEST_CPU |
|
||||
MPIC_NO_RESET;
|
||||
|
||||
struct device_node *np;
|
||||
|
||||
if (ppc_md.get_irq == mpic_get_coreint_irq)
|
||||
flags |= MPIC_ENABLE_COREINT;
|
||||
|
||||
|
@ -47,13 +44,6 @@ void __init corenet_gen_pic_init(void)
|
|||
BUG_ON(mpic == NULL);
|
||||
|
||||
mpic_init(mpic);
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
|
||||
if (np) {
|
||||
qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
|
||||
qe_ic_cascade_high_mpic);
|
||||
of_node_put(np);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
* Support deep sleep feature for T104x
|
||||
*
|
||||
* Copyright 2018 NXP
|
||||
* Author: Chenhui Zhao <chenhui.zhao@freescale.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the above-listed copyright holders nor the
|
||||
* names of any contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation, either version 2 of that License or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/fsl_pm.h>
|
||||
|
||||
#define SIZE_1MB 0x100000
|
||||
#define SIZE_2MB 0x200000
|
||||
|
||||
#define CPC_CPCHDBCR0 0x10f00
|
||||
#define CPC_CPCHDBCR0_SPEC_DIS 0x08000000
|
||||
|
||||
#define CCSR_SCFG_DPSLPCR 0xfc000
|
||||
#define CCSR_SCFG_DPSLPCR_WDRR_EN 0x1
|
||||
#define CCSR_SCFG_SPARECR2 0xfc504
|
||||
#define CCSR_SCFG_SPARECR3 0xfc508
|
||||
|
||||
#define CCSR_GPIO1_GPDIR 0x130000
|
||||
#define CCSR_GPIO1_GPODR 0x130004
|
||||
#define CCSR_GPIO1_GPDAT 0x130008
|
||||
#define CCSR_GPIO1_GPDIR_29 0x4
|
||||
|
||||
#define RCPM_BLOCK_OFFSET 0x00022000
|
||||
#define EPU_BLOCK_OFFSET 0x00000000
|
||||
#define NPC_BLOCK_OFFSET 0x00001000
|
||||
|
||||
#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);
|
||||
|
||||
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;
|
||||
int ret = 0;
|
||||
phys_addr_t ccsr_phy_addr, dcsr_phy_addr;
|
||||
|
||||
saved_law = NULL;
|
||||
ccsr_base = NULL;
|
||||
dcsr_base = NULL;
|
||||
pld_base = NULL;
|
||||
|
||||
ccsr_phy_addr = get_immrbase();
|
||||
if (ccsr_phy_addr == -1) {
|
||||
pr_err("%s: Can't get the address of CCSR\n", __func__);
|
||||
ret = -EINVAL;
|
||||
goto ccsr_err;
|
||||
}
|
||||
ccsr_base = ioremap(ccsr_phy_addr, SIZE_2MB);
|
||||
if (!ccsr_base) {
|
||||
ret = -ENOMEM;
|
||||
goto ccsr_err;
|
||||
}
|
||||
|
||||
dcsr_phy_addr = get_dcsrbase();
|
||||
if (dcsr_phy_addr == -1) {
|
||||
pr_err("%s: Can't get the address of DCSR\n", __func__);
|
||||
ret = -EINVAL;
|
||||
goto dcsr_err;
|
||||
}
|
||||
dcsr_base = ioremap(dcsr_phy_addr, SIZE_1MB);
|
||||
if (!dcsr_base) {
|
||||
ret = -ENOMEM;
|
||||
goto dcsr_err;
|
||||
}
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,tetra-fpga");
|
||||
if (np) {
|
||||
pld_flag = T1040QDS_TETRA_FLAG;
|
||||
} else {
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,deepsleep-cpld");
|
||||
if (np) {
|
||||
pld_flag = T104xRDB_CPLD_FLAG;
|
||||
} else {
|
||||
pr_err("%s: Can't find the FPGA/CPLD node\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto pld_err;
|
||||
}
|
||||
}
|
||||
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 alloc_err;
|
||||
}
|
||||
ret = of_property_read_u32(np, "fsl,num-laws", &num_laws);
|
||||
if (ret) {
|
||||
ret = -EINVAL;
|
||||
goto alloc_err;
|
||||
}
|
||||
|
||||
saved_law = kzalloc(sizeof(*saved_law) * num_laws, GFP_KERNEL);
|
||||
if (!saved_law) {
|
||||
ret = -ENOMEM;
|
||||
goto alloc_err;
|
||||
}
|
||||
of_node_put(np);
|
||||
|
||||
return 0;
|
||||
|
||||
alloc_err:
|
||||
iounmap(pld_base);
|
||||
pld_base = NULL;
|
||||
pld_err:
|
||||
iounmap(dcsr_base);
|
||||
dcsr_base = NULL;
|
||||
dcsr_err:
|
||||
iounmap(ccsr_base);
|
||||
ccsr_base = NULL;
|
||||
ccsr_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fsl_dp_iounmap(void)
|
||||
{
|
||||
if (dcsr_base) {
|
||||
iounmap(dcsr_base);
|
||||
dcsr_base = NULL;
|
||||
}
|
||||
|
||||
if (ccsr_base) {
|
||||
iounmap(ccsr_base);
|
||||
ccsr_base = NULL;
|
||||
}
|
||||
|
||||
if (pld_base) {
|
||||
iounmap(pld_base);
|
||||
pld_base = NULL;
|
||||
}
|
||||
|
||||
kfree(saved_law);
|
||||
saved_law = NULL;
|
||||
}
|
||||
|
||||
static void fsl_dp_ddr_save(void *ccsr_base)
|
||||
{
|
||||
u32 ddr_buff_addr;
|
||||
|
||||
/*
|
||||
* DDR training initialization will break 128 bytes at the beginning
|
||||
* of DDR, therefore, save them so that the bootloader will restore
|
||||
* them. Assume that DDR is mapped to the address space started with
|
||||
* CONFIG_PAGE_OFFSET.
|
||||
*/
|
||||
memcpy(ddr_buff, (void *)CONFIG_PAGE_OFFSET, DDR_BUF_SIZE);
|
||||
|
||||
/* assume ddr_buff is in the physical address space of 4GB */
|
||||
ddr_buff_addr = (u32)(__pa(ddr_buff) & 0xffffffff);
|
||||
|
||||
/*
|
||||
* the bootloader will restore the first 128 bytes of DDR from
|
||||
* the location indicated by the register SPARECR3
|
||||
*/
|
||||
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;
|
||||
|
||||
/* the bootloader will finally jump to this address to return kernel */
|
||||
#ifdef CONFIG_PPC32
|
||||
resume_addr = (u32)(__pa(fsl_booke_deep_sleep_resume));
|
||||
#else
|
||||
resume_addr = (u32)(__pa(*(u64 *)fsl_booke_deep_sleep_resume)
|
||||
& 0xffffffff);
|
||||
#endif
|
||||
|
||||
/* use the register SPARECR2 to save the resume address */
|
||||
out_be32(ccsr_base + CCSR_SCFG_SPARECR2, resume_addr);
|
||||
|
||||
}
|
||||
|
||||
int fsl_enter_epu_deepsleep(void)
|
||||
{
|
||||
fsl_dp_ddr_save(ccsr_base);
|
||||
|
||||
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);
|
||||
|
||||
/* set GPIO1_29 as an output pin (not open-drain), and output 0 */
|
||||
clrbits32(ccsr_base + CCSR_GPIO1_GPDAT, CCSR_GPIO1_GPDIR_29);
|
||||
clrbits32(ccsr_base + CCSR_GPIO1_GPODR, CCSR_GPIO1_GPDIR_29);
|
||||
setbits32(ccsr_base + CCSR_GPIO1_GPDIR, CCSR_GPIO1_GPDIR_29);
|
||||
|
||||
/*
|
||||
* Disable CPC speculation to avoid deep sleep hang, especially
|
||||
* in secure boot mode. This bit will be cleared automatically
|
||||
* when resuming from deep sleep.
|
||||
*/
|
||||
setbits32(ccsr_base + CPC_CPCHDBCR0, CPC_CPCHDBCR0_SPEC_DIS);
|
||||
|
||||
fsl_epu_setup_default(dcsr_base + EPU_BLOCK_OFFSET);
|
||||
fsl_npc_setup_default(dcsr_base + NPC_BLOCK_OFFSET);
|
||||
out_be32(dcsr_base + RCPM_BLOCK_OFFSET + CSTTACR0, 0x00001001);
|
||||
out_be32(dcsr_base + RCPM_BLOCK_OFFSET + CG1CR0, 0x00000001);
|
||||
|
||||
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);
|
||||
|
||||
fsl_epu_clean_default(dcsr_base + EPU_BLOCK_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -45,7 +45,6 @@
|
|||
#include <sysdev/fsl_pci.h>
|
||||
#include <sysdev/simple_gpio.h>
|
||||
#include <soc/fsl/qe/qe.h>
|
||||
#include <soc/fsl/qe/qe_ic.h>
|
||||
#include <asm/mpic.h>
|
||||
#include <asm/swiotlb.h>
|
||||
#include "smp.h"
|
||||
|
@ -279,20 +278,6 @@ static void __init mpc85xx_mds_qeic_init(void)
|
|||
of_node_put(np);
|
||||
return;
|
||||
}
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
|
||||
if (!np) {
|
||||
np = of_find_node_by_type(NULL, "qeic");
|
||||
if (!np)
|
||||
return;
|
||||
}
|
||||
|
||||
if (machine_is(p1021_mds))
|
||||
qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
|
||||
qe_ic_cascade_high_mpic);
|
||||
else
|
||||
qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL);
|
||||
of_node_put(np);
|
||||
}
|
||||
#else
|
||||
static void __init mpc85xx_mds_qe_init(void) { }
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <asm/udbg.h>
|
||||
#include <asm/mpic.h>
|
||||
#include <soc/fsl/qe/qe.h>
|
||||
#include <soc/fsl/qe/qe_ic.h>
|
||||
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
@ -44,10 +43,6 @@ void __init mpc85xx_rdb_pic_init(void)
|
|||
{
|
||||
struct mpic *mpic;
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
struct device_node *np;
|
||||
#endif
|
||||
|
||||
if (of_machine_is_compatible("fsl,MPC85XXRDB-CAMP")) {
|
||||
mpic = mpic_alloc(NULL, 0, MPIC_NO_RESET |
|
||||
MPIC_BIG_ENDIAN |
|
||||
|
@ -62,18 +57,6 @@ void __init mpc85xx_rdb_pic_init(void)
|
|||
|
||||
BUG_ON(mpic == NULL);
|
||||
mpic_init(mpic);
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
|
||||
if (np) {
|
||||
qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
|
||||
qe_ic_cascade_high_mpic);
|
||||
of_node_put(np);
|
||||
|
||||
} else
|
||||
pr_err("%s: Could not find qe-ic node\n", __func__);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Support Power Management feature
|
||||
*
|
||||
* Copyright 2018 NXP
|
||||
* Author: Chenhui Zhao <chenhui.zhao@freescale.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the above-listed copyright holders nor the
|
||||
* names of any contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation, either version 2 of that License or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include <asm/fsl_pm.h>
|
||||
|
||||
#define FSL_SLEEP 0x1
|
||||
#define FSL_DEEP_SLEEP 0x2
|
||||
|
||||
int (*fsl_enter_deepsleep)(void);
|
||||
|
||||
/* specify the sleep state of the present platform */
|
||||
unsigned int sleep_pm_state;
|
||||
/* supported sleep modes by the present platform */
|
||||
static unsigned int sleep_modes;
|
||||
|
||||
/**
|
||||
* fsl_set_power_except - set which IP block is not powerdown when sleep,
|
||||
* such as MAC, USB, etc.
|
||||
*
|
||||
* @dev: a pointer to the struct device
|
||||
* @on: if 1, do not power down; if 0, power down.
|
||||
*/
|
||||
void fsl_set_power_except(struct device *dev, int on)
|
||||
{
|
||||
u32 value[2];
|
||||
u32 pw_mask;
|
||||
int ret;
|
||||
struct device_node *mac_node;
|
||||
const phandle *phandle_prop;
|
||||
|
||||
if (dev && !strncmp(dev->bus->name, "usb", 3)) {
|
||||
struct usb_device *udev = container_of(dev,
|
||||
struct usb_device, dev);
|
||||
struct device *controller = udev->bus->controller;
|
||||
|
||||
ret = of_property_read_u32_array(controller->parent->of_node,
|
||||
"sleep", value, 2);
|
||||
} else
|
||||
ret = of_property_read_u32_array(dev->of_node, "sleep",
|
||||
value, 2);
|
||||
|
||||
if (ret) {
|
||||
/* search fman mac node */
|
||||
phandle_prop = of_get_property(dev->of_node, "fsl,fman-mac",
|
||||
NULL);
|
||||
if (phandle_prop == NULL)
|
||||
goto err;
|
||||
|
||||
mac_node = of_find_node_by_phandle(*phandle_prop);
|
||||
ret = of_property_read_u32_array(mac_node, "sleep", value, 2);
|
||||
of_node_put(mac_node);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
/* get the second value, it is a mask */
|
||||
pw_mask = value[1];
|
||||
qoriq_pm_ops->set_ip_power(on, pw_mask);
|
||||
return;
|
||||
|
||||
err:
|
||||
dev_err(dev, "Can not set wakeup sources\n");
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsl_set_power_except);
|
||||
|
||||
void qoriq_set_wakeup_source(struct device *dev, void *enable)
|
||||
{
|
||||
if (!device_may_wakeup(dev))
|
||||
return;
|
||||
|
||||
fsl_set_power_except(dev, *((int *)enable));
|
||||
}
|
||||
|
||||
static int qoriq_suspend_enter(suspend_state_t state)
|
||||
{
|
||||
int ret = 0;
|
||||
int cpu;
|
||||
|
||||
switch (state) {
|
||||
case PM_SUSPEND_STANDBY:
|
||||
|
||||
if (cur_cpu_spec->cpu_flush_caches)
|
||||
cur_cpu_spec->cpu_flush_caches();
|
||||
|
||||
ret = qoriq_pm_ops->plat_enter_sleep();
|
||||
|
||||
break;
|
||||
|
||||
case PM_SUSPEND_MEM:
|
||||
|
||||
cpu = smp_processor_id();
|
||||
qoriq_pm_ops->irq_mask(cpu);
|
||||
|
||||
ret = fsl_enter_deepsleep();
|
||||
|
||||
qoriq_pm_ops->irq_unmask(cpu);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qoriq_suspend_valid(suspend_state_t state)
|
||||
{
|
||||
set_pm_suspend_state(state);
|
||||
|
||||
if (state == PM_SUSPEND_STANDBY && (sleep_modes & FSL_SLEEP))
|
||||
return 1;
|
||||
|
||||
if (state == PM_SUSPEND_MEM && (sleep_modes & FSL_DEEP_SLEEP))
|
||||
return 1;
|
||||
|
||||
set_pm_suspend_state(PM_SUSPEND_ON);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qoriq_suspend_begin(suspend_state_t state)
|
||||
{
|
||||
const int enable = 1;
|
||||
|
||||
dpm_for_each_dev((void *)&enable, qoriq_set_wakeup_source);
|
||||
|
||||
if (state == PM_SUSPEND_MEM)
|
||||
return fsl_dp_iomap();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qoriq_suspend_end(void)
|
||||
{
|
||||
const int enable = 0;
|
||||
|
||||
dpm_for_each_dev((void *)&enable, qoriq_set_wakeup_source);
|
||||
|
||||
set_pm_suspend_state(PM_SUSPEND_ON);
|
||||
fsl_dp_iounmap();
|
||||
}
|
||||
|
||||
static const struct platform_suspend_ops qoriq_suspend_ops = {
|
||||
.valid = qoriq_suspend_valid,
|
||||
.enter = qoriq_suspend_enter,
|
||||
.begin = qoriq_suspend_begin,
|
||||
.end = qoriq_suspend_end,
|
||||
};
|
||||
|
||||
static const struct of_device_id deepsleep_matches[] = {
|
||||
{
|
||||
.compatible = "fsl,t1040-rcpm",
|
||||
},
|
||||
{
|
||||
.compatible = "fsl,t1024-rcpm",
|
||||
},
|
||||
{
|
||||
.compatible = "fsl,t1023-rcpm",
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init qoriq_suspend_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
sleep_modes = FSL_SLEEP;
|
||||
sleep_pm_state = PLAT_PM_SLEEP;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-rcpm-2.0");
|
||||
if (np)
|
||||
sleep_pm_state = PLAT_PM_LPM20;
|
||||
|
||||
np = of_find_matching_node_and_match(NULL, deepsleep_matches, NULL);
|
||||
if (np) {
|
||||
fsl_enter_deepsleep = fsl_enter_epu_deepsleep;
|
||||
sleep_modes |= FSL_DEEP_SLEEP;
|
||||
}
|
||||
|
||||
suspend_set_ops(&qoriq_suspend_ops);
|
||||
set_pm_suspend_state(PM_SUSPEND_ON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(qoriq_suspend_init);
|
File diff suppressed because it is too large
Load Diff
|
@ -19,7 +19,6 @@
|
|||
#include <asm/udbg.h>
|
||||
#include <asm/mpic.h>
|
||||
#include <soc/fsl/qe/qe.h>
|
||||
#include <soc/fsl/qe/qe_ic.h>
|
||||
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
@ -31,26 +30,12 @@ static void __init twr_p1025_pic_init(void)
|
|||
{
|
||||
struct mpic *mpic;
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
struct device_node *np;
|
||||
#endif
|
||||
|
||||
mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
|
||||
MPIC_SINGLE_DEST_CPU,
|
||||
0, 256, " OpenPIC ");
|
||||
|
||||
BUG_ON(mpic == NULL);
|
||||
mpic_init(mpic);
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
|
||||
if (np) {
|
||||
qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
|
||||
qe_ic_cascade_high_mpic);
|
||||
of_node_put(np);
|
||||
} else
|
||||
pr_err("Could not find qe-ic node\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
|
|
|
@ -5,6 +5,7 @@ menuconfig PPC_86xx
|
|||
depends on PPC_BOOK3S_32
|
||||
select FSL_SOC
|
||||
select ALTIVEC
|
||||
select FSL_PMC if SUSPEND
|
||||
help
|
||||
The Freescale E600 SoCs have 74xx cores.
|
||||
|
||||
|
|
|
@ -16,54 +16,192 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pm.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <asm/switch_to.h>
|
||||
#include <asm/fsl_pm.h>
|
||||
|
||||
struct pmc_regs {
|
||||
__be32 devdisr;
|
||||
__be32 devdisr2;
|
||||
__be32 :32;
|
||||
__be32 :32;
|
||||
__be32 pmcsr;
|
||||
#define PMCSR_SLP (1 << 17)
|
||||
__be32 res1;
|
||||
__be32 res2;
|
||||
__be32 powmgtcsr;
|
||||
#define POWMGTCSR_SLP 0x00020000
|
||||
#define POWMGTCSR_DPSLP 0x00100000
|
||||
#define POWMGTCSR_LOSSLESS 0x00400000
|
||||
__be32 res3[2];
|
||||
__be32 pmcdr;
|
||||
};
|
||||
|
||||
static struct device *pmc_dev;
|
||||
static struct pmc_regs __iomem *pmc_regs;
|
||||
static unsigned int pmc_flag;
|
||||
|
||||
#define PMC_SLEEP 0x1
|
||||
#define PMC_DEEP_SLEEP 0x2
|
||||
#define PMC_LOSSLESS 0x4
|
||||
|
||||
/**
|
||||
* mpc85xx_pmc_set_wake - enable devices as wakeup event source
|
||||
* @dev: a device affected
|
||||
* @enable: True to enable event generation; false to disable
|
||||
*
|
||||
* This enables the device as a wakeup event source, or disables it.
|
||||
*
|
||||
* RETURN VALUE:
|
||||
* 0 is returned on success.
|
||||
* -EINVAL is returned if device is not supposed to wake up the system.
|
||||
* -ENODEV is returned if PMC is unavailable.
|
||||
* Error code depending on the platform is returned if both the platform and
|
||||
* the native mechanism fail to enable the generation of wake-up events
|
||||
*/
|
||||
int mpc85xx_pmc_set_wake(struct device *dev, bool enable)
|
||||
{
|
||||
int ret = 0;
|
||||
struct device_node *clk_np;
|
||||
const u32 *prop;
|
||||
u32 pmcdr_mask;
|
||||
|
||||
if (!pmc_regs) {
|
||||
dev_err(dev, "%s: PMC is unavailable\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (enable && !device_may_wakeup(dev))
|
||||
return -EINVAL;
|
||||
|
||||
clk_np = of_parse_phandle(dev->of_node, "fsl,pmc-handle", 0);
|
||||
if (!clk_np)
|
||||
return -EINVAL;
|
||||
|
||||
prop = of_get_property(clk_np, "fsl,pmcdr-mask", NULL);
|
||||
if (!prop) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
pmcdr_mask = be32_to_cpup(prop);
|
||||
|
||||
if (enable)
|
||||
/* clear to enable clock in low power mode */
|
||||
clrbits32(&pmc_regs->pmcdr, pmcdr_mask);
|
||||
else
|
||||
setbits32(&pmc_regs->pmcdr, pmcdr_mask);
|
||||
|
||||
out:
|
||||
of_node_put(clk_np);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mpc85xx_pmc_set_wake);
|
||||
|
||||
/**
|
||||
* mpc85xx_pmc_set_lossless_ethernet - enable lossless ethernet
|
||||
* in (deep) sleep mode
|
||||
* @enable: True to enable event generation; false to disable
|
||||
*/
|
||||
void mpc85xx_pmc_set_lossless_ethernet(int enable)
|
||||
{
|
||||
if (pmc_flag & PMC_LOSSLESS) {
|
||||
if (enable)
|
||||
setbits32(&pmc_regs->powmgtcsr, POWMGTCSR_LOSSLESS);
|
||||
else
|
||||
clrbits32(&pmc_regs->powmgtcsr, POWMGTCSR_LOSSLESS);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mpc85xx_pmc_set_lossless_ethernet);
|
||||
|
||||
static int pmc_suspend_enter(suspend_state_t state)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
int result;
|
||||
|
||||
setbits32(&pmc_regs->pmcsr, PMCSR_SLP);
|
||||
/* At this point, the CPU is asleep. */
|
||||
switch (state) {
|
||||
#ifdef CONFIG_PPC_85xx
|
||||
case PM_SUSPEND_MEM:
|
||||
#ifdef CONFIG_SPE
|
||||
enable_kernel_spe();
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_FPU
|
||||
enable_kernel_fp();
|
||||
#endif
|
||||
|
||||
/* Upon resume, wait for SLP bit to be clear. */
|
||||
ret = spin_event_timeout((in_be32(&pmc_regs->pmcsr) & PMCSR_SLP) == 0,
|
||||
10000, 10) ? 0 : -ETIMEDOUT;
|
||||
if (ret)
|
||||
dev_err(pmc_dev, "tired waiting for SLP bit to clear\n");
|
||||
pr_debug("%s: Entering deep sleep\n", __func__);
|
||||
|
||||
local_irq_disable();
|
||||
mpc85xx_enter_deep_sleep(get_immrbase(), POWMGTCSR_DPSLP);
|
||||
|
||||
pr_debug("%s: Resumed from deep sleep\n", __func__);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case PM_SUSPEND_STANDBY:
|
||||
local_irq_disable();
|
||||
flush_dcache_L1();
|
||||
|
||||
setbits32(&pmc_regs->powmgtcsr, POWMGTCSR_SLP);
|
||||
/* At this point, the CPU is asleep. */
|
||||
|
||||
/* Upon resume, wait for SLP bit to be clear. */
|
||||
result = spin_event_timeout(
|
||||
(in_be32(&pmc_regs->powmgtcsr) & POWMGTCSR_SLP) == 0,
|
||||
10000, 10);
|
||||
if (!result) {
|
||||
pr_err("%s: timeout waiting for SLP bit "
|
||||
"to be cleared\n", __func__);
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pmc_suspend_valid(suspend_state_t state)
|
||||
{
|
||||
if (state != PM_SUSPEND_STANDBY)
|
||||
return 0;
|
||||
return 1;
|
||||
set_pm_suspend_state(state);
|
||||
|
||||
if (((pmc_flag & PMC_SLEEP) && (state == PM_SUSPEND_STANDBY)) ||
|
||||
((pmc_flag & PMC_DEEP_SLEEP) && (state == PM_SUSPEND_MEM)))
|
||||
return 1;
|
||||
|
||||
set_pm_suspend_state(PM_SUSPEND_ON);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pmc_suspend_end(void)
|
||||
{
|
||||
set_pm_suspend_state(PM_SUSPEND_ON);
|
||||
}
|
||||
|
||||
static const struct platform_suspend_ops pmc_suspend_ops = {
|
||||
.valid = pmc_suspend_valid,
|
||||
.enter = pmc_suspend_enter,
|
||||
.end = pmc_suspend_end,
|
||||
};
|
||||
|
||||
static int pmc_probe(struct platform_device *ofdev)
|
||||
static int pmc_probe(struct platform_device *pdev)
|
||||
{
|
||||
pmc_regs = of_iomap(ofdev->dev.of_node, 0);
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
||||
pmc_regs = of_iomap(np, 0);
|
||||
if (!pmc_regs)
|
||||
return -ENOMEM;
|
||||
|
||||
pmc_dev = &ofdev->dev;
|
||||
pmc_flag = PMC_SLEEP;
|
||||
if (of_device_is_compatible(np, "fsl,mpc8536-pmc"))
|
||||
pmc_flag |= PMC_DEEP_SLEEP;
|
||||
|
||||
if (of_device_is_compatible(np, "fsl,p1022-pmc"))
|
||||
pmc_flag |= PMC_DEEP_SLEEP | PMC_LOSSLESS;
|
||||
|
||||
suspend_set_ops(&pmc_suspend_ops);
|
||||
set_pm_suspend_state(PM_SUSPEND_ON);
|
||||
|
||||
pr_info("Freescale PMC driver\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,37 @@ extern void init_fcc_ioports(struct fs_platform_info*);
|
|||
extern void init_fec_ioports(struct fs_platform_info*);
|
||||
extern void init_smc_ioports(struct fs_uart_platform_info*);
|
||||
static phys_addr_t immrbase = -1;
|
||||
static phys_addr_t dcsrbase = -1;
|
||||
|
||||
phys_addr_t get_dcsrbase(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
const __be32 *prop;
|
||||
int size;
|
||||
u32 naddr;
|
||||
|
||||
if (dcsrbase != -1)
|
||||
return dcsrbase;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,dcsr");
|
||||
if (!np)
|
||||
return -1;
|
||||
|
||||
prop = of_get_property(np, "#address-cells", &size);
|
||||
if (prop && size == 4)
|
||||
naddr = be32_to_cpup(prop);
|
||||
else
|
||||
naddr = 2;
|
||||
|
||||
prop = of_get_property(np, "ranges", NULL);
|
||||
if (prop)
|
||||
dcsrbase = of_translate_address(np, prop + naddr);
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
return dcsrbase;
|
||||
}
|
||||
EXPORT_SYMBOL(get_dcsrbase);
|
||||
|
||||
phys_addr_t get_immrbase(void)
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
struct spi_device;
|
||||
|
||||
extern phys_addr_t get_dcsrbase(void);
|
||||
extern phys_addr_t get_immrbase(void);
|
||||
#if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE)
|
||||
extern u32 get_brgfreq(void);
|
||||
|
@ -44,5 +45,22 @@ extern struct platform_diu_data_ops diu_ops;
|
|||
void __noreturn fsl_hv_restart(char *cmd);
|
||||
void __noreturn fsl_hv_halt(void);
|
||||
|
||||
/*
|
||||
* Cast the ccsrbar to 64-bit parameter so that the assembly
|
||||
* code can be compatible with both 32-bit & 36-bit.
|
||||
*/
|
||||
extern void mpc85xx_enter_deep_sleep(u64 ccsrbar, u32 powmgtreq);
|
||||
|
||||
#ifdef CONFIG_FSL_PMC
|
||||
int mpc85xx_pmc_set_wake(struct device *dev, bool enable);
|
||||
void mpc85xx_pmc_set_lossless_ethernet(int enable);
|
||||
#else
|
||||
static inline int mpc85xx_pmc_set_wake(struct device *dev, bool enable)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#define mpc85xx_pmc_set_lossless_ethernet(enable) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -40,4 +40,15 @@ config DPAA2_CONSOLE
|
|||
/dev/dpaa2_mc_console and /dev/dpaa2_aiop_console,
|
||||
which can be used to dump the Management Complex and AIOP
|
||||
firmware logs.
|
||||
|
||||
config FSL_QIXIS
|
||||
tristate "QIXIS system controller driver"
|
||||
depends on OF
|
||||
select REGMAP_I2C
|
||||
select REGMAP_MMIO
|
||||
default n
|
||||
help
|
||||
Say y here to enable QIXIS system controller api. The qixis driver
|
||||
provides FPGA functions to control system.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
obj-$(CONFIG_FSL_DPAA) += qbman/
|
||||
obj-$(CONFIG_QUICC_ENGINE) += qe/
|
||||
obj-$(CONFIG_CPM) += qe/
|
||||
obj-$(CONFIG_FSL_QIXIS) += qixis_ctrl.o
|
||||
obj-$(CONFIG_FSL_GUTS) += guts.o
|
||||
obj-$(CONFIG_FSL_MC_DPIO) += dpio/
|
||||
obj-$(CONFIG_DPAA2_CONSOLE) += dpaa2-console.o
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/* Freescale QIXIS system controller driver.
|
||||
*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
* Copyright 2018-2019 NXP
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* QIXIS MAP */
|
||||
struct fsl_qixis_regs {
|
||||
u8 id; /* Identification Registers */
|
||||
u8 version; /* Version Register */
|
||||
u8 qixis_ver; /* QIXIS Version Register */
|
||||
u8 reserved1[0x1f];
|
||||
};
|
||||
|
||||
struct qixis_priv {
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
static struct regmap_config qixis_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static const struct mfd_cell fsl_qixis_devs[] = {
|
||||
{
|
||||
.name = "reg-mux",
|
||||
.of_compatible = "reg-mux",
|
||||
},
|
||||
};
|
||||
|
||||
static int fsl_qixis_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
struct qixis_priv *priv;
|
||||
int ret = 0;
|
||||
u32 qver;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
priv = devm_kzalloc(&client->dev, sizeof(struct qixis_priv),
|
||||
GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->regmap = regmap_init_i2c(client, &qixis_regmap_config);
|
||||
regmap_read(priv->regmap, offsetof(struct fsl_qixis_regs, qixis_ver),
|
||||
&qver);
|
||||
pr_info("Freescale QIXIS Version: 0x%08x\n", qver);
|
||||
|
||||
i2c_set_clientdata(client, priv);
|
||||
|
||||
if (of_device_is_compatible(client->dev.of_node, "simple-mfd"))
|
||||
ret = devm_mfd_add_devices(&client->dev, -1, fsl_qixis_devs,
|
||||
ARRAY_SIZE(fsl_qixis_devs), NULL, 0,
|
||||
NULL);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
regmap_exit(priv->regmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fsl_qixis_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct qixis_priv *priv;
|
||||
|
||||
priv = i2c_get_clientdata(client);
|
||||
regmap_exit(priv->regmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id fsl_qixis_i2c_of_match[] = {
|
||||
{ .compatible = "fsl,fpga-qixis-i2c" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fsl_qixis_i2c_of_match);
|
||||
|
||||
static struct i2c_driver fsl_qixis_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "qixis_ctrl_i2c",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(fsl_qixis_i2c_of_match),
|
||||
},
|
||||
.probe_new = fsl_qixis_i2c_probe,
|
||||
.remove = fsl_qixis_i2c_remove,
|
||||
};
|
||||
module_i2c_driver(fsl_qixis_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("Wang Dongsheng <dongsheng.wang@freescale.com>");
|
||||
MODULE_DESCRIPTION("Freescale QIXIS system controller driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
Loading…
Reference in New Issue