diff options
author | Matt Porter <mporter@linaro.org> | 2013-12-19 09:23:09 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2013-12-23 15:33:02 -0500 |
commit | 7597fdfca983025a3de91d4b3cf7b21ba452003c (patch) | |
tree | 987f56d57b710be7aaf8ebecdc200fc0a9f4df5e /drivers | |
parent | 26799f1d23d07c2c4db2ccdba43c0e61baeaebee (diff) |
phy: add Broadcom Kona USB2 PHY driver
Add a driver for the internal Broadcom Kona USB 2.0 PHY found
on the BCM281xx family of SoCs.
Signed-off-by: Matt Porter <mporter@linaro.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/phy/Kconfig | 6 | ||||
-rw-r--r-- | drivers/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/phy/phy-bcm-kona-usb2.c | 158 |
3 files changed, 165 insertions, 0 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 330ef2d06567..a49e85349d81 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
@@ -51,4 +51,10 @@ config PHY_EXYNOS_DP_VIDEO | |||
51 | help | 51 | help |
52 | Support for Display Port PHY found on Samsung EXYNOS SoCs. | 52 | Support for Display Port PHY found on Samsung EXYNOS SoCs. |
53 | 53 | ||
54 | config BCM_KONA_USB2_PHY | ||
55 | tristate "Broadcom Kona USB2 PHY Driver" | ||
56 | depends on GENERIC_PHY | ||
57 | help | ||
58 | Enable this to support the Broadcom Kona USB 2.0 PHY. | ||
59 | |||
54 | endmenu | 60 | endmenu |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index d0caae9cfb83..c447f1a98ac5 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
@@ -3,6 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_GENERIC_PHY) += phy-core.o | 5 | obj-$(CONFIG_GENERIC_PHY) += phy-core.o |
6 | obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o | ||
6 | obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o | 7 | obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o |
7 | obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o | 8 | obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o |
8 | obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o | 9 | obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o |
diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c new file mode 100644 index 000000000000..efc5c1a13a5d --- /dev/null +++ b/drivers/phy/phy-bcm-kona-usb2.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * phy-bcm-kona-usb2.c - Broadcom Kona USB2 Phy Driver | ||
3 | * | ||
4 | * Copyright (C) 2013 Linaro Limited | ||
5 | * Matt Porter <mporter@linaro.org> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
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/delay.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/phy/phy.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | |||
26 | #define OTGCTL (0) | ||
27 | #define OTGCTL_OTGSTAT2 BIT(31) | ||
28 | #define OTGCTL_OTGSTAT1 BIT(30) | ||
29 | #define OTGCTL_PRST_N_SW BIT(11) | ||
30 | #define OTGCTL_HRESET_N BIT(10) | ||
31 | #define OTGCTL_UTMI_LINE_STATE1 BIT(9) | ||
32 | #define OTGCTL_UTMI_LINE_STATE0 BIT(8) | ||
33 | |||
34 | #define P1CTL (8) | ||
35 | #define P1CTL_SOFT_RESET BIT(1) | ||
36 | #define P1CTL_NON_DRIVING BIT(0) | ||
37 | |||
38 | struct bcm_kona_usb { | ||
39 | void __iomem *regs; | ||
40 | }; | ||
41 | |||
42 | static void bcm_kona_usb_phy_power(struct bcm_kona_usb *phy, int on) | ||
43 | { | ||
44 | u32 val; | ||
45 | |||
46 | val = readl(phy->regs + OTGCTL); | ||
47 | if (on) { | ||
48 | /* Configure and power PHY */ | ||
49 | val &= ~(OTGCTL_OTGSTAT2 | OTGCTL_OTGSTAT1 | | ||
50 | OTGCTL_UTMI_LINE_STATE1 | OTGCTL_UTMI_LINE_STATE0); | ||
51 | val |= OTGCTL_PRST_N_SW | OTGCTL_HRESET_N; | ||
52 | } else { | ||
53 | val &= ~(OTGCTL_PRST_N_SW | OTGCTL_HRESET_N); | ||
54 | } | ||
55 | writel(val, phy->regs + OTGCTL); | ||
56 | } | ||
57 | |||
58 | static int bcm_kona_usb_phy_init(struct phy *gphy) | ||
59 | { | ||
60 | struct bcm_kona_usb *phy = phy_get_drvdata(gphy); | ||
61 | u32 val; | ||
62 | |||
63 | /* Soft reset PHY */ | ||
64 | val = readl(phy->regs + P1CTL); | ||
65 | val &= ~P1CTL_NON_DRIVING; | ||
66 | val |= P1CTL_SOFT_RESET; | ||
67 | writel(val, phy->regs + P1CTL); | ||
68 | writel(val & ~P1CTL_SOFT_RESET, phy->regs + P1CTL); | ||
69 | /* Reset needs to be asserted for 2ms */ | ||
70 | mdelay(2); | ||
71 | writel(val | P1CTL_SOFT_RESET, phy->regs + P1CTL); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int bcm_kona_usb_phy_power_on(struct phy *gphy) | ||
77 | { | ||
78 | struct bcm_kona_usb *phy = phy_get_drvdata(gphy); | ||
79 | |||
80 | bcm_kona_usb_phy_power(phy, 1); | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static int bcm_kona_usb_phy_power_off(struct phy *gphy) | ||
86 | { | ||
87 | struct bcm_kona_usb *phy = phy_get_drvdata(gphy); | ||
88 | |||
89 | bcm_kona_usb_phy_power(phy, 0); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static struct phy_ops ops = { | ||
95 | .init = bcm_kona_usb_phy_init, | ||
96 | .power_on = bcm_kona_usb_phy_power_on, | ||
97 | .power_off = bcm_kona_usb_phy_power_off, | ||
98 | .owner = THIS_MODULE, | ||
99 | }; | ||
100 | |||
101 | static int bcm_kona_usb2_probe(struct platform_device *pdev) | ||
102 | { | ||
103 | struct device *dev = &pdev->dev; | ||
104 | struct bcm_kona_usb *phy; | ||
105 | struct resource *res; | ||
106 | struct phy *gphy; | ||
107 | struct phy_provider *phy_provider; | ||
108 | |||
109 | phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); | ||
110 | if (!phy) | ||
111 | return -ENOMEM; | ||
112 | |||
113 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
114 | phy->regs = devm_ioremap_resource(&pdev->dev, res); | ||
115 | if (IS_ERR(phy->regs)) | ||
116 | return PTR_ERR(phy->regs); | ||
117 | |||
118 | platform_set_drvdata(pdev, phy); | ||
119 | |||
120 | gphy = devm_phy_create(dev, &ops, NULL); | ||
121 | if (IS_ERR(gphy)) | ||
122 | return PTR_ERR(gphy); | ||
123 | |||
124 | /* The Kona PHY supports an 8-bit wide UTMI interface */ | ||
125 | phy_set_bus_width(gphy, 8); | ||
126 | |||
127 | phy_set_drvdata(gphy, phy); | ||
128 | |||
129 | phy_provider = devm_of_phy_provider_register(dev, | ||
130 | of_phy_simple_xlate); | ||
131 | if (IS_ERR(phy_provider)) | ||
132 | return PTR_ERR(phy_provider); | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static const struct of_device_id bcm_kona_usb2_dt_ids[] = { | ||
138 | { .compatible = "brcm,kona-usb2-phy" }, | ||
139 | { /* sentinel */ } | ||
140 | }; | ||
141 | |||
142 | MODULE_DEVICE_TABLE(of, bcm_kona_usb2_dt_ids); | ||
143 | |||
144 | static struct platform_driver bcm_kona_usb2_driver = { | ||
145 | .probe = bcm_kona_usb2_probe, | ||
146 | .driver = { | ||
147 | .name = "bcm-kona-usb2", | ||
148 | .owner = THIS_MODULE, | ||
149 | .of_match_table = bcm_kona_usb2_dt_ids, | ||
150 | }, | ||
151 | }; | ||
152 | |||
153 | module_platform_driver(bcm_kona_usb2_driver); | ||
154 | |||
155 | MODULE_ALIAS("platform:bcm-kona-usb2"); | ||
156 | MODULE_AUTHOR("Matt Porter <mporter@linaro.org>"); | ||
157 | MODULE_DESCRIPTION("BCM Kona USB 2.0 PHY driver"); | ||
158 | MODULE_LICENSE("GPL v2"); | ||