.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
---|
1 | 2 | /* |
---|
2 | 3 | * Universal Flash Storage Host controller driver |
---|
3 | | - * |
---|
4 | | - * This code is based on drivers/scsi/ufs/ufshcd.h |
---|
5 | 4 | * Copyright (C) 2011-2013 Samsung India Software Operations |
---|
6 | 5 | * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. |
---|
7 | 6 | * |
---|
8 | 7 | * Authors: |
---|
9 | 8 | * Santosh Yaraganavi <santosh.sy@samsung.com> |
---|
10 | 9 | * Vinayak Holikatti <h.vinayak@samsung.com> |
---|
11 | | - * |
---|
12 | | - * This program is free software; you can redistribute it and/or |
---|
13 | | - * modify it under the terms of the GNU General Public License |
---|
14 | | - * as published by the Free Software Foundation; either version 2 |
---|
15 | | - * of the License, or (at your option) any later version. |
---|
16 | | - * See the COPYING file in the top-level directory or visit |
---|
17 | | - * <http://www.gnu.org/licenses/gpl-2.0.html> |
---|
18 | | - * |
---|
19 | | - * This program is distributed in the hope that it will be useful, |
---|
20 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
21 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
22 | | - * GNU General Public License for more details. |
---|
23 | | - * |
---|
24 | | - * This program is provided "AS IS" and "WITH ALL FAULTS" and |
---|
25 | | - * without warranty of any kind. You are solely responsible for |
---|
26 | | - * determining the appropriateness of using and distributing |
---|
27 | | - * the program and assume all risks associated with your exercise |
---|
28 | | - * of rights with respect to the program, including but not limited |
---|
29 | | - * to infringement of third party rights, the risks and costs of |
---|
30 | | - * program errors, damage to or loss of data, programs or equipment, |
---|
31 | | - * and unavailability or interruption of operations. Under no |
---|
32 | | - * circumstances will the contributor of this Program be liable for |
---|
33 | | - * any damages of any kind arising from your use or distribution of |
---|
34 | | - * this program. |
---|
35 | 10 | */ |
---|
36 | 11 | |
---|
37 | 12 | #ifndef _UFSHCD_H |
---|
.. | .. |
---|
55 | 30 | #include <linux/clk.h> |
---|
56 | 31 | #include <linux/completion.h> |
---|
57 | 32 | #include <linux/regulator/consumer.h> |
---|
| 33 | +#include <linux/bitfield.h> |
---|
| 34 | +#include <linux/devfreq.h> |
---|
| 35 | +#include <linux/keyslot-manager.h> |
---|
58 | 36 | #include "unipro.h" |
---|
59 | 37 | |
---|
60 | 38 | #include <asm/irq.h> |
---|
.. | .. |
---|
68 | 46 | #include <linux/android_kabi.h> |
---|
69 | 47 | |
---|
70 | 48 | #include "ufs.h" |
---|
| 49 | +#include "ufs_quirks.h" |
---|
71 | 50 | #include "ufshci.h" |
---|
72 | 51 | |
---|
73 | 52 | #define UFSHCD "ufshcd" |
---|
.. | .. |
---|
80 | 59 | DEV_CMD_TYPE_QUERY = 0x1, |
---|
81 | 60 | }; |
---|
82 | 61 | |
---|
| 62 | +enum ufs_event_type { |
---|
| 63 | + /* uic specific errors */ |
---|
| 64 | + UFS_EVT_PA_ERR = 0, |
---|
| 65 | + UFS_EVT_DL_ERR, |
---|
| 66 | + UFS_EVT_NL_ERR, |
---|
| 67 | + UFS_EVT_TL_ERR, |
---|
| 68 | + UFS_EVT_DME_ERR, |
---|
| 69 | + |
---|
| 70 | + /* fatal errors */ |
---|
| 71 | + UFS_EVT_AUTO_HIBERN8_ERR, |
---|
| 72 | + UFS_EVT_FATAL_ERR, |
---|
| 73 | + UFS_EVT_LINK_STARTUP_FAIL, |
---|
| 74 | + UFS_EVT_RESUME_ERR, |
---|
| 75 | + UFS_EVT_SUSPEND_ERR, |
---|
| 76 | + |
---|
| 77 | + /* abnormal events */ |
---|
| 78 | + UFS_EVT_DEV_RESET, |
---|
| 79 | + UFS_EVT_HOST_RESET, |
---|
| 80 | + UFS_EVT_ABORT, |
---|
| 81 | + |
---|
| 82 | + UFS_EVT_CNT, |
---|
| 83 | +}; |
---|
| 84 | + |
---|
83 | 85 | /** |
---|
84 | 86 | * struct uic_command - UIC command structure |
---|
85 | 87 | * @command: UIC command |
---|
.. | .. |
---|
87 | 89 | * @argument2: UIC command argument 2 |
---|
88 | 90 | * @argument3: UIC command argument 3 |
---|
89 | 91 | * @cmd_active: Indicate if UIC command is outstanding |
---|
90 | | - * @result: UIC command result |
---|
91 | 92 | * @done: UIC command completion |
---|
92 | 93 | */ |
---|
93 | 94 | struct uic_command { |
---|
.. | .. |
---|
96 | 97 | u32 argument2; |
---|
97 | 98 | u32 argument3; |
---|
98 | 99 | int cmd_active; |
---|
99 | | - int result; |
---|
100 | 100 | struct completion done; |
---|
101 | 101 | }; |
---|
102 | 102 | |
---|
.. | .. |
---|
116 | 116 | UIC_LINK_OFF_STATE = 0, /* Link powered down or disabled */ |
---|
117 | 117 | UIC_LINK_ACTIVE_STATE = 1, /* Link is in Fast/Slow/Sleep state */ |
---|
118 | 118 | UIC_LINK_HIBERN8_STATE = 2, /* Link is in Hibernate state */ |
---|
| 119 | + UIC_LINK_BROKEN_STATE = 3, /* Link is in broken state */ |
---|
119 | 120 | }; |
---|
120 | 121 | |
---|
121 | 122 | #define ufshcd_is_link_off(hba) ((hba)->uic_link_state == UIC_LINK_OFF_STATE) |
---|
.. | .. |
---|
123 | 124 | UIC_LINK_ACTIVE_STATE) |
---|
124 | 125 | #define ufshcd_is_link_hibern8(hba) ((hba)->uic_link_state == \ |
---|
125 | 126 | UIC_LINK_HIBERN8_STATE) |
---|
| 127 | +#define ufshcd_is_link_broken(hba) ((hba)->uic_link_state == \ |
---|
| 128 | + UIC_LINK_BROKEN_STATE) |
---|
126 | 129 | #define ufshcd_set_link_off(hba) ((hba)->uic_link_state = UIC_LINK_OFF_STATE) |
---|
127 | 130 | #define ufshcd_set_link_active(hba) ((hba)->uic_link_state = \ |
---|
128 | 131 | UIC_LINK_ACTIVE_STATE) |
---|
129 | 132 | #define ufshcd_set_link_hibern8(hba) ((hba)->uic_link_state = \ |
---|
130 | 133 | UIC_LINK_HIBERN8_STATE) |
---|
| 134 | +#define ufshcd_set_link_broken(hba) ((hba)->uic_link_state = \ |
---|
| 135 | + UIC_LINK_BROKEN_STATE) |
---|
| 136 | + |
---|
| 137 | +#define ufshcd_set_ufs_dev_active(h) \ |
---|
| 138 | + ((h)->curr_dev_pwr_mode = UFS_ACTIVE_PWR_MODE) |
---|
| 139 | +#define ufshcd_set_ufs_dev_sleep(h) \ |
---|
| 140 | + ((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE) |
---|
| 141 | +#define ufshcd_set_ufs_dev_poweroff(h) \ |
---|
| 142 | + ((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE) |
---|
| 143 | +#define ufshcd_is_ufs_dev_active(h) \ |
---|
| 144 | + ((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE) |
---|
| 145 | +#define ufshcd_is_ufs_dev_sleep(h) \ |
---|
| 146 | + ((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE) |
---|
| 147 | +#define ufshcd_is_ufs_dev_poweroff(h) \ |
---|
| 148 | + ((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE) |
---|
131 | 149 | |
---|
132 | 150 | /* |
---|
133 | 151 | * UFS Power management levels. |
---|
.. | .. |
---|
168 | 186 | * @intr_cmd: Interrupt command (doesn't participate in interrupt aggregation) |
---|
169 | 187 | * @issue_time_stamp: time stamp for debug purposes |
---|
170 | 188 | * @compl_time_stamp: time stamp for statistics |
---|
171 | | - * @crypto_enable: whether or not the request needs inline crypto operations |
---|
172 | | - * @crypto_key_slot: the key slot to use for inline crypto |
---|
| 189 | + * @crypto_key_slot: the key slot to use for inline crypto (-1 if none) |
---|
173 | 190 | * @data_unit_num: the data unit number for the first block for inline crypto |
---|
174 | 191 | * @req_abort_skip: skip request abort task flag |
---|
175 | 192 | */ |
---|
.. | .. |
---|
195 | 212 | bool intr_cmd; |
---|
196 | 213 | ktime_t issue_time_stamp; |
---|
197 | 214 | ktime_t compl_time_stamp; |
---|
198 | | -#if IS_ENABLED(CONFIG_SCSI_UFS_CRYPTO) |
---|
199 | | - bool crypto_enable; |
---|
200 | | - u8 crypto_key_slot; |
---|
| 215 | +#ifdef CONFIG_SCSI_UFS_CRYPTO |
---|
| 216 | + int crypto_key_slot; |
---|
201 | 217 | u64 data_unit_num; |
---|
202 | | -#endif /* CONFIG_SCSI_UFS_CRYPTO */ |
---|
| 218 | +#endif |
---|
203 | 219 | |
---|
204 | 220 | bool req_abort_skip; |
---|
| 221 | + |
---|
| 222 | + ANDROID_KABI_RESERVE(1); |
---|
205 | 223 | }; |
---|
206 | 224 | |
---|
207 | 225 | /** |
---|
.. | .. |
---|
221 | 239 | * @type: device management command type - Query, NOP OUT |
---|
222 | 240 | * @lock: lock to allow one command at a time |
---|
223 | 241 | * @complete: internal commands completion |
---|
224 | | - * @tag_wq: wait queue until free command slot is available |
---|
225 | 242 | */ |
---|
226 | 243 | struct ufs_dev_cmd { |
---|
227 | 244 | enum dev_cmd_type type; |
---|
228 | 245 | struct mutex lock; |
---|
229 | 246 | struct completion *complete; |
---|
230 | | - wait_queue_head_t tag_wq; |
---|
231 | 247 | struct ufs_query query; |
---|
232 | | -}; |
---|
233 | | - |
---|
234 | | -struct ufs_desc_size { |
---|
235 | | - int dev_desc; |
---|
236 | | - int pwr_desc; |
---|
237 | | - int geom_desc; |
---|
238 | | - int interc_desc; |
---|
239 | | - int unit_desc; |
---|
240 | | - int conf_desc; |
---|
241 | | - int hlth_desc; |
---|
242 | 248 | }; |
---|
243 | 249 | |
---|
244 | 250 | /** |
---|
.. | .. |
---|
249 | 255 | * @max_freq: maximum frequency supported by the clock |
---|
250 | 256 | * @min_freq: min frequency that can be used for clock scaling |
---|
251 | 257 | * @curr_freq: indicates the current frequency that it is set to |
---|
| 258 | + * @keep_link_active: indicates that the clk should not be disabled if |
---|
| 259 | + link is active |
---|
252 | 260 | * @enabled: variable to check against multiple enable/disable |
---|
253 | 261 | */ |
---|
254 | 262 | struct ufs_clk_info { |
---|
.. | .. |
---|
258 | 266 | u32 max_freq; |
---|
259 | 267 | u32 min_freq; |
---|
260 | 268 | u32 curr_freq; |
---|
| 269 | + bool keep_link_active; |
---|
261 | 270 | bool enabled; |
---|
262 | 271 | }; |
---|
263 | 272 | |
---|
.. | .. |
---|
280 | 289 | bool is_valid; |
---|
281 | 290 | struct ufs_pa_layer_attr info; |
---|
282 | 291 | }; |
---|
283 | | - |
---|
284 | | -union ufs_crypto_cfg_entry; |
---|
285 | 292 | |
---|
286 | 293 | /** |
---|
287 | 294 | * struct ufs_hba_variant_ops - variant specific callbacks |
---|
.. | .. |
---|
309 | 316 | * @resume: called during host controller PM callback |
---|
310 | 317 | * @dbg_register_dump: used to dump controller debug information |
---|
311 | 318 | * @phy_initialization: used to initialize phys |
---|
312 | | - * @program_key: program an inline encryption key into a keyslot |
---|
| 319 | + * @device_reset: called to issue a reset pulse on the UFS device |
---|
| 320 | + * @program_key: program or evict an inline encryption key |
---|
| 321 | + * @event_notify: called to notify important events |
---|
313 | 322 | */ |
---|
314 | 323 | struct ufs_hba_variant_ops { |
---|
315 | 324 | const char *name; |
---|
.. | .. |
---|
333 | 342 | void (*setup_task_mgmt)(struct ufs_hba *, int, u8); |
---|
334 | 343 | void (*hibern8_notify)(struct ufs_hba *, enum uic_cmd_dme, |
---|
335 | 344 | enum ufs_notify_change_status); |
---|
336 | | - int (*apply_dev_quirks)(struct ufs_hba *); |
---|
| 345 | + int (*apply_dev_quirks)(struct ufs_hba *hba); |
---|
| 346 | + void (*fixup_dev_quirks)(struct ufs_hba *hba); |
---|
337 | 347 | int (*suspend)(struct ufs_hba *, enum ufs_pm_op); |
---|
338 | 348 | int (*resume)(struct ufs_hba *, enum ufs_pm_op); |
---|
339 | 349 | void (*dbg_register_dump)(struct ufs_hba *hba); |
---|
340 | 350 | int (*phy_initialization)(struct ufs_hba *); |
---|
| 351 | + int (*device_reset)(struct ufs_hba *hba); |
---|
| 352 | + void (*config_scaling_param)(struct ufs_hba *hba, |
---|
| 353 | + struct devfreq_dev_profile *profile, |
---|
| 354 | + void *data); |
---|
341 | 355 | int (*program_key)(struct ufs_hba *hba, |
---|
342 | 356 | const union ufs_crypto_cfg_entry *cfg, int slot); |
---|
343 | | - |
---|
344 | | - ANDROID_KABI_RESERVE(1); |
---|
345 | | - ANDROID_KABI_RESERVE(2); |
---|
346 | | - ANDROID_KABI_RESERVE(3); |
---|
347 | | - ANDROID_KABI_RESERVE(4); |
---|
348 | | -}; |
---|
349 | | - |
---|
350 | | -struct keyslot_mgmt_ll_ops; |
---|
351 | | -struct ufs_hba_crypto_variant_ops { |
---|
352 | | - void (*setup_rq_keyslot_manager)(struct ufs_hba *hba, |
---|
353 | | - struct request_queue *q); |
---|
354 | | - void (*destroy_rq_keyslot_manager)(struct ufs_hba *hba, |
---|
355 | | - struct request_queue *q); |
---|
356 | | - int (*hba_init_crypto)(struct ufs_hba *hba, |
---|
357 | | - const struct keyslot_mgmt_ll_ops *ksm_ops); |
---|
358 | | - void (*enable)(struct ufs_hba *hba); |
---|
359 | | - void (*disable)(struct ufs_hba *hba); |
---|
360 | | - int (*suspend)(struct ufs_hba *hba, enum ufs_pm_op pm_op); |
---|
361 | | - int (*resume)(struct ufs_hba *hba, enum ufs_pm_op pm_op); |
---|
362 | | - int (*debug)(struct ufs_hba *hba); |
---|
363 | | - int (*prepare_lrbp_crypto)(struct ufs_hba *hba, |
---|
364 | | - struct scsi_cmnd *cmd, |
---|
365 | | - struct ufshcd_lrb *lrbp); |
---|
366 | | - int (*map_sg_crypto)(struct ufs_hba *hba, struct ufshcd_lrb *lrbp); |
---|
367 | | - int (*complete_lrbp_crypto)(struct ufs_hba *hba, |
---|
368 | | - struct scsi_cmnd *cmd, |
---|
369 | | - struct ufshcd_lrb *lrbp); |
---|
370 | | - void *priv; |
---|
| 357 | + void (*event_notify)(struct ufs_hba *hba, |
---|
| 358 | + enum ufs_event_type evt, void *data); |
---|
371 | 359 | |
---|
372 | 360 | ANDROID_KABI_RESERVE(1); |
---|
373 | 361 | ANDROID_KABI_RESERVE(2); |
---|
.. | .. |
---|
396 | 384 | * @delay_attr: sysfs attribute to control delay_attr |
---|
397 | 385 | * @enable_attr: sysfs attribute to enable/disable clock gating |
---|
398 | 386 | * @is_enabled: Indicates the current status of clock gating |
---|
| 387 | + * @is_initialized: Indicates whether clock gating is initialized or not |
---|
399 | 388 | * @active_reqs: number of requests that are pending and should be waited for |
---|
400 | 389 | * completion before gating clocks. |
---|
401 | 390 | */ |
---|
.. | .. |
---|
408 | 397 | struct device_attribute delay_attr; |
---|
409 | 398 | struct device_attribute enable_attr; |
---|
410 | 399 | bool is_enabled; |
---|
| 400 | + bool is_initialized; |
---|
411 | 401 | int active_reqs; |
---|
412 | 402 | struct workqueue_struct *clk_gating_workq; |
---|
| 403 | + |
---|
| 404 | + ANDROID_KABI_RESERVE(1); |
---|
413 | 405 | }; |
---|
414 | 406 | |
---|
415 | 407 | struct ufs_saved_pwr_info { |
---|
.. | .. |
---|
431 | 423 | * @workq: workqueue to schedule devfreq suspend/resume work |
---|
432 | 424 | * @suspend_work: worker to suspend devfreq |
---|
433 | 425 | * @resume_work: worker to resume devfreq |
---|
434 | | - * @is_allowed: tracks if scaling is currently allowed or not |
---|
| 426 | + * @min_gear: lowest HS gear to scale down to |
---|
| 427 | + * @is_enabled: tracks if scaling is currently enabled or not, controlled by |
---|
| 428 | + clkscale_enable sysfs node |
---|
| 429 | + * @is_allowed: tracks if scaling is currently allowed or not, used to block |
---|
| 430 | + clock scaling which is not invoked from devfreq governor |
---|
| 431 | + * @is_initialized: Indicates whether clock scaling is initialized or not |
---|
435 | 432 | * @is_busy_started: tracks if busy period has started or not |
---|
436 | 433 | * @is_suspended: tracks if devfreq is suspended or not |
---|
437 | 434 | */ |
---|
438 | 435 | struct ufs_clk_scaling { |
---|
439 | 436 | int active_reqs; |
---|
440 | 437 | unsigned long tot_busy_t; |
---|
441 | | - unsigned long window_start_t; |
---|
| 438 | + ktime_t window_start_t; |
---|
442 | 439 | ktime_t busy_start_t; |
---|
443 | 440 | struct device_attribute enable_attr; |
---|
444 | 441 | struct ufs_saved_pwr_info saved_pwr_info; |
---|
445 | 442 | struct workqueue_struct *workq; |
---|
446 | 443 | struct work_struct suspend_work; |
---|
447 | 444 | struct work_struct resume_work; |
---|
| 445 | + u32 min_gear; |
---|
| 446 | + bool is_enabled; |
---|
448 | 447 | bool is_allowed; |
---|
| 448 | + bool is_initialized; |
---|
449 | 449 | bool is_busy_started; |
---|
450 | 450 | bool is_suspended; |
---|
| 451 | + |
---|
| 452 | + ANDROID_KABI_RESERVE(1); |
---|
451 | 453 | }; |
---|
452 | 454 | |
---|
| 455 | +#define UFS_EVENT_HIST_LENGTH 8 |
---|
453 | 456 | /** |
---|
454 | | - * struct ufs_init_prefetch - contains data that is pre-fetched once during |
---|
455 | | - * initialization |
---|
456 | | - * @icc_level: icc level which was read during initialization |
---|
457 | | - */ |
---|
458 | | -struct ufs_init_prefetch { |
---|
459 | | - u32 icc_level; |
---|
460 | | -}; |
---|
461 | | - |
---|
462 | | -#define UIC_ERR_REG_HIST_LENGTH 8 |
---|
463 | | -/** |
---|
464 | | - * struct ufs_uic_err_reg_hist - keeps history of uic errors |
---|
| 457 | + * struct ufs_event_hist - keeps history of errors |
---|
465 | 458 | * @pos: index to indicate cyclic buffer position |
---|
466 | 459 | * @reg: cyclic buffer for registers value |
---|
467 | 460 | * @tstamp: cyclic buffer for time stamp |
---|
| 461 | + * @cnt: error counter |
---|
468 | 462 | */ |
---|
469 | | -struct ufs_uic_err_reg_hist { |
---|
| 463 | +struct ufs_event_hist { |
---|
470 | 464 | int pos; |
---|
471 | | - u32 reg[UIC_ERR_REG_HIST_LENGTH]; |
---|
472 | | - ktime_t tstamp[UIC_ERR_REG_HIST_LENGTH]; |
---|
| 465 | + u32 val[UFS_EVENT_HIST_LENGTH]; |
---|
| 466 | + ktime_t tstamp[UFS_EVENT_HIST_LENGTH]; |
---|
| 467 | + unsigned long long cnt; |
---|
473 | 468 | }; |
---|
474 | 469 | |
---|
475 | 470 | /** |
---|
476 | 471 | * struct ufs_stats - keeps usage/err statistics |
---|
| 472 | + * @last_intr_status: record the last interrupt status. |
---|
| 473 | + * @last_intr_ts: record the last interrupt timestamp. |
---|
477 | 474 | * @hibern8_exit_cnt: Counter to keep track of number of exits, |
---|
478 | 475 | * reset this after link-startup. |
---|
479 | 476 | * @last_hibern8_exit_tstamp: Set time after the hibern8 exit. |
---|
480 | 477 | * Clear after the first successful command completion. |
---|
481 | | - * @pa_err: tracks pa-uic errors |
---|
482 | | - * @dl_err: tracks dl-uic errors |
---|
483 | | - * @nl_err: tracks nl-uic errors |
---|
484 | | - * @tl_err: tracks tl-uic errors |
---|
485 | | - * @dme_err: tracks dme errors |
---|
486 | 478 | */ |
---|
487 | 479 | struct ufs_stats { |
---|
| 480 | + u32 last_intr_status; |
---|
| 481 | + ktime_t last_intr_ts; |
---|
| 482 | + |
---|
488 | 483 | u32 hibern8_exit_cnt; |
---|
489 | 484 | ktime_t last_hibern8_exit_tstamp; |
---|
490 | | - struct ufs_uic_err_reg_hist pa_err; |
---|
491 | | - struct ufs_uic_err_reg_hist dl_err; |
---|
492 | | - struct ufs_uic_err_reg_hist nl_err; |
---|
493 | | - struct ufs_uic_err_reg_hist tl_err; |
---|
494 | | - struct ufs_uic_err_reg_hist dme_err; |
---|
| 485 | + struct ufs_event_hist event[UFS_EVT_CNT]; |
---|
| 486 | +}; |
---|
| 487 | + |
---|
| 488 | +enum ufshcd_quirks { |
---|
| 489 | + /* Interrupt aggregation support is broken */ |
---|
| 490 | + UFSHCD_QUIRK_BROKEN_INTR_AGGR = 1 << 0, |
---|
| 491 | + |
---|
| 492 | + /* |
---|
| 493 | + * delay before each dme command is required as the unipro |
---|
| 494 | + * layer has shown instabilities |
---|
| 495 | + */ |
---|
| 496 | + UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS = 1 << 1, |
---|
| 497 | + |
---|
| 498 | + /* |
---|
| 499 | + * If UFS host controller is having issue in processing LCC (Line |
---|
| 500 | + * Control Command) coming from device then enable this quirk. |
---|
| 501 | + * When this quirk is enabled, host controller driver should disable |
---|
| 502 | + * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE |
---|
| 503 | + * attribute of device to 0). |
---|
| 504 | + */ |
---|
| 505 | + UFSHCD_QUIRK_BROKEN_LCC = 1 << 2, |
---|
| 506 | + |
---|
| 507 | + /* |
---|
| 508 | + * The attribute PA_RXHSUNTERMCAP specifies whether or not the |
---|
| 509 | + * inbound Link supports unterminated line in HS mode. Setting this |
---|
| 510 | + * attribute to 1 fixes moving to HS gear. |
---|
| 511 | + */ |
---|
| 512 | + UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP = 1 << 3, |
---|
| 513 | + |
---|
| 514 | + /* |
---|
| 515 | + * This quirk needs to be enabled if the host controller only allows |
---|
| 516 | + * accessing the peer dme attributes in AUTO mode (FAST AUTO or |
---|
| 517 | + * SLOW AUTO). |
---|
| 518 | + */ |
---|
| 519 | + UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE = 1 << 4, |
---|
| 520 | + |
---|
| 521 | + /* |
---|
| 522 | + * This quirk needs to be enabled if the host controller doesn't |
---|
| 523 | + * advertise the correct version in UFS_VER register. If this quirk |
---|
| 524 | + * is enabled, standard UFS host driver will call the vendor specific |
---|
| 525 | + * ops (get_ufs_hci_version) to get the correct version. |
---|
| 526 | + */ |
---|
| 527 | + UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION = 1 << 5, |
---|
| 528 | + |
---|
| 529 | + /* |
---|
| 530 | + * Clear handling for transfer/task request list is just opposite. |
---|
| 531 | + */ |
---|
| 532 | + UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR = 1 << 6, |
---|
| 533 | + |
---|
| 534 | + /* |
---|
| 535 | + * This quirk needs to be enabled if host controller doesn't allow |
---|
| 536 | + * that the interrupt aggregation timer and counter are reset by s/w. |
---|
| 537 | + */ |
---|
| 538 | + UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR = 1 << 7, |
---|
| 539 | + |
---|
| 540 | + /* |
---|
| 541 | + * This quirks needs to be enabled if host controller cannot be |
---|
| 542 | + * enabled via HCE register. |
---|
| 543 | + */ |
---|
| 544 | + UFSHCI_QUIRK_BROKEN_HCE = 1 << 8, |
---|
| 545 | + |
---|
| 546 | + /* |
---|
| 547 | + * This quirk needs to be enabled if the host controller regards |
---|
| 548 | + * resolution of the values of PRDTO and PRDTL in UTRD as byte. |
---|
| 549 | + */ |
---|
| 550 | + UFSHCD_QUIRK_PRDT_BYTE_GRAN = 1 << 9, |
---|
| 551 | + |
---|
| 552 | + /* |
---|
| 553 | + * This quirk needs to be enabled if the host controller reports |
---|
| 554 | + * OCS FATAL ERROR with device error through sense data |
---|
| 555 | + */ |
---|
| 556 | + UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR = 1 << 10, |
---|
| 557 | + |
---|
| 558 | + /* |
---|
| 559 | + * This quirk needs to be enabled if the host controller has |
---|
| 560 | + * auto-hibernate capability but it doesn't work. |
---|
| 561 | + */ |
---|
| 562 | + UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8 = 1 << 11, |
---|
| 563 | + |
---|
| 564 | + /* |
---|
| 565 | + * This quirk needs to disable manual flush for write booster |
---|
| 566 | + */ |
---|
| 567 | + UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL = 1 << 12, |
---|
| 568 | + |
---|
| 569 | + /* |
---|
| 570 | + * This quirk needs to disable unipro timeout values |
---|
| 571 | + * before power mode change |
---|
| 572 | + */ |
---|
| 573 | + UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING = 1 << 13, |
---|
| 574 | + |
---|
| 575 | + /* |
---|
| 576 | + * This quirk allows only sg entries aligned with page size. |
---|
| 577 | + */ |
---|
| 578 | + UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE = 1 << 14, |
---|
| 579 | + |
---|
| 580 | + /* |
---|
| 581 | + * This quirk needs to be enabled if the host controller does not |
---|
| 582 | + * support UIC command |
---|
| 583 | + */ |
---|
| 584 | + UFSHCD_QUIRK_BROKEN_UIC_CMD = 1 << 15, |
---|
| 585 | + |
---|
| 586 | + /* |
---|
| 587 | + * This quirk needs to be enabled if the host controller cannot |
---|
| 588 | + * support interface configuration. |
---|
| 589 | + */ |
---|
| 590 | + UFSHCD_QUIRK_SKIP_INTERFACE_CONFIGURATION = 1 << 16, |
---|
| 591 | + |
---|
| 592 | + /* |
---|
| 593 | + * This quirk needs to be enabled if the host controller supports inline |
---|
| 594 | + * encryption, but it needs to initialize the crypto capabilities in a |
---|
| 595 | + * nonstandard way and/or it needs to override blk_ksm_ll_ops. If |
---|
| 596 | + * enabled, the standard code won't initialize the blk_keyslot_manager; |
---|
| 597 | + * ufs_hba_variant_ops::init() must do it instead. |
---|
| 598 | + */ |
---|
| 599 | + UFSHCD_QUIRK_CUSTOM_KEYSLOT_MANAGER = 1 << 20, |
---|
| 600 | + |
---|
| 601 | + /* |
---|
| 602 | + * This quirk needs to be enabled if the host controller supports inline |
---|
| 603 | + * encryption, but the CRYPTO_GENERAL_ENABLE bit is not implemented and |
---|
| 604 | + * breaks the HCE sequence if used. |
---|
| 605 | + */ |
---|
| 606 | + UFSHCD_QUIRK_BROKEN_CRYPTO_ENABLE = 1 << 21, |
---|
| 607 | + |
---|
| 608 | + /* |
---|
| 609 | + * This quirk needs to be enabled if the host controller requires that |
---|
| 610 | + * the PRDT be cleared after each encrypted request because encryption |
---|
| 611 | + * keys were stored in it. |
---|
| 612 | + */ |
---|
| 613 | + UFSHCD_QUIRK_KEYS_IN_PRDT = 1 << 22, |
---|
| 614 | +}; |
---|
| 615 | + |
---|
| 616 | +enum ufshcd_caps { |
---|
| 617 | + /* Allow dynamic clk gating */ |
---|
| 618 | + UFSHCD_CAP_CLK_GATING = 1 << 0, |
---|
| 619 | + |
---|
| 620 | + /* Allow hiberb8 with clk gating */ |
---|
| 621 | + UFSHCD_CAP_HIBERN8_WITH_CLK_GATING = 1 << 1, |
---|
| 622 | + |
---|
| 623 | + /* Allow dynamic clk scaling */ |
---|
| 624 | + UFSHCD_CAP_CLK_SCALING = 1 << 2, |
---|
| 625 | + |
---|
| 626 | + /* Allow auto bkops to enabled during runtime suspend */ |
---|
| 627 | + UFSHCD_CAP_AUTO_BKOPS_SUSPEND = 1 << 3, |
---|
| 628 | + |
---|
| 629 | + /* |
---|
| 630 | + * This capability allows host controller driver to use the UFS HCI's |
---|
| 631 | + * interrupt aggregation capability. |
---|
| 632 | + * CAUTION: Enabling this might reduce overall UFS throughput. |
---|
| 633 | + */ |
---|
| 634 | + UFSHCD_CAP_INTR_AGGR = 1 << 4, |
---|
| 635 | + |
---|
| 636 | + /* |
---|
| 637 | + * This capability allows the device auto-bkops to be always enabled |
---|
| 638 | + * except during suspend (both runtime and suspend). |
---|
| 639 | + * Enabling this capability means that device will always be allowed |
---|
| 640 | + * to do background operation when it's active but it might degrade |
---|
| 641 | + * the performance of ongoing read/write operations. |
---|
| 642 | + */ |
---|
| 643 | + UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND = 1 << 5, |
---|
| 644 | + |
---|
| 645 | + /* |
---|
| 646 | + * This capability allows host controller driver to automatically |
---|
| 647 | + * enable runtime power management by itself instead of waiting |
---|
| 648 | + * for userspace to control the power management. |
---|
| 649 | + */ |
---|
| 650 | + UFSHCD_CAP_RPM_AUTOSUSPEND = 1 << 6, |
---|
| 651 | + |
---|
| 652 | + /* |
---|
| 653 | + * This capability allows the host controller driver to turn-on |
---|
| 654 | + * WriteBooster, if the underlying device supports it and is |
---|
| 655 | + * provisioned to be used. This would increase the write performance. |
---|
| 656 | + */ |
---|
| 657 | + UFSHCD_CAP_WB_EN = 1 << 7, |
---|
| 658 | + |
---|
| 659 | + /* |
---|
| 660 | + * This capability allows the host controller driver to use the |
---|
| 661 | + * inline crypto engine, if it is present |
---|
| 662 | + */ |
---|
| 663 | + UFSHCD_CAP_CRYPTO = 1 << 8, |
---|
| 664 | + |
---|
| 665 | + /* |
---|
| 666 | + * This capability allows the controller regulators to be put into |
---|
| 667 | + * lpm mode aggressively during clock gating. |
---|
| 668 | + * This would increase power savings. |
---|
| 669 | + */ |
---|
| 670 | + UFSHCD_CAP_AGGR_POWER_COLLAPSE = 1 << 9, |
---|
| 671 | +}; |
---|
| 672 | + |
---|
| 673 | +struct ufs_hba_variant_params { |
---|
| 674 | + struct devfreq_dev_profile devfreq_profile; |
---|
| 675 | + struct devfreq_simple_ondemand_data ondemand_data; |
---|
| 676 | + u16 hba_enable_delay_us; |
---|
| 677 | + u32 wb_flush_threshold; |
---|
| 678 | +}; |
---|
| 679 | + |
---|
| 680 | +#ifdef CONFIG_SCSI_UFS_HPB |
---|
| 681 | +/** |
---|
| 682 | + * struct ufshpb_dev_info - UFSHPB device related info |
---|
| 683 | + * @num_lu: the number of user logical unit to check whether all lu finished |
---|
| 684 | + * initialization |
---|
| 685 | + * @rgn_size: device reported HPB region size |
---|
| 686 | + * @srgn_size: device reported HPB sub-region size |
---|
| 687 | + * @slave_conf_cnt: counter to check all lu finished initialization |
---|
| 688 | + * @hpb_disabled: flag to check if HPB is disabled |
---|
| 689 | + * @max_hpb_single_cmd: device reported bMAX_DATA_SIZE_FOR_SINGLE_CMD value |
---|
| 690 | + * @is_legacy: flag to check HPB 1.0 |
---|
| 691 | + * @control_mode: either host or device |
---|
| 692 | + */ |
---|
| 693 | +struct ufshpb_dev_info { |
---|
| 694 | + int num_lu; |
---|
| 695 | + int rgn_size; |
---|
| 696 | + int srgn_size; |
---|
| 697 | + atomic_t slave_conf_cnt; |
---|
| 698 | + bool hpb_disabled; |
---|
| 699 | + u8 max_hpb_single_cmd; |
---|
| 700 | + bool is_legacy; |
---|
| 701 | + u8 control_mode; |
---|
| 702 | +}; |
---|
| 703 | +#endif |
---|
| 704 | + |
---|
| 705 | +struct ufs_hba_monitor { |
---|
| 706 | + unsigned long chunk_size; |
---|
| 707 | + |
---|
| 708 | + unsigned long nr_sec_rw[2]; |
---|
| 709 | + ktime_t total_busy[2]; |
---|
| 710 | + |
---|
| 711 | + unsigned long nr_req[2]; |
---|
| 712 | + /* latencies*/ |
---|
| 713 | + ktime_t lat_sum[2]; |
---|
| 714 | + ktime_t lat_max[2]; |
---|
| 715 | + ktime_t lat_min[2]; |
---|
| 716 | + |
---|
| 717 | + u32 nr_queued[2]; |
---|
| 718 | + ktime_t busy_start_ts[2]; |
---|
| 719 | + |
---|
| 720 | + ktime_t enabled_ts; |
---|
| 721 | + bool enabled; |
---|
495 | 722 | }; |
---|
496 | 723 | |
---|
497 | 724 | /** |
---|
.. | .. |
---|
506 | 733 | * @host: Scsi_Host instance of the driver |
---|
507 | 734 | * @dev: device handle |
---|
508 | 735 | * @lrb: local reference block |
---|
509 | | - * @lrb_in_use: lrb in use |
---|
| 736 | + * @cmd_queue: Used to allocate command tags from hba->host->tag_set. |
---|
510 | 737 | * @outstanding_tasks: Bits representing outstanding task requests |
---|
511 | 738 | * @outstanding_reqs: Bits representing outstanding transfer requests |
---|
512 | 739 | * @capabilities: UFS Controller Capabilities |
---|
513 | 740 | * @nutrs: Transfer Request Queue depth supported by controller |
---|
514 | 741 | * @nutmrs: Task Management Queue depth supported by controller |
---|
| 742 | + * @reserved_slot: Used to submit device commands. Protected by @dev_cmd.lock. |
---|
515 | 743 | * @ufs_version: UFS Version to which controller complies |
---|
516 | 744 | * @vops: pointer to variant specific operations |
---|
517 | 745 | * @priv: pointer to variant specific private data |
---|
.. | .. |
---|
519 | 747 | * @irq: Irq number of the controller |
---|
520 | 748 | * @active_uic_cmd: handle of active UIC command |
---|
521 | 749 | * @uic_cmd_mutex: mutex for uic command |
---|
522 | | - * @tm_wq: wait queue for task management |
---|
523 | | - * @tm_tag_wq: wait queue for free task management slots |
---|
524 | | - * @tm_slots_in_use: bit map of task management request slots in use |
---|
| 750 | + * @tmf_tag_set: TMF tag set. |
---|
| 751 | + * @tmf_queue: Used to allocate TMF tags. |
---|
525 | 752 | * @pwr_done: completion for power mode change |
---|
526 | | - * @tm_condition: condition variable for task management |
---|
527 | 753 | * @ufshcd_state: UFSHCD states |
---|
528 | 754 | * @eh_flags: Error handling flags |
---|
529 | 755 | * @intr_mask: Interrupt Mask Bits |
---|
530 | 756 | * @ee_ctrl_mask: Exception event control mask |
---|
531 | 757 | * @is_powered: flag to check if HBA is powered |
---|
532 | | - * @is_init_prefetch: flag to check if data was pre-fetched in initialization |
---|
533 | | - * @init_prefetch_data: data pre-fetched during initialization |
---|
| 758 | + * @shutting_down: flag to check if shutdown has been invoked |
---|
| 759 | + * @host_sem: semaphore used to serialize concurrent contexts |
---|
| 760 | + * @eh_wq: Workqueue that eh_work works on |
---|
534 | 761 | * @eh_work: Worker to handle UFS errors that require s/w attention |
---|
535 | 762 | * @eeh_work: Worker to handle exception events |
---|
536 | 763 | * @errors: HBA errors |
---|
537 | 764 | * @uic_error: UFS interconnect layer error status |
---|
538 | 765 | * @saved_err: sticky error mask |
---|
539 | 766 | * @saved_uic_err: sticky UIC error mask |
---|
| 767 | + * @force_reset: flag to force eh_work perform a full reset |
---|
| 768 | + * @force_pmc: flag to force a power mode change |
---|
540 | 769 | * @silence_err_logs: flag to silence error logs |
---|
541 | 770 | * @dev_cmd: ufs device management command information |
---|
542 | 771 | * @last_dme_cmd_tstamp: time stamp of the last completed DME command |
---|
.. | .. |
---|
570 | 799 | |
---|
571 | 800 | struct Scsi_Host *host; |
---|
572 | 801 | struct device *dev; |
---|
| 802 | + struct request_queue *cmd_queue; |
---|
573 | 803 | /* |
---|
574 | 804 | * This field is to keep a reference to "scsi_device" corresponding to |
---|
575 | 805 | * "UFS device" W-LU. |
---|
576 | 806 | */ |
---|
577 | 807 | struct scsi_device *sdev_ufs_device; |
---|
| 808 | + struct scsi_device *sdev_rpmb; |
---|
578 | 809 | |
---|
579 | 810 | enum ufs_dev_pwr_mode curr_dev_pwr_mode; |
---|
580 | 811 | enum uic_link_state uic_link_state; |
---|
.. | .. |
---|
590 | 821 | u32 ahit; |
---|
591 | 822 | |
---|
592 | 823 | struct ufshcd_lrb *lrb; |
---|
593 | | - unsigned long lrb_in_use; |
---|
594 | 824 | |
---|
595 | 825 | unsigned long outstanding_tasks; |
---|
596 | 826 | unsigned long outstanding_reqs; |
---|
.. | .. |
---|
598 | 828 | u32 capabilities; |
---|
599 | 829 | int nutrs; |
---|
600 | 830 | int nutmrs; |
---|
| 831 | +#if 0 |
---|
| 832 | + /* |
---|
| 833 | + * This has been moved into struct ufs_hba_add_info because of the GKI. |
---|
| 834 | + */ |
---|
| 835 | + u32 reserved_slot; |
---|
| 836 | +#endif |
---|
601 | 837 | u32 ufs_version; |
---|
602 | | - struct ufs_hba_variant_ops *vops; |
---|
| 838 | + const struct ufs_hba_variant_ops *vops; |
---|
| 839 | + struct ufs_hba_variant_params *vps; |
---|
603 | 840 | void *priv; |
---|
604 | | - const struct ufs_hba_crypto_variant_ops *crypto_vops; |
---|
605 | 841 | size_t sg_entry_size; |
---|
606 | 842 | unsigned int irq; |
---|
607 | 843 | bool is_irq_enabled; |
---|
608 | | - |
---|
609 | | - /* Interrupt aggregation support is broken */ |
---|
610 | | - #define UFSHCD_QUIRK_BROKEN_INTR_AGGR 0x1 |
---|
611 | | - |
---|
612 | | - /* |
---|
613 | | - * delay before each dme command is required as the unipro |
---|
614 | | - * layer has shown instabilities |
---|
615 | | - */ |
---|
616 | | - #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS 0x2 |
---|
617 | | - |
---|
618 | | - /* |
---|
619 | | - * If UFS host controller is having issue in processing LCC (Line |
---|
620 | | - * Control Command) coming from device then enable this quirk. |
---|
621 | | - * When this quirk is enabled, host controller driver should disable |
---|
622 | | - * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE |
---|
623 | | - * attribute of device to 0). |
---|
624 | | - */ |
---|
625 | | - #define UFSHCD_QUIRK_BROKEN_LCC 0x4 |
---|
626 | | - |
---|
627 | | - /* |
---|
628 | | - * The attribute PA_RXHSUNTERMCAP specifies whether or not the |
---|
629 | | - * inbound Link supports unterminated line in HS mode. Setting this |
---|
630 | | - * attribute to 1 fixes moving to HS gear. |
---|
631 | | - */ |
---|
632 | | - #define UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP 0x8 |
---|
633 | | - |
---|
634 | | - /* |
---|
635 | | - * This quirk needs to be enabled if the host contoller only allows |
---|
636 | | - * accessing the peer dme attributes in AUTO mode (FAST AUTO or |
---|
637 | | - * SLOW AUTO). |
---|
638 | | - */ |
---|
639 | | - #define UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE 0x10 |
---|
640 | | - |
---|
641 | | - /* |
---|
642 | | - * This quirk needs to be enabled if the host contoller doesn't |
---|
643 | | - * advertise the correct version in UFS_VER register. If this quirk |
---|
644 | | - * is enabled, standard UFS host driver will call the vendor specific |
---|
645 | | - * ops (get_ufs_hci_version) to get the correct version. |
---|
646 | | - */ |
---|
647 | | - #define UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION 0x20 |
---|
648 | | - |
---|
649 | | - /* |
---|
650 | | - * This quirk needs to be enabled if the host contoller regards |
---|
651 | | - * resolution of the values of PRDTO and PRDTL in UTRD as byte. |
---|
652 | | - */ |
---|
653 | | - #define UFSHCD_QUIRK_PRDT_BYTE_GRAN 0x80 |
---|
654 | | - |
---|
655 | | - /* |
---|
656 | | - * Clear handling for transfer/task request list is just opposite. |
---|
657 | | - */ |
---|
658 | | - #define UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR 0x100 |
---|
659 | | - |
---|
660 | | - /* |
---|
661 | | - * This quirk needs to be enabled if host controller doesn't allow |
---|
662 | | - * that the interrupt aggregation timer and counter are reset by s/w. |
---|
663 | | - */ |
---|
664 | | - #define UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR 0x200 |
---|
665 | | - |
---|
666 | | - /* |
---|
667 | | - * This quirks needs to be enabled if host controller cannot be |
---|
668 | | - * enabled via HCE register. |
---|
669 | | - */ |
---|
670 | | - #define UFSHCI_QUIRK_BROKEN_HCE 0x400 |
---|
671 | | - |
---|
672 | | - /* |
---|
673 | | - * This quirk needs to be enabled if the host controller advertises |
---|
674 | | - * inline encryption support but it doesn't work correctly. |
---|
675 | | - */ |
---|
676 | | - #define UFSHCD_QUIRK_BROKEN_CRYPTO 0x800 |
---|
| 844 | + enum ufs_ref_clk_freq dev_ref_clk_freq; |
---|
677 | 845 | |
---|
678 | 846 | unsigned int quirks; /* Deviations from standard UFSHCI spec. */ |
---|
679 | 847 | |
---|
680 | 848 | /* Device deviations from standard UFS device spec. */ |
---|
681 | 849 | unsigned int dev_quirks; |
---|
682 | 850 | |
---|
683 | | - wait_queue_head_t tm_wq; |
---|
684 | | - wait_queue_head_t tm_tag_wq; |
---|
685 | | - unsigned long tm_condition; |
---|
686 | | - unsigned long tm_slots_in_use; |
---|
| 851 | + struct blk_mq_tag_set tmf_tag_set; |
---|
| 852 | + struct request_queue *tmf_queue; |
---|
| 853 | +#if 0 |
---|
| 854 | + /* |
---|
| 855 | + * This has been moved into struct ufs_hba_add_info because of the GKI. |
---|
| 856 | + */ |
---|
| 857 | + struct request **tmf_rqs; |
---|
| 858 | +#endif |
---|
687 | 859 | |
---|
688 | 860 | struct uic_command *active_uic_cmd; |
---|
689 | 861 | struct mutex uic_cmd_mutex; |
---|
.. | .. |
---|
694 | 866 | u32 intr_mask; |
---|
695 | 867 | u16 ee_ctrl_mask; |
---|
696 | 868 | bool is_powered; |
---|
697 | | - bool is_init_prefetch; |
---|
698 | | - struct ufs_init_prefetch init_prefetch_data; |
---|
| 869 | + bool shutting_down; |
---|
| 870 | + struct semaphore host_sem; |
---|
699 | 871 | |
---|
700 | 872 | /* Work Queues */ |
---|
| 873 | + struct workqueue_struct *eh_wq; |
---|
701 | 874 | struct work_struct eh_work; |
---|
702 | 875 | struct work_struct eeh_work; |
---|
703 | 876 | |
---|
.. | .. |
---|
707 | 880 | u32 saved_err; |
---|
708 | 881 | u32 saved_uic_err; |
---|
709 | 882 | struct ufs_stats ufs_stats; |
---|
| 883 | + bool force_reset; |
---|
| 884 | + bool force_pmc; |
---|
710 | 885 | bool silence_err_logs; |
---|
711 | 886 | |
---|
712 | 887 | /* Device management request data */ |
---|
.. | .. |
---|
732 | 907 | struct ufs_clk_gating clk_gating; |
---|
733 | 908 | /* Control to enable/disable host capabilities */ |
---|
734 | 909 | u32 caps; |
---|
735 | | - /* Allow dynamic clk gating */ |
---|
736 | | -#define UFSHCD_CAP_CLK_GATING (1 << 0) |
---|
737 | | - /* Allow hiberb8 with clk gating */ |
---|
738 | | -#define UFSHCD_CAP_HIBERN8_WITH_CLK_GATING (1 << 1) |
---|
739 | | - /* Allow dynamic clk scaling */ |
---|
740 | | -#define UFSHCD_CAP_CLK_SCALING (1 << 2) |
---|
741 | | - /* Allow auto bkops to enabled during runtime suspend */ |
---|
742 | | -#define UFSHCD_CAP_AUTO_BKOPS_SUSPEND (1 << 3) |
---|
743 | | - /* |
---|
744 | | - * This capability allows host controller driver to use the UFS HCI's |
---|
745 | | - * interrupt aggregation capability. |
---|
746 | | - * CAUTION: Enabling this might reduce overall UFS throughput. |
---|
747 | | - */ |
---|
748 | | -#define UFSHCD_CAP_INTR_AGGR (1 << 4) |
---|
749 | | - /* |
---|
750 | | - * This capability allows the device auto-bkops to be always enabled |
---|
751 | | - * except during suspend (both runtime and suspend). |
---|
752 | | - * Enabling this capability means that device will always be allowed |
---|
753 | | - * to do background operation when it's active but it might degrade |
---|
754 | | - * the performance of ongoing read/write operations. |
---|
755 | | - */ |
---|
756 | | -#define UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND (1 << 5) |
---|
757 | | - /* |
---|
758 | | - * This capability allows host controller driver to automatically |
---|
759 | | - * enable runtime power management by itself instead of waiting |
---|
760 | | - * for userspace to control the power management. |
---|
761 | | - */ |
---|
762 | | -#define UFSHCD_CAP_RPM_AUTOSUSPEND (1 << 6) |
---|
763 | | - /* |
---|
764 | | - * This capability allows the host controller driver to use the |
---|
765 | | - * inline crypto engine, if it is present |
---|
766 | | - */ |
---|
767 | | -#define UFSHCD_CAP_CRYPTO (1 << 7) |
---|
768 | 910 | |
---|
769 | 911 | struct devfreq *devfreq; |
---|
770 | 912 | struct ufs_clk_scaling clk_scaling; |
---|
.. | .. |
---|
774 | 916 | bool is_urgent_bkops_lvl_checked; |
---|
775 | 917 | |
---|
776 | 918 | struct rw_semaphore clk_scaling_lock; |
---|
777 | | - struct ufs_desc_size desc_size; |
---|
| 919 | + unsigned char desc_size[QUERY_DESC_IDN_MAX]; |
---|
778 | 920 | atomic_t scsi_block_reqs_cnt; |
---|
779 | 921 | |
---|
| 922 | + struct device bsg_dev; |
---|
| 923 | + struct request_queue *bsg_queue; |
---|
| 924 | + bool wb_buf_flush_enabled; |
---|
| 925 | + bool wb_enabled; |
---|
| 926 | + struct delayed_work rpm_dev_flush_recheck_work; |
---|
| 927 | + |
---|
| 928 | +#if 0 |
---|
| 929 | + /* This has been moved into struct ufs_hba_add_info. */ |
---|
| 930 | + struct ufshpb_dev_info ufshpb_dev; |
---|
| 931 | +#endif |
---|
| 932 | + |
---|
| 933 | + struct ufs_hba_monitor monitor; |
---|
| 934 | + |
---|
780 | 935 | #ifdef CONFIG_SCSI_UFS_CRYPTO |
---|
781 | | - /* crypto */ |
---|
782 | 936 | union ufs_crypto_capabilities crypto_capabilities; |
---|
783 | 937 | union ufs_crypto_cap_entry *crypto_cap_array; |
---|
784 | 938 | u32 crypto_cfg_register; |
---|
785 | | - struct keyslot_manager *ksm; |
---|
786 | | -#endif /* CONFIG_SCSI_UFS_CRYPTO */ |
---|
| 939 | + struct blk_keyslot_manager ksm; |
---|
| 940 | +#endif |
---|
| 941 | +#ifdef CONFIG_DEBUG_FS |
---|
| 942 | + struct dentry *debugfs_root; |
---|
| 943 | +#endif |
---|
787 | 944 | |
---|
788 | 945 | ANDROID_KABI_RESERVE(1); |
---|
789 | 946 | ANDROID_KABI_RESERVE(2); |
---|
.. | .. |
---|
827 | 984 | #endif |
---|
828 | 985 | } |
---|
829 | 986 | |
---|
| 987 | +static inline bool ufshcd_can_aggressive_pc(struct ufs_hba *hba) |
---|
| 988 | +{ |
---|
| 989 | + return !!(ufshcd_is_link_hibern8(hba) && |
---|
| 990 | + (hba->caps & UFSHCD_CAP_AGGR_POWER_COLLAPSE)); |
---|
| 991 | +} |
---|
| 992 | + |
---|
| 993 | +static inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba) |
---|
| 994 | +{ |
---|
| 995 | + return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT) && |
---|
| 996 | + !(hba->quirks & UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8); |
---|
| 997 | +} |
---|
| 998 | + |
---|
| 999 | +static inline bool ufshcd_is_auto_hibern8_enabled(struct ufs_hba *hba) |
---|
| 1000 | +{ |
---|
| 1001 | + return FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, hba->ahit) ? true : false; |
---|
| 1002 | +} |
---|
| 1003 | + |
---|
| 1004 | +static inline bool ufshcd_is_wb_allowed(struct ufs_hba *hba) |
---|
| 1005 | +{ |
---|
| 1006 | + return hba->caps & UFSHCD_CAP_WB_EN; |
---|
| 1007 | +} |
---|
| 1008 | + |
---|
| 1009 | +static inline bool ufshcd_is_user_access_allowed(struct ufs_hba *hba) |
---|
| 1010 | +{ |
---|
| 1011 | + return !hba->shutting_down; |
---|
| 1012 | +} |
---|
| 1013 | + |
---|
830 | 1014 | #define ufshcd_writel(hba, val, reg) \ |
---|
831 | 1015 | writel((val), (hba)->mmio_base + (reg)) |
---|
832 | 1016 | #define ufshcd_readl(hba, reg) \ |
---|
.. | .. |
---|
851 | 1035 | |
---|
852 | 1036 | int ufshcd_alloc_host(struct device *, struct ufs_hba **); |
---|
853 | 1037 | void ufshcd_dealloc_host(struct ufs_hba *); |
---|
| 1038 | +int ufshcd_hba_enable(struct ufs_hba *hba); |
---|
854 | 1039 | int ufshcd_init(struct ufs_hba * , void __iomem * , unsigned int); |
---|
| 1040 | +int ufshcd_link_recovery(struct ufs_hba *hba); |
---|
| 1041 | +int ufshcd_make_hba_operational(struct ufs_hba *hba); |
---|
855 | 1042 | void ufshcd_remove(struct ufs_hba *); |
---|
| 1043 | +int ufshcd_uic_hibern8_exit(struct ufs_hba *hba); |
---|
| 1044 | +void ufshcd_delay_us(unsigned long us, unsigned long tolerance); |
---|
856 | 1045 | int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask, |
---|
857 | 1046 | u32 val, unsigned long interval_us, |
---|
858 | | - unsigned long timeout_ms, bool can_sleep); |
---|
| 1047 | + unsigned long timeout_ms); |
---|
| 1048 | +void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk); |
---|
| 1049 | +void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val); |
---|
| 1050 | +void ufshcd_hba_stop(struct ufs_hba *hba); |
---|
859 | 1051 | |
---|
860 | 1052 | static inline void check_upiu_size(void) |
---|
861 | 1053 | { |
---|
.. | .. |
---|
887 | 1079 | struct ufs_hba *hba) |
---|
888 | 1080 | { |
---|
889 | 1081 | return hba->caps & UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND; |
---|
| 1082 | +} |
---|
| 1083 | + |
---|
| 1084 | +static inline u8 ufshcd_wb_get_query_index(struct ufs_hba *hba) |
---|
| 1085 | +{ |
---|
| 1086 | + if (hba->dev_info.b_wb_buffer_type == WB_BUF_MODE_LU_DEDICATED) |
---|
| 1087 | + return hba->dev_info.wb_dedicated_lu; |
---|
| 1088 | + return 0; |
---|
890 | 1089 | } |
---|
891 | 1090 | |
---|
892 | 1091 | extern int ufshcd_runtime_suspend(struct ufs_hba *hba); |
---|
.. | .. |
---|
956 | 1155 | pwr_info->pwr_tx == FASTAUTO_MODE); |
---|
957 | 1156 | } |
---|
958 | 1157 | |
---|
| 1158 | +static inline int ufshcd_disable_host_tx_lcc(struct ufs_hba *hba) |
---|
| 1159 | +{ |
---|
| 1160 | + return ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); |
---|
| 1161 | +} |
---|
| 1162 | + |
---|
959 | 1163 | /* Expose Query-Request API */ |
---|
960 | 1164 | int ufshcd_query_descriptor_retry(struct ufs_hba *hba, |
---|
961 | 1165 | enum query_opcode opcode, |
---|
.. | .. |
---|
970 | 1174 | u8 param_size); |
---|
971 | 1175 | int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, |
---|
972 | 1176 | enum attr_idn idn, u8 index, u8 selector, u32 *attr_val); |
---|
| 1177 | +int ufshcd_query_attr_retry(struct ufs_hba *hba, |
---|
| 1178 | + enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector, |
---|
| 1179 | + u32 *attr_val); |
---|
973 | 1180 | int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, |
---|
974 | | - enum flag_idn idn, bool *flag_res); |
---|
975 | | -int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, |
---|
976 | | - u8 *buf, u32 size, bool ascii); |
---|
| 1181 | + enum flag_idn idn, u8 index, bool *flag_res); |
---|
| 1182 | +int ufshcd_query_flag_retry(struct ufs_hba *hba, |
---|
| 1183 | + enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res); |
---|
| 1184 | +int ufshcd_bkops_ctrl(struct ufs_hba *hba, enum bkops_status status); |
---|
| 1185 | + |
---|
| 1186 | +void ufshcd_auto_hibern8_enable(struct ufs_hba *hba); |
---|
| 1187 | +void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit); |
---|
| 1188 | +void ufshcd_fixup_dev_quirks(struct ufs_hba *hba, struct ufs_dev_fix *fixups); |
---|
| 1189 | +#define SD_ASCII_STD true |
---|
| 1190 | +#define SD_RAW false |
---|
| 1191 | +int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index, |
---|
| 1192 | + u8 **buf, bool ascii); |
---|
977 | 1193 | |
---|
978 | 1194 | int ufshcd_hold(struct ufs_hba *hba, bool async); |
---|
979 | 1195 | void ufshcd_release(struct ufs_hba *hba); |
---|
980 | 1196 | |
---|
981 | | -int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, |
---|
982 | | - int *desc_length); |
---|
| 1197 | +void ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, |
---|
| 1198 | + int *desc_length); |
---|
983 | 1199 | |
---|
984 | 1200 | u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba); |
---|
| 1201 | + |
---|
| 1202 | +int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd); |
---|
| 1203 | + |
---|
| 1204 | +int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, |
---|
| 1205 | + struct utp_upiu_req *req_upiu, |
---|
| 1206 | + struct utp_upiu_req *rsp_upiu, |
---|
| 1207 | + int msgcode, |
---|
| 1208 | + u8 *desc_buff, int *buff_len, |
---|
| 1209 | + enum query_opcode desc_op); |
---|
985 | 1210 | |
---|
986 | 1211 | /* Wrapper functions for safely calling variant operations */ |
---|
987 | 1212 | static inline const char *ufshcd_get_var_name(struct ufs_hba *hba) |
---|
.. | .. |
---|
1013 | 1238 | return ufshcd_readl(hba, REG_UFS_VERSION); |
---|
1014 | 1239 | } |
---|
1015 | 1240 | |
---|
| 1241 | +static inline bool ufshcd_has_utrlcnr(struct ufs_hba *hba) |
---|
| 1242 | +{ |
---|
| 1243 | + return (hba->ufs_version >= ufshci_version(3, 0)); |
---|
| 1244 | +} |
---|
| 1245 | + |
---|
1016 | 1246 | static inline int ufshcd_vops_clk_scale_notify(struct ufs_hba *hba, |
---|
1017 | 1247 | bool up, enum ufs_notify_change_status status) |
---|
1018 | 1248 | { |
---|
1019 | 1249 | if (hba->vops && hba->vops->clk_scale_notify) |
---|
1020 | 1250 | return hba->vops->clk_scale_notify(hba, up, status); |
---|
1021 | 1251 | return 0; |
---|
| 1252 | +} |
---|
| 1253 | + |
---|
| 1254 | +static inline void ufshcd_vops_event_notify(struct ufs_hba *hba, |
---|
| 1255 | + enum ufs_event_type evt, |
---|
| 1256 | + void *data) |
---|
| 1257 | +{ |
---|
| 1258 | + if (hba->vops && hba->vops->event_notify) |
---|
| 1259 | + hba->vops->event_notify(hba, evt, data); |
---|
1022 | 1260 | } |
---|
1023 | 1261 | |
---|
1024 | 1262 | static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on, |
---|
.. | .. |
---|
1066 | 1304 | return -ENOTSUPP; |
---|
1067 | 1305 | } |
---|
1068 | 1306 | |
---|
1069 | | -static inline void ufshcd_vops_setup_xfer_req(struct ufs_hba *hba, int tag, |
---|
1070 | | - bool is_scsi_cmd) |
---|
1071 | | -{ |
---|
1072 | | - if (hba->vops && hba->vops->setup_xfer_req) |
---|
1073 | | - return hba->vops->setup_xfer_req(hba, tag, is_scsi_cmd); |
---|
1074 | | -} |
---|
1075 | | - |
---|
1076 | 1307 | static inline void ufshcd_vops_setup_task_mgmt(struct ufs_hba *hba, |
---|
1077 | 1308 | int tag, u8 tm_function) |
---|
1078 | 1309 | { |
---|
.. | .. |
---|
1093 | 1324 | if (hba->vops && hba->vops->apply_dev_quirks) |
---|
1094 | 1325 | return hba->vops->apply_dev_quirks(hba); |
---|
1095 | 1326 | return 0; |
---|
| 1327 | +} |
---|
| 1328 | + |
---|
| 1329 | +static inline void ufshcd_vops_fixup_dev_quirks(struct ufs_hba *hba) |
---|
| 1330 | +{ |
---|
| 1331 | + if (hba->vops && hba->vops->fixup_dev_quirks) |
---|
| 1332 | + hba->vops->fixup_dev_quirks(hba); |
---|
1096 | 1333 | } |
---|
1097 | 1334 | |
---|
1098 | 1335 | static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op) |
---|
.. | .. |
---|
1117 | 1354 | hba->vops->dbg_register_dump(hba); |
---|
1118 | 1355 | } |
---|
1119 | 1356 | |
---|
| 1357 | +static inline void ufshcd_vops_device_reset(struct ufs_hba *hba) |
---|
| 1358 | +{ |
---|
| 1359 | + if (hba->vops && hba->vops->device_reset) { |
---|
| 1360 | + int err = hba->vops->device_reset(hba); |
---|
| 1361 | + |
---|
| 1362 | + if (!err) { |
---|
| 1363 | + ufshcd_set_ufs_dev_active(hba); |
---|
| 1364 | + if (ufshcd_is_wb_allowed(hba)) { |
---|
| 1365 | + hba->wb_enabled = false; |
---|
| 1366 | + hba->wb_buf_flush_enabled = false; |
---|
| 1367 | + } |
---|
| 1368 | + } |
---|
| 1369 | + if (err != -EOPNOTSUPP) |
---|
| 1370 | + ufshcd_update_evt_hist(hba, UFS_EVT_DEV_RESET, err); |
---|
| 1371 | + } |
---|
| 1372 | +} |
---|
| 1373 | + |
---|
| 1374 | +static inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba, |
---|
| 1375 | + struct devfreq_dev_profile |
---|
| 1376 | + *profile, void *data) |
---|
| 1377 | +{ |
---|
| 1378 | + if (hba->vops && hba->vops->config_scaling_param) |
---|
| 1379 | + hba->vops->config_scaling_param(hba, profile, data); |
---|
| 1380 | +} |
---|
| 1381 | + |
---|
1120 | 1382 | extern struct ufs_pm_lvl_states ufs_pm_lvl_states[]; |
---|
1121 | 1383 | |
---|
1122 | 1384 | /* |
---|
.. | .. |
---|
1136 | 1398 | |
---|
1137 | 1399 | int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len, |
---|
1138 | 1400 | const char *prefix); |
---|
1139 | | - |
---|
| 1401 | +int ufshcd_uic_hibern8_enter(struct ufs_hba *hba); |
---|
| 1402 | +int ufshcd_uic_hibern8_exit(struct ufs_hba *hba); |
---|
1140 | 1403 | #endif /* End of Header */ |
---|