meta-ampere: Support virtual Ethernet over USB device

Implement systemd service to create an Ethernet over USB interface
for communication between CPU and BMC.

Tested:
1. Check usb0 ethernet interface in BMC console
root@mtjade:~# ifconfig usb0
usb0      Link encap:Ethernet  HWaddr DA:F7:E9:A3:5A:0C
          inet addr:192.168.0.10  Bcast:192.168.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:412 (412.0 B)
2. Check USB Ethernet device on Host Linux
$ lsusb | grep Ethernet
Bus 001 Device 004: ID 1d6b:0103 Linux Foundation NCM (Ethernet) Gadget

Signed-off-by: Chanh Nguyen <chanh@os.amperecomputing.com>
Signed-off-by: Thang Q. Nguyen <thang@os.amperecomputing.com>
Change-Id: Icb7c096df426233e8f2ee7318f2a1805f07ab3a7
diff --git a/meta-common/recipes-ac01/usbnet/ampere-usbnet.bb b/meta-common/recipes-ac01/usbnet/ampere-usbnet.bb
new file mode 100644
index 0000000..f683f80
--- /dev/null
+++ b/meta-common/recipes-ac01/usbnet/ampere-usbnet.bb
@@ -0,0 +1,30 @@
+SUMMARY = "Ampere Computing LLC Add Ethernet over USB gadget device"
+DESCRIPTION = "Add Ethernet over USB gadget device for Ampere systems"
+PR = "r1"
+
+LICENSE = "Apache-2.0"
+S = "${WORKDIR}"
+
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+inherit systemd
+inherit obmc-phosphor-systemd
+
+DEPENDS = "systemd"
+RDEPENDS_${PN} = "bash"
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = " \
+        ampere_add_usbnet_gadget.service \
+        "
+
+SRC_URI += "file://00-bmc-usb0.network"
+SRC_URI += "file://ampere_add_usbnet_gadget.sh"
+
+do_install_append() {
+        install -d ${D}${sbindir}
+        install -d ${D}/etc/systemd/network
+        install -m 744 ${WORKDIR}/ampere_add_usbnet_gadget.sh ${D}${sbindir}/
+        install -m 644 ${WORKDIR}/00-bmc-usb0.network \
+                       ${D}/etc/systemd/network/
+}
diff --git a/meta-common/recipes-ac01/usbnet/ampere-usbnet/00-bmc-usb0.network b/meta-common/recipes-ac01/usbnet/ampere-usbnet/00-bmc-usb0.network
new file mode 100644
index 0000000..640fe04
--- /dev/null
+++ b/meta-common/recipes-ac01/usbnet/ampere-usbnet/00-bmc-usb0.network
@@ -0,0 +1,7 @@
+[Match]
+Name=usb0
+[Address]
+Address=192.168.0.10/16
+[Network]
+LinkLocalAddressing=no
+IPv6AcceptRA=no
diff --git a/meta-common/recipes-ac01/usbnet/ampere-usbnet/ampere_add_usbnet_gadget.service b/meta-common/recipes-ac01/usbnet/ampere-usbnet/ampere_add_usbnet_gadget.service
new file mode 100644
index 0000000..428263a
--- /dev/null
+++ b/meta-common/recipes-ac01/usbnet/ampere-usbnet/ampere_add_usbnet_gadget.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Ampere adds Ethernet over USB gadget device
+Wants=systemd-networkd.service
+Before=systemd-networkd.service
+After=phosphor-ipmi-host.service
+
+[Service]
+ExecStart=/usr/bin/env ampere_add_usbnet_gadget.sh
+SyslogIdentifier=ampere_add_usbnet_gadget.sh
+Type=oneshot
+
+[Install]
+WantedBy=systemd-networkd.service
diff --git a/meta-common/recipes-ac01/usbnet/ampere-usbnet/ampere_add_usbnet_gadget.sh b/meta-common/recipes-ac01/usbnet/ampere-usbnet/ampere_add_usbnet_gadget.sh
new file mode 100644
index 0000000..c4c2c27
--- /dev/null
+++ b/meta-common/recipes-ac01/usbnet/ampere-usbnet/ampere_add_usbnet_gadget.sh
@@ -0,0 +1,93 @@
+#!/bin/sh
+
+# Add an Ethernet over USB gadget device and connect to a port of Aspeed USB
+# virtual hub. If can't find any free port on virtual hub, exit with failure.
+# If can't find the virtual hub, exit with failure.
+
+# Author: Thinh Hung Pham <thinh.pham@amperecomputing.com>
+# Signed-off-by: Chanh Nguyen <chnguyen@amperecomputing.com>
+
+UDC_SYSPATH=/sys/class/udc
+VHUB_DEVICE=1e6a0000.usb-vhub:p
+GADGET_CONFIG_SYSPATH=/sys/kernel/config/usb_gadget
+USBNET=usbnet
+# The number of port on AST2500 USB virtual hub
+NUM_PORT_USB_HUB=5
+# idVendor = 0x1d6b: Linux Foundation
+VENDORID=0x1d6b
+# idProduct = 0x0103: NCM (Ethernet) Gadget
+PRODUCTID=0x0103
+# Language code = 0x409: English – United States
+LANGUAGEID=0x409
+SERIALNUMBER=cafecafe
+MANUFACTURER=Aspeed
+FUNCTION=ecm.usb0
+
+if [ ! -d ${GADGET_CONFIG_SYSPATH} ]; then
+	# GADGET_CONFIG_SYSPATH is not exist
+	# Return 1 so that systemd knows the service failed to start
+	echo "ERROR: ${GADGET_CONFIG_SYSPATH} : doesn't exist!"
+	exit 1
+fi
+
+find_free_vhub_port(){
+	for ((i=1;i<=${NUM_PORT_USB_HUB};i++))
+	do
+		state=$(cat ${UDC_SYSPATH}/${VHUB_DEVICE}${i}/state)
+		func=$(cat ${UDC_SYSPATH}/${VHUB_DEVICE}${i}/function)
+		if [ "${state}" == "not attached" -a "${func}" == "" ]; then
+			FREEUDC=${VHUB_DEVICE}${i}
+			break
+		fi
+	done
+	if [ ${i} -eq 6 ]; then
+		# Can't find a free port
+		# Return 1 so that systemd knows the service failed to start
+		echo "ERROR: Can't find a free port !"
+		exit 1
+	fi
+}
+
+if [ -d ${GADGET_CONFIG_SYSPATH}/${USBNET} ]; then
+	cd ${GADGET_CONFIG_SYSPATH}/${USBNET}
+else
+	# Create the gadget
+	mkdir ${GADGET_CONFIG_SYSPATH}/${USBNET}
+	cd ${GADGET_CONFIG_SYSPATH}/${USBNET}
+
+	# Configure the gadget
+	echo ${VENDORID} > idVendor
+	echo ${PRODUCTID} > idProduct
+	mkdir strings/${LANGUAGEID}
+	echo ${SERIALNUMBER} > strings/${LANGUAGEID}/serialnumber
+	echo ${MANUFACTURER} > strings/${LANGUAGEID}/manufacturer
+	echo ${USBNET} > strings/${LANGUAGEID}/product
+
+	# Create the configuration
+	mkdir configs/c.1
+	mkdir configs/c.1/strings/${LANGUAGEID}
+
+	# Create the function
+	mkdir functions/${FUNCTION}
+
+	# Associate the function with its configuration
+	ln -s functions/${FUNCTION} configs/c.1
+fi
+
+# Find an available virtual hub port
+find_free_vhub_port
+
+# Enable the gadget
+echo ${FREEUDC} > UDC
+
+if [[ $? -ne 0 ]]; then
+	# End
+	cd - > /dev/null
+	# Virtual HUB is not available
+	# Return 1 so that systemd knows the service failed to start
+	exit 1
+fi
+
+# End
+cd - > /dev/null
+
diff --git a/meta-jade/conf/machine/mtjade.conf b/meta-jade/conf/machine/mtjade.conf
index c7bf92b..5999392 100644
--- a/meta-jade/conf/machine/mtjade.conf
+++ b/meta-jade/conf/machine/mtjade.conf
@@ -7,3 +7,7 @@
 require conf/distro/include/phosphor-isolation.inc
 
 VOLATILE_LOG_DIR = "no"
+
+OBMC_IMAGE_EXTRA_INSTALL_append = "\
+                                   ampere-usbnet \
+                                  "
diff --git a/meta-jade/recipes-kernel/linux/linux-aspeed/mtjade.cfg b/meta-jade/recipes-kernel/linux/linux-aspeed/mtjade.cfg
index 9afe14a..fdda06d 100644
--- a/meta-jade/recipes-kernel/linux/linux-aspeed/mtjade.cfg
+++ b/meta-jade/recipes-kernel/linux/linux-aspeed/mtjade.cfg
@@ -14,3 +14,9 @@
 CONFIG_SENSORS_LM75=y
 CONFIG_I2C_SLAVE=y
 CONFIG_SENSORS_ASPEED=y
+
+CONFIG_USB_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_ASPEED_VHUB=y
+CONFIG_USB_CONFIGFS_ECM=y