blob: b0470cd33e86d5093146e46b80324e7253c90858 [file] [log] [blame]
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -07001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
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 <debug.h>
30#include <reg.h>
31#include <ufs_hw.h>
32#include <utp.h>
33#include <upiu.h>
34#include <uic.h>
35#include <ucs.h>
36#include <dme.h>
37#include <string.h>
38#include <platform/iomap.h>
39#include <kernel/mutex.h>
40
41static int ufs_dev_init(struct ufs_dev *dev)
42{
43 /* Init the mutexes. */
44 mutex_init(&(dev->uic_data.uic_mutex));
45 mutex_init(&(dev->utrd_data.bitmap_mutex));
46 mutex_init(&(dev->utmrd_data.bitmap_mutex));
47
48 /* Initialize wait lists. */
49 list_initialize(&(dev->utrd_data.list_head.list_node));
50 list_initialize(&(dev->utmrd_data.list_head.list_node));
51
52 /* Initialize the bitmaps. */
53 dev->utrd_data.bitmap = 0;
54 dev->utmrd_data.bitmap = 0;
55
56 /* Initialize task ids. */
57 dev->utrd_data.task_id = 0;
58 dev->utmrd_data.task_id = 0;
59
60 /* Allocate memory for lists. */
61 dev->utrd_data.list_base_addr = ufs_alloc_trans_req_list();
62 dev->utmrd_data.list_base_addr = ufs_alloc_task_mgmt_req_list();
63
64 if (!dev->utrd_data.list_base_addr || !dev->utmrd_data.list_base_addr)
65 return -UFS_FAILURE;
66
67 return UFS_SUCCESS;
68}
69
70static void ufs_setup_req_lists(struct ufs_dev *dev)
71{
72 uint32_t val;
73
74 writel(dev->utmrd_data.list_base_addr, UFS_UTMRLBA(dev->base));
75 writel(dev->utmrd_data.list_base_addr << 32, UFS_UTMRLBAU(dev->base));
76
77 writel(dev->utrd_data.list_base_addr, UFS_UTRLBA(dev->base));
78 writel(dev->utrd_data.list_base_addr << 32, UFS_UTRLBAU(dev->base));
79
80 writel(1, UFS_UTMRLRSR(dev->base));
81 writel(1, UFS_UTRLRSR(dev->base));
82
83 /* Enable the required irqs. */
84 val = UFS_IE_UTRCE | UFS_IE_UEE | UFS_IE_UTMRCE | UFS_IE_UCCE ;
85 ufs_irq_enable(dev, val);
86}
87
88int ufs_read(struct ufs_dev* dev, uint64_t start_lba, addr_t buffer, uint32_t num_blocks)
89{
90 struct scsi_rdwr_req req;
91 int ret;
92
93 req.data_buffer_base = buffer;
94 req.lun = 0;
95 req.num_blocks = num_blocks;
96 req.start_lba = start_lba / dev->block_size;
97
98 ret = ucs_do_scsi_read(dev, &req);
99 if (ret)
100 {
101 dprintf(CRITICAL, "UFS read failed.\n");
102 }
103
104 return ret;
105}
106
107int ufs_write(struct ufs_dev* dev, uint64_t start_lba, addr_t buffer, uint32_t num_blocks)
108{
109 struct scsi_rdwr_req req;
110 int ret;
111
112 req.data_buffer_base = buffer;
113 req.lun = 0;
114 req.num_blocks = num_blocks;
115 req.start_lba = start_lba / dev->block_size;
116
117 ret = ucs_do_scsi_write(dev, &req);
118 if (ret)
119 {
120 dprintf(CRITICAL, "UFS write failed.\n");
121 }
122
123 return ret;
124}
125uint64_t ufs_get_dev_capacity(struct ufs_dev* dev)
126{
127 uint64_t capacity;
128 int ret = 0;
129
130 ret = dme_read_unit_desc(dev, 0, &capacity);
131 if (ret)
132 {
133 dprintf(CRITICAL, "Failed to read unit descriptor\n");
134 }
135
136 return capacity;
137}
138
139uint32_t ufs_get_serial_num(struct ufs_dev* dev)
140{
141 int ret;
142
143 ret = dme_read_device_desc(dev);
144 if (ret)
145 {
146 dprintf(CRITICAL, "UFS get serial number failed.\n");
147 }
148
149 return dev->serial_num;
150}
151
152uint32_t ufs_get_page_size(struct ufs_dev* dev)
153{
154 return dev->block_size;
155}
156
157int ufs_init(struct ufs_dev *dev)
158{
159 uint32_t ret = UFS_SUCCESS;
160 uint64_t cap;
161
162 dev->block_size = 4096;
163
164 /* Init dev struct. */
165 ret = ufs_dev_init(dev);
166 if (ret != UFS_SUCCESS)
167 {
168 dprintf(CRITICAL, "UFS init failed\n");
169 goto ufs_init_err;
170 }
171
172 /* Perform Data link init. */
173 ret = uic_init(dev);
174 if (ret != UFS_SUCCESS)
175 {
176 dprintf(CRITICAL, "UFS init failed\n");
177 goto ufs_init_err;
178 }
179
180 /* Setup request lists. */
181 ufs_setup_req_lists(dev);
182
183 /* Send NOP to check if device UTP layer is ready. */
184 ret = dme_send_nop_query(dev);
185 if (ret != UFS_SUCCESS)
186 {
187 dprintf(CRITICAL, "UFS init failed\n");
188 goto ufs_init_err;
189 }
190
191 ret = dme_set_fdeviceinit(dev);
192 if (ret != UFS_SUCCESS)
193 {
194 dprintf(CRITICAL, "UFS init failed\n");
195 goto ufs_init_err;
196 }
197
198 ret = ucs_scsi_send_inquiry(dev);
199 if (ret != UFS_SUCCESS)
200 {
201 dprintf(CRITICAL, "UFS init failed\n");
202 goto ufs_init_err;
203 }
204
205ufs_init_err:
206 return ret;
207}