2626
2727#include <linux/uaccess.h>
2828
29+ #include <linux/irq.h>
30+ #include <linux/interrupt.h>
31+ #include <linux/poll.h>
32+ #include <linux/irqdomain.h>
2933
3034/*
3135 * This supports access to SPI devices using normal userspace I/O calls.
@@ -79,6 +83,10 @@ struct spidev_data {
7983 u8 * tx_buffer ;
8084 u8 * rx_buffer ;
8185 u32 speed_hz ;
86+ int irq ;
87+ bool notified ;
88+ struct wait_queue_head waitq ;
89+ spinlock_t irq_lock ;
8290};
8391
8492static LIST_HEAD (device_list );
@@ -90,6 +98,43 @@ MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");
9098
9199/*-------------------------------------------------------------------------*/
92100
101+ static irqreturn_t handshake_irq (int __attribute__((unused )) irq , void * id )
102+ {
103+ struct spidev_data * spidev = id ;
104+ unsigned long flags ;
105+
106+ spin_lock_irqsave (& spidev -> irq_lock , flags );
107+ spidev -> notified = true;
108+ spin_unlock_irqrestore (& spidev -> irq_lock , flags );
109+ wake_up_interruptible (& spidev -> waitq );
110+
111+ return IRQ_HANDLED ;
112+ }
113+
114+ static int spidev_irq_get (struct spi_device * spi )
115+ {
116+ struct irq_fwspec fwspec ;
117+ struct irq_domain * domain ;
118+ struct spi_controller * ctlr = spi -> controller ;
119+ int irq = - EINVAL ;
120+
121+ fwspec .fwnode = dev_fwnode (ctlr -> dev .parent );
122+ fwspec .param [0 ] = spi_get_chipselect (spi , 0 );
123+ fwspec .param [1 ] = IRQ_TYPE_EDGE_RISING ;
124+ fwspec .param_count = 2 ;
125+
126+ domain = irq_find_matching_fwnode (fwspec .fwnode , DOMAIN_BUS_ANY );
127+ if (!domain )
128+ return - EINVAL ;
129+ dev_info (& spi -> dev , "found domain: %s\n" , domain -> name );
130+
131+ irq = irq_create_fwspec_mapping (& fwspec );
132+ if (irq <= 0 )
133+ return - EINVAL ;
134+
135+ return irq ;
136+ }
137+
93138static ssize_t
94139spidev_sync_unlocked (struct spi_device * spi , struct spi_message * message )
95140{
@@ -673,6 +718,22 @@ static int spidev_release(struct inode *inode, struct file *filp)
673718 return 0 ;
674719}
675720
721+ static unsigned int spidev_poll (struct file * filp , struct poll_table_struct * wait )
722+ {
723+ struct spidev_data * spidev ;
724+ __poll_t mask = 0 ;
725+
726+ spidev = filp -> private_data ;
727+ poll_wait (filp , & spidev -> waitq , wait );
728+ if (spidev -> notified ) {
729+ mask |= ( POLLIN | POLLRDNORM );
730+ spin_lock_irq (& spidev -> irq_lock );
731+ spidev -> notified = false;
732+ spin_unlock_irq (& spidev -> irq_lock );
733+ }
734+ return mask ;
735+ }
736+
676737static const struct file_operations spidev_fops = {
677738 .owner = THIS_MODULE ,
678739 /* REVISIT switch to aio primitives, so that userspace
@@ -684,6 +745,7 @@ static const struct file_operations spidev_fops = {
684745 .unlocked_ioctl = spidev_ioctl ,
685746 .compat_ioctl = spidev_compat_ioctl ,
686747 .open = spidev_open ,
748+ .poll = spidev_poll ,
687749 .release = spidev_release ,
688750};
689751
@@ -772,7 +834,7 @@ static int spidev_probe(struct spi_device *spi)
772834{
773835 int (* match )(struct device * dev );
774836 struct spidev_data * spidev ;
775- int status ;
837+ int status , irq ;
776838 unsigned long minor ;
777839
778840 match = device_get_match_data (& spi -> dev );
@@ -791,6 +853,7 @@ static int spidev_probe(struct spi_device *spi)
791853 spidev -> spi = spi ;
792854 mutex_init (& spidev -> spi_lock );
793855 mutex_init (& spidev -> buf_lock );
856+ spin_lock_init (& spidev -> irq_lock );
794857
795858 INIT_LIST_HEAD (& spidev -> device_entry );
796859
@@ -819,6 +882,24 @@ static int spidev_probe(struct spi_device *spi)
819882
820883 spidev -> speed_hz = spi -> max_speed_hz ;
821884
885+ init_waitqueue_head (& spidev -> waitq );
886+ //ACPI_GENERIC_GSI is NOT supported on x86 !?
887+ //irq = fwnode_irq_get(dev_fwnode(&spi->dev), 0);
888+ irq = spidev_irq_get (spi );
889+ if (irq < 0 ) {
890+ dev_info (& spi -> dev , "fail to get device irq %d\n" , irq );
891+ } else {
892+ dev_dbg (& spi -> dev , "got mapped irq %d\n" , irq );
893+ status = request_irq (irq , handshake_irq ,
894+ IRQF_TRIGGER_RISING , dev_name (& spi -> dev ),
895+ spidev );
896+ if (status ) {
897+ dev_dbg (& spi -> dev , "unable to request irq %d\n" , irq );
898+ status = 0 ;
899+ } else
900+ spidev -> irq = irq ;
901+ }
902+
822903 if (status == 0 )
823904 spi_set_drvdata (spi , spidev );
824905 else
0 commit comments