0001-UPSTREAM-soc-rockchip-add-handler-for-usb-uart-funct.patch (9392B)
1 From c0c863786b85a631e22eeae78f572d3f151af490 Mon Sep 17 00:00:00 2001 2 From: Heiko Stuebner <heiko@sntech.de> 3 Date: Mon, 25 May 2015 16:38:07 +0200 4 Subject: [PATCH 3/4] UPSTREAM: soc/rockchip: add handler for usb-uart 5 functionality 6 7 Some Rockchip SoCs provide the possibility to use a usb-phy as passthru for 8 the debug uart, making it possible to get console output without needing to 9 open the device. 10 11 This patch adds an early_initcall to enable this functionality conditionally 12 and also disables the corresponding usb controller in the devicetree. 13 14 Change-Id: I397df8f402c752125cf512332398757b91a899f8 15 Signed-off-by: Alexandru M Stan <amstan@chromium.org> 16 --- 17 drivers/soc/Kconfig | 1 + 18 drivers/soc/Makefile | 1 + 19 drivers/soc/rockchip/Kconfig | 13 ++ 20 drivers/soc/rockchip/Makefile | 1 + 21 drivers/soc/rockchip/rockchip_usb_uart.c | 223 +++++++++++++++++++++++++++++++ 22 5 files changed, 239 insertions(+) 23 create mode 100644 drivers/soc/rockchip/Kconfig 24 create mode 100644 drivers/soc/rockchip/Makefile 25 create mode 100644 drivers/soc/rockchip/rockchip_usb_uart.c 26 27 diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig 28 index 1ee0b57..ad2f71a 100644 29 --- a/drivers/soc/Kconfig 30 +++ b/drivers/soc/Kconfig 31 @@ -2,6 +2,7 @@ menu "SOC (System On Chip) specific Drivers" 32 33 source "drivers/soc/img/Kconfig" 34 source "drivers/soc/qcom/Kconfig" 35 +source "drivers/soc/rockchip/Kconfig" 36 source "drivers/soc/tegra/Kconfig" 37 38 endmenu 39 diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile 40 index bc43b87..d80386c 100644 41 --- a/drivers/soc/Makefile 42 +++ b/drivers/soc/Makefile 43 @@ -4,4 +4,5 @@ 44 45 obj-$(CONFIG_SOC_IMG) += img/ 46 obj-$(CONFIG_ARCH_QCOM) += qcom/ 47 +obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ 48 obj-$(CONFIG_ARCH_TEGRA) += tegra/ 49 diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig 50 new file mode 100644 51 index 0000000..24d4e05 52 --- /dev/null 53 +++ b/drivers/soc/rockchip/Kconfig 54 @@ -0,0 +1,13 @@ 55 +# 56 +# Rockchip Soc drivers 57 +# 58 +config ROCKCHIP_USB_UART 59 + bool "Rockchip usb-uart override" 60 + depends on ARCH_ROCKCHIP 61 + select MFD_SYSCON 62 + help 63 + Say y here to enable usb-uart functionality. Newer Rockchip SoCs 64 + provide means to repurpose one usb phy as uart2 output, making it 65 + possible to get debug output without needing to open a device. 66 + To enable this function on boot, add a rockchip.usb_uart option 67 + to the kernel commandline. 68 diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile 69 new file mode 100644 70 index 0000000..b5dd6f8 71 --- /dev/null 72 +++ b/drivers/soc/rockchip/Makefile 73 @@ -0,0 +1 @@ 74 +obj-$(CONFIG_ROCKCHIP_USB_UART) += rockchip_usb_uart.o 75 diff --git a/drivers/soc/rockchip/rockchip_usb_uart.c b/drivers/soc/rockchip/rockchip_usb_uart.c 76 new file mode 100644 77 index 0000000..97754f9 78 --- /dev/null 79 +++ b/drivers/soc/rockchip/rockchip_usb_uart.c 80 @@ -0,0 +1,223 @@ 81 +/* 82 + * Copyright (c) 2015 Heiko Stuebner <heiko@sntech.de> 83 + * 84 + * This program is free software; you can redistribute it and/or modify 85 + * it under the terms of the GNU General Public License as published by 86 + * the Free Software Foundation; either version 2 of the License, or 87 + * (at your option) any later version. 88 + * 89 + * This program is distributed in the hope that it will be useful, 90 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 91 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 92 + * GNU General Public License for more details. 93 + */ 94 + 95 +#include <linux/kernel.h> 96 +#include <linux/init.h> 97 +#include <linux/errno.h> 98 +#include <linux/mfd/syscon.h> 99 +#include <linux/of_address.h> 100 +#include <linux/of_platform.h> 101 +#include <linux/regmap.h> 102 +#include <linux/slab.h> 103 + 104 +#define HIWORD_UPDATE(val, mask) \ 105 + ((val) | (mask) << 16) 106 + 107 +struct rockchip_uart_data { 108 + const char *grf_compatible; 109 + const char *usb_compatible; 110 + phys_addr_t usb_phys_addr; 111 + int (*init_uart)(const struct rockchip_uart_data *data, 112 + struct regmap *grf); 113 +}; 114 + 115 +static int enable_usb_uart = 0; 116 + 117 +#define RK3288_UOC0_CON0 0x320 118 +#define RK3288_UOC0_CON0_COMMON_ON_N BIT(0) 119 +#define RK3288_UOC0_CON0_DISABLE BIT(4) 120 + 121 +#define RK3288_UOC0_CON2 0x328 122 +#define RK3288_UOC0_CON2_SOFT_CON_SEL BIT(2) 123 + 124 +#define RK3288_UOC0_CON3 0x32c 125 +#define RK3288_UOC0_CON3_UTMI_SUSPENDN BIT(0) 126 +#define RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING (1 << 1) 127 +#define RK3288_UOC0_CON3_UTMI_OPMODE_MASK (3 << 1) 128 +#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC (1 << 3) 129 +#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK (3 << 3) 130 +#define RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED BIT(5) 131 +#define RK3288_UOC0_CON3_BYPASSDMEN BIT(6) 132 +#define RK3288_UOC0_CON3_BYPASSSEL BIT(7) 133 + 134 +/* 135 + * Enable the bypass of uart2 data through the otg usb phy. 136 + * Original description in the TRM. 137 + * 1. Disable the OTG block by setting OTGDISABLE0 to 1’b1. 138 + * 2. Disable the pull-up resistance on the D+ line by setting OPMODE0[1:0] to 2’b01. 139 + * 3. To ensure that the XO, Bias, and PLL blocks are powered down in Suspend mode, set COMMONONN to 1’b1. 140 + * 4. Place the USB PHY in Suspend mode by setting SUSPENDM0 to 1’b0. 141 + * 5. Set BYPASSSEL0 to 1’b1. 142 + * 6. To transmit data, controls BYPASSDMEN0, and BYPASSDMDATA0. 143 + * To receive data, monitor FSVPLUS0. 144 + * 145 + * The actual code in the vendor kernel does some things differently. 146 + */ 147 +static int __init rk3288_init_usb_uart(const struct rockchip_uart_data *data, 148 + struct regmap *grf) 149 +{ 150 + u32 val; 151 + int ret; 152 + 153 + pr_info("%s\n", __func__); 154 + 155 + /* 156 + * COMMON_ON and DISABLE settings are described in the TRM, 157 + * but where not present in the original code. 158 + */ 159 + val = HIWORD_UPDATE(RK3288_UOC0_CON0_COMMON_ON_N 160 + | RK3288_UOC0_CON0_DISABLE, 161 + RK3288_UOC0_CON0_COMMON_ON_N 162 + | RK3288_UOC0_CON0_DISABLE); 163 + ret = regmap_write(grf, RK3288_UOC0_CON0, val); 164 + if (ret) 165 + return ret; 166 + 167 + // FIXME: this makes my system hang, for whatever reason 168 + val = HIWORD_UPDATE(RK3288_UOC0_CON2_SOFT_CON_SEL, 169 + RK3288_UOC0_CON2_SOFT_CON_SEL); 170 + ret = regmap_write(grf, RK3288_UOC0_CON2, val); 171 + if (ret) 172 + return ret; 173 + 174 + val = HIWORD_UPDATE(RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING 175 + | RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC 176 + | RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED, 177 + RK3288_UOC0_CON3_UTMI_SUSPENDN 178 + | RK3288_UOC0_CON3_UTMI_OPMODE_MASK 179 + | RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK 180 + | RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED); 181 + ret = regmap_write(grf, RK3288_UOC0_CON3, val); 182 + if (ret) 183 + return ret; 184 + 185 + val = HIWORD_UPDATE(RK3288_UOC0_CON3_BYPASSSEL 186 + | RK3288_UOC0_CON3_BYPASSDMEN, 187 + RK3288_UOC0_CON3_BYPASSSEL 188 + | RK3288_UOC0_CON3_BYPASSDMEN); 189 + ret = regmap_write(grf, RK3288_UOC0_CON3, val); 190 + if (ret) 191 + return ret; 192 + 193 + return 0; 194 +} 195 + 196 +const struct rockchip_uart_data rk3288_uart_data = { 197 + .grf_compatible = "rockchip,rk3288-grf", 198 + .usb_compatible = "rockchip,rk3288-usb", 199 + .usb_phys_addr = 0xff580000, 200 + .init_uart = rk3288_init_usb_uart, 201 +}; 202 + 203 +static const struct of_device_id rockchip_usb_uart_ids[] = { 204 + { .compatible = "rockchip,rk3288", .data = &rk3288_uart_data }, 205 + { } 206 +}; 207 + 208 +/* 209 + * Find the usb controller using the shared usb-uart-phy in the dts and 210 + * disable it. 211 + */ 212 +static int __init 213 +rockchip_disable_usb_controller(const struct rockchip_uart_data *data) 214 +{ 215 + struct device_node *np; 216 + 217 + for_each_compatible_node(np, NULL, data->usb_compatible) { 218 + struct property *new_status; 219 + struct resource res; 220 + int ret; 221 + 222 + ret = of_address_to_resource(np, 0, &res); 223 + if (ret) { 224 + pr_err("%s: could not get address of usb controller %s\n", 225 + __func__, np->full_name); 226 + continue; 227 + } 228 + 229 + /* not the controller we're looking for */ 230 + if (res.start != data->usb_phys_addr) 231 + continue; 232 + 233 + pr_info("%s: disabling usb controller %s\n", 234 + __func__, np->full_name); 235 + 236 + new_status = kzalloc(sizeof(*new_status), GFP_KERNEL); 237 + if (!new_status) 238 + return -ENOMEM; 239 + 240 + new_status->name = kstrdup("status", GFP_KERNEL); 241 + new_status->length = sizeof("disabled"); 242 + new_status->value = kstrdup("disabled", GFP_KERNEL); 243 + 244 + return of_update_property(np, new_status); 245 + } 246 + 247 + return 0; 248 +} 249 + 250 +static const struct of_device_id *rockchip_usb_uart_data_lookup(void) 251 +{ 252 + struct device_node *root; 253 + const struct of_device_id *id; 254 + 255 + root = of_find_node_by_path("/"); 256 + if (!root) 257 + return NULL; 258 + 259 + id = of_match_node(rockchip_usb_uart_ids, root); 260 + of_node_put(root); 261 + 262 + return id; 263 +} 264 + 265 +static int __init rockchip_init_usb_uart(void) 266 +{ 267 + const struct of_device_id *match; 268 + const struct rockchip_uart_data *data; 269 + struct regmap *grf; 270 + int ret; 271 + 272 + if (!enable_usb_uart) 273 + return 0; 274 + 275 + match = rockchip_usb_uart_data_lookup(); 276 + if (!match) 277 + return -ENOTSUPP; 278 + 279 + pr_info("%s: using settings for %s\n", __func__, match->compatible); 280 + data = match->data; 281 + 282 + grf = syscon_regmap_lookup_by_compatible(data->grf_compatible); 283 + if (IS_ERR(grf)) { 284 + pr_err("%s: could not find GRF syscon\n", __func__); 285 + return PTR_ERR(grf); 286 + } 287 + 288 + ret = data->init_uart(data, grf); 289 + if (ret) { 290 + pr_err("%s: could not init usb_uart\n", __func__); 291 + return ret; 292 + } 293 + 294 + return rockchip_disable_usb_controller(data); 295 +} 296 +early_initcall(rockchip_init_usb_uart); 297 + 298 +static int __init rockchip_usb_uart(char *buf) 299 +{ 300 + enable_usb_uart = true; 301 + return 0; 302 +} 303 +early_param("rockchip.usb_uart", rockchip_usb_uart); 304 -- 305 2.4.4 306