^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Allwinner sun4i USB phy driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2014-2015 Hans de Goede <hdegoede@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Based on code from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Modelled after: Samsung S5P/Exynos SoC series MIPI CSIS/DSIM DPHY driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2013 Samsung Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/extcon-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/of_gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/phy/phy-sun4i-usb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/power_supply.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/reset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/usb/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define REG_ISCR 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define REG_PHYCTL_A10 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define REG_PHYBIST 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define REG_PHYTUNE 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define REG_PHYCTL_A33 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define REG_PHY_OTGCTL 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define REG_PMU_UNK1 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define PHYCTL_DATA BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define OTGCTL_ROUTE_MUSB BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define SUNXI_AHB_ICHR8_EN BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define SUNXI_AHB_INCR4_BURST_EN BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define SUNXI_AHB_INCRX_ALIGN_EN BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define SUNXI_ULPI_BYPASS_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* ISCR, Interface Status and Control bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define ISCR_ID_PULLUP_EN (1 << 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define ISCR_DPDM_PULLUP_EN (1 << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* sunxi has the phy id/vbus pins not connected, so we use the force bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define ISCR_FORCE_ID_MASK (3 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define ISCR_FORCE_ID_LOW (2 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define ISCR_FORCE_ID_HIGH (3 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define ISCR_FORCE_VBUS_MASK (3 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define ISCR_FORCE_VBUS_LOW (2 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define ISCR_FORCE_VBUS_HIGH (3 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* Common Control Bits for Both PHYs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define PHY_PLL_BW 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define PHY_RES45_CAL_EN 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* Private Control Bits for Each PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define PHY_TX_AMPLITUDE_TUNE 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define PHY_TX_SLEWRATE_TUNE 0x22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define PHY_VBUSVALID_TH_SEL 0x25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define PHY_PULLUP_RES_SEL 0x27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define PHY_OTG_FUNC_EN 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define PHY_VBUS_DET_EN 0x29
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define PHY_DISCON_TH_SEL 0x2a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define PHY_SQUELCH_DETECT 0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* A83T specific control bits for PHY0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define PHY_CTL_VBUSVLDEXT BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define PHY_CTL_SIDDQ BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* A83T specific control bits for PHY2 HSIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define SUNXI_EHCI_HS_FORCE BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define SUNXI_HSIC_CONNECT_DET BIT(17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define SUNXI_HSIC_CONNECT_INT BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define SUNXI_HSIC BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define MAX_PHYS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * Note do not raise the debounce time, we must report Vusb high within 100ms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * otherwise we get Vbus errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define DEBOUNCE_TIME msecs_to_jiffies(50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define POLL_TIME msecs_to_jiffies(250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) enum sun4i_usb_phy_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) sun4i_a10_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) sun6i_a31_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) sun8i_a33_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) sun8i_a83t_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) sun8i_h3_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) sun8i_r40_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) sun8i_v3s_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) sun50i_a64_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) sun50i_h6_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct sun4i_usb_phy_cfg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) int num_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int hsic_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) enum sun4i_usb_phy_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) u32 disc_thresh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u8 phyctl_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) bool dedicated_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) bool enable_pmu_unk1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) bool phy0_dual_route;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int missing_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct sun4i_usb_phy_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) const struct sun4i_usb_phy_cfg *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) enum usb_dr_mode dr_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) spinlock_t reg_lock; /* guard access to phyctl reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct sun4i_usb_phy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) void __iomem *pmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct regulator *vbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct reset_control *reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct clk *clk2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) bool regulator_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) } phys[MAX_PHYS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* phy0 / otg related variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct extcon_dev *extcon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) bool phy0_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct gpio_desc *id_det_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct gpio_desc *vbus_det_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct power_supply *vbus_power_supply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct notifier_block vbus_power_nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) bool vbus_power_nb_registered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) bool force_session_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int id_det_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int vbus_det_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int id_det;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int vbus_det;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct delayed_work detect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define to_sun4i_usb_phy_data(phy) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static void sun4i_usb_phy0_update_iscr(struct phy *_phy, u32 clr, u32 set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) u32 iscr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) iscr = readl(data->base + REG_ISCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) iscr &= ~clr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) iscr |= set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) writel(iscr, data->base + REG_ISCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static void sun4i_usb_phy0_set_id_detect(struct phy *phy, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) val = ISCR_FORCE_ID_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) val = ISCR_FORCE_ID_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_ID_MASK, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static void sun4i_usb_phy0_set_vbus_detect(struct phy *phy, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) val = ISCR_FORCE_VBUS_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) val = ISCR_FORCE_VBUS_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_VBUS_MASK, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) u32 temp, usbc_bit = BIT(phy->index * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) void __iomem *phyctl = phy_data->base + phy_data->cfg->phyctl_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) spin_lock_irqsave(&phy_data->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (phy_data->cfg->phyctl_offset == REG_PHYCTL_A33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* SoCs newer than A33 need us to set phyctl to 0 explicitly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) writel(0, phyctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) temp = readl(phyctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* clear the address portion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) temp &= ~(0xff << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* set the address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) temp |= ((addr + i) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) writel(temp, phyctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* set the data bit and clear usbc bit*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) temp = readb(phyctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (data & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) temp |= PHYCTL_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) temp &= ~PHYCTL_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) temp &= ~usbc_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) writeb(temp, phyctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* pulse usbc_bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) temp = readb(phyctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) temp |= usbc_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) writeb(temp, phyctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) temp = readb(phyctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) temp &= ~usbc_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) writeb(temp, phyctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) data >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) spin_unlock_irqrestore(&phy_data->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) u32 bits, reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (!phy->pmu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* A83T USB2 is HSIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (phy_data->cfg->type == sun8i_a83t_phy && phy->index == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) bits |= SUNXI_EHCI_HS_FORCE | SUNXI_HSIC_CONNECT_INT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) SUNXI_HSIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) reg_value = readl(phy->pmu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) reg_value |= bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) reg_value &= ~bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) writel(reg_value, phy->pmu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static int sun4i_usb_phy_init(struct phy *_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ret = clk_prepare_enable(phy->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) ret = clk_prepare_enable(phy->clk2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) clk_disable_unprepare(phy->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ret = reset_control_deassert(phy->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) clk_disable_unprepare(phy->clk2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) clk_disable_unprepare(phy->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (data->cfg->type == sun8i_a83t_phy ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) data->cfg->type == sun50i_h6_phy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (phy->index == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) val = readl(data->base + data->cfg->phyctl_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) val |= PHY_CTL_VBUSVLDEXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) val &= ~PHY_CTL_SIDDQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) writel(val, data->base + data->cfg->phyctl_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (phy->pmu && data->cfg->enable_pmu_unk1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) val = readl(phy->pmu + REG_PMU_UNK1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) writel(val & ~2, phy->pmu + REG_PMU_UNK1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* Enable USB 45 Ohm resistor calibration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (phy->index == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /* Adjust PHY's magnitude and rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* Disconnect threshold adjustment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) data->cfg->disc_thresh, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) sun4i_usb_phy_passby(phy, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (phy->index == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) data->phy0_init = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /* Enable pull-ups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_DPDM_PULLUP_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_ID_PULLUP_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* Force ISCR and cable state updates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) data->id_det = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) data->vbus_det = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) queue_delayed_work(system_wq, &data->detect, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static int sun4i_usb_phy_exit(struct phy *_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (phy->index == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (data->cfg->type == sun8i_a83t_phy ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) data->cfg->type == sun50i_h6_phy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) void __iomem *phyctl = data->base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) data->cfg->phyctl_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) writel(readl(phyctl) | PHY_CTL_SIDDQ, phyctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* Disable pull-ups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_PULLUP_EN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) data->phy0_init = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) sun4i_usb_phy_passby(phy, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) reset_control_assert(phy->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) clk_disable_unprepare(phy->clk2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) clk_disable_unprepare(phy->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int sun4i_usb_phy0_get_id_det(struct sun4i_usb_phy_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) switch (data->dr_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) case USB_DR_MODE_OTG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (data->id_det_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return gpiod_get_value_cansleep(data->id_det_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return 1; /* Fallback to peripheral mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) case USB_DR_MODE_HOST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) case USB_DR_MODE_PERIPHERAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int sun4i_usb_phy0_get_vbus_det(struct sun4i_usb_phy_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (data->vbus_det_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return gpiod_get_value_cansleep(data->vbus_det_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (data->vbus_power_supply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) union power_supply_propval val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) r = power_supply_get_property(data->vbus_power_supply,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) POWER_SUPPLY_PROP_PRESENT, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (r == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return val.intval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* Fallback: report vbus as high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return data->vbus_det_gpio || data->vbus_power_supply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static bool sun4i_usb_phy0_poll(struct sun4i_usb_phy_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if ((data->id_det_gpio && data->id_det_irq <= 0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) (data->vbus_det_gpio && data->vbus_det_irq <= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * The A31/A23/A33 companion pmics (AXP221/AXP223) do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * generate vbus change interrupts when the board is driving
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * vbus using the N_VBUSEN pin on the pmic, so we must poll
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * when using the pmic for vbus-det _and_ we're driving vbus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if ((data->cfg->type == sun6i_a31_phy ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) data->cfg->type == sun8i_a33_phy) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) data->vbus_power_supply && data->phys[0].regulator_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static int sun4i_usb_phy_power_on(struct phy *_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (!phy->vbus || phy->regulator_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /* For phy0 only turn on Vbus if we don't have an ext. Vbus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (phy->index == 0 && sun4i_usb_phy0_have_vbus_det(data) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) data->vbus_det) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) dev_warn(&_phy->dev, "External vbus detected, not enabling our own vbus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) ret = regulator_enable(phy->vbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) phy->regulator_on = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (phy->index == 0 && sun4i_usb_phy0_poll(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) static int sun4i_usb_phy_power_off(struct phy *_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (!phy->vbus || !phy->regulator_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) regulator_disable(phy->vbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) phy->regulator_on = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * phy0 vbus typically slowly discharges, sometimes this causes the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (phy->index == 0 && !sun4i_usb_phy0_poll(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) mod_delayed_work(system_wq, &data->detect, POLL_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static int sun4i_usb_phy_set_mode(struct phy *_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) enum phy_mode mode, int submode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) int new_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (phy->index != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (mode == PHY_MODE_USB_HOST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) case PHY_MODE_USB_HOST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) new_mode = USB_DR_MODE_HOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) case PHY_MODE_USB_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) new_mode = USB_DR_MODE_PERIPHERAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) case PHY_MODE_USB_OTG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) new_mode = USB_DR_MODE_OTG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (new_mode != data->dr_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) dev_info(&_phy->dev, "Changing dr_mode to %d\n", new_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) data->dr_mode = new_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) data->id_det = -1; /* Force reprocessing of id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) data->force_session_end = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) queue_delayed_work(system_wq, &data->detect, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) void sun4i_usb_phy_set_squelch_detect(struct phy *_phy, bool enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) sun4i_usb_phy_write(phy, PHY_SQUELCH_DETECT, enabled ? 0 : 2, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) EXPORT_SYMBOL_GPL(sun4i_usb_phy_set_squelch_detect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) static const struct phy_ops sun4i_usb_phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) .init = sun4i_usb_phy_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) .exit = sun4i_usb_phy_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) .power_on = sun4i_usb_phy_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) .power_off = sun4i_usb_phy_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) .set_mode = sun4i_usb_phy_set_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static void sun4i_usb_phy0_reroute(struct sun4i_usb_phy_data *data, int id_det)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) u32 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) regval = readl(data->base + REG_PHY_OTGCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (id_det == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* Host mode. Route phy0 to EHCI/OHCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) regval &= ~OTGCTL_ROUTE_MUSB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* Peripheral mode. Route phy0 to MUSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) regval |= OTGCTL_ROUTE_MUSB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) writel(regval, data->base + REG_PHY_OTGCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct sun4i_usb_phy_data *data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) container_of(work, struct sun4i_usb_phy_data, detect.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct phy *phy0 = data->phys[0].phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct sun4i_usb_phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) bool force_session_end, id_notify = false, vbus_notify = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) int id_det, vbus_det;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (!phy0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) phy = phy_get_drvdata(phy0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) id_det = sun4i_usb_phy0_get_id_det(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) vbus_det = sun4i_usb_phy0_get_vbus_det(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) mutex_lock(&phy0->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (!data->phy0_init) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) mutex_unlock(&phy0->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) force_session_end = data->force_session_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) data->force_session_end = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (id_det != data->id_det) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /* id-change, force session end if we've no vbus detection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (data->dr_mode == USB_DR_MODE_OTG &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) !sun4i_usb_phy0_have_vbus_det(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) force_session_end = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* When entering host mode (id = 0) force end the session now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (force_session_end && id_det == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) sun4i_usb_phy0_set_vbus_detect(phy0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) msleep(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) sun4i_usb_phy0_set_vbus_detect(phy0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) sun4i_usb_phy0_set_id_detect(phy0, id_det);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) data->id_det = id_det;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) id_notify = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (vbus_det != data->vbus_det) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) data->vbus_det = vbus_det;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) vbus_notify = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) mutex_unlock(&phy0->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (id_notify) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) extcon_set_state_sync(data->extcon, EXTCON_USB_HOST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) !id_det);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /* When leaving host mode force end the session here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (force_session_end && id_det == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) mutex_lock(&phy0->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) sun4i_usb_phy0_set_vbus_detect(phy0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) msleep(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) sun4i_usb_phy0_set_vbus_detect(phy0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) mutex_unlock(&phy0->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /* Enable PHY0 passby for host mode only. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) sun4i_usb_phy_passby(phy, !id_det);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* Re-route PHY0 if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (data->cfg->phy0_dual_route)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) sun4i_usb_phy0_reroute(data, id_det);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (vbus_notify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) extcon_set_state_sync(data->extcon, EXTCON_USB, vbus_det);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (sun4i_usb_phy0_poll(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) queue_delayed_work(system_wq, &data->detect, POLL_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) struct sun4i_usb_phy_data *data = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) /* vbus or id changed, let the pins settle and then scan them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) static int sun4i_usb_phy0_vbus_notify(struct notifier_block *nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) unsigned long val, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct sun4i_usb_phy_data *data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) container_of(nb, struct sun4i_usb_phy_data, vbus_power_nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) struct power_supply *psy = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /* Properties on the vbus_power_supply changed, scan vbus_det */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (val == PSY_EVENT_PROP_CHANGED && psy == data->vbus_power_supply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) static struct phy *sun4i_usb_phy_xlate(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct of_phandle_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (args->args[0] >= data->cfg->num_phys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (data->cfg->missing_phys & BIT(args->args[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return data->phys[args->args[0]].phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) static int sun4i_usb_phy_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (data->vbus_power_nb_registered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) power_supply_unreg_notifier(&data->vbus_power_nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (data->id_det_irq > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) devm_free_irq(dev, data->id_det_irq, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (data->vbus_det_irq > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) devm_free_irq(dev, data->vbus_det_irq, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) cancel_delayed_work_sync(&data->detect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) static const unsigned int sun4i_usb_phy0_cable[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) EXTCON_USB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) EXTCON_USB_HOST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) EXTCON_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) static int sun4i_usb_phy_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) struct sun4i_usb_phy_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) struct phy_provider *phy_provider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) spin_lock_init(&data->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) dev_set_drvdata(dev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) data->cfg = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (!data->cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) data->base = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (IS_ERR(data->base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return PTR_ERR(data->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) data->id_det_gpio = devm_gpiod_get_optional(dev, "usb0_id_det",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) GPIOD_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (IS_ERR(data->id_det_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) dev_err(dev, "Couldn't request ID GPIO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return PTR_ERR(data->id_det_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) data->vbus_det_gpio = devm_gpiod_get_optional(dev, "usb0_vbus_det",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) GPIOD_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (IS_ERR(data->vbus_det_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) dev_err(dev, "Couldn't request VBUS detect GPIO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return PTR_ERR(data->vbus_det_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) "usb0_vbus_power-supply");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (IS_ERR(data->vbus_power_supply)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) dev_err(dev, "Couldn't get the VBUS power supply\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return PTR_ERR(data->vbus_power_supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (!data->vbus_power_supply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) data->dr_mode = of_usb_get_dr_mode_by_phy(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) data->extcon = devm_extcon_dev_allocate(dev, sun4i_usb_phy0_cable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (IS_ERR(data->extcon)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) dev_err(dev, "Couldn't allocate our extcon device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return PTR_ERR(data->extcon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) ret = devm_extcon_dev_register(dev, data->extcon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) dev_err(dev, "failed to register extcon: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) for (i = 0; i < data->cfg->num_phys; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) struct sun4i_usb_phy *phy = data->phys + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) char name[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (data->cfg->missing_phys & BIT(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) snprintf(name, sizeof(name), "usb%d_vbus", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) phy->vbus = devm_regulator_get_optional(dev, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (IS_ERR(phy->vbus)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (PTR_ERR(phy->vbus) == -EPROBE_DEFER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) dev_err(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) "Couldn't get regulator %s... Deferring probe\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) phy->vbus = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (data->cfg->dedicated_clocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) snprintf(name, sizeof(name), "usb%d_phy", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) strlcpy(name, "usb_phy", sizeof(name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) phy->clk = devm_clk_get(dev, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (IS_ERR(phy->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) dev_err(dev, "failed to get clock %s\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) return PTR_ERR(phy->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /* The first PHY is always tied to OTG, and never HSIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (data->cfg->hsic_index && i == data->cfg->hsic_index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) /* HSIC needs secondary clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) snprintf(name, sizeof(name), "usb%d_hsic_12M", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) phy->clk2 = devm_clk_get(dev, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (IS_ERR(phy->clk2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) dev_err(dev, "failed to get clock %s\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return PTR_ERR(phy->clk2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) snprintf(name, sizeof(name), "usb%d_reset", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) phy->reset = devm_reset_control_get(dev, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (IS_ERR(phy->reset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) dev_err(dev, "failed to get reset %s\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return PTR_ERR(phy->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (i || data->cfg->phy0_dual_route) { /* No pmu for musb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) snprintf(name, sizeof(name), "pmu%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) res = platform_get_resource_byname(pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) IORESOURCE_MEM, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) phy->pmu = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (IS_ERR(phy->pmu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return PTR_ERR(phy->pmu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (IS_ERR(phy->phy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) dev_err(dev, "failed to create PHY %d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) return PTR_ERR(phy->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) phy->index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) phy_set_drvdata(phy->phy, &data->phys[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) data->id_det_irq = gpiod_to_irq(data->id_det_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (data->id_det_irq > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) ret = devm_request_irq(dev, data->id_det_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) sun4i_usb_phy0_id_vbus_det_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) "usb0-id-det", data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) dev_err(dev, "Err requesting id-det-irq: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (data->vbus_det_irq > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) ret = devm_request_irq(dev, data->vbus_det_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) sun4i_usb_phy0_id_vbus_det_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) "usb0-vbus-det", data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) dev_err(dev, "Err requesting vbus-det-irq: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) data->vbus_det_irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) sun4i_usb_phy_remove(pdev); /* Stop detect work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (data->vbus_power_supply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) data->vbus_power_nb.notifier_call = sun4i_usb_phy0_vbus_notify;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) data->vbus_power_nb.priority = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) ret = power_supply_reg_notifier(&data->vbus_power_nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) sun4i_usb_phy_remove(pdev); /* Stop detect work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) data->vbus_power_nb_registered = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (IS_ERR(phy_provider)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) sun4i_usb_phy_remove(pdev); /* Stop detect work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return PTR_ERR(phy_provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) dev_dbg(dev, "successfully loaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) .num_phys = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) .type = sun4i_a10_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) .disc_thresh = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) .phyctl_offset = REG_PHYCTL_A10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) .dedicated_clocks = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) .enable_pmu_unk1 = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) .num_phys = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) .type = sun4i_a10_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) .disc_thresh = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) .phyctl_offset = REG_PHYCTL_A10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) .dedicated_clocks = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) .enable_pmu_unk1 = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) .num_phys = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) .type = sun6i_a31_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) .disc_thresh = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) .phyctl_offset = REG_PHYCTL_A10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) .dedicated_clocks = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) .enable_pmu_unk1 = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) .num_phys = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) .type = sun4i_a10_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) .disc_thresh = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) .phyctl_offset = REG_PHYCTL_A10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) .dedicated_clocks = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) .enable_pmu_unk1 = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) .num_phys = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) .type = sun6i_a31_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) .disc_thresh = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) .phyctl_offset = REG_PHYCTL_A10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) .dedicated_clocks = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) .enable_pmu_unk1 = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) .num_phys = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) .type = sun8i_a33_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) .disc_thresh = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) .phyctl_offset = REG_PHYCTL_A33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) .dedicated_clocks = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) .enable_pmu_unk1 = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) .num_phys = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) .hsic_index = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) .type = sun8i_a83t_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) .phyctl_offset = REG_PHYCTL_A33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) .dedicated_clocks = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) .num_phys = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) .type = sun8i_h3_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) .disc_thresh = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) .phyctl_offset = REG_PHYCTL_A33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) .dedicated_clocks = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) .enable_pmu_unk1 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) .phy0_dual_route = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) static const struct sun4i_usb_phy_cfg sun8i_r40_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) .num_phys = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) .type = sun8i_r40_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) .disc_thresh = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) .phyctl_offset = REG_PHYCTL_A33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) .dedicated_clocks = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) .enable_pmu_unk1 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) .phy0_dual_route = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) .num_phys = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) .type = sun8i_v3s_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) .disc_thresh = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) .phyctl_offset = REG_PHYCTL_A33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) .dedicated_clocks = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) .enable_pmu_unk1 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) .phy0_dual_route = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) .num_phys = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) .type = sun50i_a64_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) .disc_thresh = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) .phyctl_offset = REG_PHYCTL_A33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) .dedicated_clocks = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) .enable_pmu_unk1 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) .phy0_dual_route = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) .num_phys = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) .type = sun50i_h6_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) .disc_thresh = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) .phyctl_offset = REG_PHYCTL_A33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) .dedicated_clocks = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .enable_pmu_unk1 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) .phy0_dual_route = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) .missing_phys = BIT(1) | BIT(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) static const struct of_device_id sun4i_usb_phy_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) { .compatible = "allwinner,sun6i-a31-usb-phy", .data = &sun6i_a31_cfg },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) { .compatible = "allwinner,sun7i-a20-usb-phy", .data = &sun7i_a20_cfg },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) { .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) { .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) { .compatible = "allwinner,sun8i-a83t-usb-phy", .data = &sun8i_a83t_cfg },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) { .compatible = "allwinner,sun8i-h3-usb-phy", .data = &sun8i_h3_cfg },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) { .compatible = "allwinner,sun8i-r40-usb-phy", .data = &sun8i_r40_cfg },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) { .compatible = "allwinner,sun50i-a64-usb-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) .data = &sun50i_a64_cfg},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) { .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) static struct platform_driver sun4i_usb_phy_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) .probe = sun4i_usb_phy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) .remove = sun4i_usb_phy_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) .of_match_table = sun4i_usb_phy_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) .name = "sun4i-usb-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) module_platform_driver(sun4i_usb_phy_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) MODULE_DESCRIPTION("Allwinner sun4i USB phy driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) MODULE_LICENSE("GPL v2");