]>
Commit | Line | Data |
---|---|---|
f93022c3 JR |
1 | /* |
2 | * Copyright (C) 2011 Jana Rapava <fermata7@gmail.com> | |
3 | * Copyright (C) 2011 CompuLab, Ltd. <www.compulab.co.il> | |
4 | * | |
5 | * Authors: Jana Rapava <fermata7@gmail.com> | |
6 | * Igor Grinberg <grinberg@compulab.co.il> | |
7 | * | |
8 | * Based on: | |
9 | * linux/drivers/usb/otg/ulpi_viewport.c | |
10 | * | |
11 | * Original Copyright follow: | |
12 | * Copyright (C) 2011 Google, Inc. | |
13 | * | |
5b8031cc | 14 | * SPDX-License-Identifier: GPL-2.0 |
f93022c3 JR |
15 | */ |
16 | ||
17 | #include <common.h> | |
18 | #include <asm/io.h> | |
19 | #include <usb/ulpi.h> | |
20 | ||
21 | /* ULPI viewport control bits */ | |
22 | #define ULPI_SS (1 << 27) | |
23 | #define ULPI_RWCTRL (1 << 29) | |
24 | #define ULPI_RWRUN (1 << 30) | |
25 | #define ULPI_WU (1 << 31) | |
26 | ||
27 | /* | |
28 | * Wait for the ULPI request to complete | |
29 | * | |
30 | * @ulpi_viewport - the address of the viewport | |
31 | * @mask - expected value to wait for | |
32 | * | |
33 | * returns 0 on mask match, ULPI_ERROR on time out. | |
34 | */ | |
3e6e809f | 35 | static int ulpi_wait(struct ulpi_viewport *ulpi_vp, u32 mask) |
f93022c3 JR |
36 | { |
37 | int timeout = CONFIG_USB_ULPI_TIMEOUT; | |
38 | ||
39 | /* Wait for the bits in mask to become zero. */ | |
40 | while (--timeout) { | |
3e6e809f | 41 | if ((readl(ulpi_vp->viewport_addr) & mask) == 0) |
f93022c3 JR |
42 | return 0; |
43 | ||
44 | udelay(1); | |
45 | } | |
46 | ||
47 | return ULPI_ERROR; | |
48 | } | |
49 | ||
50 | /* | |
51 | * Wake the ULPI PHY up for communication | |
52 | * | |
53 | * returns 0 on success. | |
54 | */ | |
3e6e809f | 55 | static int ulpi_wakeup(struct ulpi_viewport *ulpi_vp) |
f93022c3 JR |
56 | { |
57 | int err; | |
58 | ||
3e6e809f | 59 | if (readl(ulpi_vp->viewport_addr) & ULPI_SS) |
f93022c3 JR |
60 | return 0; /* already awake */ |
61 | ||
3e6e809f | 62 | writel(ULPI_WU, ulpi_vp->viewport_addr); |
f93022c3 | 63 | |
3e6e809f | 64 | err = ulpi_wait(ulpi_vp, ULPI_WU); |
f93022c3 JR |
65 | if (err) |
66 | printf("ULPI wakeup timed out\n"); | |
67 | ||
68 | return err; | |
69 | } | |
70 | ||
71 | /* | |
72 | * Issue a ULPI read/write request | |
73 | * | |
74 | * @value - the ULPI request | |
75 | */ | |
3e6e809f | 76 | static int ulpi_request(struct ulpi_viewport *ulpi_vp, u32 value) |
f93022c3 JR |
77 | { |
78 | int err; | |
79 | ||
3e6e809f | 80 | err = ulpi_wakeup(ulpi_vp); |
f93022c3 JR |
81 | if (err) |
82 | return err; | |
83 | ||
3e6e809f | 84 | writel(value, ulpi_vp->viewport_addr); |
f93022c3 | 85 | |
3e6e809f | 86 | err = ulpi_wait(ulpi_vp, ULPI_RWRUN); |
f93022c3 JR |
87 | if (err) |
88 | printf("ULPI request timed out\n"); | |
89 | ||
90 | return err; | |
91 | } | |
92 | ||
3e6e809f | 93 | int ulpi_write(struct ulpi_viewport *ulpi_vp, u8 *reg, u32 value) |
f93022c3 JR |
94 | { |
95 | u32 val = ULPI_RWRUN | ULPI_RWCTRL | ((u32)reg << 16) | (value & 0xff); | |
96 | ||
3e6e809f G |
97 | val |= (ulpi_vp->port_num & 0x7) << 24; |
98 | return ulpi_request(ulpi_vp, val); | |
f93022c3 JR |
99 | } |
100 | ||
3e6e809f | 101 | u32 ulpi_read(struct ulpi_viewport *ulpi_vp, u8 *reg) |
f93022c3 | 102 | { |
4256101f | 103 | int err; |
f93022c3 JR |
104 | u32 val = ULPI_RWRUN | ((u32)reg << 16); |
105 | ||
3e6e809f G |
106 | val |= (ulpi_vp->port_num & 0x7) << 24; |
107 | err = ulpi_request(ulpi_vp, val); | |
f93022c3 JR |
108 | if (err) |
109 | return err; | |
110 | ||
3e6e809f | 111 | return (readl(ulpi_vp->viewport_addr) >> 8) & 0xff; |
f93022c3 | 112 | } |