hid-mcp2221.c (2b703bbda2713fd2a7d98029ea6c44f9c3159f34) hid-mcp2221.c (328de1c519c5c0925151cae47944a1c1a0333bcd)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * MCP2221A - Microchip USB to I2C Host Protocol Bridge
4 *
5 * Copyright (c) 2020, Rishi Gupta <gupt21@gmail.com>
6 *
7 * Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/20005565B.pdf
8 */
9
10#include <linux/module.h>
11#include <linux/err.h>
12#include <linux/mutex.h>
13#include <linux/completion.h>
14#include <linux/delay.h>
15#include <linux/hid.h>
16#include <linux/hidraw.h>
17#include <linux/i2c.h>
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * MCP2221A - Microchip USB to I2C Host Protocol Bridge
4 *
5 * Copyright (c) 2020, Rishi Gupta <gupt21@gmail.com>
6 *
7 * Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/20005565B.pdf
8 */
9
10#include <linux/module.h>
11#include <linux/err.h>
12#include <linux/mutex.h>
13#include <linux/completion.h>
14#include <linux/delay.h>
15#include <linux/hid.h>
16#include <linux/hidraw.h>
17#include <linux/i2c.h>
18#include <linux/gpio/driver.h>
18#include "hid-ids.h"
19
20/* Commands codes in a raw output report */
21enum {
22 MCP2221_I2C_WR_DATA = 0x90,
23 MCP2221_I2C_WR_NO_STOP = 0x94,
24 MCP2221_I2C_RD_DATA = 0x91,
25 MCP2221_I2C_RD_RPT_START = 0x93,
26 MCP2221_I2C_GET_DATA = 0x40,
27 MCP2221_I2C_PARAM_OR_STATUS = 0x10,
28 MCP2221_I2C_SET_SPEED = 0x20,
29 MCP2221_I2C_CANCEL = 0x10,
19#include "hid-ids.h"
20
21/* Commands codes in a raw output report */
22enum {
23 MCP2221_I2C_WR_DATA = 0x90,
24 MCP2221_I2C_WR_NO_STOP = 0x94,
25 MCP2221_I2C_RD_DATA = 0x91,
26 MCP2221_I2C_RD_RPT_START = 0x93,
27 MCP2221_I2C_GET_DATA = 0x40,
28 MCP2221_I2C_PARAM_OR_STATUS = 0x10,
29 MCP2221_I2C_SET_SPEED = 0x20,
30 MCP2221_I2C_CANCEL = 0x10,
31 MCP2221_GPIO_SET = 0x50,
32 MCP2221_GPIO_GET = 0x51,
30};
31
32/* Response codes in a raw input report */
33enum {
34 MCP2221_SUCCESS = 0x00,
35 MCP2221_I2C_ENG_BUSY = 0x01,
36 MCP2221_I2C_START_TOUT = 0x12,
37 MCP2221_I2C_STOP_TOUT = 0x62,
38 MCP2221_I2C_WRADDRL_TOUT = 0x23,
39 MCP2221_I2C_WRDATA_TOUT = 0x44,
40 MCP2221_I2C_WRADDRL_NACK = 0x25,
41 MCP2221_I2C_MASK_ADDR_NACK = 0x40,
42 MCP2221_I2C_WRADDRL_SEND = 0x21,
43 MCP2221_I2C_ADDR_NACK = 0x25,
44 MCP2221_I2C_READ_COMPL = 0x55,
33};
34
35/* Response codes in a raw input report */
36enum {
37 MCP2221_SUCCESS = 0x00,
38 MCP2221_I2C_ENG_BUSY = 0x01,
39 MCP2221_I2C_START_TOUT = 0x12,
40 MCP2221_I2C_STOP_TOUT = 0x62,
41 MCP2221_I2C_WRADDRL_TOUT = 0x23,
42 MCP2221_I2C_WRDATA_TOUT = 0x44,
43 MCP2221_I2C_WRADDRL_NACK = 0x25,
44 MCP2221_I2C_MASK_ADDR_NACK = 0x40,
45 MCP2221_I2C_WRADDRL_SEND = 0x21,
46 MCP2221_I2C_ADDR_NACK = 0x25,
47 MCP2221_I2C_READ_COMPL = 0x55,
48 MCP2221_ALT_F_NOT_GPIOV = 0xEE,
49 MCP2221_ALT_F_NOT_GPIOD = 0xEF,
45};
46
47/*
48 * There is no way to distinguish responses. Therefore next command
49 * is sent only after response to previous has been received. Mutex
50 * lock is used for this purpose mainly.
51 */
52struct mcp2221 {
53 struct hid_device *hdev;
54 struct i2c_adapter adapter;
55 struct mutex lock;
56 struct completion wait_in_report;
57 u8 *rxbuf;
58 u8 txbuf[64];
59 int rxbuf_idx;
60 int status;
61 u8 cur_i2c_clk_div;
50};
51
52/*
53 * There is no way to distinguish responses. Therefore next command
54 * is sent only after response to previous has been received. Mutex
55 * lock is used for this purpose mainly.
56 */
57struct mcp2221 {
58 struct hid_device *hdev;
59 struct i2c_adapter adapter;
60 struct mutex lock;
61 struct completion wait_in_report;
62 u8 *rxbuf;
63 u8 txbuf[64];
64 int rxbuf_idx;
65 int status;
66 u8 cur_i2c_clk_div;
67 struct gpio_chip *gc;
68 u8 gp_idx;
69 u8 gpio_dir;
62};
63
64/*
65 * Default i2c bus clock frequency 400 kHz. Modify this if you
66 * want to set some other frequency (min 50 kHz - max 400 kHz).
67 */
68static uint i2c_clk_freq = 400;
69

--- 451 unchanged lines hidden (view full) ---

521}
522
523static const struct i2c_algorithm mcp_i2c_algo = {
524 .master_xfer = mcp_i2c_xfer,
525 .smbus_xfer = mcp_smbus_xfer,
526 .functionality = mcp_i2c_func,
527};
528
70};
71
72/*
73 * Default i2c bus clock frequency 400 kHz. Modify this if you
74 * want to set some other frequency (min 50 kHz - max 400 kHz).
75 */
76static uint i2c_clk_freq = 400;
77

--- 451 unchanged lines hidden (view full) ---

529}
530
531static const struct i2c_algorithm mcp_i2c_algo = {
532 .master_xfer = mcp_i2c_xfer,
533 .smbus_xfer = mcp_smbus_xfer,
534 .functionality = mcp_i2c_func,
535};
536
537static 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
554static 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
572static 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
586static 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
599static 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
618static 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
529/* Gives current state of i2c engine inside mcp2221 */
530static int mcp_get_i2c_eng_state(struct mcp2221 *mcp,
531 u8 *data, u8 idx)
532{
533 int ret;
534
535 switch (data[idx]) {
536 case MCP2221_I2C_WRADDRL_NACK:

--- 96 unchanged lines hidden (view full) ---

633 mcp->status = -EIO;
634 break;
635 default:
636 mcp->status = -EIO;
637 }
638 complete(&mcp->wait_in_report);
639 break;
640
641/* Gives current state of i2c engine inside mcp2221 */
642static int mcp_get_i2c_eng_state(struct mcp2221 *mcp,
643 u8 *data, u8 idx)
644{
645 int ret;
646
647 switch (data[idx]) {
648 case MCP2221_I2C_WRADDRL_NACK:

--- 96 unchanged lines hidden (view full) ---

745 mcp->status = -EIO;
746 break;
747 default:
748 mcp->status = -EIO;
749 }
750 complete(&mcp->wait_in_report);
751 break;
752
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
641 default:
642 mcp->status = -EIO;
643 complete(&mcp->wait_in_report);
644 }
645
646 return 1;
647}
648

--- 48 unchanged lines hidden (view full) ---

697
698 ret = i2c_add_adapter(&mcp->adapter);
699 if (ret) {
700 hid_err(hdev, "can't add usb-i2c adapter: %d\n", ret);
701 goto err_i2c;
702 }
703 i2c_set_adapdata(&mcp->adapter, mcp);
704
786 default:
787 mcp->status = -EIO;
788 complete(&mcp->wait_in_report);
789 }
790
791 return 1;
792}
793

--- 48 unchanged lines hidden (view full) ---

842
843 ret = i2c_add_adapter(&mcp->adapter);
844 if (ret) {
845 hid_err(hdev, "can't add usb-i2c adapter: %d\n", ret);
846 goto err_i2c;
847 }
848 i2c_set_adapdata(&mcp->adapter, mcp);
849
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
705 return 0;
706
872 return 0;
873
874err_gc:
875 i2c_del_adapter(&mcp->adapter);
707err_i2c:
708 hid_hw_close(mcp->hdev);
709err_hstop:
710 hid_hw_stop(mcp->hdev);
711 return ret;
712}
713
714static void mcp2221_remove(struct hid_device *hdev)

--- 28 unchanged lines hidden ---
876err_i2c:
877 hid_hw_close(mcp->hdev);
878err_hstop:
879 hid_hw_stop(mcp->hdev);
880 return ret;
881}
882
883static void mcp2221_remove(struct hid_device *hdev)

--- 28 unchanged lines hidden ---