~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/alchemy/common/usb.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * USB block power/access management abstraction.
  4  *
  5  * Au1000+: The OHCI block control register is at the far end of the OHCI memory
  6  *          area. Au1550 has OHCI on different base address. No need to handle
  7  *          UDC here.
  8  * Au1200:  one register to control access and clocks to O/EHCI, UDC and OTG
  9  *          as well as the PHY for EHCI and UDC.
 10  *
 11  */
 12 
 13 #include <linux/clk.h>
 14 #include <linux/export.h>
 15 #include <linux/init.h>
 16 #include <linux/io.h>
 17 #include <linux/spinlock.h>
 18 #include <linux/syscore_ops.h>
 19 #include <asm/cpu.h>
 20 #include <asm/mach-au1x00/au1000.h>
 21 
 22 /* control register offsets */
 23 #define AU1000_OHCICFG  0x7fffc
 24 #define AU1550_OHCICFG  0x07ffc
 25 #define AU1200_USBCFG   0x04
 26 
 27 /* Au1000 USB block config bits */
 28 #define USBHEN_RD       (1 << 4)                /* OHCI reset-done indicator */
 29 #define USBHEN_CE       (1 << 3)                /* OHCI block clock enable */
 30 #define USBHEN_E        (1 << 2)                /* OHCI block enable */
 31 #define USBHEN_C        (1 << 1)                /* OHCI block coherency bit */
 32 #define USBHEN_BE       (1 << 0)                /* OHCI Big-Endian */
 33 
 34 /* Au1200 USB config bits */
 35 #define USBCFG_PFEN     (1 << 31)               /* prefetch enable (undoc) */
 36 #define USBCFG_RDCOMB   (1 << 30)               /* read combining (undoc) */
 37 #define USBCFG_UNKNOWN  (5 << 20)               /* unknown, leave this way */
 38 #define USBCFG_SSD      (1 << 23)               /* serial short detect en */
 39 #define USBCFG_PPE      (1 << 19)               /* HS PHY PLL */
 40 #define USBCFG_UCE      (1 << 18)               /* UDC clock enable */
 41 #define USBCFG_ECE      (1 << 17)               /* EHCI clock enable */
 42 #define USBCFG_OCE      (1 << 16)               /* OHCI clock enable */
 43 #define USBCFG_FLA(x)   (((x) & 0x3f) << 8)
 44 #define USBCFG_UCAM     (1 << 7)                /* coherent access (undoc) */
 45 #define USBCFG_GME      (1 << 6)                /* OTG mem access */
 46 #define USBCFG_DBE      (1 << 5)                /* UDC busmaster enable */
 47 #define USBCFG_DME      (1 << 4)                /* UDC mem enable */
 48 #define USBCFG_EBE      (1 << 3)                /* EHCI busmaster enable */
 49 #define USBCFG_EME      (1 << 2)                /* EHCI mem enable */
 50 #define USBCFG_OBE      (1 << 1)                /* OHCI busmaster enable */
 51 #define USBCFG_OME      (1 << 0)                /* OHCI mem enable */
 52 #define USBCFG_INIT_AU1200      (USBCFG_PFEN | USBCFG_RDCOMB | USBCFG_UNKNOWN |\
 53                                  USBCFG_SSD | USBCFG_FLA(0x20) | USBCFG_UCAM | \
 54                                  USBCFG_GME | USBCFG_DBE | USBCFG_DME |        \
 55                                  USBCFG_EBE | USBCFG_EME | USBCFG_OBE |        \
 56                                  USBCFG_OME)
 57 
 58 /* Au1300 USB config registers */
 59 #define USB_DWC_CTRL1           0x00
 60 #define USB_DWC_CTRL2           0x04
 61 #define USB_VBUS_TIMER          0x10
 62 #define USB_SBUS_CTRL           0x14
 63 #define USB_MSR_ERR             0x18
 64 #define USB_DWC_CTRL3           0x1C
 65 #define USB_DWC_CTRL4           0x20
 66 #define USB_OTG_STATUS          0x28
 67 #define USB_DWC_CTRL5           0x2C
 68 #define USB_DWC_CTRL6           0x30
 69 #define USB_DWC_CTRL7           0x34
 70 #define USB_PHY_STATUS          0xC0
 71 #define USB_INT_STATUS          0xC4
 72 #define USB_INT_ENABLE          0xC8
 73 
 74 #define USB_DWC_CTRL1_OTGD      0x04 /* set to DISable OTG */
 75 #define USB_DWC_CTRL1_HSTRS     0x02 /* set to ENable EHCI */
 76 #define USB_DWC_CTRL1_DCRS      0x01 /* set to ENable UDC */
 77 
 78 #define USB_DWC_CTRL2_PHY1RS    0x04 /* set to enable PHY1 */
 79 #define USB_DWC_CTRL2_PHY0RS    0x02 /* set to enable PHY0 */
 80 #define USB_DWC_CTRL2_PHYRS     0x01 /* set to enable PHY */
 81 
 82 #define USB_DWC_CTRL3_OHCI1_CKEN        (1 << 19)
 83 #define USB_DWC_CTRL3_OHCI0_CKEN        (1 << 18)
 84 #define USB_DWC_CTRL3_EHCI0_CKEN        (1 << 17)
 85 #define USB_DWC_CTRL3_OTG0_CKEN         (1 << 16)
 86 
 87 #define USB_SBUS_CTRL_SBCA              0x04 /* coherent access */
 88 
 89 #define USB_INTEN_FORCE                 0x20
 90 #define USB_INTEN_PHY                   0x10
 91 #define USB_INTEN_UDC                   0x08
 92 #define USB_INTEN_EHCI                  0x04
 93 #define USB_INTEN_OHCI1                 0x02
 94 #define USB_INTEN_OHCI0                 0x01
 95 
 96 static DEFINE_SPINLOCK(alchemy_usb_lock);
 97 
 98 static inline void __au1300_usb_phyctl(void __iomem *base, int enable)
 99 {
100         unsigned long r, s;
101 
102         r = __raw_readl(base + USB_DWC_CTRL2);
103         s = __raw_readl(base + USB_DWC_CTRL3);
104 
105         s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN |
106                 USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN;
107 
108         if (enable) {
109                 /* simply enable all PHYs */
110                 r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
111                      USB_DWC_CTRL2_PHYRS;
112                 __raw_writel(r, base + USB_DWC_CTRL2);
113                 wmb();
114         } else if (!s) {
115                 /* no USB block active, do disable all PHYs */
116                 r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
117                        USB_DWC_CTRL2_PHYRS);
118                 __raw_writel(r, base + USB_DWC_CTRL2);
119                 wmb();
120         }
121 }
122 
123 static inline void __au1300_ohci_control(void __iomem *base, int enable, int id)
124 {
125         unsigned long r;
126 
127         if (enable) {
128                 __raw_writel(1, base + USB_DWC_CTRL7);  /* start OHCI clock */
129                 wmb();
130 
131                 r = __raw_readl(base + USB_DWC_CTRL3);  /* enable OHCI block */
132                 r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
133                                : USB_DWC_CTRL3_OHCI1_CKEN;
134                 __raw_writel(r, base + USB_DWC_CTRL3);
135                 wmb();
136 
137                 __au1300_usb_phyctl(base, enable);      /* power up the PHYs */
138 
139                 r = __raw_readl(base + USB_INT_ENABLE);
140                 r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1;
141                 __raw_writel(r, base + USB_INT_ENABLE);
142                 wmb();
143 
144                 /* reset the OHCI start clock bit */
145                 __raw_writel(0, base + USB_DWC_CTRL7);
146                 wmb();
147         } else {
148                 r = __raw_readl(base + USB_INT_ENABLE);
149                 r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1);
150                 __raw_writel(r, base + USB_INT_ENABLE);
151                 wmb();
152 
153                 r = __raw_readl(base + USB_DWC_CTRL3);
154                 r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
155                                  : USB_DWC_CTRL3_OHCI1_CKEN);
156                 __raw_writel(r, base + USB_DWC_CTRL3);
157                 wmb();
158 
159                 __au1300_usb_phyctl(base, enable);
160         }
161 }
162 
163 static inline void __au1300_ehci_control(void __iomem *base, int enable)
164 {
165         unsigned long r;
166 
167         if (enable) {
168                 r = __raw_readl(base + USB_DWC_CTRL3);
169                 r |= USB_DWC_CTRL3_EHCI0_CKEN;
170                 __raw_writel(r, base + USB_DWC_CTRL3);
171                 wmb();
172 
173                 r = __raw_readl(base + USB_DWC_CTRL1);
174                 r |= USB_DWC_CTRL1_HSTRS;
175                 __raw_writel(r, base + USB_DWC_CTRL1);
176                 wmb();
177 
178                 __au1300_usb_phyctl(base, enable);
179 
180                 r = __raw_readl(base + USB_INT_ENABLE);
181                 r |= USB_INTEN_EHCI;
182                 __raw_writel(r, base + USB_INT_ENABLE);
183                 wmb();
184         } else {
185                 r = __raw_readl(base + USB_INT_ENABLE);
186                 r &= ~USB_INTEN_EHCI;
187                 __raw_writel(r, base + USB_INT_ENABLE);
188                 wmb();
189 
190                 r = __raw_readl(base + USB_DWC_CTRL1);
191                 r &= ~USB_DWC_CTRL1_HSTRS;
192                 __raw_writel(r, base + USB_DWC_CTRL1);
193                 wmb();
194 
195                 r = __raw_readl(base + USB_DWC_CTRL3);
196                 r &= ~USB_DWC_CTRL3_EHCI0_CKEN;
197                 __raw_writel(r, base + USB_DWC_CTRL3);
198                 wmb();
199 
200                 __au1300_usb_phyctl(base, enable);
201         }
202 }
203 
204 static inline void __au1300_udc_control(void __iomem *base, int enable)
205 {
206         unsigned long r;
207 
208         if (enable) {
209                 r = __raw_readl(base + USB_DWC_CTRL1);
210                 r |= USB_DWC_CTRL1_DCRS;
211                 __raw_writel(r, base + USB_DWC_CTRL1);
212                 wmb();
213 
214                 __au1300_usb_phyctl(base, enable);
215 
216                 r = __raw_readl(base + USB_INT_ENABLE);
217                 r |= USB_INTEN_UDC;
218                 __raw_writel(r, base + USB_INT_ENABLE);
219                 wmb();
220         } else {
221                 r = __raw_readl(base + USB_INT_ENABLE);
222                 r &= ~USB_INTEN_UDC;
223                 __raw_writel(r, base + USB_INT_ENABLE);
224                 wmb();
225 
226                 r = __raw_readl(base + USB_DWC_CTRL1);
227                 r &= ~USB_DWC_CTRL1_DCRS;
228                 __raw_writel(r, base + USB_DWC_CTRL1);
229                 wmb();
230 
231                 __au1300_usb_phyctl(base, enable);
232         }
233 }
234 
235 static inline void __au1300_otg_control(void __iomem *base, int enable)
236 {
237         unsigned long r;
238         if (enable) {
239                 r = __raw_readl(base + USB_DWC_CTRL3);
240                 r |= USB_DWC_CTRL3_OTG0_CKEN;
241                 __raw_writel(r, base + USB_DWC_CTRL3);
242                 wmb();
243 
244                 r = __raw_readl(base + USB_DWC_CTRL1);
245                 r &= ~USB_DWC_CTRL1_OTGD;
246                 __raw_writel(r, base + USB_DWC_CTRL1);
247                 wmb();
248 
249                 __au1300_usb_phyctl(base, enable);
250         } else {
251                 r = __raw_readl(base + USB_DWC_CTRL1);
252                 r |= USB_DWC_CTRL1_OTGD;
253                 __raw_writel(r, base + USB_DWC_CTRL1);
254                 wmb();
255 
256                 r = __raw_readl(base + USB_DWC_CTRL3);
257                 r &= ~USB_DWC_CTRL3_OTG0_CKEN;
258                 __raw_writel(r, base + USB_DWC_CTRL3);
259                 wmb();
260 
261                 __au1300_usb_phyctl(base, enable);
262         }
263 }
264 
265 static inline int au1300_usb_control(int block, int enable)
266 {
267         void __iomem *base =
268                 (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
269         int ret = 0;
270 
271         switch (block) {
272         case ALCHEMY_USB_OHCI0:
273                 __au1300_ohci_control(base, enable, 0);
274                 break;
275         case ALCHEMY_USB_OHCI1:
276                 __au1300_ohci_control(base, enable, 1);
277                 break;
278         case ALCHEMY_USB_EHCI0:
279                 __au1300_ehci_control(base, enable);
280                 break;
281         case ALCHEMY_USB_UDC0:
282                 __au1300_udc_control(base, enable);
283                 break;
284         case ALCHEMY_USB_OTG0:
285                 __au1300_otg_control(base, enable);
286                 break;
287         default:
288                 ret = -ENODEV;
289         }
290         return ret;
291 }
292 
293 static inline void au1300_usb_init(void)
294 {
295         void __iomem *base =
296                 (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
297 
298         /* set some sane defaults.  Note: we don't fiddle with DWC_CTRL4
299          * here at all: Port 2 routing (EHCI or UDC) must be set either
300          * by boot firmware or platform init code; I can't autodetect
301          * a sane setting.
302          */
303         __raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */
304         wmb();
305         __raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */
306         wmb();
307         __raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */
308         wmb();
309         __raw_writel(~0, base + USB_INT_STATUS); /* clear int status */
310         wmb();
311         /* set coherent access bit */
312         __raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL);
313         wmb();
314 }
315 
316 static inline void __au1200_ohci_control(void __iomem *base, int enable)
317 {
318         unsigned long r = __raw_readl(base + AU1200_USBCFG);
319         if (enable) {
320                 __raw_writel(r | USBCFG_OCE, base + AU1200_USBCFG);
321                 wmb();
322                 udelay(2000);
323         } else {
324                 __raw_writel(r & ~USBCFG_OCE, base + AU1200_USBCFG);
325                 wmb();
326                 udelay(1000);
327         }
328 }
329 
330 static inline void __au1200_ehci_control(void __iomem *base, int enable)
331 {
332         unsigned long r = __raw_readl(base + AU1200_USBCFG);
333         if (enable) {
334                 __raw_writel(r | USBCFG_ECE | USBCFG_PPE, base + AU1200_USBCFG);
335                 wmb();
336                 udelay(1000);
337         } else {
338                 if (!(r & USBCFG_UCE))          /* UDC also off? */
339                         r &= ~USBCFG_PPE;       /* yes: disable HS PHY PLL */
340                 __raw_writel(r & ~USBCFG_ECE, base + AU1200_USBCFG);
341                 wmb();
342                 udelay(1000);
343         }
344 }
345 
346 static inline void __au1200_udc_control(void __iomem *base, int enable)
347 {
348         unsigned long r = __raw_readl(base + AU1200_USBCFG);
349         if (enable) {
350                 __raw_writel(r | USBCFG_UCE | USBCFG_PPE, base + AU1200_USBCFG);
351                 wmb();
352         } else {
353                 if (!(r & USBCFG_ECE))          /* EHCI also off? */
354                         r &= ~USBCFG_PPE;       /* yes: disable HS PHY PLL */
355                 __raw_writel(r & ~USBCFG_UCE, base + AU1200_USBCFG);
356                 wmb();
357         }
358 }
359 
360 static inline int au1200_usb_control(int block, int enable)
361 {
362         void __iomem *base =
363                         (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
364 
365         switch (block) {
366         case ALCHEMY_USB_OHCI0:
367                 __au1200_ohci_control(base, enable);
368                 break;
369         case ALCHEMY_USB_UDC0:
370                 __au1200_udc_control(base, enable);
371                 break;
372         case ALCHEMY_USB_EHCI0:
373                 __au1200_ehci_control(base, enable);
374                 break;
375         default:
376                 return -ENODEV;
377         }
378         return 0;
379 }
380 
381 
382 /* initialize USB block(s) to a known working state */
383 static inline void au1200_usb_init(void)
384 {
385         void __iomem *base =
386                         (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
387         __raw_writel(USBCFG_INIT_AU1200, base + AU1200_USBCFG);
388         wmb();
389         udelay(1000);
390 }
391 
392 static inline int au1000_usb_init(unsigned long rb, int reg)
393 {
394         void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
395         unsigned long r = __raw_readl(base);
396         struct clk *c;
397 
398         /* 48MHz check. Don't init if no one can provide it */
399         c = clk_get(NULL, "usbh_clk");
400         if (IS_ERR(c))
401                 return -ENODEV;
402         if (clk_round_rate(c, 48000000) != 48000000) {
403                 clk_put(c);
404                 return -ENODEV;
405         }
406         if (clk_set_rate(c, 48000000)) {
407                 clk_put(c);
408                 return -ENODEV;
409         }
410         clk_put(c);
411 
412 #if defined(__BIG_ENDIAN)
413         r |= USBHEN_BE;
414 #endif
415         r |= USBHEN_C;
416 
417         __raw_writel(r, base);
418         wmb();
419         udelay(1000);
420 
421         return 0;
422 }
423 
424 
425 static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
426 {
427         void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
428         unsigned long r = __raw_readl(base + creg);
429         struct clk *c = clk_get(NULL, "usbh_clk");
430 
431         if (IS_ERR(c))
432                 return;
433 
434         if (enable) {
435                 if (clk_prepare_enable(c))
436                         goto out;
437 
438                 __raw_writel(r | USBHEN_CE, base + creg);
439                 wmb();
440                 udelay(1000);
441                 __raw_writel(r | USBHEN_CE | USBHEN_E, base + creg);
442                 wmb();
443                 udelay(1000);
444 
445                 /* wait for reset complete (read reg twice: au1500 erratum) */
446                 while (__raw_readl(base + creg),
447                         !(__raw_readl(base + creg) & USBHEN_RD))
448                         udelay(1000);
449         } else {
450                 __raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
451                 wmb();
452                 clk_disable_unprepare(c);
453         }
454 out:
455         clk_put(c);
456 }
457 
458 static inline int au1000_usb_control(int block, int enable, unsigned long rb,
459                                      int creg)
460 {
461         int ret = 0;
462 
463         switch (block) {
464         case ALCHEMY_USB_OHCI0:
465                 __au1xx0_ohci_control(enable, rb, creg);
466                 break;
467         default:
468                 ret = -ENODEV;
469         }
470         return ret;
471 }
472 
473 /*
474  * alchemy_usb_control - control Alchemy on-chip USB blocks
475  * @block:      USB block to target
476  * @enable:     set 1 to enable a block, 0 to disable
477  */
478 int alchemy_usb_control(int block, int enable)
479 {
480         unsigned long flags;
481         int ret;
482 
483         spin_lock_irqsave(&alchemy_usb_lock, flags);
484         switch (alchemy_get_cputype()) {
485         case ALCHEMY_CPU_AU1000:
486         case ALCHEMY_CPU_AU1500:
487         case ALCHEMY_CPU_AU1100:
488                 ret = au1000_usb_control(block, enable,
489                         AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
490                 break;
491         case ALCHEMY_CPU_AU1550:
492                 ret = au1000_usb_control(block, enable,
493                         AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
494                 break;
495         case ALCHEMY_CPU_AU1200:
496                 ret = au1200_usb_control(block, enable);
497                 break;
498         case ALCHEMY_CPU_AU1300:
499                 ret = au1300_usb_control(block, enable);
500                 break;
501         default:
502                 ret = -ENODEV;
503         }
504         spin_unlock_irqrestore(&alchemy_usb_lock, flags);
505         return ret;
506 }
507 EXPORT_SYMBOL_GPL(alchemy_usb_control);
508 
509 
510 static unsigned long alchemy_usb_pmdata[2];
511 
512 static void au1000_usb_pm(unsigned long br, int creg, int susp)
513 {
514         void __iomem *base = (void __iomem *)KSEG1ADDR(br);
515 
516         if (susp) {
517                 alchemy_usb_pmdata[0] = __raw_readl(base + creg);
518                 /* There appears to be some undocumented reset register.... */
519                 __raw_writel(0, base + 0x04);
520                 wmb();
521                 __raw_writel(0, base + creg);
522                 wmb();
523         } else {
524                 __raw_writel(alchemy_usb_pmdata[0], base + creg);
525                 wmb();
526         }
527 }
528 
529 static void au1200_usb_pm(int susp)
530 {
531         void __iomem *base =
532                         (void __iomem *)KSEG1ADDR(AU1200_USB_OTG_PHYS_ADDR);
533         if (susp) {
534                 /* save OTG_CAP/MUX registers which indicate port routing */
535                 /* FIXME: write an OTG driver to do that */
536                 alchemy_usb_pmdata[0] = __raw_readl(base + 0x00);
537                 alchemy_usb_pmdata[1] = __raw_readl(base + 0x04);
538         } else {
539                 /* restore access to all MMIO areas */
540                 au1200_usb_init();
541 
542                 /* restore OTG_CAP/MUX registers */
543                 __raw_writel(alchemy_usb_pmdata[0], base + 0x00);
544                 __raw_writel(alchemy_usb_pmdata[1], base + 0x04);
545                 wmb();
546         }
547 }
548 
549 static void au1300_usb_pm(int susp)
550 {
551         void __iomem *base =
552                         (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
553         /* remember Port2 routing */
554         if (susp) {
555                 alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4);
556         } else {
557                 au1300_usb_init();
558                 __raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4);
559                 wmb();
560         }
561 }
562 
563 static void alchemy_usb_pm(int susp)
564 {
565         switch (alchemy_get_cputype()) {
566         case ALCHEMY_CPU_AU1000:
567         case ALCHEMY_CPU_AU1500:
568         case ALCHEMY_CPU_AU1100:
569                 au1000_usb_pm(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG, susp);
570                 break;
571         case ALCHEMY_CPU_AU1550:
572                 au1000_usb_pm(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG, susp);
573                 break;
574         case ALCHEMY_CPU_AU1200:
575                 au1200_usb_pm(susp);
576                 break;
577         case ALCHEMY_CPU_AU1300:
578                 au1300_usb_pm(susp);
579                 break;
580         }
581 }
582 
583 static int alchemy_usb_suspend(void)
584 {
585         alchemy_usb_pm(1);
586         return 0;
587 }
588 
589 static void alchemy_usb_resume(void)
590 {
591         alchemy_usb_pm(0);
592 }
593 
594 static struct syscore_ops alchemy_usb_pm_ops = {
595         .suspend        = alchemy_usb_suspend,
596         .resume         = alchemy_usb_resume,
597 };
598 
599 static int __init alchemy_usb_init(void)
600 {
601         int ret = 0;
602 
603         switch (alchemy_get_cputype()) {
604         case ALCHEMY_CPU_AU1000:
605         case ALCHEMY_CPU_AU1500:
606         case ALCHEMY_CPU_AU1100:
607                 ret = au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR,
608                                       AU1000_OHCICFG);
609                 break;
610         case ALCHEMY_CPU_AU1550:
611                 ret = au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR,
612                                       AU1550_OHCICFG);
613                 break;
614         case ALCHEMY_CPU_AU1200:
615                 au1200_usb_init();
616                 break;
617         case ALCHEMY_CPU_AU1300:
618                 au1300_usb_init();
619                 break;
620         }
621 
622         if (!ret)
623                 register_syscore_ops(&alchemy_usb_pm_ops);
624 
625         return ret;
626 }
627 arch_initcall(alchemy_usb_init);
628 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php