2020#include <linux/of_platform.h>
2121#include <linux/platform_device.h>
2222
23+ #include "irq-msi-lib.h"
24+
2325#include <dt-bindings/interrupt-controller/mvebu-icu.h>
2426
2527/* ICU registers */
@@ -60,14 +62,52 @@ struct mvebu_icu_msi_data {
6062 const struct mvebu_icu_subset_data * subset_data ;
6163};
6264
63- struct mvebu_icu_irq_data {
64- struct mvebu_icu * icu ;
65- unsigned int icu_group ;
66- unsigned int type ;
67- };
68-
6965static DEFINE_STATIC_KEY_FALSE (legacy_bindings );
7066
67+ static int mvebu_icu_translate (struct irq_domain * d , struct irq_fwspec * fwspec ,
68+ unsigned long * hwirq , unsigned int * type )
69+ {
70+ unsigned int param_count = static_branch_unlikely (& legacy_bindings ) ? 3 : 2 ;
71+ struct mvebu_icu_msi_data * msi_data = d -> host_data ;
72+ struct mvebu_icu * icu = msi_data -> icu ;
73+
74+ /* Check the count of the parameters in dt */
75+ if (WARN_ON (fwspec -> param_count != param_count )) {
76+ dev_err (icu -> dev , "wrong ICU parameter count %d\n" ,
77+ fwspec -> param_count );
78+ return - EINVAL ;
79+ }
80+
81+ if (static_branch_unlikely (& legacy_bindings )) {
82+ * hwirq = fwspec -> param [1 ];
83+ * type = fwspec -> param [2 ] & IRQ_TYPE_SENSE_MASK ;
84+ if (fwspec -> param [0 ] != ICU_GRP_NSR ) {
85+ dev_err (icu -> dev , "wrong ICU group type %x\n" ,
86+ fwspec -> param [0 ]);
87+ return - EINVAL ;
88+ }
89+ } else {
90+ * hwirq = fwspec -> param [0 ];
91+ * type = fwspec -> param [1 ] & IRQ_TYPE_SENSE_MASK ;
92+
93+ /*
94+ * The ICU receives level interrupts. While the NSR are also
95+ * level interrupts, SEI are edge interrupts. Force the type
96+ * here in this case. Please note that this makes the interrupt
97+ * handling unreliable.
98+ */
99+ if (msi_data -> subset_data -> icu_group == ICU_GRP_SEI )
100+ * type = IRQ_TYPE_EDGE_RISING ;
101+ }
102+
103+ if (* hwirq >= ICU_MAX_IRQS ) {
104+ dev_err (icu -> dev , "invalid interrupt number %ld\n" , * hwirq );
105+ return - EINVAL ;
106+ }
107+
108+ return 0 ;
109+ }
110+
71111static void mvebu_icu_init (struct mvebu_icu * icu ,
72112 struct mvebu_icu_msi_data * msi_data ,
73113 struct msi_msg * msg )
@@ -89,6 +129,14 @@ static void mvebu_icu_init(struct mvebu_icu *icu,
89129 writel_relaxed (msg [1 ].address_lo , icu -> base + subset -> offset_clr_al );
90130}
91131
132+ /* Start of area to be removed once all parent chips provide MSI parent */
133+
134+ struct mvebu_icu_irq_data {
135+ struct mvebu_icu * icu ;
136+ unsigned int icu_group ;
137+ unsigned int type ;
138+ };
139+
92140static void mvebu_icu_write_msg (struct msi_desc * desc , struct msi_msg * msg )
93141{
94142 struct irq_data * d = irq_get_irq_data (desc -> irq );
@@ -269,6 +317,109 @@ static const struct irq_domain_ops mvebu_icu_domain_ops = {
269317 .free = mvebu_icu_irq_domain_free ,
270318};
271319
320+ /* End of removal area */
321+
322+ static int mvebu_icu_msi_init (struct irq_domain * domain , struct msi_domain_info * info ,
323+ unsigned int virq , irq_hw_number_t hwirq , msi_alloc_info_t * arg )
324+ {
325+ irq_domain_set_hwirq_and_chip (domain , virq , hwirq , info -> chip , info -> chip_data );
326+ return irq_set_irqchip_state (virq , IRQCHIP_STATE_PENDING , false);
327+ }
328+
329+ static void mvebu_icu_set_desc (msi_alloc_info_t * arg , struct msi_desc * desc )
330+ {
331+ arg -> desc = desc ;
332+ arg -> hwirq = (u32 )desc -> data .icookie .value ;
333+ }
334+
335+ static void mvebu_icu_write_msi_msg (struct irq_data * d , struct msi_msg * msg )
336+ {
337+ struct mvebu_icu_msi_data * msi_data = d -> chip_data ;
338+ unsigned int icu_group = msi_data -> subset_data -> icu_group ;
339+ struct msi_desc * desc = irq_data_get_msi_desc (d );
340+ struct mvebu_icu * icu = msi_data -> icu ;
341+ unsigned int type ;
342+ u32 icu_int ;
343+
344+ if (msg -> address_lo || msg -> address_hi ) {
345+ /* One off initialization per domain */
346+ mvebu_icu_init (icu , msi_data , msg );
347+ /* Configure the ICU with irq number & type */
348+ icu_int = msg -> data | ICU_INT_ENABLE ;
349+ type = (unsigned int )(desc -> data .icookie .value >> 32 );
350+ if (type & IRQ_TYPE_EDGE_RISING )
351+ icu_int |= ICU_IS_EDGE ;
352+ icu_int |= icu_group << ICU_GROUP_SHIFT ;
353+ } else {
354+ /* De-configure the ICU */
355+ icu_int = 0 ;
356+ }
357+
358+ writel_relaxed (icu_int , icu -> base + ICU_INT_CFG (d -> hwirq ));
359+
360+ /*
361+ * The SATA unit has 2 ports, and a dedicated ICU entry per
362+ * port. The ahci sata driver supports only one irq interrupt
363+ * per SATA unit. To solve this conflict, we configure the 2
364+ * SATA wired interrupts in the south bridge into 1 GIC
365+ * interrupt in the north bridge. Even if only a single port
366+ * is enabled, if sata node is enabled, both interrupts are
367+ * configured (regardless of which port is actually in use).
368+ */
369+ if (d -> hwirq == ICU_SATA0_ICU_ID || d -> hwirq == ICU_SATA1_ICU_ID ) {
370+ writel_relaxed (icu_int , icu -> base + ICU_INT_CFG (ICU_SATA0_ICU_ID ));
371+ writel_relaxed (icu_int , icu -> base + ICU_INT_CFG (ICU_SATA1_ICU_ID ));
372+ }
373+ }
374+
375+ static const struct msi_domain_template mvebu_icu_nsr_msi_template = {
376+ .chip = {
377+ .name = "ICU-NSR" ,
378+ .irq_mask = irq_chip_mask_parent ,
379+ .irq_unmask = irq_chip_unmask_parent ,
380+ .irq_eoi = irq_chip_eoi_parent ,
381+ .irq_set_type = irq_chip_set_type_parent ,
382+ .irq_write_msi_msg = mvebu_icu_write_msi_msg ,
383+ .flags = IRQCHIP_SUPPORTS_LEVEL_MSI ,
384+ },
385+
386+ .ops = {
387+ .msi_translate = mvebu_icu_translate ,
388+ .msi_init = mvebu_icu_msi_init ,
389+ .set_desc = mvebu_icu_set_desc ,
390+ },
391+
392+ .info = {
393+ .bus_token = DOMAIN_BUS_WIRED_TO_MSI ,
394+ .flags = MSI_FLAG_LEVEL_CAPABLE |
395+ MSI_FLAG_USE_DEV_FWNODE ,
396+ },
397+ };
398+
399+ static const struct msi_domain_template mvebu_icu_sei_msi_template = {
400+ .chip = {
401+ .name = "ICU-SEI" ,
402+ .irq_mask = irq_chip_mask_parent ,
403+ .irq_unmask = irq_chip_unmask_parent ,
404+ .irq_ack = irq_chip_ack_parent ,
405+ .irq_set_type = irq_chip_set_type_parent ,
406+ .irq_write_msi_msg = mvebu_icu_write_msi_msg ,
407+ .flags = IRQCHIP_SUPPORTS_LEVEL_MSI ,
408+ },
409+
410+ .ops = {
411+ .msi_translate = mvebu_icu_translate ,
412+ .msi_init = mvebu_icu_msi_init ,
413+ .set_desc = mvebu_icu_set_desc ,
414+ },
415+
416+ .info = {
417+ .bus_token = DOMAIN_BUS_WIRED_TO_MSI ,
418+ .flags = MSI_FLAG_LEVEL_CAPABLE |
419+ MSI_FLAG_USE_DEV_FWNODE ,
420+ },
421+ };
422+
272423static const struct mvebu_icu_subset_data mvebu_icu_nsr_subset_data = {
273424 .icu_group = ICU_GRP_NSR ,
274425 .offset_set_ah = ICU_SETSPI_NSR_AH ,
@@ -298,7 +449,6 @@ static const struct of_device_id mvebu_icu_subset_of_match[] = {
298449static int mvebu_icu_subset_probe (struct platform_device * pdev )
299450{
300451 struct mvebu_icu_msi_data * msi_data ;
301- struct device_node * msi_parent_dn ;
302452 struct device * dev = & pdev -> dev ;
303453 struct irq_domain * irq_domain ;
304454
@@ -314,15 +464,24 @@ static int mvebu_icu_subset_probe(struct platform_device *pdev)
314464 msi_data -> subset_data = of_device_get_match_data (dev );
315465 }
316466
317- dev -> msi .domain = of_msi_get_domain (dev , dev -> of_node ,
318- DOMAIN_BUS_PLATFORM_MSI );
467+ dev -> msi .domain = of_msi_get_domain (dev , dev -> of_node , DOMAIN_BUS_PLATFORM_MSI );
319468 if (!dev -> msi .domain )
320469 return - EPROBE_DEFER ;
321470
322- msi_parent_dn = irq_domain_get_of_node (dev -> msi .domain );
323- if (!msi_parent_dn )
471+ if (!irq_domain_get_of_node (dev -> msi .domain ))
324472 return - ENODEV ;
325473
474+ if (irq_domain_is_msi_parent (dev -> msi .domain )) {
475+ bool sei = msi_data -> subset_data -> icu_group == ICU_GRP_SEI ;
476+ const struct msi_domain_template * tmpl ;
477+
478+ tmpl = sei ? & mvebu_icu_sei_msi_template : & mvebu_icu_nsr_msi_template ;
479+
480+ if (!msi_create_device_irq_domain (dev , MSI_DEFAULT_DOMAIN , tmpl ,
481+ ICU_MAX_IRQS , NULL , msi_data ))
482+ return - ENOMEM ;
483+ }
484+
326485 irq_domain = platform_msi_create_device_tree_domain (dev , ICU_MAX_IRQS ,
327486 mvebu_icu_write_msg ,
328487 & mvebu_icu_domain_ops ,
0 commit comments