blob: 8244576ac3764c26e1b281437ea321b27a2cd39a [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;
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -080094 req.lun = dev->current_lun;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070095 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;
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800114 req.lun = dev->current_lun;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700115 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{
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800148 uint64_t capacity;
149 uint8_t lun = dev->current_lun;
150
151 capacity = dev->lun_cfg[lun].logical_blk_cnt * dev->block_size;
152
153 return capacity;
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700154}
155
156uint32_t ufs_get_erase_blk_size(struct ufs_dev* dev)
157{
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800158 uint32_t erase_blk_size;
159 uint8_t lun = dev->current_lun;
160
161 erase_blk_size = dev->lun_cfg[lun].erase_blk_size;
162
163 return erase_blk_size;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700164}
165
166uint32_t ufs_get_serial_num(struct ufs_dev* dev)
167{
168 int ret;
169
170 ret = dme_read_device_desc(dev);
171 if (ret)
172 {
173 dprintf(CRITICAL, "UFS get serial number failed.\n");
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700174 ufs_dump_hc_registers(dev);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700175 }
176
177 return dev->serial_num;
178}
179
180uint32_t ufs_get_page_size(struct ufs_dev* dev)
181{
182 return dev->block_size;
183}
184
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800185uint8_t ufs_get_num_of_luns(struct ufs_dev* dev)
186{
187 return dev->num_lus;
188}
189
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700190int ufs_init(struct ufs_dev *dev)
191{
192 uint32_t ret = UFS_SUCCESS;
193 uint64_t cap;
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800194 uint8_t lun = 0;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700195
196 dev->block_size = 4096;
197
198 /* Init dev struct. */
199 ret = ufs_dev_init(dev);
200 if (ret != UFS_SUCCESS)
201 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700202 dprintf(CRITICAL, "UFS dev_init failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700203 goto ufs_init_err;
204 }
205
206 /* Perform Data link init. */
207 ret = uic_init(dev);
208 if (ret != UFS_SUCCESS)
209 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700210 dprintf(CRITICAL, "UFS uic_init failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700211 goto ufs_init_err;
212 }
213
214 /* Setup request lists. */
215 ufs_setup_req_lists(dev);
216
217 /* Send NOP to check if device UTP layer is ready. */
218 ret = dme_send_nop_query(dev);
219 if (ret != UFS_SUCCESS)
220 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700221 dprintf(CRITICAL, "UFS dme_send_nop_query failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700222 goto ufs_init_err;
223 }
224
225 ret = dme_set_fdeviceinit(dev);
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700226 if (ret != UFS_SUCCESS)
227 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700228 dprintf(CRITICAL, "UFS dme_set_fdeviceinit failed\n");
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700229 goto ufs_init_err;
230 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700231
232 ret = ucs_scsi_send_inquiry(dev);
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700233 if (ret != UFS_SUCCESS)
234 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700235 dprintf(CRITICAL, "UFS ucs_scsi_send_inquiry failed\n");
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700236 goto ufs_init_err;
237 }
238
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800239 ret = dme_read_device_desc(dev);
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700240 if (ret != UFS_SUCCESS)
241 {
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800242 dprintf(CRITICAL, "dme_read_dev_desc read failed\n");
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700243 goto ufs_init_err;
244 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700245
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800246
247 for(lun=0; lun < dev->num_lus; lun++)
248 {
249 ret = dme_read_unit_desc(dev, lun);
250 if (ret != UFS_SUCCESS)
251 {
252 dprintf(CRITICAL, "UFS dme_read_unit_desc failed\n");
253 goto ufs_init_err;
254 }
255 }
256
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700257 dprintf(CRITICAL,"UFS init success\n");
258
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700259ufs_init_err:
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700260
261 if(ret != UFS_SUCCESS)
262 {
263 ufs_dump_hc_registers(dev);
264 }
265
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700266 return ret;
267}
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700268
269void ufs_dump_hc_registers(struct ufs_dev *dev)
270{
271 uint32_t base = dev->base;
272
273 dprintf(CRITICAL,"------Host controller register dump ---------\n");
274 dprintf(CRITICAL,"UFS_UECPA 0x%x\n",readl(UFS_UECPA(base)));
275 dprintf(CRITICAL,"UFS_UECDL 0x%x\n",readl(UFS_UECDL(base)));
276 dprintf(CRITICAL,"UFS_UECN 0x%x\n", readl(UFS_UECN(base)));
277 dprintf(CRITICAL,"UFS_UECT 0x%x\n",readl(UFS_UECT(base)));
278 dprintf(CRITICAL,"UFS_UECDME 0x%x\n",readl(UFS_UECDME(base)));
279 dprintf(CRITICAL,"UFS_HCS 0x%x\n", readl(UFS_HCS(base)));
280 dprintf(CRITICAL,"-----------End--------------------------------\n");
281}