From ccd98c68bae73be658319dc9ab1f2a6ab3fafa87 Mon Sep 17 00:00:00 2001 From: Kevin Mihelich Date: Fri, 3 Jul 2015 02:06:55 +0000 Subject: [PATCH] core/linux-veyron to 3.14.0-5 --- .../0001-use-chromiumos-mwifiex-drivers.patch | 2 +- ...reate-AP-and-P2P-interfaces-upon-dri.patch | 2 +- ...kchip-add-handler-for-usb-uart-funct.patch | 306 ++++++++++++++++++ ...fix-brcmfmac-oops-and-race-condition.patch | 114 +++++++ core/linux-veyron/PKGBUILD | 14 +- core/linux-veyron/config | 1 + 6 files changed, 433 insertions(+), 6 deletions(-) create mode 100644 core/linux-veyron/0003-UPSTREAM-soc-rockchip-add-handler-for-usb-uart-funct.patch create mode 100644 core/linux-veyron/0004-fix-brcmfmac-oops-and-race-condition.patch diff --git a/core/linux-veyron/0001-use-chromiumos-mwifiex-drivers.patch b/core/linux-veyron/0001-use-chromiumos-mwifiex-drivers.patch index c737a8a21..a922f00ca 100644 --- a/core/linux-veyron/0001-use-chromiumos-mwifiex-drivers.patch +++ b/core/linux-veyron/0001-use-chromiumos-mwifiex-drivers.patch @@ -1,7 +1,7 @@ From d1f7cbbd8efbc022222d84a697595ba9f6637de0 Mon Sep 17 00:00:00 2001 From: Kevin Mihelich Date: Thu, 25 Jun 2015 20:35:06 -0600 -Subject: [PATCH 1/2] use chromiumos mwifiex drivers +Subject: [PATCH 1/4] use chromiumos mwifiex drivers Signed-off-by: Kevin Mihelich --- diff --git a/core/linux-veyron/0002-mwifiex-do-not-create-AP-and-P2P-interfaces-upon-dri.patch b/core/linux-veyron/0002-mwifiex-do-not-create-AP-and-P2P-interfaces-upon-dri.patch index b0f6a43c6..7842d8fc9 100644 --- a/core/linux-veyron/0002-mwifiex-do-not-create-AP-and-P2P-interfaces-upon-dri.patch +++ b/core/linux-veyron/0002-mwifiex-do-not-create-AP-and-P2P-interfaces-upon-dri.patch @@ -1,7 +1,7 @@ From d24fdf29978108413eb405302255139fdbb94a16 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Mon, 19 Aug 2013 16:10:21 -0700 -Subject: [PATCH 2/2] mwifiex: do not create AP and P2P interfaces upon driver +Subject: [PATCH 2/4] mwifiex: do not create AP and P2P interfaces upon driver loading Bug 60747 - 1286:2044 [Microsoft Surface Pro] diff --git a/core/linux-veyron/0003-UPSTREAM-soc-rockchip-add-handler-for-usb-uart-funct.patch b/core/linux-veyron/0003-UPSTREAM-soc-rockchip-add-handler-for-usb-uart-funct.patch new file mode 100644 index 000000000..cdcb9f93a --- /dev/null +++ b/core/linux-veyron/0003-UPSTREAM-soc-rockchip-add-handler-for-usb-uart-funct.patch @@ -0,0 +1,306 @@ +From c0c863786b85a631e22eeae78f572d3f151af490 Mon Sep 17 00:00:00 2001 +From: Heiko Stuebner +Date: Mon, 25 May 2015 16:38:07 +0200 +Subject: [PATCH 3/4] UPSTREAM: soc/rockchip: add handler for usb-uart + functionality + +Some Rockchip SoCs provide the possibility to use a usb-phy as passthru for +the debug uart, making it possible to get console output without needing to +open the device. + +This patch adds an early_initcall to enable this functionality conditionally +and also disables the corresponding usb controller in the devicetree. + +Change-Id: I397df8f402c752125cf512332398757b91a899f8 +Signed-off-by: Alexandru M Stan +--- + drivers/soc/Kconfig | 1 + + drivers/soc/Makefile | 1 + + drivers/soc/rockchip/Kconfig | 13 ++ + drivers/soc/rockchip/Makefile | 1 + + drivers/soc/rockchip/rockchip_usb_uart.c | 223 +++++++++++++++++++++++++++++++ + 5 files changed, 239 insertions(+) + create mode 100644 drivers/soc/rockchip/Kconfig + create mode 100644 drivers/soc/rockchip/Makefile + create mode 100644 drivers/soc/rockchip/rockchip_usb_uart.c + +diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig +index 1ee0b57..ad2f71a 100644 +--- a/drivers/soc/Kconfig ++++ b/drivers/soc/Kconfig +@@ -2,6 +2,7 @@ menu "SOC (System On Chip) specific Drivers" + + source "drivers/soc/img/Kconfig" + source "drivers/soc/qcom/Kconfig" ++source "drivers/soc/rockchip/Kconfig" + source "drivers/soc/tegra/Kconfig" + + endmenu +diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile +index bc43b87..d80386c 100644 +--- a/drivers/soc/Makefile ++++ b/drivers/soc/Makefile +@@ -4,4 +4,5 @@ + + obj-$(CONFIG_SOC_IMG) += img/ + obj-$(CONFIG_ARCH_QCOM) += qcom/ ++obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ + obj-$(CONFIG_ARCH_TEGRA) += tegra/ +diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig +new file mode 100644 +index 0000000..24d4e05 +--- /dev/null ++++ b/drivers/soc/rockchip/Kconfig +@@ -0,0 +1,13 @@ ++# ++# Rockchip Soc drivers ++# ++config ROCKCHIP_USB_UART ++ bool "Rockchip usb-uart override" ++ depends on ARCH_ROCKCHIP ++ select MFD_SYSCON ++ help ++ Say y here to enable usb-uart functionality. Newer Rockchip SoCs ++ provide means to repurpose one usb phy as uart2 output, making it ++ possible to get debug output without needing to open a device. ++ To enable this function on boot, add a rockchip.usb_uart option ++ to the kernel commandline. +diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile +new file mode 100644 +index 0000000..b5dd6f8 +--- /dev/null ++++ b/drivers/soc/rockchip/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_ROCKCHIP_USB_UART) += rockchip_usb_uart.o +diff --git a/drivers/soc/rockchip/rockchip_usb_uart.c b/drivers/soc/rockchip/rockchip_usb_uart.c +new file mode 100644 +index 0000000..97754f9 +--- /dev/null ++++ b/drivers/soc/rockchip/rockchip_usb_uart.c +@@ -0,0 +1,223 @@ ++/* ++ * Copyright (c) 2015 Heiko Stuebner ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define HIWORD_UPDATE(val, mask) \ ++ ((val) | (mask) << 16) ++ ++struct rockchip_uart_data { ++ const char *grf_compatible; ++ const char *usb_compatible; ++ phys_addr_t usb_phys_addr; ++ int (*init_uart)(const struct rockchip_uart_data *data, ++ struct regmap *grf); ++}; ++ ++static int enable_usb_uart = 0; ++ ++#define RK3288_UOC0_CON0 0x320 ++#define RK3288_UOC0_CON0_COMMON_ON_N BIT(0) ++#define RK3288_UOC0_CON0_DISABLE BIT(4) ++ ++#define RK3288_UOC0_CON2 0x328 ++#define RK3288_UOC0_CON2_SOFT_CON_SEL BIT(2) ++ ++#define RK3288_UOC0_CON3 0x32c ++#define RK3288_UOC0_CON3_UTMI_SUSPENDN BIT(0) ++#define RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING (1 << 1) ++#define RK3288_UOC0_CON3_UTMI_OPMODE_MASK (3 << 1) ++#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC (1 << 3) ++#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK (3 << 3) ++#define RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED BIT(5) ++#define RK3288_UOC0_CON3_BYPASSDMEN BIT(6) ++#define RK3288_UOC0_CON3_BYPASSSEL BIT(7) ++ ++/* ++ * Enable the bypass of uart2 data through the otg usb phy. ++ * Original description in the TRM. ++ * 1. Disable the OTG block by setting OTGDISABLE0 to 1’b1. ++ * 2. Disable the pull-up resistance on the D+ line by setting OPMODE0[1:0] to 2’b01. ++ * 3. To ensure that the XO, Bias, and PLL blocks are powered down in Suspend mode, set COMMONONN to 1’b1. ++ * 4. Place the USB PHY in Suspend mode by setting SUSPENDM0 to 1’b0. ++ * 5. Set BYPASSSEL0 to 1’b1. ++ * 6. To transmit data, controls BYPASSDMEN0, and BYPASSDMDATA0. ++ * To receive data, monitor FSVPLUS0. ++ * ++ * The actual code in the vendor kernel does some things differently. ++ */ ++static int __init rk3288_init_usb_uart(const struct rockchip_uart_data *data, ++ struct regmap *grf) ++{ ++ u32 val; ++ int ret; ++ ++ pr_info("%s\n", __func__); ++ ++ /* ++ * COMMON_ON and DISABLE settings are described in the TRM, ++ * but where not present in the original code. ++ */ ++ val = HIWORD_UPDATE(RK3288_UOC0_CON0_COMMON_ON_N ++ | RK3288_UOC0_CON0_DISABLE, ++ RK3288_UOC0_CON0_COMMON_ON_N ++ | RK3288_UOC0_CON0_DISABLE); ++ ret = regmap_write(grf, RK3288_UOC0_CON0, val); ++ if (ret) ++ return ret; ++ ++ // FIXME: this makes my system hang, for whatever reason ++ val = HIWORD_UPDATE(RK3288_UOC0_CON2_SOFT_CON_SEL, ++ RK3288_UOC0_CON2_SOFT_CON_SEL); ++ ret = regmap_write(grf, RK3288_UOC0_CON2, val); ++ if (ret) ++ return ret; ++ ++ val = HIWORD_UPDATE(RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING ++ | RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC ++ | RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED, ++ RK3288_UOC0_CON3_UTMI_SUSPENDN ++ | RK3288_UOC0_CON3_UTMI_OPMODE_MASK ++ | RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK ++ | RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED); ++ ret = regmap_write(grf, RK3288_UOC0_CON3, val); ++ if (ret) ++ return ret; ++ ++ val = HIWORD_UPDATE(RK3288_UOC0_CON3_BYPASSSEL ++ | RK3288_UOC0_CON3_BYPASSDMEN, ++ RK3288_UOC0_CON3_BYPASSSEL ++ | RK3288_UOC0_CON3_BYPASSDMEN); ++ ret = regmap_write(grf, RK3288_UOC0_CON3, val); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++const struct rockchip_uart_data rk3288_uart_data = { ++ .grf_compatible = "rockchip,rk3288-grf", ++ .usb_compatible = "rockchip,rk3288-usb", ++ .usb_phys_addr = 0xff580000, ++ .init_uart = rk3288_init_usb_uart, ++}; ++ ++static const struct of_device_id rockchip_usb_uart_ids[] = { ++ { .compatible = "rockchip,rk3288", .data = &rk3288_uart_data }, ++ { } ++}; ++ ++/* ++ * Find the usb controller using the shared usb-uart-phy in the dts and ++ * disable it. ++ */ ++static int __init ++rockchip_disable_usb_controller(const struct rockchip_uart_data *data) ++{ ++ struct device_node *np; ++ ++ for_each_compatible_node(np, NULL, data->usb_compatible) { ++ struct property *new_status; ++ struct resource res; ++ int ret; ++ ++ ret = of_address_to_resource(np, 0, &res); ++ if (ret) { ++ pr_err("%s: could not get address of usb controller %s\n", ++ __func__, np->full_name); ++ continue; ++ } ++ ++ /* not the controller we're looking for */ ++ if (res.start != data->usb_phys_addr) ++ continue; ++ ++ pr_info("%s: disabling usb controller %s\n", ++ __func__, np->full_name); ++ ++ new_status = kzalloc(sizeof(*new_status), GFP_KERNEL); ++ if (!new_status) ++ return -ENOMEM; ++ ++ new_status->name = kstrdup("status", GFP_KERNEL); ++ new_status->length = sizeof("disabled"); ++ new_status->value = kstrdup("disabled", GFP_KERNEL); ++ ++ return of_update_property(np, new_status); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id *rockchip_usb_uart_data_lookup(void) ++{ ++ struct device_node *root; ++ const struct of_device_id *id; ++ ++ root = of_find_node_by_path("/"); ++ if (!root) ++ return NULL; ++ ++ id = of_match_node(rockchip_usb_uart_ids, root); ++ of_node_put(root); ++ ++ return id; ++} ++ ++static int __init rockchip_init_usb_uart(void) ++{ ++ const struct of_device_id *match; ++ const struct rockchip_uart_data *data; ++ struct regmap *grf; ++ int ret; ++ ++ if (!enable_usb_uart) ++ return 0; ++ ++ match = rockchip_usb_uart_data_lookup(); ++ if (!match) ++ return -ENOTSUPP; ++ ++ pr_info("%s: using settings for %s\n", __func__, match->compatible); ++ data = match->data; ++ ++ grf = syscon_regmap_lookup_by_compatible(data->grf_compatible); ++ if (IS_ERR(grf)) { ++ pr_err("%s: could not find GRF syscon\n", __func__); ++ return PTR_ERR(grf); ++ } ++ ++ ret = data->init_uart(data, grf); ++ if (ret) { ++ pr_err("%s: could not init usb_uart\n", __func__); ++ return ret; ++ } ++ ++ return rockchip_disable_usb_controller(data); ++} ++early_initcall(rockchip_init_usb_uart); ++ ++static int __init rockchip_usb_uart(char *buf) ++{ ++ enable_usb_uart = true; ++ return 0; ++} ++early_param("rockchip.usb_uart", rockchip_usb_uart); +-- +2.4.4 + diff --git a/core/linux-veyron/0004-fix-brcmfmac-oops-and-race-condition.patch b/core/linux-veyron/0004-fix-brcmfmac-oops-and-race-condition.patch new file mode 100644 index 000000000..60f9f3b6c --- /dev/null +++ b/core/linux-veyron/0004-fix-brcmfmac-oops-and-race-condition.patch @@ -0,0 +1,114 @@ +From 6dc781566c97f06b5c0d491f34c9b23e72cb74be Mon Sep 17 00:00:00 2001 +From: Kevin Mihelich +Date: Thu, 2 Jul 2015 17:48:41 -0600 +Subject: [PATCH 4/4] fix brcmfmac oops and race condition + +This fixes a potential null pointer dereference by checking if null before +freeing the vif struct. + +Also works around a race condition between brcm_patchram_plus loading the BT +firmware, which exposes the wireless device, and the kernel loading bcrmfmac. +100ms delay loops up to 1s are added around the first three initialization +functions to hold off a failure until the device is actually ready. This is a +hack. + +Signed-off-by: Kevin Mihelich +--- + .../wireless-3.8/brcm80211/brcmfmac/dhd_common.c | 47 ++++++++++++++-------- + .../wireless-3.8/brcm80211/brcmfmac/dhd_linux.c | 4 +- + 2 files changed, 32 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/wireless-3.8/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless-3.8/brcm80211/brcmfmac/dhd_common.c +index 05d4042..7006d19 100644 +--- a/drivers/net/wireless-3.8/brcm80211/brcmfmac/dhd_common.c ++++ b/drivers/net/wireless-3.8/brcm80211/brcmfmac/dhd_common.c +@@ -252,25 +252,34 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) + struct brcmf_join_pref_params join_pref_params[2]; + char *ptr; + s32 err; ++ int i; + + /* retreive mac address */ +- err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, +- sizeof(ifp->mac_addr)); +- if (err < 0) { +- brcmf_err("Retreiving cur_etheraddr failed, %d\n", +- err); +- goto done; ++ for (i = 0; i < 9; i++) { ++ err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, ++ sizeof(ifp->mac_addr)); ++ if (err < 0 && i == 9) { ++ brcmf_err("Retreiving cur_etheraddr failed, %d\n", ++ err); ++ goto done; ++ } else { ++ msleep(100); ++ } + } + memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); + + /* query for 'ver' to get version info from firmware */ +- memset(buf, 0, sizeof(buf)); +- strcpy(buf, "ver"); +- err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); +- if (err < 0) { +- brcmf_err("Retreiving version information failed, %d\n", +- err); +- goto done; ++ for (i = 0; i < 10; i++) { ++ memset(buf, 0, sizeof(buf)); ++ strcpy(buf, "ver"); ++ err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); ++ if (err < 0 && i == 9) { ++ brcmf_err("Retreiving version information failed, %d\n", ++ err); ++ goto done; ++ } else { ++ msleep(100); ++ } + } + ptr = (char *)buf; + strsep(&ptr, "\n"); +@@ -283,10 +292,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) + strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); + + /* set mpc */ +- err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); +- if (err) { +- brcmf_err("failed setting mpc\n"); +- goto done; ++ for (i = 0; i < 10; i++) { ++ err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); ++ if (err && i == 9) { ++ brcmf_err("failed setting mpc\n"); ++ goto done; ++ } else { ++ msleep(100); ++ } + } + + /* +diff --git a/drivers/net/wireless-3.8/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless-3.8/brcm80211/brcmfmac/dhd_linux.c +index 128161c..d3db8f7 100644 +--- a/drivers/net/wireless-3.8/brcm80211/brcmfmac/dhd_linux.c ++++ b/drivers/net/wireless-3.8/brcm80211/brcmfmac/dhd_linux.c +@@ -974,13 +974,13 @@ fail: + brcmf_fws_deinit(drvr); + } + if (drvr->iflist[0]) { +- if (ifp->ndev->destructor == NULL) ++ if (ifp->ndev->destructor == NULL && ifp->vif) + brcmf_free_vif(ifp->vif); + free_netdev(ifp->ndev); + drvr->iflist[0] = NULL; + } + if (p2p_ifp) { +- if (p2p_ifp->ndev->destructor == NULL) ++ if (p2p_ifp->ndev->destructor == NULL && p2p_ifp->vif) + brcmf_free_vif(p2p_ifp->vif); + free_netdev(p2p_ifp->ndev); + drvr->iflist[1] = NULL; +-- +2.4.4 + diff --git a/core/linux-veyron/PKGBUILD b/core/linux-veyron/PKGBUILD index de513f407..3c7335e88 100644 --- a/core/linux-veyron/PKGBUILD +++ b/core/linux-veyron/PKGBUILD @@ -7,7 +7,7 @@ pkgbase=linux-veyron _kernelname=${pkgbase#linux} _desc="Veyron Chromebooks" pkgver=3.14.0 -pkgrel=4 +pkgrel=5 _commit=ec35b77b5626479af06faf09e196034c928100ee arch=('armv7h') url="https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-3.14" @@ -20,6 +20,8 @@ source=("https://chromium.googlesource.com/chromiumos/third_party/kernel/+archiv 'http://archlinuxarm.org/builder/src/veyron/BCM4354_003.001.012.0306.0659.hcd' '0001-use-chromiumos-mwifiex-drivers.patch' '0002-mwifiex-do-not-create-AP-and-P2P-interfaces-upon-dri.patch' + '0003-UPSTREAM-soc-rockchip-add-handler-for-usb-uart-funct.patch' + '0004-fix-brcmfmac-oops-and-race-condition.patch' 'config' 'kernel.its' 'kernel.keyblock' @@ -32,9 +34,11 @@ md5sums=('bfe89c90286511d358a7a1d89f776dfc' '5e2d7cd74de07d13052de99411c13a2f' '1534c1dbfe5df35a5634072f7b912840' '20f8931f3795e5226829d48c3d470334' - 'b40864640c0dc67feb87f82019a0212e' - '3b4bb3ab088502164c507b85217e1fd0' - '1981c2ceb90d166cd7b0024bc55d5d17' + 'c052528d853e04cfe40f90ec681bac53' + '7c505a86de18e42158dbdfc146e2cee7' + '16072b50894af1550d3d767259f0f98c' + 'e4d12c67b4c14cd9431887a6a7792547' + '7c4eb4a450bd79b1d78221312670c753' '1d77c34a9c759a7f54df718cd80de567' '61c5ff73c136ed07a7aadbf58db3d96a' '584777ae88bce2c5659960151b64c7d8' @@ -45,6 +49,8 @@ md5sums=('bfe89c90286511d358a7a1d89f776dfc' prepare() { git apply 0001-use-chromiumos-mwifiex-drivers.patch git apply 0002-mwifiex-do-not-create-AP-and-P2P-interfaces-upon-dri.patch + git apply 0003-UPSTREAM-soc-rockchip-add-handler-for-usb-uart-funct.patch + git apply 0004-fix-brcmfmac-oops-and-race-condition.patch cp config .config diff --git a/core/linux-veyron/config b/core/linux-veyron/config index f96abf0a2..4cd4e4a29 100644 --- a/core/linux-veyron/config +++ b/core/linux-veyron/config @@ -3625,6 +3625,7 @@ CONFIG_CHROMEOS_VBC_EC=y # SOC (System On Chip) specific Drivers # # CONFIG_SOC_IMG is not set +CONFIG_ROCKCHIP_USB_UART=y # CONFIG_TEGRA_124_DVFS is not set # CONFIG_EDP_MANAGEMENT is not set CONFIG_CLKDEV_LOOKUP=y