diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-15 13:24:55 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-15 13:24:55 -0500 |
commit | e29876723f7cb7728f0d6a674d23f92673e9f112 (patch) | |
tree | ea1da8bf77139f6cc6de029988208a7eddaf2002 /drivers/phy | |
parent | 8c988ae787af4900bec5410658e8a82844185c85 (diff) | |
parent | 4d4bac4499e9955521af80198063ef9c2f2bd634 (diff) |
Merge tag 'usb-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB patches from Greg KH:
"Here's the big pull request for the USB driver tree for 3.20-rc1.
Nothing major happening here, just lots of gadget driver updates, new
device ids, and a bunch of cleanups.
All of these have been in linux-next for a while with no reported
issues"
* tag 'usb-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (299 commits)
usb: musb: fix device hotplug behind hub
usb: dwc2: Fix a bug in reading the endpoint directions from reg.
staging: emxx_udc: fix the build error
usb: Retry port status check on resume to work around RH bugs
Revert "usb: Reset USB-3 devices on USB-3 link bounce"
uhci-hub: use HUB_CHAR_*
usb: kconfig: replace PPC_OF with PPC
ehci-pci: disable for Intel MID platforms (update)
usb: gadget: Kconfig: use bool instead of boolean
usb: musb: blackfin: remove incorrect __exit_p()
USB: fix use-after-free bug in usb_hcd_unlink_urb()
ehci-pci: disable for Intel MID platforms
usb: host: pci_quirks: joing string literals
USB: add flag for HCDs that can't receive wakeup requests (isp1760-hcd)
USB: usbfs: allow URBs to be reaped after disconnection
cdc-acm: kill unnecessary messages
cdc-acm: add sanity checks
usb: phy: phy-generic: Fix USB PHY gpio reset
usb: dwc2: fix USB core dependencies
usb: renesas_usbhs: fix NULL pointer dereference in dma_release_channel()
...
Diffstat (limited to 'drivers/phy')
-rw-r--r-- | drivers/phy/Kconfig | 7 | ||||
-rw-r--r-- | drivers/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/phy/phy-armada375-usb2.c | 4 | ||||
-rw-r--r-- | drivers/phy/phy-exynos-mipi-video.c | 89 | ||||
-rw-r--r-- | drivers/phy/phy-miphy28lp.c | 61 | ||||
-rw-r--r-- | drivers/phy/phy-rockchip-usb.c | 158 | ||||
-rw-r--r-- | drivers/phy/phy-ti-pipe3.c | 143 |
7 files changed, 369 insertions, 94 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 26a7623e551e..2962de205ba7 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
@@ -239,6 +239,13 @@ config PHY_QCOM_IPQ806X_SATA | |||
239 | depends on OF | 239 | depends on OF |
240 | select GENERIC_PHY | 240 | select GENERIC_PHY |
241 | 241 | ||
242 | config PHY_ROCKCHIP_USB | ||
243 | tristate "Rockchip USB2 PHY Driver" | ||
244 | depends on ARCH_ROCKCHIP && OF | ||
245 | select GENERIC_PHY | ||
246 | help | ||
247 | Enable this to support the Rockchip USB 2.0 PHY. | ||
248 | |||
242 | config PHY_ST_SPEAR1310_MIPHY | 249 | config PHY_ST_SPEAR1310_MIPHY |
243 | tristate "ST SPEAR1310-MIPHY driver" | 250 | tristate "ST SPEAR1310-MIPHY driver" |
244 | select GENERIC_PHY | 251 | select GENERIC_PHY |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index cfbb72064516..f080e1bb2a74 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
@@ -28,6 +28,7 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o | |||
28 | phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o | 28 | phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o |
29 | obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o | 29 | obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o |
30 | obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o | 30 | obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o |
31 | obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o | ||
31 | obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o | 32 | obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o |
32 | obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o | 33 | obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o |
33 | obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o | 34 | obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o |
diff --git a/drivers/phy/phy-armada375-usb2.c b/drivers/phy/phy-armada375-usb2.c index ac7d99d01cb3..7c99ca256f05 100644 --- a/drivers/phy/phy-armada375-usb2.c +++ b/drivers/phy/phy-armada375-usb2.c | |||
@@ -118,8 +118,8 @@ static int armada375_usb_phy_probe(struct platform_device *pdev) | |||
118 | 118 | ||
119 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 119 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
120 | usb_cluster_base = devm_ioremap_resource(&pdev->dev, res); | 120 | usb_cluster_base = devm_ioremap_resource(&pdev->dev, res); |
121 | if (!usb_cluster_base) | 121 | if (IS_ERR(usb_cluster_base)) |
122 | return -ENOMEM; | 122 | return PTR_ERR(usb_cluster_base); |
123 | 123 | ||
124 | phy = devm_phy_create(dev, NULL, &armada375_usb_phy_ops); | 124 | phy = devm_phy_create(dev, NULL, &armada375_usb_phy_ops); |
125 | if (IS_ERR(phy)) { | 125 | if (IS_ERR(phy)) { |
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c index 943e0f88a120..f017b2f2a54e 100644 --- a/drivers/phy/phy-exynos-mipi-video.c +++ b/drivers/phy/phy-exynos-mipi-video.c | |||
@@ -12,19 +12,18 @@ | |||
12 | #include <linux/err.h> | 12 | #include <linux/err.h> |
13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/mfd/syscon/exynos4-pmu.h> | ||
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/of.h> | 17 | #include <linux/of.h> |
17 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
18 | #include <linux/phy/phy.h> | 19 | #include <linux/phy/phy.h> |
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/regmap.h> | ||
20 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
23 | #include <linux/mfd/syscon.h> | ||
21 | 24 | ||
22 | /* MIPI_PHYn_CONTROL register offset: n = 0..1 */ | 25 | /* MIPI_PHYn_CONTROL reg. offset (for base address from ioremap): n = 0..1 */ |
23 | #define EXYNOS_MIPI_PHY_CONTROL(n) ((n) * 4) | 26 | #define EXYNOS_MIPI_PHY_CONTROL(n) ((n) * 4) |
24 | #define EXYNOS_MIPI_PHY_ENABLE (1 << 0) | ||
25 | #define EXYNOS_MIPI_PHY_SRESETN (1 << 1) | ||
26 | #define EXYNOS_MIPI_PHY_MRESETN (1 << 2) | ||
27 | #define EXYNOS_MIPI_PHY_RESET_MASK (3 << 1) | ||
28 | 27 | ||
29 | enum exynos_mipi_phy_id { | 28 | enum exynos_mipi_phy_id { |
30 | EXYNOS_MIPI_PHY_ID_CSIS0, | 29 | EXYNOS_MIPI_PHY_ID_CSIS0, |
@@ -38,43 +37,62 @@ enum exynos_mipi_phy_id { | |||
38 | ((id) == EXYNOS_MIPI_PHY_ID_DSIM0 || (id) == EXYNOS_MIPI_PHY_ID_DSIM1) | 37 | ((id) == EXYNOS_MIPI_PHY_ID_DSIM0 || (id) == EXYNOS_MIPI_PHY_ID_DSIM1) |
39 | 38 | ||
40 | struct exynos_mipi_video_phy { | 39 | struct exynos_mipi_video_phy { |
41 | spinlock_t slock; | ||
42 | struct video_phy_desc { | 40 | struct video_phy_desc { |
43 | struct phy *phy; | 41 | struct phy *phy; |
44 | unsigned int index; | 42 | unsigned int index; |
45 | } phys[EXYNOS_MIPI_PHYS_NUM]; | 43 | } phys[EXYNOS_MIPI_PHYS_NUM]; |
44 | spinlock_t slock; | ||
46 | void __iomem *regs; | 45 | void __iomem *regs; |
46 | struct mutex mutex; | ||
47 | struct regmap *regmap; | ||
47 | }; | 48 | }; |
48 | 49 | ||
49 | static int __set_phy_state(struct exynos_mipi_video_phy *state, | 50 | static int __set_phy_state(struct exynos_mipi_video_phy *state, |
50 | enum exynos_mipi_phy_id id, unsigned int on) | 51 | enum exynos_mipi_phy_id id, unsigned int on) |
51 | { | 52 | { |
53 | const unsigned int offset = EXYNOS4_MIPI_PHY_CONTROL(id / 2); | ||
52 | void __iomem *addr; | 54 | void __iomem *addr; |
53 | u32 reg, reset; | 55 | u32 val, reset; |
54 | |||
55 | addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2); | ||
56 | 56 | ||
57 | if (is_mipi_dsim_phy_id(id)) | 57 | if (is_mipi_dsim_phy_id(id)) |
58 | reset = EXYNOS_MIPI_PHY_MRESETN; | 58 | reset = EXYNOS4_MIPI_PHY_MRESETN; |
59 | else | ||
60 | reset = EXYNOS_MIPI_PHY_SRESETN; | ||
61 | |||
62 | spin_lock(&state->slock); | ||
63 | reg = readl(addr); | ||
64 | if (on) | ||
65 | reg |= reset; | ||
66 | else | 59 | else |
67 | reg &= ~reset; | 60 | reset = EXYNOS4_MIPI_PHY_SRESETN; |
68 | writel(reg, addr); | 61 | |
69 | 62 | if (state->regmap) { | |
70 | /* Clear ENABLE bit only if MRESETN, SRESETN bits are not set. */ | 63 | mutex_lock(&state->mutex); |
71 | if (on) | 64 | regmap_read(state->regmap, offset, &val); |
72 | reg |= EXYNOS_MIPI_PHY_ENABLE; | 65 | if (on) |
73 | else if (!(reg & EXYNOS_MIPI_PHY_RESET_MASK)) | 66 | val |= reset; |
74 | reg &= ~EXYNOS_MIPI_PHY_ENABLE; | 67 | else |
68 | val &= ~reset; | ||
69 | regmap_write(state->regmap, offset, val); | ||
70 | if (on) | ||
71 | val |= EXYNOS4_MIPI_PHY_ENABLE; | ||
72 | else if (!(val & EXYNOS4_MIPI_PHY_RESET_MASK)) | ||
73 | val &= ~EXYNOS4_MIPI_PHY_ENABLE; | ||
74 | regmap_write(state->regmap, offset, val); | ||
75 | mutex_unlock(&state->mutex); | ||
76 | } else { | ||
77 | addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2); | ||
78 | |||
79 | spin_lock(&state->slock); | ||
80 | val = readl(addr); | ||
81 | if (on) | ||
82 | val |= reset; | ||
83 | else | ||
84 | val &= ~reset; | ||
85 | writel(val, addr); | ||
86 | /* Clear ENABLE bit only if MRESETN, SRESETN bits are not set */ | ||
87 | if (on) | ||
88 | val |= EXYNOS4_MIPI_PHY_ENABLE; | ||
89 | else if (!(val & EXYNOS4_MIPI_PHY_RESET_MASK)) | ||
90 | val &= ~EXYNOS4_MIPI_PHY_ENABLE; | ||
91 | |||
92 | writel(val, addr); | ||
93 | spin_unlock(&state->slock); | ||
94 | } | ||
75 | 95 | ||
76 | writel(reg, addr); | ||
77 | spin_unlock(&state->slock); | ||
78 | return 0; | 96 | return 0; |
79 | } | 97 | } |
80 | 98 | ||
@@ -118,7 +136,6 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev) | |||
118 | { | 136 | { |
119 | struct exynos_mipi_video_phy *state; | 137 | struct exynos_mipi_video_phy *state; |
120 | struct device *dev = &pdev->dev; | 138 | struct device *dev = &pdev->dev; |
121 | struct resource *res; | ||
122 | struct phy_provider *phy_provider; | 139 | struct phy_provider *phy_provider; |
123 | unsigned int i; | 140 | unsigned int i; |
124 | 141 | ||
@@ -126,14 +143,22 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev) | |||
126 | if (!state) | 143 | if (!state) |
127 | return -ENOMEM; | 144 | return -ENOMEM; |
128 | 145 | ||
129 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 146 | state->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); |
147 | if (IS_ERR(state->regmap)) { | ||
148 | struct resource *res; | ||
130 | 149 | ||
131 | state->regs = devm_ioremap_resource(dev, res); | 150 | dev_info(dev, "regmap lookup failed: %ld\n", |
132 | if (IS_ERR(state->regs)) | 151 | PTR_ERR(state->regmap)); |
133 | return PTR_ERR(state->regs); | 152 | |
153 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
154 | state->regs = devm_ioremap_resource(dev, res); | ||
155 | if (IS_ERR(state->regs)) | ||
156 | return PTR_ERR(state->regs); | ||
157 | } | ||
134 | 158 | ||
135 | dev_set_drvdata(dev, state); | 159 | dev_set_drvdata(dev, state); |
136 | spin_lock_init(&state->slock); | 160 | spin_lock_init(&state->slock); |
161 | mutex_init(&state->mutex); | ||
137 | 162 | ||
138 | for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) { | 163 | for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) { |
139 | struct phy *phy = devm_phy_create(dev, NULL, | 164 | struct phy *phy = devm_phy_create(dev, NULL, |
diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c index 27fa62ce6136..9b2848e6115d 100644 --- a/drivers/phy/phy-miphy28lp.c +++ b/drivers/phy/phy-miphy28lp.c | |||
@@ -194,6 +194,14 @@ | |||
194 | #define MIPHY_SATA_BANK_NB 3 | 194 | #define MIPHY_SATA_BANK_NB 3 |
195 | #define MIPHY_PCIE_BANK_NB 2 | 195 | #define MIPHY_PCIE_BANK_NB 2 |
196 | 196 | ||
197 | enum { | ||
198 | SYSCFG_CTRL, | ||
199 | SYSCFG_STATUS, | ||
200 | SYSCFG_PCI, | ||
201 | SYSCFG_SATA, | ||
202 | SYSCFG_REG_MAX, | ||
203 | }; | ||
204 | |||
197 | struct miphy28lp_phy { | 205 | struct miphy28lp_phy { |
198 | struct phy *phy; | 206 | struct phy *phy; |
199 | struct miphy28lp_dev *phydev; | 207 | struct miphy28lp_dev *phydev; |
@@ -211,10 +219,7 @@ struct miphy28lp_phy { | |||
211 | u32 sata_gen; | 219 | u32 sata_gen; |
212 | 220 | ||
213 | /* Sysconfig registers offsets needed to configure the device */ | 221 | /* Sysconfig registers offsets needed to configure the device */ |
214 | u32 syscfg_miphy_ctrl; | 222 | u32 syscfg_reg[SYSCFG_REG_MAX]; |
215 | u32 syscfg_miphy_status; | ||
216 | u32 syscfg_pci; | ||
217 | u32 syscfg_sata; | ||
218 | u8 type; | 223 | u8 type; |
219 | }; | 224 | }; |
220 | 225 | ||
@@ -834,12 +839,12 @@ static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy) | |||
834 | if (!miphy_phy->osc_rdy) | 839 | if (!miphy_phy->osc_rdy) |
835 | return 0; | 840 | return 0; |
836 | 841 | ||
837 | if (!miphy_phy->syscfg_miphy_status) | 842 | if (!miphy_phy->syscfg_reg[SYSCFG_STATUS]) |
838 | return -EINVAL; | 843 | return -EINVAL; |
839 | 844 | ||
840 | do { | 845 | do { |
841 | regmap_read(miphy_dev->regmap, miphy_phy->syscfg_miphy_status, | 846 | regmap_read(miphy_dev->regmap, |
842 | &val); | 847 | miphy_phy->syscfg_reg[SYSCFG_STATUS], &val); |
843 | 848 | ||
844 | if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY) | 849 | if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY) |
845 | cpu_relax(); | 850 | cpu_relax(); |
@@ -888,7 +893,7 @@ static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val) | |||
888 | int err; | 893 | int err; |
889 | struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; | 894 | struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; |
890 | 895 | ||
891 | if (!miphy_phy->syscfg_miphy_ctrl) | 896 | if (!miphy_phy->syscfg_reg[SYSCFG_CTRL]) |
892 | return -EINVAL; | 897 | return -EINVAL; |
893 | 898 | ||
894 | err = reset_control_assert(miphy_phy->miphy_rst); | 899 | err = reset_control_assert(miphy_phy->miphy_rst); |
@@ -900,7 +905,8 @@ static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val) | |||
900 | if (miphy_phy->osc_force_ext) | 905 | if (miphy_phy->osc_force_ext) |
901 | miphy_val |= MIPHY_OSC_FORCE_EXT; | 906 | miphy_val |= MIPHY_OSC_FORCE_EXT; |
902 | 907 | ||
903 | regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_miphy_ctrl, | 908 | regmap_update_bits(miphy_dev->regmap, |
909 | miphy_phy->syscfg_reg[SYSCFG_CTRL], | ||
904 | MIPHY_CTRL_MASK, miphy_val); | 910 | MIPHY_CTRL_MASK, miphy_val); |
905 | 911 | ||
906 | err = reset_control_deassert(miphy_phy->miphy_rst); | 912 | err = reset_control_deassert(miphy_phy->miphy_rst); |
@@ -917,8 +923,9 @@ static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy) | |||
917 | struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; | 923 | struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; |
918 | int err, sata_conf = SATA_CTRL_SELECT_SATA; | 924 | int err, sata_conf = SATA_CTRL_SELECT_SATA; |
919 | 925 | ||
920 | if ((!miphy_phy->syscfg_sata) || (!miphy_phy->syscfg_pci) | 926 | if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) || |
921 | || (!miphy_phy->base)) | 927 | (!miphy_phy->syscfg_reg[SYSCFG_PCI]) || |
928 | (!miphy_phy->base)) | ||
922 | return -EINVAL; | 929 | return -EINVAL; |
923 | 930 | ||
924 | dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base); | 931 | dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base); |
@@ -926,10 +933,11 @@ static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy) | |||
926 | /* Configure the glue-logic */ | 933 | /* Configure the glue-logic */ |
927 | sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE); | 934 | sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE); |
928 | 935 | ||
929 | regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_sata, | 936 | regmap_update_bits(miphy_dev->regmap, |
937 | miphy_phy->syscfg_reg[SYSCFG_SATA], | ||
930 | SATA_CTRL_MASK, sata_conf); | 938 | SATA_CTRL_MASK, sata_conf); |
931 | 939 | ||
932 | regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_pci, | 940 | regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI], |
933 | PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE); | 941 | PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE); |
934 | 942 | ||
935 | /* MiPHY path and clocking init */ | 943 | /* MiPHY path and clocking init */ |
@@ -951,17 +959,19 @@ static int miphy28lp_init_pcie(struct miphy28lp_phy *miphy_phy) | |||
951 | struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; | 959 | struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; |
952 | int err; | 960 | int err; |
953 | 961 | ||
954 | if ((!miphy_phy->syscfg_sata) || (!miphy_phy->syscfg_pci) | 962 | if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) || |
963 | (!miphy_phy->syscfg_reg[SYSCFG_PCI]) | ||
955 | || (!miphy_phy->base) || (!miphy_phy->pipebase)) | 964 | || (!miphy_phy->base) || (!miphy_phy->pipebase)) |
956 | return -EINVAL; | 965 | return -EINVAL; |
957 | 966 | ||
958 | dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base); | 967 | dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base); |
959 | 968 | ||
960 | /* Configure the glue-logic */ | 969 | /* Configure the glue-logic */ |
961 | regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_sata, | 970 | regmap_update_bits(miphy_dev->regmap, |
971 | miphy_phy->syscfg_reg[SYSCFG_SATA], | ||
962 | SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE); | 972 | SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE); |
963 | 973 | ||
964 | regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_pci, | 974 | regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI], |
965 | PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL); | 975 | PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL); |
966 | 976 | ||
967 | /* MiPHY path and clocking init */ | 977 | /* MiPHY path and clocking init */ |
@@ -1156,7 +1166,8 @@ static int miphy28lp_probe_resets(struct device_node *node, | |||
1156 | static int miphy28lp_of_probe(struct device_node *np, | 1166 | static int miphy28lp_of_probe(struct device_node *np, |
1157 | struct miphy28lp_phy *miphy_phy) | 1167 | struct miphy28lp_phy *miphy_phy) |
1158 | { | 1168 | { |
1159 | struct resource res; | 1169 | int i; |
1170 | u32 ctrlreg; | ||
1160 | 1171 | ||
1161 | miphy_phy->osc_force_ext = | 1172 | miphy_phy->osc_force_ext = |
1162 | of_property_read_bool(np, "st,osc-force-ext"); | 1173 | of_property_read_bool(np, "st,osc-force-ext"); |
@@ -1175,18 +1186,10 @@ static int miphy28lp_of_probe(struct device_node *np, | |||
1175 | if (!miphy_phy->sata_gen) | 1186 | if (!miphy_phy->sata_gen) |
1176 | miphy_phy->sata_gen = SATA_GEN1; | 1187 | miphy_phy->sata_gen = SATA_GEN1; |
1177 | 1188 | ||
1178 | if (!miphy28lp_get_resource_byname(np, "miphy-ctrl-glue", &res)) | 1189 | for (i = 0; i < SYSCFG_REG_MAX; i++) { |
1179 | miphy_phy->syscfg_miphy_ctrl = res.start; | 1190 | if (!of_property_read_u32_index(np, "st,syscfg", i, &ctrlreg)) |
1180 | 1191 | miphy_phy->syscfg_reg[i] = ctrlreg; | |
1181 | if (!miphy28lp_get_resource_byname(np, "miphy-status-glue", &res)) | 1192 | } |
1182 | miphy_phy->syscfg_miphy_status = res.start; | ||
1183 | |||
1184 | if (!miphy28lp_get_resource_byname(np, "pcie-glue", &res)) | ||
1185 | miphy_phy->syscfg_pci = res.start; | ||
1186 | |||
1187 | if (!miphy28lp_get_resource_byname(np, "sata-glue", &res)) | ||
1188 | miphy_phy->syscfg_sata = res.start; | ||
1189 | |||
1190 | 1193 | ||
1191 | return 0; | 1194 | return 0; |
1192 | } | 1195 | } |
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c new file mode 100644 index 000000000000..22011c3b6a4b --- /dev/null +++ b/drivers/phy/phy-rockchip-usb.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * Rockchip usb PHY driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Yunzhi Li <lyz@rock-chips.com> | ||
5 | * Copyright (C) 2014 ROCKCHIP, Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/mutex.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/of_address.h> | ||
24 | #include <linux/phy/phy.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/regulator/consumer.h> | ||
27 | #include <linux/reset.h> | ||
28 | #include <linux/regmap.h> | ||
29 | #include <linux/mfd/syscon.h> | ||
30 | |||
31 | /* | ||
32 | * The higher 16-bit of this register is used for write protection | ||
33 | * only if BIT(13 + 16) set to 1 the BIT(13) can be written. | ||
34 | */ | ||
35 | #define SIDDQ_WRITE_ENA BIT(29) | ||
36 | #define SIDDQ_ON BIT(13) | ||
37 | #define SIDDQ_OFF (0 << 13) | ||
38 | |||
39 | struct rockchip_usb_phy { | ||
40 | unsigned int reg_offset; | ||
41 | struct regmap *reg_base; | ||
42 | struct clk *clk; | ||
43 | struct phy *phy; | ||
44 | }; | ||
45 | |||
46 | static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy, | ||
47 | bool siddq) | ||
48 | { | ||
49 | return regmap_write(phy->reg_base, phy->reg_offset, | ||
50 | SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF)); | ||
51 | } | ||
52 | |||
53 | static int rockchip_usb_phy_power_off(struct phy *_phy) | ||
54 | { | ||
55 | struct rockchip_usb_phy *phy = phy_get_drvdata(_phy); | ||
56 | int ret = 0; | ||
57 | |||
58 | /* Power down usb phy analog blocks by set siddq 1 */ | ||
59 | ret = rockchip_usb_phy_power(phy, 1); | ||
60 | if (ret) | ||
61 | return ret; | ||
62 | |||
63 | clk_disable_unprepare(phy->clk); | ||
64 | if (ret) | ||
65 | return ret; | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int rockchip_usb_phy_power_on(struct phy *_phy) | ||
71 | { | ||
72 | struct rockchip_usb_phy *phy = phy_get_drvdata(_phy); | ||
73 | int ret = 0; | ||
74 | |||
75 | ret = clk_prepare_enable(phy->clk); | ||
76 | if (ret) | ||
77 | return ret; | ||
78 | |||
79 | /* Power up usb phy analog blocks by set siddq 0 */ | ||
80 | ret = rockchip_usb_phy_power(phy, 0); | ||
81 | if (ret) | ||
82 | return ret; | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static struct phy_ops ops = { | ||
88 | .power_on = rockchip_usb_phy_power_on, | ||
89 | .power_off = rockchip_usb_phy_power_off, | ||
90 | .owner = THIS_MODULE, | ||
91 | }; | ||
92 | |||
93 | static int rockchip_usb_phy_probe(struct platform_device *pdev) | ||
94 | { | ||
95 | struct device *dev = &pdev->dev; | ||
96 | struct rockchip_usb_phy *rk_phy; | ||
97 | struct phy_provider *phy_provider; | ||
98 | struct device_node *child; | ||
99 | struct regmap *grf; | ||
100 | unsigned int reg_offset; | ||
101 | |||
102 | grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); | ||
103 | if (IS_ERR(grf)) { | ||
104 | dev_err(&pdev->dev, "Missing rockchip,grf property\n"); | ||
105 | return PTR_ERR(grf); | ||
106 | } | ||
107 | |||
108 | for_each_available_child_of_node(dev->of_node, child) { | ||
109 | rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL); | ||
110 | if (!rk_phy) | ||
111 | return -ENOMEM; | ||
112 | |||
113 | if (of_property_read_u32(child, "reg", ®_offset)) { | ||
114 | dev_err(dev, "missing reg property in node %s\n", | ||
115 | child->name); | ||
116 | return -EINVAL; | ||
117 | } | ||
118 | |||
119 | rk_phy->reg_offset = reg_offset; | ||
120 | rk_phy->reg_base = grf; | ||
121 | |||
122 | rk_phy->clk = of_clk_get_by_name(child, "phyclk"); | ||
123 | if (IS_ERR(rk_phy->clk)) | ||
124 | rk_phy->clk = NULL; | ||
125 | |||
126 | rk_phy->phy = devm_phy_create(dev, child, &ops); | ||
127 | if (IS_ERR(rk_phy->phy)) { | ||
128 | dev_err(dev, "failed to create PHY\n"); | ||
129 | return PTR_ERR(rk_phy->phy); | ||
130 | } | ||
131 | phy_set_drvdata(rk_phy->phy, rk_phy); | ||
132 | } | ||
133 | |||
134 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
135 | return PTR_ERR_OR_ZERO(phy_provider); | ||
136 | } | ||
137 | |||
138 | static const struct of_device_id rockchip_usb_phy_dt_ids[] = { | ||
139 | { .compatible = "rockchip,rk3288-usb-phy" }, | ||
140 | {} | ||
141 | }; | ||
142 | |||
143 | MODULE_DEVICE_TABLE(of, rockchip_usb_phy_dt_ids); | ||
144 | |||
145 | static struct platform_driver rockchip_usb_driver = { | ||
146 | .probe = rockchip_usb_phy_probe, | ||
147 | .driver = { | ||
148 | .name = "rockchip-usb-phy", | ||
149 | .owner = THIS_MODULE, | ||
150 | .of_match_table = rockchip_usb_phy_dt_ids, | ||
151 | }, | ||
152 | }; | ||
153 | |||
154 | module_platform_driver(rockchip_usb_driver); | ||
155 | |||
156 | MODULE_AUTHOR("Yunzhi Li <lyz@rock-chips.com>"); | ||
157 | MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver"); | ||
158 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c index 465de2c800f2..95c88f929f27 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/phy-ti-pipe3.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/phy/omap_control_phy.h> | 29 | #include <linux/phy/omap_control_phy.h> |
30 | #include <linux/of_platform.h> | 30 | #include <linux/of_platform.h> |
31 | #include <linux/spinlock.h> | ||
31 | 32 | ||
32 | #define PLL_STATUS 0x00000004 | 33 | #define PLL_STATUS 0x00000004 |
33 | #define PLL_GO 0x00000008 | 34 | #define PLL_GO 0x00000008 |
@@ -82,6 +83,10 @@ struct ti_pipe3 { | |||
82 | struct clk *refclk; | 83 | struct clk *refclk; |
83 | struct clk *div_clk; | 84 | struct clk *div_clk; |
84 | struct pipe3_dpll_map *dpll_map; | 85 | struct pipe3_dpll_map *dpll_map; |
86 | bool enabled; | ||
87 | spinlock_t lock; /* serialize clock enable/disable */ | ||
88 | /* the below flag is needed specifically for SATA */ | ||
89 | bool refclk_enabled; | ||
85 | }; | 90 | }; |
86 | 91 | ||
87 | static struct pipe3_dpll_map dpll_map_usb[] = { | 92 | static struct pipe3_dpll_map dpll_map_usb[] = { |
@@ -307,6 +312,7 @@ static int ti_pipe3_probe(struct platform_device *pdev) | |||
307 | return -ENOMEM; | 312 | return -ENOMEM; |
308 | 313 | ||
309 | phy->dev = &pdev->dev; | 314 | phy->dev = &pdev->dev; |
315 | spin_lock_init(&phy->lock); | ||
310 | 316 | ||
311 | if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { | 317 | if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { |
312 | match = of_match_device(of_match_ptr(ti_pipe3_id_table), | 318 | match = of_match_device(of_match_ptr(ti_pipe3_id_table), |
@@ -333,21 +339,24 @@ static int ti_pipe3_probe(struct platform_device *pdev) | |||
333 | } | 339 | } |
334 | } | 340 | } |
335 | 341 | ||
342 | phy->refclk = devm_clk_get(phy->dev, "refclk"); | ||
343 | if (IS_ERR(phy->refclk)) { | ||
344 | dev_err(&pdev->dev, "unable to get refclk\n"); | ||
345 | /* older DTBs have missing refclk in SATA PHY | ||
346 | * so don't bail out in case of SATA PHY. | ||
347 | */ | ||
348 | if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) | ||
349 | return PTR_ERR(phy->refclk); | ||
350 | } | ||
351 | |||
336 | if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) { | 352 | if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) { |
337 | phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); | 353 | phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); |
338 | if (IS_ERR(phy->wkupclk)) { | 354 | if (IS_ERR(phy->wkupclk)) { |
339 | dev_err(&pdev->dev, "unable to get wkupclk\n"); | 355 | dev_err(&pdev->dev, "unable to get wkupclk\n"); |
340 | return PTR_ERR(phy->wkupclk); | 356 | return PTR_ERR(phy->wkupclk); |
341 | } | 357 | } |
342 | |||
343 | phy->refclk = devm_clk_get(phy->dev, "refclk"); | ||
344 | if (IS_ERR(phy->refclk)) { | ||
345 | dev_err(&pdev->dev, "unable to get refclk\n"); | ||
346 | return PTR_ERR(phy->refclk); | ||
347 | } | ||
348 | } else { | 358 | } else { |
349 | phy->wkupclk = ERR_PTR(-ENODEV); | 359 | phy->wkupclk = ERR_PTR(-ENODEV); |
350 | phy->refclk = ERR_PTR(-ENODEV); | ||
351 | } | 360 | } |
352 | 361 | ||
353 | if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { | 362 | if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { |
@@ -426,33 +435,42 @@ static int ti_pipe3_remove(struct platform_device *pdev) | |||
426 | } | 435 | } |
427 | 436 | ||
428 | #ifdef CONFIG_PM | 437 | #ifdef CONFIG_PM |
429 | 438 | static int ti_pipe3_enable_refclk(struct ti_pipe3 *phy) | |
430 | static int ti_pipe3_runtime_suspend(struct device *dev) | ||
431 | { | 439 | { |
432 | struct ti_pipe3 *phy = dev_get_drvdata(dev); | 440 | if (!IS_ERR(phy->refclk) && !phy->refclk_enabled) { |
441 | int ret; | ||
433 | 442 | ||
434 | if (!IS_ERR(phy->wkupclk)) | 443 | ret = clk_prepare_enable(phy->refclk); |
435 | clk_disable_unprepare(phy->wkupclk); | 444 | if (ret) { |
445 | dev_err(phy->dev, "Failed to enable refclk %d\n", ret); | ||
446 | return ret; | ||
447 | } | ||
448 | phy->refclk_enabled = true; | ||
449 | } | ||
450 | |||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | static void ti_pipe3_disable_refclk(struct ti_pipe3 *phy) | ||
455 | { | ||
436 | if (!IS_ERR(phy->refclk)) | 456 | if (!IS_ERR(phy->refclk)) |
437 | clk_disable_unprepare(phy->refclk); | 457 | clk_disable_unprepare(phy->refclk); |
438 | if (!IS_ERR(phy->div_clk)) | ||
439 | clk_disable_unprepare(phy->div_clk); | ||
440 | 458 | ||
441 | return 0; | 459 | phy->refclk_enabled = false; |
442 | } | 460 | } |
443 | 461 | ||
444 | static int ti_pipe3_runtime_resume(struct device *dev) | 462 | static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy) |
445 | { | 463 | { |
446 | u32 ret = 0; | 464 | int ret = 0; |
447 | struct ti_pipe3 *phy = dev_get_drvdata(dev); | 465 | unsigned long flags; |
448 | 466 | ||
449 | if (!IS_ERR(phy->refclk)) { | 467 | spin_lock_irqsave(&phy->lock, flags); |
450 | ret = clk_prepare_enable(phy->refclk); | 468 | if (phy->enabled) |
451 | if (ret) { | 469 | goto err1; |
452 | dev_err(phy->dev, "Failed to enable refclk %d\n", ret); | 470 | |
453 | goto err1; | 471 | ret = ti_pipe3_enable_refclk(phy); |
454 | } | 472 | if (ret) |
455 | } | 473 | goto err1; |
456 | 474 | ||
457 | if (!IS_ERR(phy->wkupclk)) { | 475 | if (!IS_ERR(phy->wkupclk)) { |
458 | ret = clk_prepare_enable(phy->wkupclk); | 476 | ret = clk_prepare_enable(phy->wkupclk); |
@@ -469,6 +487,9 @@ static int ti_pipe3_runtime_resume(struct device *dev) | |||
469 | goto err3; | 487 | goto err3; |
470 | } | 488 | } |
471 | } | 489 | } |
490 | |||
491 | phy->enabled = true; | ||
492 | spin_unlock_irqrestore(&phy->lock, flags); | ||
472 | return 0; | 493 | return 0; |
473 | 494 | ||
474 | err3: | 495 | err3: |
@@ -479,20 +500,80 @@ err2: | |||
479 | if (!IS_ERR(phy->refclk)) | 500 | if (!IS_ERR(phy->refclk)) |
480 | clk_disable_unprepare(phy->refclk); | 501 | clk_disable_unprepare(phy->refclk); |
481 | 502 | ||
503 | ti_pipe3_disable_refclk(phy); | ||
482 | err1: | 504 | err1: |
505 | spin_unlock_irqrestore(&phy->lock, flags); | ||
483 | return ret; | 506 | return ret; |
484 | } | 507 | } |
485 | 508 | ||
509 | static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy) | ||
510 | { | ||
511 | unsigned long flags; | ||
512 | |||
513 | spin_lock_irqsave(&phy->lock, flags); | ||
514 | if (!phy->enabled) { | ||
515 | spin_unlock_irqrestore(&phy->lock, flags); | ||
516 | return; | ||
517 | } | ||
518 | |||
519 | if (!IS_ERR(phy->wkupclk)) | ||
520 | clk_disable_unprepare(phy->wkupclk); | ||
521 | /* Don't disable refclk for SATA PHY due to Errata i783 */ | ||
522 | if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) | ||
523 | ti_pipe3_disable_refclk(phy); | ||
524 | if (!IS_ERR(phy->div_clk)) | ||
525 | clk_disable_unprepare(phy->div_clk); | ||
526 | phy->enabled = false; | ||
527 | spin_unlock_irqrestore(&phy->lock, flags); | ||
528 | } | ||
529 | |||
530 | static int ti_pipe3_runtime_suspend(struct device *dev) | ||
531 | { | ||
532 | struct ti_pipe3 *phy = dev_get_drvdata(dev); | ||
533 | |||
534 | ti_pipe3_disable_clocks(phy); | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int ti_pipe3_runtime_resume(struct device *dev) | ||
539 | { | ||
540 | struct ti_pipe3 *phy = dev_get_drvdata(dev); | ||
541 | int ret = 0; | ||
542 | |||
543 | ret = ti_pipe3_enable_clocks(phy); | ||
544 | return ret; | ||
545 | } | ||
546 | |||
547 | static int ti_pipe3_suspend(struct device *dev) | ||
548 | { | ||
549 | struct ti_pipe3 *phy = dev_get_drvdata(dev); | ||
550 | |||
551 | ti_pipe3_disable_clocks(phy); | ||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | static int ti_pipe3_resume(struct device *dev) | ||
556 | { | ||
557 | struct ti_pipe3 *phy = dev_get_drvdata(dev); | ||
558 | int ret; | ||
559 | |||
560 | ret = ti_pipe3_enable_clocks(phy); | ||
561 | if (ret) | ||
562 | return ret; | ||
563 | |||
564 | pm_runtime_disable(dev); | ||
565 | pm_runtime_set_active(dev); | ||
566 | pm_runtime_enable(dev); | ||
567 | return 0; | ||
568 | } | ||
569 | #endif | ||
570 | |||
486 | static const struct dev_pm_ops ti_pipe3_pm_ops = { | 571 | static const struct dev_pm_ops ti_pipe3_pm_ops = { |
487 | SET_RUNTIME_PM_OPS(ti_pipe3_runtime_suspend, | 572 | SET_RUNTIME_PM_OPS(ti_pipe3_runtime_suspend, |
488 | ti_pipe3_runtime_resume, NULL) | 573 | ti_pipe3_runtime_resume, NULL) |
574 | SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume) | ||
489 | }; | 575 | }; |
490 | 576 | ||
491 | #define DEV_PM_OPS (&ti_pipe3_pm_ops) | ||
492 | #else | ||
493 | #define DEV_PM_OPS NULL | ||
494 | #endif | ||
495 | |||
496 | #ifdef CONFIG_OF | 577 | #ifdef CONFIG_OF |
497 | static const struct of_device_id ti_pipe3_id_table[] = { | 578 | static const struct of_device_id ti_pipe3_id_table[] = { |
498 | { | 579 | { |
@@ -520,7 +601,7 @@ static struct platform_driver ti_pipe3_driver = { | |||
520 | .remove = ti_pipe3_remove, | 601 | .remove = ti_pipe3_remove, |
521 | .driver = { | 602 | .driver = { |
522 | .name = "ti-pipe3", | 603 | .name = "ti-pipe3", |
523 | .pm = DEV_PM_OPS, | 604 | .pm = &ti_pipe3_pm_ops, |
524 | .of_match_table = of_match_ptr(ti_pipe3_id_table), | 605 | .of_match_table = of_match_ptr(ti_pipe3_id_table), |
525 | }, | 606 | }, |
526 | }; | 607 | }; |