9
9
#include <linux/mutex.h>
10
10
#include <linux/module.h>
11
11
#include <linux/mod_devicetable.h>
12
+ #include <linux/platform_data/mlxreg.h>
12
13
#include <linux/slab.h>
13
14
14
15
#include "cmd.h"
51
52
#define MLXSW_I2C_TIMEOUT_MSECS 5000
52
53
#define MLXSW_I2C_MAX_DATA_SIZE 256
53
54
55
+ /* Driver can be initialized by kernel platform driver or from the user
56
+ * space. In the first case IRQ line number is passed through the platform
57
+ * data, otherwise default IRQ line is to be used. Default IRQ is relevant
58
+ * only for specific I2C slave address, allowing 3.4 MHz I2C path to the chip
59
+ * (special hardware feature for I2C acceleration).
60
+ */
61
+ #define MLXSW_I2C_DEFAULT_IRQ 17
62
+ #define MLXSW_FAST_I2C_SLAVE 0x37
63
+
54
64
/**
55
65
* struct mlxsw_i2c - device private data:
56
66
* @cmd: command attributes;
63
73
* @core: switch core pointer;
64
74
* @bus_info: bus info block;
65
75
* @block_size: maximum block size allowed to pass to under layer;
76
+ * @pdata: device platform data;
77
+ * @irq_work: interrupts work item;
78
+ * @irq: IRQ line number;
66
79
*/
67
80
struct mlxsw_i2c {
68
81
struct {
@@ -76,6 +89,9 @@ struct mlxsw_i2c {
76
89
struct mlxsw_core * core ;
77
90
struct mlxsw_bus_info bus_info ;
78
91
u16 block_size ;
92
+ struct mlxreg_core_hotplug_platform_data * pdata ;
93
+ struct work_struct irq_work ;
94
+ int irq ;
79
95
};
80
96
81
97
#define MLXSW_I2C_READ_MSG (_client , _addr_buf , _buf , _len ) { \
@@ -546,6 +562,67 @@ static void mlxsw_i2c_fini(void *bus_priv)
546
562
mlxsw_i2c -> core = NULL ;
547
563
}
548
564
565
+ static void mlxsw_i2c_work_handler (struct work_struct * work )
566
+ {
567
+ struct mlxsw_i2c * mlxsw_i2c ;
568
+
569
+ mlxsw_i2c = container_of (work , struct mlxsw_i2c , irq_work );
570
+ mlxsw_core_irq_event_handlers_call (mlxsw_i2c -> core );
571
+ }
572
+
573
+ static irqreturn_t mlxsw_i2c_irq_handler (int irq , void * dev )
574
+ {
575
+ struct mlxsw_i2c * mlxsw_i2c = dev ;
576
+
577
+ mlxsw_core_schedule_work (& mlxsw_i2c -> irq_work );
578
+
579
+ /* Interrupt handler shares IRQ line with 'main' interrupt handler.
580
+ * Return here IRQ_NONE, while main handler will return IRQ_HANDLED.
581
+ */
582
+ return IRQ_NONE ;
583
+ }
584
+
585
+ static int mlxsw_i2c_irq_init (struct mlxsw_i2c * mlxsw_i2c , u8 addr )
586
+ {
587
+ int err ;
588
+
589
+ /* Initialize interrupt handler if system hotplug driver is reachable,
590
+ * otherwise interrupt line is not enabled and interrupts will not be
591
+ * raised to CPU. Also request_irq() call will be not valid.
592
+ */
593
+ if (!IS_REACHABLE (CONFIG_MLXREG_HOTPLUG ))
594
+ return 0 ;
595
+
596
+ /* Set default interrupt line. */
597
+ if (mlxsw_i2c -> pdata && mlxsw_i2c -> pdata -> irq )
598
+ mlxsw_i2c -> irq = mlxsw_i2c -> pdata -> irq ;
599
+ else if (addr == MLXSW_FAST_I2C_SLAVE )
600
+ mlxsw_i2c -> irq = MLXSW_I2C_DEFAULT_IRQ ;
601
+
602
+ if (!mlxsw_i2c -> irq )
603
+ return 0 ;
604
+
605
+ INIT_WORK (& mlxsw_i2c -> irq_work , mlxsw_i2c_work_handler );
606
+ err = request_irq (mlxsw_i2c -> irq , mlxsw_i2c_irq_handler ,
607
+ IRQF_TRIGGER_FALLING | IRQF_SHARED , "mlxsw-i2c" ,
608
+ mlxsw_i2c );
609
+ if (err ) {
610
+ dev_err (mlxsw_i2c -> bus_info .dev , "Failed to request irq: %d\n" ,
611
+ err );
612
+ return err ;
613
+ }
614
+
615
+ return 0 ;
616
+ }
617
+
618
+ static void mlxsw_i2c_irq_fini (struct mlxsw_i2c * mlxsw_i2c )
619
+ {
620
+ if (!IS_REACHABLE (CONFIG_MLXREG_HOTPLUG ) || !mlxsw_i2c -> irq )
621
+ return ;
622
+ cancel_work_sync (& mlxsw_i2c -> irq_work );
623
+ free_irq (mlxsw_i2c -> irq , mlxsw_i2c );
624
+ }
625
+
549
626
static const struct mlxsw_bus mlxsw_i2c_bus = {
550
627
.kind = "i2c" ,
551
628
.init = mlxsw_i2c_init ,
@@ -638,17 +715,24 @@ static int mlxsw_i2c_probe(struct i2c_client *client,
638
715
mlxsw_i2c -> bus_info .dev = & client -> dev ;
639
716
mlxsw_i2c -> bus_info .low_frequency = true;
640
717
mlxsw_i2c -> dev = & client -> dev ;
718
+ mlxsw_i2c -> pdata = client -> dev .platform_data ;
719
+
720
+ err = mlxsw_i2c_irq_init (mlxsw_i2c , client -> addr );
721
+ if (err )
722
+ goto errout ;
641
723
642
724
err = mlxsw_core_bus_device_register (& mlxsw_i2c -> bus_info ,
643
725
& mlxsw_i2c_bus , mlxsw_i2c , false,
644
726
NULL , NULL );
645
727
if (err ) {
646
728
dev_err (& client -> dev , "Fail to register core bus\n" );
647
- return err ;
729
+ goto err_bus_device_register ;
648
730
}
649
731
650
732
return 0 ;
651
733
734
+ err_bus_device_register :
735
+ mlxsw_i2c_irq_fini (mlxsw_i2c );
652
736
errout :
653
737
mutex_destroy (& mlxsw_i2c -> cmd .lock );
654
738
i2c_set_clientdata (client , NULL );
@@ -661,6 +745,7 @@ static int mlxsw_i2c_remove(struct i2c_client *client)
661
745
struct mlxsw_i2c * mlxsw_i2c = i2c_get_clientdata (client );
662
746
663
747
mlxsw_core_bus_device_unregister (mlxsw_i2c -> core , false);
748
+ mlxsw_i2c_irq_fini (mlxsw_i2c );
664
749
mutex_destroy (& mlxsw_i2c -> cmd .lock );
665
750
666
751
return 0 ;
0 commit comments