| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Rockchip usb PHY driver |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2014 Yunzhi Li <lyz@rock-chips.com> |
|---|
| 5 | 6 | * Copyright (C) 2014 ROCKCHIP, Inc. |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - * the Free Software Foundation; either version 2 of the License. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 14 | | - * GNU General Public License for more details. |
|---|
| 15 | 7 | */ |
|---|
| 16 | 8 | |
|---|
| 17 | 9 | #include <linux/clk.h> |
|---|
| .. | .. |
|---|
| 42 | 34 | #define HIWORD_UPDATE(val, mask) \ |
|---|
| 43 | 35 | ((val) | (mask) << 16) |
|---|
| 44 | 36 | |
|---|
| 45 | | -#define UOC_CON0_SIDDQ BIT(13) |
|---|
| 37 | +#define UOC_CON0 0x00 |
|---|
| 38 | +#define UOC_CON0_SIDDQ BIT(13) |
|---|
| 39 | +#define UOC_CON0_DISABLE BIT(4) |
|---|
| 40 | +#define UOC_CON0_COMMON_ON_N BIT(0) |
|---|
| 41 | + |
|---|
| 42 | +#define UOC_CON2 0x08 |
|---|
| 43 | +#define UOC_CON2_SOFT_CON_SEL BIT(2) |
|---|
| 44 | + |
|---|
| 45 | +#define UOC_CON3 0x0c |
|---|
| 46 | +/* bits present on rk3188 and rk3288 phys */ |
|---|
| 47 | +#define UOC_CON3_UTMI_TERMSEL_FULLSPEED BIT(5) |
|---|
| 48 | +#define UOC_CON3_UTMI_XCVRSEELCT_FSTRANSC (1 << 3) |
|---|
| 49 | +#define UOC_CON3_UTMI_XCVRSEELCT_MASK (3 << 3) |
|---|
| 50 | +#define UOC_CON3_UTMI_OPMODE_NODRIVING (1 << 1) |
|---|
| 51 | +#define UOC_CON3_UTMI_OPMODE_MASK (3 << 1) |
|---|
| 52 | +#define UOC_CON3_UTMI_SUSPENDN BIT(0) |
|---|
| 46 | 53 | |
|---|
| 47 | 54 | #define RK3288_UOC0_CON0 0x320 |
|---|
| 48 | 55 | #define RK3288_UOC0_CON0_COMMON_ON_N BIT(0) |
|---|
| .. | .. |
|---|
| 115 | 122 | struct rockchip_usb_phy_base; |
|---|
| 116 | 123 | struct rockchip_usb_phy_pdata { |
|---|
| 117 | 124 | struct rockchip_usb_phys *phys; |
|---|
| 118 | | - int (*init_usb_uart)(struct regmap *grf); |
|---|
| 125 | + int (*init_usb_uart)(struct regmap *grf, |
|---|
| 126 | + const struct rockchip_usb_phy_pdata *pdata); |
|---|
| 119 | 127 | int usb_uart_phy; |
|---|
| 120 | 128 | }; |
|---|
| 121 | 129 | |
|---|
| .. | .. |
|---|
| 648 | 656 | rk_phy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; |
|---|
| 649 | 657 | else |
|---|
| 650 | 658 | rk_phy->chg_type = POWER_SUPPLY_TYPE_USB_CDP; |
|---|
| 651 | | - /* fall through */ |
|---|
| 659 | + fallthrough; |
|---|
| 652 | 660 | case USB_CHG_STATE_SECONDARY_DONE: |
|---|
| 653 | 661 | rk_phy->chg_state = USB_CHG_STATE_DETECTED; |
|---|
| 654 | | - /* fall through */ |
|---|
| 662 | + fallthrough; |
|---|
| 655 | 663 | case USB_CHG_STATE_DETECTED: |
|---|
| 656 | 664 | /* put the controller in normal mode */ |
|---|
| 657 | 665 | val = HIWORD_UPDATE(0, RK3288_UOC0_CON2_SOFT_CON_SEL); |
|---|
| .. | .. |
|---|
| 795 | 803 | mutex_init(&rk_phy->mutex); |
|---|
| 796 | 804 | |
|---|
| 797 | 805 | if (of_property_read_u32(child, "reg", ®_offset)) { |
|---|
| 798 | | - dev_err(base->dev, "missing reg property in node %s\n", |
|---|
| 799 | | - child->name); |
|---|
| 806 | + dev_err(base->dev, "missing reg property in node %pOFn\n", |
|---|
| 807 | + child); |
|---|
| 800 | 808 | return -EINVAL; |
|---|
| 801 | 809 | } |
|---|
| 802 | 810 | |
|---|
| .. | .. |
|---|
| 906 | 914 | }, |
|---|
| 907 | 915 | }; |
|---|
| 908 | 916 | |
|---|
| 917 | +static int __init rockchip_init_usb_uart_common(struct regmap *grf, |
|---|
| 918 | + const struct rockchip_usb_phy_pdata *pdata) |
|---|
| 919 | +{ |
|---|
| 920 | + int regoffs = pdata->phys[pdata->usb_uart_phy].reg; |
|---|
| 921 | + int ret; |
|---|
| 922 | + u32 val; |
|---|
| 923 | + |
|---|
| 924 | + /* |
|---|
| 925 | + * COMMON_ON and DISABLE settings are described in the TRM, |
|---|
| 926 | + * but were not present in the original code. |
|---|
| 927 | + * Also disable the analog phy components to save power. |
|---|
| 928 | + */ |
|---|
| 929 | + val = HIWORD_UPDATE(UOC_CON0_COMMON_ON_N |
|---|
| 930 | + | UOC_CON0_DISABLE |
|---|
| 931 | + | UOC_CON0_SIDDQ, |
|---|
| 932 | + UOC_CON0_COMMON_ON_N |
|---|
| 933 | + | UOC_CON0_DISABLE |
|---|
| 934 | + | UOC_CON0_SIDDQ); |
|---|
| 935 | + ret = regmap_write(grf, regoffs + UOC_CON0, val); |
|---|
| 936 | + if (ret) |
|---|
| 937 | + return ret; |
|---|
| 938 | + |
|---|
| 939 | + val = HIWORD_UPDATE(UOC_CON2_SOFT_CON_SEL, |
|---|
| 940 | + UOC_CON2_SOFT_CON_SEL); |
|---|
| 941 | + ret = regmap_write(grf, regoffs + UOC_CON2, val); |
|---|
| 942 | + if (ret) |
|---|
| 943 | + return ret; |
|---|
| 944 | + |
|---|
| 945 | + val = HIWORD_UPDATE(UOC_CON3_UTMI_OPMODE_NODRIVING |
|---|
| 946 | + | UOC_CON3_UTMI_XCVRSEELCT_FSTRANSC |
|---|
| 947 | + | UOC_CON3_UTMI_TERMSEL_FULLSPEED, |
|---|
| 948 | + UOC_CON3_UTMI_SUSPENDN |
|---|
| 949 | + | UOC_CON3_UTMI_OPMODE_MASK |
|---|
| 950 | + | UOC_CON3_UTMI_XCVRSEELCT_MASK |
|---|
| 951 | + | UOC_CON3_UTMI_TERMSEL_FULLSPEED); |
|---|
| 952 | + ret = regmap_write(grf, UOC_CON3, val); |
|---|
| 953 | + if (ret) |
|---|
| 954 | + return ret; |
|---|
| 955 | + |
|---|
| 956 | + return 0; |
|---|
| 957 | +} |
|---|
| 958 | + |
|---|
| 959 | +#define RK3188_UOC0_CON0 0x10c |
|---|
| 960 | +#define RK3188_UOC0_CON0_BYPASSSEL BIT(9) |
|---|
| 961 | +#define RK3188_UOC0_CON0_BYPASSDMEN BIT(8) |
|---|
| 962 | + |
|---|
| 963 | +/* |
|---|
| 964 | + * Enable the bypass of uart2 data through the otg usb phy. |
|---|
| 965 | + * See description of rk3288-variant for details. |
|---|
| 966 | + */ |
|---|
| 967 | +static int __init rk3188_init_usb_uart(struct regmap *grf, |
|---|
| 968 | + const struct rockchip_usb_phy_pdata *pdata) |
|---|
| 969 | +{ |
|---|
| 970 | + u32 val; |
|---|
| 971 | + int ret; |
|---|
| 972 | + |
|---|
| 973 | + ret = rockchip_init_usb_uart_common(grf, pdata); |
|---|
| 974 | + if (ret) |
|---|
| 975 | + return ret; |
|---|
| 976 | + |
|---|
| 977 | + val = HIWORD_UPDATE(RK3188_UOC0_CON0_BYPASSSEL |
|---|
| 978 | + | RK3188_UOC0_CON0_BYPASSDMEN, |
|---|
| 979 | + RK3188_UOC0_CON0_BYPASSSEL |
|---|
| 980 | + | RK3188_UOC0_CON0_BYPASSDMEN); |
|---|
| 981 | + ret = regmap_write(grf, RK3188_UOC0_CON0, val); |
|---|
| 982 | + if (ret) |
|---|
| 983 | + return ret; |
|---|
| 984 | + |
|---|
| 985 | + return 0; |
|---|
| 986 | +} |
|---|
| 987 | + |
|---|
| 909 | 988 | static const struct rockchip_usb_phy_pdata rk3188_pdata = { |
|---|
| 910 | 989 | .phys = (struct rockchip_usb_phys[]){ |
|---|
| 911 | 990 | { .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" }, |
|---|
| 912 | 991 | { .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" }, |
|---|
| 913 | 992 | { /* sentinel */ } |
|---|
| 914 | 993 | }, |
|---|
| 994 | + .init_usb_uart = rk3188_init_usb_uart, |
|---|
| 995 | + .usb_uart_phy = 0, |
|---|
| 915 | 996 | }; |
|---|
| 916 | 997 | |
|---|
| 917 | 998 | /* |
|---|
| .. | .. |
|---|
| 929 | 1010 | * |
|---|
| 930 | 1011 | * The actual code in the vendor kernel does some things differently. |
|---|
| 931 | 1012 | */ |
|---|
| 932 | | -static int __init rk3288_init_usb_uart(struct regmap *grf) |
|---|
| 1013 | +static int __init rk3288_init_usb_uart(struct regmap *grf, |
|---|
| 1014 | + const struct rockchip_usb_phy_pdata *pdata) |
|---|
| 933 | 1015 | { |
|---|
| 934 | 1016 | u32 val; |
|---|
| 935 | 1017 | int ret; |
|---|
| 936 | 1018 | |
|---|
| 937 | | - /* |
|---|
| 938 | | - * COMMON_ON and DISABLE settings are described in the TRM, |
|---|
| 939 | | - * but were not present in the original code. |
|---|
| 940 | | - * Also disable the analog phy components to save power. |
|---|
| 941 | | - */ |
|---|
| 942 | | - val = HIWORD_UPDATE(RK3288_UOC0_CON0_COMMON_ON_N |
|---|
| 943 | | - | RK3288_UOC0_CON0_DISABLE |
|---|
| 944 | | - | UOC_CON0_SIDDQ, |
|---|
| 945 | | - RK3288_UOC0_CON0_COMMON_ON_N |
|---|
| 946 | | - | RK3288_UOC0_CON0_DISABLE |
|---|
| 947 | | - | UOC_CON0_SIDDQ); |
|---|
| 948 | | - ret = regmap_write(grf, RK3288_UOC0_CON0, val); |
|---|
| 949 | | - if (ret) |
|---|
| 950 | | - return ret; |
|---|
| 951 | | - |
|---|
| 952 | | - val = HIWORD_UPDATE(RK3288_UOC0_CON2_SOFT_CON_SEL, |
|---|
| 953 | | - RK3288_UOC0_CON2_SOFT_CON_SEL); |
|---|
| 954 | | - ret = regmap_write(grf, RK3288_UOC0_CON2, val); |
|---|
| 955 | | - if (ret) |
|---|
| 956 | | - return ret; |
|---|
| 957 | | - |
|---|
| 958 | | - val = HIWORD_UPDATE(RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING |
|---|
| 959 | | - | RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC |
|---|
| 960 | | - | RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED, |
|---|
| 961 | | - RK3288_UOC0_CON3_UTMI_SUSPENDN |
|---|
| 962 | | - | RK3288_UOC0_CON3_UTMI_OPMODE_MASK |
|---|
| 963 | | - | RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK |
|---|
| 964 | | - | RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED); |
|---|
| 965 | | - ret = regmap_write(grf, RK3288_UOC0_CON3, val); |
|---|
| 1019 | + ret = rockchip_init_usb_uart_common(grf, pdata); |
|---|
| 966 | 1020 | if (ret) |
|---|
| 967 | 1021 | return ret; |
|---|
| 968 | 1022 | |
|---|
| .. | .. |
|---|
| 1097 | 1151 | return PTR_ERR(grf); |
|---|
| 1098 | 1152 | } |
|---|
| 1099 | 1153 | |
|---|
| 1100 | | - ret = data->init_usb_uart(grf); |
|---|
| 1154 | + ret = data->init_usb_uart(grf, data); |
|---|
| 1101 | 1155 | if (ret) { |
|---|
| 1102 | 1156 | pr_err("%s: could not init usb_uart, %d\n", __func__, ret); |
|---|
| 1103 | 1157 | enable_usb_uart = 0; |
|---|