From 76e0c88dbd2498487044b9705641de306d8f23ab Mon Sep 17 00:00:00 2001 From: Qing Zhang Date: Thu, 4 Mar 2021 19:00:57 +0800 Subject: MIPS: Loongson64: Move loongson_system_configuration to loongson.h The purpose of separating loongson_system_configuration from boot_param.h is to keep the other structure consistent with the firmware. Signed-off-by: Jiaxun Yang Signed-off-by: Qing Zhang Acked-by: Jiaxun Yang Signed-off-by: Thomas Bogendoerfer --- drivers/irqchip/irq-loongson-liointc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c index 09b91b81851c..249566a23cc4 100644 --- a/drivers/irqchip/irq-loongson-liointc.c +++ b/drivers/irqchip/irq-loongson-liointc.c @@ -16,7 +16,7 @@ #include #include -#include +#include #define LIOINTC_CHIP_IRQ 32 #define LIOINTC_NUM_PARENT 4 -- cgit v1.2.3 From fb009cbdd0693bd633f11e99526617b3d392cfad Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 8 Mar 2021 10:03:16 +0100 Subject: firmware: bcm47xx_nvram: rename finding function and its variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Use "bcm47xx_" function name prefix for consistency 2. It takes flash start as argument so s/iobase/flash_start/ 3. "off" was used for finding flash end so just call it "flash_size" Signed-off-by: Rafał Miłecki Signed-off-by: Thomas Bogendoerfer --- drivers/firmware/broadcom/bcm47xx_nvram.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c index 835ece9c00f1..b04007adc79f 100644 --- a/drivers/firmware/broadcom/bcm47xx_nvram.c +++ b/drivers/firmware/broadcom/bcm47xx_nvram.c @@ -48,11 +48,13 @@ static u32 find_nvram_size(void __iomem *end) return 0; } -/* Probe for NVRAM header */ -static int nvram_find_and_copy(void __iomem *iobase, u32 lim) +/** + * bcm47xx_nvram_find_and_copy - find NVRAM on flash mapping & copy it + */ +static int bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_size) { struct nvram_header __iomem *header; - u32 off; + size_t flash_size; u32 size; if (nvram_len) { @@ -61,25 +63,25 @@ static int nvram_find_and_copy(void __iomem *iobase, u32 lim) } /* TODO: when nvram is on nand flash check for bad blocks first. */ - off = FLASH_MIN; - while (off <= lim) { + flash_size = FLASH_MIN; + while (flash_size <= res_size) { /* Windowed flash access */ - size = find_nvram_size(iobase + off); + size = find_nvram_size(flash_start + flash_size); if (size) { - header = (struct nvram_header *)(iobase + off - size); + header = (struct nvram_header *)(flash_start + flash_size - size); goto found; } - off <<= 1; + flash_size <<= 1; } /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ - header = (struct nvram_header *)(iobase + 4096); + header = (struct nvram_header *)(flash_start + 4096); if (header->magic == NVRAM_MAGIC) { size = NVRAM_SPACE; goto found; } - header = (struct nvram_header *)(iobase + 1024); + header = (struct nvram_header *)(flash_start + 1024); if (header->magic == NVRAM_MAGIC) { size = NVRAM_SPACE; goto found; @@ -124,7 +126,7 @@ int bcm47xx_nvram_init_from_mem(u32 base, u32 lim) if (!iobase) return -ENOMEM; - err = nvram_find_and_copy(iobase, lim); + err = bcm47xx_nvram_find_and_copy(iobase, lim); iounmap(iobase); -- cgit v1.2.3 From 0a24b51a3264a3f942a75025ea5ff6133c8989b0 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 8 Mar 2021 10:03:17 +0100 Subject: firmware: bcm47xx_nvram: add helper checking for NVRAM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids duplicating code doing casting and checking for NVRAM magic. Signed-off-by: Rafał Miłecki Signed-off-by: Thomas Bogendoerfer --- drivers/firmware/broadcom/bcm47xx_nvram.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c index b04007adc79f..99f3ec180be6 100644 --- a/drivers/firmware/broadcom/bcm47xx_nvram.c +++ b/drivers/firmware/broadcom/bcm47xx_nvram.c @@ -34,14 +34,20 @@ static char nvram_buf[NVRAM_SPACE]; static size_t nvram_len; static const u32 nvram_sizes[] = {0x6000, 0x8000, 0xF000, 0x10000}; +/** + * bcm47xx_nvram_is_valid - check for a valid NVRAM at specified memory + */ +static bool bcm47xx_nvram_is_valid(void __iomem *nvram) +{ + return ((struct nvram_header *)nvram)->magic == NVRAM_MAGIC; +} + static u32 find_nvram_size(void __iomem *end) { - struct nvram_header __iomem *header; int i; for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { - header = (struct nvram_header *)(end - nvram_sizes[i]); - if (header->magic == NVRAM_MAGIC) + if (bcm47xx_nvram_is_valid(end - nvram_sizes[i])) return nvram_sizes[i]; } @@ -55,6 +61,7 @@ static int bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_siz { struct nvram_header __iomem *header; size_t flash_size; + size_t offset; u32 size; if (nvram_len) { @@ -68,31 +75,30 @@ static int bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_siz /* Windowed flash access */ size = find_nvram_size(flash_start + flash_size); if (size) { - header = (struct nvram_header *)(flash_start + flash_size - size); + offset = flash_size - size; goto found; } flash_size <<= 1; } /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ - header = (struct nvram_header *)(flash_start + 4096); - if (header->magic == NVRAM_MAGIC) { - size = NVRAM_SPACE; + + offset = 4096; + if (bcm47xx_nvram_is_valid(flash_start + offset)) goto found; - } - header = (struct nvram_header *)(flash_start + 1024); - if (header->magic == NVRAM_MAGIC) { - size = NVRAM_SPACE; + offset = 1024; + if (bcm47xx_nvram_is_valid(flash_start + offset)) goto found; - } pr_err("no nvram found\n"); return -ENXIO; found: + header = (struct nvram_header *)(flash_start + offset); __ioread32_copy(nvram_buf, header, sizeof(*header) / 4); nvram_len = ((struct nvram_header *)(nvram_buf))->len; + size = res_size - offset; if (nvram_len > size) { pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n"); nvram_len = size; -- cgit v1.2.3 From 298923cf999cecd2ef06df126f85a3d68da8c4d8 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 8 Mar 2021 10:03:18 +0100 Subject: firmware: bcm47xx_nvram: extract code copying NVRAM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This simplifies function finding NVRAM. It doesn't directly deal with NVRAM structure anymore and is a bit smaller. Signed-off-by: Rafał Miłecki Signed-off-by: Thomas Bogendoerfer --- drivers/firmware/broadcom/bcm47xx_nvram.c | 43 ++++++++++++++++++------------- 1 file changed, 25 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c index 99f3ec180be6..09f51b95849e 100644 --- a/drivers/firmware/broadcom/bcm47xx_nvram.c +++ b/drivers/firmware/broadcom/bcm47xx_nvram.c @@ -54,12 +54,35 @@ static u32 find_nvram_size(void __iomem *end) return 0; } +/** + * bcm47xx_nvram_copy - copy NVRAM to internal buffer + */ +static void bcm47xx_nvram_copy(void __iomem *nvram_start, size_t res_size) +{ + struct nvram_header __iomem *header = nvram_start; + size_t copy_size; + + copy_size = header->len; + if (copy_size > res_size) { + pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n"); + copy_size = res_size; + } + if (copy_size >= NVRAM_SPACE) { + pr_err("nvram on flash (%zu bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", + copy_size, NVRAM_SPACE - 1); + copy_size = NVRAM_SPACE - 1; + } + + __ioread32_copy(nvram_buf, nvram_start, DIV_ROUND_UP(copy_size, 4)); + nvram_buf[NVRAM_SPACE - 1] = '\0'; + nvram_len = copy_size; +} + /** * bcm47xx_nvram_find_and_copy - find NVRAM on flash mapping & copy it */ static int bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_size) { - struct nvram_header __iomem *header; size_t flash_size; size_t offset; u32 size; @@ -95,23 +118,7 @@ static int bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_siz return -ENXIO; found: - header = (struct nvram_header *)(flash_start + offset); - __ioread32_copy(nvram_buf, header, sizeof(*header) / 4); - nvram_len = ((struct nvram_header *)(nvram_buf))->len; - size = res_size - offset; - if (nvram_len > size) { - pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n"); - nvram_len = size; - } - if (nvram_len >= NVRAM_SPACE) { - pr_err("nvram on flash (%zu bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", - nvram_len, NVRAM_SPACE - 1); - nvram_len = NVRAM_SPACE - 1; - } - /* proceed reading data after header */ - __ioread32_copy(nvram_buf + sizeof(*header), header + 1, - DIV_ROUND_UP(nvram_len, 4)); - nvram_buf[NVRAM_SPACE - 1] = '\0'; + bcm47xx_nvram_copy(flash_start + offset, res_size - offset); return 0; } -- cgit v1.2.3 From 98b68324f67236e8c9152976535dc1f27fb67ba8 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 8 Mar 2021 10:03:19 +0100 Subject: firmware: bcm47xx_nvram: look for NVRAM with for instead of while MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This loop requires variable initialization, stop condition and post iteration increment. It's pretty much a for loop definition. Signed-off-by: Rafał Miłecki Signed-off-by: Thomas Bogendoerfer --- drivers/firmware/broadcom/bcm47xx_nvram.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c index 09f51b95849e..1d2271b1e07a 100644 --- a/drivers/firmware/broadcom/bcm47xx_nvram.c +++ b/drivers/firmware/broadcom/bcm47xx_nvram.c @@ -93,15 +93,13 @@ static int bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_siz } /* TODO: when nvram is on nand flash check for bad blocks first. */ - flash_size = FLASH_MIN; - while (flash_size <= res_size) { + for (flash_size = FLASH_MIN; flash_size <= res_size; flash_size <<= 1) { /* Windowed flash access */ size = find_nvram_size(flash_start + flash_size); if (size) { offset = flash_size - size; goto found; } - flash_size <<= 1; } /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ -- cgit v1.2.3 From f52da4ccfec9192e17f5c16260dfdd6d3ea76f65 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 8 Mar 2021 10:03:20 +0100 Subject: firmware: bcm47xx_nvram: inline code checking NVRAM size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Separated function was not improving code quality much (or at all). Moreover it expected possible flash end address as argument and it was returning NVRAM size. The new code always operates on offsets which means less logic and less calculations. Signed-off-by: Rafał Miłecki Signed-off-by: Thomas Bogendoerfer --- drivers/firmware/broadcom/bcm47xx_nvram.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c index 1d2271b1e07a..bd235833b687 100644 --- a/drivers/firmware/broadcom/bcm47xx_nvram.c +++ b/drivers/firmware/broadcom/bcm47xx_nvram.c @@ -42,18 +42,6 @@ static bool bcm47xx_nvram_is_valid(void __iomem *nvram) return ((struct nvram_header *)nvram)->magic == NVRAM_MAGIC; } -static u32 find_nvram_size(void __iomem *end) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { - if (bcm47xx_nvram_is_valid(end - nvram_sizes[i])) - return nvram_sizes[i]; - } - - return 0; -} - /** * bcm47xx_nvram_copy - copy NVRAM to internal buffer */ @@ -85,7 +73,7 @@ static int bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_siz { size_t flash_size; size_t offset; - u32 size; + int i; if (nvram_len) { pr_warn("nvram already initialized\n"); @@ -93,12 +81,13 @@ static int bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_siz } /* TODO: when nvram is on nand flash check for bad blocks first. */ + + /* Try every possible flash size and check for NVRAM at its end */ for (flash_size = FLASH_MIN; flash_size <= res_size; flash_size <<= 1) { - /* Windowed flash access */ - size = find_nvram_size(flash_start + flash_size); - if (size) { - offset = flash_size - size; - goto found; + for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { + offset = flash_size - nvram_sizes[i]; + if (bcm47xx_nvram_is_valid(flash_start + offset)) + goto found; } } -- cgit v1.2.3 From b2c4c3969fd7d79caf05f1ebfcaa330e020ecc36 Mon Sep 17 00:00:00 2001 From: Qing Zhang Date: Mon, 15 Mar 2021 15:50:02 +0800 Subject: irqchip/loongson-liointc: irqchip add 2.0 version Add IO interrupt controller support for Loongson-2K1000, different from the Loongson-3A series is that Loongson-2K1000 has 64 interrupt sources, 0-31 correspond to the device tree liointc0 device node, and the other correspond to liointc1 node. Signed-off-by: Jiaxun Yang Signed-off-by: Qing Zhang Tested-by: Ming Wang Acked-by: Marc Zyngier Signed-off-by: Thomas Bogendoerfer --- drivers/irqchip/irq-loongson-liointc.c | 58 ++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c index 249566a23cc4..8ccb30421806 100644 --- a/drivers/irqchip/irq-loongson-liointc.c +++ b/drivers/irqchip/irq-loongson-liointc.c @@ -20,6 +20,7 @@ #define LIOINTC_CHIP_IRQ 32 #define LIOINTC_NUM_PARENT 4 +#define LIOINTC_NUM_CORES 4 #define LIOINTC_INTC_CHIP_START 0x20 @@ -42,6 +43,7 @@ struct liointc_handler_data { struct liointc_priv { struct irq_chip_generic *gc; struct liointc_handler_data handler[LIOINTC_NUM_PARENT]; + void __iomem *core_isr[LIOINTC_NUM_CORES]; u8 map_cache[LIOINTC_CHIP_IRQ]; bool has_lpc_irq_errata; }; @@ -51,11 +53,12 @@ static void liointc_chained_handle_irq(struct irq_desc *desc) struct liointc_handler_data *handler = irq_desc_get_handler_data(desc); struct irq_chip *chip = irq_desc_get_chip(desc); struct irq_chip_generic *gc = handler->priv->gc; + int core = get_ebase_cpunum() % LIOINTC_NUM_CORES; u32 pending; chained_irq_enter(chip, desc); - pending = readl(gc->reg_base + LIOINTC_REG_INTC_STATUS); + pending = readl(handler->priv->core_isr[core]); if (!pending) { /* Always blame LPC IRQ if we have that bug */ @@ -141,6 +144,18 @@ static void liointc_resume(struct irq_chip_generic *gc) } static const char * const parent_names[] = {"int0", "int1", "int2", "int3"}; +static const char * const core_reg_names[] = {"isr0", "isr1", "isr2", "isr3"}; + +static void __iomem *liointc_get_reg_byname(struct device_node *node, + const char *name) +{ + int index = of_property_match_string(node, "reg-names", name); + + if (index < 0) + return NULL; + + return of_iomap(node, index); +} static int __init liointc_of_init(struct device_node *node, struct device_node *parent) @@ -159,10 +174,28 @@ static int __init liointc_of_init(struct device_node *node, if (!priv) return -ENOMEM; - base = of_iomap(node, 0); - if (!base) { - err = -ENODEV; - goto out_free_priv; + if (of_device_is_compatible(node, "loongson,liointc-2.0")) { + base = liointc_get_reg_byname(node, "main"); + if (!base) { + err = -ENODEV; + goto out_free_priv; + } + + for (i = 0; i < LIOINTC_NUM_CORES; i++) + priv->core_isr[i] = liointc_get_reg_byname(node, core_reg_names[i]); + if (!priv->core_isr[0]) { + err = -ENODEV; + goto out_iounmap_base; + } + } else { + base = of_iomap(node, 0); + if (!base) { + err = -ENODEV; + goto out_free_priv; + } + + for (i = 0; i < LIOINTC_NUM_CORES; i++) + priv->core_isr[i] = base + LIOINTC_REG_INTC_STATUS; } for (i = 0; i < LIOINTC_NUM_PARENT; i++) { @@ -172,7 +205,7 @@ static int __init liointc_of_init(struct device_node *node, } if (!have_parent) { err = -ENODEV; - goto out_iounmap; + goto out_iounmap_isr; } sz = of_property_read_variable_u32_array(node, @@ -183,7 +216,7 @@ static int __init liointc_of_init(struct device_node *node, if (sz < 4) { pr_err("loongson-liointc: No parent_int_map\n"); err = -ENODEV; - goto out_iounmap; + goto out_iounmap_isr; } for (i = 0; i < LIOINTC_NUM_PARENT; i++) @@ -195,7 +228,7 @@ static int __init liointc_of_init(struct device_node *node, if (!domain) { pr_err("loongson-liointc: cannot add IRQ domain\n"); err = -EINVAL; - goto out_iounmap; + goto out_iounmap_isr; } err = irq_alloc_domain_generic_chips(domain, 32, 1, @@ -260,7 +293,13 @@ static int __init liointc_of_init(struct device_node *node, out_free_domain: irq_domain_remove(domain); -out_iounmap: +out_iounmap_isr: + for (i = 0; i < LIOINTC_NUM_CORES; i++) { + if (!priv->core_isr[i]) + continue; + iounmap(priv->core_isr[i]); + } +out_iounmap_base: iounmap(base); out_free_priv: kfree(priv); @@ -270,3 +309,4 @@ out_free_priv: IRQCHIP_DECLARE(loongson_liointc_1_0, "loongson,liointc-1.0", liointc_of_init); IRQCHIP_DECLARE(loongson_liointc_1_0a, "loongson,liointc-1.0a", liointc_of_init); +IRQCHIP_DECLARE(loongson_liointc_2_0, "loongson,liointc-2.0", liointc_of_init); -- cgit v1.2.3