diff --git a/package/kernel/linux/modules/usb.mk b/package/kernel/linux/modules/usb.mk
index 4fe17f56ec2..2e449318ba9 100644
--- a/package/kernel/linux/modules/usb.mk
+++ b/package/kernel/linux/modules/usb.mk
@@ -1375,6 +1375,29 @@ endef
 $(eval $(call KernelPackage,usbip-server))
 
 
+define KernelPackage/usb-chipidea
+  TITLE:=Host and device support for Chipidea controllers
+  DEPENDS:=+USB_GADGET_SUPPORT:kmod-usb-gadget
+  KCONFIG:= \
+	CONFIG_NOP_USB_XCEIV=y \
+	CONFIG_EXTCON \
+	CONFIG_USB_CHIPIDEA \
+	CONFIG_USB_CHIPIDEA_HOST=y \
+	CONFIG_USB_CHIPIDEA_UDC=y \
+	CONFIG_USB_CHIPIDEA_DEBUG=y
+  FILES:= \
+	$(LINUX_DIR)/drivers/extcon/extcon.ko \
+	$(LINUX_DIR)/drivers/usb/chipidea/ci_hdrc.ko
+  AUTOLOAD:=$(call AutoLoad,51,ci_hdrc,0)
+  $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-chipidea/description
+ Kernel support for USB Chipidea controllers
+endef
+
+$(eval $(call KernelPackage,usb-chipidea))
+
 define KernelPackage/usbmon
   TITLE:=USB traffic monitor
   KCONFIG:=CONFIG_USB_MON
diff --git a/target/linux/ar71xx/Makefile b/target/linux/ar71xx/Makefile
index a8df2b036e9..ecc6d37051f 100644
--- a/target/linux/ar71xx/Makefile
+++ b/target/linux/ar71xx/Makefile
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 ARCH:=mips
 BOARD:=ar71xx
 BOARDNAME:=Atheros AR7xxx/AR9xxx
-FEATURES:=mips16
+FEATURES:=mips16 usbgadget
 CPU_TYPE:=24kc
 SUBTARGETS:=generic nand mikrotik
 
diff --git a/target/linux/ar71xx/patches-4.4/920-usb-chipidea-AR933x-platform-support.patch b/target/linux/ar71xx/patches-4.4/920-usb-chipidea-AR933x-platform-support.patch
new file mode 100644
index 00000000000..41eb7f2895a
--- /dev/null
+++ b/target/linux/ar71xx/patches-4.4/920-usb-chipidea-AR933x-platform-support.patch
@@ -0,0 +1,99 @@
+Index: linux-4.4.4/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+===================================================================
+--- linux-4.4.4.orig/arch/mips/include/asm/mach-ath79/ar71xx_regs.h	2016-03-31 21:43:10.595132564 +0300
++++ linux-4.4.4/arch/mips/include/asm/mach-ath79/ar71xx_regs.h	2016-03-31 21:56:21.463152017 +0300
+@@ -641,6 +641,7 @@
+ 
+ #define AR933X_BOOTSTRAP_MDIO_GPIO_EN	BIT(18)
+ #define AR933X_BOOTSTRAP_EEPBUSY	BIT(4)
++#define AR933X_BOOTSTRAP_USB_MODE_HOST	BIT(3)
+ #define AR933X_BOOTSTRAP_REF_CLK_40	BIT(0)
+ 
+ #define AR934X_BOOTSTRAP_SW_OPTION8	BIT(23)
+@@ -670,6 +671,8 @@
+ 
+ #define QCA956X_BOOTSTRAP_REF_CLK_40	BIT(2)
+ 
++#define AR933X_USB_CONFIG_HOST_ONLY   BIT(8)
++
+ #define AR934X_PCIE_WMAC_INT_WMAC_MISC		BIT(0)
+ #define AR934X_PCIE_WMAC_INT_WMAC_TX		BIT(1)
+ #define AR934X_PCIE_WMAC_INT_WMAC_RXLP		BIT(2)
+Index: linux-4.4.4/arch/mips/ath79/dev-usb.c
+===================================================================
+--- linux-4.4.4.orig/arch/mips/ath79/dev-usb.c	2016-03-31 21:43:10.407132560 +0300
++++ linux-4.4.4/arch/mips/ath79/dev-usb.c	2016-03-31 21:43:10.707132567 +0300
+@@ -19,6 +19,9 @@
+ #include <linux/platform_device.h>
+ #include <linux/usb/ehci_pdriver.h>
+ #include <linux/usb/ohci_pdriver.h>
++#include <linux/usb/otg.h>
++#include <linux/usb/chipidea.h>
++#include <linux/usb/usb_phy_generic.h>
+ 
+ #include <asm/mach-ath79/ath79.h>
+ #include <asm/mach-ath79/ar71xx_regs.h>
+@@ -170,6 +173,54 @@
+ 			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2));
+ }
+ 
++static void __init ar933x_usb_setup_ctrl_config(void)
++{
++	void __iomem *usb_ctrl_base, *usb_config_reg;
++	u32 usb_config;
++
++	usb_ctrl_base = ioremap(AR71XX_USB_CTRL_BASE, AR71XX_USB_CTRL_SIZE);
++	usb_config_reg = usb_ctrl_base + AR71XX_USB_CTRL_REG_CONFIG;
++	usb_config = __raw_readl(usb_config_reg);
++	usb_config &= ~AR933X_USB_CONFIG_HOST_ONLY;
++	__raw_writel(usb_config, usb_config_reg);
++	iounmap(usb_ctrl_base);
++}
++
++static void __init ar933x_ci_usb_setup(void)
++{
++	u32 bootstrap;
++	enum usb_dr_mode dr_mode;
++	struct ci_hdrc_platform_data ci_pdata;
++	struct platform_device *phy;
++
++	bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
++	if (bootstrap & AR933X_BOOTSTRAP_USB_MODE_HOST) {
++		dr_mode = USB_DR_MODE_HOST;
++	} else {
++		dr_mode = USB_DR_MODE_PERIPHERAL;
++		ar933x_usb_setup_ctrl_config();
++	}
++
++	memset(&ci_pdata, 0, sizeof(ci_pdata));
++	ci_pdata.name = "ci_hdrc_ar933x";
++	ci_pdata.capoffset = DEF_CAPOFFSET;
++	ci_pdata.dr_mode = dr_mode;
++	ci_pdata.flags = CI_HDRC_DUAL_ROLE_NOT_OTG | CI_HDRC_DP_ALWAYS_PULLUP;
++	ci_pdata.vbus_extcon.edev = ERR_PTR(-ENODEV);
++	ci_pdata.id_extcon.edev = ERR_PTR(-ENODEV);
++	ci_pdata.itc_setting = 1;
++
++	/* register a nop PHY */
++	phy = usb_phy_generic_register();
++	if (IS_ERR(phy))
++		return;
++
++	ath79_usb_register("ci_hdrc", -1,
++			   AR933X_EHCI_BASE, AR933X_EHCI_SIZE,
++			   ATH79_CPU_IRQ(3),
++			   &ci_pdata, sizeof(ci_pdata));
++}
++
+ static void __init ar933x_usb_setup(void)
+ {
+ 	ath79_device_reset_set(AR933X_RESET_USBSUS_OVERRIDE);
+@@ -185,6 +236,8 @@
+ 			   AR933X_EHCI_BASE, AR933X_EHCI_SIZE,
+ 			   ATH79_CPU_IRQ(3),
+ 			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2));
++
++	ar933x_ci_usb_setup();
+ }
+ 
+ static void enable_tx_tx_idp_violation_fix(unsigned base)
diff --git a/target/linux/ar71xx/patches-4.4/930-chipidea-pullup.patch b/target/linux/ar71xx/patches-4.4/930-chipidea-pullup.patch
new file mode 100644
index 00000000000..12568234bc8
--- /dev/null
+++ b/target/linux/ar71xx/patches-4.4/930-chipidea-pullup.patch
@@ -0,0 +1,80 @@
+Index: linux-4.4.4/drivers/usb/chipidea/ci.h
+===================================================================
+--- linux-4.4.4.orig/drivers/usb/chipidea/ci.h	2016-03-31 21:39:23.571126980 +0300
++++ linux-4.4.4/drivers/usb/chipidea/ci.h	2016-03-31 21:39:23.567126980 +0300
+@@ -199,6 +199,7 @@
+  * @in_lpm: if the core in low power mode
+  * @wakeup_int: if wakeup interrupt occur
+  * @rev: The revision number for controller
++ * @dp_always_pullup: keep dp always pullup at device mode
+  */
+ struct ci_hdrc {
+ 	struct device			*dev;
+@@ -248,6 +249,7 @@
+ 	bool				in_lpm;
+ 	bool				wakeup_int;
+ 	enum ci_revision		rev;
++	bool				dp_always_pullup;
+ };
+ 
+ static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
+Index: linux-4.4.4/drivers/usb/chipidea/core.c
+===================================================================
+--- linux-4.4.4.orig/drivers/usb/chipidea/core.c	2016-03-31 21:39:23.571126980 +0300
++++ linux-4.4.4/drivers/usb/chipidea/core.c	2016-03-31 21:41:33.159130168 +0300
+@@ -883,7 +883,7 @@
+ {
+ 	ci_hdrc_gadget_destroy(ci);
+ 	ci_hdrc_host_destroy(ci);
+-	if (ci->is_otg)
++	if (!ci->dp_always_pullup && ci->roles[CI_ROLE_GADGET])
+ 		ci_hdrc_otg_destroy(ci);
+ }
+ 
+@@ -933,6 +933,9 @@
+ 	ci->supports_runtime_pm = !!(ci->platdata->flags &
+ 		CI_HDRC_SUPPORTS_RUNTIME_PM);
+ 
++	ci->dp_always_pullup = !!(ci->platdata->flags &
++					 CI_HDRC_DP_ALWAYS_PULLUP);
++
+ 	ret = hw_device_init(ci, base);
+ 	if (ret < 0) {
+ 		dev_err(dev, "can't initialize hardware\n");
+@@ -998,7 +1001,7 @@
+ 		goto deinit_phy;
+ 	}
+ 
+-	if (ci->is_otg && ci->roles[CI_ROLE_GADGET]) {
++	if (!ci->dp_always_pullup && ci->roles[CI_ROLE_GADGET]) {
+ 		ret = ci_hdrc_otg_init(ci);
+ 		if (ret) {
+ 			dev_err(dev, "init otg fails, ret = %d\n", ret);
+Index: linux-4.4.4/drivers/usb/chipidea/otg.c
+===================================================================
+--- linux-4.4.4.orig/drivers/usb/chipidea/otg.c	2016-03-31 21:39:23.571126980 +0300
++++ linux-4.4.4/drivers/usb/chipidea/otg.c	2016-03-31 21:39:23.567126980 +0300
+@@ -95,8 +95,10 @@
+ 
+ void ci_handle_vbus_change(struct ci_hdrc *ci)
+ {
+-	if (!ci->is_otg)
++	if (ci->dp_always_pullup) {
++		usb_gadget_vbus_connect(&ci->gadget);
+ 		return;
++	}
+ 
+ 	if (hw_read_otgsc(ci, OTGSC_BSV))
+ 		usb_gadget_vbus_connect(&ci->gadget);
+Index: linux-4.4.4/include/linux/usb/chipidea.h
+===================================================================
+--- linux-4.4.4.orig/include/linux/usb/chipidea.h	2016-03-31 21:39:23.571126980 +0300
++++ linux-4.4.4/include/linux/usb/chipidea.h	2016-03-31 21:39:23.567126980 +0300
+@@ -55,6 +55,7 @@
+ #define CI_HDRC_OVERRIDE_AHB_BURST	BIT(9)
+ #define CI_HDRC_OVERRIDE_TX_BURST	BIT(10)
+ #define CI_HDRC_OVERRIDE_RX_BURST	BIT(11)
++#define CI_HDRC_DP_ALWAYS_PULLUP BIT(12)
+ 	enum usb_dr_mode	dr_mode;
+ #define CI_HDRC_CONTROLLER_RESET_EVENT		0
+ #define CI_HDRC_CONTROLLER_STOPPED_EVENT	1