From d9d95bcad38d18536ecf344e3f4105ed3c7dc7f7 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:08 +0100 Subject: soc: fsl: qe: rename qe_(clr/set/clrset)bit* helpers Make it clear that these operate on big-endian registers (i.e. use the iowrite*be primitives) before we introduce more uses of them and allow the QE drivers to be built for platforms other than ppc32. Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- include/soc/fsl/qe/qe.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/soc/fsl/qe/qe.h b/include/soc/fsl/qe/qe.h index c1036d16ed03..a1aa4eb28f0c 100644 --- a/include/soc/fsl/qe/qe.h +++ b/include/soc/fsl/qe/qe.h @@ -241,20 +241,20 @@ static inline int qe_alive_during_sleep(void) #define qe_muram_offset cpm_muram_offset #define qe_muram_dma cpm_muram_dma -#define qe_setbits32(_addr, _v) iowrite32be(ioread32be(_addr) | (_v), (_addr)) -#define qe_clrbits32(_addr, _v) iowrite32be(ioread32be(_addr) & ~(_v), (_addr)) +#define qe_setbits_be32(_addr, _v) iowrite32be(ioread32be(_addr) | (_v), (_addr)) +#define qe_clrbits_be32(_addr, _v) iowrite32be(ioread32be(_addr) & ~(_v), (_addr)) -#define qe_setbits16(_addr, _v) iowrite16be(ioread16be(_addr) | (_v), (_addr)) -#define qe_clrbits16(_addr, _v) iowrite16be(ioread16be(_addr) & ~(_v), (_addr)) +#define qe_setbits_be16(_addr, _v) iowrite16be(ioread16be(_addr) | (_v), (_addr)) +#define qe_clrbits_be16(_addr, _v) iowrite16be(ioread16be(_addr) & ~(_v), (_addr)) -#define qe_setbits8(_addr, _v) iowrite8(ioread8(_addr) | (_v), (_addr)) -#define qe_clrbits8(_addr, _v) iowrite8(ioread8(_addr) & ~(_v), (_addr)) +#define qe_setbits_8(_addr, _v) iowrite8(ioread8(_addr) | (_v), (_addr)) +#define qe_clrbits_8(_addr, _v) iowrite8(ioread8(_addr) & ~(_v), (_addr)) -#define qe_clrsetbits32(addr, clear, set) \ +#define qe_clrsetbits_be32(addr, clear, set) \ iowrite32be((ioread32be(addr) & ~(clear)) | (set), (addr)) -#define qe_clrsetbits16(addr, clear, set) \ +#define qe_clrsetbits_be16(addr, clear, set) \ iowrite16be((ioread16be(addr) & ~(clear)) | (set), (addr)) -#define qe_clrsetbits8(addr, clear, set) \ +#define qe_clrsetbits_8(addr, clear, set) \ iowrite8((ioread8(addr) & ~(clear)) | (set), (addr)) /* Structure that defines QE firmware binary files. -- cgit v1.2.3 From 6ac9b61786cc64ae5cbfb69413137656f72e8204 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:09 +0100 Subject: soc: fsl: qe: introduce qe_io{read,write}* wrappers The QUICC engine drivers use the powerpc-specific out_be32() etc. In order to allow those drivers to build for other architectures, those must be replaced by iowrite32be(). However, on powerpc, out_be32() is a simple inline function while iowrite32be() is out-of-line. So in order not to introduce a performance regression on powerpc when making the drivers work on other architectures, introduce qe_io* helpers. Also define the qe_{clr,set,clrset}bits* helpers in terms of these new macros. Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- include/soc/fsl/qe/qe.h | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/soc/fsl/qe/qe.h b/include/soc/fsl/qe/qe.h index a1aa4eb28f0c..9cac04c692fd 100644 --- a/include/soc/fsl/qe/qe.h +++ b/include/soc/fsl/qe/qe.h @@ -241,21 +241,37 @@ static inline int qe_alive_during_sleep(void) #define qe_muram_offset cpm_muram_offset #define qe_muram_dma cpm_muram_dma -#define qe_setbits_be32(_addr, _v) iowrite32be(ioread32be(_addr) | (_v), (_addr)) -#define qe_clrbits_be32(_addr, _v) iowrite32be(ioread32be(_addr) & ~(_v), (_addr)) +#ifdef CONFIG_PPC32 +#define qe_iowrite8(val, addr) out_8(addr, val) +#define qe_iowrite16be(val, addr) out_be16(addr, val) +#define qe_iowrite32be(val, addr) out_be32(addr, val) +#define qe_ioread8(addr) in_8(addr) +#define qe_ioread16be(addr) in_be16(addr) +#define qe_ioread32be(addr) in_be32(addr) +#else +#define qe_iowrite8(val, addr) iowrite8(val, addr) +#define qe_iowrite16be(val, addr) iowrite16be(val, addr) +#define qe_iowrite32be(val, addr) iowrite32be(val, addr) +#define qe_ioread8(addr) ioread8(addr) +#define qe_ioread16be(addr) ioread16be(addr) +#define qe_ioread32be(addr) ioread32be(addr) +#endif + +#define qe_setbits_be32(_addr, _v) qe_iowrite32be(qe_ioread32be(_addr) | (_v), (_addr)) +#define qe_clrbits_be32(_addr, _v) qe_iowrite32be(qe_ioread32be(_addr) & ~(_v), (_addr)) -#define qe_setbits_be16(_addr, _v) iowrite16be(ioread16be(_addr) | (_v), (_addr)) -#define qe_clrbits_be16(_addr, _v) iowrite16be(ioread16be(_addr) & ~(_v), (_addr)) +#define qe_setbits_be16(_addr, _v) qe_iowrite16be(qe_ioread16be(_addr) | (_v), (_addr)) +#define qe_clrbits_be16(_addr, _v) qe_iowrite16be(qe_ioread16be(_addr) & ~(_v), (_addr)) -#define qe_setbits_8(_addr, _v) iowrite8(ioread8(_addr) | (_v), (_addr)) -#define qe_clrbits_8(_addr, _v) iowrite8(ioread8(_addr) & ~(_v), (_addr)) +#define qe_setbits_8(_addr, _v) qe_iowrite8(qe_ioread8(_addr) | (_v), (_addr)) +#define qe_clrbits_8(_addr, _v) qe_iowrite8(qe_ioread8(_addr) & ~(_v), (_addr)) #define qe_clrsetbits_be32(addr, clear, set) \ - iowrite32be((ioread32be(addr) & ~(clear)) | (set), (addr)) + qe_iowrite32be((qe_ioread32be(addr) & ~(clear)) | (set), (addr)) #define qe_clrsetbits_be16(addr, clear, set) \ - iowrite16be((ioread16be(addr) & ~(clear)) | (set), (addr)) + qe_iowrite16be((qe_ioread16be(addr) & ~(clear)) | (set), (addr)) #define qe_clrsetbits_8(addr, clear, set) \ - iowrite8((ioread8(addr) & ~(clear)) | (set), (addr)) + qe_iowrite8((qe_ioread8(addr) & ~(clear)) | (set), (addr)) /* Structure that defines QE firmware binary files. * -- cgit v1.2.3 From 273e66721e368764659dde52ee4702567c921f49 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:16 +0100 Subject: soc: fsl: qe: use qe_ic_cascade_{low, high}_mpic also on 83xx The *_ipic and *_mpic handlers are almost identical - the only difference is that the latter end with an unconditional chip->irq_eoi() call. Since IPIC does not have ->irq_eoi, we can reduce some code duplication by calling irq_eoi conditionally. This is similar to what is already done in mpc8xxx_gpio_irq_cascade(). This leaves the functions slightly misnamed, but that will be fixed in a subsequent patch. Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- arch/powerpc/platforms/83xx/misc.c | 2 +- include/soc/fsl/qe/qe_ic.h | 24 ++++-------------------- 2 files changed, 5 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/arch/powerpc/platforms/83xx/misc.c b/arch/powerpc/platforms/83xx/misc.c index 6399865a625e..02e4341fa0d8 100644 --- a/arch/powerpc/platforms/83xx/misc.c +++ b/arch/powerpc/platforms/83xx/misc.c @@ -102,7 +102,7 @@ void __init mpc83xx_qe_init_IRQ(void) if (!np) return; } - qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic); + qe_ic_init(np, 0, qe_ic_cascade_low_mpic, qe_ic_cascade_high_mpic); of_node_put(np); } diff --git a/include/soc/fsl/qe/qe_ic.h b/include/soc/fsl/qe/qe_ic.h index 714a9b890d8d..bfaa233d8328 100644 --- a/include/soc/fsl/qe/qe_ic.h +++ b/include/soc/fsl/qe/qe_ic.h @@ -74,24 +74,6 @@ void qe_ic_set_highest_priority(unsigned int virq, int high); int qe_ic_set_priority(unsigned int virq, unsigned int priority); int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high); -static inline void qe_ic_cascade_low_ipic(struct irq_desc *desc) -{ - struct qe_ic *qe_ic = irq_desc_get_handler_data(desc); - unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic); - - if (cascade_irq != NO_IRQ) - generic_handle_irq(cascade_irq); -} - -static inline void qe_ic_cascade_high_ipic(struct irq_desc *desc) -{ - struct qe_ic *qe_ic = irq_desc_get_handler_data(desc); - unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic); - - if (cascade_irq != NO_IRQ) - generic_handle_irq(cascade_irq); -} - static inline void qe_ic_cascade_low_mpic(struct irq_desc *desc) { struct qe_ic *qe_ic = irq_desc_get_handler_data(desc); @@ -101,7 +83,8 @@ static inline void qe_ic_cascade_low_mpic(struct irq_desc *desc) if (cascade_irq != NO_IRQ) generic_handle_irq(cascade_irq); - chip->irq_eoi(&desc->irq_data); + if (chip->irq_eoi) + chip->irq_eoi(&desc->irq_data); } static inline void qe_ic_cascade_high_mpic(struct irq_desc *desc) @@ -113,7 +96,8 @@ static inline void qe_ic_cascade_high_mpic(struct irq_desc *desc) if (cascade_irq != NO_IRQ) generic_handle_irq(cascade_irq); - chip->irq_eoi(&desc->irq_data); + if (chip->irq_eoi) + chip->irq_eoi(&desc->irq_data); } static inline void qe_ic_cascade_muxed_mpic(struct irq_desc *desc) -- cgit v1.2.3 From 4e0e161d3cc403823159b2c15b6f4c9f642fd1d3 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:17 +0100 Subject: soc: fsl: qe: move calls of qe_ic_init out of arch/powerpc/ Having to call qe_ic_init() from platform-specific code makes it awkward to allow building the QE drivers for ARM. It's also a needless duplication of code, and slightly error-prone: Instead of the caller needing to know the details of whether the QUICC Engine High and QUICC Engine Low are actually the same interrupt (see e.g. the machine_is() in mpc85xx_mds_qeic_init), just let the init function choose the appropriate handlers after it has parsed the DT and figured it out. If the two interrupts are distinct, use separate handlers, otherwise use the handler which first checks the CHIVEC register (for the high priority interrupts), then the CIVEC. All existing callers pass 0 for flags, so continue to do that from the new single caller. Later cleanups will remove that argument from qe_ic_init and simplify the body, as well as make qe_ic_init into a proper init function for an IRQCHIP_DECLARE, eliminating the need to manually look up the fsl,qe-ic node. Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- arch/powerpc/platforms/83xx/km83xx.c | 1 - arch/powerpc/platforms/83xx/misc.c | 16 --------------- arch/powerpc/platforms/83xx/mpc832x_mds.c | 1 - arch/powerpc/platforms/83xx/mpc832x_rdb.c | 1 - arch/powerpc/platforms/83xx/mpc836x_mds.c | 1 - arch/powerpc/platforms/83xx/mpc836x_rdk.c | 1 - arch/powerpc/platforms/83xx/mpc83xx.h | 2 -- arch/powerpc/platforms/85xx/corenet_generic.c | 10 --------- arch/powerpc/platforms/85xx/mpc85xx_mds.c | 27 ------------------------- arch/powerpc/platforms/85xx/mpc85xx_rdb.c | 17 ---------------- arch/powerpc/platforms/85xx/twr_p102x.c | 15 -------------- drivers/soc/fsl/qe/qe_ic.c | 29 ++++++++++++++++++++++++--- include/soc/fsl/qe/qe_ic.h | 7 ------- 13 files changed, 26 insertions(+), 102 deletions(-) (limited to 'include') diff --git a/arch/powerpc/platforms/83xx/km83xx.c b/arch/powerpc/platforms/83xx/km83xx.c index 273145aed90a..5c6227f7bc37 100644 --- a/arch/powerpc/platforms/83xx/km83xx.c +++ b/arch/powerpc/platforms/83xx/km83xx.c @@ -34,7 +34,6 @@ #include #include #include -#include #include "mpc83xx.h" diff --git a/arch/powerpc/platforms/83xx/misc.c b/arch/powerpc/platforms/83xx/misc.c index 02e4341fa0d8..41a9aed9f4ae 100644 --- a/arch/powerpc/platforms/83xx/misc.c +++ b/arch/powerpc/platforms/83xx/misc.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include @@ -92,24 +91,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_mpic, qe_ic_cascade_high_mpic); - 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 */ diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index b428835e5919..1c73af104d19 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c @@ -33,7 +33,6 @@ #include #include #include -#include #include "mpc83xx.h" diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 4588ce632484..87f68ca06255 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c index 240a26d88b07..1264fac54c30 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c @@ -40,7 +40,6 @@ #include #include #include -#include #include "mpc83xx.h" diff --git a/arch/powerpc/platforms/83xx/mpc836x_rdk.c b/arch/powerpc/platforms/83xx/mpc836x_rdk.c index 9923059cb111..b7119e443920 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_rdk.c +++ b/arch/powerpc/platforms/83xx/mpc836x_rdk.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index 459145623334..d343f6ce2599 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h @@ -73,10 +73,8 @@ extern int mpc834x_usb_cfg(void); extern int mpc831x_usb_cfg(void); extern void mpc83xx_ipic_init_IRQ(void); #ifdef CONFIG_QUICC_ENGINE -extern void mpc83xx_qe_init_IRQ(void); extern void mpc83xx_ipic_and_qe_init_IRQ(void); #else -static inline void __init mpc83xx_qe_init_IRQ(void) {} #define mpc83xx_ipic_and_qe_init_IRQ mpc83xx_ipic_init_IRQ #endif /* CONFIG_QUICC_ENGINE */ diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c index a328a741b457..27ac38f7e1a9 100644 --- a/arch/powerpc/platforms/85xx/corenet_generic.c +++ b/arch/powerpc/platforms/85xx/corenet_generic.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -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); - } } /* diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 381a6ac8cb4b..7759eca7d535 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include "smp.h" @@ -268,33 +267,8 @@ static void __init mpc85xx_mds_qe_init(void) } } -static void __init mpc85xx_mds_qeic_init(void) -{ - struct device_node *np; - - np = of_find_compatible_node(NULL, NULL, "fsl,qe"); - if (!of_device_is_available(np)) { - 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) { } -static void __init mpc85xx_mds_qeic_init(void) { } #endif /* CONFIG_QUICC_ENGINE */ static void __init mpc85xx_mds_setup_arch(void) @@ -364,7 +338,6 @@ static void __init mpc85xx_mds_pic_init(void) BUG_ON(mpic == NULL); mpic_init(mpic); - mpc85xx_mds_qeic_init(); } static int __init mpc85xx_mds_probe(void) diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c index 7f9a84f85766..80a80174768c 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -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 - } /* diff --git a/arch/powerpc/platforms/85xx/twr_p102x.c b/arch/powerpc/platforms/85xx/twr_p102x.c index 6c3c0cdaee9a..9abb1e9f73c4 100644 --- a/arch/powerpc/platforms/85xx/twr_p102x.c +++ b/arch/powerpc/platforms/85xx/twr_p102x.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -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 } /* ************************************************************************ diff --git a/drivers/soc/fsl/qe/qe_ic.c b/drivers/soc/fsl/qe/qe_ic.c index f170926ce4d1..a062efac398b 100644 --- a/drivers/soc/fsl/qe/qe_ic.c +++ b/drivers/soc/fsl/qe/qe_ic.c @@ -314,10 +314,10 @@ unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic) return irq_linear_revmap(qe_ic->irqhost, irq); } -void __init qe_ic_init(struct device_node *node, unsigned int flags, - void (*low_handler)(struct irq_desc *desc), - void (*high_handler)(struct irq_desc *desc)) +static void __init qe_ic_init(struct device_node *node, unsigned int flags) { + void (*low_handler)(struct irq_desc *desc); + void (*high_handler)(struct irq_desc *desc); struct qe_ic *qe_ic; struct resource res; u32 temp = 0, ret; @@ -349,6 +349,13 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags, kfree(qe_ic); return; } + if (qe_ic->virq_high != qe_ic->virq_low) { + low_handler = qe_ic_cascade_low_mpic; + high_handler = qe_ic_cascade_high_mpic; + } else { + low_handler = qe_ic_cascade_muxed_mpic; + high_handler = NULL; + } /* default priority scheme is grouped. If spread mode is */ /* required, configure cicr accordingly. */ @@ -381,6 +388,22 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags, } } +static int __init qe_ic_of_init(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 -ENODEV; + } + qe_ic_init(np, 0); + of_node_put(np); + return 0; +} +subsys_initcall(qe_ic_of_init); + void qe_ic_set_highest_priority(unsigned int virq, int high) { struct qe_ic *qe_ic = qe_ic_from_irq(virq); diff --git a/include/soc/fsl/qe/qe_ic.h b/include/soc/fsl/qe/qe_ic.h index bfaa233d8328..a47a0d26acbd 100644 --- a/include/soc/fsl/qe/qe_ic.h +++ b/include/soc/fsl/qe/qe_ic.h @@ -54,16 +54,9 @@ enum qe_ic_grp_id { }; #ifdef CONFIG_QUICC_ENGINE -void qe_ic_init(struct device_node *node, unsigned int flags, - void (*low_handler)(struct irq_desc *desc), - void (*high_handler)(struct irq_desc *desc)); unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic); unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic); #else -static inline void qe_ic_init(struct device_node *node, unsigned int flags, - void (*low_handler)(struct irq_desc *desc), - void (*high_handler)(struct irq_desc *desc)) -{} static inline unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic) { return 0; } static inline unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic) -- cgit v1.2.3 From a36742d13a1deb16b9e80cbb303b7b6b2d2e120d Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:20 +0100 Subject: soc: fsl: qe: move qe_ic_cascade_* functions to qe_ic.c These functions are only ever called through a function pointer, and therefore it makes no sense for them to be "static inline" - gcc has no choice but to emit a copy in each translation unit that takes the address of one of these. Since they are now only referenced from qe_ic.c, just make them local to that file. Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/qe_ic.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/soc/fsl/qe/qe_ic.h | 42 ------------------------------------------ 2 files changed, 42 insertions(+), 42 deletions(-) (limited to 'include') diff --git a/drivers/soc/fsl/qe/qe_ic.c b/drivers/soc/fsl/qe/qe_ic.c index a062efac398b..94ccbeeb1ad1 100644 --- a/drivers/soc/fsl/qe/qe_ic.c +++ b/drivers/soc/fsl/qe/qe_ic.c @@ -314,6 +314,48 @@ unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic) return irq_linear_revmap(qe_ic->irqhost, irq); } +static void qe_ic_cascade_low_mpic(struct irq_desc *desc) +{ + struct qe_ic *qe_ic = irq_desc_get_handler_data(desc); + unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic); + struct irq_chip *chip = irq_desc_get_chip(desc); + + if (cascade_irq != NO_IRQ) + generic_handle_irq(cascade_irq); + + if (chip->irq_eoi) + chip->irq_eoi(&desc->irq_data); +} + +static void qe_ic_cascade_high_mpic(struct irq_desc *desc) +{ + struct qe_ic *qe_ic = irq_desc_get_handler_data(desc); + unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic); + struct irq_chip *chip = irq_desc_get_chip(desc); + + if (cascade_irq != NO_IRQ) + generic_handle_irq(cascade_irq); + + if (chip->irq_eoi) + chip->irq_eoi(&desc->irq_data); +} + +static void qe_ic_cascade_muxed_mpic(struct irq_desc *desc) +{ + struct qe_ic *qe_ic = irq_desc_get_handler_data(desc); + unsigned int cascade_irq; + struct irq_chip *chip = irq_desc_get_chip(desc); + + cascade_irq = qe_ic_get_high_irq(qe_ic); + if (cascade_irq == NO_IRQ) + cascade_irq = qe_ic_get_low_irq(qe_ic); + + if (cascade_irq != NO_IRQ) + generic_handle_irq(cascade_irq); + + chip->irq_eoi(&desc->irq_data); +} + static void __init qe_ic_init(struct device_node *node, unsigned int flags) { void (*low_handler)(struct irq_desc *desc); diff --git a/include/soc/fsl/qe/qe_ic.h b/include/soc/fsl/qe/qe_ic.h index a47a0d26acbd..43e4ce95c6a0 100644 --- a/include/soc/fsl/qe/qe_ic.h +++ b/include/soc/fsl/qe/qe_ic.h @@ -67,46 +67,4 @@ void qe_ic_set_highest_priority(unsigned int virq, int high); int qe_ic_set_priority(unsigned int virq, unsigned int priority); int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high); -static inline void qe_ic_cascade_low_mpic(struct irq_desc *desc) -{ - struct qe_ic *qe_ic = irq_desc_get_handler_data(desc); - unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic); - struct irq_chip *chip = irq_desc_get_chip(desc); - - if (cascade_irq != NO_IRQ) - generic_handle_irq(cascade_irq); - - if (chip->irq_eoi) - chip->irq_eoi(&desc->irq_data); -} - -static inline void qe_ic_cascade_high_mpic(struct irq_desc *desc) -{ - struct qe_ic *qe_ic = irq_desc_get_handler_data(desc); - unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic); - struct irq_chip *chip = irq_desc_get_chip(desc); - - if (cascade_irq != NO_IRQ) - generic_handle_irq(cascade_irq); - - if (chip->irq_eoi) - chip->irq_eoi(&desc->irq_data); -} - -static inline void qe_ic_cascade_muxed_mpic(struct irq_desc *desc) -{ - struct qe_ic *qe_ic = irq_desc_get_handler_data(desc); - unsigned int cascade_irq; - struct irq_chip *chip = irq_desc_get_chip(desc); - - cascade_irq = qe_ic_get_high_irq(qe_ic); - if (cascade_irq == NO_IRQ) - cascade_irq = qe_ic_get_low_irq(qe_ic); - - if (cascade_irq != NO_IRQ) - generic_handle_irq(cascade_irq); - - chip->irq_eoi(&desc->irq_data); -} - #endif /* _ASM_POWERPC_QE_IC_H */ -- cgit v1.2.3 From d7c2878cfcfad2bccc939b755ef2386d13b49684 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:22 +0100 Subject: soc: fsl: qe: remove unused qe_ic_set_* functions There are no current callers of these functions, and they use the ppc-specific virq_to_hw(). So removing them gets us one step closer to building QE support for ARM. If the functionality is ever actually needed, the code can be dug out of git and then adapted to work on all architectures, but for future reference please note that I believe qe_ic_set_priority is buggy: The "priority < 4" should be "priority <= 4", and in the else branch 24 should be replaced by 28, at least if I'm reading the data sheet right. Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/qe_ic.c | 94 ---------------------------------------------- include/soc/fsl/qe/qe_ic.h | 4 -- 2 files changed, 98 deletions(-) (limited to 'include') diff --git a/drivers/soc/fsl/qe/qe_ic.c b/drivers/soc/fsl/qe/qe_ic.c index de2ca2e3a648..4839dcd5c5d3 100644 --- a/drivers/soc/fsl/qe/qe_ic.c +++ b/drivers/soc/fsl/qe/qe_ic.c @@ -445,97 +445,3 @@ static int __init qe_ic_of_init(void) return 0; } subsys_initcall(qe_ic_of_init); - -void qe_ic_set_highest_priority(unsigned int virq, int high) -{ - struct qe_ic *qe_ic = qe_ic_from_irq(virq); - unsigned int src = virq_to_hw(virq); - u32 temp = 0; - - temp = qe_ic_read(qe_ic->regs, QEIC_CICR); - - temp &= ~CICR_HP_MASK; - temp |= src << CICR_HP_SHIFT; - - temp &= ~CICR_HPIT_MASK; - temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << CICR_HPIT_SHIFT; - - qe_ic_write(qe_ic->regs, QEIC_CICR, temp); -} - -/* Set Priority level within its group, from 1 to 8 */ -int qe_ic_set_priority(unsigned int virq, unsigned int priority) -{ - struct qe_ic *qe_ic = qe_ic_from_irq(virq); - unsigned int src = virq_to_hw(virq); - u32 temp; - - if (priority > 8 || priority == 0) - return -EINVAL; - if (WARN_ONCE(src >= ARRAY_SIZE(qe_ic_info), - "%s: Invalid hw irq number for QEIC\n", __func__)) - return -EINVAL; - if (qe_ic_info[src].pri_reg == 0) - return -EINVAL; - - temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].pri_reg); - - if (priority < 4) { - temp &= ~(0x7 << (32 - priority * 3)); - temp |= qe_ic_info[src].pri_code << (32 - priority * 3); - } else { - temp &= ~(0x7 << (24 - priority * 3)); - temp |= qe_ic_info[src].pri_code << (24 - priority * 3); - } - - qe_ic_write(qe_ic->regs, qe_ic_info[src].pri_reg, temp); - - return 0; -} - -/* Set a QE priority to use high irq, only priority 1~2 can use high irq */ -int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high) -{ - struct qe_ic *qe_ic = qe_ic_from_irq(virq); - unsigned int src = virq_to_hw(virq); - u32 temp, control_reg = QEIC_CICNR, shift = 0; - - if (priority > 2 || priority == 0) - return -EINVAL; - if (WARN_ONCE(src >= ARRAY_SIZE(qe_ic_info), - "%s: Invalid hw irq number for QEIC\n", __func__)) - return -EINVAL; - - switch (qe_ic_info[src].pri_reg) { - case QEIC_CIPZCC: - shift = CICNR_ZCC1T_SHIFT; - break; - case QEIC_CIPWCC: - shift = CICNR_WCC1T_SHIFT; - break; - case QEIC_CIPYCC: - shift = CICNR_YCC1T_SHIFT; - break; - case QEIC_CIPXCC: - shift = CICNR_XCC1T_SHIFT; - break; - case QEIC_CIPRTA: - shift = CRICR_RTA1T_SHIFT; - control_reg = QEIC_CRICR; - break; - case QEIC_CIPRTB: - shift = CRICR_RTB1T_SHIFT; - control_reg = QEIC_CRICR; - break; - default: - return -EINVAL; - } - - shift += (2 - priority) * 2; - temp = qe_ic_read(qe_ic->regs, control_reg); - temp &= ~(SIGNAL_MASK << shift); - temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << shift; - qe_ic_write(qe_ic->regs, control_reg, temp); - - return 0; -} diff --git a/include/soc/fsl/qe/qe_ic.h b/include/soc/fsl/qe/qe_ic.h index 43e4ce95c6a0..d47eb231519e 100644 --- a/include/soc/fsl/qe/qe_ic.h +++ b/include/soc/fsl/qe/qe_ic.h @@ -63,8 +63,4 @@ static inline unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic) { return 0; } #endif /* CONFIG_QUICC_ENGINE */ -void qe_ic_set_highest_priority(unsigned int virq, int high); -int qe_ic_set_priority(unsigned int virq, unsigned int priority); -int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high); - #endif /* _ASM_POWERPC_QE_IC_H */ -- cgit v1.2.3 From 5bd2022234527f70219b9c37beb71fbdbdfc3f5b Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:24 +0100 Subject: soc: fsl: qe: make qe_ic_get_{low,high}_irq static These are only called from within qe_ic.c, so make them static. Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/qe_ic.c | 4 ++-- include/soc/fsl/qe/qe_ic.h | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/soc/fsl/qe/qe_ic.c b/drivers/soc/fsl/qe/qe_ic.c index 8f74bc6efd5c..23b457e884d8 100644 --- a/drivers/soc/fsl/qe/qe_ic.c +++ b/drivers/soc/fsl/qe/qe_ic.c @@ -283,7 +283,7 @@ static const struct irq_domain_ops qe_ic_host_ops = { }; /* Return an interrupt vector or 0 if no interrupt is pending. */ -unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic) +static unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic) { int irq; @@ -299,7 +299,7 @@ unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic) } /* Return an interrupt vector or 0 if no interrupt is pending. */ -unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic) +static unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic) { int irq; diff --git a/include/soc/fsl/qe/qe_ic.h b/include/soc/fsl/qe/qe_ic.h index d47eb231519e..70bb5a0f6535 100644 --- a/include/soc/fsl/qe/qe_ic.h +++ b/include/soc/fsl/qe/qe_ic.h @@ -53,14 +53,4 @@ enum qe_ic_grp_id { QE_IC_GRP_RISCB /* QE interrupt controller RISC group B */ }; -#ifdef CONFIG_QUICC_ENGINE -unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic); -unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic); -#else -static inline unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic) -{ return 0; } -static inline unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic) -{ return 0; } -#endif /* CONFIG_QUICC_ENGINE */ - #endif /* _ASM_POWERPC_QE_IC_H */ -- cgit v1.2.3 From 9dab15b1a0e3fabdca9e1adb13ef946332b8c0b8 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:26 +0100 Subject: soc: fsl: qe: merge qe_ic.h headers into qe_ic.c The public qe_ic.h header is no longer included by anything but qe_ic.c. Merge both headers into qe_ic.c, and drop the unused constants. Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/qe_ic.c | 52 +++++++++++++++++++++++- drivers/soc/fsl/qe/qe_ic.h | 99 ---------------------------------------------- include/soc/fsl/qe/qe_ic.h | 56 -------------------------- 3 files changed, 50 insertions(+), 157 deletions(-) delete mode 100644 drivers/soc/fsl/qe/qe_ic.h delete mode 100644 include/soc/fsl/qe/qe_ic.h (limited to 'include') diff --git a/drivers/soc/fsl/qe/qe_ic.c b/drivers/soc/fsl/qe/qe_ic.c index 4832884da5bb..0dd5bdb04a14 100644 --- a/drivers/soc/fsl/qe/qe_ic.c +++ b/drivers/soc/fsl/qe/qe_ic.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -25,9 +26,56 @@ #include #include #include -#include -#include "qe_ic.h" +#define NR_QE_IC_INTS 64 + +/* QE IC registers offset */ +#define QEIC_CICR 0x00 +#define QEIC_CIVEC 0x04 +#define QEIC_CIPXCC 0x10 +#define QEIC_CIPYCC 0x14 +#define QEIC_CIPWCC 0x18 +#define QEIC_CIPZCC 0x1c +#define QEIC_CIMR 0x20 +#define QEIC_CRIMR 0x24 +#define QEIC_CIPRTA 0x30 +#define QEIC_CIPRTB 0x34 +#define QEIC_CHIVEC 0x60 + +struct qe_ic { + /* Control registers offset */ + u32 __iomem *regs; + + /* The remapper for this QEIC */ + struct irq_domain *irqhost; + + /* The "linux" controller struct */ + struct irq_chip hc_irq; + + /* VIRQ numbers of QE high/low irqs */ + unsigned int virq_high; + unsigned int virq_low; +}; + +/* + * QE interrupt controller internal structure + */ +struct qe_ic_info { + /* Location of this source at the QIMR register */ + u32 mask; + + /* Mask register offset */ + u32 mask_reg; + + /* + * For grouped interrupts sources - the interrupt code as + * appears at the group priority register + */ + u8 pri_code; + + /* Group priority register offset */ + u32 pri_reg; +}; static DEFINE_RAW_SPINLOCK(qe_ic_lock); diff --git a/drivers/soc/fsl/qe/qe_ic.h b/drivers/soc/fsl/qe/qe_ic.h deleted file mode 100644 index 9420378d9b6b..000000000000 --- a/drivers/soc/fsl/qe/qe_ic.h +++ /dev/null @@ -1,99 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * drivers/soc/fsl/qe/qe_ic.h - * - * QUICC ENGINE Interrupt Controller Header - * - * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved. - * - * Author: Li Yang - * Based on code from Shlomi Gridish - */ -#ifndef _POWERPC_SYSDEV_QE_IC_H -#define _POWERPC_SYSDEV_QE_IC_H - -#include - -#define NR_QE_IC_INTS 64 - -/* QE IC registers offset */ -#define QEIC_CICR 0x00 -#define QEIC_CIVEC 0x04 -#define QEIC_CRIPNR 0x08 -#define QEIC_CIPNR 0x0c -#define QEIC_CIPXCC 0x10 -#define QEIC_CIPYCC 0x14 -#define QEIC_CIPWCC 0x18 -#define QEIC_CIPZCC 0x1c -#define QEIC_CIMR 0x20 -#define QEIC_CRIMR 0x24 -#define QEIC_CICNR 0x28 -#define QEIC_CIPRTA 0x30 -#define QEIC_CIPRTB 0x34 -#define QEIC_CRICR 0x3c -#define QEIC_CHIVEC 0x60 - -/* Interrupt priority registers */ -#define CIPCC_SHIFT_PRI0 29 -#define CIPCC_SHIFT_PRI1 26 -#define CIPCC_SHIFT_PRI2 23 -#define CIPCC_SHIFT_PRI3 20 -#define CIPCC_SHIFT_PRI4 13 -#define CIPCC_SHIFT_PRI5 10 -#define CIPCC_SHIFT_PRI6 7 -#define CIPCC_SHIFT_PRI7 4 - -/* CICR priority modes */ -#define CICR_GWCC 0x00040000 -#define CICR_GXCC 0x00020000 -#define CICR_GYCC 0x00010000 -#define CICR_GZCC 0x00080000 -#define CICR_GRTA 0x00200000 -#define CICR_GRTB 0x00400000 -#define CICR_HPIT_SHIFT 8 -#define CICR_HPIT_MASK 0x00000300 -#define CICR_HP_SHIFT 24 -#define CICR_HP_MASK 0x3f000000 - -/* CICNR */ -#define CICNR_WCC1T_SHIFT 20 -#define CICNR_ZCC1T_SHIFT 28 -#define CICNR_YCC1T_SHIFT 12 -#define CICNR_XCC1T_SHIFT 4 - -/* CRICR */ -#define CRICR_RTA1T_SHIFT 20 -#define CRICR_RTB1T_SHIFT 28 - -/* Signal indicator */ -#define SIGNAL_MASK 3 -#define SIGNAL_HIGH 2 -#define SIGNAL_LOW 0 - -struct qe_ic { - /* Control registers offset */ - u32 __iomem *regs; - - /* The remapper for this QEIC */ - struct irq_domain *irqhost; - - /* The "linux" controller struct */ - struct irq_chip hc_irq; - - /* VIRQ numbers of QE high/low irqs */ - unsigned int virq_high; - unsigned int virq_low; -}; - -/* - * QE interrupt controller internal structure - */ -struct qe_ic_info { - u32 mask; /* location of this source at the QIMR register. */ - u32 mask_reg; /* Mask register offset */ - u8 pri_code; /* for grouped interrupts sources - the interrupt - code as appears at the group priority register */ - u32 pri_reg; /* Group priority register offset */ -}; - -#endif /* _POWERPC_SYSDEV_QE_IC_H */ diff --git a/include/soc/fsl/qe/qe_ic.h b/include/soc/fsl/qe/qe_ic.h deleted file mode 100644 index 70bb5a0f6535..000000000000 --- a/include/soc/fsl/qe/qe_ic.h +++ /dev/null @@ -1,56 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved. - * - * Authors: Shlomi Gridish - * Li Yang - * - * Description: - * QE IC external definitions and structure. - */ -#ifndef _ASM_POWERPC_QE_IC_H -#define _ASM_POWERPC_QE_IC_H - -#include - -struct device_node; -struct qe_ic; - -#define NUM_OF_QE_IC_GROUPS 6 - -/* Flags when we init the QE IC */ -#define QE_IC_SPREADMODE_GRP_W 0x00000001 -#define QE_IC_SPREADMODE_GRP_X 0x00000002 -#define QE_IC_SPREADMODE_GRP_Y 0x00000004 -#define QE_IC_SPREADMODE_GRP_Z 0x00000008 -#define QE_IC_SPREADMODE_GRP_RISCA 0x00000010 -#define QE_IC_SPREADMODE_GRP_RISCB 0x00000020 - -#define QE_IC_LOW_SIGNAL 0x00000100 -#define QE_IC_HIGH_SIGNAL 0x00000200 - -#define QE_IC_GRP_W_PRI0_DEST_SIGNAL_HIGH 0x00001000 -#define QE_IC_GRP_W_PRI1_DEST_SIGNAL_HIGH 0x00002000 -#define QE_IC_GRP_X_PRI0_DEST_SIGNAL_HIGH 0x00004000 -#define QE_IC_GRP_X_PRI1_DEST_SIGNAL_HIGH 0x00008000 -#define QE_IC_GRP_Y_PRI0_DEST_SIGNAL_HIGH 0x00010000 -#define QE_IC_GRP_Y_PRI1_DEST_SIGNAL_HIGH 0x00020000 -#define QE_IC_GRP_Z_PRI0_DEST_SIGNAL_HIGH 0x00040000 -#define QE_IC_GRP_Z_PRI1_DEST_SIGNAL_HIGH 0x00080000 -#define QE_IC_GRP_RISCA_PRI0_DEST_SIGNAL_HIGH 0x00100000 -#define QE_IC_GRP_RISCA_PRI1_DEST_SIGNAL_HIGH 0x00200000 -#define QE_IC_GRP_RISCB_PRI0_DEST_SIGNAL_HIGH 0x00400000 -#define QE_IC_GRP_RISCB_PRI1_DEST_SIGNAL_HIGH 0x00800000 -#define QE_IC_GRP_W_DEST_SIGNAL_SHIFT (12) - -/* QE interrupt sources groups */ -enum qe_ic_grp_id { - QE_IC_GRP_W = 0, /* QE interrupt controller group W */ - QE_IC_GRP_X, /* QE interrupt controller group X */ - QE_IC_GRP_Y, /* QE interrupt controller group Y */ - QE_IC_GRP_Z, /* QE interrupt controller group Z */ - QE_IC_GRP_RISCA, /* QE interrupt controller RISC group A */ - QE_IC_GRP_RISCB /* QE interrupt controller RISC group B */ -}; - -#endif /* _ASM_POWERPC_QE_IC_H */ -- cgit v1.2.3 From d5b4a762b7bb4a472b2a525749d3bea8023035bc Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:31 +0100 Subject: soc: fsl: move cpm.h from powerpc/include/asm to include/soc/fsl Some drivers, e.g. ucc_uart, need definitions from cpm.h. In order to allow building those drivers for non-ppc based SOCs, move the header to include/soc/fsl. For now, leave a trivial wrapper at the old location so drivers can be updated one by one. Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- arch/powerpc/include/asm/cpm.h | 172 +---------------------------------------- include/soc/fsl/cpm.h | 171 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+), 171 deletions(-) create mode 100644 include/soc/fsl/cpm.h (limited to 'include') diff --git a/arch/powerpc/include/asm/cpm.h b/arch/powerpc/include/asm/cpm.h index 4c24ea8209bb..ce483b0f8a4d 100644 --- a/arch/powerpc/include/asm/cpm.h +++ b/arch/powerpc/include/asm/cpm.h @@ -1,171 +1 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __CPM_H -#define __CPM_H - -#include -#include -#include -#include -#include - -/* - * SPI Parameter RAM common to QE and CPM. - */ -struct spi_pram { - __be16 rbase; /* Rx Buffer descriptor base address */ - __be16 tbase; /* Tx Buffer descriptor base address */ - u8 rfcr; /* Rx function code */ - u8 tfcr; /* Tx function code */ - __be16 mrblr; /* Max receive buffer length */ - __be32 rstate; /* Internal */ - __be32 rdp; /* Internal */ - __be16 rbptr; /* Internal */ - __be16 rbc; /* Internal */ - __be32 rxtmp; /* Internal */ - __be32 tstate; /* Internal */ - __be32 tdp; /* Internal */ - __be16 tbptr; /* Internal */ - __be16 tbc; /* Internal */ - __be32 txtmp; /* Internal */ - __be32 res; /* Tx temp. */ - __be16 rpbase; /* Relocation pointer (CPM1 only) */ - __be16 res1; /* Reserved */ -}; - -/* - * USB Controller pram common to QE and CPM. - */ -struct usb_ctlr { - u8 usb_usmod; - u8 usb_usadr; - u8 usb_uscom; - u8 res1[1]; - __be16 usb_usep[4]; - u8 res2[4]; - __be16 usb_usber; - u8 res3[2]; - __be16 usb_usbmr; - u8 res4[1]; - u8 usb_usbs; - /* Fields down below are QE-only */ - __be16 usb_ussft; - u8 res5[2]; - __be16 usb_usfrn; - u8 res6[0x22]; -} __attribute__ ((packed)); - -/* - * Function code bits, usually generic to devices. - */ -#ifdef CONFIG_CPM1 -#define CPMFCR_GBL ((u_char)0x00) /* Flag doesn't exist in CPM1 */ -#define CPMFCR_TC2 ((u_char)0x00) /* Flag doesn't exist in CPM1 */ -#define CPMFCR_DTB ((u_char)0x00) /* Flag doesn't exist in CPM1 */ -#define CPMFCR_BDB ((u_char)0x00) /* Flag doesn't exist in CPM1 */ -#else -#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */ -#define CPMFCR_TC2 ((u_char)0x04) /* Transfer code 2 value */ -#define CPMFCR_DTB ((u_char)0x02) /* Use local bus for data when set */ -#define CPMFCR_BDB ((u_char)0x01) /* Use local bus for BD when set */ -#endif -#define CPMFCR_EB ((u_char)0x10) /* Set big endian byte order */ - -/* Opcodes common to CPM1 and CPM2 -*/ -#define CPM_CR_INIT_TRX ((ushort)0x0000) -#define CPM_CR_INIT_RX ((ushort)0x0001) -#define CPM_CR_INIT_TX ((ushort)0x0002) -#define CPM_CR_HUNT_MODE ((ushort)0x0003) -#define CPM_CR_STOP_TX ((ushort)0x0004) -#define CPM_CR_GRA_STOP_TX ((ushort)0x0005) -#define CPM_CR_RESTART_TX ((ushort)0x0006) -#define CPM_CR_CLOSE_RX_BD ((ushort)0x0007) -#define CPM_CR_SET_GADDR ((ushort)0x0008) -#define CPM_CR_SET_TIMER ((ushort)0x0008) -#define CPM_CR_STOP_IDMA ((ushort)0x000b) - -/* Buffer descriptors used by many of the CPM protocols. */ -typedef struct cpm_buf_desc { - ushort cbd_sc; /* Status and Control */ - ushort cbd_datlen; /* Data length in buffer */ - uint cbd_bufaddr; /* Buffer address in host memory */ -} cbd_t; - -/* Buffer descriptor control/status used by serial - */ - -#define BD_SC_EMPTY (0x8000) /* Receive is empty */ -#define BD_SC_READY (0x8000) /* Transmit is ready */ -#define BD_SC_WRAP (0x2000) /* Last buffer descriptor */ -#define BD_SC_INTRPT (0x1000) /* Interrupt on change */ -#define BD_SC_LAST (0x0800) /* Last buffer in frame */ -#define BD_SC_TC (0x0400) /* Transmit CRC */ -#define BD_SC_CM (0x0200) /* Continuous mode */ -#define BD_SC_ID (0x0100) /* Rec'd too many idles */ -#define BD_SC_P (0x0100) /* xmt preamble */ -#define BD_SC_BR (0x0020) /* Break received */ -#define BD_SC_FR (0x0010) /* Framing error */ -#define BD_SC_PR (0x0008) /* Parity error */ -#define BD_SC_NAK (0x0004) /* NAK - did not respond */ -#define BD_SC_OV (0x0002) /* Overrun */ -#define BD_SC_UN (0x0002) /* Underrun */ -#define BD_SC_CD (0x0001) /* */ -#define BD_SC_CL (0x0001) /* Collision */ - -/* Buffer descriptor control/status used by Ethernet receive. - * Common to SCC and FCC. - */ -#define BD_ENET_RX_EMPTY (0x8000) -#define BD_ENET_RX_WRAP (0x2000) -#define BD_ENET_RX_INTR (0x1000) -#define BD_ENET_RX_LAST (0x0800) -#define BD_ENET_RX_FIRST (0x0400) -#define BD_ENET_RX_MISS (0x0100) -#define BD_ENET_RX_BC (0x0080) /* FCC Only */ -#define BD_ENET_RX_MC (0x0040) /* FCC Only */ -#define BD_ENET_RX_LG (0x0020) -#define BD_ENET_RX_NO (0x0010) -#define BD_ENET_RX_SH (0x0008) -#define BD_ENET_RX_CR (0x0004) -#define BD_ENET_RX_OV (0x0002) -#define BD_ENET_RX_CL (0x0001) -#define BD_ENET_RX_STATS (0x01ff) /* All status bits */ - -/* Buffer descriptor control/status used by Ethernet transmit. - * Common to SCC and FCC. - */ -#define BD_ENET_TX_READY (0x8000) -#define BD_ENET_TX_PAD (0x4000) -#define BD_ENET_TX_WRAP (0x2000) -#define BD_ENET_TX_INTR (0x1000) -#define BD_ENET_TX_LAST (0x0800) -#define BD_ENET_TX_TC (0x0400) -#define BD_ENET_TX_DEF (0x0200) -#define BD_ENET_TX_HB (0x0100) -#define BD_ENET_TX_LC (0x0080) -#define BD_ENET_TX_RL (0x0040) -#define BD_ENET_TX_RCMASK (0x003c) -#define BD_ENET_TX_UN (0x0002) -#define BD_ENET_TX_CSL (0x0001) -#define BD_ENET_TX_STATS (0x03ff) /* All status bits */ - -/* Buffer descriptor control/status used by Transparent mode SCC. - */ -#define BD_SCC_TX_LAST (0x0800) - -/* Buffer descriptor control/status used by I2C. - */ -#define BD_I2C_START (0x0400) - -#ifdef CONFIG_CPM -int cpm_command(u32 command, u8 opcode); -#else -static inline int cpm_command(u32 command, u8 opcode) -{ - return -ENOSYS; -} -#endif /* CONFIG_CPM */ - -int cpm2_gpiochip_add32(struct device *dev); - -#endif +#include diff --git a/include/soc/fsl/cpm.h b/include/soc/fsl/cpm.h new file mode 100644 index 000000000000..4c24ea8209bb --- /dev/null +++ b/include/soc/fsl/cpm.h @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __CPM_H +#define __CPM_H + +#include +#include +#include +#include +#include + +/* + * SPI Parameter RAM common to QE and CPM. + */ +struct spi_pram { + __be16 rbase; /* Rx Buffer descriptor base address */ + __be16 tbase; /* Tx Buffer descriptor base address */ + u8 rfcr; /* Rx function code */ + u8 tfcr; /* Tx function code */ + __be16 mrblr; /* Max receive buffer length */ + __be32 rstate; /* Internal */ + __be32 rdp; /* Internal */ + __be16 rbptr; /* Internal */ + __be16 rbc; /* Internal */ + __be32 rxtmp; /* Internal */ + __be32 tstate; /* Internal */ + __be32 tdp; /* Internal */ + __be16 tbptr; /* Internal */ + __be16 tbc; /* Internal */ + __be32 txtmp; /* Internal */ + __be32 res; /* Tx temp. */ + __be16 rpbase; /* Relocation pointer (CPM1 only) */ + __be16 res1; /* Reserved */ +}; + +/* + * USB Controller pram common to QE and CPM. + */ +struct usb_ctlr { + u8 usb_usmod; + u8 usb_usadr; + u8 usb_uscom; + u8 res1[1]; + __be16 usb_usep[4]; + u8 res2[4]; + __be16 usb_usber; + u8 res3[2]; + __be16 usb_usbmr; + u8 res4[1]; + u8 usb_usbs; + /* Fields down below are QE-only */ + __be16 usb_ussft; + u8 res5[2]; + __be16 usb_usfrn; + u8 res6[0x22]; +} __attribute__ ((packed)); + +/* + * Function code bits, usually generic to devices. + */ +#ifdef CONFIG_CPM1 +#define CPMFCR_GBL ((u_char)0x00) /* Flag doesn't exist in CPM1 */ +#define CPMFCR_TC2 ((u_char)0x00) /* Flag doesn't exist in CPM1 */ +#define CPMFCR_DTB ((u_char)0x00) /* Flag doesn't exist in CPM1 */ +#define CPMFCR_BDB ((u_char)0x00) /* Flag doesn't exist in CPM1 */ +#else +#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */ +#define CPMFCR_TC2 ((u_char)0x04) /* Transfer code 2 value */ +#define CPMFCR_DTB ((u_char)0x02) /* Use local bus for data when set */ +#define CPMFCR_BDB ((u_char)0x01) /* Use local bus for BD when set */ +#endif +#define CPMFCR_EB ((u_char)0x10) /* Set big endian byte order */ + +/* Opcodes common to CPM1 and CPM2 +*/ +#define CPM_CR_INIT_TRX ((ushort)0x0000) +#define CPM_CR_INIT_RX ((ushort)0x0001) +#define CPM_CR_INIT_TX ((ushort)0x0002) +#define CPM_CR_HUNT_MODE ((ushort)0x0003) +#define CPM_CR_STOP_TX ((ushort)0x0004) +#define CPM_CR_GRA_STOP_TX ((ushort)0x0005) +#define CPM_CR_RESTART_TX ((ushort)0x0006) +#define CPM_CR_CLOSE_RX_BD ((ushort)0x0007) +#define CPM_CR_SET_GADDR ((ushort)0x0008) +#define CPM_CR_SET_TIMER ((ushort)0x0008) +#define CPM_CR_STOP_IDMA ((ushort)0x000b) + +/* Buffer descriptors used by many of the CPM protocols. */ +typedef struct cpm_buf_desc { + ushort cbd_sc; /* Status and Control */ + ushort cbd_datlen; /* Data length in buffer */ + uint cbd_bufaddr; /* Buffer address in host memory */ +} cbd_t; + +/* Buffer descriptor control/status used by serial + */ + +#define BD_SC_EMPTY (0x8000) /* Receive is empty */ +#define BD_SC_READY (0x8000) /* Transmit is ready */ +#define BD_SC_WRAP (0x2000) /* Last buffer descriptor */ +#define BD_SC_INTRPT (0x1000) /* Interrupt on change */ +#define BD_SC_LAST (0x0800) /* Last buffer in frame */ +#define BD_SC_TC (0x0400) /* Transmit CRC */ +#define BD_SC_CM (0x0200) /* Continuous mode */ +#define BD_SC_ID (0x0100) /* Rec'd too many idles */ +#define BD_SC_P (0x0100) /* xmt preamble */ +#define BD_SC_BR (0x0020) /* Break received */ +#define BD_SC_FR (0x0010) /* Framing error */ +#define BD_SC_PR (0x0008) /* Parity error */ +#define BD_SC_NAK (0x0004) /* NAK - did not respond */ +#define BD_SC_OV (0x0002) /* Overrun */ +#define BD_SC_UN (0x0002) /* Underrun */ +#define BD_SC_CD (0x0001) /* */ +#define BD_SC_CL (0x0001) /* Collision */ + +/* Buffer descriptor control/status used by Ethernet receive. + * Common to SCC and FCC. + */ +#define BD_ENET_RX_EMPTY (0x8000) +#define BD_ENET_RX_WRAP (0x2000) +#define BD_ENET_RX_INTR (0x1000) +#define BD_ENET_RX_LAST (0x0800) +#define BD_ENET_RX_FIRST (0x0400) +#define BD_ENET_RX_MISS (0x0100) +#define BD_ENET_RX_BC (0x0080) /* FCC Only */ +#define BD_ENET_RX_MC (0x0040) /* FCC Only */ +#define BD_ENET_RX_LG (0x0020) +#define BD_ENET_RX_NO (0x0010) +#define BD_ENET_RX_SH (0x0008) +#define BD_ENET_RX_CR (0x0004) +#define BD_ENET_RX_OV (0x0002) +#define BD_ENET_RX_CL (0x0001) +#define BD_ENET_RX_STATS (0x01ff) /* All status bits */ + +/* Buffer descriptor control/status used by Ethernet transmit. + * Common to SCC and FCC. + */ +#define BD_ENET_TX_READY (0x8000) +#define BD_ENET_TX_PAD (0x4000) +#define BD_ENET_TX_WRAP (0x2000) +#define BD_ENET_TX_INTR (0x1000) +#define BD_ENET_TX_LAST (0x0800) +#define BD_ENET_TX_TC (0x0400) +#define BD_ENET_TX_DEF (0x0200) +#define BD_ENET_TX_HB (0x0100) +#define BD_ENET_TX_LC (0x0080) +#define BD_ENET_TX_RL (0x0040) +#define BD_ENET_TX_RCMASK (0x003c) +#define BD_ENET_TX_UN (0x0002) +#define BD_ENET_TX_CSL (0x0001) +#define BD_ENET_TX_STATS (0x03ff) /* All status bits */ + +/* Buffer descriptor control/status used by Transparent mode SCC. + */ +#define BD_SCC_TX_LAST (0x0800) + +/* Buffer descriptor control/status used by I2C. + */ +#define BD_I2C_START (0x0400) + +#ifdef CONFIG_CPM +int cpm_command(u32 command, u8 opcode); +#else +static inline int cpm_command(u32 command, u8 opcode) +{ + return -ENOSYS; +} +#endif /* CONFIG_CPM */ + +int cpm2_gpiochip_add32(struct device *dev); + +#endif -- cgit v1.2.3 From c1c80cde7f78c058dcbf0f5c384822094751e022 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:32 +0100 Subject: soc/fsl/qe/qe.h: update include path for cpm.h asm/cpm.h under arch/powerpc is now just a wrapper for including soc/fsl/cpm.h. In order to make the qe.h header usable on other architectures, use the latter path directly. Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- include/soc/fsl/qe/qe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/soc/fsl/qe/qe.h b/include/soc/fsl/qe/qe.h index 9cac04c692fd..521fa3a177e0 100644 --- a/include/soc/fsl/qe/qe.h +++ b/include/soc/fsl/qe/qe.h @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 800cd6fb76f0ec7711deb72a86c924db1ae42648 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:40 +0100 Subject: soc: fsl: qe: change return type of cpm_muram_alloc() to s32 There are a number of problems with cpm_muram_alloc() and its callers. Most callers assign the return value to some variable and then use IS_ERR_VALUE to check for allocation failure. However, when that variable is not sizeof(long), this leads to warnings - and it is indeed broken to do e.g. u32 foo = cpm_muram_alloc(); if (IS_ERR_VALUE(foo)) on a 64-bit platform, since the condition foo >= (unsigned long)-ENOMEM is tautologically false. There are also callers that ignore the possibility of error, and then there are those that check for error by comparing the return value to 0... One could fix that by changing all callers to store the return value temporarily in an "unsigned long" and test that. However, use of IS_ERR_VALUE() is error-prone and should be restricted to things which are inherently long-sized (stuff in pt_regs etc.). Instead, let's aim for changing to the standard kernel style int foo = cpm_muram_alloc(); if (foo < 0) deal_with_it() some->where = foo; Changing the return type from unsigned long to s32 (aka signed int) doesn't change the value that gets stored into any of the callers' variables except if the caller was storing the result in a u64 _and_ the allocation failed, so in itself this patch should be a no-op. Another problem with cpm_muram_alloc() is that it can certainly validly return 0 - and except if some cpm_muram_alloc_fixed() call interferes, the very first cpm_muram_alloc() call will return just that. But that shows that both ucc_slow_free() and ucc_fast_free() are buggy, since they assume that a value of 0 means "that field was never allocated". We'll later change cpm_muram_free() to accept (and ignore) a negative offset, so callers can use a sentinel of -1 instead of 0 and just unconditionally call cpm_muram_free(). Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/qe_common.c | 29 ++++++++++++++++------------- include/soc/fsl/qe/qe.h | 16 ++++++++-------- 2 files changed, 24 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/drivers/soc/fsl/qe/qe_common.c b/drivers/soc/fsl/qe/qe_common.c index 83e85e61669f..84c90105e588 100644 --- a/drivers/soc/fsl/qe/qe_common.c +++ b/drivers/soc/fsl/qe/qe_common.c @@ -32,7 +32,7 @@ static phys_addr_t muram_pbase; struct muram_block { struct list_head head; - unsigned long start; + s32 start; int size; }; @@ -110,13 +110,14 @@ out_muram: * @algo: algorithm for alloc. * @data: data for genalloc's algorithm. * - * This function returns an offset into the muram area. + * This function returns a non-negative offset into the muram area, or + * a negative errno on failure. */ -static unsigned long cpm_muram_alloc_common(unsigned long size, - genpool_algo_t algo, void *data) +static s32 cpm_muram_alloc_common(unsigned long size, + genpool_algo_t algo, void *data) { struct muram_block *entry; - unsigned long start; + s32 start; if (!muram_pool && cpm_muram_init()) goto out2; @@ -137,7 +138,7 @@ static unsigned long cpm_muram_alloc_common(unsigned long size, out1: gen_pool_free(muram_pool, start, size); out2: - return (unsigned long)-ENOMEM; + return -ENOMEM; } /* @@ -145,13 +146,14 @@ out2: * @size: number of bytes to allocate * @align: requested alignment, in bytes * - * This function returns an offset into the muram area. + * This function returns a non-negative offset into the muram area, or + * a negative errno on failure. * Use cpm_dpram_addr() to get the virtual address of the area. * Use cpm_muram_free() to free the allocation. */ -unsigned long cpm_muram_alloc(unsigned long size, unsigned long align) +s32 cpm_muram_alloc(unsigned long size, unsigned long align) { - unsigned long start; + s32 start; unsigned long flags; struct genpool_data_align muram_pool_data; @@ -168,7 +170,7 @@ EXPORT_SYMBOL(cpm_muram_alloc); * cpm_muram_free - free a chunk of multi-user ram * @offset: The beginning of the chunk as returned by cpm_muram_alloc(). */ -int cpm_muram_free(unsigned long offset) +int cpm_muram_free(s32 offset) { unsigned long flags; int size; @@ -194,13 +196,14 @@ EXPORT_SYMBOL(cpm_muram_free); * cpm_muram_alloc_fixed - reserve a specific region of multi-user ram * @offset: offset of allocation start address * @size: number of bytes to allocate - * This function returns an offset into the muram area + * This function returns @offset if the area was available, a negative + * errno otherwise. * Use cpm_dpram_addr() to get the virtual address of the area. * Use cpm_muram_free() to free the allocation. */ -unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size) +s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size) { - unsigned long start; + s32 start; unsigned long flags; struct genpool_data_fixed muram_pool_data_fixed; diff --git a/include/soc/fsl/qe/qe.h b/include/soc/fsl/qe/qe.h index 521fa3a177e0..f589ae3f1216 100644 --- a/include/soc/fsl/qe/qe.h +++ b/include/soc/fsl/qe/qe.h @@ -98,26 +98,26 @@ static inline void qe_reset(void) {} int cpm_muram_init(void); #if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) -unsigned long cpm_muram_alloc(unsigned long size, unsigned long align); -int cpm_muram_free(unsigned long offset); -unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); +s32 cpm_muram_alloc(unsigned long size, unsigned long align); +int cpm_muram_free(s32 offset); +s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); void __iomem *cpm_muram_addr(unsigned long offset); unsigned long cpm_muram_offset(void __iomem *addr); dma_addr_t cpm_muram_dma(void __iomem *addr); #else -static inline unsigned long cpm_muram_alloc(unsigned long size, - unsigned long align) +static inline s32 cpm_muram_alloc(unsigned long size, + unsigned long align) { return -ENOSYS; } -static inline int cpm_muram_free(unsigned long offset) +static inline int cpm_muram_free(s32 offset) { return -ENOSYS; } -static inline unsigned long cpm_muram_alloc_fixed(unsigned long offset, - unsigned long size) +static inline s32 cpm_muram_alloc_fixed(unsigned long offset, + unsigned long size) { return -ENOSYS; } -- cgit v1.2.3 From 754f40e0977cd20c37ef4837ec2904ccd89125ce Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:41 +0100 Subject: soc: fsl: qe: make cpm_muram_free() return void Nobody uses the return value from cpm_muram_free, and functions that free resources usually return void. One could imagine a use for a "how much have I allocated" a la ksize(), but knowing how much one had access to after the fact is useless. Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/qe_common.c | 3 +-- include/soc/fsl/qe/qe.h | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/soc/fsl/qe/qe_common.c b/drivers/soc/fsl/qe/qe_common.c index 84c90105e588..962835488f66 100644 --- a/drivers/soc/fsl/qe/qe_common.c +++ b/drivers/soc/fsl/qe/qe_common.c @@ -170,7 +170,7 @@ EXPORT_SYMBOL(cpm_muram_alloc); * cpm_muram_free - free a chunk of multi-user ram * @offset: The beginning of the chunk as returned by cpm_muram_alloc(). */ -int cpm_muram_free(s32 offset) +void cpm_muram_free(s32 offset) { unsigned long flags; int size; @@ -188,7 +188,6 @@ int cpm_muram_free(s32 offset) } gen_pool_free(muram_pool, offset + GENPOOL_OFFSET, size); spin_unlock_irqrestore(&cpm_muram_lock, flags); - return size; } EXPORT_SYMBOL(cpm_muram_free); diff --git a/include/soc/fsl/qe/qe.h b/include/soc/fsl/qe/qe.h index f589ae3f1216..e282ac01ec08 100644 --- a/include/soc/fsl/qe/qe.h +++ b/include/soc/fsl/qe/qe.h @@ -99,7 +99,7 @@ int cpm_muram_init(void); #if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) s32 cpm_muram_alloc(unsigned long size, unsigned long align); -int cpm_muram_free(s32 offset); +void cpm_muram_free(s32 offset); s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); void __iomem *cpm_muram_addr(unsigned long offset); unsigned long cpm_muram_offset(void __iomem *addr); @@ -111,9 +111,8 @@ static inline s32 cpm_muram_alloc(unsigned long size, return -ENOSYS; } -static inline int cpm_muram_free(s32 offset) +static inline void cpm_muram_free(s32 offset) { - return -ENOSYS; } static inline s32 cpm_muram_alloc_fixed(unsigned long offset, -- cgit v1.2.3 From 611780a6aa500345360bcda8a6dfdcd0666d4695 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:45 +0100 Subject: soc: fsl: qe: avoid IS_ERR_VALUE in ucc_slow.c When trying to build this for a 64-bit platform, one gets warnings from using IS_ERR_VALUE on something which is not sizeof(long). Instead, change the various *_offset fields to store a signed integer, and simply check for a negative return from qe_muram_alloc(). Since qe_muram_free() now accepts and ignores a negative argument, we only need to make sure these fields are initialized with -1, and we can just unconditionally call qe_muram_free() in ucc_slow_free(). Note that the error case for us_pram_offset failed to set that field to 0 (which, as noted earlier, is anyway a bogus sentinel value). Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/ucc_slow.c | 22 +++++++++------------- include/soc/fsl/qe/ucc_slow.h | 6 +++--- 2 files changed, 12 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/soc/fsl/qe/ucc_slow.c b/drivers/soc/fsl/qe/ucc_slow.c index 9b55fd0f50c6..274d34449846 100644 --- a/drivers/soc/fsl/qe/ucc_slow.c +++ b/drivers/soc/fsl/qe/ucc_slow.c @@ -154,6 +154,9 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc __func__); return -ENOMEM; } + uccs->rx_base_offset = -1; + uccs->tx_base_offset = -1; + uccs->us_pram_offset = -1; /* Fill slow UCC structure */ uccs->us_info = us_info; @@ -179,7 +182,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc /* Get PRAM base */ uccs->us_pram_offset = qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM); - if (IS_ERR_VALUE(uccs->us_pram_offset)) { + if (uccs->us_pram_offset < 0) { printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __func__); ucc_slow_free(uccs); return -ENOMEM; @@ -206,10 +209,9 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc uccs->rx_base_offset = qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd), QE_ALIGNMENT_OF_BD); - if (IS_ERR_VALUE(uccs->rx_base_offset)) { + if (uccs->rx_base_offset < 0) { printk(KERN_ERR "%s: cannot allocate %u RX BDs\n", __func__, us_info->rx_bd_ring_len); - uccs->rx_base_offset = 0; ucc_slow_free(uccs); return -ENOMEM; } @@ -217,9 +219,8 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc uccs->tx_base_offset = qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd), QE_ALIGNMENT_OF_BD); - if (IS_ERR_VALUE(uccs->tx_base_offset)) { + if (uccs->tx_base_offset < 0) { printk(KERN_ERR "%s: cannot allocate TX BDs", __func__); - uccs->tx_base_offset = 0; ucc_slow_free(uccs); return -ENOMEM; } @@ -352,14 +353,9 @@ void ucc_slow_free(struct ucc_slow_private * uccs) if (!uccs) return; - if (uccs->rx_base_offset) - qe_muram_free(uccs->rx_base_offset); - - if (uccs->tx_base_offset) - qe_muram_free(uccs->tx_base_offset); - - if (uccs->us_pram) - qe_muram_free(uccs->us_pram_offset); + qe_muram_free(uccs->rx_base_offset); + qe_muram_free(uccs->tx_base_offset); + qe_muram_free(uccs->us_pram_offset); if (uccs->us_regs) iounmap(uccs->us_regs); diff --git a/include/soc/fsl/qe/ucc_slow.h b/include/soc/fsl/qe/ucc_slow.h index 8696fdea2ae9..d187a6be83bc 100644 --- a/include/soc/fsl/qe/ucc_slow.h +++ b/include/soc/fsl/qe/ucc_slow.h @@ -185,7 +185,7 @@ struct ucc_slow_private { struct ucc_slow_info *us_info; struct ucc_slow __iomem *us_regs; /* Ptr to memory map of UCC regs */ struct ucc_slow_pram *us_pram; /* a pointer to the parameter RAM */ - u32 us_pram_offset; + s32 us_pram_offset; int enabled_tx; /* Whether channel is enabled for Tx (ENT) */ int enabled_rx; /* Whether channel is enabled for Rx (ENR) */ int stopped_tx; /* Whether channel has been stopped for Tx @@ -194,8 +194,8 @@ struct ucc_slow_private { struct list_head confQ; /* frames passed to chip waiting for tx */ u32 first_tx_bd_mask; /* mask is used in Tx routine to save status and length for first BD in a frame */ - u32 tx_base_offset; /* first BD in Tx BD table offset (In MURAM) */ - u32 rx_base_offset; /* first BD in Rx BD table offset (In MURAM) */ + s32 tx_base_offset; /* first BD in Tx BD table offset (In MURAM) */ + s32 rx_base_offset; /* first BD in Rx BD table offset (In MURAM) */ struct qe_bd *confBd; /* next BD for confirm after Tx */ struct qe_bd *tx_bd; /* next BD for new Tx request */ struct qe_bd *rx_bd; /* next BD to collect after Rx */ -- cgit v1.2.3 From c93c159aefb089e79def966b99079b585c9108e2 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 28 Nov 2019 15:55:48 +0100 Subject: soc: fsl: qe: avoid IS_ERR_VALUE in ucc_fast.c When building this on a 64-bit platform gcc rightly warns that the error checking is broken (-ENOMEM stored in an u32 does not compare greater than (unsigned long)-MAX_ERRNO). Instead, change the ucc_fast_[tr]x_virtual_fifo_base_offset members to s32 and use an ordinary check-for-negative. Also, this avoids treating 0 as "this cannot have been returned from qe_muram_alloc() so don't free it". Reviewed-by: Timur Tabi Signed-off-by: Rasmus Villemoes Signed-off-by: Li Yang --- drivers/soc/fsl/qe/ucc_fast.c | 15 ++++++--------- include/soc/fsl/qe/ucc_fast.h | 4 ++-- 2 files changed, 8 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/soc/fsl/qe/ucc_fast.c b/drivers/soc/fsl/qe/ucc_fast.c index ca0452497a20..ad6193ea4597 100644 --- a/drivers/soc/fsl/qe/ucc_fast.c +++ b/drivers/soc/fsl/qe/ucc_fast.c @@ -197,6 +197,8 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc __func__); return -ENOMEM; } + uccf->ucc_fast_tx_virtual_fifo_base_offset = -1; + uccf->ucc_fast_rx_virtual_fifo_base_offset = -1; /* Fill fast UCC structure */ uccf->uf_info = uf_info; @@ -265,10 +267,9 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc /* Allocate memory for Tx Virtual Fifo */ uccf->ucc_fast_tx_virtual_fifo_base_offset = qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT); - if (IS_ERR_VALUE(uccf->ucc_fast_tx_virtual_fifo_base_offset)) { + if (uccf->ucc_fast_tx_virtual_fifo_base_offset < 0) { printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO\n", __func__); - uccf->ucc_fast_tx_virtual_fifo_base_offset = 0; ucc_fast_free(uccf); return -ENOMEM; } @@ -278,10 +279,9 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc qe_muram_alloc(uf_info->urfs + UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT); - if (IS_ERR_VALUE(uccf->ucc_fast_rx_virtual_fifo_base_offset)) { + if (uccf->ucc_fast_rx_virtual_fifo_base_offset < 0) { printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO\n", __func__); - uccf->ucc_fast_rx_virtual_fifo_base_offset = 0; ucc_fast_free(uccf); return -ENOMEM; } @@ -384,11 +384,8 @@ void ucc_fast_free(struct ucc_fast_private * uccf) if (!uccf) return; - if (uccf->ucc_fast_tx_virtual_fifo_base_offset) - qe_muram_free(uccf->ucc_fast_tx_virtual_fifo_base_offset); - - if (uccf->ucc_fast_rx_virtual_fifo_base_offset) - qe_muram_free(uccf->ucc_fast_rx_virtual_fifo_base_offset); + qe_muram_free(uccf->ucc_fast_tx_virtual_fifo_base_offset); + qe_muram_free(uccf->ucc_fast_rx_virtual_fifo_base_offset); if (uccf->uf_regs) iounmap(uccf->uf_regs); diff --git a/include/soc/fsl/qe/ucc_fast.h b/include/soc/fsl/qe/ucc_fast.h index e9cc46042a83..ba0e838f962a 100644 --- a/include/soc/fsl/qe/ucc_fast.h +++ b/include/soc/fsl/qe/ucc_fast.h @@ -188,9 +188,9 @@ struct ucc_fast_private { int stopped_tx; /* Whether channel has been stopped for Tx (STOP_TX, etc.) */ int stopped_rx; /* Whether channel has been stopped for Rx */ - u32 ucc_fast_tx_virtual_fifo_base_offset;/* pointer to base of Tx + s32 ucc_fast_tx_virtual_fifo_base_offset;/* pointer to base of Tx virtual fifo */ - u32 ucc_fast_rx_virtual_fifo_base_offset;/* pointer to base of Rx + s32 ucc_fast_rx_virtual_fifo_base_offset;/* pointer to base of Rx virtual fifo */ #ifdef STATISTICS u32 tx_frames; /* Transmitted frames counter. */ -- cgit v1.2.3 From 18ec173d56a13d239dfabe9fe67c36edaa155847 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 18 Nov 2019 17:40:08 +0000 Subject: dt-bindings: power: Add rpmh power-domain bindings for SM8150 Add RPMH power-domain bindings for the SM8150 family of SoCs. Reviewed-by: Bjorn Andersson Reviewed-by: Stephen Boyd Reviewed-by: Rajendra Nayak Reviewed-by: Rob Herring Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/0101016e7f99ad2b-2bce2fac-2f02-4b3f-ac64-09942f7251ea-000000@us-west-2.amazonses.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/power/qcom,rpmpd.txt | 1 + include/dt-bindings/power/qcom-rpmpd.h | 14 ++++++++++++++ 2 files changed, 15 insertions(+) (limited to 'include') diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt index bc75bf49cdae..f3bbaa4aef29 100644 --- a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt @@ -10,6 +10,7 @@ Required Properties: * qcom,msm8998-rpmpd: RPM Power domain for the msm8998 family of SoC * qcom,qcs404-rpmpd: RPM Power domain for the qcs404 family of SoC * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC + * qcom,sm8150-rpmhpd: RPMh Power domain for the sm8150 family of SoC - #power-domain-cells: number of cells in Power domain specifier must be 1. - operating-points-v2: Phandle to the OPP table for the Power domain. diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h index f05f8b1808ec..7d43bafc0026 100644 --- a/include/dt-bindings/power/qcom-rpmpd.h +++ b/include/dt-bindings/power/qcom-rpmpd.h @@ -15,12 +15,26 @@ #define SDM845_GFX 7 #define SDM845_MSS 8 +/* SM8150 Power Domain Indexes */ +#define SM8150_MSS 0 +#define SM8150_EBI 1 +#define SM8150_LMX 2 +#define SM8150_LCX 3 +#define SM8150_GFX 4 +#define SM8150_MX 5 +#define SM8150_MX_AO 6 +#define SM8150_CX 7 +#define SM8150_CX_AO 8 +#define SM8150_MMCX 9 +#define SM8150_MMCX_AO 10 + /* SDM845 Power Domain performance levels */ #define RPMH_REGULATOR_LEVEL_RETENTION 16 #define RPMH_REGULATOR_LEVEL_MIN_SVS 48 #define RPMH_REGULATOR_LEVEL_LOW_SVS 64 #define RPMH_REGULATOR_LEVEL_SVS 128 #define RPMH_REGULATOR_LEVEL_SVS_L1 192 +#define RPMH_REGULATOR_LEVEL_SVS_L2 224 #define RPMH_REGULATOR_LEVEL_NOM 256 #define RPMH_REGULATOR_LEVEL_NOM_L1 320 #define RPMH_REGULATOR_LEVEL_NOM_L2 336 -- cgit v1.2.3 From 52a4cb577bde6e69fae451c10c8b2ec69033263a Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 18 Nov 2019 17:40:15 +0000 Subject: dt-bindings: power: Add rpmh power-domain bindings for sc7180 Add RPMH power-domain bindings for the SC7180 family of SoCs. Reviewed-by: Stephen Boyd Reviewed-by: Rajendra Nayak Reviewed-by: Bjorn Andersson Reviewed-by: Rob Herring Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/0101016e7f99ca4e-47d442f4-b923-4eea-b812-898e5476beab-000000@us-west-2.amazonses.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/power/qcom,rpmpd.txt | 1 + include/dt-bindings/power/qcom-rpmpd.h | 10 ++++++++++ 2 files changed, 11 insertions(+) (limited to 'include') diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt index f3bbaa4aef29..6346d00b1b40 100644 --- a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt @@ -9,6 +9,7 @@ Required Properties: * qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC * qcom,msm8998-rpmpd: RPM Power domain for the msm8998 family of SoC * qcom,qcs404-rpmpd: RPM Power domain for the qcs404 family of SoC + * qcom,sc7180-rpmhpd: RPMh Power domain for the sc7180 family of SoC * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC * qcom,sm8150-rpmhpd: RPMh Power domain for the sm8150 family of SoC - #power-domain-cells: number of cells in Power domain specifier diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h index 7d43bafc0026..3f74096d5a7c 100644 --- a/include/dt-bindings/power/qcom-rpmpd.h +++ b/include/dt-bindings/power/qcom-rpmpd.h @@ -28,6 +28,16 @@ #define SM8150_MMCX 9 #define SM8150_MMCX_AO 10 +/* SC7180 Power Domain Indexes */ +#define SC7180_CX 0 +#define SC7180_CX_AO 1 +#define SC7180_GFX 2 +#define SC7180_MX 3 +#define SC7180_MX_AO 4 +#define SC7180_LMX 5 +#define SC7180_LCX 6 +#define SC7180_MSS 7 + /* SDM845 Power Domain performance levels */ #define RPMH_REGULATOR_LEVEL_RETENTION 16 #define RPMH_REGULATOR_LEVEL_MIN_SVS 48 -- cgit v1.2.3 From 461011b1e1ab62aa8a8af78d5b7ee0f81bd1fa37 Mon Sep 17 00:00:00 2001 From: Ravi Patel Date: Tue, 12 Nov 2019 00:35:55 -0800 Subject: drivers: firmware: xilinx: Add support for feature check Query for corresponding feature before calling EEMI API from the driver. Signed-off-by: Ravi Patel Signed-off-by: Michal Simek Signed-off-by: Rajan Vaja --- drivers/firmware/xilinx/zynqmp.c | 43 ++++++++++++++++++++++++++++++++++++ include/linux/firmware/xlnx-zynqmp.h | 7 ++++++ 2 files changed, 50 insertions(+) (limited to 'include') diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index 75bdfaa08380..0137bf328e54 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -26,6 +26,9 @@ static const struct zynqmp_eemi_ops *eemi_ops_tbl; +static bool feature_check_enabled; +static u32 zynqmp_pm_features[PM_API_MAX]; + static const struct mfd_cell firmware_devs[] = { { .name = "zynqmp_power_controller", @@ -44,6 +47,8 @@ static int zynqmp_pm_ret_code(u32 ret_status) case XST_PM_SUCCESS: case XST_PM_DOUBLE_REQ: return 0; + case XST_PM_NO_FEATURE: + return -ENOTSUPP; case XST_PM_NO_ACCESS: return -EACCES; case XST_PM_ABORT_SUSPEND: @@ -126,6 +131,39 @@ static noinline int do_fw_call_hvc(u64 arg0, u64 arg1, u64 arg2, return zynqmp_pm_ret_code((enum pm_ret_status)res.a0); } +/** + * zynqmp_pm_feature() - Check weather given feature is supported or not + * @api_id: API ID to check + * + * Return: Returns status, either success or error+reason + */ +static int zynqmp_pm_feature(u32 api_id) +{ + int ret; + u32 ret_payload[PAYLOAD_ARG_CNT]; + u64 smc_arg[2]; + + if (!feature_check_enabled) + return 0; + + /* Return value if feature is already checked */ + if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED) + return zynqmp_pm_features[api_id]; + + smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK; + smc_arg[1] = api_id; + + ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload); + if (ret) { + zynqmp_pm_features[api_id] = PM_FEATURE_INVALID; + return PM_FEATURE_INVALID; + } + + zynqmp_pm_features[api_id] = ret_payload[1]; + + return zynqmp_pm_features[api_id]; +} + /** * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer * caller function depending on the configuration @@ -160,6 +198,9 @@ int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1, */ u64 smc_arg[4]; + if (zynqmp_pm_feature(pm_api_id) == PM_FEATURE_INVALID) + return -ENOTSUPP; + smc_arg[0] = PM_SIP_SVC | pm_api_id; smc_arg[1] = ((u64)arg1 << 32) | arg0; smc_arg[2] = ((u64)arg3 << 32) | arg2; @@ -715,6 +756,8 @@ static int zynqmp_firmware_probe(struct platform_device *pdev) np = of_find_compatible_node(NULL, NULL, "xlnx,versal"); if (!np) return 0; + + feature_check_enabled = true; } of_node_put(np); diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index e41ad9e37136..e72eccf69721 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -48,6 +48,10 @@ #define ZYNQMP_PM_CAPABILITY_WAKEUP 0x4U #define ZYNQMP_PM_CAPABILITY_UNUSABLE 0x8U +/* Feature check status */ +#define PM_FEATURE_INVALID -1 +#define PM_FEATURE_UNCHECKED 0 + /* * Firmware FPGA Manager flags * XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration @@ -78,11 +82,14 @@ enum pm_api_id { PM_CLOCK_GETRATE, PM_CLOCK_SETPARENT, PM_CLOCK_GETPARENT, + PM_FEATURE_CHECK = 63, + PM_API_MAX, }; /* PMU-FW return status codes */ enum pm_ret_status { XST_PM_SUCCESS = 0, + XST_PM_NO_FEATURE = 19, XST_PM_INTERNAL = 2000, XST_PM_CONFLICT, XST_PM_NO_ACCESS, -- cgit v1.2.3 From 94f6345712b37e4bb23cb265ce4c65b9d177e75a Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 12 Dec 2019 08:57:58 -0800 Subject: bus: ti-sysc: Implement quirk handling for CLKDM_NOAUTO For dra7 dcan and dwc3 instances we need to block clockdomain autoidle. Let's do this with CLKDM_NOAUTO quirk flag and enable it for dcan and dwc3. Cc: Keerthy Cc: Roger Quadros Cc: Tero Kristo Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 10 ++++++++-- include/linux/platform_data/ti-sysc.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index f4d1597df0a2..d9c8b00a3b85 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -473,7 +473,7 @@ static void sysc_clkdm_deny_idle(struct sysc *ddata) { struct ti_sysc_platform_data *pdata; - if (ddata->legacy_mode) + if (ddata->legacy_mode || (ddata->cfg.quirks & SYSC_QUIRK_CLKDM_NOAUTO)) return; pdata = dev_get_platdata(ddata->dev); @@ -485,7 +485,7 @@ static void sysc_clkdm_allow_idle(struct sysc *ddata) { struct ti_sysc_platform_data *pdata; - if (ddata->legacy_mode) + if (ddata->legacy_mode || (ddata->cfg.quirks & SYSC_QUIRK_CLKDM_NOAUTO)) return; pdata = dev_get_platdata(ddata->dev); @@ -1245,6 +1245,12 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { /* Quirks that need to be set based on detected module */ SYSC_QUIRK("aess", 0, 0, 0x10, -1, 0x40000000, 0xffffffff, SYSC_MODULE_QUIRK_AESS), + SYSC_QUIRK("dcan", 0x48480000, 0x20, -1, -1, 0xa3170504, 0xffffffff, + SYSC_QUIRK_CLKDM_NOAUTO), + SYSC_QUIRK("dwc3", 0x48880000, 0, 0x10, -1, 0x500a0200, 0xffffffff, + SYSC_QUIRK_CLKDM_NOAUTO), + SYSC_QUIRK("dwc3", 0x488c0000, 0, 0x10, -1, 0x500a0200, 0xffffffff, + SYSC_QUIRK_CLKDM_NOAUTO), SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, SYSC_MODULE_QUIRK_HDQ1W), SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff, diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 8cfe570fdece..2cbde6542849 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -49,6 +49,7 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSC_QUIRK_CLKDM_NOAUTO BIT(21) #define SYSC_QUIRK_FORCE_MSTANDBY BIT(20) #define SYSC_MODULE_QUIRK_AESS BIT(19) #define SYSC_MODULE_QUIRK_SGX BIT(18) -- cgit v1.2.3 From ee7a9c9f67c59008b330deff2762bd8cf1407eec Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 21 Dec 2018 18:08:08 +0000 Subject: firmware: arm_scmi: Add support for multiple device per protocol Currently only one scmi device is created for each protocol enumerated. However, there is requirement to make use of some procotols by multiple kernel subsystems/frameworks. One such example is SCMI PERFORMANCE protocol which can be used by both cpufreq and devfreq drivers. Similarly, SENSOR protocol may be used by hwmon and iio subsystems, and POWER protocol may be used by genpd and regulator drivers. In order to achieve that, let us extend the scmi bus to match based not only protocol id but also the scmi device name if one is available. Reviewed-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/bus.c | 20 +++++++++++++++++--- drivers/firmware/arm_scmi/driver.c | 6 +++--- include/linux/scmi_protocol.h | 5 ++++- 3 files changed, 24 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index 7a30952b463d..3714e6307b05 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -28,8 +28,12 @@ scmi_dev_match_id(struct scmi_device *scmi_dev, struct scmi_driver *scmi_drv) return NULL; for (; id->protocol_id; id++) - if (id->protocol_id == scmi_dev->protocol_id) - return id; + if (id->protocol_id == scmi_dev->protocol_id) { + if (!id->name) + return id; + else if (!strcmp(id->name, scmi_dev->name)) + return id; + } return NULL; } @@ -125,7 +129,8 @@ static void scmi_device_release(struct device *dev) } struct scmi_device * -scmi_device_create(struct device_node *np, struct device *parent, int protocol) +scmi_device_create(struct device_node *np, struct device *parent, int protocol, + const char *name) { int id, retval; struct scmi_device *scmi_dev; @@ -134,8 +139,15 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol) if (!scmi_dev) return NULL; + scmi_dev->name = kstrdup_const(name ?: "unknown", GFP_KERNEL); + if (!scmi_dev->name) { + kfree(scmi_dev); + return NULL; + } + id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL); if (id < 0) { + kfree_const(scmi_dev->name); kfree(scmi_dev); return NULL; } @@ -154,6 +166,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol) return scmi_dev; put_dev: + kfree_const(scmi_dev->name); put_device(&scmi_dev->dev); ida_simple_remove(&scmi_bus_id, id); return NULL; @@ -161,6 +174,7 @@ put_dev: void scmi_device_destroy(struct scmi_device *scmi_dev) { + kfree_const(scmi_dev->name); scmi_handle_put(scmi_dev->handle); ida_simple_remove(&scmi_bus_id, scmi_dev->id); device_unregister(&scmi_dev->dev); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 3eb0382491ce..dee7ce3bd815 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -803,11 +803,11 @@ scmi_mbox_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id) static inline void scmi_create_protocol_device(struct device_node *np, struct scmi_info *info, - int prot_id) + int prot_id, const char *name) { struct scmi_device *sdev; - sdev = scmi_device_create(np, info->dev, prot_id); + sdev = scmi_device_create(np, info->dev, prot_id, name); if (!sdev) { dev_err(info->dev, "failed to create %d protocol device\n", prot_id); @@ -892,7 +892,7 @@ static int scmi_probe(struct platform_device *pdev) continue; } - scmi_create_protocol_device(child, info, prot_id); + scmi_create_protocol_device(child, info, prot_id, NULL); } return 0; diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 881fea47c83d..5c873a59b387 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -257,6 +257,7 @@ enum scmi_std_protocol { struct scmi_device { u32 id; u8 protocol_id; + const char *name; struct device dev; struct scmi_handle *handle; }; @@ -264,11 +265,13 @@ struct scmi_device { #define to_scmi_dev(d) container_of(d, struct scmi_device, dev) struct scmi_device * -scmi_device_create(struct device_node *np, struct device *parent, int protocol); +scmi_device_create(struct device_node *np, struct device *parent, int protocol, + const char *name); void scmi_device_destroy(struct scmi_device *scmi_dev); struct scmi_device_id { u8 protocol_id; + const char *name; }; struct scmi_driver { -- cgit v1.2.3 From 257d0e20ec4f94e33ac463b918fb82bb1b2dcbe0 Mon Sep 17 00:00:00 2001 From: Lukasz Luba Date: Tue, 17 Dec 2019 13:43:44 +0000 Subject: include: trace: Add SCMI header with trace events Adding trace events would help to measure the speed of the communication channel. It can be also potentially used helpful during investigation of some issues platforms which use different transport layer. Update also MAINTAINERS file with information that the new trace events are maintained. Suggested-by: Jim Quinlan Signed-off-by: Lukasz Luba Signed-off-by: Sudeep Holla --- MAINTAINERS | 1 + include/trace/events/scmi.h | 90 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 include/trace/events/scmi.h (limited to 'include') diff --git a/MAINTAINERS b/MAINTAINERS index bd5847e802de..5bea0797a086 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15965,6 +15965,7 @@ F: drivers/firmware/arm_scpi.c F: drivers/firmware/arm_scmi/ F: drivers/reset/reset-scmi.c F: include/linux/sc[mp]i_protocol.h +F: include/trace/events/scmi.h SYSTEM RESET/SHUTDOWN DRIVERS M: Sebastian Reichel diff --git a/include/trace/events/scmi.h b/include/trace/events/scmi.h new file mode 100644 index 000000000000..f076c430d243 --- /dev/null +++ b/include/trace/events/scmi.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM scmi + +#if !defined(_TRACE_SCMI_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_SCMI_H + +#include + +TRACE_EVENT(scmi_xfer_begin, + TP_PROTO(int transfer_id, u8 msg_id, u8 protocol_id, u16 seq, + bool poll), + TP_ARGS(transfer_id, msg_id, protocol_id, seq, poll), + + TP_STRUCT__entry( + __field(int, transfer_id) + __field(u8, msg_id) + __field(u8, protocol_id) + __field(u16, seq) + __field(bool, poll) + ), + + TP_fast_assign( + __entry->transfer_id = transfer_id; + __entry->msg_id = msg_id; + __entry->protocol_id = protocol_id; + __entry->seq = seq; + __entry->poll = poll; + ), + + TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u poll=%u", + __entry->transfer_id, __entry->msg_id, __entry->protocol_id, + __entry->seq, __entry->poll) +); + +TRACE_EVENT(scmi_xfer_end, + TP_PROTO(int transfer_id, u8 msg_id, u8 protocol_id, u16 seq, + u32 status), + TP_ARGS(transfer_id, msg_id, protocol_id, seq, status), + + TP_STRUCT__entry( + __field(int, transfer_id) + __field(u8, msg_id) + __field(u8, protocol_id) + __field(u16, seq) + __field(u32, status) + ), + + TP_fast_assign( + __entry->transfer_id = transfer_id; + __entry->msg_id = msg_id; + __entry->protocol_id = protocol_id; + __entry->seq = seq; + __entry->status = status; + ), + + TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u status=%u", + __entry->transfer_id, __entry->msg_id, __entry->protocol_id, + __entry->seq, __entry->status) +); + +TRACE_EVENT(scmi_rx_done, + TP_PROTO(int transfer_id, u8 msg_id, u8 protocol_id, u16 seq, + u8 msg_type), + TP_ARGS(transfer_id, msg_id, protocol_id, seq, msg_type), + + TP_STRUCT__entry( + __field(int, transfer_id) + __field(u8, msg_id) + __field(u8, protocol_id) + __field(u16, seq) + __field(u8, msg_type) + ), + + TP_fast_assign( + __entry->transfer_id = transfer_id; + __entry->msg_id = msg_id; + __entry->protocol_id = protocol_id; + __entry->seq = seq; + __entry->msg_type = msg_type; + ), + + TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u msg_type=%u", + __entry->transfer_id, __entry->msg_id, __entry->protocol_id, + __entry->seq, __entry->msg_type) +); +#endif /* _TRACE_SCMI_H */ + +/* This part must be outside protection */ +#include -- cgit v1.2.3 From a5df0d4e9d7d774bdd43b893fb4b1d0a743a053a Mon Sep 17 00:00:00 2001 From: Tomer Maimon Date: Wed, 6 Nov 2019 16:53:30 +0200 Subject: dt-bindings: reset: Add binding constants for NPCM7xx reset controller Add device tree binding constants for Nuvoton BMC NPCM7xx reset controller. Signed-off-by: Tomer Maimon Reviewed-by: Rob Herring Signed-off-by: Philipp Zabel --- include/dt-bindings/reset/nuvoton,npcm7xx-reset.h | 91 +++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 include/dt-bindings/reset/nuvoton,npcm7xx-reset.h (limited to 'include') diff --git a/include/dt-bindings/reset/nuvoton,npcm7xx-reset.h b/include/dt-bindings/reset/nuvoton,npcm7xx-reset.h new file mode 100644 index 000000000000..df088e68a9ba --- /dev/null +++ b/include/dt-bindings/reset/nuvoton,npcm7xx-reset.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (c) 2019 Nuvoton Technology corporation. + +#ifndef _DT_BINDINGS_NPCM7XX_RESET_H +#define _DT_BINDINGS_NPCM7XX_RESET_H + +#define NPCM7XX_RESET_IPSRST1 0x20 +#define NPCM7XX_RESET_IPSRST2 0x24 +#define NPCM7XX_RESET_IPSRST3 0x34 + +/* Reset lines on IP1 reset module (NPCM7XX_RESET_IPSRST1) */ +#define NPCM7XX_RESET_FIU3 1 +#define NPCM7XX_RESET_UDC1 5 +#define NPCM7XX_RESET_EMC1 6 +#define NPCM7XX_RESET_UART_2_3 7 +#define NPCM7XX_RESET_UDC2 8 +#define NPCM7XX_RESET_PECI 9 +#define NPCM7XX_RESET_AES 10 +#define NPCM7XX_RESET_UART_0_1 11 +#define NPCM7XX_RESET_MC 12 +#define NPCM7XX_RESET_SMB2 13 +#define NPCM7XX_RESET_SMB3 14 +#define NPCM7XX_RESET_SMB4 15 +#define NPCM7XX_RESET_SMB5 16 +#define NPCM7XX_RESET_PWM_M0 18 +#define NPCM7XX_RESET_TIMER_0_4 19 +#define NPCM7XX_RESET_TIMER_5_9 20 +#define NPCM7XX_RESET_EMC2 21 +#define NPCM7XX_RESET_UDC4 22 +#define NPCM7XX_RESET_UDC5 23 +#define NPCM7XX_RESET_UDC6 24 +#define NPCM7XX_RESET_UDC3 25 +#define NPCM7XX_RESET_ADC 27 +#define NPCM7XX_RESET_SMB6 28 +#define NPCM7XX_RESET_SMB7 29 +#define NPCM7XX_RESET_SMB0 30 +#define NPCM7XX_RESET_SMB1 31 + +/* Reset lines on IP2 reset module (NPCM7XX_RESET_IPSRST2) */ +#define NPCM7XX_RESET_MFT0 0 +#define NPCM7XX_RESET_MFT1 1 +#define NPCM7XX_RESET_MFT2 2 +#define NPCM7XX_RESET_MFT3 3 +#define NPCM7XX_RESET_MFT4 4 +#define NPCM7XX_RESET_MFT5 5 +#define NPCM7XX_RESET_MFT6 6 +#define NPCM7XX_RESET_MFT7 7 +#define NPCM7XX_RESET_MMC 8 +#define NPCM7XX_RESET_SDHC 9 +#define NPCM7XX_RESET_GFX_SYS 10 +#define NPCM7XX_RESET_AHB_PCIBRG 11 +#define NPCM7XX_RESET_VDMA 12 +#define NPCM7XX_RESET_ECE 13 +#define NPCM7XX_RESET_VCD 14 +#define NPCM7XX_RESET_OTP 16 +#define NPCM7XX_RESET_SIOX1 18 +#define NPCM7XX_RESET_SIOX2 19 +#define NPCM7XX_RESET_3DES 21 +#define NPCM7XX_RESET_PSPI1 22 +#define NPCM7XX_RESET_PSPI2 23 +#define NPCM7XX_RESET_GMAC2 25 +#define NPCM7XX_RESET_USB_HOST 26 +#define NPCM7XX_RESET_GMAC1 28 +#define NPCM7XX_RESET_CP 31 + +/* Reset lines on IP3 reset module (NPCM7XX_RESET_IPSRST3) */ +#define NPCM7XX_RESET_PWM_M1 0 +#define NPCM7XX_RESET_SMB12 1 +#define NPCM7XX_RESET_SPIX 2 +#define NPCM7XX_RESET_SMB13 3 +#define NPCM7XX_RESET_UDC0 4 +#define NPCM7XX_RESET_UDC7 5 +#define NPCM7XX_RESET_UDC8 6 +#define NPCM7XX_RESET_UDC9 7 +#define NPCM7XX_RESET_PCI_MAILBOX 9 +#define NPCM7XX_RESET_SMB14 12 +#define NPCM7XX_RESET_SHA 13 +#define NPCM7XX_RESET_SEC_ECC 14 +#define NPCM7XX_RESET_PCIE_RC 15 +#define NPCM7XX_RESET_TIMER_10_14 16 +#define NPCM7XX_RESET_RNG 17 +#define NPCM7XX_RESET_SMB15 18 +#define NPCM7XX_RESET_SMB8 19 +#define NPCM7XX_RESET_SMB9 20 +#define NPCM7XX_RESET_SMB10 21 +#define NPCM7XX_RESET_SMB11 22 +#define NPCM7XX_RESET_ESPI 23 +#define NPCM7XX_RESET_USB_PHY_1 24 +#define NPCM7XX_RESET_USB_PHY_2 25 + +#endif -- cgit v1.2.3 From 49fdcd7577efe9efe863cdbb154f32a96970c1bc Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 10 Oct 2019 12:01:48 +0200 Subject: firmware: psci: Export functions to manage the OSI mode To allow subsequent changes to implement support for OSI mode through the cpuidle-psci driver, export the existing psci_has_osi_support(). Export also a new function, psci_set_osi_mode(), that allows its caller to enable the OS-initiated CPU-suspend mode in the PSCI FW. To deal with backwards compatibility for a kernel started through a kexec call, default to set the CPU-suspend mode to the Platform Coordinated mode during boot. Signed-off-by: Ulf Hansson Reviewed-by: Sudeep Holla --- drivers/firmware/psci/psci.c | 18 ++++++++++++++++-- include/linux/psci.h | 2 ++ 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index b3b6c15e7b36..2937d44b5df4 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -97,7 +97,7 @@ static inline bool psci_has_ext_power_state(void) PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK; } -static inline bool psci_has_osi_support(void) +bool psci_has_osi_support(void) { return psci_cpu_suspend_feature & PSCI_1_0_OS_INITIATED; } @@ -162,6 +162,15 @@ static u32 psci_get_version(void) return invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0); } +int psci_set_osi_mode(void) +{ + int err; + + err = invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE, + PSCI_1_0_SUSPEND_MODE_OSI, 0, 0); + return psci_to_linux_errno(err); +} + static int psci_cpu_suspend(u32 state, unsigned long entry_point) { int err; @@ -544,9 +553,14 @@ static int __init psci_1_0_init(struct device_node *np) if (err) return err; - if (psci_has_osi_support()) + if (psci_has_osi_support()) { pr_info("OSI mode supported.\n"); + /* Default to PC mode. */ + invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE, + PSCI_1_0_SUSPEND_MODE_PC, 0, 0); + } + return 0; } diff --git a/include/linux/psci.h b/include/linux/psci.h index ebe0a881d13d..a67712b73b6c 100644 --- a/include/linux/psci.h +++ b/include/linux/psci.h @@ -18,6 +18,8 @@ bool psci_tos_resident_on(int cpu); int psci_cpu_suspend_enter(u32 state); bool psci_power_state_is_valid(u32 state); +int psci_set_osi_mode(void); +bool psci_has_osi_support(void); enum smccc_version { SMCCC_VERSION_1_0, -- cgit v1.2.3 From b9f8c26afc405a4a616e765e949bdd551151e41d Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 10 Oct 2019 12:01:48 +0200 Subject: of: base: Add of_get_cpu_state_node() to get idle states for a CPU node The CPU's idle state nodes are currently parsed at the common cpuidle DT library, but also when initializing data for specific CPU idle operations, as in the PSCI cpuidle driver case and qcom-spm cpuidle case. To avoid open-coding, let's introduce of_get_cpu_state_node(), which takes the device node for the CPU and the index to the requested idle state node, as in-parameters. In case a corresponding idle state node is found, it returns the node with the refcount incremented for it, else it returns NULL. Moreover, for PSCI there are two options to describe the CPU's idle states [1], either via a flattened description or a hierarchical layout. Hence, let's take both options into account. [1] Documentation/devicetree/bindings/arm/psci.yaml Suggested-by: Sudeep Holla Co-developed-by: Lina Iyer Signed-off-by: Lina Iyer Reviewed-by: Rob Herring Reviewed-by: Daniel Lezcano Signed-off-by: Ulf Hansson Reviewed-by: Sudeep Holla --- drivers/of/base.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/of.h | 8 ++++++++ 2 files changed, 44 insertions(+) (limited to 'include') diff --git a/drivers/of/base.c b/drivers/of/base.c index db7fbc0c0893..614f0c674995 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -489,6 +489,42 @@ int of_cpu_node_to_id(struct device_node *cpu_node) } EXPORT_SYMBOL(of_cpu_node_to_id); +/** + * of_get_cpu_state_node - Get CPU's idle state node at the given index + * + * @cpu_node: The device node for the CPU + * @index: The index in the list of the idle states + * + * Two generic methods can be used to describe a CPU's idle states, either via + * a flattened description through the "cpu-idle-states" binding or via the + * hierarchical layout, using the "power-domains" and the "domain-idle-states" + * bindings. This function check for both and returns the idle state node for + * the requested index. + * + * In case an idle state node is found at @index, the refcount is incremented + * for it, so call of_node_put() on it when done. Returns NULL if not found. + */ +struct device_node *of_get_cpu_state_node(struct device_node *cpu_node, + int index) +{ + struct of_phandle_args args; + int err; + + err = of_parse_phandle_with_args(cpu_node, "power-domains", + "#power-domain-cells", 0, &args); + if (!err) { + struct device_node *state_node = + of_parse_phandle(args.np, "domain-idle-states", index); + + of_node_put(args.np); + if (state_node) + return state_node; + } + + return of_parse_phandle(cpu_node, "cpu-idle-states", index); +} +EXPORT_SYMBOL(of_get_cpu_state_node); + /** * __of_device_is_compatible() - Check if the node matches given constraints * @device: pointer to node diff --git a/include/linux/of.h b/include/linux/of.h index 844f89e1b039..c669c0a4732f 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -351,6 +351,8 @@ extern const void *of_get_property(const struct device_node *node, int *lenp); extern struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); extern struct device_node *of_get_next_cpu_node(struct device_node *prev); +extern struct device_node *of_get_cpu_state_node(struct device_node *cpu_node, + int index); #define for_each_property_of_node(dn, pp) \ for (pp = dn->properties; pp != NULL; pp = pp->next) @@ -765,6 +767,12 @@ static inline struct device_node *of_get_next_cpu_node(struct device_node *prev) return NULL; } +static inline struct device_node *of_get_cpu_state_node(struct device_node *cpu_node, + int index) +{ + return NULL; +} + static inline int of_n_addr_cells(struct device_node *np) { return 0; -- cgit v1.2.3 From 9c6ceecb6541954dfc410aa8883f872469326c73 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 10 Oct 2019 12:01:48 +0200 Subject: cpuidle: psci: Support CPU hotplug for the hierarchical model When the hierarchical CPU topology is used and when a CPU is put offline, that CPU prevents its PM domain from being powered off, which is because genpd observes the corresponding attached device as being active from a runtime PM point of view. Furthermore, any potential master PM domains are also prevented from being powered off. To address this limitation, let's add add a new CPU hotplug state (CPUHP_AP_CPU_PM_STARTING) and register up/down callbacks for it, which allows us to deal with runtime PM accordingly. Signed-off-by: Ulf Hansson Reviewed-by: Sudeep Holla Acked-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle-psci.c | 45 +++++++++++++++++++++++++++++++++++++++++- include/linux/cpuhotplug.h | 1 + 2 files changed, 45 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c index 6e7804e697ed..9d779be27071 100644 --- a/drivers/cpuidle/cpuidle-psci.c +++ b/drivers/cpuidle/cpuidle-psci.c @@ -8,6 +8,7 @@ #define pr_fmt(fmt) "CPUidle PSCI: " fmt +#include #include #include #include @@ -31,6 +32,7 @@ struct psci_cpuidle_data { static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data); static DEFINE_PER_CPU(u32, domain_state); +static bool psci_cpuidle_use_cpuhp __initdata; static inline void psci_set_domain_state(u32 state) { @@ -72,6 +74,44 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev, return ret; } +static int psci_idle_cpuhp_up(unsigned int cpu) +{ + struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev); + + if (pd_dev) + pm_runtime_get_sync(pd_dev); + + return 0; +} + +static int psci_idle_cpuhp_down(unsigned int cpu) +{ + struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev); + + if (pd_dev) { + pm_runtime_put_sync(pd_dev); + /* Clear domain state to start fresh at next online. */ + psci_set_domain_state(0); + } + + return 0; +} + +static void __init psci_idle_init_cpuhp(void) +{ + int err; + + if (!psci_cpuidle_use_cpuhp) + return; + + err = cpuhp_setup_state_nocalls(CPUHP_AP_CPU_PM_STARTING, + "cpuidle/psci:online", + psci_idle_cpuhp_up, + psci_idle_cpuhp_down); + if (err) + pr_warn("Failed %d while setup cpuhp state\n", err); +} + static int psci_enter_idle_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, int idx) { @@ -166,9 +206,11 @@ static int __init psci_dt_cpu_init_idle(struct cpuidle_driver *drv, * selection of a shared state for the domain, assumes the * domain states are all deeper states. */ - if (data->dev) + if (data->dev) { drv->states[state_count - 1].enter = psci_enter_domain_idle_state; + psci_cpuidle_use_cpuhp = true; + } } /* Idle states parsed correctly, store them in the per-cpu struct. */ @@ -289,6 +331,7 @@ static int __init psci_idle_init(void) goto out_fail; } + psci_idle_init_cpuhp(); return 0; out_fail: diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index e51ee772b9f5..01f04ed6ad92 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -95,6 +95,7 @@ enum cpuhp_state { CPUHP_AP_OFFLINE, CPUHP_AP_SCHED_STARTING, CPUHP_AP_RCUTREE_DYING, + CPUHP_AP_CPU_PM_STARTING, CPUHP_AP_IRQ_GIC_STARTING, CPUHP_AP_IRQ_HIP04_STARTING, CPUHP_AP_IRQ_ARMADA_XP_STARTING, -- cgit v1.2.3 From dedd14925ec6f82a2840c009bc175e2b528ace8e Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 30 Dec 2019 13:59:30 +0100 Subject: PM / Domains: Introduce a genpd OF helper that removes a subdomain We already have the of_genpd_add_subdomain() helper, but no corresponding of_genpd_remove_subdomain(), so let's add it. Subsequent changes starts to make use of it. Signed-off-by: Ulf Hansson Acked-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/pm_domain.h | 8 ++++++++ 2 files changed, 46 insertions(+) (limited to 'include') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 8e5725b11ee8..959d6d5eb000 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2302,6 +2302,44 @@ out: } EXPORT_SYMBOL_GPL(of_genpd_add_subdomain); +/** + * of_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain. + * @parent_spec: OF phandle args to use for parent PM domain look-up + * @subdomain_spec: OF phandle args to use for subdomain look-up + * + * Looks-up a parent PM domain and subdomain based upon phandle args + * provided and removes the subdomain from the parent PM domain. Returns a + * negative error code on failure. + */ +int of_genpd_remove_subdomain(struct of_phandle_args *parent_spec, + struct of_phandle_args *subdomain_spec) +{ + struct generic_pm_domain *parent, *subdomain; + int ret; + + mutex_lock(&gpd_list_lock); + + parent = genpd_get_from_provider(parent_spec); + if (IS_ERR(parent)) { + ret = PTR_ERR(parent); + goto out; + } + + subdomain = genpd_get_from_provider(subdomain_spec); + if (IS_ERR(subdomain)) { + ret = PTR_ERR(subdomain); + goto out; + } + + ret = pm_genpd_remove_subdomain(parent, subdomain); + +out: + mutex_unlock(&gpd_list_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(of_genpd_remove_subdomain); + /** * of_genpd_remove_last - Remove the last PM domain registered for a provider * @provider: Pointer to device structure associated with provider diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 5a31c711b896..9ec78ee53652 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -284,6 +284,8 @@ void of_genpd_del_provider(struct device_node *np); int of_genpd_add_device(struct of_phandle_args *args, struct device *dev); int of_genpd_add_subdomain(struct of_phandle_args *parent_spec, struct of_phandle_args *subdomain_spec); +int of_genpd_remove_subdomain(struct of_phandle_args *parent_spec, + struct of_phandle_args *subdomain_spec); struct generic_pm_domain *of_genpd_remove_last(struct device_node *np); int of_genpd_parse_idle_states(struct device_node *dn, struct genpd_power_state **states, int *n); @@ -322,6 +324,12 @@ static inline int of_genpd_add_subdomain(struct of_phandle_args *parent_spec, return -ENODEV; } +static inline int of_genpd_remove_subdomain(struct of_phandle_args *parent_spec, + struct of_phandle_args *subdomain_spec) +{ + return -ENODEV; +} + static inline int of_genpd_parse_idle_states(struct device_node *dn, struct genpd_power_state **states, int *n) { -- cgit v1.2.3 From a6a0bc7ca993e30e832314f5a8bd62a802f35ce9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 3 Jan 2020 23:08:25 +0100 Subject: firmware: scm: Add stubs for OCMEM and restore_sec_cfg_available Add few more stubs (for OCMEM-related functions and qcom_scm_restore_sec_cfg_available()) in case of !CONFIG_QCOM_SCM. These are actually not necessary for builds but provide them for completeness. Reviewed-by: Brian Masney Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200103220825.28710-1-krzk@kernel.org Signed-off-by: Bjorn Andersson --- include/linux/qcom_scm.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index d05ddac9a57e..2c1d20312ce0 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -105,6 +105,11 @@ static inline bool qcom_scm_is_available(void) { return false; } static inline bool qcom_scm_hdcp_available(void) { return false; } static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { return -ENODEV; } +static inline bool qcom_scm_ocmem_lock_available(void) { return false; } +static inline int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset, + u32 size, u32 mode) { return -ENODEV; } +static inline int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset, + u32 size) { return -ENODEV; } static inline bool qcom_scm_pas_supported(u32 peripheral) { return false; } static inline int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size) { return -ENODEV; } @@ -121,6 +126,7 @@ static inline void qcom_scm_cpu_power_down(u32 flags) {} static inline u32 qcom_scm_get_version(void) { return 0; } static inline u32 qcom_scm_set_remote_state(u32 state,u32 id) { return -ENODEV; } +static inline bool qcom_scm_restore_sec_cfg_available(void) { return false; } static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) { return -ENODEV; } static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { return -ENODEV; } static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; } -- cgit v1.2.3 From 945005409bfb55398d70c56178972d3750529dd6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 4 Jan 2020 16:20:52 +0100 Subject: soc: samsung: Rename Samsung and Exynos to lowercase Fix up inconsistent usage of upper and lowercase letters in "Samsung" and "Exynos" names. "SAMSUNG" and "EXYNOS" are not abbreviations but regular trademarked names. Therefore they should be written with lowercase letters starting with capital letter. The lowercase "Exynos" name is promoted by its manufacturer Samsung Electronics Co., Ltd., in advertisement materials and on website. Although advertisement materials usually use uppercase "SAMSUNG", the lowercase version is used in all legal aspects (e.g. on Wikipedia and in privacy/legal statements on https://www.samsung.com/semiconductor/privacy-global/). Signed-off-by: Krzysztof Kozlowski --- drivers/soc/samsung/Kconfig | 2 +- drivers/soc/samsung/exynos-chipid.c | 2 +- drivers/soc/samsung/exynos-pmu.c | 2 +- drivers/soc/samsung/exynos-pmu.h | 2 +- drivers/soc/samsung/exynos3250-pmu.c | 2 +- drivers/soc/samsung/exynos4-pmu.c | 2 +- drivers/soc/samsung/exynos5250-pmu.c | 2 +- drivers/soc/samsung/exynos5420-pmu.c | 2 +- include/linux/soc/samsung/exynos-pmu.h | 2 +- include/linux/soc/samsung/exynos-regs-pmu.h | 16 ++++++++-------- 10 files changed, 17 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig index 27fc59bbb520..c7a2003687c7 100644 --- a/drivers/soc/samsung/Kconfig +++ b/drivers/soc/samsung/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # -# SAMSUNG SoC drivers +# Samsung SoC drivers # menuconfig SOC_SAMSUNG bool "Samsung SoC driver support" if COMPILE_TEST diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c index b89c26a71c6e..2dad4961a80b 100644 --- a/drivers/soc/samsung/exynos-chipid.c +++ b/drivers/soc/samsung/exynos-chipid.c @@ -3,7 +3,7 @@ * Copyright (c) 2019 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * - * EXYNOS - CHIP ID support + * Exynos - CHIP ID support * Author: Pankaj Dubey * Author: Bartlomiej Zolnierkiewicz */ diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c index 7da2701c871a..17304fa18429 100644 --- a/drivers/soc/samsung/exynos-pmu.c +++ b/drivers/soc/samsung/exynos-pmu.c @@ -3,7 +3,7 @@ // Copyright (c) 2011-2014 Samsung Electronics Co., Ltd. // http://www.samsung.com/ // -// EXYNOS - CPU PMU(Power Management Unit) support +// Exynos - CPU PMU(Power Management Unit) support #include #include diff --git a/drivers/soc/samsung/exynos-pmu.h b/drivers/soc/samsung/exynos-pmu.h index 977e4daf5a0f..5e851f32307e 100644 --- a/drivers/soc/samsung/exynos-pmu.h +++ b/drivers/soc/samsung/exynos-pmu.h @@ -3,7 +3,7 @@ * Copyright (c) 2015 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Header for EXYNOS PMU Driver support + * Header for Exynos PMU Driver support */ #ifndef __EXYNOS_PMU_H diff --git a/drivers/soc/samsung/exynos3250-pmu.c b/drivers/soc/samsung/exynos3250-pmu.c index 275d348ed9c9..30f230ed1769 100644 --- a/drivers/soc/samsung/exynos3250-pmu.c +++ b/drivers/soc/samsung/exynos3250-pmu.c @@ -3,7 +3,7 @@ // Copyright (c) 2011-2015 Samsung Electronics Co., Ltd. // http://www.samsung.com/ // -// EXYNOS3250 - CPU PMU (Power Management Unit) support +// Exynos3250 - CPU PMU (Power Management Unit) support #include #include diff --git a/drivers/soc/samsung/exynos4-pmu.c b/drivers/soc/samsung/exynos4-pmu.c index a7cdbf1aac0c..cb35103565a6 100644 --- a/drivers/soc/samsung/exynos4-pmu.c +++ b/drivers/soc/samsung/exynos4-pmu.c @@ -3,7 +3,7 @@ // Copyright (c) 2011-2015 Samsung Electronics Co., Ltd. // http://www.samsung.com/ // -// EXYNOS4 - CPU PMU(Power Management Unit) support +// Exynos4 - CPU PMU(Power Management Unit) support #include #include diff --git a/drivers/soc/samsung/exynos5250-pmu.c b/drivers/soc/samsung/exynos5250-pmu.c index 19b38e008145..7a2d50be6b4a 100644 --- a/drivers/soc/samsung/exynos5250-pmu.c +++ b/drivers/soc/samsung/exynos5250-pmu.c @@ -3,7 +3,7 @@ // Copyright (c) 2011-2015 Samsung Electronics Co., Ltd. // http://www.samsung.com/ // -// EXYNOS5250 - CPU PMU (Power Management Unit) support +// Exynos5250 - CPU PMU (Power Management Unit) support #include #include diff --git a/drivers/soc/samsung/exynos5420-pmu.c b/drivers/soc/samsung/exynos5420-pmu.c index b236d3b47b49..6fedcd78cb45 100644 --- a/drivers/soc/samsung/exynos5420-pmu.c +++ b/drivers/soc/samsung/exynos5420-pmu.c @@ -3,7 +3,7 @@ // Copyright (c) 2011-2015 Samsung Electronics Co., Ltd. // http://www.samsung.com/ // -// EXYNOS5420 - CPU PMU (Power Management Unit) support +// Exynos5420 - CPU PMU (Power Management Unit) support #include #include diff --git a/include/linux/soc/samsung/exynos-pmu.h b/include/linux/soc/samsung/exynos-pmu.h index fc0b445bb36b..a4f5516cc956 100644 --- a/include/linux/soc/samsung/exynos-pmu.h +++ b/include/linux/soc/samsung/exynos-pmu.h @@ -3,7 +3,7 @@ * Copyright (c) 2014 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Header for EXYNOS PMU Driver support + * Header for Exynos PMU Driver support */ #ifndef __LINUX_SOC_EXYNOS_PMU_H diff --git a/include/linux/soc/samsung/exynos-regs-pmu.h b/include/linux/soc/samsung/exynos-regs-pmu.h index 5addaf5ccbce..fc9250fb3133 100644 --- a/include/linux/soc/samsung/exynos-regs-pmu.h +++ b/include/linux/soc/samsung/exynos-regs-pmu.h @@ -3,7 +3,7 @@ * Copyright (c) 2010-2015 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * EXYNOS - Power management unit definition + * Exynos - Power management unit definition * * Notice: * This is not a list of all Exynos Power Management Unit SFRs. @@ -185,7 +185,7 @@ /* Only for S5Pv210 */ #define S5PV210_EINT_WAKEUP_MASK 0xC004 -/* Only for EXYNOS4210 */ +/* Only for Exynos4210 */ #define S5P_CMU_CLKSTOP_LCD1_LOWPWR 0x1154 #define S5P_CMU_RESET_LCD1_LOWPWR 0x1174 #define S5P_MODIMIF_MEM_LOWPWR 0x11C4 @@ -193,7 +193,7 @@ #define S5P_SATA_MEM_LOWPWR 0x11E4 #define S5P_LCD1_LOWPWR 0x1394 -/* Only for EXYNOS4x12 */ +/* Only for Exynos4x12 */ #define S5P_ISP_ARM_LOWPWR 0x1050 #define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR 0x1054 #define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR 0x1058 @@ -234,7 +234,7 @@ #define S5P_SECSS_MEM_OPTION 0x2EC8 #define S5P_ROTATOR_MEM_OPTION 0x2F48 -/* Only for EXYNOS4412 */ +/* Only for Exynos4412 */ #define S5P_ARM_CORE2_LOWPWR 0x1020 #define S5P_DIS_IRQ_CORE2 0x1024 #define S5P_DIS_IRQ_CENTRAL2 0x1028 @@ -242,7 +242,7 @@ #define S5P_DIS_IRQ_CORE3 0x1034 #define S5P_DIS_IRQ_CENTRAL3 0x1038 -/* Only for EXYNOS3XXX */ +/* Only for Exynos3XXX */ #define EXYNOS3_ARM_CORE0_SYS_PWR_REG 0x1000 #define EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG 0x1004 #define EXYNOS3_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG 0x1008 @@ -347,7 +347,7 @@ #define EXYNOS3_OPTION_USE_SC_FEEDBACK (1 << 1) #define EXYNOS3_OPTION_SKIP_DEACTIVATE_ACEACP_IN_PWDN (1 << 7) -/* For EXYNOS5 */ +/* For Exynos5 */ #define EXYNOS5_AUTO_WDTRESET_DISABLE 0x0408 #define EXYNOS5_MASK_WDTRESET_REQUEST 0x040C @@ -484,7 +484,7 @@ #define EXYNOS5420_SWRESET_KFC_SEL 0x3 -/* Only for EXYNOS5420 */ +/* Only for Exynos5420 */ #define EXYNOS5420_L2RSTDISABLE_VALUE BIT(3) #define EXYNOS5420_LPI_MASK 0x0004 @@ -645,7 +645,7 @@ | EXYNOS5420_KFC_USE_STANDBY_WFI2 \ | EXYNOS5420_KFC_USE_STANDBY_WFI3) -/* For EXYNOS5433 */ +/* For Exynos5433 */ #define EXYNOS5433_EINT_WAKEUP_MASK (0x060C) #define EXYNOS5433_USBHOST30_PHY_CONTROL (0x0728) #define EXYNOS5433_PAD_RETENTION_AUD_OPTION (0x3028) -- cgit v1.2.3 From 9a1108d2b001cda1af17160c78afedfff92e2202 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Tue, 7 Jan 2020 13:04:12 -0800 Subject: firmware: qcom_scm: Remove unused qcom_scm_get_version Remove unused qcom_scm_get_version. Reviewed-by: Bjorn Andersson Reviewed-by: Vinod Koul Reviewed-by: Stephen Boyd Tested-by: Brian Masney # arm32 Tested-by: Stephan Gerhold Signed-off-by: Elliot Berman Link: https://lore.kernel.org/r/1578431066-19600-4-git-send-email-eberman@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom_scm-32.c | 36 ------------------------------------ include/linux/qcom_scm.h | 2 -- 2 files changed, 38 deletions(-) (limited to 'include') diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c index 6e62f73627ba..8b5724069f27 100644 --- a/drivers/firmware/qcom_scm-32.c +++ b/drivers/firmware/qcom_scm-32.c @@ -292,42 +292,6 @@ static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2) return r0; } -u32 qcom_scm_get_version(void) -{ - int context_id; - static u32 version = -1; - register u32 r0 asm("r0"); - register u32 r1 asm("r1"); - - if (version != -1) - return version; - - mutex_lock(&qcom_scm_lock); - - r0 = 0x1 << 8; - r1 = (u32)&context_id; - do { - asm volatile( - __asmeq("%0", "r0") - __asmeq("%1", "r1") - __asmeq("%2", "r0") - __asmeq("%3", "r1") -#ifdef REQUIRES_SEC - ".arch_extension sec\n" -#endif - "smc #0 @ switch to secure world\n" - : "=r" (r0), "=r" (r1) - : "r" (r0), "r" (r1) - : "r2", "r3", "r12"); - } while (r0 == QCOM_SCM_INTERRUPTED); - - version = r1; - mutex_unlock(&qcom_scm_lock); - - return version; -} -EXPORT_SYMBOL(qcom_scm_get_version); - /** * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus * @entry: Entry point function for the cpus diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 2c1d20312ce0..98e775d7a3ec 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -78,7 +78,6 @@ extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, const struct qcom_scm_vmperm *newvm, unsigned int dest_cnt); extern void qcom_scm_cpu_power_down(u32 flags); -extern u32 qcom_scm_get_version(void); extern int qcom_scm_set_remote_state(u32 state, u32 id); extern bool qcom_scm_restore_sec_cfg_available(void); extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); @@ -123,7 +122,6 @@ static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, const struct qcom_scm_vmperm *newvm, unsigned int dest_cnt) { return -ENODEV; } static inline void qcom_scm_cpu_power_down(u32 flags) {} -static inline u32 qcom_scm_get_version(void) { return 0; } static inline u32 qcom_scm_set_remote_state(u32 state,u32 id) { return -ENODEV; } static inline bool qcom_scm_restore_sec_cfg_available(void) { return false; } -- cgit v1.2.3 From 65f0c90b7d468545590992c61a19f9dc0aac61ef Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Tue, 7 Jan 2020 13:04:24 -0800 Subject: firmware: qcom_scm: Order functions, definitions by service/command Definitions throughout qcom_scm are loosely grouped and loosely ordered. Sort all the functions/definitions by service ID/command ID to improve sanity when needing to add new functionality to this driver. Acked-by: Bjorn Andersson Tested-by: Brian Masney # arm32 Tested-by: Stephan Gerhold Signed-off-by: Elliot Berman Link: https://lore.kernel.org/r/1578431066-19600-16-git-send-email-eberman@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom_scm.c | 376 ++++++++++++++++++++++---------------------- drivers/firmware/qcom_scm.h | 120 +++++++------- include/linux/qcom_scm.h | 123 ++++++++------- 3 files changed, 315 insertions(+), 304 deletions(-) (limited to 'include') diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 5efe7292cd43..5ba4c85a9257 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -85,33 +85,33 @@ static void qcom_scm_clk_disable(void) } /** - * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus + * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus * @entry: Entry point function for the cpus * @cpus: The cpumask of cpus that will use the entry point * - * Set the cold boot address of the cpus. Any cpu outside the supported - * range would be removed from the cpu present mask. + * Set the Linux entry point for the SCM to transfer control to when coming + * out of a power down. CPU power down may be executed on cpuidle or hotplug. */ -int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) +int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) { - return __qcom_scm_set_cold_boot_addr(__scm ? __scm->dev : NULL, entry, - cpus); + return __qcom_scm_set_warm_boot_addr(__scm->dev, entry, cpus); } -EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); +EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); /** - * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus + * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus * @entry: Entry point function for the cpus * @cpus: The cpumask of cpus that will use the entry point * - * Set the Linux entry point for the SCM to transfer control to when coming - * out of a power down. CPU power down may be executed on cpuidle or hotplug. + * Set the cold boot address of the cpus. Any cpu outside the supported + * range would be removed from the cpu present mask. */ -int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) +int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) { - return __qcom_scm_set_warm_boot_addr(__scm->dev, entry, cpus); + return __qcom_scm_set_cold_boot_addr(__scm ? __scm->dev : NULL, entry, + cpus); } -EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); +EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); /** * qcom_scm_cpu_power_down() - Power down the cpu @@ -127,107 +127,33 @@ void qcom_scm_cpu_power_down(u32 flags) } EXPORT_SYMBOL(qcom_scm_cpu_power_down); -/** - * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. - * - * Return true if HDCP is supported, false if not. - */ -bool qcom_scm_hdcp_available(void) -{ - int ret = qcom_scm_clk_enable(); - - if (ret) - return ret; - - ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP, - QCOM_SCM_HDCP_INVOKE); - - qcom_scm_clk_disable(); - - return ret > 0 ? true : false; -} -EXPORT_SYMBOL(qcom_scm_hdcp_available); - -/** - * qcom_scm_hdcp_req() - Send HDCP request. - * @req: HDCP request array - * @req_cnt: HDCP request array count - * @resp: response buffer passed to SCM - * - * Write HDCP register(s) through SCM. - */ -int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) -{ - int ret = qcom_scm_clk_enable(); - - if (ret) - return ret; - - ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp); - qcom_scm_clk_disable(); - return ret; -} -EXPORT_SYMBOL(qcom_scm_hdcp_req); - -/** - * qcom_scm_pas_supported() - Check if the peripheral authentication service is - * available for the given peripherial - * @peripheral: peripheral id - * - * Returns true if PAS is supported for this peripheral, otherwise false. - */ -bool qcom_scm_pas_supported(u32 peripheral) +int qcom_scm_set_remote_state(u32 state, u32 id) { - int ret; - - ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PIL_PAS_IS_SUPPORTED); - if (ret <= 0) - return false; - - return __qcom_scm_pas_supported(__scm->dev, peripheral); + return __qcom_scm_set_remote_state(__scm->dev, state, id); } -EXPORT_SYMBOL(qcom_scm_pas_supported); +EXPORT_SYMBOL(qcom_scm_set_remote_state); -/** - * qcom_scm_ocmem_lock_available() - is OCMEM lock/unlock interface available - */ -bool qcom_scm_ocmem_lock_available(void) +static void qcom_scm_set_download_mode(bool enable) { - return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_OCMEM, - QCOM_SCM_OCMEM_LOCK_CMD); -} -EXPORT_SYMBOL(qcom_scm_ocmem_lock_available); + bool avail; + int ret = 0; -/** - * qcom_scm_ocmem_lock() - call OCMEM lock interface to assign an OCMEM - * region to the specified initiator - * - * @id: tz initiator id - * @offset: OCMEM offset - * @size: OCMEM size - * @mode: access mode (WIDE/NARROW) - */ -int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset, u32 size, - u32 mode) -{ - return __qcom_scm_ocmem_lock(__scm->dev, id, offset, size, mode); -} -EXPORT_SYMBOL(qcom_scm_ocmem_lock); + avail = __qcom_scm_is_call_available(__scm->dev, + QCOM_SCM_SVC_BOOT, + QCOM_SCM_BOOT_SET_DLOAD_MODE); + if (avail) { + ret = __qcom_scm_set_dload_mode(__scm->dev, enable); + } else if (__scm->dload_mode_addr) { + ret = __qcom_scm_io_writel(__scm->dev, __scm->dload_mode_addr, + enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0); + } else { + dev_err(__scm->dev, + "No available mechanism for setting download mode\n"); + } -/** - * qcom_scm_ocmem_unlock() - call OCMEM unlock interface to release an OCMEM - * region from the specified initiator - * - * @id: tz initiator id - * @offset: OCMEM offset - * @size: OCMEM size - */ -int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset, u32 size) -{ - return __qcom_scm_ocmem_unlock(__scm->dev, id, offset, size); + if (ret) + dev_err(__scm->dev, "failed to set download mode: %d\n", ret); } -EXPORT_SYMBOL(qcom_scm_ocmem_unlock); /** * qcom_scm_pas_init_image() - Initialize peripheral authentication service @@ -342,6 +268,26 @@ int qcom_scm_pas_shutdown(u32 peripheral) } EXPORT_SYMBOL(qcom_scm_pas_shutdown); +/** + * qcom_scm_pas_supported() - Check if the peripheral authentication service is + * available for the given peripherial + * @peripheral: peripheral id + * + * Returns true if PAS is supported for this peripheral, otherwise false. + */ +bool qcom_scm_pas_supported(u32 peripheral) +{ + int ret; + + ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL, + QCOM_SCM_PIL_PAS_IS_SUPPORTED); + if (ret <= 0) + return false; + + return __qcom_scm_pas_supported(__scm->dev, peripheral); +} +EXPORT_SYMBOL(qcom_scm_pas_supported); + static int qcom_scm_pas_reset_assert(struct reset_controller_dev *rcdev, unsigned long idx) { @@ -365,6 +311,18 @@ static const struct reset_control_ops qcom_scm_pas_reset_ops = { .deassert = qcom_scm_pas_reset_deassert, }; +int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) +{ + return __qcom_scm_io_readl(__scm->dev, addr, val); +} +EXPORT_SYMBOL(qcom_scm_io_readl); + +int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) +{ + return __qcom_scm_io_writel(__scm->dev, addr, val); +} +EXPORT_SYMBOL(qcom_scm_io_writel); + /** * qcom_scm_restore_sec_cfg_available() - Check if secure environment * supports restore security config interface. @@ -396,87 +354,6 @@ int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) } EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init); -int qcom_scm_qsmmu500_wait_safe_toggle(bool en) -{ - return __qcom_scm_qsmmu500_wait_safe_toggle(__scm->dev, en); -} -EXPORT_SYMBOL(qcom_scm_qsmmu500_wait_safe_toggle); - -int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) -{ - return __qcom_scm_io_readl(__scm->dev, addr, val); -} -EXPORT_SYMBOL(qcom_scm_io_readl); - -int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) -{ - return __qcom_scm_io_writel(__scm->dev, addr, val); -} -EXPORT_SYMBOL(qcom_scm_io_writel); - -static void qcom_scm_set_download_mode(bool enable) -{ - bool avail; - int ret = 0; - - avail = __qcom_scm_is_call_available(__scm->dev, - QCOM_SCM_SVC_BOOT, - QCOM_SCM_BOOT_SET_DLOAD_MODE); - if (avail) { - ret = __qcom_scm_set_dload_mode(__scm->dev, enable); - } else if (__scm->dload_mode_addr) { - ret = __qcom_scm_io_writel(__scm->dev, __scm->dload_mode_addr, - enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0); - } else { - dev_err(__scm->dev, - "No available mechanism for setting download mode\n"); - } - - if (ret) - dev_err(__scm->dev, "failed to set download mode: %d\n", ret); -} - -static int qcom_scm_find_dload_address(struct device *dev, u64 *addr) -{ - struct device_node *tcsr; - struct device_node *np = dev->of_node; - struct resource res; - u32 offset; - int ret; - - tcsr = of_parse_phandle(np, "qcom,dload-mode", 0); - if (!tcsr) - return 0; - - ret = of_address_to_resource(tcsr, 0, &res); - of_node_put(tcsr); - if (ret) - return ret; - - ret = of_property_read_u32_index(np, "qcom,dload-mode", 1, &offset); - if (ret < 0) - return ret; - - *addr = res.start + offset; - - return 0; -} - -/** - * qcom_scm_is_available() - Checks if SCM is available - */ -bool qcom_scm_is_available(void) -{ - return !!__scm; -} -EXPORT_SYMBOL(qcom_scm_is_available); - -int qcom_scm_set_remote_state(u32 state, u32 id) -{ - return __qcom_scm_set_remote_state(__scm->dev, state, id); -} -EXPORT_SYMBOL(qcom_scm_set_remote_state); - /** * qcom_scm_assign_mem() - Make a secure call to reassign memory ownership * @mem_addr: mem region whose ownership need to be reassigned @@ -559,6 +436,129 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, } EXPORT_SYMBOL(qcom_scm_assign_mem); +/** + * qcom_scm_ocmem_lock_available() - is OCMEM lock/unlock interface available + */ +bool qcom_scm_ocmem_lock_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_OCMEM, + QCOM_SCM_OCMEM_LOCK_CMD); +} +EXPORT_SYMBOL(qcom_scm_ocmem_lock_available); + +/** + * qcom_scm_ocmem_lock() - call OCMEM lock interface to assign an OCMEM + * region to the specified initiator + * + * @id: tz initiator id + * @offset: OCMEM offset + * @size: OCMEM size + * @mode: access mode (WIDE/NARROW) + */ +int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset, u32 size, + u32 mode) +{ + return __qcom_scm_ocmem_lock(__scm->dev, id, offset, size, mode); +} +EXPORT_SYMBOL(qcom_scm_ocmem_lock); + +/** + * qcom_scm_ocmem_unlock() - call OCMEM unlock interface to release an OCMEM + * region from the specified initiator + * + * @id: tz initiator id + * @offset: OCMEM offset + * @size: OCMEM size + */ +int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset, u32 size) +{ + return __qcom_scm_ocmem_unlock(__scm->dev, id, offset, size); +} +EXPORT_SYMBOL(qcom_scm_ocmem_unlock); + +/** + * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. + * + * Return true if HDCP is supported, false if not. + */ +bool qcom_scm_hdcp_available(void) +{ + int ret = qcom_scm_clk_enable(); + + if (ret) + return ret; + + ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP, + QCOM_SCM_HDCP_INVOKE); + + qcom_scm_clk_disable(); + + return ret > 0 ? true : false; +} +EXPORT_SYMBOL(qcom_scm_hdcp_available); + +/** + * qcom_scm_hdcp_req() - Send HDCP request. + * @req: HDCP request array + * @req_cnt: HDCP request array count + * @resp: response buffer passed to SCM + * + * Write HDCP register(s) through SCM. + */ +int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) +{ + int ret = qcom_scm_clk_enable(); + + if (ret) + return ret; + + ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp); + qcom_scm_clk_disable(); + return ret; +} +EXPORT_SYMBOL(qcom_scm_hdcp_req); + +int qcom_scm_qsmmu500_wait_safe_toggle(bool en) +{ + return __qcom_scm_qsmmu500_wait_safe_toggle(__scm->dev, en); +} +EXPORT_SYMBOL(qcom_scm_qsmmu500_wait_safe_toggle); + +static int qcom_scm_find_dload_address(struct device *dev, u64 *addr) +{ + struct device_node *tcsr; + struct device_node *np = dev->of_node; + struct resource res; + u32 offset; + int ret; + + tcsr = of_parse_phandle(np, "qcom,dload-mode", 0); + if (!tcsr) + return 0; + + ret = of_address_to_resource(tcsr, 0, &res); + of_node_put(tcsr); + if (ret) + return ret; + + ret = of_property_read_u32_index(np, "qcom,dload-mode", 1, &offset); + if (ret < 0) + return ret; + + *addr = res.start + offset; + + return 0; +} + +/** + * qcom_scm_is_available() - Checks if SCM is available + */ +bool qcom_scm_is_available(void) +{ + return !!__scm; +} +EXPORT_SYMBOL(qcom_scm_is_available); + static int qcom_scm_probe(struct platform_device *pdev) { struct qcom_scm *scm; diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index a02255684946..56ace3bb9d88 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -4,64 +4,83 @@ #ifndef __QCOM_SCM_INT_H #define __QCOM_SCM_INT_H -#define QCOM_SCM_SVC_BOOT 0x1 -#define QCOM_SCM_BOOT_SET_ADDR 0x1 -#define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 -#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0xa -extern int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id); -extern int __qcom_scm_set_dload_mode(struct device *dev, bool enable); - +#define QCOM_SCM_SVC_BOOT 0x01 +#define QCOM_SCM_BOOT_SET_ADDR 0x01 +#define QCOM_SCM_BOOT_TERMINATE_PC 0x02 +#define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 +#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, const cpumask_t *cpus); extern int __qcom_scm_set_cold_boot_addr(struct device *dev, void *entry, const cpumask_t *cpus); - -#define QCOM_SCM_BOOT_TERMINATE_PC 0x2 -#define QCOM_SCM_FLUSH_FLAG_MASK 0x3 extern void __qcom_scm_cpu_power_down(struct device *dev, u32 flags); +extern int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id); +extern int __qcom_scm_set_dload_mode(struct device *dev, bool enable); +#define QCOM_SCM_FLUSH_FLAG_MASK 0x3 + +#define QCOM_SCM_SVC_PIL 0x02 +#define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x01 +#define QCOM_SCM_PIL_PAS_MEM_SETUP 0x02 +#define QCOM_SCM_PIL_PAS_AUTH_AND_RESET 0x05 +#define QCOM_SCM_PIL_PAS_SHUTDOWN 0x06 +#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07 +#define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a +extern bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral); +extern int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, + dma_addr_t metadata_phys); +extern int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, + phys_addr_t addr, phys_addr_t size); +extern int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral); +extern int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral); +extern int __qcom_scm_pas_mss_reset(struct device *dev, bool reset); -#define QCOM_SCM_SVC_IO 0x5 -#define QCOM_SCM_IO_READ 0x1 -#define QCOM_SCM_IO_WRITE 0x2 +#define QCOM_SCM_SVC_IO 0x05 +#define QCOM_SCM_IO_READ 0x01 +#define QCOM_SCM_IO_WRITE 0x02 extern int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, unsigned int *val); extern int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val); -#define QCOM_SCM_SVC_INFO 0x6 -#define QCOM_SCM_INFO_IS_CALL_AVAIL 0x1 +#define QCOM_SCM_SVC_INFO 0x06 +#define QCOM_SCM_INFO_IS_CALL_AVAIL 0x01 extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id); -#define QCOM_SCM_SVC_HDCP 0x11 -#define QCOM_SCM_HDCP_INVOKE 0x01 -extern int __qcom_scm_hdcp_req(struct device *dev, - struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); - -extern void __qcom_scm_init(void); - -#define QCOM_SCM_SVC_OCMEM 0xf -#define QCOM_SCM_OCMEM_LOCK_CMD 0x1 -#define QCOM_SCM_OCMEM_UNLOCK_CMD 0x2 +#define QCOM_SCM_SVC_MP 0x0c +#define QCOM_SCM_MP_RESTORE_SEC_CFG 0x02 +#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03 +#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04 +#define QCOM_SCM_MP_ASSIGN 0x16 +extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, + u32 spare); +extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, + size_t *size); +extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, + u32 size, u32 spare); +extern int __qcom_scm_assign_mem(struct device *dev, + phys_addr_t mem_region, size_t mem_sz, + phys_addr_t src, size_t src_sz, + phys_addr_t dest, size_t dest_sz); +#define QCOM_SCM_SVC_OCMEM 0x0f +#define QCOM_SCM_OCMEM_LOCK_CMD 0x01 +#define QCOM_SCM_OCMEM_UNLOCK_CMD 0x02 extern int __qcom_scm_ocmem_lock(struct device *dev, u32 id, u32 offset, u32 size, u32 mode); extern int __qcom_scm_ocmem_unlock(struct device *dev, u32 id, u32 offset, u32 size); -#define QCOM_SCM_SVC_PIL 0x2 -#define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x1 -#define QCOM_SCM_PIL_PAS_MEM_SETUP 0x2 -#define QCOM_SCM_PIL_PAS_AUTH_AND_RESET 0x5 -#define QCOM_SCM_PIL_PAS_SHUTDOWN 0x6 -#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x7 -#define QCOM_SCM_PIL_PAS_MSS_RESET 0xa -extern bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral); -extern int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, - dma_addr_t metadata_phys); -extern int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, - phys_addr_t addr, phys_addr_t size); -extern int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral); -extern int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral); -extern int __qcom_scm_pas_mss_reset(struct device *dev, bool reset); +#define QCOM_SCM_SVC_HDCP 0x11 +#define QCOM_SCM_HDCP_INVOKE 0x01 +extern int __qcom_scm_hdcp_req(struct device *dev, + struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); + +#define QCOM_SCM_SVC_SMMU_PROGRAM 0x15 +#define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x03 +#define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x02 +extern int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, + bool enable); + +extern void __qcom_scm_init(void); /* common error codes */ #define QCOM_SCM_V2_EBUSY -12 @@ -90,25 +109,4 @@ static inline int qcom_scm_remap_error(int err) return -EINVAL; } -#define QCOM_SCM_SVC_MP 0xc -#define QCOM_SCM_MP_RESTORE_SEC_CFG 2 -extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, - u32 spare); -#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 3 -#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 4 -#define QCOM_SCM_SVC_SMMU_PROGRAM 0x15 -#define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x3 -#define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x2 -extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, - size_t *size); -extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, - u32 size, u32 spare); -extern int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, - bool enable); -#define QCOM_SCM_MP_ASSIGN 0x16 -extern int __qcom_scm_assign_mem(struct device *dev, - phys_addr_t mem_region, size_t mem_sz, - phys_addr_t src, size_t src_sz, - phys_addr_t dest, size_t dest_sz); - #endif diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 98e775d7a3ec..3d6a24697761 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2010-2015, 2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2015, 2018-2019 The Linux Foundation. All rights reserved. * Copyright (C) 2015 Linaro Ltd. */ #ifndef __QCOM_SCM_H @@ -55,81 +55,94 @@ enum qcom_scm_sec_dev_id { #define QCOM_SCM_PERM_RWX (QCOM_SCM_PERM_RW | QCOM_SCM_PERM_EXEC) #if IS_ENABLED(CONFIG_QCOM_SCM) +extern bool qcom_scm_is_available(void); + extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); -extern bool qcom_scm_is_available(void); -extern bool qcom_scm_hdcp_available(void); -extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, - u32 *resp); -extern bool qcom_scm_ocmem_lock_available(void); -extern int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset, - u32 size, u32 mode); -extern int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset, - u32 size); -extern bool qcom_scm_pas_supported(u32 peripheral); +extern void qcom_scm_cpu_power_down(u32 flags); +extern int qcom_scm_set_remote_state(u32 state, u32 id); + extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size); extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size); extern int qcom_scm_pas_auth_and_reset(u32 peripheral); extern int qcom_scm_pas_shutdown(u32 peripheral); -extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, - unsigned int *src, - const struct qcom_scm_vmperm *newvm, - unsigned int dest_cnt); -extern void qcom_scm_cpu_power_down(u32 flags); -extern int qcom_scm_set_remote_state(u32 state, u32 id); +extern bool qcom_scm_pas_supported(u32 peripheral); + +extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val); +extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val); + extern bool qcom_scm_restore_sec_cfg_available(void); extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size); extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); +extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, + unsigned int *src, + const struct qcom_scm_vmperm *newvm, + unsigned int dest_cnt); + +extern bool qcom_scm_ocmem_lock_available(void); +extern int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset, + u32 size, u32 mode); +extern int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset, + u32 size); + +extern bool qcom_scm_hdcp_available(void); +extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, + u32 *resp); + extern int qcom_scm_qsmmu500_wait_safe_toggle(bool en); -extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val); -extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val); #else #include -static inline -int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) -{ - return -ENODEV; -} -static inline -int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) -{ - return -ENODEV; -} static inline bool qcom_scm_is_available(void) { return false; } -static inline bool qcom_scm_hdcp_available(void) { return false; } -static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, - u32 *resp) { return -ENODEV; } -static inline bool qcom_scm_ocmem_lock_available(void) { return false; } -static inline int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset, - u32 size, u32 mode) { return -ENODEV; } -static inline int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset, - u32 size) { return -ENODEV; } -static inline bool qcom_scm_pas_supported(u32 peripheral) { return false; } + +static inline int qcom_scm_set_cold_boot_addr(void *entry, + const cpumask_t *cpus) { return -ENODEV; } +static inline int qcom_scm_set_warm_boot_addr(void *entry, + const cpumask_t *cpus) { return -ENODEV; } +static inline void qcom_scm_cpu_power_down(u32 flags) {} +static inline u32 qcom_scm_set_remote_state(u32 state,u32 id) + { return -ENODEV; } + static inline int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, - size_t size) { return -ENODEV; } + size_t size) { return -ENODEV; } static inline int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, - phys_addr_t size) { return -ENODEV; } -static inline int -qcom_scm_pas_auth_and_reset(u32 peripheral) { return -ENODEV; } + phys_addr_t size) { return -ENODEV; } +static inline int qcom_scm_pas_auth_and_reset(u32 peripheral) + { return -ENODEV; } static inline int qcom_scm_pas_shutdown(u32 peripheral) { return -ENODEV; } -static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, - unsigned int *src, - const struct qcom_scm_vmperm *newvm, - unsigned int dest_cnt) { return -ENODEV; } -static inline void qcom_scm_cpu_power_down(u32 flags) {} -static inline u32 -qcom_scm_set_remote_state(u32 state,u32 id) { return -ENODEV; } +static inline bool qcom_scm_pas_supported(u32 peripheral) { return false; } + +static inline int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) + { return -ENODEV; } +static inline int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) + { return -ENODEV; } + static inline bool qcom_scm_restore_sec_cfg_available(void) { return false; } -static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) { return -ENODEV; } -static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { return -ENODEV; } -static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; } -static inline int qcom_scm_qsmmu500_wait_safe_toggle(bool en) { return -ENODEV; } -static inline int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) { return -ENODEV; } -static inline int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) { return -ENODEV; } +static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) + { return -ENODEV; } +static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) + { return -ENODEV; } +static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) + { return -ENODEV; } +static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, + unsigned int *src, const struct qcom_scm_vmperm *newvm, + unsigned int dest_cnt) { return -ENODEV; } + +static inline bool qcom_scm_ocmem_lock_available(void) { return false; } +static inline int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset, + u32 size, u32 mode) { return -ENODEV; } +static inline int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, + u32 offset, u32 size) { return -ENODEV; } + +static inline bool qcom_scm_hdcp_available(void) { return false; } +static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, + u32 *resp) { return -ENODEV; } + +static inline int qcom_scm_qsmmu500_wait_safe_toggle(bool en) + { return -ENODEV; } #endif #endif -- cgit v1.2.3 From 56f6737167ca733a6334d8313030f5a22761a439 Mon Sep 17 00:00:00 2001 From: Mars Cheng Date: Fri, 12 Jul 2019 17:43:39 +0800 Subject: dt-bindings: mediatek: add MT6765 power dt-bindings This adds power dt-bindings for MT6765 Signed-off-by: Mars Cheng Signed-off-by: Owen Chen Signed-off-by: Macpaul Lin Reviewed-by: Rob Herring Signed-off-by: Matthias Brugger --- Documentation/devicetree/bindings/soc/mediatek/scpsys.txt | 6 ++++++ include/dt-bindings/power/mt6765-power.h | 14 ++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 include/dt-bindings/power/mt6765-power.h (limited to 'include') diff --git a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt index 8f469d85833b..2bc367793aec 100644 --- a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt +++ b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt @@ -11,6 +11,7 @@ The driver implements the Generic PM domain bindings described in power/power-domain.yaml. It provides the power domains defined in - include/dt-bindings/power/mt8173-power.h - include/dt-bindings/power/mt6797-power.h +- include/dt-bindings/power/mt6765-power.h - include/dt-bindings/power/mt2701-power.h - include/dt-bindings/power/mt2712-power.h - include/dt-bindings/power/mt7622-power.h @@ -19,6 +20,7 @@ Required properties: - compatible: Should be one of: - "mediatek,mt2701-scpsys" - "mediatek,mt2712-scpsys" + - "mediatek,mt6765-scpsys" - "mediatek,mt6797-scpsys" - "mediatek,mt7622-scpsys" - "mediatek,mt7623-scpsys", "mediatek,mt2701-scpsys": For MT7623 SoC @@ -33,6 +35,10 @@ Required properties: enabled before enabling certain power domains. Required clocks for MT2701 or MT7623: "mm", "mfg", "ethif" Required clocks for MT2712: "mm", "mfg", "venc", "jpgdec", "audio", "vdec" + Required clocks for MT6765: MUX: "mm", "mfg" + CG: "mm-0", "mm-1", "mm-2", "mm-3", "isp-0", + "isp-1", "cam-0", "cam-1", "cam-2", + "cam-3","cam-4" Required clocks for MT6797: "mm", "mfg", "vdec" Required clocks for MT7622 or MT7629: "hif_sel" Required clocks for MT7623A: "ethif" diff --git a/include/dt-bindings/power/mt6765-power.h b/include/dt-bindings/power/mt6765-power.h new file mode 100644 index 000000000000..d347b4ee9eed --- /dev/null +++ b/include/dt-bindings/power/mt6765-power.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _DT_BINDINGS_POWER_MT6765_POWER_H +#define _DT_BINDINGS_POWER_MT6765_POWER_H + +#define MT6765_POWER_DOMAIN_CONN 0 +#define MT6765_POWER_DOMAIN_MM 1 +#define MT6765_POWER_DOMAIN_MFG_ASYNC 2 +#define MT6765_POWER_DOMAIN_ISP 3 +#define MT6765_POWER_DOMAIN_MFG 4 +#define MT6765_POWER_DOMAIN_MFG_CORE0 5 +#define MT6765_POWER_DOMAIN_CAM 6 +#define MT6765_POWER_DOMAIN_VCODEC 7 + +#endif /* _DT_BINDINGS_POWER_MT6765_POWER_H */ -- cgit v1.2.3