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 --- |