aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bus
diff options
context:
space:
mode:
authorSuzuki K. Poulose <suzuki.poulose@arm.com>2015-03-18 08:24:38 -0400
committerWill Deacon <will.deacon@arm.com>2015-03-27 09:44:15 -0400
commitf6b9e83ce05e362f4190cf2b4281d85cd094e541 (patch)
tree4ac34422b3914cb2ac9a82c1c185db6d6c62ac37 /drivers/bus
parentb1862199be6098855b598b69f5098d2fb4cecfcb (diff)
arm-cci: Rearrange code for splitting PMU vs driver code
No functional changes, only code re-arrangements for easier split of the PMU code vs low level driver code. Extracts the port handling code to cci_probe_ports(). Tested-by: Sudeep Holla <sudeep.holla@arm.com> Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org> Acked-by: Punit Agrawal <punit.agrawal@arm.com> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/bus')
-rw-r--r--drivers/bus/arm-cci.c326
1 files changed, 163 insertions, 163 deletions
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index 68ef6f2aa24d..5d29ec34078e 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -29,42 +29,29 @@
29#include <asm/cacheflush.h> 29#include <asm/cacheflush.h>
30#include <asm/smp_plat.h> 30#include <asm/smp_plat.h>
31 31
32#define DRIVER_NAME "CCI-400" 32static void __iomem *cci_ctrl_base;
33#define DRIVER_NAME_PMU DRIVER_NAME " PMU" 33static unsigned long cci_ctrl_phys;
34
35#define CCI_PORT_CTRL 0x0
36#define CCI_CTRL_STATUS 0xc
37
38#define CCI_ENABLE_SNOOP_REQ 0x1
39#define CCI_ENABLE_DVM_REQ 0x2
40#define CCI_ENABLE_REQ (CCI_ENABLE_SNOOP_REQ | CCI_ENABLE_DVM_REQ)
41 34
42struct cci_nb_ports { 35struct cci_nb_ports {
43 unsigned int nb_ace; 36 unsigned int nb_ace;
44 unsigned int nb_ace_lite; 37 unsigned int nb_ace_lite;
45}; 38};
46 39
47enum cci_ace_port_type { 40static const struct cci_nb_ports cci400_ports = {
48 ACE_INVALID_PORT = 0x0, 41 .nb_ace = 2,
49 ACE_PORT, 42 .nb_ace_lite = 3
50 ACE_LITE_PORT,
51}; 43};
52 44
53struct cci_ace_port { 45static const struct of_device_id arm_cci_matches[] = {
54 void __iomem *base; 46 {.compatible = "arm,cci-400", .data = &cci400_ports },
55 unsigned long phys; 47 {},
56 enum cci_ace_port_type type;
57 struct device_node *dn;
58}; 48};
59 49
60static struct cci_ace_port *ports;
61static unsigned int nb_cci_ports;
62
63static void __iomem *cci_ctrl_base;
64static unsigned long cci_ctrl_phys;
65
66#ifdef CONFIG_HW_PERF_EVENTS 50#ifdef CONFIG_HW_PERF_EVENTS
67 51
52#define DRIVER_NAME "CCI-400"
53#define DRIVER_NAME_PMU DRIVER_NAME " PMU"
54
68#define CCI_PMCR 0x0100 55#define CCI_PMCR 0x0100
69#define CCI_PID2 0x0fe8 56#define CCI_PID2 0x0fe8
70 57
@@ -75,6 +62,47 @@ static unsigned long cci_ctrl_phys;
75#define CCI_PID2_REV_MASK 0xf0 62#define CCI_PID2_REV_MASK 0xf0
76#define CCI_PID2_REV_SHIFT 4 63#define CCI_PID2_REV_SHIFT 4
77 64
65#define CCI_PMU_EVT_SEL 0x000
66#define CCI_PMU_CNTR 0x004
67#define CCI_PMU_CNTR_CTRL 0x008
68#define CCI_PMU_OVRFLW 0x00c
69
70#define CCI_PMU_OVRFLW_FLAG 1
71
72#define CCI_PMU_CNTR_BASE(idx) ((idx) * SZ_4K)
73
74#define CCI_PMU_CNTR_MASK ((1ULL << 32) -1)
75
76#define CCI_PMU_EVENT_MASK 0xff
77#define CCI_PMU_EVENT_SOURCE(event) ((event >> 5) & 0x7)
78#define CCI_PMU_EVENT_CODE(event) (event & 0x1f)
79
80#define CCI_PMU_MAX_HW_EVENTS 5 /* CCI PMU has 4 counters + 1 cycle counter */
81
82struct cci_pmu_hw_events {
83 struct perf_event *events[CCI_PMU_MAX_HW_EVENTS];
84 unsigned long used_mask[BITS_TO_LONGS(CCI_PMU_MAX_HW_EVENTS)];
85 raw_spinlock_t pmu_lock;
86};
87
88struct cci_pmu {
89 void __iomem *base;
90 struct pmu pmu;
91 int nr_irqs;
92 int irqs[CCI_PMU_MAX_HW_EVENTS];
93 unsigned long active_irqs;
94 struct pmu_port_event_ranges *port_ranges;
95 struct cci_pmu_hw_events hw_events;
96 struct platform_device *plat_device;
97 int num_events;
98 atomic_t active_events;
99 struct mutex reserve_mutex;
100 cpumask_t cpus;
101};
102static struct cci_pmu *pmu;
103
104#define to_cci_pmu(c) (container_of(c, struct cci_pmu, pmu))
105
78/* Port ids */ 106/* Port ids */
79#define CCI_PORT_S0 0 107#define CCI_PORT_S0 0
80#define CCI_PORT_S1 1 108#define CCI_PORT_S1 1
@@ -89,17 +117,6 @@ static unsigned long cci_ctrl_phys;
89#define CCI_REV_R1 1 117#define CCI_REV_R1 1
90#define CCI_REV_R1_PX 5 118#define CCI_REV_R1_PX 5
91 119
92#define CCI_PMU_EVT_SEL 0x000
93#define CCI_PMU_CNTR 0x004
94#define CCI_PMU_CNTR_CTRL 0x008
95#define CCI_PMU_OVRFLW 0x00c
96
97#define CCI_PMU_OVRFLW_FLAG 1
98
99#define CCI_PMU_CNTR_BASE(idx) ((idx) * SZ_4K)
100
101#define CCI_PMU_CNTR_MASK ((1ULL << 32) -1)
102
103/* 120/*
104 * Instead of an event id to monitor CCI cycles, a dedicated counter is 121 * Instead of an event id to monitor CCI cycles, a dedicated counter is
105 * provided. Use 0xff to represent CCI cycles and hope that no future revisions 122 * provided. Use 0xff to represent CCI cycles and hope that no future revisions
@@ -109,12 +126,6 @@ enum cci400_perf_events {
109 CCI_PMU_CYCLES = 0xff 126 CCI_PMU_CYCLES = 0xff
110}; 127};
111 128
112#define CCI_PMU_EVENT_MASK 0xff
113#define CCI_PMU_EVENT_SOURCE(event) ((event >> 5) & 0x7)
114#define CCI_PMU_EVENT_CODE(event) (event & 0x1f)
115
116#define CCI_PMU_MAX_HW_EVENTS 5 /* CCI PMU has 4 counters + 1 cycle counter */
117
118#define CCI_PMU_CYCLE_CNTR_IDX 0 129#define CCI_PMU_CYCLE_CNTR_IDX 0
119#define CCI_PMU_CNTR0_IDX 1 130#define CCI_PMU_CNTR0_IDX 1
120#define CCI_PMU_CNTR_LAST(cci_pmu) (CCI_PMU_CYCLE_CNTR_IDX + cci_pmu->num_events - 1) 131#define CCI_PMU_CNTR_LAST(cci_pmu) (CCI_PMU_CYCLE_CNTR_IDX + cci_pmu->num_events - 1)
@@ -172,60 +183,6 @@ static char *const pmu_names[] = {
172 [CCI_REV_R1] = "CCI_400_r1", 183 [CCI_REV_R1] = "CCI_400_r1",
173}; 184};
174 185
175struct cci_pmu_hw_events {
176 struct perf_event *events[CCI_PMU_MAX_HW_EVENTS];
177 unsigned long used_mask[BITS_TO_LONGS(CCI_PMU_MAX_HW_EVENTS)];
178 raw_spinlock_t pmu_lock;
179};
180
181struct cci_pmu {
182 void __iomem *base;
183 struct pmu pmu;
184 int nr_irqs;
185 int irqs[CCI_PMU_MAX_HW_EVENTS];
186 unsigned long active_irqs;
187 struct pmu_port_event_ranges *port_ranges;
188 struct cci_pmu_hw_events hw_events;
189 struct platform_device *plat_device;
190 int num_events;
191 atomic_t active_events;
192 struct mutex reserve_mutex;
193 cpumask_t cpus;
194};
195static struct cci_pmu *pmu;
196
197#define to_cci_pmu(c) (container_of(c, struct cci_pmu, pmu))
198
199static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
200{
201 int i;
202
203 for (i = 0; i < nr_irqs; i++)
204 if (irq == irqs[i])
205 return true;
206
207 return false;
208}
209
210static int probe_cci_revision(void)
211{
212 int rev;
213 rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK;
214 rev >>= CCI_PID2_REV_SHIFT;
215
216 if (rev < CCI_REV_R1_PX)
217 return CCI_REV_R0;
218 else
219 return CCI_REV_R1;
220}
221
222static struct pmu_port_event_ranges *port_range_by_rev(void)
223{
224 int rev = probe_cci_revision();
225
226 return &port_event_range[rev];
227}
228
229static int pmu_is_valid_slave_event(u8 ev_code) 186static int pmu_is_valid_slave_event(u8 ev_code)
230{ 187{
231 return pmu->port_ranges->slave_min <= ev_code && 188 return pmu->port_ranges->slave_min <= ev_code &&
@@ -265,6 +222,25 @@ static int pmu_validate_hw_event(u8 hw_event)
265 return -ENOENT; 222 return -ENOENT;
266} 223}
267 224
225static int probe_cci_revision(void)
226{
227 int rev;
228 rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK;
229 rev >>= CCI_PID2_REV_SHIFT;
230
231 if (rev < CCI_REV_R1_PX)
232 return CCI_REV_R0;
233 else
234 return CCI_REV_R1;
235}
236
237static struct pmu_port_event_ranges *port_range_by_rev(void)
238{
239 int rev = probe_cci_revision();
240
241 return &port_event_range[rev];
242}
243
268static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx) 244static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
269{ 245{
270 return CCI_PMU_CYCLE_CNTR_IDX <= idx && 246 return CCI_PMU_CYCLE_CNTR_IDX <= idx &&
@@ -902,6 +878,17 @@ static const struct of_device_id arm_cci_pmu_matches[] = {
902 {}, 878 {},
903}; 879};
904 880
881static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
882{
883 int i;
884
885 for (i = 0; i < nr_irqs; i++)
886 if (irq == irqs[i])
887 return true;
888
889 return false;
890}
891
905static int cci_pmu_probe(struct platform_device *pdev) 892static int cci_pmu_probe(struct platform_device *pdev)
906{ 893{
907 struct resource *res; 894 struct resource *res;
@@ -972,8 +959,65 @@ static int cci_platform_probe(struct platform_device *pdev)
972 return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); 959 return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
973} 960}
974 961
962static struct platform_driver cci_pmu_driver = {
963 .driver = {
964 .name = DRIVER_NAME_PMU,
965 .of_match_table = arm_cci_pmu_matches,
966 },
967 .probe = cci_pmu_probe,
968};
969
970static struct platform_driver cci_platform_driver = {
971 .driver = {
972 .name = DRIVER_NAME,
973 .of_match_table = arm_cci_matches,
974 },
975 .probe = cci_platform_probe,
976};
977
978static int __init cci_platform_init(void)
979{
980 int ret;
981
982 ret = platform_driver_register(&cci_pmu_driver);
983 if (ret)
984 return ret;
985
986 return platform_driver_register(&cci_platform_driver);
987}
988
989#else /* !CONFIG_HW_PERF_EVENTS */
990
991static int __init cci_platform_init(void)
992{
993 return 0;
994}
995
975#endif /* CONFIG_HW_PERF_EVENTS */ 996#endif /* CONFIG_HW_PERF_EVENTS */
976 997
998#define CCI_PORT_CTRL 0x0
999#define CCI_CTRL_STATUS 0xc
1000
1001#define CCI_ENABLE_SNOOP_REQ 0x1
1002#define CCI_ENABLE_DVM_REQ 0x2
1003#define CCI_ENABLE_REQ (CCI_ENABLE_SNOOP_REQ | CCI_ENABLE_DVM_REQ)
1004
1005enum cci_ace_port_type {
1006 ACE_INVALID_PORT = 0x0,
1007 ACE_PORT,
1008 ACE_LITE_PORT,
1009};
1010
1011struct cci_ace_port {
1012 void __iomem *base;
1013 unsigned long phys;
1014 enum cci_ace_port_type type;
1015 struct device_node *dn;
1016};
1017
1018static struct cci_ace_port *ports;
1019static unsigned int nb_cci_ports;
1020
977struct cpu_port { 1021struct cpu_port {
978 u64 mpidr; 1022 u64 mpidr;
979 u32 port; 1023 u32 port;
@@ -1293,36 +1337,20 @@ int notrace __cci_control_port_by_index(u32 port, bool enable)
1293} 1337}
1294EXPORT_SYMBOL_GPL(__cci_control_port_by_index); 1338EXPORT_SYMBOL_GPL(__cci_control_port_by_index);
1295 1339
1296static const struct cci_nb_ports cci400_ports = {
1297 .nb_ace = 2,
1298 .nb_ace_lite = 3
1299};
1300
1301static const struct of_device_id arm_cci_matches[] = {
1302 {.compatible = "arm,cci-400", .data = &cci400_ports },
1303 {},
1304};
1305
1306static const struct of_device_id arm_cci_ctrl_if_matches[] = { 1340static const struct of_device_id arm_cci_ctrl_if_matches[] = {
1307 {.compatible = "arm,cci-400-ctrl-if", }, 1341 {.compatible = "arm,cci-400-ctrl-if", },
1308 {}, 1342 {},
1309}; 1343};
1310 1344
1311static int cci_probe(void) 1345static int cci_probe_ports(struct device_node *np)
1312{ 1346{
1313 struct cci_nb_ports const *cci_config; 1347 struct cci_nb_ports const *cci_config;
1314 int ret, i, nb_ace = 0, nb_ace_lite = 0; 1348 int ret, i, nb_ace = 0, nb_ace_lite = 0;
1315 struct device_node *np, *cp; 1349 struct device_node *cp;
1316 struct resource res; 1350 struct resource res;
1317 const char *match_str; 1351 const char *match_str;
1318 bool is_ace; 1352 bool is_ace;
1319 1353
1320 np = of_find_matching_node(NULL, arm_cci_matches);
1321 if (!np)
1322 return -ENODEV;
1323
1324 if (!of_device_is_available(np))
1325 return -ENODEV;
1326 1354
1327 cci_config = of_match_node(arm_cci_matches, np)->data; 1355 cci_config = of_match_node(arm_cci_matches, np)->data;
1328 if (!cci_config) 1356 if (!cci_config)
@@ -1334,17 +1362,6 @@ static int cci_probe(void)
1334 if (!ports) 1362 if (!ports)
1335 return -ENOMEM; 1363 return -ENOMEM;
1336 1364
1337 ret = of_address_to_resource(np, 0, &res);
1338 if (!ret) {
1339 cci_ctrl_base = ioremap(res.start, resource_size(&res));
1340 cci_ctrl_phys = res.start;
1341 }
1342 if (ret || !cci_ctrl_base) {
1343 WARN(1, "unable to ioremap CCI ctrl\n");
1344 ret = -ENXIO;
1345 goto memalloc_err;
1346 }
1347
1348 for_each_child_of_node(np, cp) { 1365 for_each_child_of_node(np, cp) {
1349 if (!of_match_node(arm_cci_ctrl_if_matches, cp)) 1366 if (!of_match_node(arm_cci_ctrl_if_matches, cp))
1350 continue; 1367 continue;
@@ -1404,12 +1421,31 @@ static int cci_probe(void)
1404 sync_cache_w(&cpu_port); 1421 sync_cache_w(&cpu_port);
1405 __sync_cache_range_w(ports, sizeof(*ports) * nb_cci_ports); 1422 __sync_cache_range_w(ports, sizeof(*ports) * nb_cci_ports);
1406 pr_info("ARM CCI driver probed\n"); 1423 pr_info("ARM CCI driver probed\n");
1424
1407 return 0; 1425 return 0;
1426}
1408 1427
1409memalloc_err: 1428static int cci_probe(void)
1429{
1430 int ret;
1431 struct device_node *np;
1432 struct resource res;
1410 1433
1411 kfree(ports); 1434 np = of_find_matching_node(NULL, arm_cci_matches);
1412 return ret; 1435 if(!np || !of_device_is_available(np))
1436 return -ENODEV;
1437
1438 ret = of_address_to_resource(np, 0, &res);
1439 if (!ret) {
1440 cci_ctrl_base = ioremap(res.start, resource_size(&res));
1441 cci_ctrl_phys = res.start;
1442 }
1443 if (ret || !cci_ctrl_base) {
1444 WARN(1, "unable to ioremap CCI ctrl\n");
1445 return -ENXIO;
1446 }
1447
1448 return cci_probe_ports(np);
1413} 1449}
1414 1450
1415static int cci_init_status = -EAGAIN; 1451static int cci_init_status = -EAGAIN;
@@ -1427,42 +1463,6 @@ static int cci_init(void)
1427 return cci_init_status; 1463 return cci_init_status;
1428} 1464}
1429 1465
1430#ifdef CONFIG_HW_PERF_EVENTS
1431static struct platform_driver cci_pmu_driver = {
1432 .driver = {
1433 .name = DRIVER_NAME_PMU,
1434 .of_match_table = arm_cci_pmu_matches,
1435 },
1436 .probe = cci_pmu_probe,
1437};
1438
1439static struct platform_driver cci_platform_driver = {
1440 .driver = {
1441 .name = DRIVER_NAME,
1442 .of_match_table = arm_cci_matches,
1443 },
1444 .probe = cci_platform_probe,
1445};
1446
1447static int __init cci_platform_init(void)
1448{
1449 int ret;
1450
1451 ret = platform_driver_register(&cci_pmu_driver);
1452 if (ret)
1453 return ret;
1454
1455 return platform_driver_register(&cci_platform_driver);
1456}
1457
1458#else
1459
1460static int __init cci_platform_init(void)
1461{
1462 return 0;
1463}
1464
1465#endif
1466/* 1466/*
1467 * To sort out early init calls ordering a helper function is provided to 1467 * To sort out early init calls ordering a helper function is provided to
1468 * check if the CCI driver has beed initialized. Function check if the driver 1468 * check if the CCI driver has beed initialized. Function check if the driver