xref: /freebsd/sys/dev/ufshci/ufshci_dev.c (revision c09daa33d6ffbbd1956bfe4dcd9ca746192d6940)
1 /*-
2  * Copyright (c) 2025, Samsung Electronics Co., Ltd.
3  * Written by Jaeyoon Choi
4  *
5  * SPDX-License-Identifier: BSD-2-Clause
6  */
7 
8 #include <sys/param.h>
9 #include <sys/bus.h>
10 #include <sys/conf.h>
11 
12 #include "ufshci_private.h"
13 #include "ufshci_reg.h"
14 
15 static int
ufshci_dev_send_query(struct ufshci_controller * ctrlr,struct ufshci_query_param param,struct ufshci_completion_poll_status * status,const char * fail_msg)16 ufshci_dev_send_query(struct ufshci_controller *ctrlr,
17     struct ufshci_query_param param,
18     struct ufshci_completion_poll_status *status, const char *fail_msg)
19 {
20 	int error;
21 
22 	status->done = 0;
23 	error = ufshci_ctrlr_cmd_send_query_request(ctrlr,
24 	    ufshci_completion_poll_cb, status, param);
25 	if (error)
26 		return (error);
27 
28 	ufshci_completion_poll(status);
29 	if (status->error) {
30 		ufshci_printf(ctrlr, "%s failed!\n", fail_msg);
31 		return (ENXIO);
32 	}
33 
34 	return (0);
35 }
36 
37 static int
ufshci_dev_read_descriptor(struct ufshci_controller * ctrlr,enum ufshci_descriptor_type desc_type,uint8_t index,uint8_t selector,void * desc,size_t desc_size)38 ufshci_dev_read_descriptor(struct ufshci_controller *ctrlr,
39     enum ufshci_descriptor_type desc_type, uint8_t index, uint8_t selector,
40     void *desc, size_t desc_size)
41 {
42 	struct ufshci_completion_poll_status status;
43 	struct ufshci_query_param param;
44 	int error;
45 
46 	param.function = UFSHCI_QUERY_FUNC_STANDARD_READ_REQUEST;
47 	param.opcode = UFSHCI_QUERY_OPCODE_READ_DESCRIPTOR;
48 	param.type = desc_type;
49 	param.index = index;
50 	param.selector = selector;
51 	param.value = 0;
52 	param.desc_size = desc_size;
53 
54 	error = ufshci_dev_send_query(ctrlr, param, &status, __func__);
55 	if (error)
56 		return (error);
57 
58 	memcpy(desc, status.cpl.response_upiu.query_response_upiu.command_data,
59 	    desc_size);
60 
61 	return (0);
62 }
63 
64 static int
ufshci_dev_read_device_descriptor(struct ufshci_controller * ctrlr,struct ufshci_device_descriptor * desc)65 ufshci_dev_read_device_descriptor(struct ufshci_controller *ctrlr,
66     struct ufshci_device_descriptor *desc)
67 {
68 	return (ufshci_dev_read_descriptor(ctrlr, UFSHCI_DESC_TYPE_DEVICE, 0, 0,
69 	    desc, sizeof(struct ufshci_device_descriptor)));
70 }
71 
72 static int
ufshci_dev_read_geometry_descriptor(struct ufshci_controller * ctrlr,struct ufshci_geometry_descriptor * desc)73 ufshci_dev_read_geometry_descriptor(struct ufshci_controller *ctrlr,
74     struct ufshci_geometry_descriptor *desc)
75 {
76 	return (ufshci_dev_read_descriptor(ctrlr, UFSHCI_DESC_TYPE_GEOMETRY, 0,
77 	    0, desc, sizeof(struct ufshci_geometry_descriptor)));
78 }
79 
80 static int
ufshci_dev_read_unit_descriptor(struct ufshci_controller * ctrlr,uint8_t lun,struct ufshci_unit_descriptor * desc)81 ufshci_dev_read_unit_descriptor(struct ufshci_controller *ctrlr, uint8_t lun,
82     struct ufshci_unit_descriptor *desc)
83 {
84 	return (ufshci_dev_read_descriptor(ctrlr, UFSHCI_DESC_TYPE_UNIT, lun, 0,
85 	    desc, sizeof(struct ufshci_unit_descriptor)));
86 }
87 
88 static int
ufshci_dev_read_flag(struct ufshci_controller * ctrlr,enum ufshci_flags flag_type,uint8_t * flag)89 ufshci_dev_read_flag(struct ufshci_controller *ctrlr,
90     enum ufshci_flags flag_type, uint8_t *flag)
91 {
92 	struct ufshci_completion_poll_status status;
93 	struct ufshci_query_param param;
94 	int error;
95 
96 	param.function = UFSHCI_QUERY_FUNC_STANDARD_READ_REQUEST;
97 	param.opcode = UFSHCI_QUERY_OPCODE_READ_FLAG;
98 	param.type = flag_type;
99 	param.index = 0;
100 	param.selector = 0;
101 	param.value = 0;
102 	param.desc_size = 0;
103 
104 	error = ufshci_dev_send_query(ctrlr, param, &status, __func__);
105 	if (error)
106 		return (error);
107 
108 	*flag = status.cpl.response_upiu.query_response_upiu.flag_value;
109 
110 	return (0);
111 }
112 
113 static int
ufshci_dev_set_flag(struct ufshci_controller * ctrlr,enum ufshci_flags flag_type)114 ufshci_dev_set_flag(struct ufshci_controller *ctrlr,
115     enum ufshci_flags flag_type)
116 {
117 	struct ufshci_completion_poll_status status;
118 	struct ufshci_query_param param;
119 
120 	param.function = UFSHCI_QUERY_FUNC_STANDARD_WRITE_REQUEST;
121 	param.opcode = UFSHCI_QUERY_OPCODE_SET_FLAG;
122 	param.type = flag_type;
123 	param.index = 0;
124 	param.selector = 0;
125 	param.value = 0;
126 	param.desc_size = 0;
127 
128 	return (ufshci_dev_send_query(ctrlr, param, &status, __func__));
129 }
130 
131 static int
ufshci_dev_clear_flag(struct ufshci_controller * ctrlr,enum ufshci_flags flag_type)132 ufshci_dev_clear_flag(struct ufshci_controller *ctrlr,
133     enum ufshci_flags flag_type)
134 {
135 	struct ufshci_completion_poll_status status;
136 	struct ufshci_query_param param;
137 
138 	param.function = UFSHCI_QUERY_FUNC_STANDARD_WRITE_REQUEST;
139 	param.opcode = UFSHCI_QUERY_OPCODE_CLEAR_FLAG;
140 	param.type = flag_type;
141 	param.index = 0;
142 	param.selector = 0;
143 	param.value = 0;
144 	param.desc_size = 0;
145 
146 	return (ufshci_dev_send_query(ctrlr, param, &status, __func__));
147 }
148 
149 static int
ufshci_dev_read_attribute(struct ufshci_controller * ctrlr,enum ufshci_attributes attr_type,uint8_t index,uint8_t selector,uint64_t * value)150 ufshci_dev_read_attribute(struct ufshci_controller *ctrlr,
151     enum ufshci_attributes attr_type, uint8_t index, uint8_t selector,
152     uint64_t *value)
153 {
154 	struct ufshci_completion_poll_status status;
155 	struct ufshci_query_param param;
156 	int error;
157 
158 	param.function = UFSHCI_QUERY_FUNC_STANDARD_READ_REQUEST;
159 	param.opcode = UFSHCI_QUERY_OPCODE_READ_ATTRIBUTE;
160 	param.type = attr_type;
161 	param.index = index;
162 	param.selector = selector;
163 	param.value = 0;
164 	param.desc_size = 0;
165 
166 	error = ufshci_dev_send_query(ctrlr, param, &status, __func__);
167 	if (error)
168 		return (error);
169 
170 	*value = be64toh(status.cpl.response_upiu.query_response_upiu.value_64);
171 
172 	return (0);
173 }
174 
175 static int
ufshci_dev_write_attribute(struct ufshci_controller * ctrlr,enum ufshci_attributes attr_type,uint8_t index,uint8_t selector,uint64_t value)176 ufshci_dev_write_attribute(struct ufshci_controller *ctrlr,
177     enum ufshci_attributes attr_type, uint8_t index, uint8_t selector,
178     uint64_t value)
179 {
180 	struct ufshci_completion_poll_status status;
181 	struct ufshci_query_param param;
182 
183 	param.function = UFSHCI_QUERY_FUNC_STANDARD_WRITE_REQUEST;
184 	param.opcode = UFSHCI_QUERY_OPCODE_WRITE_ATTRIBUTE;
185 	param.type = attr_type;
186 	param.index = index;
187 	param.selector = selector;
188 	param.value = value;
189 	param.desc_size = 0;
190 
191 	return (ufshci_dev_send_query(ctrlr, param, &status, __func__));
192 }
193 
194 int
ufshci_dev_init(struct ufshci_controller * ctrlr)195 ufshci_dev_init(struct ufshci_controller *ctrlr)
196 {
197 	int timeout = ticks + MSEC_2_TICKS(ctrlr->device_init_timeout_in_ms);
198 	sbintime_t delta_t = SBT_1US;
199 	uint8_t flag;
200 	int error;
201 	const uint8_t device_init_completed = 0;
202 
203 	error = ufshci_dev_set_flag(ctrlr, UFSHCI_FLAG_F_DEVICE_INIT);
204 	if (error)
205 		return (error);
206 
207 	/* Wait for the UFSHCI_FLAG_F_DEVICE_INIT flag to change */
208 	while (1) {
209 		error = ufshci_dev_read_flag(ctrlr, UFSHCI_FLAG_F_DEVICE_INIT,
210 		    &flag);
211 		if (error)
212 			return (error);
213 		if (flag == device_init_completed)
214 			break;
215 		if (timeout - ticks < 0) {
216 			ufshci_printf(ctrlr,
217 			    "device init did not become %d "
218 			    "within %d ms\n",
219 			    device_init_completed,
220 			    ctrlr->device_init_timeout_in_ms);
221 			return (ENXIO);
222 		}
223 
224 		pause_sbt("ufshciinit", delta_t, 0, C_PREL(1));
225 		delta_t = min(SBT_1MS, delta_t * 3 / 2);
226 	}
227 
228 	return (0);
229 }
230 
231 int
ufshci_dev_reset(struct ufshci_controller * ctrlr)232 ufshci_dev_reset(struct ufshci_controller *ctrlr)
233 {
234 	if (ufshci_uic_send_dme_endpoint_reset(ctrlr))
235 		return (ENXIO);
236 
237 	return (ufshci_dev_init(ctrlr));
238 }
239 
240 int
ufshci_dev_init_reference_clock(struct ufshci_controller * ctrlr)241 ufshci_dev_init_reference_clock(struct ufshci_controller *ctrlr)
242 {
243 	int error;
244 	uint8_t index, selector;
245 	uint64_t value;
246 
247 	index = 0;    /* bRefClkFreq is device type attribute */
248 	selector = 0; /* bRefClkFreq is device type attribute */
249 
250 	/*
251 	 * bRefClkFreq is a persistent attribute. Skip the write when
252 	 * the device already holds the wanted value.
253 	 */
254 	error = ufshci_dev_read_attribute(ctrlr, UFSHCI_ATTR_B_REF_CLK_FREQ,
255 	    index, selector, &value);
256 	if (error != 0) {
257 		ufshci_printf(ctrlr, "bRefClkFreq read failed, writing %u\n",
258 		    ctrlr->ref_clk);
259 	} else if ((uint32_t)value == ctrlr->ref_clk) {
260 		return (0);
261 	} else {
262 		ufshci_printf(ctrlr, "changing bRefClkFreq from %u to %u\n",
263 		    (uint32_t)value, ctrlr->ref_clk);
264 	}
265 
266 	error = ufshci_dev_write_attribute(ctrlr, UFSHCI_ATTR_B_REF_CLK_FREQ,
267 	    index, selector, ctrlr->ref_clk);
268 	if (error)
269 		return (error);
270 
271 	return (0);
272 }
273 
274 int
ufshci_dev_init_unipro(struct ufshci_controller * ctrlr)275 ufshci_dev_init_unipro(struct ufshci_controller *ctrlr)
276 {
277 	uint32_t pa_granularity, peer_pa_granularity;
278 	uint32_t t_activate, pear_t_activate;
279 
280 	if (ctrlr->quirks & UFSHCI_QUIRK_LONG_PEER_PA_TACTIVATE) {
281 		/*
282 		 * PA_Granularity: Granularity for PA_TActivate and
283 		 * PA_Hibern8Time
284 		 * - 1=1us, 2=4us, 3=8us, 4=16us, 5=32us, 6=100us
285 		 */
286 		if (ufshci_uic_send_dme_get(ctrlr, PA_Granularity,
287 			&pa_granularity))
288 			return (ENXIO);
289 		if (ufshci_uic_send_dme_peer_get(ctrlr, PA_Granularity,
290 			&peer_pa_granularity))
291 			return (ENXIO);
292 
293 		/*
294 		 * PA_TActivate: Time to wait before activating a burst in order
295 		 * to wake-up peer M-RX UniPro automatically sets timing
296 		 * information such as PA_TActivate through the
297 		 * PACP_CAP_EXT1_ind command during Link Startup operation.
298 		 */
299 		if (ufshci_uic_send_dme_get(ctrlr, PA_TActivate, &t_activate))
300 			return (ENXIO);
301 		if (ufshci_uic_send_dme_peer_get(ctrlr, PA_TActivate,
302 			&pear_t_activate))
303 			return (ENXIO);
304 
305 		/*
306 		 * Intel Lake-field UFSHCI has a quirk. We need to add 200us to
307 		 * the PEER's PA_TActivate.
308 		 */
309 		if (pa_granularity == peer_pa_granularity) {
310 			pear_t_activate = t_activate + 2;
311 			if (ufshci_uic_send_dme_peer_set(ctrlr, PA_TActivate,
312 				pear_t_activate))
313 				return (ENXIO);
314 		}
315 	}
316 
317 	return (0);
318 }
319 
320 int
ufshci_dev_init_uic_power_mode(struct ufshci_controller * ctrlr)321 ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr)
322 {
323 	/*
324 	 * TX/RX PWRMode:
325 	 * - TX[3:0], RX[7:4]
326 	 * - Fast Mode = 1, Slow Mode = 2, FastAuto Mode = 4, SlowAuto Mode = 5
327 	 */
328 	const uint32_t fast_mode = 1;
329 	const uint32_t rx_bit_shift = 4;
330 	uint32_t peer_granularity;
331 
332 	/* Update lanes with available TX/RX lanes */
333 	if (ufshci_uic_send_dme_get(ctrlr, PA_AvailTxDataLanes,
334 		&ctrlr->max_tx_lanes))
335 		return (ENXIO);
336 	if (ufshci_uic_send_dme_get(ctrlr, PA_AvailRxDataLanes,
337 		&ctrlr->max_rx_lanes))
338 		return (ENXIO);
339 
340 	/* Get max HS-GEAR value */
341 	if (ufshci_uic_send_dme_get(ctrlr, PA_MaxRxHSGear,
342 		&ctrlr->max_rx_hs_gear))
343 		return (ENXIO);
344 
345 	/* Set the data lane to max */
346 	ctrlr->tx_lanes = ctrlr->max_tx_lanes;
347 	ctrlr->rx_lanes = ctrlr->max_rx_lanes;
348 	if (ufshci_uic_send_dme_set(ctrlr, PA_ActiveTxDataLanes,
349 		ctrlr->tx_lanes))
350 		return (ENXIO);
351 	if (ufshci_uic_send_dme_set(ctrlr, PA_ActiveRxDataLanes,
352 		ctrlr->rx_lanes))
353 		return (ENXIO);
354 
355 	if (ctrlr->quirks & UFSHCI_QUIRK_CHANGE_LANE_AND_GEAR_SEPARATELY) {
356 		/* Before changing gears, first change the number of lanes. */
357 		if (ufshci_uic_send_dme_get(ctrlr, PA_PWRMode,
358 			&ctrlr->tx_rx_power_mode))
359 			return (ENXIO);
360 		if (ufshci_uic_send_dme_set(ctrlr, PA_PWRMode,
361 			ctrlr->tx_rx_power_mode))
362 			return (ENXIO);
363 
364 		/* Wait for power mode changed. */
365 		if (ufshci_uic_power_mode_ready(ctrlr)) {
366 			ufshci_reg_dump(ctrlr);
367 			return (ENXIO);
368 		}
369 	}
370 
371 	/* Set HS-GEAR to max gear */
372 	ctrlr->hs_gear = ctrlr->max_rx_hs_gear;
373 	if (ufshci_uic_send_dme_set(ctrlr, PA_TxGear, ctrlr->hs_gear))
374 		return (ENXIO);
375 	if (ufshci_uic_send_dme_set(ctrlr, PA_RxGear, ctrlr->hs_gear))
376 		return (ENXIO);
377 
378 	/*
379 	 * Set termination
380 	 * - HS-MODE = ON / LS-MODE = OFF
381 	 */
382 	if (ufshci_uic_send_dme_set(ctrlr, PA_TxTermination, true))
383 		return (ENXIO);
384 	if (ufshci_uic_send_dme_set(ctrlr, PA_RxTermination, true))
385 		return (ENXIO);
386 
387 	/* Set HSSeries */
388 	if (ufshci_uic_send_dme_set(ctrlr, PA_HSSeries, ctrlr->hs_series))
389 		return (ENXIO);
390 
391 	/* HS-G4 and above need initial adaptation. */
392 	if (ctrlr->hs_gear >= 4 &&
393 	    ufshci_uic_send_dme_set(ctrlr, PA_TxHsAdaptType, PA_INITIAL_ADAPT))
394 		return (ENXIO);
395 
396 	/* Set Timeout values */
397 	if (ufshci_uic_send_dme_set(ctrlr, PA_PWRModeUserData0,
398 		DL_FC0ProtectionTimeOutVal_Default))
399 		return (ENXIO);
400 	if (ufshci_uic_send_dme_set(ctrlr, PA_PWRModeUserData1,
401 		DL_TC0ReplayTimeOutVal_Default))
402 		return (ENXIO);
403 	if (ufshci_uic_send_dme_set(ctrlr, PA_PWRModeUserData2,
404 		DL_AFC0ReqTimeOutVal_Default))
405 		return (ENXIO);
406 	if (ufshci_uic_send_dme_set(ctrlr, PA_PWRModeUserData3,
407 		DL_FC0ProtectionTimeOutVal_Default))
408 		return (ENXIO);
409 	if (ufshci_uic_send_dme_set(ctrlr, PA_PWRModeUserData4,
410 		DL_TC0ReplayTimeOutVal_Default))
411 		return (ENXIO);
412 	if (ufshci_uic_send_dme_set(ctrlr, PA_PWRModeUserData5,
413 		DL_AFC0ReqTimeOutVal_Default))
414 		return (ENXIO);
415 
416 	if (ufshci_uic_send_dme_set(ctrlr, DME_LocalFC0ProtectionTimeOutVal,
417 		DL_FC0ProtectionTimeOutVal_Default))
418 		return (ENXIO);
419 	if (ufshci_uic_send_dme_set(ctrlr, DME_LocalTC0ReplayTimeOutVal,
420 		DL_TC0ReplayTimeOutVal_Default))
421 		return (ENXIO);
422 	if (ufshci_uic_send_dme_set(ctrlr, DME_LocalAFC0ReqTimeOutVal,
423 		DL_AFC0ReqTimeOutVal_Default))
424 		return (ENXIO);
425 
426 	/* Set TX/RX PWRMode */
427 	ctrlr->tx_rx_power_mode = (fast_mode << rx_bit_shift) | fast_mode;
428 	if (ufshci_uic_send_dme_set(ctrlr, PA_PWRMode, ctrlr->tx_rx_power_mode))
429 		return (ENXIO);
430 
431 	/* Wait for power mode changed. */
432 	if (ufshci_uic_power_mode_ready(ctrlr)) {
433 		ufshci_reg_dump(ctrlr);
434 		return (ENXIO);
435 	}
436 
437 	if (ctrlr->quirks & UFSHCI_QUIRK_WAIT_AFTER_POWER_MODE_CHANGE) {
438 		/*
439 		 * Intel Lake-field UFSHCI has a quirk.
440 		 * We need to wait 1250us and clear dme error.
441 		 */
442 		pause_sbt("ufshci", ustosbt(1250), 0, C_PREL(1));
443 
444 		/* Test with dme_peer_get to make sure there are no errors. */
445 		if (ufshci_uic_send_dme_peer_get(ctrlr, PA_Granularity,
446 			&peer_granularity))
447 			return (ENXIO);
448 	}
449 
450 	return (0);
451 }
452 
453 void
ufshci_dev_enable_auto_hibernate(struct ufshci_controller * ctrlr)454 ufshci_dev_enable_auto_hibernate(struct ufshci_controller *ctrlr)
455 {
456 	if (!ctrlr->ufs_dev.auto_hibernation_supported)
457 		return;
458 
459 	ufshci_mmio_write_4(ctrlr, ahit, ctrlr->ufs_dev.ahit);
460 }
461 
462 void
ufshci_dev_init_auto_hibernate(struct ufshci_controller * ctrlr)463 ufshci_dev_init_auto_hibernate(struct ufshci_controller *ctrlr)
464 {
465 	ctrlr->ufs_dev.auto_hibernation_supported =
466 	    UFSHCIV(UFSHCI_CAP_REG_AUTOH8, ctrlr->cap) &&
467 	    !(ctrlr->quirks & UFSHCI_QUIRK_BROKEN_AUTO_HIBERNATE);
468 
469 	if (!ctrlr->ufs_dev.auto_hibernation_supported)
470 		return;
471 
472 	/* The default value for auto hibernation is 150 ms */
473 	ctrlr->ufs_dev.ahit = 0;
474 	ctrlr->ufs_dev.ahit |= UFSHCIF(UFSHCI_AHIT_REG_AH8ITV, 150);
475 	ctrlr->ufs_dev.ahit |= UFSHCIF(UFSHCI_AHIT_REG_TS, 3);
476 
477 	ufshci_dev_enable_auto_hibernate(ctrlr);
478 }
479 
480 void
ufshci_dev_init_uic_link_state(struct ufshci_controller * ctrlr)481 ufshci_dev_init_uic_link_state(struct ufshci_controller *ctrlr)
482 {
483 	ctrlr->ufs_dev.link_state = UFSHCI_UIC_LINK_STATE_ACTIVE;
484 }
485 
486 int
ufshci_dev_init_ufs_power_mode(struct ufshci_controller * ctrlr)487 ufshci_dev_init_ufs_power_mode(struct ufshci_controller *ctrlr)
488 {
489 	ctrlr->ufs_dev.power_mode_supported = false;
490 
491 	if (ctrlr->quirks & UFSHCI_QUIRK_SKIP_WELL_KNOWN_LUNS)
492 		return (0);
493 
494 	if (ctrlr->ufs_device_wlun_periph == NULL) {
495 		/* The returned reference is kept by the cached pointer. */
496 		ctrlr->ufs_device_wlun_periph = ufshci_sim_find_periph(ctrlr,
497 		    UFSHCI_WLUN_UFS_DEVICE);
498 		if (ctrlr->ufs_device_wlun_periph == NULL) {
499 			ufshci_printf(ctrlr,
500 			    "Well-known LUN `UFS Device (0x50)` not found\n");
501 			return (0);
502 		}
503 	}
504 
505 	ctrlr->ufs_dev.power_mode_supported = true;
506 	ctrlr->ufs_dev.power_mode = UFSHCI_DEV_PWR_ACTIVE;
507 
508 	return (0);
509 }
510 
511 int
ufshci_dev_get_descriptor(struct ufshci_controller * ctrlr)512 ufshci_dev_get_descriptor(struct ufshci_controller *ctrlr)
513 {
514 	struct ufshci_device *device = &ctrlr->ufs_dev;
515 	/*
516 	 * The kDeviceDensityUnit is defined in the spec as 512.
517 	 * qTotalRawDeviceCapacity use big-endian byte ordering.
518 	 */
519 	const uint32_t device_density_unit = 512;
520 	uint32_t ver;
521 	int error;
522 
523 	error = ufshci_dev_read_device_descriptor(ctrlr, &device->dev_desc);
524 	if (error)
525 		return (error);
526 
527 	ver = be16toh(device->dev_desc.wSpecVersion);
528 	ufshci_printf(ctrlr, "UFS device spec version %u.%u.%u\n",
529 	    UFSHCIV(UFSHCI_VER_REG_MJR, ver), UFSHCIV(UFSHCI_VER_REG_MNR, ver),
530 	    UFSHCIV(UFSHCI_VER_REG_VS, ver));
531 	ufshci_printf(ctrlr, "%u enabled LUNs found\n",
532 	    device->dev_desc.bNumberLU);
533 
534 	error = ufshci_dev_read_geometry_descriptor(ctrlr, &device->geo_desc);
535 	if (error)
536 		return (error);
537 
538 	if (device->geo_desc.bMaxNumberLU == 0) {
539 		device->max_lun_count = 8;
540 	} else if (device->geo_desc.bMaxNumberLU == 1) {
541 		device->max_lun_count = 32;
542 	} else {
543 		ufshci_printf(ctrlr,
544 		    "Invalid Geometry Descriptor bMaxNumberLU value=%d\n",
545 		    device->geo_desc.bMaxNumberLU);
546 		return (ENXIO);
547 	}
548 	ctrlr->max_lun_count = device->max_lun_count;
549 
550 	ufshci_printf(ctrlr, "UFS device total size is %lu bytes\n",
551 	    be64toh(device->geo_desc.qTotalRawDeviceCapacity) *
552 		device_density_unit);
553 
554 	return (0);
555 }
556 
557 static int
ufshci_dev_enable_write_booster(struct ufshci_controller * ctrlr)558 ufshci_dev_enable_write_booster(struct ufshci_controller *ctrlr)
559 {
560 	struct ufshci_device *dev = &ctrlr->ufs_dev;
561 	int error;
562 
563 	/* Enable WriteBooster */
564 	error = ufshci_dev_set_flag(ctrlr, UFSHCI_FLAG_F_WRITE_BOOSTER_EN);
565 	if (error) {
566 		ufshci_printf(ctrlr, "Failed to enable WriteBooster\n");
567 		return (error);
568 	}
569 	dev->is_wb_enabled = true;
570 
571 	/* Enable WriteBooster buffer flush during hibernate */
572 	error = ufshci_dev_set_flag(ctrlr,
573 	    UFSHCI_FLAG_F_WB_BUFFER_FLUSH_DURING_HIBERNATE);
574 	if (error) {
575 		ufshci_printf(ctrlr,
576 		    "Failed to enable WriteBooster buffer flush during hibernate\n");
577 		return (error);
578 	}
579 
580 	/* Enable WriteBooster buffer flush */
581 	error = ufshci_dev_set_flag(ctrlr, UFSHCI_FLAG_F_WB_BUFFER_FLUSH_EN);
582 	if (error) {
583 		ufshci_printf(ctrlr,
584 		    "Failed to enable WriteBooster buffer flush\n");
585 		return (error);
586 	}
587 	dev->is_wb_flush_enabled = true;
588 
589 	return (0);
590 }
591 
592 static int
ufshci_dev_disable_write_booster(struct ufshci_controller * ctrlr)593 ufshci_dev_disable_write_booster(struct ufshci_controller *ctrlr)
594 {
595 	struct ufshci_device *dev = &ctrlr->ufs_dev;
596 	int error;
597 
598 	/* Disable WriteBooster buffer flush */
599 	error = ufshci_dev_clear_flag(ctrlr, UFSHCI_FLAG_F_WB_BUFFER_FLUSH_EN);
600 	if (error) {
601 		ufshci_printf(ctrlr,
602 		    "Failed to disable WriteBooster buffer flush\n");
603 		return (error);
604 	}
605 	dev->is_wb_flush_enabled = false;
606 
607 	/* Disable WriteBooster buffer flush during hibernate */
608 	error = ufshci_dev_clear_flag(ctrlr,
609 	    UFSHCI_FLAG_F_WB_BUFFER_FLUSH_DURING_HIBERNATE);
610 	if (error) {
611 		ufshci_printf(ctrlr,
612 		    "Failed to disable WriteBooster buffer flush during hibernate\n");
613 		return (error);
614 	}
615 
616 	/* Disable WriteBooster */
617 	error = ufshci_dev_clear_flag(ctrlr, UFSHCI_FLAG_F_WRITE_BOOSTER_EN);
618 	if (error) {
619 		ufshci_printf(ctrlr, "Failed to disable WriteBooster\n");
620 		return (error);
621 	}
622 	dev->is_wb_enabled = false;
623 
624 	return (0);
625 }
626 
627 static int
ufshci_dev_is_write_booster_buffer_life_time_left(struct ufshci_controller * ctrlr,bool * is_life_time_left)628 ufshci_dev_is_write_booster_buffer_life_time_left(
629     struct ufshci_controller *ctrlr, bool *is_life_time_left)
630 {
631 	struct ufshci_device *dev = &ctrlr->ufs_dev;
632 	uint8_t buffer_lun;
633 	uint64_t life_time;
634 	uint32_t error;
635 
636 	if (dev->wb_buffer_type == UFSHCI_DESC_WB_BUF_TYPE_LU_DEDICATED)
637 		buffer_lun = dev->wb_dedicated_lu;
638 	else
639 		buffer_lun = 0;
640 
641 	error = ufshci_dev_read_attribute(ctrlr,
642 	    UFSHCI_ATTR_B_WB_BUFFER_LIFE_TIME_EST, buffer_lun, 0, &life_time);
643 	if (error)
644 		return (error);
645 
646 	*is_life_time_left = (life_time != UFSHCI_ATTR_WB_LIFE_EXCEEDED);
647 
648 	return (0);
649 }
650 
651 /*
652  * This function is not yet in use. It will be used when suspend/resume is
653  * implemented.
654  */
655 static __unused int
ufshci_dev_need_write_booster_buffer_flush(struct ufshci_controller * ctrlr,bool * need_flush)656 ufshci_dev_need_write_booster_buffer_flush(struct ufshci_controller *ctrlr,
657     bool *need_flush)
658 {
659 	struct ufshci_device *dev = &ctrlr->ufs_dev;
660 	bool is_life_time_left = false;
661 	uint64_t available_buffer_size, current_buffer_size;
662 	uint8_t buffer_lun;
663 	uint32_t error;
664 
665 	*need_flush = false;
666 
667 	if (!dev->is_wb_enabled)
668 		return (0);
669 
670 	error = ufshci_dev_is_write_booster_buffer_life_time_left(ctrlr,
671 	    &is_life_time_left);
672 	if (error)
673 		return (error);
674 
675 	if (!is_life_time_left)
676 		return (ufshci_dev_disable_write_booster(ctrlr));
677 
678 	if (dev->wb_buffer_type == UFSHCI_DESC_WB_BUF_TYPE_LU_DEDICATED)
679 		buffer_lun = dev->wb_dedicated_lu;
680 	else
681 		buffer_lun = 0;
682 
683 	error = ufshci_dev_read_attribute(ctrlr,
684 	    UFSHCI_ATTR_B_AVAILABLE_WB_BUFFER_SIZE, buffer_lun, 0,
685 	    &available_buffer_size);
686 	if (error)
687 		return (error);
688 
689 	switch (dev->wb_user_space_config_option) {
690 	case UFSHCI_DESC_WB_BUF_USER_SPACE_REDUCTION:
691 		*need_flush = (available_buffer_size <=
692 		    UFSHCI_ATTR_WB_AVAILABLE_10);
693 		break;
694 	case UFSHCI_DESC_WB_BUF_PRESERVE_USER_SPACE:
695 		/*
696 		 * In PRESERVE USER SPACE mode, flush should be performed when
697 		 * the current buffer is greater than 0 and the available buffer
698 		 * below write_booster_flush_threshold is left.
699 		 */
700 		error = ufshci_dev_read_attribute(ctrlr,
701 		    UFSHCI_ATTR_D_CURRENT_WB_BUFFER_SIZE, buffer_lun, 0,
702 		    &current_buffer_size);
703 		if (error)
704 			return (error);
705 
706 		if (current_buffer_size == 0)
707 			return (0);
708 
709 		*need_flush = (available_buffer_size <
710 		    dev->write_booster_flush_threshold);
711 		break;
712 	default:
713 		ufshci_printf(ctrlr,
714 		    "Invalid bWriteBoosterBufferPreserveUserSpaceEn value");
715 		return (EINVAL);
716 	}
717 
718 	/*
719 	 * TODO: Need to handle WRITEBOOSTER_FLUSH_NEEDED exception case from
720 	 * wExceptionEventStatus attribute.
721 	 */
722 
723 	return (0);
724 }
725 
726 int
ufshci_dev_config_write_booster(struct ufshci_controller * ctrlr)727 ufshci_dev_config_write_booster(struct ufshci_controller *ctrlr)
728 {
729 	struct ufshci_device *dev = &ctrlr->ufs_dev;
730 	uint32_t extended_ufs_feature_support;
731 	uint32_t alloc_units = 0;
732 	struct ufshci_unit_descriptor unit_desc;
733 	uint8_t lun;
734 	bool is_life_time_left;
735 	uint32_t mega_byte = 1024 * 1024;
736 	uint32_t error = 0;
737 
738 	extended_ufs_feature_support = be32toh(
739 	    dev->dev_desc.dExtendedUfsFeaturesSupport);
740 	if (!(extended_ufs_feature_support &
741 		UFSHCI_DESC_EXT_UFS_FEATURE_WRITE_BOOSTER)) {
742 		/* This device does not support Write Booster */
743 		return (0);
744 	}
745 
746 	if (ufshci_dev_enable_write_booster(ctrlr))
747 		return (0);
748 
749 	/* Get WriteBooster buffer parameters */
750 	dev->wb_buffer_type = dev->dev_desc.bWriteBoosterBufferType;
751 	dev->wb_user_space_config_option =
752 	    dev->dev_desc.bWriteBoosterBufferPreserveUserSpaceEn;
753 
754 	/*
755 	 * Find the size of the write buffer.
756 	 * With LU-dedicated (00h), the WriteBooster buffer is assigned
757 	 * exclusively to one chosen LU (not one-per-LU), whereas Shared (01h)
758 	 * uses a single device-wide buffer shared by multiple LUs.
759 	 */
760 	if (dev->wb_buffer_type == UFSHCI_DESC_WB_BUF_TYPE_SINGLE_SHARED) {
761 		alloc_units = be32toh(
762 		    dev->dev_desc.dNumSharedWriteBoosterBufferAllocUnits);
763 		ufshci_printf(ctrlr,
764 		    "WriteBooster buffer type = Shared, alloc_units=%d\n",
765 		    alloc_units);
766 	} else if (dev->wb_buffer_type ==
767 	    UFSHCI_DESC_WB_BUF_TYPE_LU_DEDICATED) {
768 		ufshci_printf(ctrlr, "WriteBooster buffer type = Dedicated\n");
769 		for (lun = 0; lun < ctrlr->max_lun_count; lun++) {
770 			/* Find a dedicated buffer using a unit descriptor */
771 			if (ufshci_dev_read_unit_descriptor(ctrlr, lun,
772 				&unit_desc))
773 				continue;
774 
775 			alloc_units = be32toh(
776 			    unit_desc.dLUNumWriteBoosterBufferAllocUnits);
777 			if (alloc_units) {
778 				dev->wb_dedicated_lu = lun;
779 				break;
780 			}
781 		}
782 	} else {
783 		ufshci_printf(ctrlr,
784 		    "Not supported WriteBooster buffer type: 0x%x\n",
785 		    dev->wb_buffer_type);
786 		goto out;
787 	}
788 
789 	if (alloc_units == 0) {
790 		ufshci_printf(ctrlr, "The WriteBooster buffer size is zero\n");
791 		goto out;
792 	}
793 
794 	dev->wb_buffer_size_mb = alloc_units *
795 	    dev->geo_desc.bAllocationUnitSize *
796 	    (be32toh(dev->geo_desc.dSegmentSize)) /
797 	    (mega_byte / UFSHCI_SECTOR_SIZE);
798 
799 	/* Set to flush when 40% of the available buffer size remains */
800 	dev->write_booster_flush_threshold = UFSHCI_ATTR_WB_AVAILABLE_40;
801 
802 	/*
803 	 * Check if WriteBooster Buffer lifetime is left.
804 	 * WriteBooster Buffer lifetime — percent of life used based on P/E
805 	 * cycles. If "preserve user space" is enabled, writes to normal user
806 	 * space also consume WB life since the area is shared.
807 	 */
808 	error = ufshci_dev_is_write_booster_buffer_life_time_left(ctrlr,
809 	    &is_life_time_left);
810 	if (error)
811 		goto out;
812 
813 	if (!is_life_time_left) {
814 		ufshci_printf(ctrlr,
815 		    "There is no WriteBooster buffer life time left.\n");
816 		goto out;
817 	}
818 
819 	ufshci_printf(ctrlr, "WriteBooster Enabled\n");
820 	return (0);
821 out:
822 	ufshci_dev_disable_write_booster(ctrlr);
823 	return (error);
824 }
825 
826 int
ufshci_dev_get_current_power_mode(struct ufshci_controller * ctrlr,uint8_t * power_mode)827 ufshci_dev_get_current_power_mode(struct ufshci_controller *ctrlr,
828     uint8_t *power_mode)
829 {
830 	uint64_t value;
831 	int err;
832 
833 	err = ufshci_dev_read_attribute(ctrlr, UFSHCI_ATTR_B_CURRENT_POWER_MODE,
834 	    /*index*/ 0, /*selector*/ 0, &value);
835 	if (err)
836 		return (err);
837 
838 	*power_mode = (uint8_t)value;
839 
840 	return (0);
841 }
842 
843 static int
ufshci_dev_hibernate_enter(struct ufshci_controller * ctrlr)844 ufshci_dev_hibernate_enter(struct ufshci_controller *ctrlr)
845 {
846 	int error;
847 
848 	error = ufshci_uic_send_dme_hibernate_enter(ctrlr);
849 	if (error)
850 		return (error);
851 
852 	return (ufshci_uic_hibernation_ready(ctrlr));
853 }
854 
855 static int
ufshci_dev_hibernate_exit(struct ufshci_controller * ctrlr)856 ufshci_dev_hibernate_exit(struct ufshci_controller *ctrlr)
857 {
858 	int error;
859 
860 	error = ufshci_uic_send_dme_hibernate_exit(ctrlr);
861 	if (error)
862 		return (error);
863 
864 	return (ufshci_uic_hibernation_ready(ctrlr));
865 }
866 
867 int
ufshci_dev_link_state_transition(struct ufshci_controller * ctrlr,enum ufshci_uic_link_state target_state)868 ufshci_dev_link_state_transition(struct ufshci_controller *ctrlr,
869     enum ufshci_uic_link_state target_state)
870 {
871 	struct ufshci_device *dev = &ctrlr->ufs_dev;
872 	int error = 0;
873 
874 	if (dev->link_state == target_state)
875 		return (0);
876 
877 	switch (target_state) {
878 	case UFSHCI_UIC_LINK_STATE_OFF:
879 		error = ufshci_dev_hibernate_enter(ctrlr);
880 		if (error)
881 			break;
882 		error = ufshci_ctrlr_disable(ctrlr);
883 		break;
884 	case UFSHCI_UIC_LINK_STATE_ACTIVE:
885 		if (dev->link_state == UFSHCI_UIC_LINK_STATE_HIBERNATE)
886 			error = ufshci_dev_hibernate_exit(ctrlr);
887 		else
888 			error = EINVAL;
889 		break;
890 	case UFSHCI_UIC_LINK_STATE_HIBERNATE:
891 		if (dev->link_state == UFSHCI_UIC_LINK_STATE_ACTIVE)
892 			error = ufshci_dev_hibernate_enter(ctrlr);
893 		else
894 			error = EINVAL;
895 		break;
896 	case UFSHCI_UIC_LINK_STATE_BROKEN:
897 		break;
898 	default:
899 		error = EINVAL;
900 		break;
901 	}
902 
903 	if (error)
904 		return (error);
905 
906 	dev->link_state = target_state;
907 
908 	return (0);
909 }
910