diff options
Diffstat (limited to 'drivers/irqchip/irq-gic-v3-its.c')
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 57 |
1 files changed, 48 insertions, 9 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 596b0a9eee99..9687f8afebff 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c | |||
@@ -169,7 +169,7 @@ static void its_encode_cmd(struct its_cmd_block *cmd, u8 cmd_nr) | |||
169 | 169 | ||
170 | static void its_encode_devid(struct its_cmd_block *cmd, u32 devid) | 170 | static void its_encode_devid(struct its_cmd_block *cmd, u32 devid) |
171 | { | 171 | { |
172 | cmd->raw_cmd[0] &= ~(0xffffUL << 32); | 172 | cmd->raw_cmd[0] &= BIT_ULL(32) - 1; |
173 | cmd->raw_cmd[0] |= ((u64)devid) << 32; | 173 | cmd->raw_cmd[0] |= ((u64)devid) << 32; |
174 | } | 174 | } |
175 | 175 | ||
@@ -802,6 +802,7 @@ static int its_alloc_tables(struct its_node *its) | |||
802 | int i; | 802 | int i; |
803 | int psz = SZ_64K; | 803 | int psz = SZ_64K; |
804 | u64 shr = GITS_BASER_InnerShareable; | 804 | u64 shr = GITS_BASER_InnerShareable; |
805 | u64 cache = GITS_BASER_WaWb; | ||
805 | 806 | ||
806 | for (i = 0; i < GITS_BASER_NR_REGS; i++) { | 807 | for (i = 0; i < GITS_BASER_NR_REGS; i++) { |
807 | u64 val = readq_relaxed(its->base + GITS_BASER + i * 8); | 808 | u64 val = readq_relaxed(its->base + GITS_BASER + i * 8); |
@@ -848,7 +849,7 @@ retry_baser: | |||
848 | val = (virt_to_phys(base) | | 849 | val = (virt_to_phys(base) | |
849 | (type << GITS_BASER_TYPE_SHIFT) | | 850 | (type << GITS_BASER_TYPE_SHIFT) | |
850 | ((entry_size - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) | | 851 | ((entry_size - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) | |
851 | GITS_BASER_WaWb | | 852 | cache | |
852 | shr | | 853 | shr | |
853 | GITS_BASER_VALID); | 854 | GITS_BASER_VALID); |
854 | 855 | ||
@@ -874,9 +875,12 @@ retry_baser: | |||
874 | * Shareability didn't stick. Just use | 875 | * Shareability didn't stick. Just use |
875 | * whatever the read reported, which is likely | 876 | * whatever the read reported, which is likely |
876 | * to be the only thing this redistributor | 877 | * to be the only thing this redistributor |
877 | * supports. | 878 | * supports. If that's zero, make it |
879 | * non-cacheable as well. | ||
878 | */ | 880 | */ |
879 | shr = tmp & GITS_BASER_SHAREABILITY_MASK; | 881 | shr = tmp & GITS_BASER_SHAREABILITY_MASK; |
882 | if (!shr) | ||
883 | cache = GITS_BASER_nC; | ||
880 | goto retry_baser; | 884 | goto retry_baser; |
881 | } | 885 | } |
882 | 886 | ||
@@ -980,16 +984,39 @@ static void its_cpu_init_lpis(void) | |||
980 | tmp = readq_relaxed(rbase + GICR_PROPBASER); | 984 | tmp = readq_relaxed(rbase + GICR_PROPBASER); |
981 | 985 | ||
982 | if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) { | 986 | if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) { |
987 | if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) { | ||
988 | /* | ||
989 | * The HW reports non-shareable, we must | ||
990 | * remove the cacheability attributes as | ||
991 | * well. | ||
992 | */ | ||
993 | val &= ~(GICR_PROPBASER_SHAREABILITY_MASK | | ||
994 | GICR_PROPBASER_CACHEABILITY_MASK); | ||
995 | val |= GICR_PROPBASER_nC; | ||
996 | writeq_relaxed(val, rbase + GICR_PROPBASER); | ||
997 | } | ||
983 | pr_info_once("GIC: using cache flushing for LPI property table\n"); | 998 | pr_info_once("GIC: using cache flushing for LPI property table\n"); |
984 | gic_rdists->flags |= RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING; | 999 | gic_rdists->flags |= RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING; |
985 | } | 1000 | } |
986 | 1001 | ||
987 | /* set PENDBASE */ | 1002 | /* set PENDBASE */ |
988 | val = (page_to_phys(pend_page) | | 1003 | val = (page_to_phys(pend_page) | |
989 | GICR_PROPBASER_InnerShareable | | 1004 | GICR_PENDBASER_InnerShareable | |
990 | GICR_PROPBASER_WaWb); | 1005 | GICR_PENDBASER_WaWb); |
991 | 1006 | ||
992 | writeq_relaxed(val, rbase + GICR_PENDBASER); | 1007 | writeq_relaxed(val, rbase + GICR_PENDBASER); |
1008 | tmp = readq_relaxed(rbase + GICR_PENDBASER); | ||
1009 | |||
1010 | if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) { | ||
1011 | /* | ||
1012 | * The HW reports non-shareable, we must remove the | ||
1013 | * cacheability attributes as well. | ||
1014 | */ | ||
1015 | val &= ~(GICR_PENDBASER_SHAREABILITY_MASK | | ||
1016 | GICR_PENDBASER_CACHEABILITY_MASK); | ||
1017 | val |= GICR_PENDBASER_nC; | ||
1018 | writeq_relaxed(val, rbase + GICR_PENDBASER); | ||
1019 | } | ||
993 | 1020 | ||
994 | /* Enable LPIs */ | 1021 | /* Enable LPIs */ |
995 | val = readl_relaxed(rbase + GICR_CTLR); | 1022 | val = readl_relaxed(rbase + GICR_CTLR); |
@@ -1026,7 +1053,7 @@ static void its_cpu_init_collection(void) | |||
1026 | * This ITS wants a linear CPU number. | 1053 | * This ITS wants a linear CPU number. |
1027 | */ | 1054 | */ |
1028 | target = readq_relaxed(gic_data_rdist_rd_base() + GICR_TYPER); | 1055 | target = readq_relaxed(gic_data_rdist_rd_base() + GICR_TYPER); |
1029 | target = GICR_TYPER_CPU_NUMBER(target); | 1056 | target = GICR_TYPER_CPU_NUMBER(target) << 16; |
1030 | } | 1057 | } |
1031 | 1058 | ||
1032 | /* Perform collection mapping */ | 1059 | /* Perform collection mapping */ |
@@ -1422,14 +1449,26 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) | |||
1422 | 1449 | ||
1423 | writeq_relaxed(baser, its->base + GITS_CBASER); | 1450 | writeq_relaxed(baser, its->base + GITS_CBASER); |
1424 | tmp = readq_relaxed(its->base + GITS_CBASER); | 1451 | tmp = readq_relaxed(its->base + GITS_CBASER); |
1425 | writeq_relaxed(0, its->base + GITS_CWRITER); | ||
1426 | writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR); | ||
1427 | 1452 | ||
1428 | if ((tmp ^ baser) & GITS_BASER_SHAREABILITY_MASK) { | 1453 | if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) { |
1454 | if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) { | ||
1455 | /* | ||
1456 | * The HW reports non-shareable, we must | ||
1457 | * remove the cacheability attributes as | ||
1458 | * well. | ||
1459 | */ | ||
1460 | baser &= ~(GITS_CBASER_SHAREABILITY_MASK | | ||
1461 | GITS_CBASER_CACHEABILITY_MASK); | ||
1462 | baser |= GITS_CBASER_nC; | ||
1463 | writeq_relaxed(baser, its->base + GITS_CBASER); | ||
1464 | } | ||
1429 | pr_info("ITS: using cache flushing for cmd queue\n"); | 1465 | pr_info("ITS: using cache flushing for cmd queue\n"); |
1430 | its->flags |= ITS_FLAGS_CMDQ_NEEDS_FLUSHING; | 1466 | its->flags |= ITS_FLAGS_CMDQ_NEEDS_FLUSHING; |
1431 | } | 1467 | } |
1432 | 1468 | ||
1469 | writeq_relaxed(0, its->base + GITS_CWRITER); | ||
1470 | writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR); | ||
1471 | |||
1433 | if (of_property_read_bool(its->msi_chip.of_node, "msi-controller")) { | 1472 | if (of_property_read_bool(its->msi_chip.of_node, "msi-controller")) { |
1434 | its->domain = irq_domain_add_tree(NULL, &its_domain_ops, its); | 1473 | its->domain = irq_domain_add_tree(NULL, &its_domain_ops, its); |
1435 | if (!its->domain) { | 1474 | if (!its->domain) { |