diff options
Diffstat (limited to 'drivers/usb/phy/phy-rcar-usb.c')
-rw-r--r-- | drivers/usb/phy/phy-rcar-usb.c | 128 |
1 files changed, 82 insertions, 46 deletions
diff --git a/drivers/usb/phy/phy-rcar-usb.c b/drivers/usb/phy/phy-rcar-usb.c index a35681b0c501..ae909408958d 100644 --- a/drivers/usb/phy/phy-rcar-usb.c +++ b/drivers/usb/phy/phy-rcar-usb.c | |||
@@ -1,8 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * Renesas R-Car USB phy driver | 2 | * Renesas R-Car USB phy driver |
3 | * | 3 | * |
4 | * Copyright (C) 2012 Renesas Solutions Corp. | 4 | * Copyright (C) 2012-2013 Renesas Solutions Corp. |
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
6 | * Copyright (C) 2013 Cogent Embedded, Inc. | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -15,17 +16,41 @@ | |||
15 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
16 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
18 | 19 | #include <linux/platform_data/usb-rcar-phy.h> | |
19 | /* USBH common register */ | 20 | |
20 | #define USBPCTRL0 0x0800 | 21 | /* REGS block */ |
21 | #define USBPCTRL1 0x0804 | 22 | #define USBPCTRL0 0x00 |
22 | #define USBST 0x0808 | 23 | #define USBPCTRL1 0x04 |
23 | #define USBEH0 0x080C | 24 | #define USBST 0x08 |
24 | #define USBOH0 0x081C | 25 | #define USBEH0 0x0C |
25 | #define USBCTL0 0x0858 | 26 | #define USBOH0 0x1C |
26 | #define EIIBC1 0x0094 | 27 | #define USBCTL0 0x58 |
27 | #define EIIBC2 0x009C | 28 | |
28 | 29 | /* High-speed signal quality characteristic control registers (R8A7778 only) */ | |
30 | #define HSQCTL1 0x24 | ||
31 | #define HSQCTL2 0x28 | ||
32 | |||
33 | /* USBPCTRL0 */ | ||
34 | #define OVC2 (1 << 10) /* (R8A7779 only) */ | ||
35 | /* Switches the OVC input pin for port 2: */ | ||
36 | /* 1: USB_OVC2, 0: OVC2 */ | ||
37 | #define OVC1_VBUS1 (1 << 9) /* Switches the OVC input pin for port 1: */ | ||
38 | /* 1: USB_OVC1, 0: OVC1/VBUS1 */ | ||
39 | /* Function mode: set to 0 */ | ||
40 | #define OVC0 (1 << 8) /* Switches the OVC input pin for port 0: */ | ||
41 | /* 1: USB_OVC0 pin, 0: OVC0 */ | ||
42 | #define OVC2_ACT (1 << 6) /* (R8A7779 only) */ | ||
43 | /* Host mode: OVC2 polarity: */ | ||
44 | /* 1: active-high, 0: active-low */ | ||
45 | #define PENC (1 << 4) /* Function mode: output level of PENC1 pin: */ | ||
46 | /* 1: high, 0: low */ | ||
47 | #define OVC0_ACT (1 << 3) /* Host mode: OVC0 polarity: */ | ||
48 | /* 1: active-high, 0: active-low */ | ||
49 | #define OVC1_ACT (1 << 1) /* Host mode: OVC1 polarity: */ | ||
50 | /* 1: active-high, 0: active-low */ | ||
51 | /* Function mode: be sure to set to 1 */ | ||
52 | #define PORT1 (1 << 0) /* Selects port 1 mode: */ | ||
53 | /* 1: function, 0: host */ | ||
29 | /* USBPCTRL1 */ | 54 | /* USBPCTRL1 */ |
30 | #define PHY_RST (1 << 2) | 55 | #define PHY_RST (1 << 2) |
31 | #define PLL_ENB (1 << 1) | 56 | #define PLL_ENB (1 << 1) |
@@ -58,8 +83,10 @@ static int rcar_usb_phy_init(struct usb_phy *phy) | |||
58 | { | 83 | { |
59 | struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy); | 84 | struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy); |
60 | struct device *dev = phy->dev; | 85 | struct device *dev = phy->dev; |
86 | struct rcar_phy_platform_data *pdata = dev->platform_data; | ||
61 | void __iomem *reg0 = priv->reg0; | 87 | void __iomem *reg0 = priv->reg0; |
62 | void __iomem *reg1 = priv->reg1; | 88 | void __iomem *reg1 = priv->reg1; |
89 | static const u8 ovcn_act[] = { OVC0_ACT, OVC1_ACT, OVC2_ACT }; | ||
63 | int i; | 90 | int i; |
64 | u32 val; | 91 | u32 val; |
65 | unsigned long flags; | 92 | unsigned long flags; |
@@ -77,7 +104,16 @@ static int rcar_usb_phy_init(struct usb_phy *phy) | |||
77 | /* (2) start USB-PHY internal PLL */ | 104 | /* (2) start USB-PHY internal PLL */ |
78 | iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1)); | 105 | iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1)); |
79 | 106 | ||
80 | /* (3) USB module status check */ | 107 | /* (3) set USB-PHY in accord with the conditions of usage */ |
108 | if (reg1) { | ||
109 | u32 hsqctl1 = pdata->ferrite_bead ? 0x41 : 0; | ||
110 | u32 hsqctl2 = pdata->ferrite_bead ? 0x0d : 7; | ||
111 | |||
112 | iowrite32(hsqctl1, reg1 + HSQCTL1); | ||
113 | iowrite32(hsqctl2, reg1 + HSQCTL2); | ||
114 | } | ||
115 | |||
116 | /* (4) USB module status check */ | ||
81 | for (i = 0; i < 1024; i++) { | 117 | for (i = 0; i < 1024; i++) { |
82 | udelay(10); | 118 | udelay(10); |
83 | val = ioread32(reg0 + USBST); | 119 | val = ioread32(reg0 + USBST); |
@@ -90,24 +126,24 @@ static int rcar_usb_phy_init(struct usb_phy *phy) | |||
90 | goto phy_init_end; | 126 | goto phy_init_end; |
91 | } | 127 | } |
92 | 128 | ||
93 | /* (4) USB-PHY reset clear */ | 129 | /* (5) USB-PHY reset clear */ |
94 | iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1)); | 130 | iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1)); |
95 | 131 | ||
96 | /* set platform specific port settings */ | 132 | /* Board specific port settings */ |
97 | iowrite32(0x00000000, (reg0 + USBPCTRL0)); | 133 | val = 0; |
98 | 134 | if (pdata->port1_func) | |
99 | /* | 135 | val |= PORT1; |
100 | * EHCI IP internal buffer setting | 136 | if (pdata->penc1) |
101 | * EHCI IP internal buffer enable | 137 | val |= PENC; |
102 | * | 138 | for (i = 0; i < 3; i++) { |
103 | * These are recommended value of a datasheet | 139 | /* OVCn bits follow each other in the right order */ |
104 | * see [USB :: EHCI internal buffer setting] | 140 | if (pdata->ovc_pin[i].select_3_3v) |
105 | */ | 141 | val |= OVC0 << i; |
106 | iowrite32(0x00ff0040, (reg0 + EIIBC1)); | 142 | /* OVCn_ACT bits are spaced by irregular intervals */ |
107 | iowrite32(0x00ff0040, (reg1 + EIIBC1)); | 143 | if (pdata->ovc_pin[i].active_high) |
108 | 144 | val |= ovcn_act[i]; | |
109 | iowrite32(0x00000001, (reg0 + EIIBC2)); | 145 | } |
110 | iowrite32(0x00000001, (reg1 + EIIBC2)); | 146 | iowrite32(val, (reg0 + USBPCTRL0)); |
111 | 147 | ||
112 | /* | 148 | /* |
113 | * Bus alignment settings | 149 | * Bus alignment settings |
@@ -134,10 +170,8 @@ static void rcar_usb_phy_shutdown(struct usb_phy *phy) | |||
134 | 170 | ||
135 | spin_lock_irqsave(&priv->lock, flags); | 171 | spin_lock_irqsave(&priv->lock, flags); |
136 | 172 | ||
137 | if (priv->counter-- == 1) { /* last user */ | 173 | if (priv->counter-- == 1) /* last user */ |
138 | iowrite32(0x00000000, (reg0 + USBPCTRL0)); | ||
139 | iowrite32(0x00000000, (reg0 + USBPCTRL1)); | 174 | iowrite32(0x00000000, (reg0 + USBPCTRL1)); |
140 | } | ||
141 | 175 | ||
142 | spin_unlock_irqrestore(&priv->lock, flags); | 176 | spin_unlock_irqrestore(&priv->lock, flags); |
143 | } | 177 | } |
@@ -147,27 +181,29 @@ static int rcar_usb_phy_probe(struct platform_device *pdev) | |||
147 | struct rcar_usb_phy_priv *priv; | 181 | struct rcar_usb_phy_priv *priv; |
148 | struct resource *res0, *res1; | 182 | struct resource *res0, *res1; |
149 | struct device *dev = &pdev->dev; | 183 | struct device *dev = &pdev->dev; |
150 | void __iomem *reg0, *reg1; | 184 | void __iomem *reg0, *reg1 = NULL; |
151 | int ret; | 185 | int ret; |
152 | 186 | ||
187 | if (!pdev->dev.platform_data) { | ||
188 | dev_err(dev, "No platform data\n"); | ||
189 | return -EINVAL; | ||
190 | } | ||
191 | |||
153 | res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 192 | res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
154 | res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 193 | if (!res0) { |
155 | if (!res0 || !res1) { | ||
156 | dev_err(dev, "Not enough platform resources\n"); | 194 | dev_err(dev, "Not enough platform resources\n"); |
157 | return -EINVAL; | 195 | return -EINVAL; |
158 | } | 196 | } |
159 | 197 | ||
160 | /* | 198 | reg0 = devm_ioremap_resource(dev, res0); |
161 | * CAUTION | 199 | if (IS_ERR(reg0)) |
162 | * | 200 | return PTR_ERR(reg0); |
163 | * Because this phy address is also mapped under OHCI/EHCI address area, | 201 | |
164 | * this driver can't use devm_request_and_ioremap(dev, res) here | 202 | res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
165 | */ | 203 | if (res1) { |
166 | reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0)); | 204 | reg1 = devm_ioremap_resource(dev, res1); |
167 | reg1 = devm_ioremap_nocache(dev, res1->start, resource_size(res1)); | 205 | if (IS_ERR(reg1)) |
168 | if (!reg0 || !reg1) { | 206 | return PTR_ERR(reg1); |
169 | dev_err(dev, "ioremap error\n"); | ||
170 | return -ENOMEM; | ||
171 | } | 207 | } |
172 | 208 | ||
173 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 209 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |