Commit | Line | Data |
---|---|---|
8673c1d7 LW |
1 | /* |
2 | * Special GIC quirks for the ARM RealView | |
3 | * Copyright (C) 2015 Linus Walleij | |
4 | */ | |
5 | #include <linux/of.h> | |
6 | #include <linux/regmap.h> | |
7 | #include <linux/mfd/syscon.h> | |
8 | #include <linux/bitops.h> | |
9 | #include <linux/irqchip.h> | |
10 | #include <linux/irqchip/arm-gic.h> | |
11 | ||
12 | #define REALVIEW_SYS_LOCK_OFFSET 0x20 | |
82b0a434 LW |
13 | #define REALVIEW_SYS_PLD_CTRL1 0x74 |
14 | #define REALVIEW_EB_REVB_SYS_PLD_CTRL1 0xD8 | |
8673c1d7 LW |
15 | #define VERSATILE_LOCK_VAL 0xA05F |
16 | #define PLD_INTMODE_MASK BIT(22)|BIT(23)|BIT(24) | |
17 | #define PLD_INTMODE_LEGACY 0x0 | |
18 | #define PLD_INTMODE_NEW_DCC BIT(22) | |
19 | #define PLD_INTMODE_NEW_NO_DCC BIT(23) | |
20 | #define PLD_INTMODE_FIQ_ENABLE BIT(24) | |
21 | ||
82b0a434 LW |
22 | /* For some reason RealView EB Rev B moved this register */ |
23 | static const struct of_device_id syscon_pldset_of_match[] = { | |
24 | { | |
25 | .compatible = "arm,realview-eb11mp-revb-syscon", | |
26 | .data = (void *)REALVIEW_EB_REVB_SYS_PLD_CTRL1, | |
27 | }, | |
28 | { | |
29 | .compatible = "arm,realview-eb11mp-revc-syscon", | |
30 | .data = (void *)REALVIEW_SYS_PLD_CTRL1, | |
31 | }, | |
32 | { | |
33 | .compatible = "arm,realview-eb-syscon", | |
34 | .data = (void *)REALVIEW_SYS_PLD_CTRL1, | |
35 | }, | |
36 | { | |
37 | .compatible = "arm,realview-pb11mp-syscon", | |
38 | .data = (void *)REALVIEW_SYS_PLD_CTRL1, | |
39 | }, | |
40 | {}, | |
41 | }; | |
42 | ||
8673c1d7 LW |
43 | static int __init |
44 | realview_gic_of_init(struct device_node *node, struct device_node *parent) | |
45 | { | |
46 | static struct regmap *map; | |
82b0a434 LW |
47 | struct device_node *np; |
48 | const struct of_device_id *gic_id; | |
49 | u32 pld1_ctrl; | |
50 | ||
51 | np = of_find_matching_node_and_match(NULL, syscon_pldset_of_match, | |
52 | &gic_id); | |
53 | if (!np) | |
54 | return -ENODEV; | |
55 | pld1_ctrl = (u32)gic_id->data; | |
8673c1d7 LW |
56 | |
57 | /* The PB11MPCore GIC needs to be configured in the syscon */ | |
82b0a434 | 58 | map = syscon_node_to_regmap(np); |
8673c1d7 LW |
59 | if (!IS_ERR(map)) { |
60 | /* new irq mode with no DCC */ | |
61 | regmap_write(map, REALVIEW_SYS_LOCK_OFFSET, | |
62 | VERSATILE_LOCK_VAL); | |
82b0a434 | 63 | regmap_update_bits(map, pld1_ctrl, |
8673c1d7 LW |
64 | PLD_INTMODE_NEW_NO_DCC, |
65 | PLD_INTMODE_MASK); | |
66 | regmap_write(map, REALVIEW_SYS_LOCK_OFFSET, 0x0000); | |
82b0a434 | 67 | pr_info("RealView GIC: set up interrupt controller to NEW mode, no DCC\n"); |
8673c1d7 | 68 | } else { |
82b0a434 LW |
69 | pr_err("RealView GIC setup: could not find syscon\n"); |
70 | return -ENODEV; | |
8673c1d7 LW |
71 | } |
72 | return gic_of_init(node, parent); | |
73 | } | |
74 | IRQCHIP_DECLARE(armtc11mp_gic, "arm,tc11mp-gic", realview_gic_of_init); | |
82b0a434 | 75 | IRQCHIP_DECLARE(armeb11mp_gic, "arm,eb11mp-gic", realview_gic_of_init); |