Message ID | 20220121110909.104-1-chevron.li@bayhubtech.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/2] mmc:sdhci-msm:fix Qualcomm sd host 7180 SD card compatibility issue | expand |
Hi Chevron, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on c9e6606c7fe92b50a02ce51dda82586ebdf99b48] url: https://github.com/0day-ci/linux/commits/Chevron-Li/mmc-sdhci-msm-fix-Qualcomm-sd-host-7180-SD-card-compatibility-issue/20220121-191113 base: c9e6606c7fe92b50a02ce51dda82586ebdf99b48 config: arc-randconfig-r043-20220121 (https://download.01.org/0day-ci/archive/20220122/202201220531.njLkAypI-lkp@intel.com/config) compiler: arceb-elf-gcc (GCC) 11.2.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/bba780c9359fe89c2a3e769bfa6373f58b90ee76 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Chevron-Li/mmc-sdhci-msm-fix-Qualcomm-sd-host-7180-SD-card-compatibility-issue/20220121-191113 git checkout bba780c9359fe89c2a3e769bfa6373f58b90ee76 # save the config file to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arc SHELL=/bin/bash If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): drivers/mmc/host/sdhci-msm.c: In function 'sdhci_msm_probe': >> drivers/mmc/host/sdhci-msm.c:2535:40: warning: variable 'bht_host' set but not used [-Wunused-but-set-variable] 2535 | struct sdhci_bht_host *bht_host; | ^~~~~~~~ vim +/bht_host +2535 drivers/mmc/host/sdhci-msm.c 2498 2499 2500 static int sdhci_msm_probe(struct platform_device *pdev) 2501 { 2502 struct sdhci_host *host; 2503 struct sdhci_pltfm_host *pltfm_host; 2504 struct sdhci_msm_host *msm_host; 2505 struct clk *clk; 2506 int ret; 2507 u16 host_version, core_minor; 2508 u32 core_version, config; 2509 u8 core_major; 2510 const struct sdhci_msm_offset *msm_offset; 2511 const struct sdhci_msm_variant_info *var_info; 2512 struct device_node *node = pdev->dev.of_node; 2513 2514 /* Bayhub patch: memory allocate for sdhci_bht_host structure */ 2515 if (of_find_property(node, "use-bayhub-bh201", NULL)) 2516 host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, 2517 sizeof(*msm_host) + sizeof(struct sdhci_bht_host)); 2518 else 2519 host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host)); 2520 if (IS_ERR(host)) 2521 return PTR_ERR(host); 2522 2523 host->sdma_boundary = 0; 2524 pltfm_host = sdhci_priv(host); 2525 msm_host = sdhci_pltfm_priv(pltfm_host); 2526 msm_host->mmc = host->mmc; 2527 msm_host->pdev = pdev; 2528 2529 ret = mmc_of_parse(host->mmc); 2530 if (ret) 2531 goto pltfm_free; 2532 2533 /* Bayhub patch: resource assign and mmc_rescan routine overload */ 2534 if (of_find_property(node, "use-bayhub-bh201", NULL)) { > 2535 struct sdhci_bht_host *bht_host; 2536 2537 bht_host = sdhci_msm_priv(msm_host); 2538 sdhci_bht_parse(msm_host->mmc); 2539 INIT_DELAYED_WORK(&host->mmc->detect, mmc_rescan_bht); 2540 } 2541 2542 /* 2543 * Based on the compatible string, load the required msm host info from 2544 * the data associated with the version info. 2545 */ 2546 var_info = of_device_get_match_data(&pdev->dev); 2547 2548 msm_host->mci_removed = var_info->mci_removed; 2549 msm_host->restore_dll_config = var_info->restore_dll_config; 2550 msm_host->var_ops = var_info->var_ops; 2551 msm_host->offset = var_info->offset; 2552 2553 msm_offset = msm_host->offset; 2554 2555 sdhci_get_of_property(pdev); 2556 sdhci_msm_get_of_property(pdev, host); 2557 2558 msm_host->saved_tuning_phase = INVALID_TUNING_PHASE; 2559 2560 /* Setup SDCC bus voter clock. */ 2561 msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus"); 2562 if (!IS_ERR(msm_host->bus_clk)) { 2563 /* Vote for max. clk rate for max. performance */ 2564 ret = clk_set_rate(msm_host->bus_clk, INT_MAX); 2565 if (ret) 2566 goto pltfm_free; 2567 ret = clk_prepare_enable(msm_host->bus_clk); 2568 if (ret) 2569 goto pltfm_free; 2570 } 2571 2572 /* Setup main peripheral bus clock */ 2573 clk = devm_clk_get(&pdev->dev, "iface"); 2574 if (IS_ERR(clk)) { 2575 ret = PTR_ERR(clk); 2576 dev_err(&pdev->dev, "Peripheral clk setup failed (%d)\n", ret); 2577 goto bus_clk_disable; 2578 } 2579 msm_host->bulk_clks[1].clk = clk; 2580 2581 /* Setup SDC MMC clock */ 2582 clk = devm_clk_get(&pdev->dev, "core"); 2583 if (IS_ERR(clk)) { 2584 ret = PTR_ERR(clk); 2585 dev_err(&pdev->dev, "SDC MMC clk setup failed (%d)\n", ret); 2586 goto bus_clk_disable; 2587 } 2588 msm_host->bulk_clks[0].clk = clk; 2589 2590 /* Check for optional interconnect paths */ 2591 ret = dev_pm_opp_of_find_icc_paths(&pdev->dev, NULL); 2592 if (ret) 2593 goto bus_clk_disable; 2594 2595 ret = devm_pm_opp_set_clkname(&pdev->dev, "core"); 2596 if (ret) 2597 goto bus_clk_disable; 2598 2599 /* OPP table is optional */ 2600 ret = devm_pm_opp_of_add_table(&pdev->dev); 2601 if (ret && ret != -ENODEV) { 2602 dev_err(&pdev->dev, "Invalid OPP table in Device tree\n"); 2603 goto bus_clk_disable; 2604 } 2605 2606 /* Vote for maximum clock rate for maximum performance */ 2607 ret = dev_pm_opp_set_rate(&pdev->dev, INT_MAX); 2608 if (ret) 2609 dev_warn(&pdev->dev, "core clock boost failed\n"); 2610 2611 clk = devm_clk_get(&pdev->dev, "cal"); 2612 if (IS_ERR(clk)) 2613 clk = NULL; 2614 msm_host->bulk_clks[2].clk = clk; 2615 2616 clk = devm_clk_get(&pdev->dev, "sleep"); 2617 if (IS_ERR(clk)) 2618 clk = NULL; 2619 msm_host->bulk_clks[3].clk = clk; 2620 2621 clk = sdhci_msm_ice_get_clk(&pdev->dev); 2622 if (IS_ERR(clk)) 2623 clk = NULL; 2624 msm_host->bulk_clks[4].clk = clk; 2625 2626 ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks), 2627 msm_host->bulk_clks); 2628 if (ret) 2629 goto bus_clk_disable; 2630 2631 /* 2632 * xo clock is needed for FLL feature of cm_dll. 2633 * In case if xo clock is not mentioned in DT, warn and proceed. 2634 */ 2635 msm_host->xo_clk = devm_clk_get(&pdev->dev, "xo"); 2636 if (IS_ERR(msm_host->xo_clk)) { 2637 ret = PTR_ERR(msm_host->xo_clk); 2638 dev_warn(&pdev->dev, "TCXO clk not present (%d)\n", ret); 2639 } 2640 2641 if (!msm_host->mci_removed) { 2642 msm_host->core_mem = devm_platform_ioremap_resource(pdev, 1); 2643 if (IS_ERR(msm_host->core_mem)) { 2644 ret = PTR_ERR(msm_host->core_mem); 2645 goto clk_disable; 2646 } 2647 } 2648 2649 /* Reset the vendor spec register to power on reset state */ 2650 writel_relaxed(CORE_VENDOR_SPEC_POR_VAL, 2651 host->ioaddr + msm_offset->core_vendor_spec); 2652 2653 if (!msm_host->mci_removed) { 2654 /* Set HC_MODE_EN bit in HC_MODE register */ 2655 msm_host_writel(msm_host, HC_MODE_EN, host, 2656 msm_offset->core_hc_mode); 2657 config = msm_host_readl(msm_host, host, 2658 msm_offset->core_hc_mode); 2659 config |= FF_CLK_SW_RST_DIS; 2660 msm_host_writel(msm_host, config, host, 2661 msm_offset->core_hc_mode); 2662 } 2663 2664 host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION)); 2665 dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n", 2666 host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >> 2667 SDHCI_VENDOR_VER_SHIFT)); 2668 2669 core_version = msm_host_readl(msm_host, host, 2670 msm_offset->core_mci_version); 2671 core_major = (core_version & CORE_VERSION_MAJOR_MASK) >> 2672 CORE_VERSION_MAJOR_SHIFT; 2673 core_minor = core_version & CORE_VERSION_MINOR_MASK; 2674 dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n", 2675 core_version, core_major, core_minor); 2676 2677 if (core_major == 1 && core_minor >= 0x42) 2678 msm_host->use_14lpp_dll_reset = true; 2679 2680 /* 2681 * SDCC 5 controller with major version 1, minor version 0x34 and later 2682 * with HS 400 mode support will use CM DLL instead of CDC LP 533 DLL. 2683 */ 2684 if (core_major == 1 && core_minor < 0x34) 2685 msm_host->use_cdclp533 = true; 2686 2687 /* 2688 * Support for some capabilities is not advertised by newer 2689 * controller versions and must be explicitly enabled. 2690 */ 2691 if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) { 2692 config = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES); 2693 config |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT; 2694 writel_relaxed(config, host->ioaddr + 2695 msm_offset->core_vendor_spec_capabilities0); 2696 } 2697 2698 if (core_major == 1 && core_minor >= 0x49) 2699 msm_host->updated_ddr_cfg = true; 2700 2701 if (core_major == 1 && core_minor >= 0x71) 2702 msm_host->uses_tassadar_dll = true; 2703 2704 ret = sdhci_msm_register_vreg(msm_host); 2705 if (ret) 2706 goto clk_disable; 2707 2708 /* 2709 * Power on reset state may trigger power irq if previous status of 2710 * PWRCTL was either BUS_ON or IO_HIGH_V. So before enabling pwr irq 2711 * interrupt in GIC, any pending power irq interrupt should be 2712 * acknowledged. Otherwise power irq interrupt handler would be 2713 * fired prematurely. 2714 */ 2715 sdhci_msm_handle_pwr_irq(host, 0); 2716 2717 /* 2718 * Ensure that above writes are propogated before interrupt enablement 2719 * in GIC. 2720 */ 2721 mb(); 2722 2723 /* Setup IRQ for handling power/voltage tasks with PMIC */ 2724 msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq"); 2725 if (msm_host->pwr_irq < 0) { 2726 ret = msm_host->pwr_irq; 2727 goto clk_disable; 2728 } 2729 2730 sdhci_msm_init_pwr_irq_wait(msm_host); 2731 /* Enable pwr irq interrupts */ 2732 msm_host_writel(msm_host, INT_MASK, host, 2733 msm_offset->core_pwrctl_mask); 2734 2735 ret = devm_request_threaded_irq(&pdev->dev, msm_host->pwr_irq, NULL, 2736 sdhci_msm_pwr_irq, IRQF_ONESHOT, 2737 dev_name(&pdev->dev), host); 2738 if (ret) { 2739 dev_err(&pdev->dev, "Request IRQ failed (%d)\n", ret); 2740 goto clk_disable; 2741 } 2742 2743 msm_host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_NEED_RSP_BUSY; 2744 2745 /* Set the timeout value to max possible */ 2746 host->max_timeout_count = 0xF; 2747 2748 pm_runtime_get_noresume(&pdev->dev); 2749 pm_runtime_set_active(&pdev->dev); 2750 pm_runtime_enable(&pdev->dev); 2751 pm_runtime_set_autosuspend_delay(&pdev->dev, 2752 MSM_MMC_AUTOSUSPEND_DELAY_MS); 2753 pm_runtime_use_autosuspend(&pdev->dev); 2754 2755 host->mmc_host_ops.start_signal_voltage_switch = 2756 sdhci_msm_start_signal_voltage_switch; 2757 host->mmc_host_ops.execute_tuning = sdhci_msm_execute_tuning; 2758 /* Bayhub patch: overload the mmc_host_ops.execute_tuning routine */ 2759 if (of_find_property(node, "use-bayhub-bh201", NULL)) 2760 host->mmc_host_ops.execute_tuning = sdhci_bht_execute_tuning; 2761 if (of_property_read_bool(node, "supports-cqe")) 2762 ret = sdhci_msm_cqe_add_host(host, pdev); 2763 else 2764 ret = sdhci_add_host(host); 2765 if (ret) 2766 goto pm_runtime_disable; 2767 2768 pm_runtime_mark_last_busy(&pdev->dev); 2769 pm_runtime_put_autosuspend(&pdev->dev); 2770 2771 return 0; 2772 2773 pm_runtime_disable: 2774 pm_runtime_disable(&pdev->dev); 2775 pm_runtime_set_suspended(&pdev->dev); 2776 pm_runtime_put_noidle(&pdev->dev); 2777 clk_disable: 2778 clk_bulk_disable_unprepare(ARRAY_SIZE(msm_host->bulk_clks), 2779 msm_host->bulk_clks); 2780 bus_clk_disable: 2781 if (!IS_ERR(msm_host->bus_clk)) 2782 clk_disable_unprepare(msm_host->bus_clk); 2783 pltfm_free: 2784 /* Bayhub patch: release assigned resource */ 2785 if (of_find_property(node, "use-bayhub-bh201", NULL)) 2786 sdhci_bht_resource_free(msm_host); 2787 sdhci_pltfm_free(pdev); 2788 return ret; 2789 } 2790 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/drivers/mmc/host/sdhci-bayhub.c b/drivers/mmc/host/sdhci-bayhub.c new file mode 100644 index 000000000000..867d465ce848 --- /dev/null +++ b/drivers/mmc/host/sdhci-bayhub.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Bayhub Technologies, Inc. BH201 SDHCI bridge IC for + * VENDOR SDHCI platform driver source file + * + * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + */ + +struct sdhci_bht_host { +}; + +static void bht_signal_voltage_on_off(struct sdhci_host *host, u32 on_off) +{ +} + +static void sdhci_bht_parse(struct mmc_host *mmc_host) +{ +} + +static void sdhci_bht_resource_free(struct sdhci_msm_host *vendor_host) +{ +} + +static void mmc_rescan_bht(struct work_struct *work) +{ +} + +static int sdhci_bht_execute_tuning(struct mmc_host *mmc, u32 opcode) +{ + int ret = 0; + + return ret; +} + diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 50c71e0ba5e4..5e19d34ef25c 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -285,8 +285,14 @@ struct sdhci_msm_host { u32 dll_config; u32 ddr_config; bool vqmmc_enabled; + unsigned long private[] ____cacheline_aligned; }; +static inline void *sdhci_msm_priv(struct sdhci_msm_host *msm_host) +{ + return (void *)msm_host->private; +} + static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -1585,6 +1591,8 @@ static void sdhci_msm_dump_pwr_ctrl_regs(struct sdhci_host *host) msm_host_readl(msm_host, host, msm_offset->core_pwrctl_mask), msm_host_readl(msm_host, host, msm_offset->core_pwrctl_ctl)); } +/* include bayhub patch for GGC chip support */ +#include "sdhci-bayhub.c" static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq) { @@ -1628,10 +1636,16 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq) /* Handle BUS ON/OFF*/ if (irq_status & CORE_PWRCTL_BUS_ON) { + /* Bayhub patch: GGC chip power on patch */ + if (of_find_property(msm_host->pdev->dev.of_node, "use-bayhub-bh201", NULL)) + bht_signal_voltage_on_off(host, 1); pwr_state = REQ_BUS_ON; io_level = REQ_IO_HIGH; } if (irq_status & CORE_PWRCTL_BUS_OFF) { + /* Bayhub patch: GGC chip power off patch */ + if (of_find_property(msm_host->pdev->dev.of_node, "use-bayhub-bh201", NULL)) + bht_signal_voltage_on_off(host, 0); pwr_state = REQ_BUS_OFF; io_level = REQ_IO_LOW; } @@ -2497,7 +2511,12 @@ static int sdhci_msm_probe(struct platform_device *pdev) const struct sdhci_msm_variant_info *var_info; struct device_node *node = pdev->dev.of_node; - host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host)); + /* Bayhub patch: memory allocate for sdhci_bht_host structure */ + if (of_find_property(node, "use-bayhub-bh201", NULL)) + host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, + sizeof(*msm_host) + sizeof(struct sdhci_bht_host)); + else + host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host)); if (IS_ERR(host)) return PTR_ERR(host); @@ -2511,6 +2530,15 @@ static int sdhci_msm_probe(struct platform_device *pdev) if (ret) goto pltfm_free; + /* Bayhub patch: resource assign and mmc_rescan routine overload */ + if (of_find_property(node, "use-bayhub-bh201", NULL)) { + struct sdhci_bht_host *bht_host; + + bht_host = sdhci_msm_priv(msm_host); + sdhci_bht_parse(msm_host->mmc); + INIT_DELAYED_WORK(&host->mmc->detect, mmc_rescan_bht); + } + /* * Based on the compatible string, load the required msm host info from * the data associated with the version info. @@ -2727,6 +2755,9 @@ static int sdhci_msm_probe(struct platform_device *pdev) host->mmc_host_ops.start_signal_voltage_switch = sdhci_msm_start_signal_voltage_switch; host->mmc_host_ops.execute_tuning = sdhci_msm_execute_tuning; + /* Bayhub patch: overload the mmc_host_ops.execute_tuning routine */ + if (of_find_property(node, "use-bayhub-bh201", NULL)) + host->mmc_host_ops.execute_tuning = sdhci_bht_execute_tuning; if (of_property_read_bool(node, "supports-cqe")) ret = sdhci_msm_cqe_add_host(host, pdev); else @@ -2750,6 +2781,9 @@ static int sdhci_msm_probe(struct platform_device *pdev) if (!IS_ERR(msm_host->bus_clk)) clk_disable_unprepare(msm_host->bus_clk); pltfm_free: + /* Bayhub patch: release assigned resource */ + if (of_find_property(node, "use-bayhub-bh201", NULL)) + sdhci_bht_resource_free(msm_host); sdhci_pltfm_free(pdev); return ret; } @@ -2763,6 +2797,9 @@ static int sdhci_msm_remove(struct platform_device *pdev) 0xffffffff); sdhci_remove_host(host, dead); + /* Bayhub patch: release assigned resource */ + if (of_find_property(msm_host->pdev->dev.of_node, "use-bayhub-bh201", NULL)) + sdhci_bht_resource_free(msm_host); pm_runtime_get_sync(&pdev->dev); pm_runtime_disable(&pdev->dev);
Improve the signal integrity for long SD bus trace by using SC7180+GGC SD host redriver chip 1.GGC is a SD bus signal re-timing IC that has been paired with the SC7180 sometimes. 2.The key points are initialized GGC chip during SD initialization and use GGC special tuning flow to re-timing SD bus signal. 3.GGC resource is initialized for GGC chip during Qualcomm host probe: 3.1 GGC structure initialization 3.2 GGC GPIO resource assignment 3.3 Reload host->mmc->detect with GGC chip special initiation flow. 3.4 Reload the host->mmc_host_ops.execute_tuning with GGC chip special tuning flow. 4.The function of the patch is already verified on Chrome OS, and Google request us to submit the patch to Linux for them future use. 5.GGC can work with any other standard SDHCI controller to improve SD signal SI and Timing. 6.GGC has cooperated with Intel/Qualcomm/MTK/SPRD sd host already and work well. Signed-off-by: Chevron Li <chevron.li@bayhubtech.com> --- Changes: 1.add a data member in sdhci_msm_host structure for extension 2.add an API to get the extension address from sdhci_msm_host structure 3.add an independent branch for GGC chip support according to the configure of DTSI --- drivers/mmc/host/sdhci-bayhub.c | 34 ++++++++++++++++++++++++++++ drivers/mmc/host/sdhci-msm.c | 39 ++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/host/sdhci-bayhub.c base-commit: c9e6606c7fe92b50a02ce51dda82586ebdf99b48