diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2012-08-06 21:08:39 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-08-10 15:05:32 -0400 |
commit | 04216bedafb1b3992a6c2b7f1518281d2ba5fc7b (patch) | |
tree | a7219c5971f999f8d7a4b2e2a8a7b5790cb82426 | |
parent | b6dd245c4594482d46507a0bfd100439be367952 (diff) |
usb: host: ehci-platform: add platform specific power callback
This patch enables to call platform specific power callback function.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/host/ehci-platform.c | 40 | ||||
-rw-r--r-- | include/linux/usb/ehci_pdriver.h | 8 |
2 files changed, 45 insertions, 3 deletions
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index a2aaef618aea..91acdde8d21f 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c | |||
@@ -105,10 +105,18 @@ static int __devinit ehci_platform_probe(struct platform_device *dev) | |||
105 | return -ENXIO; | 105 | return -ENXIO; |
106 | } | 106 | } |
107 | 107 | ||
108 | if (pdata->power_on) { | ||
109 | err = pdata->power_on(dev); | ||
110 | if (err < 0) | ||
111 | return err; | ||
112 | } | ||
113 | |||
108 | hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, | 114 | hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, |
109 | dev_name(&dev->dev)); | 115 | dev_name(&dev->dev)); |
110 | if (!hcd) | 116 | if (!hcd) { |
111 | return -ENOMEM; | 117 | err = -ENOMEM; |
118 | goto err_power; | ||
119 | } | ||
112 | 120 | ||
113 | hcd->rsrc_start = res_mem->start; | 121 | hcd->rsrc_start = res_mem->start; |
114 | hcd->rsrc_len = resource_size(res_mem); | 122 | hcd->rsrc_len = resource_size(res_mem); |
@@ -136,12 +144,17 @@ err_release_region: | |||
136 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 144 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
137 | err_put_hcd: | 145 | err_put_hcd: |
138 | usb_put_hcd(hcd); | 146 | usb_put_hcd(hcd); |
147 | err_power: | ||
148 | if (pdata->power_off) | ||
149 | pdata->power_off(dev); | ||
150 | |||
139 | return err; | 151 | return err; |
140 | } | 152 | } |
141 | 153 | ||
142 | static int __devexit ehci_platform_remove(struct platform_device *dev) | 154 | static int __devexit ehci_platform_remove(struct platform_device *dev) |
143 | { | 155 | { |
144 | struct usb_hcd *hcd = platform_get_drvdata(dev); | 156 | struct usb_hcd *hcd = platform_get_drvdata(dev); |
157 | struct usb_ehci_pdata *pdata = dev->dev.platform_data; | ||
145 | 158 | ||
146 | usb_remove_hcd(hcd); | 159 | usb_remove_hcd(hcd); |
147 | iounmap(hcd->regs); | 160 | iounmap(hcd->regs); |
@@ -149,6 +162,9 @@ static int __devexit ehci_platform_remove(struct platform_device *dev) | |||
149 | usb_put_hcd(hcd); | 162 | usb_put_hcd(hcd); |
150 | platform_set_drvdata(dev, NULL); | 163 | platform_set_drvdata(dev, NULL); |
151 | 164 | ||
165 | if (pdata->power_off) | ||
166 | pdata->power_off(dev); | ||
167 | |||
152 | return 0; | 168 | return 0; |
153 | } | 169 | } |
154 | 170 | ||
@@ -157,14 +173,32 @@ static int __devexit ehci_platform_remove(struct platform_device *dev) | |||
157 | static int ehci_platform_suspend(struct device *dev) | 173 | static int ehci_platform_suspend(struct device *dev) |
158 | { | 174 | { |
159 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 175 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
176 | struct usb_ehci_pdata *pdata = dev->platform_data; | ||
177 | struct platform_device *pdev = | ||
178 | container_of(dev, struct platform_device, dev); | ||
160 | bool do_wakeup = device_may_wakeup(dev); | 179 | bool do_wakeup = device_may_wakeup(dev); |
180 | int ret; | ||
181 | |||
182 | ret = ehci_suspend(hcd, do_wakeup); | ||
161 | 183 | ||
162 | return ehci_suspend(hcd, do_wakeup); | 184 | if (pdata->power_suspend) |
185 | pdata->power_suspend(pdev); | ||
186 | |||
187 | return ret; | ||
163 | } | 188 | } |
164 | 189 | ||
165 | static int ehci_platform_resume(struct device *dev) | 190 | static int ehci_platform_resume(struct device *dev) |
166 | { | 191 | { |
167 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 192 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
193 | struct usb_ehci_pdata *pdata = dev->platform_data; | ||
194 | struct platform_device *pdev = | ||
195 | container_of(dev, struct platform_device, dev); | ||
196 | |||
197 | if (pdata->power_on) { | ||
198 | int err = pdata->power_on(pdev); | ||
199 | if (err < 0) | ||
200 | return err; | ||
201 | } | ||
168 | 202 | ||
169 | ehci_resume(hcd, false); | 203 | ehci_resume(hcd, false); |
170 | return 0; | 204 | return 0; |
diff --git a/include/linux/usb/ehci_pdriver.h b/include/linux/usb/ehci_pdriver.h index 1894f42fe3f7..c9d09f8b7ff2 100644 --- a/include/linux/usb/ehci_pdriver.h +++ b/include/linux/usb/ehci_pdriver.h | |||
@@ -41,6 +41,14 @@ struct usb_ehci_pdata { | |||
41 | unsigned big_endian_mmio:1; | 41 | unsigned big_endian_mmio:1; |
42 | unsigned port_power_on:1; | 42 | unsigned port_power_on:1; |
43 | unsigned port_power_off:1; | 43 | unsigned port_power_off:1; |
44 | |||
45 | /* Turn on all power and clocks */ | ||
46 | int (*power_on)(struct platform_device *pdev); | ||
47 | /* Turn off all power and clocks */ | ||
48 | void (*power_off)(struct platform_device *pdev); | ||
49 | /* Turn on only VBUS suspend power and hotplug detection, | ||
50 | * turn off everything else */ | ||
51 | void (*power_suspend)(struct platform_device *pdev); | ||
44 | }; | 52 | }; |
45 | 53 | ||
46 | #endif /* __USB_CORE_EHCI_PDRIVER_H */ | 54 | #endif /* __USB_CORE_EHCI_PDRIVER_H */ |