blob: 5728bf7f92046ea47e7c8adf8a512a6eb010a0ab [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");
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700102 ufs_dump_hc_registers(dev);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700103 }
104
105 return ret;
106}
107
108int ufs_write(struct ufs_dev* dev, uint64_t start_lba, addr_t buffer, uint32_t num_blocks)
109{
110 struct scsi_rdwr_req req;
111 int ret;
112
113 req.data_buffer_base = buffer;
114 req.lun = 0;
115 req.num_blocks = num_blocks;
116 req.start_lba = start_lba / dev->block_size;
117
118 ret = ucs_do_scsi_write(dev, &req);
119 if (ret)
120 {
121 dprintf(CRITICAL, "UFS write failed.\n");
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700122 ufs_dump_hc_registers(dev);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700123 }
124
125 return ret;
126}
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700127
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700128int ufs_erase(struct ufs_dev* dev, uint64_t start_lba, uint32_t num_blocks)
129{
130 struct scsi_unmap_req req;
131 int ret;
132
133 req.lun = dev->current_lun;
134 req.start_lba = start_lba / dev->block_size;
135 req.num_blocks = num_blocks;
136
137 ret = ucs_do_scsi_unmap(dev, &req);
138 if(ret)
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700139 {
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700140 dprintf(CRITICAL, "UFS erase failed \n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700141 }
142
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700143 return ret;
144}
145
146uint64_t ufs_get_dev_capacity(struct ufs_dev* dev)
147{
148 return dev->capacity;
149}
150
151uint32_t ufs_get_erase_blk_size(struct ufs_dev* dev)
152{
153 return dev->erase_blk_size;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700154}
155
156uint32_t ufs_get_serial_num(struct ufs_dev* dev)
157{
158 int ret;
159
160 ret = dme_read_device_desc(dev);
161 if (ret)
162 {
163 dprintf(CRITICAL, "UFS get serial number failed.\n");
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700164 ufs_dump_hc_registers(dev);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700165 }
166
167 return dev->serial_num;
168}
169
170uint32_t ufs_get_page_size(struct ufs_dev* dev)
171{
172 return dev->block_size;
173}
174
175int ufs_init(struct ufs_dev *dev)
176{
177 uint32_t ret = UFS_SUCCESS;
178 uint64_t cap;
179
180 dev->block_size = 4096;
181
182 /* Init dev struct. */
183 ret = ufs_dev_init(dev);
184 if (ret != UFS_SUCCESS)
185 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700186 dprintf(CRITICAL, "UFS dev_init failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700187 goto ufs_init_err;
188 }
189
190 /* Perform Data link init. */
191 ret = uic_init(dev);
192 if (ret != UFS_SUCCESS)
193 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700194 dprintf(CRITICAL, "UFS uic_init failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700195 goto ufs_init_err;
196 }
197
198 /* Setup request lists. */
199 ufs_setup_req_lists(dev);
200
201 /* Send NOP to check if device UTP layer is ready. */
202 ret = dme_send_nop_query(dev);
203 if (ret != UFS_SUCCESS)
204 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700205 dprintf(CRITICAL, "UFS dme_send_nop_query failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700206 goto ufs_init_err;
207 }
208
209 ret = dme_set_fdeviceinit(dev);
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700210 if (ret != UFS_SUCCESS)
211 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700212 dprintf(CRITICAL, "UFS dme_set_fdeviceinit failed\n");
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700213 goto ufs_init_err;
214 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700215
216 ret = ucs_scsi_send_inquiry(dev);
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700217 if (ret != UFS_SUCCESS)
218 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700219 dprintf(CRITICAL, "UFS ucs_scsi_send_inquiry failed\n");
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700220 goto ufs_init_err;
221 }
222
223 ret = dme_read_unit_desc(dev, 0);
224 if (ret != UFS_SUCCESS)
225 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700226 dprintf(CRITICAL, "UFS dme_read_unit_desc failed\n");
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700227 goto ufs_init_err;
228 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700229
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700230 dprintf(CRITICAL,"UFS init success\n");
231
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700232ufs_init_err:
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700233
234 if(ret != UFS_SUCCESS)
235 {
236 ufs_dump_hc_registers(dev);
237 }
238
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700239 return ret;
240}
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700241
242void ufs_dump_hc_registers(struct ufs_dev *dev)
243{
244 uint32_t base = dev->base;
245
246 dprintf(CRITICAL,"------Host controller register dump ---------\n");
247 dprintf(CRITICAL,"UFS_UECPA 0x%x\n",readl(UFS_UECPA(base)));
248 dprintf(CRITICAL,"UFS_UECDL 0x%x\n",readl(UFS_UECDL(base)));
249 dprintf(CRITICAL,"UFS_UECN 0x%x\n", readl(UFS_UECN(base)));
250 dprintf(CRITICAL,"UFS_UECT 0x%x\n",readl(UFS_UECT(base)));
251 dprintf(CRITICAL,"UFS_UECDME 0x%x\n",readl(UFS_UECDME(base)));
252 dprintf(CRITICAL,"UFS_HCS 0x%x\n", readl(UFS_HCS(base)));
253 dprintf(CRITICAL,"-----------End--------------------------------\n");
254}