18
18
#include <linux/i2c.h>
19
19
#include <linux/gpio/driver.h>
20
20
#include <linux/iio/iio.h>
21
+ #include <linux/minmax.h>
21
22
#include "hid-ids.h"
22
23
23
24
/* Commands codes in a raw output report */
@@ -55,6 +56,27 @@ enum {
55
56
MCP2221_ALT_F_NOT_GPIOD = 0xEF ,
56
57
};
57
58
59
+ /* MCP SRAM read offsets cmd: MCP2221_GET_SRAM_SETTINGS */
60
+ enum {
61
+ MCP2221_SRAM_RD_GP0 = 22 ,
62
+ MCP2221_SRAM_RD_GP1 = 23 ,
63
+ MCP2221_SRAM_RD_GP2 = 24 ,
64
+ MCP2221_SRAM_RD_GP3 = 25 ,
65
+ };
66
+
67
+ /* MCP SRAM write offsets cmd: MCP2221_SET_SRAM_SETTINGS */
68
+ enum {
69
+ MCP2221_SRAM_WR_GP_ENA_ALTER = 7 ,
70
+ MCP2221_SRAM_WR_GP0 = 8 ,
71
+ MCP2221_SRAM_WR_GP1 = 9 ,
72
+ MCP2221_SRAM_WR_GP2 = 10 ,
73
+ MCP2221_SRAM_WR_GP3 = 11 ,
74
+ };
75
+
76
+ #define MCP2221_SRAM_GP_DESIGN_MASK 0x07
77
+ #define MCP2221_SRAM_GP_DIRECTION_MASK 0x08
78
+ #define MCP2221_SRAM_GP_VALUE_MASK 0x10
79
+
58
80
/* MCP GPIO direction encoding */
59
81
enum {
60
82
MCP2221_DIR_OUT = 0x00 ,
@@ -241,10 +263,7 @@ static int mcp_i2c_write(struct mcp2221 *mcp,
241
263
242
264
idx = 0 ;
243
265
sent = 0 ;
244
- if (msg -> len < 60 )
245
- len = msg -> len ;
246
- else
247
- len = 60 ;
266
+ len = min (msg -> len , 60 );
248
267
249
268
do {
250
269
mcp -> txbuf [0 ] = type ;
@@ -271,10 +290,7 @@ static int mcp_i2c_write(struct mcp2221 *mcp,
271
290
break ;
272
291
273
292
idx = idx + len ;
274
- if ((msg -> len - sent ) < 60 )
275
- len = msg -> len - sent ;
276
- else
277
- len = 60 ;
293
+ len = min (msg -> len - sent , 60 );
278
294
279
295
/*
280
296
* Testing shows delay is needed between successive writes
@@ -607,6 +623,80 @@ static const struct i2c_algorithm mcp_i2c_algo = {
607
623
};
608
624
609
625
#if IS_REACHABLE (CONFIG_GPIOLIB )
626
+ static int mcp_gpio_read_sram (struct mcp2221 * mcp )
627
+ {
628
+ int ret ;
629
+
630
+ memset (mcp -> txbuf , 0 , 64 );
631
+ mcp -> txbuf [0 ] = MCP2221_GET_SRAM_SETTINGS ;
632
+
633
+ mutex_lock (& mcp -> lock );
634
+ ret = mcp_send_data_req_status (mcp , mcp -> txbuf , 64 );
635
+ mutex_unlock (& mcp -> lock );
636
+
637
+ return ret ;
638
+ }
639
+
640
+ /*
641
+ * If CONFIG_IIO is not enabled, check for the gpio pins
642
+ * if they are in gpio mode. For the ones which are not
643
+ * in gpio mode, set them into gpio mode.
644
+ */
645
+ static int mcp2221_check_gpio_pinfunc (struct mcp2221 * mcp )
646
+ {
647
+ int i ;
648
+ int needgpiofix = 0 ;
649
+ int ret ;
650
+
651
+ if (IS_ENABLED (CONFIG_IIO ))
652
+ return 0 ;
653
+
654
+ ret = mcp_gpio_read_sram (mcp );
655
+ if (ret )
656
+ return ret ;
657
+
658
+ for (i = 0 ; i < MCP_NGPIO ; i ++ ) {
659
+ if ((mcp -> mode [i ] & MCP2221_SRAM_GP_DESIGN_MASK ) != 0x0 ) {
660
+ dev_warn (& mcp -> hdev -> dev ,
661
+ "GPIO %d not in gpio mode\n" , i );
662
+ needgpiofix = 1 ;
663
+ }
664
+ }
665
+
666
+ if (!needgpiofix )
667
+ return 0 ;
668
+
669
+ /*
670
+ * Set all bytes to 0, so Bit 7 is not set. The chip
671
+ * only changes content of a register when bit 7 is set.
672
+ */
673
+ memset (mcp -> txbuf , 0 , 64 );
674
+ mcp -> txbuf [0 ] = MCP2221_SET_SRAM_SETTINGS ;
675
+
676
+ /*
677
+ * Set bit 7 in MCP2221_SRAM_WR_GP_ENA_ALTER to enable
678
+ * loading of a new set of gpio settings to GP SRAM
679
+ */
680
+ mcp -> txbuf [MCP2221_SRAM_WR_GP_ENA_ALTER ] = 0x80 ;
681
+ for (i = 0 ; i < MCP_NGPIO ; i ++ ) {
682
+ if ((mcp -> mode [i ] & MCP2221_SRAM_GP_DESIGN_MASK ) == 0x0 ) {
683
+ /* write current GPIO mode */
684
+ mcp -> txbuf [MCP2221_SRAM_WR_GP0 + i ] = mcp -> mode [i ];
685
+ } else {
686
+ /* pin is not in gpio mode, set it to input mode */
687
+ mcp -> txbuf [MCP2221_SRAM_WR_GP0 + i ] = 0x08 ;
688
+ dev_warn (& mcp -> hdev -> dev ,
689
+ "Set GPIO mode for gpio pin %d!\n" , i );
690
+ }
691
+ }
692
+
693
+ mutex_lock (& mcp -> lock );
694
+ ret = mcp_send_data_req_status (mcp , mcp -> txbuf , 64 );
695
+ mutex_unlock (& mcp -> lock );
696
+
697
+ return ret ;
698
+ }
699
+
610
700
static int mcp_gpio_get (struct gpio_chip * gc ,
611
701
unsigned int offset )
612
702
{
@@ -1218,6 +1308,8 @@ static int mcp2221_probe(struct hid_device *hdev,
1218
1308
ret = devm_gpiochip_add_data (& hdev -> dev , mcp -> gc , mcp );
1219
1309
if (ret )
1220
1310
return ret ;
1311
+
1312
+ mcp2221_check_gpio_pinfunc (mcp );
1221
1313
#endif
1222
1314
1223
1315
#if IS_REACHABLE (CONFIG_IIO )
0 commit comments