From 1db23779385dbf71e51aaa52950e4741fe340d0a Mon Sep 17 00:00:00 2001
From: "ganesh.andhale" <ganesh.andhale@einfochips.com>
Date: Thu, 28 Oct 2021 17:37:27 +0530
Subject: [PATCH 5/5] Updated-linux-Added-LTE-USB-support

---
 arch/arm/boot/dts/am335x-evse.dts | 39 ++++++++++++++++++++++++++++++-
 drivers/net/usb/qmi_wwan.c        | 27 ++++++++++++++++++++-
 drivers/usb/serial/option.c       | 22 +++++++++++++++++
 drivers/usb/serial/usb_wwan.c     | 14 +++++++++++
 4 files changed, 100 insertions(+), 2 deletions(-)
 mode change 100644 => 100755 drivers/net/usb/qmi_wwan.c
 mode change 100644 => 100755 drivers/usb/serial/option.c
 mode change 100644 => 100755 drivers/usb/serial/usb_wwan.c

diff --git a/arch/arm/boot/dts/am335x-evse.dts b/arch/arm/boot/dts/am335x-evse.dts
index 28a7a66c9..075422657 100644
--- a/arch/arm/boot/dts/am335x-evse.dts
+++ b/arch/arm/boot/dts/am335x-evse.dts
@@ -44,7 +44,7 @@

 &am33xx_pinmux {
   pinctrl-names = "default";
-  pinctrl-0 = <&oled_gpio>;
+  pinctrl-0 = <&oled_gpio &lte_gpio>;

   i2c0_pins: pinmux_i2c0_pins {
     pinctrl-single,pins = <
@@ -60,6 +60,12 @@
     >;
   };

+  usb0_pins_default: usb0_pins_default {
+    pinctrl-single,pins = <
+      AM33XX_IOPAD(0xa1c, PIN_OUTPUT | MUX_MODE0) /* (G16) USB0_DRVVBUS.USB0_DRVVBUS */
+    >;
+  };
+
   oled_gpio: pinmux_oled_pins {
     pinctrl-single,pins = <
       AM33XX_IOPAD(0x8b8, PIN_OUTPUT_PULLUP | MUX_MODE7) /* (V3) lcd_data6.gpio2[12] OLED Power - EN */
@@ -68,6 +74,14 @@
     >;
   };

+  lte_gpio: lte_gpio {
+    pinctrl-single,pins = <
+      AM33XX_IOPAD(0x824, PIN_OUTPUT_PULLUP | MUX_MODE7) /* (W16) gpmc_ad9.gpio0[23] */
+      AM33XX_IOPAD(0x828, PIN_OUTPUT_PULLUP | MUX_MODE7) /* (T12) gpmc_ad10.gpio0[26] */
+      AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE7) /* (V8) gpmc_be0n_cle.gpio2[5] */
+    >;
+  };
+
   sdcard_pins: pinmux_sdcard_pins {
     pinctrl-single,pins = <
       AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE5)        /* (B16) spi0_cs1.mmc0_sdcd  */
@@ -104,6 +118,29 @@
   status = "okay";
 };

+&usb {
+       status = "okay";
+};
+
+&usb_ctrl_mod {
+        status = "okay";
+};
+
+&usb0_phy {
+        status = "okay";
+};
+
+&usb0 {
+       status = "okay";
+       dr_mode = "host";
+       pinctrl-0 = <&usb0_pins_default>;
+       gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>, <&gpio0 26 GPIO_ACTIVE_HIGH>;
+};
+
+&cppi41dma {
+        status = "okay";
+};
+
 &i2c0 {
   pinctrl-names = "default";
   pinctrl-0 = <&i2c0_pins>;
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
old mode 100644
new mode 100755
index 6508d7005..594e91be5
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -45,6 +45,26 @@
  * commands on a serial interface
  */

+#if 1 //Added by Quectel
+struct sk_buff *qmi_wwan_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+if (dev->udev->descriptor.idVendor != cpu_to_le16(0x2C7C))
+return skb;
+// Skip Ethernet header from message
+if (dev->net->hard_header_len == 0)
+return skb;
+else
+skb_reset_mac_header(skb); if (skb_pull(skb, ETH_HLEN)) {
+return skb;
+} else {
+dev_err(&dev->intf->dev, "Packet Dropped ");
+}
+// Filter the packet out, release it
+dev_kfree_skb_any(skb);
+return NULL;
+}
+#endif
+
 /* driver specific data */
 struct qmi_wwan_state {
        struct usb_driver *subdriver;
@@ -891,7 +911,11 @@ static const struct driver_info    qmi_wwan_info = {
        .bind           = qmi_wwan_bind,
        .unbind         = qmi_wwan_unbind,
        .manage_power   = qmi_wwan_manage_power,
-       .rx_fixup       = qmi_wwan_rx_fixup,
+       //.rx_fixup       = qmi_wwan_rx_fixup,
+       #if 1 //Added by Quectel
+       .tx_fixup = qmi_wwan_tx_fixup,
+       .rx_fixup = qmi_wwan_rx_fixup,
+       #endif
 };

 static const struct driver_info        qmi_wwan_info_quirk_dtr = {
@@ -1334,6 +1358,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x0b3c, 0xc00a, 6)},    /* Olivetti Olicard 160 */
        {QMI_FIXED_INTF(0x0b3c, 0xc00b, 4)},    /* Olivetti Olicard 500 */
        {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)},    /* Cinterion PLxx */
+       {QMI_FIXED_INTF(0x2C7C, 0x0306, 4)},    /* Quectel EG06/EP06/EM06 */
        {QMI_QUIRK_SET_DTR(0x1e2d, 0x006f, 8)}, /* Cinterion PLS83/PLS63 */
        {QMI_FIXED_INTF(0x1e2d, 0x0053, 4)},    /* Cinterion PHxx,PXxx */
        {QMI_FIXED_INTF(0x1e2d, 0x0063, 10)},   /* Cinterion ALASxx (1 RmNet) */
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
old mode 100644
new mode 100755
index 5c167bc08..658d89c66
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -2045,6 +2045,7 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = RSVD(4) },
        { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) },                   /* OLICARD300 - MT6225 */
        { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
+       { USB_DEVICE(0x2C7C, 0x0306) },                                                         /* QUECTEL EM06 */
        { USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) },
        { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD200, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_6802, 0xff, 0xff, 0xff) },
@@ -2106,6 +2107,10 @@ static struct usb_serial_driver option_1port_device = {
        .suspend           = usb_wwan_suspend,
        .resume            = usb_wwan_resume,
 #endif
+#if 1 //Added by Quectel
+       .reset_resume = usb_wwan_resume,
+#endif
+
 };

 static struct usb_serial_driver * const serial_drivers[] = {
@@ -2148,6 +2153,23 @@ static int option_probe(struct usb_serial *serial,
        if (device_flags & NUMEP2 && iface_desc->bNumEndpoints != 2)
                return -ENODEV;

+#if 1 //Added by Quectel
+//Quectel UC20's interface 4 can be used as USB network device
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
+                       serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)
+                               && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
+               return -ENODEV;
+//Quectel EC20's interface 4 can be used as USB network device
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
+               serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)
+                       && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
+               return -ENODEV;
+//Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96/AG35's interface 4 can be used as USB network device
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)
+               && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
+               return -ENODEV;
+#endif
+
        /* Store the device flags so we can use them during attach. */
        usb_set_serial_data(serial, (void *)device_flags);

diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
old mode 100644
new mode 100755
index 4b9845807..426449728
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -479,6 +479,20 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
        if (intfdata->use_zlp && dir == USB_DIR_OUT)
                urb->transfer_flags |= URB_ZERO_PACKET;

+       #if 1 //Added by Quectel for zero packet
+       if (dir == USB_DIR_OUT) {
+       struct usb_device_descriptor *desc = &serial->dev->descriptor;
+       if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9090))
+               urb->transfer_flags |= URB_ZERO_PACKET;
+       if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9003))
+               urb->transfer_flags |= URB_ZERO_PACKET;
+       if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9215))
+               urb->transfer_flags |= URB_ZERO_PACKET;
+       if (desc->idVendor == cpu_to_le16(0x2C7C))
+               urb->transfer_flags |= URB_ZERO_PACKET;
+       }
+       #endif
+
        return urb;
 }

--
2.17.1