blob: aa5f90b3cfd49567d32238c23e6cf0b308d418fb [file] [log] [blame]
Channagoud Kadabiab887302015-02-20 10:55:58 -08001/* 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 <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>
Sridhar Parasuram3c0b0b82014-09-25 18:06:51 -070037#include <qgic.h>
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070038#include <string.h>
39#include <platform/iomap.h>
Sridhar Parasuram3c0b0b82014-09-25 18:06:51 -070040#include <platform/irqs.h>
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070041#include <kernel/mutex.h>
42
43static int ufs_dev_init(struct ufs_dev *dev)
44{
45 /* Init the mutexes. */
46 mutex_init(&(dev->uic_data.uic_mutex));
47 mutex_init(&(dev->utrd_data.bitmap_mutex));
48 mutex_init(&(dev->utmrd_data.bitmap_mutex));
49
50 /* Initialize wait lists. */
51 list_initialize(&(dev->utrd_data.list_head.list_node));
52 list_initialize(&(dev->utmrd_data.list_head.list_node));
53
54 /* Initialize the bitmaps. */
55 dev->utrd_data.bitmap = 0;
56 dev->utmrd_data.bitmap = 0;
57
58 /* Initialize task ids. */
59 dev->utrd_data.task_id = 0;
60 dev->utmrd_data.task_id = 0;
61
62 /* Allocate memory for lists. */
63 dev->utrd_data.list_base_addr = ufs_alloc_trans_req_list();
64 dev->utmrd_data.list_base_addr = ufs_alloc_task_mgmt_req_list();
65
66 if (!dev->utrd_data.list_base_addr || !dev->utmrd_data.list_base_addr)
67 return -UFS_FAILURE;
68
69 return UFS_SUCCESS;
70}
71
72static void ufs_setup_req_lists(struct ufs_dev *dev)
73{
74 uint32_t val;
75
76 writel(dev->utmrd_data.list_base_addr, UFS_UTMRLBA(dev->base));
77 writel(dev->utmrd_data.list_base_addr << 32, UFS_UTMRLBAU(dev->base));
78
79 writel(dev->utrd_data.list_base_addr, UFS_UTRLBA(dev->base));
80 writel(dev->utrd_data.list_base_addr << 32, UFS_UTRLBAU(dev->base));
81
82 writel(1, UFS_UTMRLRSR(dev->base));
83 writel(1, UFS_UTRLRSR(dev->base));
84
85 /* Enable the required irqs. */
Sridhar Parasuram7357e9b2014-10-01 12:19:11 -070086 val = UFS_IE_UEE | UFS_IE_UCCE ;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070087 ufs_irq_enable(dev, val);
Sridhar Parasuram3c0b0b82014-09-25 18:06:51 -070088 // Change UFS_IRQ to level based
89 qgic_change_interrupt_cfg(UFS_IRQ, INTERRUPT_LVL_N_TO_N);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070090}
91
Sridhar Parasuramb66c9c32014-10-27 09:36:01 -070092static void ufs_rpmb_init(struct ufs_dev *dev)
93{
94 int ret = 0;
95
96 // calculate the size of rpmb partition in sectors
97 ret = dme_read_unit_desc(dev, UFS_WLUN_RPMB);
98 if (ret != UFS_SUCCESS)
99 {
100 dprintf(CRITICAL, "UFS dme_read_unit_desc failed for RPMB Partition\n");
101 return;
102 }
103
104 // gets the number of rpmb frames allowed in a single UPIU commands
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800105 ret = dme_read_geo_desc(dev);
Sridhar Parasuramb66c9c32014-10-27 09:36:01 -0700106 if (ret != UFS_SUCCESS)
107 {
108 dprintf(CRITICAL, "UFS dme_read_geo_desc failed for RPMB Partition\n");
109 return;
110 }
111#ifdef DEBUG_UFS
112 dprintf(INFO, "RPMB: Logical Block Count: 0x%x\n", dev->rpmb_num_blocks);
113 dprintf(INFO, "RPMB: RPMB Read Write Size: 0x%x\n", dev->rpmb_rw_size);
114#endif
115}
116
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700117int ufs_read(struct ufs_dev* dev, uint64_t start_lba, addr_t buffer, uint32_t num_blocks)
118{
119 struct scsi_rdwr_req req;
120 int ret;
121
122 req.data_buffer_base = buffer;
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800123 req.lun = dev->current_lun;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700124 req.num_blocks = num_blocks;
125 req.start_lba = start_lba / dev->block_size;
126
127 ret = ucs_do_scsi_read(dev, &req);
128 if (ret)
129 {
130 dprintf(CRITICAL, "UFS read failed.\n");
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700131 ufs_dump_hc_registers(dev);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700132 }
133
134 return ret;
135}
136
137int ufs_write(struct ufs_dev* dev, uint64_t start_lba, addr_t buffer, uint32_t num_blocks)
138{
139 struct scsi_rdwr_req req;
140 int ret;
141
142 req.data_buffer_base = buffer;
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800143 req.lun = dev->current_lun;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700144 req.num_blocks = num_blocks;
145 req.start_lba = start_lba / dev->block_size;
146
147 ret = ucs_do_scsi_write(dev, &req);
148 if (ret)
149 {
150 dprintf(CRITICAL, "UFS write failed.\n");
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700151 ufs_dump_hc_registers(dev);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700152 }
153
154 return ret;
155}
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700156
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700157int ufs_erase(struct ufs_dev* dev, uint64_t start_lba, uint32_t num_blocks)
158{
159 struct scsi_unmap_req req;
160 int ret;
161
162 req.lun = dev->current_lun;
163 req.start_lba = start_lba / dev->block_size;
164 req.num_blocks = num_blocks;
165
166 ret = ucs_do_scsi_unmap(dev, &req);
167 if(ret)
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700168 {
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700169 dprintf(CRITICAL, "UFS erase failed \n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700170 }
Channagoud Kadabiab887302015-02-20 10:55:58 -0800171
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700172 return ret;
173}
174
175uint64_t ufs_get_dev_capacity(struct ufs_dev* dev)
176{
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800177 uint64_t capacity;
178 uint8_t lun = dev->current_lun;
179
180 capacity = dev->lun_cfg[lun].logical_blk_cnt * dev->block_size;
181
182 return capacity;
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700183}
184
185uint32_t ufs_get_erase_blk_size(struct ufs_dev* dev)
186{
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800187 uint32_t erase_blk_size;
188 uint8_t lun = dev->current_lun;
189
190 erase_blk_size = dev->lun_cfg[lun].erase_blk_size;
191
192 return erase_blk_size;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700193}
194
195uint32_t ufs_get_serial_num(struct ufs_dev* dev)
196{
197 int ret;
198
199 ret = dme_read_device_desc(dev);
200 if (ret)
201 {
202 dprintf(CRITICAL, "UFS get serial number failed.\n");
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700203 ufs_dump_hc_registers(dev);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700204 }
205
206 return dev->serial_num;
207}
208
209uint32_t ufs_get_page_size(struct ufs_dev* dev)
210{
211 return dev->block_size;
212}
213
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800214uint8_t ufs_get_num_of_luns(struct ufs_dev* dev)
215{
216 return dev->num_lus;
217}
218
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700219int ufs_init(struct ufs_dev *dev)
220{
221 uint32_t ret = UFS_SUCCESS;
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800222 uint8_t lun = 0;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700223
224 dev->block_size = 4096;
225
226 /* Init dev struct. */
227 ret = ufs_dev_init(dev);
228 if (ret != UFS_SUCCESS)
229 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700230 dprintf(CRITICAL, "UFS dev_init failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700231 goto ufs_init_err;
232 }
233
234 /* Perform Data link init. */
235 ret = uic_init(dev);
236 if (ret != UFS_SUCCESS)
237 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700238 dprintf(CRITICAL, "UFS uic_init failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700239 goto ufs_init_err;
240 }
241
242 /* Setup request lists. */
243 ufs_setup_req_lists(dev);
244
245 /* Send NOP to check if device UTP layer is ready. */
246 ret = dme_send_nop_query(dev);
247 if (ret != UFS_SUCCESS)
248 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700249 dprintf(CRITICAL, "UFS dme_send_nop_query failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700250 goto ufs_init_err;
251 }
252
253 ret = dme_set_fdeviceinit(dev);
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700254 if (ret != UFS_SUCCESS)
255 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700256 dprintf(CRITICAL, "UFS dme_set_fdeviceinit failed\n");
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700257 goto ufs_init_err;
258 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700259
260 ret = ucs_scsi_send_inquiry(dev);
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700261 if (ret != UFS_SUCCESS)
262 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700263 dprintf(CRITICAL, "UFS ucs_scsi_send_inquiry failed\n");
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700264 goto ufs_init_err;
265 }
266
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800267 ret = dme_read_device_desc(dev);
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700268 if (ret != UFS_SUCCESS)
269 {
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800270 dprintf(CRITICAL, "dme_read_dev_desc read failed\n");
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700271 goto ufs_init_err;
272 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700273
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800274
275 for(lun=0; lun < dev->num_lus; lun++)
276 {
277 ret = dme_read_unit_desc(dev, lun);
278 if (ret != UFS_SUCCESS)
279 {
280 dprintf(CRITICAL, "UFS dme_read_unit_desc failed\n");
281 goto ufs_init_err;
282 }
283 }
284
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700285 dprintf(CRITICAL,"UFS init success\n");
286
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700287ufs_init_err:
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700288
289 if(ret != UFS_SUCCESS)
290 {
291 ufs_dump_hc_registers(dev);
292 }
293
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700294 return ret;
295}
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700296
Sridhar Parasuram9ab24812014-10-01 10:51:23 -0700297void ufs_dump_is_register(struct ufs_dev *dev)
298{
299 uint32_t base = dev->base;
300 dprintf(CRITICAL,"UFS_IS 0x%x\n",readl(UFS_IS(base)));
301}
302
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700303void ufs_dump_hc_registers(struct ufs_dev *dev)
304{
305 uint32_t base = dev->base;
306
307 dprintf(CRITICAL,"------Host controller register dump ---------\n");
308 dprintf(CRITICAL,"UFS_UECPA 0x%x\n",readl(UFS_UECPA(base)));
309 dprintf(CRITICAL,"UFS_UECDL 0x%x\n",readl(UFS_UECDL(base)));
310 dprintf(CRITICAL,"UFS_UECN 0x%x\n", readl(UFS_UECN(base)));
311 dprintf(CRITICAL,"UFS_UECT 0x%x\n",readl(UFS_UECT(base)));
312 dprintf(CRITICAL,"UFS_UECDME 0x%x\n",readl(UFS_UECDME(base)));
313 dprintf(CRITICAL,"UFS_HCS 0x%x\n", readl(UFS_HCS(base)));
314 dprintf(CRITICAL,"-----------End--------------------------------\n");
315}