^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Samsung Exynos5 SoC series USB DRD PHY driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Phy provider for USB 3.0 DRD controller on Exynos5 SoC series
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2014 Samsung Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Author: Vivek Gautam <gautam.vivek@samsung.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/iopoll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/soc/samsung/exynos-regs-pmu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* Exynos USB PHY registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define EXYNOS5_FSEL_9MHZ6 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define EXYNOS5_FSEL_10MHZ 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define EXYNOS5_FSEL_12MHZ 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define EXYNOS5_FSEL_19MHZ2 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define EXYNOS5_FSEL_20MHZ 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define EXYNOS5_FSEL_24MHZ 0x5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define EXYNOS5_FSEL_50MHZ 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* Exynos5: USB 3.0 DRD PHY registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define EXYNOS5_DRD_LINKSYSTEM 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define LINKSYSTEM_FLADJ_MASK (0x3f << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define LINKSYSTEM_FLADJ(_x) ((_x) << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define LINKSYSTEM_XHCI_VERSION_CONTROL BIT(27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define EXYNOS5_DRD_PHYUTMI 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define PHYUTMI_OTGDISABLE BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define PHYUTMI_FORCESUSPEND BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define PHYUTMI_FORCESLEEP BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define EXYNOS5_DRD_PHYPIPE 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define EXYNOS5_DRD_PHYCLKRST 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define PHYCLKRST_EN_UTMISUSPEND BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define PHYCLKRST_SSC_REFCLKSEL_MASK (0xff << 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define PHYCLKRST_SSC_REFCLKSEL(_x) ((_x) << 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define PHYCLKRST_SSC_RANGE_MASK (0x03 << 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define PHYCLKRST_SSC_RANGE(_x) ((_x) << 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define PHYCLKRST_SSC_EN BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define PHYCLKRST_REF_SSP_EN BIT(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define PHYCLKRST_REF_CLKDIV2 BIT(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x32 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define PHYCLKRST_FSEL_UTMI_MASK (0x7 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define PHYCLKRST_FSEL_PIPE_MASK (0x7 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define PHYCLKRST_FSEL(_x) ((_x) << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define PHYCLKRST_FSEL_PAD_100MHZ (0x27 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define PHYCLKRST_FSEL_PAD_24MHZ (0x2a << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define PHYCLKRST_FSEL_PAD_20MHZ (0x31 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define PHYCLKRST_FSEL_PAD_19_2MHZ (0x38 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define PHYCLKRST_RETENABLEN BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define PHYCLKRST_PORTRESET BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define PHYCLKRST_COMMONONN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define EXYNOS5_DRD_PHYREG0 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define PHYREG0_SSC_REF_CLK_SEL BIT(21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define PHYREG0_SSC_RANGE BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define PHYREG0_CR_WRITE BIT(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define PHYREG0_CR_READ BIT(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define PHYREG0_CR_DATA_IN(_x) ((_x) << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define PHYREG0_CR_CAP_DATA BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define PHYREG0_CR_CAP_ADDR BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define EXYNOS5_DRD_PHYREG1 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define PHYREG1_CR_DATA_OUT(_x) ((_x) << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define PHYREG1_CR_ACK BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define EXYNOS5_DRD_PHYPARAM0 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define PHYPARAM0_REF_USE_PAD BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define PHYPARAM0_REF_LOSLEVEL_MASK (0x1f << 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define PHYPARAM0_REF_LOSLEVEL (0x9 << 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define EXYNOS5_DRD_PHYPARAM1 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define PHYPARAM1_PCS_TXDEEMPH_MASK (0x1f << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define PHYPARAM1_PCS_TXDEEMPH (0x1c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define EXYNOS5_DRD_PHYTERM 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define EXYNOS5_DRD_PHYTEST 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define PHYTEST_POWERDOWN_SSP BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define PHYTEST_POWERDOWN_HSP BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define EXYNOS5_DRD_PHYADP 0x2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define EXYNOS5_DRD_PHYUTMICLKSEL 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define PHYUTMICLKSEL_UTMI_CLKSEL BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define EXYNOS5_DRD_PHYRESUME 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define EXYNOS5_DRD_LINKPORT 0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN (0x15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define LOSLEVEL_OVRD_IN_LOS_BIAS_5420 (0x5 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT (0x0 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define LOSLEVEL_OVRD_IN_EN (0x1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT (0x9 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN (0x12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420 (0x5 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT (0x4 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG (0x1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M (0x4 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M (0x8 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M (0x8 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M (0x20 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5 (0x20 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M (0x40 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define KHZ 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define MHZ (KHZ * KHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) enum exynos5_usbdrd_phy_id {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) EXYNOS5_DRDPHY_UTMI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) EXYNOS5_DRDPHY_PIPE3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) EXYNOS5_DRDPHYS_NUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct phy_usb_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct exynos5_usbdrd_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct exynos5_usbdrd_phy_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) unsigned int (*set_refclk)(struct phy_usb_instance *inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct exynos5_usbdrd_phy_drvdata {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) const struct exynos5_usbdrd_phy_config *phy_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) u32 pmu_offset_usbdrd0_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u32 pmu_offset_usbdrd1_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) bool has_common_clk_gate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * @dev: pointer to device instance of this platform device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * @reg_phy: usb phy controller register memory base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * @clk: phy clock for register access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * @pipeclk: clock for pipe3 phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * @utmiclk: clock for utmi+ phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * @itpclk: clock for ITP generation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * @drv_data: pointer to SoC level driver data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * @phys: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * instances each with its 'phy' and 'phy_cfg'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * @extrefclk: frequency select settings when using 'separate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * reference clocks' for SS and HS operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * @ref_clk: reference clock to PHY block from which PHY's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * operational clocks are derived
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * @vbus: VBUS regulator for phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * @vbus_boost: Boost regulator for VBUS present on few Exynos boards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct exynos5_usbdrd_phy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) void __iomem *reg_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct clk *pipeclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct clk *utmiclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct clk *itpclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) const struct exynos5_usbdrd_phy_drvdata *drv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct phy_usb_instance {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u32 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct regmap *reg_pmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) u32 pmu_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) const struct exynos5_usbdrd_phy_config *phy_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) } phys[EXYNOS5_DRDPHYS_NUM];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) u32 extrefclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct clk *ref_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct regulator *vbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct regulator *vbus_boost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return container_of((inst), struct exynos5_usbdrd_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) phys[(inst)->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * exynos5_rate_to_clk() converts the supplied clock rate to the value that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * can be written to the phy register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /* EXYNOS5_FSEL_MASK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) case 9600 * KHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) *reg = EXYNOS5_FSEL_9MHZ6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) case 10 * MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) *reg = EXYNOS5_FSEL_10MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) case 12 * MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *reg = EXYNOS5_FSEL_12MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) case 19200 * KHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) *reg = EXYNOS5_FSEL_19MHZ2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) case 20 * MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) *reg = EXYNOS5_FSEL_20MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) case 24 * MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) *reg = EXYNOS5_FSEL_24MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case 50 * MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *reg = EXYNOS5_FSEL_50MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) unsigned int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (!inst->reg_pmu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) val = on ? 0 : EXYNOS4_PHY_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) regmap_update_bits(inst->reg_pmu, inst->pmu_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) EXYNOS4_PHY_ENABLE, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * Sets the pipe3 phy's clk as EXTREFCLK (XXTI) which is internal clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * from clock core. Further sets multiplier values and spread spectrum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * clock settings for SuperSpeed operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* restore any previous reference clock settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* Use EXTREFCLK as ref clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) reg &= ~PHYCLKRST_REFCLKSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /* FSEL settings corresponding to reference clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) PHYCLKRST_MPLL_MULTIPLIER_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) PHYCLKRST_SSC_REFCLKSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) switch (phy_drd->extrefclk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) case EXYNOS5_FSEL_50MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) PHYCLKRST_SSC_REFCLKSEL(0x00));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) case EXYNOS5_FSEL_24MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) PHYCLKRST_SSC_REFCLKSEL(0x88));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) case EXYNOS5_FSEL_20MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) PHYCLKRST_SSC_REFCLKSEL(0x00));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case EXYNOS5_FSEL_19MHZ2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) PHYCLKRST_SSC_REFCLKSEL(0x88));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dev_dbg(phy_drd->dev, "unsupported ref clk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * Sets the utmi phy's clk as EXTREFCLK (XXTI) which is internal clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * from clock core. Further sets the FSEL values for HighSpeed operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* restore any previous reference clock settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) reg &= ~PHYCLKRST_REFCLKSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) PHYCLKRST_MPLL_MULTIPLIER_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) PHYCLKRST_SSC_REFCLKSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /* Set Tx De-Emphasis level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) reg |= PHYPARAM1_PCS_TXDEEMPH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) reg &= ~PHYTEST_POWERDOWN_SSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* Set Loss-of-Signal Detector sensitivity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) reg |= PHYPARAM0_REF_LOSLEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /* Set Tx De-Emphasis level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) reg |= PHYPARAM1_PCS_TXDEEMPH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* UTMI Power Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) writel(PHYUTMI_OTGDISABLE, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) reg &= ~PHYTEST_POWERDOWN_HSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static int exynos5_usbdrd_phy_init(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct phy_usb_instance *inst = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) ret = clk_prepare_enable(phy_drd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /* Reset USB 3.0 PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYRESUME);
^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) * Setting the Frame length Adj value[6:1] to default 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * See xHCI 1.0 spec, 5.2.4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) reg = LINKSYSTEM_XHCI_VERSION_CONTROL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) LINKSYSTEM_FLADJ(0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /* Select PHY CLK source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) reg &= ~PHYPARAM0_REF_USE_PAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /* This bit must be set for both HS and SS operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) reg |= PHYUTMICLKSEL_UTMI_CLKSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* UTMI or PIPE3 specific init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) inst->phy_cfg->phy_init(phy_drd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* reference clock settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) reg = inst->phy_cfg->set_refclk(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /* Digital power supply in normal operating mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) reg |= PHYCLKRST_RETENABLEN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* Enable ref clock for SS function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) PHYCLKRST_REF_SSP_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /* Enable spread spectrum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) PHYCLKRST_SSC_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* Power down HS Bias and PLL blocks in suspend mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) PHYCLKRST_COMMONONN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* Reset the port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) PHYCLKRST_PORTRESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) reg &= ~PHYCLKRST_PORTRESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) clk_disable_unprepare(phy_drd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static int exynos5_usbdrd_phy_exit(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct phy_usb_instance *inst = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) ret = clk_prepare_enable(phy_drd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) reg = PHYUTMI_OTGDISABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) PHYUTMI_FORCESUSPEND |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) PHYUTMI_FORCESLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* Resetting the PHYCLKRST enable bits to reduce leakage current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) reg &= ~(PHYCLKRST_REF_SSP_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) PHYCLKRST_SSC_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) PHYCLKRST_COMMONONN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* Control PHYTEST to remove leakage current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) reg |= PHYTEST_POWERDOWN_SSP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) PHYTEST_POWERDOWN_HSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) clk_disable_unprepare(phy_drd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static int exynos5_usbdrd_phy_power_on(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct phy_usb_instance *inst = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) clk_prepare_enable(phy_drd->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (!phy_drd->drv_data->has_common_clk_gate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) clk_prepare_enable(phy_drd->pipeclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) clk_prepare_enable(phy_drd->utmiclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) clk_prepare_enable(phy_drd->itpclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /* Enable VBUS supply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (phy_drd->vbus_boost) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ret = regulator_enable(phy_drd->vbus_boost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) dev_err(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) "Failed to enable VBUS boost supply\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) goto fail_vbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (phy_drd->vbus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) ret = regulator_enable(phy_drd->vbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) dev_err(phy_drd->dev, "Failed to enable VBUS supply\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) goto fail_vbus_boost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /* Power-on PHY*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) inst->phy_cfg->phy_isol(inst, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) fail_vbus_boost:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (phy_drd->vbus_boost)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) regulator_disable(phy_drd->vbus_boost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) fail_vbus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) clk_disable_unprepare(phy_drd->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (!phy_drd->drv_data->has_common_clk_gate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) clk_disable_unprepare(phy_drd->itpclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) clk_disable_unprepare(phy_drd->utmiclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) clk_disable_unprepare(phy_drd->pipeclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static int exynos5_usbdrd_phy_power_off(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct phy_usb_instance *inst = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* Power-off the PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) inst->phy_cfg->phy_isol(inst, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) /* Disable VBUS supply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (phy_drd->vbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) regulator_disable(phy_drd->vbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (phy_drd->vbus_boost)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) regulator_disable(phy_drd->vbus_boost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) clk_disable_unprepare(phy_drd->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (!phy_drd->drv_data->has_common_clk_gate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) clk_disable_unprepare(phy_drd->itpclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) clk_disable_unprepare(phy_drd->pipeclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) clk_disable_unprepare(phy_drd->utmiclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) u32 val, u32 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) unsigned int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) err = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) result, (result & PHYREG1_CR_ACK), 1, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (err == -ETIMEDOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) dev_err(phy_drd->dev, "CRPORT handshake timeout1 (0x%08x)\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) err = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) result, !(result & PHYREG1_CR_ACK), 1, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (err == -ETIMEDOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) dev_err(phy_drd->dev, "CRPORT handshake timeout2 (0x%08x)\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static int crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) u32 addr, u32 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* Write Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) writel(PHYREG0_CR_DATA_IN(addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) PHYREG0_CR_CAP_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* Write Data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) writel(PHYREG0_CR_DATA_IN(data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) PHYREG0_CR_CAP_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) PHYREG0_CR_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * Calibrate few PHY parameters using CR_PORT register to meet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * SuperSpeed requirements on Exynos5420 and Exynos5800 systems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * which have 28nm USB 3.0 DRD PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static int exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) unsigned int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) int ret = 0;
^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) * Change los_bias to (0x5) for 28nm PHY from a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * default value (0x0); los_level is set as default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * (0x9) as also reflected in los_level[30:26] bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * of PHYPARAM0 register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) LOSLEVEL_OVRD_IN_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) ret = crport_ctrl_write(phy_drd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) dev_err(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) "Failed setting Loss-of-Signal level for SuperSpeed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * to raise Tx signal level from its default value of (0x4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) ret = crport_ctrl_write(phy_drd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) dev_err(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) "Failed setting Tx-Vboost-Level for SuperSpeed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * Set proper time to wait for RxDetect measurement, for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * desired reference clock of PHY, by tuning the CR_PORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) * register LANE0.TX_DEBUG which is internal to PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * This fixes issue with few USB 3.0 devices, which are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) * not detected (not even generate interrupts on the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) * on insertion) without this change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * e.g. Samsung SUM-TSB16S 3.0 USB drive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) switch (phy_drd->extrefclk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) case EXYNOS5_FSEL_50MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) case EXYNOS5_FSEL_20MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) case EXYNOS5_FSEL_19MHZ2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) case EXYNOS5_FSEL_24MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) ret = crport_ctrl_write(phy_drd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) dev_err(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) "Fail to set RxDet measurement time for SuperSpeed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) struct of_phandle_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (WARN_ON(args->args[0] >= EXYNOS5_DRDPHYS_NUM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return phy_drd->phys[args->args[0]].phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) static int exynos5_usbdrd_phy_calibrate(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct phy_usb_instance *inst = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) return exynos5420_usbdrd_phy_calibrate(phy_drd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) static const struct phy_ops exynos5_usbdrd_phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) .init = exynos5_usbdrd_phy_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) .exit = exynos5_usbdrd_phy_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) .power_on = exynos5_usbdrd_phy_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) .power_off = exynos5_usbdrd_phy_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) .calibrate = exynos5_usbdrd_phy_calibrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) unsigned long ref_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) phy_drd->clk = devm_clk_get(phy_drd->dev, "phy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (IS_ERR(phy_drd->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) dev_err(phy_drd->dev, "Failed to get phy clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return PTR_ERR(phy_drd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (IS_ERR(phy_drd->ref_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) dev_err(phy_drd->dev, "Failed to get phy reference clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return PTR_ERR(phy_drd->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) ref_rate = clk_get_rate(phy_drd->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) ref_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (!phy_drd->drv_data->has_common_clk_gate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (IS_ERR(phy_drd->pipeclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) dev_info(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) "PIPE3 phy operational clock not specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) phy_drd->pipeclk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (IS_ERR(phy_drd->utmiclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) dev_info(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) "UTMI phy operational clock not specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) phy_drd->utmiclk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (IS_ERR(phy_drd->itpclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) dev_info(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) "ITP clock from main OSC not specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) phy_drd->itpclk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) .id = EXYNOS5_DRDPHY_UTMI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) .phy_isol = exynos5_usbdrd_phy_isol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) .phy_init = exynos5_usbdrd_utmi_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .set_refclk = exynos5_usbdrd_utmi_set_refclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) .id = EXYNOS5_DRDPHY_PIPE3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) .phy_isol = exynos5_usbdrd_phy_isol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) .phy_init = exynos5_usbdrd_pipe3_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) .set_refclk = exynos5_usbdrd_pipe3_set_refclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) .phy_cfg = phy_cfg_exynos5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) .has_common_clk_gate = true,
^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) static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .phy_cfg = phy_cfg_exynos5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .has_common_clk_gate = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .phy_cfg = phy_cfg_exynos5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) .pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .has_common_clk_gate = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) .phy_cfg = phy_cfg_exynos5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .has_common_clk_gate = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) .compatible = "samsung,exynos5250-usbdrd-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) .data = &exynos5250_usbdrd_phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) .compatible = "samsung,exynos5420-usbdrd-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) .data = &exynos5420_usbdrd_phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) .compatible = "samsung,exynos5433-usbdrd-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) .data = &exynos5433_usbdrd_phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) .compatible = "samsung,exynos7-usbdrd-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) .data = &exynos7_usbdrd_phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) struct device_node *node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) struct exynos5_usbdrd_phy *phy_drd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) struct phy_provider *phy_provider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) const struct exynos5_usbdrd_phy_drvdata *drv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) struct regmap *reg_pmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) u32 pmu_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) int channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) phy_drd = devm_kzalloc(dev, sizeof(*phy_drd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (!phy_drd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) dev_set_drvdata(dev, phy_drd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) phy_drd->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) phy_drd->reg_phy = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (IS_ERR(phy_drd->reg_phy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return PTR_ERR(phy_drd->reg_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) drv_data = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (!drv_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) phy_drd->drv_data = drv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) dev_err(dev, "Failed to initialize clocks\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) "samsung,pmu-syscon");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (IS_ERR(reg_pmu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) dev_err(dev, "Failed to lookup PMU regmap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return PTR_ERR(reg_pmu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) * Exynos5420 SoC has multiple channels for USB 3.0 PHY, with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) * each having separate power control registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) * 'channel' facilitates to set such registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) channel = of_alias_get_id(node, "usbdrdphy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (channel < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) dev_dbg(dev, "Not a multi-controller usbdrd phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) switch (channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd1_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd0_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /* Get Vbus regulators */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) phy_drd->vbus = devm_regulator_get(dev, "vbus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (IS_ERR(phy_drd->vbus)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) ret = PTR_ERR(phy_drd->vbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (ret == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) dev_warn(dev, "Failed to get VBUS supply regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) phy_drd->vbus = NULL;
^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) phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) if (IS_ERR(phy_drd->vbus_boost)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) ret = PTR_ERR(phy_drd->vbus_boost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (ret == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) dev_warn(dev, "Failed to get VBUS boost supply regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) phy_drd->vbus_boost = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) dev_vdbg(dev, "Creating usbdrd_phy phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) struct phy *phy = devm_phy_create(dev, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) &exynos5_usbdrd_phy_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (IS_ERR(phy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) dev_err(dev, "Failed to create usbdrd_phy phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return PTR_ERR(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) phy_drd->phys[i].phy = phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) phy_drd->phys[i].index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) phy_drd->phys[i].reg_pmu = reg_pmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) phy_drd->phys[i].pmu_offset = pmu_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) phy_set_drvdata(phy, &phy_drd->phys[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) phy_provider = devm_of_phy_provider_register(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) exynos5_usbdrd_phy_xlate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (IS_ERR(phy_provider)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) dev_err(phy_drd->dev, "Failed to register phy provider\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return PTR_ERR(phy_provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static struct platform_driver exynos5_usb3drd_phy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) .probe = exynos5_usbdrd_phy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) .of_match_table = exynos5_usbdrd_phy_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) .name = "exynos5_usb3drd_phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) .suppress_bind_attrs = 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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) module_platform_driver(exynos5_usb3drd_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) MODULE_DESCRIPTION("Samsung Exynos5 SoCs USB 3.0 DRD controller PHY driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) MODULE_ALIAS("platform:exynos5_usb3drd_phy");