Lines Matching +full:sun8i +full:- +full:a23 +full:- +full:usb +full:- +full:phy

2  * Allwinner sun4i USB PHY driver
8 * Modelled arch/arm/mach-sunxi/usb_phy.c to compatible with generic-phy.
10 * SPDX-License-Identifier: GPL-2.0+
17 #include <generic-phy.h>
18 #include <phy-sun4i-usb.h>
37 /* Private Control Bits for Each PHY */
136 static void sun4i_usb_phy_write(struct phy *phy, u32 addr, u32 data, int len) in sun4i_usb_phy_write() argument
138 struct sun4i_usb_phy_data *phy_data = dev_get_priv(phy->dev); in sun4i_usb_phy_write()
139 struct sun4i_usb_phy_plat *usb_phy = &phy_data->usb_phy[phy->id]; in sun4i_usb_phy_write()
140 u32 temp, usbc_bit = BIT(usb_phy->id * 2); in sun4i_usb_phy_write()
141 void __iomem *phyctl = phy_data->base + phy_data->cfg->phyctl_offset; in sun4i_usb_phy_write()
144 if (phy_data->cfg->phyctl_offset == REG_PHYCTL_A33) { in sun4i_usb_phy_write()
181 static void sun4i_usb_phy_passby(struct phy *phy, bool enable) in sun4i_usb_phy_passby() argument
183 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); in sun4i_usb_phy_passby()
184 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; in sun4i_usb_phy_passby()
187 if (!usb_phy->pmu) in sun4i_usb_phy_passby()
194 if (data->cfg->type == sun8i_a83t_phy && usb_phy->id == 2) in sun4i_usb_phy_passby()
198 reg_value = readl(usb_phy->pmu); in sun4i_usb_phy_passby()
205 writel(reg_value, usb_phy->pmu); in sun4i_usb_phy_passby()
208 static int sun4i_usb_phy_power_on(struct phy *phy) in sun4i_usb_phy_power_on() argument
210 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); in sun4i_usb_phy_power_on()
211 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; in sun4i_usb_phy_power_on()
218 usb_phy->power_on_count++; in sun4i_usb_phy_power_on()
219 if (usb_phy->power_on_count != 1) in sun4i_usb_phy_power_on()
222 if (usb_phy->gpio_vbus >= 0) in sun4i_usb_phy_power_on()
223 gpio_set_value(usb_phy->gpio_vbus, SUNXI_GPIO_PULL_UP); in sun4i_usb_phy_power_on()
228 static int sun4i_usb_phy_power_off(struct phy *phy) in sun4i_usb_phy_power_off() argument
230 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); in sun4i_usb_phy_power_off()
231 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; in sun4i_usb_phy_power_off()
233 usb_phy->power_on_count--; in sun4i_usb_phy_power_off()
234 if (usb_phy->power_on_count != 0) in sun4i_usb_phy_power_off()
237 if (usb_phy->gpio_vbus >= 0) in sun4i_usb_phy_power_off()
238 gpio_set_value(usb_phy->gpio_vbus, SUNXI_GPIO_PULL_DISABLE); in sun4i_usb_phy_power_off()
247 regval = readl(data->base + REG_PHY_OTGCTL); in sun4i_usb_phy0_reroute()
255 writel(regval, data->base + REG_PHY_OTGCTL); in sun4i_usb_phy0_reroute()
258 static int sun4i_usb_phy_init(struct phy *phy) in sun4i_usb_phy_init() argument
260 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); in sun4i_usb_phy_init()
261 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; in sun4i_usb_phy_init()
265 ret = clk_enable(&usb_phy->clocks); in sun4i_usb_phy_init()
267 dev_err(dev, "failed to enable usb_%ldphy clock\n", phy->id); in sun4i_usb_phy_init()
271 ret = reset_deassert(&usb_phy->resets); in sun4i_usb_phy_init()
273 dev_err(dev, "failed to deassert usb_%ldreset reset\n", phy->id); in sun4i_usb_phy_init()
277 if (data->cfg->type == sun8i_a83t_phy) { in sun4i_usb_phy_init()
278 if (phy->id == 0) { in sun4i_usb_phy_init()
279 val = readl(data->base + data->cfg->phyctl_offset); in sun4i_usb_phy_init()
282 writel(val, data->base + data->cfg->phyctl_offset); in sun4i_usb_phy_init()
285 if (usb_phy->pmu && data->cfg->enable_pmu_unk1) { in sun4i_usb_phy_init()
286 val = readl(usb_phy->pmu + REG_PMU_UNK1); in sun4i_usb_phy_init()
287 writel(val & ~2, usb_phy->pmu + REG_PMU_UNK1); in sun4i_usb_phy_init()
290 if (usb_phy->id == 0) in sun4i_usb_phy_init()
291 sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, in sun4i_usb_phy_init()
295 /* Adjust PHY's magnitude and rate */ in sun4i_usb_phy_init()
296 sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, in sun4i_usb_phy_init()
301 sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, in sun4i_usb_phy_init()
302 data->cfg->disc_thresh, PHY_DISCON_TH_LEN); in sun4i_usb_phy_init()
305 sun4i_usb_phy_passby(phy, true); in sun4i_usb_phy_init()
312 static int sun4i_usb_phy_exit(struct phy *phy) in sun4i_usb_phy_exit() argument
314 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); in sun4i_usb_phy_exit()
315 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; in sun4i_usb_phy_exit()
318 if (phy->id == 0) { in sun4i_usb_phy_exit()
319 if (data->cfg->type == sun8i_a83t_phy) { in sun4i_usb_phy_exit()
320 void __iomem *phyctl = data->base + in sun4i_usb_phy_exit()
321 data->cfg->phyctl_offset; in sun4i_usb_phy_exit()
327 sun4i_usb_phy_passby(phy, false); in sun4i_usb_phy_exit()
329 ret = clk_disable(&usb_phy->clocks); in sun4i_usb_phy_exit()
331 dev_err(dev, "failed to disable usb_%ldphy clock\n", phy->id); in sun4i_usb_phy_exit()
335 ret = reset_assert(&usb_phy->resets); in sun4i_usb_phy_exit()
337 dev_err(dev, "failed to assert usb_%ldreset reset\n", phy->id); in sun4i_usb_phy_exit()
344 static int sun4i_usb_phy_xlate(struct phy *phy, in sun4i_usb_phy_xlate() argument
347 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); in sun4i_usb_phy_xlate()
349 if (args->args_count >= data->cfg->num_phys) in sun4i_usb_phy_xlate()
350 return -EINVAL; in sun4i_usb_phy_xlate()
352 if (args->args_count) in sun4i_usb_phy_xlate()
353 phy->id = args->args[0]; in sun4i_usb_phy_xlate()
355 phy->id = 0; in sun4i_usb_phy_xlate()
357 debug("%s: phy_id = %ld\n", __func__, phy->id); in sun4i_usb_phy_xlate()
361 int sun4i_usb_phy_vbus_detect(struct phy *phy) in sun4i_usb_phy_vbus_detect() argument
363 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); in sun4i_usb_phy_vbus_detect()
364 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; in sun4i_usb_phy_vbus_detect()
367 debug("%s: id_det = %d\n", __func__, usb_phy->gpio_id_det); in sun4i_usb_phy_vbus_detect()
369 if (usb_phy->gpio_vbus_det < 0) in sun4i_usb_phy_vbus_detect()
370 return usb_phy->gpio_vbus_det; in sun4i_usb_phy_vbus_detect()
372 err = gpio_get_value(usb_phy->gpio_vbus_det); in sun4i_usb_phy_vbus_detect()
378 while (err > 0 && retries--) { in sun4i_usb_phy_vbus_detect()
380 err = gpio_get_value(usb_phy->gpio_vbus_det); in sun4i_usb_phy_vbus_detect()
386 int sun4i_usb_phy_id_detect(struct phy *phy) in sun4i_usb_phy_id_detect() argument
388 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); in sun4i_usb_phy_id_detect()
389 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; in sun4i_usb_phy_id_detect()
391 debug("%s: id_det = %d\n", __func__, usb_phy->gpio_id_det); in sun4i_usb_phy_id_detect()
393 if (usb_phy->gpio_id_det < 0) in sun4i_usb_phy_id_detect()
394 return usb_phy->gpio_id_det; in sun4i_usb_phy_id_detect()
396 return gpio_get_value(usb_phy->gpio_id_det); in sun4i_usb_phy_id_detect()
399 void sun4i_usb_phy_set_squelch_detect(struct phy *phy, bool enabled) in sun4i_usb_phy_set_squelch_detect() argument
401 sun4i_usb_phy_write(phy, PHY_SQUELCH_DETECT, enabled ? 0 : 2, 2); in sun4i_usb_phy_set_squelch_detect()
418 data->cfg = (const struct sun4i_usb_phy_cfg *)dev_get_driver_data(dev); in sun4i_usb_phy_probe()
419 if (!data->cfg) in sun4i_usb_phy_probe()
420 return -EINVAL; in sun4i_usb_phy_probe()
422 data->base = (void __iomem *)devfdt_get_addr_name(dev, "phy_ctrl"); in sun4i_usb_phy_probe()
423 if (IS_ERR(data->base)) in sun4i_usb_phy_probe()
424 return PTR_ERR(data->base); in sun4i_usb_phy_probe()
426 data->usb_phy = plat; in sun4i_usb_phy_probe()
427 for (i = 0; i < data->cfg->num_phys; i++) { in sun4i_usb_phy_probe()
428 struct sun4i_usb_phy_plat *phy = &plat[i]; in sun4i_usb_phy_probe() local
432 phy->gpio_vbus = sunxi_name_to_gpio(info->gpio_vbus); in sun4i_usb_phy_probe()
433 if (phy->gpio_vbus >= 0) { in sun4i_usb_phy_probe()
434 ret = gpio_request(phy->gpio_vbus, "usb_vbus"); in sun4i_usb_phy_probe()
437 ret = gpio_direction_output(phy->gpio_vbus, 0); in sun4i_usb_phy_probe()
442 phy->gpio_vbus_det = sunxi_name_to_gpio(info->gpio_vbus_det); in sun4i_usb_phy_probe()
443 if (phy->gpio_vbus_det >= 0) { in sun4i_usb_phy_probe()
444 ret = gpio_request(phy->gpio_vbus_det, "usb_vbus_det"); in sun4i_usb_phy_probe()
447 ret = gpio_direction_input(phy->gpio_vbus_det); in sun4i_usb_phy_probe()
452 phy->gpio_id_det = sunxi_name_to_gpio(info->gpio_id_det); in sun4i_usb_phy_probe()
453 if (phy->gpio_id_det >= 0) { in sun4i_usb_phy_probe()
454 ret = gpio_request(phy->gpio_id_det, "usb_id_det"); in sun4i_usb_phy_probe()
457 ret = gpio_direction_input(phy->gpio_id_det); in sun4i_usb_phy_probe()
460 sunxi_gpio_set_pull(phy->gpio_id_det, SUNXI_GPIO_PULL_UP); in sun4i_usb_phy_probe()
463 if (data->cfg->dedicated_clocks) in sun4i_usb_phy_probe()
464 snprintf(name, sizeof(name), "usb%d_phy", i); in sun4i_usb_phy_probe()
468 ret = clk_get_by_name(dev, name, &phy->clocks); in sun4i_usb_phy_probe()
470 dev_err(dev, "failed to get usb%d_phy clock phandle\n", i); in sun4i_usb_phy_probe()
474 snprintf(name, sizeof(name), "usb%d_reset", i); in sun4i_usb_phy_probe()
475 ret = reset_get_by_name(dev, name, &phy->resets); in sun4i_usb_phy_probe()
477 dev_err(dev, "failed to get usb%d_reset reset phandle\n", i); in sun4i_usb_phy_probe()
481 if (i || data->cfg->phy0_dual_route) { in sun4i_usb_phy_probe()
483 phy->pmu = (void __iomem *)devfdt_get_addr_name(dev, name); in sun4i_usb_phy_probe()
484 if (IS_ERR(phy->pmu)) in sun4i_usb_phy_probe()
485 return PTR_ERR(phy->pmu); in sun4i_usb_phy_probe()
488 phy->id = i; in sun4i_usb_phy_probe()
491 debug("Allwinner Sun4I USB PHY driver loaded\n"); in sun4i_usb_phy_probe()
587 { .compatible = "allwinner,sun4i-a10-usb-phy", .data = (ulong)&sun4i_a10_cfg },
588 { .compatible = "allwinner,sun5i-a13-usb-phy", .data = (ulong)&sun5i_a13_cfg },
589 { .compatible = "allwinner,sun6i-a31-usb-phy", .data = (ulong)&sun6i_a31_cfg },
590 { .compatible = "allwinner,sun7i-a20-usb-phy", .data = (ulong)&sun7i_a20_cfg },
591 { .compatible = "allwinner,sun8i-a23-usb-phy", .data = (ulong)&sun8i_a23_cfg },
592 { .compatible = "allwinner,sun8i-a33-usb-phy", .data = (ulong)&sun8i_a33_cfg },
593 { .compatible = "allwinner,sun8i-a83t-usb-phy", .data = (ulong)&sun8i_a83t_cfg },
594 { .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg },
595 { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = (ulong)&sun8i_v3s_cfg },
596 { .compatible = "allwinner,sun50i-a64-usb-phy", .data = (ulong)&sun50i_a64_cfg},