blob: 0605678185376e8364a69c4507056229944b2398 [file] [log] [blame]
Sridhar Parasuramc6fb2ef2014-09-18 09:50:30 -07001/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdlib.h>
30#include <arch/ops.h>
31#include <sys/types.h>
32#include <reg.h>
33#include <platform/interrupts.h>
34#include <platform/iomap.h>
35#include <platform/irqs.h>
36#include <ufs_hw.h>
37#include <utp.h>
Sridhar Parasuramc6fb2ef2014-09-18 09:50:30 -070038#include <ufs.h>
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070039
40uint64_t ufs_alloc_trans_req_list()
41{
42 void *ptr;
43
44 ptr = memalign(lcm(CACHE_LINE, 1024), 32 * sizeof(struct utp_trans_req_desc));
45
46 if (!ptr)
47 {
48 dprintf(CRITICAL, "Failed to allocate utrd list.\n");
49 }
50
51 return (addr_t) ptr;
52}
53
54uint64_t ufs_alloc_task_mgmt_req_list()
55{
56 addr_t ptr = (addr_t) memalign(1024, 1024);
57
58 if (!ptr)
59 {
60 dprintf(CRITICAL, "Failed to allocate memory for Task mamagement request list.\n");
61 }
62
63 return ptr;
64}
65
66int ufs_enable_hci(struct ufs_dev *dev)
67{
68 int ret;
69
70 /* Enable host controller */
71 writel(UFS_HCE_ENABLE, UFS_HCE(dev->base));
72
73 /* Wait until host controller is enabled. */
74 ret = ufs_reg_target_val_timeout_loop(UFS_HCE(dev->base), 1, UFS_HCE_TIMEOUT);
75 if (ret)
76 {
77 dprintf(CRITICAL, "Failed to enable UFS host controller.\n");
78 }
79
80 return ret;
81}
82
83void ufs_irq_enable(struct ufs_dev *dev, uint32_t irq)
84{
85 /* Clear all irqs. */
86 writel(0xFFFFFFFF, UFS_IS(dev->base));
87
88 writel(irq, UFS_IE(dev->base));
89 register_int_handler(UFS_IRQ, ufs_irq_handler, dev);
90 unmask_interrupt(UFS_IRQ);
91}
92
93enum handler_return ufs_irq_handler(void* data)
94{
95 uint32_t val;
96 struct ufs_dev *dev = (struct ufs_dev *) data;
97 struct ufs_req_irq_type irq;
98
99 val = readl(UFS_IS(dev->base));
100
Sridhar Parasuramc6fb2ef2014-09-18 09:50:30 -0700101 if (val & UFS_IS_SBFES)
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700102 {
103 /* Controller might be in a bad state, unrecoverable error. */
Sridhar Parasuramc6fb2ef2014-09-18 09:50:30 -0700104 dprintf(CRITICAL, "UFS error: System Bus Fatal Error\n");
105 ASSERT(0);
106 }
107 else if (val & UFS_IS_UTPES)
108 {
109 /* Unrecoverable error occured at the utp layer */
110 dprintf(CRITICAL, "UFS error: UTP Error\n");
111 ASSERT(0);
112 }
113 else if ((val & UFS_IS_HCFES) || (val & UFS_IS_DFES))
114 {
115 /* Controller might be in a bad state, unrecoverable error. */
116 /* HCFES: Host Controller Fatal Error Status */
117 /* DFES: Device Fatal Error Status */
118 dprintf(CRITICAL, "UFS error: HCFES:0x%x DFES:0x%x\n",
119 val & UFS_IS_HCFES, val & UFS_IS_DFES);
120 ASSERT(0);
121 }
122 else if (val & UFS_IS_UE)
123 {
124 /* Error in one of the layers in the UniPro stack */
125 dprintf(CRITICAL, "UFS error: UE. Dumping UIC Error code registers\n");
126 ufs_dump_hc_registers(dev);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700127 ASSERT(0);
128 }
129
130 while (val)
131 {
132 irq.irq_handled = 0;
133
134 if (val & UFS_IS_UCCS)
135 {
136 /* UIC command */
137 event_signal(&(dev->uic_data.uic_event), false);
138 /* Clear irq. */
139 writel(UFS_IS_UCCS, UFS_IS(dev->base));
140 val &= ~UFS_IS_UCCS;
141 irq.irq_handled = UFS_IS_UCCS;
142 continue;
143 }
144 else if (val & UFS_IS_UTRCS)
145 {
146 /* UTRD completion. */
147 irq.list = &(dev->utrd_data.list_head.list_node);
148 irq.irq_handled = UFS_IS_UTRCS;
149 irq.door_bell_reg = UFS_UTRLDBR(dev->base);
150
151 /* Clear irq. */
152 writel(irq.irq_handled, UFS_IS(dev->base));
153 val &= ~irq.irq_handled;
154
155 utp_process_req_completion(&irq);
156 }
157 else if (val & UFS_IS_UTMRCS)
158 {
159 /* UTMRD completion. */
160 irq.list = &(dev->utmrd_data.list_head.list_node);
161 irq.irq_handled = UFS_IS_UTMRCS;
162 /* TODO: Fill in door bell reg for management requests. */
163
164 /* Clear irq. */
165 writel(irq.irq_handled, UFS_IS(dev->base));
166 val &= ~irq.irq_handled;
167
168 utp_process_req_completion(&irq);
169 }
170 else
171 {
172 dprintf(CRITICAL, "Unknown irq.\n");
173 ASSERT(0);
174 }
175 }
176
177 return INT_NO_RESCHEDULE;
178}
179
180int ufs_reg_target_val_timeout_loop(uint32_t reg_addr, uint32_t target_val, uint32_t timeout)
181{
182 uint32_t try_again;
183 uint32_t val;
184
185 try_again = timeout;
186
187 do
188 {
189 try_again--;
190 val = readl(reg_addr);
191 } while (!(val & target_val) && try_again);
192
193 if (!(val & target_val))
194 return -UFS_FAILURE;
195 else
196 return UFS_SUCCESS;
197}