aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-02-26 11:28:11 -0500
committerDavid S. Miller <davem@davemloft.net>2018-02-26 11:28:11 -0500
commit25ab47ef48bceeac9371cb291199244484932857 (patch)
tree86f5d8d2257aecf04b682028d9851d7fd0c62eb3
parent65b53bfd497b052277f89afb3839ace38190974c (diff)
parentf8c193ca1f7d3b69c031970815d14e09de396ee8 (diff)
Merge branch 'mv88e6xxx-Poll-when-no-interrupt-defined'
Andrew Lunn says: ==================== mv88e6xxx: Poll when no interrupt defined Not all boards using the mv88e6xxx switches have the interrupt output connected to a GPIO. On these boards phylib has to poll the PHYs, rather than use interrupts. Have the driver poll the interrupt status register, which is more efficient than having phylib do it. And it enables other switch interrupts to be services. The Armada 370RD is such a board without a interrupt GPIO. Now that interrupts work, wire up the PHYs to make use if them. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/arm/boot/dts/armada-370-rd.dts32
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c146
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.h3
3 files changed, 138 insertions, 43 deletions
diff --git a/arch/arm/boot/dts/armada-370-rd.dts b/arch/arm/boot/dts/armada-370-rd.dts
index 8b2fa9a49967..c28afb242393 100644
--- a/arch/arm/boot/dts/armada-370-rd.dts
+++ b/arch/arm/boot/dts/armada-370-rd.dts
@@ -56,6 +56,7 @@
56 56
57/dts-v1/; 57/dts-v1/;
58#include <dt-bindings/input/input.h> 58#include <dt-bindings/input/input.h>
59#include <dt-bindings/interrupt-controller/irq.h>
59#include <dt-bindings/gpio/gpio.h> 60#include <dt-bindings/gpio/gpio.h>
60#include "armada-370.dtsi" 61#include "armada-370.dtsi"
61 62
@@ -243,6 +244,8 @@
243 #address-cells = <1>; 244 #address-cells = <1>;
244 #size-cells = <0>; 245 #size-cells = <0>;
245 reg = <0x10>; 246 reg = <0x10>;
247 interrupt-controller;
248 #interrupt-cells = <2>;
246 249
247 ports { 250 ports {
248 #address-cells = <1>; 251 #address-cells = <1>;
@@ -278,6 +281,35 @@
278 }; 281 };
279 }; 282 };
280 }; 283 };
284
285 mdio {
286 #address-cells = <1>;
287 #size-cells = <0>;
288
289 switchphy0: switchphy@0 {
290 reg = <0>;
291 interrupt-parent = <&switch>;
292 interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
293 };
294
295 switchphy1: switchphy@1 {
296 reg = <1>;
297 interrupt-parent = <&switch>;
298 interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
299 };
300
301 switchphy2: switchphy@2 {
302 reg = <2>;
303 interrupt-parent = <&switch>;
304 interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
305 };
306
307 switchphy3: switchphy@3 {
308 reg = <3>;
309 interrupt-parent = <&switch>;
310 interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
311 };
312 };
281 }; 313 };
282}; 314};
283 315
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index e1b5c5c66fce..24486f96dd39 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -253,9 +253,8 @@ static void mv88e6xxx_g1_irq_unmask(struct irq_data *d)
253 chip->g1_irq.masked &= ~(1 << n); 253 chip->g1_irq.masked &= ~(1 << n);
254} 254}
255 255
256static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id) 256static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
257{ 257{
258 struct mv88e6xxx_chip *chip = dev_id;
259 unsigned int nhandled = 0; 258 unsigned int nhandled = 0;
260 unsigned int sub_irq; 259 unsigned int sub_irq;
261 unsigned int n; 260 unsigned int n;
@@ -280,6 +279,13 @@ out:
280 return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); 279 return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
281} 280}
282 281
282static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id)
283{
284 struct mv88e6xxx_chip *chip = dev_id;
285
286 return mv88e6xxx_g1_irq_thread_work(chip);
287}
288
283static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d) 289static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d)
284{ 290{
285 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); 291 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
@@ -335,7 +341,7 @@ static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = {
335 .xlate = irq_domain_xlate_twocell, 341 .xlate = irq_domain_xlate_twocell,
336}; 342};
337 343
338static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip) 344static void mv88e6xxx_g1_irq_free_common(struct mv88e6xxx_chip *chip)
339{ 345{
340 int irq, virq; 346 int irq, virq;
341 u16 mask; 347 u16 mask;
@@ -344,8 +350,6 @@ static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)
344 mask &= ~GENMASK(chip->g1_irq.nirqs, 0); 350 mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
345 mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask); 351 mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, mask);
346 352
347 free_irq(chip->irq, chip);
348
349 for (irq = 0; irq < chip->g1_irq.nirqs; irq++) { 353 for (irq = 0; irq < chip->g1_irq.nirqs; irq++) {
350 virq = irq_find_mapping(chip->g1_irq.domain, irq); 354 virq = irq_find_mapping(chip->g1_irq.domain, irq);
351 irq_dispose_mapping(virq); 355 irq_dispose_mapping(virq);
@@ -354,7 +358,14 @@ static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)
354 irq_domain_remove(chip->g1_irq.domain); 358 irq_domain_remove(chip->g1_irq.domain);
355} 359}
356 360
357static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip) 361static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)
362{
363 mv88e6xxx_g1_irq_free(chip);
364
365 free_irq(chip->irq, chip);
366}
367
368static int mv88e6xxx_g1_irq_setup_common(struct mv88e6xxx_chip *chip)
358{ 369{
359 int err, irq, virq; 370 int err, irq, virq;
360 u16 reg, mask; 371 u16 reg, mask;
@@ -387,13 +398,6 @@ static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
387 if (err) 398 if (err)
388 goto out_disable; 399 goto out_disable;
389 400
390 err = request_threaded_irq(chip->irq, NULL,
391 mv88e6xxx_g1_irq_thread_fn,
392 IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
393 dev_name(chip->dev), chip);
394 if (err)
395 goto out_disable;
396
397 return 0; 401 return 0;
398 402
399out_disable: 403out_disable:
@@ -411,6 +415,62 @@ out_mapping:
411 return err; 415 return err;
412} 416}
413 417
418static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
419{
420 int err;
421
422 err = mv88e6xxx_g1_irq_setup_common(chip);
423 if (err)
424 return err;
425
426 err = request_threaded_irq(chip->irq, NULL,
427 mv88e6xxx_g1_irq_thread_fn,
428 IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
429 dev_name(chip->dev), chip);
430 if (err)
431 mv88e6xxx_g1_irq_free_common(chip);
432
433 return err;
434}
435
436static void mv88e6xxx_irq_poll(struct kthread_work *work)
437{
438 struct mv88e6xxx_chip *chip = container_of(work,
439 struct mv88e6xxx_chip,
440 irq_poll_work.work);
441 mv88e6xxx_g1_irq_thread_work(chip);
442
443 kthread_queue_delayed_work(chip->kworker, &chip->irq_poll_work,
444 msecs_to_jiffies(100));
445}
446
447static int mv88e6xxx_irq_poll_setup(struct mv88e6xxx_chip *chip)
448{
449 int err;
450
451 err = mv88e6xxx_g1_irq_setup_common(chip);
452 if (err)
453 return err;
454
455 kthread_init_delayed_work(&chip->irq_poll_work,
456 mv88e6xxx_irq_poll);
457
458 chip->kworker = kthread_create_worker(0, dev_name(chip->dev));
459 if (IS_ERR(chip->kworker))
460 return PTR_ERR(chip->kworker);
461
462 kthread_queue_delayed_work(chip->kworker, &chip->irq_poll_work,
463 msecs_to_jiffies(100));
464
465 return 0;
466}
467
468static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip)
469{
470 kthread_cancel_delayed_work_sync(&chip->irq_poll_work);
471 kthread_destroy_worker(chip->kworker);
472}
473
414int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask) 474int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask)
415{ 475{
416 int i; 476 int i;
@@ -4034,33 +4094,34 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
4034 goto out; 4094 goto out;
4035 } 4095 }
4036 4096
4037 if (chip->irq > 0) { 4097 /* Has to be performed before the MDIO bus is created, because
4038 /* Has to be performed before the MDIO bus is created, 4098 * the PHYs will link there interrupts to these interrupt
4039 * because the PHYs will link there interrupts to these 4099 * controllers
4040 * interrupt controllers 4100 */
4041 */ 4101 mutex_lock(&chip->reg_lock);
4042 mutex_lock(&chip->reg_lock); 4102 if (chip->irq > 0)
4043 err = mv88e6xxx_g1_irq_setup(chip); 4103 err = mv88e6xxx_g1_irq_setup(chip);
4044 mutex_unlock(&chip->reg_lock); 4104 else
4045 4105 err = mv88e6xxx_irq_poll_setup(chip);
4046 if (err) 4106 mutex_unlock(&chip->reg_lock);
4047 goto out;
4048
4049 if (chip->info->g2_irqs > 0) {
4050 err = mv88e6xxx_g2_irq_setup(chip);
4051 if (err)
4052 goto out_g1_irq;
4053 }
4054 4107
4055 err = mv88e6xxx_g1_atu_prob_irq_setup(chip); 4108 if (err)
4056 if (err) 4109 goto out;
4057 goto out_g2_irq;
4058 4110
4059 err = mv88e6xxx_g1_vtu_prob_irq_setup(chip); 4111 if (chip->info->g2_irqs > 0) {
4112 err = mv88e6xxx_g2_irq_setup(chip);
4060 if (err) 4113 if (err)
4061 goto out_g1_atu_prob_irq; 4114 goto out_g1_irq;
4062 } 4115 }
4063 4116
4117 err = mv88e6xxx_g1_atu_prob_irq_setup(chip);
4118 if (err)
4119 goto out_g2_irq;
4120
4121 err = mv88e6xxx_g1_vtu_prob_irq_setup(chip);
4122 if (err)
4123 goto out_g1_atu_prob_irq;
4124
4064 err = mv88e6xxx_mdios_register(chip, np); 4125 err = mv88e6xxx_mdios_register(chip, np);
4065 if (err) 4126 if (err)
4066 goto out_g1_vtu_prob_irq; 4127 goto out_g1_vtu_prob_irq;
@@ -4074,20 +4135,19 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
4074out_mdio: 4135out_mdio:
4075 mv88e6xxx_mdios_unregister(chip); 4136 mv88e6xxx_mdios_unregister(chip);
4076out_g1_vtu_prob_irq: 4137out_g1_vtu_prob_irq:
4077 if (chip->irq > 0) 4138 mv88e6xxx_g1_vtu_prob_irq_free(chip);
4078 mv88e6xxx_g1_vtu_prob_irq_free(chip);
4079out_g1_atu_prob_irq: 4139out_g1_atu_prob_irq:
4080 if (chip->irq > 0) 4140 mv88e6xxx_g1_atu_prob_irq_free(chip);
4081 mv88e6xxx_g1_atu_prob_irq_free(chip);
4082out_g2_irq: 4141out_g2_irq:
4083 if (chip->info->g2_irqs > 0 && chip->irq > 0) 4142 if (chip->info->g2_irqs > 0)
4084 mv88e6xxx_g2_irq_free(chip); 4143 mv88e6xxx_g2_irq_free(chip);
4085out_g1_irq: 4144out_g1_irq:
4086 if (chip->irq > 0) { 4145 mutex_lock(&chip->reg_lock);
4087 mutex_lock(&chip->reg_lock); 4146 if (chip->irq > 0)
4088 mv88e6xxx_g1_irq_free(chip); 4147 mv88e6xxx_g1_irq_free(chip);
4089 mutex_unlock(&chip->reg_lock); 4148 else
4090 } 4149 mv88e6xxx_irq_poll_free(chip);
4150 mutex_unlock(&chip->reg_lock);
4091out: 4151out:
4092 return err; 4152 return err;
4093} 4153}
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 97d7915f32c7..d6a1391dc268 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -15,6 +15,7 @@
15#include <linux/if_vlan.h> 15#include <linux/if_vlan.h>
16#include <linux/irq.h> 16#include <linux/irq.h>
17#include <linux/gpio/consumer.h> 17#include <linux/gpio/consumer.h>
18#include <linux/kthread.h>
18#include <linux/phy.h> 19#include <linux/phy.h>
19#include <linux/ptp_clock_kernel.h> 20#include <linux/ptp_clock_kernel.h>
20#include <linux/timecounter.h> 21#include <linux/timecounter.h>
@@ -245,6 +246,8 @@ struct mv88e6xxx_chip {
245 int watchdog_irq; 246 int watchdog_irq;
246 int atu_prob_irq; 247 int atu_prob_irq;
247 int vtu_prob_irq; 248 int vtu_prob_irq;
249 struct kthread_worker *kworker;
250 struct kthread_delayed_work irq_poll_work;
248 251
249 /* GPIO resources */ 252 /* GPIO resources */
250 u8 gpio_data[2]; 253 u8 gpio_data[2];