Skip to content

Commit

Permalink
drv: irq: fix rk356x pci its issue & pci register ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
unifreq committed Dec 24, 2022
1 parent c4208a1 commit 3025fa1
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 17 deletions.
8 changes: 8 additions & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,14 @@ config SOCIONEXT_SYNQUACER_PREITS

If unsure, say Y.

config ROCKCHIP_ERRATUM_114514
bool "Rockchip RK3568 force no_local_cache"
default y
help
They consider this as a SoC implement design instead of a bug.

If unsure, say Y.

endmenu # "ARM errata workarounds via the alternatives framework"

choice
Expand Down
4 changes: 2 additions & 2 deletions arch/arm64/boot/dts/rockchip/rk3568.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
num-ib-windows = <6>;
num-ob-windows = <2>;
max-link-speed = <3>;
msi-map = <0x1000 &gic 0x1000 0x1000>;
msi-map = <0x1000 &its 0x1000 0x1000>;
num-lanes = <1>;
phys = <&pcie30phy>;
phy-names = "pcie-phy";
Expand Down Expand Up @@ -139,7 +139,7 @@
num-ib-windows = <6>;
num-ob-windows = <2>;
max-link-speed = <3>;
msi-map = <0x2000 &gic 0x2000 0x1000>;
msi-map = <0x2000 &its 0x2000 0x1000>;
num-lanes = <2>;
phys = <&pcie30phy>;
phy-names = "pcie-phy";
Expand Down
28 changes: 18 additions & 10 deletions arch/arm64/boot/dts/rockchip/rk356x.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -315,14 +315,21 @@

gic: interrupt-controller@fd400000 {
compatible = "arm,gic-v3";
#interrupt-cells = <3>;
#address-cells = <2>;
#size-cells = <2>;
ranges;
interrupt-controller;

reg = <0x0 0xfd400000 0 0x10000>, /* GICD */
<0x0 0xfd460000 0 0x80000>; /* GICR */
<0x0 0xfd460000 0 0xc0000>; /* GICR */
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <3>;
mbi-alias = <0x0 0xfd410000>;
mbi-ranges = <296 24>;
msi-controller;
its: interrupt-controller@fd440000 {
compatible = "arm,gic-v3-its";
msi-controller;
#msi-cells = <1>;
reg = <0x0 0xfd440000 0x0 0x20000>;
};
};

usb_host0_ehci: usb@fd800000 {
Expand Down Expand Up @@ -962,7 +969,7 @@
compatible = "rockchip,rk3568-pcie";
reg = <0x3 0xc0000000 0x0 0x00400000>,
<0x0 0xfe260000 0x0 0x00010000>,
<0x3 0x3f000000 0x0 0x01000000>;
<0x0 0xf4000000 0x0 0x00100000>;
reg-names = "dbi", "apb", "config";
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
Expand All @@ -986,13 +993,14 @@
num-ib-windows = <6>;
num-ob-windows = <2>;
max-link-speed = <2>;
msi-map = <0x0 &gic 0x0 0x1000>;
msi-map = <0x0 &its 0x0 0x1000>;
num-lanes = <1>;
phys = <&combphy2 PHY_TYPE_PCIE>;
phy-names = "pcie-phy";
power-domains = <&power RK3568_PD_PIPE>;
ranges = <0x01000000 0x0 0x3ef00000 0x3 0x3ef00000 0x0 0x00100000
0x02000000 0x0 0x00000000 0x3 0x00000000 0x0 0x3ef00000>;
ranges = <0x01000000 0x0 0xf4100000 0x0 0xf4100000 0x0 0x00100000>,
<0x02000000 0x0 0xf4200000 0x0 0xf4200000 0x0 0x01e00000>,
<0x03000000 0x0 0x40000000 0x3 0x00000000 0x0 0x40000000>;
resets = <&cru SRST_PCIE20_POWERUP>;
reset-names = "pipe";
#address-cells = <3>;
Expand Down
68 changes: 63 additions & 5 deletions drivers/irqchip/irq-gic-v3-its.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

#define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0)
#define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1)
#define RDIST_FLAGS_FORCE_NO_LOCAL_CACHE (1 << 2)

#define RD_LOCAL_LPI_ENABLED BIT(0)
#define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1)
Expand Down Expand Up @@ -2178,6 +2179,11 @@ static struct page *its_allocate_prop_table(gfp_t gfp_flags)
{
struct page *prop_page;

if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE) {
pr_err("ITS ALLOCATE PROP WORKAROUND\n");
gfp_flags |= GFP_DMA;
}

prop_page = alloc_pages(gfp_flags, get_order(LPI_PROPBASE_SZ));
if (!prop_page)
return NULL;
Expand Down Expand Up @@ -2301,6 +2307,7 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
u32 alloc_pages, psz;
struct page *page;
void *base;
gfp_t gfp_flags;

psz = baser->psz;
alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
Expand All @@ -2312,7 +2319,10 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
order = get_order(GITS_BASER_PAGES_MAX * psz);
}

page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, order);
gfp_flags = GFP_KERNEL | __GFP_ZERO;
if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE)
gfp_flags |= GFP_DMA;
page = alloc_pages_node(its->numa_node, gfp_flags, order);
if (!page)
return -ENOMEM;

Expand Down Expand Up @@ -2359,6 +2369,13 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
its_write_baser(its, baser, val);
tmp = baser->val;

if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE) {
if (tmp & GITS_BASER_SHAREABILITY_MASK)
tmp &= ~GITS_BASER_SHAREABILITY_MASK;
else
gic_flush_dcache_to_poc(base, PAGE_ORDER_TO_SIZE(order));
}

if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
/*
* Shareability didn't stick. Just use
Expand Down Expand Up @@ -2941,6 +2958,10 @@ static struct page *its_allocate_pending_table(gfp_t gfp_flags)
{
struct page *pend_page;

if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE) {
gfp_flags |= GFP_DMA;
}

pend_page = alloc_pages(gfp_flags | __GFP_ZERO,
get_order(LPI_PENDBASE_SZ));
if (!pend_page)
Expand Down Expand Up @@ -3096,6 +3117,9 @@ static void its_cpu_init_lpis(void)
gicr_write_propbaser(val, rbase + GICR_PROPBASER);
tmp = gicr_read_propbaser(rbase + GICR_PROPBASER);

if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE)
tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK;

if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
/*
Expand All @@ -3120,6 +3144,9 @@ static void its_cpu_init_lpis(void)
gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
tmp = gicr_read_pendbaser(rbase + GICR_PENDBASER);

if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE)
tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK;

if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {
/*
* The HW reports non-shareable, we must remove the
Expand Down Expand Up @@ -3283,7 +3310,12 @@ static bool its_alloc_table_entry(struct its_node *its,

/* Allocate memory for 2nd level table */
if (!table[idx]) {
page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO;
if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE) {
gfp_flags |= GFP_DMA;
}

page = alloc_pages_node(its->numa_node, gfp_flags,
get_order(baser->psz));
if (!page)
return false;
Expand Down Expand Up @@ -3372,22 +3404,27 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
int nr_lpis;
int nr_ites;
int sz;
gfp_t gfp_flags;

if (!its_alloc_device_table(its, dev_id))
return NULL;

if (WARN_ON(!is_power_of_2(nvecs)))
nvecs = roundup_pow_of_two(nvecs);

dev = kzalloc(sizeof(*dev), GFP_KERNEL);
gfp_flags = GFP_KERNEL;
if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE)
gfp_flags |= GFP_DMA;

dev = kzalloc(sizeof(*dev), gfp_flags);
/*
* Even if the device wants a single LPI, the ITT must be
* sized as a power of two (and you need at least one bit...).
*/
nr_ites = max(2, nvecs);
sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
itt = kzalloc_node(sz, GFP_KERNEL, its->numa_node);
itt = kzalloc_node(sz, gfp_flags, its->numa_node);
if (alloc_lpis) {
lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis);
if (lpi_map)
Expand Down Expand Up @@ -4710,6 +4747,13 @@ static bool __maybe_unused its_enable_quirk_hip07_161600802(void *data)
return true;
}

static bool __maybe_unused its_enable_quirk_rk3568(void *data)
{
gic_rdists->flags |= RDIST_FLAGS_FORCE_NO_LOCAL_CACHE;

return true;
}

static const struct gic_quirk its_quirks[] = {
#ifdef CONFIG_CAVIUM_ERRATUM_22375
{
Expand Down Expand Up @@ -4755,6 +4799,14 @@ static const struct gic_quirk its_quirks[] = {
.mask = 0xffffffff,
.init = its_enable_quirk_hip07_161600802,
},
#endif
#ifdef CONFIG_ROCKCHIP_ERRATUM_114514
{
.desc = "ITS: Rockchip erratum 114514",
.iidr = 0x0201743b,
.mask = 0xffffffff,
.init = its_enable_quirk_rk3568,
},
#endif
{
}
Expand Down Expand Up @@ -5011,6 +5063,7 @@ static int __init its_probe_one(struct resource *res,
struct page *page;
u32 ctlr;
int err;
gfp_t gfp_flags;

its_base = its_map_one(res, &err);
if (!its_base)
Expand Down Expand Up @@ -5064,7 +5117,9 @@ static int __init its_probe_one(struct resource *res,

its->numa_node = numa_node;

page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
gfp_flags = GFP_KERNEL | __GFP_ZERO | GFP_DMA;

page = alloc_pages_node(its->numa_node, gfp_flags,
get_order(ITS_CMD_QUEUE_SZ));
if (!page) {
err = -ENOMEM;
Expand Down Expand Up @@ -5095,6 +5150,9 @@ static int __init its_probe_one(struct resource *res,
gits_write_cbaser(baser, its->base + GITS_CBASER);
tmp = gits_read_cbaser(its->base + GITS_CBASER);

if (gic_rdists->flags & RDIST_FLAGS_FORCE_NO_LOCAL_CACHE)
tmp &= ~GITS_CBASER_SHAREABILITY_MASK;

if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) {
if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) {
/*
Expand Down

0 comments on commit 3025fa1

Please sign in to comment.