Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arch/loongarch/include/asm/numa.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/nodemask.h>

#define NODE_ADDRSPACE_SHIFT 44
#define NODES_PER_FLATMODE_NODE 4

#define pa_to_nid(addr) (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT)
#define nid_to_addrbase(nid) (_ULCAST_(nid) << NODE_ADDRSPACE_SHIFT)
Expand Down
39 changes: 31 additions & 8 deletions arch/loongarch/kernel/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ static int __init efimap_populate_hugepages(
if (pud_none(*pud)) {
void *p = memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);

if (!p)
if (!p) {
pr_err("can not alloc efimap huge pages!\n");
return -1;
}
pmd_init(p);
pud_populate(&init_mm, pud, p);
}
Expand All @@ -88,7 +90,8 @@ static void __init efi_map_pgt(void)
{
unsigned long node;
unsigned long start, end;
unsigned long start_pfn, end_pfn;
efi_memory_desc_t *md;
u32 mem_type;

pgd_efi = memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
if (!pgd_efi) {
Expand All @@ -105,13 +108,33 @@ static void __init efi_map_pgt(void)
/* MMIO Registers, Uncached */
efimap_populate_hugepages(SZ_256M | (node << 44),
SZ_512M | (node << 44), PAGE_KERNEL_SUC);
}

get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
start = ALIGN_DOWN(start_pfn << PAGE_SHIFT, PMD_SIZE);
end = ALIGN(end_pfn << PAGE_SHIFT, PMD_SIZE);

/* System memory, Cached */
efimap_populate_hugepages(node ? start : SZ_512M, end, PAGE_KERNEL);
/* Parse memory information */
for_each_efi_memory_desc(md) {
mem_type = md->type;
start = ALIGN_DOWN(md->phys_addr, PMD_SIZE);
end = ALIGN(start + (md->num_pages << EFI_PAGE_SHIFT), PMD_SIZE);
node = start >> 44;

switch (mem_type) {
case EFI_LOADER_CODE:
case EFI_LOADER_DATA:
case EFI_BOOT_SERVICES_CODE:
case EFI_BOOT_SERVICES_DATA:
case EFI_PAL_CODE:
case EFI_UNUSABLE_MEMORY:
case EFI_ACPI_RECLAIM_MEMORY:
case EFI_RESERVED_TYPE:
case EFI_RUNTIME_SERVICES_CODE:
case EFI_RUNTIME_SERVICES_DATA:
efimap_populate_hugepages(node ? start : SZ_512M, end, PAGE_KERNEL);
break;
case EFI_MEMORY_MAPPED_IO:
case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
efimap_populate_hugepages(node ? start : SZ_512M, end, PAGE_KERNEL_SUC);
break;
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions arch/loongarch/kernel/legacy_boot.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <linux/acpi.h>
#include <linux/of_address.h>
#include <linux/screen_info.h>
#include <asm/loongson.h>

#define ADDRESS_TYPE_SYSRAM 1
#define ADDRESS_TYPE_RESERVED 2
Expand Down Expand Up @@ -89,4 +90,6 @@ extern int __init
pch_msi_parse_madt(union acpi_subtable_headers *header,
const unsigned long end);
extern struct irq_domain *get_pchpic_irq_domain(void);

extern __init void fw_init_cmdline(unsigned long argc, unsigned long cmdp);
#endif
6 changes: 5 additions & 1 deletion arch/loongarch/kernel/relocate.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <asm/inst.h>
#include <asm/sections.h>
#include <asm/setup.h>
#include "legacy_boot.h"

#define RELOCATED(x) ((void *)((long)x + reloc_offset))
#define RELOCATED_KASLR(x) ((void *)((long)x + random_offset))
Expand Down Expand Up @@ -172,7 +173,10 @@ unsigned long __init relocate_kernel(void)
void *location_new = _text; /* Default to original kernel start */
char *cmdline = early_ioremap(fw_arg1, COMMAND_LINE_SIZE); /* Boot command line is passed in fw_arg1 */

strscpy(boot_command_line, cmdline, COMMAND_LINE_SIZE);
if (fw_arg0 < 2)
strscpy(boot_command_line, cmdline, COMMAND_LINE_SIZE);
else
fw_init_cmdline(fw_arg0, TO_CACHE(fw_arg1)); /* OLD BPI parameters */

#ifdef CONFIG_RANDOMIZE_BASE
location_new = determine_relocation_address();
Expand Down
4 changes: 2 additions & 2 deletions drivers/irqchip/irq-loongson-eiointc.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ int __init pch_msi_parse_madt(union acpi_subtable_headers *header,
int node;

if (cpu_has_flatmode)
node = cpu_to_node(eiointc_priv[nr_pics - 1]->node * CORES_PER_EIO_NODE);
node = eiointc_priv[nr_pics - 1]->node / NODES_PER_FLATMODE_NODE;
else
node = eiointc_priv[nr_pics - 1]->node;

Expand Down Expand Up @@ -455,7 +455,7 @@ int __init eiointc_acpi_init(struct irq_domain *parent,
goto out_free_handle;

if (cpu_has_flatmode)
node = cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE);
node = acpi_eiointc->node / NODES_PER_FLATMODE_NODE;
else
node = acpi_eiointc->node;
acpi_set_vec_parent(node, priv->eiointc_domain, pch_group);
Expand Down
70 changes: 56 additions & 14 deletions drivers/irqchip/irq-loongson-pch-pic.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#define PCH_INT_HTVEC(irq) (0x200 + irq)
#define PCH_PIC_POL 0x3e0

#define PIC_UNDEF_VECTOR 255
#define PIC_COUNT_PER_REG 32
#define PIC_REG_COUNT 2
#define PIC_COUNT (PIC_COUNT_PER_REG * PIC_REG_COUNT)
Expand All @@ -46,6 +47,8 @@ struct pch_pic {
u32 saved_vec_en[PIC_REG_COUNT];
u32 saved_vec_pol[PIC_REG_COUNT];
u32 saved_vec_edge[PIC_REG_COUNT];
u8 table[PIC_COUNT];
int inuse;
};

static struct pch_pic *pch_pic_priv[MAX_IO_PICS];
Expand All @@ -57,6 +60,11 @@ struct irq_domain *get_pchpic_irq_domain(void)
return pch_pic_priv[0]->pic_domain;
}

static inline u8 hwirq_to_bit(struct pch_pic *priv, int hirq)
{
return priv->table[hirq];
}

static void pch_pic_bitset(struct pch_pic *priv, int offset, int bit)
{
u32 reg;
Expand Down Expand Up @@ -85,45 +93,47 @@ static void pch_pic_mask_irq(struct irq_data *d)
{
struct pch_pic *priv = irq_data_get_irq_chip_data(d);

pch_pic_bitset(priv, PCH_PIC_MASK, d->hwirq);
pch_pic_bitset(priv, PCH_PIC_MASK, hwirq_to_bit(priv, d->hwirq));
irq_chip_mask_parent(d);
}

static void pch_pic_unmask_irq(struct irq_data *d)
{
struct pch_pic *priv = irq_data_get_irq_chip_data(d);
int bit = hwirq_to_bit(priv, d->hwirq);

writel(BIT(PIC_REG_BIT(d->hwirq)),
priv->base + PCH_PIC_CLR + PIC_REG_IDX(d->hwirq) * 4);
priv->base + PCH_PIC_CLR + PIC_REG_IDX(bit) * 4);

irq_chip_unmask_parent(d);
pch_pic_bitclr(priv, PCH_PIC_MASK, d->hwirq);
pch_pic_bitclr(priv, PCH_PIC_MASK, bit);
}

static int pch_pic_set_type(struct irq_data *d, unsigned int type)
{
struct pch_pic *priv = irq_data_get_irq_chip_data(d);
int bit = hwirq_to_bit(priv, d->hwirq);
int ret = 0;

switch (type) {
case IRQ_TYPE_EDGE_RISING:
pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
pch_pic_bitset(priv, PCH_PIC_EDGE, bit);
pch_pic_bitclr(priv, PCH_PIC_POL, bit);
irq_set_handler_locked(d, handle_edge_irq);
break;
case IRQ_TYPE_EDGE_FALLING:
pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
pch_pic_bitset(priv, PCH_PIC_EDGE, bit);
pch_pic_bitset(priv, PCH_PIC_POL, bit);
irq_set_handler_locked(d, handle_edge_irq);
break;
case IRQ_TYPE_LEVEL_HIGH:
pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
pch_pic_bitclr(priv, PCH_PIC_EDGE, bit);
pch_pic_bitclr(priv, PCH_PIC_POL, bit);
irq_set_handler_locked(d, handle_level_irq);
break;
case IRQ_TYPE_LEVEL_LOW:
pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
pch_pic_bitclr(priv, PCH_PIC_EDGE, bit);
pch_pic_bitset(priv, PCH_PIC_POL, bit);
irq_set_handler_locked(d, handle_level_irq);
break;
default:
Expand All @@ -138,11 +148,12 @@ static void pch_pic_ack_irq(struct irq_data *d)
{
unsigned int reg;
struct pch_pic *priv = irq_data_get_irq_chip_data(d);
int bit = hwirq_to_bit(priv, d->hwirq);

reg = readl(priv->base + PCH_PIC_EDGE + PIC_REG_IDX(d->hwirq) * 4);
reg = readl(priv->base + PCH_PIC_EDGE + PIC_REG_IDX(bit) * 4);
if (reg & BIT(PIC_REG_BIT(d->hwirq))) {
writel(BIT(PIC_REG_BIT(d->hwirq)),
priv->base + PCH_PIC_CLR + PIC_REG_IDX(d->hwirq) * 4);
priv->base + PCH_PIC_CLR + PIC_REG_IDX(bit) * 4);
}
irq_chip_ack_parent(d);
}
Expand All @@ -164,6 +175,8 @@ static int pch_pic_domain_translate(struct irq_domain *d,
{
struct pch_pic *priv = d->host_data;
struct device_node *of_node = to_of_node(fwspec->fwnode);
unsigned long flags;
int i;

if (of_node) {
if (fwspec->param_count < 2)
Expand All @@ -176,12 +189,33 @@ static int pch_pic_domain_translate(struct irq_domain *d,
return -EINVAL;

*hwirq = fwspec->param[0] - priv->gsi_base;

if (fwspec->param_count > 1)
*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
else
*type = IRQ_TYPE_NONE;
}

raw_spin_lock_irqsave(&priv->pic_lock, flags);
/* Check pic-table to confirm if the hwirq has been assigned */
for (i = 0; i < priv->inuse; i++) {
if (priv->table[i] == *hwirq) {
*hwirq = i;
break;
}
}
if (i == priv->inuse) {
/* Assign a new hwirq in pic-table */
if (priv->inuse >= PIC_COUNT) {
pr_err("pch-pic domain has no free vectors\n");
raw_spin_unlock_irqrestore(&priv->pic_lock, flags);
return -EINVAL;
}
priv->table[priv->inuse] = *hwirq;
*hwirq = priv->inuse++;
}
raw_spin_unlock_irqrestore(&priv->pic_lock, flags);

return 0;
}

Expand All @@ -199,6 +233,9 @@ static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq,
if (err)
return err;

/* Write vector ID */
writeb(priv->ht_vec_base + hwirq, priv->base + PCH_INT_HTVEC(hwirq_to_bit(priv, hwirq)));

parent_fwspec.fwnode = domain->parent->fwnode;
parent_fwspec.param_count = 1;
parent_fwspec.param[0] = hwirq + priv->ht_vec_base;
Expand Down Expand Up @@ -227,7 +264,7 @@ static void pch_pic_reset(struct pch_pic *priv)

for (i = 0; i < PIC_COUNT; i++) {
/* Write vector ID */
writeb(priv->ht_vec_base + i, priv->base + PCH_INT_HTVEC(i));
writeb(priv->ht_vec_base + i, priv->base + PCH_INT_HTVEC(hwirq_to_bit(priv, i)));
/* Hardcode route to HT0 Lo */
writeb(1, priv->base + PCH_INT_ROUTE(i));
}
Expand Down Expand Up @@ -289,6 +326,7 @@ static int pch_pic_init(phys_addr_t addr, unsigned long size, int vec_base,
u32 gsi_base)
{
struct pch_pic *priv;
int i;

priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
Expand All @@ -299,6 +337,10 @@ static int pch_pic_init(phys_addr_t addr, unsigned long size, int vec_base,
if (!priv->base)
goto free_priv;

priv->inuse = 0;
for (i = 0; i < PIC_COUNT; i++)
priv->table[i] = PIC_UNDEF_VECTOR;

priv->ht_vec_base = vec_base;
priv->vec_count = ((readq(priv->base) >> 48) & 0xff) + 1;
priv->gsi_base = gsi_base;
Expand Down