FILE
ufshcd-pci.c
File preview with syntax highlighting.
linux-6.19.14/drivers/ufs/host/ufshcd-pci.c
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Universal Flash Storage Host controller PCI glue driver 4 * 5 * Copyright (C) 2011-2013 Samsung India Software Operations 6 * 7 * Authors: 8 * Santosh Yaraganavi <santosh.sy@samsung.com> 9 * Vinayak Holikatti <h.vinayak@samsung.com> 10 */ 11 12#include <ufs/ufshcd.h> 13#include <linux/delay.h> 14#include <linux/module.h> 15#include <linux/pci.h> 16#include <linux/pm_runtime.h> 17#include <linux/pm_qos.h> 18#include <linux/suspend.h> 19#include <linux/debugfs.h> 20#include <linux/uuid.h> 21#include <linux/acpi.h> 22#include <linux/gpio/consumer.h> 23 24#define MAX_SUPP_MAC 64 25 26enum intel_ufs_dsm_func_id { 27 INTEL_DSM_FNS = 0, 28 INTEL_DSM_RESET = 1, 29}; 30 31struct intel_host { 32 u32 dsm_fns; 33 u32 active_ltr; 34 u32 idle_ltr; 35 int saved_spm_lvl; 36 struct dentry *debugfs_root; 37 struct gpio_desc *reset_gpio; 38}; 39 40static const guid_t intel_dsm_guid = 41 GUID_INIT(0x1A4832A0, 0x7D03, 0x43CA, 42 0xB0, 0x20, 0xF6, 0xDC, 0xD1, 0x2A, 0x19, 0x50); 43 44static bool __intel_dsm_supported(struct intel_host *host, 45 enum intel_ufs_dsm_func_id fn) 46{ 47 return fn < 32 && fn >= 0 && (host->dsm_fns & (1u << fn)); 48} 49 50#define INTEL_DSM_SUPPORTED(host, name) \ 51 __intel_dsm_supported(host, INTEL_DSM_##name) 52 53static int __intel_dsm(struct intel_host *intel_host, struct device *dev, 54 unsigned int fn, u32 *result) 55{ 56 union acpi_object *obj; 57 int err = 0; 58 size_t len; 59 60 obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(dev), &intel_dsm_guid, 0, fn, NULL, 61 ACPI_TYPE_BUFFER); 62 if (!obj) 63 return -EOPNOTSUPP; 64 65 if (obj->buffer.length < 1) { 66 err = -EINVAL; 67 goto out; 68 } 69 70 len = min_t(size_t, obj->buffer.length, 4); 71 72 *result = 0; 73 memcpy(result, obj->buffer.pointer, len); 74out: 75 ACPI_FREE(obj); 76 77 return err; 78} 79 80static int intel_dsm(struct intel_host *intel_host, struct device *dev, 81 unsigned int fn, u32 *result) 82{ 83 if (!__intel_dsm_supported(intel_host, fn)) 84 return -EOPNOTSUPP; 85 86 return __intel_dsm(intel_host, dev, fn, result); 87} 88 89static void intel_dsm_init(struct intel_host *intel_host, struct device *dev) 90{ 91 int err; 92 93 err = __intel_dsm(intel_host, dev, INTEL_DSM_FNS, &intel_host->dsm_fns); 94 dev_dbg(dev, "DSM fns %#x, error %d\n", intel_host->dsm_fns, err); 95} 96 97static int ufs_intel_hce_enable_notify(struct ufs_hba *hba, 98 enum ufs_notify_change_status status) 99{ 100 /* Cannot enable ICE until after HC enable */ 101 if (status == POST_CHANGE && hba->caps & UFSHCD_CAP_CRYPTO) { 102 u32 hce = ufshcd_readl(hba, REG_CONTROLLER_ENABLE); 103 104 hce |= CRYPTO_GENERAL_ENABLE; 105 ufshcd_writel(hba, hce, REG_CONTROLLER_ENABLE); 106 } 107 108 return 0; 109} 110 111static int ufs_intel_disable_lcc(struct ufs_hba *hba) 112{ 113 u32 attr = UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE); 114 u32 lcc_enable = 0; 115 116 ufshcd_dme_get(hba, attr, &lcc_enable); 117 if (lcc_enable) 118 ufshcd_disable_host_tx_lcc(hba); 119 120 return 0; 121} 122 123static int ufs_intel_link_startup_notify(struct ufs_hba *hba, 124 enum ufs_notify_change_status status) 125{ 126 int err = 0; 127 128 switch (status) { 129 case PRE_CHANGE: 130 err = ufs_intel_disable_lcc(hba); 131 break; 132 case POST_CHANGE: 133 break; 134 default: 135 break; 136 } 137 138 return err; 139} 140 141static int ufs_intel_set_lanes(struct ufs_hba *hba, u32 lanes) 142{ 143 struct ufs_pa_layer_attr pwr_info = hba->pwr_info; 144 int ret; 145 146 pwr_info.lane_rx = lanes; 147 pwr_info.lane_tx = lanes; 148 ret = ufshcd_config_pwr_mode(hba, &pwr_info); 149 if (ret) 150 dev_err(hba->dev, "%s: Setting %u lanes, err = %d\n", 151 __func__, lanes, ret); 152 return ret; 153} 154 155static int ufs_intel_lkf_pwr_change_notify(struct ufs_hba *hba, 156 enum ufs_notify_change_status status, 157 const struct ufs_pa_layer_attr *dev_max_params, 158 struct ufs_pa_layer_attr *dev_req_params) 159{ 160 int err = 0; 161 162 switch (status) { 163 case PRE_CHANGE: 164 if (ufshcd_is_hs_mode(dev_max_params) && 165 (hba->pwr_info.lane_rx != 2 || hba->pwr_info.lane_tx != 2)) 166 ufs_intel_set_lanes(hba, 2); 167 memcpy(dev_req_params, dev_max_params, sizeof(*dev_req_params)); 168 break; 169 case POST_CHANGE: 170 if (ufshcd_is_hs_mode(dev_req_params)) { 171 u32 peer_granularity; 172 173 usleep_range(1000, 1250); 174 err = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_GRANULARITY), 175 &peer_granularity); 176 } 177 break; 178 default: 179 break; 180 } 181 182 return err; 183} 184 185static int ufs_intel_lkf_apply_dev_quirks(struct ufs_hba *hba) 186{ 187 u32 granularity, peer_granularity; 188 u32 pa_tactivate, peer_pa_tactivate; 189 int ret; 190 191 ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_GRANULARITY), &granularity); 192 if (ret) 193 goto out; 194 195 ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_GRANULARITY), &peer_granularity); 196 if (ret) 197 goto out; 198 199 ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_TACTIVATE), &pa_tactivate); 200 if (ret) 201 goto out; 202 203 ret = ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_TACTIVATE), &peer_pa_tactivate); 204 if (ret) 205 goto out; 206 207 if (granularity == peer_granularity) { 208 u32 new_peer_pa_tactivate = pa_tactivate + 2; 209 210 ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(PA_TACTIVATE), new_peer_pa_tactivate); 211 } 212out: 213 return ret; 214} 215 216#define INTEL_ACTIVELTR 0x804 217#define INTEL_IDLELTR 0x808 218 219#define INTEL_LTR_REQ BIT(15) 220#define INTEL_LTR_SCALE_MASK GENMASK(11, 10) 221#define INTEL_LTR_SCALE_1US (2 << 10) 222#define INTEL_LTR_SCALE_32US (3 << 10) 223#define INTEL_LTR_VALUE_MASK GENMASK(9, 0) 224 225static void intel_cache_ltr(struct ufs_hba *hba) 226{ 227 struct intel_host *host = ufshcd_get_variant(hba); 228 229 host->active_ltr = readl(hba->mmio_base + INTEL_ACTIVELTR); 230 host->idle_ltr = readl(hba->mmio_base + INTEL_IDLELTR); 231} 232 233static void intel_ltr_set(struct device *dev, s32 val) 234{ 235 struct ufs_hba *hba = dev_get_drvdata(dev); 236 struct intel_host *host = ufshcd_get_variant(hba); 237 u32 ltr; 238 239 pm_runtime_get_sync(dev); 240 241 /* 242 * Program latency tolerance (LTR) accordingly what has been asked 243 * by the PM QoS layer or disable it in case we were passed 244 * negative value or PM_QOS_LATENCY_ANY. 245 */ 246 ltr = readl(hba->mmio_base + INTEL_ACTIVELTR); 247 248 if (val == PM_QOS_LATENCY_ANY || val < 0) { 249 ltr &= ~INTEL_LTR_REQ; 250 } else { 251 ltr |= INTEL_LTR_REQ; 252 ltr &= ~INTEL_LTR_SCALE_MASK; 253 ltr &= ~INTEL_LTR_VALUE_MASK; 254 255 if (val > INTEL_LTR_VALUE_MASK) { 256 val >>= 5; 257 if (val > INTEL_LTR_VALUE_MASK) 258 val = INTEL_LTR_VALUE_MASK; 259 ltr |= INTEL_LTR_SCALE_32US | val; 260 } else { 261 ltr |= INTEL_LTR_SCALE_1US | val; 262 } 263 } 264 265 if (ltr == host->active_ltr) 266 goto out; 267 268 writel(ltr, hba->mmio_base + INTEL_ACTIVELTR); 269 writel(ltr, hba->mmio_base + INTEL_IDLELTR); 270 271 /* Cache the values into intel_host structure */ 272 intel_cache_ltr(hba); 273out: 274 pm_runtime_put(dev); 275} 276 277static void intel_ltr_expose(struct device *dev) 278{ 279 dev->power.set_latency_tolerance = intel_ltr_set; 280 dev_pm_qos_expose_latency_tolerance(dev); 281} 282 283static void intel_ltr_hide(struct device *dev) 284{ 285 dev_pm_qos_hide_latency_tolerance(dev); 286 dev->power.set_latency_tolerance = NULL; 287} 288 289static void intel_add_debugfs(struct ufs_hba *hba) 290{ 291 struct dentry *dir = debugfs_create_dir(dev_name(hba->dev), NULL); 292 struct intel_host *host = ufshcd_get_variant(hba); 293 294 intel_cache_ltr(hba); 295 296 host->debugfs_root = dir; 297 debugfs_create_x32("active_ltr", 0444, dir, &host->active_ltr); 298 debugfs_create_x32("idle_ltr", 0444, dir, &host->idle_ltr); 299} 300 301static void intel_remove_debugfs(struct ufs_hba *hba) 302{ 303 struct intel_host *host = ufshcd_get_variant(hba); 304 305 debugfs_remove_recursive(host->debugfs_root); 306} 307 308static int ufs_intel_device_reset(struct ufs_hba *hba) 309{ 310 struct intel_host *host = ufshcd_get_variant(hba); 311 312 if (INTEL_DSM_SUPPORTED(host, RESET)) { 313 u32 result = 0; 314 int err; 315 316 err = intel_dsm(host, hba->dev, INTEL_DSM_RESET, &result); 317 if (!err && !result) 318 err = -EIO; 319 if (err) 320 dev_err(hba->dev, "%s: DSM error %d result %u\n", 321 __func__, err, result); 322 return err; 323 } 324 325 if (!host->reset_gpio) 326 return -EOPNOTSUPP; 327 328 gpiod_set_value_cansleep(host->reset_gpio, 1); 329 usleep_range(10, 15); 330 331 gpiod_set_value_cansleep(host->reset_gpio, 0); 332 usleep_range(10, 15); 333 334 return 0; 335} 336 337static struct gpio_desc *ufs_intel_get_reset_gpio(struct device *dev) 338{ 339 /* GPIO in _DSD has active low setting */ 340 return devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 341} 342 343static int ufs_intel_common_init(struct ufs_hba *hba) 344{ 345 struct intel_host *host; 346 347 hba->caps |= UFSHCD_CAP_RPM_AUTOSUSPEND; 348 349 host = devm_kzalloc(hba->dev, sizeof(*host), GFP_KERNEL); 350 if (!host) 351 return -ENOMEM; 352 host->saved_spm_lvl = -1; 353 ufshcd_set_variant(hba, host); 354 intel_dsm_init(host, hba->dev); 355 if (INTEL_DSM_SUPPORTED(host, RESET)) { 356 if (hba->vops->device_reset) 357 hba->caps |= UFSHCD_CAP_DEEPSLEEP; 358 } else { 359 if (hba->vops->device_reset) 360 host->reset_gpio = ufs_intel_get_reset_gpio(hba->dev); 361 if (IS_ERR(host->reset_gpio)) { 362 dev_err(hba->dev, "%s: failed to get reset GPIO, error %ld\n", 363 __func__, PTR_ERR(host->reset_gpio)); 364 host->reset_gpio = NULL; 365 } 366 if (host->reset_gpio) { 367 gpiod_set_value_cansleep(host->reset_gpio, 0); 368 hba->caps |= UFSHCD_CAP_DEEPSLEEP; 369 } 370 } 371 intel_ltr_expose(hba->dev); 372 intel_add_debugfs(hba); 373 return 0; 374} 375 376static void ufs_intel_common_exit(struct ufs_hba *hba) 377{ 378 intel_remove_debugfs(hba); 379 intel_ltr_hide(hba->dev); 380} 381 382static int ufs_intel_resume(struct ufs_hba *hba, enum ufs_pm_op op) 383{ 384 if (ufshcd_is_link_hibern8(hba)) { 385 int ret = ufshcd_uic_hibern8_exit(hba); 386 387 if (!ret) { 388 ufshcd_set_link_active(hba); 389 } else { 390 dev_err(hba->dev, "%s: hibern8 exit failed %d\n", 391 __func__, ret); 392 /* 393 * Force reset and restore. Any other actions can lead 394 * to an unrecoverable state. 395 */ 396 ufshcd_set_link_off(hba); 397 } 398 } 399 400 return 0; 401} 402 403static int ufs_intel_ehl_init(struct ufs_hba *hba) 404{ 405 hba->quirks |= UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8; 406 return ufs_intel_common_init(hba); 407} 408 409static int ufs_intel_lkf_init(struct ufs_hba *hba) 410{ 411 int err; 412 413 hba->nop_out_timeout = 200; 414 hba->quirks |= UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8; 415 hba->caps |= UFSHCD_CAP_CRYPTO; 416 err = ufs_intel_common_init(hba); 417 /* LKF always needs a full reset, so set PM accordingly */ 418 if (hba->caps & UFSHCD_CAP_DEEPSLEEP) { 419 hba->spm_lvl = UFS_PM_LVL_6; 420 hba->rpm_lvl = UFS_PM_LVL_6; 421 } else { 422 hba->spm_lvl = UFS_PM_LVL_5; 423 hba->rpm_lvl = UFS_PM_LVL_5; 424 } 425 return err; 426} 427 428static int ufs_intel_adl_init(struct ufs_hba *hba) 429{ 430 hba->nop_out_timeout = 200; 431 hba->quirks |= UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8 | 432 UFSHCD_QUIRK_PERFORM_LINK_STARTUP_ONCE; 433 hba->caps |= UFSHCD_CAP_WB_EN; 434 return ufs_intel_common_init(hba); 435} 436 437static int ufs_intel_mtl_init(struct ufs_hba *hba) 438{ 439 hba->rpm_lvl = UFS_PM_LVL_2; 440 hba->spm_lvl = UFS_PM_LVL_2; 441 hba->caps |= UFSHCD_CAP_CRYPTO | UFSHCD_CAP_WB_EN; 442 return ufs_intel_common_init(hba); 443} 444 445static int ufs_qemu_get_hba_mac(struct ufs_hba *hba) 446{ 447 return MAX_SUPP_MAC; 448} 449 450static int ufs_qemu_mcq_config_resource(struct ufs_hba *hba) 451{ 452 hba->mcq_base = hba->mmio_base + ufshcd_mcq_queue_cfg_addr(hba); 453 454 return 0; 455} 456 457static int ufs_qemu_op_runtime_config(struct ufs_hba *hba) 458{ 459 struct ufshcd_mcq_opr_info_t *opr; 460 int i; 461 462 u32 sqdao = ufsmcq_readl(hba, ufshcd_mcq_cfg_offset(REG_SQDAO, 0)); 463 u32 sqisao = ufsmcq_readl(hba, ufshcd_mcq_cfg_offset(REG_SQISAO, 0)); 464 u32 cqdao = ufsmcq_readl(hba, ufshcd_mcq_cfg_offset(REG_CQDAO, 0)); 465 u32 cqisao = ufsmcq_readl(hba, ufshcd_mcq_cfg_offset(REG_CQISAO, 0)); 466 467 hba->mcq_opr[OPR_SQD].offset = sqdao; 468 hba->mcq_opr[OPR_SQIS].offset = sqisao; 469 hba->mcq_opr[OPR_CQD].offset = cqdao; 470 hba->mcq_opr[OPR_CQIS].offset = cqisao; 471 472 for (i = 0; i < OPR_MAX; i++) { 473 opr = &hba->mcq_opr[i]; 474 opr->stride = 48; 475 opr->base = hba->mmio_base + opr->offset; 476 } 477 478 return 0; 479} 480 481static struct ufs_hba_variant_ops ufs_qemu_hba_vops = { 482 .name = "qemu-pci", 483 .get_hba_mac = ufs_qemu_get_hba_mac, 484 .mcq_config_resource = ufs_qemu_mcq_config_resource, 485 .op_runtime_config = ufs_qemu_op_runtime_config, 486}; 487 488static struct ufs_hba_variant_ops ufs_intel_cnl_hba_vops = { 489 .name = "intel-pci", 490 .init = ufs_intel_common_init, 491 .exit = ufs_intel_common_exit, 492 .link_startup_notify = ufs_intel_link_startup_notify, 493 .resume = ufs_intel_resume, 494}; 495 496static struct ufs_hba_variant_ops ufs_intel_ehl_hba_vops = { 497 .name = "intel-pci", 498 .init = ufs_intel_ehl_init, 499 .exit = ufs_intel_common_exit, 500 .link_startup_notify = ufs_intel_link_startup_notify, 501 .resume = ufs_intel_resume, 502}; 503 504static struct ufs_hba_variant_ops ufs_intel_lkf_hba_vops = { 505 .name = "intel-pci", 506 .init = ufs_intel_lkf_init, 507 .exit = ufs_intel_common_exit, 508 .hce_enable_notify = ufs_intel_hce_enable_notify, 509 .link_startup_notify = ufs_intel_link_startup_notify, 510 .pwr_change_notify = ufs_intel_lkf_pwr_change_notify, 511 .apply_dev_quirks = ufs_intel_lkf_apply_dev_quirks, 512 .resume = ufs_intel_resume, 513 .device_reset = ufs_intel_device_reset, 514}; 515 516static struct ufs_hba_variant_ops ufs_intel_adl_hba_vops = { 517 .name = "intel-pci", 518 .init = ufs_intel_adl_init, 519 .exit = ufs_intel_common_exit, 520 .link_startup_notify = ufs_intel_link_startup_notify, 521 .resume = ufs_intel_resume, 522 .device_reset = ufs_intel_device_reset, 523}; 524 525static struct ufs_hba_variant_ops ufs_intel_mtl_hba_vops = { 526 .name = "intel-pci", 527 .init = ufs_intel_mtl_init, 528 .exit = ufs_intel_common_exit, 529 .hce_enable_notify = ufs_intel_hce_enable_notify, 530 .link_startup_notify = ufs_intel_link_startup_notify, 531 .resume = ufs_intel_resume, 532 .device_reset = ufs_intel_device_reset, 533}; 534 535#ifdef CONFIG_PM_SLEEP 536static int ufshcd_pci_restore(struct device *dev) 537{ 538 struct ufs_hba *hba = dev_get_drvdata(dev); 539 540 /* Force a full reset and restore */ 541 ufshcd_set_link_off(hba); 542 543 return ufshcd_system_resume(dev); 544} 545 546static int ufs_intel_suspend_prepare(struct device *dev) 547{ 548 struct ufs_hba *hba = dev_get_drvdata(dev); 549 struct intel_host *host = ufshcd_get_variant(hba); 550 int err; 551 552 /* 553 * Only s2idle (S0ix) retains link state. Force power-off 554 * (UFS_PM_LVL_5) for any other case. 555 */ 556 if (pm_suspend_target_state != PM_SUSPEND_TO_IDLE && hba->spm_lvl < UFS_PM_LVL_5) { 557 host->saved_spm_lvl = hba->spm_lvl; 558 hba->spm_lvl = UFS_PM_LVL_5; 559 } 560 561 err = ufshcd_suspend_prepare(dev); 562 563 if (err < 0 && host->saved_spm_lvl != -1) { 564 hba->spm_lvl = host->saved_spm_lvl; 565 host->saved_spm_lvl = -1; 566 } 567 568 return err; 569} 570 571static void ufs_intel_resume_complete(struct device *dev) 572{ 573 struct ufs_hba *hba = dev_get_drvdata(dev); 574 struct intel_host *host = ufshcd_get_variant(hba); 575 576 ufshcd_resume_complete(dev); 577 578 if (host->saved_spm_lvl != -1) { 579 hba->spm_lvl = host->saved_spm_lvl; 580 host->saved_spm_lvl = -1; 581 } 582} 583 584static int ufshcd_pci_suspend_prepare(struct device *dev) 585{ 586 struct ufs_hba *hba = dev_get_drvdata(dev); 587 588 if (!strcmp(hba->vops->name, "intel-pci")) 589 return ufs_intel_suspend_prepare(dev); 590 591 return ufshcd_suspend_prepare(dev); 592} 593 594static void ufshcd_pci_resume_complete(struct device *dev) 595{ 596 struct ufs_hba *hba = dev_get_drvdata(dev); 597 598 if (!strcmp(hba->vops->name, "intel-pci")) { 599 ufs_intel_resume_complete(dev); 600 return; 601 } 602 603 ufshcd_resume_complete(dev); 604} 605#endif 606 607/** 608 * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space 609 * data structure memory 610 * @pdev: pointer to PCI handle 611 */ 612static void ufshcd_pci_remove(struct pci_dev *pdev) 613{ 614 struct ufs_hba *hba = pci_get_drvdata(pdev); 615 616 pm_runtime_forbid(&pdev->dev); 617 pm_runtime_get_noresume(&pdev->dev); 618 ufshcd_remove(hba); 619} 620 621/** 622 * ufshcd_pci_probe - probe routine of the driver 623 * @pdev: pointer to PCI device handle 624 * @id: PCI device id 625 * 626 * Return: 0 on success, non-zero value on failure. 627 */ 628static int 629ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 630{ 631 struct ufs_hba *hba; 632 void __iomem *mmio_base; 633 int err; 634 635 err = pcim_enable_device(pdev); 636 if (err) { 637 dev_err(&pdev->dev, "pcim_enable_device failed\n"); 638 return err; 639 } 640 641 pci_set_master(pdev); 642 643 mmio_base = pcim_iomap_region(pdev, 0, UFSHCD); 644 if (IS_ERR(mmio_base)) { 645 dev_err(&pdev->dev, "request and iomap failed\n"); 646 return PTR_ERR(mmio_base); 647 } 648 649 err = ufshcd_alloc_host(&pdev->dev, &hba); 650 if (err) { 651 dev_err(&pdev->dev, "Allocation failed\n"); 652 return err; 653 } 654 655 hba->vops = (struct ufs_hba_variant_ops *)id->driver_data; 656 657 err = ufshcd_init(hba, mmio_base, pdev->irq); 658 if (err) { 659 dev_err(&pdev->dev, "Initialization failed\n"); 660 return err; 661 } 662 663 pm_runtime_put_noidle(&pdev->dev); 664 pm_runtime_allow(&pdev->dev); 665 666 return 0; 667} 668 669static const struct dev_pm_ops ufshcd_pci_pm_ops = { 670 SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL) 671#ifdef CONFIG_PM_SLEEP 672 .suspend = ufshcd_system_suspend, 673 .resume = ufshcd_system_resume, 674 .freeze = ufshcd_system_suspend, 675 .thaw = ufshcd_system_resume, 676 .poweroff = ufshcd_system_suspend, 677 .restore = ufshcd_pci_restore, 678 .prepare = ufshcd_pci_suspend_prepare, 679 .complete = ufshcd_pci_resume_complete, 680#endif 681}; 682 683static const struct pci_device_id ufshcd_pci_tbl[] = { 684 { PCI_VENDOR_ID_REDHAT, 0x0013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 685 (kernel_ulong_t)&ufs_qemu_hba_vops }, 686 { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 687 { PCI_VDEVICE(INTEL, 0x9DFA), (kernel_ulong_t)&ufs_intel_cnl_hba_vops }, 688 { PCI_VDEVICE(INTEL, 0x4B41), (kernel_ulong_t)&ufs_intel_ehl_hba_vops }, 689 { PCI_VDEVICE(INTEL, 0x4B43), (kernel_ulong_t)&ufs_intel_ehl_hba_vops }, 690 { PCI_VDEVICE(INTEL, 0x98FA), (kernel_ulong_t)&ufs_intel_lkf_hba_vops }, 691 { PCI_VDEVICE(INTEL, 0x51FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops }, 692 { PCI_VDEVICE(INTEL, 0x54FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops }, 693 { PCI_VDEVICE(INTEL, 0x7E47), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, 694 { PCI_VDEVICE(INTEL, 0xA847), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, 695 { PCI_VDEVICE(INTEL, 0x7747), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, 696 { PCI_VDEVICE(INTEL, 0xE447), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, 697 { PCI_VDEVICE(INTEL, 0x4D47), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, 698 { } /* terminate list */ 699}; 700 701MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl); 702 703static struct pci_driver ufshcd_pci_driver = { 704 .name = UFSHCD, 705 .id_table = ufshcd_pci_tbl, 706 .probe = ufshcd_pci_probe, 707 .remove = ufshcd_pci_remove, 708 .driver = { 709 .pm = &ufshcd_pci_pm_ops 710 }, 711}; 712 713module_pci_driver(ufshcd_pci_driver); 714 715MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>"); 716MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>"); 717MODULE_DESCRIPTION("UFS host controller PCI glue driver"); 718MODULE_LICENSE("GPL");
~/
Read-only file preview.