mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-25 17:27:01 +00:00
Adding CP2112 latest patch & Enabling USB_ACM in linux config to create TTY interface for CPU to BMC communication.
This commit is contained in:
@@ -2450,7 +2450,7 @@ CONFIG_HID_GENERIC=y
|
||||
# CONFIG_HID_BELKIN is not set
|
||||
# CONFIG_HID_CHERRY is not set
|
||||
# CONFIG_HID_CHICONY is not set
|
||||
# CONFIG_HID_CP2112 is not set
|
||||
CONFIG_HID_CP2112=y
|
||||
# CONFIG_HID_CYPRESS is not set
|
||||
# CONFIG_HID_DRAGONRISE is not set
|
||||
# CONFIG_HID_EMS_FF is not set
|
||||
@@ -2561,7 +2561,7 @@ CONFIG_USB_UHCI_HCD=y
|
||||
#
|
||||
# USB Device Class drivers
|
||||
#
|
||||
# CONFIG_USB_ACM is not set
|
||||
CONFIG_USB_ACM=y
|
||||
# CONFIG_USB_PRINTER is not set
|
||||
# CONFIG_USB_WDM is not set
|
||||
# CONFIG_USB_TMC is not set
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
|
||||
index bc37acd..fee4c66 100644
|
||||
--- a/drivers/hid/hid-cp2112.c
|
||||
+++ b/drivers/hid/hid-cp2112.c
|
||||
@@ -156,6 +156,7 @@ struct cp2112_device {
|
||||
wait_queue_head_t wait;
|
||||
u8 read_data[61];
|
||||
u8 read_length;
|
||||
+ u8 hwversion;
|
||||
int xfer_status;
|
||||
atomic_t read_avail;
|
||||
atomic_t xfer_avail;
|
||||
@@ -427,6 +428,156 @@ static int cp2112_write_req(void *buf, u8 slave_address, u8 command, u8 *data,
|
||||
return data_length + 4;
|
||||
}
|
||||
|
||||
+static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data,
|
||||
+ u8 data_length)
|
||||
+{
|
||||
+ struct cp2112_write_req_report *report = buf;
|
||||
+
|
||||
+ if (data_length > sizeof(report->data))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ report->report = CP2112_DATA_WRITE_REQUEST;
|
||||
+ report->slave_address = slave_address << 1;
|
||||
+ report->length = data_length;
|
||||
+ memcpy(report->data, data, data_length);
|
||||
+ return data_length + 3;
|
||||
+}
|
||||
+
|
||||
+static int cp2112_i2c_write_read_req(void *buf, u8 slave_address,
|
||||
+ u8 *addr, int addr_length,
|
||||
+ int read_length)
|
||||
+{
|
||||
+ struct cp2112_write_read_req_report *report = buf;
|
||||
+
|
||||
+ if (read_length < 1 || read_length > 512 ||
|
||||
+ addr_length > sizeof(report->target_address))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ report->report = CP2112_DATA_WRITE_READ_REQUEST;
|
||||
+ report->slave_address = slave_address << 1;
|
||||
+ report->length = cpu_to_be16(read_length);
|
||||
+ report->target_address_length = addr_length;
|
||||
+ memcpy(report->target_address, addr, addr_length);
|
||||
+ return addr_length + 5;
|
||||
+}
|
||||
+
|
||||
+static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
||||
+ int num)
|
||||
+{
|
||||
+ struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data;
|
||||
+ struct hid_device *hdev = dev->hdev;
|
||||
+ u8 buf[64];
|
||||
+ ssize_t count;
|
||||
+ ssize_t read_length = 0;
|
||||
+ u8 *read_buf = NULL;
|
||||
+ unsigned int retries;
|
||||
+ int ret;
|
||||
+
|
||||
+ hid_dbg(hdev, "I2C %d messages\n", num);
|
||||
+
|
||||
+ if (num == 1) {
|
||||
+ if (msgs->flags & I2C_M_RD) {
|
||||
+ hid_dbg(hdev, "I2C read %#04x len %d\n",
|
||||
+ msgs->addr, msgs->len);
|
||||
+ read_length = msgs->len;
|
||||
+ read_buf = msgs->buf;
|
||||
+ count = cp2112_read_req(buf, msgs->addr, msgs->len);
|
||||
+ } else {
|
||||
+ hid_dbg(hdev, "I2C write %#04x len %d\n",
|
||||
+ msgs->addr, msgs->len);
|
||||
+ count = cp2112_i2c_write_req(buf, msgs->addr,
|
||||
+ msgs->buf, msgs->len);
|
||||
+ }
|
||||
+ if (count < 0)
|
||||
+ return count;
|
||||
+ } else if (dev->hwversion > 1 && /* no repeated start in rev 1 */
|
||||
+ num == 2 &&
|
||||
+ msgs[0].addr == msgs[1].addr &&
|
||||
+ !(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) {
|
||||
+ hid_dbg(hdev, "I2C write-read %#04x wlen %d rlen %d\n",
|
||||
+ msgs[0].addr, msgs[0].len, msgs[1].len);
|
||||
+ read_length = msgs[1].len;
|
||||
+ read_buf = msgs[1].buf;
|
||||
+ count = cp2112_i2c_write_read_req(buf, msgs[0].addr,
|
||||
+ msgs[0].buf, msgs[0].len, msgs[1].len);
|
||||
+ if (count < 0)
|
||||
+ return count;
|
||||
+ } else {
|
||||
+ hid_err(hdev,
|
||||
+ "Multi-message I2C transactions not supported\n");
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+
|
||||
+ ret = hid_hw_power(hdev, PM_HINT_FULLON);
|
||||
+ if (ret < 0) {
|
||||
+ hid_err(hdev, "power management error: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = cp2112_hid_output(hdev, buf, count, HID_OUTPUT_REPORT);
|
||||
+ if (ret < 0) {
|
||||
+ hid_warn(hdev, "Error starting transaction: %d\n", ret);
|
||||
+ goto power_normal;
|
||||
+ }
|
||||
+
|
||||
+ for (retries = 0; retries < XFER_STATUS_RETRIES; ++retries) {
|
||||
+ ret = cp2112_xfer_status(dev);
|
||||
+ if (-EBUSY == ret)
|
||||
+ continue;
|
||||
+ if (ret < 0)
|
||||
+ goto power_normal;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (XFER_STATUS_RETRIES <= retries) {
|
||||
+ hid_warn(hdev, "Transfer timed out, cancelling.\n");
|
||||
+ buf[0] = CP2112_CANCEL_TRANSFER;
|
||||
+ buf[1] = 0x01;
|
||||
+
|
||||
+ ret = cp2112_hid_output(hdev, buf, 2, HID_OUTPUT_REPORT);
|
||||
+ if (ret < 0)
|
||||
+ hid_warn(hdev, "Error cancelling transaction: %d\n",
|
||||
+ ret);
|
||||
+
|
||||
+ ret = -ETIMEDOUT;
|
||||
+ goto power_normal;
|
||||
+ }
|
||||
+
|
||||
+ for (count = 0; count < read_length;) {
|
||||
+ ret = cp2112_read(dev, read_buf + count, read_length - count);
|
||||
+ if (ret < 0)
|
||||
+ goto power_normal;
|
||||
+ if (ret == 0) {
|
||||
+ hid_err(hdev, "read returned 0\n");
|
||||
+ ret = -EIO;
|
||||
+ goto power_normal;
|
||||
+ }
|
||||
+ count += ret;
|
||||
+ if (count > read_length) {
|
||||
+ /*
|
||||
+ * The hardware returned too much data.
|
||||
+ * This is mostly harmless because cp2112_read()
|
||||
+ * has a limit check so didn't overrun our
|
||||
+ * buffer. Nevertheless, we return an error
|
||||
+ * because something is seriously wrong and
|
||||
+ * it shouldn't go unnoticed.
|
||||
+ */
|
||||
+ hid_err(hdev, "long read: %d > %zd\n",
|
||||
+ ret, read_length - count + ret);
|
||||
+ ret = -EIO;
|
||||
+ goto power_normal;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* return the number of transferred messages */
|
||||
+ ret = num;
|
||||
+
|
||||
+power_normal:
|
||||
+ hid_hw_power(hdev, PM_HINT_NORMAL);
|
||||
+ hid_dbg(hdev, "I2C transfer finished: %d\n", ret);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write, u8 command,
|
||||
int size, union i2c_smbus_data *data)
|
||||
@@ -593,7 +744,8 @@ power_normal:
|
||||
|
||||
static u32 cp2112_functionality(struct i2c_adapter *adap)
|
||||
{
|
||||
- return I2C_FUNC_SMBUS_BYTE |
|
||||
+ return I2C_FUNC_I2C |
|
||||
+ I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA |
|
||||
@@ -603,6 +755,7 @@ static u32 cp2112_functionality(struct i2c_adapter *adap)
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm smbus_algorithm = {
|
||||
+ .master_xfer = cp2112_i2c_xfer,
|
||||
.smbus_xfer = cp2112_xfer,
|
||||
.functionality = cp2112_functionality,
|
||||
};
|
||||
@@ -925,6 +1078,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
dev->adap.dev.parent = &hdev->dev;
|
||||
snprintf(dev->adap.name, sizeof(dev->adap.name),
|
||||
"CP2112 SMBus Bridge on hiddev%d", hdev->minor);
|
||||
+ dev->hwversion = buf[2];
|
||||
init_waitqueue_head(&dev->wait);
|
||||
|
||||
hid_device_io_start(hdev);
|
||||
|
||||
@@ -26,4 +26,5 @@ platform-powerpc-dni-7448-r0.patch
|
||||
platform-powerpc-quanta-lb9-r0.patch
|
||||
driver-support-intel-igb-bcm50210-phy.patch
|
||||
driver-igb-netberg-aurora.patch
|
||||
driver-hid-cp2112-mods.patch
|
||||
gcc-no-pie.patch
|
||||
|
||||
Reference in New Issue
Block a user