1515#include <linux/hid.h>
1616#include <linux/hidraw.h>
1717#include <linux/i2c.h>
18+ #include <linux/gpio/driver.h>
1819#include "hid-ids.h"
1920
2021/* Commands codes in a raw output report */
2728 MCP2221_I2C_PARAM_OR_STATUS = 0x10 ,
2829 MCP2221_I2C_SET_SPEED = 0x20 ,
2930 MCP2221_I2C_CANCEL = 0x10 ,
31+ MCP2221_GPIO_SET = 0x50 ,
32+ MCP2221_GPIO_GET = 0x51 ,
3033};
3134
3235/* Response codes in a raw input report */
4245 MCP2221_I2C_WRADDRL_SEND = 0x21 ,
4346 MCP2221_I2C_ADDR_NACK = 0x25 ,
4447 MCP2221_I2C_READ_COMPL = 0x55 ,
48+ MCP2221_ALT_F_NOT_GPIOV = 0xEE ,
49+ MCP2221_ALT_F_NOT_GPIOD = 0xEF ,
4550};
4651
4752/*
@@ -59,6 +64,9 @@ struct mcp2221 {
5964 int rxbuf_idx ;
6065 int status ;
6166 u8 cur_i2c_clk_div ;
67+ struct gpio_chip * gc ;
68+ u8 gp_idx ;
69+ u8 gpio_dir ;
6270};
6371
6472/*
@@ -526,6 +534,110 @@ static const struct i2c_algorithm mcp_i2c_algo = {
526534 .functionality = mcp_i2c_func ,
527535};
528536
537+ static int mcp_gpio_get (struct gpio_chip * gc ,
538+ unsigned int offset )
539+ {
540+ int ret ;
541+ struct mcp2221 * mcp = gpiochip_get_data (gc );
542+
543+ mcp -> txbuf [0 ] = MCP2221_GPIO_GET ;
544+
545+ mcp -> gp_idx = (offset + 1 ) * 2 ;
546+
547+ mutex_lock (& mcp -> lock );
548+ ret = mcp_send_data_req_status (mcp , mcp -> txbuf , 1 );
549+ mutex_unlock (& mcp -> lock );
550+
551+ return ret ;
552+ }
553+
554+ static void mcp_gpio_set (struct gpio_chip * gc ,
555+ unsigned int offset , int value )
556+ {
557+ struct mcp2221 * mcp = gpiochip_get_data (gc );
558+
559+ memset (mcp -> txbuf , 0 , 18 );
560+ mcp -> txbuf [0 ] = MCP2221_GPIO_SET ;
561+
562+ mcp -> gp_idx = ((offset + 1 ) * 4 ) - 1 ;
563+
564+ mcp -> txbuf [mcp -> gp_idx - 1 ] = 1 ;
565+ mcp -> txbuf [mcp -> gp_idx ] = !!value ;
566+
567+ mutex_lock (& mcp -> lock );
568+ mcp_send_data_req_status (mcp , mcp -> txbuf , 18 );
569+ mutex_unlock (& mcp -> lock );
570+ }
571+
572+ static int mcp_gpio_dir_set (struct mcp2221 * mcp ,
573+ unsigned int offset , u8 val )
574+ {
575+ memset (mcp -> txbuf , 0 , 18 );
576+ mcp -> txbuf [0 ] = MCP2221_GPIO_SET ;
577+
578+ mcp -> gp_idx = (offset + 1 ) * 5 ;
579+
580+ mcp -> txbuf [mcp -> gp_idx - 1 ] = 1 ;
581+ mcp -> txbuf [mcp -> gp_idx ] = val ;
582+
583+ return mcp_send_data_req_status (mcp , mcp -> txbuf , 18 );
584+ }
585+
586+ static int mcp_gpio_direction_input (struct gpio_chip * gc ,
587+ unsigned int offset )
588+ {
589+ int ret ;
590+ struct mcp2221 * mcp = gpiochip_get_data (gc );
591+
592+ mutex_lock (& mcp -> lock );
593+ ret = mcp_gpio_dir_set (mcp , offset , 0 );
594+ mutex_unlock (& mcp -> lock );
595+
596+ return ret ;
597+ }
598+
599+ static int mcp_gpio_direction_output (struct gpio_chip * gc ,
600+ unsigned int offset , int value )
601+ {
602+ int ret ;
603+ struct mcp2221 * mcp = gpiochip_get_data (gc );
604+
605+ mutex_lock (& mcp -> lock );
606+ ret = mcp_gpio_dir_set (mcp , offset , 1 );
607+ mutex_unlock (& mcp -> lock );
608+
609+ /* Can't configure as output, bailout early */
610+ if (ret )
611+ return ret ;
612+
613+ mcp_gpio_set (gc , offset , value );
614+
615+ return 0 ;
616+ }
617+
618+ static int mcp_gpio_get_direction (struct gpio_chip * gc ,
619+ unsigned int offset )
620+ {
621+ int ret ;
622+ struct mcp2221 * mcp = gpiochip_get_data (gc );
623+
624+ mcp -> txbuf [0 ] = MCP2221_GPIO_GET ;
625+
626+ mcp -> gp_idx = (offset + 1 ) * 2 ;
627+
628+ mutex_lock (& mcp -> lock );
629+ ret = mcp_send_data_req_status (mcp , mcp -> txbuf , 1 );
630+ mutex_unlock (& mcp -> lock );
631+
632+ if (ret )
633+ return ret ;
634+
635+ if (mcp -> gpio_dir )
636+ return GPIO_LINE_DIRECTION_IN ;
637+
638+ return GPIO_LINE_DIRECTION_OUT ;
639+ }
640+
529641/* Gives current state of i2c engine inside mcp2221 */
530642static int mcp_get_i2c_eng_state (struct mcp2221 * mcp ,
531643 u8 * data , u8 idx )
@@ -638,6 +750,39 @@ static int mcp2221_raw_event(struct hid_device *hdev,
638750 complete (& mcp -> wait_in_report );
639751 break ;
640752
753+ case MCP2221_GPIO_GET :
754+ switch (data [1 ]) {
755+ case MCP2221_SUCCESS :
756+ if ((data [mcp -> gp_idx ] == MCP2221_ALT_F_NOT_GPIOV ) ||
757+ (data [mcp -> gp_idx + 1 ] == MCP2221_ALT_F_NOT_GPIOD )) {
758+ mcp -> status = - ENOENT ;
759+ } else {
760+ mcp -> status = !!data [mcp -> gp_idx ];
761+ mcp -> gpio_dir = !!data [mcp -> gp_idx + 1 ];
762+ }
763+ break ;
764+ default :
765+ mcp -> status = - EAGAIN ;
766+ }
767+ complete (& mcp -> wait_in_report );
768+ break ;
769+
770+ case MCP2221_GPIO_SET :
771+ switch (data [1 ]) {
772+ case MCP2221_SUCCESS :
773+ if ((data [mcp -> gp_idx ] == MCP2221_ALT_F_NOT_GPIOV ) ||
774+ (data [mcp -> gp_idx - 1 ] == MCP2221_ALT_F_NOT_GPIOV )) {
775+ mcp -> status = - ENOENT ;
776+ } else {
777+ mcp -> status = 0 ;
778+ }
779+ break ;
780+ default :
781+ mcp -> status = - EAGAIN ;
782+ }
783+ complete (& mcp -> wait_in_report );
784+ break ;
785+
641786 default :
642787 mcp -> status = - EIO ;
643788 complete (& mcp -> wait_in_report );
@@ -702,8 +847,32 @@ static int mcp2221_probe(struct hid_device *hdev,
702847 }
703848 i2c_set_adapdata (& mcp -> adapter , mcp );
704849
850+ /* Setup GPIO chip */
851+ mcp -> gc = devm_kzalloc (& hdev -> dev , sizeof (* mcp -> gc ), GFP_KERNEL );
852+ if (!mcp -> gc ) {
853+ ret = - ENOMEM ;
854+ goto err_gc ;
855+ }
856+
857+ mcp -> gc -> label = "mcp2221_gpio" ;
858+ mcp -> gc -> direction_input = mcp_gpio_direction_input ;
859+ mcp -> gc -> direction_output = mcp_gpio_direction_output ;
860+ mcp -> gc -> get_direction = mcp_gpio_get_direction ;
861+ mcp -> gc -> set = mcp_gpio_set ;
862+ mcp -> gc -> get = mcp_gpio_get ;
863+ mcp -> gc -> ngpio = 4 ;
864+ mcp -> gc -> base = -1 ;
865+ mcp -> gc -> can_sleep = 1 ;
866+ mcp -> gc -> parent = & hdev -> dev ;
867+
868+ ret = devm_gpiochip_add_data (& hdev -> dev , mcp -> gc , mcp );
869+ if (ret )
870+ goto err_gc ;
871+
705872 return 0 ;
706873
874+ err_gc :
875+ i2c_del_adapter (& mcp -> adapter );
707876err_i2c :
708877 hid_hw_close (mcp -> hdev );
709878err_hstop :
0 commit comments