.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Rockchip USB2.0 PHY with Innosilicon IP block driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License as published by |
---|
8 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
9 | | - * (at your option) any later version. |
---|
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 | 6 | */ |
---|
16 | 7 | |
---|
17 | 8 | #include <linux/clk.h> |
---|
.. | .. |
---|
34 | 25 | #include <linux/pm_runtime.h> |
---|
35 | 26 | #include <linux/power_supply.h> |
---|
36 | 27 | #include <linux/regmap.h> |
---|
| 28 | +#include <linux/reset.h> |
---|
37 | 29 | #include <linux/rockchip/cpu.h> |
---|
38 | 30 | #include <linux/mfd/syscon.h> |
---|
39 | 31 | #include <linux/usb/of.h> |
---|
40 | 32 | #include <linux/usb/otg.h> |
---|
| 33 | +#include <linux/usb/role.h> |
---|
| 34 | +#include <linux/usb/typec_mux.h> |
---|
41 | 35 | #include <linux/wakelock.h> |
---|
42 | 36 | |
---|
43 | 37 | #define BIT_WRITEABLE_SHIFT 16 |
---|
.. | .. |
---|
63 | 57 | }; |
---|
64 | 58 | |
---|
65 | 59 | /** |
---|
66 | | - * Different states involved in USB charger detection. |
---|
67 | | - * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection |
---|
| 60 | + * enum usb_chg_state - Different states involved in USB charger detection. |
---|
| 61 | + * @USB_CHG_STATE_UNDEFINED: USB charger is not connected or detection |
---|
68 | 62 | * process is not yet started. |
---|
69 | | - * USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact. |
---|
70 | | - * USB_CHG_STATE_DCD_DONE Data pin contact is detected. |
---|
71 | | - * USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects |
---|
| 63 | + * @USB_CHG_STATE_WAIT_FOR_DCD: Waiting for Data pins contact. |
---|
| 64 | + * @USB_CHG_STATE_DCD_DONE: Data pin contact is detected. |
---|
| 65 | + * @USB_CHG_STATE_PRIMARY_DONE: Primary detection is completed (Detects |
---|
72 | 66 | * between SDP and DCP/CDP). |
---|
73 | | - * USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects |
---|
74 | | - * between DCP and CDP). |
---|
75 | | - * USB_CHG_STATE_DETECTED USB charger type is determined. |
---|
| 67 | + * @USB_CHG_STATE_SECONDARY_DONE: Secondary detection is completed (Detects |
---|
| 68 | + * between DCP and CDP). |
---|
| 69 | + * @USB_CHG_STATE_DETECTED: USB charger type is determined. |
---|
76 | 70 | */ |
---|
77 | 71 | enum usb_chg_state { |
---|
78 | 72 | USB_CHG_STATE_UNDEFINED = 0, |
---|
.. | .. |
---|
103 | 97 | }; |
---|
104 | 98 | |
---|
105 | 99 | /** |
---|
106 | | - * struct rockchip_chg_det_reg: usb charger detect registers |
---|
| 100 | + * struct rockchip_chg_det_reg - usb charger detect registers |
---|
107 | 101 | * @cp_det: charging port detected successfully. |
---|
108 | 102 | * @dcp_det: dedicated charging port detected successfully. |
---|
109 | 103 | * @dp_det: assert data pin connect successfully. |
---|
.. | .. |
---|
129 | 123 | }; |
---|
130 | 124 | |
---|
131 | 125 | /** |
---|
132 | | - * struct rockchip_usb2phy_port_cfg: usb-phy port configuration. |
---|
| 126 | + * struct rockchip_usb2phy_port_cfg - usb-phy port configuration. |
---|
133 | 127 | * @phy_sus: phy suspend register. |
---|
| 128 | + * @pipe_phystatus: select pipe phystatus from grf or phy. |
---|
134 | 129 | * @bvalid_det_en: vbus valid rise detection enable register. |
---|
135 | 130 | * @bvalid_det_st: vbus valid rise detection status register. |
---|
136 | 131 | * @bvalid_det_clr: vbus valid rise detection clear register. |
---|
137 | | - * @bvalid_set: bvalid select and set to usb controller. |
---|
| 132 | + * @bvalid_grf_con: vbus valid software control. |
---|
| 133 | + * @bvalid_grf_sel: vbus valid software control select. |
---|
| 134 | + * @bvalid_phy_con: vbus valid external select and enable. |
---|
138 | 135 | * @bypass_dm_en: usb bypass uart DM enable register. |
---|
139 | 136 | * @bypass_sel: usb bypass uart select register. |
---|
140 | 137 | * @bypass_iomux: usb bypass uart GRF iomux register. |
---|
141 | 138 | * @bypass_bc: bypass battery charging module. |
---|
142 | 139 | * @bypass_otg: bypass otg module. |
---|
143 | 140 | * @bypass_host: bypass host module. |
---|
| 141 | + * @disfall_en: host disconnect fall edge detection enable. |
---|
| 142 | + * @disfall_st: host disconnect fall edge detection state. |
---|
| 143 | + * @disfall_clr: host disconnect fall edge detection clear. |
---|
| 144 | + * @disrise_en: host disconnect rise edge detection enable. |
---|
| 145 | + * @disrise_st: host disconnect rise edge detection state. |
---|
| 146 | + * @disrise_clr: host disconnect rise edge detection clear. |
---|
144 | 147 | * @ls_det_en: linestate detection enable register. |
---|
145 | 148 | * @ls_det_st: linestate detection state register. |
---|
146 | 149 | * @ls_det_clr: linestate detection clear register. |
---|
.. | .. |
---|
163 | 166 | */ |
---|
164 | 167 | struct rockchip_usb2phy_port_cfg { |
---|
165 | 168 | struct usb2phy_reg phy_sus; |
---|
| 169 | + struct usb2phy_reg pipe_phystatus; |
---|
166 | 170 | struct usb2phy_reg bvalid_det_en; |
---|
167 | 171 | struct usb2phy_reg bvalid_det_st; |
---|
168 | 172 | struct usb2phy_reg bvalid_det_clr; |
---|
169 | | - struct usb2phy_reg bvalid_set; |
---|
| 173 | + struct usb2phy_reg bvalid_grf_con; |
---|
| 174 | + struct usb2phy_reg bvalid_grf_sel; |
---|
| 175 | + struct usb2phy_reg bvalid_phy_con; |
---|
170 | 176 | struct usb2phy_reg bypass_dm_en; |
---|
171 | 177 | struct usb2phy_reg bypass_sel; |
---|
172 | 178 | struct usb2phy_reg bypass_iomux; |
---|
173 | 179 | struct usb2phy_reg bypass_bc; |
---|
174 | 180 | struct usb2phy_reg bypass_otg; |
---|
175 | 181 | struct usb2phy_reg bypass_host; |
---|
| 182 | + struct usb2phy_reg disfall_en; |
---|
| 183 | + struct usb2phy_reg disfall_st; |
---|
| 184 | + struct usb2phy_reg disfall_clr; |
---|
| 185 | + struct usb2phy_reg disrise_en; |
---|
| 186 | + struct usb2phy_reg disrise_st; |
---|
| 187 | + struct usb2phy_reg disrise_clr; |
---|
176 | 188 | struct usb2phy_reg ls_det_en; |
---|
177 | 189 | struct usb2phy_reg ls_det_st; |
---|
178 | 190 | struct usb2phy_reg ls_det_clr; |
---|
.. | .. |
---|
194 | 206 | }; |
---|
195 | 207 | |
---|
196 | 208 | /** |
---|
197 | | - * struct rockchip_usb2phy_cfg: usb-phy configuration. |
---|
| 209 | + * struct rockchip_usb2phy_cfg - usb-phy configuration. |
---|
198 | 210 | * @reg: the address offset of grf for usb-phy config. |
---|
199 | 211 | * @num_ports: specify how many ports that the phy has. |
---|
200 | | - * @phy_tuning: phy default parameters tunning. |
---|
| 212 | + * @phy_tuning: phy default parameters tuning. |
---|
201 | 213 | * @vbus_detect: vbus voltage level detection function. |
---|
202 | 214 | * @clkout_ctl: keep on/turn off output clk of phy via commonon bit. |
---|
203 | 215 | * @clkout_ctl_phy: keep on/turn off output clk of phy via phy inner |
---|
204 | 216 | * debug register. |
---|
| 217 | + * @ls_filter_con: set linestate filter time. |
---|
| 218 | + * @port_cfgs: usb-phy port configurations. |
---|
205 | 219 | * @ls_filter_con: set linestate filter time. |
---|
206 | 220 | * @chg_det: charger detection registers. |
---|
207 | 221 | */ |
---|
208 | 222 | struct rockchip_usb2phy_cfg { |
---|
209 | 223 | unsigned int reg; |
---|
210 | 224 | unsigned int num_ports; |
---|
211 | | - int (*phy_tuning)(struct rockchip_usb2phy *); |
---|
| 225 | + int (*phy_tuning)(struct rockchip_usb2phy *rphy); |
---|
212 | 226 | int (*vbus_detect)(struct rockchip_usb2phy *rphy, |
---|
213 | 227 | const struct usb2phy_reg *vbus_det_en, |
---|
214 | 228 | bool en); |
---|
.. | .. |
---|
220 | 234 | }; |
---|
221 | 235 | |
---|
222 | 236 | /** |
---|
223 | | - * struct rockchip_usb2phy_port: usb-phy port data. |
---|
| 237 | + * struct rockchip_usb2phy_port - usb-phy port data. |
---|
| 238 | + * @phy: generic phy. |
---|
224 | 239 | * @port_id: flag for otg port or host port. |
---|
225 | 240 | * @low_power_en: enable enter low power when suspend. |
---|
226 | 241 | * @perip_connected: flag for periphyeral connect status. |
---|
227 | 242 | * @prev_iddig: previous otg port id pin status. |
---|
| 243 | + * @sel_pipe_phystatus: select pipe phystatus from grf. |
---|
228 | 244 | * @suspended: phy suspended flag. |
---|
| 245 | + * @typec_vbus_det: Type-C otg vbus detect. |
---|
229 | 246 | * @utmi_avalid: utmi avalid status usage flag. |
---|
230 | 247 | * true - use avalid to get vbus status |
---|
231 | | - * flase - use bvalid to get vbus status |
---|
| 248 | + * false - use bvalid to get vbus status |
---|
232 | 249 | * @vbus_attached: otg device vbus status. |
---|
233 | 250 | * @vbus_always_on: otg vbus is always powered on. |
---|
234 | 251 | * @vbus_enabled: vbus regulator status. |
---|
235 | 252 | * @bypass_uart_en: usb bypass uart enable, passed from DT. |
---|
| 253 | + * @host_disconnect: usb host disconnect status. |
---|
| 254 | + * @dis_u2_susphy: disable usb2 phy suspend. |
---|
236 | 255 | * @bvalid_irq: IRQ number assigned for vbus valid rise detection. |
---|
237 | 256 | * @ls_irq: IRQ number assigned for linestate detection. |
---|
238 | 257 | * @id_irq: IRQ number assigned for id fall or rise detection. |
---|
.. | .. |
---|
244 | 263 | * @otg_sm_work: OTG state machine work. |
---|
245 | 264 | * @sm_work: HOST state machine work. |
---|
246 | 265 | * @vbus: vbus regulator supply on few rockchip boards. |
---|
247 | | - * @phy_cfg: port register configuration, assigned by driver data. |
---|
| 266 | + * @sw: orientation switch, communicate with TCPM (Type-C Port Manager). |
---|
| 267 | + * @port_cfg: port register configuration, assigned by driver data. |
---|
248 | 268 | * @event_nb: hold event notification callback. |
---|
249 | 269 | * @state: define OTG enumeration states before device reset. |
---|
250 | 270 | * @mode: the dr_mode of the controller. |
---|
.. | .. |
---|
255 | 275 | bool low_power_en; |
---|
256 | 276 | bool perip_connected; |
---|
257 | 277 | bool prev_iddig; |
---|
| 278 | + bool sel_pipe_phystatus; |
---|
258 | 279 | bool suspended; |
---|
| 280 | + bool typec_vbus_det; |
---|
259 | 281 | bool utmi_avalid; |
---|
260 | 282 | bool vbus_attached; |
---|
261 | 283 | bool vbus_always_on; |
---|
262 | 284 | bool vbus_enabled; |
---|
263 | 285 | bool bypass_uart_en; |
---|
| 286 | + bool host_disconnect; |
---|
264 | 287 | bool dis_u2_susphy; |
---|
265 | 288 | int bvalid_irq; |
---|
266 | 289 | int ls_irq; |
---|
.. | .. |
---|
272 | 295 | struct delayed_work otg_sm_work; |
---|
273 | 296 | struct delayed_work sm_work; |
---|
274 | 297 | struct regulator *vbus; |
---|
| 298 | + struct typec_switch *sw; |
---|
275 | 299 | const struct rockchip_usb2phy_port_cfg *port_cfg; |
---|
276 | 300 | struct notifier_block event_nb; |
---|
277 | 301 | struct wake_lock wakelock; |
---|
.. | .. |
---|
280 | 304 | }; |
---|
281 | 305 | |
---|
282 | 306 | /** |
---|
283 | | - * struct rockchip_usb2phy: usb2.0 phy driver data. |
---|
| 307 | + * struct rockchip_usb2phy - usb2.0 phy driver data. |
---|
| 308 | + * @dev: pointer to device. |
---|
284 | 309 | * @grf: General Register Files regmap. |
---|
285 | 310 | * @usbgrf: USB General Register Files regmap. |
---|
| 311 | + * @usbctrl_grf: USB Controller General Register Files regmap. |
---|
286 | 312 | * *phy_base: the base address of USB PHY. |
---|
| 313 | + * @phy_reset: phy reset control. |
---|
287 | 314 | * @clks: array of phy input clocks. |
---|
288 | 315 | * @clk480m: clock struct of phy output clk. |
---|
289 | | - * @clk_hw: clock struct of phy output clk management. |
---|
| 316 | + * @clk480m_hw: clock struct of phy output clk management. |
---|
290 | 317 | * @num_clks: number of phy input clocks. |
---|
291 | 318 | * @chg_state: states involved in USB charger detection. |
---|
292 | 319 | * @chg_type: USB charger types. |
---|
.. | .. |
---|
306 | 333 | struct device *dev; |
---|
307 | 334 | struct regmap *grf; |
---|
308 | 335 | struct regmap *usbgrf; |
---|
| 336 | + struct regmap *usbctrl_grf; |
---|
309 | 337 | void __iomem *phy_base; |
---|
| 338 | + struct reset_control *phy_reset; |
---|
310 | 339 | struct clk_bulk_data *clks; |
---|
311 | 340 | struct clk *clk480m; |
---|
312 | 341 | struct clk_hw clk480m_hw; |
---|
.. | .. |
---|
376 | 405 | orig = readl(base + reg->offset); |
---|
377 | 406 | tmp = (orig & mask) >> reg->bitstart; |
---|
378 | 407 | return tmp == reg->enable; |
---|
| 408 | +} |
---|
| 409 | + |
---|
| 410 | +static inline void phy_clear_bits(void __iomem *reg, u32 bits) |
---|
| 411 | +{ |
---|
| 412 | + u32 tmp = readl(reg); |
---|
| 413 | + |
---|
| 414 | + tmp &= ~bits; |
---|
| 415 | + writel(tmp, reg); |
---|
| 416 | +} |
---|
| 417 | + |
---|
| 418 | +static inline void phy_set_bits(void __iomem *reg, u32 bits) |
---|
| 419 | +{ |
---|
| 420 | + u32 tmp = readl(reg); |
---|
| 421 | + |
---|
| 422 | + tmp |= bits; |
---|
| 423 | + writel(tmp, reg); |
---|
| 424 | +} |
---|
| 425 | + |
---|
| 426 | +static inline void phy_update_bits(void __iomem *reg, u32 mask, u32 val) |
---|
| 427 | +{ |
---|
| 428 | + u32 tmp = readl(reg); |
---|
| 429 | + |
---|
| 430 | + tmp &= ~mask; |
---|
| 431 | + tmp |= val & mask; |
---|
| 432 | + writel(tmp, reg); |
---|
| 433 | +} |
---|
| 434 | + |
---|
| 435 | +static int rockchip_usb2phy_reset(struct rockchip_usb2phy *rphy) |
---|
| 436 | +{ |
---|
| 437 | + int ret; |
---|
| 438 | + |
---|
| 439 | + if (!rphy->phy_reset) |
---|
| 440 | + return 0; |
---|
| 441 | + |
---|
| 442 | + ret = reset_control_assert(rphy->phy_reset); |
---|
| 443 | + if (ret) |
---|
| 444 | + return ret; |
---|
| 445 | + |
---|
| 446 | + udelay(10); |
---|
| 447 | + |
---|
| 448 | + ret = reset_control_deassert(rphy->phy_reset); |
---|
| 449 | + if (ret) |
---|
| 450 | + return ret; |
---|
| 451 | + |
---|
| 452 | + usleep_range(100, 200); |
---|
| 453 | + |
---|
| 454 | + return 0; |
---|
379 | 455 | } |
---|
380 | 456 | |
---|
381 | 457 | static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw) |
---|
.. | .. |
---|
595 | 671 | return ret; |
---|
596 | 672 | } |
---|
597 | 673 | |
---|
| 674 | +static int rockchip_usb2phy_enable_host_disc_irq(struct rockchip_usb2phy *rphy, |
---|
| 675 | + struct rockchip_usb2phy_port *rport, |
---|
| 676 | + bool en) |
---|
| 677 | +{ |
---|
| 678 | + int ret; |
---|
| 679 | + |
---|
| 680 | + ret = property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true); |
---|
| 681 | + if (ret) |
---|
| 682 | + goto out; |
---|
| 683 | + |
---|
| 684 | + ret = property_enable(rphy->grf, &rport->port_cfg->disfall_en, en); |
---|
| 685 | + if (ret) |
---|
| 686 | + goto out; |
---|
| 687 | + |
---|
| 688 | + ret = property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true); |
---|
| 689 | + if (ret) |
---|
| 690 | + goto out; |
---|
| 691 | + |
---|
| 692 | + ret = property_enable(rphy->grf, &rport->port_cfg->disrise_en, en); |
---|
| 693 | +out: |
---|
| 694 | + return ret; |
---|
| 695 | +} |
---|
| 696 | + |
---|
598 | 697 | static int rockchip_usb_bypass_uart(struct rockchip_usb2phy_port *rport, |
---|
599 | 698 | bool en) |
---|
600 | 699 | { |
---|
.. | .. |
---|
693 | 792 | struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); |
---|
694 | 793 | struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); |
---|
695 | 794 | int ret = 0; |
---|
| 795 | + unsigned int ul, ul_mask; |
---|
696 | 796 | |
---|
697 | 797 | mutex_lock(&rport->mutex); |
---|
| 798 | + |
---|
| 799 | + if (rport->sel_pipe_phystatus) |
---|
| 800 | + property_enable(rphy->usbctrl_grf, |
---|
| 801 | + &rport->port_cfg->pipe_phystatus, true); |
---|
698 | 802 | |
---|
699 | 803 | if (rport->port_id == USB2PHY_PORT_OTG && |
---|
700 | 804 | (rport->mode == USB_DR_MODE_PERIPHERAL || |
---|
.. | .. |
---|
721 | 825 | "failed to enable bvalid irq\n"); |
---|
722 | 826 | goto out; |
---|
723 | 827 | } |
---|
724 | | - |
---|
725 | 828 | schedule_delayed_work(&rport->otg_sm_work, |
---|
726 | | - OTG_SCHEDULE_DELAY); |
---|
| 829 | + rport->typec_vbus_det ? 0 : OTG_SCHEDULE_DELAY); |
---|
727 | 830 | } |
---|
728 | 831 | } else if (rport->port_id == USB2PHY_PORT_HOST) { |
---|
| 832 | + if (rport->port_cfg->disfall_en.offset) { |
---|
| 833 | + ret = regmap_read(rphy->grf, rport->port_cfg->utmi_ls.offset, &ul); |
---|
| 834 | + if (ret < 0) |
---|
| 835 | + goto out; |
---|
| 836 | + ul_mask = GENMASK(rport->port_cfg->utmi_ls.bitend, |
---|
| 837 | + rport->port_cfg->utmi_ls.bitstart); |
---|
| 838 | + rport->host_disconnect = (ul & ul_mask) == 0 ? true : false; |
---|
| 839 | + ret = rockchip_usb2phy_enable_host_disc_irq(rphy, rport, true); |
---|
| 840 | + if (ret) { |
---|
| 841 | + dev_err(rphy->dev, "failed to enable disconnect irq\n"); |
---|
| 842 | + goto out; |
---|
| 843 | + } |
---|
| 844 | + } |
---|
| 845 | + |
---|
729 | 846 | /* clear linestate and enable linestate detect irq */ |
---|
730 | 847 | ret = rockchip_usb2phy_enable_line_irq(rphy, rport, true); |
---|
731 | 848 | if (ret) { |
---|
.. | .. |
---|
771 | 888 | goto unlock; |
---|
772 | 889 | |
---|
773 | 890 | ret = property_enable(base, &rport->port_cfg->phy_sus, false); |
---|
774 | | - if (ret) |
---|
| 891 | + if (ret) { |
---|
| 892 | + clk_disable_unprepare(rphy->clk480m); |
---|
775 | 893 | goto unlock; |
---|
| 894 | + } |
---|
| 895 | + |
---|
| 896 | + /* |
---|
| 897 | + * For rk3588, it needs to reset phy when exit from |
---|
| 898 | + * suspend mode with common_on_n 1'b1(aka REFCLK_LOGIC, |
---|
| 899 | + * Bias, and PLL blocks are powered down) for lower |
---|
| 900 | + * power consumption. If you don't want to reset phy, |
---|
| 901 | + * please keep the common_on_n 1'b0 to set these blocks |
---|
| 902 | + * remain powered. |
---|
| 903 | + */ |
---|
| 904 | + if (rport->port_id == USB2PHY_PORT_OTG && |
---|
| 905 | + of_device_is_compatible(rphy->dev->of_node, "rockchip,rk3588-usb2phy")) { |
---|
| 906 | + ret = rockchip_usb2phy_reset(rphy); |
---|
| 907 | + if (ret) { |
---|
| 908 | + clk_disable_unprepare(rphy->clk480m); |
---|
| 909 | + goto unlock; |
---|
| 910 | + } |
---|
| 911 | + } |
---|
776 | 912 | |
---|
777 | 913 | /* waiting for the utmi_clk to become stable */ |
---|
778 | 914 | usleep_range(1500, 2000); |
---|
.. | .. |
---|
830 | 966 | if (rport->port_id == USB2PHY_PORT_HOST) |
---|
831 | 967 | cancel_delayed_work_sync(&rport->sm_work); |
---|
832 | 968 | else if (rport->port_id == USB2PHY_PORT_OTG && |
---|
833 | | - rport->bvalid_irq > 0) |
---|
| 969 | + rport->otg_sm_work.work.func) |
---|
834 | 970 | flush_delayed_work(&rport->otg_sm_work); |
---|
835 | 971 | |
---|
836 | 972 | return 0; |
---|
.. | .. |
---|
859 | 995 | return ret; |
---|
860 | 996 | } |
---|
861 | 997 | |
---|
862 | | -static int rockchip_usb2phy_set_mode(struct phy *phy, enum phy_mode mode) |
---|
| 998 | +static int rockchip_usb2phy_set_mode(struct phy *phy, |
---|
| 999 | + enum phy_mode mode, int submode) |
---|
863 | 1000 | { |
---|
864 | 1001 | struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); |
---|
865 | 1002 | struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); |
---|
.. | .. |
---|
871 | 1008 | |
---|
872 | 1009 | switch (mode) { |
---|
873 | 1010 | case PHY_MODE_USB_OTG: |
---|
| 1011 | + if (rphy->edev_self && submode) { |
---|
| 1012 | + if (submode == USB_ROLE_HOST) { |
---|
| 1013 | + extcon_set_state(rphy->edev, EXTCON_USB_HOST, true); |
---|
| 1014 | + extcon_set_state(rphy->edev, EXTCON_USB, false); |
---|
| 1015 | + } else if (submode == USB_ROLE_DEVICE) { |
---|
| 1016 | + extcon_set_state(rphy->edev, EXTCON_USB_HOST, false); |
---|
| 1017 | + extcon_set_state(rphy->edev, EXTCON_USB, true); |
---|
| 1018 | + } |
---|
| 1019 | + |
---|
| 1020 | + return ret; |
---|
| 1021 | + } |
---|
| 1022 | + |
---|
874 | 1023 | /* |
---|
875 | 1024 | * In case of using vbus to detect connect state by u2phy, |
---|
876 | 1025 | * enable vbus detect on otg mode. |
---|
877 | | - * |
---|
878 | | - * fallthrough |
---|
879 | 1026 | */ |
---|
| 1027 | + fallthrough; |
---|
880 | 1028 | case PHY_MODE_USB_DEVICE: |
---|
881 | 1029 | /* Disable VBUS supply */ |
---|
882 | 1030 | rockchip_set_vbus_power(rport, false); |
---|
883 | 1031 | extcon_set_state_sync(rphy->edev, EXTCON_USB_VBUS_EN, false); |
---|
| 1032 | + /* For vbus always on, set EXTCON_USB to true. */ |
---|
| 1033 | + if (rport->vbus_always_on) |
---|
| 1034 | + extcon_set_state(rphy->edev, EXTCON_USB, true); |
---|
| 1035 | + rport->perip_connected = true; |
---|
884 | 1036 | vbus_det_en = true; |
---|
885 | 1037 | break; |
---|
886 | 1038 | case PHY_MODE_USB_HOST: |
---|
.. | .. |
---|
893 | 1045 | } |
---|
894 | 1046 | |
---|
895 | 1047 | extcon_set_state_sync(rphy->edev, EXTCON_USB_VBUS_EN, true); |
---|
896 | | - /* fallthrough */ |
---|
| 1048 | + /* For vbus always on, deinit EXTCON_USB to false. */ |
---|
| 1049 | + if (rport->vbus_always_on) |
---|
| 1050 | + extcon_set_state(rphy->edev, EXTCON_USB, false); |
---|
| 1051 | + rport->perip_connected = false; |
---|
| 1052 | + fallthrough; |
---|
897 | 1053 | case PHY_MODE_INVALID: |
---|
898 | 1054 | vbus_det_en = false; |
---|
899 | 1055 | break; |
---|
.. | .. |
---|
953 | 1109 | return sprintf(buf, "otg\n"); |
---|
954 | 1110 | case USB_DR_MODE_UNKNOWN: |
---|
955 | 1111 | return sprintf(buf, "UNKNOWN\n"); |
---|
956 | | - default: |
---|
957 | | - break; |
---|
958 | 1112 | } |
---|
959 | 1113 | |
---|
960 | 1114 | return -EINVAL; |
---|
.. | .. |
---|
1011 | 1165 | |
---|
1012 | 1166 | switch (rport->mode) { |
---|
1013 | 1167 | case USB_DR_MODE_HOST: |
---|
1014 | | - rockchip_usb2phy_set_mode(rport->phy, PHY_MODE_USB_HOST); |
---|
| 1168 | + rockchip_usb2phy_set_mode(rport->phy, PHY_MODE_USB_HOST, 0); |
---|
1015 | 1169 | property_enable(base, &rport->port_cfg->iddig_output, false); |
---|
1016 | 1170 | property_enable(base, &rport->port_cfg->iddig_en, true); |
---|
1017 | 1171 | break; |
---|
1018 | 1172 | case USB_DR_MODE_PERIPHERAL: |
---|
1019 | | - rockchip_usb2phy_set_mode(rport->phy, PHY_MODE_USB_DEVICE); |
---|
| 1173 | + rockchip_usb2phy_set_mode(rport->phy, PHY_MODE_USB_DEVICE, 0); |
---|
1020 | 1174 | property_enable(base, &rport->port_cfg->iddig_output, true); |
---|
1021 | 1175 | property_enable(base, &rport->port_cfg->iddig_en, true); |
---|
1022 | 1176 | break; |
---|
1023 | 1177 | case USB_DR_MODE_OTG: |
---|
1024 | | - rockchip_usb2phy_set_mode(rport->phy, PHY_MODE_USB_OTG); |
---|
| 1178 | + rockchip_usb2phy_set_mode(rport->phy, PHY_MODE_USB_OTG, 0); |
---|
1025 | 1179 | property_enable(base, &rport->port_cfg->iddig_output, false); |
---|
1026 | 1180 | property_enable(base, &rport->port_cfg->iddig_en, false); |
---|
1027 | 1181 | break; |
---|
.. | .. |
---|
1060 | 1214 | |
---|
1061 | 1215 | mutex_lock(&rport->mutex); |
---|
1062 | 1216 | |
---|
1063 | | - if (rport->utmi_avalid) |
---|
| 1217 | + if (rport->port_cfg->bvalid_grf_con.enable && rport->typec_vbus_det) |
---|
| 1218 | + rport->vbus_attached = |
---|
| 1219 | + property_enabled(rphy->grf, &rport->port_cfg->bvalid_grf_con); |
---|
| 1220 | + else if (rport->utmi_avalid) |
---|
1064 | 1221 | rport->vbus_attached = |
---|
1065 | 1222 | property_enabled(rphy->grf, &rport->port_cfg->utmi_avalid); |
---|
1066 | 1223 | else |
---|
.. | .. |
---|
1082 | 1239 | rockchip_usb2phy_power_off(rport->phy); |
---|
1083 | 1240 | mutex_lock(&rport->mutex); |
---|
1084 | 1241 | } |
---|
1085 | | - /* fall through */ |
---|
| 1242 | + fallthrough; |
---|
1086 | 1243 | case OTG_STATE_B_IDLE: |
---|
1087 | 1244 | if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) > 0 || |
---|
1088 | | - extcon_get_state(rphy->edev, EXTCON_USB_VBUS_EN) > 0 ) { |
---|
| 1245 | + extcon_get_state(rphy->edev, EXTCON_USB_VBUS_EN) > 0) { |
---|
1089 | 1246 | dev_dbg(&rport->phy->dev, "usb otg host connect\n"); |
---|
1090 | 1247 | rport->state = OTG_STATE_A_HOST; |
---|
1091 | 1248 | rphy->chg_state = USB_CHG_STATE_UNDEFINED; |
---|
.. | .. |
---|
1139 | 1296 | } else { |
---|
1140 | 1297 | rphy->chg_state = USB_CHG_STATE_UNDEFINED; |
---|
1141 | 1298 | rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; |
---|
| 1299 | + rport->perip_connected = false; |
---|
1142 | 1300 | mutex_unlock(&rport->mutex); |
---|
1143 | 1301 | if (!rport->dis_u2_susphy) |
---|
1144 | 1302 | rockchip_usb2phy_power_off(rport->phy); |
---|
.. | .. |
---|
1370 | 1528 | rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; |
---|
1371 | 1529 | else |
---|
1372 | 1530 | rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP; |
---|
1373 | | - /* fall through */ |
---|
| 1531 | + fallthrough; |
---|
1374 | 1532 | case USB_CHG_STATE_SECONDARY_DONE: |
---|
1375 | 1533 | rphy->chg_state = USB_CHG_STATE_DETECTED; |
---|
1376 | | - /* fall through */ |
---|
| 1534 | + fallthrough; |
---|
1377 | 1535 | case USB_CHG_STATE_DETECTED: |
---|
| 1536 | + if (rphy->phy_cfg->chg_det.chg_mode.offset != |
---|
| 1537 | + rport->port_cfg->phy_sus.offset) |
---|
| 1538 | + property_enable(base, &rphy->phy_cfg->chg_det.chg_mode, false); |
---|
| 1539 | + |
---|
1378 | 1540 | /* Restore the PHY suspend configuration */ |
---|
1379 | 1541 | phy_sus_reg = &rport->port_cfg->phy_sus; |
---|
1380 | 1542 | mask = GENMASK(phy_sus_reg->bitend, phy_sus_reg->bitstart); |
---|
1381 | 1543 | ret = regmap_write(base, phy_sus_reg->offset, |
---|
1382 | | - ((rphy->phy_sus_cfg << |
---|
1383 | | - phy_sus_reg->bitstart) | |
---|
1384 | | - (mask << BIT_WRITEABLE_SHIFT))); |
---|
| 1544 | + (rphy->phy_sus_cfg | (mask << BIT_WRITEABLE_SHIFT))); |
---|
1385 | 1545 | if (ret) |
---|
1386 | 1546 | dev_err(&rport->phy->dev, |
---|
1387 | 1547 | "Fail to set phy_sus reg offset 0x%x, ret %d\n", |
---|
1388 | 1548 | phy_sus_reg->offset, ret); |
---|
1389 | 1549 | mutex_unlock(&rport->mutex); |
---|
1390 | 1550 | rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); |
---|
1391 | | - dev_info(&rport->phy->dev, "charger = %s\n", |
---|
| 1551 | + dev_dbg(&rport->phy->dev, "charger = %s\n", |
---|
1392 | 1552 | chg_to_string(rphy->chg_type)); |
---|
1393 | 1553 | return; |
---|
1394 | 1554 | default: |
---|
.. | .. |
---|
1422 | 1582 | struct rockchip_usb2phy_port *rport = |
---|
1423 | 1583 | container_of(work, struct rockchip_usb2phy_port, sm_work.work); |
---|
1424 | 1584 | struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); |
---|
1425 | | - unsigned int sh = rport->port_cfg->utmi_hstdet.bitend - |
---|
1426 | | - rport->port_cfg->utmi_hstdet.bitstart + 1; |
---|
1427 | | - unsigned int ul, uhd, state; |
---|
| 1585 | + unsigned int sh, ul, uhd, state; |
---|
1428 | 1586 | unsigned int ul_mask, uhd_mask; |
---|
1429 | 1587 | int ret; |
---|
1430 | 1588 | |
---|
1431 | 1589 | if (!rport->port_cfg->utmi_ls.offset || |
---|
1432 | | - !rport->port_cfg->utmi_hstdet.offset) { |
---|
| 1590 | + (!rport->port_cfg->utmi_hstdet.offset && |
---|
| 1591 | + !rport->port_cfg->disfall_en.offset)) { |
---|
1433 | 1592 | dev_dbg(&rport->phy->dev, "some property may not be specified\n"); |
---|
1434 | 1593 | return; |
---|
1435 | 1594 | } |
---|
.. | .. |
---|
1440 | 1599 | if (ret < 0) |
---|
1441 | 1600 | goto next_schedule; |
---|
1442 | 1601 | |
---|
1443 | | - ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd); |
---|
1444 | | - if (ret < 0) |
---|
1445 | | - goto next_schedule; |
---|
1446 | | - |
---|
1447 | | - uhd_mask = GENMASK(rport->port_cfg->utmi_hstdet.bitend, |
---|
1448 | | - rport->port_cfg->utmi_hstdet.bitstart); |
---|
1449 | 1602 | ul_mask = GENMASK(rport->port_cfg->utmi_ls.bitend, |
---|
1450 | 1603 | rport->port_cfg->utmi_ls.bitstart); |
---|
1451 | 1604 | |
---|
1452 | | - /* stitch on utmi_ls and utmi_hstdet as phy state */ |
---|
1453 | | - state = ((uhd & uhd_mask) >> rport->port_cfg->utmi_hstdet.bitstart) | |
---|
1454 | | - (((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << sh); |
---|
| 1605 | + if (rport->port_cfg->utmi_hstdet.offset) { |
---|
| 1606 | + ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd); |
---|
| 1607 | + if (ret < 0) |
---|
| 1608 | + goto next_schedule; |
---|
| 1609 | + |
---|
| 1610 | + uhd_mask = GENMASK(rport->port_cfg->utmi_hstdet.bitend, |
---|
| 1611 | + rport->port_cfg->utmi_hstdet.bitstart); |
---|
| 1612 | + |
---|
| 1613 | + sh = rport->port_cfg->utmi_hstdet.bitend - |
---|
| 1614 | + rport->port_cfg->utmi_hstdet.bitstart + 1; |
---|
| 1615 | + /* stitch on utmi_ls and utmi_hstdet as phy state */ |
---|
| 1616 | + state = ((uhd & uhd_mask) >> rport->port_cfg->utmi_hstdet.bitstart) | |
---|
| 1617 | + (((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << sh); |
---|
| 1618 | + } else { |
---|
| 1619 | + state = ((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << 1 | |
---|
| 1620 | + rport->host_disconnect; |
---|
| 1621 | + } |
---|
1455 | 1622 | |
---|
1456 | 1623 | switch (state) { |
---|
1457 | 1624 | case PHY_STATE_HS_ONLINE: |
---|
.. | .. |
---|
1472 | 1639 | dev_dbg(&rport->phy->dev, "FS/LS online\n"); |
---|
1473 | 1640 | break; |
---|
1474 | 1641 | } |
---|
1475 | | - /* fall through */ |
---|
| 1642 | + fallthrough; |
---|
1476 | 1643 | case PHY_STATE_CONNECT: |
---|
1477 | 1644 | if (rport->suspended) { |
---|
1478 | 1645 | dev_dbg(&rport->phy->dev, "Connected\n"); |
---|
.. | .. |
---|
1516 | 1683 | mutex_unlock(&rport->mutex); |
---|
1517 | 1684 | return; |
---|
1518 | 1685 | default: |
---|
1519 | | - dev_dbg(&rport->phy->dev, "unknown phy state\n"); |
---|
| 1686 | + dev_dbg(&rport->phy->dev, "unknown phy state %d\n", state); |
---|
1520 | 1687 | break; |
---|
1521 | 1688 | } |
---|
1522 | 1689 | |
---|
.. | .. |
---|
1530 | 1697 | struct rockchip_usb2phy_port *rport = data; |
---|
1531 | 1698 | struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); |
---|
1532 | 1699 | |
---|
1533 | | - if (!property_enabled(rphy->grf, &rport->port_cfg->ls_det_st)) |
---|
| 1700 | + if (!property_enabled(rphy->grf, &rport->port_cfg->ls_det_st) || |
---|
| 1701 | + !property_enabled(rphy->grf, &rport->port_cfg->ls_det_en)) |
---|
1534 | 1702 | return IRQ_NONE; |
---|
1535 | 1703 | |
---|
1536 | 1704 | dev_dbg(&rport->phy->dev, "linestate interrupt\n"); |
---|
.. | .. |
---|
1539 | 1707 | |
---|
1540 | 1708 | /* disable linestate detect irq and clear its status */ |
---|
1541 | 1709 | rockchip_usb2phy_enable_line_irq(rphy, rport, false); |
---|
| 1710 | + |
---|
| 1711 | + /* |
---|
| 1712 | + * For host port, it may miss disc irq when device is connected, |
---|
| 1713 | + * in this case, we can clear host_disconnect state depend on |
---|
| 1714 | + * the linestate irq. |
---|
| 1715 | + */ |
---|
| 1716 | + if (rport->port_id == USB2PHY_PORT_HOST && rport->port_cfg->disfall_en.offset) |
---|
| 1717 | + rport->host_disconnect = false; |
---|
1542 | 1718 | |
---|
1543 | 1719 | mutex_unlock(&rport->mutex); |
---|
1544 | 1720 | |
---|
.. | .. |
---|
1571 | 1747 | if (rport->bypass_uart_en) |
---|
1572 | 1748 | rockchip_usb_bypass_uart(rport, false); |
---|
1573 | 1749 | |
---|
1574 | | - cancel_delayed_work_sync(&rport->otg_sm_work); |
---|
1575 | | - rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); |
---|
| 1750 | + if (rport->otg_sm_work.work.func) { |
---|
| 1751 | + cancel_delayed_work_sync(&rport->otg_sm_work); |
---|
| 1752 | + rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); |
---|
| 1753 | + } |
---|
1576 | 1754 | |
---|
1577 | 1755 | return IRQ_HANDLED; |
---|
1578 | 1756 | } |
---|
.. | .. |
---|
1593 | 1771 | if (property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st)) { |
---|
1594 | 1772 | property_enable(rphy->grf, &rport->port_cfg->idfall_det_clr, |
---|
1595 | 1773 | true); |
---|
1596 | | - cable_vbus_state = true; |
---|
| 1774 | + /* |
---|
| 1775 | + * if id fall det, switch to host if ID Detector pin is floating |
---|
| 1776 | + * or iddig status is low. |
---|
| 1777 | + */ |
---|
| 1778 | + if (!rport->port_cfg->utmi_iddig.enable || |
---|
| 1779 | + !property_enabled(rphy->grf, &rport->port_cfg->utmi_iddig)) |
---|
| 1780 | + cable_vbus_state = true; |
---|
1597 | 1781 | } else if (property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st)) { |
---|
1598 | 1782 | property_enable(rphy->grf, &rport->port_cfg->idrise_det_clr, |
---|
1599 | 1783 | true); |
---|
.. | .. |
---|
1607 | 1791 | extcon_sync(rphy->edev, EXTCON_USB_VBUS_EN); |
---|
1608 | 1792 | |
---|
1609 | 1793 | rockchip_set_vbus_power(rport, cable_vbus_state); |
---|
| 1794 | + |
---|
| 1795 | + mutex_unlock(&rport->mutex); |
---|
| 1796 | + |
---|
| 1797 | + return IRQ_HANDLED; |
---|
| 1798 | +} |
---|
| 1799 | + |
---|
| 1800 | +static irqreturn_t rockchip_usb2phy_host_disc_irq(int irq, void *data) |
---|
| 1801 | +{ |
---|
| 1802 | + struct rockchip_usb2phy_port *rport = data; |
---|
| 1803 | + struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); |
---|
| 1804 | + |
---|
| 1805 | + if (!property_enabled(rphy->grf, &rport->port_cfg->disfall_st) && |
---|
| 1806 | + !property_enabled(rphy->grf, &rport->port_cfg->disrise_st)) |
---|
| 1807 | + return IRQ_NONE; |
---|
| 1808 | + |
---|
| 1809 | + mutex_lock(&rport->mutex); |
---|
| 1810 | + |
---|
| 1811 | + /* clear disconnect fall or rise detect irq pending status */ |
---|
| 1812 | + if (property_enabled(rphy->grf, &rport->port_cfg->disfall_st)) { |
---|
| 1813 | + property_enable(rphy->grf, &rport->port_cfg->disfall_clr, |
---|
| 1814 | + true); |
---|
| 1815 | + rport->host_disconnect = false; |
---|
| 1816 | + } else if (property_enabled(rphy->grf, &rport->port_cfg->disrise_st)) { |
---|
| 1817 | + property_enable(rphy->grf, &rport->port_cfg->disrise_clr, |
---|
| 1818 | + true); |
---|
| 1819 | + rport->host_disconnect = true; |
---|
| 1820 | + } |
---|
1610 | 1821 | |
---|
1611 | 1822 | mutex_unlock(&rport->mutex); |
---|
1612 | 1823 | |
---|
.. | .. |
---|
1637 | 1848 | if (!rport->phy) |
---|
1638 | 1849 | continue; |
---|
1639 | 1850 | |
---|
| 1851 | + /* |
---|
| 1852 | + * Handle disc irq before linestate irq to set the disc |
---|
| 1853 | + * state for sm work scheduled in the linestate irq handler. |
---|
| 1854 | + */ |
---|
| 1855 | + if (rport->port_id == USB2PHY_PORT_HOST && |
---|
| 1856 | + rport->port_cfg->disfall_en.offset) |
---|
| 1857 | + ret |= rockchip_usb2phy_host_disc_irq(irq, rport); |
---|
| 1858 | + |
---|
1640 | 1859 | /* Handle linestate irq for both otg port and host port */ |
---|
1641 | | - ret = rockchip_usb2phy_linestate_irq(irq, rport); |
---|
| 1860 | + ret |= rockchip_usb2phy_linestate_irq(irq, rport); |
---|
1642 | 1861 | |
---|
1643 | 1862 | /* |
---|
1644 | 1863 | * Handle bvalid irq and id irq for otg port which |
---|
.. | .. |
---|
1777 | 1996 | return ret; |
---|
1778 | 1997 | } |
---|
1779 | 1998 | |
---|
| 1999 | +static void rockchip_usb2phy_usb_bvalid_enable(struct rockchip_usb2phy_port *rport, |
---|
| 2000 | + u8 enable) |
---|
| 2001 | +{ |
---|
| 2002 | + struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); |
---|
| 2003 | + const struct rockchip_usb2phy_port_cfg *cfg = rport->port_cfg; |
---|
| 2004 | + |
---|
| 2005 | + if (cfg->bvalid_phy_con.enable) |
---|
| 2006 | + property_enable(rphy->grf, &cfg->bvalid_phy_con, enable); |
---|
| 2007 | + |
---|
| 2008 | + if (cfg->bvalid_grf_con.enable) |
---|
| 2009 | + property_enable(rphy->grf, &cfg->bvalid_grf_con, enable); |
---|
| 2010 | +} |
---|
| 2011 | + |
---|
| 2012 | +static int rockchip_usb2phy_orien_sw_set(struct typec_switch *sw, |
---|
| 2013 | + enum typec_orientation orien) |
---|
| 2014 | +{ |
---|
| 2015 | + struct rockchip_usb2phy_port *rport = typec_switch_get_drvdata(sw); |
---|
| 2016 | + |
---|
| 2017 | + dev_dbg(&rport->phy->dev, "type-c orientation: %d\n", orien); |
---|
| 2018 | + |
---|
| 2019 | + mutex_lock(&rport->mutex); |
---|
| 2020 | + rockchip_usb2phy_usb_bvalid_enable(rport, orien != TYPEC_ORIENTATION_NONE); |
---|
| 2021 | + mutex_unlock(&rport->mutex); |
---|
| 2022 | + |
---|
| 2023 | + return 0; |
---|
| 2024 | +} |
---|
| 2025 | + |
---|
| 2026 | +static int |
---|
| 2027 | +rockchip_usb2phy_setup_orien_switch(struct rockchip_usb2phy *rphy, |
---|
| 2028 | + struct rockchip_usb2phy_port *rport) |
---|
| 2029 | +{ |
---|
| 2030 | + struct typec_switch_desc sw_desc = { }; |
---|
| 2031 | + struct device *dev = rphy->dev; |
---|
| 2032 | + |
---|
| 2033 | + sw_desc.drvdata = rport; |
---|
| 2034 | + sw_desc.fwnode = dev_fwnode(dev); |
---|
| 2035 | + sw_desc.set = rockchip_usb2phy_orien_sw_set; |
---|
| 2036 | + |
---|
| 2037 | + rport->sw = typec_switch_register(dev, &sw_desc); |
---|
| 2038 | + if (IS_ERR(rport->sw)) { |
---|
| 2039 | + dev_err(dev, "Error register typec orientation switch: %ld\n", |
---|
| 2040 | + PTR_ERR(rport->sw)); |
---|
| 2041 | + return PTR_ERR(rport->sw); |
---|
| 2042 | + } |
---|
| 2043 | + |
---|
| 2044 | + return 0; |
---|
| 2045 | +} |
---|
| 2046 | + |
---|
| 2047 | +static void rockchip_usb2phy_orien_switch_unregister(void *data) |
---|
| 2048 | +{ |
---|
| 2049 | + struct rockchip_usb2phy_port *rport = data; |
---|
| 2050 | + |
---|
| 2051 | + typec_switch_unregister(rport->sw); |
---|
| 2052 | +} |
---|
| 2053 | + |
---|
1780 | 2054 | static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy, |
---|
1781 | 2055 | struct rockchip_usb2phy_port *rport, |
---|
1782 | 2056 | struct device_node *child_np) |
---|
.. | .. |
---|
1861 | 2135 | rport->low_power_en = |
---|
1862 | 2136 | of_property_read_bool(child_np, "rockchip,low-power-mode"); |
---|
1863 | 2137 | |
---|
| 2138 | + /* For type-c with vbus_det always pull up */ |
---|
| 2139 | + rport->typec_vbus_det = |
---|
| 2140 | + of_property_read_bool(child_np, "rockchip,typec-vbus-det"); |
---|
| 2141 | + |
---|
| 2142 | + rport->sel_pipe_phystatus = |
---|
| 2143 | + of_property_read_bool(child_np, "rockchip,sel-pipe-phystatus"); |
---|
| 2144 | + |
---|
| 2145 | + if (rport->sel_pipe_phystatus) { |
---|
| 2146 | + rphy->usbctrl_grf = |
---|
| 2147 | + syscon_regmap_lookup_by_phandle(rphy->dev->of_node, |
---|
| 2148 | + "rockchip,usbctrl-grf"); |
---|
| 2149 | + if (IS_ERR(rphy->usbctrl_grf)) { |
---|
| 2150 | + dev_err(rphy->dev, "Failed to map usbctrl-grf\n"); |
---|
| 2151 | + return PTR_ERR(rphy->usbctrl_grf); |
---|
| 2152 | + } |
---|
| 2153 | + } |
---|
| 2154 | + |
---|
1864 | 2155 | /* Get Vbus regulators */ |
---|
1865 | 2156 | rport->vbus = devm_regulator_get_optional(&rport->phy->dev, "vbus"); |
---|
1866 | 2157 | if (IS_ERR(rport->vbus)) { |
---|
.. | .. |
---|
1868 | 2159 | if (ret == -EPROBE_DEFER) |
---|
1869 | 2160 | return ret; |
---|
1870 | 2161 | |
---|
1871 | | - dev_warn(&rport->phy->dev, "No vbus specified for otg port\n"); |
---|
| 2162 | + if (rport->mode == USB_DR_MODE_OTG) |
---|
| 2163 | + dev_warn(&rport->phy->dev, "No vbus specified for otg port\n"); |
---|
1872 | 2164 | rport->vbus = NULL; |
---|
1873 | 2165 | } |
---|
1874 | 2166 | |
---|
.. | .. |
---|
1891 | 2183 | return ret; |
---|
1892 | 2184 | } |
---|
1893 | 2185 | |
---|
| 2186 | + if (IS_REACHABLE(CONFIG_TYPEC) && |
---|
| 2187 | + device_property_present(rphy->dev, "orientation-switch")) { |
---|
| 2188 | + ret = rockchip_usb2phy_setup_orien_switch(rphy, rport); |
---|
| 2189 | + if (ret) |
---|
| 2190 | + return ret; |
---|
| 2191 | + |
---|
| 2192 | + ret = devm_add_action_or_reset(rphy->dev, |
---|
| 2193 | + rockchip_usb2phy_orien_switch_unregister, |
---|
| 2194 | + rport); |
---|
| 2195 | + if (ret) |
---|
| 2196 | + return ret; |
---|
| 2197 | + } |
---|
| 2198 | + |
---|
| 2199 | + /* |
---|
| 2200 | + * Set the utmi bvalid come from the usb phy or grf. |
---|
| 2201 | + * For most of Rockchip SoCs, them have VBUSDET pin |
---|
| 2202 | + * for the usb phy to detect the USB VBUS and set |
---|
| 2203 | + * the bvalid signal, so select the bvalid from the |
---|
| 2204 | + * usb phy by default. And for those SoCs which don't |
---|
| 2205 | + * have VBUSDET pin (e.g. RV1103), it needs to select |
---|
| 2206 | + * the bvaid from the grf and set bvalid to be valid |
---|
| 2207 | + * (high) by default. |
---|
| 2208 | + */ |
---|
| 2209 | + if (rport->port_cfg->bvalid_grf_sel.enable != 0) { |
---|
| 2210 | + if (of_machine_is_compatible("rockchip,rv1103")) |
---|
| 2211 | + property_enable(base, &rport->port_cfg->bvalid_grf_sel, true); |
---|
| 2212 | + else |
---|
| 2213 | + property_enable(base, &rport->port_cfg->bvalid_grf_sel, false); |
---|
| 2214 | + } |
---|
| 2215 | + |
---|
| 2216 | + if (rport->vbus_always_on) |
---|
| 2217 | + extcon_set_state(rphy->edev, EXTCON_USB, true); |
---|
| 2218 | + |
---|
1894 | 2219 | if (rport->vbus_always_on || rport->mode == USB_DR_MODE_HOST || |
---|
1895 | 2220 | rport->mode == USB_DR_MODE_UNKNOWN) |
---|
1896 | 2221 | goto out; |
---|
1897 | | - |
---|
1898 | | - /* Select bvalid of usb phy as bvalid of usb controller */ |
---|
1899 | | - if (rport->port_cfg->bvalid_set.enable != 0) |
---|
1900 | | - property_enable(base, &rport->port_cfg->bvalid_set, false); |
---|
1901 | 2222 | |
---|
1902 | 2223 | wake_lock_init(&rport->wakelock, WAKE_LOCK_SUSPEND, "rockchip_otg"); |
---|
1903 | 2224 | ret = devm_add_action_or_reset(rphy->dev, rockchip_otg_wake_lock_destroy, |
---|
.. | .. |
---|
2012 | 2333 | |
---|
2013 | 2334 | /* find out a proper config which can be matched with dt. */ |
---|
2014 | 2335 | index = 0; |
---|
2015 | | - while (phy_cfgs[index].reg) { |
---|
| 2336 | + do { |
---|
2016 | 2337 | if (phy_cfgs[index].reg == reg) { |
---|
2017 | 2338 | rphy->phy_cfg = &phy_cfgs[index]; |
---|
2018 | 2339 | break; |
---|
2019 | 2340 | } |
---|
2020 | 2341 | |
---|
2021 | 2342 | ++index; |
---|
2022 | | - } |
---|
| 2343 | + } while (phy_cfgs[index].reg); |
---|
2023 | 2344 | |
---|
2024 | 2345 | if (!rphy->phy_cfg) { |
---|
2025 | | - dev_err(dev, "no phy-config can be matched with %s node\n", |
---|
2026 | | - np->name); |
---|
| 2346 | + dev_err(dev, "no phy-config can be matched with %pOFn node\n", |
---|
| 2347 | + np); |
---|
2027 | 2348 | return -EINVAL; |
---|
2028 | 2349 | } |
---|
2029 | 2350 | |
---|
2030 | 2351 | pm_runtime_set_active(dev); |
---|
2031 | 2352 | pm_runtime_enable(dev); |
---|
2032 | 2353 | pm_runtime_get_sync(dev); |
---|
| 2354 | + |
---|
| 2355 | + |
---|
| 2356 | + rphy->phy_reset = devm_reset_control_get_optional(dev, "phy"); |
---|
| 2357 | + if (IS_ERR(rphy->phy_reset)) |
---|
| 2358 | + return PTR_ERR(rphy->phy_reset); |
---|
2033 | 2359 | |
---|
2034 | 2360 | ret = devm_clk_bulk_get_all(dev, &rphy->clks); |
---|
2035 | 2361 | if (ret == -EPROBE_DEFER) |
---|
.. | .. |
---|
2057 | 2383 | struct phy *phy; |
---|
2058 | 2384 | |
---|
2059 | 2385 | /* This driver aims to support both otg-port and host-port */ |
---|
2060 | | - if (of_node_cmp(child_np->name, "host-port") && |
---|
2061 | | - of_node_cmp(child_np->name, "otg-port")) |
---|
| 2386 | + if (!of_node_name_eq(child_np, "host-port") && |
---|
| 2387 | + !of_node_name_eq(child_np, "otg-port")) |
---|
2062 | 2388 | goto next_child; |
---|
2063 | 2389 | |
---|
2064 | 2390 | phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops); |
---|
.. | .. |
---|
2072 | 2398 | phy_set_drvdata(rport->phy, rport); |
---|
2073 | 2399 | |
---|
2074 | 2400 | /* initialize otg/host port separately */ |
---|
2075 | | - if (!of_node_cmp(child_np->name, "host-port")) { |
---|
| 2401 | + if (of_node_name_eq(child_np, "host-port")) { |
---|
2076 | 2402 | ret = rockchip_usb2phy_host_port_init(rphy, rport, |
---|
2077 | 2403 | child_np); |
---|
2078 | 2404 | if (ret) |
---|
.. | .. |
---|
2136 | 2462 | pm_runtime_put_sync(dev); |
---|
2137 | 2463 | pm_runtime_disable(dev); |
---|
2138 | 2464 | clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks); |
---|
2139 | | - |
---|
2140 | 2465 | return ret; |
---|
2141 | 2466 | } |
---|
2142 | 2467 | |
---|
.. | .. |
---|
2203 | 2528 | { |
---|
2204 | 2529 | int ret; |
---|
2205 | 2530 | |
---|
2206 | | - /* Open pre-emphasize in non-chirp state for otg port */ |
---|
2207 | | - ret = regmap_write(rphy->grf, 0x0, 0x00070004); |
---|
2208 | | - if (ret) |
---|
2209 | | - return ret; |
---|
| 2531 | + if (soc_is_rk3308bs()) { |
---|
| 2532 | + /* Turn off differential receiver in suspend mode */ |
---|
| 2533 | + ret = regmap_update_bits(rphy->grf, 0x30, BIT(2), 0); |
---|
| 2534 | + if (ret) |
---|
| 2535 | + return ret; |
---|
2210 | 2536 | |
---|
2211 | | - /* Open pre-emphasize in non-chirp state for host port */ |
---|
2212 | | - ret = regmap_write(rphy->grf, 0x30, 0x00070004); |
---|
2213 | | - if (ret) |
---|
2214 | | - return ret; |
---|
| 2537 | + /* Enable otg port pre-emphasis during non-chirp phase */ |
---|
| 2538 | + ret = regmap_update_bits(rphy->grf, 0, GENMASK(2, 0), BIT(2)); |
---|
| 2539 | + if (ret) |
---|
| 2540 | + return ret; |
---|
2215 | 2541 | |
---|
2216 | | - /* Turn off differential receiver in suspend mode */ |
---|
2217 | | - ret = regmap_write(rphy->grf, 0x18, 0x00040000); |
---|
2218 | | - if (ret) |
---|
2219 | | - return ret; |
---|
| 2542 | + /* Set otg port squelch trigger point configure to 100mv */ |
---|
| 2543 | + ret = regmap_update_bits(rphy->grf, 0x004, GENMASK(7, 5), 0x40); |
---|
| 2544 | + if (ret) |
---|
| 2545 | + return ret; |
---|
| 2546 | + |
---|
| 2547 | + ret = regmap_update_bits(rphy->grf, 0x008, BIT(0), 0x1); |
---|
| 2548 | + if (ret) |
---|
| 2549 | + return ret; |
---|
| 2550 | + |
---|
| 2551 | + /* Enable host port pre-emphasis during non-chirp phase */ |
---|
| 2552 | + ret = regmap_update_bits(rphy->grf, 0x400, GENMASK(2, 0), BIT(2)); |
---|
| 2553 | + if (ret) |
---|
| 2554 | + return ret; |
---|
| 2555 | + |
---|
| 2556 | + /* Set host port squelch trigger point configure to 100mv */ |
---|
| 2557 | + ret = regmap_update_bits(rphy->grf, 0x404, GENMASK(7, 5), 0x40); |
---|
| 2558 | + if (ret) |
---|
| 2559 | + return ret; |
---|
| 2560 | + |
---|
| 2561 | + ret = regmap_update_bits(rphy->grf, 0x408, BIT(0), 0x1); |
---|
| 2562 | + if (ret) |
---|
| 2563 | + return ret; |
---|
| 2564 | + } else { |
---|
| 2565 | + /* Open pre-emphasize in non-chirp state for otg port */ |
---|
| 2566 | + ret = regmap_write(rphy->grf, 0x0, 0x00070004); |
---|
| 2567 | + if (ret) |
---|
| 2568 | + return ret; |
---|
| 2569 | + |
---|
| 2570 | + /* Open pre-emphasize in non-chirp state for host port */ |
---|
| 2571 | + ret = regmap_write(rphy->grf, 0x30, 0x00070004); |
---|
| 2572 | + if (ret) |
---|
| 2573 | + return ret; |
---|
| 2574 | + |
---|
| 2575 | + /* Turn off differential receiver in suspend mode */ |
---|
| 2576 | + ret = regmap_write(rphy->grf, 0x18, 0x00040000); |
---|
| 2577 | + if (ret) |
---|
| 2578 | + return ret; |
---|
| 2579 | + } |
---|
2220 | 2580 | |
---|
2221 | 2581 | return 0; |
---|
2222 | 2582 | } |
---|
.. | .. |
---|
2379 | 2739 | |
---|
2380 | 2740 | static int rk3528_usb2phy_tuning(struct rockchip_usb2phy *rphy) |
---|
2381 | 2741 | { |
---|
2382 | | - u32 reg; |
---|
2383 | 2742 | int ret = 0; |
---|
2384 | 2743 | |
---|
2385 | 2744 | /* Turn off otg port differential receiver in suspend mode */ |
---|
2386 | | - reg = readl(rphy->phy_base + 0x30); |
---|
2387 | | - writel(reg & ~BIT(2), rphy->phy_base + 0x30); |
---|
| 2745 | + phy_clear_bits(rphy->phy_base + 0x30, BIT(2)); |
---|
2388 | 2746 | |
---|
2389 | 2747 | /* Turn off host port differential receiver in suspend mode */ |
---|
2390 | | - reg = readl(rphy->phy_base + 0x0430); |
---|
2391 | | - writel(reg & ~BIT(2), rphy->phy_base + 0x0430); |
---|
| 2748 | + phy_clear_bits(rphy->phy_base + 0x430, BIT(2)); |
---|
2392 | 2749 | |
---|
2393 | 2750 | /* Set otg port HS eye height to 400mv(default is 450mv) */ |
---|
2394 | | - reg = readl(rphy->phy_base + 0x30); |
---|
2395 | | - reg &= ~GENMASK(6, 4); |
---|
2396 | | - reg |= (0x00 << 4); |
---|
2397 | | - writel(reg, rphy->phy_base + 0x30); |
---|
| 2751 | + phy_update_bits(rphy->phy_base + 0x30, GENMASK(6, 4), (0x00 << 4)); |
---|
2398 | 2752 | |
---|
2399 | 2753 | /* Set host port HS eye height to 400mv(default is 450mv) */ |
---|
2400 | | - reg = readl(rphy->phy_base + 0x430); |
---|
2401 | | - reg &= ~GENMASK(6, 4); |
---|
2402 | | - reg |= (0x00 << 4); |
---|
2403 | | - writel(reg, rphy->phy_base + 0x430); |
---|
| 2754 | + phy_update_bits(rphy->phy_base + 0x430, GENMASK(6, 4), (0x00 << 4)); |
---|
2404 | 2755 | |
---|
2405 | 2756 | /* Choose the Tx fs/ls data as linestate from TX driver for otg port */ |
---|
2406 | | - reg = readl(rphy->phy_base + 0x94); |
---|
2407 | | - reg &= ~GENMASK(6, 3); |
---|
2408 | | - reg |= (0x03 << 3); |
---|
2409 | | - writel(reg, rphy->phy_base + 0x94); |
---|
| 2757 | + phy_update_bits(rphy->phy_base + 0x94, GENMASK(6, 3), (0x03 << 3)); |
---|
2410 | 2758 | |
---|
2411 | 2759 | /* Enable otg and host ports phy irq to pmu wakeup source */ |
---|
2412 | 2760 | ret |= regmap_write(rphy->grf, 0x80004, 0x00030003); |
---|
.. | .. |
---|
2414 | 2762 | return ret; |
---|
2415 | 2763 | } |
---|
2416 | 2764 | |
---|
2417 | | -static int rk3568_usb2phy_tuning(struct rockchip_usb2phy *rphy) |
---|
| 2765 | +static int rk3562_usb2phy_tuning(struct rockchip_usb2phy *rphy) |
---|
2418 | 2766 | { |
---|
2419 | | - u32 reg; |
---|
2420 | 2767 | int ret = 0; |
---|
2421 | 2768 | |
---|
2422 | | - reg = readl(rphy->phy_base + 0x30); |
---|
2423 | | - /* turn off differential reciver in suspend mode */ |
---|
2424 | | - writel(reg & ~BIT(2), rphy->phy_base + 0x30); |
---|
| 2769 | + /* Turn off differential receiver by default to save power */ |
---|
| 2770 | + phy_clear_bits(rphy->phy_base + 0x0030, BIT(2)); |
---|
| 2771 | + phy_clear_bits(rphy->phy_base + 0x0430, BIT(2)); |
---|
2425 | 2772 | |
---|
2426 | | - reg = readl(rphy->phy_base); |
---|
| 2773 | + /* Enable pre-emphasis during non-chirp phase */ |
---|
| 2774 | + phy_update_bits(rphy->phy_base, GENMASK(2, 0), 0x04); |
---|
| 2775 | + phy_update_bits(rphy->phy_base + 0x0400, GENMASK(2, 0), 0x04); |
---|
| 2776 | + |
---|
| 2777 | + /* Set HS eye height to 425mv(default is 400mv) */ |
---|
| 2778 | + phy_update_bits(rphy->phy_base + 0x0030, GENMASK(6, 4), (0x05 << 4)); |
---|
| 2779 | + phy_update_bits(rphy->phy_base + 0x0430, GENMASK(6, 4), (0x05 << 4)); |
---|
| 2780 | + |
---|
| 2781 | + /* Set the bvalid filter time to 10ms based on the u2phy grf pclk 100MHz */ |
---|
| 2782 | + ret |= regmap_write(rphy->grf, 0x0138, FILTER_COUNTER); |
---|
| 2783 | + |
---|
| 2784 | + /* Set the id filter time to 10ms based on the u2phy grf pclk 100MHz */ |
---|
| 2785 | + ret |= regmap_write(rphy->grf, 0x013c, FILTER_COUNTER); |
---|
| 2786 | + |
---|
| 2787 | + /* Enable host port wakeup irq */ |
---|
| 2788 | + ret |= regmap_write(rphy->grf, 0x010c, 0x80008000); |
---|
| 2789 | + |
---|
| 2790 | + return ret; |
---|
| 2791 | +} |
---|
| 2792 | + |
---|
| 2793 | +static int rk3568_usb2phy_tuning(struct rockchip_usb2phy *rphy) |
---|
| 2794 | +{ |
---|
| 2795 | + int ret = 0; |
---|
| 2796 | + |
---|
| 2797 | + /* Turn off differential receiver by default to save power */ |
---|
| 2798 | + phy_clear_bits(rphy->phy_base + 0x30, BIT(2)); |
---|
| 2799 | + |
---|
2427 | 2800 | /* Enable otg port pre-emphasis during non-chirp phase */ |
---|
2428 | | - reg &= ~(0x07 << 0); |
---|
2429 | | - reg |= (0x04 << 0); |
---|
2430 | | - writel(reg, rphy->phy_base); |
---|
| 2801 | + phy_update_bits(rphy->phy_base, GENMASK(2, 0), 0x04); |
---|
2431 | 2802 | |
---|
2432 | | - reg = readl(rphy->phy_base + 0x0400); |
---|
2433 | 2803 | /* Enable host port pre-emphasis during non-chirp phase */ |
---|
2434 | | - reg &= ~(0x07 << 0); |
---|
2435 | | - reg |= (0x04 << 0); |
---|
2436 | | - writel(reg, rphy->phy_base + 0x0400); |
---|
| 2804 | + phy_update_bits(rphy->phy_base + 0x0400, GENMASK(2, 0), 0x04); |
---|
2437 | 2805 | |
---|
2438 | 2806 | if (rphy->phy_cfg->reg == 0xfe8a0000) { |
---|
2439 | 2807 | /* Set otg port HS eye height to 437.5mv(default is 400mv) */ |
---|
2440 | | - reg = readl(rphy->phy_base + 0x30); |
---|
2441 | | - reg &= ~(0x07 << 4); |
---|
2442 | | - reg |= (0x06 << 4); |
---|
2443 | | - writel(reg, rphy->phy_base + 0x30); |
---|
| 2808 | + phy_update_bits(rphy->phy_base + 0x30, GENMASK(6, 4), (0x06 << 4)); |
---|
2444 | 2809 | |
---|
2445 | 2810 | /* |
---|
2446 | 2811 | * Set the bvalid filter time to 10ms |
---|
.. | .. |
---|
2461 | 2826 | return ret; |
---|
2462 | 2827 | } |
---|
2463 | 2828 | |
---|
| 2829 | +static int rv1106_usb2phy_tuning(struct rockchip_usb2phy *rphy) |
---|
| 2830 | +{ |
---|
| 2831 | + /* Always enable pre-emphasis in SOF & EOP & chirp & non-chirp state */ |
---|
| 2832 | + phy_update_bits(rphy->phy_base + 0x30, GENMASK(2, 0), 0x07); |
---|
| 2833 | + |
---|
| 2834 | + if (rockchip_get_cpu_version()) { |
---|
| 2835 | + /* Set Tx HS pre_emphasize strength to 3'b001 */ |
---|
| 2836 | + phy_update_bits(rphy->phy_base + 0x40, GENMASK(5, 3), (0x01 << 3)); |
---|
| 2837 | + } else { |
---|
| 2838 | + /* Set Tx HS pre_emphasize strength to 3'b011 */ |
---|
| 2839 | + phy_update_bits(rphy->phy_base + 0x40, GENMASK(5, 3), (0x03 << 3)); |
---|
| 2840 | + } |
---|
| 2841 | + |
---|
| 2842 | + /* Set RX Squelch trigger point configure to 4'b0000(112.5 mV) */ |
---|
| 2843 | + phy_update_bits(rphy->phy_base + 0x64, GENMASK(6, 3), (0x00 << 3)); |
---|
| 2844 | + |
---|
| 2845 | + /* Turn off differential receiver by default to save power */ |
---|
| 2846 | + phy_clear_bits(rphy->phy_base + 0x100, BIT(6)); |
---|
| 2847 | + |
---|
| 2848 | + /* Set 45ohm HS ODT value to 5'b10111 to increase driver strength */ |
---|
| 2849 | + phy_update_bits(rphy->phy_base + 0x11c, GENMASK(4, 0), 0x17); |
---|
| 2850 | + |
---|
| 2851 | + /* Set Tx HS eye height tuning to 3'b011(462 mV)*/ |
---|
| 2852 | + phy_update_bits(rphy->phy_base + 0x124, GENMASK(4, 2), (0x03 << 2)); |
---|
| 2853 | + |
---|
| 2854 | + /* Bypass Squelch detector calibration */ |
---|
| 2855 | + phy_update_bits(rphy->phy_base + 0x1a4, GENMASK(7, 4), (0x01 << 4)); |
---|
| 2856 | + phy_update_bits(rphy->phy_base + 0x1b4, GENMASK(7, 4), (0x01 << 4)); |
---|
| 2857 | + |
---|
| 2858 | + /* Set HS disconnect detect mode to single ended detect mode */ |
---|
| 2859 | + phy_set_bits(rphy->phy_base + 0x70, BIT(2)); |
---|
| 2860 | + |
---|
| 2861 | + return 0; |
---|
| 2862 | +} |
---|
| 2863 | + |
---|
2464 | 2864 | static int rockchip_usb2phy_vbus_det_control(struct rockchip_usb2phy *rphy, |
---|
2465 | 2865 | const struct usb2phy_reg *vbus_det_en, |
---|
2466 | 2866 | bool en) |
---|
2467 | 2867 | { |
---|
2468 | | - u32 reg; |
---|
2469 | | - |
---|
2470 | 2868 | if (en) { |
---|
2471 | | - reg = readl(rphy->phy_base + vbus_det_en->offset); |
---|
2472 | 2869 | /* Enable vbus voltage level detection function */ |
---|
2473 | | - writel(reg & ~BIT(7), rphy->phy_base + vbus_det_en->offset); |
---|
| 2870 | + phy_clear_bits(rphy->phy_base + vbus_det_en->offset, BIT(7)); |
---|
2474 | 2871 | } else { |
---|
2475 | | - reg = readl(rphy->phy_base + vbus_det_en->offset); |
---|
2476 | 2872 | /* Disable vbus voltage level detection function */ |
---|
2477 | | - writel(reg | BIT(7), rphy->phy_base + vbus_det_en->offset); |
---|
| 2873 | + phy_set_bits(rphy->phy_base + vbus_det_en->offset, BIT(7)); |
---|
2478 | 2874 | } |
---|
2479 | 2875 | |
---|
2480 | 2876 | return 0; |
---|
| 2877 | +} |
---|
| 2878 | + |
---|
| 2879 | +static int rk3588_usb2phy_tuning(struct rockchip_usb2phy *rphy) |
---|
| 2880 | +{ |
---|
| 2881 | + unsigned int reg; |
---|
| 2882 | + int ret = 0; |
---|
| 2883 | + |
---|
| 2884 | + /* Read the SIDDQ control register */ |
---|
| 2885 | + ret = regmap_read(rphy->grf, 0x0008, ®); |
---|
| 2886 | + if (ret) |
---|
| 2887 | + return ret; |
---|
| 2888 | + |
---|
| 2889 | + if (reg & BIT(13)) { |
---|
| 2890 | + /* Deassert SIDDQ to power on analog block */ |
---|
| 2891 | + ret = regmap_write(rphy->grf, 0x0008, |
---|
| 2892 | + GENMASK(29, 29) | 0x0000); |
---|
| 2893 | + if (ret) |
---|
| 2894 | + return ret; |
---|
| 2895 | + |
---|
| 2896 | + /* Do reset after exit IDDQ mode */ |
---|
| 2897 | + ret = rockchip_usb2phy_reset(rphy); |
---|
| 2898 | + if (ret) |
---|
| 2899 | + return ret; |
---|
| 2900 | + } |
---|
| 2901 | + |
---|
| 2902 | + if (rphy->phy_cfg->reg == 0x0000) { |
---|
| 2903 | + /* |
---|
| 2904 | + * Set USB2 PHY0 suspend configuration for USB3_0 |
---|
| 2905 | + * 1. Set utmi_termselect to 1'b1 (en FS terminations) |
---|
| 2906 | + * 2. Set utmi_xcvrselect to 2'b01 (FS transceiver) |
---|
| 2907 | + * 3. Set utmi_opmode to 2'b01 (no-driving) |
---|
| 2908 | + */ |
---|
| 2909 | + ret |= regmap_write(rphy->grf, 0x000c, |
---|
| 2910 | + GENMASK(20, 16) | 0x0015); |
---|
| 2911 | + |
---|
| 2912 | + /* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */ |
---|
| 2913 | + ret |= regmap_write(rphy->grf, 0x0004, |
---|
| 2914 | + GENMASK(27, 24) | 0x0900); |
---|
| 2915 | + |
---|
| 2916 | + /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */ |
---|
| 2917 | + ret |= regmap_write(rphy->grf, 0x0008, |
---|
| 2918 | + GENMASK(20, 19) | 0x0010); |
---|
| 2919 | + |
---|
| 2920 | + /* Pullup iddig pin for USB3_0 OTG mode */ |
---|
| 2921 | + ret |= regmap_write(rphy->grf, 0x0010, |
---|
| 2922 | + GENMASK(17, 16) | 0x0003); |
---|
| 2923 | + } else if (rphy->phy_cfg->reg == 0x4000) { |
---|
| 2924 | + /* |
---|
| 2925 | + * Set USB2 PHY1 suspend configuration for USB3_1 |
---|
| 2926 | + * 1. Set utmi_termselect to 1'b1 (en FS terminations) |
---|
| 2927 | + * 2. Set utmi_xcvrselect to 2'b01(FS transceiver) |
---|
| 2928 | + * 3. Set utmi_opmode to 2'b01 (no-driving) |
---|
| 2929 | + */ |
---|
| 2930 | + ret |= regmap_write(rphy->grf, 0x000c, |
---|
| 2931 | + GENMASK(20, 16) | 0x0015); |
---|
| 2932 | + |
---|
| 2933 | + /* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */ |
---|
| 2934 | + ret |= regmap_write(rphy->grf, 0x0004, |
---|
| 2935 | + GENMASK(27, 24) | 0x0900); |
---|
| 2936 | + |
---|
| 2937 | + /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */ |
---|
| 2938 | + ret |= regmap_write(rphy->grf, 0x0008, |
---|
| 2939 | + GENMASK(20, 19) | 0x0010); |
---|
| 2940 | + |
---|
| 2941 | + /* Pullup iddig pin for USB3_1 OTG mode */ |
---|
| 2942 | + ret |= regmap_write(rphy->grf, 0x0010, |
---|
| 2943 | + GENMASK(17, 16) | 0x0003); |
---|
| 2944 | + } else if (rphy->phy_cfg->reg == 0x8000) { |
---|
| 2945 | + /* |
---|
| 2946 | + * Set USB2 PHY2 suspend configuration for USB2_0 |
---|
| 2947 | + * 1. Set utmi_termselect to 1'b1 (en FS terminations) |
---|
| 2948 | + * 2. Set utmi_xcvrselect to 2'b01(FS transceiver) |
---|
| 2949 | + * 3. Set utmi_opmode to 2'b00 (normal) |
---|
| 2950 | + */ |
---|
| 2951 | + ret |= regmap_write(rphy->grf, 0x000c, |
---|
| 2952 | + GENMASK(20, 16) | 0x0014); |
---|
| 2953 | + |
---|
| 2954 | + /* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */ |
---|
| 2955 | + ret |= regmap_write(rphy->grf, 0x0004, |
---|
| 2956 | + GENMASK(27, 24) | 0x0900); |
---|
| 2957 | + |
---|
| 2958 | + /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */ |
---|
| 2959 | + ret |= regmap_write(rphy->grf, 0x0008, |
---|
| 2960 | + GENMASK(20, 19) | 0x0010); |
---|
| 2961 | + } else if (rphy->phy_cfg->reg == 0xc000) { |
---|
| 2962 | + /* |
---|
| 2963 | + * Set USB2 PHY3 suspend configuration for USB2_1 |
---|
| 2964 | + * 1. Set utmi_termselect to 1'b1 (en FS terminations) |
---|
| 2965 | + * 2. Set utmi_xcvrselect to 2'b01(FS transceiver) |
---|
| 2966 | + * 3. Set utmi_opmode to 2'b00 (normal) |
---|
| 2967 | + */ |
---|
| 2968 | + ret |= regmap_write(rphy->grf, 0x000c, |
---|
| 2969 | + GENMASK(20, 16) | 0x0014); |
---|
| 2970 | + |
---|
| 2971 | + /* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */ |
---|
| 2972 | + ret |= regmap_write(rphy->grf, 0x0004, |
---|
| 2973 | + GENMASK(27, 24) | 0x0900); |
---|
| 2974 | + |
---|
| 2975 | + /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */ |
---|
| 2976 | + ret |= regmap_write(rphy->grf, 0x0008, |
---|
| 2977 | + GENMASK(20, 19) | 0x0010); |
---|
| 2978 | + } |
---|
| 2979 | + |
---|
| 2980 | + return ret; |
---|
2481 | 2981 | } |
---|
2482 | 2982 | |
---|
2483 | 2983 | #ifdef CONFIG_PM_SLEEP |
---|
.. | .. |
---|
2571 | 3071 | if (device_may_wakeup(rphy->dev)) |
---|
2572 | 3072 | wakeup_enable = true; |
---|
2573 | 3073 | |
---|
| 3074 | + /* |
---|
| 3075 | + * PHY lost power in suspend, it needs to reset |
---|
| 3076 | + * PHY to recovery clock to usb controller. |
---|
| 3077 | + */ |
---|
| 3078 | + if (!wakeup_enable) |
---|
| 3079 | + rockchip_usb2phy_reset(rphy); |
---|
| 3080 | + |
---|
2574 | 3081 | if (phy_cfg->phy_tuning) |
---|
2575 | 3082 | ret = phy_cfg->phy_tuning(rphy); |
---|
2576 | 3083 | |
---|
.. | .. |
---|
2622 | 3129 | if (ret) |
---|
2623 | 3130 | return ret; |
---|
2624 | 3131 | } |
---|
| 3132 | + } |
---|
| 3133 | + |
---|
| 3134 | + /* Enable bvalid detect irq */ |
---|
| 3135 | + if (rport->port_id == USB2PHY_PORT_OTG && |
---|
| 3136 | + (rport->mode == USB_DR_MODE_PERIPHERAL || |
---|
| 3137 | + rport->mode == USB_DR_MODE_OTG) && |
---|
| 3138 | + (rport->bvalid_irq > 0 || rport->otg_mux_irq > 0 || rphy->irq > 0) && |
---|
| 3139 | + !rport->vbus_always_on) { |
---|
| 3140 | + ret = rockchip_usb2phy_enable_vbus_irq(rphy, rport, |
---|
| 3141 | + true); |
---|
| 3142 | + if (ret) { |
---|
| 3143 | + dev_err(rphy->dev, |
---|
| 3144 | + "failed to enable bvalid irq\n"); |
---|
| 3145 | + return ret; |
---|
| 3146 | + } |
---|
| 3147 | + |
---|
| 3148 | + if (property_enabled(rphy->grf, &rport->port_cfg->utmi_bvalid)) |
---|
| 3149 | + schedule_delayed_work(&rport->otg_sm_work, |
---|
| 3150 | + OTG_SCHEDULE_DELAY); |
---|
| 3151 | + |
---|
2625 | 3152 | } |
---|
2626 | 3153 | |
---|
2627 | 3154 | if (rport->port_id == USB2PHY_PORT_OTG && wakeup_enable && |
---|
.. | .. |
---|
2909 | 3436 | .ls_det_clr = { 0x0118, 0, 0, 0, 1 }, |
---|
2910 | 3437 | .utmi_avalid = { 0x0120, 10, 10, 0, 1 }, |
---|
2911 | 3438 | .utmi_bvalid = { 0x0120, 9, 9, 0, 1 }, |
---|
2912 | | - .utmi_iddig = { 0x0120, 6, 6, 0, 1 }, |
---|
2913 | 3439 | .utmi_ls = { 0x0120, 5, 4, 0, 1 }, |
---|
2914 | 3440 | .vbus_det_en = { 0x001c, 15, 15, 1, 0 }, |
---|
2915 | 3441 | }, |
---|
.. | .. |
---|
2987 | 3513 | .vbus_det_en = { 0x079c, 15, 15, 1, 0 }, |
---|
2988 | 3514 | }, |
---|
2989 | 3515 | [USB2PHY_PORT_HOST] = { |
---|
2990 | | - .phy_sus = { 0x0728, 8, 0, 0, 0x1d1 }, |
---|
| 3516 | + .phy_sus = { 0x0728, 15, 0, 0, 0x1d1 }, |
---|
2991 | 3517 | .ls_det_en = { 0x0680, 4, 4, 0, 1 }, |
---|
2992 | 3518 | .ls_det_st = { 0x0690, 4, 4, 0, 1 }, |
---|
2993 | 3519 | .ls_det_clr = { 0x06a0, 4, 4, 0, 1 } |
---|
.. | .. |
---|
3128 | 3654 | .bvalid_det_en = { 0x60074, 2, 2, 0, 1 }, |
---|
3129 | 3655 | .bvalid_det_st = { 0x60078, 2, 2, 0, 1 }, |
---|
3130 | 3656 | .bvalid_det_clr = { 0x6007c, 2, 2, 0, 1 }, |
---|
3131 | | - .bvalid_set = { 0x6004c, 15, 14, 0, 3 }, |
---|
3132 | 3657 | .iddig_output = { 0x6004c, 10, 10, 0, 1 }, |
---|
3133 | 3658 | .iddig_en = { 0x6004c, 9, 9, 0, 1 }, |
---|
3134 | 3659 | .idfall_det_en = { 0x60074, 5, 5, 0, 1 }, |
---|
.. | .. |
---|
3172 | 3697 | } |
---|
3173 | 3698 | }; |
---|
3174 | 3699 | |
---|
| 3700 | +static const struct rockchip_usb2phy_cfg rk3562_phy_cfgs[] = { |
---|
| 3701 | + { |
---|
| 3702 | + .reg = 0xff740000, |
---|
| 3703 | + .num_ports = 2, |
---|
| 3704 | + .phy_tuning = rk3562_usb2phy_tuning, |
---|
| 3705 | + .vbus_detect = rockchip_usb2phy_vbus_det_control, |
---|
| 3706 | + .clkout_ctl = { 0x0108, 4, 4, 1, 0 }, |
---|
| 3707 | + .ls_filter_con = { 0x0130, 19, 0, 0x30100, 0x00020 }, |
---|
| 3708 | + .port_cfgs = { |
---|
| 3709 | + [USB2PHY_PORT_OTG] = { |
---|
| 3710 | + .phy_sus = { 0x0100, 8, 0, 0, 0x1d1 }, |
---|
| 3711 | + .bvalid_det_en = { 0x0110, 2, 2, 0, 1 }, |
---|
| 3712 | + .bvalid_det_st = { 0x0114, 2, 2, 0, 1 }, |
---|
| 3713 | + .bvalid_det_clr = { 0x0118, 2, 2, 0, 1 }, |
---|
| 3714 | + .bvalid_grf_sel = { 0x0108, 15, 14, 0, 3 }, |
---|
| 3715 | + .bypass_dm_en = { 0x0108, 2, 2, 0, 1}, |
---|
| 3716 | + .bypass_sel = { 0x0108, 3, 3, 0, 1}, |
---|
| 3717 | + .iddig_output = { 0x0100, 10, 10, 0, 1 }, |
---|
| 3718 | + .iddig_en = { 0x0100, 9, 9, 0, 1 }, |
---|
| 3719 | + .idfall_det_en = { 0x0110, 5, 5, 0, 1 }, |
---|
| 3720 | + .idfall_det_st = { 0x0114, 5, 5, 0, 1 }, |
---|
| 3721 | + .idfall_det_clr = { 0x0118, 5, 5, 0, 1 }, |
---|
| 3722 | + .idrise_det_en = { 0x0110, 4, 4, 0, 1 }, |
---|
| 3723 | + .idrise_det_st = { 0x0114, 4, 4, 0, 1 }, |
---|
| 3724 | + .idrise_det_clr = { 0x0118, 4, 4, 0, 1 }, |
---|
| 3725 | + .ls_det_en = { 0x0110, 0, 0, 0, 1 }, |
---|
| 3726 | + .ls_det_st = { 0x0114, 0, 0, 0, 1 }, |
---|
| 3727 | + .ls_det_clr = { 0x0118, 0, 0, 0, 1 }, |
---|
| 3728 | + .utmi_avalid = { 0x0120, 10, 10, 0, 1 }, |
---|
| 3729 | + .utmi_bvalid = { 0x0120, 9, 9, 0, 1 }, |
---|
| 3730 | + .utmi_iddig = { 0x0120, 6, 6, 0, 1 }, |
---|
| 3731 | + .utmi_ls = { 0x0120, 5, 4, 0, 1 }, |
---|
| 3732 | + .vbus_det_en = { 0x003c, 7, 7, 0, 1 }, |
---|
| 3733 | + }, |
---|
| 3734 | + [USB2PHY_PORT_HOST] = { |
---|
| 3735 | + .phy_sus = { 0x0104, 8, 0, 0x1d2, 0x1d1 }, |
---|
| 3736 | + .ls_det_en = { 0x0110, 1, 1, 0, 1 }, |
---|
| 3737 | + .ls_det_st = { 0x0114, 1, 1, 0, 1 }, |
---|
| 3738 | + .ls_det_clr = { 0x0118, 1, 1, 0, 1 }, |
---|
| 3739 | + .utmi_ls = { 0x0120, 17, 16, 0, 1 }, |
---|
| 3740 | + .utmi_hstdet = { 0x0120, 19, 19, 0, 1 } |
---|
| 3741 | + } |
---|
| 3742 | + }, |
---|
| 3743 | + .chg_det = { |
---|
| 3744 | + .chg_mode = { 0x0100, 8, 0, 0, 0x1d7 }, |
---|
| 3745 | + .cp_det = { 0x0120, 24, 24, 0, 1 }, |
---|
| 3746 | + .dcp_det = { 0x0120, 23, 23, 0, 1 }, |
---|
| 3747 | + .dp_det = { 0x0120, 25, 25, 0, 1 }, |
---|
| 3748 | + .idm_sink_en = { 0x0108, 8, 8, 0, 1 }, |
---|
| 3749 | + .idp_sink_en = { 0x0108, 7, 7, 0, 1 }, |
---|
| 3750 | + .idp_src_en = { 0x0108, 9, 9, 0, 1 }, |
---|
| 3751 | + .rdm_pdwn_en = { 0x0108, 10, 10, 0, 1 }, |
---|
| 3752 | + .vdm_src_en = { 0x0108, 12, 12, 0, 1 }, |
---|
| 3753 | + .vdp_src_en = { 0x0108, 11, 11, 0, 1 }, |
---|
| 3754 | + }, |
---|
| 3755 | + }, |
---|
| 3756 | + { /* sentinel */ } |
---|
| 3757 | +}; |
---|
| 3758 | + |
---|
3175 | 3759 | static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = { |
---|
3176 | 3760 | { |
---|
3177 | 3761 | .reg = 0xfe8a0000, |
---|
.. | .. |
---|
3186 | 3770 | .bvalid_det_en = { 0x0080, 2, 2, 0, 1 }, |
---|
3187 | 3771 | .bvalid_det_st = { 0x0084, 2, 2, 0, 1 }, |
---|
3188 | 3772 | .bvalid_det_clr = { 0x0088, 2, 2, 0, 1 }, |
---|
3189 | | - .bvalid_set = { 0x0008, 15, 14, 0, 3 }, |
---|
| 3773 | + .bvalid_grf_sel = { 0x0008, 15, 14, 0, 3 }, |
---|
3190 | 3774 | .bypass_dm_en = { 0x0008, 2, 2, 0, 1}, |
---|
3191 | 3775 | .bypass_sel = { 0x0008, 3, 3, 0, 1}, |
---|
3192 | 3776 | .iddig_output = { 0x0000, 10, 10, 0, 1 }, |
---|
.. | .. |
---|
3257 | 3841 | { /* sentinel */ } |
---|
3258 | 3842 | }; |
---|
3259 | 3843 | |
---|
| 3844 | +static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = { |
---|
| 3845 | + { |
---|
| 3846 | + .reg = 0x0000, |
---|
| 3847 | + .num_ports = 1, |
---|
| 3848 | + .phy_tuning = rk3588_usb2phy_tuning, |
---|
| 3849 | + .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, |
---|
| 3850 | + .ls_filter_con = { 0x0040, 19, 0, 0x30100, 0x00020 }, |
---|
| 3851 | + .port_cfgs = { |
---|
| 3852 | + [USB2PHY_PORT_OTG] = { |
---|
| 3853 | + .phy_sus = { 0x000c, 11, 11, 0, 1 }, |
---|
| 3854 | + .pipe_phystatus = { 0x001c, 3, 2, 0, 2 }, |
---|
| 3855 | + .bvalid_det_en = { 0x0080, 1, 1, 0, 1 }, |
---|
| 3856 | + .bvalid_det_st = { 0x0084, 1, 1, 0, 1 }, |
---|
| 3857 | + .bvalid_det_clr = { 0x0088, 1, 1, 0, 1 }, |
---|
| 3858 | + .bvalid_grf_sel = { 0x0010, 3, 3, 0, 1 }, |
---|
| 3859 | + .bvalid_grf_con = { 0x0010, 3, 2, 2, 3 }, |
---|
| 3860 | + .bvalid_phy_con = { 0x0008, 1, 0, 2, 3 }, |
---|
| 3861 | + .bypass_dm_en = { 0x000c, 5, 5, 0, 1 }, |
---|
| 3862 | + .bypass_sel = { 0x000c, 6, 6, 0, 1 }, |
---|
| 3863 | + .iddig_output = { 0x0010, 0, 0, 0, 1 }, |
---|
| 3864 | + .iddig_en = { 0x0010, 1, 1, 0, 1 }, |
---|
| 3865 | + .idfall_det_en = { 0x0080, 4, 4, 0, 1 }, |
---|
| 3866 | + .idfall_det_st = { 0x0084, 4, 4, 0, 1 }, |
---|
| 3867 | + .idfall_det_clr = { 0x0088, 4, 4, 0, 1 }, |
---|
| 3868 | + .idrise_det_en = { 0x0080, 3, 3, 0, 1 }, |
---|
| 3869 | + .idrise_det_st = { 0x0084, 3, 3, 0, 1 }, |
---|
| 3870 | + .idrise_det_clr = { 0x0088, 3, 3, 0, 1 }, |
---|
| 3871 | + .ls_det_en = { 0x0080, 0, 0, 0, 1 }, |
---|
| 3872 | + .ls_det_st = { 0x0084, 0, 0, 0, 1 }, |
---|
| 3873 | + .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, |
---|
| 3874 | + .disfall_en = { 0x0080, 6, 6, 0, 1 }, |
---|
| 3875 | + .disfall_st = { 0x0084, 6, 6, 0, 1 }, |
---|
| 3876 | + .disfall_clr = { 0x0088, 6, 6, 0, 1 }, |
---|
| 3877 | + .disrise_en = { 0x0080, 5, 5, 0, 1 }, |
---|
| 3878 | + .disrise_st = { 0x0084, 5, 5, 0, 1 }, |
---|
| 3879 | + .disrise_clr = { 0x0088, 5, 5, 0, 1 }, |
---|
| 3880 | + .utmi_avalid = { 0x00c0, 7, 7, 0, 1 }, |
---|
| 3881 | + .utmi_bvalid = { 0x00c0, 6, 6, 0, 1 }, |
---|
| 3882 | + .utmi_iddig = { 0x00c0, 5, 5, 0, 1 }, |
---|
| 3883 | + .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, |
---|
| 3884 | + } |
---|
| 3885 | + }, |
---|
| 3886 | + .chg_det = { |
---|
| 3887 | + .chg_mode = { 0x0008, 2, 2, 0, 1 }, |
---|
| 3888 | + .cp_det = { 0x00c0, 0, 0, 0, 1 }, |
---|
| 3889 | + .dcp_det = { 0x00c0, 0, 0, 0, 1 }, |
---|
| 3890 | + .dp_det = { 0x00c0, 1, 1, 1, 0 }, |
---|
| 3891 | + .idm_sink_en = { 0x0008, 5, 5, 1, 0 }, |
---|
| 3892 | + .idp_sink_en = { 0x0008, 5, 5, 0, 1 }, |
---|
| 3893 | + .idp_src_en = { 0x0008, 14, 14, 0, 1 }, |
---|
| 3894 | + .rdm_pdwn_en = { 0x0008, 14, 14, 0, 1 }, |
---|
| 3895 | + .vdm_src_en = { 0x0008, 7, 6, 0, 3 }, |
---|
| 3896 | + .vdp_src_en = { 0x0008, 7, 6, 0, 3 }, |
---|
| 3897 | + }, |
---|
| 3898 | + }, |
---|
| 3899 | + { |
---|
| 3900 | + .reg = 0x4000, |
---|
| 3901 | + .num_ports = 1, |
---|
| 3902 | + .phy_tuning = rk3588_usb2phy_tuning, |
---|
| 3903 | + .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, |
---|
| 3904 | + .ls_filter_con = { 0x0040, 19, 0, 0x30100, 0x00020 }, |
---|
| 3905 | + .port_cfgs = { |
---|
| 3906 | + [USB2PHY_PORT_OTG] = { |
---|
| 3907 | + .phy_sus = { 0x000c, 11, 11, 0, 1 }, |
---|
| 3908 | + .pipe_phystatus = { 0x0034, 3, 2, 0, 2 }, |
---|
| 3909 | + .bvalid_det_en = { 0x0080, 1, 1, 0, 1 }, |
---|
| 3910 | + .bvalid_det_st = { 0x0084, 1, 1, 0, 1 }, |
---|
| 3911 | + .bvalid_det_clr = { 0x0088, 1, 1, 0, 1 }, |
---|
| 3912 | + .bvalid_grf_sel = { 0x0010, 3, 3, 0, 1 }, |
---|
| 3913 | + .bvalid_grf_con = { 0x0010, 3, 2, 2, 3 }, |
---|
| 3914 | + .bvalid_phy_con = { 0x0008, 1, 0, 2, 3 }, |
---|
| 3915 | + .bypass_dm_en = { 0x000c, 5, 5, 0, 1 }, |
---|
| 3916 | + .bypass_sel = { 0x000c, 6, 6, 0, 1 }, |
---|
| 3917 | + .iddig_output = { 0x0010, 0, 0, 0, 1 }, |
---|
| 3918 | + .iddig_en = { 0x0010, 1, 1, 0, 1 }, |
---|
| 3919 | + .idfall_det_en = { 0x0080, 4, 4, 0, 1 }, |
---|
| 3920 | + .idfall_det_st = { 0x0084, 4, 4, 0, 1 }, |
---|
| 3921 | + .idfall_det_clr = { 0x0088, 4, 4, 0, 1 }, |
---|
| 3922 | + .idrise_det_en = { 0x0080, 3, 3, 0, 1 }, |
---|
| 3923 | + .idrise_det_st = { 0x0084, 3, 3, 0, 1 }, |
---|
| 3924 | + .idrise_det_clr = { 0x0088, 3, 3, 0, 1 }, |
---|
| 3925 | + .ls_det_en = { 0x0080, 0, 0, 0, 1 }, |
---|
| 3926 | + .ls_det_st = { 0x0084, 0, 0, 0, 1 }, |
---|
| 3927 | + .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, |
---|
| 3928 | + .disfall_en = { 0x0080, 6, 6, 0, 1 }, |
---|
| 3929 | + .disfall_st = { 0x0084, 6, 6, 0, 1 }, |
---|
| 3930 | + .disfall_clr = { 0x0088, 6, 6, 0, 1 }, |
---|
| 3931 | + .disrise_en = { 0x0080, 5, 5, 0, 1 }, |
---|
| 3932 | + .disrise_st = { 0x0084, 5, 5, 0, 1 }, |
---|
| 3933 | + .disrise_clr = { 0x0088, 5, 5, 0, 1 }, |
---|
| 3934 | + .utmi_avalid = { 0x00c0, 7, 7, 0, 1 }, |
---|
| 3935 | + .utmi_bvalid = { 0x00c0, 6, 6, 0, 1 }, |
---|
| 3936 | + .utmi_iddig = { 0x00c0, 5, 5, 0, 1 }, |
---|
| 3937 | + .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, |
---|
| 3938 | + } |
---|
| 3939 | + }, |
---|
| 3940 | + .chg_det = { |
---|
| 3941 | + .chg_mode = { 0x0008, 2, 2, 0, 1 }, |
---|
| 3942 | + .cp_det = { 0x00c0, 0, 0, 0, 1 }, |
---|
| 3943 | + .dcp_det = { 0x00c0, 0, 0, 0, 1 }, |
---|
| 3944 | + .dp_det = { 0x00c0, 1, 1, 1, 0 }, |
---|
| 3945 | + .idm_sink_en = { 0x0008, 5, 5, 1, 0 }, |
---|
| 3946 | + .idp_sink_en = { 0x0008, 5, 5, 0, 1 }, |
---|
| 3947 | + .idp_src_en = { 0x0008, 14, 14, 0, 1 }, |
---|
| 3948 | + .rdm_pdwn_en = { 0x0008, 14, 14, 0, 1 }, |
---|
| 3949 | + .vdm_src_en = { 0x0008, 7, 6, 0, 3 }, |
---|
| 3950 | + .vdp_src_en = { 0x0008, 7, 6, 0, 3 }, |
---|
| 3951 | + }, |
---|
| 3952 | + }, |
---|
| 3953 | + { |
---|
| 3954 | + .reg = 0x8000, |
---|
| 3955 | + .num_ports = 1, |
---|
| 3956 | + .phy_tuning = rk3588_usb2phy_tuning, |
---|
| 3957 | + .clkout_ctl = { 0x0000, 0, 0, 0, 0 }, |
---|
| 3958 | + .ls_filter_con = { 0x0040, 19, 0, 0x30100, 0x00020 }, |
---|
| 3959 | + .port_cfgs = { |
---|
| 3960 | + [USB2PHY_PORT_HOST] = { |
---|
| 3961 | + .phy_sus = { 0x0008, 2, 2, 0, 1 }, |
---|
| 3962 | + .ls_det_en = { 0x0080, 0, 0, 0, 1 }, |
---|
| 3963 | + .ls_det_st = { 0x0084, 0, 0, 0, 1 }, |
---|
| 3964 | + .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, |
---|
| 3965 | + .disfall_en = { 0x0080, 6, 6, 0, 1 }, |
---|
| 3966 | + .disfall_st = { 0x0084, 6, 6, 0, 1 }, |
---|
| 3967 | + .disfall_clr = { 0x0088, 6, 6, 0, 1 }, |
---|
| 3968 | + .disrise_en = { 0x0080, 5, 5, 0, 1 }, |
---|
| 3969 | + .disrise_st = { 0x0084, 5, 5, 0, 1 }, |
---|
| 3970 | + .disrise_clr = { 0x0088, 5, 5, 0, 1 }, |
---|
| 3971 | + .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, |
---|
| 3972 | + } |
---|
| 3973 | + }, |
---|
| 3974 | + }, |
---|
| 3975 | + { |
---|
| 3976 | + .reg = 0xc000, |
---|
| 3977 | + .num_ports = 1, |
---|
| 3978 | + .phy_tuning = rk3588_usb2phy_tuning, |
---|
| 3979 | + .clkout_ctl = { 0x0000, 0, 0, 0, 0 }, |
---|
| 3980 | + .ls_filter_con = { 0x0040, 19, 0, 0x30100, 0x00020 }, |
---|
| 3981 | + .port_cfgs = { |
---|
| 3982 | + [USB2PHY_PORT_HOST] = { |
---|
| 3983 | + .phy_sus = { 0x0008, 2, 2, 0, 1 }, |
---|
| 3984 | + .ls_det_en = { 0x0080, 0, 0, 0, 1 }, |
---|
| 3985 | + .ls_det_st = { 0x0084, 0, 0, 0, 1 }, |
---|
| 3986 | + .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, |
---|
| 3987 | + .disfall_en = { 0x0080, 6, 6, 0, 1 }, |
---|
| 3988 | + .disfall_st = { 0x0084, 6, 6, 0, 1 }, |
---|
| 3989 | + .disfall_clr = { 0x0088, 6, 6, 0, 1 }, |
---|
| 3990 | + .disrise_en = { 0x0080, 5, 5, 0, 1 }, |
---|
| 3991 | + .disrise_st = { 0x0084, 5, 5, 0, 1 }, |
---|
| 3992 | + .disrise_clr = { 0x0088, 5, 5, 0, 1 }, |
---|
| 3993 | + .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, |
---|
| 3994 | + } |
---|
| 3995 | + }, |
---|
| 3996 | + }, |
---|
| 3997 | + { /* sentinel */ } |
---|
| 3998 | +}; |
---|
| 3999 | + |
---|
| 4000 | +static const struct rockchip_usb2phy_cfg rv1106_phy_cfgs[] = { |
---|
| 4001 | + { |
---|
| 4002 | + .reg = 0xff3e0000, |
---|
| 4003 | + .num_ports = 1, |
---|
| 4004 | + .phy_tuning = rv1106_usb2phy_tuning, |
---|
| 4005 | + .clkout_ctl = { 0x0058, 4, 4, 1, 0 }, |
---|
| 4006 | + .port_cfgs = { |
---|
| 4007 | + [USB2PHY_PORT_OTG] = { |
---|
| 4008 | + .phy_sus = { 0x0050, 8, 0, 0, 0x1d1 }, |
---|
| 4009 | + .bvalid_det_en = { 0x0100, 2, 2, 0, 1 }, |
---|
| 4010 | + .bvalid_det_st = { 0x0104, 2, 2, 0, 1 }, |
---|
| 4011 | + .bvalid_det_clr = { 0x0108, 2, 2, 0, 1 }, |
---|
| 4012 | + .bvalid_grf_sel = { 0x0058, 15, 14, 0, 3 }, |
---|
| 4013 | + .iddig_output = { 0x0050, 10, 10, 0, 1 }, |
---|
| 4014 | + .iddig_en = { 0x0050, 9, 9, 0, 1 }, |
---|
| 4015 | + .idfall_det_en = { 0x0100, 5, 5, 0, 1 }, |
---|
| 4016 | + .idfall_det_st = { 0x0104, 5, 5, 0, 1 }, |
---|
| 4017 | + .idfall_det_clr = { 0x0108, 5, 5, 0, 1 }, |
---|
| 4018 | + .idrise_det_en = { 0x0100, 4, 4, 0, 1 }, |
---|
| 4019 | + .idrise_det_st = { 0x0104, 4, 4, 0, 1 }, |
---|
| 4020 | + .idrise_det_clr = { 0x0108, 4, 4, 0, 1 }, |
---|
| 4021 | + .ls_det_en = { 0x0100, 0, 0, 0, 1 }, |
---|
| 4022 | + .ls_det_st = { 0x0104, 0, 0, 0, 1 }, |
---|
| 4023 | + .ls_det_clr = { 0x0108, 0, 0, 0, 1 }, |
---|
| 4024 | + .utmi_avalid = { 0x0060, 10, 10, 0, 1 }, |
---|
| 4025 | + .utmi_bvalid = { 0x0060, 9, 9, 0, 1 }, |
---|
| 4026 | + .utmi_iddig = { 0x0060, 6, 6, 0, 1 }, |
---|
| 4027 | + .utmi_ls = { 0x0060, 5, 4, 0, 1 }, |
---|
| 4028 | + }, |
---|
| 4029 | + }, |
---|
| 4030 | + .chg_det = { |
---|
| 4031 | + .chg_mode = { 0x0050, 8, 0, 0, 0x1d7 }, |
---|
| 4032 | + .cp_det = { 0x0060, 13, 13, 0, 1 }, |
---|
| 4033 | + .dcp_det = { 0x0060, 12, 12, 0, 1 }, |
---|
| 4034 | + .dp_det = { 0x0060, 14, 14, 0, 1 }, |
---|
| 4035 | + .idm_sink_en = { 0x0058, 8, 8, 0, 1 }, |
---|
| 4036 | + .idp_sink_en = { 0x0058, 7, 7, 0, 1 }, |
---|
| 4037 | + .idp_src_en = { 0x0058, 9, 9, 0, 1 }, |
---|
| 4038 | + .rdm_pdwn_en = { 0x0058, 10, 10, 0, 1 }, |
---|
| 4039 | + .vdm_src_en = { 0x0058, 12, 12, 0, 1 }, |
---|
| 4040 | + .vdp_src_en = { 0x0058, 11, 11, 0, 1 }, |
---|
| 4041 | + }, |
---|
| 4042 | + }, |
---|
| 4043 | + { /* sentinel */ } |
---|
| 4044 | +}; |
---|
| 4045 | + |
---|
3260 | 4046 | static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = { |
---|
3261 | 4047 | { |
---|
3262 | 4048 | .reg = 0x100, |
---|
.. | .. |
---|
3300 | 4086 | }; |
---|
3301 | 4087 | |
---|
3302 | 4088 | static const struct of_device_id rockchip_usb2phy_dt_match[] = { |
---|
| 4089 | +#ifdef CONFIG_CPU_PX30 |
---|
| 4090 | + { .compatible = "rockchip,px30-usb2phy", .data = &rk3328_phy_cfgs }, |
---|
| 4091 | +#endif |
---|
| 4092 | +#ifdef CONFIG_CPU_RK1808 |
---|
3303 | 4093 | { .compatible = "rockchip,rk1808-usb2phy", .data = &rk1808_phy_cfgs }, |
---|
| 4094 | +#endif |
---|
| 4095 | +#ifdef CONFIG_CPU_RK312X |
---|
3304 | 4096 | { .compatible = "rockchip,rk3128-usb2phy", .data = &rk312x_phy_cfgs }, |
---|
| 4097 | +#endif |
---|
| 4098 | +#ifdef CONFIG_CPU_RK322X |
---|
3305 | 4099 | { .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs }, |
---|
| 4100 | +#endif |
---|
| 4101 | +#ifdef CONFIG_CPU_RK3308 |
---|
3306 | 4102 | { .compatible = "rockchip,rk3308-usb2phy", .data = &rk3308_phy_cfgs }, |
---|
| 4103 | +#endif |
---|
| 4104 | +#ifdef CONFIG_CPU_RK3328 |
---|
3307 | 4105 | { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs }, |
---|
| 4106 | +#endif |
---|
| 4107 | +#ifdef CONFIG_CPU_RK3366 |
---|
3308 | 4108 | { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs }, |
---|
| 4109 | +#endif |
---|
| 4110 | +#ifdef CONFIG_CPU_RK3368 |
---|
3309 | 4111 | { .compatible = "rockchip,rk3368-usb2phy", .data = &rk3368_phy_cfgs }, |
---|
| 4112 | +#endif |
---|
| 4113 | +#ifdef CONFIG_CPU_RK3399 |
---|
3310 | 4114 | { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs }, |
---|
| 4115 | +#endif |
---|
| 4116 | +#ifdef CONFIG_CPU_RK3528 |
---|
3311 | 4117 | { .compatible = "rockchip,rk3528-usb2phy", .data = &rk3528_phy_cfgs }, |
---|
| 4118 | +#endif |
---|
| 4119 | +#ifdef CONFIG_CPU_RK3562 |
---|
| 4120 | + { .compatible = "rockchip,rk3562-usb2phy", .data = &rk3562_phy_cfgs }, |
---|
| 4121 | +#endif |
---|
| 4122 | +#ifdef CONFIG_CPU_RK3568 |
---|
3312 | 4123 | { .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs }, |
---|
| 4124 | +#endif |
---|
| 4125 | +#ifdef CONFIG_CPU_RK3588 |
---|
| 4126 | + { .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs }, |
---|
| 4127 | +#endif |
---|
| 4128 | +#ifdef CONFIG_CPU_RV1106 |
---|
| 4129 | + { .compatible = "rockchip,rv1106-usb2phy", .data = &rv1106_phy_cfgs }, |
---|
| 4130 | +#endif |
---|
| 4131 | +#ifdef CONFIG_CPU_RV1108 |
---|
3313 | 4132 | { .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs }, |
---|
| 4133 | +#endif |
---|
3314 | 4134 | {} |
---|
3315 | 4135 | }; |
---|
3316 | 4136 | MODULE_DEVICE_TABLE(of, rockchip_usb2phy_dt_match); |
---|