Merge remote-tracking branch 'origin/msm-5.4' into msm-waipio
* origin/msm-5.4 at kernel.lnx.5.4-200305.1 soc: qcom: pmic_glink: add debugfs to filter logs msm: kgsl: Enable the CX GSDC before accessing IOMMU registers msm: kgsl: Move the IOMMU clocks to the KGSL device msm: kgsl: Move GMU to a component device msm: kgsl: Minor cleanups for kgsl bus probe msm: pcie: Revert "scale CX and rate change after DRV resume" defconfig: Enable CPU isolation cooling device for lahaina NFC: Add driver to configure NFC-I3C controller GPIOs soc: qcom: Kconfig: Fix the dependencies for minidump defconfig: lahaina-qgki: Move minidump to QGKI defconfig: lahaina: Enable qbt_handler DLKM qbt_handler: Make the qbt driver as DLKM for GKI msm: cvp: avoid OOB write while accessing memory clk: qcom: update the DisplayPort clocks scsi: ufs: crypto fix on QTI ufs iommu/arm-smmu: Cleanup qsmmuv500_iova_to_phys_hard() iommu/arm-smmu: Remove DOMAIN_ATTR_DEBUG iommu/arm-smmu: Cleanup arm_smmu_init() iommu/arm-smmu: Rationalize TLB sync timeout handling msm: kgsl: Make a device specific scales_bandwidth function msm-poweroff: Correct the SCM_DLOAD_BOTHDUMPS definition qcom_scm: Add entry for minidump download mode phy: ufs: Refactor phy_power_on and phy_calibrate callbacks dt-bindings: clock: Add support for clock ids for SHIMA drm: Add DisplayPort colorspace property creation function drm: Rename HDMI colorspace property creation function arm64: mm: improve the mem-offline device node availability check arm64: Honor limits set by boot parameter msm: cvp: Add AXI reset pulse msm: kgsl: Set default bus control to true defconfig: lahaina: Enable gpu devfreq governors on lahaina slim-msm-ngd: Check current state of sub system restart notifier slim-msm-ngd: Prevent system suspend during initialization defconfig: lahaina: enable QBT_HANDLER leds: qti-flash: Add maximum available flash current prediction qbt_handler: Change return type of qbt_poll scripts: gki: Ensure HOSTLD and HOSTAR are not changed scsi: ufs-qcom: Refactor phy_power_on/off calls scsi: ufs-qcom: Adjust the order of bus bandwidth voting and unvoting mm/oom-kill: Remove obsolete IS_ENABLED check mm/oom-kill: Add option to panic when killing foreground app defconfig: lahaina: Expose additional page debugging info mm, page_owner: set page owner info for tail pages mm/Kconfig: Re-add HAVE_USERSPACE_LOW_MEMORY_KILLER cnss2: Avoid double calling MHI force wake put cnss2: Add meta into as a segment to firmware RAM dump cnss2: Retry if PCI link training fails ANDROID: kbuild: avoid excessively long argument lists iommu/arm-smmu: Cleanup context fault logging logic trace/sched: Fix compilation issues on !SMP scsi: ufshcd-qti: Always allow vendor to configure clocks scsi: ufs-qcom: Get low power levels from devicetree scsi: ufshcd-qti: enable runtime-pm arm64: defconfig: Enable the pinctrl-shima driver pinctrl: qcom: Add support for Shima SoC pin control drivers: soc: qti: Add support for fingerprint driver ASoC: compare CPU DAI stream name to find BE DAI cnss2: Expose APIs to prevent and allow PCIe L1 state msm: pcie: add option to disable L1ss TO for DRV suspend msm: pcie: cache l1ss timeout in drv_info msm: pcie: scale CX and rate change after DRV resume msm: pcie: provide APIs to prevent and allow PCIe ASPM L1 mmc: sdhci-msm: Support Retention of SDCC Regs in CX Collapse mmc: sdhci-msm: Add SD card DLL setting for SRD104 Mode mmc: sdhci-msm: Add support for bus bandwidth voting cnss2: Extend idle restart timeout msm: ADSPRPC: Enable Asynchronous RPC cnss2: Avoid idle restart completely if reboot is in progress cnss2: Add sysfs entry for system shutdown cnss2: Set WLAON_QFPROM_PWR_CTRL_REG during power on and off cnss2: Add sanity check for cnss pm runtime APIs cnss2: check wlfw mac before switching to mission mode msm: adsprpc: Initialize adsp memory region scsi: ufshcd-qti: Fix null pointer check defconfig: arm64: enable required configs for trusted VM defconfig: arm64: Enable data defconfigs Revert "mm: oom-kill: Add lmk_kill possible for ULMK" iommu/arm-smmu: Add support for active-only interconnect votes sched: walt: Improve the scheduler memshare: Modify the driver to be dynamically loadable msm: ipa: create ipa framework arm64: defconfig: Enable Shima platform arm64: Kconfig: Add config option for Shima slim-msm-ngd: Depend on PIL driver notification instead of qmi msm: kgsl: Initialize LPAC registers interconnect: Print the tag in the debugfs summary ucsi: start usb host mode when partner type is power cable/ufp msm: kgsl: Remove the extra recovery hop msm: kgsl: Set bus scaling function during gmu probe msm: kgsl: Keep a copy of CP INIT cmdstream msm: kgsl: Clear halt before gmu boot qseecom: change qseecom_process_listener_from_smcinvoke firmware: qcom_scm: fix for missing listener id Merge fbe changes from upstream 5.4 msm: kgsl: Override UBWC configuration for A660 based on DDR type msm: kgsl: Add A660 hardware clock gating register values msm: ipa: Fix ipa3_wwan_xmit return type sched: walt: Improve the scheduler sched: walt: Improve the scheduler sched: walt: move walt_stats member in cfs_rq under CFS_BANDWIDTH sched: use rq_clock if WALT is not enabled trace: Add trace points for tasklet entry/exit defconfig: lahaina-qgki: Remove CONFIG_IIO config from QGKI defconfig: enable msm_performance driver on Lahaina interconnect: Move internal structs into a separate file interconnect: qcom: Add multiple voter support defconfig: Enable UFS BSG driver defconfig: lahaina-gki: enable the glink debug spmi controller driver spmi: add glink debug spmi controller driver haven: doorbell: Remove locks around read/send defconfig: arm64: Remove QTEE_SHM_BRIDGE scripts: gki: Add proper MAKE PATH pinctrl: qcom: Correctly configure the SDC2 pins ANDROID: Kconfig.gki: Remove most of the built in qcom clks include: regulator: Add header for RPM-SMD voltage levels dt-bindings: clock: update DisplayPort clock names for Lahaina drivers: llcc: Remove programming of cache override registers serial: msm_geni_serial: Set clock freq correctly for RUMI crypto: msm: add compat_qcedev to support 32bit process msm: adsprpc: protect access of context table soc: qcom: msm_perf: Add msm_performance module ion: don't wakeup refill threads for order-0 requests ion: Reduce secure system heap allocation time by stealing pages usb: dwc3: Do not initiate remote wakeup from core layer clk: qcom: remove flags for byte div clk src slim-msm-ngd: Add qmi deferred response check in pm resume slim-msm-ngd: Add wake lock to avoid race with suspend and SSR dt-bindings: ipcc: Add MPROC signal for TZ scsi: ufshcd-qti: Add quirk to disable fastauto mode scsi: ufshcd-qti: Fix hibern8 timeout during scaling clk: qcom: gpucc-lahaina: Remove CLK_IS_CRITICAL msm-geni-serial: Use dma_alloc_coherent to avoid dma map/unmap usb: gadget: f_fs: set req->num_sgs as 0 for non-sg transfer msm: kgsl: Enable I/O coherency on A660 kernel_headers: Add missing mem-buf.h UAPI header file memshare: Add snapshot of memshare driver thermal: adc-tm: Fix ADC_TM channel mapping thermal: adc-tm: Fix compilation recipe in makefile iio: adc: qcom-spmi-adc5: Add SID in ADC IIO channel properties ion: Fix pool refill error dt-bindings: interconnect: Add disp specific nodes for Lahaina iio: adc: Add full-scale voltage for PMIC7 ADC msm: ipa: Update debugfs to print rules correctly clk: qcom: clk-alpha-pll: Remove already enabled warning in PLL configs msm: ipa: Update WLAN pipes to use WLAN2 clients cnss2: Replace "%p" with "%pK" iio: adc: qcom-vadc-common: Change ADC7 die_temp output unit to mC defconfig: arm64: Enable QCOM_SCM driver arm64: Kconfig: Add ARCH_QCOM dependency for ARCH_QTI_VM defconfig: arm64: Add ARCH_QCOM config haven: Pass doorbell irq number to client callback interconnect: qcom: Remove duplicate compatible string interconnect: qcom: Configure QoS when provider is sync stated interconnect: qcom: Enable the QoS ports iommu: iommu-debug: Fix race with respect to test buffer allocation iommu: qti: Track iommu domains iommu: iommu-debug: Remove CONFIG_IOMMU_DEBUG_TRACKING arm64: defconfig: Disable CONFIG_IOMMU_DEBUG_TRACKING net: wireless: Add snapshot of db.txt Revert "cfg80211: reg: remove support for built-in regdb" interconnect: qcom: Do not set any QoS for the NSP defconfig: msm: Enable QUPv3 drivers on Lahaina QGKI perf image arm64: defconfig: Enable CPUFREQ-HW for Lahaina leds: qti-flash: Add support for qti_flash_led_prepare() msm: adsprpc: Cache invalidate optimization Revert "pinctrl: msm: Configure interrupts as input and gpio mode" msm: adsprpc: Cache flush operation optimization arm64: defconfig: Enable the mem-buf driver on Lahaina QGKI soc: qcom: mem-buf: Add support for inter-VM memory sharing msm: kgsl: Do not mark all buffers as iocoherent arm64: defconfig: Enable CONFIG_PANIC_ON_OOPS arm64: defconfig: Add LOCALVERSION strings for Lahaina clk: qcom: Cache vdd vote if clk is unprepared arm64: defconfig: Enable QCOM watchdog for Lahaina radio: RTC6226: fill device capabilities in video_device thermal: adc-tm: Correct a macro expression for PMIC7 ADC_TM msm: adsprpc: Remove output buffers from cache flush logic msm: adsprpc: Add error handling checks msm: adsprpc: Add force no flush and invalidate flag adsprpc: use uint for counters and maintain consistency in datatypes msm: adsprpc: Remove remote mappings after PD is up clk: qcom: gcc-lahaina: Enable gpu_memnoc_gfx and gpu_snoc_dvm_gfx always msm: cvp: buffer managerment optimization for Lahaina soc: qcom: Add forever loop after non-secure bite configuration defconfig: lahaina: enable FSA driver on Lahaina sched: Provide stub definitions for WALT haven: Add support for MEM_NOTIFY haven: Add support for MEM_SHARE/MEM_LEND haven: Add support for the MEM_ACCEPT call haven: Add support for the MEM_RELEASE/MEM_RECLAIM calls haven: Add support for the MEM_QCOM_LOOKUP_SGL call haven: Add support for the mem-buf driver's message queue haven: Add the memparcel handle as a well known haven type PM / devfreq: Remove dependencies between sysfs nodes and suspend count soc: qcom: Remove incorrect error check from Guest VM PIL Loader eud: Handle multiple events with eud interrupt i3c: i3c-master-msm-geni: Support for 3.4 Mhz,400 Khz kernel_headers: Fix headers not detected in incremental builds dma-mapping-fast: Align memory allocation to dma_alloc_attrs expectations msm: cvp: Disable CVP power collapse leds: qti-flash: Add individual APIs to enable and disable switch defconfig: lahaina-gki: Enable USB Audio QMI Service driver sound: usb: Fix incorrect type assignments arm64: defconfig: Enable USB_F_FS_IPC_LOGGING for lahaina_debug, take 3 power: supply: qti_battery_charger: Handle generic notification soc: qcom: qti_battery_debug: Update QBG device context dump length arm64: defconfig: Enable new touchscreen on Lahaina arm64: defconfig: Enable touchscreen on Lahaina defconfig: lahaina: Enable KGSL driver serial: msm_geni_serial: Cover console under GENI_CONSOLE config defconfig: lahaina: Enable DYNAMIC_DEBUG firmware: shmbridge: Enable shmbridge by default serial: msm_geni_serial: Manage HSUART clocks when read HW Ver arm64: defconfig: Enable QCOM EUD driver clk: qcom: clk-rpmh: Wait for completion when enabling clocks ANDROID: serdev: Fix platform device support msm: tsens: Add code to support thermal framework changes soc: qcom: rpmh: Add completion status to rpmh debug information msm: kgsl: Add rgmu_init() for firmware loading leds: qti-flash: Update interrupt names ASoC: Update the widgets power up/down sequence msm: cvp: Enable CVP auto PIL thermal: adc-tm: Fix match table description and Makefile ASoC: pcm: update the start-up sequence for playback msm: synx: redesign callback registration and dispatch ion: msm: Add support for secure allocations for the Trusted UI(TUI) VMID soc: qcom: secure_buffer: Add support for the Trusted UI(TUI) VMID lib/list_sort: fix function type mismatches kernel_headers: Add missing header for lahaina crypto: msm: Rename qcrypto module crypto: msm: Build qcedev and qcedev-smmu together crypto: msm: Fix compile errors crypto: msm: Fix incorrect boolean logic Revert "defconfig: lahaina: enable FSA driver on Lahaina" Add hdcp_qseecom driver snapshot for Lahaina mm: set the watermark_boost before updating the low and high wmarks mm, oom: check LMK enabled for pagefault_out_of_memory() mm: oom: enable the sysctl_reap_mem_on_sigkill by default defconfig: Enable userspace low memory killer for Lahaina mm, oom: Modify default value of panic_on_oom mm: oom-kill: Add lmk_kill possible for ULMK defconfig: arm64: Add SELinux configs defconfig: lahaina: Enable CONFIG_EDAC_QGKI flag drivers: edac: Avoid configuring interrupt register in polling mode arm64: defconfig: Enable Haven HVC Driver tty: Add Haven RM Console driver haven: rm: Add VM Services - Console APIs haven: rm: Add IRQ Management APIs for IRQ lending msm: kgsl: Fix gdsc disable timeout during reset msm: kgsl: Always boot GMU with default CM3 config ion: msm: Add support for the Trusted UI(TUI) dynamic carveout heap coresight-etm4x: Don't set LPOVERRIDE bit when tupwr-disable is true ASoC: pcm: update arch_setup_dma_ops to of_dma_configure for hostless mm: make faultaround produce old ptes wil6210: prevent ioctl access while in reset or suspend drivers: edac: Defer work for the polling EDAC driver edac: Allow the option of creating a deferrable work for polling ASoC: dt-bindings: update soundwire port configurations defconfig: lahaina: Enable hv-haptics driver input: qcom-hv-haptics: correct pattern source checking logic defconfig: lahaina: enable FSA driver on Lahaina defconfig: lahaina: Enable the Type-C alternate mode driver soc: qcom: Add Type-C alternate mode driver ion: Add support for dynamic carveout heaps i3c: i3c-master-msm-geni: Propagate tip changes from 4.19 leds: qti-flash: Fix updating flags when disabling flash/torch device sound: usb: Add snapshot for usb audio qmi driver ion: msm: Add support for addition/removal of memory to ION heaps ion: msm: Add support for querying the security state of heaps ion: msm: Add support for mapping VMIDs to ION flags Bluetooth: Remove unused regulator entries msm: cvp: Relocate Synx init/uninit calls qseecom: add compat_qseecom to support 32bit process drivers: llcc: edac: Add a config flag for non GKI variants msm: cvp: Enable CVP power collapse and LLC defconfig: arm64: Enable wakelock feature for lahaina defconfig: Enable ARCH_QTI_VM config arm64: Kconfig: Add config option for QTI's virtual machine soc: qcom: ipcc: Do not reset the device during probe power: reset: use nvmem restart_reason sched/fair: bonus vruntime for task boost 3 defconfig: Split CNSS configs to GKI and debug devfreq: memlat: Add CPU Hotplug and Idle awareness in memlat input: touchscreen: Enable new Focaltech touch driver soc: qcom: rpmh: Correct rpm_msg pointer offset and add list_del drivers: cpuidle: lpm-levels: Move local_irq_enable drivers: soc: qcom: rpmh: Correctly set dirty flag include/linux: add HDCP QSEECOM header file arm64: defconfig: Enable USB Mass Storage drivers on Lahaina arm64: defconfig: lahaina: Enable GuestVM PIL support soc: qcom: Add Guest VM PIL loader dwc3-msm: Add USB role switch handling ucsi: Add usage of USB role switch functionality scsi: ufs: Fix phy init sequence haven: Add VM management support for clients arm64: defconfig: Enable haven doorbell driver haven: Add haven doorbell driver arm64: defconfig: Enable Haven virtualization drivers haven: Add Haven Resource Manager Driver arm64: defconfig: Enable extcon USB GPIO driver on Lahaina msm: kgsl: Make the scratch privileged clk: qcom: gdsc-regulator: Add support for proxy consumers msm: kgsl: Set busmon driver data msm: kgsl: Do not call dispatcher functions directly drivers: thermal: Avoid trip evaluation for disabled thermal zone haven: Add Haven Message Queue driver arch: arm64: hh: Add Haven arm64 hypercall interface haven: hcall: Add Haven hypercall interface haven: Add common Haven types and macros Revert "rpmsg: glink: Set tail pointer to 0 at end of FIFO" Revert "PM / QoS: Redefine FREQ_QOS_MAX_DEFAULT_VALUE to S32_MAX" Revert "UPSTREAM: firmware/qcom_scm: Add scm call to handle smmu errata" Revert "UPSTREAM: firmware: qcom_scm-64: Add atomic version of qcom_scm_call" Revert "UPSTREAM: cpufreq: qcom-hw: Move driver initialization earlier" msm: kgsl: Dump maximum possible IB1 size in snapshot scsi: ufs-qti: Remove the second init in hba probe path ufs: ufs-qcom: Clean up UFS PHY mode and submode selection msm: kgsl: Handle error from nvmem_cell_read while reading speed_bin fuse coresight: csr: read MSR start address and size from dt regulator: Add snapshot of qpnp-amoled regulator driver msm: cvp: fix DSP probe crash sched: micro optimization for sched_energy_present extcon: usb-gpio: Add support for optional VBUS output enable GPIO msm: ipa4: debug patch gsi interrupt issue usb: ep0: complete the pending control request before soft-disconnect mhi: dev: uci: add support for DIAG and DCI clients msm: cvp: Add debug node control power collapse msm: pcie: always enable BDF to SID for PCIe RC mode msm: adsprpc: detect privileged processes based on group ID eud: Set pdev->id value to 0 and add set_mctrl() API usb: dwc3: Remove extra format specifier psi: Improve ftrace events soc: qcom: spcom: propagate print macro parameters to pr_*() psi: print threshold time in decimal psi: use proper accessor msm: adsprpc: Separate header and non-ion copy buffer sched/uclamp: Fix a bug in propagating uclamp value in new cgroups input: qti-hv-haptics: Add debugfs parameters to configure effects input: qcom,hv-haptics: Add DT definitions input: misc: Add initial driver to support QTI HV haptics clk: qcom: clk-alpha-pll: Fix zonda set_rate failure when PLL is disabled arm64: Call idle notifiers in CPU idle ANDROID: idle_notifier: Add generic idle notifiers defconfig: lahaina: enable QTI battery debug driver soc: qcom: add initial version of qti_battery_debug driver kernel_headers: Add missing kernel headers to lahaina defconfig: enable QSEECOM as a GKI module qseecom: use of_reserved_mem_lookup to get heap base and size iommu/arm-smmu: Use an atomic context when fastmap is set on GKI msm: pcie: remove PCI_MSM_MSI dependencies msm: pcie: add support to control pipe clk mux for LPM msm: pcie: add support for gcc_aggre_noc_pcie_*_axi_clk qseeecom: Fix possible unused function clk: qcom: gpucc: Enable cx_gmu, hub_cx_int_clk always usb: gadget: configfs: Add max_speed setting iommu-debug: allocate test_virt_addr when reading it iommu: iommu-debug: Fix return code for iommu_debug_dma_unmap_write Add support BT/FM CHK 3.2 chip f_fs: Return correct USB endpoint descriptor to user space daemon usb: gadget: Update functions for SSP descriptors defconfig: lahaina: correct PMIC ADC driver config enablement defconfig: lahaina: remove disablement of SPMI temp alarm driver clk: qcom: gpucc: Add support for HLOS1_VOTE_GPU_SMMU_CLK dt-bindings: clock: Add support for HLOS1_VOTE_SMMU_CLK hrtimer: fix issue during core isolation kernel headers: Update comparison logic scsi: ufs: Make crypto updates on QTI ufs arm64: defconfig: Enable MSM PCIe and MHI Host driver for lahaina msm: pcie: configure PCIe and MSI as modules in Makefile iommu: io-pgtable-fast: Fix IOMMU configuration usage in self-tests dwc3-msm: Add dwc3_msm_release_ss_lane() API msm: cvp: Support releasing persistent buffer msm: kgsl: Move secvid programming to gpudev msm: kgsl: Do dispatcher init at first open msm: kgsl: Move APRIV config to a6xx start msm: kgsl: Move preemption start to ringbuffer start msm: kgsl: Move ringbuffer global allocations to init time msm: kgsl: Fix memory leak in a6xx_init msm: kgsl: Create first_open and last_close msm: kgsl: Add function to get context bank number Revert "devfreq: bimc_bwmon: Add support to enable BWMON clks" arm64: defconfig: Enable memory debug configs on Lahaina usb: dwc3-msm: Fix out-of-bounds access in bus voting pwm: pwm-qti-lpg: Refactor qpnp_lpg_parse_dt() for readability soc: fsa4480-i2c: Register with UCSI for audio accessory notifications ucsi: ucsi_glink: Notify upon change in connector status linux: scm: Update the API for assign memory to subsys arm64: defconfig: enable flash LED driver on Lahaina leds: add support for QTI flash LED driver ANDROID: Re-use SUGOV_RT_MAX_FREQ to control uclamp rt behavior ANDROID: cpufreq/schedutil: Select frequency using util_avg for RT pwm: pwm-qti-lpg: Handle nvmem device lookup failure properly clk: qcom: clk-rpmh: Mark rfclka2 as optional for Lahaina tracing: rework sched_preempt_disable trace point implementation sched: core: reset preemption/irqsoff disable timestamp defconfig: enable schedutil governor on Lahaina msm: cvp: Use compiler data type in uapi sched/core: Fix size of rq::uclamp initialization iommu/arm-smmu: log outstanding transactions on sync timeout msm: gsi: Fix the WARNING for gsi_write_channel_scratch arm64: defconfig: Enable QRTR MHI on lahaina_debug interconnect: qcom: Add QoS config support net: qrtr: Introduce MHI transport for qrtr PM / devfreq: Make governor registration less verbose regulator: qcom_pm8008-regulator: correct chip-en chip variable type cpuidle: lpm-levels: update lpm_disallowed() with sched hints mhi: Export more symbols mhi: Fix compile errors msm: pcie: update PCIe RC and MSI driver to compile as GKI modules regulator: qcom_pm8008: correct parent supply voltage voting arm64: defconfig: Enable CFI_PERMISSIVE flag scripts: gki: Add LD to make args to enable CFI/LTO soc: qcom: glink_pkt: Fix minor version in device creation Revert "usb: dwc3: gadget: Fix logical condition" arm64: defconfig: Enable SG support in Lahaina GKI defconfig: lahaina: enable the battery charger driver power: supply: Add QTI battery charger defconfig: lahaina-gki: enable the qcom_pm8008-regulator driver regulator: qcom_pm8008: allow multiple PM8008 instances with unique names regulator: qcom_pm8008: change reg property format from u16 to u32 regulator: qcom_pm8008: Add LDO OCP interrupt support regulator: add a regulator driver for the PM8008 PMIC defconfig: Add kernel hardening features dwc3: gadget: Fix dr_mode check with USB device mode APIs msm: ipa4: Fix to unmap the page if skb allocation failed defconfig: lahaina-gki: enable various USB CONFIGFS functions usb: gadget: f_cdev: Fix func_suspend usb: gadget: Make USB_CONFIGFS_NCM buildable as a module usb: gadget: f_gsi: Fix function suspend usb: gadget: Add function wakeup support cnss2: Add daemon_support dts option for QCA6390 input: touchscreen: Add new Focaltech touch driver regulator: refgen: add support for proxy consumers regulator: rpmh-regulator: support parent supply specification in subnodes msm: kgsl: Remove write-only register from snapshot arm64: defconfig: Enable TSENS driver for lahaina memory_dump: add new feature for cpuss dump iommu/iova: Limit IOVA alignment using CONFIG_ARM64_DMA_IOMMU_ALIGNMENT power: reset: Add qcom_dload command to poweroff driver msm: ipa: clear the ipa pipeline before any ep config Revert "cnss2: Add support to monitor PM QOS votes" net: cnss2: Build generic netlink support by default sched/fair: consider uclamp boost while deciding the start_cpu NFC: Add support to get NFC interface type msm: ipa: split quota stat memory between q6 and ap Example kernel headers header_lib package uapi: sound: remove redundant QGKI config checks Revert "FROMLIST: scsi: ufs-qcom: Adjust bus bandwidth voting and unvoting" msm: kgsl: Remove icc path from gmu device msm: kgsl: Add support for multiple ddr tables msm: kgsl: Setup LPAC global pagetable msm: kgsl: Check snapshot status after snapshot msm: kgsl: Update a660 CP indexed register ranges qcom: soc_sleep_stats: Correctly read accumulated sleep length iommu/arm-smmu: Replace while loop with for_each_set_bit iommu/arm-smmu: enhance tlb sync timeout handler uapi: sound: remove redundant QGKI config checks soc: qcom: pmic_glink: add support for multiple pmic_glink devices psi: Use deferrable psi_avgs_work psi: Introduce ftrace events cnss2: NULL terminate FW build ID string arm64: defconfig: Enable CMA performance optimizations on Lahaina mm: Allow only __GFP_CMA allocations from Movable zone mm: fix the use of ALLOC_CMA zram: allow zram to allocate CMA pages mm: fix cma accounting in zone_watermark_ok mm: add cma pcp list arm64: defconfig: Re-enable USB_F_FS_IPC_LOGGING for lahaina_debug cma: redirect page allocation to CMA arm64: defconfig: Enable CMA debug configs on Lahaina Revert "mm: cma: make writeable CMA debugfs optional" ion: Make MSM pool auto refill built-in only soc: qcom: Add module dependence for spss_utils input: touchscreen: Enable FTS Touch driver input: touchscreen: Add STMicroelectronics Touchscreen driver drivers: lpm-levels: Use cpu_do_idle for shallower LPM entry wil6210: add ioctl interface wil6210: fix vendor command policy for vendor unspec commands wil6210: add policy for all vendor commands NFC: Made the QTI NFC drivers GKI compliant Revert "defconfig: lahaina: Enable QRNG driver" interconnect: qcom: Add sync_state for Lahaina QNOC defconfig: Lahaina: update external display module config soc: pil: Disable error-ready timeout uapi: sound: remove redundant QGKI config checks smp: Wake up all idle CPUs when suspending to idle uapi: sound: remove redundant QGKI config checks uapi: sound: remove redundant QGKI config checks uapi: sound: remove redundant QGKI config checks arm64: defconfig: Enable CONFIG_MODULE_SIG to allow module signing defconfig: lahaina: enable QTI crypto driver msm: cvp: Avoid overflowing the stack frame arm64: defconfig: Enable RTB driver devfreq: bwmon: Export symbols driver: soc: qcom: Fix function prototype PM / devfreq: memlat: Export symbols drivers: qcom: Fix a parameter for sysfs_attr_init() PM / devfreq: Fix CONFIG check for cache HW monitor prototype clocks: Add a missing header to clk/qcom/common.h PM /devfreq: Fix function prototype PM / devfreq: memlat: Use the cpumask_pr_args macros msm: kgsl: Remove unused header from gpu_bwmon thermal: Fix trace_thermal_zone_trip dma-buf: Export missing dma_buf_ref_mod symbol iommu: dma-mapping-fast: Export symbols drivers: pinctrl: Export msm_qup_write PM / devfreq: Add MODULE_LICENSE for arm-memlat-mon PM / devfreq: Export tracepoint symbols firmware: qcom-scm: Force built in drivers to depend on QCOM SCM coresight: Remove duplicate Kconfig entries include: Fixup headers to pass KERNEL_HEADER_TEST soc: spcom: Add ipc logging engine uapi: sound: remove redundant QGKI config check msm: IPA: remove unsupport enum for uC debug stats msm: cvp: CVP DSP driver restructure for Lahaina arm64: defconfig: Enable USB role switch driver on lahaina clk: qcom: Fix accessing of clks element during the probe usb: gadget: Don't perform start xfer with USB BAM endpoint msm: cvp: FD support in fence path cpufreq: schedutil: fix CPU util when WALT is enabled drivers: thermal: Add support to change thermal zone configuration arm64: defconfig: Enable debug cc clock driver for Lahaina arm64: defconfig: Enable CONFIG_BALANCE_ANON_FILE_RECLAIM on Lahaina arm64: defconfig: Enable clean page reclaim tracking on Lahaina iommu/arm-smmu: Fix memory leak with respect to TBU data structures msm: cvp: Enable CVP driver on DSP defconfig: change default governor to performance on lahaina hwrng: update qrng driver copyright and license marking msm:ipa: Address the -Wmisleading-indentation warning socinfo: Avoid sysfs entry name changes between kernel versions clk: qcom: rcg: update the DFS macro for RCG msm: pcie: correct error check of wakeup source registration msm: kgsl: Disable GBIF_CLIENT_QOS on a660v1 msm: kgsl: Skip the intersecting vma clk: qcom: debug: Remove use of hw init clk: qcom: Add debug cc clk measure nodes for Lahaina arm64: defconfig: Remove CONFIG_SPS from lahaina_debug.config msm: ipa4: Fix using of tag_desc NFC: Add NFC hardware check and get info ioctl cpufreq: qcom-cpufreq-hw: Initialize the data type for offsets to u16 ASoC: core: Add compat ioctl support for listen driver msm: ipa: Fix using generic name for offload connect/disconnect msm: ipa: stop remote IPA channels if tethering is not enabled arm64: defconfig: Enable SMCInvoke driver for Lahaina SMCInvoke: Add SMCInvoke driver snapshot for Lahaina msm: cvp: remove version and deprecated functions qseecom: update interface as per new scm driver msm: cvp: Add flush api in uapi drivers: thermal: Add config sysfs entry support for thermal zones mm: swap: Add null pointer check selinux: stop flooding the log buffer fs/buffer.c: Revoke LRU when trying to drop buffers defconfig: arm64: Enable sched debug features on Lahaiana sched/core: Fix compilation issues when WALT is enabled sched/fair: skip 6% energy check when best_energy_cpu is idle interconnect: qcom: Change bcm voter initlevel clk: qcom: gcc-lahaina: Add PCIe and UFS clock muxes dt-bindings: clock: gcc: Add PCIe pipe and UFS symbol clocks clk: qcom: Fix incorrect mux_get_parent mapping defconfig: Lahaina: enable external display module msm: ipa: vote for device side through mhi for tethering use cases msm: ipa: tune mhip ring size shrink to 6 elements defconfig: lahaina-qgki: Enable thermal drivers msm:ipa: mhip ring size optimization msm:ipa: uc based flow control for UL tethering offload msm:ipa: stop UL IPA TX channel at the end of the probe msm:ipa: continue ODL logging on MHIP post modem SSR coresight: csr: update programming sequence of enabling etr to bam coresight: fix tmc flush timeout issue coresight: tmc: leverage etr disable/enable when switching mode coresight: tmc: add usb support to etr platform: msm: add support for external display module usb: typec: ucsi: fix spelling mistake "connetor" -> "connector" usb: typec: ucsi: Actually enable all the interface notifications usb: typec: ucsi: Store the notification mask usb: typec: ucsi: Fix the notification bit offsets PM / QoS: Reorder pm_qos/freq_qos/dev_pm_qos structs PM / QoS: Redefine FREQ_QOS_MAX_DEFAULT_VALUE to S32_MAX arm64: defconfig: Enable USB QDSS and USB BAM drivers on Lahaina msm: kgsl: Check correct register for clamps on a660 msm: kgsl: Set DMA Mask for gmu device msm: kgsl: Setup CP_CHICKEN_DBG register for a660 msm: kgsl: Add A660 to the gpulist dt-bindings: clock: add MDSS clock names for Lahaina iommu/arm-smmu: avoid possible deadlock during map_sg iommu: Fixup selftests ion: Fix API changes in dma-buf-ref.c sched: walt: Improve the scheduler sched: walt: improve the scheduler sched/fair: Don't place wakee on waker cpu if colocate enabled arm64: defconfig: Enable qseecom driver for Lahaina msm: kgsl: Don't error out if dst size is not equal to src in copy_prop arm64: defconfig: Enable SPS driver for lahaina msm:ipa: Race condition observed during client disconnect defconfig: Enable DCC driver for GKI dt-bindings: Add new port types for SWR 1.6 feature HID: Trace events for external sensor driver HID: qvr: Correct axes orientation HID:correct mag axis config for External viewer HID: qvr: wait event interruptible timeout change HID: qvr: Decrease wait event interruptible timeout value HID: qvr: Optimized Viewer Requirements HID: qvr: Code refactoring HID: Read calibration data from external sensor HID: Filtering mag data depending on timestamp HID: external sensor driver msm: adsprpc: HMX,Async-FastRPC capability sched/walt: Avoid walt irq work in offlined cpu sched/fair: Improve the scheduler interconnect: qcom: Fix MACRO fields for Lahaina iinterconnect: qcom: Hold high bandwidth vote for keepalive BCMs scsi: ufshcd-qti: Port the new crypto framework to QTI ufs msm: ipa: Add SMMU driver as soft dependency for IPA include: sound: add stub function for wcd dsp manager iommu/arm-smmu: Rename the ARM SMMU module regmap: Quit the read-loop based on position of file-offset arm64: qcom: Enable QTI config scsi: ufs-qti: Check for valid vcc before accessing iommu/arm-smmu: Use dev_iommu_fwspec_get() to retrieve IOMMU fwspec iommu/arm-smmu: Unregister TBU driver when unloading the SMMU module crypto: msm: Add QTI crypto drivers iommu/arm-smmu: Add missing iommu_device_unregister() msm: ipa: fix ipa_disable_apps_wan_cons_deaggr declaration Revert "drivers: qcom: cmd-db: modularize commandDB driver" msm: kgsl: Calculate the offset of context bank 0 arm64: defconfig: Enable poweroff driver for Lahaina GKI power: reset: Add snapshot of msm-poweroff msm: kgsl: Refactor IOMMU contexts msm: kgsl: Support global secure memory objects msm: kgsl: Add a function to map global buffers msm: ipa3: IPA clock vote ioctl msm: ipa3: IPA clock vote ioctl msm: tsens: Add Tsens driver snapshot arm64: defconfig: Enable slimbus driver config for lahaina msm: cvp: remove additional checks in response_handler defconfig: lahaina: Enable ADC drivers for lahaina coresight: tmc: etr: Add sys interface for ETR thermal: adc-tm: Add support for PMIC7 ADC_TM thermal: adc-tm: Add ADC_TM driver snapshot msm: ipa : Fix KW array index issue on dbg_buff msm: IPA: add the missing iounmap handle arm64: defconfig: Enable all memory hotplug related configs on Lahaina soc: qcom: mem-offline: Clear page-table entries after offline soc: qcom: mem-offline: Set offlinable region based on minimum DDR sizes arm64: Update dram end address while randomizing base arm64: mm/memblock: Update memory limit calculation drivers: base: expose amount allocated per block dma-mapping-fast: Remap contiguous pages only when needed arm64: mm: Fix compilation when CONFIG_MEMORY_HOTPLUG is not enabled mm, oom: Try to online memory block before killing arm64: Make section size configurable for memory hotplug mm/memory_hotplug: Add hot-added memory blocks to ZONE_MOVABLE type arm64: Override memory limit set by boot parameter soc: qcom: mem-offline: Add a snapshot of the mem-offline driver qseecom: Add qseecom driver snapshot for Lahaina defconfig: Lahaina: Enable support for WLAN arm64: defconfig: Enable TSENS driver for lahaina firmware: qcom_scm: Add changes for tsens reinit NFC: Add NFC I2C and I3C drivers for SNxxx Linux 5.4.7 iwlwifi: pcie: move power gating workaround earlier in the flow nbd: fix shutdown and recv work deadlock v2 mmc: sdhci: Add a quirk for broken command queuing mmc: sdhci: Workaround broken command queuing on Intel GLK mmc: sdhci-of-esdhc: fix P2020 errata handling mmc: sdhci: Update the tuning failed messages to pr_debug level mmc: sdhci-of-esdhc: Revert "mmc: sdhci-of-esdhc: add erratum A-009204 support" mmc: sdhci-msm: Correct the offset and value for DDR_CONFIG register ocxl: Fix concurrent AFU open and device removal powerpc/irq: fix stack overflow verification powerpc/vcpu: Assume dedicated processors as non-preempt x86/mce: Fix possibly incorrect severity calculation on AMD x86/MCE/AMD: Allow Reserved types to be overwritten in smca_banks[] x86/MCE/AMD: Do not use rdmsr_safe_on_cpu() in smca_configure() x86/intel: Disable HPET on Intel Coffee Lake H platforms KVM: arm64: Ensure 'params' is initialised when looking up sys register KVM: arm/arm64: Properly handle faulting of device mappings kvm: x86: Host feature SSBD doesn't imply guest feature AMD_SSBD kvm: x86: Host feature SSBD doesn't imply guest feature SPEC_CTRL_SSBD KVM: PPC: Book3S HV: Fix regression on big endian hosts iocost: over-budget forced IOs should schedule async delay ext4: validate the debug_want_extra_isize mount option at parse time ext4: unlock on error in ext4_expand_extra_isize() ext4: check for directory entries too close to block end ext4: fix ext4_empty_dir() for directories with holes clk: imx: pll14xx: fix clk_pll14xx_wait_lock clk: imx: clk-composite-8m: add lock to gate/mux clk: imx: clk-imx7ulp: Add missing sentinel of ulp_div_table pinctrl: baytrail: Really serialize all register accesses serial: sprd: Add clearing break interrupt operation tty/serial: atmel: fix out of range clock divider handling staging: comedi: gsc_hpdi: check dma_alloc_coherent() return value platform/x86: hp-wmi: Make buffer for HPWMI_FEATURE2_QUERY 128 bytes intel_th: msu: Fix window switching without windows intel_th: Fix freeing IRQs intel_th: pci: Add Elkhart Lake SOC support intel_th: pci: Add Comet Lake PCH-V support USB: EHCI: Do not return -EPIPE when hub is disconnected mm: vmscan: protect shrinker idr replace with CONFIG_MEMCG KEYS: asymmetric: return ENOMEM if akcipher_request_alloc() fails cpufreq: Avoid leaving stale IRQ work items during CPU offline efi/memreserve: Register reservations as 'reserved' in /proc/iomem spi: fsl: use platform_get_irq() instead of of_irq_to_resource() spi: fsl: don't map irq during probe usbip: Fix error path of vhci_recv_ret_submit() usbip: Fix receive error in vhci-hcd when using scatter-gather can: flexcan: add low power enter/exit acknowledgment helper ARM: dts: Fix vcsi regulator to be always-on for droid4 to prevent hangs s390/ftrace: fix endless recursion in function_graph tracer md: avoid invalid memory access for array sb->dev_roles RDMA/siw: Fix post_recv QP state locking ath10k: Revert "ath10k: add cleanup in ath10k_sta_state()" drm/amdgpu: fix uninitialized variable pasid_mapping_needed usb: xhci: Fix build warning seen with CONFIG_PM=n spi: cadence: Correct handling of native chipselect spi: dw: Correct handling of native chipselect selftests: net: tls: remove recv_rcvbuf test can: kvaser_usb: kvaser_usb_leaf: Fix some info-leaks to USB devices can: flexcan: poll MCR_LPM_ACK instead of GPR ACK for stop mode acknowledgment can: flexcan: fix possible deadlock and out-of-order reception after wakeup can: j1939: j1939_sk_bind(): take priv after lock is held can: m_can: tcan4x5x: add required delay after reset can: xilinx_can: Fix missing Rx can packets on CANFD2.0 iommu/vt-d: Allocate reserved region for ISA with correct permission iommu/vt-d: Set ISA bridge reserved region as relaxable iommu/vt-d: Fix dmar pte read access not set error iommu: set group default domain before creating direct mappings iommu: fix KASAN use-after-free in iommu_insert_resv_region tpm: fix invalid locking in NONBLOCKING mode tpm_tis: reserve chip for duration of tpm_tis_core_init mmc: mediatek: fix CMD_TA to 2 for MT8173 HS200/HS400 mode Revert "mmc: sdhci: Fix incorrect switch to HS mode" btrfs: don't prematurely free work in scrub_missing_raid56_worker() btrfs: don't prematurely free work in reada_start_machine_worker() MIPS: futex: Restore \n after sync instructions net: wireless: intel: iwlwifi: fix GRO_NORMAL packet stalling ibmvnic: Fix completion structure initialization RDMA/bnxt_re: Fix chip number validation Broadcom's Gen P5 series bpf: Provide better register bounds after jmp32 instructions RDMA/bnxt_re: Fix stat push into dma buffer on gen p5 devices RDMA/bnxt_re: Fix missing le16_to_cpu tools, bpf: Fix build for 'make -s tools/bpf O=<dir>' net: phy: initialise phydev speed and duplex sanely ice: Fix setting coalesce to handle DCB configuration ice: Only disable VF state when freeing each VF resources drm/amdgpu: fix bad DMA from INTERRUPT_CNTL2 mips: fix build when "48 bits virtual memory" is enabled libtraceevent: Fix memory leakage in copy_filter_type crypto: vmx - Avoid weird build failures mac80211: consider QoS Null frames for STA_NULLFUNC_ACKED crypto: sun4i-ss - Fix 64-bit size_t warnings on sun4i-ss-hash.c crypto: sun4i-ss - Fix 64-bit size_t warnings s390/cpumf: Adjust registration of s390 PMU device drivers mt76: fix possible out-of-bound access in mt7615_fill_txs/mt7603_fill_txs net: ethernet: ti: ale: clean ale tbl on init and intf restart ASoC: soc-pcm: check symmetry before hw_params fbtft: Make sure string is NULL terminated iwlwifi: check kasprintf() return value bnxt_en: Improve RX buffer error handling. s390/kasan: support memcpy_real with TRACE_IRQFLAGS s390/crypto: Fix unsigned variable compared with zero perf probe: Fix to show function entry line as probe-able perf session: Fix decompression of PERF_RECORD_COMPRESSED records brcmfmac: remove monitor interface when detaching net-af_xdp: Use correct number of channels from ethtool x86/insn: Add some Intel instructions to the opcode map ASoC: Intel: bytcr_rt5640: Update quirk for Acer Switch 10 SW5-012 2-in-1 firmware_loader: Fix labels with comma for builtin firmware net: phy: avoid matching all-ones clause 45 PHY IDs bnxt_en: Return proper error code for non-existent NVM variable selftests, bpf: Workaround an alu32 sub-register spilling issue selftests, bpf: Fix test_tc_tunnel hanging perf/core: Fix the mlock accounting, again ASoC: wm5100: add missed pm_runtime_disable spi: st-ssc4: add missed pm_runtime_disable ASoC: wm2200: add missed operations in remove and probe failure sched/uclamp: Fix overzealous type replacement btrfs: don't prematurely free work in run_ordered_work() btrfs: don't prematurely free work in end_workqueue_fn() mmc: tmio: Add MMC_CAP_ERASE to allow erase/discard/trim requests crypto: virtio - deal with unsupported input sizes xhci-pci: Allow host runtime PM as default also for Intel Ice Lake xHCI tun: fix data-race in gro_normal_list() spi: tegra20-slink: add missed clk_unprepare regulator: core: Let boot-on regulators be powered off ASoC: wm8904: fix regcache handling iwlwifi: mvm: fix unaligned read of rx_pkt_status bcache: fix deadlock in bcache_allocator tracing/kprobe: Check whether the non-suffixed symbol is notrace MIPS: ralink: enable PCI support only if driver for mt7621 SoC is selected tracing: use kvcalloc for tgid_map array allocation RDMA/efa: Clear the admin command buffer prior to its submission qtnfmac: fix using skb after free x86/crash: Add a forward declaration of struct kimage qtnfmac: fix invalid channel information output qtnfmac: fix debugfs support for multiple cards cpufreq: Register drivers only after CPU devices have been registered bcache: fix static checker warning in bcache_device_free() parport: load lowlevel driver if ports not found nvme: Discard workaround for non-conformant devices net: ethernet: ti: Add dependency for TI_DAVINCI_EMAC s390/disassembler: don't hide instruction addresses r8169: respect EEE user setting when restarting network net: dsa: sja1105: Disallow management xmit during switch reset ASoC: Intel: kbl_rt5663_rt5514_max98927: Add dmic format constraint bpf, testing: Workaround a verifier failure for test_progs iio: dac: ad5446: Add support for new AD5600 DAC ASoC: rt5677: Mark reg RT5677_PWR_ANLG2 as volatile spi: pxa2xx: Add missed security checks media: vim2m: media_device_cleanup was called too early media: vicodec: media_device_cleanup was called too early EDAC/ghes: Fix grain calculation iio: cros_ec_baro: set info_mask_shared_by_all_available field media: v4l2-ctrl: Lock main_hdl on operations of requests_queued. media: cedrus: Use helpers to access capture queue media: si470x-i2c: add missed operations in remove ice: delay less crypto: atmel - Fix authenc support when it is set to m soundwire: intel: fix PDI/stream mapping for Bulk media: pvrusb2: Fix oops on tear-down when radio support is not present selftests: net: Fix printf format warnings on arm fsi: core: Fix small accesses and unaligned offsets via sysfs ath10k: fix get invalid tx rate for Mesh metric media: exynos4-is: fix wrong mdev and v4l2 dev order in error path drm/amdgpu: Avoid accidental thread reactivation. selftests: proc: Make va_max 1MB cgroup: freezer: don't change task and cgroups status unnecessarily s390/bpf: Use kvcalloc for addrs array libbpf: Fix negative FD close() in xsk_setup_xdp_prog() perf probe: Filter out instances except for inlined subroutine and subprogram perf probe: Skip end-of-sequence and non statement lines perf probe: Fix to show calling lines of inlined functions perf probe: Return a better scope DIE if there is no best scope net: avoid potential false sharing in neighbor related code perf probe: Skip overlapped location on searching variables perf parse: If pmu configuration fails free terms xen/gntdev: Use select for DMA_SHARED_BUFFER ice: Check for null pointer dereference when setting rings drm/amdgpu: fix potential double drop fence reference drm/amd/powerplay: fix struct init in renoir_print_clk_levels drm/amdgpu: disallow direct upload save restore list from gfx driver perf tools: Splice events onto evlist even on error perf tools: Fix cross compile for ARM64 perf probe: Fix to probe a function which has no entry pc libsubcmd: Use -O0 with DEBUG=1 perf probe: Fix to show inlined function callsite without entry_pc perf probe: Fix to show ranges of variables in functions without entry_pc perf probe: Fix to probe an inline function which has no entry pc perf probe: Walk function lines in lexical blocks perf jevents: Fix resource leak in process_mapfile() and main() perf probe: Fix to list probe event with correct line number perf cs-etm: Fix definition of macro TO_CS_QUEUE_NR perf probe: Fix to find range-only function instance rtlwifi: fix memory leak in rtl92c_set_fw_rsvdpagepkt() drm: msm: a6xx: fix debug bus register configuration RDMA/core: Fix return code when modify_port isn't supported ALSA: timer: Limit max amount of slave instances spi: img-spfi: fix potential double release bnx2x: Fix PF-VF communication over multi-cos queues. spi: dw: Fix Designware SPI loopback media: vivid: media_device_cleanup was called too early ASoC: SOF: topology: set trigger order for FE DAI link nvmem: core: fix nvmem_cell_write inline function nvmem: imx-ocotp: reset error status on probe media: staging/imx: Use a shorter name for driver nvme: introduce "Command Aborted By host" status code media: v4l2-core: fix touch support in v4l_g_fmt media: rcar_drif: fix a memory disclosure cpufreq: sun50i: Fix CPU speed bin detection ixgbe: protect TX timestamping from API misuse pinctrl: amd: fix __iomem annotation in amd_gpio_irq_handler() pinctrl: qcom: sc7180: Add missing tile info in SDC_QDSD_PINGROUP/UFS_RESET ASoC: SOF: imx: fix reverse CONFIG_SND_SOC_SOF_OF dependency spi: sifive: disable clk when probe fails and remove ALSA: pcm: Fix missing check of the new non-cached buffer type Bluetooth: Fix advertising duplicated flags libbpf: Fix error handling in bpf_map__reuse_fd() iio: dln2-adc: fix iio_triggered_buffer_postenable() position ALSA: bebob: expand sleep just after breaking connections for protocol version 1 pinctrl: sh-pfc: sh7734: Fix duplicate TCLK1_B net/mlx5e: Verify that rule has at least one fwd/drop action loop: fix no-unmap write-zeroes request behavior libata: Ensure ata_port probe has completed before detach net: hns3: add struct netdev_queue debug info for TX timeout s390/mm: add mm_pxd_folded() checks to pxd_free() s390: add error handling to perf_callchain_kernel s390/time: ensure get_clock_monotonic() returns monotonic values phy: qcom-usb-hs: Fix extcon double register after power cycle phy: renesas: phy-rcar-gen2: Fix the array off by one warning net: dsa: LAN9303: select REGMAP when LAN9303 enable gpu: host1x: Allocate gather copy for host1x staging: wilc1000: check if device is initialzied before changing vif RDMA/core: Set DMA parameters correctly RDMA/qedr: Fix srqs xarray initialization RDMA/hns: Fix memory leak on 'context' on error return path RDMA/qedr: Fix memory leak in user qp and mr ACPI: button: Add DMI quirk for Medion Akoya E2215T spi: sprd: adi: Add missing lock protection when rebooting ubsan, x86: Annotate and allow __ubsan_handle_shift_out_of_bounds() in uaccess regions regulator: core: Release coupled_rdevs on regulator_init_coupling() error drm/tegra: sor: Use correct SOR index on Tegra210 net: phy: dp83867: enable robust auto-mdix i40e: Wrong 'Advertised FEC modes' after set FEC to AUTO drm/amd/display: correctly populate dpp refclk in fpga i40e: initialize ITRN registers with correct values drm/amd/display: setting the DIG_MODE to the correct value. arm64: psci: Reduce the waiting time for cpu_psci_cpu_kill() EDAC/amd64: Set grain per DIMM drm: Don't free jobs in wait_event_interruptible() md/bitmap: avoid race window between md_bitmap_resize and bitmap_file_clear_bit staging: wilc1000: potential corruption in wilc_parse_join_bss_param() md: no longer compare spare disk superblock events in super_load media: smiapp: Register sensor after enabling runtime PM on the device media: aspeed: clear garbage interrupts media: imx7-mipi-csis: Add a check for devm_regulator_get media: st-mipid02: add a check for devm_gpiod_get_optional media: ov5640: Make 2592x1944 mode only available at 15 fps media: ad5820: Define entity function media: ov6650: Fix stored frame interval not in sync with hardware drm/nouveau: Don't grab runtime PM refs for HPD IRQs media: aspeed: set hsync and vsync polarities to normal before starting mode detection media: cedrus: Fix undefined shift with a SHIFT_AND_MASK_BITS macro x86/ioapic: Prevent inconsistent state when moving an interrupt ipmi: Don't allow device module unload when in use RDMA/siw: Fix SQ/RQ drain logic rtl8xxxu: fix RTL8723BU connection failure issue after warm reboot ASoC: soc-pcm: fixup dpcm_prune_paths() loop continue drm/gma500: fix memory disclosures due to uninitialized bytes RDMA/hns: Fix wrong parameters when initial mtt of srq->idx_que net: hns3: log and clear hardware error after reset complete selftests/bpf: Make a copy of subtest name perf tests: Disable bp_signal testing for arm64 power: supply: cpcap-battery: Check voltage before orderly_poweroff staging: iio: ad9834: add a check for devm_clk_get drm/amdgpu: fix amdgpu trace event print string format error drm/amd/display: fix header for RN clk mgr drm/amd/display: enable hostvm based on roimmu active for dcn2.1 x86/mce: Lower throttling MCE messages' priority to warning bpf/stackmap: Fix deadlock with rq_lock in bpf_get_stack() Bluetooth: hci_core: fix init for HCI_USER_CHANNEL Bluetooth: Workaround directed advertising bug in Broadcom controllers Bluetooth: missed cpu_to_le16 conversion in hci_init4_req Bluetooth: btusb: avoid unused function warning iio: adc: max1027: Reset the device at probe time drm/amd/powerplay: avoid disabling ECC if RAS is enabled for VEGA20 usb: usbfs: Suppress problematic bind and unbind uevents. perf vendor events arm64: Fix Hisi hip08 DDRC PMU eventname perf test: Avoid infinite loop for task exit case perf report: Add warning when libunwind not compiled in perf test: Report failure for mmap events drm/bridge: dw-hdmi: Restore audio when setting a mode rtw88: coex: Set 4 slot mode for A2DP ath10k: Correct error handling of dma_map_single() x86/mm: Use the correct function type for native_set_fixmap() drm/amd/display: Program DWB watermarks from correct state extcon: sm5502: Reset registers during initialization drm/amd/display: Fix dongle_caps containing stale information. syscalls/x86: Use the correct function type in SYSCALL_DEFINE0 drm/amd/display: add new active dongle to existent w/a media: ti-vpe: vpe: fix a v4l2-compliance failure about invalid sizeimage drm/amd/display: wait for set pipe mcp command completion drm/amd/display: Properly round nominal frequency for SPD media: ti-vpe: vpe: ensure buffers are cleaned up properly in abort cases media: ti-vpe: vpe: fix a v4l2-compliance failure causing a kernel panic media: ti-vpe: vpe: Make sure YUYV is set as default format media: ti-vpe: vpe: fix a v4l2-compliance failure about frame sequence number media: ti-vpe: vpe: fix a v4l2-compliance warning about invalid pixel format media: ti-vpe: vpe: Fix Motion Vector vpdma stride ASoC: SOF: enable sync_write in hdac_bus misc: fastrpc: fix memory leak from miscdev->name crypto: aegis128/simd - build 32-bit ARM for v8 architecture explicitly crypto: inside-secure - Fix a maybe-uninitialized warning media: cx88: Fix some error handling path in 'cx8800_initdev()' team: call RCU read lock when walking the port_list net/smc: increase device refcount for added link group libbpf: Fix passing uninitialized bytes to setsockopt libbpf: Fix struct end padding in btf_dump selftests/bpf: Fix btf_dump padding test case drm/drm_vblank: Change EINVAL by the correct errno mwifiex: pcie: Fix memory leak in mwifiex_pcie_init_evt_ring MIPS: futex: Emit Loongson3 sync workarounds within asm drm/amdkfd: Fix MQD size calculation block: Fix writeback throttling W=1 compiler warnings samples: pktgen: fix proc_cmd command result check logic drm/bridge: dw-hdmi: Refuse DDC/CI transfers on the internal I2C controller media: meson/ao-cec: move cec_notifier_cec_adap_register after hw setup media: cec-funcs.h: add status_req checks media: flexcop-usb: fix NULL-ptr deref in flexcop_usb_transfer_init() tools/memory-model: Fix data race detection for unordered store and load regulator: max8907: Fix the usage of uninitialized variable in max8907_regulator_probe() hwrng: omap3-rom - Call clk_disable_unprepare() on exit only if not idled crypto: aegis128-neon - use Clang compatible cflags for ARM usb: renesas_usbhs: add suspend event support in gadget mode drm/amd/display: fix struct init in update_bounding_box rtw88: fix NSS of hw_cap media: venus: Fix occasionally failures to suspend drm/amd/display: set minimum abm backlight level selftests/bpf: Correct path to include msg + path drm/amd/powerplay: A workaround to GPU RESET on APU x86/math-emu: Check __copy_from_user() result drm/amdkfd: fix a potential NULL pointer dereference (v2) drm/sun4i: dsi: Fix TCON DRQ set bits pinctrl: devicetree: Avoid taking direct reference to device name string drm/amd/display: Set number of pipes to 1 if the second pipe was disabled media: vimc: Fix gpf in rmmod path when stream is active ath10k: fix offchannel tx failure when no ath10k_mac_tx_frm_has_freq media: venus: core: Fix msm8996 frequency table tools/power/cpupower: Fix initializer override in hsw_ext_cstates media: ov6650: Fix stored crop rectangle not in sync with hardware media: ov6650: Fix stored frame format not in sync with hardware media: i2c: ov2659: Fix missing 720p register config media: ov6650: Fix crop rectangle alignment not passed back media: i2c: ov2659: fix s_stream return value media: ov6650: Fix control handler not freed on init error media: max2175: Fix build error without CONFIG_REGMAP_I2C media: vim2m: Fix BUG_ON in vim2m_device_release() media: vim2m: Fix abort issue media: seco-cec: Add a missing 'release_region()' in an error handling path media: cedrus: fill in bus_info for media device media: am437x-vpfe: Setting STD to current value is not an error spi: gpio: prevent memory leak in spi_gpio_probe drm/komeda: Workaround for broken FLIP_COMPLETE timestamps IB/iser: bound protection_sg size by data_sg size ath10k: fix backtrace on coredump Revert "pinctrl: sh-pfc: r8a77990: Fix MOD_SEL1 bit31 when using SIM0_D" Revert "pinctrl: sh-pfc: r8a77990: Fix MOD_SEL1 bit30 when using SSI_SCK2 and SSI_WS2" libertas: fix a potential NULL pointer dereference rtlwifi: prevent memory leak in rtl_usb_probe staging: rtl8188eu: fix possible null dereference staging: rtl8192u: fix multiple memory leaks on error path drm/meson: vclk: use the correct G12A frac max value spi: Add call to spi_slave_abort() function when spidev driver is released ath10k: Check if station exists before forwarding tx airtime report drm/amd/display: Handle virtual signal type in disable_link() ath10k: add cleanup in ath10k_sta_state() drm/amd/display: Rebuild mapped resources after pipe split drm/ttm: return -EBUSY on pipelining with no_gpu_wait (v2) drm/amdgpu: grab the id mgr lock while accessing passid_mapping drm/amdgpu/sriov: add ring_stop before ring_create in psp v11 code iio: light: bh1750: Resolve compiler warning and make code more readable iio: max31856: add missing of_node and parent references to iio_dev drm/amd/display: OTC underflow fix drm/bridge: analogix-anx78xx: silence -EPROBE_DEFER warnings drm/amd/display: verify stream link before link test drm: Use EOPNOTSUPP, not ENOTSUPP drm: exynos: exynos_hdmi: use cec_notifier_conn_(un)register drm/panel: Add missing drm_panel_init() in panel drivers drm/mipi-dbi: fix a loop in debugfs code drm: mst: Fix query_payload ack reply struct drm/virtio: switch virtio_gpu_wait_ioctl() to gem helper. drm/vc4/vc4_hdmi: fill in connector info ALSA: hda/ca0132 - Fix work handling in delayed HP detection ALSA: hda/ca0132 - Avoid endless loop ALSA: hda/ca0132 - Keep power on during processing DSP response ALSA: pcm: Avoid possible info leaks from PCM stream buffers Btrfs: fix removal logic of the tree mod log that leads to use-after-free issues btrfs: handle ENOENT in btrfs_uuid_tree_iterate btrfs: do not leak reloc root if we fail to read the fs root btrfs: skip log replay on orphaned roots btrfs: abort transaction after failed inode updates in create_subvol btrfs: send: remove WARN_ON for readonly mount Btrfs: fix missing data checksums after replaying a log tree btrfs: return error pointer from alloc_test_extent_buffer Btrfs: make tree checker detect checksum items with overlapping ranges btrfs: do not call synchronize_srcu() in inode_tree_del btrfs: don't double lock the subvol_sem for rename exchange NFC: nxp-nci: Fix probing without ACPI net: dsa: b53: Fix egress flooding settings net: stmmac: platform: Fix MDIO init for platforms without PHY net: ethernet: ti: davinci_cpdma: fix warning "device driver frees DMA memory with different size" mlxsw: spectrum_router: Remove unlikely user-triggerable warning dpaa2-ptp: fix double free of the ptp_qoriq IRQ net: ena: fix issues in setting interrupt moderation params in ethtool net: ena: fix default tx interrupt moderation interval bonding: fix bond_neigh_init() neighbour: remove neigh_cleanup() method selftests: forwarding: Delete IPv6 address at the end sctp: fully initialize v4 addr in some functions sctp: fix memleak on err handling of stream initialization qede: Fix multicast mac configuration qede: Disable hardware gro when xdp prog is installed nfp: flower: fix stats id allocation net: usb: lan78xx: Fix suspend/resume PHY register access error net-sysfs: Call dev_hold always in rx_queue_add_kobject net: qlogic: Fix error paths in ql_alloc_large_buffers() net: phy: ensure that phy IDs are correctly typed net: nfc: nci: fix a possible sleep-in-atomic-context bug in nci_uart_tty_receive() net: hisilicon: Fix a BUG trigered by wrong bytes_compl net: gemini: Fix memory leak in gmac_setup_txqs net: dst: Force 4-byte alignment of dst_metrics mod_devicetable: fix PHY module format fjes: fix missed check in fjes_acpi_add af_packet: set defaule value for tmo arm64: defconfig: Enable CPUFREQ-HW for Lahaina arm64: Add fallback option during memory hot add mm/Kconfig: Enable MEMORY_HOTPLUG for arm64 arm64: Honor limits set by bootloader arm64: Add "remove" probe driver for memory hot-remove arm64: Hot-remove implementation for arm64 arm64: memory-hotplug: Add MEMORY_HOTPLUG, MEMORY_HOTREMOVE, MEMORY_PROBE arm64: Memory hotplug support for arm64 platform msm: IPA: uC debug stats for loadable modules ASoC: compress: add support for Vorbis and amrwb_plus ANDROID: Kconfig.gki: Add Hidden SPRD DRM configs defconfig: Enable MHI Host driver for lahaina mhi: add snapshot for MHI driver stack mhi: core: export symbols for references uapi: sound: add new meta key to get DSP render position Kconfig: add description for AUDIO_QGKI SoC: pcm: Add delay_blk feature include: Add snapshot of header files for wcd spi and dsp manager ALSA: jack: Add support to report second microphone defconfig: lahaina-qgki: enable CONFIG_AUDIO_QGKI uapi: sound: latency mode support for transcode loopback ASoC: msm: add support for different compressed formats ASoc: msm: qdspv2: Clock recovery support in compress driver dt-bindings: sound: Add snapshot of audio port types for soundwire ASoC: msm: qdsp6v2: Add TrueHD HDMI compress pass-though msm: dt-binding: add snapshot of audio external clockfor Lahaina ASoC: msm: qdsp6v2: Support to set session start delay arm64: defconfig: Enable CONFIG_BT_SLIM on Lahaina bluetooth: add change for btfm slimbus driver ASoC: msm: qdsp6v2: Support to configure render window ASoC: msm: qdsp6v2: Support to configure clk recovery mode ASoC: msm: qdsp6v2: Support to configure render mode ASoC: Cold start latency reduction SoC: soc-pcm: call pcm_new when creating new pcm ASoC: compress: update snd_soc_platform to snd_soc_component ANDROID: Add a tracepoint for mapping inode to full path Revert "drm/virtio: fix DRM_FORMAT_* handling" ANDROID: gki_defconfig: Disable TRANSPARENT_HUGEPAGE staging: android: ion: Remove unused rbtree for ion_buffer kasan: Zero shadow memory on memory hotplug defconfig: lahaina: Enable QRNG driver drivers: slimbus: Makefile: Correct makefile configuration ASoC: core: Support for compress ioctls ASoC: pcm: Add support for compat mode wil6210: notify cfg80211_new_sta upon connection before init tx ring wil6210: allow disabling EDMG through force_edmg_channel debugfs wil6210: fix update SSID when changing beacon Linux 5.4.6 ALSA: hda: Fix regression by strip mask fix drm/amdgpu: add invalidate semaphore limit for SRIOV and picasso in gmc9 drm/amdgpu: avoid using invalidate semaphore for picasso drm/i915/gvt: Fix cmd length check for MI_ATOMIC drm/amdgpu/gfx10: re-init clear state buffer after gpu reset drm/amdgpu/gfx10: explicitly wait for cp idle after halt/unhalt drm/amdgpu: invalidate mmhub semaphore workaround in gmc9/gmc10 drm/amdgpu: initialize vm_inv_eng0_sem for gfxhub and mmhub drm/amd/display: add default clocks if not able to fetch them drm/amd/display: re-enable wait in pipelock, but add timeout drm/dp_mst: Correct the bug in drm_dp_update_payload_part1() drm/radeon: fix r1xx/r2xx register checker for POT textures drm/i915/fbc: Disable fbc by default on all glk+ drm/nouveau/kms/nv50-: Limit MST BPC to 8 drm/nouveau/kms/nv50-: Store the bpc we're using in nv50_head_atom drm/nouveau/kms/nv50-: Call outp_atomic_check_view() before handling PBN scsi: qla2xxx: Fix incorrect SFUB length used for Secure Flash Update MB Cmd scsi: qla2xxx: Correctly retrieve and interpret active flash region scsi: qla2xxx: Change discovery state before PLOGI scsi: qla2xxx: Added support for MPI and PEP regions for ISP28XX scsi: qla2xxx: Initialize free_work before flushing it scsi: qla2xxx: Ignore NULL pointer in tcm_qla2xxx_free_mcmd scsi: iscsi: Fix a potential deadlock in the timeout handler scsi: ufs: Disable autohibern8 feature in Cadence UFS dm thin: Flush data device before committing metadata dm thin metadata: Add support for a pre-commit callback dm clone: Flush destination device before committing metadata dm clone metadata: Use a two phase commit dm clone metadata: Track exact changes per transaction dm btree: increase rebalance threshold in __rebalance2() dm mpath: remove harmful bio-based optimization drm: meson: venc: cvbs: fix CVBS mode matching drm/mgag200: Flag all G200 SE A machines as broken wrt <startadd> drm/mgag200: Add workaround for HW that does not support 'startadd' drm/mgag200: Store flags from PCI driver data in device structure drm/mgag200: Extract device type from flags drm/panfrost: Fix a race in panfrost_gem_free_object() drm/panfrost: Fix a BO leak in panfrost_ioctl_mmap_bo() drm/panfrost: Fix a race in panfrost_ioctl_madvise() dma-buf: Fix memory leak in sync_file_merge() vfio/pci: call irq_bypass_unregister_producer() before freeing irq ARM: tegra: Fix FLOW_CTLR_HALT register clobbering by tegra_resume() ARM: dts: s3c64xx: Fix init order of clock providers cifs: Fix retrieval of DFS referrals in cifs_mount() CIFS: Fix NULL pointer dereference in mid callback CIFS: Do not miss cancelled OPEN responses CIFS: Close open handle after interrupted close CIFS: Respect O_SYNC and O_DIRECT flags during reconnect cifs: Don't display RDMA transport on reconnect cifs: smbd: Return -ECONNABORTED when trasnport is not in connected state cifs: smbd: Return -EINVAL when the number of iovs exceeds SMBDIRECT_MAX_SGE cifs: smbd: Add messages on RDMA session destroy and reconnection cifs: smbd: Only queue work for error recovery on memory registration cifs: smbd: Return -EAGAIN when transport is reconnecting rpmsg: glink: Free pending deferred work on remove rpmsg: glink: Don't send pending rx_done during remove rpmsg: glink: Fix rpmsg_register_device err handling rpmsg: glink: Put an extra reference during cleanup rpmsg: glink: Fix use after free in open_ack TIMEOUT case rpmsg: glink: Fix reuse intents memory leak issue rpmsg: glink: Set tail pointer to 0 at end of FIFO xtensa: fix syscall_set_return_value xtensa: fix TLB sanity checker gfs2: fix glock reference problem in gfs2_trans_remove_revoke gfs2: Multi-block allocations in gfs2_page_mkwrite xtensa: use MEMBLOCK_ALLOC_ANYWHERE for KASAN shadow map block: fix "check bi_size overflow before merge" PM / QoS: Redefine FREQ_QOS_MAX_DEFAULT_VALUE to S32_MAX PCI: Apply Cavium ACS quirk to ThunderX2 and ThunderX3 PCI: rcar: Fix missing MACCTLR register setting in initialization sequence PCI: Do not use bus number zero from EA capability PCI/MSI: Fix incorrect MSI-X masking on resume PCI: Fix Intel ACS quirk UPDCR register address PCI: pciehp: Avoid returning prematurely from sysfs requests PCI/PM: Always return devices to D0 when thawing PCI/switchtec: Read all 64 bits of part_event_bitmap mmc: core: Re-work HW reset for SDIO cards mmc: core: Drop check for mmc_card_is_removable() in mmc_rescan() mmc: block: Add CMD13 polling for MMC IOCTLS with R1B response mmc: block: Make card_busy_detect() a bit more generic USB: Fix incorrect DMA allocations for local memory pool drivers ANDROID: update ABI for db845c changes BACKPORT: iommu: arm-smmu-impl: Add sdm845 implementation hook UPSTREAM: firmware/qcom_scm: Add scm call to handle smmu errata UPSTREAM: firmware: qcom_scm-64: Add atomic version of qcom_scm_call UPSTREAM: cpufreq: qcom-hw: Move driver initialization earlier UPSTREAM: cpufreq: Initialize cpufreq-dt driver earlier UPSTREAM: cpufreq: Initialize the governors in core_initcall ANDROID: tty: serial_core: Export uart_console_device so it can be used by modules ANDROID: gki_defconfig: Add qcom pcie options to gki_defconfig ANDROID: Kconfig.gki: Add entries for qcom clk drivers ANDROID: Kconfig.gki: Add PINCTRL_MSM to QCOM Hidden configs ANDROID: Kconfig.gki: Add hidden CONFIG_WANT_DEV_COREDUMP for DRM_MSM driver ANDROID: PCI: qcom: Add support for SDM845 PCIe controller ANDROID: PCI: qcom: Fix the fixup of PCI_VENDOR_ID_QCOM ANDROID: phy: qcom: qmp: Add SDM845 QHP PCIe PHY ANDROID: phy: qcom: qmp: Add SDM845 PCIe QMP PHY support ANDROID: phy: qcom: qmp: Use power_on/off ops for PCIe ANDROID: phy: qcom-qmp: Increase PHY ready timeout msm: ipa3: Fix to ignore frag status packet in lan consumer pipe cpufreq: qcom-cpufreq-hw: Fix incorrect type warning from sparse arm64: defconfig: Enable SPS driver for Lahaina ASoC: compress: propagate the error code from the compress framework ASoC: msm: Update the encode option and sample rate Asoc: Add audio backend to hwdep interface ALSA: pcm: fix blocking while loop in snd_pcm_update_hw_ptr0() ASoC: Compress: Check and set pcm_new driver op ASoC: dapm: Avoid static route b/w cpu and codec dai scsi: ufs-qcom: Add reset control support for host controller scsi: ufs-qcom: Add ioctl interface for ufs query requests BACKPORT: FROMLIST: scsi: ufs: Export query request interfaces ALSA: compress: Add support to send codec specific data scsi: ufs-qti: Fix overwriting model name ASoC: msm: qdsp6v2: Cleanup of compress offload drivers ALSA: PCM: User control API implementation ALSA: PCM: volume API implementation ALSA: core: Handle user defined ioctls coresight: tmc: Fix mem_lock dead lock cpufreq: record CPUFREQ stat for fast switch path cpufreq: Add snapshot of qcom-cpufreq driver arm64: defconfig: Enable debug features on Lahaina coresight: ost: correct the kconfig dependency Bluetooth: Re-initialize regulator to NULL on error ANDROID: gki_defconfig: Enable CONFIG_GNSS_CMDLINE_SERIAL ANDROID: gnss: Add command line test driver ANDROID: serdev: add platform device support ANDROID: usb: gadget: Add configfs attribuite for controling match_existing_only net: cnss2: Remove unsupported symbol references ANDROID: gki_defconfig: enable ARM64_SW_TTBR0_PAN ANDROID: gki_defconfig: Set BINFMT_MISC as =m arm64: defconfig: Enable EDAC driver support for QCOM SoCs msm: sps: Fix build warnings msm: ipa3: Fix to avoid memory out of bound access error wil6210: reduce ucode_debug memory region wil6210: enable access category queues wil6210: allow sending special packets when tx ring is full wil6210: Support ndo_select_queue in net_device_ops wil6210: add verification for cid upper bound wil6210: take mem_lock for writing in crash dump collection wil6210: minimize the time that mem_lock is held wil6210: enable AP/PCP power save soc: mem_dump: fix physical address mapping issue soc: mem_dump: Add support for CPU subsystem register dump soc: qcom: Update the dump table region size in imem soc: qcom: Unify the memory dump entries registration arm64: defconfig: Enable minidump driver on Lahaina GKI soc: qcom: Add snapshot of minidump FROMLIST: ARM: Remove arm_pm_restart() FROMLIST: ARM64: Remove arm_pm_restart() FROMLIST: ARM: Register with kernel restart handler FROMLIST: drivers: firmware: psci: Register with kernel restart handler FROMLIST: ARM: xen: Register with kernel restart handler FROMLIST: ARM: prima2: Register with kernel restart handler shmbridge: get bridge mem pool's DMA address with dma_map_single firmware: qcom_scm: Add calls to support poweroff driver firmware: qcom_scm: Expose qcom_scm_set_download_mode arm64: defconfig: Enable WALT for Lahaina sched: Improve the scheduler hwrng: Add QRNG driver snapshot for kona msm: sps: Add SPS driver snapshot ANDROID: ASoC: add hikey960-i2s DT bindings ANDROID: sound: Add hikey960 i2s audio driver ANDROID: HACK: adv7511: Add poweron delay to allow for EDID probing to work ANDROID: drm: kirin: Fix Makefile to correct for module builds ANDROID: drm: kirin960: Remove one mode-line that seems to be causing trouble ANDROID: drm: kirin: remove wait for VACTIVE IRQ ANDROID: drm: kirin: Add kirin960 dpe driver support ANDROID: drm: kirin: Introduce kirin960 ANDROID: arm64: dts: hi3660: Add support for usb on Hikey960 ANDROID: arm64: dts: hikey960: Fix bootwarning on mapping reboot reason syscon ANDROID: arm64: dts: hi3660: adb reboot node ANDROID: arm64: dts: hi3660: enable gpu ANDROID: arm64: dts: hi3660-hikey960: Add i2s & sound device ANDROID: arm64: dts: hi3660: add display driver dts ANDROID: arm64: dts: hikey960: Add CMA entry for ION/framebuffers ANDROID: mm/memory.c: export mm_trace_rss_stat ANDROID: update ABI for 5.4.5 Linux 5.4.5 r8169: add missing RX enabling for WoL on RTL8125 net: mscc: ocelot: unregister the PTP clock on deinit ionic: keep users rss hash across lif reset xdp: obtain the mem_id mutex before trying to remove an entry. page_pool: do not release pool until inflight == 0. net/mlx5e: ethtool, Fix analysis of speed setting net/mlx5e: Fix translation of link mode into speed net/mlx5e: Fix freeing flow with kfree() and not kvfree() net/mlx5e: Fix SFF 8472 eeprom length act_ct: support asymmetric conntrack net/mlx5e: Fix TXQ indices to be sequential net: Fixed updating of ethertype in skb_mpls_push() hsr: fix a NULL pointer dereference in hsr_dev_xmit() Fixed updating of ethertype in function skb_mpls_pop gre: refetch erspan header from skb->data after pskb_may_pull() cls_flower: Fix the behavior using port ranges with hw-offload net: sched: allow indirect blocks to bind to clsact in TC net: core: rename indirect block ingress cb function tcp: Protect accesses to .ts_recent_stamp with {READ,WRITE}_ONCE() tcp: tighten acceptance of ACKs not matching a child socket tcp: fix rejected syncookies due to stale timestamps net: ipv6_stub: use ip6_dst_lookup_flow instead of ip6_dst_lookup net: ipv6: add net argument to ip6_dst_lookup_flow net/mlx5e: Query global pause state before setting prio2buffer tipc: fix ordering of tipc module init and exit routine tcp: md5: fix potential overestimation of TCP option space openvswitch: support asymmetric conntrack net/tls: Fix return values to avoid ENOTSUPP net: thunderx: start phy before starting autonegotiation net_sched: validate TCA_KIND attribute in tc_chain_tmplt_add() net: sched: fix dump qlen for sch_mq/sch_mqprio with NOLOCK subqueues net: ethernet: ti: cpsw: fix extra rx interrupt net: dsa: fix flow dissection on Tx path net: bridge: deny dev_set_mac_address() when unregistering mqprio: Fix out-of-bounds access in mqprio_dump inet: protect against too small mtu values. ANDROID: add initial ABI whitelist for android-5.4 wil6210: dump Rx status message on errors arm64: config: Enable socinfo driver for QCOM SoCs coresight: Add snapshot of jtagv8 driver defconfig: lahaina-gki: enable ufs 7nm phy for lahaina phy: qcom-ufs: add 7nm UFS QMP PHY support on Lahaina phy: qcom-ufs: add UFS HS-G4 support phy: qcom-ufs: move PHY configurations after vregs and clocks are enabled phy: qcom-ufs: don't error out if vddp-ref-clk-supply is absent phy: qcom-ufs: make ref_clk as optional phy: qcom-ufs: separate out 2 lanes configuration phy: qcom-ufs: set no runtime PM callbacks flag phy: qcom-ufs: parse ref-clk details prior to resource request phy: qcom-ufs: remove warnings for optional clocks phy: qcom-ufs: add optional ref aux clk phy: qcom-ufs: don't probe for "dev_ref_clk_ctrl_mem" phy: qcom-ufs: remove failure when rx/tx_iface_clk are absent defconfig: Initial genericarmv8 defconfig mm: oom_kill: dump info of all tasks when the FG process is killed iommu/arm-smmu: restrict secure vmid update while attached iommu/arm-smmu: reduce tlb sync poll retry latency interconnect: qcom: Build icc-rpmh with qnoc-lahaina kbuild: Disable the gcc-wrapper with an environment variable PM / devfreq: icc: add support for L3 voting PM / devfreq: memlat: add support for shared core-dev tables sched: Support Energy Aware Scheduling irrespective of governor sched: Add schedutil snapshot PM / devfreq: memlat: simplify core-dev table parsing logic ANDROID: abi update for 5.4.4 ANDROID: mm: Throttle rss_stat tracepoint FROMLIST: vsprintf: Inline call to ptr_to_hashval UPSTREAM: rss_stat: Add support to detect RSS updates of external mm UPSTREAM: mm: emit tracepoint when RSS changes defconfig: Enable QCOM_RUN_QUEUE_STATS time: Add rq_stats snapshot Linux 5.4.4 EDAC/ghes: Do not warn when incrementing refcount on 0 r8169: fix rtl_hw_jumbo_disable for RTL8168evl workqueue: Fix missing kfree(rescuer) in destroy_workqueue() blk-mq: make sure that line break can be printed ext4: fix leak of quota reservations ext4: fix a bug in ext4_wait_for_tail_page_commit splice: only read in as much information as there is pipe buffer space rtc: disable uie before setting time and enable after USB: dummy-hcd: increase max number of devices to 32 powerpc: Define arch_is_kernel_initmem_freed() for lockdep mm/shmem.c: cast the type of unmap_start to u64 s390/kaslr: store KASLR offset for early dumps s390/smp,vdso: fix ASCE handling firmware: qcom: scm: Ensure 'a0' status code is treated as signed ext4: work around deleting a file with i_nlink == 0 safely mm: memcg/slab: wait for !root kmem_cache refcnt killing on root kmem_cache destruction mfd: rk808: Fix RK818 ID template mm, memfd: fix COW issue on MAP_PRIVATE and F_SEAL_FUTURE_WRITE mappings powerpc: Fix vDSO clock_getres() powerpc: Avoid clang warnings around setjmp and longjmp omap: pdata-quirks: remove openpandora quirks for mmc3 and wl1251 omap: pdata-quirks: revert pandora specific gpiod additions iio: ad7949: fix channels mixups iio: ad7949: kill pointless "readback"-handling code Revert "scsi: qla2xxx: Fix memory leak when sending I/O fails" scsi: qla2xxx: Fix a dma_pool_free() call scsi: qla2xxx: Fix SRB leak on switch command timeout reiserfs: fix extended attributes on the root directory ext4: Fix credit estimate for final inode freeing quota: fix livelock in dquot_writeback_dquots seccomp: avoid overflow in implicit constant conversion ext2: check err when partial != NULL quota: Check that quota is not dirty before release video/hdmi: Fix AVI bar unpack powerpc/xive: Skip ioremap() of ESB pages for LSI interrupts powerpc: Allow flush_icache_range to work across ranges >4GB powerpc/xive: Prevent page fault issues in the machine crash handler powerpc: Allow 64bit VDSO __kernel_sync_dicache to work across ranges >4GB coresight: Serialize enabling/disabling a link device. stm class: Lose the protocol driver when dropping its reference ppdev: fix PPGETTIME/PPSETTIME ioctls RDMA/core: Fix ib_dma_max_seg_size() ARM: dts: omap3-tao3530: Fix incorrect MMC card detection GPIO polarity mmc: host: omap_hsmmc: add code for special init of wl1251 to get rid of pandora_wl1251_init_card pinctrl: samsung: Fix device node refcount leaks in S3C64xx wakeup controller init pinctrl: samsung: Fix device node refcount leaks in init code pinctrl: samsung: Fix device node refcount leaks in S3C24xx wakeup controller init pinctrl: samsung: Fix device node refcount leaks in Exynos wakeup controller init pinctrl: samsung: Add of_node_put() before return in error path pinctrl: armada-37xx: Fix irq mask access in armada_37xx_irq_set_type() pinctrl: rza2: Fix gpio name typos ACPI: PM: Avoid attaching ACPI PM domain to certain devices ACPI: EC: Rework flushing of pending work ACPI: bus: Fix NULL pointer check in acpi_bus_get_private_data() ACPI: OSL: only free map once in osl.c ACPI / hotplug / PCI: Allocate resources directly under the non-hotplug bridge ACPI: LPSS: Add dmi quirk for skipping _DEP check for some device-links ACPI: LPSS: Add LNXVIDEO -> BYT I2C1 to lpss_device_links ACPI: LPSS: Add LNXVIDEO -> BYT I2C7 to lpss_device_links ACPI / utils: Move acpi_dev_get_first_match_dev() under CONFIG_ACPI ALSA: hda/realtek - Line-out jack doesn't work on a Dell AIO ALSA: oxfw: fix return value in error path of isochronous resources reservation ALSA: fireface: fix return value in error path of isochronous resources reservation cpufreq: powernv: fix stack bloat and hard limit on number of CPUs PM / devfreq: Lock devfreq in trans_stat_show intel_th: pci: Add Tiger Lake CPU support intel_th: pci: Add Ice Lake CPU support intel_th: Fix a double put_device() in error path powerpc/perf: Disable trace_imc pmu drm/panfrost: Open/close the perfcnt BO perf tests: Fix out of bounds memory access erofs: zero out when listxattr is called with no xattr cpuidle: use first valid target residency as poll time cpuidle: teo: Fix "early hits" handling for disabled idle states cpuidle: teo: Consider hits and misses metrics of disabled states cpuidle: teo: Rename local variable in teo_select() cpuidle: teo: Ignore disabled idle states that are too deep cpuidle: Do not unset the driver if it is there already media: cec.h: CEC_OP_REC_FLAG_ values were swapped media: radio: wl1273: fix interrupt masking on release media: bdisp: fix memleak on release media: vimc: sen: remove unused kthread_sen field media: hantro: Fix picture order count table enable media: hantro: Fix motion vectors usage condition media: hantro: Fix s_fmt for dynamic resolution changes s390/mm: properly clear _PAGE_NOEXEC bit when it is not supported ar5523: check NULL before memcpy() in ar5523_cmd() wil6210: check len before memcpy() calls cgroup: pids: use atomic64_t for pids->limit blk-mq: avoid sysfs buffer overflow with too many CPU cores md: improve handling of bio with REQ_PREFLUSH in md_flush_request() ASoC: fsl_audmix: Add spin lock to protect tdms ASoC: Jack: Fix NULL pointer dereference in snd_soc_jack_report ASoC: rt5645: Fixed typo for buddy jack support. ASoC: rt5645: Fixed buddy jack support. workqueue: Fix pwq ref leak in rescuer_thread() workqueue: Fix spurious sanity check failures in destroy_workqueue() dm zoned: reduce overhead of backing device checks dm writecache: handle REQ_FUA hwrng: omap - Fix RNG wait loop timeout ovl: relax WARN_ON() on rename to self ovl: fix corner case of non-unique st_dev;st_ino ovl: fix lookup failure on multi lower squashfs lib: raid6: fix awk build warnings rtlwifi: rtl8192de: Fix missing enable interrupt flag rtlwifi: rtl8192de: Fix missing callback that tests for hw release of buffer rtlwifi: rtl8192de: Fix missing code to retrieve RX buffer address btrfs: record all roots for rename exchange on a subvol Btrfs: send, skip backreference walking for extents with many references btrfs: Remove btrfs_bio::flags member btrfs: Avoid getting stuck during cyclic writebacks Btrfs: fix negative subv_writers counter and data space leak after buffered write Btrfs: fix metadata space leak on fixup worker failure to set range as delalloc btrfs: use refcount_inc_not_zero in kill_all_nodes btrfs: use btrfs_block_group_cache_done in update_block_group btrfs: check page->mapping when loading free space cache iwlwifi: pcie: fix support for transmitting SKBs with fraglist usb: typec: fix use after free in typec_register_port() phy: renesas: rcar-gen3-usb2: Fix sysfs interface of "role" usb: dwc3: ep0: Clear started flag on completion usb: dwc3: gadget: Clear started flag for non-IOC usb: dwc3: gadget: Fix logical condition usb: dwc3: pci: add ID for the Intel Comet Lake -H variant virtio-balloon: fix managed page counts when migrating pages between zones virt_wifi: fix use-after-free in virt_wifi_newlink() mtd: rawnand: Change calculating of position page containing BBM mtd: spear_smi: Fix Write Burst mode brcmfmac: disable PCIe interrupts before bus reset EDAC/altera: Use fast register IO for S10 IRQs tpm: Switch to platform_get_irq_optional() tpm: add check after commands attribs tab allocation usb: mon: Fix a deadlock in usbmon between mmap and read usb: core: urb: fix URB structure initialization function USB: adutux: fix interface sanity check usb: roles: fix a potential use after free USB: serial: io_edgeport: fix epic endpoint lookup USB: idmouse: fix interface sanity checks USB: atm: ueagle-atm: add missing endpoint check iio: adc: ad7124: Enable internal reference iio: adc: ad7606: fix reading unnecessary data from device iio: imu: inv_mpu6050: fix temperature reporting using bad unit iio: humidity: hdc100x: fix IIO_HUMIDITYRELATIVE channel reporting iio: adis16480: Fix scales factors iio: imu: st_lsm6dsx: fix ODR check in st_lsm6dsx_write_raw iio: adis16480: Add debugfs_reg_access entry ARM: dts: pandora-common: define wl1251 as child node of mmc3 usb: common: usb-conn-gpio: Don't log an error on probe deferral interconnect: qcom: qcs404: Walk the list safely on node removal interconnect: qcom: sdm845: Walk the list safely on node removal xhci: make sure interrupts are restored to correct state xhci: handle some XHCI_TRUST_TX_LENGTH quirks cases as default behaviour. xhci: Increase STS_HALT timeout in xhci_suspend() xhci: fix USB3 device initiated resume race with roothub autosuspend xhci: Fix memory leak in xhci_add_in_port() usb: xhci: only set D3hot for pci device staging: gigaset: add endpoint-type sanity check staging: gigaset: fix illegal free on probe errors staging: gigaset: fix general protection fault on probe staging: vchiq: call unregister_chrdev_region() when driver registration fails staging: rtl8712: fix interface sanity check staging: rtl8188eu: fix interface sanity check staging: exfat: fix multiple definition error of `rename_file' binder: fix incorrect calculation for num_valid usb: host: xhci-tegra: Correct phy enable sequence usb: Allow USB device to be warm reset in suspended state USB: documentation: flags on usb-storage versus UAS USB: uas: heed CAPACITY_HEURISTICS USB: uas: honor flag to avoid CAPACITY16 media: venus: remove invalid compat_ioctl32 handler ceph: fix compat_ioctl for ceph_dir_operations compat_ioctl: add compat_ptr_ioctl() scsi: qla2xxx: Fix memory leak when sending I/O fails scsi: qla2xxx: Fix double scsi_done for abort path scsi: qla2xxx: Fix driver unload hang scsi: qla2xxx: Do command completion on abort timeout scsi: zfcp: trace channel log even for FCP command responses scsi: lpfc: Fix bad ndlp ptr in xri aborted handling Revert "nvme: Add quirk for Kingston NVME SSD running FW E8FK11.T" nvme: Namepace identification descriptor list is optional usb: gadget: pch_udc: fix use after free usb: gadget: configfs: Fix missing spin_lock_init() mm: vmstat: add pageoutclean drivers: thermal: qmi_cooling: Add snapshot of QMI cooling device driver drivers: thermal: Add a snapshot of bcl soc driver drivers: thermal: bcl_pmic5: Add snapshot of bcl driver drivers: thermal: qmi_sensor: Add snapshot of qmi sensor driver drivers: thermal: cpu_isolate: Add a snapshot of cpu isolate msm: cvp: Fence path for Lahaina cpufreq: qcom-hw: cleanup the driver for HW driver coresight: stm: STM master side access control scsi: ufs-qti: port UFS driver changes for QTI configuration socinfo: add socinfo driver uio: Kconfig: Enable msm shared memory driver defconfig: lahaina: enable PCIe root complex and PCIe MSI for lahaina msm: pcie: remove deprecated explicit clock retention support msm: pcie: add lahaina PCI device ID to PCI table msm: pcie: update deprecated wakeup_source_* API msm: pcie: add snapshot of PCIe root complex bus driver usb: xhci: Add helper API to issue stop endpoint command usb: xhci: Add helper APIs to return xhci dma addresses usb: xhci: Add support for secondary interrupters defconfig: enable cdsp loader on Lahaina as DLKM module defconfig: lahaina: enable the UCSI Glink driver usb: typec: ucsi: add QTI UCSI Glink driver sched/walt: Improve the scheduler sched/walt: Improve the scheduler sched/fair: Avoid force newly idle load balance if have iowait task sched/fair: Improve the scheduler sched/fair: Force gold cpus to do idle lb when silver has big tasks defconfig: enable fastrpc driver on Lahaina BACKPORT: FROMLIST: scsi: ufs: Export query request interfaces defconfig: lahaina-gki: enable qpnp-power-on driver input: qpnp-power-on: add support for PON_GEN3 subtype PON peripherals dt-bindings: input: add qpnp-power-on bindings input: add snapshot of qpnp-power-on driver defconfig: lahaina-qgki: enable regmap debugfs features defconfig: lahaina-gki: enable gpio-keys driver defconfig: lahaina-gki: enable SPMI and PMIC drivers defconfig: lahaina-qgki: enable CONFIG_IIO pinctrl: qcom: spmi-gpio: define an irqchip for each pinctrl device pinctrl: qcom: spmi-gpio: add support for PMR735A and PMR735B PMIC variants pinctrl: Add wakeup gpio register and bit information msm: ipa: load IPA FW after smmu CB are probed iio: adc: Add support for PMIC7 VADC dt-bindings: iio: Add PMIC7 ADC support soc: qcom: reserve memory in memory dump probe slimbus: Add snapshot of slimbus driver msm: ipa4: Allocate coalescing close frame command payload coresight: enable stm logging for trace events, marker and printk arm64: defconfig: Enable QUPv3 and GPI drivers on lahaina coresight-tmc: Re-use ETR buffer across use cases coresight-tmc: add support to configure flush and reset CTIs coresight: Add snapshot of Coresight cti driver coresight: Add regulator and clock vote for coresight components msm: ipa: add support to updated wdi3 scratch register2 alone msm: ipa: Fix not sending QMI sync indication msm: ipa: Add graceful handling to skip partial packets msm: ipa: Fix not to update state during pipe reset msm: ipa: Update IPA register offsets and fields wil6210: fix iommu_unmap in IPA mode wil6210: new NL command to get driver capabilities wil6210: use wigig.ini as a configuration file wil6210: extend bus voting support for wider bandwidth wil6210: ipa stop/wake queue based on outstanding packets wil6210: add support for spi slave reset wil6210: update the disconnect sequence for the IPA disconnect wil6210: support VR profiles wil6210: add support for sensing over SPI wil6210: support IPA offload wil6210: support multiple desc and status rings handling wil6210: support NL_60G_GEN_FW_RESET UNSPEC vendor command wil6210: add support for pci linkdown recovery wil6210: add support for headroom configuration arm64: defconfig: Enable spcom driver on Lahaina cpufreq: qcom: Update cycle counter logic for CPUFREQ HW cpufreq: qcom-cpufreq-hw: Initialize the spinlock before usage cpufreq: qcom-hw: Add register offsets for non-epss devices cpufreq: qcom-hw: Update freq_scale from fast_switch path cpufreq: qcom-hw: Add support for EPSS CPUFREQ firmware net: cnss2: Update CNSS2 driver ANDROID: update abi with unbindable_ports sysctl BACKPORT: FROMLIST: net: introduce ip_local_unbindable_ports sysctl ANDROID: update abi for 5.4.3 merge ANDROID: update abi_gki_aarch64.xml for ion, drm changes ANDROID: drivers: gpu: drm: export drm_mode_convert_umode symbol ANDROID: ion: flush cache before exporting non-cached buffers Linux 5.4.3 kselftest: Fix NULL INSTALL_PATH for TARGETS runlist perf script: Fix invalid LBR/binary mismatch error EDAC/ghes: Fix locking and memory barrier issues watchdog: aspeed: Fix clock behaviour for ast2600 drm/mcde: Fix an error handling path in 'mcde_probe()' md/raid0: Fix an error message in raid0_make_request() cpufreq: imx-cpufreq-dt: Correct i.MX8MN's default speed grade value ALSA: hda - Fix pending unsol events at shutdown KVM: x86: fix out-of-bounds write in KVM_GET_EMULATED_CPUID (CVE-2019-19332) binder: Handle start==NULL in binder_update_page_range() binder: Prevent repeated use of ->mmap() via NULL mapping binder: Fix race between mmap() and binder_alloc_print_pages() Revert "serial/8250: Add support for NI-Serial PXI/PXIe+485 devices" vcs: prevent write access to vcsu devices thermal: Fix deadlock in thermal thermal_zone_device_check iomap: Fix pipe page leakage during splicing bdev: Refresh bdev size for disks without partitioning bdev: Factor out bdev revalidation into a common helper rfkill: allocate static minor RDMA/qib: Validate ->show()/store() callbacks before calling them can: ucan: fix non-atomic allocation in completion handler spi: Fix NULL pointer when setting SPI_CS_HIGH for GPIO CS spi: Fix SPI_CS_HIGH setting when using native and GPIO CS spi: atmel: Fix CS high support spi: stm32-qspi: Fix kernel oops when unbinding driver spi: spi-fsl-qspi: Clear TDH bits in FLSHCR register crypto: user - fix memory leak in crypto_reportstat crypto: user - fix memory leak in crypto_report crypto: ecdh - fix big endian bug in ECC library crypto: ccp - fix uninitialized list head crypto: geode-aes - switch to skcipher for cbc(aes) fallback crypto: af_alg - cast ki_complete ternary op to int crypto: atmel-aes - Fix IV handling when req->nbytes < ivsize crypto: crypto4xx - fix double-free in crypto4xx_destroy_sdr KVM: x86: Grab KVM's srcu lock when setting nested state KVM: x86: Remove a spurious export of a static function KVM: x86: fix presentation of TSX feature in ARCH_CAPABILITIES KVM: x86: do not modify masked bits of shared MSRs KVM: arm/arm64: vgic: Don't rely on the wrong pending table KVM: nVMX: Always write vmcs02.GUEST_CR3 during nested VM-Enter KVM: PPC: Book3S HV: XIVE: Set kvm->arch.xive when VPs are allocated KVM: PPC: Book3S HV: XIVE: Fix potential page leak on error path KVM: PPC: Book3S HV: XIVE: Free previous EQ page when setting up a new one arm64: dts: exynos: Revert "Remove unneeded address space mapping for soc node" arm64: Validate tagged addresses in access_ok() called from kernel threads drm/i810: Prevent underflow in ioctl drm: damage_helper: Fix race checking plane->state->fb drm/msm: fix memleak on release jbd2: Fix possible overflow in jbd2_log_space_left() kernfs: fix ino wrap-around detection nfsd: restore NFSv3 ACL support nfsd: Ensure CLONE persists data and metadata changes to the target file can: slcan: Fix use-after-free Read in slcan_open tty: vt: keyboard: reject invalid keycodes CIFS: Fix SMB2 oplock break processing CIFS: Fix NULL-pointer dereference in smb2_push_mandatory_locks x86/PCI: Avoid AMD FCH XHCI USB PME# from D0 defect x86/mm/32: Sync only to VMALLOC_END in vmalloc_sync_all() media: rc: mark input device as pointing stick Input: Fix memory leak in psxpad_spi_probe coresight: etm4x: Fix input validation for sysfs. Input: goodix - add upside-down quirk for Teclast X89 tablet Input: synaptics-rmi4 - don't increment rmiaddr for SMBus transfers Input: synaptics-rmi4 - re-enable IRQs in f34v7_do_reflash Input: synaptics - switch another X1 Carbon 6 to RMI/SMbus soc: mediatek: cmdq: fixup wrong input order of write api ALSA: hda: Modify stream stripe mask only when needed ALSA: hda - Add mute led support for HP ProBook 645 G4 ALSA: pcm: oss: Avoid potential buffer overflows ALSA: hda/realtek - Fix inverted bass GPIO pin on Acer 8951G ALSA: hda/realtek - Dell headphone has noise on unmute for ALC236 ALSA: hda/realtek - Enable the headset-mic on a Xiaomi's laptop ALSA: hda/realtek - Enable internal speaker of ASUS UX431FLC SUNRPC: Avoid RPC delays when exiting suspend io_uring: ensure req->submit is copied when req is deferred io_uring: fix missing kmap() declaration on powerpc fuse: verify attributes fuse: verify write return fuse: verify nlink fuse: fix leak of fuse_io_priv io_uring: transform send/recvmsg() -ERESTARTSYS to -EINTR io_uring: fix dead-hung for non-iter fixed rw mwifiex: Re-work support for SDIO HW reset serial: ifx6x60: add missed pm_runtime_disable serial: 8250_dw: Avoid double error messaging when IRQ absent serial: stm32: fix clearing interrupt error flags serial: serial_core: Perform NULL checks for break_ctl ops serial: pl011: Fix DMA ->flush_buffer() tty: serial: msm_serial: Fix flow control tty: serial: fsl_lpuart: use the sg count from dma_map_sg serial: 8250-mtk: Use platform_get_irq_optional() for optional irq usb: gadget: u_serial: add missing port entry locking staging/octeon: Use stubs for MIPS && !CAVIUM_OCTEON_SOC mailbox: tegra: Fix superfluous IRQ error message time: Zero the upper 32-bits in __kernel_timespec on 32-bit lp: fix sparc64 LPSETTIMEOUT ioctl sparc64: implement ioremap_uc perf scripts python: exported-sql-viewer.py: Fix use of TRUE with SQLite arm64: tegra: Fix 'active-low' warning for Jetson Xavier regulator arm64: tegra: Fix 'active-low' warning for Jetson TX1 regulator rsi: release skb if rsi_prepare_beacon fails phy: phy-qcom-ufs: add receive line configuration ufs: qcom: port from msm-4.19 scsi: ufs-qcom: Clock scaling code restructure defconfig: lahaina-gki: Enable USB Electrical and Link test support clk: dt-bindings: Define clock IDs supported by bolero codec FROMLIST: scsi: ufs: Fix ufshcd_hold() caused scheduling while atomic FROMLIST: scsi: ufs: Add dev ref clock gating wait time support FROMLIST: scsi: ufs-qcom: Adjust bus bandwidth voting and unvoting FROMLIST: scsi: ufs: Remove the check before call setup clock notify vops FROMLIST: scsi: ufs: set load before setting voltage in regulators FROMLIST: scsi: ufs: Flush exception event before suspend FROMLIST: scsi: ufs: Do not rely on prefetched data FROMLIST: scsi: ufs: Fix up clock scaling FROMGIT: scsi: ufs: Do not free irq in suspend FROMGIT: scsi: ufs: Do not clear the DL layer timers FROMGIT: scsi: ufs: Release clock if DMA map fails FROMGIT: scsi: ufs: Use DBD setting in mode sense FROMGIT: scsi: core: Adjust DBD setting in MODE SENSE for caching mode page per LLD FROMGIT: scsi: ufs: Complete pending requests in host reset and restore path FROMGIT: scsi: ufs: Avoid messing up the compl_time_stamp of lrbs FROMGIT: scsi: ufs: Update VCCQ2 and VCCQ min/max voltage hard codes FROMGIT: scsi: ufs: Recheck bkops level if bkops is disabled drivers: thermal: of-thermal: Add support for virtual sensor drivers: thermal: of-thermal: Add a snapshot of of-thermal drivers: thermal: Add QTI_THERMAL config clk: qcom: Fix orphaned sleep clocks for Lahaina arm64: defconfig: Remove IKHEADERS option drivers: thermal: cpu_cooling: Use Policy cpu as cdev ID thermal: Include qcom thermal drivers for CONFIG_ARCH_QCOM arm64: Remove cpu_soft_reset() prototype uapi: Fix QCOM headers to work with UAPI_HEADER_TEST Revert "perf: Set the DSU PMU to be readable from any CPU" msm: kgsl: Check the return value of sysfs functions dma-mapping-fast: Clean up common code dma-mapping-fast: Add support for DMA_ATTR_FORCE_CONTIGUOUS dma-mapping-fast: Do not clobber existing atomic pool dma-mapping-fast: Reorganize common behavior drivers: soc: qcom: Add snapshot of EUD driver msm: adsprpc: Remove IPC logging from fastrpc driver ANDROID: update abi_gki_aarch64.xml for LTO, CFI, and SCS ANDROID: gki_defconfig: enable LTO, CFI, and SCS wil6210: fix for "runtime PM when interface is down" wil6210: support FCC board file wil6210: force EDMG channel through debugfs wil6210: publish/receive WMI events/commands through nl wil6210: BRP antenna limit API wil6210: support configurable board file via sysfs wil6210: use country specific board file upon reg domain change wil6210: allow flashless boot when OTP is empty wil6210: drop RX probe reponses with low SNR wil6210: add sysfs for setting connect SNR threshold wil6210: support AOA in FTM session wil6210: potential buffer overflow in wmi_evt_aoa_meas wil6210: send uevent when creating sysfs files wil6210: add option to ignore OTA regulatory hints wil6210: add sysfs file for enable/disable fst link loss wil6210: add sysfs for thermal throttling configuration coresight: ost: Add snapshot of Coresight OST driver soc: qcom: subsys_notif: Add early SSR notifications for PCIe DRV ANDROID: update abi_gki_aarch64.xml for CONFIG_GNSS ANDROID: cuttlefish_defconfig: Enable CONFIG_GNSS rtc: rtc-pm8xxx: add support for PMK8350 RTC ANDROID: gki_defconfig: enable HID configs defconfig: lahaina-gki: Enable QTI Tri-LED driver arm64: defconfig: Enable tz_log driver for Lahaina firmware: qcom: Add TZ log driver snapshot for Lahaina Revert "soc: qcom: socinfo: Expose custom attributes" UPSTREAM: arm64: Validate tagged addresses in access_ok() called from kernel threads soc: qcom: spcom: add spcom as DLKM for GKI cpufreq: qcom-hw: use no_log when reading cpu counter val cpufreq: qcom-hw: Register child devices cpufreq: qcom-hw: Add ready callback to register CPU cooling device cpufreq: qcom-hw: add cycle counter support cpufreq: qcom-hw: remove check for hw enable during probe cpufreq: qcom-hw: Set dvfs_possible_from_any_cpu cpufreq driver flag cpufreq: qcom-hw: Notify the current frequency to the topology driver cpufreq: qcom-hw: register with Energy Model framework cpufreq: qcom: Read voltage LUT and populate OPP cpufreq: qcom-hw: use pre-defined core count for max cores cpufreq: qcom: Add snapshot of cpufreq-hw usb: host: xhci: Replace msleep with usleep_range usb: host: xhci: Change L1 timeout default to 128us usb: xhci: Add support for SINGLE_STEP_SET_FEATURE test of EHSET host: xhci-plat: Enable autosuspend functionality with root hub usb: core: Enable xhci irq after starting controller usb: xhci-plat: Remove system PM call backs xhci-plat: Use USB glue driver device as sysdev arm64: defconfig: Enable EPSS L3 Interconnect driver for Lahaina arm64: defconfig: Enable QCOM clock debug features firmware: qcom_scm: Export invoke callback response API firmware: qcom_scm: Move qseecom specific workarounds sched/fair: Improve the scheduler sched/fair: Improve the scheduler FROMLIST: sched/fair: Use wake_q length as a hint for wake_wide sched/fair: Improve the scheduler sched: use the CPU true capacity while sorting the min/mid/max CPUs cpuset: Restore tasks affinity while moving across cpusets PM / EM: Micro optimization in em_pd_energy sched: trace : Print current sched domain overutilization status ANDROID: sched/fair: Reduce balance interval to 1 jiffy if we have a misfit task ANDROID: trace/sched: Add tracepoint for sched_overutilized events ANDROID: sched: Per-Sched-domain over utilization sched: Add snapshot of task boost feature watchdog: use per_cpu_ptr() in watchdog_disable() Revert "softirq: Let ksoftirqd do its job" Revert "Mark HI and TASKLET softirq synchronous" genirq: Honour IRQ's affinity hint during migration softirq: Don't defer all softirq during RT task sched/cpupri: Exclude isolated CPUs from the lowest_mask softirq: defer softirq processing to ksoftirqd if CPU is busy with RT sched: avoid migrating when softint on tgt cpu should be short sched: avoid scheduling RT threads on cores currently handling softirqs sched/rt: Add snapshot of changes to RT class sched/fair: Add snapshot of load-balancing changes sched/fair: Add snapshot of placement changes sched: Add snapshot of preemption and IRQs disable callers sched: Add snapshot of sched_{up,down}migrate knobs kernel: Add snapshot of changes to support cpu isolation sched: Add sched_enq_deq_task trace point sched: Add snapshot of Window Assisted Load Tracking (WALT) interconnect: qcom: Prevent duplicate BCMs being added to commit list scripts: Makefile: Remove flags which are not support by EXT_DTC scripts: Makefile: add support to use external DTC scripts: Makefile: Add multi overlay dtbo-base apply verify scripts: Makefile: Change output overlay from .dtb to .tmp scripts: Makefile: add support to compile DT overlay blobs leds: Add snapshot of QTI Tri-LED driver soc: qcom: add secure processor communication (spcom) driver msm: kgsl: Remove legacy support for clock_set_flags msm: kgsl: Remove enhanced memory accounting msm: kgsl: Add an option to always enable I/O coherency msm: kgsl: bus dcvs fixes msm: kgsl: Generate TCS votes to send to the GMU msm: kgsl: Use bulk clock functions for GMU msm: kgsl: Modernize bus scaling msm: kgsl: Dynamically create an OPP table at runtime msm: kgsl: Move voltage levels to the GPU specific powerlevels msm: kgsl: Bring in the GPU bandwidth governor msm: kgsl: Fixup kernel API changes msm: kgsl: Bring in the GPU frequency governor msm: kgsl: Remove "zero" power level msm: kgsl: Move the system PM operations to adreno msm: kgsl: Re-export the UAPI header arm64: defconfig: Enable spss_utils driver on Lahaina coresight: funnel: add support for multiple output ports coresight: Kconfig: Add CORESIGHT_QGKI configuration ANDROID: kbuild: limit LTO inlining ANDROID: kbuild: merge module sections with LTO msm: adsprpc: Updating dependencies for fastrpc driver arm64: defconfig: Enable printing unhashed pointers on Lahaina arm64: defconfig: Enable devfreq drivers on Lahaina usb: gadget: f_fs: Add support for IPC logging defconfig: lahaina-gki: Enable PWM LPG driver pwm: Add snapshot of QTI PWM LPG driver defconfig: lahaina-gki: Enable MFD SPMI PMIC driver clk: qcom: Add additional clock debugfs support clk: add/modify debugfs support for clocks interconnect: qcom: Add EPSS L3 support for Lahaina dt-bindings: interconnect: Add epss l3 header for Lahaina drivers: llcc edac: Add Cache Error Reporting driver for llcc drivers: soc: qcom: Add snapshot of boot stats driver drivers: firmware: psci: Register with kernel restart handler msm: ipa: Free rx_wrapper for tmp_alloc pages ANDROID: f2fs: fix possible merge of unencrypted with encrypted I/O spi: spi-msm-geni: Add support to make SPI driver GKI compliant coresight: Add snapshot of remote etm driver coresight: Add snapshot of remote qdss driver wil6210: added sysfs file for FTM calibration wil6210: fix QCA_WLAN_VENDOR_ATTR_FREQ attribute ID wil6210: support FTM/AOA while unassociated wil6210: initial support for FTM and AOA ANDROID: gki_defconfig: Enable UCLAMP by default firmware: qcom_scm: Check for NULL before dereferencing __scm ANDROID: make sure proc mount options are applied ANDROID: sound: usb: Add helper APIs to enable audio stream devfreq: Do not allow tunable updates when device is suspended PM/devfreq: Do not switch governors from sysfs when device is suspended PM / devfreq: Fix race condition between suspend/resume and governor_store PM / devfreq: Introduce an event lock Revert "PM / devfreq: Modify the device name as devfreq(X) for sysfs" PM / devfreq: qoslat: Update voting level definitions devfreq: Allow bw_hwmon resume with zero resume freq devfreq: bwmon: Increase the IOPercentage limits to 400 qcom-llcc-pmu: Update the LLCC PMU configurations for kona perf: Introduce a LLCC PMU PM / devfreq: Add support for memory latency QoS voting PM / devfreq: memlat: optimize freq and stall_pct calculations PM / devfreq: memlat: Aggregate memlat mons under a controller devfreq: detect ddr type and add frequency table accordingly PM / devfreq: bw_hwmon: use unsigned parameter for bytes_to_mbps devfreq: bimc_bwmon: Add support to enable BWMON clks devfreq: return error code when governor start fails devfreq: bw_mon: check for the return value of start_monitor devfreq: Do not round up bandwidth on BWMON4 devices PM / devfreq: bw_hwmon: Fix a race condition in hwmon stop devfreq: suppress platform driver bind / unbind feature devfreq: suppress platform driver bind / unbind feature devfreq: update freq variable in compute_freq function devfreq: memlat: Add suspend/resume for mem_latency PM / devfreq: icc: Switch to OPP APIs PM / devfreq: bw_hwmon: Reset clear bits for some hardware versions PM / devfreq: memlat: Add support for compute-bound logic msm: kgsl: Set up the adreno device at runtime msm: kgsl: Add dedicated boolean functions for adreno sysfs msm: kgsl: Make a child device just for the bwmon governor msm: kgsl: Remove nonsense around the a5xx and a6xx SMMU table update msm: kgsl: Move memory pool initialization to the KGSL core msm: kgsl: Cleanup the device tree probing for memory pools msm: kgsl: Use DMA APIs for memory pool cache maintenance msm: kgsl: Move kgsl_pool_allocate_pages() msm: kgsl: Legacy efuse doesn't need adreno_device msm: kgsl: Make the a6xx mbox client static msm: kgsl: Make switch out of secure more target specific msm: kgsl: Clean up preemption msm: kgsl: Make RGMU use the regular GPU powerlevels msm: kgsl: Cleanup iommu device tree probe msm: kgsl: Consolidate zap shader loading dmaengine: gpi: Add support to make GPI driver GKI compliant PM / devfreq: memlat: Look for min stall% in addition to ratio criteria devfreq: simple-dev: Make the freq-table property optional PM / devfreq: bw_hwmon: Add support for specifying count factor PM / devfreq: bw_hwmon: Add support for configuring byte MID match PM / devfreq: bw_hwmon: Add support for BWMON5 monitors PM / devfreq: bw_hwmon: Split out sw and hw paths PM / devfreq: bw_hwmon: Reflow some code PM / devfreq: bw_hwmon: irq can be negative PM / devfreq: bimc-bwmon: Add support for version 4 PM / devfreq: bw_hwmon: Add HW offload support to governor PM / devfreq: Introduce a memory-latency governor PM / devfreq: bw_hwmon: Expose a throttle adjust tunable devfreq: devfreq_simple_dev: Add support for preparing device clock PM / devfreq: bw_hwmon: Update to low latency, high sampling rate algorithm PM / devfreq: governor_cache_hwmon: Fix race in monitor start/stop PM / devfreq: bimc-bwmon: set a floor_mbps for irq threshold PM / devfreq: cache_hwmon: Use array for reporting monitor stats PM / devfreq: cache_hwmon: Move IRQ handling to device drivers PM / devfreq: Refactor Cache HWmon governor to be more generic PM / devfreq: bimc-bwmon: Add support for version 2 usb: gadget: ffs: Use local copy of descriptors for userspace copy soc: qcom: ssr: Export find_subsys_device function ALSA: compress: Add support to send codec specific data arm64: defconfig: Enable Lazy DMA Mapping on Lahaina GKI msm:ipa: changing err prints to dbg prints drivers: thermal: Add a snapshot of thermal framework usb: dwc3-msm: Add soft dependency on phy drivers msm: ipa3: SRAM NAT, DDR NAT, back-and-forth NAT iommu/arm-smmu: Reduce log spam from ECATS translation timeouts ANDROID: Update ABI representation ANDROID: Don't base allmodconfig on gki_defconfig ANDROID: Disable UNWINDER_ORC for allmodconfig ANDROID: ASoC: Fix 'allmodconfig' build break dmaengine: gpi: Add support for 32-bit kernel dmaengine: gpi: Capture GPI hardware status during GSI General interrupt uio: msm_sharedmem: Fix format specifier to print resource_size_t uio: msm_sharedmem: Use proper format to print phys_addr_t uio: msm_sharedmem: Add support for HYP call uio: Add snapshot of MSM sharedmem driver iommu/arm-smmu: Express fastmap domain geometries correctly ANDROID: sched, cpuidle: Track cpuidle state index in the scheduler topology: Add snapshot of possible sibling cpu mask changes sched: Add snapshot of affinity changes sched: reduce sleep duration in wait_task_inactive() power: em: correct increasing freq/power ratio sched/topology: Enable EAS on SMP systems also ANDROID: sched/fair: Avoid unnecessary balancing of asymmetric capacity groups Revert "sched/deadline: Remove cpu_active_mask from cpudl_find()" trace/sched: set priority to 150 for deadline tasks sched: turn off the TTWU_QUEUE feature cpu/hotplug: Ensure that sched domains are rebuilt before hotplug sched: Introduce PANIC_ON_SCHED_BUG timer: Add function to migrate timers hrtimer: make sure PINNED flag is cleared after removing hrtimer hrtimer.h: prevent pinned timer state from breaking inactive test hrtimer: create hrtimer_quiesce_cpu() to isolate CPU from hrtimers timer: create timer_quiesce_cpu() to isolate CPU from timers hrtimer: update timer->state with 'pinned' information serial: Add UART port for EUD Linux 5.4.2 platform/x86: hp-wmi: Fix ACPI errors caused by passing 0 as input size platform/x86: hp-wmi: Fix ACPI errors caused by too small buffer HID: core: check whether Usage Page item is after Usage ID items crypto: talitos - Fix build error by selecting LIB_DES Revert "jffs2: Fix possible null-pointer dereferences in jffs2_add_frag_to_fragtree()" ext4: add more paranoia checking in ext4_expand_extra_isize handling r8169: fix resume on cable plug-in r8169: fix jumbo configuration for RTL8168evl selftests: pmtu: use -oneline for ip route list cache tipc: fix link name length check selftests: bpf: correct perror strings selftests: bpf: test_sockmap: handle file creation failures gracefully net/tls: use sg_next() to walk sg entries net/tls: remove the dead inplace_crypto code selftests/tls: add a test for fragmented messages net: skmsg: fix TLS 1.3 crash with full sk_msg net/tls: free the record on encryption error net/tls: take into account that bpf_exec_tx_verdict() may free the record openvswitch: remove another BUG_ON() openvswitch: drop unneeded BUG_ON() in ovs_flow_cmd_build_info() sctp: cache netns in sctp_ep_common slip: Fix use-after-free Read in slip_open sctp: Fix memory leak in sctp_sf_do_5_2_4_dupcook openvswitch: fix flow command message size net: sched: fix `tc -s class show` no bstats on class with nolock subqueues net: psample: fix skb_over_panic net: macb: add missed tasklet_kill net: dsa: sja1105: fix sja1105_parse_rgmii_delays() mdio_bus: don't use managed reset-controller macvlan: schedule bc_work even if error gve: Fix the queue page list allocated pages count x86/fpu: Don't cache access to fpu_fpregs_owner_ctx thunderbolt: Power cycle the router if NVM authentication fails mei: me: add comet point V device id mei: bus: prefix device names on bus with the bus name USB: serial: ftdi_sio: add device IDs for U-Blox C099-F9P staging: rtl8723bs: Add 024c:0525 to the list of SDIO device-ids staging: rtl8723bs: Drop ACPI device ids staging: rtl8192e: fix potential use after free staging: wilc1000: fix illegal memory access in wilc_parse_join_bss_param() usb: dwc2: use a longer core rest timeout in dwc2_core_reset() driver core: platform: use the correct callback type for bus_find_device crypto: inside-secure - Fix stability issue with Macchiatobin net: disallow ancillary data for __sys_{send,recv}msg_file() net: separate out the msghdr copy from ___sys_{send,recv}msg() io_uring: async workers should inherit the user creds PM / devfreq: icc: Add suspend/resume APIs PM / devfreq: governor_bw_hwmon: Add suspend/resume support PM / devfreq: Add MSM BIMC bwmon support for bw_hwmon governor msm: devfreq_icc: Add devfreq driver for device bandwidth voting devfreq: Add CPUBW HW monitor governor arm64: defconfig: Enable RPMh clock driver for Lahaina wil6210: add module parameter for alternate interface name ANDROID: Update ABI representation arm64: defconfig: Enable CONFIG_I2C_RTC6226_QCA on Lahaina defconfig: enable fastrpc driver on Lahaina media: v4l2-core: guard code against ABI breakage msm: cvp: Disabe sys cache and dsp initialization checkpatch: check symlinks while searching compatible strings UPSTREAM: of: property: Add device link support for interrupt-parent, dmas and -gpio(s) UPSTREAM: of: property: Fix the semantics of of_is_ancestor_of() UPSTREAM: i2c: of: Populate fwnode in of_i2c_get_board_info() UPSTREAM: regulator: core: Don't try to remove device links if add failed UPSTREAM: driver core: Clarify documentation for fwnode_operations.add_links() mm: cma: Reduce dmesg spam mm: cma: make writeable CMA debugfs optional mm: cma: restrict base_pfn exposure clk: qcom: add clk rpmh support for Lahaina dt-bindings: clock: Add rpmh header for Lahaina mm: cma: Print region name on failure dt-bindings: sound: Add GPR device tree bindings lib/vsprintf: Less restrictive hashed pointer printing firmware: qcom_scm: Add MODULE_LICENSE firmware: qcom-scm: Fix formatting errors in the trace string msm: kgsl: Make secure memory depend on QCOM_SECURE_BUFFER msm: kgsl: Fix context refcounting for adreno debugfs msm: kgsl: Fix linked sysfs files msm: kgsl: Replace the sorted dispatcher pending list msm: kgsl: Use a simpler algorithm to find SVM addresses msm: kgsl: Move globals to the KGSL device handle msm: kgsl: Reorganize the shared memory APIs msm: kgsl: Stop using KGSL_MEMDESC_CONTIG msm: kgsl: Remove unneeded static inline functions msm: kgsl: Make 'globals' a device level debugfs file msm: kgsl: Remove a few unused device tree properties msm: kgsl: Move always on timer reads to target specific code msm: kgsl: Cleanup GPU regulators msm: kgsl: Make coresight optional msm: kgsl: Add support for the Adreno GPU ANDROID: Update ABI representation ANDROID: gki_defconfig: IIO=y msm: ipa: Add PIL driver as soft dependency for IPA msm: ipa3: Fix to hold the clock until replenish the descriptors msm: ipa3: Fix to increase timeout value for send command ANDROID: Update ABI representation coresight: funnel: add support for duplicating funnel devices msm: adsprpc: Fix adsprpc info leak mm, page_owner: record time and pid iommu: arm-smmu: clear TBU halt request when halt times out iommu/arm-smmu: fix stale fault reporting in ecats operation clk: qcom: dispcc: Fix stuck on warning for disp_cc_mdss_mdp_lut_clk clk: qcom: gpucc: Voltage voting support for Lahaina clk: qcom: camcc: Voltage voting support for Lahaina clk: qcom: gcc: Voltage voting support for Lahaina ANDROID: ASoC: core - add hostless DAI support mm: usercopy: skip stack page span check ANDROID: gki_defconfig: =m's applied for virtio configs in arm64 arm64: defconfig: Enable the MSM ION heaps on Lahaina GKI arm64: defconfig: Enable secure buffer driver on Lahaina GKI msm: ipa3: Fix to avoid buffer overread serial: msm_geni_serial: Ensure to set clock freq correctly soc: qcom: Add spss transport for Glink Probe driver ANDROID: Update ABI representation after 5.4.1 merge Linux 5.4.1 KVM: PPC: Book3S HV: Flush link stack on guest exit to host kernel powerpc/book3s64: Fix link stack flush on context switch staging: comedi: usbduxfast: usbduxfast_ai_cmdtest rounding error USB: serial: option: add support for Foxconn T77W968 LTE modules USB: serial: option: add support for DW5821e with eSIM support USB: serial: mos7840: fix remote wakeup USB: serial: mos7720: fix remote wakeup USB: serial: mos7840: add USB ID to support Moxa UPort 2210 appledisplay: fix error handling in the scheduled work USB: chaoskey: fix error case of a timeout usb-serial: cp201x: support Mark-10 digital force gauge usbip: Fix uninitialized symbol 'nents' in stub_recv_cmd_submit() usbip: tools: fix fd leakage in the function of read_attr_usbip_status USBIP: add config dependency for SGL_ALLOC ALSA: hda - Disable audio component for legacy Nvidia HDMI codecs media: mceusb: fix out of bounds read in MCE receiver buffer media: imon: invalid dereference in imon_touch_event media: cxusb: detect cxusb_ctrl_msg error in query media: b2c2-flexcop-usb: add sanity checking media: uvcvideo: Fix error path in control parsing failure futex: Prevent exit livelock futex: Provide distinct return value when owner is exiting futex: Add mutex around futex exit futex: Provide state handling for exec() as well futex: Sanitize exit state handling futex: Mark the begin of futex exit explicitly futex: Set task::futex_state to DEAD right after handling futex exit futex: Split futex_mm_release() for exit/exec exit/exec: Seperate mm_release() futex: Replace PF_EXITPIDONE with a state futex: Move futex exit handling into futex code cpufreq: Add NULL checks to show() and store() methods of cpufreq media: usbvision: Fix races among open, close, and disconnect media: usbvision: Fix invalid accesses after device disconnect media: vivid: Fix wrong locking that causes race conditions on streaming stop media: vivid: Set vid_cap_streaming and vid_out_streaming to true ALSA: usb-audio: Fix Scarlett 6i6 Gen 2 port data ALSA: usb-audio: Fix NULL dereference at parsing BADD futex: Prevent robust futex exit race x86/entry/32: Fix FIXUP_ESPFIX_STACK with user CR3 x86/pti/32: Calculate the various PTI cpu_entry_area sizes correctly, make the CPU_ENTRY_AREA_PAGES assert precise selftests/x86/sigreturn/32: Invalidate DS and ES when abusing the kernel selftests/x86/mov_ss_trap: Fix the SYSENTER test x86/entry/32: Fix NMI vs ESPFIX x86/entry/32: Unwind the ESPFIX stack earlier on exception entry x86/entry/32: Move FIXUP_FRAME after pushing %fs in SAVE_ALL x86/entry/32: Use %ss segment where required x86/entry/32: Fix IRET exception x86/cpu_entry_area: Add guard page for entry stack on 32bit x86/pti/32: Size initial_page_table correctly x86/doublefault/32: Fix stack canaries in the double fault handler x86/xen/32: Simplify ring check in xen_iret_crit_fixup() x86/xen/32: Make xen_iret_crit_fixup() independent of frame layout x86/stackframe/32: Repair 32-bit Xen PV nbd: prevent memory leak x86/speculation: Fix redundant MDS mitigation message x86/speculation: Fix incorrect MDS/TAA mitigation status x86/insn: Fix awk regexp warnings md/raid10: prevent access of uninitialized resync_pages offset Revert "dm crypt: use WQ_HIGHPRI for the IO and crypt workqueues" Revert "Bluetooth: hci_ll: set operational frequency earlier" ath10k: restore QCA9880-AR1A (v1) detection ath10k: Fix HOST capability QMI incompatibility ath10k: Fix a NULL-ptr-deref bug in ath10k_usb_alloc_urb_from_pipe ath9k_hw: fix uninitialized variable data Bluetooth: Fix invalid-free in bcsp_close() serial: msm_geni_serial: Add missing changes from 4.19 kernel msm: ipa: Enable IPA compilation for Lahaina drivers: soc: qcom: Add snapshot of driver for FSA4480 I2C device i3c: i3c-master-qcom-geni: Add I3C GENI driver snapshot firmware: qcom_scm: Add trace points to scm driver ANDROID: gki_defconfig: enable CONFIG_REGULATOR_FIXED_VOLTAGE soc: qcom: Remove downstream scm driver FROMLIST: crypto: arm64/sha: fix function types ANDROID: arm64: kvm: disable CFI ANDROID: arm64: add __nocfi to __apply_alternatives ANDROID: arm64: add __pa_function ANDROID: arm64: add __nocfi to functions that jump to a physical address ANDROID: arm64: bpf: implement arch_bpf_jit_check_func ANDROID: bpf: validate bpf_func when BPF_JIT is enabled with CFI ANDROID: add support for Clang's Control Flow Integrity (CFI) ANDROID: arm64: allow LTO_CLANG and THINLTO to be selected FROMLIST: arm64: fix alternatives with LLVM's integrated assembler FROMLIST: arm64: lse: fix LSE atomics with LLVM's integrated assembler ANDROID: arm64: disable HAVE_ARCH_PREL32_RELOCATIONS with LTO_CLANG ANDROID: arm64: vdso: disable LTO ANDROID: irqchip/gic-v3: rename gic_of_init to work around a ThinLTO+CFI bug ANDROID: soc/tegra: disable ARCH_TEGRA_210_SOC with LTO ANDROID: init: ensure initcall ordering with LTO ANDROID: drivers/misc/lkdtm: disable LTO for rodata.o ANDROID: efi/libstub: disable LTO ANDROID: scripts/mod: disable LTO for empty.c ANDROID: kbuild: fix dynamic ftrace with clang LTO ANDROID: kbuild: add support for Clang LTO ANDROID: kbuild: add CONFIG_LD_IS_LLD FROMGIT: driver core: platform: use the correct callback type for bus_find_device FROMLIST: arm64: implement Shadow Call Stack FROMLIST: arm64: disable SCS for hypervisor code FROMLIST: arm64: vdso: disable Shadow Call Stack FROMLIST: arm64: efi: restore x18 if it was corrupted FROMLIST: arm64: preserve x18 when CPU is suspended FROMLIST: arm64: reserve x18 from general allocation with SCS FROMLIST: arm64: disable function graph tracing with SCS FROMLIST: scs: add support for stack usage debugging FROMLIST: scs: add accounting FROMLIST: add support for Clang's Shadow Call Stack (SCS) FROMLIST: arm64: kernel: avoid x18 in __cpu_soft_restart FROMLIST: arm64: kvm: stop treating register x18 as caller save FROMLIST: arm64/lib: copy_page: avoid x18 register in assembler code FROMLIST: arm64: mm: avoid x18 in idmap_kpti_install_ng_mappings ANDROID: clang: update to 10.0.1 clk: qcom: dispcc: Voltage voting support for Lahaina clk: qcom: videocc: Voltage voting support for Lahaina msm: cvp: Avoid CVP loading at boot ANDROID: update ABI representation ABI: aarch64: Update ABI snapshot based on v5.4 msm: ipa: fix ipa driver compilation issue iommu: dma-mapping-fast: fix iova alloc wrap ALSA: pcm: use lock to protect substream runtime resource ALSA: pcm: add locks for accessing runtime resource ALSA: compress: Memset timestamp structure to zero kconfig: add new config AUDIO_QGKI for audio Asoc: Add audio backend to hwdep interface kernel: Create and export kernel headers usb: dwc3-msm: Delete sysfs files on driver remove FROMLIST: pwm: Convert period and duty cycle to u64 drivers: pinctrl: msm: remove redundant call to set handler ANDROID: gki_defconfig: FW_CACHE to no FROMGIT: firmware_class: make firmware caching configurable msm: adsprpc: Making adsprpc gki compliant ANDROID: gki_defconfig: removed CONFIG_PM_WAKELOCKS ANDROID: gki_defconfig: enable CONFIG_IKHEADERS as m ANDROID: update ABI representation FROMLIST: reboot: Export reboot_mode FROMLIST: iommu/arm-smmu: Update my email address in MODULE_AUTHOR() FROMLIST: iommu/arm-smmu: Allow building as a module FROMLIST: iommu/arm-smmu: Unregister IOMMU and bus ops on device removal FROMLIST: iommu/arm-smmu-v3: Allow building as a module FROMLIST: iommu/arm-smmu-v3: Unregister IOMMU and bus ops on device removal FROMLIST: iommu/arm-smmu: Prevent forced unbinding of Arm SMMU drivers FROMLIST: Revert "iommu/arm-smmu: Make arm-smmu explicitly non-modular" FROMLIST: Revert "iommu/arm-smmu: Make arm-smmu-v3 explicitly non-modular" FROMLIST: drivers/iommu: Allow IOMMU bus ops to be unregistered FROMLIST: iommu/of: Take a ref to the IOMMU driver during ->of_xlate() FROMLIST: drivers/iommu: Take a ref to the IOMMU driver prior to ->add_device() FROMLIST: PCI: Export pci_ats_disabled() as a GPL symbol to modules FROMLIST: iommu/of: Request ACS from the PCI core when configuring IOMMU linkage FROMLIST: drivers/iommu: Export core IOMMU API symbols to permit modular drivers FROMGIT: of: property: Add device link support for "iommu-map" Revert "FROMLIST: iommu: Export core IOMMU functions to kernel modules" Revert "FROMLIST: PCI: Export PCI ACS and DMA searching functions to modules" Revert "FROMLIST: of: Export of_phandle_iterator_args() to modules" usb: typec: ucsi: Optimise ucsi_unregister() usb: typec: ucsi: New error codes usb: typec: ucsi: Remove all bit-fields usb: typec: ucsi: Remove struct ucsi_control usb: typec: ucsi: Remove the old API usb: typec: ucsi: ccg: Move to the new API usb: typec: ucsi: acpi: Move to the new API usb: typec: ucsi: Simplified registration and I/O API usb: typec: Remove the callback members from struct typec_capability usb: typec: ucsi: Start using struct typec_operations usb: typec: tps6598x: Start using struct typec_operations usb: typec: tcpm: Start using struct typec_operations usb: typec: Separate the operations vector usb: typec: Introduce typec_get_drvdata() usb: typec: Copy everything from struct typec_capability during registration ANDROID: initial branch preparations for 5.4 soc: qcom: spss_utils: fix emulation logic for lahaina rumi i2c: i2c-msm-geni: Add support to make I2C driver GKI compliant ALSA: uapi: add new macro SNDRV_AUDIO_QGKI ALSA: compress: Add APTX format support in ALSA uapi: sound : update audio decoder format headers SoC: soc-core: export function to find components defconfig: lahaina-gki: enable the fixed regulator driver regulator: fixed: add support for proxy consumers arm64: defconfig: Enable aop-qmp clock driver for Lahaina clk: qcom: clk-aop-qmp: Update CLK_ENABLE_HAND_OFF flag to 0 clk: qcom: clk-aop-qmp: Add module support to this driver arm64: defconfig: Enable IPC IRQ bridge for Lahaina arm64: defconfig: Enable GLINK Packet driver for Lahaina usb: dt-bindings: Add USB QMP PHY registers definition arm64: defconfig: Disable hvc console for lahaina SoC usb: dwc3-msm: Don't use devm_ioremap when ringing GSI DB usb: dwc3-msm: Simplify GSI register macros regulator: rpmh-regulator: add support for proxy consumers defconfig: lahaina-gki: enable the regulator proxy consumer library regulator: add proxy consumer library mm: oom_kill: reap memory of a task that receives SIGKILL ion: msm: Move msm_ion probe to subsys_initcall_sync soc: qcom: secure_buffer: Move to subsys_initcall drivers: irqchip: qcom-pdc: remove SPI config in SCM msm: cvp: Init reserved cdsp_mem defconfig: Enable qcom_scm as a module firmware: qcom_scm: Add calls for watchdog tests firmware: qcom_scm: Add calls for seccam firmware: qcom_scm: Add calls for csptest firmware: qcom_smc: Add compatibility layer for qseecom soc: qcom: Migrate SCM calls in secure_buffer soc: qcom: secure_buffer: Migrate to qcom_scm usage firmware: qcom_scm: Add support to assign multiple memory regions firmware: qcom_scm: Permit early SCM calls before driver probe soc: qcom: Prune unused SCM calls soc: qcom: Migrating to upstream SCM driver in smcinvoke firmware: qcom_scm: Add memory protection API for MDF firmware: qcom_scm: Add a scm calls for displace memory protect thermal: qcom: Migrate SCM calls in msm_lmh_dcvs thermal: qcom: Migrate SCM calls in lmh_dbg msm: cvp: Migrate SCM calls firmware: qcom_scm: Add support for protecting videos input: touchscreen: synaptics_dsx: Migrate SCM calls firmware: qcom_scm: Add calls for camera soc: qcom: Migrate SCM calls in remoteqdss firmware: qcom: Migrate SCM calls in tz_log soc: qcom: Migrate SCM calls in PIL firmware: qcom_scm: Add calls for pfk_ice msm: kgsl: Migrate SCM calls in GPU bus governor coresight: tpdm: Migrate SCM calls soc: qcom: Migrate SCM calls in qtee_shmbridge soc: qcom: Migrate SCM calls in msm_tz_smmu msm: kgsl: Migrate SCM calls in kgsl iommu usb: dwc3: Issue core soft reset upon controller halt failure usb: dwc3: gadget: Clear pending events when stopping controller usb: gadget: Prevent race between composite_setup & USB disconnect msm: ipa4: add MAC filtering for 802_1Q packets platform: msm: Migrate SCM calls in IPAv3 soc: qcom: Migrate SCM calls in jtagv8 crypto: ice: Migrate SCM calls iommu/arm-smmu: Migrate SCM IO calls in arm-smmu soc: qcom: Migrate SCM calls in core hang msm: kgsl: Migrate SCM calls in adreno soc: qcom: Migrate SCM call to disable watchdog firmware: qcom_scm: Use qtee_shmbridge if available firmware: qcom_scm: Merge qtee_shmbridge and qcom_scm firmware: qcom_scm: Rename -64 -> -smc, remove -32 msm: ipa: Update WDI3.0 specific GSI interface for Lahaina arm64: defconfig: Enable the ARM SMMU module on Lahaina iommu/arm-smmu: Allow the ARM-SMMU driver to be a module Revert "iommu/arm-smmu: Make arm-smmu explicitly non-modular" iommu/arm-smmu: Fix atomic domain handling iommu/arm-smmu: Use a bitmap for the SMMU domain attributes clk: qcom: gpucc: Fix gpll0 parent names usb: phy: Remove unused register offsets techpack: Replace xtype with type while searching for sub-dirs iommu/arm-smmu: Remove legacy bindings bus initialization initcall msm: ipa: replace dma_zalloc_coherent() soc: qcom: Add Kconfig dependency for SENSORS_SSC msm: ipa: Adapt IPA driver to several DLKMs msm: ipa: Update IPA driver Kconfig iommu/arm-smmu: Remove DOMAIN_ATTR_BITMAP_IOVA_ALLOCATOR usb: dwc3-msm: Fix usage of find_matching_dbm_ep() usb: dwc3-msm: Fix invalid usb_psy access during remove msm: adsprpc: fix compilation errors in fastrpc driver on lahaina iommu/arm-smmu: Fix atomic domain attribute check ANDROID: usb: gadget: configfs: Support multiple android instances clk: qcom: clk-dummy: convert into a platform driver usb: dwc3: Suppress error message about optional clks msm: ipa: add a thin parsing option for status packets msm: ipa: Added an option to enable NAPI in 11ad ASoC: core: add debug log for cpu dais msm: ipa4: Update mask and shift values for aggr force close register clk: qcom: gcc: Fix num_parent count for gcc_usb3 clk init data msm: ipa3: Fix to memory allocation failure arm64: defconfig: Enable CVP driver PM / devfreq: Add cache HW monitor governor soc: qcom: secure_buffer: Add missing dma_unmap_single firmware: qcom_scm: Support SCM calls before qcom_scm probe firmware: qcom_scm: Enable legacy convention in qcom_scm-64.c firmware: qcom_scm: Merge legacy and SMCCC conventions firmware: qcom_scm-32: Add device argument to atomic calls firmware: qcom_scm-32: Create common legacy atomic call firmware: qcom_scm-32: Fill SMCCC register in qcom_scm_call firmware: qcom_scm-32: Use qcom_scm_desc in non-atomic calls firmware: qcom_scm-32: Use SMC arch wrappers firmware: qcom_scm-64: Improve SMC convention detection firmware: qcom_scm-64: Fill SMC registers in qcom_scm_call_smccc firmware: qcom_scm-64: Remove qcom_scm_call_do_smccc firmware: qcom_scm-64: Add SCM results to descriptor firmware: qcom_scm-64: Move svc/cmd/owner into qcom_scm_desc firmware: qcom_scm: Remove unused qcom_scm_get_version firmware: qcom_scm: Order functions, definitions by svc/cmd firmware: qcom_scm: Apply consistent naming scheme to command IDs firmware: qcom_scm-64: Make SMCCC macros less magical firmware: qcom_scm: Add funcnum IDs firmware: qcom_scm: Rename macros and structures firmware/qcom_scm: Add scm call to handle smmu errata firmware: qcom_scm-64: Add atomic version of qcom_scm_call defconfig: Enable QCOM_SCM on Lahaina QGKI defconfig: lahaina: Add QTI_PMIC_GLINK driver soc: qcom: Add PMIC Glink driver PM / devfreq: Add devfreq driver for simple device soc: qcom: qsee_ipc_irq_bridge: Use __poll_t for qiib_poll msm: ipa: Bus Scaling/Interconnect Migration arm64: defconfig: Enable CONFIG_MSM_BT_POWER on Lahaina msm: ipa4: Fix to overcome KW issues msm: ipa: IMD command bugfixes msm: ipa: update ipa driver APIs for recent wakeup_source and dma ASoC: core: Fix possible NULL pointer dereference soc: qcom: Add snapshot of watchdog driver interconnect: qcom: add virt_clk provider and QUP nodes platform: msm-geni-se: Add missing fixes from msm-4.19 ASoC: msm: Add compressed TX and passthrough support Subject: [PATCH 2/3] ABI: aarch64: Update ABI snapshot based on v5.4-rc6 msm: adsprpc: update driver to latest version from msm-4.19 msm: gsi: close coal frame before HPS CLEAR msm: cvp: Port CVP driver to 5.x kernel msm: ipa3: Fix to race condition in updating current polling state msm: ipa4: Fix to use common PM handle for coalescing and default pipe ASoC: core: update NAME_SIZE to 64 arm64: defconfig: Enable cam cc clock driver for Lahaina msm:ipa: stop the UL MHIP channels after probe msm: ipa: typo in ioctl ipa3_ioctl_mdfy_flt_rule_v2 function usb: dwc3-msm: Set vbus_active in peripheral only mode ALSA: core: Expose sound card online/offline state msm: ipa4: add generic header processing context defconfig: lahaina-gki: enable USB PHY drivers ASoC: msm: fix integer overflow for long duration offload playback ALSA: jack: update jack types spi: spi-msm-geni: Add SPI GENI driver snapshot clk: qcom: clk-rcg2: add callbacks to deal with voltage voting clk: qcom: clk-alpha-pll: add callbacks to deal with voltage voting clk: qcom: regmap: Add regmap support for voltage voting arm64: defconfig: Enable USB DIAG driver on Lahaina usb: phy: Make phy drivers GKI compatible arm64: defconfig: Enable CONFIG_ION_POOL_AUTO_REFILL on Lahaina arm64: defconfig: Enable QRTR on Lahaina soc: qcom: qpnp-pbs: replace #ifdef with #if IS_ENABLED() platform: msm: qpnp-revid: replace #ifdef with #if IS_ENABLED() soc: qcom: secure_buffer: change the way of divide clk: qcom: add vdd-class voltage regulator voting support defconfig: Lahaina: Enable support for console UART usb: phy: Remove reset link training related workaround usb: gadget: Add snapshot of USB GSI function driver regmap: Make regmap debugfs write optional regmap: improve debugfs interface to dump specific addresses usb: gadget: f_qdss: Fix compilation errors msm: ipa: Enable NAPI on IPA LAN CONS pipe msm: ipa3: add VLAN ID filtering arm64: defconfig: Enable global synx driver arm64: defconfig: Enable global synx driver usb: dwc3: Set vbus_active in peripheral-only mode spmi: regmap: enable userspace writes nvmem: Add snapshot of QTI SDAM driver soc: qcom: Add snapshot of QTI PBS driver soc: qcom: Add snapshot of GLINK_PKT Driver arm64: defconfig: Enable SPSS GLINK driver on Lahaina pinctrl: qcom: Expose ufs_reset as gpio on Lahaina soc: qcom: SSR: Fix registration order for wakeup source clk: qcom: Add cam cc clock driver for Lahaina platform: qpnp-revid: Add REVID support for PM8008, SMB1355 and SMB1390 platform: qpnp-revid: Add REVID support for PM6125 platform: qpnp-revid: Add REVID support for PM7250B platform: msm: Add snapshot of QPNP_REVID driver spmi: spmi-pmic-arb-debug: Change the probe init order spmi: spmi-pmic-arb-debug: add clock management support spmi: add SPMI PMIC arbiter debug bus driver mfd: introduce I2C PMIC controller msm: ipa : Fix update of buffer recycle stats thermal: qcom-spmi-temp-alarm: add support for GEN2 rev 1 PMIC peripherals pinctrl: qcom: spmi-gpio: add support for PM*8350* PMIC variants pinctrl: qcom: spmi-gpio: correct parent irqspec translation pinctrl: qcom: spmi-gpio: Fix the GPIO strength mapping pinctrl: qcom: spmi-gpio: add support to enable/disable output mfd: qcom-spmi-pmic: instantiate pmic peripherals at arch_initcall mfd: qcom-spmi-pmic: add support for slow SPMI busses spmi: spmi-pmic-arb: Fix hw_irq overflow spmi: pmic-arb: support updating interrupt type flags spmi: spmi-pmic-arb: increase SPMI transaction timeout delay spmi: spmi-pmic-arb: block access for invalid PMIC arbiter v5 SPMI writes spmi: spmi-pmic-arb: correct duplicate APID to PPID mapping logic spmi-pmic-arb: add support to dispatch interrupt based on IRQ status spmi: spmi-pmic-arb: check apid against limits before calling irq handler spmi: pmic-arb: do not ack and clear peripheral interrupts in cleanup_irq spmi: pmic_arb: add a print in cleanup_irq spmi: pmic-arb: instantiate spmi_devices at arch_initcall iommu/arm-smmu: Move the SMMU driver to subsys_initcall defconfig: lahaina-gki: enable USB_DWC3_MSM spmi: pmic-arb: Use asynchronous probe bluetooth: Add bluetooth slimbus slave drivers clk: qcom: Set BRANCH_HALT_SKIP for clocks controlled by PMU clk: dt-bindings: gcc: Add PCIE AXI clocks clk: qcom: Update gcc clk parent mappings and hw ctrl flag interconnect: Move Lahaina interconnect driver to core_initcall msm: ipa: Add stats for page recycling coresight: byte-cntr: Add support for streaming interface for ETR Coresight: byte-cntr: Don't read byte-cntr when etr is diasbled msm:ipa: unvote PCIe clock only if it was voted before msm: ipa: fix race condition between USB connect and modem SSR msm: gsi: Set cookie correctly for GCI channel TREs msm: ipa3: Change smmu mapping logs to low priority coresight: Add snapshot of Coresight byte counter driver msm: ipa: Disable csum offload and status for ODL pipe msm: ipa: Retry gsi channel stop for producer channels clk: dt-bindings: gcc: Add USB PIPE clocks clk: qcom: clk-alpha-pll: Remove zonda pll set rate delay clk: qcom: clk-alpha-pll: Add support for controlling zonda5lpe PLL arm64: defconfig: Enable gpu cc clock driver for Lahaina clk: qcom: Add gpu cc clock driver for Lahaina arm64: defconfig: Enable global synx driver serial: msm_geni_serial: Double clock-divider for kona based hw serial: msm-geni-serial: Remove usage of wakeup_source_init API drivers: pinctrl: msm: Add fwnode when setting up hireachy ASoC: msm: qdsp6v2: Get path delay support in compress path techpack: Fix uapi headers_install ion: Assume in-kernel clients for prefetch and drain soc: qcom: smp2p: Don't check for NULL before ipc_log_string() rpmsg: Don't check for NULL before ipc_log_string() net: cnss2: Don't check for NULL before ipc_log_string() mailbox: Don't check for NULL before ipc_log_string() msm: adsprpc: Don't check for NULL before ipc_log_string() usb: dwc3: Fix string format warnings iommu/arm-smmu: Fix string format warnings regulator: Fix formatting warnings in rpmh-regulator scsi: ufs: Fix compiler warning arm64: defconfig: Enable shmbridge driver shmbridge: GKI change for shmbridge cnss2: Switch to new genl structure cnss_genl: Use new structure for genl cnss_prealloc: Use new API to print stack trace i2c: i2c-msm-geni: Add I2C GENI driver snapshot media: v4l2-core: Enable VIDIOC_DQBUF ioctl functionality dmaengine: gpi: add GPI dmaengine driver snapshot usb: gadget: Add support for usb runtime pm APIs usb: gadget: rndis: Add packet filter handling for hw accelerated path USB: rndis: Honor dl_max_packet_size value sent by host usb: gadget: rndis: Add new rndis parameters usb: gadget: Add support for rndis flow control callback usb: Add support for rndis uplink aggregation usb: dwc3-msm: Allow xo_clk to be optional usb: dwc3-msm: Get usb power_supply from device tree usb: dwc3-msm: Add usb_ep_autoconfig_by_name usb: dwc3: Enable PHY deep low power mode in L1 suspend msm: ipa3: Ratelimit the error logs for pkts with invalid status usb: dwc3: Add DWC3 MSM driver coresight: tmc: migrate byte counter to new tmc framework coresight: tmc: Read the TMC mode register only if clk is enabled of: reserved-memory: Bypass rmem initialization check for carveouts msm: synx: Porting synx driver to 5.x kernel net: qrtr: Use proper endianness when logging usb: phy: Add snapshot of QTI USB PHY drivers platform: msm: Add snapshot of USB BAM driver usb: gadget: Add snapshot of USB CDEV function driver usb: gadget: Add snapshot of CCID function driver soc: qcom: spss_utils: add spss_utils as DLKM for GKI soc: qcom: add secure processor subsystem (spss) utils driver defconfig: enable power drivers for lahaina cpuidle: lpm-levels: Update functions to static shmbridge: Add shmbridge driver snapshot for lahaina coresight: csr: Add msr support dcc_v2: Remove duplicate function usb: dwc3: Allow dwc_usb31 to operate in dual-role usb: dwc3: Fix use after free crash from dwc3 interrupt handler usb: dwc3: Prevent continuous retries on error event usb: gadget: Add new ipc log buffer to log request and dma usb: dwc3: Check USB LPM status before accessing registers usb: dwc3: Stop active transfer on control endpoints usb: dwc3: Disable the irq before clearing run_stop bit dwc3: gadget: Take copy of dwc->gadget_driver before releasing lock usb: dwc3: gadget: Enable SUSPEND event after CONNECT DONE usb: dwc3: Check return value for debugfs_create_dir() usb: dwc3: gadget: Ensure no control transfers in progress when stopping usb: dwc3: gadget: Fix runtime PM vote from pull_up handler usb: dwc3: Avoid NULL pointer access usb: dwc3: request 2mA VBUS current when suspending usb: dwc3: Add support for PM suspend and hibernation in host mode usb: dwc3: ep0: Fail enqueue() when racing with vbus_sess disconnect dwc3: gadget: Don't queue USB request if pull up is getting disabled usb: dwc3: Fix USB gadget initialization sequence usb: dwc3: Avoid NULL pointer access in dwc3_calc_trbs_left usb: dwc3: Do not traverse list using list_for_each_safe usb: dwc3: gadget: delay clearing run/stop when setup just arrived dwc3: gadget: Stop active transfer pending on ep0 out/in during reset usb: dwc3: Fix incorrect ep0 state on reset usb: dwc3: resize txfifo of IN/INT endpoint before enabling it usb: dwc3: Add QTI MSM platform specific feature and other changes msm-geni-se : Correct the icc src/dst read logic for single path usb: gadget: Add snapshot of USB QDSS function driver arm64: Kconfig: Don't select COMMON_CLK_QCOM in ARCH_LAHAINA defconfig: lahaina-gki: Enable support for QCOM clock drivers soc: qcom: Add snapshot of IPC IRQ bridge driver msm: qdsp6v2: Add timestamp support for compress capture drivers: cpuidle: lpm-levels-of: conform to arm,idle-state definition drivers: soc: qcom: snapshot of sleep drivers for Lahaina ion: msm: Remove dentry_path() usage on heap debugfs file creation errors synx: Add synx cancel signaling status usb: gadget: Add check gadget function bind or not iommu/arm-smmu: bypass hypervisor and read sync/inval status register usb: dwc3: gadget: Keep track of IRQ timing statistics usb: dwc3: Keep track of interrupt statistics usb: dwc3: debug: Add logging APIs using IPC logging framework usb: xhci-plat: Add DT parameter to program xhci imod_interval usb: dwc3: Increase the inter packet gap for USB 2.0 net: qrtr: Fix wakeup_source_register net: qrtr: Add IPC logging for qrtr interconnect: qcom: lahaina: Remove stub functions interconnect: qcom: fix up endianness for rpmh messages icc: qcom: Refactor icc rpmh support iommu/arm-smmu: report BID, PID and MID of client on context fault mm: cma: add trace events for CMA alloc perf testing mm: vmscan: support complete shrinker reclaim mm: vmscan: support equal reclaim for anon and file pages arm64: defconfig: Enable CONFIG_VM_EVENT_COUNTERS on Lahaina mm: run the showmem notifier in alloc failure mm, oom: run the showmem notifier in oom mm: cma: retry only on EBUSY mm: cma: Increase retries if less blocks available mm: cma: Register with show_mem notification framework mm: cma: sleep between retries in cma_alloc mm: swap: free up swap on mm reap iommu/io-pgtable: Deprecate IO_PGTABLE_QUIRK_NO_DMA iommu/arm-smmu: Use existing facilities for I/O Coherent PTWs ion: msm: Add support for ION heaps to implement prefetch and drain dma-mapping: Remove exposure of dma_get_[base/size] ion: Simplify carveout heap base/size retrieval/error handling ion: msm: Remove [cma/dma]_get_[base/size] usage ion: Conditionally compile page pool refill code usb: gadget: f_ncm: allocate/free net device upon driver bind/unbind msm: ADSPRPC: Fix buffer length for capability API msm: ipa3: Query stats from Q6 NLO PROD/CONS msm: ipa3: Fix to check DMA address valid or not before unmap msm: ipa4: Fix to increase coaleascing common event ring size pinctrl: qcom: lahaina: add GPIO wakeup interrupt map pinctrl: qcom: setup GPIO chip in hierarchy drivers: qcom: Add SoC sleep stats driver drivers: soc: qcom: Add ddr stats driver ASoC: Add a debug message to track widget power up/down ASoC: Change info logs to debug ABI: aarch64: Update ABI snapshot based on v5.4-rc3 msm: IPA: mhi_proxy: correct the mhi vote for both bus and device msm: camera: Add camera dt binding definitions msm: ipa: Add IPA producer and consumer clients for AQC scsi: qcom-ufs: Add support for bus voting using ICB framework clk: dt-bindings: gpu-cc: Update gpu clock driver header for Lahaina defconfig: lahaina-gki: Enable DISP_CC clock driver clk: qcom: Add DISP_CC clock driver for Lahaina defconfig: lahaina-gki: Enable VIDEO_CC clock driver clk: qcom: Add VIDEO_CC clock driver for Lahaina usb: gadget: Add snapshot of USB DIAG function driver ABI: aarch64: Update ABI snapshot based on v5.4-rc1 msm: ipa3: get ipa clk for issuing uc cmds soc: qcom: scm: Fix SCM device initialization mm: showmem: make the notifiers atomic mm: Add notifier framework for showing memory mm: allow page poisoning to be enabled by default arm64: defconfig: Enable RPMSG drivers on Lahaina soc: qcom: Add snapshot for Glink Probe driver usb: dwc3: gadget: Update chain bit correctly when using sg list mm: ratelimit swap write errors mm: slub: panic for object and slab errors mm: Kconfig: Add DEBUG_SLUB_PANIC_ON option mm/page_owner: ask users about default setting of PAGE_OWNER defconfig: lahaina-qgki: enable QTI regulator debugfs features regulator: core: add support to log enabled regulators during suspend regulator: core: add debugfs regulator monitoring and control features net: qrtr: Send HELLO message on endpoint register net: qrtr: Add pm_wakeup_event() support net: qrtr: Make qrtr rx threads as RT priorities net: qrtr: Move rx worker to separate worker thread net: qrtr: Add support to read qrtr packet size net: qrtr: Handle IPCR control port format of older targets net: qrtr: Return success if control port is not bound net: qrtr: Add dynamic node id configuration net: qrtr: Add permission rules for QTI targets net: qrtr: Add support for DEL_PROC control message net: qrtr: Add forwarding support based on net id net: qrtr: Add non blocking option for tx_resume net: qrtr: Move tx_resume handling to work context net: qrtr: Send BYE message for all nodes on ept net: qrtr: Add node assignment on new server net: qrtr: Rename qrtr_all_nodes to qrtr_all_epts net: qrtr: Add support for multiple nodes on a single ept net: qrtr: use alloc_skb_with_frags() in rx path net: qrtr: Check function pointer before calling net: qrtr: Prevent stale ports from sending net: qrtr: Detach socket from sock during release msm: ipa3: Fix to not remove endpoint delay if stop channel fails arm64: defconfig: Enable IPC IRQ driver for Lahaina soc: qcom: Add snapshot for QSEE IPC IRQ driver rpmsg: Add snapshot of RPMSG glink driver for spss drivers: pinctrl: Add QUP macros for read/write on Lahaina pinctrl: Add api to enable/disable wakeup capability for a gpio drivers: pinctrl: Add support for read/write of QUP registers msm: ipa3: remove ipa3_ctx access from wan driver and qmi service msm: ipa: mark the IPA clock on in virtual/emulation mode msm: gsi: gsi channel QoS register update lib: Ignore kasan errors from find_next_bit and last bit net: qrtr: Change port allocation to use cyclic idr net: qrtr: Change node mutex to a rw_semaphore net: qrtr: Add socket mode optimization net: qrtr: Do not send packets before hello negotiation ion: msm: Correct OF node refcount handling in error paths msm: ipa: Allocate pages in a wq context pinctrl: qcom: Add EGPIO feature support to pinctrl driver clk: qcom: Export clk_lucid_5lpe_pll_configure() msm: ipa: update mem_part table for IPA SRAM msm: gsi: gsi 2.9 upgrade msm: ipa: Configure IPA pipes and group resources for Lahaina IPA 4.9 net: qrtr: Align header and payload net: qrtr: Remove receive worker soc: qcom: qmi_interface: Protect sk_user_data with RCU arm64: defconfig: Enable CONFIG_QGKI for Non GKI build soc: qcom: Add a config flag to know the build variant ion: msm: enable debugfs for ion heaps ion: Allow the system heap to expose debug information ion: msm: Expose ION API to query buffer VM information ion: msm: Assume devicetree support ion: msm: Correct msm_ion_parse_dt() error propagation ion: msm: Upgrade the ION ABI version ion: msm: Rename msm_ion_of.[c/h] to msm_ion.[c/h] ion: msm: Fix several errors in the MSM ION kernel header of: Make of_get_ddrtype module friendly soc: qcom: secure_buffer: Fix secure buffer device initialization iommu/arm-smmu: Fix context fault interrupt test iommu/arm-smmu: Use bitfields for the TBU debug registers serial: msm_geni_serial:Add snapshot of serial UART driver platform: msm: Add snapshot of GENI serial engine driver regulator: add verbose error messages for invalid voltage requests usb: dwc3: qcom: Use GDSC regulator if available defconfig: lahaina-gki: enable refgen regulator driver regulator: add refgen regulator driver arm64: defconfig: Enable gcc clock driver for Lahaina clk: qcom: Override clks halt check with BRANCH_HALT_VOTED clk: qcom: Add gcc clock driver for Lahaina clk: dt-bindings: gcc: Update gcc clock driver header for Lahaina defconfig: lahaina-gki: enable rpmh-regulator driver net: qrtr: Make qrtr_port_lookup() use RCU net: qrtr: Implement outgoing flow control net: qrtr: Migrate node lookup tree to spinlock net: qrtr: Move resume-tx transmission to recvmsg net: qrtr: Stop rx_worker before freeing node rpmsg: Add snapshot of RPMSG drivers for lahaina iommu: iommu-debug: check valid pfn before performing ATOS ops msm: ipa3: SRAM NAT, DDR NAT, back-and-forth NAT irqchip: qcom-pdc: Add IPC logging support irqchip: qcom-pdc: Additionally set type in SPI config registers irqchip: qcom-pdc: add irqchip set/get state calls drivers: qcom: rpmh-rsc: add IPC logging support for RSC driver soc: qcom: rpmh-rsc: log interrupt status when TCS is busy soc: qcom: rpmh: Fix sending incorrect data during rpmh flush ARM: smp: export pending IPI state drivers: clksource: add API to return cval msm: ipa4: Fix to add wake up handle for coalescing pipe iommu: iommu-debug: Add support for page table dump dma-mapping-fast: add support for atomic fastmap allocations defconfig: enable reserved memory check on Lahaina of: reserved_mem: Check that memory reserved in device tree is in use msm: ipa: add the version check for FnR stats ioctl msm: kgsl: Add the kgsl uapi header file ipa3: add hasting AP+STA quota/stats support iommu/arm-smmu: Adopt bitfield model for remaining SMMU registers iommu/arm-smmu: Add reset implementation hook iommu/arm-smmu: Add context init implementation hook iommu/arm-smmu: Move Secure access quirk to implementation iommu/arm-smmu: Add configuration implementation hook iommu/arm-smmu: Add implementation infrastructure iommu/arm-smmu: Rename arm-smmu-regs.h iommu/arm-smmu: Abstract GR0 accesses iommu/arm-smmu: Abstract context bank accesses iommu/arm-smmu: Abstract GR1 accesses iommu/arm-smmu: Get rid of weird "atomic" write iommu/arm-smmu: Split arm_smmu_tlb_inv_range_nosync() iommu/arm-smmu: Rework cb_base handling iommu/arm-smmu: Convert context bank registers to bitfields iommu/arm-smmu: Convert GR1 registers to bitfields iommu/arm-smmu: Convert GR0 registers to bitfields iommu/arm-smmu: Fix SMMU derivation in arm_smmu_power_off_atomic of: reserved_mem: add missing of_node_put() for proper ref-counting msm: ipa3: remove ipa3_ctx access from wan driver and qmi service msm: ipa: add additional checks to prevent use-after free errors soc: qcom: qmi_interface: Remove ineffective mutex lock from txn struct soc: qcom: qmi_interface: Release mutex lock before return soc: qcom: qmi_interface: Add send timeout helper soc: qcom: qmi_interface: Fix race between net_reset and release soc: qcom: qmi: Remove txn idr entry in qmi handle release soc: qcom: qmi_interface: sync release and data_ready callback ion: msm: Correct memory-region of_node reference counting ion: msm: Prevent log-spam from ION dmabuf mmap failures Revert "staging: android: ion: Use the MSM dmabuf ops when possible" ion: Update the heaps to use the MSM ION dmabuf ops for CMO ion: msm: Update the heap IDs as per the ION core standards include: dt-bindings: ion: Add header for the MSM ION heap IDs ion: msm: Define heap IDs as constants in their own file clk: qcom: clk-alpha-pll: Add support for controlling Lucid5lpe PLLs arm64: defconfig: Enable SSR, PIL, Sysmon, and PDR drivers soc: qcom: Fix printk format warnings from subsystem restart soc: qcom: Select MSM_PIL for SUBSYSTEM_RESTART drivers: irqchip: add PDC irqdomain for wakeup capable GPIOs msm: ipa: Enable qmi send request to remove last connection msm: ipa: remove unneeded files ion: remove cpu binding of pool refill kthreads staging: android: ion: Ratelimit warning message iommu/arm-smmu: Mask TLBI address correctly ion: msm: Relocate MSM ION header directly to include/uapi/linux ion: Fail system secure heap creation if system heap is unavailable msm: ipa: Fix KW P1 issue msm:ipa : enable HOLB drop timeout on MHIP producer channels msm: ipa: Fix accessing coal registers when clock is off msm: ipa3: Fix to memory allocation failure msm: ipa: Decrease refcount of the pages held in cache before freeing msm: ipa: Fix race condition between timer expiry for wq and pipe teardown iommu: iommu-debug: select IOMMU_DEBUGFS for iommu tests msm: ipa: Enable USB DPL end point regulator: add rpmh-regulator driver dt-bindings: regulator: rpmh-regulator: add new intermediate voltage levels dt-bindings: regulator: rpmh-regulator: add SVS_L2 voltage level dt-binding: regulator: rpmh-regulator: define RPMh sets and regulator modes drivers: llcc-lahaina: Update the SCT table for MMUHWT soc: qcom: qmi_interface: Add new error enum msm: ipa4: Fix to update the polling mode for coalescing channel driver: pinctrl: Add reserved GPIOs for Lahaina soc: qcom: pil: Correct memory-region of_node reference counting msm: ipa: Fix the double unmap page recycling cleanup on ssr drivers: irqchip: pdc: Do not toggle IRQ_ENABLE during mask/unmask genirq: Introduce irq_chip_get/set_parent_state calls msm: IPA: mhi_proxy: correct the return for mhi unvote on ssr msm: ipa: Fix the missing page recycling cleanup on ssr coresight: Add snapshot of Coresight hwevent driver coresight: csr: Add multiple CSR devices support coresight: Add snapshot of Coresight dummy driver ABI: aarch64: Update ABI snapshot based on v5.3 msm: ipa: Ignore empty ipa config file msm: ipa4: Set return value if coalescing frame open msm: ipa4: Don't decrease the client count if suspend fail msm: ipa4: support coalescing pipe suspend msm: ipa: allow abort for disable_clks msm: ipa4: add masked ipa_wigig debug registers values msm: ipa: Use Qtimer for DPL IPA timer techpack: Kbuild: Fix to compile the techpack completely arm64: defconfig: Clean the lines for unset CONFIGs msm: ipa4: Update endpoint prefetch config for lito msm: ipa4: Don't query wigig client tethering stats for all targets ABI: aarch64: Update ABI snapshot based on v5.3-rc6 coresight: Add snapshot of Coresight tgu driver coresight-etm4x: Merge ETM changes radio: RTC6226: Make the rtc6226 driver compatible with QTI platform driver: pinctrl: Update pinctrl mappings for Lahiana soc: qcom: secure_buffer: Trace hyp_assign calls trace: secure_buffer: Introduce trace events for secure buffer coresight: Add snapshot of Coresight csr driver dcc_v2: Don't set the default value to sram when dcc is enabled msm: CDSP: add CDSP loader driver irqdomain: add bus token DOMAIN_BUS_WAKEUP ion: Use correct heap when freeing secure system heap buffers ion: msm: Remove unnecessary free when destroying an ION buffer ion: msm: Only check heap IDs if the heap has been initialized Bluetooth: btpower: Add snapshot of BT power driver defconfig: Add MSM Core Hang Detection as module drivers: soc: Add snapshot of MSM Core Hang Detection msm: ipa: Add snapshot of IPA driver msm: adsprpc: add fastrpc driver files ABI: Update ABI snapshot with latest kernel build tools scripts: Consider env vaiables while running 'make' techpack: replace type with xtype while searching for sub-dirs synx : Add snapshot for global synx driver support soc: qcom: configure ipcc interrupt as wakeup capable coresight: Add snapshot of Coresight TPDM and TPDA driver coresight: Add common header file coresight: etm: Add check of trace unit power property drivers: qcom: rpmh: Add standalone mode support for RPMH drivers: qcom: rpmh-rsc: write PDC data drivers: qcom: rpmh-rsc: return if the controller is idle drivers: qcom: rpmh-rsc: optimize redundant read to determine TCS idle drivers: qcom: rpmh-rsc: clear active mode configuration for waketcs drivers: qcom: rpmh-rsc: output debug information from RSC drivers: qcom: rpmh: add 'solver' state support for RSC controllers drivers: qcom: rpmh-rsc: do not read back the register write on trigger soc: qcom: dcc: Support new DCC HW feature soc: qcom: Add snapshot of the dcc v2 driver dt-bindings: Add dt bindings head file for dcc soc: qcom: Add snapshot of the memory dump v2 driver qseecom: add uapi headfile for Lahaina bring up clk: qcom: clk-debug: Unflatten mux tree clk: qcom: clk-debug: Add custom measure operators for mccc_clk clk: qcom: clk-debug: Add support for enable mask for debug clk clk: qcom: clk-debug: Disable the DEBUG clocks when not being used clk: clk-debug: Update file permission for clk_measure debugfs clk: qcom: Add support for debugfs measure clock clk: avoid returning local variable pointers during clock registration dt-bindings: clock: Add rpmh clock binding IDs for Kona clk: qcom: define vdd_levels enum and vdd_corner[] map clk: qcom: Add support for divider flags and table clk: qcom: common: only register reset controllers which define resets clk: qcom: common: add device tree consumer support for clk_hws clk: qcom: add clk rpmh support for Kona clk: qcom: clk-spmi-pmic-div: avoid potential divide-by-0 clk: qcom: clk-spmi-pmic-div: add support for clock-output-names clk: qcom: clk-aop-qmp: use correct name pointer before clock registration clk: qcom: clk-aop-qmp: pass mbox pointer by reference in qmp_update_client clk: qcom: clk-aop-qmp: Fix issue with registering the clock provider clk: qcom: clk-aop-qmp: correct mailbox channel request logic clk: qcom: clk-aop-qmp: Do not send duplicate requests to AOP clk: qcom: Add support for AOP clock controller clk: qcom: gdsc: Remove global mutex lock in enable/disable callbacks clk: qcom: gdsc-regulator: Remove polling logic when disabling GDSC HW CTL clk: qcom: gdsc-regulator: refactor gdsc_probe() to reduce complexity clk: qcom: gdsc-regulator: add support for enabling retention registers clk: qcom: gdsc-regulator: Add MMCX specific logic clk: qcom: gdsc-regulator: Place a min operational vote on GDSC parent clk: qcom: Add support for regulator based GDSC control clk: qcom: Add support for hardware control branch clocks clk: qcom: clk-rcg2: correct set rate handling for FORCE_ENABLE_RCG clk: qcom: rcg2: Add support for hardware control mode clk: qcom: rcg2: Remove support for update_src_map clk: qcom: clk-rcg2: Read RCG source before calculating clk rate clk: qcom: Retrieve pre_div from freq_tbl for shared RCG clk: qcom: rcg2: Add DIV_ROUND_CLOSEST_ULL to roundoff RCG frequency clk: qcom: add null pointer checks for parent clocks clk: qcom: clk-rcg2: Fix QUPV3 DFSR M and N register mode overwrite clk: qcom: clk-rcg: update DEFINE_RCG_DFS() macro clk: qcom: Add support for clock dependency clk: Add additional checking to some clock driver functions clk: qcom: Add RCG support for DP source clk: qcom: Add support for RCGs with dynamic and fixed sources clk: qcom: clk-rcg2: Add support to force enable an RCG clk: qcom: clk-rcg2: Configure the RCGs to a safe frequency as needed clk: qcom: clk-alpha-pll: check pcal_done from mode register clk: qcom: clk-alpha-pll: add FREQ_DET support to Zonda PLL lock detection clk: qcom: alpha: do not configure PLL during probe if already enabled clk: qcom: clk-alpha-pll: add support to reconfigure PLLs during prepare clk: qcom: clk-alpha-pll: add support for custom register initialization clk: qcom: clk-alpha-pll: Remove reconfiguration of PLLs clk: qcom: clk-alpha-pll: Add support for controlling zonda pll clk: qcom: clk-alpha-pll: add additional configuration support for PLLs clk: qcom: clk-alpha-pll: Add support for controlling Lucid PLLs arm64: defconfig: Enable sensors_ssc on Lahaina drivers: of: Add API to find ddr device type radio: Add snapshot for FM radio support radio: RTC6226: Add support for RTC6226 FM chip include: rmnet_data: Add snapshot of headers drivers: sensors: add sensors ssc driver drivers: qcom: rpmh-rsc: modularize RSC controller driver drivers: qcom: cmd-db: Dump resource data via debugfs pinctrl-lahaina: Correct the pinconfig base address arm64: defconfig: Enable llcc perfmon drivers drivers: llcc_perfmon: support for dual memory controller added drivers: llcc_perfmon: Add llcc_perfmon support net: cnss_prealloc: Add snapshot of cnss_prealloc driver defconfig: Update test configs for debug defconfig drivers: GICv3: Enable logging of interrupts that triggered wakeup defconfig: Enable fastmap on Lahaina net: cnss_genl: Add snapshot of cnss_genl driver soc: qcom: qmi_interface: Abort pending transaction soc: qcom: qmi_interface: Add default send timeout soc: qcom: qmi_interface: Do not print error for 0 pkt arm64: defconfig: Enable SMP2P Sleepstate on Lahaina arm64: defconfig: Enable MSM QMP driver for Lahaina arm64: defconfig: Enable QMP DEBUGFS driver on Lahaina arm64: defconfig: Enable SMP2P and dependencies on Lahaina arm64: defconfig: Enable IPC logging driver on Lahaina soc: qcom: Add snapshot of smp2p sleepstate driver soc: qcom: smp2p: Fix two warnings soc: qcom: smp2p: Prevent suspend for threaded irq soc: qcom: smp2p: Add enable_irq_wake to SMP2P IRQ soc: qcom: smp2p: Add logs in smp2p_update_bits soc: qcom: smp2p: Add IPC logging support defconfig: Enable the MSM ION heaps on Lahaina staging: android: ion: Use the MSM dmabuf ops when possible staging: android: ion: Do not assign heap IDs as heaps register Revert "staging: android: ion: Remove file ion_carveout_heap.c" ion: Merge all ION related changes from msm-4.19 to msm-lahaina net: cnss_utils: Add snapshot of cnss_utils driver ABI: aarch64: Update ABI snapshot based on v5.3-rc4 coresight: add node to reset all coresight devices trace: rtb: add msm_rtb tracing perf: Set the DSU PMU to be readable from any CPU qcom: soc: minidump: Add snapshot of minidump.h soc: qcom: Add snapshot of SSR, PIL, Sysmon, and PDR drivers coresight: add support to enable multiple coresight paths arm64: defconfig: Enable CONFIG_SPARSEMEM_VMEMMAP on Lahaina iommu: io-pgtable-fast: Use the DMA APIs for cache cleaning defconfig: arm64: Enable uncompressed kernel for Lahaina epoll: drop struct epoll_event definition drivers: qcom: cmd-db: Report if command DB is initialized as standalone drivers: qcom: cmd-db: modularize commandDB driver drivers: irqchip: enable PDC irqchip for QCOM Lahaina SoC spdx: Modify spdx tag from GPL-2.0 to GPL-2.0-only coresight: Set clk rate for all coresight devices soc: qcom: smp2p: Add restart ack feature soc: qcom: smp2p: Introduce pending state for virtual irq drivers: mailbox: fix race resulting in multiple message submission soc: qcom: smem: Update max processors in soc Revert "checkpatch: forbid filesystem accesses from within the kernel." Revert "checkpatch: close filp_open loophole." Revert "checkpatch: deprecate unbounded string functions." Revert "checkpatch: Add warnings for use of mdelay()" iommu: Update the offset of the extended domain attributes iommu/arm-smmu: Fix a few compiler warnings Revert "checkpatch: complain about the use of dsb()." Revert "checkpatch: Add exceptions for "dsb" keyword usage" iommu/dma-iommu: Allow dma_info_to_prot to be used globally mailbox: Add snapshot of MSM QMP driver soc: qcom: Add snapshot of MSM QMP debugfs client trace: Add snapshot of ipc logging driver ufs: ufshcd: Prevent sleeping in IRQ context coresight: add support for device names ABI: aarch64: Update ABI snapshot based on v5.3-rc1 ARM64: smp: Fix function prototypes net: cnss2: Add snapshot of CNSS2 driver arm64: defconfig: Enable EDAC drivers drivers: edac: Add Cache Error Reporting driver edac: Allow panic on correctable errors (CE) sched: Add a check for cpu unbound deferrable timers timer: Initialize global deferrable timer ARM64: Flush the caches for non panicking CPUs in case of a kernel panic ARM64: smp: Save CPU registers before IPI_CPU_STOP processing arm64: msm: Add support for uncompressed kernel image ARM: arch_timer: force re-selection of the best clocksource clocksource: add API to force re-selection of the best clocksource defconfig: Disable ZONE_DMA32 on Lahaina iommu: Align QCOM_IOMMU_IO_PGTABLE_QUIRKS with other configs defconfig: Enable panics on TLB_SYNC timeouts on Lahaina defconfig: Enable all IOMMU related configs on Lahaina arm64: defconfig: Enable IPCC driver as a module kernel: rcu: Panic on RCU stall soc: qcom: ipcc: Add snapshot of IPCC controller irqdomain: Implement and expose API to clear IRQ mapping for radix tree drivers: irq: Add debug information for irq type warnings timer: Add a global deferrable timer dtc: add integer overflow checks in fdt header arm64: mm: Log the process id in the rtb ARM: gic-v3: Log the IRQs in RTB before handling an IRQ PM / wakeup: Add msm_show_resume_irq_mask to print off wakeup irq iommu/arm-smmu: Merge all IOMMU changes from msm-4.19 to msm-lahaina printk: Make the console flush configurable in hotplug path arm64: defconfig: Enable LLCC driver drivers: llcc: Add LLCC driver for Lahaina Revert "arm64: kill flush_cache_all()" Revert "arm64: Remove unused macros from assembler.h" Revert "arm64: Remove unused daif related functions/macros" cpu-hotplug: Always use real time scheduling when hotplugging a CPU smp: Allow booting a specific subset of CPUs cpu/hotplug: Add cpuhp_latency trace event workqueue: fix possible livelock with concurrent mod_delayed_work() usb : dwc3: Initialize kernel stack variables properly arm64: Dump stack for all CPUs on SMP CPU stop drivers: llcc: Add new usecase IDs drivers: llcc: Create child platform device for llcc_perfmon drivers: llcc: Support targets that can write to llcc registers drivers: llcc: Write to sub-cache register based on version drivers: llcc: Configure cache override registers ABI: aarch64: Update the ABI snapshot for v5.2 irq-chip: gic-v3: remove print message in irq driver defconfig: lahaina-gki: enable qualcomm ufs driver ufs: ufs-qcom: Add support for presilicon configuration ufs: ufshcd: Add check for broken auto-h8 support defconfig: lahaina-gki: enable presilicon ufs phy driver ABI: aarch64: Update ABI snapshot based for v5.2 arm64: Apply erratum 1024718 to Cortex A55 r2p0 phy: qcom-ufs-qrbtc: Add ufs phy driver for presilicon defonfig: Enable QCOM UFS Phy driver defconfig: lahaina-gki: enable lahaina icc driver arm64: defconfig: Enable USB drivers on Lahaina usb: host: xhci-plat: Avoid unneeded internal declaration warning usb: phy-qcom-emu: Fix typo for memory resource name usb: phy: Add driver for USB PHY on QTI emulation platform phy: phy-qcom-ufs: Modify phy voltage limits rpmsg : glink: validate head and tail index before fifo read write soc: qcom: qmi_encdec: Restrict string length in decode soc: qcom: smem: validate fields of shared structures arm64: Add 32-bit sigcontext definition to uapi signcontext.h net: core: neighbour: Change the print format for addresses scripts: gki: Clean the generted files by hand instead of mrproper elf: Add elf headers helpers support interconnect: qcom: Add Lahaina interconnect provider driver icc: dt-bindings: add endpoint IDs for Lahaina interconnects ABI: Update ABI snapshot due to rolling kernel upgrade Merge remote-tracking branch 'remotes/origin/tmp-f686d9f' into msm-lahaina arm64: defconfig: Enable the QCOM SCM driver soc: qcom: scm: Add snapshot of QCOM SCM driver arm64: defconfig: Enable the pinctrl-lahaina driver pinctrl: qcom: Add lahaina pinctrl driver pinctrl-msm: Allow the driver to be compiled as a module checkpatch: Fix commit log check for a filename clk: qcom: clk-dummy: Add a dummy clock provider msm_rtb: Add _no_log variants msm_rtb: Add snapshot of msm_rtb.h defconfig: lahaina-gki: enable stub-regulator driver regulator: dt-bindings: rpmh-regulator: add header for voltage levels regulator: add stub-regulator driver .gitignore: Add device tree vendor directories to gitignore techpack: add tech package support scripts: gki: Fix setting of a CONFIG if it's unset in base defconfig ABI: Update ABI snapshot due to libabigail tool changes clk: dt-bindings: add clock IDs for Lahaina clock controllers .gitignore: Add techpack directory to gitignore .gitignore: Exclude the GKI generated defconfigs ABI: Update ABI snapshot based on new code baseline checkpatch: Handle continuation headers ABI: Update to the ABI definition file hvc_dcc: Disable preemption when cheking for smp_processor_id arm64: defconfig: Enable ARM DCC driver hvc_dcc: Make dcc driver read/write from CPU0 ABI: Add initial ABI definition based on gki_defconfig checkpatch: Treat duplicate signatures as a different error class checkpatch: allow copyright statements > 80 columns checkpatch: Use upstream commit text length checks checkpatch: Excuse reverts from "summary line over 75 characters" check checkpatch: require commit text checkpatch: Don't complain about MIME headers. checkpatch: Fix the commit log false positive warnings checkpatch: warn on long summary, commit text lines checkpatch: complain about the use of dsb(). checkpatch: warn on subject line not followed by blank line checkpatch: Add exceptions for "dsb" keyword usage checkpatch: close filp_open loophole. checkpatch: Handle long multi-line macros better. checkpatch: deprecate unbounded string functions. checkpatch: forbid implied-barrier I/O functions. checkpatch: forbid filesystem accesses from within the kernel. checkpatch: Check for illegal return codes checkpatch: Add warnings for use of mdelay() checkpatch: Exceptions for CLK_* macros and some spaces in macros arm64: defconfig: Enable Lahaina platform arm64: Kconfig: Add config option for Lahaina ARM: dts: qcom: Add vendor directory to the Makefile docs: Makefile: Don't look for Makefiles in bindings Documentation: devicetree: Remove devicetree bindings from kernel defconfig: Add initial defconfig fragments for Lahaina scripts: gki: Add GKI support scripts: snapshot of kernel build utility scripts Makefile: Disable undefined-optimized and add -fno-builtin ANDROID: HACK: arm64, LLVMLinux: use -mno-implicit-float kbuild: Check for 'clang' string in the entire --version output Change-Id: Ie31e65a8b2960eca7d7e52e7a2201a656ac4825d Signed-off-by: Venkata Narendra Kumar Gutta <vnkgutta@codeaurora.org> Signed-off-by: Elliot Berman <eberman@codeaurora.org>
This commit is contained in:
commit
792b143158
8
.gitignore
vendored
8
.gitignore
vendored
@ -146,3 +146,11 @@ x509.genkey
|
||||
|
||||
# Clang's compilation database file
|
||||
/compile_commands.json
|
||||
|
||||
# GKI generated defconfigs
|
||||
arch/*/configs/vendor/*-gki_defconfig
|
||||
arch/*/configs/vendor/*-qgki_defconfig
|
||||
arch/*/configs/vendor/*-qgki-debug_defconfig
|
||||
|
||||
# vendor device tree directories
|
||||
arch/arm64/boot/dts/vendor/
|
||||
|
45
Android.bp
Normal file
45
Android.bp
Normal file
@ -0,0 +1,45 @@
|
||||
cc_binary_host {
|
||||
name: "unifdef",
|
||||
srcs: ["scripts/unifdef.c"],
|
||||
sanitize: {
|
||||
never: true,
|
||||
},
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "gen-headers_install.sh",
|
||||
srcs: ["scripts/headers_install.sh"],
|
||||
tools: ["unifdef"],
|
||||
out: ["headers_install.sh"],
|
||||
cmd: "sed 's+scripts/unifdef+$(location unifdef)+g' $(in) > $(out)",
|
||||
}
|
||||
|
||||
cc_prebuilt_binary {
|
||||
name: "headers_install.sh",
|
||||
device_supported: false,
|
||||
host_supported: true,
|
||||
srcs: [":gen-headers_install.sh"],
|
||||
}
|
||||
|
||||
// Use the following for verbose output from kernel_headers.py.
|
||||
// kernel_headers_verbose = "--verbose "
|
||||
// Use the following for minimal output from kernel_headers.py.
|
||||
kernel_headers_verbose = ""
|
||||
|
||||
build = ["gen_headers_arm.bp", "gen_headers_arm64.bp"]
|
||||
|
||||
cc_library_headers {
|
||||
name: "qti_kernel_headers",
|
||||
arch: {
|
||||
arm: {
|
||||
generated_headers: ["qti_generate_kernel_headers_arm"],
|
||||
export_generated_headers: ["qti_generate_kernel_headers_arm"],
|
||||
},
|
||||
arm64: {
|
||||
generated_headers: ["qti_generate_kernel_headers_arm64"],
|
||||
export_generated_headers: ["qti_generate_kernel_headers_arm64"],
|
||||
},
|
||||
},
|
||||
vendor: true,
|
||||
recovery_available: true,
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
subdir-y := devicetree/bindings/
|
||||
subdir-y :=
|
||||
|
||||
# Check for broken documentation file references
|
||||
ifeq ($(CONFIG_WARN_MISSING_DOCUMENTS),y)
|
||||
|
@ -432,6 +432,10 @@
|
||||
embedded devices based on command line input.
|
||||
See Documentation/block/cmdline-partition.rst
|
||||
|
||||
boot_cpus= [SMP]
|
||||
Rather than attempting to online all possible CPUs at
|
||||
boot time, only online the specified set of CPUs.
|
||||
|
||||
boot_delay= Milliseconds to delay each printk during boot.
|
||||
Values larger than 10 seconds (10000) are changed to
|
||||
no delay (0).
|
||||
|
361
Documentation/arm/msm/msm_ipc_logging.txt
Normal file
361
Documentation/arm/msm/msm_ipc_logging.txt
Normal file
@ -0,0 +1,361 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
This module will be used to log the events by any module/driver which
|
||||
enables Inter Processor Communication (IPC). Some of the IPC drivers such
|
||||
as Message Routers, Multiplexers etc. which act as a passive pipe need
|
||||
some mechanism to log their events. Since all such IPC drivers handle a
|
||||
large amount of traffic/events, using kernel logs renders kernel logs
|
||||
unusable by other drivers and also degrades the performance of IPC
|
||||
drivers. This new module will help in logging such high frequency IPC
|
||||
driver events while keeping the standard kernel logging mechanism
|
||||
intact.
|
||||
|
||||
Hardware description
|
||||
====================
|
||||
|
||||
This module does not drive any hardware resource and will only use the
|
||||
kernel memory-space to log the events.
|
||||
|
||||
Software description
|
||||
====================
|
||||
|
||||
Design Goals
|
||||
------------
|
||||
This module is designed to
|
||||
* support logging for drivers handling large amount of
|
||||
traffic/events
|
||||
* define & differentiate events/logs from different drivers
|
||||
* support both id-based and stream-based logging
|
||||
* support extracting the logs from both live target & memory dump
|
||||
|
||||
IPC Log Context
|
||||
----------------
|
||||
|
||||
This module will support logging by multiple drivers. To differentiate
|
||||
between the multiple drivers that are using this logging mechanism, each
|
||||
driver will be assigned a unique context by this module. Associated with
|
||||
each context is the logging space, dynamically allocated from the kernel
|
||||
memory-space, specific to that context so that the events logged using that
|
||||
context will not interfere with other contexts.
|
||||
|
||||
Event Logging
|
||||
--------------
|
||||
|
||||
Every event will be logged as a <Type: Size: Value> combination. Type
|
||||
field identifies the type of the event that is logged. Size field represents
|
||||
the size of the log information. Value field represents the actual
|
||||
information being logged. This approach will support both id-based logging
|
||||
and stream-based logging. This approach will also support logging sub-events
|
||||
of an event. This module will provide helper routines to encode/decode the
|
||||
logs to/from this format.
|
||||
|
||||
Encode Context
|
||||
---------------
|
||||
|
||||
Encode context is a temporary storage space that will be used by the client
|
||||
drivers to log the events in <Type: Size: Value> format. The client drivers
|
||||
will perform an encode start operation to initialize the encode context
|
||||
data structure. Then the client drivers will log their events into the
|
||||
encode context. Upon completion of event logging, the client drivers will
|
||||
perform an encode end operation to finalize the encode context data
|
||||
structure to be logged. Then this updated encode context data structure
|
||||
will be written into the client driver's IPC Log Context. The maximum
|
||||
event log size will be defined as 256 bytes.
|
||||
|
||||
Log Space
|
||||
----------
|
||||
|
||||
Each context (Figure 1) has an associated log space, which is dynamically
|
||||
allocated from the kernel memory-space. The log space is organized as a list of
|
||||
1 or more kernel memory pages. Each page (Figure 2) contains header information
|
||||
which is used to differentiate the log kernel page from the other kernel pages.
|
||||
|
||||
|
||||
0 ---------------------------------
|
||||
| magic_no = 0x25874452 |
|
||||
---------------------------------
|
||||
| nmagic_no = 0x52784425 |
|
||||
---------------------------------
|
||||
| version |
|
||||
---------------------------------
|
||||
| user_version |
|
||||
---------------------------------
|
||||
| log_id |
|
||||
---------------------------------
|
||||
| header_size |
|
||||
---------------------------------
|
||||
| |
|
||||
| |
|
||||
| name [20 chars] |
|
||||
| |
|
||||
| |
|
||||
---------------------------------
|
||||
| run-time data structures |
|
||||
---------------------------------
|
||||
Figure 1 - Log Context Structure
|
||||
|
||||
|
||||
31 0
|
||||
0 ---------------------------------
|
||||
| magic_no = 0x52784425 |
|
||||
---------------------------------
|
||||
| nmagic_no = 0xAD87BBDA |
|
||||
---------------------------------
|
||||
|1| page_num |
|
||||
---------------------------------
|
||||
| read_offset | write_offset |
|
||||
---------------------------------
|
||||
| log_id |
|
||||
---------------------------------
|
||||
| start_time low word |
|
||||
| start_time high word |
|
||||
---------------------------------
|
||||
| end_time low word |
|
||||
| end_time high word |
|
||||
---------------------------------
|
||||
| context offset |
|
||||
---------------------------------
|
||||
| run-time data structures |
|
||||
. . . . .
|
||||
---------------------------------
|
||||
| |
|
||||
| Log Data |
|
||||
. . .
|
||||
. . .
|
||||
| |
|
||||
--------------------------------- PAGE_SIZE - 1
|
||||
Figure 2 - Log Page Structure
|
||||
|
||||
In addition to extracting logs at runtime through DebugFS, IPC Logging has been
|
||||
designed to allow extraction of logs from a memory dump. The magic numbers,
|
||||
timestamps, and context offset are all added to support the memory-dump
|
||||
extraction use case.
|
||||
|
||||
Design
|
||||
======
|
||||
|
||||
Alternate solutions discussed include using kernel & SMEM logs which are
|
||||
limited in size and hence using them render them unusable by other drivers.
|
||||
Also kernel logging into serial console is slowing down the performance of
|
||||
the drivers by multiple times and sometimes lead to APPs watchdog bite.
|
||||
|
||||
Power Management
|
||||
================
|
||||
|
||||
Not-Applicable
|
||||
|
||||
SMP/multi-core
|
||||
==============
|
||||
|
||||
This module uses spinlocks & mutexes to handle multi-core safety.
|
||||
|
||||
Security
|
||||
========
|
||||
|
||||
Not-Applicable
|
||||
|
||||
Performance
|
||||
===========
|
||||
|
||||
This logging mechanism, based on experimental data, is not expected to
|
||||
cause a significant performance degradation. Under worst case, it can
|
||||
cause 1 - 2 percent degradation in the throughput of the IPC Drivers.
|
||||
|
||||
Interface
|
||||
=========
|
||||
|
||||
Exported Data Structures
|
||||
------------------------
|
||||
struct encode_context {
|
||||
struct tsv_header hdr;
|
||||
char buff[MAX_MSG_SIZE];
|
||||
int offset;
|
||||
};
|
||||
|
||||
struct decode_context {
|
||||
int output_format;
|
||||
char *buff;
|
||||
int size;
|
||||
};
|
||||
|
||||
Kernel-Space Interface APIs
|
||||
----------------------------
|
||||
/*
|
||||
* ipc_log_context_create: Create a ipc log context
|
||||
*
|
||||
* @max_num_pages: Number of pages of logging space required (max. 10)
|
||||
* @mod_name : Name of the directory entry under DEBUGFS
|
||||
* @user_version : Version number of user-defined message formats
|
||||
*
|
||||
* returns reference to context on success, NULL on failure
|
||||
*/
|
||||
void *ipc_log_context_create(int max_num_pages, const char *mod_name,
|
||||
uint16_t user_version);
|
||||
|
||||
/*
|
||||
* msg_encode_start: Start encoding a log message
|
||||
*
|
||||
* @ectxt: Temporary storage to hold the encoded message
|
||||
* @type: Root event type defined by the module which is logging
|
||||
*/
|
||||
void msg_encode_start(struct encode_context *ectxt, uint32_t type);
|
||||
|
||||
/*
|
||||
* msg_encode_end: Complete the message encode process
|
||||
*
|
||||
* @ectxt: Temporary storage which holds the encoded message
|
||||
*/
|
||||
void msg_encode_end(struct encode_context *ectxt);
|
||||
|
||||
/*
|
||||
* tsv_timestamp_write: Writes the current timestamp count
|
||||
*
|
||||
* @ectxt: Context initialized by calling msg_encode_start()
|
||||
*
|
||||
* Returns 0 on success, -ve error code on failure
|
||||
*/
|
||||
int tsv_timestamp_write(struct encode_context *ectxt);
|
||||
|
||||
/*
|
||||
* tsv_pointer_write: Writes a data pointer
|
||||
*
|
||||
* @ectxt: Context initialized by calling msg_encode_start()
|
||||
* @pointer: Pointer value to write
|
||||
*
|
||||
* Returns 0 on success, -ve error code on failure
|
||||
*/
|
||||
int tsv_pointer_write(struct encode_context *ectxt, void *pointer);
|
||||
|
||||
/*
|
||||
* tsv_int32_write: Writes a 32-bit integer value
|
||||
*
|
||||
* @ectxt: Context initialized by calling msg_encode_start()
|
||||
* @n: Integer to write
|
||||
*
|
||||
* Returns 0 on success, -ve error code on failure
|
||||
*/
|
||||
int tsv_int32_write(struct encode_context *ectxt, int32_t n);
|
||||
|
||||
/*
|
||||
* tsv_byte_array_write: Writes a byte array
|
||||
*
|
||||
* @ectxt: Context initialized by calling msg_encode_start()
|
||||
* @data: Location of data
|
||||
* @data_size: Size of data to be written
|
||||
*
|
||||
* Returns 0 on success, -ve error code on failure
|
||||
*/
|
||||
int tsv_byte_array_write(struct encode_context *ectxt,
|
||||
void *data, int data_size);
|
||||
|
||||
/*
|
||||
* ipc_log_write: Write the encoded message into the log space
|
||||
*
|
||||
* @ctxt: IPC log context where the message has to be logged into
|
||||
* @ectxt: Temporary storage containing the encoded message
|
||||
*/
|
||||
void ipc_log_write(unsigned long ctxt, struct encode_context *ectxt);
|
||||
|
||||
/*
|
||||
* ipc_log_string: Helper function to log a string
|
||||
*
|
||||
* @dlctxt: IPC Log Context created using ipc_log_context_create()
|
||||
* @fmt: Data specified using format specifiers
|
||||
*/
|
||||
int ipc_log_string(unsigned long dlctxt, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
* tsv_timestamp_read: Reads a timestamp
|
||||
*
|
||||
* @ectxt: Context retrieved by reading from log space
|
||||
* @dctxt: Temporary storage to hold the decoded message
|
||||
* @format: Output format while dumping through DEBUGFS
|
||||
*/
|
||||
void tsv_timestamp_read(struct encode_context *ectxt,
|
||||
struct decode_context *dctxt, const char *format);
|
||||
|
||||
/*
|
||||
* tsv_pointer_read: Reads a data pointer
|
||||
*
|
||||
* @ectxt: Context retrieved by reading from log space
|
||||
* @dctxt: Temporary storage to hold the decoded message
|
||||
* @format: Output format while dumping through DEBUGFS
|
||||
*/
|
||||
void tsv_pointer_read(struct encode_context *ectxt,
|
||||
struct decode_context *dctxt, const char *format);
|
||||
|
||||
/*
|
||||
* tsv_int32_read: Reads a 32-bit integer value
|
||||
*
|
||||
* @ectxt: Context retrieved by reading from log space
|
||||
* @dctxt: Temporary storage to hold the decoded message
|
||||
* @format: Output format while dumping through DEBUGFS
|
||||
*/
|
||||
void tsv_int32_read(struct encode_context *ectxt,
|
||||
struct decode_context *dctxt, const char *format);
|
||||
|
||||
/*
|
||||
* tsv_byte_array_read: Reads a byte array/string
|
||||
*
|
||||
* @ectxt: Context retrieved by reading from log space
|
||||
* @dctxt: Temporary storage to hold the decoded message
|
||||
* @format: Output format while dumping through DEBUGFS
|
||||
*/
|
||||
void tsv_byte_array_read(struct encode_context *ectxt,
|
||||
struct decode_context *dctxt, const char *format);
|
||||
|
||||
/*
|
||||
* add_deserialization_func: Register a deserialization function to
|
||||
* to unpack the subevents of a main event
|
||||
*
|
||||
* @ctxt: IPC log context to which the deserialization function has
|
||||
* to be registered
|
||||
* @type: Main/Root event, defined by the module which is logging, to
|
||||
* which this deserialization function has to be registered.
|
||||
* @dfune: Deserialization function to be registered
|
||||
*
|
||||
* return 0 on success, -ve value on FAILURE
|
||||
*/
|
||||
int add_deserialization_func(unsigned long ctxt, int type,
|
||||
void (*dfunc)(struct encode_context *,
|
||||
struct decode_context *));
|
||||
|
||||
Driver parameters
|
||||
=================
|
||||
|
||||
Not-Applicable
|
||||
|
||||
Config options
|
||||
==============
|
||||
|
||||
Not-Applicable
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
This module will partially depend on CONFIG_DEBUGFS, in order to dump the
|
||||
logs through debugfs. If CONFIG_DEBUGFS is disabled, the above mentioned
|
||||
helper functions will perform no operation and return appropriate error
|
||||
code if the return value is non void. Under such circumstances the logs can
|
||||
only be extracted through the memory dump.
|
||||
|
||||
User space utilities
|
||||
====================
|
||||
|
||||
DEBUGFS
|
||||
|
||||
Other
|
||||
=====
|
||||
|
||||
Not-Applicable
|
||||
|
||||
Known issues
|
||||
============
|
||||
|
||||
None
|
||||
|
||||
To do
|
||||
=====
|
||||
|
||||
None
|
276
Documentation/mhi.txt
Normal file
276
Documentation/mhi.txt
Normal file
@ -0,0 +1,276 @@
|
||||
Overview of Linux kernel MHI support
|
||||
====================================
|
||||
|
||||
Modem-Host Interface (MHI)
|
||||
=========================
|
||||
MHI used by the host to control and communicate with modem over high speed
|
||||
peripheral bus. Even though MHI can be easily adapt to any peripheral buses,
|
||||
primarily used with PCIe based devices. The host has one or more PCIe root
|
||||
ports connected to modem device. The host has limited access to device memory
|
||||
space, including register configuration and control the device operation.
|
||||
Data transfers are invoked from the device.
|
||||
|
||||
All data structures used by MHI are in the host system memory. Using PCIe
|
||||
interface, the device accesses those data structures. MHI data structures and
|
||||
data buffers in the host system memory regions are mapped for device.
|
||||
|
||||
Memory spaces
|
||||
-------------
|
||||
PCIe Configurations : Used for enumeration and resource management, such as
|
||||
interrupt and base addresses. This is done by mhi control driver.
|
||||
|
||||
MMIO
|
||||
----
|
||||
MHI MMIO : Memory mapped IO consists of set of registers in the device hardware,
|
||||
which are mapped to the host memory space through PCIe base address register
|
||||
(BAR)
|
||||
|
||||
MHI control registers : Access to MHI configurations registers
|
||||
(struct mhi_controller.regs).
|
||||
|
||||
MHI BHI register: Boot host interface registers (struct mhi_controller.bhi) used
|
||||
for firmware download before MHI initialization.
|
||||
|
||||
Channel db array : Doorbell registers (struct mhi_chan.tre_ring.db_addr) used by
|
||||
host to notify device there is new work to do.
|
||||
|
||||
Event db array : Associated with event context array
|
||||
(struct mhi_event.ring.db_addr), host uses to notify device free events are
|
||||
available.
|
||||
|
||||
Data structures
|
||||
---------------
|
||||
Host memory : Directly accessed by the host to manage the MHI data structures
|
||||
and buffers. The device accesses the host memory over the PCIe interface.
|
||||
|
||||
Channel context array : All channel configurations are organized in channel
|
||||
context data array.
|
||||
|
||||
struct __packed mhi_chan_ctxt;
|
||||
struct mhi_ctxt.chan_ctxt;
|
||||
|
||||
Transfer rings : Used by host to schedule work items for a channel and organized
|
||||
as a circular queue of transfer descriptors (TD).
|
||||
|
||||
struct __packed mhi_tre;
|
||||
struct mhi_chan.tre_ring;
|
||||
|
||||
Event context array : All event configurations are organized in event context
|
||||
data array.
|
||||
|
||||
struct mhi_ctxt.er_ctxt;
|
||||
struct __packed mhi_event_ctxt;
|
||||
|
||||
Event rings: Used by device to send completion and state transition messages to
|
||||
host
|
||||
|
||||
struct mhi_event.ring;
|
||||
struct __packed mhi_tre;
|
||||
|
||||
Command context array: All command configurations are organized in command
|
||||
context data array.
|
||||
|
||||
struct __packed mhi_cmd_ctxt;
|
||||
struct mhi_ctxt.cmd_ctxt;
|
||||
|
||||
Command rings: Used by host to send MHI commands to device
|
||||
|
||||
struct __packed mhi_tre;
|
||||
struct mhi_cmd.ring;
|
||||
|
||||
Transfer rings
|
||||
--------------
|
||||
MHI channels are logical, unidirectional data pipes between host and device.
|
||||
Each channel associated with a single transfer ring. The data direction can be
|
||||
either inbound (device to host) or outbound (host to device). Transfer
|
||||
descriptors are managed by using transfer rings, which are defined for each
|
||||
channel between device and host and resides in the host memory.
|
||||
|
||||
Transfer ring Pointer: Transfer Ring Array
|
||||
[Read Pointer (RP)] ----------->[Ring Element] } TD
|
||||
[Write Pointer (WP)]- [Ring Element]
|
||||
- [Ring Element]
|
||||
--------->[Ring Element]
|
||||
[Ring Element]
|
||||
|
||||
1. Host allocate memory for transfer ring
|
||||
2. Host sets base, read pointer, write pointer in corresponding channel context
|
||||
3. Ring is considered empty when RP == WP
|
||||
4. Ring is considered full when WP + 1 == RP
|
||||
4. RP indicates the next element to be serviced by device
|
||||
4. When host new buffer to send, host update the Ring element with buffer
|
||||
information
|
||||
5. Host increment the WP to next element
|
||||
6. Ring the associated channel DB.
|
||||
|
||||
Event rings
|
||||
-----------
|
||||
Events from the device to host are organized in event rings and defined in event
|
||||
descriptors. Event rings are array of EDs that resides in the host memory.
|
||||
|
||||
Transfer ring Pointer: Event Ring Array
|
||||
[Read Pointer (RP)] ----------->[Ring Element] } ED
|
||||
[Write Pointer (WP)]- [Ring Element]
|
||||
- [Ring Element]
|
||||
--------->[Ring Element]
|
||||
[Ring Element]
|
||||
|
||||
1. Host allocate memory for event ring
|
||||
2. Host sets base, read pointer, write pointer in corresponding channel context
|
||||
3. Both host and device has local copy of RP, WP
|
||||
3. Ring is considered empty (no events to service) when WP + 1 == RP
|
||||
4. Ring is full of events when RP == WP
|
||||
4. RP - 1 = last event device programmed
|
||||
4. When there is a new event device need to send, device update ED pointed by RP
|
||||
5. Device increment RP to next element
|
||||
6. Device trigger and interrupt
|
||||
|
||||
Example Operation for data transfer:
|
||||
|
||||
1. Host prepare TD with buffer information
|
||||
2. Host increment Chan[id].ctxt.WP
|
||||
3. Host ring channel DB register
|
||||
4. Device wakes up process the TD
|
||||
5. Device generate a completion event for that TD by updating ED
|
||||
6. Device increment Event[id].ctxt.RP
|
||||
7. Device trigger MSI to wake host
|
||||
8. Host wakes up and check event ring for completion event
|
||||
9. Host update the Event[i].ctxt.WP to indicate processed of completion event.
|
||||
|
||||
Time sync
|
||||
---------
|
||||
To synchronize two applications between host and external modem, MHI provide
|
||||
native support to get external modems free running timer value in a fast
|
||||
reliable method. MHI clients do not need to create client specific methods to
|
||||
get modem time.
|
||||
|
||||
When client requests modem time, MHI host will automatically capture host time
|
||||
at that moment so clients are able to do accurate drift adjustment.
|
||||
|
||||
Example:
|
||||
|
||||
Client request time @ time T1
|
||||
|
||||
Host Time: Tx
|
||||
Modem Time: Ty
|
||||
|
||||
Client request time @ time T2
|
||||
Host Time: Txx
|
||||
Modem Time: Tyy
|
||||
|
||||
Then drift is:
|
||||
Tyy - Ty + <drift> == Txx - Tx
|
||||
|
||||
Clients are free to implement their own drift algorithms, what MHI host provide
|
||||
is a way to accurately correlate host time with external modem time.
|
||||
|
||||
To avoid link level latencies, controller must support capabilities to disable
|
||||
any link level latency.
|
||||
|
||||
During Time capture host will:
|
||||
1. Capture host time
|
||||
2. Trigger doorbell to capture modem time
|
||||
|
||||
It's important time between Step 2 to Step 1 is deterministic as possible.
|
||||
Therefore, MHI host will:
|
||||
1. Disable any MHI related to low power modes.
|
||||
2. Disable preemption
|
||||
3. Request bus master to disable any link level latencies. Controller
|
||||
should disable all low power modes such as L0s, L1, L1ss.
|
||||
|
||||
MHI States
|
||||
----------
|
||||
|
||||
enum MHI_STATE {
|
||||
MHI_STATE_RESET : MHI is in reset state, POR state. Host is not allowed to
|
||||
access device MMIO register space.
|
||||
MHI_STATE_READY : Device is ready for initialization. Host can start MHI
|
||||
initialization by programming MMIO
|
||||
MHI_STATE_M0 : MHI is in fully active state, data transfer is active
|
||||
MHI_STATE_M1 : Device in a suspended state
|
||||
MHI_STATE_M2 : MHI in low power mode, device may enter lower power mode.
|
||||
MHI_STATE_M3 : Both host and device in suspended state. PCIe link is not
|
||||
accessible to device.
|
||||
|
||||
MHI Initialization
|
||||
------------------
|
||||
|
||||
1. After system boots, the device is enumerated over PCIe interface
|
||||
2. Host allocate MHI context for event, channel and command arrays
|
||||
3. Initialize context array, and prepare interrupts
|
||||
3. Host waits until device enter READY state
|
||||
4. Program MHI MMIO registers and set device into MHI_M0 state
|
||||
5. Wait for device to enter M0 state
|
||||
|
||||
Linux Software Architecture
|
||||
===========================
|
||||
|
||||
MHI Controller
|
||||
--------------
|
||||
MHI controller is also the MHI bus master. In charge of managing the physical
|
||||
link between host and device. Not involved in actual data transfer. At least
|
||||
for PCIe based buses, for other type of bus, we can expand to add support.
|
||||
|
||||
Roles:
|
||||
1. Turn on PCIe bus and configure the link
|
||||
2. Configure MSI, SMMU, and IOMEM
|
||||
3. Allocate struct mhi_controller and register with MHI bus framework
|
||||
2. Initiate power on and shutdown sequence
|
||||
3. Initiate suspend and resume
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
1. Allocate control data structure by calling mhi_alloc_controller()
|
||||
2. Initialize mhi_controller with all the known information such as:
|
||||
- Device Topology
|
||||
- IOMMU window
|
||||
- IOMEM mapping
|
||||
- Device to use for memory allocation, and of_node with DT configuration
|
||||
- Configure asynchronous callback functions
|
||||
3. Register MHI controller with MHI bus framework by calling
|
||||
of_register_mhi_controller()
|
||||
|
||||
After successfully registering controller can initiate any of these power modes:
|
||||
|
||||
1. Power up sequence
|
||||
- mhi_prepare_for_power_up()
|
||||
- mhi_async_power_up()
|
||||
- mhi_sync_power_up()
|
||||
2. Power down sequence
|
||||
- mhi_power_down()
|
||||
- mhi_unprepare_after_power_down()
|
||||
3. Initiate suspend
|
||||
- mhi_pm_suspend()
|
||||
4. Initiate resume
|
||||
- mhi_pm_resume()
|
||||
|
||||
MHI Devices
|
||||
-----------
|
||||
Logical device that bind to maximum of two physical MHI channels. Once MHI is in
|
||||
powered on state, each supported channel by controller will be allocated as a
|
||||
mhi_device.
|
||||
|
||||
Each supported device would be enumerated under
|
||||
/sys/bus/mhi/devices/
|
||||
|
||||
struct mhi_device;
|
||||
|
||||
MHI Driver
|
||||
----------
|
||||
Each MHI driver can bind to one or more MHI devices. MHI host driver will bind
|
||||
mhi_device to mhi_driver.
|
||||
|
||||
All registered drivers are visible under
|
||||
/sys/bus/mhi/drivers/
|
||||
|
||||
struct mhi_driver;
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
1. Register driver using mhi_driver_register
|
||||
2. Before sending data, prepare device for transfer by calling
|
||||
mhi_prepare_for_transfer
|
||||
3. Initiate data transfer by calling mhi_queue_transfer
|
||||
4. After finish, call mhi_unprepare_from_transfer to end data transfer
|
@ -200,5 +200,23 @@ Then in some part of your code after your wiphy has been registered:
|
||||
Statically compiled regulatory database
|
||||
---------------------------------------
|
||||
|
||||
When a database should be fixed into the kernel, it can be provided as a
|
||||
firmware file at build time that is then linked into the kernel.
|
||||
In most situations the userland solution using CRDA as described
|
||||
above is the preferred solution. However in some cases a set of
|
||||
rules built into the kernel itself may be desirable. To account
|
||||
for this situation, a configuration option has been provided
|
||||
(i.e. CONFIG_CFG80211_INTERNAL_REGDB). With this option enabled,
|
||||
the wireless database information contained in net/wireless/db.txt is
|
||||
used to generate a data structure encoded in net/wireless/regdb.c.
|
||||
That option also enables code in net/wireless/reg.c which queries
|
||||
the data in regdb.c as an alternative to using CRDA.
|
||||
|
||||
The file net/wireless/db.txt should be kept up-to-date with the db.txt
|
||||
file available in the git repository here:
|
||||
|
||||
git://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git
|
||||
|
||||
Again, most users in most situations should be using the CRDA package
|
||||
provided with their distribution, and in most other situations users
|
||||
should be building and using CRDA on their own rather than using
|
||||
this option. If you are not absolutely sure that you should be using
|
||||
CONFIG_CFG80211_INTERNAL_REGDB then _DO_NOT_USE_IT_.
|
||||
|
@ -183,6 +183,10 @@ partial drain
|
||||
EOF is reached and now DSP can start skipping padding delay. Also next write
|
||||
data would belong to next track
|
||||
|
||||
- set_next_track_param
|
||||
This routine is called to send to DSP codec specific data of subsequent track
|
||||
in gapless before first write.
|
||||
|
||||
Sequence flow for gapless would be:
|
||||
- Open
|
||||
- Get caps / codec caps
|
||||
|
26
Makefile
26
Makefile
@ -406,7 +406,7 @@ KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS) $(HOSTLDLIBS)
|
||||
# Make variables (CC, etc...)
|
||||
AS = $(CROSS_COMPILE)as
|
||||
LD = $(CROSS_COMPILE)ld
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
REAL_CC = $(CROSS_COMPILE)gcc
|
||||
CPP = $(CC) -E
|
||||
AR = $(CROSS_COMPILE)ar
|
||||
NM = $(CROSS_COMPILE)nm
|
||||
@ -427,6 +427,14 @@ PYTHON3 = python3
|
||||
CHECK = sparse
|
||||
BASH = bash
|
||||
|
||||
ifndef DISABLE_WRAPPER
|
||||
# Use the wrapper for the compiler. This wrapper scans for new
|
||||
# warnings and causes the build to stop upon encountering them
|
||||
CC = $(srctree)/scripts/gcc-wrapper.py $(REAL_CC)
|
||||
else
|
||||
CC = $(REAL_CC)
|
||||
endif
|
||||
|
||||
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
|
||||
-Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF)
|
||||
NOSTDINC_FLAGS :=
|
||||
@ -524,7 +532,7 @@ ifdef building_out_of_srctree
|
||||
{ echo "# this is build directory, ignore it"; echo "*"; } > .gitignore
|
||||
endif
|
||||
|
||||
ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
|
||||
ifneq ($(shell $(CC) --version 2>&1 | grep clang),)
|
||||
ifneq ($(CROSS_COMPILE),)
|
||||
CLANG_TRIPLE ?= $(CROSS_COMPILE)
|
||||
CLANG_FLAGS += --target=$(notdir $(CLANG_TRIPLE:%-=%))
|
||||
@ -1252,17 +1260,27 @@ PHONY += archheaders archscripts
|
||||
|
||||
hdr-inst := -f $(srctree)/scripts/Makefile.headersinst obj
|
||||
|
||||
techpack-dirs := $(shell find $(srctree)/techpack -maxdepth 1 -mindepth 1 -type d -not -name ".*")
|
||||
techpack-dirs := $(subst $(srctree)/,,$(techpack-dirs))
|
||||
|
||||
PHONY += headers
|
||||
headers: $(version_h) scripts_unifdef uapi-asm-generic archheaders archscripts
|
||||
$(if $(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/Kbuild),, \
|
||||
$(error Headers not exportable for the $(SRCARCH) architecture))
|
||||
$(Q)$(MAKE) $(hdr-inst)=include/uapi
|
||||
$(Q)$(MAKE) $(hdr-inst)=arch/$(SRCARCH)/include/uapi
|
||||
$(Q)for d in $(techpack-dirs); do \
|
||||
$(MAKE) $(hdr-inst)=$$d/include/uapi; \
|
||||
done
|
||||
|
||||
# Deprecated. It is no-op now.
|
||||
PHONY += headers_check
|
||||
headers_check:
|
||||
@:
|
||||
headers_check: headers
|
||||
$(Q)$(MAKE) $(hdr-inst)=include/uapi HDRCHECK=1
|
||||
$(Q)$(MAKE) $(hdr-inst)=arch/$(SRCARCH)/include/uapi HDRCHECK=1
|
||||
$(Q)for d in $(techpack-dirs); do \
|
||||
$(MAKE) $(hdr-inst)=$$d/include/uapi HDRCHECK=1; \
|
||||
done
|
||||
|
||||
ifdef CONFIG_HEADERS_INSTALL
|
||||
prepare: headers
|
||||
|
250772
abi_gki_aarch64.xml
Normal file
250772
abi_gki_aarch64.xml
Normal file
File diff suppressed because it is too large
Load Diff
859
abi_gki_aarch64_whitelist
Normal file
859
abi_gki_aarch64_whitelist
Normal file
@ -0,0 +1,859 @@
|
||||
[abi_whitelist]
|
||||
add_timer
|
||||
add_uevent_var
|
||||
add_wait_queue
|
||||
alloc_chrdev_region
|
||||
__alloc_disk_node
|
||||
alloc_etherdev_mqs
|
||||
alloc_netdev_mqs
|
||||
alloc_pages_exact
|
||||
__alloc_pages_nodemask
|
||||
__alloc_percpu
|
||||
__alloc_skb
|
||||
alloc_workqueue
|
||||
arch_bpf_jit_check_func
|
||||
__arch_copy_from_user
|
||||
__arch_copy_to_user
|
||||
arm64_const_caps_ready
|
||||
autoremove_wake_function
|
||||
bcmp
|
||||
blk_cleanup_queue
|
||||
blk_execute_rq
|
||||
blk_get_queue
|
||||
blk_get_request
|
||||
blk_mq_alloc_tag_set
|
||||
blk_mq_complete_request
|
||||
__blk_mq_end_request
|
||||
blk_mq_end_request
|
||||
blk_mq_free_tag_set
|
||||
blk_mq_init_queue
|
||||
blk_mq_quiesce_queue
|
||||
blk_mq_requeue_request
|
||||
blk_mq_run_hw_queues
|
||||
blk_mq_start_request
|
||||
blk_mq_start_stopped_hw_queues
|
||||
blk_mq_stop_hw_queue
|
||||
blk_mq_unquiesce_queue
|
||||
blk_mq_virtio_map_queues
|
||||
blk_put_queue
|
||||
blk_put_request
|
||||
blk_queue_alignment_offset
|
||||
blk_queue_bounce_limit
|
||||
blk_queue_can_use_dma_map_merging
|
||||
blk_queue_flag_clear
|
||||
blk_queue_flag_set
|
||||
blk_queue_io_min
|
||||
blk_queue_io_opt
|
||||
blk_queue_logical_block_size
|
||||
blk_queue_max_discard_sectors
|
||||
blk_queue_max_discard_segments
|
||||
blk_queue_max_hw_sectors
|
||||
blk_queue_max_segments
|
||||
blk_queue_max_segment_size
|
||||
blk_queue_max_write_zeroes_sectors
|
||||
blk_queue_physical_block_size
|
||||
blk_queue_rq_timeout
|
||||
blk_queue_write_cache
|
||||
blk_rq_map_kern
|
||||
blk_rq_map_sg
|
||||
blk_status_to_errno
|
||||
blk_update_request
|
||||
bpf_prog_add
|
||||
bpf_prog_put
|
||||
bpf_prog_sub
|
||||
bpf_stats_enabled_key
|
||||
bpf_trace_run10
|
||||
bpf_trace_run2
|
||||
bpf_trace_run8
|
||||
bpf_warn_invalid_xdp_action
|
||||
build_skb
|
||||
bus_register
|
||||
bus_unregister
|
||||
call_netdevice_notifiers
|
||||
call_rcu
|
||||
cancel_delayed_work
|
||||
cancel_delayed_work_sync
|
||||
cancel_work_sync
|
||||
capable
|
||||
cdev_add
|
||||
cdev_alloc
|
||||
cdev_del
|
||||
cdev_device_add
|
||||
cdev_device_del
|
||||
cdev_init
|
||||
cfg80211_connect_done
|
||||
cfg80211_disconnected
|
||||
cfg80211_inform_bss_data
|
||||
cfg80211_put_bss
|
||||
cfg80211_scan_done
|
||||
__cfi_slowpath
|
||||
check_disk_change
|
||||
__check_object_size
|
||||
__class_create
|
||||
class_destroy
|
||||
__class_register
|
||||
class_unregister
|
||||
clear_page
|
||||
clk_disable
|
||||
clk_enable
|
||||
clk_get_rate
|
||||
clk_prepare
|
||||
clk_unprepare
|
||||
complete
|
||||
complete_all
|
||||
completion_done
|
||||
console_suspend_enabled
|
||||
__const_udelay
|
||||
consume_skb
|
||||
_copy_from_iter_full
|
||||
copy_page
|
||||
_copy_to_iter
|
||||
cpu_bit_bitmap
|
||||
cpufreq_generic_attr
|
||||
cpufreq_register_driver
|
||||
cpufreq_unregister_driver
|
||||
__cpuhp_remove_state
|
||||
__cpuhp_setup_state
|
||||
__cpuhp_state_add_instance
|
||||
__cpuhp_state_remove_instance
|
||||
cpu_hwcap_keys
|
||||
cpu_hwcaps
|
||||
cpumask_next
|
||||
cpumask_next_wrap
|
||||
cpu_number
|
||||
__cpu_online_mask
|
||||
cpus_read_lock
|
||||
cpus_read_unlock
|
||||
cpu_topology
|
||||
crypto_ablkcipher_type
|
||||
crypto_dequeue_request
|
||||
crypto_enqueue_request
|
||||
crypto_init_queue
|
||||
crypto_register_alg
|
||||
crypto_unregister_alg
|
||||
datagram_poll
|
||||
debugfs_attr_read
|
||||
debugfs_attr_write
|
||||
debugfs_create_dir
|
||||
debugfs_create_file
|
||||
debugfs_create_file_unsafe
|
||||
debugfs_create_x32
|
||||
debugfs_remove
|
||||
debugfs_remove_recursive
|
||||
debug_smp_processor_id
|
||||
default_llseek
|
||||
default_wake_function
|
||||
delayed_work_timer_fn
|
||||
del_gendisk
|
||||
del_timer
|
||||
del_timer_sync
|
||||
destroy_workqueue
|
||||
dev_add_pack
|
||||
dev_close
|
||||
dev_driver_string
|
||||
_dev_err
|
||||
dev_fwnode
|
||||
__dev_get_by_index
|
||||
dev_get_by_index
|
||||
dev_get_by_index_rcu
|
||||
dev_get_stats
|
||||
device_add
|
||||
device_add_disk
|
||||
device_create
|
||||
device_create_file
|
||||
device_del
|
||||
device_destroy
|
||||
device_for_each_child
|
||||
device_initialize
|
||||
device_init_wakeup
|
||||
device_property_present
|
||||
device_property_read_u32_array
|
||||
device_register
|
||||
device_remove_file
|
||||
device_unregister
|
||||
_dev_info
|
||||
__dev_kfree_skb_any
|
||||
devm_clk_get
|
||||
dev_mc_sync_multiple
|
||||
dev_mc_unsync
|
||||
devm_gpiod_get_index
|
||||
devm_ioremap
|
||||
devm_kasprintf
|
||||
devm_kfree
|
||||
devm_kmalloc
|
||||
devm_platform_ioremap_resource
|
||||
devm_regulator_get_optional
|
||||
__devm_request_region
|
||||
devm_request_threaded_irq
|
||||
__devm_reset_control_get
|
||||
devm_rtc_allocate_device
|
||||
_dev_notice
|
||||
dev_open
|
||||
dev_pm_domain_attach
|
||||
dev_pm_domain_detach
|
||||
dev_printk
|
||||
dev_queue_xmit
|
||||
dev_remove_pack
|
||||
devres_add
|
||||
__devres_alloc_node
|
||||
devres_destroy
|
||||
devres_free
|
||||
dev_set_mtu
|
||||
dev_set_name
|
||||
dev_uc_sync_multiple
|
||||
dev_uc_unsync
|
||||
_dev_warn
|
||||
disable_irq
|
||||
dma_alloc_attrs
|
||||
dma_direct_map_page
|
||||
dma_direct_map_sg
|
||||
dma_direct_sync_sg_for_cpu
|
||||
dma_direct_sync_sg_for_device
|
||||
dma_direct_sync_single_for_cpu
|
||||
dma_direct_sync_single_for_device
|
||||
dma_direct_unmap_page
|
||||
dma_direct_unmap_sg
|
||||
dma_fence_context_alloc
|
||||
dma_fence_enable_sw_signaling
|
||||
dma_fence_init
|
||||
dma_fence_match_context
|
||||
dma_fence_release
|
||||
dma_fence_signal
|
||||
dma_fence_signal_locked
|
||||
dma_fence_wait_timeout
|
||||
dma_free_attrs
|
||||
dma_get_merge_boundary
|
||||
dma_max_mapping_size
|
||||
dma_resv_add_excl_fence
|
||||
dma_resv_add_shared_fence
|
||||
dma_resv_copy_fences
|
||||
dma_resv_fini
|
||||
dma_resv_init
|
||||
dma_resv_reserve_shared
|
||||
dma_resv_test_signaled_rcu
|
||||
dma_resv_wait_timeout_rcu
|
||||
dma_set_coherent_mask
|
||||
dma_set_mask
|
||||
driver_register
|
||||
driver_unregister
|
||||
drm_add_edid_modes
|
||||
drm_add_modes_noedid
|
||||
drm_atomic_helper_check
|
||||
drm_atomic_helper_cleanup_planes
|
||||
drm_atomic_helper_commit
|
||||
drm_atomic_helper_commit_hw_done
|
||||
drm_atomic_helper_commit_modeset_disables
|
||||
drm_atomic_helper_commit_modeset_enables
|
||||
drm_atomic_helper_commit_planes
|
||||
drm_atomic_helper_connector_destroy_state
|
||||
drm_atomic_helper_connector_duplicate_state
|
||||
drm_atomic_helper_connector_reset
|
||||
drm_atomic_helper_crtc_destroy_state
|
||||
drm_atomic_helper_crtc_duplicate_state
|
||||
drm_atomic_helper_crtc_reset
|
||||
drm_atomic_helper_dirtyfb
|
||||
drm_atomic_helper_disable_plane
|
||||
drm_atomic_helper_page_flip
|
||||
drm_atomic_helper_plane_destroy_state
|
||||
drm_atomic_helper_plane_duplicate_state
|
||||
drm_atomic_helper_plane_reset
|
||||
drm_atomic_helper_set_config
|
||||
drm_atomic_helper_shutdown
|
||||
drm_atomic_helper_update_plane
|
||||
drm_atomic_helper_wait_for_vblanks
|
||||
drm_class_device_register
|
||||
drm_class_device_unregister
|
||||
drm_clflush_pages
|
||||
drm_compat_ioctl
|
||||
drm_connector_attach_edid_property
|
||||
drm_connector_attach_encoder
|
||||
drm_connector_cleanup
|
||||
drm_connector_init
|
||||
drm_connector_register
|
||||
drm_connector_unregister
|
||||
drm_connector_update_edid_property
|
||||
drm_crtc_cleanup
|
||||
drm_crtc_init_with_planes
|
||||
drm_crtc_send_vblank_event
|
||||
drm_cvt_mode
|
||||
drm_dbg
|
||||
drm_debugfs_create_files
|
||||
drm_dev_alloc
|
||||
drm_dev_put
|
||||
drm_dev_register
|
||||
drm_dev_set_unique
|
||||
drm_dev_unregister
|
||||
drm_do_get_edid
|
||||
drm_encoder_cleanup
|
||||
drm_encoder_init
|
||||
drm_err
|
||||
drm_framebuffer_init
|
||||
drm_gem_fb_create_handle
|
||||
drm_gem_fb_destroy
|
||||
drm_gem_handle_create
|
||||
drm_gem_object_init
|
||||
drm_gem_object_lookup
|
||||
drm_gem_object_put_unlocked
|
||||
drm_gem_object_release
|
||||
drm_gem_prime_fd_to_handle
|
||||
drm_gem_prime_handle_to_fd
|
||||
drm_gem_prime_mmap
|
||||
drm_helper_hpd_irq_event
|
||||
drm_helper_mode_fill_fb_struct
|
||||
drm_helper_probe_single_connector_modes
|
||||
drm_ioctl
|
||||
drm_kms_helper_hotplug_event
|
||||
drm_mm_init
|
||||
drm_mm_insert_node_in_range
|
||||
drm_mm_print
|
||||
drm_mm_remove_node
|
||||
drm_mm_takedown
|
||||
drm_mode_config_cleanup
|
||||
drm_mode_config_init
|
||||
drm_mode_config_reset
|
||||
drm_mode_probed_add
|
||||
drm_open
|
||||
drm_plane_cleanup
|
||||
drm_poll
|
||||
drm_prime_pages_to_sg
|
||||
drm_printf
|
||||
__drm_printfn_debug
|
||||
drm_put_dev
|
||||
drm_read
|
||||
drm_release
|
||||
drm_set_preferred_mode
|
||||
drm_universal_plane_init
|
||||
drm_vma_offset_add
|
||||
drm_vma_offset_lookup_locked
|
||||
drm_vma_offset_manager_destroy
|
||||
drm_vma_offset_manager_init
|
||||
drm_vma_offset_remove
|
||||
eth_commit_mac_addr_change
|
||||
ether_setup
|
||||
eth_prepare_mac_addr_change
|
||||
__ethtool_get_link_ksettings
|
||||
ethtool_op_get_link
|
||||
ethtool_op_get_ts_info
|
||||
eth_type_trans
|
||||
eth_validate_addr
|
||||
event_triggers_call
|
||||
fasync_helper
|
||||
fd_install
|
||||
find_next_bit
|
||||
finish_wait
|
||||
flow_keys_basic_dissector
|
||||
flush_work
|
||||
flush_workqueue
|
||||
fput
|
||||
free_irq
|
||||
free_netdev
|
||||
__free_pages
|
||||
free_pages_exact
|
||||
free_percpu
|
||||
freezing_slow_path
|
||||
fsl8250_handle_irq
|
||||
generic_file_llseek
|
||||
get_device
|
||||
get_random_bytes
|
||||
__get_task_comm
|
||||
get_unused_fd_flags
|
||||
gpiod_cansleep
|
||||
gpiod_get_raw_value
|
||||
gpiod_get_raw_value_cansleep
|
||||
gpiod_get_value
|
||||
gpiod_get_value_cansleep
|
||||
gpiod_is_active_low
|
||||
gpiod_set_debounce
|
||||
gpiod_to_irq
|
||||
hrtimer_active
|
||||
hrtimer_cancel
|
||||
hrtimer_forward
|
||||
hrtimer_init
|
||||
hrtimer_start_range_ns
|
||||
hvc_alloc
|
||||
hvc_instantiate
|
||||
hvc_kick
|
||||
hvc_poll
|
||||
hvc_remove
|
||||
__hvc_resize
|
||||
hwrng_register
|
||||
hwrng_unregister
|
||||
ida_alloc_range
|
||||
ida_destroy
|
||||
ida_free
|
||||
init_net
|
||||
init_timer_key
|
||||
init_wait_entry
|
||||
__init_waitqueue_head
|
||||
input_alloc_absinfo
|
||||
input_allocate_device
|
||||
input_event
|
||||
input_free_device
|
||||
input_mt_init_slots
|
||||
input_register_device
|
||||
input_set_abs_params
|
||||
input_unregister_device
|
||||
iomem_resource
|
||||
__ioremap
|
||||
iounmap
|
||||
irq_dispose_mapping
|
||||
irq_set_affinity_hint
|
||||
irq_set_irq_wake
|
||||
jiffies
|
||||
jiffies_to_msecs
|
||||
kernel_kobj
|
||||
kfree
|
||||
kfree_skb
|
||||
kill_fasync
|
||||
kimage_vaddr
|
||||
kimage_voffset
|
||||
__kmalloc
|
||||
kmalloc_caches
|
||||
kmalloc_order_trace
|
||||
kmem_cache_alloc
|
||||
kmem_cache_alloc_trace
|
||||
kmem_cache_create
|
||||
kmem_cache_destroy
|
||||
kmem_cache_free
|
||||
kmemdup
|
||||
kobject_del
|
||||
kobject_init_and_add
|
||||
kobject_put
|
||||
kobject_uevent
|
||||
kobject_uevent_env
|
||||
kstrtoull
|
||||
kthread_create_on_node
|
||||
kthread_create_worker
|
||||
kthread_destroy_worker
|
||||
kthread_queue_work
|
||||
kthread_should_stop
|
||||
kthread_stop
|
||||
ktime_get
|
||||
ktime_get_mono_fast_ns
|
||||
ktime_get_real_seconds
|
||||
ktime_get_ts64
|
||||
ktime_get_with_offset
|
||||
kvfree
|
||||
kvmalloc_node
|
||||
kzfree
|
||||
led_classdev_register_ext
|
||||
led_classdev_unregister
|
||||
led_trigger_event
|
||||
led_trigger_register_simple
|
||||
led_trigger_unregister_simple
|
||||
__local_bh_enable_ip
|
||||
lock_sock_nested
|
||||
mark_page_accessed
|
||||
memcpy
|
||||
__memcpy_fromio
|
||||
__memcpy_toio
|
||||
memdup_user
|
||||
memmove
|
||||
memparse
|
||||
memset
|
||||
__memset_io
|
||||
misc_deregister
|
||||
misc_register
|
||||
mod_timer
|
||||
__module_get
|
||||
module_put
|
||||
__msecs_to_jiffies
|
||||
msleep
|
||||
__mutex_init
|
||||
mutex_is_locked
|
||||
mutex_lock
|
||||
mutex_lock_interruptible
|
||||
mutex_trylock
|
||||
mutex_unlock
|
||||
__napi_alloc_skb
|
||||
napi_complete_done
|
||||
napi_consume_skb
|
||||
napi_disable
|
||||
napi_gro_receive
|
||||
napi_hash_del
|
||||
__napi_schedule
|
||||
napi_schedule_prep
|
||||
__netdev_alloc_skb
|
||||
netdev_change_features
|
||||
netdev_err
|
||||
netdev_increment_features
|
||||
netdev_info
|
||||
netdev_lower_state_changed
|
||||
netdev_master_upper_dev_link
|
||||
netdev_notify_peers
|
||||
netdev_pick_tx
|
||||
netdev_rx_handler_register
|
||||
netdev_rx_handler_unregister
|
||||
netdev_upper_dev_link
|
||||
netdev_upper_dev_unlink
|
||||
netdev_warn
|
||||
netif_carrier_off
|
||||
netif_carrier_on
|
||||
netif_device_attach
|
||||
netif_device_detach
|
||||
netif_napi_add
|
||||
netif_napi_del
|
||||
netif_receive_skb
|
||||
netif_rx
|
||||
netif_rx_ni
|
||||
netif_schedule_queue
|
||||
netif_set_real_num_rx_queues
|
||||
netif_set_real_num_tx_queues
|
||||
__netif_set_xps_queue
|
||||
netif_stacked_transfer_operstate
|
||||
netif_tx_stop_all_queues
|
||||
netif_tx_wake_queue
|
||||
netlink_capable
|
||||
__netlink_dump_start
|
||||
net_ratelimit
|
||||
nf_conntrack_destroy
|
||||
nla_memcpy
|
||||
__nla_parse
|
||||
nla_put
|
||||
__nlmsg_put
|
||||
no_llseek
|
||||
nonseekable_open
|
||||
noop_llseek
|
||||
nr_cpu_ids
|
||||
nr_swap_pages
|
||||
nsecs_to_jiffies
|
||||
__num_online_cpus
|
||||
of_address_to_resource
|
||||
of_alias_get_id
|
||||
of_device_get_match_data
|
||||
of_device_is_big_endian
|
||||
of_device_is_compatible
|
||||
of_find_property
|
||||
of_get_child_by_name
|
||||
of_get_next_child
|
||||
of_get_property
|
||||
of_irq_get
|
||||
of_parse_phandle
|
||||
of_property_read_u64
|
||||
of_property_read_variable_u32_array
|
||||
panic
|
||||
param_ops_bool
|
||||
param_ops_int
|
||||
param_ops_uint
|
||||
passthru_features_check
|
||||
pci_alloc_irq_vectors_affinity
|
||||
pci_bus_type
|
||||
pci_disable_device
|
||||
pci_enable_device
|
||||
pci_find_capability
|
||||
pci_find_ext_capability
|
||||
pci_find_next_capability
|
||||
pci_free_irq_vectors
|
||||
pci_iomap_range
|
||||
pci_irq_get_affinity
|
||||
pci_irq_vector
|
||||
pci_read_config_byte
|
||||
pci_read_config_dword
|
||||
__pci_register_driver
|
||||
pci_release_selected_regions
|
||||
pci_request_selected_regions
|
||||
pci_set_master
|
||||
pci_unregister_driver
|
||||
PDE_DATA
|
||||
__per_cpu_offset
|
||||
perf_trace_buf_alloc
|
||||
perf_trace_run_bpf_submit
|
||||
physvirt_offset
|
||||
pipe_lock
|
||||
pipe_unlock
|
||||
platform_device_add
|
||||
platform_device_add_data
|
||||
platform_device_alloc
|
||||
platform_device_del
|
||||
platform_device_put
|
||||
platform_device_register_full
|
||||
platform_device_unregister
|
||||
__platform_driver_register
|
||||
platform_driver_unregister
|
||||
platform_get_irq
|
||||
platform_get_resource
|
||||
pm_generic_resume
|
||||
pm_generic_runtime_resume
|
||||
pm_generic_runtime_suspend
|
||||
pm_generic_suspend
|
||||
__pm_runtime_disable
|
||||
pm_runtime_enable
|
||||
__pm_runtime_idle
|
||||
__pm_runtime_resume
|
||||
pm_runtime_set_autosuspend_delay
|
||||
__pm_runtime_set_status
|
||||
__pm_runtime_suspend
|
||||
__pm_runtime_use_autosuspend
|
||||
pm_wakeup_dev_event
|
||||
prandom_u32
|
||||
preempt_count_add
|
||||
preempt_count_sub
|
||||
preempt_schedule
|
||||
preempt_schedule_notrace
|
||||
prepare_to_wait
|
||||
prepare_to_wait_event
|
||||
printk
|
||||
proc_create_net_single
|
||||
proc_mkdir_data
|
||||
proto_register
|
||||
proto_unregister
|
||||
__put_cred
|
||||
put_device
|
||||
put_disk
|
||||
__put_page
|
||||
put_unused_fd
|
||||
queue_delayed_work_on
|
||||
queue_work_on
|
||||
___ratelimit
|
||||
_raw_read_lock
|
||||
_raw_read_unlock
|
||||
_raw_spin_lock
|
||||
_raw_spin_lock_bh
|
||||
_raw_spin_lock_irq
|
||||
_raw_spin_lock_irqsave
|
||||
_raw_spin_trylock
|
||||
_raw_spin_unlock
|
||||
_raw_spin_unlock_bh
|
||||
_raw_spin_unlock_irq
|
||||
_raw_spin_unlock_irqrestore
|
||||
_raw_write_lock_bh
|
||||
_raw_write_unlock_bh
|
||||
rcu_barrier
|
||||
__rcu_read_lock
|
||||
__rcu_read_unlock
|
||||
refcount_dec_and_test_checked
|
||||
refcount_inc_checked
|
||||
refcount_inc_not_zero_checked
|
||||
__refrigerator
|
||||
register_blkdev
|
||||
__register_chrdev
|
||||
register_netdev
|
||||
register_netdevice
|
||||
register_netdevice_notifier
|
||||
register_pernet_subsys
|
||||
register_pm_notifier
|
||||
register_shrinker
|
||||
regulator_count_voltages
|
||||
regulator_disable
|
||||
regulator_enable
|
||||
regulator_get_current_limit
|
||||
regulator_get_voltage
|
||||
regulator_is_supported_voltage
|
||||
regulator_list_voltage
|
||||
regulator_set_voltage
|
||||
release_sock
|
||||
remove_proc_entry
|
||||
remove_wait_queue
|
||||
__request_module
|
||||
request_threaded_irq
|
||||
reservation_ww_class
|
||||
reset_control_assert
|
||||
reset_control_deassert
|
||||
revalidate_disk
|
||||
round_jiffies
|
||||
__rtc_register_device
|
||||
rtc_time64_to_tm
|
||||
rtc_tm_to_time64
|
||||
rtc_update_irq
|
||||
rtnl_is_locked
|
||||
rtnl_link_register
|
||||
rtnl_link_unregister
|
||||
rtnl_lock
|
||||
rtnl_register_module
|
||||
rtnl_unlock
|
||||
rtnl_unregister
|
||||
rtnl_unregister_all
|
||||
sched_clock
|
||||
sched_setscheduler
|
||||
schedule
|
||||
schedule_timeout
|
||||
scnprintf
|
||||
security_sock_graft
|
||||
seq_lseek
|
||||
seq_printf
|
||||
seq_putc
|
||||
seq_puts
|
||||
seq_read
|
||||
serial8250_get_port
|
||||
serial8250_register_8250_port
|
||||
serial8250_resume_port
|
||||
serial8250_suspend_port
|
||||
serial8250_unregister_port
|
||||
set_disk_ro
|
||||
set_page_dirty
|
||||
sg_alloc_table
|
||||
__sg_alloc_table_from_pages
|
||||
sg_copy_from_buffer
|
||||
sg_copy_to_buffer
|
||||
sg_free_table
|
||||
sg_init_one
|
||||
sg_init_table
|
||||
sg_miter_next
|
||||
sg_miter_start
|
||||
sg_miter_stop
|
||||
sg_nents
|
||||
sg_nents_for_len
|
||||
sg_next
|
||||
shmem_file_setup
|
||||
shmem_read_mapping_page_gfp
|
||||
si_mem_available
|
||||
si_meminfo
|
||||
simple_attr_open
|
||||
simple_attr_read
|
||||
simple_attr_release
|
||||
simple_attr_write
|
||||
simple_read_from_buffer
|
||||
simple_strtoul
|
||||
single_open
|
||||
single_release
|
||||
sk_alloc
|
||||
skb_add_rx_frag
|
||||
skb_clone
|
||||
skb_coalesce_rx_frag
|
||||
skb_copy
|
||||
skb_dequeue
|
||||
__skb_flow_dissect
|
||||
skb_free_datagram
|
||||
skb_page_frag_refill
|
||||
skb_partial_csum_set
|
||||
skb_put
|
||||
skb_queue_purge
|
||||
skb_queue_tail
|
||||
skb_recv_datagram
|
||||
skb_to_sgvec
|
||||
skb_trim
|
||||
skb_tstamp_tx
|
||||
sk_free
|
||||
snprintf
|
||||
sock_alloc_send_skb
|
||||
sock_diag_register
|
||||
sock_diag_save_cookie
|
||||
sock_diag_unregister
|
||||
sock_efree
|
||||
sock_gettstamp
|
||||
sock_i_ino
|
||||
sock_init_data
|
||||
sock_no_accept
|
||||
sock_no_bind
|
||||
sock_no_connect
|
||||
sock_no_getname
|
||||
sock_no_getsockopt
|
||||
sock_no_ioctl
|
||||
sock_no_listen
|
||||
sock_no_mmap
|
||||
sock_no_sendpage
|
||||
sock_no_setsockopt
|
||||
sock_no_shutdown
|
||||
sock_no_socketpair
|
||||
sock_queue_rcv_skb
|
||||
__sock_recv_ts_and_drops
|
||||
sock_register
|
||||
__sock_tx_timestamp
|
||||
sock_unregister
|
||||
softnet_data
|
||||
__splice_from_pipe
|
||||
sprintf
|
||||
sscanf
|
||||
__stack_chk_fail
|
||||
__stack_chk_guard
|
||||
strcmp
|
||||
strcpy
|
||||
string_get_size
|
||||
strlcpy
|
||||
strlen
|
||||
strncmp
|
||||
strncpy
|
||||
strstr
|
||||
swiotlb_max_segment
|
||||
sync_file_create
|
||||
sync_file_get_fence
|
||||
synchronize_hardirq
|
||||
synchronize_irq
|
||||
synchronize_net
|
||||
synchronize_rcu
|
||||
sysfs_create_bin_file
|
||||
sysfs_create_group
|
||||
__sysfs_match_string
|
||||
sysfs_remove_bin_file
|
||||
sysfs_remove_group
|
||||
system_freezable_wq
|
||||
system_freezing_cnt
|
||||
system_wq
|
||||
__this_cpu_preempt_check
|
||||
trace_define_field
|
||||
trace_event_buffer_commit
|
||||
trace_event_buffer_reserve
|
||||
trace_event_ignore_this_pid
|
||||
trace_event_raw_init
|
||||
trace_event_reg
|
||||
trace_handle_return
|
||||
__tracepoint_dma_fence_emit
|
||||
__tracepoint_xdp_exception
|
||||
trace_print_symbols_seq
|
||||
trace_raw_output_prep
|
||||
trace_seq_printf
|
||||
try_module_get
|
||||
unlock_page
|
||||
unmap_mapping_range
|
||||
unregister_blkdev
|
||||
__unregister_chrdev
|
||||
unregister_chrdev_region
|
||||
unregister_netdev
|
||||
unregister_netdevice_many
|
||||
unregister_netdevice_notifier
|
||||
unregister_netdevice_queue
|
||||
unregister_pernet_subsys
|
||||
unregister_pm_notifier
|
||||
unregister_shrinker
|
||||
up_read
|
||||
usb_add_gadget_udc
|
||||
usb_add_hcd
|
||||
usb_create_hcd
|
||||
usb_create_shared_hcd
|
||||
usb_del_gadget_udc
|
||||
usb_disabled
|
||||
usb_ep_set_maxpacket_limit
|
||||
usb_gadget_giveback_request
|
||||
usb_gadget_udc_reset
|
||||
usb_get_dev
|
||||
usb_hcd_check_unlink_urb
|
||||
usb_hcd_giveback_urb
|
||||
usb_hcd_is_primary_hcd
|
||||
usb_hcd_link_urb_to_ep
|
||||
usb_hcd_poll_rh_status
|
||||
usb_hcd_resume_root_hub
|
||||
usb_hcd_unlink_urb_from_ep
|
||||
usb_put_dev
|
||||
usb_put_hcd
|
||||
usb_remove_hcd
|
||||
usleep_range
|
||||
vabits_actual
|
||||
vmalloc_to_page
|
||||
vmap
|
||||
vmemmap
|
||||
vmf_insert_mixed
|
||||
vmf_insert_pfn
|
||||
vm_get_page_prot
|
||||
vunmap
|
||||
wait_for_completion
|
||||
wait_for_completion_killable
|
||||
wait_woken
|
||||
__wake_up
|
||||
wake_up_process
|
||||
__warn_printk
|
||||
wiphy_free
|
||||
wiphy_new_nm
|
||||
wiphy_register
|
||||
wiphy_unregister
|
||||
woken_wake_function
|
||||
ww_mutex_lock
|
||||
ww_mutex_lock_interruptible
|
||||
ww_mutex_unlock
|
||||
xdp_convert_zc_to_xdp_frame
|
||||
xdp_do_flush_map
|
||||
xdp_do_redirect
|
||||
xdp_return_frame
|
||||
xdp_return_frame_rx_napi
|
||||
xdp_rxq_info_reg
|
||||
xdp_rxq_info_reg_mem_model
|
||||
xdp_rxq_info_unreg
|
1351
abi_gki_qcom_whitelist
Normal file
1351
abi_gki_qcom_whitelist
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,6 @@
|
||||
extern void cpu_init(void);
|
||||
|
||||
void soft_restart(unsigned long);
|
||||
extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
|
||||
extern void (*arm_pm_idle)(void);
|
||||
|
||||
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
|
||||
|
@ -18,7 +18,6 @@ typedef void (*phys_reset_t)(unsigned long, bool);
|
||||
/*
|
||||
* Function pointers to optional machine specific functions
|
||||
*/
|
||||
void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
|
||||
void (*pm_power_off)(void);
|
||||
EXPORT_SYMBOL(pm_power_off);
|
||||
|
||||
@ -138,10 +137,7 @@ void machine_restart(char *cmd)
|
||||
local_irq_disable();
|
||||
smp_send_stop();
|
||||
|
||||
if (arm_pm_restart)
|
||||
arm_pm_restart(reboot_mode, cmd);
|
||||
else
|
||||
do_kernel_restart(cmd);
|
||||
do_kernel_restart(cmd);
|
||||
|
||||
/* Give a grace period for failure to restart of 1s */
|
||||
mdelay(1000);
|
||||
|
@ -1073,6 +1073,20 @@ void __init hyp_mode_check(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void (*__arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
|
||||
|
||||
static int arm_restart(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
__arm_pm_restart(action, data);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block arm_restart_nb = {
|
||||
.notifier_call = arm_restart,
|
||||
.priority = 128,
|
||||
};
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
const struct machine_desc *mdesc;
|
||||
@ -1132,8 +1146,10 @@ void __init setup_arch(char **cmdline_p)
|
||||
paging_init(mdesc);
|
||||
request_standard_resources(mdesc);
|
||||
|
||||
if (mdesc->restart)
|
||||
arm_pm_restart = mdesc->restart;
|
||||
if (mdesc->restart) {
|
||||
__arm_pm_restart = mdesc->restart;
|
||||
register_restart_handler(&arm_restart_nb);
|
||||
}
|
||||
|
||||
unflatten_device_tree();
|
||||
|
||||
|
@ -52,6 +52,11 @@
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/ipi.h>
|
||||
|
||||
#ifdef CONFIG_QGKI_LPM_IPI_CHECK
|
||||
DEFINE_PER_CPU(bool, pending_ipi);
|
||||
EXPORT_PER_CPU_SYMBOL(pending_ipi);
|
||||
#endif /* CONFIG_QGKI_LPM_IPI_CHECK */
|
||||
|
||||
/*
|
||||
* as from 2.5, kernels no longer have an init_tasks structure
|
||||
* so we need some other way of telling a new secondary core
|
||||
@ -523,6 +528,13 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = {
|
||||
|
||||
static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
|
||||
{
|
||||
#ifdef CONFIG_QGKI_LPM_IPI_CHECK
|
||||
unsigned int cpu;
|
||||
|
||||
for_each_cpu(cpu, target)
|
||||
per_cpu(pending_ipi, cpu) = true;
|
||||
#endif /* CONFIG_QGKI_LPM_IPI_CHECK */
|
||||
|
||||
trace_ipi_raise_rcuidle(target, ipi_types[ipinr]);
|
||||
__smp_cross_call(target, ipinr);
|
||||
}
|
||||
@ -697,6 +709,11 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
|
||||
|
||||
if ((unsigned)ipinr < NR_IPI)
|
||||
trace_ipi_exit_rcuidle(ipi_types[ipinr]);
|
||||
|
||||
#ifdef CONFIG_QGKI_LPM_IPI_CHECK
|
||||
this_cpu_write(pending_ipi, false);
|
||||
#endif /* CONFIG_QGKI_LPM_IPI_CHECK */
|
||||
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
|
@ -64,11 +64,18 @@ static struct reset_controller_dev sirfsoc_reset_controller = {
|
||||
|
||||
#define SIRFSOC_SYS_RST_BIT BIT(31)
|
||||
|
||||
static void sirfsoc_restart(enum reboot_mode mode, const char *cmd)
|
||||
static int sirfsoc_restart(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
writel(SIRFSOC_SYS_RST_BIT, sirfsoc_rstc_base);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block sirfsoc_restart_nb = {
|
||||
.notifier_call = sirfsoc_restart,
|
||||
.priority = 192,
|
||||
};
|
||||
|
||||
static int sirfsoc_rstc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
@ -79,7 +86,7 @@ static int sirfsoc_rstc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
sirfsoc_reset_controller.of_node = np;
|
||||
arm_pm_restart = sirfsoc_restart;
|
||||
register_restart_handler(&sirfsoc_restart_nb);
|
||||
|
||||
if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
|
||||
reset_controller_register(&sirfsoc_reset_controller);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/pvclock_gtod.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/time64.h>
|
||||
#include <linux/timekeeping.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
@ -180,11 +181,18 @@ void xen_reboot(int reason)
|
||||
BUG_ON(rc);
|
||||
}
|
||||
|
||||
static void xen_restart(enum reboot_mode reboot_mode, const char *cmd)
|
||||
static int xen_restart(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
xen_reboot(SHUTDOWN_reboot);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block xen_restart_nb = {
|
||||
.notifier_call = xen_restart,
|
||||
.priority = 192,
|
||||
};
|
||||
|
||||
static void xen_power_off(void)
|
||||
{
|
||||
@ -405,7 +413,7 @@ static int __init xen_pm_init(void)
|
||||
return -ENODEV;
|
||||
|
||||
pm_power_off = xen_power_off;
|
||||
arm_pm_restart = xen_restart;
|
||||
register_restart_handler(&xen_restart_nb);
|
||||
if (!xen_initial_domain()) {
|
||||
struct timespec64 ts;
|
||||
xen_read_wallclock(&ts);
|
||||
|
@ -278,15 +278,32 @@ config ZONE_DMA
|
||||
default y
|
||||
|
||||
config ZONE_DMA32
|
||||
bool "Support DMA32 zone" if EXPERT
|
||||
bool "Enable or Disable Zone DMA"
|
||||
default y
|
||||
help
|
||||
This option enables/disables the DMA zone.
|
||||
|
||||
config ARCH_ENABLE_MEMORY_HOTPLUG
|
||||
depends on !NUMA
|
||||
def_bool y
|
||||
|
||||
config ARCH_ENABLE_MEMORY_HOTREMOVE
|
||||
def_bool y
|
||||
|
||||
config SMP
|
||||
def_bool y
|
||||
|
||||
config HOTPLUG_SIZE_BITS
|
||||
int "Memory hotplug block size(29 => 512MB 30 => 1GB)"
|
||||
depends on SPARSEMEM
|
||||
depends on MEMORY_HOTPLUG
|
||||
default 30
|
||||
help
|
||||
Selects granularity of hotplug memory. Block
|
||||
size for memory hotplug is represent as a power
|
||||
of 2.
|
||||
If unsure, stick with default value.
|
||||
|
||||
config KERNEL_MODE_NEON
|
||||
def_bool y
|
||||
|
||||
@ -1022,9 +1039,34 @@ config ARCH_WANT_HUGE_PMD_SHARE
|
||||
config ARCH_HAS_CACHE_LINE_SIZE
|
||||
def_bool y
|
||||
|
||||
if ARM64 && IOMMU_DMA
|
||||
|
||||
config ARM64_DMA_IOMMU_ALIGNMENT
|
||||
int "Maximum PAGE_SIZE order of alignment for DMA IOMMU buffers"
|
||||
range 4 9
|
||||
default 9
|
||||
help
|
||||
DMA mapping framework by default aligns all buffers to the smallest
|
||||
PAGE_SIZE order which is greater than or equal to the requested buffer
|
||||
size. This works well for buffers up to a few hundreds kilobytes, but
|
||||
for larger buffers it just a waste of address space. Drivers which has
|
||||
relatively small addressing window (like 64Mib) might run out of
|
||||
virtual space with just a few allocations.
|
||||
|
||||
With this parameter you can specify the maximum PAGE_SIZE order for
|
||||
DMA IOMMU buffers. Larger buffers will be aligned only to this
|
||||
specified order. The order is expressed as a power of two multiplied
|
||||
by the PAGE_SIZE.
|
||||
|
||||
endif
|
||||
|
||||
config ARCH_ENABLE_SPLIT_PMD_PTLOCK
|
||||
def_bool y if PGTABLE_LEVELS > 2
|
||||
|
||||
config ARCH_MEMORY_PROBE
|
||||
def_bool y
|
||||
depends on MEMORY_HOTPLUG
|
||||
|
||||
# Supported by clang >= 7.0
|
||||
config CC_HAVE_SHADOW_CALL_STACK
|
||||
def_bool $(cc-option, -fsanitize=shadow-call-stack -ffixed-x18)
|
||||
@ -1767,6 +1809,40 @@ config DMI
|
||||
|
||||
endmenu
|
||||
|
||||
choice
|
||||
prompt "Kernel compression method"
|
||||
default BUILD_ARM64_KERNEL_COMPRESSION_GZIP
|
||||
help
|
||||
Allows choice between gzip compressed or uncompressed
|
||||
kernel image. Decision is based on whether the bootloader
|
||||
can handle (un)compressed kernel images. Most BLs are capable
|
||||
of decomprssing kernel images and this is the default choice.
|
||||
|
||||
config BUILD_ARM64_KERNEL_COMPRESSION_GZIP
|
||||
bool "Build compressed kernel image"
|
||||
help
|
||||
Build a kernel image using gzip
|
||||
compression. gzip is based on the DEFLATE
|
||||
algorithm. Check if your bootloader is
|
||||
capable of decompressing images.
|
||||
|
||||
config BUILD_ARM64_UNCOMPRESSED_KERNEL
|
||||
bool "Build uncompressed kernel image"
|
||||
help
|
||||
Build a kernel image without
|
||||
compression. An uncompressed kernel
|
||||
image may improve performance in
|
||||
certain situations.
|
||||
endchoice
|
||||
|
||||
config BUILD_ARM64_DT_OVERLAY
|
||||
bool "enable DT overlay compilation support"
|
||||
depends on OF
|
||||
help
|
||||
This option enables support for DT overlay compilation.
|
||||
Enabling this option sets required flags to add DT
|
||||
overlay in the compilation.
|
||||
|
||||
config SYSVIPC_COMPAT
|
||||
def_bool y
|
||||
depends on COMPAT && SYSVIPC
|
||||
|
@ -187,6 +187,31 @@ config ARCH_QCOM
|
||||
help
|
||||
This enables support for the ARMv8 based Qualcomm chipsets.
|
||||
|
||||
config ARCH_LAHAINA
|
||||
bool "Enable Support for Qualcomm Technologies, Inc. LAHAINA"
|
||||
depends on ARCH_QCOM
|
||||
help
|
||||
This enables support for the Qualcomm Technologies, Inc.'s
|
||||
LAHAINA chipset. If you do not wish to build a kernel that
|
||||
runs on this chipset or if you are unsure, say 'N' here.
|
||||
|
||||
config ARCH_QTI_VM
|
||||
bool "Enable Virtual Machines Support for Qualcomm Technologies, Inc."
|
||||
depends on ARCH_QCOM
|
||||
help
|
||||
This enables support for the Qualcomm Technologies, Inc.'s
|
||||
Virtual Machines. If you wish to build a kernel that doesn't
|
||||
require VM support or if you are unsure,
|
||||
say 'N' here.
|
||||
|
||||
config ARCH_SHIMA
|
||||
bool "Enable Support for Qualcomm Technologies, Inc. SHIMA"
|
||||
depends on ARCH_QCOM
|
||||
help
|
||||
This enables support for the Qualcomm Technologies, Inc.'s
|
||||
SHIMA chipset. If you do not wish to build a kernel that
|
||||
runs on this chipset or if you are unsure, say 'N' here.
|
||||
|
||||
config ARCH_REALTEK
|
||||
bool "Realtek Platforms"
|
||||
select RESET_CONTROLLER
|
||||
|
@ -125,12 +125,17 @@ core-y += arch/arm64/
|
||||
libs-y := arch/arm64/lib/ $(libs-y)
|
||||
core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
|
||||
|
||||
ifeq ($(CONFIG_BUILD_ARM64_KERNEL_COMPRESSION_GZIP),y)
|
||||
KBUILD_TARGET := Image.gz
|
||||
else
|
||||
KBUILD_TARGET := Image
|
||||
endif
|
||||
|
||||
# Default target when executing plain make
|
||||
boot := arch/arm64/boot
|
||||
KBUILD_IMAGE := $(boot)/Image.gz
|
||||
|
||||
all: Image.gz
|
||||
KBUILD_IMAGE := $(boot)/$(KBUILD_TARGET)
|
||||
|
||||
all: $(KBUILD_TARGET)
|
||||
|
||||
Image: vmlinux
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
|
||||
|
@ -28,3 +28,9 @@ subdir-y += synaptics
|
||||
subdir-y += ti
|
||||
subdir-y += xilinx
|
||||
subdir-y += zte
|
||||
|
||||
dtstree := $(srctree)/$(src)
|
||||
vendor := $(dtstree)/vendor
|
||||
ifneq "$(wildcard $(vendor)/Makefile)" ""
|
||||
subdir-y += vendor
|
||||
endif
|
||||
|
114
arch/arm64/boot/dts/hisilicon/hi3660-drm.dtsi
Normal file
114
arch/arm64/boot/dts/hisilicon/hi3660-drm.dtsi
Normal file
@ -0,0 +1,114 @@
|
||||
/{
|
||||
dpe: dpe@E8600000 {
|
||||
compatible = "hisilicon,hi3660-dpe";
|
||||
status = "ok";
|
||||
|
||||
reg = <0x0 0xE8600000 0x0 0x80000>,
|
||||
<0x0 0xFFF35000 0 0x1000>,
|
||||
<0x0 0xFFF0A000 0 0x1000>,
|
||||
<0x0 0xFFF31000 0 0x1000>,
|
||||
<0x0 0xE86C0000 0 0x10000>;
|
||||
interrupts = <0 245 4>;
|
||||
|
||||
clocks = <&crg_ctrl HI3660_ACLK_GATE_DSS>,
|
||||
<&crg_ctrl HI3660_PCLK_GATE_DSS>,
|
||||
<&crg_ctrl HI3660_CLK_GATE_EDC0>,
|
||||
<&crg_ctrl HI3660_CLK_GATE_LDI0>,
|
||||
<&crg_ctrl HI3660_CLK_GATE_LDI1>,
|
||||
<&sctrl HI3660_CLK_GATE_DSS_AXI_MM>,
|
||||
<&sctrl HI3660_PCLK_GATE_MMBUF>;
|
||||
clock-names = "aclk_dss",
|
||||
"pclk_dss",
|
||||
"clk_edc0",
|
||||
"clk_ldi0",
|
||||
"clk_ldi1",
|
||||
"clk_dss_axi_mm",
|
||||
"pclk_mmbuf";
|
||||
|
||||
dma-coherent;
|
||||
|
||||
port {
|
||||
dpe_out: endpoint {
|
||||
remote-endpoint = <&dsi_in>;
|
||||
};
|
||||
};
|
||||
|
||||
iommu_info {
|
||||
start-addr = <0x8000>;
|
||||
size = <0xbfff8000>;
|
||||
};
|
||||
};
|
||||
|
||||
dsi: dsi@E8601000 {
|
||||
compatible = "hisilicon,hi3660-dsi";
|
||||
status = "ok";
|
||||
|
||||
reg = <0 0xE8601000 0 0x7F000>,
|
||||
<0 0xFFF35000 0 0x1000>;
|
||||
|
||||
clocks = <&crg_ctrl HI3660_CLK_GATE_TXDPHY0_REF>,
|
||||
<&crg_ctrl HI3660_CLK_GATE_TXDPHY1_REF>,
|
||||
<&crg_ctrl HI3660_CLK_GATE_TXDPHY0_CFG>,
|
||||
<&crg_ctrl HI3660_CLK_GATE_TXDPHY1_CFG>,
|
||||
<&crg_ctrl HI3660_PCLK_GATE_DSI0>,
|
||||
<&crg_ctrl HI3660_PCLK_GATE_DSI1>;
|
||||
clock-names = "clk_txdphy0_ref",
|
||||
"clk_txdphy1_ref",
|
||||
"clk_txdphy0_cfg",
|
||||
"clk_txdphy1_cfg",
|
||||
"pclk_dsi0",
|
||||
"pclk_dsi1";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
mux-gpio = <&gpio2 4 0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dsi_in: endpoint {
|
||||
remote-endpoint = <&dpe_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
|
||||
dsi_out0: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&adv7533_in>;
|
||||
};
|
||||
|
||||
dsi_out1: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&panel0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
panel@1 {
|
||||
compatible = "hisilicon,mipi-hikey";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
status = "ok";
|
||||
reg = <1>;
|
||||
panel-width-mm = <94>;
|
||||
panel-height-mm = <151>;
|
||||
vdd-supply = <&ldo3>;
|
||||
pwr-en-gpio = <&gpio27 0 0>;
|
||||
bl-en-gpio = <&gpio27 2 0>;
|
||||
pwm-gpio = <&gpio22 6 0>;
|
||||
|
||||
port {
|
||||
panel0_in: endpoint {
|
||||
remote-endpoint = <&dsi_out1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
19
arch/arm64/boot/dts/hisilicon/hi3660-gpu.dtsi
Normal file
19
arch/arm64/boot/dts/hisilicon/hi3660-gpu.dtsi
Normal file
@ -0,0 +1,19 @@
|
||||
/{
|
||||
gpu: mali@E82C0000 {
|
||||
compatible = "arm,malit6xx", "arm,mali-midgard";
|
||||
#cooling-cells = <3>; /* min followed by max */
|
||||
gpu_outstanding = <0x0>;
|
||||
reg = <0x0 0xE82C0000 0x0 0x4000>;
|
||||
interrupts = <0 258 4 0 259 4 0 260 4>;
|
||||
interrupt-names = "JOB", "MMU", "GPU";
|
||||
operating-points = <
|
||||
/* <frequency> <voltage>*/
|
||||
178000 650000
|
||||
400000 700000
|
||||
533000 800000
|
||||
807000 900000
|
||||
960000 1000000
|
||||
1037000 1100000
|
||||
>;
|
||||
};
|
||||
};
|
@ -10,9 +10,13 @@
|
||||
|
||||
#include "hi3660.dtsi"
|
||||
#include "hikey960-pinctrl.dtsi"
|
||||
#include "hi3660-drm.dtsi"
|
||||
#include "hi3660-gpu.dtsi"
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/usb/pd.h>
|
||||
|
||||
/ {
|
||||
model = "HiKey960";
|
||||
@ -45,6 +49,23 @@ reserved-memory {
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
fastboot_cma: fastboot-cma-mem {
|
||||
reg = <0x0 0x16c00000 0x0 0x4000000>;
|
||||
compatible = "shared-dma-pool";
|
||||
hisi,cma-sec;
|
||||
reusable;
|
||||
};
|
||||
|
||||
uefi-reboot-mode {
|
||||
reg = <0x0 0x32100000 0x0 0x00001000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
bl31 {
|
||||
reg = <0x0 0x20200000 0x0 0x200000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
ramoops@32000000 {
|
||||
compatible = "ramoops";
|
||||
reg = <0x0 0x32000000 0x0 0x00100000>;
|
||||
@ -52,6 +73,14 @@ ramoops@32000000 {
|
||||
console-size = <0x00020000>;
|
||||
ftrace-size = <0x00020000>;
|
||||
};
|
||||
|
||||
/* global autoconfigured region for contiguous allocations */
|
||||
linux,cma {
|
||||
compatible = "shared-dma-pool";
|
||||
reg = <0x0 0x20C00000 0x0 0x4000000>;
|
||||
reusable;
|
||||
linux,cma-default;
|
||||
};
|
||||
};
|
||||
|
||||
reboot-mode-syscon@32100000 {
|
||||
@ -196,6 +225,59 @@ optee {
|
||||
method = "smc";
|
||||
};
|
||||
};
|
||||
|
||||
hisi_hikey_usb: hisi_hikey_usb {
|
||||
compatible = "hisilicon,gpio_hubv1";
|
||||
typec-vbus-gpios = <&gpio25 2 GPIO_ACTIVE_HIGH>;
|
||||
otg-switch-gpios = <&gpio25 6 GPIO_ACTIVE_HIGH>;
|
||||
hub-vdd33-en-gpios = <&gpio5 6 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usbhub5734_pmx_func>;
|
||||
usb-role-switch;
|
||||
|
||||
port {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
hikey_usb_ep0: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&dwc3_role_switch>;
|
||||
};
|
||||
hikey_usb_ep1: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&rt1711h_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2s2: hi3660_i2s {
|
||||
compatible = "hisilicon,hi3660-i2s-1.0";
|
||||
reg = <0x0 0xe804f800 0x0 0x400>,
|
||||
<0x0 0xe804e000 0x0 0x400>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s2_pmx_func &i2s2_cfg_func>;
|
||||
dmas = <&asp_dmac 18 &asp_dmac 19>;
|
||||
dma-names = "rx", "tx";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
|
||||
sound {
|
||||
compatible = "simple-audio-card";
|
||||
simple-audio-card,name = "hikey-hdmi";
|
||||
simple-audio-card,format = "i2s";
|
||||
|
||||
simple-audio-card,bitclock-master = <&sound_master>;
|
||||
simple-audio-card,frame-master = <&sound_master>;
|
||||
|
||||
sound_master: simple-audio-card,cpu {
|
||||
sound-dai = <&i2s2>;
|
||||
};
|
||||
|
||||
simple-audio-card,codec {
|
||||
sound-dai = <&adv7533>;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
@ -526,11 +608,54 @@ &i2c0 {
|
||||
&i2c1 {
|
||||
status = "okay";
|
||||
|
||||
rt1711h: rt1711h@4e {
|
||||
compatible = "richtek,rt1711h";
|
||||
reg = <0x4e>;
|
||||
status = "ok";
|
||||
interrupt-parent = <&gpio27>;
|
||||
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usb_cfg_func>;
|
||||
|
||||
usb_con: connector {
|
||||
compatible = "usb-c-connector";
|
||||
label = "USB-C";
|
||||
data-role = "dual";
|
||||
power-role = "dual";
|
||||
try-power-role = "sink";
|
||||
source-pdos = <PDO_FIXED(5000, 500, PDO_FIXED_USB_COMM)>;
|
||||
sink-pdos = <PDO_FIXED(5000, 500, PDO_FIXED_USB_COMM)
|
||||
PDO_VAR(5000, 5000, 1000)>;
|
||||
op-sink-microwatt = <10000000>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
usb_con_ss: endpoint {
|
||||
remote-endpoint = <&dwc3_ss>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
port {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
rt1711h_ep: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&hikey_usb_ep1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
adv7533: adv7533@39 {
|
||||
status = "ok";
|
||||
compatible = "adi,adv7533";
|
||||
reg = <0x39>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&i2c7 {
|
||||
|
@ -355,6 +355,12 @@ pctrl: pctrl@e8a09000 {
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
pmctrl: pmctrl@fff31000 {
|
||||
compatible = "hisilicon,hi3660-pmctrl", "syscon";
|
||||
reg = <0x0 0xfff31000 0x0 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
pmuctrl: crg_ctrl@fff34000 {
|
||||
compatible = "hisilicon,hi3660-pmuctrl", "syscon";
|
||||
reg = <0x0 0xfff34000 0x0 0x1000>;
|
||||
@ -367,6 +373,13 @@ sctrl: sctrl@fff0a000 {
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
reboot {
|
||||
compatible = "hisilicon,hi3660-reboot";
|
||||
pmu-regmap = <&pmuctrl>;
|
||||
sctrl-regmap = <&sctrl>;
|
||||
reboot-offset = <0x4>;
|
||||
};
|
||||
|
||||
iomcu: iomcu@ffd7e000 {
|
||||
compatible = "hisilicon,hi3660-iomcu", "syscon";
|
||||
reg = <0x0 0xffd7e000 0x0 0x1000>;
|
||||
@ -431,7 +444,28 @@ i2c1: i2c@ffd72000 {
|
||||
resets = <&iomcu_rst 0x20 4>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1_pmx_func &i2c1_cfg_func>;
|
||||
status = "disabled";
|
||||
status = "ok";
|
||||
|
||||
adv7533: adv7533@39 {
|
||||
status = "ok";
|
||||
compatible = "adi,adv7533";
|
||||
reg = <0x39>;
|
||||
v1p2-supply = <&ldo3>;
|
||||
vdd-supply = <&ldo3>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <1 2>;
|
||||
pd-gpio = <&gpio5 1 0>;
|
||||
sel-gpio = <&gpio2 4 0>;
|
||||
adi,dsi-lanes = <4>;
|
||||
adi,disable-timing-generator;
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
port {
|
||||
adv7533_in: endpoint {
|
||||
remote-endpoint = <&dsi_out0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c3: i2c@fdf0c000 {
|
||||
@ -1152,6 +1186,70 @@ map1 {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
usb3_otg_bc: usb3_otg_bc@ff200000 {
|
||||
compatible = "syscon", "simple-mfd";
|
||||
reg = <0x0 0xff200000 0x0 0x1000>;
|
||||
|
||||
usb_phy: usb-phy {
|
||||
compatible = "hisilicon,hi3660-usb-phy";
|
||||
#phy-cells = <0>;
|
||||
hisilicon,pericrg-syscon = <&crg_ctrl>;
|
||||
hisilicon,pctrl-syscon = <&pctrl>;
|
||||
hisilicon,eye-diagram-param = <0x22466e4>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
dwc3: dwc3@ff100000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x0 0xff100000 0x0 0x100000>;
|
||||
|
||||
clocks = <&crg_ctrl HI3660_CLK_ABB_USB>,
|
||||
<&crg_ctrl HI3660_ACLK_GATE_USB3OTG>;
|
||||
clock-names = "ref", "bus_early";
|
||||
|
||||
assigned-clocks = <&crg_ctrl HI3660_ACLK_GATE_USB3OTG>;
|
||||
assigned-clock-rates = <229000000>;
|
||||
|
||||
resets = <&crg_rst 0x90 8>,
|
||||
<&crg_rst 0x90 7>,
|
||||
<&crg_rst 0x90 6>,
|
||||
<&crg_rst 0x90 5>;
|
||||
|
||||
interrupts = <0 159 4>, <0 161 4>;
|
||||
phys = <&usb_phy>;
|
||||
phy-names = "usb3-phy";
|
||||
|
||||
dr_mode = "otg";
|
||||
maximum-speed = "super-speed";
|
||||
phy_type = "utmi";
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,lfps_filter_quirk;
|
||||
snps,dis_u2_susphy_quirk;
|
||||
snps,dis_u3_susphy_quirk;
|
||||
snps,tx_de_emphasis_quirk;
|
||||
snps,tx_de_emphasis = <1>;
|
||||
snps,dis_enblslpm_quirk;
|
||||
snps,gctl-reset-quirk;
|
||||
usb-role-switch;
|
||||
role-switch-default-mode = "host";
|
||||
|
||||
port {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dwc3_role_switch: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&hikey_usb_ep0>;
|
||||
};
|
||||
|
||||
dwc3_ss: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&usb_con_ss>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
CONFIG_LOCALVERSION="-mainline"
|
||||
CONFIG_AUDIT=y
|
||||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
@ -119,7 +118,6 @@ CONFIG_IPV6_MIP6=y
|
||||
CONFIG_IPV6_VTI=y
|
||||
CONFIG_IPV6_MULTIPLE_TABLES=y
|
||||
CONFIG_NETFILTER=y
|
||||
# CONFIG_BRIDGE_NETFILTER is not set
|
||||
CONFIG_NF_CONNTRACK=y
|
||||
CONFIG_NF_CONNTRACK_SECMARK=y
|
||||
CONFIG_NF_CONNTRACK_EVENTS=y
|
||||
@ -364,15 +362,12 @@ CONFIG_DMADEVICES=y
|
||||
CONFIG_UIO=y
|
||||
CONFIG_STAGING=y
|
||||
CONFIG_ASHMEM=y
|
||||
CONFIG_ANDROID_VSOC=y
|
||||
CONFIG_ION=y
|
||||
CONFIG_ION_SYSTEM_HEAP=y
|
||||
CONFIG_COMMON_CLK_SCPI=y
|
||||
CONFIG_HWSPINLOCK=y
|
||||
CONFIG_MAILBOX=y
|
||||
CONFIG_ARM_SMMU=y
|
||||
CONFIG_QCOM_COMMAND_DB=y
|
||||
CONFIG_QCOM_RPMH=y
|
||||
CONFIG_DEVFREQ_GOV_PERFORMANCE=y
|
||||
CONFIG_DEVFREQ_GOV_POWERSAVE=y
|
||||
CONFIG_DEVFREQ_GOV_USERSPACE=y
|
||||
|
@ -1,4 +1,3 @@
|
||||
CONFIG_LOCALVERSION="-mainline"
|
||||
CONFIG_AUDIT=y
|
||||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
|
162
arch/arm64/configs/vendor/lahaina_GKI.config
vendored
Normal file
162
arch/arm64/configs/vendor/lahaina_GKI.config
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
CONFIG_ARCH_QCOM=y
|
||||
CONFIG_ARCH_LAHAINA=y
|
||||
CONFIG_ARCH_SHIMA=y
|
||||
CONFIG_HVC_DCC=y
|
||||
CONFIG_HVC_DCC_SERIALIZE_SMP=y
|
||||
CONFIG_REGULATOR_STUB=m
|
||||
CONFIG_REGULATOR_PROXY_CONSUMER=m
|
||||
CONFIG_PINCTRL_LAHAINA=m
|
||||
CONFIG_KEYBOARD_GPIO=m
|
||||
# CONFIG_IKHEADERS is not set
|
||||
CONFIG_SND_USB_AUDIO_QMI=m
|
||||
CONFIG_EXTCON=m
|
||||
CONFIG_SPMI_MSM_PMIC_ARB=m
|
||||
CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=m
|
||||
CONFIG_SPMI_QTI_GLINK_DEBUG=m
|
||||
CONFIG_MFD_I2C_PMIC=m
|
||||
CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
|
||||
CONFIG_NVMEM_SPMI_SDAM=m
|
||||
CONFIG_RTC_DRV_PM8XXX=m
|
||||
CONFIG_QCOM_SPMI_ADC5=m
|
||||
CONFIG_QCOM_SPMI_TEMP_ALARM=m
|
||||
CONFIG_INPUT_QPNP_POWER_ON=m
|
||||
CONFIG_INPUT_QCOM_HV_HAPTICS=m
|
||||
CONFIG_NOP_USB_XCEIV=m
|
||||
CONFIG_USB_QCOM_EMU_PHY=m
|
||||
CONFIG_USB_XHCI_HCD=m
|
||||
CONFIG_USB_DWC3=m
|
||||
CONFIG_USB_DWC3_QCOM=m
|
||||
CONFIG_USB_DWC3_MSM=m
|
||||
CONFIG_USB_EHSET_TEST_FIXTURE=m
|
||||
CONFIG_USB_LINK_LAYER_TEST=m
|
||||
CONFIG_USB_CONFIGFS_NCM=m
|
||||
CONFIG_USB_CONFIGFS_F_DIAG=m
|
||||
CONFIG_USB_CONFIGFS_F_CCID=m
|
||||
CONFIG_USB_CONFIGFS_F_CDEV=m
|
||||
CONFIG_USB_CONFIGFS_F_GSI=m
|
||||
CONFIG_USB_CONFIGFS_MASS_STORAGE=m
|
||||
CONFIG_USB_STORAGE=m
|
||||
CONFIG_TYPEC=m
|
||||
CONFIG_TYPEC_UCSI=m
|
||||
CONFIG_UCSI_QTI_GLINK=m
|
||||
CONFIG_INTERCONNECT_QCOM=m
|
||||
CONFIG_INTERCONNECT_QCOM_LAHAINA=m
|
||||
CONFIG_PHY_QCOM_UFS=m
|
||||
CONFIG_PHY_QCOM_UFS_QRBTC_SDM845=m
|
||||
CONFIG_PHY_QCOM_UFS_V4=m
|
||||
CONFIG_SCSI_UFS_QCOM=m
|
||||
CONFIG_SCSI_UFS_BSG=y
|
||||
CONFIG_CHR_DEV_SG=m
|
||||
CONFIG_MSM_CORE_HANG_DETECT=m
|
||||
CONFIG_PANIC_ON_OOPS=y
|
||||
CONFIG_QCOM_LLCC=m
|
||||
CONFIG_QCOM_LAHAINA_LLCC=m
|
||||
CONFIG_QCOM_IPCC=m
|
||||
CONFIG_QCOM_WATCHDOG=m
|
||||
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
|
||||
CONFIG_QCOM_SCM=m
|
||||
CONFIG_QTEE_SHM_BRIDGE=y
|
||||
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
|
||||
CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL=y
|
||||
CONFIG_HWSPINLOCK_QCOM=m
|
||||
CONFIG_QCOM_GLINK_PKT=m
|
||||
CONFIG_QCOM_SMEM=m
|
||||
CONFIG_QCOM_SMP2P=m
|
||||
CONFIG_QCOM_SMSM=m
|
||||
CONFIG_MSM_QMP=m
|
||||
CONFIG_QCOM_SMP2P_SLEEPSTATE=m
|
||||
CONFIG_RPMSG_CHAR=m
|
||||
CONFIG_RPMSG_QCOM_GLINK_SMEM=m
|
||||
CONFIG_QCOM_GLINK=m
|
||||
CONFIG_MSM_GLINK_SSR=m
|
||||
CONFIG_QTI_PMIC_GLINK=m
|
||||
CONFIG_QTI_BATTERY_CHARGER=m
|
||||
CONFIG_QTI_BATTERY_GLINK_DEBUG=m
|
||||
CONFIG_QTI_ALTMODE_GLINK=m
|
||||
CONFIG_QRTR_MHI=m
|
||||
CONFIG_QSEE_IPC_IRQ_BRIDGE=m
|
||||
CONFIG_SENSORS_SSC=m
|
||||
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
|
||||
CONFIG_MSM_SUBSYSTEM_RESTART=m
|
||||
CONFIG_SETUP_SSR_NOTIF_TIMEOUTS=y
|
||||
CONFIG_SSR_SYSMON_NOTIF_TIMEOUT=20000
|
||||
CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT=20000
|
||||
CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT=y
|
||||
CONFIG_MSM_PIL_SSR_GENERIC=m
|
||||
CONFIG_MSM_SERVICE_LOCATOR=m
|
||||
CONFIG_MSM_SERVICE_NOTIFIER=m
|
||||
CONFIG_QSEE_IPC_IRQ=m
|
||||
CONFIG_RPMSG_QCOM_GLINK_SPSS=m
|
||||
CONFIG_REGULATOR_RPMH=m
|
||||
CONFIG_REGULATOR_FIXED_VOLTAGE=m
|
||||
CONFIG_REGULATOR_QCOM_PM8008=m
|
||||
CONFIG_MSM_GCC_LAHAINA=m
|
||||
CONFIG_REGULATOR_REFGEN=m
|
||||
CONFIG_MSM_VIDEOCC_LAHAINA=m
|
||||
CONFIG_MSM_DISPCC_LAHAINA=m
|
||||
CONFIG_COMMON_CLK_QCOM=m
|
||||
CONFIG_MSM_GPUCC_LAHAINA=m
|
||||
CONFIG_MSM_GLOBAL_SYNX=m
|
||||
CONFIG_QRTR=m
|
||||
CONFIG_QRTR_SMD=m
|
||||
CONFIG_USB_MSM_SSPHY_QMP=m
|
||||
CONFIG_MSM_HSUSB_PHY=m
|
||||
CONFIG_MSM_CAMCC_LAHAINA=m
|
||||
CONFIG_MSM_BT_POWER=m
|
||||
CONFIG_ARM_SMMU=m
|
||||
CONFIG_QTI_IOMMU_SUPPORT=m
|
||||
CONFIG_MSM_CLK_AOP_QMP=m
|
||||
CONFIG_MSM_SPSS_UTILS=m
|
||||
CONFIG_IPA3=m
|
||||
CONFIG_IPA_WDI_UNIFIED_API=y
|
||||
CONFIG_CNSS2=m
|
||||
CONFIG_CNSS2_QMI=y
|
||||
CONFIG_CNSS_ASYNC=y
|
||||
CONFIG_BUS_AUTO_SUSPEND=y
|
||||
CONFIG_CNSS_QCA6490=y
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_QCOM_SECURE_BUFFER=m
|
||||
CONFIG_ION_MSM_HEAPS=m
|
||||
CONFIG_QCOM_CLK_RPMH=m
|
||||
CONFIG_QCOM_LAZY_MAPPING=m
|
||||
CONFIG_MFD_SPMI_PMIC=m
|
||||
CONFIG_PWM_QTI_LPG=m
|
||||
CONFIG_INTERCONNECT_QCOM_EPSS_L3=m
|
||||
CONFIG_LEDS_CLASS_FLASH=m
|
||||
CONFIG_LEDS_QTI_FLASH=m
|
||||
CONFIG_LEDS_QTI_TRI_LED=m
|
||||
CONFIG_MSM_SPCOM=m
|
||||
CONFIG_MSM_ADSPRPC=m
|
||||
CONFIG_MSM_CDSP_LOADER=m
|
||||
CONFIG_UIO_MSM_SHAREDMEM=m
|
||||
CONFIG_QCOM_SOCINFO=m
|
||||
CONFIG_BTFM_SLIM=m
|
||||
CONFIG_VIRT_DRIVERS=y
|
||||
CONFIG_HAVEN_DRIVERS=y
|
||||
CONFIG_HH_MSGQ=m
|
||||
CONFIG_HH_RM_DRV=m
|
||||
CONFIG_HH_DBL=m
|
||||
CONFIG_HVC_HAVEN=m
|
||||
# CONFIG_HVC_HAVEN_CONSOLE is not set
|
||||
# CONFIG_CFI_PERMISSIVE is not set
|
||||
# CONFIG_SND_SOC_WCD9335 is not set
|
||||
# CONFIG_SLIM_QCOM_CTRL is not set
|
||||
# CONFIG_SLIM_QCOM_NGD_CTRL is not set
|
||||
# CONFIG_SLIMBUS_MSM_CTRL is not set
|
||||
# CONFIG_SLIMBUS_MSM_NGD is not set
|
||||
CONFIG_USB_ROLE_SWITCH=m
|
||||
CONFIG_MHI_BUS=m
|
||||
CONFIG_MHI_UCI=m
|
||||
# CONFIG_PCI_MSM is not set
|
||||
CONFIG_EXTCON_USB_GPIO=m
|
||||
CONFIG_PM_WAKELOCKS=y
|
||||
CONFIG_MMC_SDHCI_MSM=m
|
||||
# CONFIG_MSM_CVP is not set
|
||||
# CONFIG_QSEECOM is not set
|
||||
# CONFIG_POWER_RESET_MSM is not set
|
||||
# CONFIG_MSM_QBT_HANDLER is not set
|
||||
CONFIG_QCOM_COMMAND_DB=m
|
||||
CONFIG_QCOM_RPMH=m
|
||||
CONFIG_QCOM_RPMHPD=m
|
@ -145,7 +145,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *,
|
||||
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
|
||||
extern void flush_dcache_page(struct page *);
|
||||
|
||||
static inline void __flush_icache_all(void)
|
||||
static __always_inline void __flush_icache_all(void)
|
||||
{
|
||||
if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
|
||||
return;
|
||||
|
@ -64,6 +64,16 @@ static inline unsigned long local_daif_save(void)
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline void local_daif_unmask(void)
|
||||
{
|
||||
trace_hardirqs_on();
|
||||
asm volatile(
|
||||
"msr daifclr, #0xf // local_daif_unmask"
|
||||
:
|
||||
:
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void local_daif_restore(unsigned long flags)
|
||||
{
|
||||
bool irq_disabled = flags & PSR_I_BIT;
|
||||
|
223
arch/arm64/include/asm/debugv8.h
Normal file
223
arch/arm64/include/asm/debugv8.h
Normal file
@ -0,0 +1,223 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2014,2016-2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ASM_DEBUGV8_H
|
||||
#define __ASM_DEBUGV8_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* 32 bit register reads for aarch 64 bit */
|
||||
#define dbg_readl(reg) RSYSL_##reg()
|
||||
/* 64 bit register reads for aarch 64 bit */
|
||||
#define dbg_readq(reg) RSYSQ_##reg()
|
||||
/* 32 and 64 bit register writes for aarch 64 bit */
|
||||
#define dbg_write(val, reg) WSYS_##reg(val)
|
||||
|
||||
#define MRSL(reg) \
|
||||
({ \
|
||||
uint64_t val; \
|
||||
asm volatile("mrs %0, "#reg : "=r" (val)); \
|
||||
val; \
|
||||
})
|
||||
|
||||
#define MRSQ(reg) \
|
||||
({ \
|
||||
uint64_t val; \
|
||||
asm volatile("mrs %0, "#reg : "=r" (val)); \
|
||||
val; \
|
||||
})
|
||||
|
||||
#define MSR(val, reg) \
|
||||
({ \
|
||||
asm volatile("msr "#reg", %0" : : "r" (val)); \
|
||||
})
|
||||
|
||||
/*
|
||||
* Debug Feature Register
|
||||
*
|
||||
* Read only
|
||||
*/
|
||||
#define RSYSQ_ID_AA64DFR0_EL1() MRSQ(ID_AA64DFR0_EL1)
|
||||
|
||||
/*
|
||||
* Debug Registers
|
||||
*
|
||||
* Available only in DBGv8
|
||||
*
|
||||
* Read only
|
||||
* MDCCSR_EL0, MDRAR_EL1, OSLSR_EL1, DBGDTRRX_EL0, DBGAUTHSTATUS_EL1
|
||||
*
|
||||
* Write only
|
||||
* DBGDTRTX_EL0, OSLAR_EL1
|
||||
*/
|
||||
/* 32 bit registers */
|
||||
#define RSYSL_DBGDTRRX_EL0() MRSL(DBGDTRRX_EL0)
|
||||
#define RSYSL_MDCCSR_EL0() MRSL(MDCCSR_EL0)
|
||||
#define RSYSL_MDSCR_EL1() MRSL(MDSCR_EL1)
|
||||
#define RSYSL_OSDTRRX_EL1() MRSL(OSDTRRX_EL1)
|
||||
#define RSYSL_OSDTRTX_EL1() MRSL(OSDTRTX_EL1)
|
||||
#define RSYSL_OSDLR_EL1() MRSL(OSDLR_EL1)
|
||||
#define RSYSL_OSLSR_EL1() MRSL(OSLSR_EL1)
|
||||
#define RSYSL_MDCCINT_EL1() MRSL(MDCCINT_EL1)
|
||||
#define RSYSL_OSECCR_EL1() MRSL(OSECCR_EL1)
|
||||
#define RSYSL_DBGPRCR_EL1() MRSL(DBGPRCR_EL1)
|
||||
#define RSYSL_DBGBCR0_EL1() MRSL(DBGBCR0_EL1)
|
||||
#define RSYSL_DBGBCR1_EL1() MRSL(DBGBCR1_EL1)
|
||||
#define RSYSL_DBGBCR2_EL1() MRSL(DBGBCR2_EL1)
|
||||
#define RSYSL_DBGBCR3_EL1() MRSL(DBGBCR3_EL1)
|
||||
#define RSYSL_DBGBCR4_EL1() MRSL(DBGBCR4_EL1)
|
||||
#define RSYSL_DBGBCR5_EL1() MRSL(DBGBCR5_EL1)
|
||||
#define RSYSL_DBGBCR6_EL1() MRSL(DBGBCR6_EL1)
|
||||
#define RSYSL_DBGBCR7_EL1() MRSL(DBGBCR7_EL1)
|
||||
#define RSYSL_DBGBCR8_EL1() MRSL(DBGBCR8_EL1)
|
||||
#define RSYSL_DBGBCR9_EL1() MRSL(DBGBCR9_EL1)
|
||||
#define RSYSL_DBGBCR10_EL1() MRSL(DBGBCR10_EL1)
|
||||
#define RSYSL_DBGBCR11_EL1() MRSL(DBGBCR11_EL1)
|
||||
#define RSYSL_DBGBCR12_EL1() MRSL(DBGBCR12_EL1)
|
||||
#define RSYSL_DBGBCR13_EL1() MRSL(DBGBCR13_EL1)
|
||||
#define RSYSL_DBGBCR14_EL1() MRSL(DBGBCR14_EL1)
|
||||
#define RSYSL_DBGBCR15_EL1() MRSL(DBGBCR15_EL1)
|
||||
#define RSYSL_DBGWCR0_EL1() MRSL(DBGWCR0_EL1)
|
||||
#define RSYSL_DBGWCR1_EL1() MRSL(DBGWCR1_EL1)
|
||||
#define RSYSL_DBGWCR2_EL1() MRSL(DBGWCR2_EL1)
|
||||
#define RSYSL_DBGWCR3_EL1() MRSL(DBGWCR3_EL1)
|
||||
#define RSYSL_DBGWCR4_EL1() MRSL(DBGWCR4_EL1)
|
||||
#define RSYSL_DBGWCR5_EL1() MRSL(DBGWCR5_EL1)
|
||||
#define RSYSL_DBGWCR6_EL1() MRSL(DBGWCR6_EL1)
|
||||
#define RSYSL_DBGWCR7_EL1() MRSL(DBGWCR7_EL1)
|
||||
#define RSYSL_DBGWCR8_EL1() MRSL(DBGWCR8_EL1)
|
||||
#define RSYSL_DBGWCR9_EL1() MRSL(DBGWCR9_EL1)
|
||||
#define RSYSL_DBGWCR10_EL1() MRSL(DBGWCR10_EL1)
|
||||
#define RSYSL_DBGWCR11_EL1() MRSL(DBGWCR11_EL1)
|
||||
#define RSYSL_DBGWCR12_EL1() MRSL(DBGWCR12_EL1)
|
||||
#define RSYSL_DBGWCR13_EL1() MRSL(DBGWCR13_EL1)
|
||||
#define RSYSL_DBGWCR14_EL1() MRSL(DBGWCR14_EL1)
|
||||
#define RSYSL_DBGWCR15_EL1() MRSL(DBGWCR15_EL1)
|
||||
#define RSYSL_DBGCLAIMSET_EL1() MRSL(DBGCLAIMSET_EL1)
|
||||
#define RSYSL_DBGCLAIMCLR_EL1() MRSL(DBGCLAIMCLR_EL1)
|
||||
#define RSYSL_DBGAUTHSTATUS_EL1() MRSL(DBGAUTHSTATUS_EL1)
|
||||
#define RSYSL_DBGVCR32_EL2() MRSL(DBGVCR32_EL2)
|
||||
#define RSYSL_MDCR_EL2() MRSL(MDCR_EL2)
|
||||
#define RSYSL_MDCR_EL3() MRSL(MDCR_EL3)
|
||||
/* 64 bit registers */
|
||||
#define RSYSQ_DBGDTR_EL0() MRSQ(DBGDTR_EL0)
|
||||
#define RSYSQ_MDRAR_EL1() MRSQ(MDRAR_EL1)
|
||||
#define RSYSQ_DBGBVR0_EL1() MRSQ(DBGBVR0_EL1)
|
||||
#define RSYSQ_DBGBVR1_EL1() MRSQ(DBGBVR1_EL1)
|
||||
#define RSYSQ_DBGBVR2_EL1() MRSQ(DBGBVR2_EL1)
|
||||
#define RSYSQ_DBGBVR3_EL1() MRSQ(DBGBVR3_EL1)
|
||||
#define RSYSQ_DBGBVR4_EL1() MRSQ(DBGBVR4_EL1)
|
||||
#define RSYSQ_DBGBVR5_EL1() MRSQ(DBGBVR5_EL1)
|
||||
#define RSYSQ_DBGBVR6_EL1() MRSQ(DBGBVR6_EL1)
|
||||
#define RSYSQ_DBGBVR7_EL1() MRSQ(DBGBVR7_EL1)
|
||||
#define RSYSQ_DBGBVR8_EL1() MRSQ(DBGBVR8_EL1)
|
||||
#define RSYSQ_DBGBVR9_EL1() MRSQ(DBGBVR9_EL1)
|
||||
#define RSYSQ_DBGBVR10_EL1() MRSQ(DBGBVR10_EL1)
|
||||
#define RSYSQ_DBGBVR11_EL1() MRSQ(DBGBVR11_EL1)
|
||||
#define RSYSQ_DBGBVR12_EL1() MRSQ(DBGBVR12_EL1)
|
||||
#define RSYSQ_DBGBVR13_EL1() MRSQ(DBGBVR13_EL1)
|
||||
#define RSYSQ_DBGBVR14_EL1() MRSQ(DBGBVR14_EL1)
|
||||
#define RSYSQ_DBGBVR15_EL1() MRSQ(DBGBVR15_EL1)
|
||||
#define RSYSQ_DBGWVR0_EL1() MRSQ(DBGWVR0_EL1)
|
||||
#define RSYSQ_DBGWVR1_EL1() MRSQ(DBGWVR1_EL1)
|
||||
#define RSYSQ_DBGWVR2_EL1() MRSQ(DBGWVR2_EL1)
|
||||
#define RSYSQ_DBGWVR3_EL1() MRSQ(DBGWVR3_EL1)
|
||||
#define RSYSQ_DBGWVR4_EL1() MRSQ(DBGWVR4_EL1)
|
||||
#define RSYSQ_DBGWVR5_EL1() MRSQ(DBGWVR5_EL1)
|
||||
#define RSYSQ_DBGWVR6_EL1() MRSQ(DBGWVR6_EL1)
|
||||
#define RSYSQ_DBGWVR7_EL1() MRSQ(DBGWVR7_EL1)
|
||||
#define RSYSQ_DBGWVR8_EL1() MRSQ(DBGWVR8_EL1)
|
||||
#define RSYSQ_DBGWVR9_EL1() MRSQ(DBGWVR9_EL1)
|
||||
#define RSYSQ_DBGWVR10_EL1() MRSQ(DBGWVR10_EL1)
|
||||
#define RSYSQ_DBGWVR11_EL1() MRSQ(DBGWVR11_EL1)
|
||||
#define RSYSQ_DBGWVR12_EL1() MRSQ(DBGWVR12_EL1)
|
||||
#define RSYSQ_DBGWVR13_EL1() MRSQ(DBGWVR13_EL1)
|
||||
#define RSYSQ_DBGWVR14_EL1() MRSQ(DBGWVR14_EL1)
|
||||
#define RSYSQ_DBGWVR15_EL1() MRSQ(DBGWVR15_EL1)
|
||||
|
||||
/* 32 bit registers */
|
||||
#define WSYS_DBGDTRTX_EL0(val) MSR(val, DBGDTRTX_EL0)
|
||||
#define WSYS_MDCCINT_EL1(val) MSR(val, MDCCINT_EL1)
|
||||
#define WSYS_MDSCR_EL1(val) MSR(val, MDSCR_EL1)
|
||||
#define WSYS_OSDTRRX_EL1(val) MSR(val, OSDTRRX_EL1)
|
||||
#define WSYS_OSDTRTX_EL1(val) MSR(val, OSDTRTX_EL1)
|
||||
#define WSYS_OSDLR_EL1(val) MSR(val, OSDLR_EL1)
|
||||
#define WSYS_OSECCR_EL1(val) MSR(val, OSECCR_EL1)
|
||||
#define WSYS_DBGPRCR_EL1(val) MSR(val, DBGPRCR_EL1)
|
||||
#define WSYS_DBGBCR0_EL1(val) MSR(val, DBGBCR0_EL1)
|
||||
#define WSYS_DBGBCR1_EL1(val) MSR(val, DBGBCR1_EL1)
|
||||
#define WSYS_DBGBCR2_EL1(val) MSR(val, DBGBCR2_EL1)
|
||||
#define WSYS_DBGBCR3_EL1(val) MSR(val, DBGBCR3_EL1)
|
||||
#define WSYS_DBGBCR4_EL1(val) MSR(val, DBGBCR4_EL1)
|
||||
#define WSYS_DBGBCR5_EL1(val) MSR(val, DBGBCR5_EL1)
|
||||
#define WSYS_DBGBCR6_EL1(val) MSR(val, DBGBCR6_EL1)
|
||||
#define WSYS_DBGBCR7_EL1(val) MSR(val, DBGBCR7_EL1)
|
||||
#define WSYS_DBGBCR8_EL1(val) MSR(val, DBGBCR8_EL1)
|
||||
#define WSYS_DBGBCR9_EL1(val) MSR(val, DBGBCR9_EL1)
|
||||
#define WSYS_DBGBCR10_EL1(val) MSR(val, DBGBCR10_EL1)
|
||||
#define WSYS_DBGBCR11_EL1(val) MSR(val, DBGBCR11_EL1)
|
||||
#define WSYS_DBGBCR12_EL1(val) MSR(val, DBGBCR12_EL1)
|
||||
#define WSYS_DBGBCR13_EL1(val) MSR(val, DBGBCR13_EL1)
|
||||
#define WSYS_DBGBCR14_EL1(val) MSR(val, DBGBCR14_EL1)
|
||||
#define WSYS_DBGBCR15_EL1(val) MSR(val, DBGBCR15_EL1)
|
||||
#define WSYS_DBGWCR0_EL1(val) MSR(val, DBGWCR0_EL1)
|
||||
#define WSYS_DBGWCR1_EL1(val) MSR(val, DBGWCR1_EL1)
|
||||
#define WSYS_DBGWCR2_EL1(val) MSR(val, DBGWCR2_EL1)
|
||||
#define WSYS_DBGWCR3_EL1(val) MSR(val, DBGWCR3_EL1)
|
||||
#define WSYS_DBGWCR4_EL1(val) MSR(val, DBGWCR4_EL1)
|
||||
#define WSYS_DBGWCR5_EL1(val) MSR(val, DBGWCR5_EL1)
|
||||
#define WSYS_DBGWCR6_EL1(val) MSR(val, DBGWCR6_EL1)
|
||||
#define WSYS_DBGWCR7_EL1(val) MSR(val, DBGWCR7_EL1)
|
||||
#define WSYS_DBGWCR8_EL1(val) MSR(val, DBGWCR8_EL1)
|
||||
#define WSYS_DBGWCR9_EL1(val) MSR(val, DBGWCR9_EL1)
|
||||
#define WSYS_DBGWCR10_EL1(val) MSR(val, DBGWCR10_EL1)
|
||||
#define WSYS_DBGWCR11_EL1(val) MSR(val, DBGWCR11_EL1)
|
||||
#define WSYS_DBGWCR12_EL1(val) MSR(val, DBGWCR12_EL1)
|
||||
#define WSYS_DBGWCR13_EL1(val) MSR(val, DBGWCR13_EL1)
|
||||
#define WSYS_DBGWCR14_EL1(val) MSR(val, DBGWCR14_EL1)
|
||||
#define WSYS_DBGWCR15_EL1(val) MSR(val, DBGWCR15_EL1)
|
||||
#define WSYS_DBGCLAIMSET_EL1(val) MSR(val, DBGCLAIMSET_EL1)
|
||||
#define WSYS_DBGCLAIMCLR_EL1(val) MSR(val, DBGCLAIMCLR_EL1)
|
||||
#define WSYS_OSLAR_EL1(val) MSR(val, OSLAR_EL1)
|
||||
#define WSYS_DBGVCR32_EL2(val) MSR(val, DBGVCR32_EL2)
|
||||
#define WSYS_MDCR_EL2(val) MSR(val, MDCR_EL2)
|
||||
#define WSYS_MDCR_EL3(val) MSR(val, MDCR_EL3)
|
||||
/* 64 bit registers */
|
||||
#define WSYS_DBGDTR_EL0(val) MSR(val, DBGDTR_EL0)
|
||||
#define WSYS_DBGBVR0_EL1(val) MSR(val, DBGBVR0_EL1)
|
||||
#define WSYS_DBGBVR1_EL1(val) MSR(val, DBGBVR1_EL1)
|
||||
#define WSYS_DBGBVR2_EL1(val) MSR(val, DBGBVR2_EL1)
|
||||
#define WSYS_DBGBVR3_EL1(val) MSR(val, DBGBVR3_EL1)
|
||||
#define WSYS_DBGBVR4_EL1(val) MSR(val, DBGBVR4_EL1)
|
||||
#define WSYS_DBGBVR5_EL1(val) MSR(val, DBGBVR5_EL1)
|
||||
#define WSYS_DBGBVR6_EL1(val) MSR(val, DBGBVR6_EL1)
|
||||
#define WSYS_DBGBVR7_EL1(val) MSR(val, DBGBVR7_EL1)
|
||||
#define WSYS_DBGBVR8_EL1(val) MSR(val, DBGBVR8_EL1)
|
||||
#define WSYS_DBGBVR9_EL1(val) MSR(val, DBGBVR9_EL1)
|
||||
#define WSYS_DBGBVR10_EL1(val) MSR(val, DBGBVR10_EL1)
|
||||
#define WSYS_DBGBVR11_EL1(val) MSR(val, DBGBVR11_EL1)
|
||||
#define WSYS_DBGBVR12_EL1(val) MSR(val, DBGBVR12_EL1)
|
||||
#define WSYS_DBGBVR13_EL1(val) MSR(val, DBGBVR13_EL1)
|
||||
#define WSYS_DBGBVR14_EL1(val) MSR(val, DBGBVR14_EL1)
|
||||
#define WSYS_DBGBVR15_EL1(val) MSR(val, DBGBVR15_EL1)
|
||||
#define WSYS_DBGWVR0_EL1(val) MSR(val, DBGWVR0_EL1)
|
||||
#define WSYS_DBGWVR1_EL1(val) MSR(val, DBGWVR1_EL1)
|
||||
#define WSYS_DBGWVR2_EL1(val) MSR(val, DBGWVR2_EL1)
|
||||
#define WSYS_DBGWVR3_EL1(val) MSR(val, DBGWVR3_EL1)
|
||||
#define WSYS_DBGWVR4_EL1(val) MSR(val, DBGWVR4_EL1)
|
||||
#define WSYS_DBGWVR5_EL1(val) MSR(val, DBGWVR5_EL1)
|
||||
#define WSYS_DBGWVR6_EL1(val) MSR(val, DBGWVR6_EL1)
|
||||
#define WSYS_DBGWVR7_EL1(val) MSR(val, DBGWVR7_EL1)
|
||||
#define WSYS_DBGWVR8_EL1(val) MSR(val, DBGWVR8_EL1)
|
||||
#define WSYS_DBGWVR9_EL1(val) MSR(val, DBGWVR9_EL1)
|
||||
#define WSYS_DBGWVR10_EL1(val) MSR(val, DBGWVR10_EL1)
|
||||
#define WSYS_DBGWVR11_EL1(val) MSR(val, DBGWVR11_EL1)
|
||||
#define WSYS_DBGWVR12_EL1(val) MSR(val, DBGWVR12_EL1)
|
||||
#define WSYS_DBGWVR13_EL1(val) MSR(val, DBGWVR13_EL1)
|
||||
#define WSYS_DBGWVR14_EL1(val) MSR(val, DBGWVR14_EL1)
|
||||
#define WSYS_DBGWVR15_EL1(val) MSR(val, DBGWVR15_EL1)
|
||||
|
||||
#endif
|
379
arch/arm64/include/asm/etmv4x.h
Normal file
379
arch/arm64/include/asm/etmv4x.h
Normal file
@ -0,0 +1,379 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2015-2017, 2019 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __ASM_ETMV4X_H
|
||||
#define __ASM_ETMV4X_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* 32 bit register reads for AArch64 */
|
||||
#define trc_readl(reg) RSYSL_##reg()
|
||||
/* 64 bit register reads for AArch64 */
|
||||
#define trc_readq(reg) RSYSQ_##reg()
|
||||
/* 32 and 64 bit register writes for AArch64 */
|
||||
#define trc_write(val, reg) WSYS_##reg(val)
|
||||
|
||||
#define MRSL(op0, op1, crn, crm, op2) \
|
||||
({ \
|
||||
uint64_t val; \
|
||||
asm volatile("mrs %0, S"#op0"_"#op1"_"#crn"_"#crm"_"#op2 : "=r" (val)); \
|
||||
val; \
|
||||
})
|
||||
|
||||
#define MRSQ(op0, op1, crn, crm, op2) \
|
||||
({ \
|
||||
uint64_t val; \
|
||||
asm volatile("mrs %0, S"#op0"_"#op1"_"#crn"_"#crm"_"#op2 : "=r" (val)); \
|
||||
val; \
|
||||
})
|
||||
|
||||
#define MSR(val, op0, op1, crn, crm, op2) \
|
||||
({ \
|
||||
asm volatile("msr S"#op0"_"#op1"_"#crn"_"#crm"_"#op2", %0" : : "r" (val)); \
|
||||
})
|
||||
|
||||
/* Clock and Power Management Register */
|
||||
#define RSYSL_CPMR_EL1() MRSL(3, 7, c15, c0, 5)
|
||||
#define WSYS_CPMR_EL1(val) MSR(val, 3, 7, c15, c0, 5)
|
||||
|
||||
/*
|
||||
* ETMv4 Registers
|
||||
*
|
||||
* Read only
|
||||
* ETMAUTHSTATUS, ETMDEVARCH, ETMDEVID, ETMIDRn[0-13], ETMOSLSR, ETMSTATR
|
||||
*
|
||||
* Write only
|
||||
* ETMOSLAR
|
||||
*/
|
||||
/* 32 bit registers */
|
||||
#define RSYSL_ETMAUTHSTATUS() MRSL(2, 1, c7, c14, 6)
|
||||
#define RSYSL_ETMAUXCTLR() MRSL(2, 1, c0, c6, 0)
|
||||
#define RSYSL_ETMCCCTLR() MRSL(2, 1, c0, c14, 0)
|
||||
#define RSYSL_ETMCIDCCTLR0() MRSL(2, 1, c3, c0, 2)
|
||||
#define RSYSL_ETMCNTCTLR0() MRSL(2, 1, c0, c4, 5)
|
||||
#define RSYSL_ETMCNTCTLR1() MRSL(2, 1, c0, c5, 5)
|
||||
#define RSYSL_ETMCNTCTLR2() MRSL(2, 1, c0, c6, 5)
|
||||
#define RSYSL_ETMCNTCTLR3() MRSL(2, 1, c0, c7, 5)
|
||||
#define RSYSL_ETMCNTRLDVR0() MRSL(2, 1, c0, c0, 5)
|
||||
#define RSYSL_ETMCNTRLDVR1() MRSL(2, 1, c0, c1, 5)
|
||||
#define RSYSL_ETMCNTRLDVR2() MRSL(2, 1, c0, c2, 5)
|
||||
#define RSYSL_ETMCNTRLDVR3() MRSL(2, 1, c0, c3, 5)
|
||||
#define RSYSL_ETMCNTVR0() MRSL(2, 1, c0, c8, 5)
|
||||
#define RSYSL_ETMCNTVR1() MRSL(2, 1, c0, c9, 5)
|
||||
#define RSYSL_ETMCNTVR2() MRSL(2, 1, c0, c10, 5)
|
||||
#define RSYSL_ETMCNTVR3() MRSL(2, 1, c0, c11, 5)
|
||||
#define RSYSL_ETMCONFIGR() MRSL(2, 1, c0, c4, 0)
|
||||
#define RSYSL_ETMDEVARCH() MRSL(2, 1, c7, c15, 6)
|
||||
#define RSYSL_ETMDEVID() MRSL(2, 1, c7, c2, 7)
|
||||
#define RSYSL_ETMEVENTCTL0R() MRSL(2, 1, c0, c8, 0)
|
||||
#define RSYSL_ETMEVENTCTL1R() MRSL(2, 1, c0, c9, 0)
|
||||
#define RSYSL_ETMEXTINSELR() MRSL(2, 1, c0, c8, 4)
|
||||
#define RSYSL_ETMIDR0() MRSL(2, 1, c0, c8, 7)
|
||||
#define RSYSL_ETMIDR1() MRSL(2, 1, c0, c9, 7)
|
||||
#define RSYSL_ETMIDR10() MRSL(2, 1, c0, c2, 6)
|
||||
#define RSYSL_ETMIDR11() MRSL(2, 1, c0, c3, 6)
|
||||
#define RSYSL_ETMIDR12() MRSL(2, 1, c0, c4, 6)
|
||||
#define RSYSL_ETMIDR13() MRSL(2, 1, c0, c5, 6)
|
||||
#define RSYSL_ETMIDR2() MRSL(2, 1, c0, c10, 7)
|
||||
#define RSYSL_ETMIDR3() MRSL(2, 1, c0, c11, 7)
|
||||
#define RSYSL_ETMIDR4() MRSL(2, 1, c0, c12, 7)
|
||||
#define RSYSL_ETMIDR5() MRSL(2, 1, c0, c13, 7)
|
||||
#define RSYSL_ETMIDR6() MRSL(2, 1, c0, c14, 7)
|
||||
#define RSYSL_ETMIDR7() MRSL(2, 1, c0, c15, 7)
|
||||
#define RSYSL_ETMIDR8() MRSL(2, 1, c0, c0, 6)
|
||||
#define RSYSL_ETMIDR9() MRSL(2, 1, c0, c1, 6)
|
||||
#define RSYSL_ETMIMSPEC0() MRSL(2, 1, c0, c0, 7)
|
||||
#define RSYSL_ETMOSLSR() MRSL(2, 1, c1, c1, 4)
|
||||
#define RSYSL_ETMPRGCTLR() MRSL(2, 1, c0, c1, 0)
|
||||
#define RSYSL_ETMRSCTLR10() MRSL(2, 1, c1, c10, 0)
|
||||
#define RSYSL_ETMRSCTLR11() MRSL(2, 1, c1, c11, 0)
|
||||
#define RSYSL_ETMRSCTLR12() MRSL(2, 1, c1, c12, 0)
|
||||
#define RSYSL_ETMRSCTLR13() MRSL(2, 1, c1, c13, 0)
|
||||
#define RSYSL_ETMRSCTLR14() MRSL(2, 1, c1, c14, 0)
|
||||
#define RSYSL_ETMRSCTLR15() MRSL(2, 1, c1, c15, 0)
|
||||
#define RSYSL_ETMRSCTLR2() MRSL(2, 1, c1, c2, 0)
|
||||
#define RSYSL_ETMRSCTLR3() MRSL(2, 1, c1, c3, 0)
|
||||
#define RSYSL_ETMRSCTLR4() MRSL(2, 1, c1, c4, 0)
|
||||
#define RSYSL_ETMRSCTLR5() MRSL(2, 1, c1, c5, 0)
|
||||
#define RSYSL_ETMRSCTLR6() MRSL(2, 1, c1, c6, 0)
|
||||
#define RSYSL_ETMRSCTLR7() MRSL(2, 1, c1, c7, 0)
|
||||
#define RSYSL_ETMRSCTLR8() MRSL(2, 1, c1, c8, 0)
|
||||
#define RSYSL_ETMRSCTLR9() MRSL(2, 1, c1, c9, 0)
|
||||
#define RSYSL_ETMRSCTLR16() MRSL(2, 1, c1, c0, 1)
|
||||
#define RSYSL_ETMRSCTLR17() MRSL(2, 1, c1, c1, 1)
|
||||
#define RSYSL_ETMRSCTLR18() MRSL(2, 1, c1, c2, 1)
|
||||
#define RSYSL_ETMRSCTLR19() MRSL(2, 1, c1, c3, 1)
|
||||
#define RSYSL_ETMRSCTLR20() MRSL(2, 1, c1, c4, 1)
|
||||
#define RSYSL_ETMRSCTLR21() MRSL(2, 1, c1, c5, 1)
|
||||
#define RSYSL_ETMRSCTLR22() MRSL(2, 1, c1, c6, 1)
|
||||
#define RSYSL_ETMRSCTLR23() MRSL(2, 1, c1, c7, 1)
|
||||
#define RSYSL_ETMRSCTLR24() MRSL(2, 1, c1, c8, 1)
|
||||
#define RSYSL_ETMRSCTLR25() MRSL(2, 1, c1, c9, 1)
|
||||
#define RSYSL_ETMRSCTLR26() MRSL(2, 1, c1, c10, 1)
|
||||
#define RSYSL_ETMRSCTLR27() MRSL(2, 1, c1, c11, 1)
|
||||
#define RSYSL_ETMRSCTLR28() MRSL(2, 1, c1, c12, 1)
|
||||
#define RSYSL_ETMRSCTLR29() MRSL(2, 1, c1, c13, 1)
|
||||
#define RSYSL_ETMRSCTLR30() MRSL(2, 1, c1, c14, 1)
|
||||
#define RSYSL_ETMRSCTLR31() MRSL(2, 1, c1, c15, 1)
|
||||
#define RSYSL_ETMSEQEVR0() MRSL(2, 1, c0, c0, 4)
|
||||
#define RSYSL_ETMSEQEVR1() MRSL(2, 1, c0, c1, 4)
|
||||
#define RSYSL_ETMSEQEVR2() MRSL(2, 1, c0, c2, 4)
|
||||
#define RSYSL_ETMSEQRSTEVR() MRSL(2, 1, c0, c6, 4)
|
||||
#define RSYSL_ETMSEQSTR() MRSL(2, 1, c0, c7, 4)
|
||||
#define RSYSL_ETMSTALLCTLR() MRSL(2, 1, c0, c11, 0)
|
||||
#define RSYSL_ETMSTATR() MRSL(2, 1, c0, c3, 0)
|
||||
#define RSYSL_ETMSYNCPR() MRSL(2, 1, c0, c13, 0)
|
||||
#define RSYSL_ETMTRACEIDR() MRSL(2, 1, c0, c0, 1)
|
||||
#define RSYSL_ETMTSCTLR() MRSL(2, 1, c0, c12, 0)
|
||||
#define RSYSL_ETMVICTLR() MRSL(2, 1, c0, c0, 2)
|
||||
#define RSYSL_ETMVIIECTLR() MRSL(2, 1, c0, c1, 2)
|
||||
#define RSYSL_ETMVISSCTLR() MRSL(2, 1, c0, c2, 2)
|
||||
#define RSYSL_ETMSSCCR0() MRSL(2, 1, c1, c0, 2)
|
||||
#define RSYSL_ETMSSCCR1() MRSL(2, 1, c1, c1, 2)
|
||||
#define RSYSL_ETMSSCCR2() MRSL(2, 1, c1, c2, 2)
|
||||
#define RSYSL_ETMSSCCR3() MRSL(2, 1, c1, c3, 2)
|
||||
#define RSYSL_ETMSSCCR4() MRSL(2, 1, c1, c4, 2)
|
||||
#define RSYSL_ETMSSCCR5() MRSL(2, 1, c1, c5, 2)
|
||||
#define RSYSL_ETMSSCCR6() MRSL(2, 1, c1, c6, 2)
|
||||
#define RSYSL_ETMSSCCR7() MRSL(2, 1, c1, c7, 2)
|
||||
#define RSYSL_ETMSSCSR0() MRSL(2, 1, c1, c8, 2)
|
||||
#define RSYSL_ETMSSCSR1() MRSL(2, 1, c1, c9, 2)
|
||||
#define RSYSL_ETMSSCSR2() MRSL(2, 1, c1, c10, 2)
|
||||
#define RSYSL_ETMSSCSR3() MRSL(2, 1, c1, c11, 2)
|
||||
#define RSYSL_ETMSSCSR4() MRSL(2, 1, c1, c12, 2)
|
||||
#define RSYSL_ETMSSCSR5() MRSL(2, 1, c1, c13, 2)
|
||||
#define RSYSL_ETMSSCSR6() MRSL(2, 1, c1, c14, 2)
|
||||
#define RSYSL_ETMSSCSR7() MRSL(2, 1, c1, c15, 2)
|
||||
#define RSYSL_ETMSSPCICR0() MRSL(2, 1, c1, c0, 3)
|
||||
#define RSYSL_ETMSSPCICR1() MRSL(2, 1, c1, c1, 3)
|
||||
#define RSYSL_ETMSSPCICR2() MRSL(2, 1, c1, c2, 3)
|
||||
#define RSYSL_ETMSSPCICR3() MRSL(2, 1, c1, c3, 3)
|
||||
#define RSYSL_ETMSSPCICR4() MRSL(2, 1, c1, c4, 3)
|
||||
#define RSYSL_ETMSSPCICR5() MRSL(2, 1, c1, c5, 3)
|
||||
#define RSYSL_ETMSSPCICR6() MRSL(2, 1, c1, c6, 3)
|
||||
#define RSYSL_ETMSSPCICR7() MRSL(2, 1, c1, c7, 3)
|
||||
|
||||
/* 64 bit registers */
|
||||
#define RSYSQ_ETMACATR0() MRSQ(2, 1, c2, c0, 2)
|
||||
#define RSYSQ_ETMACATR1() MRSQ(2, 1, c2, c2, 2)
|
||||
#define RSYSQ_ETMACATR2() MRSQ(2, 1, c2, c4, 2)
|
||||
#define RSYSQ_ETMACATR3() MRSQ(2, 1, c2, c6, 2)
|
||||
#define RSYSQ_ETMACATR4() MRSQ(2, 1, c2, c8, 2)
|
||||
#define RSYSQ_ETMACATR5() MRSQ(2, 1, c2, c10, 2)
|
||||
#define RSYSQ_ETMACATR6() MRSQ(2, 1, c2, c12, 2)
|
||||
#define RSYSQ_ETMACATR7() MRSQ(2, 1, c2, c14, 2)
|
||||
#define RSYSQ_ETMACATR8() MRSQ(2, 1, c2, c0, 3)
|
||||
#define RSYSQ_ETMACATR9() MRSQ(2, 1, c2, c2, 3)
|
||||
#define RSYSQ_ETMACATR10() MRSQ(2, 1, c2, c4, 3)
|
||||
#define RSYSQ_ETMACATR11() MRSQ(2, 1, c2, c6, 3)
|
||||
#define RSYSQ_ETMACATR12() MRSQ(2, 1, c2, c8, 3)
|
||||
#define RSYSQ_ETMACATR13() MRSQ(2, 1, c2, c10, 3)
|
||||
#define RSYSQ_ETMACATR14() MRSQ(2, 1, c2, c12, 3)
|
||||
#define RSYSQ_ETMACATR15() MRSQ(2, 1, c2, c14, 3)
|
||||
#define RSYSQ_ETMCIDCVR0() MRSQ(2, 1, c3, c0, 0)
|
||||
#define RSYSQ_ETMCIDCVR1() MRSQ(2, 1, c3, c2, 0)
|
||||
#define RSYSQ_ETMCIDCVR2() MRSQ(2, 1, c3, c4, 0)
|
||||
#define RSYSQ_ETMCIDCVR3() MRSQ(2, 1, c3, c6, 0)
|
||||
#define RSYSQ_ETMCIDCVR4() MRSQ(2, 1, c3, c8, 0)
|
||||
#define RSYSQ_ETMCIDCVR5() MRSQ(2, 1, c3, c10, 0)
|
||||
#define RSYSQ_ETMCIDCVR6() MRSQ(2, 1, c3, c12, 0)
|
||||
#define RSYSQ_ETMCIDCVR7() MRSQ(2, 1, c3, c14, 0)
|
||||
#define RSYSQ_ETMACVR0() MRSQ(2, 1, c2, c0, 0)
|
||||
#define RSYSQ_ETMACVR1() MRSQ(2, 1, c2, c2, 0)
|
||||
#define RSYSQ_ETMACVR2() MRSQ(2, 1, c2, c4, 0)
|
||||
#define RSYSQ_ETMACVR3() MRSQ(2, 1, c2, c6, 0)
|
||||
#define RSYSQ_ETMACVR4() MRSQ(2, 1, c2, c8, 0)
|
||||
#define RSYSQ_ETMACVR5() MRSQ(2, 1, c2, c10, 0)
|
||||
#define RSYSQ_ETMACVR6() MRSQ(2, 1, c2, c12, 0)
|
||||
#define RSYSQ_ETMACVR7() MRSQ(2, 1, c2, c14, 0)
|
||||
#define RSYSQ_ETMACVR8() MRSQ(2, 1, c2, c0, 1)
|
||||
#define RSYSQ_ETMACVR9() MRSQ(2, 1, c2, c2, 1)
|
||||
#define RSYSQ_ETMACVR10() MRSQ(2, 1, c2, c4, 1)
|
||||
#define RSYSQ_ETMACVR11() MRSQ(2, 1, c2, c6, 1)
|
||||
#define RSYSQ_ETMACVR12() MRSQ(2, 1, c2, c8, 1)
|
||||
#define RSYSQ_ETMACVR13() MRSQ(2, 1, c2, c10, 1)
|
||||
#define RSYSQ_ETMACVR14() MRSQ(2, 1, c2, c12, 1)
|
||||
#define RSYSQ_ETMACVR15() MRSQ(2, 1, c2, c14, 1)
|
||||
#define RSYSQ_ETMVMIDCVR0() MRSQ(2, 1, c3, c0, 1)
|
||||
#define RSYSQ_ETMVMIDCVR1() MRSQ(2, 1, c3, c2, 1)
|
||||
#define RSYSQ_ETMVMIDCVR2() MRSQ(2, 1, c3, c4, 1)
|
||||
#define RSYSQ_ETMVMIDCVR3() MRSQ(2, 1, c3, c6, 1)
|
||||
#define RSYSQ_ETMVMIDCVR4() MRSQ(2, 1, c3, c8, 1)
|
||||
#define RSYSQ_ETMVMIDCVR5() MRSQ(2, 1, c3, c10, 1)
|
||||
#define RSYSQ_ETMVMIDCVR6() MRSQ(2, 1, c3, c12, 1)
|
||||
#define RSYSQ_ETMVMIDCVR7() MRSQ(2, 1, c3, c14, 1)
|
||||
#define RSYSQ_ETMDVCVR0() MRSQ(2, 1, c2, c0, 4)
|
||||
#define RSYSQ_ETMDVCVR1() MRSQ(2, 1, c2, c4, 4)
|
||||
#define RSYSQ_ETMDVCVR2() MRSQ(2, 1, c2, c8, 4)
|
||||
#define RSYSQ_ETMDVCVR3() MRSQ(2, 1, c2, c12, 4)
|
||||
#define RSYSQ_ETMDVCVR4() MRSQ(2, 1, c2, c0, 5)
|
||||
#define RSYSQ_ETMDVCVR5() MRSQ(2, 1, c2, c4, 5)
|
||||
#define RSYSQ_ETMDVCVR6() MRSQ(2, 1, c2, c8, 5)
|
||||
#define RSYSQ_ETMDVCVR7() MRSQ(2, 1, c2, c12, 5)
|
||||
#define RSYSQ_ETMDVCMR0() MRSQ(2, 1, c2, c0, 6)
|
||||
#define RSYSQ_ETMDVCMR1() MRSQ(2, 1, c2, c4, 6)
|
||||
#define RSYSQ_ETMDVCMR2() MRSQ(2, 1, c2, c8, 6)
|
||||
#define RSYSQ_ETMDVCMR3() MRSQ(2, 1, c2, c12, 6)
|
||||
#define RSYSQ_ETMDVCMR4() MRSQ(2, 1, c2, c0, 7)
|
||||
#define RSYSQ_ETMDVCMR5() MRSQ(2, 1, c2, c4, 7)
|
||||
#define RSYSQ_ETMDVCMR6() MRSQ(2, 1, c2, c8, 7)
|
||||
#define RSYSQ_ETMDVCMR7() MRSQ(2, 1, c2, c12, 7)
|
||||
|
||||
/* 32 and 64 bit registers */
|
||||
#define WSYS_ETMAUXCTLR(val) MSR(val, 2, 1, c0, c6, 0)
|
||||
#define WSYS_ETMACATR0(val) MSR(val, 2, 1, c2, c0, 2)
|
||||
#define WSYS_ETMACATR1(val) MSR(val, 2, 1, c2, c2, 2)
|
||||
#define WSYS_ETMACATR2(val) MSR(val, 2, 1, c2, c4, 2)
|
||||
#define WSYS_ETMACATR3(val) MSR(val, 2, 1, c2, c6, 2)
|
||||
#define WSYS_ETMACATR4(val) MSR(val, 2, 1, c2, c8, 2)
|
||||
#define WSYS_ETMACATR5(val) MSR(val, 2, 1, c2, c10, 2)
|
||||
#define WSYS_ETMACATR6(val) MSR(val, 2, 1, c2, c12, 2)
|
||||
#define WSYS_ETMACATR7(val) MSR(val, 2, 1, c2, c14, 2)
|
||||
#define WSYS_ETMACATR8(val) MSR(val, 2, 1, c2, c0, 3)
|
||||
#define WSYS_ETMACATR9(val) MSR(val, 2, 1, c2, c2, 3)
|
||||
#define WSYS_ETMACATR10(val) MSR(val, 2, 1, c2, c4, 3)
|
||||
#define WSYS_ETMACATR11(val) MSR(val, 2, 1, c2, c6, 3)
|
||||
#define WSYS_ETMACATR12(val) MSR(val, 2, 1, c2, c8, 3)
|
||||
#define WSYS_ETMACATR13(val) MSR(val, 2, 1, c2, c10, 3)
|
||||
#define WSYS_ETMACATR14(val) MSR(val, 2, 1, c2, c12, 3)
|
||||
#define WSYS_ETMACATR15(val) MSR(val, 2, 1, c2, c14, 3)
|
||||
#define WSYS_ETMACVR0(val) MSR(val, 2, 1, c2, c0, 0)
|
||||
#define WSYS_ETMACVR1(val) MSR(val, 2, 1, c2, c2, 0)
|
||||
#define WSYS_ETMACVR2(val) MSR(val, 2, 1, c2, c4, 0)
|
||||
#define WSYS_ETMACVR3(val) MSR(val, 2, 1, c2, c6, 0)
|
||||
#define WSYS_ETMACVR4(val) MSR(val, 2, 1, c2, c8, 0)
|
||||
#define WSYS_ETMACVR5(val) MSR(val, 2, 1, c2, c10, 0)
|
||||
#define WSYS_ETMACVR6(val) MSR(val, 2, 1, c2, c12, 0)
|
||||
#define WSYS_ETMACVR7(val) MSR(val, 2, 1, c2, c14, 0)
|
||||
#define WSYS_ETMACVR8(val) MSR(val, 2, 1, c2, c0, 1)
|
||||
#define WSYS_ETMACVR9(val) MSR(val, 2, 1, c2, c2, 1)
|
||||
#define WSYS_ETMACVR10(val) MSR(val, 2, 1, c2, c4, 1)
|
||||
#define WSYS_ETMACVR11(val) MSR(val, 2, 1, c2, c6, 1)
|
||||
#define WSYS_ETMACVR12(val) MSR(val, 2, 1, c2, c8, 1)
|
||||
#define WSYS_ETMACVR13(val) MSR(val, 2, 1, c2, c10, 1)
|
||||
#define WSYS_ETMACVR14(val) MSR(val, 2, 1, c2, c12, 1)
|
||||
#define WSYS_ETMACVR15(val) MSR(val, 2, 1, c2, c14, 1)
|
||||
#define WSYS_ETMCCCTLR(val) MSR(val, 2, 1, c0, c14, 0)
|
||||
#define WSYS_ETMCIDCCTLR0(val) MSR(val, 2, 1, c3, c0, 2)
|
||||
#define WSYS_ETMCIDCVR0(val) MSR(val, 2, 1, c3, c0, 0)
|
||||
#define WSYS_ETMCIDCVR1(val) MSR(val, 2, 1, c3, c2, 0)
|
||||
#define WSYS_ETMCIDCVR2(val) MSR(val, 2, 1, c3, c4, 0)
|
||||
#define WSYS_ETMCIDCVR3(val) MSR(val, 2, 1, c3, c6, 0)
|
||||
#define WSYS_ETMCIDCVR4(val) MSR(val, 2, 1, c3, c8, 0)
|
||||
#define WSYS_ETMCIDCVR5(val) MSR(val, 2, 1, c3, c10, 0)
|
||||
#define WSYS_ETMCIDCVR6(val) MSR(val, 2, 1, c3, c12, 0)
|
||||
#define WSYS_ETMCIDCVR7(val) MSR(val, 2, 1, c3, c14, 0)
|
||||
#define WSYS_ETMCNTCTLR0(val) MSR(val, 2, 1, c0, c4, 5)
|
||||
#define WSYS_ETMCNTCTLR1(val) MSR(val, 2, 1, c0, c5, 5)
|
||||
#define WSYS_ETMCNTCTLR2(val) MSR(val, 2, 1, c0, c6, 5)
|
||||
#define WSYS_ETMCNTCTLR3(val) MSR(val, 2, 1, c0, c7, 5)
|
||||
#define WSYS_ETMCNTRLDVR0(val) MSR(val, 2, 1, c0, c0, 5)
|
||||
#define WSYS_ETMCNTRLDVR1(val) MSR(val, 2, 1, c0, c1, 5)
|
||||
#define WSYS_ETMCNTRLDVR2(val) MSR(val, 2, 1, c0, c2, 5)
|
||||
#define WSYS_ETMCNTRLDVR3(val) MSR(val, 2, 1, c0, c3, 5)
|
||||
#define WSYS_ETMCNTVR0(val) MSR(val, 2, 1, c0, c8, 5)
|
||||
#define WSYS_ETMCNTVR1(val) MSR(val, 2, 1, c0, c9, 5)
|
||||
#define WSYS_ETMCNTVR2(val) MSR(val, 2, 1, c0, c10, 5)
|
||||
#define WSYS_ETMCNTVR3(val) MSR(val, 2, 1, c0, c11, 5)
|
||||
#define WSYS_ETMCONFIGR(val) MSR(val, 2, 1, c0, c4, 0)
|
||||
#define WSYS_ETMEVENTCTL0R(val) MSR(val, 2, 1, c0, c8, 0)
|
||||
#define WSYS_ETMEVENTCTL1R(val) MSR(val, 2, 1, c0, c9, 0)
|
||||
#define WSYS_ETMEXTINSELR(val) MSR(val, 2, 1, c0, c8, 4)
|
||||
#define WSYS_ETMIMSPEC0(val) MSR(val, 2, 1, c0, c0, 7)
|
||||
#define WSYS_ETMOSLAR(val) MSR(val, 2, 1, c1, c0, 4)
|
||||
#define WSYS_ETMPRGCTLR(val) MSR(val, 2, 1, c0, c1, 0)
|
||||
#define WSYS_ETMRSCTLR10(val) MSR(val, 2, 1, c1, c10, 0)
|
||||
#define WSYS_ETMRSCTLR11(val) MSR(val, 2, 1, c1, c11, 0)
|
||||
#define WSYS_ETMRSCTLR12(val) MSR(val, 2, 1, c1, c12, 0)
|
||||
#define WSYS_ETMRSCTLR13(val) MSR(val, 2, 1, c1, c13, 0)
|
||||
#define WSYS_ETMRSCTLR14(val) MSR(val, 2, 1, c1, c14, 0)
|
||||
#define WSYS_ETMRSCTLR15(val) MSR(val, 2, 1, c1, c15, 0)
|
||||
#define WSYS_ETMRSCTLR2(val) MSR(val, 2, 1, c1, c2, 0)
|
||||
#define WSYS_ETMRSCTLR3(val) MSR(val, 2, 1, c1, c3, 0)
|
||||
#define WSYS_ETMRSCTLR4(val) MSR(val, 2, 1, c1, c4, 0)
|
||||
#define WSYS_ETMRSCTLR5(val) MSR(val, 2, 1, c1, c5, 0)
|
||||
#define WSYS_ETMRSCTLR6(val) MSR(val, 2, 1, c1, c6, 0)
|
||||
#define WSYS_ETMRSCTLR7(val) MSR(val, 2, 1, c1, c7, 0)
|
||||
#define WSYS_ETMRSCTLR8(val) MSR(val, 2, 1, c1, c8, 0)
|
||||
#define WSYS_ETMRSCTLR9(val) MSR(val, 2, 1, c1, c9, 0)
|
||||
#define WSYS_ETMRSCTLR16(val) MSR(val, 2, 1, c1, c0, 1)
|
||||
#define WSYS_ETMRSCTLR17(val) MSR(val, 2, 1, c1, c1, 1)
|
||||
#define WSYS_ETMRSCTLR18(val) MSR(val, 2, 1, c1, c2, 1)
|
||||
#define WSYS_ETMRSCTLR19(val) MSR(val, 2, 1, c1, c3, 1)
|
||||
#define WSYS_ETMRSCTLR20(val) MSR(val, 2, 1, c1, c4, 1)
|
||||
#define WSYS_ETMRSCTLR21(val) MSR(val, 2, 1, c1, c5, 1)
|
||||
#define WSYS_ETMRSCTLR22(val) MSR(val, 2, 1, c1, c6, 1)
|
||||
#define WSYS_ETMRSCTLR23(val) MSR(val, 2, 1, c1, c7, 1)
|
||||
#define WSYS_ETMRSCTLR24(val) MSR(val, 2, 1, c1, c8, 1)
|
||||
#define WSYS_ETMRSCTLR25(val) MSR(val, 2, 1, c1, c9, 1)
|
||||
#define WSYS_ETMRSCTLR26(val) MSR(val, 2, 1, c1, c10, 1)
|
||||
#define WSYS_ETMRSCTLR27(val) MSR(val, 2, 1, c1, c11, 1)
|
||||
#define WSYS_ETMRSCTLR28(val) MSR(val, 2, 1, c1, c12, 1)
|
||||
#define WSYS_ETMRSCTLR29(val) MSR(val, 2, 1, c1, c13, 1)
|
||||
#define WSYS_ETMRSCTLR30(val) MSR(val, 2, 1, c1, c14, 1)
|
||||
#define WSYS_ETMRSCTLR31(val) MSR(val, 2, 1, c1, c15, 1)
|
||||
#define WSYS_ETMSEQEVR0(val) MSR(val, 2, 1, c0, c0, 4)
|
||||
#define WSYS_ETMSEQEVR1(val) MSR(val, 2, 1, c0, c1, 4)
|
||||
#define WSYS_ETMSEQEVR2(val) MSR(val, 2, 1, c0, c2, 4)
|
||||
#define WSYS_ETMSEQRSTEVR(val) MSR(val, 2, 1, c0, c6, 4)
|
||||
#define WSYS_ETMSEQSTR(val) MSR(val, 2, 1, c0, c7, 4)
|
||||
#define WSYS_ETMSTALLCTLR(val) MSR(val, 2, 1, c0, c11, 0)
|
||||
#define WSYS_ETMSYNCPR(val) MSR(val, 2, 1, c0, c13, 0)
|
||||
#define WSYS_ETMTRACEIDR(val) MSR(val, 2, 1, c0, c0, 1)
|
||||
#define WSYS_ETMTSCTLR(val) MSR(val, 2, 1, c0, c12, 0)
|
||||
#define WSYS_ETMVICTLR(val) MSR(val, 2, 1, c0, c0, 2)
|
||||
#define WSYS_ETMVIIECTLR(val) MSR(val, 2, 1, c0, c1, 2)
|
||||
#define WSYS_ETMVISSCTLR(val) MSR(val, 2, 1, c0, c2, 2)
|
||||
#define WSYS_ETMVMIDCVR0(val) MSR(val, 2, 1, c3, c0, 1)
|
||||
#define WSYS_ETMVMIDCVR1(val) MSR(val, 2, 1, c3, c2, 1)
|
||||
#define WSYS_ETMVMIDCVR2(val) MSR(val, 2, 1, c3, c4, 1)
|
||||
#define WSYS_ETMVMIDCVR3(val) MSR(val, 2, 1, c3, c6, 1)
|
||||
#define WSYS_ETMVMIDCVR4(val) MSR(val, 2, 1, c3, c8, 1)
|
||||
#define WSYS_ETMVMIDCVR5(val) MSR(val, 2, 1, c3, c10, 1)
|
||||
#define WSYS_ETMVMIDCVR6(val) MSR(val, 2, 1, c3, c12, 1)
|
||||
#define WSYS_ETMVMIDCVR7(val) MSR(val, 2, 1, c3, c14, 1)
|
||||
#define WSYS_ETMDVCVR0(val) MSR(val, 2, 1, c2, c0, 4)
|
||||
#define WSYS_ETMDVCVR1(val) MSR(val, 2, 1, c2, c4, 4)
|
||||
#define WSYS_ETMDVCVR2(val) MSR(val, 2, 1, c2, c8, 4)
|
||||
#define WSYS_ETMDVCVR3(val) MSR(val, 2, 1, c2, c12, 4)
|
||||
#define WSYS_ETMDVCVR4(val) MSR(val, 2, 1, c2, c0, 5)
|
||||
#define WSYS_ETMDVCVR5(val) MSR(val, 2, 1, c2, c4, 5)
|
||||
#define WSYS_ETMDVCVR6(val) MSR(val, 2, 1, c2, c8, 5)
|
||||
#define WSYS_ETMDVCVR7(val) MSR(val, 2, 1, c2, c12, 5)
|
||||
#define WSYS_ETMDVCMR0(val) MSR(val, 2, 1, c2, c0, 6)
|
||||
#define WSYS_ETMDVCMR1(val) MSR(val, 2, 1, c2, c4, 6)
|
||||
#define WSYS_ETMDVCMR2(val) MSR(val, 2, 1, c2, c8, 6)
|
||||
#define WSYS_ETMDVCMR3(val) MSR(val, 2, 1, c2, c12, 6)
|
||||
#define WSYS_ETMDVCMR4(val) MSR(val, 2, 1, c2, c0, 7)
|
||||
#define WSYS_ETMDVCMR5(val) MSR(val, 2, 1, c2, c4, 7)
|
||||
#define WSYS_ETMDVCMR6(val) MSR(val, 2, 1, c2, c8, 7)
|
||||
#define WSYS_ETMDVCMR7(val) MSR(val, 2, 1, c2, c12, 7)
|
||||
#define WSYS_ETMSSCCR0(val) MSR(val, 2, 1, c1, c0, 2)
|
||||
#define WSYS_ETMSSCCR1(val) MSR(val, 2, 1, c1, c1, 2)
|
||||
#define WSYS_ETMSSCCR2(val) MSR(val, 2, 1, c1, c2, 2)
|
||||
#define WSYS_ETMSSCCR3(val) MSR(val, 2, 1, c1, c3, 2)
|
||||
#define WSYS_ETMSSCCR4(val) MSR(val, 2, 1, c1, c4, 2)
|
||||
#define WSYS_ETMSSCCR5(val) MSR(val, 2, 1, c1, c5, 2)
|
||||
#define WSYS_ETMSSCCR6(val) MSR(val, 2, 1, c1, c6, 2)
|
||||
#define WSYS_ETMSSCCR7(val) MSR(val, 2, 1, c1, c7, 2)
|
||||
#define WSYS_ETMSSCSR0(val) MSR(val, 2, 1, c1, c8, 2)
|
||||
#define WSYS_ETMSSCSR1(val) MSR(val, 2, 1, c1, c9, 2)
|
||||
#define WSYS_ETMSSCSR2(val) MSR(val, 2, 1, c1, c10, 2)
|
||||
#define WSYS_ETMSSCSR3(val) MSR(val, 2, 1, c1, c11, 2)
|
||||
#define WSYS_ETMSSCSR4(val) MSR(val, 2, 1, c1, c12, 2)
|
||||
#define WSYS_ETMSSCSR5(val) MSR(val, 2, 1, c1, c13, 2)
|
||||
#define WSYS_ETMSSCSR6(val) MSR(val, 2, 1, c1, c14, 2)
|
||||
#define WSYS_ETMSSCSR7(val) MSR(val, 2, 1, c1, c15, 2)
|
||||
#define WSYS_ETMSSPCICR0(val) MSR(val, 2, 1, c1, c0, 3)
|
||||
#define WSYS_ETMSSPCICR1(val) MSR(val, 2, 1, c1, c1, 3)
|
||||
#define WSYS_ETMSSPCICR2(val) MSR(val, 2, 1, c1, c2, 3)
|
||||
#define WSYS_ETMSSPCICR3(val) MSR(val, 2, 1, c1, c3, 3)
|
||||
#define WSYS_ETMSSPCICR4(val) MSR(val, 2, 1, c1, c4, 3)
|
||||
#define WSYS_ETMSSPCICR5(val) MSR(val, 2, 1, c1, c5, 3)
|
||||
#define WSYS_ETMSSPCICR6(val) MSR(val, 2, 1, c1, c6, 3)
|
||||
#define WSYS_ETMSSPCICR7(val) MSR(val, 2, 1, c1, c7, 3)
|
||||
|
||||
#endif
|
57
arch/arm64/include/asm/haven/hcall.h
Normal file
57
arch/arm64/include/asm/haven/hcall.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#ifndef __ASM_HH_HCALL_H
|
||||
#define __ASM_HH_HCALL_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/haven/hcall_common.h>
|
||||
|
||||
/**
|
||||
* _hh_hcall: Performs an AArch64-specific call into hypervisor using Haven ABI
|
||||
* @hcall_num: Hypercall function ID to invoke
|
||||
* @args: Hypercall argument registers
|
||||
* @resp: Pointer to location to store response
|
||||
*/
|
||||
static inline int _hh_hcall(const hh_hcall_fnid_t hcall_num,
|
||||
const struct hh_hcall_args args,
|
||||
struct hh_hcall_resp *resp)
|
||||
{
|
||||
uint64_t _x18;
|
||||
|
||||
register uint64_t _x0 asm("x0") = args.arg0;
|
||||
register uint64_t _x1 asm("x1") = args.arg1;
|
||||
register uint64_t _x2 asm("x2") = args.arg2;
|
||||
register uint64_t _x3 asm("x3") = args.arg3;
|
||||
register uint64_t _x4 asm("x4") = args.arg4;
|
||||
register uint64_t _x5 asm("x5") = args.arg5;
|
||||
register uint64_t _x6 asm("x6") = args.arg6;
|
||||
register uint64_t _x7 asm("x7") = args.arg7;
|
||||
|
||||
asm volatile (
|
||||
"str x18, [%[_x18]]\n"
|
||||
"hvc %[num]\n"
|
||||
"ldr x18, [%[_x18]]\n"
|
||||
"str xzr, [%[_x18]]\n"
|
||||
: "+r"(_x0), "+r"(_x1), "+r"(_x2), "+r"(_x3), "+r"(_x4),
|
||||
"+r"(_x5), "+r"(_x6), "+r"(_x7)
|
||||
: [num] "i" (hcall_num), [_x18] "r"(&_x18)
|
||||
: "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17",
|
||||
"memory"
|
||||
);
|
||||
|
||||
resp->resp0 = _x0;
|
||||
resp->resp1 = _x1;
|
||||
resp->resp2 = _x2;
|
||||
resp->resp3 = _x3;
|
||||
resp->resp4 = _x4;
|
||||
resp->resp5 = _x5;
|
||||
resp->resp6 = _x6;
|
||||
resp->resp7 = _x7;
|
||||
|
||||
return _x0;
|
||||
}
|
||||
|
||||
#endif
|
@ -167,6 +167,7 @@ extern void iounmap(volatile void __iomem *addr);
|
||||
extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
|
||||
|
||||
#define ioremap(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
|
||||
#define ioremap_nocache(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
|
||||
#define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
|
||||
|
||||
/*
|
||||
|
@ -16,8 +16,10 @@
|
||||
struct mm_struct;
|
||||
struct cpu_suspend_ctx;
|
||||
|
||||
extern void cpu_cache_off(void);
|
||||
extern void cpu_do_idle(void);
|
||||
extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
|
||||
extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
|
||||
extern void cpu_do_suspend(struct cpu_suspend_ctx *ptr);
|
||||
extern u64 cpu_do_resume(phys_addr_t ptr, u64 idmap_ttbr);
|
||||
|
||||
|
@ -7,7 +7,11 @@
|
||||
|
||||
#ifdef CONFIG_SPARSEMEM
|
||||
#define MAX_PHYSMEM_BITS CONFIG_ARM64_PA_BITS
|
||||
#ifndef CONFIG_MEMORY_HOTPLUG
|
||||
#define SECTION_SIZE_BITS 30
|
||||
#else
|
||||
#define SECTION_SIZE_BITS CONFIG_HOTPLUG_SIZE_BITS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -32,8 +32,6 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
|
||||
struct mm_struct;
|
||||
extern void __show_regs(struct pt_regs *);
|
||||
|
||||
extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_SYSTEM_MISC_H */
|
||||
|
@ -17,6 +17,7 @@
|
||||
#ifndef _UAPI__ASM_SIGCONTEXT_H
|
||||
#define _UAPI__ASM_SIGCONTEXT_H
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/types.h>
|
||||
@ -248,5 +249,36 @@ struct sve_context {
|
||||
|
||||
#define SVE_SIG_CONTEXT_SIZE(vq) \
|
||||
(SVE_SIG_REGS_OFFSET + SVE_SIG_REGS_SIZE(vq))
|
||||
#else /* CONFIG_64BIT */
|
||||
|
||||
/*
|
||||
* Signal context structure - contains all info to do with the state
|
||||
* before the signal handler was invoked. Note: only add new entries
|
||||
* to the end of the structure.
|
||||
*/
|
||||
struct sigcontext {
|
||||
unsigned long trap_no;
|
||||
unsigned long error_code;
|
||||
unsigned long oldmask;
|
||||
unsigned long arm_r0;
|
||||
unsigned long arm_r1;
|
||||
unsigned long arm_r2;
|
||||
unsigned long arm_r3;
|
||||
unsigned long arm_r4;
|
||||
unsigned long arm_r5;
|
||||
unsigned long arm_r6;
|
||||
unsigned long arm_r7;
|
||||
unsigned long arm_r8;
|
||||
unsigned long arm_r9;
|
||||
unsigned long arm_r10;
|
||||
unsigned long arm_fp;
|
||||
unsigned long arm_ip;
|
||||
unsigned long arm_sp;
|
||||
unsigned long arm_lr;
|
||||
unsigned long arm_pc;
|
||||
unsigned long arm_cpsr;
|
||||
unsigned long fault_address;
|
||||
};
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
#endif /* _UAPI__ASM_SIGCONTEXT_H */
|
||||
|
@ -1171,7 +1171,7 @@ static bool cpu_has_broken_dbm(void)
|
||||
/* List of CPUs which have broken DBM support. */
|
||||
static const struct midr_range cpus[] = {
|
||||
#ifdef CONFIG_ARM64_ERRATUM_1024718
|
||||
MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 1, 0), // A55 r0p0 -r1p0
|
||||
MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 2, 0), // A55 r0p0 -r2p0
|
||||
#endif
|
||||
{},
|
||||
};
|
||||
|
@ -67,8 +67,6 @@ EXPORT_SYMBOL(__stack_chk_guard);
|
||||
void (*pm_power_off)(void);
|
||||
EXPORT_SYMBOL_GPL(pm_power_off);
|
||||
|
||||
void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
|
||||
|
||||
static void __cpu_do_idle(void)
|
||||
{
|
||||
dsb(sy);
|
||||
@ -198,10 +196,7 @@ void machine_restart(char *cmd)
|
||||
efi_reboot(reboot_mode, NULL);
|
||||
|
||||
/* Now call the architecture specific reboot code. */
|
||||
if (arm_pm_restart)
|
||||
arm_pm_restart(reboot_mode, cmd);
|
||||
else
|
||||
do_kernel_restart(cmd);
|
||||
do_kernel_restart(cmd);
|
||||
|
||||
/*
|
||||
* Whoops - the architecture was unable to reboot.
|
||||
|
@ -976,3 +976,14 @@ void bpf_jit_free_exec(void *addr)
|
||||
{
|
||||
return vfree(addr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CFI_CLANG
|
||||
bool arch_bpf_jit_check_func(const struct bpf_prog *prog)
|
||||
{
|
||||
const uintptr_t func = (const uintptr_t)prog->bpf_func;
|
||||
|
||||
/* bpf_func must be correctly aligned and within the BPF JIT region */
|
||||
return (func >= BPF_JIT_REGION_START && func < BPF_JIT_REGION_END &&
|
||||
IS_ALIGNED(func, sizeof(u32)));
|
||||
}
|
||||
#endif
|
||||
|
@ -645,6 +645,13 @@ static int kvmppc_xive_native_set_queue_config(struct kvmppc_xive *xive,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
page = gfn_to_page(kvm, gfn);
|
||||
if (is_error_page(page)) {
|
||||
srcu_read_unlock(&kvm->srcu, srcu_idx);
|
||||
pr_err("Couldn't get queue page %llx!\n", kvm_eq.qaddr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qaddr = page_to_virt(page) + (kvm_eq.qaddr & ~PAGE_MASK);
|
||||
srcu_read_unlock(&kvm->srcu, srcu_idx);
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
CONFIG_LOCALVERSION="-mainline"
|
||||
# CONFIG_USELIB is not set
|
||||
CONFIG_AUDIT=y
|
||||
CONFIG_NO_HZ=y
|
||||
@ -49,9 +48,6 @@ CONFIG_HYPERVISOR_GUEST=y
|
||||
CONFIG_PARAVIRT=y
|
||||
CONFIG_NR_CPUS=32
|
||||
CONFIG_EFI=y
|
||||
CONFIG_PM_WAKELOCKS=y
|
||||
CONFIG_PM_WAKELOCKS_LIMIT=0
|
||||
# CONFIG_PM_WAKELOCKS_GC is not set
|
||||
CONFIG_CPU_FREQ_TIMES=y
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
|
||||
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
|
||||
@ -259,6 +255,7 @@ CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
CONFIG_SERIAL_DEV_BUS=y
|
||||
CONFIG_VIRTIO_CONSOLE=m
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_HPET=y
|
||||
# CONFIG_I2C_COMPAT is not set
|
||||
|
86
arch/x86/kernel/doublefault.c
Normal file
86
arch/x86/kernel/doublefault.c
Normal file
@ -0,0 +1,86 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/debug.h>
|
||||
#include <linux/init_task.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/desc.h>
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
|
||||
#define DOUBLEFAULT_STACKSIZE (1024)
|
||||
static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE];
|
||||
#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE)
|
||||
|
||||
#define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + MAXMEM)
|
||||
|
||||
static void doublefault_fn(void)
|
||||
{
|
||||
struct desc_ptr gdt_desc = {0, 0};
|
||||
unsigned long gdt, tss;
|
||||
|
||||
native_store_gdt(&gdt_desc);
|
||||
gdt = gdt_desc.address;
|
||||
|
||||
printk(KERN_EMERG "PANIC: double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size);
|
||||
|
||||
if (ptr_ok(gdt)) {
|
||||
gdt += GDT_ENTRY_TSS << 3;
|
||||
tss = get_desc_base((struct desc_struct *)gdt);
|
||||
printk(KERN_EMERG "double fault, tss at %08lx\n", tss);
|
||||
|
||||
if (ptr_ok(tss)) {
|
||||
struct x86_hw_tss *t = (struct x86_hw_tss *)tss;
|
||||
|
||||
printk(KERN_EMERG "eip = %08lx, esp = %08lx\n",
|
||||
t->ip, t->sp);
|
||||
|
||||
printk(KERN_EMERG "eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n",
|
||||
t->ax, t->bx, t->cx, t->dx);
|
||||
printk(KERN_EMERG "esi = %08lx, edi = %08lx\n",
|
||||
t->si, t->di);
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
struct x86_hw_tss doublefault_tss __cacheline_aligned = {
|
||||
.sp0 = STACK_START,
|
||||
.ss0 = __KERNEL_DS,
|
||||
.ldt = 0,
|
||||
.io_bitmap_base = INVALID_IO_BITMAP_OFFSET,
|
||||
|
||||
.ip = (unsigned long) doublefault_fn,
|
||||
/* 0x2 bit is always set */
|
||||
.flags = X86_EFLAGS_SF | 0x2,
|
||||
.sp = STACK_START,
|
||||
.es = __USER_DS,
|
||||
.cs = __KERNEL_CS,
|
||||
.ss = __KERNEL_DS,
|
||||
.ds = __USER_DS,
|
||||
.fs = __KERNEL_PERCPU,
|
||||
#ifndef CONFIG_X86_32_LAZY_GS
|
||||
.gs = __KERNEL_STACK_CANARY,
|
||||
#endif
|
||||
|
||||
.__cr3 = __pa_nodebug(swapper_pg_dir),
|
||||
};
|
||||
|
||||
/* dummy for do_double_fault() call */
|
||||
void df_debug(struct pt_regs *regs, long error_code) {}
|
||||
|
||||
#else /* !CONFIG_X86_32 */
|
||||
|
||||
void df_debug(struct pt_regs *regs, long error_code)
|
||||
{
|
||||
pr_emerg("PANIC: double fault, error_code: 0x%lx\n", error_code);
|
||||
show_regs(regs);
|
||||
panic("Machine halted.");
|
||||
}
|
||||
#endif
|
@ -1337,6 +1337,8 @@ static u64 kvm_get_arch_capabilities(void)
|
||||
else if (!boot_cpu_has_bug(X86_BUG_TAA))
|
||||
data |= ARCH_CAP_TAA_NO;
|
||||
|
||||
/* KVM does not emulate MSR_IA32_TSX_CTRL. */
|
||||
data &= ~ARCH_CAP_TSX_CTRL_MSR;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
. ${ROOT_DIR}/common/build.config.common
|
||||
. ${ROOT_DIR}/common/build.config.aarch64
|
||||
. ${ROOT_DIR}/common/build.config.gki
|
||||
|
||||
|
@ -133,6 +133,17 @@ static const struct dmi_system_id dmi_lid_quirks[] = {
|
||||
},
|
||||
.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Medion Akoya E2215T, notification of the LID device only
|
||||
* happens on close, not on open and _LID always returns closed.
|
||||
*/
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "E2215T MD60198"),
|
||||
},
|
||||
.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -654,7 +654,7 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
int ret;
|
||||
struct binderfs_info *info;
|
||||
struct inode *inode = NULL;
|
||||
struct binderfs_device device_info = { 0 };
|
||||
struct binderfs_device device_info = { {0} };
|
||||
const char *name;
|
||||
size_t len;
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE;
|
||||
DEFINE_PER_CPU(unsigned long, max_cpu_freq);
|
||||
@ -219,6 +220,7 @@ init_cpu_capacity_callback(struct notifier_block *nb,
|
||||
|
||||
if (cpumask_empty(cpus_to_visit)) {
|
||||
topology_normalize_cpu_scale();
|
||||
walt_update_cluster_topology();
|
||||
schedule_work(&update_topology_flags_work);
|
||||
free_raw_capacity();
|
||||
pr_debug("cpu_capacity: parsing done\n");
|
||||
@ -481,6 +483,26 @@ const struct cpumask *cpu_coregroup_mask(int cpu)
|
||||
return core_mask;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_WALT
|
||||
void update_possible_siblings_masks(unsigned int cpuid)
|
||||
{
|
||||
struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
|
||||
int cpu;
|
||||
|
||||
if (cpuid_topo->package_id == -1)
|
||||
return;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
cpu_topo = &cpu_topology[cpu];
|
||||
|
||||
if (cpuid_topo->package_id != cpu_topo->package_id)
|
||||
continue;
|
||||
cpumask_set_cpu(cpuid, &cpu_topo->core_possible_sibling);
|
||||
cpumask_set_cpu(cpu, &cpuid_topo->core_possible_sibling);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void update_siblings_masks(unsigned int cpuid)
|
||||
{
|
||||
struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
|
||||
@ -560,6 +582,9 @@ __weak int __init parse_acpi_topology(void)
|
||||
#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
|
||||
void __init init_cpu_topology(void)
|
||||
{
|
||||
#ifdef CONFIG_SCHED_WALT
|
||||
int cpu;
|
||||
#endif
|
||||
reset_cpu_topology();
|
||||
|
||||
/*
|
||||
@ -570,5 +595,11 @@ void __init init_cpu_topology(void)
|
||||
reset_cpu_topology();
|
||||
else if (of_have_populated_dt() && parse_dt_topology())
|
||||
reset_cpu_topology();
|
||||
#ifdef CONFIG_SCHED_WALT
|
||||
else {
|
||||
for_each_possible_cpu(cpu)
|
||||
update_possible_siblings_masks(cpu);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
@ -1156,6 +1156,11 @@ int lock_device_hotplug_sysfs(void)
|
||||
return restart_syscall();
|
||||
}
|
||||
|
||||
void lock_device_hotplug_assert(void)
|
||||
{
|
||||
lockdep_assert_held(&device_hotplug_lock);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLOCK
|
||||
static inline int device_is_not_partition(struct device *dev)
|
||||
{
|
||||
|
@ -183,9 +183,94 @@ static struct attribute_group crash_note_cpu_attr_group = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static ssize_t isolate_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
||||
ssize_t rc;
|
||||
int cpuid = cpu->dev.id;
|
||||
unsigned int isolated = cpu_isolated(cpuid);
|
||||
|
||||
rc = scnprintf(buf, PAGE_SIZE-2, "%d\n", isolated);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(isolate);
|
||||
|
||||
static struct attribute *cpu_isolated_attrs[] = {
|
||||
&dev_attr_isolate.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group cpu_isolated_attr_group = {
|
||||
.attrs = cpu_isolated_attrs,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_WALT
|
||||
static ssize_t sched_load_boost_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t rc;
|
||||
int boost;
|
||||
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
||||
int cpuid = cpu->dev.id;
|
||||
|
||||
boost = per_cpu(sched_load_boost, cpuid);
|
||||
rc = scnprintf(buf, PAGE_SIZE-2, "%d\n", boost);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t __ref sched_load_boost_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int err;
|
||||
int boost;
|
||||
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
||||
int cpuid = cpu->dev.id;
|
||||
|
||||
err = kstrtoint(strstrip((char *)buf), 0, &boost);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* -100 is low enough to cancel out CPU's load and make it near zro.
|
||||
* 1000 is close to the maximum value that cpu_util_freq_{walt,pelt}
|
||||
* can take without overflow.
|
||||
*/
|
||||
if (boost < -100 || boost > 1000)
|
||||
return -EINVAL;
|
||||
|
||||
per_cpu(sched_load_boost, cpuid) = boost;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(sched_load_boost);
|
||||
|
||||
static struct attribute *sched_cpu_attrs[] = {
|
||||
&dev_attr_sched_load_boost.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group sched_cpu_attr_group = {
|
||||
.attrs = sched_cpu_attrs,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct attribute_group *common_cpu_attr_groups[] = {
|
||||
#ifdef CONFIG_KEXEC
|
||||
&crash_note_cpu_attr_group,
|
||||
#endif
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
&cpu_isolated_attr_group,
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_WALT
|
||||
&sched_cpu_attr_group,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@ -193,6 +278,12 @@ static const struct attribute_group *common_cpu_attr_groups[] = {
|
||||
static const struct attribute_group *hotplugable_cpu_attr_groups[] = {
|
||||
#ifdef CONFIG_KEXEC
|
||||
&crash_note_cpu_attr_group,
|
||||
#endif
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
&cpu_isolated_attr_group,
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_WALT
|
||||
&sched_cpu_attr_group,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@ -223,6 +314,7 @@ static struct cpu_attr cpu_attrs[] = {
|
||||
_CPU_ATTR(online, &__cpu_online_mask),
|
||||
_CPU_ATTR(possible, &__cpu_possible_mask),
|
||||
_CPU_ATTR(present, &__cpu_present_mask),
|
||||
_CPU_ATTR(core_ctl_isolated, &__cpu_isolated_mask),
|
||||
};
|
||||
|
||||
/*
|
||||
@ -472,6 +564,7 @@ static struct attribute *cpu_root_attrs[] = {
|
||||
&cpu_attrs[0].attr.attr,
|
||||
&cpu_attrs[1].attr.attr,
|
||||
&cpu_attrs[2].attr.attr,
|
||||
&cpu_attrs[3].attr.attr,
|
||||
&dev_attr_kernel_max.attr,
|
||||
&dev_attr_offline.attr,
|
||||
&dev_attr_isolated.attr,
|
||||
|
@ -99,6 +99,12 @@ extern int pm_async_enabled;
|
||||
/* drivers/base/power/main.c */
|
||||
extern struct list_head dpm_list; /* The active device list */
|
||||
|
||||
#ifdef CONFIG_QCOM_SHOW_RESUME_IRQ
|
||||
extern int msm_show_resume_irq_mask;
|
||||
#else
|
||||
#define msm_show_resume_irq_mask 0
|
||||
#endif
|
||||
|
||||
static inline struct device *to_device(struct list_head *entry)
|
||||
{
|
||||
return container_of(entry, struct device, power.entry);
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include <linux/pm_wakeirq.h>
|
||||
#include <linux/types.h>
|
||||
#include <trace/events/power.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdesc.h>
|
||||
|
||||
#include "power.h"
|
||||
|
||||
@ -977,7 +980,21 @@ void pm_wakeup_clear(bool reset)
|
||||
|
||||
void pm_system_irq_wakeup(unsigned int irq_number)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
const char *name = "null";
|
||||
|
||||
if (pm_wakeup_irq == 0) {
|
||||
if (msm_show_resume_irq_mask) {
|
||||
desc = irq_to_desc(irq_number);
|
||||
if (desc == NULL)
|
||||
name = "stray irq";
|
||||
else if (desc->action && desc->action->name)
|
||||
name = desc->action->name;
|
||||
|
||||
pr_warn("%s: %d triggered %s\n", __func__,
|
||||
irq_number, name);
|
||||
|
||||
}
|
||||
pm_wakeup_irq = irq_number;
|
||||
pm_system_wakeup();
|
||||
}
|
||||
|
@ -53,3 +53,20 @@ config REGMAP_SCCB
|
||||
config REGMAP_I3C
|
||||
tristate
|
||||
depends on I3C
|
||||
|
||||
config REGMAP_QTI_DEBUG
|
||||
bool "Regmap QTI debug feature support"
|
||||
depends on REGMAP && DEBUG_FS && QGKI
|
||||
help
|
||||
Say yes to enable QTI debug features. This provides a runtime debugfs
|
||||
interface to read and write a subset of regmap registers. This
|
||||
interface is more performant and easier to use than the traditional
|
||||
method which dumps all registers defined in a given regmap.
|
||||
|
||||
config REGMAP_ALLOW_WRITE_DEBUGFS
|
||||
depends on REGMAP && DEBUG_FS
|
||||
bool "Allow REGMAP debugfs write"
|
||||
help
|
||||
Say 'y' here to allow the regmap debugfs write. Regmap debugfs write
|
||||
could be risky when accessing some essential hardwares, so it is not
|
||||
recommended to enable this option on any production device.
|
||||
|
@ -84,6 +84,11 @@ struct regmap {
|
||||
|
||||
struct list_head debugfs_off_cache;
|
||||
struct mutex cache_lock;
|
||||
|
||||
#ifdef CONFIG_REGMAP_QTI_DEBUG
|
||||
unsigned int dump_address;
|
||||
unsigned int dump_count;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
unsigned int max_register;
|
||||
|
@ -288,8 +288,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
|
||||
count, ppos);
|
||||
}
|
||||
|
||||
#undef REGMAP_ALLOW_WRITE_DEBUGFS
|
||||
#ifdef REGMAP_ALLOW_WRITE_DEBUGFS
|
||||
#ifdef CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS
|
||||
/*
|
||||
* This can be dangerous especially when we have clients such as
|
||||
* PMICs, therefore don't provide any real compile time configuration option
|
||||
@ -339,6 +338,72 @@ static const struct file_operations regmap_map_fops = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_REGMAP_QTI_DEBUG
|
||||
static ssize_t regmap_data_read_file(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct regmap *map = file->private_data;
|
||||
int new_count;
|
||||
|
||||
regmap_calc_tot_len(map, NULL, 0);
|
||||
new_count = map->dump_count * map->debugfs_tot_len;
|
||||
if (new_count > count)
|
||||
new_count = count;
|
||||
|
||||
if (*ppos == 0)
|
||||
*ppos = map->dump_address * map->debugfs_tot_len;
|
||||
else if (*ppos >= map->dump_address * map->debugfs_tot_len
|
||||
+ map->dump_count * map->debugfs_tot_len)
|
||||
return 0;
|
||||
else if (*ppos < map->dump_address * map->debugfs_tot_len)
|
||||
return 0;
|
||||
|
||||
return regmap_read_debugfs(map, 0, map->max_register, user_buf,
|
||||
new_count, ppos);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS
|
||||
static ssize_t regmap_data_write_file(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char buf[32];
|
||||
size_t buf_size;
|
||||
char *start = buf;
|
||||
unsigned long value;
|
||||
struct regmap *map = file->private_data;
|
||||
int ret;
|
||||
|
||||
buf_size = min(count, (sizeof(buf)-1));
|
||||
if (copy_from_user(buf, user_buf, buf_size))
|
||||
return -EFAULT;
|
||||
buf[buf_size] = 0;
|
||||
|
||||
while (*start == ' ')
|
||||
start++;
|
||||
if (kstrtoul(start, 16, &value))
|
||||
return -EINVAL;
|
||||
|
||||
/* Userspace has been fiddling around behind the kernel's back */
|
||||
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
|
||||
|
||||
ret = regmap_write(map, map->dump_address, value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return buf_size;
|
||||
}
|
||||
#else
|
||||
#define regmap_data_write_file NULL
|
||||
#endif
|
||||
|
||||
static const struct file_operations regmap_data_fops = {
|
||||
.open = simple_open,
|
||||
.read = regmap_data_read_file,
|
||||
.write = regmap_data_write_file,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
#endif
|
||||
|
||||
static ssize_t regmap_range_read_file(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
@ -598,7 +663,7 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
|
||||
if (map->max_register || regmap_readable(map, 0)) {
|
||||
umode_t registers_mode;
|
||||
|
||||
#if defined(REGMAP_ALLOW_WRITE_DEBUGFS)
|
||||
#ifdef CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS
|
||||
registers_mode = 0600;
|
||||
#else
|
||||
registers_mode = 0400;
|
||||
@ -608,6 +673,16 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
|
||||
map, ®map_map_fops);
|
||||
debugfs_create_file("access", 0400, map->debugfs,
|
||||
map, ®map_access_fops);
|
||||
|
||||
#ifdef CONFIG_REGMAP_QTI_DEBUG
|
||||
debugfs_create_x32("address", 0600, map->debugfs,
|
||||
&map->dump_address);
|
||||
map->dump_count = 1;
|
||||
debugfs_create_u32("count", 0600, map->debugfs,
|
||||
&map->dump_count);
|
||||
debugfs_create_file("data", registers_mode, map->debugfs,
|
||||
map, ®map_data_fops);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (map->cache_type) {
|
||||
|
@ -1362,13 +1362,14 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
|
||||
__GFP_KSWAPD_RECLAIM |
|
||||
__GFP_NOWARN |
|
||||
__GFP_HIGHMEM |
|
||||
__GFP_MOVABLE);
|
||||
__GFP_MOVABLE |
|
||||
__GFP_CMA);
|
||||
if (!handle) {
|
||||
zcomp_stream_put(zram->comp);
|
||||
atomic64_inc(&zram->stats.writestall);
|
||||
handle = zs_malloc(zram->mem_pool, comp_len,
|
||||
GFP_NOIO | __GFP_HIGHMEM |
|
||||
__GFP_MOVABLE);
|
||||
__GFP_MOVABLE | __GFP_CMA);
|
||||
if (handle)
|
||||
goto compress_again;
|
||||
return -ENOMEM;
|
||||
|
@ -425,4 +425,30 @@ config BT_HCIRSI
|
||||
Say Y here to compile support for HCI over Redpine into the
|
||||
kernel or say M to compile as a module.
|
||||
|
||||
config MSM_BT_POWER
|
||||
tristate "MSM Bluetooth Power Control"
|
||||
depends on ARCH_QCOM
|
||||
help
|
||||
MSM Bluetooth Power control driver.
|
||||
This provides a parameter to switch on/off power from PMIC
|
||||
to Bluetooth device. This will control LDOs/Clock/GPIOs to
|
||||
control Bluetooth Chipset based on power on/off sequence.
|
||||
|
||||
Say Y here to compile support for Bluetooth Power driver
|
||||
into the kernel or say M to compile as a module.
|
||||
|
||||
config BTFM_SLIM
|
||||
tristate "MSM Bluetooth/FM Slimbus Device"
|
||||
depends on MSM_BT_POWER
|
||||
select SLIMBUS
|
||||
help
|
||||
This enables BT/FM slimbus driver to get multiple audio channel.
|
||||
This will make use of slimbus platform driver and slimbus
|
||||
codec driver to communicate with slimbus machine driver and LPSS which
|
||||
is Slimbus master.Slimbus slave initialization and configuration
|
||||
will be done through this driver.
|
||||
|
||||
Say Y here to compile support for Bluetooth slimbus driver
|
||||
into the kernel or say M to compile as a module.
|
||||
|
||||
endmenu
|
||||
|
@ -30,6 +30,12 @@ obj-$(CONFIG_BT_HCIUART_NOKIA) += hci_nokia.o
|
||||
|
||||
obj-$(CONFIG_BT_HCIRSI) += btrsi.o
|
||||
|
||||
obj-$(CONFIG_MSM_BT_POWER) += btpower.o
|
||||
|
||||
bt_fm_slim-objs := btfm_slim.o btfm_slim_codec.o btfm_slim_slave.o
|
||||
|
||||
obj-$(CONFIG_BTFM_SLIM) += bt_fm_slim.o
|
||||
|
||||
btmrvl-y := btmrvl_main.o
|
||||
btmrvl-$(CONFIG_DEBUG_FS) += btmrvl_debugfs.o
|
||||
|
||||
|
616
drivers/bluetooth/btfm_slim.c
Normal file
616
drivers/bluetooth/btfm_slim.c
Normal file
@ -0,0 +1,616 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/btpower.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
#include "btfm_slim.h"
|
||||
#include "btfm_slim_slave.h"
|
||||
|
||||
int btfm_slim_write(struct btfmslim *btfmslim,
|
||||
uint16_t reg, int bytes, void *src, uint8_t pgd)
|
||||
{
|
||||
int ret, i;
|
||||
struct slim_ele_access msg;
|
||||
int slim_write_tries = SLIM_SLAVE_RW_MAX_TRIES;
|
||||
|
||||
BTFMSLIM_DBG("Write to %s", pgd?"PGD":"IFD");
|
||||
msg.start_offset = SLIM_SLAVE_REG_OFFSET + reg;
|
||||
msg.num_bytes = bytes;
|
||||
msg.comp = NULL;
|
||||
|
||||
for ( ; slim_write_tries != 0; slim_write_tries--) {
|
||||
mutex_lock(&btfmslim->xfer_lock);
|
||||
ret = slim_change_val_element(pgd ? btfmslim->slim_pgd :
|
||||
&btfmslim->slim_ifd, &msg, src, bytes);
|
||||
mutex_unlock(&btfmslim->xfer_lock);
|
||||
if (ret == 0)
|
||||
break;
|
||||
usleep_range(5000, 5100);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
BTFMSLIM_ERR("failed (%d)", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < bytes; i++)
|
||||
BTFMSLIM_DBG("Write 0x%02x to reg 0x%x", ((uint8_t *)src)[i],
|
||||
reg + i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btfm_slim_write_pgd(struct btfmslim *btfmslim,
|
||||
uint16_t reg, int bytes, void *src)
|
||||
{
|
||||
return btfm_slim_write(btfmslim, reg, bytes, src, PGD);
|
||||
}
|
||||
|
||||
int btfm_slim_write_inf(struct btfmslim *btfmslim,
|
||||
uint16_t reg, int bytes, void *src)
|
||||
{
|
||||
return btfm_slim_write(btfmslim, reg, bytes, src, IFD);
|
||||
}
|
||||
|
||||
int btfm_slim_read(struct btfmslim *btfmslim, unsigned short reg,
|
||||
int bytes, void *dest, uint8_t pgd)
|
||||
{
|
||||
int ret, i;
|
||||
struct slim_ele_access msg;
|
||||
int slim_read_tries = SLIM_SLAVE_RW_MAX_TRIES;
|
||||
|
||||
BTFMSLIM_DBG("Read from %s", pgd?"PGD":"IFD");
|
||||
msg.start_offset = SLIM_SLAVE_REG_OFFSET + reg;
|
||||
msg.num_bytes = bytes;
|
||||
msg.comp = NULL;
|
||||
|
||||
for ( ; slim_read_tries != 0; slim_read_tries--) {
|
||||
mutex_lock(&btfmslim->xfer_lock);
|
||||
ret = slim_request_val_element(pgd ? btfmslim->slim_pgd :
|
||||
&btfmslim->slim_ifd, &msg, dest, bytes);
|
||||
mutex_unlock(&btfmslim->xfer_lock);
|
||||
if (ret == 0)
|
||||
break;
|
||||
usleep_range(5000, 5100);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
BTFMSLIM_ERR("failed (%d)", ret);
|
||||
|
||||
for (i = 0; i < bytes; i++)
|
||||
BTFMSLIM_DBG("Read 0x%02x from reg 0x%x", ((uint8_t *)dest)[i],
|
||||
reg + i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btfm_slim_read_pgd(struct btfmslim *btfmslim,
|
||||
uint16_t reg, int bytes, void *dest)
|
||||
{
|
||||
return btfm_slim_read(btfmslim, reg, bytes, dest, PGD);
|
||||
}
|
||||
|
||||
int btfm_slim_read_inf(struct btfmslim *btfmslim,
|
||||
uint16_t reg, int bytes, void *dest)
|
||||
{
|
||||
return btfm_slim_read(btfmslim, reg, bytes, dest, IFD);
|
||||
}
|
||||
|
||||
int btfm_slim_enable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
|
||||
uint8_t rxport, uint32_t rates, uint8_t grp, uint8_t nchan)
|
||||
{
|
||||
int ret, i;
|
||||
struct slim_ch prop;
|
||||
struct btfmslim_ch *chan = ch;
|
||||
uint16_t ch_h[2];
|
||||
|
||||
if (!btfmslim || !ch)
|
||||
return -EINVAL;
|
||||
|
||||
BTFMSLIM_DBG("port: %d ch: %d", ch->port, ch->ch);
|
||||
|
||||
/* Define the channel with below parameters */
|
||||
prop.prot = ((rates == 44100) || (rates == 88200)) ?
|
||||
SLIM_PUSH : SLIM_AUTO_ISO;
|
||||
prop.baser = ((rates == 44100) || (rates == 88200)) ?
|
||||
SLIM_RATE_11025HZ : SLIM_RATE_4000HZ;
|
||||
prop.dataf = ((rates == 48000) || (rates == 44100) ||
|
||||
(rates == 88200) || (rates == 96000)) ?
|
||||
SLIM_CH_DATAF_NOT_DEFINED : SLIM_CH_DATAF_LPCM_AUDIO;
|
||||
|
||||
/* for feedback channel, PCM bit should not be set */
|
||||
if (btfm_feedback_ch_setting) {
|
||||
BTFMSLIM_DBG("port open for feedback ch, not setting PCM bit");
|
||||
prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
|
||||
/* reset so that next port open sets the data format properly */
|
||||
btfm_feedback_ch_setting = 0;
|
||||
}
|
||||
prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
|
||||
prop.ratem = ((rates == 44100) || (rates == 88200)) ?
|
||||
(rates/11025) : (rates/4000);
|
||||
prop.sampleszbits = 16;
|
||||
|
||||
ch_h[0] = ch->ch_hdl;
|
||||
ch_h[1] = (grp) ? (ch+1)->ch_hdl : 0;
|
||||
|
||||
BTFMSLIM_INFO("channel define - prot:%d, dataf:%d, auxf:%d",
|
||||
prop.prot, prop.dataf, prop.auxf);
|
||||
BTFMSLIM_INFO("channel define - rates:%d, baser:%d, ratem:%d",
|
||||
rates, prop.baser, prop.ratem);
|
||||
|
||||
ret = slim_define_ch(btfmslim->slim_pgd, &prop, ch_h, nchan, grp,
|
||||
&ch->grph);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("slim_define_ch failed ret[%d]", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < nchan; i++, ch++) {
|
||||
/* Enable port through registration setting */
|
||||
if (btfmslim->vendor_port_en) {
|
||||
ret = btfmslim->vendor_port_en(btfmslim, ch->port,
|
||||
rxport, 1);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("vendor_port_en failed ret[%d]",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (rxport) {
|
||||
BTFMSLIM_INFO("slim_connect_sink(port: %d, ch: %d)",
|
||||
ch->port, ch->ch);
|
||||
/* Connect Port with channel given by Machine driver*/
|
||||
ret = slim_connect_sink(btfmslim->slim_pgd,
|
||||
&ch->port_hdl, 1, ch->ch_hdl);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("slim_connect_sink failed ret[%d]",
|
||||
ret);
|
||||
goto remove_channel;
|
||||
}
|
||||
|
||||
} else {
|
||||
BTFMSLIM_INFO("slim_connect_src(port: %d, ch: %d)",
|
||||
ch->port, ch->ch);
|
||||
/* Connect Port with channel given by Machine driver*/
|
||||
ret = slim_connect_src(btfmslim->slim_pgd, ch->port_hdl,
|
||||
ch->ch_hdl);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("slim_connect_src failed ret[%d]",
|
||||
ret);
|
||||
goto remove_channel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Activate the channel immediately */
|
||||
BTFMSLIM_INFO(
|
||||
"port: %d, ch: %d, grp: %d, ch->grph: 0x%x, ch_hdl: 0x%x",
|
||||
chan->port, chan->ch, grp, chan->grph, chan->ch_hdl);
|
||||
ret = slim_control_ch(btfmslim->slim_pgd, (grp ? chan->grph :
|
||||
chan->ch_hdl), SLIM_CH_ACTIVATE, true);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("slim_control_ch failed ret[%d]", ret);
|
||||
goto remove_channel;
|
||||
}
|
||||
|
||||
error:
|
||||
return ret;
|
||||
|
||||
remove_channel:
|
||||
/* Remove the channel immediately*/
|
||||
ret = slim_control_ch(btfmslim->slim_pgd, (grp ? ch->grph : ch->ch_hdl),
|
||||
SLIM_CH_REMOVE, true);
|
||||
if (ret < 0)
|
||||
BTFMSLIM_ERR("slim_control_ch failed ret[%d]", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int btfm_slim_disable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
|
||||
uint8_t rxport, uint8_t grp, uint8_t nchan)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
if (!btfmslim || !ch)
|
||||
return -EINVAL;
|
||||
|
||||
BTFMSLIM_INFO("port:%d, grp: %d, ch->grph:0x%x, ch->ch_hdl:0x%x ",
|
||||
ch->port, grp, ch->grph, ch->ch_hdl);
|
||||
|
||||
/* For 44.1/88.2 Khz A2DP Rx, disconnect the port first */
|
||||
if (rxport &&
|
||||
(btfmslim->sample_rate == 44100 ||
|
||||
btfmslim->sample_rate == 88200)) {
|
||||
BTFMSLIM_DBG("disconnecting the ports, removing the channel");
|
||||
ret = slim_disconnect_ports(btfmslim->slim_pgd,
|
||||
&ch->port_hdl, 1);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("slim_disconnect_ports failed ret[%d]",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove the channel immediately*/
|
||||
ret = slim_control_ch(btfmslim->slim_pgd, (grp ? ch->grph : ch->ch_hdl),
|
||||
SLIM_CH_REMOVE, true);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("slim_control_ch failed ret[%d]", ret);
|
||||
if (btfmslim->sample_rate != 44100 &&
|
||||
btfmslim->sample_rate != 88200) {
|
||||
ret = slim_disconnect_ports(btfmslim->slim_pgd,
|
||||
&ch->port_hdl, 1);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("disconnect_ports failed ret[%d]",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable port through registration setting */
|
||||
for (i = 0; i < nchan; i++, ch++) {
|
||||
if (btfmslim->vendor_port_en) {
|
||||
ret = btfmslim->vendor_port_en(btfmslim, ch->port,
|
||||
rxport, 0);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("vendor_port_en failed ret[%d]",
|
||||
ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
static int btfm_slim_get_logical_addr(struct slim_device *slim)
|
||||
{
|
||||
int ret = 0;
|
||||
const unsigned long timeout = jiffies +
|
||||
msecs_to_jiffies(SLIM_SLAVE_PRESENT_TIMEOUT);
|
||||
|
||||
do {
|
||||
ret = slim_get_logical_addr(slim, slim->e_addr,
|
||||
ARRAY_SIZE(slim->e_addr), &slim->laddr);
|
||||
if (!ret) {
|
||||
BTFMSLIM_DBG("Assigned l-addr: 0x%x", slim->laddr);
|
||||
break;
|
||||
}
|
||||
/* Give SLIMBUS time to report present and be ready. */
|
||||
usleep_range(1000, 1100);
|
||||
BTFMSLIM_DBG("retyring get logical addr");
|
||||
} while (time_before(jiffies, timeout));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btfm_slim_alloc_port(struct btfmslim *btfmslim)
|
||||
{
|
||||
int ret = -EINVAL, i;
|
||||
int chipset_ver;
|
||||
struct btfmslim_ch *rx_chs;
|
||||
struct btfmslim_ch *tx_chs;
|
||||
|
||||
if (!btfmslim)
|
||||
return ret;
|
||||
|
||||
chipset_ver = btpower_get_chipset_version();
|
||||
BTFMSLIM_INFO("chipset soc version:%x", chipset_ver);
|
||||
|
||||
rx_chs = btfmslim->rx_chs;
|
||||
tx_chs = btfmslim->tx_chs;
|
||||
if ((chipset_ver >= QCA_CHEROKEE_SOC_ID_0310) &&
|
||||
(chipset_ver <= QCA_CHEROKEE_SOC_ID_0320_UMC)) {
|
||||
for (i = 0; (tx_chs->port != BTFM_SLIM_PGD_PORT_LAST) &&
|
||||
(i < BTFM_SLIM_NUM_CODEC_DAIS); i++, tx_chs++) {
|
||||
if (tx_chs->port == SLAVE_SB_PGD_PORT_TX1_FM)
|
||||
tx_chs->port = CHRKVER3_SB_PGD_PORT_TX1_FM;
|
||||
else if (tx_chs->port == SLAVE_SB_PGD_PORT_TX2_FM)
|
||||
tx_chs->port = CHRKVER3_SB_PGD_PORT_TX2_FM;
|
||||
BTFMSLIM_INFO("Tx port:%d", tx_chs->port);
|
||||
}
|
||||
tx_chs = btfmslim->tx_chs;
|
||||
}
|
||||
if (!rx_chs || !tx_chs)
|
||||
return ret;
|
||||
|
||||
BTFMSLIM_DBG("Rx: id\tname\tport\thdl\tch\tch_hdl");
|
||||
for (i = 0 ; (rx_chs->port != BTFM_SLIM_PGD_PORT_LAST) &&
|
||||
(i < BTFM_SLIM_NUM_CODEC_DAIS); i++, rx_chs++) {
|
||||
|
||||
/* Get Rx port handler from slimbus driver based
|
||||
* on port number
|
||||
*/
|
||||
ret = slim_get_slaveport(btfmslim->slim_pgd->laddr,
|
||||
rx_chs->port, &rx_chs->port_hdl, SLIM_SINK);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("slave port failure port#%d - ret[%d]",
|
||||
rx_chs->port, SLIM_SINK);
|
||||
return ret;
|
||||
}
|
||||
BTFMSLIM_DBG(" %d\t%s\t%d\t%x\t%d\t%x", rx_chs->id,
|
||||
rx_chs->name, rx_chs->port, rx_chs->port_hdl,
|
||||
rx_chs->ch, rx_chs->ch_hdl);
|
||||
}
|
||||
|
||||
BTFMSLIM_DBG("Tx: id\tname\tport\thdl\tch\tch_hdl");
|
||||
for (i = 0; (tx_chs->port != BTFM_SLIM_PGD_PORT_LAST) &&
|
||||
(i < BTFM_SLIM_NUM_CODEC_DAIS); i++, tx_chs++) {
|
||||
|
||||
/* Get Tx port handler from slimbus driver based
|
||||
* on port number
|
||||
*/
|
||||
ret = slim_get_slaveport(btfmslim->slim_pgd->laddr,
|
||||
tx_chs->port, &tx_chs->port_hdl, SLIM_SRC);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("slave port failure port#%d - ret[%d]",
|
||||
tx_chs->port, SLIM_SRC);
|
||||
return ret;
|
||||
}
|
||||
BTFMSLIM_DBG(" %d\t%s\t%d\t%x\t%d\t%x", tx_chs->id,
|
||||
tx_chs->name, tx_chs->port, tx_chs->port_hdl,
|
||||
tx_chs->ch, tx_chs->ch_hdl);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int btfm_slim_hw_init(struct btfmslim *btfmslim)
|
||||
{
|
||||
int ret;
|
||||
|
||||
BTFMSLIM_DBG("");
|
||||
if (!btfmslim)
|
||||
return -EINVAL;
|
||||
|
||||
if (btfmslim->enabled) {
|
||||
BTFMSLIM_DBG("Already enabled");
|
||||
return 0;
|
||||
}
|
||||
mutex_lock(&btfmslim->io_lock);
|
||||
|
||||
/* Assign Logical Address for PGD (Ported Generic Device)
|
||||
* enumeration address
|
||||
*/
|
||||
ret = btfm_slim_get_logical_addr(btfmslim->slim_pgd);
|
||||
if (ret) {
|
||||
BTFMSLIM_ERR("failed to get slimbus %s logical address: %d",
|
||||
btfmslim->slim_pgd->name, ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Assign Logical Address for Ported Generic Device
|
||||
* enumeration address
|
||||
*/
|
||||
ret = btfm_slim_get_logical_addr(&btfmslim->slim_ifd);
|
||||
if (ret) {
|
||||
BTFMSLIM_ERR("failed to get slimbus %s logical address: %d",
|
||||
btfmslim->slim_ifd.name, ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Allocate ports with logical address to get port handler from
|
||||
* slimbus driver
|
||||
*/
|
||||
ret = btfm_slim_alloc_port(btfmslim);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* Start vendor specific initialization and get port information */
|
||||
if (btfmslim->vendor_init)
|
||||
ret = btfmslim->vendor_init(btfmslim);
|
||||
|
||||
/* Only when all registers read/write successfully, it set to
|
||||
* enabled status
|
||||
*/
|
||||
btfmslim->enabled = 1;
|
||||
error:
|
||||
mutex_unlock(&btfmslim->io_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int btfm_slim_hw_deinit(struct btfmslim *btfmslim)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!btfmslim)
|
||||
return -EINVAL;
|
||||
|
||||
if (!btfmslim->enabled) {
|
||||
BTFMSLIM_DBG("Already disabled");
|
||||
return 0;
|
||||
}
|
||||
mutex_lock(&btfmslim->io_lock);
|
||||
btfmslim->enabled = 0;
|
||||
mutex_unlock(&btfmslim->io_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btfm_slim_get_dt_info(struct btfmslim *btfmslim)
|
||||
{
|
||||
int ret = 0;
|
||||
struct slim_device *slim = btfmslim->slim_pgd;
|
||||
struct slim_device *slim_ifd = &btfmslim->slim_ifd;
|
||||
struct property *prop;
|
||||
|
||||
if (!slim || !slim_ifd)
|
||||
return -EINVAL;
|
||||
|
||||
if (slim->dev.of_node) {
|
||||
BTFMSLIM_DBG("Platform data from device tree (%s)",
|
||||
slim->name);
|
||||
ret = of_property_read_string(slim->dev.of_node,
|
||||
"qcom,btfm-slim-ifd", &slim_ifd->name);
|
||||
if (ret) {
|
||||
BTFMSLIM_ERR("Looking up %s property in node %s failed",
|
||||
"qcom,btfm-slim-ifd",
|
||||
slim->dev.of_node->full_name);
|
||||
return -ENODEV;
|
||||
}
|
||||
BTFMSLIM_DBG("qcom,btfm-slim-ifd (%s)", slim_ifd->name);
|
||||
|
||||
prop = of_find_property(slim->dev.of_node,
|
||||
"qcom,btfm-slim-ifd-elemental-addr", NULL);
|
||||
if (!prop) {
|
||||
BTFMSLIM_ERR("Looking up %s property in node %s failed",
|
||||
"qcom,btfm-slim-ifd-elemental-addr",
|
||||
slim->dev.of_node->full_name);
|
||||
return -ENODEV;
|
||||
} else if (prop->length != 6) {
|
||||
BTFMSLIM_ERR(
|
||||
"invalid codec slim ifd addr. addr length= %d",
|
||||
prop->length);
|
||||
return -ENODEV;
|
||||
}
|
||||
memcpy(slim_ifd->e_addr, prop->value, 6);
|
||||
BTFMSLIM_DBG(
|
||||
"PGD Enum Addr: %.02x:%.02x:%.02x:%.02x:%.02x: %.02x",
|
||||
slim->e_addr[0], slim->e_addr[1], slim->e_addr[2],
|
||||
slim->e_addr[3], slim->e_addr[4], slim->e_addr[5]);
|
||||
BTFMSLIM_DBG(
|
||||
"IFD Enum Addr: %.02x:%.02x:%.02x:%.02x:%.02x: %.02x",
|
||||
slim_ifd->e_addr[0], slim_ifd->e_addr[1],
|
||||
slim_ifd->e_addr[2], slim_ifd->e_addr[3],
|
||||
slim_ifd->e_addr[4], slim_ifd->e_addr[5]);
|
||||
} else {
|
||||
BTFMSLIM_ERR("Platform data is not valid");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btfm_slim_probe(struct slim_device *slim)
|
||||
{
|
||||
int ret = 0;
|
||||
struct btfmslim *btfm_slim;
|
||||
|
||||
BTFMSLIM_DBG("");
|
||||
if (!slim->ctrl)
|
||||
return -EINVAL;
|
||||
|
||||
/* Allocation btfmslim data pointer */
|
||||
btfm_slim = kzalloc(sizeof(struct btfmslim), GFP_KERNEL);
|
||||
if (btfm_slim == NULL) {
|
||||
BTFMSLIM_ERR("error, allocation failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* BTFM Slimbus driver control data configuration */
|
||||
btfm_slim->slim_pgd = slim;
|
||||
|
||||
/* Assign vendor specific function */
|
||||
btfm_slim->rx_chs = SLIM_SLAVE_RXPORT;
|
||||
btfm_slim->tx_chs = SLIM_SLAVE_TXPORT;
|
||||
btfm_slim->vendor_init = SLIM_SLAVE_INIT;
|
||||
btfm_slim->vendor_port_en = SLIM_SLAVE_PORT_EN;
|
||||
|
||||
/* Created Mutex for slimbus data transfer */
|
||||
mutex_init(&btfm_slim->io_lock);
|
||||
mutex_init(&btfm_slim->xfer_lock);
|
||||
|
||||
/* Get Device tree node for Interface Device enumeration address */
|
||||
ret = btfm_slim_get_dt_info(btfm_slim);
|
||||
if (ret)
|
||||
goto dealloc;
|
||||
|
||||
/* Add Interface Device for slimbus driver */
|
||||
ret = slim_add_device(btfm_slim->slim_pgd->ctrl, &btfm_slim->slim_ifd);
|
||||
if (ret) {
|
||||
BTFMSLIM_ERR("error, adding SLIMBUS device failed");
|
||||
goto dealloc;
|
||||
}
|
||||
|
||||
/* Platform driver data allocation */
|
||||
slim->dev.platform_data = btfm_slim;
|
||||
|
||||
/* Driver specific data allocation */
|
||||
btfm_slim->dev = &slim->dev;
|
||||
ret = btfm_slim_register_codec(&slim->dev);
|
||||
if (ret) {
|
||||
BTFMSLIM_ERR("error, registering slimbus codec failed");
|
||||
goto free;
|
||||
}
|
||||
|
||||
ret = btpower_register_slimdev(&slim->dev);
|
||||
if (ret < 0) {
|
||||
btfm_slim_unregister_codec(&slim->dev);
|
||||
goto free;
|
||||
}
|
||||
return ret;
|
||||
free:
|
||||
slim_remove_device(&btfm_slim->slim_ifd);
|
||||
dealloc:
|
||||
mutex_destroy(&btfm_slim->io_lock);
|
||||
mutex_destroy(&btfm_slim->xfer_lock);
|
||||
kfree(btfm_slim);
|
||||
return ret;
|
||||
}
|
||||
static int btfm_slim_remove(struct slim_device *slim)
|
||||
{
|
||||
struct btfmslim *btfm_slim = slim->dev.platform_data;
|
||||
|
||||
BTFMSLIM_DBG("");
|
||||
mutex_destroy(&btfm_slim->io_lock);
|
||||
mutex_destroy(&btfm_slim->xfer_lock);
|
||||
snd_soc_unregister_component(&slim->dev);
|
||||
|
||||
BTFMSLIM_DBG("slim_remove_device() - btfm_slim->slim_ifd");
|
||||
slim_remove_device(&btfm_slim->slim_ifd);
|
||||
|
||||
kfree(btfm_slim);
|
||||
|
||||
BTFMSLIM_DBG("slim_remove_device() - btfm_slim->slim_pgd");
|
||||
slim_remove_device(slim);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct slim_device_id btfm_slim_id[] = {
|
||||
{SLIM_SLAVE_COMPATIBLE_STR, 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct slim_driver btfm_slim_driver = {
|
||||
.driver = {
|
||||
.name = "btfmslim-driver",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = btfm_slim_probe,
|
||||
.remove = btfm_slim_remove,
|
||||
.id_table = btfm_slim_id
|
||||
};
|
||||
|
||||
static int __init btfm_slim_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
BTFMSLIM_DBG("");
|
||||
ret = slim_driver_register(&btfm_slim_driver);
|
||||
if (ret)
|
||||
BTFMSLIM_ERR("Failed to register slimbus driver: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit btfm_slim_exit(void)
|
||||
{
|
||||
BTFMSLIM_DBG("");
|
||||
slim_driver_unregister(&btfm_slim_driver);
|
||||
}
|
||||
|
||||
module_init(btfm_slim_init);
|
||||
module_exit(btfm_slim_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("BTFM Slimbus Slave driver");
|
169
drivers/bluetooth/btfm_slim.h
Normal file
169
drivers/bluetooth/btfm_slim.h
Normal file
@ -0,0 +1,169 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef BTFM_SLIM_H
|
||||
#define BTFM_SLIM_H
|
||||
#include <linux/slimbus/slimbus.h>
|
||||
|
||||
#define BTFMSLIM_DBG(fmt, arg...) pr_debug("%s: " fmt "\n", __func__, ## arg)
|
||||
#define BTFMSLIM_INFO(fmt, arg...) pr_info("%s: " fmt "\n", __func__, ## arg)
|
||||
#define BTFMSLIM_ERR(fmt, arg...) pr_err("%s: " fmt "\n", __func__, ## arg)
|
||||
|
||||
/* Vendor specific defines
|
||||
* This should redefines in slimbus slave specific header
|
||||
*/
|
||||
#define SLIM_SLAVE_COMPATIBLE_STR "btfmslim_slave"
|
||||
#define SLIM_SLAVE_REG_OFFSET 0x0000
|
||||
#define SLIM_SLAVE_RXPORT NULL
|
||||
#define SLIM_SLAVE_TXPORT NULL
|
||||
#define SLIM_SLAVE_INIT NULL
|
||||
#define SLIM_SLAVE_PORT_EN NULL
|
||||
|
||||
/* Misc defines */
|
||||
#define SLIM_SLAVE_RW_MAX_TRIES 3
|
||||
#define SLIM_SLAVE_PRESENT_TIMEOUT 100
|
||||
|
||||
#define PGD 1
|
||||
#define IFD 0
|
||||
|
||||
|
||||
/* Codec driver defines */
|
||||
enum {
|
||||
BTFM_FM_SLIM_TX = 0,
|
||||
BTFM_BT_SCO_SLIM_TX,
|
||||
BTFM_BT_SCO_A2DP_SLIM_RX,
|
||||
BTFM_BT_SPLIT_A2DP_SLIM_RX,
|
||||
BTFM_SLIM_NUM_CODEC_DAIS
|
||||
};
|
||||
|
||||
/* Slimbus Port defines - This should be redefined in specific device file */
|
||||
#define BTFM_SLIM_PGD_PORT_LAST 0xFF
|
||||
|
||||
struct btfmslim_ch {
|
||||
int id;
|
||||
char *name;
|
||||
uint32_t port_hdl; /* slimbus port handler */
|
||||
uint16_t port; /* slimbus port number */
|
||||
|
||||
uint8_t ch; /* slimbus channel number */
|
||||
uint16_t ch_hdl; /* slimbus channel handler */
|
||||
uint16_t grph; /* slimbus group channel handler */
|
||||
};
|
||||
|
||||
struct btfmslim {
|
||||
struct device *dev;
|
||||
struct slim_device *slim_pgd;
|
||||
struct slim_device slim_ifd;
|
||||
struct mutex io_lock;
|
||||
struct mutex xfer_lock;
|
||||
uint8_t enabled;
|
||||
|
||||
uint32_t num_rx_port;
|
||||
uint32_t num_tx_port;
|
||||
uint32_t sample_rate;
|
||||
|
||||
struct btfmslim_ch *rx_chs;
|
||||
struct btfmslim_ch *tx_chs;
|
||||
|
||||
int (*vendor_init)(struct btfmslim *btfmslim);
|
||||
int (*vendor_port_en)(struct btfmslim *btfmslim, uint8_t port_num,
|
||||
uint8_t rxport, uint8_t enable);
|
||||
};
|
||||
|
||||
extern int btfm_feedback_ch_setting;
|
||||
|
||||
/**
|
||||
* btfm_slim_hw_init: Initialize slimbus slave device
|
||||
* Returns:
|
||||
* 0: Success
|
||||
* else: Fail
|
||||
*/
|
||||
int btfm_slim_hw_init(struct btfmslim *btfmslim);
|
||||
|
||||
/**
|
||||
* btfm_slim_hw_deinit: Deinitialize slimbus slave device
|
||||
* Returns:
|
||||
* 0: Success
|
||||
* else: Fail
|
||||
*/
|
||||
int btfm_slim_hw_deinit(struct btfmslim *btfmslim);
|
||||
|
||||
/**
|
||||
* btfm_slim_write: write value to pgd or ifd device
|
||||
* @btfmslim: slimbus slave device data pointer.
|
||||
* @reg: slimbus slave register address
|
||||
* @bytes: length of data
|
||||
* @src: data pointer to write
|
||||
* @pgd: selection for device: either PGD or IFD
|
||||
* Returns:
|
||||
* -EINVAL
|
||||
* -ETIMEDOUT
|
||||
* -ENOMEM
|
||||
*/
|
||||
int btfm_slim_write(struct btfmslim *btfmslim,
|
||||
uint16_t reg, int bytes, void *src, uint8_t pgd);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* btfm_slim_read: read value from pgd or ifd device
|
||||
* @btfmslim: slimbus slave device data pointer.
|
||||
* @reg: slimbus slave register address
|
||||
* @bytes: length of data
|
||||
* @dest: data pointer to read
|
||||
* @pgd: selection for device: either PGD or IFD
|
||||
* Returns:
|
||||
* -EINVAL
|
||||
* -ETIMEDOUT
|
||||
* -ENOMEM
|
||||
*/
|
||||
int btfm_slim_read(struct btfmslim *btfmslim,
|
||||
uint16_t reg, int bytes, void *dest, uint8_t pgd);
|
||||
|
||||
|
||||
/**
|
||||
* btfm_slim_enable_ch: enable channel for slimbus slave port
|
||||
* @btfmslim: slimbus slave device data pointer.
|
||||
* @ch: slimbus slave channel pointer
|
||||
* @rxport: rxport or txport
|
||||
* Returns:
|
||||
* -EINVAL
|
||||
* -ETIMEDOUT
|
||||
* -ENOMEM
|
||||
*/
|
||||
int btfm_slim_enable_ch(struct btfmslim *btfmslim,
|
||||
struct btfmslim_ch *ch, uint8_t rxport, uint32_t rates,
|
||||
uint8_t grp, uint8_t nchan);
|
||||
|
||||
/**
|
||||
* btfm_slim_disable_ch: disable channel for slimbus slave port
|
||||
* @btfmslim: slimbus slave device data pointer.
|
||||
* @ch: slimbus slave channel pointer
|
||||
* @rxport: rxport or txport
|
||||
* Returns:
|
||||
* -EINVAL
|
||||
* -ETIMEDOUT
|
||||
* -ENOMEM
|
||||
*/
|
||||
int btfm_slim_disable_ch(struct btfmslim *btfmslim,
|
||||
struct btfmslim_ch *ch, uint8_t rxport, uint8_t grp, uint8_t nchan);
|
||||
|
||||
/**
|
||||
* btfm_slim_register_codec: Register codec driver in slimbus device node
|
||||
* @dev: device node
|
||||
* Returns:
|
||||
* -ENOMEM
|
||||
* 0
|
||||
*/
|
||||
int btfm_slim_register_codec(struct device *dev);
|
||||
|
||||
/**
|
||||
* btfm_slim_unregister_codec: Unregister codec driver in slimbus device node
|
||||
* @dev: device node
|
||||
* Returns:
|
||||
* VOID
|
||||
*/
|
||||
void btfm_slim_unregister_codec(struct device *dev);
|
||||
#endif /* BTFM_SLIM_H */
|
459
drivers/bluetooth/btfm_slim_codec.c
Normal file
459
drivers/bluetooth/btfm_slim_codec.c
Normal file
@ -0,0 +1,459 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/slimbus/slimbus.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
#include "btfm_slim.h"
|
||||
|
||||
static int bt_soc_enable_status;
|
||||
int btfm_feedback_ch_setting;
|
||||
|
||||
static int btfm_slim_codec_write(struct snd_soc_component *codec,
|
||||
unsigned int reg, unsigned int value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int btfm_slim_codec_read(struct snd_soc_component *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bt_soc_status_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
ucontrol->value.integer.value[0] = bt_soc_enable_status;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bt_soc_status_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int btfm_get_feedback_ch_setting(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
ucontrol->value.integer.value[0] = btfm_feedback_ch_setting;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int btfm_put_feedback_ch_setting(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
btfm_feedback_ch_setting = ucontrol->value.integer.value[0];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new status_controls[] = {
|
||||
SOC_SINGLE_EXT("BT SOC status", 0, 0, 1, 0,
|
||||
bt_soc_status_get,
|
||||
bt_soc_status_put),
|
||||
SOC_SINGLE_EXT("BT set feedback channel", 0, 0, 1, 0,
|
||||
btfm_get_feedback_ch_setting,
|
||||
btfm_put_feedback_ch_setting)
|
||||
};
|
||||
|
||||
|
||||
static int btfm_slim_codec_probe(struct snd_soc_component *codec)
|
||||
{
|
||||
snd_soc_add_component_controls(codec, status_controls,
|
||||
ARRAY_SIZE(status_controls));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btfm_slim_codec_remove(struct snd_soc_component *codec)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static int btfm_slim_dai_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int ret;
|
||||
struct btfmslim *btfmslim = dai->dev->platform_data;
|
||||
|
||||
BTFMSLIM_DBG("substream = %s stream = %d dai->name = %s",
|
||||
substream->name, substream->stream, dai->name);
|
||||
ret = btfm_slim_hw_init(btfmslim);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void btfm_slim_dai_shutdown(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int i;
|
||||
struct btfmslim *btfmslim = dai->dev->platform_data;
|
||||
struct btfmslim_ch *ch;
|
||||
uint8_t rxport, grp = false, nchan = 1;
|
||||
|
||||
BTFMSLIM_DBG("dai->name: %s, dai->id: %d, dai->rate: %d", dai->name,
|
||||
dai->id, dai->rate);
|
||||
|
||||
switch (dai->id) {
|
||||
case BTFM_FM_SLIM_TX:
|
||||
grp = true; nchan = 2;
|
||||
ch = btfmslim->tx_chs;
|
||||
rxport = 0;
|
||||
break;
|
||||
case BTFM_BT_SCO_SLIM_TX:
|
||||
ch = btfmslim->tx_chs;
|
||||
rxport = 0;
|
||||
break;
|
||||
case BTFM_BT_SCO_A2DP_SLIM_RX:
|
||||
case BTFM_BT_SPLIT_A2DP_SLIM_RX:
|
||||
ch = btfmslim->rx_chs;
|
||||
rxport = 1;
|
||||
break;
|
||||
case BTFM_SLIM_NUM_CODEC_DAIS:
|
||||
default:
|
||||
BTFMSLIM_ERR("dai->id is invalid:%d", dai->id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Search for dai->id matched port handler */
|
||||
for (i = 0; (i < BTFM_SLIM_NUM_CODEC_DAIS) &&
|
||||
(ch->id != BTFM_SLIM_NUM_CODEC_DAIS) &&
|
||||
(ch->id != dai->id); ch++, i++)
|
||||
;
|
||||
|
||||
if ((ch->port == BTFM_SLIM_PGD_PORT_LAST) ||
|
||||
(ch->id == BTFM_SLIM_NUM_CODEC_DAIS)) {
|
||||
BTFMSLIM_ERR("ch is invalid!!");
|
||||
return;
|
||||
}
|
||||
|
||||
btfm_slim_disable_ch(btfmslim, ch, rxport, grp, nchan);
|
||||
btfm_slim_hw_deinit(btfmslim);
|
||||
}
|
||||
|
||||
static int btfm_slim_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
BTFMSLIM_DBG("dai->name = %s DAI-ID %x rate %d num_ch %d",
|
||||
dai->name, dai->id, params_rate(params),
|
||||
params_channels(params));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btfm_slim_dai_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int i, ret = -EINVAL;
|
||||
struct btfmslim *btfmslim = dai->dev->platform_data;
|
||||
struct btfmslim_ch *ch;
|
||||
uint8_t rxport, grp = false, nchan = 1;
|
||||
|
||||
bt_soc_enable_status = 0;
|
||||
|
||||
BTFMSLIM_DBG("dai->name: %s, dai->id: %d, dai->rate: %d", dai->name,
|
||||
dai->id, dai->rate);
|
||||
|
||||
/* save sample rate */
|
||||
btfmslim->sample_rate = dai->rate;
|
||||
|
||||
switch (dai->id) {
|
||||
case BTFM_FM_SLIM_TX:
|
||||
grp = true; nchan = 2;
|
||||
ch = btfmslim->tx_chs;
|
||||
rxport = 0;
|
||||
break;
|
||||
case BTFM_BT_SCO_SLIM_TX:
|
||||
ch = btfmslim->tx_chs;
|
||||
rxport = 0;
|
||||
break;
|
||||
case BTFM_BT_SCO_A2DP_SLIM_RX:
|
||||
case BTFM_BT_SPLIT_A2DP_SLIM_RX:
|
||||
ch = btfmslim->rx_chs;
|
||||
rxport = 1;
|
||||
break;
|
||||
case BTFM_SLIM_NUM_CODEC_DAIS:
|
||||
default:
|
||||
BTFMSLIM_ERR("dai->id is invalid:%d", dai->id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Search for dai->id matched port handler */
|
||||
for (i = 0; (i < BTFM_SLIM_NUM_CODEC_DAIS) &&
|
||||
(ch->id != BTFM_SLIM_NUM_CODEC_DAIS) &&
|
||||
(ch->id != dai->id); ch++, i++)
|
||||
;
|
||||
|
||||
if ((ch->port == BTFM_SLIM_PGD_PORT_LAST) ||
|
||||
(ch->id == BTFM_SLIM_NUM_CODEC_DAIS)) {
|
||||
BTFMSLIM_ERR("ch is invalid!!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btfm_slim_enable_ch(btfmslim, ch, rxport, dai->rate, grp, nchan);
|
||||
|
||||
/* save the enable channel status */
|
||||
if (ret == 0)
|
||||
bt_soc_enable_status = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function will be called once during boot up */
|
||||
static int btfm_slim_dai_set_channel_map(struct snd_soc_dai *dai,
|
||||
unsigned int tx_num, unsigned int *tx_slot,
|
||||
unsigned int rx_num, unsigned int *rx_slot)
|
||||
{
|
||||
int ret = -EINVAL, i;
|
||||
struct btfmslim *btfmslim = dai->dev->platform_data;
|
||||
struct btfmslim_ch *rx_chs;
|
||||
struct btfmslim_ch *tx_chs;
|
||||
|
||||
BTFMSLIM_DBG("");
|
||||
|
||||
if (!btfmslim)
|
||||
return ret;
|
||||
|
||||
rx_chs = btfmslim->rx_chs;
|
||||
tx_chs = btfmslim->tx_chs;
|
||||
|
||||
if (!rx_chs || !tx_chs)
|
||||
return ret;
|
||||
|
||||
BTFMSLIM_DBG("Rx: id\tname\tport\thdl\tch\tch_hdl");
|
||||
for (i = 0; (rx_chs->port != BTFM_SLIM_PGD_PORT_LAST) && (i < rx_num);
|
||||
i++, rx_chs++) {
|
||||
/* Set Rx Channel number from machine driver and
|
||||
* get channel handler from slimbus driver
|
||||
*/
|
||||
rx_chs->ch = *(uint8_t *)(rx_slot + i);
|
||||
ret = slim_query_ch(btfmslim->slim_pgd, rx_chs->ch,
|
||||
&rx_chs->ch_hdl);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("slim_query_ch failure ch#%d - ret[%d]",
|
||||
rx_chs->ch, ret);
|
||||
goto error;
|
||||
}
|
||||
BTFMSLIM_DBG(" %d\t%s\t%d\t%x\t%d\t%x", rx_chs->id,
|
||||
rx_chs->name, rx_chs->port, rx_chs->port_hdl,
|
||||
rx_chs->ch, rx_chs->ch_hdl);
|
||||
}
|
||||
|
||||
BTFMSLIM_DBG("Tx: id\tname\tport\thdl\tch\tch_hdl");
|
||||
for (i = 0; (tx_chs->port != BTFM_SLIM_PGD_PORT_LAST) && (i < tx_num);
|
||||
i++, tx_chs++) {
|
||||
/* Set Tx Channel number from machine driver and
|
||||
* get channel handler from slimbus driver
|
||||
*/
|
||||
tx_chs->ch = *(uint8_t *)(tx_slot + i);
|
||||
ret = slim_query_ch(btfmslim->slim_pgd, tx_chs->ch,
|
||||
&tx_chs->ch_hdl);
|
||||
if (ret < 0) {
|
||||
BTFMSLIM_ERR("slim_query_ch failure ch#%d - ret[%d]",
|
||||
tx_chs->ch, ret);
|
||||
goto error;
|
||||
}
|
||||
BTFMSLIM_DBG(" %d\t%s\t%d\t%x\t%d\t%x", tx_chs->id,
|
||||
tx_chs->name, tx_chs->port, tx_chs->port_hdl,
|
||||
tx_chs->ch, tx_chs->ch_hdl);
|
||||
}
|
||||
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btfm_slim_dai_get_channel_map(struct snd_soc_dai *dai,
|
||||
unsigned int *tx_num, unsigned int *tx_slot,
|
||||
unsigned int *rx_num, unsigned int *rx_slot)
|
||||
{
|
||||
int i, ret = -EINVAL, *slot = NULL, j = 0, num = 1;
|
||||
struct btfmslim *btfmslim = dai->dev->platform_data;
|
||||
struct btfmslim_ch *ch = NULL;
|
||||
|
||||
if (!btfmslim)
|
||||
return ret;
|
||||
|
||||
switch (dai->id) {
|
||||
case BTFM_FM_SLIM_TX:
|
||||
num = 2;
|
||||
case BTFM_BT_SCO_SLIM_TX:
|
||||
if (!tx_slot || !tx_num) {
|
||||
BTFMSLIM_ERR("Invalid tx_slot %p or tx_num %p",
|
||||
tx_slot, tx_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
ch = btfmslim->tx_chs;
|
||||
if (!ch)
|
||||
return -EINVAL;
|
||||
slot = tx_slot;
|
||||
*rx_slot = 0;
|
||||
*tx_num = num;
|
||||
*rx_num = 0;
|
||||
break;
|
||||
case BTFM_BT_SCO_A2DP_SLIM_RX:
|
||||
case BTFM_BT_SPLIT_A2DP_SLIM_RX:
|
||||
if (!rx_slot || !rx_num) {
|
||||
BTFMSLIM_ERR("Invalid rx_slot %p or rx_num %p",
|
||||
rx_slot, rx_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
ch = btfmslim->rx_chs;
|
||||
if (!ch)
|
||||
return -EINVAL;
|
||||
slot = rx_slot;
|
||||
*tx_slot = 0;
|
||||
*tx_num = 0;
|
||||
*rx_num = num;
|
||||
break;
|
||||
default:
|
||||
BTFMSLIM_ERR("Unsupported DAI %d", dai->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
do {
|
||||
if (!ch)
|
||||
return -EINVAL;
|
||||
for (i = 0; (i < BTFM_SLIM_NUM_CODEC_DAIS) && (ch->id !=
|
||||
BTFM_SLIM_NUM_CODEC_DAIS) && (ch->id != dai->id);
|
||||
ch++, i++)
|
||||
;
|
||||
|
||||
if (ch->id == BTFM_SLIM_NUM_CODEC_DAIS ||
|
||||
i == BTFM_SLIM_NUM_CODEC_DAIS) {
|
||||
BTFMSLIM_ERR(
|
||||
"No channel has been allocated for dai (%d)",
|
||||
dai->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!slot)
|
||||
return -EINVAL;
|
||||
*(slot + j) = ch->ch;
|
||||
BTFMSLIM_DBG("id:%d, port:%d, ch:%d, slot: %d", ch->id,
|
||||
ch->port, ch->ch, *(slot + j));
|
||||
|
||||
/* In case it has mulitiple channels */
|
||||
if (++j < num)
|
||||
ch++;
|
||||
} while (j < num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_ops btfmslim_dai_ops = {
|
||||
.startup = btfm_slim_dai_startup,
|
||||
.shutdown = btfm_slim_dai_shutdown,
|
||||
.hw_params = btfm_slim_dai_hw_params,
|
||||
.prepare = btfm_slim_dai_prepare,
|
||||
.set_channel_map = btfm_slim_dai_set_channel_map,
|
||||
.get_channel_map = btfm_slim_dai_get_channel_map,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver btfmslim_dai[] = {
|
||||
{ /* FM Audio data multiple channel : FM -> qdsp */
|
||||
.name = "btfm_fm_slim_tx",
|
||||
.id = BTFM_FM_SLIM_TX,
|
||||
.capture = {
|
||||
.stream_name = "FM TX Capture",
|
||||
.rates = SNDRV_PCM_RATE_48000, /* 48 KHz */
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE, /* 16 bits */
|
||||
.rate_max = 48000,
|
||||
.rate_min = 48000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
},
|
||||
.ops = &btfmslim_dai_ops,
|
||||
},
|
||||
{ /* Bluetooth SCO voice uplink: bt -> modem */
|
||||
.name = "btfm_bt_sco_slim_tx",
|
||||
.id = BTFM_BT_SCO_SLIM_TX,
|
||||
.capture = {
|
||||
.stream_name = "SCO TX Capture",
|
||||
/* 8 KHz or 16 KHz */
|
||||
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000
|
||||
| SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000
|
||||
| SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE, /* 16 bits */
|
||||
.rate_max = 96000,
|
||||
.rate_min = 8000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 1,
|
||||
},
|
||||
.ops = &btfmslim_dai_ops,
|
||||
},
|
||||
{ /* Bluetooth SCO voice downlink: modem -> bt or A2DP Playback */
|
||||
.name = "btfm_bt_sco_a2dp_slim_rx",
|
||||
.id = BTFM_BT_SCO_A2DP_SLIM_RX,
|
||||
.playback = {
|
||||
.stream_name = "SCO A2DP RX Playback",
|
||||
/* 8/16/44.1/48/88.2/96 Khz */
|
||||
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000
|
||||
| SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000
|
||||
| SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE, /* 16 bits */
|
||||
.rate_max = 96000,
|
||||
.rate_min = 8000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 1,
|
||||
},
|
||||
.ops = &btfmslim_dai_ops,
|
||||
},
|
||||
{ /* Bluetooth Split A2DP data: qdsp -> bt */
|
||||
.name = "btfm_bt_split_a2dp_slim_rx",
|
||||
.id = BTFM_BT_SPLIT_A2DP_SLIM_RX,
|
||||
.playback = {
|
||||
.stream_name = "SPLIT A2DP Playback",
|
||||
.rates = SNDRV_PCM_RATE_48000, /* 48 KHz */
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE, /* 16 bits */
|
||||
.rate_max = 48000,
|
||||
.rate_min = 48000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 1,
|
||||
},
|
||||
.ops = &btfmslim_dai_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver btfmslim_codec = {
|
||||
.probe = btfm_slim_codec_probe,
|
||||
.remove = btfm_slim_codec_remove,
|
||||
.read = btfm_slim_codec_read,
|
||||
.write = btfm_slim_codec_write,
|
||||
};
|
||||
|
||||
int btfm_slim_register_codec(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
BTFMSLIM_DBG("");
|
||||
/* Register Codec driver */
|
||||
ret = snd_soc_register_component(dev, &btfmslim_codec,
|
||||
btfmslim_dai, ARRAY_SIZE(btfmslim_dai));
|
||||
|
||||
if (ret)
|
||||
BTFMSLIM_ERR("failed to register codec (%d)", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void btfm_slim_unregister_codec(struct device *dev)
|
||||
{
|
||||
BTFMSLIM_DBG("");
|
||||
/* Unregister Codec driver */
|
||||
snd_soc_unregister_component(dev);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("BTFM Slimbus Codec driver");
|
||||
MODULE_LICENSE("GPL v2");
|
189
drivers/bluetooth/btfm_slim_slave.c
Normal file
189
drivers/bluetooth/btfm_slim_slave.c
Normal file
@ -0,0 +1,189 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slimbus/slimbus.h>
|
||||
#include "btfm_slim.h"
|
||||
#include "btfm_slim_slave.h"
|
||||
|
||||
/* SLAVE (WCN3990/QCA6390) Port assignment */
|
||||
struct btfmslim_ch slave_rxport[] = {
|
||||
{.id = BTFM_BT_SCO_A2DP_SLIM_RX, .name = "SCO_A2P_Rx",
|
||||
.port = SLAVE_SB_PGD_PORT_RX_SCO},
|
||||
{.id = BTFM_BT_SPLIT_A2DP_SLIM_RX, .name = "A2P_Rx",
|
||||
.port = SLAVE_SB_PGD_PORT_RX_A2P},
|
||||
{.id = BTFM_SLIM_NUM_CODEC_DAIS, .name = "",
|
||||
.port = BTFM_SLIM_PGD_PORT_LAST},
|
||||
};
|
||||
|
||||
struct btfmslim_ch slave_txport[] = {
|
||||
{.id = BTFM_BT_SCO_SLIM_TX, .name = "SCO_Tx",
|
||||
.port = SLAVE_SB_PGD_PORT_TX_SCO},
|
||||
{.id = BTFM_FM_SLIM_TX, .name = "FM_Tx1",
|
||||
.port = SLAVE_SB_PGD_PORT_TX1_FM},
|
||||
{.id = BTFM_FM_SLIM_TX, .name = "FM_Tx2",
|
||||
.port = SLAVE_SB_PGD_PORT_TX2_FM},
|
||||
{.id = BTFM_SLIM_NUM_CODEC_DAIS, .name = "",
|
||||
.port = BTFM_SLIM_PGD_PORT_LAST},
|
||||
};
|
||||
|
||||
/* Function description */
|
||||
int btfm_slim_slave_hw_init(struct btfmslim *btfmslim)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t reg_val;
|
||||
uint16_t reg;
|
||||
|
||||
BTFMSLIM_DBG("");
|
||||
|
||||
if (!btfmslim)
|
||||
return -EINVAL;
|
||||
|
||||
/* Get SB_SLAVE_HW_REV_MSB value*/
|
||||
reg = SLAVE_SB_SLAVE_HW_REV_MSB;
|
||||
ret = btfm_slim_read(btfmslim, reg, 1, ®_val, IFD);
|
||||
if (ret) {
|
||||
BTFMSLIM_ERR("failed to read (%d) reg 0x%x", ret, reg);
|
||||
goto error;
|
||||
}
|
||||
BTFMSLIM_DBG("Major Rev: 0x%x, Minor Rev: 0x%x",
|
||||
(reg_val & 0xF0) >> 4, (reg_val & 0x0F));
|
||||
|
||||
/* Get SB_SLAVE_HW_REV_LSB value*/
|
||||
reg = SLAVE_SB_SLAVE_HW_REV_LSB;
|
||||
ret = btfm_slim_read(btfmslim, reg, 1, ®_val, IFD);
|
||||
if (ret) {
|
||||
BTFMSLIM_ERR("failed to read (%d) reg 0x%x", ret, reg);
|
||||
goto error;
|
||||
}
|
||||
BTFMSLIM_DBG("Step Rev: 0x%x", reg_val);
|
||||
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int is_fm_port(uint8_t port_num)
|
||||
{
|
||||
if (port_num == SLAVE_SB_PGD_PORT_TX1_FM ||
|
||||
port_num == CHRKVER3_SB_PGD_PORT_TX1_FM ||
|
||||
port_num == CHRKVER3_SB_PGD_PORT_TX2_FM ||
|
||||
port_num == SLAVE_SB_PGD_PORT_TX2_FM)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btfm_slim_slave_enable_port(struct btfmslim *btfmslim, uint8_t port_num,
|
||||
uint8_t rxport, uint8_t enable)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t reg_val = 0, en;
|
||||
uint8_t rxport_num = 0;
|
||||
uint16_t reg;
|
||||
|
||||
BTFMSLIM_DBG("port(%d) enable(%d)", port_num, enable);
|
||||
if (rxport) {
|
||||
BTFMSLIM_DBG("sample rate is %d", btfmslim->sample_rate);
|
||||
if (enable &&
|
||||
btfmslim->sample_rate != 44100 &&
|
||||
btfmslim->sample_rate != 88200) {
|
||||
BTFMSLIM_DBG("setting multichannel bit");
|
||||
/* For SCO Rx, A2DP Rx other than 44.1 and 88.2Khz */
|
||||
if (port_num < 24) {
|
||||
rxport_num = port_num - 16;
|
||||
reg_val = 0x01 << rxport_num;
|
||||
reg = SLAVE_SB_PGD_RX_PORTn_MULTI_CHNL_0(
|
||||
rxport_num);
|
||||
} else {
|
||||
rxport_num = port_num - 24;
|
||||
reg_val = 0x01 << rxport_num;
|
||||
reg = SLAVE_SB_PGD_RX_PORTn_MULTI_CHNL_1(
|
||||
rxport_num);
|
||||
}
|
||||
|
||||
BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
|
||||
reg_val, reg);
|
||||
ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD);
|
||||
if (ret) {
|
||||
BTFMSLIM_ERR("failed to write (%d) reg 0x%x",
|
||||
ret, reg);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
/* Port enable */
|
||||
reg = SLAVE_SB_PGD_PORT_RX_CFGN(port_num - 0x10);
|
||||
goto enable_disable_rxport;
|
||||
}
|
||||
if (!enable)
|
||||
goto enable_disable_txport;
|
||||
|
||||
/* txport */
|
||||
/* Multiple Channel Setting */
|
||||
if (is_fm_port(port_num)) {
|
||||
if (port_num == CHRKVER3_SB_PGD_PORT_TX1_FM)
|
||||
reg_val = (0x1 << CHRKVER3_SB_PGD_PORT_TX1_FM);
|
||||
else if (port_num == CHRKVER3_SB_PGD_PORT_TX2_FM)
|
||||
reg_val = (0x1 << CHRKVER3_SB_PGD_PORT_TX2_FM);
|
||||
else
|
||||
reg_val = (0x1 << SLAVE_SB_PGD_PORT_TX1_FM) |
|
||||
(0x1 << SLAVE_SB_PGD_PORT_TX2_FM);
|
||||
reg = SLAVE_SB_PGD_TX_PORTn_MULTI_CHNL_0(port_num);
|
||||
BTFMSLIM_INFO("writing reg_val (%d) to reg(%x)", reg_val, reg);
|
||||
ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD);
|
||||
if (ret) {
|
||||
BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg);
|
||||
goto error;
|
||||
}
|
||||
} else if (port_num == SLAVE_SB_PGD_PORT_TX_SCO) {
|
||||
/* SCO Tx */
|
||||
reg_val = 0x1 << SLAVE_SB_PGD_PORT_TX_SCO;
|
||||
reg = SLAVE_SB_PGD_TX_PORTn_MULTI_CHNL_0(port_num);
|
||||
BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
|
||||
reg_val, reg);
|
||||
ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD);
|
||||
if (ret) {
|
||||
BTFMSLIM_ERR("failed to write (%d) reg 0x%x",
|
||||
ret, reg);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable Tx port hw auto recovery for underrun or overrun error */
|
||||
reg_val = (SLAVE_ENABLE_OVERRUN_AUTO_RECOVERY |
|
||||
SLAVE_ENABLE_UNDERRUN_AUTO_RECOVERY);
|
||||
reg = SLAVE_SB_PGD_PORT_TX_OR_UR_CFGN(port_num);
|
||||
ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD);
|
||||
if (ret) {
|
||||
BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg);
|
||||
goto error;
|
||||
}
|
||||
|
||||
enable_disable_txport:
|
||||
/* Port enable */
|
||||
reg = SLAVE_SB_PGD_PORT_TX_CFGN(port_num);
|
||||
|
||||
enable_disable_rxport:
|
||||
if (enable)
|
||||
en = SLAVE_SB_PGD_PORT_ENABLE;
|
||||
else
|
||||
en = SLAVE_SB_PGD_PORT_DISABLE;
|
||||
|
||||
if (is_fm_port(port_num))
|
||||
reg_val = en | SLAVE_SB_PGD_PORT_WM_L8;
|
||||
else if (port_num == SLAVE_SB_PGD_PORT_TX_SCO)
|
||||
reg_val = enable ? en | SLAVE_SB_PGD_PORT_WM_L1 : en;
|
||||
else
|
||||
reg_val = enable ? en | SLAVE_SB_PGD_PORT_WM_LB : en;
|
||||
|
||||
if (enable && port_num == SLAVE_SB_PGD_PORT_TX_SCO)
|
||||
BTFMSLIM_INFO("programming SCO Tx with reg_val %d to reg 0x%x",
|
||||
reg_val, reg);
|
||||
|
||||
ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD);
|
||||
if (ret)
|
||||
BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg);
|
||||
|
||||
error:
|
||||
return ret;
|
||||
}
|
161
drivers/bluetooth/btfm_slim_slave.h
Normal file
161
drivers/bluetooth/btfm_slim_slave.h
Normal file
@ -0,0 +1,161 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef BTFM_SLIM_SLAVE_H
|
||||
#define BTFM_SLIM_SLAVE_H
|
||||
#include "btfm_slim.h"
|
||||
|
||||
/* Registers Address */
|
||||
#define SLAVE_SB_COMP_TEST 0x00000000
|
||||
#define SLAVE_SB_SLAVE_HW_REV_MSB 0x00000001
|
||||
#define SLAVE_SB_SLAVE_HW_REV_LSB 0x00000002
|
||||
#define SLAVE_SB_DEBUG_FEATURES 0x00000005
|
||||
#define SLAVE_SB_INTF_INT_EN 0x00000010
|
||||
#define SLAVE_SB_INTF_INT_STATUS 0x00000011
|
||||
#define SLAVE_SB_INTF_INT_CLR 0x00000012
|
||||
#define SLAVE_SB_FRM_CFG 0x00000013
|
||||
#define SLAVE_SB_FRM_STATUS 0x00000014
|
||||
#define SLAVE_SB_FRM_INT_EN 0x00000015
|
||||
#define SLAVE_SB_FRM_INT_STATUS 0x00000016
|
||||
#define SLAVE_SB_FRM_INT_CLR 0x00000017
|
||||
#define SLAVE_SB_FRM_WAKEUP 0x00000018
|
||||
#define SLAVE_SB_FRM_CLKCTL_DONE 0x00000019
|
||||
#define SLAVE_SB_FRM_IE_STATUS 0x0000001A
|
||||
#define SLAVE_SB_FRM_VE_STATUS 0x0000001B
|
||||
#define SLAVE_SB_PGD_TX_CFG_STATUS 0x00000020
|
||||
#define SLAVE_SB_PGD_RX_CFG_STATUS 0x00000021
|
||||
#define SLAVE_SB_PGD_DEV_INT_EN 0x00000022
|
||||
#define SLAVE_SB_PGD_DEV_INT_STATUS 0x00000023
|
||||
#define SLAVE_SB_PGD_DEV_INT_CLR 0x00000024
|
||||
#define SLAVE_SB_PGD_PORT_INT_EN_RX_0 0x00000030
|
||||
#define SLAVE_SB_PGD_PORT_INT_EN_RX_1 0x00000031
|
||||
#define SLAVE_SB_PGD_PORT_INT_EN_TX_0 0x00000032
|
||||
#define SLAVE_SB_PGD_PORT_INT_EN_TX_1 0x00000033
|
||||
#define SLAVE_SB_PGD_PORT_INT_STATUS_RX_0 0x00000034
|
||||
#define SLAVE_SB_PGD_PORT_INT_STATUS_RX_1 0x00000035
|
||||
#define SLAVE_SB_PGD_PORT_INT_STATUS_TX_0 0x00000036
|
||||
#define SLAVE_SB_PGD_PORT_INT_STATUS_TX_1 0x00000037
|
||||
#define SLAVE_SB_PGD_PORT_INT_CLR_RX_0 0x00000038
|
||||
#define SLAVE_SB_PGD_PORT_INT_CLR_RX_1 0x00000039
|
||||
#define SLAVE_SB_PGD_PORT_INT_CLR_TX_0 0x0000003A
|
||||
#define SLAVE_SB_PGD_PORT_INT_CLR_TX_1 0x0000003B
|
||||
#define SLAVE_SB_PGD_PORT_RX_CFGN(n) (0x00000040 + n)
|
||||
#define SLAVE_SB_PGD_PORT_TX_CFGN(n) (0x00000050 + n)
|
||||
#define SLAVE_SB_PGD_PORT_INT_RX_SOURCEN(n) (0x00000060 + n)
|
||||
#define SLAVE_SB_PGD_PORT_INT_TX_SOURCEN(n) (0x00000070 + n)
|
||||
#define SLAVE_SB_PGD_PORT_RX_STATUSN(n) (0x00000080 + n)
|
||||
#define SLAVE_SB_PGD_PORT_TX_STATUSN(n) (0x00000090 + n)
|
||||
#define SLAVE_SB_PGD_TX_PORTn_MULTI_CHNL_0(n) (0x00000100 + 0x4*n)
|
||||
#define SLAVE_SB_PGD_TX_PORTn_MULTI_CHNL_1(n) (0x00000101 + 0x4*n)
|
||||
#define SLAVE_SB_PGD_RX_PORTn_MULTI_CHNL_0(n) (0x00000180 + 0x4*n)
|
||||
#define SLAVE_SB_PGD_RX_PORTn_MULTI_CHNL_1(n) (0x00000181 + 0x4*n)
|
||||
#define SLAVE_SB_PGD_PORT_TX_OR_UR_CFGN(n) (0x000001F0 + n)
|
||||
|
||||
/* Register Bit Setting */
|
||||
#define SLAVE_ENABLE_OVERRUN_AUTO_RECOVERY (0x1 << 1)
|
||||
#define SLAVE_ENABLE_UNDERRUN_AUTO_RECOVERY (0x1 << 0)
|
||||
#define SLAVE_SB_PGD_PORT_ENABLE (0x1 << 0)
|
||||
#define SLAVE_SB_PGD_PORT_DISABLE (0x0 << 0)
|
||||
#define SLAVE_SB_PGD_PORT_WM_L1 (0x1 << 1)
|
||||
#define SLAVE_SB_PGD_PORT_WM_L2 (0x2 << 1)
|
||||
#define SLAVE_SB_PGD_PORT_WM_L3 (0x3 << 1)
|
||||
#define SLAVE_SB_PGD_PORT_WM_L8 (0x8 << 1)
|
||||
#define SLAVE_SB_PGD_PORT_WM_LB (0xB << 1)
|
||||
|
||||
#define SLAVE_SB_PGD_PORT_RX_NUM 16
|
||||
#define SLAVE_SB_PGD_PORT_TX_NUM 16
|
||||
|
||||
/* PGD Port Map */
|
||||
#define SLAVE_SB_PGD_PORT_TX_SCO 0
|
||||
#define SLAVE_SB_PGD_PORT_TX1_FM 1
|
||||
#define SLAVE_SB_PGD_PORT_TX2_FM 2
|
||||
#define CHRKVER3_SB_PGD_PORT_TX1_FM 4
|
||||
#define CHRKVER3_SB_PGD_PORT_TX2_FM 5
|
||||
#define SLAVE_SB_PGD_PORT_RX_SCO 16
|
||||
#define SLAVE_SB_PGD_PORT_RX_A2P 17
|
||||
|
||||
enum {
|
||||
QCA_CHEROKEE_SOC_ID_0200 = 0x40010200,
|
||||
QCA_CHEROKEE_SOC_ID_0201 = 0x40010201,
|
||||
QCA_CHEROKEE_SOC_ID_0210 = 0x40010214,
|
||||
QCA_CHEROKEE_SOC_ID_0211 = 0x40010224,
|
||||
QCA_CHEROKEE_SOC_ID_0310 = 0x40010310,
|
||||
QCA_CHEROKEE_SOC_ID_0320 = 0x40010320,
|
||||
QCA_CHEROKEE_SOC_ID_0320_UMC = 0x40014320,
|
||||
};
|
||||
|
||||
enum {
|
||||
QCA_APACHE_SOC_ID_0100 = 0x40020120,
|
||||
QCA_APACHE_SOC_ID_0110 = 0x40020130,
|
||||
QCA_APACHE_SOC_ID_0120 = 0x40020140,
|
||||
QCA_APACHE_SOC_ID_0121 = 0x40020150,
|
||||
};
|
||||
|
||||
enum {
|
||||
QCA_COMANCHE_SOC_ID_0101 = 0x40070101,
|
||||
QCA_COMANCHE_SOC_ID_0110 = 0x40070110,
|
||||
QCA_COMANCHE_SOC_ID_0120 = 0x40070120,
|
||||
};
|
||||
|
||||
enum {
|
||||
QCA_HASTINGS_SOC_ID_0200 = 0x400A0200,
|
||||
};
|
||||
|
||||
/* Function Prototype */
|
||||
|
||||
/*
|
||||
* btfm_slim_slave_hw_init: Initialize slave specific slimbus slave device
|
||||
* @btfmslim: slimbus slave device data pointer.
|
||||
* Returns:
|
||||
* 0: Success
|
||||
* else: Fail
|
||||
*/
|
||||
int btfm_slim_slave_hw_init(struct btfmslim *btfmslim);
|
||||
|
||||
/*
|
||||
* btfm_slim_slave_enable_rxport: Enable slave Rx port by given port number
|
||||
* @btfmslim: slimbus slave device data pointer.
|
||||
* @portNum: slimbus slave port number to enable
|
||||
* @rxport: rxport or txport
|
||||
* @enable: enable port or disable port
|
||||
* Returns:
|
||||
* 0: Success
|
||||
* else: Fail
|
||||
*/
|
||||
int btfm_slim_slave_enable_port(struct btfmslim *btfmslim, uint8_t portNum,
|
||||
uint8_t rxport, uint8_t enable);
|
||||
|
||||
/* Specific defines for slave slimbus device */
|
||||
#define SLAVE_SLIM_REG_OFFSET 0x0800
|
||||
|
||||
#ifdef SLIM_SLAVE_REG_OFFSET
|
||||
#undef SLIM_SLAVE_REG_OFFSET
|
||||
#define SLIM_SLAVE_REG_OFFSET SLAVE_SLIM_REG_OFFSET
|
||||
#endif
|
||||
|
||||
/* Assign vendor specific function */
|
||||
extern struct btfmslim_ch slave_txport[];
|
||||
extern struct btfmslim_ch slave_rxport[];
|
||||
|
||||
#ifdef SLIM_SLAVE_RXPORT
|
||||
#undef SLIM_SLAVE_RXPORT
|
||||
#define SLIM_SLAVE_RXPORT (&slave_rxport[0])
|
||||
#endif
|
||||
|
||||
#ifdef SLIM_SLAVE_TXPORT
|
||||
#undef SLIM_SLAVE_TXPORT
|
||||
#define SLIM_SLAVE_TXPORT (&slave_txport[0])
|
||||
#endif
|
||||
|
||||
#ifdef SLIM_SLAVE_INIT
|
||||
#undef SLIM_SLAVE_INIT
|
||||
#define SLIM_SLAVE_INIT btfm_slim_slave_hw_init
|
||||
#endif
|
||||
|
||||
#ifdef SLIM_SLAVE_PORT_EN
|
||||
#undef SLIM_SLAVE_PORT_EN
|
||||
#define SLIM_SLAVE_PORT_EN btfm_slim_slave_enable_port
|
||||
#endif
|
||||
#endif
|
772
drivers/bluetooth/btpower.c
Normal file
772
drivers/bluetooth/btpower.c
Normal file
@ -0,0 +1,772 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Bluetooth Power Switch Module
|
||||
* controls power to external Bluetooth device
|
||||
* with interface to power management device
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rfkill.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/btpower.h>
|
||||
|
||||
#if defined CONFIG_BT_SLIM_QCA6390 || \
|
||||
defined CONFIG_BT_SLIM_QCA6490 || \
|
||||
defined CONFIG_BTFM_SLIM_WCN3990
|
||||
#include "btfm_slim.h"
|
||||
#endif
|
||||
#include <linux/fs.h>
|
||||
|
||||
static const struct of_device_id bt_power_match_table[] = {
|
||||
{ .compatible = "qcom,qca6174" },
|
||||
{ .compatible = "qcom,wcn3990" },
|
||||
{ .compatible = "qcom,qca6390" },
|
||||
{ .compatible = "qcom,qca6490" },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct bt_power_vreg_data bt_power_vreg_info[] = {
|
||||
{NULL, "qcom,bt-vdd-aon", 950000, 950000, 0, false, true},
|
||||
{NULL, "qcom,bt-vdd-dig", 950000, 952000, 0, false, true},
|
||||
{NULL, "qcom,bt-vdd-rfa1", 1900000, 1900000, 0, false, true},
|
||||
{NULL, "qcom,bt-vdd-rfa2", 1900000, 1900000, 0, false, true},
|
||||
{NULL, "qcom,bt-vdd-asd", 0, 0, 0, false, false},
|
||||
};
|
||||
|
||||
#define BT_VREG_INFO_SIZE ARRAY_SIZE(bt_power_vreg_info)
|
||||
|
||||
static int bt_power_vreg_get(struct platform_device *pdev);
|
||||
static int bt_power_vreg_set(enum bt_power_modes mode);
|
||||
static void bt_power_vreg_put(void);
|
||||
|
||||
static struct bluetooth_power_platform_data *bt_power_pdata;
|
||||
static struct platform_device *btpdev;
|
||||
static bool previous;
|
||||
static int pwr_state;
|
||||
static struct class *bt_class;
|
||||
static int bt_major;
|
||||
static int soc_id;
|
||||
|
||||
static int bt_vreg_enable(struct bt_power_vreg_data *vreg)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
pr_debug("%s: vreg_en for : %s\n", __func__, vreg->name);
|
||||
|
||||
if (!vreg->is_enabled) {
|
||||
if ((vreg->min_vol != 0) && (vreg->max_vol != 0)) {
|
||||
rc = regulator_set_voltage(vreg->reg,
|
||||
vreg->min_vol,
|
||||
vreg->max_vol);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: regulator_set_voltage(%s) failed rc=%d\n",
|
||||
__func__, vreg->name, rc);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (vreg->load_curr >= 0) {
|
||||
rc = regulator_set_load(vreg->reg,
|
||||
vreg->load_curr);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: regulator_set_load(%s) failed rc=%d\n",
|
||||
__func__, vreg->name, rc);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
rc = regulator_enable(vreg->reg);
|
||||
if (rc < 0) {
|
||||
pr_err("regulator_enable(%s) failed. rc=%d\n",
|
||||
__func__, vreg->name, rc);
|
||||
goto out;
|
||||
}
|
||||
vreg->is_enabled = true;
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bt_vreg_enable_retention(struct bt_power_vreg_data *vreg)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!vreg)
|
||||
return rc;
|
||||
|
||||
pr_debug("%s: enable_retention for : %s\n", __func__, vreg->name);
|
||||
|
||||
if ((vreg->is_enabled) && (vreg->is_retention_supp)) {
|
||||
if ((vreg->min_vol != 0) && (vreg->max_vol != 0)) {
|
||||
/* Set the min voltage to 0 */
|
||||
rc = regulator_set_voltage(vreg->reg, 0, vreg->max_vol);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: regulator_set_voltage(%s) failed rc=%d\n",
|
||||
__func__, vreg->name, rc);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (vreg->load_curr >= 0) {
|
||||
rc = regulator_set_load(vreg->reg, 0);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: regulator_set_load(%s) failed rc=%d\n",
|
||||
__func__, vreg->name, rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bt_vreg_disable(struct bt_power_vreg_data *vreg)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!vreg)
|
||||
return rc;
|
||||
|
||||
pr_debug("vreg_disable for : %s\n", __func__, vreg->name);
|
||||
|
||||
if (vreg->is_enabled) {
|
||||
rc = regulator_disable(vreg->reg);
|
||||
if (rc < 0) {
|
||||
pr_err("%s, regulator_disable(%s) failed. rc=%d\n",
|
||||
__func__, vreg->name, rc);
|
||||
goto out;
|
||||
}
|
||||
vreg->is_enabled = false;
|
||||
|
||||
if ((vreg->min_vol != 0) && (vreg->max_vol != 0)) {
|
||||
/* Set the min voltage to 0 */
|
||||
rc = regulator_set_voltage(vreg->reg, 0,
|
||||
vreg->max_vol);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: regulator_set_voltage(%s) failed rc=%d\n",
|
||||
__func__, vreg->name, rc);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (vreg->load_curr >= 0) {
|
||||
rc = regulator_set_load(vreg->reg, 0);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: regulator_set_load(%s) failed rc=%d\n",
|
||||
__func__, vreg->name, rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bt_clk_enable(struct bt_power_clk_data *clk)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
pr_debug("%s: %s\n", __func__, clk->name);
|
||||
|
||||
/* Get the clock handle for vreg */
|
||||
if (!clk->clk || clk->is_enabled) {
|
||||
pr_err("%s: error - node: %p, clk->is_enabled:%d\n",
|
||||
__func__, clk->clk, clk->is_enabled);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = clk_prepare_enable(clk->clk);
|
||||
if (rc) {
|
||||
pr_err("%s: failed to enable %s, rc(%d)\n",
|
||||
__func__, clk->name, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
clk->is_enabled = true;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bt_clk_disable(struct bt_power_clk_data *clk)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
pr_debug("%s: %s\n", __func__, clk->name);
|
||||
|
||||
/* Get the clock handle for vreg */
|
||||
if (!clk->clk || !clk->is_enabled) {
|
||||
pr_err("%s: error - node: %p, clk->is_enabled:%d\n",
|
||||
__func__, clk->clk, clk->is_enabled);
|
||||
return -EINVAL;
|
||||
}
|
||||
clk_disable_unprepare(clk->clk);
|
||||
|
||||
clk->is_enabled = false;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bt_configure_gpios(int on)
|
||||
{
|
||||
int rc = 0;
|
||||
int bt_reset_gpio = bt_power_pdata->bt_gpio_sys_rst;
|
||||
|
||||
pr_debug("%s: bt_gpio= %d on: %d\n", __func__, bt_reset_gpio, on);
|
||||
|
||||
if (on) {
|
||||
rc = gpio_request(bt_reset_gpio, "bt_sys_rst_n");
|
||||
if (rc) {
|
||||
pr_err("%s: unable to request gpio %d (%d)\n",
|
||||
__func__, bt_reset_gpio, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = gpio_direction_output(bt_reset_gpio, 0);
|
||||
if (rc) {
|
||||
pr_err("%s: Unable to set direction\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
msleep(50);
|
||||
rc = gpio_direction_output(bt_reset_gpio, 1);
|
||||
if (rc) {
|
||||
pr_err("%s: Unable to set direction\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
msleep(50);
|
||||
} else {
|
||||
gpio_set_value(bt_reset_gpio, 0);
|
||||
msleep(100);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bluetooth_power(int on)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
pr_debug("%s: on: %d\n", __func__, on);
|
||||
|
||||
if (on == 1) {
|
||||
rc = bt_power_vreg_set(BT_POWER_ENABLE);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: bt_power regulators config failed\n",
|
||||
__func__);
|
||||
goto regulator_fail;
|
||||
}
|
||||
/* Parse dt_info and check if a target requires clock voting.
|
||||
* Enable BT clock when BT is on and disable it when BT is off
|
||||
*/
|
||||
if (bt_power_pdata->bt_chip_clk) {
|
||||
rc = bt_clk_enable(bt_power_pdata->bt_chip_clk);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: bt_power gpio config failed\n",
|
||||
__func__);
|
||||
goto clk_fail;
|
||||
}
|
||||
}
|
||||
if (bt_power_pdata->bt_gpio_sys_rst > 0) {
|
||||
rc = bt_configure_gpios(on);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: bt_power gpio config failed\n",
|
||||
__func__);
|
||||
goto gpio_fail;
|
||||
}
|
||||
}
|
||||
} else if (on == 0) {
|
||||
// Power Off
|
||||
if (bt_power_pdata->bt_gpio_sys_rst > 0)
|
||||
bt_configure_gpios(on);
|
||||
gpio_fail:
|
||||
if (bt_power_pdata->bt_gpio_sys_rst > 0)
|
||||
gpio_free(bt_power_pdata->bt_gpio_sys_rst);
|
||||
if (bt_power_pdata->bt_chip_clk)
|
||||
bt_clk_disable(bt_power_pdata->bt_chip_clk);
|
||||
clk_fail:
|
||||
regulator_fail:
|
||||
bt_power_vreg_set(BT_POWER_DISABLE);
|
||||
} else if (on == 2) {
|
||||
/* Retention mode */
|
||||
bt_power_vreg_set(BT_POWER_RETENTION);
|
||||
} else {
|
||||
pr_err("%s: Invalid power mode: %d\n", __func__, on);
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bluetooth_toggle_radio(void *data, bool blocked)
|
||||
{
|
||||
int ret = 0;
|
||||
int (*power_control)(int enable);
|
||||
|
||||
power_control =
|
||||
((struct bluetooth_power_platform_data *)data)->bt_power_setup;
|
||||
|
||||
if (previous != blocked)
|
||||
ret = (*power_control)(!blocked);
|
||||
if (!ret)
|
||||
previous = blocked;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct rfkill_ops bluetooth_power_rfkill_ops = {
|
||||
.set_block = bluetooth_toggle_radio,
|
||||
};
|
||||
|
||||
static ssize_t extldo_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return scnprintf(buf, 6, "false\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(extldo);
|
||||
|
||||
static int bluetooth_power_rfkill_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rfkill *rfkill;
|
||||
int ret;
|
||||
|
||||
rfkill = rfkill_alloc("bt_power", &pdev->dev, RFKILL_TYPE_BLUETOOTH,
|
||||
&bluetooth_power_rfkill_ops,
|
||||
pdev->dev.platform_data);
|
||||
|
||||
if (!rfkill) {
|
||||
dev_err(&pdev->dev, "rfkill allocate failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* add file into rfkill0 to handle LDO27 */
|
||||
ret = device_create_file(&pdev->dev, &dev_attr_extldo);
|
||||
if (ret < 0)
|
||||
pr_err("%s: device create file error\n", __func__);
|
||||
|
||||
/* force Bluetooth off during init to allow for user control */
|
||||
rfkill_init_sw_state(rfkill, 1);
|
||||
previous = true;
|
||||
|
||||
ret = rfkill_register(rfkill);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "rfkill register failed=%d\n", ret);
|
||||
rfkill_destroy(rfkill);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, rfkill);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bluetooth_power_rfkill_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rfkill *rfkill;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
rfkill = platform_get_drvdata(pdev);
|
||||
if (rfkill)
|
||||
rfkill_unregister(rfkill);
|
||||
rfkill_destroy(rfkill);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
#define MAX_PROP_SIZE 32
|
||||
static int bt_dt_parse_vreg_info(struct device *dev,
|
||||
struct bt_power_vreg_data **vreg_data, const char *vreg_name)
|
||||
{
|
||||
int len;
|
||||
const __be32 *prop;
|
||||
char prop_name[MAX_PROP_SIZE];
|
||||
struct bt_power_vreg_data *vreg = *vreg_data;
|
||||
struct device_node *np = dev->of_node;
|
||||
|
||||
pr_debug("%s: vreg dev tree parse for %s\n", __func__, vreg_name);
|
||||
|
||||
snprintf(prop_name, sizeof(prop_name), "%s-supply", vreg_name);
|
||||
if (of_parse_phandle(np, prop_name, 0)) {
|
||||
snprintf(prop_name, sizeof(prop_name), "%s-config", vreg->name);
|
||||
|
||||
prop = of_get_property(dev->of_node, prop_name, &len);
|
||||
if (!prop || len != (4 * sizeof(__be32))) {
|
||||
pr_debug("%s: Property %s %s, use default\n",
|
||||
__func__, prop_name,
|
||||
prop ? "invalid format" : "doesn't exist");
|
||||
} else {
|
||||
vreg->min_vol = be32_to_cpup(&prop[0]);
|
||||
vreg->max_vol = be32_to_cpup(&prop[1]);
|
||||
vreg->load_curr = be32_to_cpup(&prop[2]);
|
||||
vreg->is_retention_supp = be32_to_cpup(&prop[4]);
|
||||
}
|
||||
|
||||
pr_debug("%s: Got regulator: %s, min_vol: %u, max_vol: %u, load_curr: %u,is_retention_supp: %u\n",
|
||||
__func__, vreg->name, vreg->min_vol, vreg->max_vol,
|
||||
vreg->load_curr, vreg->is_retention_supp);
|
||||
} else
|
||||
pr_info("%s: %s is not provided in device tree\n",
|
||||
__func__, vreg_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bt_dt_parse_clk_info(struct device *dev,
|
||||
struct bt_power_clk_data **clk_data)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct bt_power_clk_data *clk = NULL;
|
||||
struct device_node *np = dev->of_node;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
*clk_data = NULL;
|
||||
if (of_parse_phandle(np, "clocks", 0)) {
|
||||
clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL);
|
||||
if (!clk) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Allocated 20 bytes size buffer for clock name string */
|
||||
clk->name = devm_kzalloc(dev, 20, GFP_KERNEL);
|
||||
|
||||
/* Parse clock name from node */
|
||||
ret = of_property_read_string_index(np, "clock-names", 0,
|
||||
&(clk->name));
|
||||
if (ret < 0) {
|
||||
pr_err("%s: reading \"clock-names\" failed\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
clk->clk = devm_clk_get(dev, clk->name);
|
||||
if (IS_ERR(clk->clk)) {
|
||||
ret = PTR_ERR(clk->clk);
|
||||
pr_err("%s: failed to get %s, ret (%d)\n",
|
||||
__func__, clk->name, ret);
|
||||
clk->clk = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
*clk_data = clk;
|
||||
} else {
|
||||
pr_err("%s: clocks is not provided in device tree\n", __func__);
|
||||
}
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bt_power_vreg_get(struct platform_device *pdev)
|
||||
{
|
||||
struct bt_power_vreg_data *vreg_info;
|
||||
int i = 0, ret = 0;
|
||||
|
||||
bt_power_pdata->vreg_info =
|
||||
devm_kzalloc(&(pdev->dev),
|
||||
sizeof(bt_power_vreg_info),
|
||||
GFP_KERNEL);
|
||||
if (!bt_power_pdata->vreg_info) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memcpy(bt_power_pdata->vreg_info, bt_power_vreg_info,
|
||||
sizeof(bt_power_vreg_info));
|
||||
|
||||
for (; i < BT_VREG_INFO_SIZE; i++) {
|
||||
vreg_info = &bt_power_pdata->vreg_info[i];
|
||||
ret = bt_dt_parse_vreg_info(&(pdev->dev), &vreg_info,
|
||||
vreg_info->name);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bt_power_vreg_set(enum bt_power_modes mode)
|
||||
{
|
||||
int i = 0, ret = 0;
|
||||
struct bt_power_vreg_data *vreg_info = NULL;
|
||||
struct device *dev = &btpdev->dev;
|
||||
|
||||
if (mode == BT_POWER_ENABLE) {
|
||||
for (; i < BT_VREG_INFO_SIZE; i++) {
|
||||
vreg_info = &bt_power_pdata->vreg_info[i];
|
||||
|
||||
/* set vreg handle if not already set */
|
||||
if (!(vreg_info->reg)) {
|
||||
vreg_info->reg = regulator_get(dev,
|
||||
vreg_info->name);
|
||||
if (IS_ERR(vreg_info->reg)) {
|
||||
ret = PTR_ERR(vreg_info->reg);
|
||||
vreg_info->reg = NULL;
|
||||
pr_err("%s: regulator_get(%s) failed. rc=%d\n",
|
||||
__func__, vreg_info->name, ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
ret = bt_vreg_enable(vreg_info);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
} else if (mode == BT_POWER_DISABLE) {
|
||||
for (; i < BT_VREG_INFO_SIZE; i++) {
|
||||
vreg_info = &bt_power_pdata->vreg_info[i];
|
||||
ret = bt_vreg_disable(vreg_info);
|
||||
}
|
||||
} else if (mode == BT_POWER_RETENTION) {
|
||||
for (; i < BT_VREG_INFO_SIZE; i++) {
|
||||
vreg_info = &bt_power_pdata->vreg_info[i];
|
||||
ret = bt_vreg_enable_retention(vreg_info);
|
||||
}
|
||||
} else {
|
||||
pr_err("%s: Invalid power mode: %d\n", __func__, mode);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bt_power_vreg_put(void)
|
||||
{
|
||||
int i = 0;
|
||||
struct bt_power_vreg_data *vreg_info = NULL;
|
||||
|
||||
for (; i < BT_VREG_INFO_SIZE; i++) {
|
||||
vreg_info = &bt_power_pdata->vreg_info[i];
|
||||
if (vreg_info->reg)
|
||||
regulator_put(vreg_info->reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int bt_power_populate_dt_pinfo(struct platform_device *pdev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
if (!bt_power_pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
bt_power_vreg_get(pdev);
|
||||
|
||||
bt_power_pdata->bt_gpio_sys_rst =
|
||||
of_get_named_gpio(pdev->dev.of_node,
|
||||
"qcom,bt-reset-gpio", 0);
|
||||
if (bt_power_pdata->bt_gpio_sys_rst < 0)
|
||||
pr_err("%s: bt-reset-gpio not provided in device tree\n",
|
||||
__func__);
|
||||
|
||||
rc = bt_dt_parse_clk_info(&pdev->dev,
|
||||
&bt_power_pdata->bt_chip_clk);
|
||||
if (rc < 0)
|
||||
pr_err("%s: clock not provided in device tree\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
bt_power_pdata->bt_power_setup = bluetooth_power;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bt_power_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
bt_power_pdata = kzalloc(sizeof(*bt_power_pdata), GFP_KERNEL);
|
||||
|
||||
if (!bt_power_pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
ret = bt_power_populate_dt_pinfo(pdev);
|
||||
if (ret < 0) {
|
||||
pr_err("%s, Failed to populate device tree info\n",
|
||||
__func__);
|
||||
goto free_pdata;
|
||||
}
|
||||
pdev->dev.platform_data = bt_power_pdata;
|
||||
} else if (pdev->dev.platform_data) {
|
||||
/* Optional data set to default if not provided */
|
||||
if (!((struct bluetooth_power_platform_data *)
|
||||
(pdev->dev.platform_data))->bt_power_setup)
|
||||
((struct bluetooth_power_platform_data *)
|
||||
(pdev->dev.platform_data))->bt_power_setup =
|
||||
bluetooth_power;
|
||||
|
||||
memcpy(bt_power_pdata, pdev->dev.platform_data,
|
||||
sizeof(struct bluetooth_power_platform_data));
|
||||
pwr_state = 0;
|
||||
} else {
|
||||
pr_err("%s: Failed to get platform data\n", __func__);
|
||||
goto free_pdata;
|
||||
}
|
||||
|
||||
if (bluetooth_power_rfkill_probe(pdev) < 0)
|
||||
goto free_pdata;
|
||||
|
||||
btpdev = pdev;
|
||||
|
||||
return 0;
|
||||
|
||||
free_pdata:
|
||||
kfree(bt_power_pdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bt_power_remove(struct platform_device *pdev)
|
||||
{
|
||||
dev_dbg(&pdev->dev, "%s\n", __func__);
|
||||
|
||||
bluetooth_power_rfkill_remove(pdev);
|
||||
bt_power_vreg_put();
|
||||
|
||||
kfree(bt_power_pdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btpower_register_slimdev(struct device *dev)
|
||||
{
|
||||
pr_debug("%s\n", __func__);
|
||||
if (!bt_power_pdata || (dev == NULL)) {
|
||||
pr_err("%s: Failed to allocate memory\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
bt_power_pdata->slim_dev = dev;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(btpower_register_slimdev);
|
||||
|
||||
int btpower_get_chipset_version(void)
|
||||
{
|
||||
pr_debug("%s\n", __func__);
|
||||
return soc_id;
|
||||
}
|
||||
EXPORT_SYMBOL(btpower_get_chipset_version);
|
||||
|
||||
static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = 0, pwr_cntrl = 0;
|
||||
int chipset_version = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case BT_CMD_SLIM_TEST:
|
||||
#if (defined CONFIG_BT_SLIM_QCA6390 || \
|
||||
defined CONFIG_BT_SLIM_QCA6490 || \
|
||||
defined CONFIG_BTFM_SLIM_WCN3990)
|
||||
if (!bt_power_pdata->slim_dev) {
|
||||
pr_err("%s: slim_dev is null\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = btfm_slim_hw_init(
|
||||
bt_power_pdata->slim_dev->platform_data
|
||||
);
|
||||
#endif
|
||||
break;
|
||||
case BT_CMD_PWR_CTRL:
|
||||
pwr_cntrl = (int)arg;
|
||||
pr_err("%s: BT_CMD_PWR_CTRL pwr_cntrl: %d\n",
|
||||
__func__, pwr_cntrl);
|
||||
if (pwr_state != pwr_cntrl) {
|
||||
ret = bluetooth_power(pwr_cntrl);
|
||||
if (!ret)
|
||||
pwr_state = pwr_cntrl;
|
||||
} else {
|
||||
pr_err("%s: BT chip state is already: %d no change\n",
|
||||
__func__, pwr_state);
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
case BT_CMD_CHIPSET_VERS:
|
||||
chipset_version = (int)arg;
|
||||
pr_err("%s: BT_CMD_CHIP_VERS soc_version:%x\n", __func__,
|
||||
chipset_version);
|
||||
if (chipset_version) {
|
||||
soc_id = chipset_version;
|
||||
} else {
|
||||
pr_err("%s: got invalid soc version\n");
|
||||
soc_id = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver bt_power_driver = {
|
||||
.probe = bt_power_probe,
|
||||
.remove = bt_power_remove,
|
||||
.driver = {
|
||||
.name = "bt_power",
|
||||
.of_match_table = bt_power_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct file_operations bt_dev_fops = {
|
||||
.unlocked_ioctl = bt_ioctl,
|
||||
.compat_ioctl = bt_ioctl,
|
||||
};
|
||||
|
||||
static int __init bluetooth_power_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = platform_driver_register(&bt_power_driver);
|
||||
if (ret) {
|
||||
pr_err("%s: platform_driver_register error: %d\n",
|
||||
__func__, ret);
|
||||
goto driver_err;
|
||||
}
|
||||
|
||||
bt_major = register_chrdev(0, "bt", &bt_dev_fops);
|
||||
if (bt_major < 0) {
|
||||
pr_err("%s: failed to allocate char dev\n", __func__);
|
||||
ret = -1;
|
||||
goto chrdev_err;
|
||||
}
|
||||
|
||||
bt_class = class_create(THIS_MODULE, "bt-dev");
|
||||
if (IS_ERR(bt_class)) {
|
||||
pr_err("%s: coudn't create class\n", __func__);
|
||||
ret = -1;
|
||||
goto class_err;
|
||||
}
|
||||
|
||||
|
||||
if (device_create(bt_class, NULL, MKDEV(bt_major, 0),
|
||||
NULL, "btpower") == NULL) {
|
||||
pr_err("%s: failed to allocate char dev\n", __func__);
|
||||
goto device_err;
|
||||
}
|
||||
return 0;
|
||||
|
||||
device_err:
|
||||
class_destroy(bt_class);
|
||||
class_err:
|
||||
unregister_chrdev(bt_major, "bt");
|
||||
chrdev_err:
|
||||
platform_driver_unregister(&bt_power_driver);
|
||||
driver_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit bluetooth_power_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&bt_power_driver);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("MSM Bluetooth power control driver");
|
||||
|
||||
module_init(bluetooth_power_init);
|
||||
module_exit(bluetooth_power_exit);
|
@ -200,6 +200,25 @@ config DA8XX_MSTPRI
|
||||
configuration. Allows to adjust the priorities of all master
|
||||
peripherals.
|
||||
|
||||
config MHI_BUS
|
||||
tristate "Modem Host Interface"
|
||||
help
|
||||
MHI Host Interface is a communication protocol to be used by the host
|
||||
to control and communcate with modem over a high speed peripheral bus.
|
||||
Enabling this module will allow host to communicate with external
|
||||
devices that support MHI protocol.
|
||||
|
||||
config MHI_DEBUG
|
||||
bool "MHI debug support"
|
||||
depends on MHI_BUS
|
||||
help
|
||||
Say yes here to enable debugging support in the MHI transport
|
||||
and individual MHI client drivers. This option will impact
|
||||
throughput as individual MHI packets and state transitions
|
||||
will be logged.
|
||||
|
||||
source "drivers/bus/fsl-mc/Kconfig"
|
||||
source "drivers/bus/mhi/controllers/Kconfig"
|
||||
source "drivers/bus/mhi/devices/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
@ -34,3 +34,4 @@ obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o
|
||||
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
|
||||
|
||||
obj-$(CONFIG_DA8XX_MSTPRI) += da8xx-mstpri.o
|
||||
obj-$(CONFIG_MHI_BUS) += mhi/
|
||||
|
9
drivers/bus/mhi/Makefile
Normal file
9
drivers/bus/mhi/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Makefile for the MHI stack
|
||||
#
|
||||
|
||||
# core layer
|
||||
obj-y += core/
|
||||
obj-y += controllers/
|
||||
obj-y += devices/
|
15
drivers/bus/mhi/controllers/Kconfig
Normal file
15
drivers/bus/mhi/controllers/Kconfig
Normal file
@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
menu "MHI controllers"
|
||||
|
||||
config MHI_QCOM
|
||||
tristate "MHI QCOM"
|
||||
depends on MHI_BUS
|
||||
help
|
||||
If you say yes to this option, MHI bus support for QCOM modem chipsets
|
||||
will be enabled. QCOM PCIe based modems uses MHI as the communication
|
||||
protocol. MHI control driver is the bus master for such modems. As the
|
||||
bus master driver, it oversees power management operations such as
|
||||
suspend, resume, powering on and off the device.
|
||||
|
||||
endmenu
|
4
drivers/bus/mhi/controllers/Makefile
Normal file
4
drivers/bus/mhi/controllers/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_MHI_QCOM) += mhi_qcom_drv.o
|
||||
mhi_qcom_drv-y := mhi_qcom.o mhi_arch_qcom.o
|
750
drivers/bus/mhi/controllers/mhi_arch_qcom.c
Normal file
750
drivers/bus/mhi/controllers/mhi_arch_qcom.c
Normal file
@ -0,0 +1,750 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.*/
|
||||
|
||||
#include <asm/dma-iommu.h>
|
||||
#include <linux/async.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/esoc_client.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/msm_pcie.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/mhi.h>
|
||||
#include "mhi_qcom.h"
|
||||
|
||||
struct arch_info {
|
||||
struct mhi_dev *mhi_dev;
|
||||
struct esoc_desc *esoc_client;
|
||||
struct esoc_client_hook esoc_ops;
|
||||
struct icc_path *icc_path;
|
||||
u32 *icc_peak_bw;
|
||||
u32 icc_peak_bw_len;
|
||||
struct msm_pcie_register_event pcie_reg_event;
|
||||
struct pci_saved_state *pcie_state;
|
||||
async_cookie_t cookie;
|
||||
void *boot_ipc_log;
|
||||
void *tsync_ipc_log;
|
||||
struct mhi_device *boot_dev;
|
||||
bool drv_connected;
|
||||
struct notifier_block pm_notifier;
|
||||
struct completion pm_completion;
|
||||
};
|
||||
|
||||
/* ipc log markings */
|
||||
#define DLOG "Dev->Host: "
|
||||
#define HLOG "Host: "
|
||||
|
||||
#define MHI_TSYNC_LOG_PAGES (10)
|
||||
|
||||
#ifdef CONFIG_MHI_DEBUG
|
||||
|
||||
#define MHI_IPC_LOG_PAGES (100)
|
||||
enum MHI_DEBUG_LEVEL mhi_ipc_log_lvl = MHI_MSG_LVL_VERBOSE;
|
||||
|
||||
#else
|
||||
|
||||
#define MHI_IPC_LOG_PAGES (10)
|
||||
enum MHI_DEBUG_LEVEL mhi_ipc_log_lvl = MHI_MSG_LVL_ERROR;
|
||||
|
||||
#endif
|
||||
|
||||
static int mhi_arch_pm_notifier(struct notifier_block *nb,
|
||||
unsigned long event, void *unused)
|
||||
{
|
||||
struct arch_info *arch_info =
|
||||
container_of(nb, struct arch_info, pm_notifier);
|
||||
|
||||
switch (event) {
|
||||
case PM_SUSPEND_PREPARE:
|
||||
reinit_completion(&arch_info->pm_completion);
|
||||
break;
|
||||
|
||||
case PM_POST_SUSPEND:
|
||||
complete_all(&arch_info->pm_completion);
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
void mhi_arch_timesync_log(struct mhi_controller *mhi_cntrl, u64 remote_time)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct arch_info *arch_info = mhi_dev->arch_info;
|
||||
|
||||
if (remote_time != U64_MAX)
|
||||
ipc_log_string(arch_info->tsync_ipc_log, "%6u.%06lu 0x%llx",
|
||||
REMOTE_TICKS_TO_SEC(remote_time),
|
||||
REMOTE_TIME_REMAINDER_US(remote_time),
|
||||
remote_time);
|
||||
}
|
||||
|
||||
static int mhi_arch_set_bus_request(struct mhi_controller *mhi_cntrl, int index)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct arch_info *arch_info = mhi_dev->arch_info;
|
||||
|
||||
MHI_LOG("Setting bus request to index %d\n", index);
|
||||
|
||||
if (index >= arch_info->icc_peak_bw_len)
|
||||
return -EINVAL;
|
||||
|
||||
if (arch_info->icc_path)
|
||||
return icc_set_bw(arch_info->icc_path, 0,
|
||||
arch_info->icc_peak_bw[index]);
|
||||
|
||||
/* default return success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mhi_arch_pci_link_state_cb(struct msm_pcie_notify *notify)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = notify->data;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
struct arch_info *arch_info = mhi_dev->arch_info;
|
||||
|
||||
switch (notify->event) {
|
||||
case MSM_PCIE_EVENT_WAKEUP:
|
||||
MHI_LOG("Received MSM_PCIE_EVENT_WAKE signal\n");
|
||||
|
||||
/* bring link out of d3cold */
|
||||
if (mhi_dev->powered_on) {
|
||||
pm_runtime_get(&pci_dev->dev);
|
||||
pm_runtime_put_noidle(&pci_dev->dev);
|
||||
}
|
||||
break;
|
||||
case MSM_PCIE_EVENT_L1SS_TIMEOUT:
|
||||
MHI_VERB("Received MSM_PCIE_EVENT_L1SS_TIMEOUT signal\n");
|
||||
|
||||
pm_runtime_mark_last_busy(&pci_dev->dev);
|
||||
pm_request_autosuspend(&pci_dev->dev);
|
||||
break;
|
||||
case MSM_PCIE_EVENT_DRV_CONNECT:
|
||||
/* drv is connected we can suspend now */
|
||||
MHI_LOG("Received MSM_PCIE_EVENT_DRV_CONNECT signal\n");
|
||||
|
||||
arch_info->drv_connected = true;
|
||||
|
||||
mutex_lock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
/* if we're in amss attempt a suspend */
|
||||
if (mhi_dev->powered_on && mhi_cntrl->ee == MHI_EE_AMSS) {
|
||||
pm_runtime_allow(&pci_dev->dev);
|
||||
pm_runtime_mark_last_busy(&pci_dev->dev);
|
||||
pm_request_autosuspend(&pci_dev->dev);
|
||||
}
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
break;
|
||||
case MSM_PCIE_EVENT_DRV_DISCONNECT:
|
||||
MHI_LOG("Received MSM_PCIE_EVENT_DRV_DISCONNECT signal\n");
|
||||
|
||||
/*
|
||||
* if link suspended bring it out of suspend and disable runtime
|
||||
* suspend
|
||||
*/
|
||||
arch_info->drv_connected = false;
|
||||
pm_runtime_forbid(&pci_dev->dev);
|
||||
break;
|
||||
default:
|
||||
MHI_ERR("Unhandled event 0x%x\n", notify->event);
|
||||
}
|
||||
}
|
||||
|
||||
static int mhi_arch_esoc_ops_power_on(void *priv, unsigned int flags)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = priv;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&mhi_cntrl->pm_mutex);
|
||||
if (mhi_dev->powered_on) {
|
||||
MHI_LOG("MHI still in active state\n");
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MHI_LOG("Enter\n");
|
||||
|
||||
/* reset rpm state */
|
||||
pm_runtime_set_active(&pci_dev->dev);
|
||||
pm_runtime_enable(&pci_dev->dev);
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
pm_runtime_forbid(&pci_dev->dev);
|
||||
ret = pm_runtime_get_sync(&pci_dev->dev);
|
||||
if (ret < 0) {
|
||||
MHI_ERR("Error with rpm resume, ret:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* re-start the link & recover default cfg states */
|
||||
ret = msm_pcie_pm_control(MSM_PCIE_RESUME, pci_dev->bus->number,
|
||||
pci_dev, NULL, 0);
|
||||
if (ret) {
|
||||
MHI_ERR("Failed to resume pcie bus ret %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mhi_dev->mdm_state = (flags & ESOC_HOOK_MDM_CRASH);
|
||||
return mhi_pci_probe(pci_dev, NULL);
|
||||
}
|
||||
|
||||
static void mhi_arch_link_off(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
|
||||
MHI_LOG("Entered\n");
|
||||
|
||||
pci_set_power_state(pci_dev, PCI_D3hot);
|
||||
|
||||
/* release the resources */
|
||||
msm_pcie_pm_control(MSM_PCIE_SUSPEND, mhi_cntrl->bus, pci_dev, NULL, 0);
|
||||
mhi_arch_set_bus_request(mhi_cntrl, 0);
|
||||
|
||||
MHI_LOG("Exited\n");
|
||||
}
|
||||
|
||||
static void mhi_arch_esoc_ops_power_off(void *priv, unsigned int flags)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = priv;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct arch_info *arch_info = mhi_dev->arch_info;
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
bool mdm_state = (flags & ESOC_HOOK_MDM_CRASH);
|
||||
|
||||
MHI_LOG("Enter: mdm_crashed:%d\n", mdm_state);
|
||||
|
||||
/*
|
||||
* Abort system suspend if system is preparing to go to suspend
|
||||
* by grabbing wake source.
|
||||
* If system is suspended, wait for pm notifier callback to notify
|
||||
* that resume has occurred with PM_POST_SUSPEND event.
|
||||
*/
|
||||
pm_stay_awake(&mhi_cntrl->mhi_dev->dev);
|
||||
wait_for_completion(&arch_info->pm_completion);
|
||||
|
||||
/* if link is in drv suspend, wake it up */
|
||||
pm_runtime_get_sync(&pci_dev->dev);
|
||||
|
||||
mutex_lock(&mhi_cntrl->pm_mutex);
|
||||
if (!mhi_dev->powered_on) {
|
||||
MHI_LOG("Not in active state\n");
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
pm_runtime_put_noidle(&pci_dev->dev);
|
||||
return;
|
||||
}
|
||||
mhi_dev->powered_on = false;
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
pm_runtime_put_noidle(&pci_dev->dev);
|
||||
|
||||
MHI_LOG("Triggering shutdown process\n");
|
||||
mhi_power_down(mhi_cntrl, !mdm_state);
|
||||
|
||||
/* turn the link off */
|
||||
mhi_deinit_pci_dev(mhi_cntrl);
|
||||
mhi_arch_link_off(mhi_cntrl);
|
||||
|
||||
/* wait for boot monitor to exit */
|
||||
async_synchronize_cookie(arch_info->cookie + 1);
|
||||
|
||||
mhi_arch_pcie_deinit(mhi_cntrl);
|
||||
mhi_cntrl->dev = NULL;
|
||||
|
||||
pm_relax(&mhi_cntrl->mhi_dev->dev);
|
||||
}
|
||||
|
||||
static void mhi_arch_esoc_ops_mdm_error(void *priv)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = priv;
|
||||
|
||||
MHI_LOG("Enter: mdm asserted\n");
|
||||
|
||||
/* transition MHI state into error state */
|
||||
mhi_control_error(mhi_cntrl);
|
||||
|
||||
MHI_LOG("Exit\n");
|
||||
}
|
||||
|
||||
static void mhi_bl_dl_cb(struct mhi_device *mhi_device,
|
||||
struct mhi_result *mhi_result)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = mhi_device->mhi_cntrl;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct arch_info *arch_info = mhi_dev->arch_info;
|
||||
char *buf = mhi_result->buf_addr;
|
||||
|
||||
/* force a null at last character */
|
||||
buf[mhi_result->bytes_xferd - 1] = 0;
|
||||
|
||||
ipc_log_string(arch_info->boot_ipc_log, "%s %s", DLOG, buf);
|
||||
}
|
||||
|
||||
static void mhi_bl_dummy_cb(struct mhi_device *mhi_dev,
|
||||
struct mhi_result *mhi_result)
|
||||
{
|
||||
}
|
||||
|
||||
static void mhi_bl_remove(struct mhi_device *mhi_device)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = mhi_device->mhi_cntrl;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct arch_info *arch_info = mhi_dev->arch_info;
|
||||
|
||||
arch_info->boot_dev = NULL;
|
||||
ipc_log_string(arch_info->boot_ipc_log,
|
||||
HLOG "Received Remove notif.\n");
|
||||
}
|
||||
|
||||
static void mhi_boot_monitor(void *data, async_cookie_t cookie)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = data;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct arch_info *arch_info = mhi_dev->arch_info;
|
||||
struct mhi_device *boot_dev;
|
||||
/* 15 sec timeout for booting device */
|
||||
const u32 timeout = msecs_to_jiffies(15000);
|
||||
|
||||
/* wait for device to enter boot stage */
|
||||
wait_event_timeout(mhi_cntrl->state_event, mhi_cntrl->ee == MHI_EE_AMSS
|
||||
|| mhi_cntrl->ee == MHI_EE_DISABLE_TRANSITION
|
||||
|| mhi_cntrl->power_down,
|
||||
timeout);
|
||||
|
||||
ipc_log_string(arch_info->boot_ipc_log, HLOG "Device current ee = %s\n",
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee));
|
||||
|
||||
/* if we successfully booted to amss disable boot log channel */
|
||||
if (mhi_cntrl->ee == MHI_EE_AMSS) {
|
||||
boot_dev = arch_info->boot_dev;
|
||||
if (boot_dev)
|
||||
mhi_unprepare_from_transfer(boot_dev);
|
||||
|
||||
if (!mhi_dev->drv_supported || arch_info->drv_connected)
|
||||
pm_runtime_allow(&mhi_dev->pci_dev->dev);
|
||||
}
|
||||
}
|
||||
|
||||
int mhi_arch_power_up(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct arch_info *arch_info = mhi_dev->arch_info;
|
||||
|
||||
/* start a boot monitor if not in crashed state */
|
||||
if (!mhi_dev->mdm_state)
|
||||
arch_info->cookie = async_schedule(mhi_boot_monitor, mhi_cntrl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mhi_arch_pcie_scale_bw(struct mhi_controller *mhi_cntrl,
|
||||
struct pci_dev *pci_dev,
|
||||
struct mhi_link_info *link_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mhi_cntrl->lpm_disable(mhi_cntrl, mhi_cntrl->priv_data);
|
||||
ret = msm_pcie_set_link_bandwidth(pci_dev, link_info->target_link_speed,
|
||||
link_info->target_link_width);
|
||||
mhi_cntrl->lpm_enable(mhi_cntrl, mhi_cntrl->priv_data);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* do a bus scale vote based on gen speeds */
|
||||
mhi_arch_set_bus_request(mhi_cntrl, link_info->target_link_speed);
|
||||
|
||||
MHI_VERB("bw changed to speed:0x%x width:0x%x\n",
|
||||
link_info->target_link_speed, link_info->target_link_width);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mhi_arch_bw_scale(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_link_info *link_info)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
|
||||
return mhi_arch_pcie_scale_bw(mhi_cntrl, pci_dev, link_info);
|
||||
}
|
||||
|
||||
static int mhi_bl_probe(struct mhi_device *mhi_device,
|
||||
const struct mhi_device_id *id)
|
||||
{
|
||||
char node_name[32];
|
||||
struct mhi_controller *mhi_cntrl = mhi_device->mhi_cntrl;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct arch_info *arch_info = mhi_dev->arch_info;
|
||||
|
||||
snprintf(node_name, sizeof(node_name), "mhi_bl_%04x_%02u.%02u.%02u",
|
||||
mhi_device->dev_id, mhi_device->domain, mhi_device->bus,
|
||||
mhi_device->slot);
|
||||
|
||||
arch_info->boot_dev = mhi_device;
|
||||
arch_info->boot_ipc_log = ipc_log_context_create(MHI_IPC_LOG_PAGES,
|
||||
node_name, 0);
|
||||
ipc_log_string(arch_info->boot_ipc_log, HLOG
|
||||
"Entered SBL, Session ID:0x%x\n", mhi_cntrl->session_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mhi_device_id mhi_bl_match_table[] = {
|
||||
{ .chan = "BL" },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct mhi_driver mhi_bl_driver = {
|
||||
.id_table = mhi_bl_match_table,
|
||||
.remove = mhi_bl_remove,
|
||||
.probe = mhi_bl_probe,
|
||||
.ul_xfer_cb = mhi_bl_dummy_cb,
|
||||
.dl_xfer_cb = mhi_bl_dl_cb,
|
||||
.driver = {
|
||||
.name = "MHI_BL",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct arch_info *arch_info = mhi_dev->arch_info;
|
||||
struct mhi_link_info *cur_link_info;
|
||||
char node[32];
|
||||
int ret;
|
||||
int size = 0;
|
||||
u16 linkstat;
|
||||
|
||||
if (!arch_info) {
|
||||
struct msm_pcie_register_event *reg_event;
|
||||
struct pci_dev *root_port;
|
||||
struct device_node *root_ofnode;
|
||||
|
||||
arch_info = devm_kzalloc(&mhi_dev->pci_dev->dev,
|
||||
sizeof(*arch_info), GFP_KERNEL);
|
||||
if (!arch_info)
|
||||
return -ENOMEM;
|
||||
|
||||
mhi_dev->arch_info = arch_info;
|
||||
arch_info->mhi_dev = mhi_dev;
|
||||
|
||||
snprintf(node, sizeof(node), "mhi_%04x_%02u.%02u.%02u",
|
||||
mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus,
|
||||
mhi_cntrl->slot);
|
||||
mhi_cntrl->log_buf = ipc_log_context_create(MHI_IPC_LOG_PAGES,
|
||||
node, 0);
|
||||
mhi_cntrl->log_lvl = mhi_ipc_log_lvl;
|
||||
|
||||
snprintf(node, sizeof(node), "mhi_tsync_%04x_%02u.%02u.%02u",
|
||||
mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus,
|
||||
mhi_cntrl->slot);
|
||||
arch_info->tsync_ipc_log = ipc_log_context_create(
|
||||
MHI_TSYNC_LOG_PAGES, node, 0);
|
||||
if (arch_info->tsync_ipc_log)
|
||||
mhi_cntrl->tsync_log = mhi_arch_timesync_log;
|
||||
|
||||
/* check if root-complex support DRV */
|
||||
root_port = pci_find_pcie_root_port(mhi_dev->pci_dev);
|
||||
root_ofnode = root_port->dev.of_node;
|
||||
if (root_ofnode->parent)
|
||||
mhi_dev->drv_supported =
|
||||
of_property_read_bool(root_ofnode->parent,
|
||||
"qcom,drv-supported");
|
||||
|
||||
/* get icc path from PCIe platform device */
|
||||
arch_info->icc_path = of_icc_get(root_port->dev.parent->parent,
|
||||
"ep_icc_path");
|
||||
if (IS_ERR_OR_NULL(arch_info->icc_path)) {
|
||||
ret = arch_info->icc_path ?
|
||||
PTR_ERR(arch_info->icc_path) : -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
of_get_property(pdev->dev.of_node, "icc_peak_bw", &size);
|
||||
if (!size)
|
||||
return -EINVAL;
|
||||
|
||||
arch_info->icc_peak_bw_len = size / sizeof(u32);
|
||||
arch_info->icc_peak_bw = devm_kcalloc(&mhi_dev->pci_dev->dev,
|
||||
arch_info->icc_peak_bw_len,
|
||||
sizeof(u32), GFP_KERNEL);
|
||||
if (!arch_info->icc_peak_bw)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_property_read_u32_array(mhi_dev->pci_dev->dev.of_node,
|
||||
"icc-peak-bw", arch_info->icc_peak_len);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
/* register with pcie rc for WAKE# events */
|
||||
reg_event = &arch_info->pcie_reg_event;
|
||||
reg_event->events =
|
||||
MSM_PCIE_EVENT_WAKEUP | MSM_PCIE_EVENT_L1SS_TIMEOUT;
|
||||
|
||||
/* if drv supported register for drv connection events */
|
||||
if (mhi_dev->drv_supported)
|
||||
reg_event->events |= MSM_PCIE_EVENT_DRV_CONNECT |
|
||||
MSM_PCIE_EVENT_DRV_DISCONNECT;
|
||||
reg_event->user = mhi_dev->pci_dev;
|
||||
reg_event->callback = mhi_arch_pci_link_state_cb;
|
||||
reg_event->notify.data = mhi_cntrl;
|
||||
ret = msm_pcie_register_event(reg_event);
|
||||
if (ret)
|
||||
MHI_LOG("Failed to reg. for link up notification\n");
|
||||
|
||||
init_completion(&arch_info->pm_completion);
|
||||
|
||||
/* register PM notifier to get post resume events */
|
||||
arch_info->pm_notifier.notifier_call = mhi_arch_pm_notifier;
|
||||
register_pm_notifier(&arch_info->pm_notifier);
|
||||
|
||||
/*
|
||||
* Mark as completed at initial boot-up to allow ESOC power on
|
||||
* callback to proceed if system has not gone to suspend
|
||||
*/
|
||||
complete_all(&arch_info->pm_completion);
|
||||
|
||||
arch_info->esoc_client = devm_register_esoc_client(
|
||||
&mhi_dev->pci_dev->dev, "mdm");
|
||||
if (IS_ERR_OR_NULL(arch_info->esoc_client)) {
|
||||
MHI_ERR("Failed to register esoc client\n");
|
||||
} else {
|
||||
/* register for power on/off hooks */
|
||||
struct esoc_client_hook *esoc_ops =
|
||||
&arch_info->esoc_ops;
|
||||
|
||||
esoc_ops->priv = mhi_cntrl;
|
||||
esoc_ops->prio = ESOC_MHI_HOOK;
|
||||
esoc_ops->esoc_link_power_on =
|
||||
mhi_arch_esoc_ops_power_on;
|
||||
esoc_ops->esoc_link_power_off =
|
||||
mhi_arch_esoc_ops_power_off;
|
||||
esoc_ops->esoc_link_mdm_crash =
|
||||
mhi_arch_esoc_ops_mdm_error;
|
||||
|
||||
ret = esoc_register_client_hook(arch_info->esoc_client,
|
||||
esoc_ops);
|
||||
if (ret)
|
||||
MHI_ERR("Failed to register esoc ops\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* MHI host driver has full autonomy to manage power state.
|
||||
* Disable all automatic power collapse features
|
||||
*/
|
||||
msm_pcie_pm_control(MSM_PCIE_DISABLE_PC, mhi_cntrl->bus,
|
||||
mhi_dev->pci_dev, NULL, 0);
|
||||
mhi_dev->pci_dev->no_d3hot = true;
|
||||
|
||||
mhi_cntrl->bw_scale = mhi_arch_bw_scale;
|
||||
|
||||
mhi_driver_register(&mhi_bl_driver);
|
||||
}
|
||||
|
||||
/* store the current bw info */
|
||||
ret = pcie_capability_read_word(mhi_dev->pci_dev,
|
||||
PCI_EXP_LNKSTA, &linkstat);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cur_link_info = &mhi_cntrl->mhi_link_info;
|
||||
cur_link_info->target_link_speed = linkstat & PCI_EXP_LNKSTA_CLS;
|
||||
cur_link_info->target_link_width = (linkstat & PCI_EXP_LNKSTA_NLW) >>
|
||||
PCI_EXP_LNKSTA_NLW_SHIFT;
|
||||
|
||||
return mhi_arch_set_bus_request(mhi_cntrl,
|
||||
cur_link_info->target_link_speed);
|
||||
}
|
||||
|
||||
void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
mhi_arch_set_bus_request(mhi_cntrl, 0);
|
||||
}
|
||||
|
||||
static int mhi_arch_drv_suspend(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
struct mhi_link_info link_info, *cur_link_info;
|
||||
bool bw_switched = false;
|
||||
int ret;
|
||||
|
||||
cur_link_info = &mhi_cntrl->mhi_link_info;
|
||||
/* if link is not in gen 1 we need to switch to gen 1 */
|
||||
if (cur_link_info->target_link_speed != PCI_EXP_LNKSTA_CLS_2_5GB) {
|
||||
link_info.target_link_speed = PCI_EXP_LNKSTA_CLS_2_5GB;
|
||||
link_info.target_link_width = cur_link_info->target_link_width;
|
||||
ret = mhi_arch_pcie_scale_bw(mhi_cntrl, pci_dev, &link_info);
|
||||
if (ret) {
|
||||
MHI_ERR("Failed to switch Gen1 speed\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
bw_switched = true;
|
||||
}
|
||||
|
||||
/* do a drv hand off */
|
||||
ret = msm_pcie_pm_control(MSM_PCIE_DRV_SUSPEND, mhi_cntrl->bus,
|
||||
pci_dev, NULL, 0);
|
||||
|
||||
/*
|
||||
* we failed to suspend and scaled down pcie bw.. need to scale up again
|
||||
*/
|
||||
if (ret && bw_switched) {
|
||||
mhi_arch_pcie_scale_bw(mhi_cntrl, pci_dev, cur_link_info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mhi_arch_link_suspend(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct arch_info *arch_info = mhi_dev->arch_info;
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
int ret = 0;
|
||||
|
||||
MHI_LOG("Entered\n");
|
||||
|
||||
/* disable inactivity timer */
|
||||
msm_pcie_l1ss_timeout_disable(pci_dev);
|
||||
|
||||
switch (mhi_dev->suspend_mode) {
|
||||
case MHI_DEFAULT_SUSPEND:
|
||||
pci_clear_master(pci_dev);
|
||||
ret = pci_save_state(mhi_dev->pci_dev);
|
||||
if (ret) {
|
||||
MHI_ERR("Failed with pci_save_state, ret:%d\n", ret);
|
||||
goto exit_suspend;
|
||||
}
|
||||
|
||||
arch_info->pcie_state = pci_store_saved_state(pci_dev);
|
||||
pci_disable_device(pci_dev);
|
||||
|
||||
pci_set_power_state(pci_dev, PCI_D3hot);
|
||||
|
||||
/* release the resources */
|
||||
msm_pcie_pm_control(MSM_PCIE_SUSPEND, mhi_cntrl->bus, pci_dev,
|
||||
NULL, 0);
|
||||
mhi_arch_set_bus_request(mhi_cntrl, 0);
|
||||
break;
|
||||
case MHI_FAST_LINK_OFF:
|
||||
ret = mhi_arch_drv_suspend(mhi_cntrl);
|
||||
break;
|
||||
case MHI_ACTIVE_STATE:
|
||||
case MHI_FAST_LINK_ON:/* keeping link on do nothing */
|
||||
break;
|
||||
}
|
||||
|
||||
exit_suspend:
|
||||
if (ret)
|
||||
msm_pcie_l1ss_timeout_enable(pci_dev);
|
||||
|
||||
MHI_LOG("Exited with ret:%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __mhi_arch_link_resume(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct arch_info *arch_info = mhi_dev->arch_info;
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
struct mhi_link_info *cur_info = &mhi_cntrl->mhi_link_info;
|
||||
int ret;
|
||||
|
||||
MHI_LOG("Entered\n");
|
||||
|
||||
/* request bus scale voting based on higher gen speed */
|
||||
ret = mhi_arch_set_bus_request(mhi_cntrl,
|
||||
cur_info->target_link_speed);
|
||||
if (ret)
|
||||
MHI_LOG("Could not set bus frequency, ret:%d\n", ret);
|
||||
|
||||
ret = msm_pcie_pm_control(MSM_PCIE_RESUME, mhi_cntrl->bus, pci_dev,
|
||||
NULL, 0);
|
||||
if (ret) {
|
||||
MHI_ERR("Link training failed, ret:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = pci_set_power_state(pci_dev, PCI_D0);
|
||||
if (ret) {
|
||||
MHI_ERR("Failed to set PCI_D0 state, ret:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = pci_enable_device(pci_dev);
|
||||
if (ret) {
|
||||
MHI_ERR("Failed to enable device, ret:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = pci_load_and_free_saved_state(pci_dev, &arch_info->pcie_state);
|
||||
if (ret)
|
||||
MHI_LOG("Failed to load saved cfg state\n");
|
||||
|
||||
pci_restore_state(pci_dev);
|
||||
pci_set_master(pci_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mhi_arch_link_resume(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
struct mhi_link_info *cur_info = &mhi_cntrl->mhi_link_info;
|
||||
int ret = 0;
|
||||
|
||||
MHI_LOG("Entered\n");
|
||||
|
||||
switch (mhi_dev->suspend_mode) {
|
||||
case MHI_DEFAULT_SUSPEND:
|
||||
ret = __mhi_arch_link_resume(mhi_cntrl);
|
||||
break;
|
||||
case MHI_FAST_LINK_OFF:
|
||||
ret = msm_pcie_pm_control(MSM_PCIE_RESUME, mhi_cntrl->bus,
|
||||
pci_dev, NULL, 0);
|
||||
if (ret ||
|
||||
cur_info->target_link_speed == PCI_EXP_LNKSTA_CLS_2_5GB)
|
||||
break;
|
||||
|
||||
/*
|
||||
* BW request from device isn't for gen 1 link speed, we can
|
||||
* only print an error here.
|
||||
*/
|
||||
if (mhi_arch_pcie_scale_bw(mhi_cntrl, pci_dev, cur_info))
|
||||
MHI_ERR(
|
||||
"Failed to honor bw request: speed:0x%x width:0x%x\n",
|
||||
cur_info->target_link_speed,
|
||||
cur_info->target_link_width);
|
||||
break;
|
||||
case MHI_ACTIVE_STATE:
|
||||
case MHI_FAST_LINK_ON:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
MHI_ERR("Link training failed, ret:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
msm_pcie_l1ss_timeout_enable(pci_dev);
|
||||
|
||||
MHI_LOG("Exited\n");
|
||||
|
||||
return 0;
|
||||
}
|
941
drivers/bus/mhi/controllers/mhi_qcom.c
Normal file
941
drivers/bus/mhi/controllers/mhi_qcom.c
Normal file
@ -0,0 +1,941 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.*/
|
||||
|
||||
#include <asm/arch_timer.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/mhi.h>
|
||||
#include "mhi_qcom.h"
|
||||
|
||||
struct firmware_info {
|
||||
unsigned int dev_id;
|
||||
const char *fw_image;
|
||||
const char *edl_image;
|
||||
};
|
||||
|
||||
static const struct firmware_info firmware_table[] = {
|
||||
{.dev_id = 0x306, .fw_image = "sdx55m/sbl1.mbn"},
|
||||
{.dev_id = 0x305, .fw_image = "sdx50m/sbl1.mbn"},
|
||||
{.dev_id = 0x304, .fw_image = "sbl.mbn", .edl_image = "edl.mbn"},
|
||||
/* default, set to debug.mbn */
|
||||
{.fw_image = "debug.mbn"},
|
||||
};
|
||||
|
||||
static int debug_mode;
|
||||
|
||||
int mhi_debugfs_trigger_m0(void *data, u64 val)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = data;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
MHI_LOG("Trigger M3 Exit\n");
|
||||
pm_runtime_get(&mhi_dev->pci_dev->dev);
|
||||
pm_runtime_put(&mhi_dev->pci_dev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(debugfs_trigger_m0_fops, NULL,
|
||||
mhi_debugfs_trigger_m0, "%llu\n");
|
||||
|
||||
int mhi_debugfs_trigger_m3(void *data, u64 val)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = data;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
MHI_LOG("Trigger M3 Entry\n");
|
||||
pm_runtime_mark_last_busy(&mhi_dev->pci_dev->dev);
|
||||
pm_request_autosuspend(&mhi_dev->pci_dev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(debugfs_trigger_m3_fops, NULL,
|
||||
mhi_debugfs_trigger_m3, "%llu\n");
|
||||
|
||||
void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
|
||||
pm_runtime_mark_last_busy(&pci_dev->dev);
|
||||
pm_runtime_dont_use_autosuspend(&pci_dev->dev);
|
||||
pm_runtime_disable(&pci_dev->dev);
|
||||
|
||||
/* reset counter for lpm state changes */
|
||||
mhi_dev->lpm_disable_depth = 0;
|
||||
|
||||
pci_free_irq_vectors(pci_dev);
|
||||
kfree(mhi_cntrl->irq);
|
||||
mhi_cntrl->irq = NULL;
|
||||
iounmap(mhi_cntrl->regs);
|
||||
mhi_cntrl->regs = NULL;
|
||||
pci_clear_master(pci_dev);
|
||||
pci_release_region(pci_dev, mhi_dev->resn);
|
||||
pci_disable_device(pci_dev);
|
||||
}
|
||||
|
||||
static int mhi_init_pci_dev(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
int ret;
|
||||
resource_size_t len;
|
||||
int i;
|
||||
|
||||
mhi_dev->resn = MHI_PCI_BAR_NUM;
|
||||
ret = pci_assign_resource(pci_dev, mhi_dev->resn);
|
||||
if (ret) {
|
||||
MHI_ERR("Error assign pci resources, ret:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = pci_enable_device(pci_dev);
|
||||
if (ret) {
|
||||
MHI_ERR("Error enabling device, ret:%d\n", ret);
|
||||
goto error_enable_device;
|
||||
}
|
||||
|
||||
ret = pci_request_region(pci_dev, mhi_dev->resn, "mhi");
|
||||
if (ret) {
|
||||
MHI_ERR("Error pci_request_region, ret:%d\n", ret);
|
||||
goto error_request_region;
|
||||
}
|
||||
|
||||
pci_set_master(pci_dev);
|
||||
|
||||
mhi_cntrl->base_addr = pci_resource_start(pci_dev, mhi_dev->resn);
|
||||
len = pci_resource_len(pci_dev, mhi_dev->resn);
|
||||
mhi_cntrl->regs = ioremap(mhi_cntrl->base_addr, len);
|
||||
if (!mhi_cntrl->regs) {
|
||||
MHI_ERR("Error ioremap region\n");
|
||||
goto error_ioremap;
|
||||
}
|
||||
|
||||
ret = pci_alloc_irq_vectors(pci_dev, mhi_cntrl->msi_required,
|
||||
mhi_cntrl->msi_required, PCI_IRQ_MSI);
|
||||
if (IS_ERR_VALUE((ulong)ret) || ret < mhi_cntrl->msi_required) {
|
||||
MHI_ERR("Failed to enable MSI, ret:%d\n", ret);
|
||||
goto error_req_msi;
|
||||
}
|
||||
|
||||
mhi_cntrl->msi_allocated = ret;
|
||||
mhi_cntrl->irq = kmalloc_array(mhi_cntrl->msi_allocated,
|
||||
sizeof(*mhi_cntrl->irq), GFP_KERNEL);
|
||||
if (!mhi_cntrl->irq) {
|
||||
ret = -ENOMEM;
|
||||
goto error_alloc_msi_vec;
|
||||
}
|
||||
|
||||
for (i = 0; i < mhi_cntrl->msi_allocated; i++) {
|
||||
mhi_cntrl->irq[i] = pci_irq_vector(pci_dev, i);
|
||||
if (mhi_cntrl->irq[i] < 0) {
|
||||
ret = mhi_cntrl->irq[i];
|
||||
goto error_get_irq_vec;
|
||||
}
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pci_dev->dev, mhi_cntrl);
|
||||
|
||||
/* configure runtime pm */
|
||||
pm_runtime_set_autosuspend_delay(&pci_dev->dev, MHI_RPM_SUSPEND_TMR_MS);
|
||||
pm_runtime_use_autosuspend(&pci_dev->dev);
|
||||
pm_suspend_ignore_children(&pci_dev->dev, true);
|
||||
|
||||
/*
|
||||
* pci framework will increment usage count (twice) before
|
||||
* calling local device driver probe function.
|
||||
* 1st pci.c pci_pm_init() calls pm_runtime_forbid
|
||||
* 2nd pci-driver.c local_pci_probe calls pm_runtime_get_sync
|
||||
* Framework expect pci device driver to call
|
||||
* pm_runtime_put_noidle to decrement usage count after
|
||||
* successful probe and and call pm_runtime_allow to enable
|
||||
* runtime suspend.
|
||||
*/
|
||||
pm_runtime_mark_last_busy(&pci_dev->dev);
|
||||
pm_runtime_put_noidle(&pci_dev->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
error_get_irq_vec:
|
||||
kfree(mhi_cntrl->irq);
|
||||
mhi_cntrl->irq = NULL;
|
||||
|
||||
error_alloc_msi_vec:
|
||||
pci_free_irq_vectors(pci_dev);
|
||||
|
||||
error_req_msi:
|
||||
iounmap(mhi_cntrl->regs);
|
||||
|
||||
error_ioremap:
|
||||
pci_clear_master(pci_dev);
|
||||
|
||||
error_request_region:
|
||||
pci_disable_device(pci_dev);
|
||||
|
||||
error_enable_device:
|
||||
pci_release_region(pci_dev, mhi_dev->resn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mhi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev);
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
MHI_LOG("Enter\n");
|
||||
|
||||
mutex_lock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
if (!mhi_dev->powered_on) {
|
||||
MHI_LOG("Not fully powered, return success\n");
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if drv is supported we will always go into drv */
|
||||
if (mhi_dev->drv_supported) {
|
||||
ret = mhi_pm_fast_suspend(mhi_cntrl, true);
|
||||
mhi_dev->suspend_mode = MHI_FAST_LINK_OFF;
|
||||
} else {
|
||||
ret = mhi_pm_suspend(mhi_cntrl);
|
||||
mhi_dev->suspend_mode = MHI_DEFAULT_SUSPEND;
|
||||
|
||||
/* regular suspend failed, probably a client has a vote */
|
||||
if (ret == -EBUSY) {
|
||||
ret = mhi_pm_fast_suspend(mhi_cntrl, false);
|
||||
mhi_dev->suspend_mode = MHI_FAST_LINK_ON;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
MHI_LOG("Abort due to ret:%d\n", ret);
|
||||
mhi_dev->suspend_mode = MHI_ACTIVE_STATE;
|
||||
goto exit_runtime_suspend;
|
||||
}
|
||||
|
||||
ret = mhi_arch_link_suspend(mhi_cntrl);
|
||||
|
||||
/* failed suspending link abort mhi suspend */
|
||||
if (ret) {
|
||||
MHI_LOG("Failed to suspend link, abort suspend\n");
|
||||
if (mhi_dev->suspend_mode == MHI_DEFAULT_SUSPEND)
|
||||
mhi_pm_resume(mhi_cntrl);
|
||||
else
|
||||
mhi_pm_fast_resume(mhi_cntrl,
|
||||
mhi_dev->suspend_mode == MHI_FAST_LINK_OFF);
|
||||
|
||||
mhi_dev->suspend_mode = MHI_ACTIVE_STATE;
|
||||
}
|
||||
|
||||
exit_runtime_suspend:
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
MHI_LOG("Exited with ret:%d\n", ret);
|
||||
|
||||
return (ret < 0) ? -EBUSY : 0;
|
||||
}
|
||||
|
||||
static int mhi_runtime_idle(struct device *dev)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev);
|
||||
|
||||
MHI_LOG("Entered returning -EBUSY\n");
|
||||
|
||||
/*
|
||||
* RPM framework during runtime resume always calls
|
||||
* rpm_idle to see if device ready to suspend.
|
||||
* If dev.power usage_count count is 0, rpm fw will call
|
||||
* rpm_idle cb to see if device is ready to suspend.
|
||||
* if cb return 0, or cb not defined the framework will
|
||||
* assume device driver is ready to suspend;
|
||||
* therefore, fw will schedule runtime suspend.
|
||||
* In MHI power management, MHI host shall go to
|
||||
* runtime suspend only after entering MHI State M2, even if
|
||||
* usage count is 0. Return -EBUSY to disable automatic suspend.
|
||||
*/
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static int mhi_runtime_resume(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev);
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
MHI_LOG("Enter\n");
|
||||
|
||||
mutex_lock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
if (!mhi_dev->powered_on) {
|
||||
MHI_LOG("Not fully powered, return success\n");
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* turn on link */
|
||||
ret = mhi_arch_link_resume(mhi_cntrl);
|
||||
if (ret)
|
||||
goto rpm_resume_exit;
|
||||
|
||||
|
||||
/* transition to M0 state */
|
||||
if (mhi_dev->suspend_mode == MHI_DEFAULT_SUSPEND)
|
||||
ret = mhi_pm_resume(mhi_cntrl);
|
||||
else
|
||||
ret = mhi_pm_fast_resume(mhi_cntrl,
|
||||
mhi_dev->suspend_mode == MHI_FAST_LINK_OFF);
|
||||
|
||||
mhi_dev->suspend_mode = MHI_ACTIVE_STATE;
|
||||
|
||||
rpm_resume_exit:
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
MHI_LOG("Exited with :%d\n", ret);
|
||||
|
||||
return (ret < 0) ? -EBUSY : 0;
|
||||
}
|
||||
|
||||
static int mhi_system_resume(struct device *dev)
|
||||
{
|
||||
return mhi_runtime_resume(dev);
|
||||
}
|
||||
|
||||
int mhi_system_suspend(struct device *dev)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev);
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
int ret;
|
||||
|
||||
MHI_LOG("Entered\n");
|
||||
|
||||
mutex_lock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
if (!mhi_dev->powered_on) {
|
||||
MHI_LOG("Not fully powered, return success\n");
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* pci framework always makes a dummy vote to rpm
|
||||
* framework to resume before calling system suspend
|
||||
* hence usage count is minimum one
|
||||
*/
|
||||
if (atomic_read(&dev->power.usage_count) > 1) {
|
||||
/*
|
||||
* clients have requested to keep link on, try
|
||||
* fast suspend. No need to notify clients since
|
||||
* we will not be turning off the pcie link
|
||||
*/
|
||||
ret = mhi_pm_fast_suspend(mhi_cntrl, false);
|
||||
mhi_dev->suspend_mode = MHI_FAST_LINK_ON;
|
||||
} else {
|
||||
/* if drv enable always do fast suspend */
|
||||
if (mhi_dev->drv_supported) {
|
||||
ret = mhi_pm_fast_suspend(mhi_cntrl, true);
|
||||
mhi_dev->suspend_mode = MHI_FAST_LINK_OFF;
|
||||
} else {
|
||||
/* try normal suspend */
|
||||
mhi_dev->suspend_mode = MHI_DEFAULT_SUSPEND;
|
||||
ret = mhi_pm_suspend(mhi_cntrl);
|
||||
|
||||
/*
|
||||
* normal suspend failed because we're busy, try
|
||||
* fast suspend before aborting system suspend.
|
||||
* this could happens if client has disabled
|
||||
* device lpm but no active vote for PCIe from
|
||||
* apps processor
|
||||
*/
|
||||
if (ret == -EBUSY) {
|
||||
ret = mhi_pm_fast_suspend(mhi_cntrl, true);
|
||||
mhi_dev->suspend_mode = MHI_FAST_LINK_ON;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
MHI_LOG("Abort due to ret:%d\n", ret);
|
||||
mhi_dev->suspend_mode = MHI_ACTIVE_STATE;
|
||||
goto exit_system_suspend;
|
||||
}
|
||||
|
||||
ret = mhi_arch_link_suspend(mhi_cntrl);
|
||||
|
||||
/* failed suspending link abort mhi suspend */
|
||||
if (ret) {
|
||||
MHI_LOG("Failed to suspend link, abort suspend\n");
|
||||
if (mhi_dev->suspend_mode == MHI_DEFAULT_SUSPEND)
|
||||
mhi_pm_resume(mhi_cntrl);
|
||||
else
|
||||
mhi_pm_fast_resume(mhi_cntrl,
|
||||
mhi_dev->suspend_mode == MHI_FAST_LINK_OFF);
|
||||
|
||||
mhi_dev->suspend_mode = MHI_ACTIVE_STATE;
|
||||
}
|
||||
|
||||
exit_system_suspend:
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
MHI_LOG("Exit with ret:%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mhi_force_suspend(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
int ret = -EIO;
|
||||
const u32 delayms = 100;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
int itr = DIV_ROUND_UP(mhi_cntrl->timeout_ms, delayms);
|
||||
|
||||
MHI_LOG("Entered\n");
|
||||
|
||||
mutex_lock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
for (; itr; itr--) {
|
||||
/*
|
||||
* This function get called soon as device entered mission mode
|
||||
* so most of the channels are still in disabled state. However,
|
||||
* sbl channels are active and clients could be trying to close
|
||||
* channels while we trying to suspend the link. So, we need to
|
||||
* re-try if MHI is busy
|
||||
*/
|
||||
ret = mhi_pm_suspend(mhi_cntrl);
|
||||
if (!ret || ret != -EBUSY)
|
||||
break;
|
||||
|
||||
MHI_LOG("MHI busy, sleeping and retry\n");
|
||||
msleep(delayms);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
goto exit_force_suspend;
|
||||
|
||||
mhi_dev->suspend_mode = MHI_DEFAULT_SUSPEND;
|
||||
ret = mhi_arch_link_suspend(mhi_cntrl);
|
||||
|
||||
exit_force_suspend:
|
||||
MHI_LOG("Force suspend ret with %d\n", ret);
|
||||
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* checks if link is down */
|
||||
static int mhi_link_status(struct mhi_controller *mhi_cntrl, void *priv)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = priv;
|
||||
u16 dev_id;
|
||||
int ret;
|
||||
|
||||
/* try reading device id, if dev id don't match, link is down */
|
||||
ret = pci_read_config_word(mhi_dev->pci_dev, PCI_DEVICE_ID, &dev_id);
|
||||
|
||||
return (ret || dev_id != mhi_cntrl->dev_id) ? -EIO : 0;
|
||||
}
|
||||
|
||||
/* disable PCIe L1 */
|
||||
static int mhi_lpm_disable(struct mhi_controller *mhi_cntrl, void *priv)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = priv;
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
int lnkctl = pci_dev->pcie_cap + PCI_EXP_LNKCTL;
|
||||
u8 val;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&mhi_dev->lpm_lock, flags);
|
||||
|
||||
/* L1 is already disabled */
|
||||
if (mhi_dev->lpm_disable_depth) {
|
||||
mhi_dev->lpm_disable_depth++;
|
||||
goto lpm_disable_exit;
|
||||
}
|
||||
|
||||
ret = pci_read_config_byte(pci_dev, lnkctl, &val);
|
||||
if (ret) {
|
||||
MHI_ERR("Error reading LNKCTL, ret:%d\n", ret);
|
||||
goto lpm_disable_exit;
|
||||
}
|
||||
|
||||
/* L1 is not supported, do not increment lpm_disable_depth */
|
||||
if (unlikely(!(val & PCI_EXP_LNKCTL_ASPM_L1)))
|
||||
goto lpm_disable_exit;
|
||||
|
||||
val &= ~PCI_EXP_LNKCTL_ASPM_L1;
|
||||
ret = pci_write_config_byte(pci_dev, lnkctl, val);
|
||||
if (ret) {
|
||||
MHI_ERR("Error writing LNKCTL to disable LPM, ret:%d\n", ret);
|
||||
goto lpm_disable_exit;
|
||||
}
|
||||
|
||||
mhi_dev->lpm_disable_depth++;
|
||||
|
||||
lpm_disable_exit:
|
||||
spin_unlock_irqrestore(&mhi_dev->lpm_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* enable PCIe L1 */
|
||||
static int mhi_lpm_enable(struct mhi_controller *mhi_cntrl, void *priv)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = priv;
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
int lnkctl = pci_dev->pcie_cap + PCI_EXP_LNKCTL;
|
||||
u8 val;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&mhi_dev->lpm_lock, flags);
|
||||
|
||||
/*
|
||||
* Exit if L1 is not supported or is already disabled or
|
||||
* decrementing lpm_disable_depth still keeps it above 0
|
||||
*/
|
||||
if (!mhi_dev->lpm_disable_depth)
|
||||
goto lpm_enable_exit;
|
||||
|
||||
if (mhi_dev->lpm_disable_depth > 1) {
|
||||
mhi_dev->lpm_disable_depth--;
|
||||
goto lpm_enable_exit;
|
||||
}
|
||||
|
||||
ret = pci_read_config_byte(pci_dev, lnkctl, &val);
|
||||
if (ret) {
|
||||
MHI_ERR("Error reading LNKCTL, ret:%d\n", ret);
|
||||
goto lpm_enable_exit;
|
||||
}
|
||||
|
||||
val |= PCI_EXP_LNKCTL_ASPM_L1;
|
||||
ret = pci_write_config_byte(pci_dev, lnkctl, val);
|
||||
if (ret) {
|
||||
MHI_ERR("Error writing LNKCTL to enable LPM, ret:%d\n", ret);
|
||||
goto lpm_enable_exit;
|
||||
}
|
||||
|
||||
mhi_dev->lpm_disable_depth = 0;
|
||||
|
||||
lpm_enable_exit:
|
||||
spin_unlock_irqrestore(&mhi_dev->lpm_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mhi_qcom_store_hwinfo(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
int i;
|
||||
|
||||
mhi_dev->serial_num = readl_relaxed(mhi_cntrl->bhi +
|
||||
MHI_BHI_SERIAL_NUM_OFFS);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mhi_dev->oem_pk_hash); i++)
|
||||
mhi_dev->oem_pk_hash[i] = readl_relaxed(mhi_cntrl->bhi +
|
||||
MHI_BHI_OEMPKHASH(i));
|
||||
}
|
||||
|
||||
static int mhi_qcom_power_up(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
enum mhi_dev_state dev_state = mhi_get_mhi_state(mhi_cntrl);
|
||||
const u32 delayus = 10;
|
||||
int itr = DIV_ROUND_UP(mhi_cntrl->timeout_ms * 1000, delayus);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* It's possible device did not go thru a cold reset before
|
||||
* power up and still in error state. If device in error state,
|
||||
* we need to trigger a soft reset before continue with power
|
||||
* up
|
||||
*/
|
||||
if (dev_state == MHI_STATE_SYS_ERR) {
|
||||
mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET);
|
||||
while (itr--) {
|
||||
dev_state = mhi_get_mhi_state(mhi_cntrl);
|
||||
if (dev_state != MHI_STATE_SYS_ERR)
|
||||
break;
|
||||
usleep_range(delayus, delayus << 1);
|
||||
}
|
||||
/* device still in error state, abort power up */
|
||||
if (dev_state == MHI_STATE_SYS_ERR)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* when coming out of SSR, initial states are not valid */
|
||||
mhi_cntrl->ee = 0;
|
||||
mhi_cntrl->power_down = false;
|
||||
|
||||
ret = mhi_arch_power_up(mhi_cntrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mhi_async_power_up(mhi_cntrl);
|
||||
|
||||
/* Update modem serial Info */
|
||||
if (!ret)
|
||||
mhi_qcom_store_hwinfo(mhi_cntrl);
|
||||
|
||||
/* power up create the dentry */
|
||||
if (mhi_cntrl->dentry) {
|
||||
debugfs_create_file("m0", 0444, mhi_cntrl->dentry, mhi_cntrl,
|
||||
&debugfs_trigger_m0_fops);
|
||||
debugfs_create_file("m3", 0444, mhi_cntrl->dentry, mhi_cntrl,
|
||||
&debugfs_trigger_m3_fops);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mhi_runtime_get(struct mhi_controller *mhi_cntrl, void *priv)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = priv;
|
||||
struct device *dev = &mhi_dev->pci_dev->dev;
|
||||
|
||||
return pm_runtime_get(dev);
|
||||
}
|
||||
|
||||
static void mhi_runtime_put(struct mhi_controller *mhi_cntrl, void *priv)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = priv;
|
||||
struct device *dev = &mhi_dev->pci_dev->dev;
|
||||
|
||||
pm_runtime_put_noidle(dev);
|
||||
}
|
||||
|
||||
static void mhi_status_cb(struct mhi_controller *mhi_cntrl,
|
||||
void *priv,
|
||||
enum MHI_CB reason)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = priv;
|
||||
struct device *dev = &mhi_dev->pci_dev->dev;
|
||||
int ret;
|
||||
|
||||
switch (reason) {
|
||||
case MHI_CB_IDLE:
|
||||
MHI_LOG("Schedule runtime suspend\n");
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_request_autosuspend(dev);
|
||||
break;
|
||||
case MHI_CB_EE_MISSION_MODE:
|
||||
/*
|
||||
* we need to force a suspend so device can switch to
|
||||
* mission mode pcie phy settings.
|
||||
*/
|
||||
pm_runtime_get(dev);
|
||||
ret = mhi_force_suspend(mhi_cntrl);
|
||||
if (!ret)
|
||||
mhi_runtime_resume(dev);
|
||||
pm_runtime_put(dev);
|
||||
break;
|
||||
default:
|
||||
MHI_ERR("Unhandled cb:0x%x\n", reason);
|
||||
}
|
||||
}
|
||||
|
||||
/* capture host SoC XO time in ticks */
|
||||
static u64 mhi_time_get(struct mhi_controller *mhi_cntrl, void *priv)
|
||||
{
|
||||
return arch_counter_get_cntvct();
|
||||
}
|
||||
|
||||
static ssize_t timeout_ms_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct mhi_device *mhi_dev = to_mhi_device(dev);
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
|
||||
/* buffer provided by sysfs has a minimum size of PAGE_SIZE */
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", mhi_cntrl->timeout_ms);
|
||||
}
|
||||
|
||||
static ssize_t timeout_ms_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct mhi_device *mhi_dev = to_mhi_device(dev);
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
u32 timeout_ms;
|
||||
|
||||
if (kstrtou32(buf, 0, &timeout_ms) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
mhi_cntrl->timeout_ms = timeout_ms;
|
||||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(timeout_ms);
|
||||
|
||||
static ssize_t power_up_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
int ret;
|
||||
struct mhi_device *mhi_dev = to_mhi_device(dev);
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
|
||||
ret = mhi_qcom_power_up(mhi_cntrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_WO(power_up);
|
||||
|
||||
static ssize_t serial_info_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct mhi_device *mhi_device = to_mhi_device(dev);
|
||||
struct mhi_controller *mhi_cntrl = mhi_device->mhi_cntrl;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
int n;
|
||||
|
||||
n = scnprintf(buf, PAGE_SIZE, "Serial Number:%u\n",
|
||||
mhi_dev->serial_num);
|
||||
|
||||
return n;
|
||||
}
|
||||
static DEVICE_ATTR_RO(serial_info);
|
||||
|
||||
static ssize_t oempkhash_info_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct mhi_device *mhi_device = to_mhi_device(dev);
|
||||
struct mhi_controller *mhi_cntrl = mhi_device->mhi_cntrl;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
int i, n = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mhi_dev->oem_pk_hash); i++)
|
||||
n += scnprintf(buf + n, PAGE_SIZE - n, "OEMPKHASH[%d]:%u\n",
|
||||
i, mhi_dev->oem_pk_hash[i]);
|
||||
|
||||
return n;
|
||||
}
|
||||
static DEVICE_ATTR_RO(oempkhash_info);
|
||||
|
||||
|
||||
static struct attribute *mhi_qcom_attrs[] = {
|
||||
&dev_attr_timeout_ms.attr,
|
||||
&dev_attr_power_up.attr,
|
||||
&dev_attr_serial_info.attr,
|
||||
&dev_attr_oempkhash_info.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group mhi_qcom_group = {
|
||||
.attrs = mhi_qcom_attrs,
|
||||
};
|
||||
|
||||
static struct mhi_controller *mhi_register_controller(struct pci_dev *pci_dev)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl;
|
||||
struct mhi_dev *mhi_dev;
|
||||
struct device_node *of_node = pci_dev->dev.of_node;
|
||||
const struct firmware_info *firmware_info;
|
||||
bool use_s1;
|
||||
u32 addr_win[2];
|
||||
const char *iommu_dma_type;
|
||||
int ret, i;
|
||||
|
||||
if (!of_node)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
mhi_cntrl = mhi_alloc_controller(sizeof(*mhi_dev));
|
||||
if (!mhi_cntrl)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
mhi_cntrl->domain = pci_domain_nr(pci_dev->bus);
|
||||
mhi_cntrl->dev_id = pci_dev->device;
|
||||
mhi_cntrl->bus = pci_dev->bus->number;
|
||||
mhi_cntrl->slot = PCI_SLOT(pci_dev->devfn);
|
||||
mhi_cntrl->of_node = of_node;
|
||||
|
||||
mhi_cntrl->iova_start = memblock_start_of_DRAM();
|
||||
mhi_cntrl->iova_stop = memblock_end_of_DRAM();
|
||||
|
||||
of_node = of_parse_phandle(mhi_cntrl->of_node, "qcom,iommu-group", 0);
|
||||
if (of_node) {
|
||||
use_s1 = true;
|
||||
|
||||
/*
|
||||
* s1 translation can be in bypass or fastmap mode
|
||||
* if "qcom,iommu-dma" property is missing, we assume s1 is
|
||||
* enabled and in default (no fastmap/atomic) mode
|
||||
*/
|
||||
ret = of_property_read_string(of_node, "qcom,iommu-dma",
|
||||
&iommu_dma_type);
|
||||
if (!ret && !strcmp("bypass", iommu_dma_type))
|
||||
use_s1 = false;
|
||||
|
||||
/*
|
||||
* if s1 translation enabled pull iova addr from dt using
|
||||
* iommu-dma-addr-pool property specified addresses
|
||||
*/
|
||||
if (use_s1) {
|
||||
ret = of_property_read_u32_array(of_node,
|
||||
"qcom,iommu-dma-addr-pool",
|
||||
addr_win, 2);
|
||||
if (ret) {
|
||||
of_node_put(of_node);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* If S1 is enabled, set MHI_CTRL start address to 0
|
||||
* so we can use low level mapping api to map buffers
|
||||
* outside of smmu domain
|
||||
*/
|
||||
mhi_cntrl->iova_start = 0;
|
||||
mhi_cntrl->iova_stop = addr_win[0] + addr_win[1];
|
||||
}
|
||||
|
||||
of_node_put(of_node);
|
||||
}
|
||||
|
||||
mhi_dev->pci_dev = pci_dev;
|
||||
spin_lock_init(&mhi_dev->lpm_lock);
|
||||
|
||||
/* setup power management apis */
|
||||
mhi_cntrl->status_cb = mhi_status_cb;
|
||||
mhi_cntrl->runtime_get = mhi_runtime_get;
|
||||
mhi_cntrl->runtime_put = mhi_runtime_put;
|
||||
mhi_cntrl->link_status = mhi_link_status;
|
||||
|
||||
mhi_cntrl->lpm_disable = mhi_lpm_disable;
|
||||
mhi_cntrl->lpm_enable = mhi_lpm_enable;
|
||||
mhi_cntrl->time_get = mhi_time_get;
|
||||
mhi_cntrl->remote_timer_freq = 19200000;
|
||||
|
||||
ret = of_register_mhi_controller(mhi_cntrl);
|
||||
if (ret)
|
||||
goto error_register;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(firmware_table); i++) {
|
||||
firmware_info = firmware_table + i;
|
||||
|
||||
/* debug mode always use default */
|
||||
if (!debug_mode && mhi_cntrl->dev_id == firmware_info->dev_id)
|
||||
break;
|
||||
}
|
||||
|
||||
mhi_cntrl->fw_image = firmware_info->fw_image;
|
||||
mhi_cntrl->edl_image = firmware_info->edl_image;
|
||||
|
||||
if (sysfs_create_group(&mhi_cntrl->mhi_dev->dev.kobj, &mhi_qcom_group))
|
||||
MHI_ERR("Error while creating the sysfs group\n");
|
||||
|
||||
return mhi_cntrl;
|
||||
|
||||
error_register:
|
||||
mhi_free_controller(mhi_cntrl);
|
||||
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
int mhi_pci_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *device_id)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl;
|
||||
u32 domain = pci_domain_nr(pci_dev->bus);
|
||||
u32 bus = pci_dev->bus->number;
|
||||
u32 dev_id = pci_dev->device;
|
||||
u32 slot = PCI_SLOT(pci_dev->devfn);
|
||||
struct mhi_dev *mhi_dev;
|
||||
int ret;
|
||||
|
||||
/* see if we already registered */
|
||||
mhi_cntrl = mhi_bdf_to_controller(domain, bus, slot, dev_id);
|
||||
if (!mhi_cntrl)
|
||||
mhi_cntrl = mhi_register_controller(pci_dev);
|
||||
|
||||
if (IS_ERR(mhi_cntrl))
|
||||
return PTR_ERR(mhi_cntrl);
|
||||
|
||||
mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
mhi_dev->powered_on = true;
|
||||
|
||||
ret = mhi_arch_pcie_init(mhi_cntrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mhi_cntrl->dev = &mhi_dev->pci_dev->dev;
|
||||
|
||||
ret = dma_set_mask_and_coherent(mhi_cntrl->dev, DMA_BIT_MASK(64));
|
||||
if (ret)
|
||||
goto error_pci_probe;
|
||||
|
||||
ret = mhi_init_pci_dev(mhi_cntrl);
|
||||
if (ret)
|
||||
goto error_pci_probe;
|
||||
|
||||
/* start power up sequence */
|
||||
if (!debug_mode) {
|
||||
ret = mhi_qcom_power_up(mhi_cntrl);
|
||||
if (ret)
|
||||
goto error_power_up;
|
||||
}
|
||||
|
||||
pm_runtime_mark_last_busy(&pci_dev->dev);
|
||||
|
||||
MHI_LOG("Return successful\n");
|
||||
|
||||
return 0;
|
||||
|
||||
error_power_up:
|
||||
mhi_deinit_pci_dev(mhi_cntrl);
|
||||
|
||||
error_pci_probe:
|
||||
mhi_arch_pcie_deinit(mhi_cntrl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(mhi_runtime_suspend,
|
||||
mhi_runtime_resume,
|
||||
mhi_runtime_idle)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(mhi_system_suspend, mhi_system_resume)
|
||||
};
|
||||
|
||||
static struct pci_device_id mhi_pcie_device_id[] = {
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0300)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0301)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0302)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0303)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0304)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0305)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0306)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, MHI_PCIE_DEBUG_ID)},
|
||||
{0},
|
||||
};
|
||||
|
||||
static struct pci_driver mhi_pcie_driver = {
|
||||
.name = "mhi",
|
||||
.id_table = mhi_pcie_device_id,
|
||||
.probe = mhi_pci_probe,
|
||||
.driver = {
|
||||
.pm = &pm_ops
|
||||
}
|
||||
};
|
||||
|
||||
module_pci_driver(mhi_pcie_driver);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("MHI_CORE");
|
||||
MODULE_DESCRIPTION("MHI Host Driver");
|
105
drivers/bus/mhi/controllers/mhi_qcom.h
Normal file
105
drivers/bus/mhi/controllers/mhi_qcom.h
Normal file
@ -0,0 +1,105 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.*/
|
||||
|
||||
#ifndef _MHI_QCOM_
|
||||
#define _MHI_QCOM_
|
||||
|
||||
/* iova cfg bitmask */
|
||||
#define MHI_SMMU_ATTACH BIT(0)
|
||||
#define MHI_SMMU_S1_BYPASS BIT(1)
|
||||
#define MHI_SMMU_FAST BIT(2)
|
||||
#define MHI_SMMU_ATOMIC BIT(3)
|
||||
#define MHI_SMMU_FORCE_COHERENT BIT(4)
|
||||
|
||||
#define MHI_PCIE_VENDOR_ID (0x17cb)
|
||||
#define MHI_PCIE_DEBUG_ID (0xffff)
|
||||
|
||||
#define MHI_BHI_SERIAL_NUM_OFFS (0x40)
|
||||
#define MHI_BHI_OEMPKHASH(n) (0x64 + (0x4 * (n)))
|
||||
#define MHI_BHI_OEMPKHASH_SEG (16)
|
||||
|
||||
/* runtime suspend timer */
|
||||
#define MHI_RPM_SUSPEND_TMR_MS (250)
|
||||
#define MHI_PCI_BAR_NUM (0)
|
||||
|
||||
/* timesync time calculations */
|
||||
#define REMOTE_TICKS_TO_US(x) (div_u64((x) * 100ULL, \
|
||||
div_u64(mhi_cntrl->remote_timer_freq, 10000ULL)))
|
||||
#define REMOTE_TICKS_TO_SEC(x) (div_u64((x), \
|
||||
mhi_cntrl->remote_timer_freq))
|
||||
#define REMOTE_TIME_REMAINDER_US(x) (REMOTE_TICKS_TO_US((x)) % \
|
||||
(REMOTE_TICKS_TO_SEC((x)) * 1000000ULL))
|
||||
|
||||
extern const char * const mhi_ee_str[MHI_EE_MAX];
|
||||
#define TO_MHI_EXEC_STR(ee) (ee >= MHI_EE_MAX ? "INVALID_EE" : mhi_ee_str[ee])
|
||||
|
||||
enum mhi_suspend_mode {
|
||||
MHI_ACTIVE_STATE,
|
||||
MHI_DEFAULT_SUSPEND,
|
||||
MHI_FAST_LINK_OFF,
|
||||
MHI_FAST_LINK_ON,
|
||||
};
|
||||
|
||||
#define MHI_IS_SUSPENDED(mode) (mode)
|
||||
|
||||
struct mhi_dev {
|
||||
struct pci_dev *pci_dev;
|
||||
bool drv_supported;
|
||||
int resn;
|
||||
void *arch_info;
|
||||
bool powered_on;
|
||||
bool mdm_state;
|
||||
dma_addr_t iova_start;
|
||||
dma_addr_t iova_stop;
|
||||
enum mhi_suspend_mode suspend_mode;
|
||||
|
||||
/* hardware info */
|
||||
u32 serial_num;
|
||||
u32 oem_pk_hash[MHI_BHI_OEMPKHASH_SEG];
|
||||
|
||||
unsigned int lpm_disable_depth;
|
||||
/* lock to toggle low power modes */
|
||||
spinlock_t lpm_lock;
|
||||
};
|
||||
|
||||
void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_pci_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *device_id);
|
||||
|
||||
#ifdef CONFIG_ARCH_QCOM
|
||||
|
||||
int mhi_arch_power_up(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_arch_link_suspend(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_arch_link_resume(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
#else
|
||||
|
||||
static inline int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_link_suspend(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mhi_arch_link_resume(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mhi_arch_power_up(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _MHI_QCOM_ */
|
4
drivers/bus/mhi/core/Makefile
Normal file
4
drivers/bus/mhi/core/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_MHI_BUS) += mhi_bus.o
|
||||
mhi_bus-y := mhi_init.o mhi_main.o mhi_pm.o mhi_boot.o mhi_dtr.o
|
668
drivers/bus/mhi/core/mhi_boot.c
Normal file
668
drivers/bus/mhi/core/mhi_boot.c
Normal file
@ -0,0 +1,668 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mhi.h>
|
||||
#include "mhi_internal.h"
|
||||
|
||||
static void mhi_process_sfr(struct mhi_controller *mhi_cntrl,
|
||||
struct file_info *info)
|
||||
{
|
||||
struct mhi_buf *mhi_buf = mhi_cntrl->rddm_image->mhi_buf;
|
||||
u8 *sfr_buf, *file_offset = info->file_offset;
|
||||
u32 file_size = info->file_size;
|
||||
u32 rem_seg_len = info->rem_seg_len;
|
||||
u32 seg_idx = info->seg_idx;
|
||||
|
||||
sfr_buf = kzalloc(file_size + 1, GFP_KERNEL);
|
||||
if (!sfr_buf)
|
||||
return;
|
||||
|
||||
while (file_size) {
|
||||
/* file offset starting from seg base */
|
||||
if (!rem_seg_len) {
|
||||
file_offset = mhi_buf[seg_idx].buf;
|
||||
if (file_size > mhi_buf[seg_idx].len)
|
||||
rem_seg_len = mhi_buf[seg_idx].len;
|
||||
else
|
||||
rem_seg_len = file_size;
|
||||
}
|
||||
|
||||
if (file_size <= rem_seg_len) {
|
||||
memcpy(sfr_buf, file_offset, file_size);
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(sfr_buf, file_offset, rem_seg_len);
|
||||
sfr_buf += rem_seg_len;
|
||||
file_size -= rem_seg_len;
|
||||
rem_seg_len = 0;
|
||||
seg_idx++;
|
||||
if (seg_idx == mhi_cntrl->rddm_image->entries) {
|
||||
MHI_ERR("invalid size for SFR file\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
sfr_buf[info->file_size] = '\0';
|
||||
|
||||
/* force sfr string to log in kernel msg */
|
||||
MHI_ERR("%s\n", sfr_buf);
|
||||
err:
|
||||
kfree(sfr_buf);
|
||||
}
|
||||
|
||||
static int mhi_find_next_file_offset(struct mhi_controller *mhi_cntrl,
|
||||
struct file_info *info, struct rddm_table_info *table_info)
|
||||
{
|
||||
struct mhi_buf *mhi_buf = mhi_cntrl->rddm_image->mhi_buf;
|
||||
|
||||
if (info->rem_seg_len >= table_info->size) {
|
||||
info->file_offset += table_info->size;
|
||||
info->rem_seg_len -= table_info->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
info->file_size = table_info->size - info->rem_seg_len;
|
||||
info->rem_seg_len = 0;
|
||||
/* iterate over segments until eof is reached */
|
||||
while (info->file_size) {
|
||||
info->seg_idx++;
|
||||
if (info->seg_idx == mhi_cntrl->rddm_image->entries) {
|
||||
MHI_ERR("invalid size for file %s\n",
|
||||
table_info->file_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (info->file_size > mhi_buf[info->seg_idx].len) {
|
||||
info->file_size -= mhi_buf[info->seg_idx].len;
|
||||
} else {
|
||||
info->file_offset = mhi_buf[info->seg_idx].buf +
|
||||
info->file_size;
|
||||
info->rem_seg_len = mhi_buf[info->seg_idx].len -
|
||||
info->file_size;
|
||||
info->file_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mhi_dump_sfr(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_buf *mhi_buf = mhi_cntrl->rddm_image->mhi_buf;
|
||||
struct rddm_header *rddm_header =
|
||||
(struct rddm_header *)mhi_buf->buf;
|
||||
struct rddm_table_info *table_info;
|
||||
struct file_info info;
|
||||
u32 table_size, n;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
if (rddm_header->header_size > sizeof(*rddm_header) ||
|
||||
rddm_header->header_size < 8) {
|
||||
MHI_ERR("invalid reported header size %u\n",
|
||||
rddm_header->header_size);
|
||||
return;
|
||||
}
|
||||
|
||||
table_size = (rddm_header->header_size - 8) / sizeof(*table_info);
|
||||
if (!table_size) {
|
||||
MHI_ERR("invalid rddm table size %u\n", table_size);
|
||||
return;
|
||||
}
|
||||
|
||||
info.file_offset = (u8 *)rddm_header + rddm_header->header_size;
|
||||
info.rem_seg_len = mhi_buf[0].len - rddm_header->header_size;
|
||||
for (n = 0; n < table_size; n++) {
|
||||
table_info = &rddm_header->table_info[n];
|
||||
|
||||
if (!strcmp(table_info->file_name, "Q6-SFR.bin")) {
|
||||
info.file_size = table_info->size;
|
||||
mhi_process_sfr(mhi_cntrl, &info);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mhi_find_next_file_offset(mhi_cntrl, &info, table_info))
|
||||
return;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(mhi_dump_sfr);
|
||||
|
||||
/* setup rddm vector table for rddm transfer and program rxvec */
|
||||
void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
|
||||
struct image_info *img_info)
|
||||
{
|
||||
struct mhi_buf *mhi_buf = img_info->mhi_buf;
|
||||
struct bhi_vec_entry *bhi_vec = img_info->bhi_vec;
|
||||
void __iomem *base = mhi_cntrl->bhie;
|
||||
u32 sequence_id;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) {
|
||||
MHI_VERB("Setting vector:%pad size:%zu\n",
|
||||
&mhi_buf->dma_addr, mhi_buf->len);
|
||||
bhi_vec->dma_addr = mhi_buf->dma_addr;
|
||||
bhi_vec->size = mhi_buf->len;
|
||||
}
|
||||
|
||||
MHI_LOG("BHIe programming for RDDM\n");
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS,
|
||||
upper_32_bits(mhi_buf->dma_addr));
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS,
|
||||
lower_32_bits(mhi_buf->dma_addr));
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len);
|
||||
sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK;
|
||||
|
||||
if (unlikely(!sequence_id))
|
||||
sequence_id = 1;
|
||||
|
||||
mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS,
|
||||
BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT,
|
||||
sequence_id);
|
||||
|
||||
MHI_LOG("address:%pad len:0x%lx sequence:%u\n",
|
||||
&mhi_buf->dma_addr, mhi_buf->len, sequence_id);
|
||||
}
|
||||
|
||||
/* collect rddm during kernel panic */
|
||||
static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
int ret;
|
||||
u32 rx_status;
|
||||
enum mhi_ee ee;
|
||||
const u32 delayus = 5000;
|
||||
u32 retry = (mhi_cntrl->timeout_ms * 1000) / delayus;
|
||||
const u32 rddm_timeout_us = 200000;
|
||||
int rddm_retry = rddm_timeout_us / delayus; /* time to enter rddm */
|
||||
void __iomem *base = mhi_cntrl->bhie;
|
||||
|
||||
MHI_LOG("Entered with pm_state:%s dev_state:%s ee:%s\n",
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state),
|
||||
TO_MHI_STATE_STR(mhi_cntrl->dev_state),
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee));
|
||||
|
||||
/*
|
||||
* This should only be executing during a kernel panic, we expect all
|
||||
* other cores to shutdown while we're collecting rddm buffer. After
|
||||
* returning from this function, we expect device to reset.
|
||||
*
|
||||
* Normaly, we would read/write pm_state only after grabbing
|
||||
* pm_lock, since we're in a panic, skipping it. Also there is no
|
||||
* gurantee this state change would take effect since
|
||||
* we're setting it w/o grabbing pmlock, it's best effort
|
||||
*/
|
||||
mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT;
|
||||
/* update should take the effect immediately */
|
||||
smp_wmb();
|
||||
|
||||
/*
|
||||
* Make sure device is not already in RDDM.
|
||||
* In case device asserts and a kernel panic follows, device will
|
||||
* already be in RDDM. Do not trigger SYS ERR again and proceed with
|
||||
* waiting for image download completion.
|
||||
*/
|
||||
ee = mhi_get_exec_env(mhi_cntrl);
|
||||
if (ee != MHI_EE_RDDM) {
|
||||
|
||||
MHI_LOG("Trigger device into RDDM mode using SYSERR\n");
|
||||
mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR);
|
||||
|
||||
MHI_LOG("Waiting for device to enter RDDM\n");
|
||||
while (rddm_retry--) {
|
||||
ee = mhi_get_exec_env(mhi_cntrl);
|
||||
if (ee == MHI_EE_RDDM)
|
||||
break;
|
||||
|
||||
udelay(delayus);
|
||||
}
|
||||
|
||||
if (rddm_retry <= 0) {
|
||||
/* Hardware reset; force device to enter rddm */
|
||||
MHI_LOG(
|
||||
"Did not enter RDDM, do a host req. reset\n");
|
||||
mhi_write_reg(mhi_cntrl, mhi_cntrl->regs,
|
||||
MHI_SOC_RESET_REQ_OFFSET,
|
||||
MHI_SOC_RESET_REQ);
|
||||
udelay(delayus);
|
||||
}
|
||||
|
||||
ee = mhi_get_exec_env(mhi_cntrl);
|
||||
}
|
||||
|
||||
MHI_LOG("Waiting for image download completion, current EE:%s\n",
|
||||
TO_MHI_EXEC_STR(ee));
|
||||
while (retry--) {
|
||||
ret = mhi_read_reg_field(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS,
|
||||
BHIE_RXVECSTATUS_STATUS_BMSK,
|
||||
BHIE_RXVECSTATUS_STATUS_SHFT,
|
||||
&rx_status);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
if (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) {
|
||||
MHI_LOG("RDDM successfully collected\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
udelay(delayus);
|
||||
}
|
||||
|
||||
ee = mhi_get_exec_env(mhi_cntrl);
|
||||
ret = mhi_read_reg(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, &rx_status);
|
||||
|
||||
MHI_ERR("Did not complete RDDM transfer\n");
|
||||
MHI_ERR("Current EE:%s\n", TO_MHI_EXEC_STR(ee));
|
||||
MHI_ERR("RXVEC_STATUS:0x%x, ret:%d\n", rx_status, ret);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* download ramdump image from device */
|
||||
int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic)
|
||||
{
|
||||
void __iomem *base = mhi_cntrl->bhie;
|
||||
u32 rx_status;
|
||||
|
||||
if (in_panic)
|
||||
return __mhi_download_rddm_in_panic(mhi_cntrl);
|
||||
|
||||
MHI_LOG("Waiting for image download completion\n");
|
||||
|
||||
/* waiting for image download completion */
|
||||
wait_event_timeout(mhi_cntrl->state_event,
|
||||
mhi_read_reg_field(mhi_cntrl, base,
|
||||
BHIE_RXVECSTATUS_OFFS,
|
||||
BHIE_RXVECSTATUS_STATUS_BMSK,
|
||||
BHIE_RXVECSTATUS_STATUS_SHFT,
|
||||
&rx_status) || rx_status,
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
return (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) ? 0 : -EIO;
|
||||
}
|
||||
EXPORT_SYMBOL(mhi_download_rddm_img);
|
||||
|
||||
static int mhi_fw_load_amss(struct mhi_controller *mhi_cntrl,
|
||||
const struct mhi_buf *mhi_buf)
|
||||
{
|
||||
void __iomem *base = mhi_cntrl->bhie;
|
||||
rwlock_t *pm_lock = &mhi_cntrl->pm_lock;
|
||||
u32 tx_status;
|
||||
|
||||
read_lock_bh(pm_lock);
|
||||
if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
|
||||
read_unlock_bh(pm_lock);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
MHI_LOG("Starting BHIe Programming\n");
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_TXVECADDR_HIGH_OFFS,
|
||||
upper_32_bits(mhi_buf->dma_addr));
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_TXVECADDR_LOW_OFFS,
|
||||
lower_32_bits(mhi_buf->dma_addr));
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_TXVECSIZE_OFFS, mhi_buf->len);
|
||||
|
||||
mhi_cntrl->sequence_id = prandom_u32() & BHIE_TXVECSTATUS_SEQNUM_BMSK;
|
||||
mhi_write_reg_field(mhi_cntrl, base, BHIE_TXVECDB_OFFS,
|
||||
BHIE_TXVECDB_SEQNUM_BMSK, BHIE_TXVECDB_SEQNUM_SHFT,
|
||||
mhi_cntrl->sequence_id);
|
||||
read_unlock_bh(pm_lock);
|
||||
|
||||
MHI_LOG("Upper:0x%x Lower:0x%x len:0x%lx sequence:%u\n",
|
||||
upper_32_bits(mhi_buf->dma_addr),
|
||||
lower_32_bits(mhi_buf->dma_addr),
|
||||
mhi_buf->len, mhi_cntrl->sequence_id);
|
||||
MHI_LOG("Waiting for image transfer completion\n");
|
||||
|
||||
/* waiting for image download completion */
|
||||
wait_event_timeout(mhi_cntrl->state_event,
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) ||
|
||||
mhi_read_reg_field(mhi_cntrl, base,
|
||||
BHIE_TXVECSTATUS_OFFS,
|
||||
BHIE_TXVECSTATUS_STATUS_BMSK,
|
||||
BHIE_TXVECSTATUS_STATUS_SHFT,
|
||||
&tx_status) || tx_status,
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))
|
||||
return -EIO;
|
||||
|
||||
return (tx_status == BHIE_TXVECSTATUS_STATUS_XFER_COMPL) ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl,
|
||||
dma_addr_t dma_addr,
|
||||
size_t size)
|
||||
{
|
||||
u32 tx_status, val;
|
||||
int i, ret;
|
||||
void __iomem *base = mhi_cntrl->bhi;
|
||||
rwlock_t *pm_lock = &mhi_cntrl->pm_lock;
|
||||
struct {
|
||||
char *name;
|
||||
u32 offset;
|
||||
} error_reg[] = {
|
||||
{ "ERROR_CODE", BHI_ERRCODE },
|
||||
{ "ERROR_DBG1", BHI_ERRDBG1 },
|
||||
{ "ERROR_DBG2", BHI_ERRDBG2 },
|
||||
{ "ERROR_DBG3", BHI_ERRDBG3 },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
MHI_LOG("Starting BHI programming\n");
|
||||
|
||||
/* program start sbl download via bhi protocol */
|
||||
read_lock_bh(pm_lock);
|
||||
if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
|
||||
read_unlock_bh(pm_lock);
|
||||
goto invalid_pm_state;
|
||||
}
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_STATUS, 0);
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_HIGH,
|
||||
upper_32_bits(dma_addr));
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_LOW,
|
||||
lower_32_bits(dma_addr));
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_IMGSIZE, size);
|
||||
mhi_cntrl->session_id = prandom_u32() & BHI_TXDB_SEQNUM_BMSK;
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_IMGTXDB, mhi_cntrl->session_id);
|
||||
read_unlock_bh(pm_lock);
|
||||
|
||||
MHI_LOG("Waiting for image transfer completion\n");
|
||||
|
||||
/* waiting for image download completion */
|
||||
wait_event_timeout(mhi_cntrl->state_event,
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) ||
|
||||
mhi_read_reg_field(mhi_cntrl, base, BHI_STATUS,
|
||||
BHI_STATUS_MASK, BHI_STATUS_SHIFT,
|
||||
&tx_status) || tx_status,
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))
|
||||
goto invalid_pm_state;
|
||||
|
||||
if (tx_status == BHI_STATUS_ERROR) {
|
||||
MHI_ERR("Image transfer failed\n");
|
||||
read_lock_bh(pm_lock);
|
||||
if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
|
||||
for (i = 0; error_reg[i].name; i++) {
|
||||
ret = mhi_read_reg(mhi_cntrl, base,
|
||||
error_reg[i].offset, &val);
|
||||
if (ret)
|
||||
break;
|
||||
MHI_ERR("reg:%s value:0x%x\n",
|
||||
error_reg[i].name, val);
|
||||
}
|
||||
}
|
||||
read_unlock_bh(pm_lock);
|
||||
goto invalid_pm_state;
|
||||
}
|
||||
|
||||
return (tx_status == BHI_STATUS_SUCCESS) ? 0 : -ETIMEDOUT;
|
||||
|
||||
invalid_pm_state:
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl,
|
||||
struct image_info *image_info)
|
||||
{
|
||||
int i;
|
||||
struct mhi_buf *mhi_buf = image_info->mhi_buf;
|
||||
|
||||
for (i = 0; i < image_info->entries; i++, mhi_buf++)
|
||||
mhi_free_contig_coherent(mhi_cntrl, mhi_buf->len, mhi_buf->buf,
|
||||
mhi_buf->dma_addr);
|
||||
|
||||
kfree(image_info->mhi_buf);
|
||||
kfree(image_info);
|
||||
}
|
||||
|
||||
int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl,
|
||||
struct image_info **image_info,
|
||||
size_t alloc_size)
|
||||
{
|
||||
size_t seg_size = mhi_cntrl->seg_len;
|
||||
/* requier additional entry for vec table */
|
||||
int segments = DIV_ROUND_UP(alloc_size, seg_size) + 1;
|
||||
int i;
|
||||
struct image_info *img_info;
|
||||
struct mhi_buf *mhi_buf;
|
||||
|
||||
MHI_LOG("Allocating bytes:%zu seg_size:%zu total_seg:%u\n",
|
||||
alloc_size, seg_size, segments);
|
||||
|
||||
img_info = kzalloc(sizeof(*img_info), GFP_KERNEL);
|
||||
if (!img_info)
|
||||
return -ENOMEM;
|
||||
|
||||
/* allocate memory for entries */
|
||||
img_info->mhi_buf = kcalloc(segments, sizeof(*img_info->mhi_buf),
|
||||
GFP_KERNEL);
|
||||
if (!img_info->mhi_buf)
|
||||
goto error_alloc_mhi_buf;
|
||||
|
||||
/* allocate and populate vector table */
|
||||
mhi_buf = img_info->mhi_buf;
|
||||
for (i = 0; i < segments; i++, mhi_buf++) {
|
||||
size_t vec_size = seg_size;
|
||||
|
||||
/* last entry is for vector table */
|
||||
if (i == segments - 1)
|
||||
vec_size = sizeof(struct bhi_vec_entry) * i;
|
||||
|
||||
mhi_buf->len = vec_size;
|
||||
mhi_buf->buf = mhi_alloc_contig_coherent(mhi_cntrl, vec_size,
|
||||
&mhi_buf->dma_addr, GFP_KERNEL);
|
||||
if (!mhi_buf->buf)
|
||||
goto error_alloc_segment;
|
||||
|
||||
MHI_LOG("Entry:%d Address:0x%llx size:%lu\n", i,
|
||||
mhi_buf->dma_addr, mhi_buf->len);
|
||||
}
|
||||
|
||||
img_info->bhi_vec = img_info->mhi_buf[segments - 1].buf;
|
||||
img_info->entries = segments;
|
||||
*image_info = img_info;
|
||||
|
||||
MHI_LOG("Successfully allocated bhi vec table\n");
|
||||
|
||||
return 0;
|
||||
|
||||
error_alloc_segment:
|
||||
for (--i, --mhi_buf; i >= 0; i--, mhi_buf--)
|
||||
mhi_free_contig_coherent(mhi_cntrl, mhi_buf->len, mhi_buf->buf,
|
||||
mhi_buf->dma_addr);
|
||||
|
||||
error_alloc_mhi_buf:
|
||||
kfree(img_info);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void mhi_firmware_copy(struct mhi_controller *mhi_cntrl,
|
||||
const struct firmware *firmware,
|
||||
struct image_info *img_info)
|
||||
{
|
||||
size_t remainder = firmware->size;
|
||||
size_t to_cpy;
|
||||
const u8 *buf = firmware->data;
|
||||
int i = 0;
|
||||
struct mhi_buf *mhi_buf = img_info->mhi_buf;
|
||||
struct bhi_vec_entry *bhi_vec = img_info->bhi_vec;
|
||||
|
||||
while (remainder) {
|
||||
MHI_ASSERT(i >= img_info->entries, "malformed vector table");
|
||||
|
||||
to_cpy = min(remainder, mhi_buf->len);
|
||||
memcpy(mhi_buf->buf, buf, to_cpy);
|
||||
bhi_vec->dma_addr = mhi_buf->dma_addr;
|
||||
bhi_vec->size = to_cpy;
|
||||
|
||||
MHI_VERB("Setting Vector:0x%llx size: %llu\n",
|
||||
bhi_vec->dma_addr, bhi_vec->size);
|
||||
buf += to_cpy;
|
||||
remainder -= to_cpy;
|
||||
i++;
|
||||
bhi_vec++;
|
||||
mhi_buf++;
|
||||
}
|
||||
}
|
||||
|
||||
void mhi_fw_load_worker(struct work_struct *work)
|
||||
{
|
||||
int ret;
|
||||
struct mhi_controller *mhi_cntrl;
|
||||
const char *fw_name;
|
||||
const struct firmware *firmware = NULL;
|
||||
struct image_info *image_info;
|
||||
void *buf;
|
||||
dma_addr_t dma_addr;
|
||||
size_t size;
|
||||
|
||||
mhi_cntrl = container_of(work, struct mhi_controller, fw_worker);
|
||||
|
||||
MHI_LOG("Waiting for device to enter PBL from EE:%s\n",
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee));
|
||||
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
MHI_IN_PBL(mhi_cntrl->ee) ||
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
|
||||
MHI_ERR("MHI is not in valid state\n");
|
||||
return;
|
||||
}
|
||||
|
||||
MHI_LOG("Device current EE:%s\n", TO_MHI_EXEC_STR(mhi_cntrl->ee));
|
||||
|
||||
/* if device in pthru, do reset to ready state transition */
|
||||
if (mhi_cntrl->ee == MHI_EE_PTHRU)
|
||||
goto fw_load_ee_pthru;
|
||||
|
||||
fw_name = (mhi_cntrl->ee == MHI_EE_EDL) ?
|
||||
mhi_cntrl->edl_image : mhi_cntrl->fw_image;
|
||||
|
||||
if (!fw_name || (mhi_cntrl->fbc_download && (!mhi_cntrl->sbl_size ||
|
||||
!mhi_cntrl->seg_len))) {
|
||||
MHI_ERR("No firmware image defined or !sbl_size || !seg_len\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = request_firmware(&firmware, fw_name, mhi_cntrl->dev);
|
||||
if (ret) {
|
||||
MHI_ERR("Error loading firmware, ret:%d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
size = (mhi_cntrl->fbc_download) ? mhi_cntrl->sbl_size : firmware->size;
|
||||
|
||||
/* the sbl size provided is maximum size, not necessarily image size */
|
||||
if (size > firmware->size)
|
||||
size = firmware->size;
|
||||
|
||||
buf = mhi_alloc_coherent(mhi_cntrl, size, &dma_addr, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
MHI_ERR("Could not allocate memory for image\n");
|
||||
release_firmware(firmware);
|
||||
return;
|
||||
}
|
||||
|
||||
/* load sbl image */
|
||||
memcpy(buf, firmware->data, size);
|
||||
ret = mhi_fw_load_sbl(mhi_cntrl, dma_addr, size);
|
||||
mhi_free_coherent(mhi_cntrl, size, buf, dma_addr);
|
||||
|
||||
if (!mhi_cntrl->fbc_download || ret || mhi_cntrl->ee == MHI_EE_EDL)
|
||||
release_firmware(firmware);
|
||||
|
||||
/* error or in edl, we're done */
|
||||
if (ret || mhi_cntrl->ee == MHI_EE_EDL)
|
||||
return;
|
||||
|
||||
write_lock_irq(&mhi_cntrl->pm_lock);
|
||||
mhi_cntrl->dev_state = MHI_STATE_RESET;
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
|
||||
/*
|
||||
* if we're doing fbc, populate vector tables while
|
||||
* device transitioning into MHI READY state
|
||||
*/
|
||||
if (mhi_cntrl->fbc_download) {
|
||||
ret = mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image,
|
||||
firmware->size);
|
||||
if (ret) {
|
||||
MHI_ERR("Error alloc size of %zu\n", firmware->size);
|
||||
goto error_alloc_fw_table;
|
||||
}
|
||||
|
||||
MHI_LOG("Copying firmware image into vector table\n");
|
||||
|
||||
/* load the firmware into BHIE vec table */
|
||||
mhi_firmware_copy(mhi_cntrl, firmware, mhi_cntrl->fbc_image);
|
||||
}
|
||||
|
||||
fw_load_ee_pthru:
|
||||
/* transitioning into MHI RESET->READY state */
|
||||
ret = mhi_ready_state_transition(mhi_cntrl);
|
||||
|
||||
MHI_LOG("To Reset->Ready PM_STATE:%s MHI_STATE:%s EE:%s, ret:%d\n",
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state),
|
||||
TO_MHI_STATE_STR(mhi_cntrl->dev_state),
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee), ret);
|
||||
|
||||
if (!mhi_cntrl->fbc_download)
|
||||
return;
|
||||
|
||||
if (ret) {
|
||||
MHI_ERR("Did not transition to READY state\n");
|
||||
goto error_read;
|
||||
}
|
||||
|
||||
/* wait for SBL event */
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
mhi_cntrl->ee == MHI_EE_SBL ||
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
|
||||
MHI_ERR("MHI did not enter BHIE\n");
|
||||
goto error_read;
|
||||
}
|
||||
|
||||
/* start full firmware image download */
|
||||
image_info = mhi_cntrl->fbc_image;
|
||||
ret = mhi_fw_load_amss(mhi_cntrl,
|
||||
/* last entry is vec table */
|
||||
&image_info->mhi_buf[image_info->entries - 1]);
|
||||
|
||||
MHI_LOG("amss fw_load, ret:%d\n", ret);
|
||||
|
||||
release_firmware(firmware);
|
||||
|
||||
return;
|
||||
|
||||
error_read:
|
||||
mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image);
|
||||
mhi_cntrl->fbc_image = NULL;
|
||||
|
||||
error_alloc_fw_table:
|
||||
release_firmware(firmware);
|
||||
}
|
227
drivers/bus/mhi/core/mhi_dtr.c
Normal file
227
drivers/bus/mhi/core/mhi_dtr.c
Normal file
@ -0,0 +1,227 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/termios.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mhi.h>
|
||||
#include "mhi_internal.h"
|
||||
|
||||
struct dtr_ctrl_msg {
|
||||
u32 preamble;
|
||||
u32 msg_id;
|
||||
u32 dest_id;
|
||||
u32 size;
|
||||
u32 msg;
|
||||
} __packed;
|
||||
|
||||
#define CTRL_MAGIC (0x4C525443)
|
||||
#define CTRL_MSG_DTR BIT(0)
|
||||
#define CTRL_MSG_RTS BIT(1)
|
||||
#define CTRL_MSG_DCD BIT(0)
|
||||
#define CTRL_MSG_DSR BIT(1)
|
||||
#define CTRL_MSG_RI BIT(3)
|
||||
#define CTRL_HOST_STATE (0x10)
|
||||
#define CTRL_DEVICE_STATE (0x11)
|
||||
#define CTRL_GET_CHID(dtr) (dtr->dest_id & 0xFF)
|
||||
|
||||
static int mhi_dtr_tiocmset(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_device *mhi_dev,
|
||||
u32 tiocm)
|
||||
{
|
||||
struct dtr_ctrl_msg *dtr_msg = NULL;
|
||||
struct mhi_chan *dtr_chan = mhi_cntrl->dtr_dev->ul_chan;
|
||||
spinlock_t *res_lock = &mhi_dev->dev.devres_lock;
|
||||
u32 cur_tiocm;
|
||||
int ret = 0;
|
||||
|
||||
cur_tiocm = mhi_dev->tiocm & ~(TIOCM_CD | TIOCM_DSR | TIOCM_RI);
|
||||
|
||||
tiocm &= (TIOCM_DTR | TIOCM_RTS);
|
||||
|
||||
/* state did not changed */
|
||||
if (cur_tiocm == tiocm)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&dtr_chan->mutex);
|
||||
|
||||
dtr_msg = kzalloc(sizeof(*dtr_msg), GFP_KERNEL);
|
||||
if (!dtr_msg) {
|
||||
ret = -ENOMEM;
|
||||
goto tiocm_exit;
|
||||
}
|
||||
|
||||
dtr_msg->preamble = CTRL_MAGIC;
|
||||
dtr_msg->msg_id = CTRL_HOST_STATE;
|
||||
dtr_msg->dest_id = mhi_dev->ul_chan_id;
|
||||
dtr_msg->size = sizeof(u32);
|
||||
if (tiocm & TIOCM_DTR)
|
||||
dtr_msg->msg |= CTRL_MSG_DTR;
|
||||
if (tiocm & TIOCM_RTS)
|
||||
dtr_msg->msg |= CTRL_MSG_RTS;
|
||||
|
||||
reinit_completion(&dtr_chan->completion);
|
||||
ret = mhi_queue_transfer(mhi_cntrl->dtr_dev, DMA_TO_DEVICE, dtr_msg,
|
||||
sizeof(*dtr_msg), MHI_EOT);
|
||||
if (ret)
|
||||
goto tiocm_exit;
|
||||
|
||||
ret = wait_for_completion_timeout(&dtr_chan->completion,
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
if (!ret) {
|
||||
MHI_ERR("Failed to receive transfer callback\n");
|
||||
ret = -EIO;
|
||||
goto tiocm_exit;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
spin_lock_irq(res_lock);
|
||||
mhi_dev->tiocm &= ~(TIOCM_DTR | TIOCM_RTS);
|
||||
mhi_dev->tiocm |= tiocm;
|
||||
spin_unlock_irq(res_lock);
|
||||
|
||||
tiocm_exit:
|
||||
kfree(dtr_msg);
|
||||
mutex_unlock(&dtr_chan->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
int ret;
|
||||
|
||||
/* ioctl not supported by this controller */
|
||||
if (!mhi_cntrl->dtr_dev)
|
||||
return -EIO;
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCMGET:
|
||||
return mhi_dev->tiocm;
|
||||
case TIOCMSET:
|
||||
{
|
||||
u32 tiocm;
|
||||
|
||||
ret = get_user(tiocm, (u32 __user *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mhi_dtr_tiocmset(mhi_cntrl, mhi_dev, tiocm);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
EXPORT_SYMBOL(mhi_ioctl);
|
||||
|
||||
static void mhi_dtr_dl_xfer_cb(struct mhi_device *mhi_dev,
|
||||
struct mhi_result *mhi_result)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
struct dtr_ctrl_msg *dtr_msg = mhi_result->buf_addr;
|
||||
u32 chan;
|
||||
spinlock_t *res_lock;
|
||||
|
||||
if (mhi_result->bytes_xferd != sizeof(*dtr_msg)) {
|
||||
MHI_ERR("Unexpected length %zu received\n",
|
||||
mhi_result->bytes_xferd);
|
||||
return;
|
||||
}
|
||||
|
||||
MHI_VERB("preamble:0x%x msg_id:%u dest_id:%u msg:0x%x\n",
|
||||
dtr_msg->preamble, dtr_msg->msg_id, dtr_msg->dest_id,
|
||||
dtr_msg->msg);
|
||||
|
||||
chan = CTRL_GET_CHID(dtr_msg);
|
||||
if (chan >= mhi_cntrl->max_chan)
|
||||
return;
|
||||
|
||||
mhi_dev = mhi_cntrl->mhi_chan[chan].mhi_dev;
|
||||
if (!mhi_dev)
|
||||
return;
|
||||
|
||||
res_lock = &mhi_dev->dev.devres_lock;
|
||||
spin_lock_irq(res_lock);
|
||||
mhi_dev->tiocm &= ~(TIOCM_CD | TIOCM_DSR | TIOCM_RI);
|
||||
|
||||
if (dtr_msg->msg & CTRL_MSG_DCD)
|
||||
mhi_dev->tiocm |= TIOCM_CD;
|
||||
|
||||
if (dtr_msg->msg & CTRL_MSG_DSR)
|
||||
mhi_dev->tiocm |= TIOCM_DSR;
|
||||
|
||||
if (dtr_msg->msg & CTRL_MSG_RI)
|
||||
mhi_dev->tiocm |= TIOCM_RI;
|
||||
spin_unlock_irq(res_lock);
|
||||
|
||||
/* Notify the update */
|
||||
mhi_notify(mhi_dev, MHI_CB_DTR_SIGNAL);
|
||||
}
|
||||
|
||||
static void mhi_dtr_ul_xfer_cb(struct mhi_device *mhi_dev,
|
||||
struct mhi_result *mhi_result)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
struct mhi_chan *dtr_chan = mhi_cntrl->dtr_dev->ul_chan;
|
||||
|
||||
MHI_VERB("Received with status:%d\n", mhi_result->transaction_status);
|
||||
if (!mhi_result->transaction_status)
|
||||
complete(&dtr_chan->completion);
|
||||
}
|
||||
|
||||
static void mhi_dtr_remove(struct mhi_device *mhi_dev)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
|
||||
mhi_cntrl->dtr_dev = NULL;
|
||||
}
|
||||
|
||||
static int mhi_dtr_probe(struct mhi_device *mhi_dev,
|
||||
const struct mhi_device_id *id)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
int ret;
|
||||
|
||||
MHI_LOG("Enter for DTR control channel\n");
|
||||
|
||||
ret = mhi_prepare_for_transfer(mhi_dev);
|
||||
if (!ret)
|
||||
mhi_cntrl->dtr_dev = mhi_dev;
|
||||
|
||||
MHI_LOG("Exit with ret:%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct mhi_device_id mhi_dtr_table[] = {
|
||||
{ .chan = "IP_CTRL" },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct mhi_driver mhi_dtr_driver = {
|
||||
.id_table = mhi_dtr_table,
|
||||
.remove = mhi_dtr_remove,
|
||||
.probe = mhi_dtr_probe,
|
||||
.ul_xfer_cb = mhi_dtr_ul_xfer_cb,
|
||||
.dl_xfer_cb = mhi_dtr_dl_xfer_cb,
|
||||
.driver = {
|
||||
.name = "MHI_DTR",
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
int __init mhi_dtr_init(void)
|
||||
{
|
||||
return mhi_driver_register(&mhi_dtr_driver);
|
||||
}
|
1861
drivers/bus/mhi/core/mhi_init.c
Normal file
1861
drivers/bus/mhi/core/mhi_init.c
Normal file
File diff suppressed because it is too large
Load Diff
940
drivers/bus/mhi/core/mhi_internal.h
Normal file
940
drivers/bus/mhi/core/mhi_internal.h
Normal file
@ -0,0 +1,940 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#include <linux/msm_rtb.h>
|
||||
|
||||
#ifndef _MHI_INT_H
|
||||
#define _MHI_INT_H
|
||||
|
||||
extern struct bus_type mhi_bus_type;
|
||||
|
||||
/* MHI mmio register mapping */
|
||||
#define PCI_INVALID_READ(val) (val == U32_MAX)
|
||||
#define MHI_REG_SIZE (SZ_4K)
|
||||
|
||||
#define MHIREGLEN (0x0)
|
||||
#define MHIREGLEN_MHIREGLEN_MASK (0xFFFFFFFF)
|
||||
#define MHIREGLEN_MHIREGLEN_SHIFT (0)
|
||||
|
||||
#define MHIVER (0x8)
|
||||
#define MHIVER_MHIVER_MASK (0xFFFFFFFF)
|
||||
#define MHIVER_MHIVER_SHIFT (0)
|
||||
|
||||
#define MHICFG (0x10)
|
||||
#define MHICFG_NHWER_MASK (0xFF000000)
|
||||
#define MHICFG_NHWER_SHIFT (24)
|
||||
#define MHICFG_NER_MASK (0xFF0000)
|
||||
#define MHICFG_NER_SHIFT (16)
|
||||
#define MHICFG_NHWCH_MASK (0xFF00)
|
||||
#define MHICFG_NHWCH_SHIFT (8)
|
||||
#define MHICFG_NCH_MASK (0xFF)
|
||||
#define MHICFG_NCH_SHIFT (0)
|
||||
|
||||
#define CHDBOFF (0x18)
|
||||
#define CHDBOFF_CHDBOFF_MASK (0xFFFFFFFF)
|
||||
#define CHDBOFF_CHDBOFF_SHIFT (0)
|
||||
|
||||
#define ERDBOFF (0x20)
|
||||
#define ERDBOFF_ERDBOFF_MASK (0xFFFFFFFF)
|
||||
#define ERDBOFF_ERDBOFF_SHIFT (0)
|
||||
|
||||
#define BHIOFF (0x28)
|
||||
#define BHIOFF_BHIOFF_MASK (0xFFFFFFFF)
|
||||
#define BHIOFF_BHIOFF_SHIFT (0)
|
||||
|
||||
#define BHIEOFF (0x2C)
|
||||
#define BHIEOFF_BHIEOFF_MASK (0xFFFFFFFF)
|
||||
#define BHIEOFF_BHIEOFF_SHIFT (0)
|
||||
|
||||
#define DEBUGOFF (0x30)
|
||||
#define DEBUGOFF_DEBUGOFF_MASK (0xFFFFFFFF)
|
||||
#define DEBUGOFF_DEBUGOFF_SHIFT (0)
|
||||
|
||||
#define MHICTRL (0x38)
|
||||
#define MHICTRL_MHISTATE_MASK (0x0000FF00)
|
||||
#define MHICTRL_MHISTATE_SHIFT (8)
|
||||
#define MHICTRL_RESET_MASK (0x2)
|
||||
#define MHICTRL_RESET_SHIFT (1)
|
||||
|
||||
#define MHISTATUS (0x48)
|
||||
#define MHISTATUS_MHISTATE_MASK (0x0000FF00)
|
||||
#define MHISTATUS_MHISTATE_SHIFT (8)
|
||||
#define MHISTATUS_SYSERR_MASK (0x4)
|
||||
#define MHISTATUS_SYSERR_SHIFT (2)
|
||||
#define MHISTATUS_READY_MASK (0x1)
|
||||
#define MHISTATUS_READY_SHIFT (0)
|
||||
|
||||
#define CCABAP_LOWER (0x58)
|
||||
#define CCABAP_LOWER_CCABAP_LOWER_MASK (0xFFFFFFFF)
|
||||
#define CCABAP_LOWER_CCABAP_LOWER_SHIFT (0)
|
||||
|
||||
#define CCABAP_HIGHER (0x5C)
|
||||
#define CCABAP_HIGHER_CCABAP_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define CCABAP_HIGHER_CCABAP_HIGHER_SHIFT (0)
|
||||
|
||||
#define ECABAP_LOWER (0x60)
|
||||
#define ECABAP_LOWER_ECABAP_LOWER_MASK (0xFFFFFFFF)
|
||||
#define ECABAP_LOWER_ECABAP_LOWER_SHIFT (0)
|
||||
|
||||
#define ECABAP_HIGHER (0x64)
|
||||
#define ECABAP_HIGHER_ECABAP_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define ECABAP_HIGHER_ECABAP_HIGHER_SHIFT (0)
|
||||
|
||||
#define CRCBAP_LOWER (0x68)
|
||||
#define CRCBAP_LOWER_CRCBAP_LOWER_MASK (0xFFFFFFFF)
|
||||
#define CRCBAP_LOWER_CRCBAP_LOWER_SHIFT (0)
|
||||
|
||||
#define CRCBAP_HIGHER (0x6C)
|
||||
#define CRCBAP_HIGHER_CRCBAP_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define CRCBAP_HIGHER_CRCBAP_HIGHER_SHIFT (0)
|
||||
|
||||
#define CRDB_LOWER (0x70)
|
||||
#define CRDB_LOWER_CRDB_LOWER_MASK (0xFFFFFFFF)
|
||||
#define CRDB_LOWER_CRDB_LOWER_SHIFT (0)
|
||||
|
||||
#define CRDB_HIGHER (0x74)
|
||||
#define CRDB_HIGHER_CRDB_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define CRDB_HIGHER_CRDB_HIGHER_SHIFT (0)
|
||||
|
||||
#define MHICTRLBASE_LOWER (0x80)
|
||||
#define MHICTRLBASE_LOWER_MHICTRLBASE_LOWER_MASK (0xFFFFFFFF)
|
||||
#define MHICTRLBASE_LOWER_MHICTRLBASE_LOWER_SHIFT (0)
|
||||
|
||||
#define MHICTRLBASE_HIGHER (0x84)
|
||||
#define MHICTRLBASE_HIGHER_MHICTRLBASE_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define MHICTRLBASE_HIGHER_MHICTRLBASE_HIGHER_SHIFT (0)
|
||||
|
||||
#define MHICTRLLIMIT_LOWER (0x88)
|
||||
#define MHICTRLLIMIT_LOWER_MHICTRLLIMIT_LOWER_MASK (0xFFFFFFFF)
|
||||
#define MHICTRLLIMIT_LOWER_MHICTRLLIMIT_LOWER_SHIFT (0)
|
||||
|
||||
#define MHICTRLLIMIT_HIGHER (0x8C)
|
||||
#define MHICTRLLIMIT_HIGHER_MHICTRLLIMIT_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define MHICTRLLIMIT_HIGHER_MHICTRLLIMIT_HIGHER_SHIFT (0)
|
||||
|
||||
#define MHIDATABASE_LOWER (0x98)
|
||||
#define MHIDATABASE_LOWER_MHIDATABASE_LOWER_MASK (0xFFFFFFFF)
|
||||
#define MHIDATABASE_LOWER_MHIDATABASE_LOWER_SHIFT (0)
|
||||
|
||||
#define MHIDATABASE_HIGHER (0x9C)
|
||||
#define MHIDATABASE_HIGHER_MHIDATABASE_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define MHIDATABASE_HIGHER_MHIDATABASE_HIGHER_SHIFT (0)
|
||||
|
||||
#define MHIDATALIMIT_LOWER (0xA0)
|
||||
#define MHIDATALIMIT_LOWER_MHIDATALIMIT_LOWER_MASK (0xFFFFFFFF)
|
||||
#define MHIDATALIMIT_LOWER_MHIDATALIMIT_LOWER_SHIFT (0)
|
||||
|
||||
#define MHIDATALIMIT_HIGHER (0xA4)
|
||||
#define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_SHIFT (0)
|
||||
|
||||
/* Host request register */
|
||||
#define MHI_SOC_RESET_REQ_OFFSET (0xB0)
|
||||
#define MHI_SOC_RESET_REQ BIT(0)
|
||||
|
||||
/* MHI misc capability registers */
|
||||
#define MISC_OFFSET (0x24)
|
||||
#define MISC_CAP_MASK (0xFFFFFFFF)
|
||||
#define MISC_CAP_SHIFT (0)
|
||||
|
||||
#define CAP_CAPID_MASK (0xFF000000)
|
||||
#define CAP_CAPID_SHIFT (24)
|
||||
#define CAP_NEXT_CAP_MASK (0x00FFF000)
|
||||
#define CAP_NEXT_CAP_SHIFT (12)
|
||||
|
||||
/* MHI Timesync offsets */
|
||||
#define TIMESYNC_CFG_OFFSET (0x00)
|
||||
#define TIMESYNC_CFG_CAPID_MASK (CAP_CAPID_MASK)
|
||||
#define TIMESYNC_CFG_CAPID_SHIFT (CAP_CAPID_SHIFT)
|
||||
#define TIMESYNC_CFG_NEXT_OFF_MASK (CAP_NEXT_CAP_MASK)
|
||||
#define TIMESYNC_CFG_NEXT_OFF_SHIFT (CAP_NEXT_CAP_SHIFT)
|
||||
#define TIMESYNC_CFG_NUMCMD_MASK (0xFF)
|
||||
#define TIMESYNC_CFG_NUMCMD_SHIFT (0)
|
||||
#define TIMESYNC_DB_OFFSET (0x4)
|
||||
#define TIMESYNC_TIME_LOW_OFFSET (0x8)
|
||||
#define TIMESYNC_TIME_HIGH_OFFSET (0xC)
|
||||
|
||||
#define TIMESYNC_CAP_ID (2)
|
||||
|
||||
/* MHI Bandwidth scaling offsets */
|
||||
#define BW_SCALE_CFG_OFFSET (0x04)
|
||||
#define BW_SCALE_CFG_CHAN_DB_ID_MASK (0xFE000000)
|
||||
#define BW_SCALE_CFG_CHAN_DB_ID_SHIFT (25)
|
||||
#define BW_SCALE_CFG_ENABLED_MASK (0x01000000)
|
||||
#define BW_SCALE_CFG_ENABLED_SHIFT (24)
|
||||
#define BW_SCALE_CFG_ER_ID_MASK (0x00F80000)
|
||||
#define BW_SCALE_CFG_ER_ID_SHIFT (19)
|
||||
|
||||
#define BW_SCALE_CAP_ID (3)
|
||||
|
||||
/* MHI BHI offfsets */
|
||||
#define BHI_BHIVERSION_MINOR (0x00)
|
||||
#define BHI_BHIVERSION_MAJOR (0x04)
|
||||
#define BHI_IMGADDR_LOW (0x08)
|
||||
#define BHI_IMGADDR_HIGH (0x0C)
|
||||
#define BHI_IMGSIZE (0x10)
|
||||
#define BHI_RSVD1 (0x14)
|
||||
#define BHI_IMGTXDB (0x18)
|
||||
#define BHI_TXDB_SEQNUM_BMSK (0x3FFFFFFF)
|
||||
#define BHI_TXDB_SEQNUM_SHFT (0)
|
||||
#define BHI_RSVD2 (0x1C)
|
||||
#define BHI_INTVEC (0x20)
|
||||
#define BHI_RSVD3 (0x24)
|
||||
#define BHI_EXECENV (0x28)
|
||||
#define BHI_STATUS (0x2C)
|
||||
#define BHI_ERRCODE (0x30)
|
||||
#define BHI_ERRDBG1 (0x34)
|
||||
#define BHI_ERRDBG2 (0x38)
|
||||
#define BHI_ERRDBG3 (0x3C)
|
||||
#define BHI_SERIALNU (0x40)
|
||||
#define BHI_SBLANTIROLLVER (0x44)
|
||||
#define BHI_NUMSEG (0x48)
|
||||
#define BHI_MSMHWID(n) (0x4C + (0x4 * n))
|
||||
#define BHI_OEMPKHASH(n) (0x64 + (0x4 * n))
|
||||
#define BHI_RSVD5 (0xC4)
|
||||
#define BHI_STATUS_MASK (0xC0000000)
|
||||
#define BHI_STATUS_SHIFT (30)
|
||||
#define BHI_STATUS_ERROR (3)
|
||||
#define BHI_STATUS_SUCCESS (2)
|
||||
#define BHI_STATUS_RESET (0)
|
||||
|
||||
/* MHI BHIE offsets */
|
||||
#define BHIE_MSMSOCID_OFFS (0x0000)
|
||||
#define BHIE_TXVECADDR_LOW_OFFS (0x002C)
|
||||
#define BHIE_TXVECADDR_HIGH_OFFS (0x0030)
|
||||
#define BHIE_TXVECSIZE_OFFS (0x0034)
|
||||
#define BHIE_TXVECDB_OFFS (0x003C)
|
||||
#define BHIE_TXVECDB_SEQNUM_BMSK (0x3FFFFFFF)
|
||||
#define BHIE_TXVECDB_SEQNUM_SHFT (0)
|
||||
#define BHIE_TXVECSTATUS_OFFS (0x0044)
|
||||
#define BHIE_TXVECSTATUS_SEQNUM_BMSK (0x3FFFFFFF)
|
||||
#define BHIE_TXVECSTATUS_SEQNUM_SHFT (0)
|
||||
#define BHIE_TXVECSTATUS_STATUS_BMSK (0xC0000000)
|
||||
#define BHIE_TXVECSTATUS_STATUS_SHFT (30)
|
||||
#define BHIE_TXVECSTATUS_STATUS_RESET (0x00)
|
||||
#define BHIE_TXVECSTATUS_STATUS_XFER_COMPL (0x02)
|
||||
#define BHIE_TXVECSTATUS_STATUS_ERROR (0x03)
|
||||
#define BHIE_RXVECADDR_LOW_OFFS (0x0060)
|
||||
#define BHIE_RXVECADDR_HIGH_OFFS (0x0064)
|
||||
#define BHIE_RXVECSIZE_OFFS (0x0068)
|
||||
#define BHIE_RXVECDB_OFFS (0x0070)
|
||||
#define BHIE_RXVECDB_SEQNUM_BMSK (0x3FFFFFFF)
|
||||
#define BHIE_RXVECDB_SEQNUM_SHFT (0)
|
||||
#define BHIE_RXVECSTATUS_OFFS (0x0078)
|
||||
#define BHIE_RXVECSTATUS_SEQNUM_BMSK (0x3FFFFFFF)
|
||||
#define BHIE_RXVECSTATUS_SEQNUM_SHFT (0)
|
||||
#define BHIE_RXVECSTATUS_STATUS_BMSK (0xC0000000)
|
||||
#define BHIE_RXVECSTATUS_STATUS_SHFT (30)
|
||||
#define BHIE_RXVECSTATUS_STATUS_RESET (0x00)
|
||||
#define BHIE_RXVECSTATUS_STATUS_XFER_COMPL (0x02)
|
||||
#define BHIE_RXVECSTATUS_STATUS_ERROR (0x03)
|
||||
|
||||
#define SOC_HW_VERSION_OFFS (0x224)
|
||||
#define SOC_HW_VERSION_FAM_NUM_BMSK (0xF0000000)
|
||||
#define SOC_HW_VERSION_FAM_NUM_SHFT (28)
|
||||
#define SOC_HW_VERSION_DEV_NUM_BMSK (0x0FFF0000)
|
||||
#define SOC_HW_VERSION_DEV_NUM_SHFT (16)
|
||||
#define SOC_HW_VERSION_MAJOR_VER_BMSK (0x0000FF00)
|
||||
#define SOC_HW_VERSION_MAJOR_VER_SHFT (8)
|
||||
#define SOC_HW_VERSION_MINOR_VER_BMSK (0x000000FF)
|
||||
#define SOC_HW_VERSION_MINOR_VER_SHFT (0)
|
||||
|
||||
/* timesync time calculations */
|
||||
#define LOCAL_TICKS_TO_US(x) (div_u64((x) * 100ULL, \
|
||||
div_u64(mhi_cntrl->local_timer_freq, 10000ULL)))
|
||||
#define REMOTE_TICKS_TO_US(x) (div_u64((x) * 100ULL, \
|
||||
div_u64(mhi_cntrl->remote_timer_freq, 10000ULL)))
|
||||
|
||||
struct mhi_event_ctxt {
|
||||
u32 reserved : 8;
|
||||
u32 intmodc : 8;
|
||||
u32 intmodt : 16;
|
||||
u32 ertype;
|
||||
u32 msivec;
|
||||
|
||||
u64 rbase __packed __aligned(4);
|
||||
u64 rlen __packed __aligned(4);
|
||||
u64 rp __packed __aligned(4);
|
||||
u64 wp __packed __aligned(4);
|
||||
};
|
||||
|
||||
struct mhi_chan_ctxt {
|
||||
u32 chstate : 8;
|
||||
u32 brstmode : 2;
|
||||
u32 pollcfg : 6;
|
||||
u32 reserved : 16;
|
||||
u32 chtype;
|
||||
u32 erindex;
|
||||
|
||||
u64 rbase __packed __aligned(4);
|
||||
u64 rlen __packed __aligned(4);
|
||||
u64 rp __packed __aligned(4);
|
||||
u64 wp __packed __aligned(4);
|
||||
};
|
||||
|
||||
struct mhi_cmd_ctxt {
|
||||
u32 reserved0;
|
||||
u32 reserved1;
|
||||
u32 reserved2;
|
||||
|
||||
u64 rbase __packed __aligned(4);
|
||||
u64 rlen __packed __aligned(4);
|
||||
u64 rp __packed __aligned(4);
|
||||
u64 wp __packed __aligned(4);
|
||||
};
|
||||
|
||||
struct mhi_tre {
|
||||
u64 ptr;
|
||||
u32 dword[2];
|
||||
};
|
||||
|
||||
struct bhi_vec_entry {
|
||||
u64 dma_addr;
|
||||
u64 size;
|
||||
};
|
||||
|
||||
enum mhi_cmd_type {
|
||||
MHI_CMD_TYPE_NOP = 1,
|
||||
MHI_CMD_TYPE_RESET = 16,
|
||||
MHI_CMD_TYPE_STOP = 17,
|
||||
MHI_CMD_TYPE_START = 18,
|
||||
MHI_CMD_TYPE_TSYNC = 24,
|
||||
};
|
||||
|
||||
/* no operation command */
|
||||
#define MHI_TRE_CMD_NOOP_PTR (0)
|
||||
#define MHI_TRE_CMD_NOOP_DWORD0 (0)
|
||||
#define MHI_TRE_CMD_NOOP_DWORD1 (MHI_CMD_TYPE_NOP << 16)
|
||||
|
||||
/* channel reset command */
|
||||
#define MHI_TRE_CMD_RESET_PTR (0)
|
||||
#define MHI_TRE_CMD_RESET_DWORD0 (0)
|
||||
#define MHI_TRE_CMD_RESET_DWORD1(chid) ((chid << 24) | \
|
||||
(MHI_CMD_TYPE_RESET << 16))
|
||||
|
||||
/* channel stop command */
|
||||
#define MHI_TRE_CMD_STOP_PTR (0)
|
||||
#define MHI_TRE_CMD_STOP_DWORD0 (0)
|
||||
#define MHI_TRE_CMD_STOP_DWORD1(chid) ((chid << 24) | (MHI_CMD_TYPE_STOP << 16))
|
||||
|
||||
/* channel start command */
|
||||
#define MHI_TRE_CMD_START_PTR (0)
|
||||
#define MHI_TRE_CMD_START_DWORD0 (0)
|
||||
#define MHI_TRE_CMD_START_DWORD1(chid) ((chid << 24) | \
|
||||
(MHI_CMD_TYPE_START << 16))
|
||||
|
||||
/* time sync cfg command */
|
||||
#define MHI_TRE_CMD_TSYNC_CFG_PTR (0)
|
||||
#define MHI_TRE_CMD_TSYNC_CFG_DWORD0 (0)
|
||||
#define MHI_TRE_CMD_TSYNC_CFG_DWORD1(er) ((MHI_CMD_TYPE_TSYNC << 16) | \
|
||||
(er << 24))
|
||||
|
||||
#define MHI_TRE_GET_CMD_CHID(tre) (((tre)->dword[1] >> 24) & 0xFF)
|
||||
#define MHI_TRE_GET_CMD_TYPE(tre) (((tre)->dword[1] >> 16) & 0xFF)
|
||||
|
||||
/* event descriptor macros */
|
||||
#define MHI_TRE_EV_PTR(ptr) (ptr)
|
||||
#define MHI_TRE_EV_DWORD0(code, len) ((code << 24) | len)
|
||||
#define MHI_TRE_EV_DWORD1(chid, type) ((chid << 24) | (type << 16))
|
||||
#define MHI_TRE_GET_EV_PTR(tre) ((tre)->ptr)
|
||||
#define MHI_TRE_GET_EV_CODE(tre) (((tre)->dword[0] >> 24) & 0xFF)
|
||||
#define MHI_TRE_GET_EV_LEN(tre) ((tre)->dword[0] & 0xFFFF)
|
||||
#define MHI_TRE_GET_EV_CHID(tre) (((tre)->dword[1] >> 24) & 0xFF)
|
||||
#define MHI_TRE_GET_EV_TYPE(tre) (((tre)->dword[1] >> 16) & 0xFF)
|
||||
#define MHI_TRE_GET_EV_STATE(tre) (((tre)->dword[0] >> 24) & 0xFF)
|
||||
#define MHI_TRE_GET_EV_EXECENV(tre) (((tre)->dword[0] >> 24) & 0xFF)
|
||||
#define MHI_TRE_GET_EV_TSYNC_SEQ(tre) ((tre)->dword[0])
|
||||
#define MHI_TRE_GET_EV_TIME(tre) ((tre)->ptr)
|
||||
#define MHI_TRE_GET_EV_COOKIE(tre) lower_32_bits((tre)->ptr)
|
||||
#define MHI_TRE_GET_EV_VEID(tre) (((tre)->dword[0] >> 16) & 0xFF)
|
||||
#define MHI_TRE_GET_EV_LINKSPEED(tre) (((tre)->dword[1] >> 24) & 0xFF)
|
||||
#define MHI_TRE_GET_EV_LINKWIDTH(tre) ((tre)->dword[0] & 0xFF)
|
||||
#define MHI_TRE_GET_EV_BW_REQ_SEQ(tre) (((tre)->dword[0] >> 8) & 0xFF)
|
||||
|
||||
/* transfer descriptor macros */
|
||||
#define MHI_TRE_DATA_PTR(ptr) (ptr)
|
||||
#define MHI_TRE_DATA_DWORD0(len) (len & MHI_MAX_MTU)
|
||||
#define MHI_TRE_DATA_DWORD1(bei, ieot, ieob, chain) ((2 << 16) | (bei << 10) \
|
||||
| (ieot << 9) | (ieob << 8) | chain)
|
||||
|
||||
/* rsc transfer descriptor macros */
|
||||
#define MHI_RSCTRE_DATA_PTR(ptr, len) (((u64)len << 48) | ptr)
|
||||
#define MHI_RSCTRE_DATA_DWORD0(cookie) (cookie)
|
||||
#define MHI_RSCTRE_DATA_DWORD1 (MHI_PKT_TYPE_COALESCING << 16)
|
||||
|
||||
enum MHI_CMD {
|
||||
MHI_CMD_RESET_CHAN,
|
||||
MHI_CMD_START_CHAN,
|
||||
MHI_CMD_STOP_CHAN,
|
||||
MHI_CMD_TIMSYNC_CFG,
|
||||
};
|
||||
|
||||
enum MHI_PKT_TYPE {
|
||||
MHI_PKT_TYPE_INVALID = 0x0,
|
||||
MHI_PKT_TYPE_NOOP_CMD = 0x1,
|
||||
MHI_PKT_TYPE_TRANSFER = 0x2,
|
||||
MHI_PKT_TYPE_COALESCING = 0x8,
|
||||
MHI_PKT_TYPE_RESET_CHAN_CMD = 0x10,
|
||||
MHI_PKT_TYPE_STOP_CHAN_CMD = 0x11,
|
||||
MHI_PKT_TYPE_START_CHAN_CMD = 0x12,
|
||||
MHI_PKT_TYPE_STATE_CHANGE_EVENT = 0x20,
|
||||
MHI_PKT_TYPE_CMD_COMPLETION_EVENT = 0x21,
|
||||
MHI_PKT_TYPE_TX_EVENT = 0x22,
|
||||
MHI_PKT_TYPE_RSC_TX_EVENT = 0x28,
|
||||
MHI_PKT_TYPE_EE_EVENT = 0x40,
|
||||
MHI_PKT_TYPE_TSYNC_EVENT = 0x48,
|
||||
MHI_PKT_TYPE_BW_REQ_EVENT = 0x50,
|
||||
MHI_PKT_TYPE_STALE_EVENT, /* internal event */
|
||||
};
|
||||
|
||||
/* MHI transfer completion events */
|
||||
enum MHI_EV_CCS {
|
||||
MHI_EV_CC_INVALID = 0x0,
|
||||
MHI_EV_CC_SUCCESS = 0x1,
|
||||
MHI_EV_CC_EOT = 0x2,
|
||||
MHI_EV_CC_OVERFLOW = 0x3,
|
||||
MHI_EV_CC_EOB = 0x4,
|
||||
MHI_EV_CC_OOB = 0x5,
|
||||
MHI_EV_CC_DB_MODE = 0x6,
|
||||
MHI_EV_CC_UNDEFINED_ERR = 0x10,
|
||||
MHI_EV_CC_BAD_TRE = 0x11,
|
||||
};
|
||||
|
||||
enum MHI_CH_STATE {
|
||||
MHI_CH_STATE_DISABLED = 0x0,
|
||||
MHI_CH_STATE_ENABLED = 0x1,
|
||||
MHI_CH_STATE_RUNNING = 0x2,
|
||||
MHI_CH_STATE_SUSPENDED = 0x3,
|
||||
MHI_CH_STATE_STOP = 0x4,
|
||||
MHI_CH_STATE_ERROR = 0x5,
|
||||
};
|
||||
|
||||
enum MHI_BRSTMODE {
|
||||
MHI_BRSTMODE_DISABLE = 0x2,
|
||||
MHI_BRSTMODE_ENABLE = 0x3,
|
||||
};
|
||||
|
||||
#define MHI_INVALID_BRSTMODE(mode) (mode != MHI_BRSTMODE_DISABLE && \
|
||||
mode != MHI_BRSTMODE_ENABLE)
|
||||
|
||||
extern const char * const mhi_ee_str[MHI_EE_MAX];
|
||||
#define TO_MHI_EXEC_STR(ee) (((ee) >= MHI_EE_MAX) ? \
|
||||
"INVALID_EE" : mhi_ee_str[ee])
|
||||
|
||||
#define MHI_IN_PBL(ee) (ee == MHI_EE_PBL || ee == MHI_EE_PTHRU || \
|
||||
ee == MHI_EE_EDL)
|
||||
|
||||
#define MHI_IN_MISSION_MODE(ee) (ee == MHI_EE_AMSS || ee == MHI_EE_WFW)
|
||||
|
||||
enum MHI_ST_TRANSITION {
|
||||
MHI_ST_TRANSITION_PBL,
|
||||
MHI_ST_TRANSITION_READY,
|
||||
MHI_ST_TRANSITION_SBL,
|
||||
MHI_ST_TRANSITION_MISSION_MODE,
|
||||
MHI_ST_TRANSITION_DISABLE,
|
||||
MHI_ST_TRANSITION_MAX,
|
||||
};
|
||||
|
||||
extern const char * const mhi_state_tran_str[MHI_ST_TRANSITION_MAX];
|
||||
#define TO_MHI_STATE_TRANS_STR(state) (((state) >= MHI_ST_TRANSITION_MAX) ? \
|
||||
"INVALID_STATE" : mhi_state_tran_str[state])
|
||||
|
||||
extern const char * const mhi_state_str[MHI_STATE_MAX];
|
||||
#define TO_MHI_STATE_STR(state) ((state >= MHI_STATE_MAX || \
|
||||
!mhi_state_str[state]) ? \
|
||||
"INVALID_STATE" : mhi_state_str[state])
|
||||
|
||||
extern const char * const mhi_log_level_str[MHI_MSG_LVL_MAX];
|
||||
#define TO_MHI_LOG_LEVEL_STR(level) ((level >= MHI_MSG_LVL_MAX || \
|
||||
!mhi_log_level_str[level]) ? \
|
||||
"Mask all" : mhi_log_level_str[level])
|
||||
|
||||
enum {
|
||||
MHI_PM_BIT_DISABLE,
|
||||
MHI_PM_BIT_POR,
|
||||
MHI_PM_BIT_M0,
|
||||
MHI_PM_BIT_M2,
|
||||
MHI_PM_BIT_M3_ENTER,
|
||||
MHI_PM_BIT_M3,
|
||||
MHI_PM_BIT_M3_EXIT,
|
||||
MHI_PM_BIT_FW_DL_ERR,
|
||||
MHI_PM_BIT_DEVICE_ERR_DETECT,
|
||||
MHI_PM_BIT_SYS_ERR_DETECT,
|
||||
MHI_PM_BIT_SYS_ERR_PROCESS,
|
||||
MHI_PM_BIT_SHUTDOWN_PROCESS,
|
||||
MHI_PM_BIT_LD_ERR_FATAL_DETECT,
|
||||
MHI_PM_BIT_SHUTDOWN_NO_ACCESS,
|
||||
MHI_PM_BIT_MAX
|
||||
};
|
||||
|
||||
/* internal power states */
|
||||
enum MHI_PM_STATE {
|
||||
MHI_PM_DISABLE = BIT(MHI_PM_BIT_DISABLE), /* MHI is not enabled */
|
||||
MHI_PM_POR = BIT(MHI_PM_BIT_POR), /* reset state */
|
||||
MHI_PM_M0 = BIT(MHI_PM_BIT_M0),
|
||||
MHI_PM_M2 = BIT(MHI_PM_BIT_M2),
|
||||
MHI_PM_M3_ENTER = BIT(MHI_PM_BIT_M3_ENTER),
|
||||
MHI_PM_M3 = BIT(MHI_PM_BIT_M3),
|
||||
MHI_PM_M3_EXIT = BIT(MHI_PM_BIT_M3_EXIT),
|
||||
/* firmware download failure state */
|
||||
MHI_PM_FW_DL_ERR = BIT(MHI_PM_BIT_FW_DL_ERR),
|
||||
/* error or shutdown detected or processing state */
|
||||
MHI_PM_DEVICE_ERR_DETECT = BIT(MHI_PM_BIT_DEVICE_ERR_DETECT),
|
||||
MHI_PM_SYS_ERR_DETECT = BIT(MHI_PM_BIT_SYS_ERR_DETECT),
|
||||
MHI_PM_SYS_ERR_PROCESS = BIT(MHI_PM_BIT_SYS_ERR_PROCESS),
|
||||
MHI_PM_SHUTDOWN_PROCESS = BIT(MHI_PM_BIT_SHUTDOWN_PROCESS),
|
||||
/* link not accessible */
|
||||
MHI_PM_LD_ERR_FATAL_DETECT = BIT(MHI_PM_BIT_LD_ERR_FATAL_DETECT),
|
||||
MHI_PM_SHUTDOWN_NO_ACCESS = BIT(MHI_PM_BIT_SHUTDOWN_NO_ACCESS),
|
||||
};
|
||||
|
||||
#define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \
|
||||
MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \
|
||||
MHI_PM_DEVICE_ERR_DETECT | MHI_PM_SYS_ERR_DETECT | \
|
||||
MHI_PM_SYS_ERR_PROCESS | MHI_PM_SHUTDOWN_PROCESS | \
|
||||
MHI_PM_FW_DL_ERR)))
|
||||
#define MHI_PM_IN_ERROR_STATE(pm_state) (pm_state >= MHI_PM_FW_DL_ERR)
|
||||
#define MHI_PM_IN_FATAL_STATE(pm_state) (pm_state >= MHI_PM_LD_ERR_FATAL_DETECT)
|
||||
#define MHI_DB_ACCESS_VALID(mhi_cntrl) (mhi_cntrl->pm_state & \
|
||||
mhi_cntrl->db_access)
|
||||
#define MHI_WAKE_DB_CLEAR_VALID(pm_state) (pm_state & (MHI_PM_M0 | \
|
||||
MHI_PM_M2 | MHI_PM_M3_EXIT))
|
||||
#define MHI_WAKE_DB_SET_VALID(pm_state) (pm_state & MHI_PM_M2)
|
||||
#define MHI_WAKE_DB_FORCE_SET_VALID(pm_state) MHI_WAKE_DB_CLEAR_VALID(pm_state)
|
||||
#define MHI_EVENT_ACCESS_INVALID(pm_state) (pm_state == MHI_PM_DISABLE || \
|
||||
MHI_PM_IN_ERROR_STATE(pm_state))
|
||||
#define MHI_PM_IN_SUSPEND_STATE(pm_state) (pm_state & \
|
||||
(MHI_PM_M3_ENTER | MHI_PM_M3))
|
||||
|
||||
/* accepted buffer type for the channel */
|
||||
enum MHI_XFER_TYPE {
|
||||
MHI_XFER_BUFFER,
|
||||
MHI_XFER_SKB,
|
||||
MHI_XFER_SCLIST,
|
||||
MHI_XFER_NOP, /* CPU offload channel, host does not accept transfer */
|
||||
MHI_XFER_DMA, /* receive dma address, already mapped by client */
|
||||
MHI_XFER_RSC_DMA, /* RSC type, accept premapped buffer */
|
||||
};
|
||||
|
||||
#define NR_OF_CMD_RINGS (1)
|
||||
#define CMD_EL_PER_RING (128)
|
||||
#define PRIMARY_CMD_RING (0)
|
||||
#define MHI_BW_SCALE_CHAN_DB (126)
|
||||
#define MHI_DEV_WAKE_DB (127)
|
||||
#define MHI_MAX_MTU (0xffff)
|
||||
|
||||
#define MHI_BW_SCALE_SETUP(er_index) ((MHI_BW_SCALE_CHAN_DB << \
|
||||
BW_SCALE_CFG_CHAN_DB_ID_SHIFT) & BW_SCALE_CFG_CHAN_DB_ID_MASK | \
|
||||
(1 << BW_SCALE_CFG_ENABLED_SHIFT) & BW_SCALE_CFG_ENABLED_MASK | \
|
||||
((er_index) << BW_SCALE_CFG_ER_ID_SHIFT) & BW_SCALE_CFG_ER_ID_MASK)
|
||||
|
||||
#define MHI_BW_SCALE_RESULT(status, seq) ((status & 0xF) << 8 | (seq & 0xFF))
|
||||
#define MHI_BW_SCALE_NACK 0xF
|
||||
|
||||
enum MHI_ER_TYPE {
|
||||
MHI_ER_TYPE_INVALID = 0x0,
|
||||
MHI_ER_TYPE_VALID = 0x1,
|
||||
};
|
||||
|
||||
enum mhi_er_priority {
|
||||
MHI_ER_PRIORITY_HIGH,
|
||||
MHI_ER_PRIORITY_MEDIUM,
|
||||
MHI_ER_PRIORITY_LOW,
|
||||
};
|
||||
|
||||
#define IS_MHI_ER_PRIORITY_LOW(ev) (ev->priority >= MHI_ER_PRIORITY_LOW)
|
||||
#define IS_MHI_ER_PRIORITY_HIGH(ev) (ev->priority == MHI_ER_PRIORITY_HIGH)
|
||||
|
||||
enum mhi_er_data_type {
|
||||
MHI_ER_DATA_ELEMENT_TYPE,
|
||||
MHI_ER_CTRL_ELEMENT_TYPE,
|
||||
MHI_ER_TSYNC_ELEMENT_TYPE,
|
||||
MHI_ER_BW_SCALE_ELEMENT_TYPE,
|
||||
MHI_ER_DATA_TYPE_MAX = MHI_ER_BW_SCALE_ELEMENT_TYPE,
|
||||
};
|
||||
|
||||
enum mhi_ch_ee_mask {
|
||||
MHI_CH_EE_PBL = BIT(MHI_EE_PBL),
|
||||
MHI_CH_EE_SBL = BIT(MHI_EE_SBL),
|
||||
MHI_CH_EE_AMSS = BIT(MHI_EE_AMSS),
|
||||
MHI_CH_EE_RDDM = BIT(MHI_EE_RDDM),
|
||||
MHI_CH_EE_PTHRU = BIT(MHI_EE_PTHRU),
|
||||
MHI_CH_EE_WFW = BIT(MHI_EE_WFW),
|
||||
MHI_CH_EE_EDL = BIT(MHI_EE_EDL),
|
||||
};
|
||||
|
||||
enum mhi_ch_type {
|
||||
MHI_CH_TYPE_INVALID = 0,
|
||||
MHI_CH_TYPE_OUTBOUND = DMA_TO_DEVICE,
|
||||
MHI_CH_TYPE_INBOUND = DMA_FROM_DEVICE,
|
||||
MHI_CH_TYPE_INBOUND_COALESCED = 3,
|
||||
};
|
||||
|
||||
struct db_cfg {
|
||||
bool reset_req;
|
||||
bool db_mode;
|
||||
u32 pollcfg;
|
||||
enum MHI_BRSTMODE brstmode;
|
||||
dma_addr_t db_val;
|
||||
void (*process_db)(struct mhi_controller *mhi_cntrl,
|
||||
struct db_cfg *db_cfg, void __iomem *io_addr,
|
||||
dma_addr_t db_val);
|
||||
};
|
||||
|
||||
struct mhi_pm_transitions {
|
||||
enum MHI_PM_STATE from_state;
|
||||
u32 to_states;
|
||||
};
|
||||
|
||||
struct state_transition {
|
||||
struct list_head node;
|
||||
enum MHI_ST_TRANSITION state;
|
||||
enum MHI_PM_STATE pm_state;
|
||||
};
|
||||
|
||||
struct mhi_ctxt {
|
||||
struct mhi_event_ctxt *er_ctxt;
|
||||
struct mhi_chan_ctxt *chan_ctxt;
|
||||
struct mhi_cmd_ctxt *cmd_ctxt;
|
||||
dma_addr_t er_ctxt_addr;
|
||||
dma_addr_t chan_ctxt_addr;
|
||||
dma_addr_t cmd_ctxt_addr;
|
||||
};
|
||||
|
||||
struct mhi_ring {
|
||||
dma_addr_t dma_handle;
|
||||
dma_addr_t iommu_base;
|
||||
u64 *ctxt_wp; /* point to ctxt wp */
|
||||
void *pre_aligned;
|
||||
void *base;
|
||||
void *rp;
|
||||
void *wp;
|
||||
size_t el_size;
|
||||
size_t len;
|
||||
size_t elements;
|
||||
size_t alloc_size;
|
||||
void __iomem *db_addr;
|
||||
};
|
||||
|
||||
struct mhi_cmd {
|
||||
struct mhi_ring ring;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
struct mhi_buf_info {
|
||||
dma_addr_t p_addr;
|
||||
void *v_addr;
|
||||
void *bb_addr;
|
||||
void *wp;
|
||||
size_t len;
|
||||
void *cb_buf;
|
||||
bool used; /* indicate element is free to use */
|
||||
bool pre_mapped; /* already pre-mapped by client */
|
||||
enum dma_data_direction dir;
|
||||
};
|
||||
|
||||
struct mhi_event {
|
||||
struct list_head node;
|
||||
u32 er_index;
|
||||
u32 intmod;
|
||||
u32 msi;
|
||||
int chan; /* this event ring is dedicated to a channel */
|
||||
enum mhi_er_priority priority;
|
||||
enum mhi_er_data_type data_type;
|
||||
struct mhi_ring ring;
|
||||
struct db_cfg db_cfg;
|
||||
bool hw_ring;
|
||||
bool cl_manage;
|
||||
bool offload_ev; /* managed by a device driver */
|
||||
bool request_irq; /* has dedicated interrupt handler */
|
||||
spinlock_t lock;
|
||||
struct mhi_chan *mhi_chan; /* dedicated to channel */
|
||||
struct tasklet_struct task;
|
||||
int (*process_event)(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_event *mhi_event,
|
||||
u32 event_quota);
|
||||
struct mhi_controller *mhi_cntrl;
|
||||
};
|
||||
|
||||
struct mhi_chan {
|
||||
u32 chan;
|
||||
const char *name;
|
||||
/*
|
||||
* important, when consuming increment tre_ring first, when releasing
|
||||
* decrement buf_ring first. If tre_ring has space, buf_ring
|
||||
* guranteed to have space so we do not need to check both rings.
|
||||
*/
|
||||
struct mhi_ring buf_ring;
|
||||
struct mhi_ring tre_ring;
|
||||
u32 er_index;
|
||||
enum mhi_ch_type type;
|
||||
enum dma_data_direction dir;
|
||||
struct db_cfg db_cfg;
|
||||
u32 ee_mask;
|
||||
enum MHI_XFER_TYPE xfer_type;
|
||||
enum MHI_CH_STATE ch_state;
|
||||
enum MHI_EV_CCS ccs;
|
||||
bool bei; /* based on interrupt moderation, true if greater than 0 */
|
||||
bool lpm_notify;
|
||||
bool configured;
|
||||
bool offload_ch;
|
||||
bool pre_alloc;
|
||||
bool auto_start;
|
||||
bool wake_capable; /* channel should wake up system */
|
||||
/* functions that generate the transfer ring elements */
|
||||
int (*gen_tre)(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan, void *buf, void *cb,
|
||||
size_t len, enum MHI_FLAGS flags);
|
||||
int (*queue_xfer)(struct mhi_device *mhi_dev,
|
||||
struct mhi_chan *mhi_chan, void *buf,
|
||||
size_t len, enum MHI_FLAGS flags);
|
||||
/* xfer call back */
|
||||
struct mhi_device *mhi_dev;
|
||||
void (*xfer_cb)(struct mhi_device *mhi_dev, struct mhi_result *result);
|
||||
struct mutex mutex;
|
||||
struct completion completion;
|
||||
rwlock_t lock;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct tsync_node {
|
||||
struct list_head node;
|
||||
u32 sequence;
|
||||
u64 local_time;
|
||||
u64 remote_time;
|
||||
struct mhi_device *mhi_dev;
|
||||
void (*cb_func)(struct mhi_device *mhi_dev, u32 sequence,
|
||||
u64 local_time, u64 remote_time);
|
||||
};
|
||||
|
||||
struct mhi_timesync {
|
||||
u32 er_index;
|
||||
void __iomem *db;
|
||||
void __iomem *time_reg;
|
||||
enum MHI_EV_CCS ccs;
|
||||
struct completion completion;
|
||||
spinlock_t lock; /* list protection */
|
||||
struct mutex lpm_mutex; /* lpm protection */
|
||||
struct list_head head;
|
||||
};
|
||||
|
||||
struct mhi_bus {
|
||||
struct list_head controller_list;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
/* default MHI timeout */
|
||||
#define MHI_TIMEOUT_MS (1000)
|
||||
extern struct mhi_bus mhi_bus;
|
||||
|
||||
/* debug fs related functions */
|
||||
int mhi_debugfs_mhi_chan_show(struct seq_file *m, void *d);
|
||||
int mhi_debugfs_mhi_event_show(struct seq_file *m, void *d);
|
||||
int mhi_debugfs_mhi_states_show(struct seq_file *m, void *d);
|
||||
int mhi_debugfs_trigger_reset(void *data, u64 val);
|
||||
|
||||
void mhi_deinit_debugfs(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_init_debugfs(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
/* power management apis */
|
||||
enum MHI_PM_STATE __must_check mhi_tryset_pm_state(
|
||||
struct mhi_controller *mhi_cntrl,
|
||||
enum MHI_PM_STATE state);
|
||||
const char *to_mhi_pm_state_str(enum MHI_PM_STATE state);
|
||||
void mhi_reset_chan(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan);
|
||||
enum mhi_ee mhi_get_exec_env(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl,
|
||||
enum MHI_ST_TRANSITION state);
|
||||
void mhi_pm_st_worker(struct work_struct *work);
|
||||
void mhi_fw_load_worker(struct work_struct *work);
|
||||
void mhi_process_sys_err(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_low_priority_worker(struct work_struct *work);
|
||||
int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_ctrl_ev_task(unsigned long data);
|
||||
int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_pm_m3_transition(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_notify(struct mhi_device *mhi_dev, enum MHI_CB cb_reason);
|
||||
int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_event *mhi_event, u32 event_quota);
|
||||
int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_event *mhi_event, u32 event_quota);
|
||||
int mhi_process_tsync_event_ring(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_event *mhi_event, u32 event_quota);
|
||||
int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_event *mhi_event, u32 event_quota);
|
||||
int mhi_send_cmd(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
||||
enum MHI_CMD cmd);
|
||||
int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
static inline void mhi_trigger_resume(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data);
|
||||
mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data);
|
||||
pm_wakeup_hard_event(&mhi_cntrl->mhi_dev->dev);
|
||||
}
|
||||
|
||||
/* queue transfer buffer */
|
||||
int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
||||
void *buf, void *cb, size_t buf_len, enum MHI_FLAGS flags);
|
||||
int mhi_queue_buf(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
|
||||
void *buf, size_t len, enum MHI_FLAGS mflags);
|
||||
int mhi_queue_skb(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
|
||||
void *buf, size_t len, enum MHI_FLAGS mflags);
|
||||
int mhi_queue_sclist(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
|
||||
void *buf, size_t len, enum MHI_FLAGS mflags);
|
||||
int mhi_queue_nop(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
|
||||
void *buf, size_t len, enum MHI_FLAGS mflags);
|
||||
int mhi_queue_dma(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
|
||||
void *buf, size_t len, enum MHI_FLAGS mflags);
|
||||
|
||||
/* register access methods */
|
||||
void mhi_db_brstmode(struct mhi_controller *mhi_cntrl, struct db_cfg *db_cfg,
|
||||
void __iomem *db_addr, dma_addr_t wp);
|
||||
void mhi_db_brstmode_disable(struct mhi_controller *mhi_cntrl,
|
||||
struct db_cfg *db_mode, void __iomem *db_addr,
|
||||
dma_addr_t wp);
|
||||
int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl,
|
||||
void __iomem *base, u32 offset, u32 *out);
|
||||
int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl,
|
||||
void __iomem *base, u32 offset, u32 mask,
|
||||
u32 shift, u32 *out);
|
||||
void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *base,
|
||||
u32 offset, u32 val);
|
||||
void mhi_write_reg_field(struct mhi_controller *mhi_cntrl, void __iomem *base,
|
||||
u32 offset, u32 mask, u32 shift, u32 val);
|
||||
void mhi_ring_er_db(struct mhi_event *mhi_event);
|
||||
void mhi_write_db(struct mhi_controller *mhi_cntrl, void __iomem *db_addr,
|
||||
dma_addr_t wp);
|
||||
void mhi_ring_cmd_db(struct mhi_controller *mhi_cntrl, struct mhi_cmd *mhi_cmd);
|
||||
void mhi_ring_chan_db(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan);
|
||||
int mhi_get_capability_offset(struct mhi_controller *mhi_cntrl, u32 capability,
|
||||
u32 *offset);
|
||||
void *mhi_to_virtual(struct mhi_ring *ring, dma_addr_t addr);
|
||||
int mhi_init_timesync(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_create_timesync_sysfs(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_destroy_timesync(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_create_sysfs(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_destroy_sysfs(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_early_notify_device(struct device *dev, void *data);
|
||||
|
||||
/* timesync log support */
|
||||
static inline void mhi_timesync_log(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_timesync *mhi_tsync = mhi_cntrl->mhi_tsync;
|
||||
|
||||
if (mhi_tsync && mhi_cntrl->tsync_log)
|
||||
mhi_cntrl->tsync_log(mhi_cntrl,
|
||||
readq_no_log(mhi_tsync->time_reg));
|
||||
}
|
||||
|
||||
/* memory allocation methods */
|
||||
static inline void *mhi_alloc_coherent(struct mhi_controller *mhi_cntrl,
|
||||
size_t size,
|
||||
dma_addr_t *dma_handle,
|
||||
gfp_t gfp)
|
||||
{
|
||||
void *buf = dma_alloc_coherent(mhi_cntrl->dev, size, dma_handle, gfp);
|
||||
|
||||
if (buf)
|
||||
atomic_add(size, &mhi_cntrl->alloc_size);
|
||||
|
||||
return buf;
|
||||
}
|
||||
static inline void mhi_free_coherent(struct mhi_controller *mhi_cntrl,
|
||||
size_t size,
|
||||
void *vaddr,
|
||||
dma_addr_t dma_handle)
|
||||
{
|
||||
atomic_sub(size, &mhi_cntrl->alloc_size);
|
||||
dma_free_coherent(mhi_cntrl->dev, size, vaddr, dma_handle);
|
||||
}
|
||||
|
||||
static inline void *mhi_alloc_contig_coherent(
|
||||
struct mhi_controller *mhi_cntrl,
|
||||
size_t size, dma_addr_t *dma_handle,
|
||||
gfp_t gfp)
|
||||
{
|
||||
void *buf = dma_alloc_attrs(mhi_cntrl->dev, size, dma_handle, gfp,
|
||||
DMA_ATTR_FORCE_CONTIGUOUS);
|
||||
|
||||
if (buf)
|
||||
atomic_add(size, &mhi_cntrl->alloc_size);
|
||||
|
||||
return buf;
|
||||
}
|
||||
static inline void mhi_free_contig_coherent(
|
||||
struct mhi_controller *mhi_cntrl,
|
||||
size_t size, void *vaddr,
|
||||
dma_addr_t dma_handle)
|
||||
{
|
||||
atomic_sub(size, &mhi_cntrl->alloc_size);
|
||||
dma_free_attrs(mhi_cntrl->dev, size, vaddr, dma_handle,
|
||||
DMA_ATTR_FORCE_CONTIGUOUS);
|
||||
}
|
||||
|
||||
struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl);
|
||||
static inline void mhi_dealloc_device(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_device *mhi_dev)
|
||||
{
|
||||
kfree(mhi_dev);
|
||||
}
|
||||
int mhi_destroy_device(struct device *dev, void *data);
|
||||
void mhi_create_devices(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl,
|
||||
struct image_info **image_info, size_t alloc_size);
|
||||
void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl,
|
||||
struct image_info *image_info);
|
||||
|
||||
int mhi_map_single_no_bb(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_buf_info *buf_info);
|
||||
int mhi_map_single_use_bb(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_buf_info *buf_info);
|
||||
void mhi_unmap_single_no_bb(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_buf_info *buf_info);
|
||||
void mhi_unmap_single_use_bb(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_buf_info *buf_info);
|
||||
|
||||
/* initialization methods */
|
||||
int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan);
|
||||
void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan);
|
||||
int mhi_init_mmio(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_deinit_dev_ctxt(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_deinit_free_irq(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_dtr_init(void);
|
||||
void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
|
||||
struct image_info *img_info);
|
||||
int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan);
|
||||
|
||||
/* isr handlers */
|
||||
irqreturn_t mhi_msi_handlr(int irq_number, void *dev);
|
||||
irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev);
|
||||
irqreturn_t mhi_intvec_handlr(int irq_number, void *dev);
|
||||
void mhi_ev_task(unsigned long data);
|
||||
|
||||
#ifdef CONFIG_MHI_DEBUG
|
||||
|
||||
#define MHI_ASSERT(cond, msg) do { \
|
||||
if (cond) \
|
||||
panic(msg); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define MHI_ASSERT(cond, msg) do { \
|
||||
if (cond) { \
|
||||
MHI_ERR(msg); \
|
||||
WARN_ON(cond); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _MHI_INT_H */
|
2540
drivers/bus/mhi/core/mhi_main.c
Normal file
2540
drivers/bus/mhi/core/mhi_main.c
Normal file
File diff suppressed because it is too large
Load Diff
1571
drivers/bus/mhi/core/mhi_pm.c
Normal file
1571
drivers/bus/mhi/core/mhi_pm.c
Normal file
File diff suppressed because it is too large
Load Diff
35
drivers/bus/mhi/devices/Kconfig
Normal file
35
drivers/bus/mhi/devices/Kconfig
Normal file
@ -0,0 +1,35 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
menu "MHI device support"
|
||||
|
||||
config MHI_NETDEV
|
||||
tristate "MHI NETDEV"
|
||||
depends on MHI_BUS
|
||||
help
|
||||
MHI based net device driver for transferring IP traffic
|
||||
between host and modem. By enabling this driver, clients
|
||||
can transfer data using standard network interface. Over
|
||||
the air traffic goes thru mhi netdev interface.
|
||||
|
||||
config MHI_UCI
|
||||
tristate "MHI UCI"
|
||||
depends on MHI_BUS
|
||||
help
|
||||
MHI based uci driver is for transferring data between host and
|
||||
modem using standard file operations from user space. Open, read,
|
||||
write, ioctl, and close operations are supported by this driver.
|
||||
Please check mhi_uci_match_table for all supported channels that
|
||||
are exposed to userspace.
|
||||
|
||||
config MHI_SATELLITE
|
||||
tristate "MHI SATELLITE"
|
||||
depends on MHI_BUS
|
||||
help
|
||||
MHI proxy satellite device driver enables NON-HLOS MHI satellite
|
||||
drivers to communicate with device over PCIe link without host
|
||||
involvement. Host facilitates propagation of events from device
|
||||
to NON-HLOS MHI satellite drivers, channel states, and power
|
||||
management over IPC communication. It helps in HLOS power
|
||||
savings.
|
||||
|
||||
endmenu
|
5
drivers/bus/mhi/devices/Makefile
Normal file
5
drivers/bus/mhi/devices/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_MHI_NETDEV) +=mhi_netdev.o
|
||||
obj-$(CONFIG_MHI_UCI) +=mhi_uci.o
|
||||
obj-$(CONFIG_MHI_SATELLITE) +=mhi_satellite.o
|
1143
drivers/bus/mhi/devices/mhi_netdev.c
Normal file
1143
drivers/bus/mhi/devices/mhi_netdev.c
Normal file
File diff suppressed because it is too large
Load Diff
1220
drivers/bus/mhi/devices/mhi_satellite.c
Normal file
1220
drivers/bus/mhi/devices/mhi_satellite.c
Normal file
File diff suppressed because it is too large
Load Diff
759
drivers/bus/mhi/devices/mhi_uci.c
Normal file
759
drivers/bus/mhi/devices/mhi_uci.c
Normal file
@ -0,0 +1,759 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.*/
|
||||
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ipc_logging.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/termios.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/mhi.h>
|
||||
|
||||
#define DEVICE_NAME "mhi"
|
||||
#define MHI_UCI_DRIVER_NAME "mhi_uci"
|
||||
|
||||
struct uci_chan {
|
||||
wait_queue_head_t wq;
|
||||
spinlock_t lock;
|
||||
struct list_head pending; /* user space waiting to read */
|
||||
struct uci_buf *cur_buf; /* current buffer user space reading */
|
||||
size_t rx_size;
|
||||
};
|
||||
|
||||
struct uci_buf {
|
||||
void *data;
|
||||
size_t len;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct uci_dev {
|
||||
struct list_head node;
|
||||
dev_t devt;
|
||||
struct device *dev;
|
||||
struct mhi_device *mhi_dev;
|
||||
const char *chan;
|
||||
struct mutex mutex; /* sync open and close */
|
||||
struct uci_chan ul_chan;
|
||||
struct uci_chan dl_chan;
|
||||
size_t mtu;
|
||||
size_t actual_mtu; /* maximum size of incoming buffer */
|
||||
int ref_count;
|
||||
bool enabled;
|
||||
u32 tiocm;
|
||||
void *ipc_log;
|
||||
};
|
||||
|
||||
struct mhi_uci_drv {
|
||||
struct list_head head;
|
||||
struct mutex lock;
|
||||
struct class *class;
|
||||
int major;
|
||||
dev_t dev_t;
|
||||
};
|
||||
|
||||
static enum MHI_DEBUG_LEVEL msg_lvl = MHI_MSG_LVL_ERROR;
|
||||
|
||||
#ifdef CONFIG_MHI_DEBUG
|
||||
|
||||
#define IPC_LOG_LVL (MHI_MSG_LVL_VERBOSE)
|
||||
#define MHI_UCI_IPC_LOG_PAGES (25)
|
||||
|
||||
#else
|
||||
|
||||
#define IPC_LOG_LVL (MHI_MSG_LVL_ERROR)
|
||||
#define MHI_UCI_IPC_LOG_PAGES (1)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MHI_DEBUG
|
||||
|
||||
#define MSG_VERB(fmt, ...) do { \
|
||||
if (msg_lvl <= MHI_MSG_LVL_VERBOSE) \
|
||||
printk("%s[D][%s] " fmt, KERN_ERR, __func__, \
|
||||
##__VA_ARGS__); \
|
||||
if (IPC_LOG_LVL <= MHI_MSG_LVL_VERBOSE) \
|
||||
ipc_log_string(uci_dev->ipc_log, "%s[D][%s] " fmt, \
|
||||
"", __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define MSG_VERB(fmt, ...)
|
||||
|
||||
#endif
|
||||
|
||||
#define MSG_LOG(fmt, ...) do { \
|
||||
if (msg_lvl <= MHI_MSG_LVL_INFO) \
|
||||
printk("%s[I][%s] " fmt, KERN_ERR, __func__, \
|
||||
##__VA_ARGS__); \
|
||||
if (IPC_LOG_LVL <= MHI_MSG_LVL_INFO) \
|
||||
ipc_log_string(uci_dev->ipc_log, "%s[I][%s] " fmt, \
|
||||
"", __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define MSG_ERR(fmt, ...) do { \
|
||||
if (msg_lvl <= MHI_MSG_LVL_ERROR) \
|
||||
printk("%s[E][%s] " fmt, KERN_ERR, __func__, \
|
||||
##__VA_ARGS__); \
|
||||
if (IPC_LOG_LVL <= MHI_MSG_LVL_ERROR) \
|
||||
ipc_log_string(uci_dev->ipc_log, "%s[E][%s] " fmt, \
|
||||
"", __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define MAX_UCI_DEVICES (64)
|
||||
|
||||
static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES);
|
||||
static struct mhi_uci_drv mhi_uci_drv;
|
||||
|
||||
static int mhi_queue_inbound(struct uci_dev *uci_dev)
|
||||
{
|
||||
struct mhi_device *mhi_dev = uci_dev->mhi_dev;
|
||||
int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE);
|
||||
size_t mtu = uci_dev->mtu;
|
||||
size_t actual_mtu = uci_dev->actual_mtu;
|
||||
void *buf;
|
||||
struct uci_buf *uci_buf;
|
||||
int ret = -EIO, i;
|
||||
|
||||
for (i = 0; i < nr_trbs; i++) {
|
||||
buf = kmalloc(mtu, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
uci_buf = buf + actual_mtu;
|
||||
uci_buf->data = buf;
|
||||
|
||||
MSG_VERB("Allocated buf %d of %d size %ld\n", i, nr_trbs,
|
||||
actual_mtu);
|
||||
|
||||
ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf,
|
||||
actual_mtu, MHI_EOT);
|
||||
if (ret) {
|
||||
kfree(buf);
|
||||
MSG_ERR("Failed to queue buffer %d\n", i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long mhi_uci_ioctl(struct file *file,
|
||||
unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct uci_dev *uci_dev = file->private_data;
|
||||
struct mhi_device *mhi_dev = uci_dev->mhi_dev;
|
||||
struct uci_chan *uci_chan = &uci_dev->dl_chan;
|
||||
long ret = -ENOIOCTLCMD;
|
||||
|
||||
mutex_lock(&uci_dev->mutex);
|
||||
|
||||
if (cmd == TIOCMGET) {
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
ret = uci_dev->tiocm;
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
} else if (uci_dev->enabled) {
|
||||
ret = mhi_ioctl(mhi_dev, cmd, arg);
|
||||
if (!ret) {
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
uci_dev->tiocm = mhi_dev->tiocm;
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mhi_uci_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct uci_dev *uci_dev = file->private_data;
|
||||
|
||||
mutex_lock(&uci_dev->mutex);
|
||||
uci_dev->ref_count--;
|
||||
if (!uci_dev->ref_count) {
|
||||
struct uci_buf *itr, *tmp;
|
||||
struct uci_chan *uci_chan;
|
||||
|
||||
MSG_LOG("Last client left, closing node\n");
|
||||
|
||||
if (uci_dev->enabled)
|
||||
mhi_unprepare_from_transfer(uci_dev->mhi_dev);
|
||||
|
||||
/* clean inbound channel */
|
||||
uci_chan = &uci_dev->dl_chan;
|
||||
list_for_each_entry_safe(itr, tmp, &uci_chan->pending, node) {
|
||||
list_del(&itr->node);
|
||||
kfree(itr->data);
|
||||
}
|
||||
if (uci_chan->cur_buf)
|
||||
kfree(uci_chan->cur_buf->data);
|
||||
|
||||
uci_chan->cur_buf = NULL;
|
||||
|
||||
if (!uci_dev->enabled) {
|
||||
MSG_LOG("Node is deleted, freeing dev node\n");
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
mutex_destroy(&uci_dev->mutex);
|
||||
clear_bit(MINOR(uci_dev->devt), uci_minors);
|
||||
kfree(uci_dev);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
MSG_LOG("exit: ref_count:%d\n", uci_dev->ref_count);
|
||||
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __poll_t mhi_uci_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
struct uci_dev *uci_dev = file->private_data;
|
||||
struct mhi_device *mhi_dev = uci_dev->mhi_dev;
|
||||
struct uci_chan *uci_chan;
|
||||
__poll_t mask = 0;
|
||||
|
||||
poll_wait(file, &uci_dev->dl_chan.wq, wait);
|
||||
poll_wait(file, &uci_dev->ul_chan.wq, wait);
|
||||
|
||||
uci_chan = &uci_dev->dl_chan;
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
if (!uci_dev->enabled) {
|
||||
mask = EPOLLERR;
|
||||
} else {
|
||||
if (!list_empty(&uci_chan->pending) || uci_chan->cur_buf) {
|
||||
MSG_VERB("Client can read from node\n");
|
||||
mask |= EPOLLIN | EPOLLRDNORM;
|
||||
}
|
||||
|
||||
if (uci_dev->tiocm) {
|
||||
MSG_VERB("Line status changed\n");
|
||||
mask |= EPOLLPRI;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
uci_chan = &uci_dev->ul_chan;
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
if (!uci_dev->enabled) {
|
||||
mask |= EPOLLERR;
|
||||
} else if (mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE) > 0) {
|
||||
MSG_VERB("Client can write to node\n");
|
||||
mask |= EPOLLOUT | EPOLLWRNORM;
|
||||
}
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
MSG_LOG("Client attempted to poll, returning mask 0x%x\n", mask);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static ssize_t mhi_uci_write(struct file *file,
|
||||
const char __user *buf,
|
||||
size_t count,
|
||||
loff_t *offp)
|
||||
{
|
||||
struct uci_dev *uci_dev = file->private_data;
|
||||
struct mhi_device *mhi_dev = uci_dev->mhi_dev;
|
||||
struct uci_chan *uci_chan = &uci_dev->ul_chan;
|
||||
size_t bytes_xfered = 0;
|
||||
int ret, nr_avail;
|
||||
|
||||
if (!buf || !count)
|
||||
return -EINVAL;
|
||||
|
||||
/* confirm channel is active */
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
if (!uci_dev->enabled) {
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
MSG_VERB("Enter: to xfer:%lu bytes\n", count);
|
||||
|
||||
while (count) {
|
||||
size_t xfer_size;
|
||||
void *kbuf;
|
||||
enum MHI_FLAGS flags;
|
||||
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
/* wait for free descriptors */
|
||||
ret = wait_event_interruptible(uci_chan->wq,
|
||||
(!uci_dev->enabled) ||
|
||||
(nr_avail = mhi_get_no_free_descriptors(mhi_dev,
|
||||
DMA_TO_DEVICE)) > 0);
|
||||
|
||||
if (ret == -ERESTARTSYS || !uci_dev->enabled) {
|
||||
MSG_LOG("Exit signal caught for node or not enabled\n");
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
xfer_size = min_t(size_t, count, uci_dev->mtu);
|
||||
kbuf = kmalloc(xfer_size, GFP_KERNEL);
|
||||
if (!kbuf) {
|
||||
MSG_ERR("Failed to allocate memory %lu\n", xfer_size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = copy_from_user(kbuf, buf, xfer_size);
|
||||
if (unlikely(ret)) {
|
||||
kfree(kbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
|
||||
/* if ring is full after this force EOT */
|
||||
if (nr_avail > 1 && (count - xfer_size))
|
||||
flags = MHI_CHAIN;
|
||||
else
|
||||
flags = MHI_EOT;
|
||||
|
||||
if (uci_dev->enabled)
|
||||
ret = mhi_queue_transfer(mhi_dev, DMA_TO_DEVICE, kbuf,
|
||||
xfer_size, flags);
|
||||
else
|
||||
ret = -ERESTARTSYS;
|
||||
|
||||
if (ret) {
|
||||
kfree(kbuf);
|
||||
goto sys_interrupt;
|
||||
}
|
||||
|
||||
bytes_xfered += xfer_size;
|
||||
count -= xfer_size;
|
||||
buf += xfer_size;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
MSG_VERB("Exit: Number of bytes xferred:%lu\n", bytes_xfered);
|
||||
|
||||
return bytes_xfered;
|
||||
|
||||
sys_interrupt:
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t mhi_uci_read(struct file *file,
|
||||
char __user *buf,
|
||||
size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct uci_dev *uci_dev = file->private_data;
|
||||
struct mhi_device *mhi_dev = uci_dev->mhi_dev;
|
||||
struct uci_chan *uci_chan = &uci_dev->dl_chan;
|
||||
struct uci_buf *uci_buf;
|
||||
char *ptr;
|
||||
size_t to_copy;
|
||||
int ret = 0;
|
||||
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
|
||||
MSG_VERB("Client provided buf len:%lu\n", count);
|
||||
|
||||
/* confirm channel is active */
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
if (!uci_dev->enabled) {
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
/* No data available to read, wait */
|
||||
if (!uci_chan->cur_buf && list_empty(&uci_chan->pending)) {
|
||||
MSG_VERB("No data available to read waiting\n");
|
||||
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
ret = wait_event_interruptible(uci_chan->wq,
|
||||
(!uci_dev->enabled ||
|
||||
!list_empty(&uci_chan->pending)));
|
||||
if (ret == -ERESTARTSYS) {
|
||||
MSG_LOG("Exit signal caught for node\n");
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
if (!uci_dev->enabled) {
|
||||
MSG_LOG("node is disabled\n");
|
||||
ret = -ERESTARTSYS;
|
||||
goto read_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* new read, get the next descriptor from the list */
|
||||
if (!uci_chan->cur_buf) {
|
||||
uci_buf = list_first_entry_or_null(&uci_chan->pending,
|
||||
struct uci_buf, node);
|
||||
if (unlikely(!uci_buf)) {
|
||||
ret = -EIO;
|
||||
goto read_error;
|
||||
}
|
||||
|
||||
list_del(&uci_buf->node);
|
||||
uci_chan->cur_buf = uci_buf;
|
||||
uci_chan->rx_size = uci_buf->len;
|
||||
MSG_VERB("Got pkt of size:%zu\n", uci_chan->rx_size);
|
||||
}
|
||||
|
||||
uci_buf = uci_chan->cur_buf;
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
/* Copy the buffer to user space */
|
||||
to_copy = min_t(size_t, count, uci_chan->rx_size);
|
||||
ptr = uci_buf->data + (uci_buf->len - uci_chan->rx_size);
|
||||
ret = copy_to_user(buf, ptr, to_copy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
MSG_VERB("Copied %lu of %lu bytes\n", to_copy, uci_chan->rx_size);
|
||||
uci_chan->rx_size -= to_copy;
|
||||
|
||||
/* we finished with this buffer, queue it back to hardware */
|
||||
if (!uci_chan->rx_size) {
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
uci_chan->cur_buf = NULL;
|
||||
|
||||
if (uci_dev->enabled)
|
||||
ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE,
|
||||
uci_buf->data,
|
||||
uci_dev->actual_mtu, MHI_EOT);
|
||||
else
|
||||
ret = -ERESTARTSYS;
|
||||
|
||||
if (ret) {
|
||||
MSG_ERR("Failed to recycle element\n");
|
||||
kfree(uci_buf->data);
|
||||
goto read_error;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
}
|
||||
|
||||
MSG_VERB("Returning %lu bytes\n", to_copy);
|
||||
|
||||
return to_copy;
|
||||
|
||||
read_error:
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mhi_uci_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct uci_dev *uci_dev = NULL, *tmp_dev;
|
||||
int ret = -EIO;
|
||||
struct uci_buf *buf_itr, *tmp;
|
||||
struct uci_chan *dl_chan;
|
||||
|
||||
mutex_lock(&mhi_uci_drv.lock);
|
||||
list_for_each_entry(tmp_dev, &mhi_uci_drv.head, node) {
|
||||
if (tmp_dev->devt == inode->i_rdev) {
|
||||
uci_dev = tmp_dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* could not find a minor node */
|
||||
if (!uci_dev)
|
||||
goto error_exit;
|
||||
|
||||
mutex_lock(&uci_dev->mutex);
|
||||
if (!uci_dev->enabled) {
|
||||
MSG_ERR("Node exist, but not in active state!\n");
|
||||
goto error_open_chan;
|
||||
}
|
||||
|
||||
uci_dev->ref_count++;
|
||||
|
||||
MSG_LOG("Node open, ref counts %u\n", uci_dev->ref_count);
|
||||
|
||||
if (uci_dev->ref_count == 1) {
|
||||
MSG_LOG("Starting channel\n");
|
||||
ret = mhi_prepare_for_transfer(uci_dev->mhi_dev);
|
||||
if (ret) {
|
||||
MSG_ERR("Error starting transfer channels\n");
|
||||
uci_dev->ref_count--;
|
||||
goto error_open_chan;
|
||||
}
|
||||
|
||||
ret = mhi_queue_inbound(uci_dev);
|
||||
if (ret)
|
||||
goto error_rx_queue;
|
||||
}
|
||||
|
||||
filp->private_data = uci_dev;
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
mutex_unlock(&mhi_uci_drv.lock);
|
||||
|
||||
return 0;
|
||||
|
||||
error_rx_queue:
|
||||
dl_chan = &uci_dev->dl_chan;
|
||||
mhi_unprepare_from_transfer(uci_dev->mhi_dev);
|
||||
list_for_each_entry_safe(buf_itr, tmp, &dl_chan->pending, node) {
|
||||
list_del(&buf_itr->node);
|
||||
kfree(buf_itr->data);
|
||||
}
|
||||
|
||||
error_open_chan:
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
|
||||
error_exit:
|
||||
mutex_unlock(&mhi_uci_drv.lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations mhidev_fops = {
|
||||
.open = mhi_uci_open,
|
||||
.release = mhi_uci_release,
|
||||
.read = mhi_uci_read,
|
||||
.write = mhi_uci_write,
|
||||
.poll = mhi_uci_poll,
|
||||
.unlocked_ioctl = mhi_uci_ioctl,
|
||||
};
|
||||
|
||||
static void mhi_uci_remove(struct mhi_device *mhi_dev)
|
||||
{
|
||||
struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev);
|
||||
|
||||
MSG_LOG("Enter\n");
|
||||
|
||||
|
||||
mutex_lock(&mhi_uci_drv.lock);
|
||||
mutex_lock(&uci_dev->mutex);
|
||||
|
||||
/* disable the node */
|
||||
spin_lock_irq(&uci_dev->dl_chan.lock);
|
||||
spin_lock_irq(&uci_dev->ul_chan.lock);
|
||||
uci_dev->enabled = false;
|
||||
spin_unlock_irq(&uci_dev->ul_chan.lock);
|
||||
spin_unlock_irq(&uci_dev->dl_chan.lock);
|
||||
wake_up(&uci_dev->dl_chan.wq);
|
||||
wake_up(&uci_dev->ul_chan.wq);
|
||||
|
||||
/* delete the node to prevent new opens */
|
||||
device_destroy(mhi_uci_drv.class, uci_dev->devt);
|
||||
uci_dev->dev = NULL;
|
||||
list_del(&uci_dev->node);
|
||||
|
||||
/* safe to free memory only if all file nodes are closed */
|
||||
if (!uci_dev->ref_count) {
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
mutex_destroy(&uci_dev->mutex);
|
||||
clear_bit(MINOR(uci_dev->devt), uci_minors);
|
||||
kfree(uci_dev);
|
||||
mutex_unlock(&mhi_uci_drv.lock);
|
||||
return;
|
||||
}
|
||||
|
||||
MSG_LOG("Exit\n");
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
mutex_unlock(&mhi_uci_drv.lock);
|
||||
|
||||
}
|
||||
|
||||
static int mhi_uci_probe(struct mhi_device *mhi_dev,
|
||||
const struct mhi_device_id *id)
|
||||
{
|
||||
struct uci_dev *uci_dev;
|
||||
int minor;
|
||||
char node_name[32];
|
||||
int dir;
|
||||
|
||||
uci_dev = kzalloc(sizeof(*uci_dev), GFP_KERNEL);
|
||||
if (!uci_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&uci_dev->mutex);
|
||||
uci_dev->mhi_dev = mhi_dev;
|
||||
|
||||
minor = find_first_zero_bit(uci_minors, MAX_UCI_DEVICES);
|
||||
if (minor >= MAX_UCI_DEVICES) {
|
||||
kfree(uci_dev);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
mutex_lock(&uci_dev->mutex);
|
||||
mutex_lock(&mhi_uci_drv.lock);
|
||||
|
||||
uci_dev->devt = MKDEV(mhi_uci_drv.major, minor);
|
||||
uci_dev->dev = device_create(mhi_uci_drv.class, &mhi_dev->dev,
|
||||
uci_dev->devt, uci_dev,
|
||||
DEVICE_NAME "_%04x_%02u.%02u.%02u%s%d",
|
||||
mhi_dev->dev_id, mhi_dev->domain,
|
||||
mhi_dev->bus, mhi_dev->slot, "_pipe_",
|
||||
mhi_dev->ul_chan_id);
|
||||
set_bit(minor, uci_minors);
|
||||
|
||||
/* create debugging buffer */
|
||||
snprintf(node_name, sizeof(node_name), "mhi_uci_%04x_%02u.%02u.%02u_%d",
|
||||
mhi_dev->dev_id, mhi_dev->domain, mhi_dev->bus, mhi_dev->slot,
|
||||
mhi_dev->ul_chan_id);
|
||||
uci_dev->ipc_log = ipc_log_context_create(MHI_UCI_IPC_LOG_PAGES,
|
||||
node_name, 0);
|
||||
|
||||
for (dir = 0; dir < 2; dir++) {
|
||||
struct uci_chan *uci_chan = (dir) ?
|
||||
&uci_dev->ul_chan : &uci_dev->dl_chan;
|
||||
spin_lock_init(&uci_chan->lock);
|
||||
init_waitqueue_head(&uci_chan->wq);
|
||||
INIT_LIST_HEAD(&uci_chan->pending);
|
||||
}
|
||||
|
||||
uci_dev->mtu = min_t(size_t, id->driver_data, mhi_dev->mtu);
|
||||
uci_dev->actual_mtu = uci_dev->mtu - sizeof(struct uci_buf);
|
||||
mhi_device_set_devdata(mhi_dev, uci_dev);
|
||||
uci_dev->enabled = true;
|
||||
|
||||
list_add(&uci_dev->node, &mhi_uci_drv.head);
|
||||
mutex_unlock(&mhi_uci_drv.lock);
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
|
||||
MSG_LOG("channel:%s successfully probed\n", mhi_dev->chan_name);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static void mhi_ul_xfer_cb(struct mhi_device *mhi_dev,
|
||||
struct mhi_result *mhi_result)
|
||||
{
|
||||
struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev);
|
||||
struct uci_chan *uci_chan = &uci_dev->ul_chan;
|
||||
|
||||
MSG_VERB("status:%d xfer_len:%zu\n", mhi_result->transaction_status,
|
||||
mhi_result->bytes_xferd);
|
||||
|
||||
kfree(mhi_result->buf_addr);
|
||||
if (!mhi_result->transaction_status)
|
||||
wake_up(&uci_chan->wq);
|
||||
}
|
||||
|
||||
static void mhi_dl_xfer_cb(struct mhi_device *mhi_dev,
|
||||
struct mhi_result *mhi_result)
|
||||
{
|
||||
struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev);
|
||||
struct uci_chan *uci_chan = &uci_dev->dl_chan;
|
||||
unsigned long flags;
|
||||
struct uci_buf *buf;
|
||||
|
||||
MSG_VERB("status:%d receive_len:%zu\n", mhi_result->transaction_status,
|
||||
mhi_result->bytes_xferd);
|
||||
|
||||
if (mhi_result->transaction_status == -ENOTCONN) {
|
||||
kfree(mhi_result->buf_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&uci_chan->lock, flags);
|
||||
buf = mhi_result->buf_addr + uci_dev->actual_mtu;
|
||||
buf->data = mhi_result->buf_addr;
|
||||
buf->len = mhi_result->bytes_xferd;
|
||||
list_add_tail(&buf->node, &uci_chan->pending);
|
||||
spin_unlock_irqrestore(&uci_chan->lock, flags);
|
||||
|
||||
if (mhi_dev->dev.power.wakeup)
|
||||
pm_wakeup_hard_event(&mhi_dev->dev);
|
||||
|
||||
wake_up(&uci_chan->wq);
|
||||
}
|
||||
|
||||
static void mhi_status_cb(struct mhi_device *mhi_dev, enum MHI_CB reason)
|
||||
{
|
||||
struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev);
|
||||
struct uci_chan *uci_chan = &uci_dev->dl_chan;
|
||||
unsigned long flags;
|
||||
|
||||
if (reason == MHI_CB_DTR_SIGNAL) {
|
||||
spin_lock_irqsave(&uci_chan->lock, flags);
|
||||
uci_dev->tiocm = mhi_dev->tiocm;
|
||||
spin_unlock_irqrestore(&uci_chan->lock, flags);
|
||||
wake_up(&uci_chan->wq);
|
||||
}
|
||||
}
|
||||
|
||||
/* .driver_data stores max mtu */
|
||||
static const struct mhi_device_id mhi_uci_match_table[] = {
|
||||
{ .chan = "LOOPBACK", .driver_data = 0x1000 },
|
||||
{ .chan = "SAHARA", .driver_data = 0x8000 },
|
||||
{ .chan = "DIAG", .driver_data = 0x1000 },
|
||||
{ .chan = "EFS", .driver_data = 0x1000 },
|
||||
{ .chan = "QMI0", .driver_data = 0x1000 },
|
||||
{ .chan = "QMI1", .driver_data = 0x1000 },
|
||||
{ .chan = "TF", .driver_data = 0x1000 },
|
||||
{ .chan = "DCI", .driver_data = 0x1000 },
|
||||
{ .chan = "DUN", .driver_data = 0x1000 },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct mhi_driver mhi_uci_driver = {
|
||||
.id_table = mhi_uci_match_table,
|
||||
.remove = mhi_uci_remove,
|
||||
.probe = mhi_uci_probe,
|
||||
.ul_xfer_cb = mhi_ul_xfer_cb,
|
||||
.dl_xfer_cb = mhi_dl_xfer_cb,
|
||||
.status_cb = mhi_status_cb,
|
||||
.driver = {
|
||||
.name = MHI_UCI_DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int mhi_uci_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = register_chrdev(0, MHI_UCI_DRIVER_NAME, &mhidev_fops);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mhi_uci_drv.major = ret;
|
||||
mhi_uci_drv.class = class_create(THIS_MODULE, MHI_UCI_DRIVER_NAME);
|
||||
if (IS_ERR(mhi_uci_drv.class))
|
||||
return -ENODEV;
|
||||
|
||||
mutex_init(&mhi_uci_drv.lock);
|
||||
INIT_LIST_HEAD(&mhi_uci_drv.head);
|
||||
|
||||
ret = mhi_driver_register(&mhi_uci_driver);
|
||||
if (ret)
|
||||
class_destroy(mhi_uci_drv.class);
|
||||
|
||||
return ret;
|
||||
}
|
||||
module_init(mhi_uci_init);
|
||||
|
||||
static void __exit mhi_uci_exit(void)
|
||||
{
|
||||
if (mhi_uci_drv.major) {
|
||||
unregister_chrdev_region(MKDEV(mhi_uci_drv.major, 0),
|
||||
mhi_uci_drv.major);
|
||||
mhi_uci_drv.major = 0;
|
||||
}
|
||||
|
||||
class_destroy(mhi_uci_drv.class);
|
||||
|
||||
mhi_driver_unregister(&mhi_uci_driver);
|
||||
}
|
||||
module_exit(mhi_uci_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("MHI_UCI");
|
||||
MODULE_DESCRIPTION("MHI UCI Driver");
|
@ -523,6 +523,23 @@ source "drivers/s390/char/Kconfig"
|
||||
|
||||
source "drivers/char/xillybus/Kconfig"
|
||||
|
||||
config MSM_ADSPRPC
|
||||
tristate "QTI FastRPC driver"
|
||||
depends on RPMSG && QCOM_SECURE_BUFFER && MSM_SERVICE_LOCATOR && MSM_SERVICE_NOTIFIER && PM_SLEEP && HAS_DMA && CMA && MMU
|
||||
help
|
||||
Provides a communication mechanism that allows clients to
|
||||
make remote method invocations across processor boundary to
|
||||
applications/compute DSP processor.
|
||||
Say M if you want to enable this module.
|
||||
|
||||
config ADSPRPC_DEBUG
|
||||
bool "Debug logs in FastRPC driver"
|
||||
help
|
||||
Enable debug logs in the fastrpc driver. Flag will be
|
||||
disabled by default to maximize RPC performance as debug
|
||||
logging will impact RPC overhead.
|
||||
Say Y here if you want to enable the logs.
|
||||
|
||||
config ADI
|
||||
tristate "SPARC Privileged ADI driver"
|
||||
depends on SPARC64
|
||||
|
@ -51,4 +51,9 @@ js-rtc-y = rtc.o
|
||||
|
||||
obj-$(CONFIG_XILLYBUS) += xillybus/
|
||||
obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
|
||||
frpc-adsprpc-objs += adsprpc.o
|
||||
ifdef CONFIG_COMPAT
|
||||
frpc-adsprpc-objs += adsprpc_compat.o
|
||||
endif
|
||||
obj-$(CONFIG_MSM_ADSPRPC) += frpc-adsprpc.o
|
||||
obj-$(CONFIG_ADI) += adi.o
|
||||
|
5363
drivers/char/adsprpc.c
Normal file
5363
drivers/char/adsprpc.c
Normal file
File diff suppressed because it is too large
Load Diff
804
drivers/char/adsprpc_compat.c
Normal file
804
drivers/char/adsprpc_compat.c
Normal file
@ -0,0 +1,804 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#include <linux/compat.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/msm_ion.h>
|
||||
|
||||
#include "adsprpc_compat.h"
|
||||
#include "adsprpc_shared.h"
|
||||
|
||||
#define COMPAT_FASTRPC_IOCTL_INVOKE \
|
||||
_IOWR('R', 1, struct compat_fastrpc_ioctl_invoke)
|
||||
#define COMPAT_FASTRPC_IOCTL_MMAP \
|
||||
_IOWR('R', 2, struct compat_fastrpc_ioctl_mmap)
|
||||
#define COMPAT_FASTRPC_IOCTL_MUNMAP \
|
||||
_IOWR('R', 3, struct compat_fastrpc_ioctl_munmap)
|
||||
#define COMPAT_FASTRPC_IOCTL_INVOKE_FD \
|
||||
_IOWR('R', 4, struct compat_fastrpc_ioctl_invoke_fd)
|
||||
#define COMPAT_FASTRPC_IOCTL_INIT \
|
||||
_IOWR('R', 6, struct compat_fastrpc_ioctl_init)
|
||||
#define COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS \
|
||||
_IOWR('R', 7, struct compat_fastrpc_ioctl_invoke_attrs)
|
||||
#define COMPAT_FASTRPC_IOCTL_GETPERF \
|
||||
_IOWR('R', 9, struct compat_fastrpc_ioctl_perf)
|
||||
#define COMPAT_FASTRPC_IOCTL_INIT_ATTRS \
|
||||
_IOWR('R', 10, struct compat_fastrpc_ioctl_init_attrs)
|
||||
#define COMPAT_FASTRPC_IOCTL_INVOKE_CRC \
|
||||
_IOWR('R', 11, struct compat_fastrpc_ioctl_invoke_crc)
|
||||
#define COMPAT_FASTRPC_IOCTL_CONTROL \
|
||||
_IOWR('R', 12, struct compat_fastrpc_ioctl_control)
|
||||
#define COMPAT_FASTRPC_IOCTL_MMAP_64 \
|
||||
_IOWR('R', 14, struct compat_fastrpc_ioctl_mmap_64)
|
||||
#define COMPAT_FASTRPC_IOCTL_MUNMAP_64 \
|
||||
_IOWR('R', 15, struct compat_fastrpc_ioctl_munmap_64)
|
||||
#define COMPAT_FASTRPC_IOCTL_GET_DSP_INFO \
|
||||
_IOWR('R', 17, \
|
||||
struct compat_fastrpc_ioctl_remote_dsp_capability)
|
||||
#define COMPAT_FASTRPC_IOCTL_INVOKE2 \
|
||||
_IOWR('R', 18, struct compat_fastrpc_ioctl_invoke2)
|
||||
|
||||
struct compat_remote_buf {
|
||||
compat_uptr_t pv; /* buffer pointer */
|
||||
compat_size_t len; /* length of buffer */
|
||||
};
|
||||
|
||||
union compat_remote_arg {
|
||||
struct compat_remote_buf buf;
|
||||
compat_uint_t h;
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_invoke {
|
||||
compat_uint_t handle; /* remote handle */
|
||||
compat_uint_t sc; /* scalars describing the data */
|
||||
compat_uptr_t pra; /* remote arguments list */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_invoke_fd {
|
||||
struct compat_fastrpc_ioctl_invoke inv;
|
||||
compat_uptr_t fds; /* fd list */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_invoke_attrs {
|
||||
struct compat_fastrpc_ioctl_invoke inv;
|
||||
compat_uptr_t fds; /* fd list */
|
||||
compat_uptr_t attrs; /* attribute list */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_invoke_crc {
|
||||
struct compat_fastrpc_ioctl_invoke inv;
|
||||
compat_uptr_t fds; /* fd list */
|
||||
compat_uptr_t attrs; /* attribute list */
|
||||
compat_uptr_t crc; /* crc list */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_invoke_async {
|
||||
struct compat_fastrpc_ioctl_invoke inv;
|
||||
compat_uptr_t fds; /* fd list */
|
||||
compat_uptr_t attrs; /* attribute list */
|
||||
compat_uptr_t crc; /* crc list */
|
||||
compat_uptr_t job; /* Async job */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_invoke2 {
|
||||
compat_uint_t req; /* type of invocation request */
|
||||
compat_uptr_t invparam; /* invocation request param */
|
||||
compat_uint_t size; /* size of invocation param */
|
||||
compat_int_t err; /* reserved */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_mmap {
|
||||
compat_int_t fd; /* ion fd */
|
||||
compat_uint_t flags; /* flags for dsp to map with */
|
||||
compat_uptr_t vaddrin; /* optional virtual address */
|
||||
compat_size_t size; /* size */
|
||||
compat_uptr_t vaddrout; /* dsps virtual address */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_mmap_64 {
|
||||
compat_int_t fd; /* ion fd */
|
||||
compat_uint_t flags; /* flags for dsp to map with */
|
||||
compat_u64 vaddrin; /* optional virtual address */
|
||||
compat_size_t size; /* size */
|
||||
compat_u64 vaddrout; /* dsps virtual address */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_munmap {
|
||||
compat_uptr_t vaddrout; /* address to unmap */
|
||||
compat_size_t size; /* size */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_munmap_64 {
|
||||
compat_u64 vaddrout; /* address to unmap */
|
||||
compat_size_t size; /* size */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_init {
|
||||
compat_uint_t flags; /* one of FASTRPC_INIT_* macros */
|
||||
compat_uptr_t file; /* pointer to elf file */
|
||||
compat_int_t filelen; /* elf file length */
|
||||
compat_int_t filefd; /* ION fd for the file */
|
||||
compat_uptr_t mem; /* mem for the PD */
|
||||
compat_int_t memlen; /* mem length */
|
||||
compat_int_t memfd; /* ION fd for the mem */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_init_attrs {
|
||||
struct compat_fastrpc_ioctl_init init;
|
||||
compat_int_t attrs; /* attributes to init process */
|
||||
compat_int_t siglen; /* test signature file length */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_perf { /* kernel performance data */
|
||||
compat_uptr_t data;
|
||||
compat_int_t numkeys;
|
||||
compat_uptr_t keys;
|
||||
};
|
||||
|
||||
#define FASTRPC_CONTROL_LATENCY (1)
|
||||
struct compat_fastrpc_ctrl_latency {
|
||||
compat_uint_t enable; /* latency control enable */
|
||||
compat_uint_t latency; /* target latency in us */
|
||||
};
|
||||
|
||||
#define FASTRPC_CONTROL_KALLOC (3)
|
||||
struct compat_fastrpc_ctrl_kalloc {
|
||||
compat_uint_t kalloc_support; /* Remote memory allocation from kernel */
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_control {
|
||||
compat_uint_t req;
|
||||
union {
|
||||
struct compat_fastrpc_ctrl_latency lp;
|
||||
struct compat_fastrpc_ctrl_kalloc kalloc;
|
||||
};
|
||||
};
|
||||
|
||||
struct compat_fastrpc_ioctl_remote_dsp_capability {
|
||||
/*
|
||||
* @param[in]: DSP domain ADSP_DOMAIN_ID,
|
||||
* SDSP_DOMAIN_ID, or CDSP_DOMAIN_ID
|
||||
*/
|
||||
compat_uint_t domain;
|
||||
/*
|
||||
* @param[in]: One of the DSP attributes
|
||||
* from enum remote_dsp_attributes
|
||||
*/
|
||||
compat_uint_t attribute_ID;
|
||||
/*
|
||||
* @param[out]: Result of the DSP
|
||||
* capability query based on attribute_ID
|
||||
*/
|
||||
compat_uint_t capability;
|
||||
};
|
||||
|
||||
static int compat_get_fastrpc_ioctl_invoke(
|
||||
struct compat_fastrpc_ioctl_invoke_async __user *inv32,
|
||||
struct fastrpc_ioctl_invoke_async __user *inv,
|
||||
unsigned int cmd)
|
||||
{
|
||||
compat_uint_t u = 0, sc = 0;
|
||||
compat_size_t s;
|
||||
compat_uptr_t p;
|
||||
union compat_remote_arg *pra32;
|
||||
union remote_arg *pra;
|
||||
int err = 0, len = 0, j = 0;
|
||||
|
||||
err = get_user(sc, &inv32->inv.sc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
len = REMOTE_SCALARS_LENGTH(sc);
|
||||
|
||||
pra = (union remote_arg *)(inv + 1);
|
||||
err = put_user(pra, &inv->inv.pra);
|
||||
err |= put_user(sc, &inv->inv.sc);
|
||||
err |= get_user(u, &inv32->inv.handle);
|
||||
err |= put_user(u, &inv->inv.handle);
|
||||
err |= get_user(p, &inv32->inv.pra);
|
||||
if (err)
|
||||
return err;
|
||||
pra32 = compat_ptr(p);
|
||||
pra = (union remote_arg *)(inv + 1);
|
||||
for (j = 0; j < len; j++) {
|
||||
err |= get_user(p, &pra32[j].buf.pv);
|
||||
err |= put_user(p, (uintptr_t *)&pra[j].buf.pv);
|
||||
err |= get_user(s, &pra32[j].buf.len);
|
||||
err |= put_user(s, &pra[j].buf.len);
|
||||
}
|
||||
|
||||
err |= put_user(NULL, &inv->fds);
|
||||
if (cmd != COMPAT_FASTRPC_IOCTL_INVOKE) {
|
||||
err |= get_user(p, &inv32->fds);
|
||||
err |= put_user(p, (compat_uptr_t *)&inv->fds);
|
||||
}
|
||||
err |= put_user(NULL, &inv->attrs);
|
||||
if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS) ||
|
||||
(cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC) ||
|
||||
(cmd == FASTRPC_INVOKE2_ASYNC)) {
|
||||
err |= get_user(p, &inv32->attrs);
|
||||
err |= put_user(p, (compat_uptr_t *)&inv->attrs);
|
||||
}
|
||||
err |= put_user(NULL, (compat_uptr_t __user **)&inv->crc);
|
||||
if (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC) {
|
||||
err |= get_user(p, &inv32->crc);
|
||||
err |= put_user(p, (compat_uptr_t __user *)&inv->crc);
|
||||
}
|
||||
err |= put_user(NULL, &inv->job);
|
||||
if (cmd == FASTRPC_INVOKE2_ASYNC) {
|
||||
err |= get_user(p, &inv32->job);
|
||||
err |= put_user(p, (compat_uptr_t __user *)&inv->job);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_fastrpc_ioctl_invoke(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct compat_fastrpc_ioctl_invoke_async __user *inv32;
|
||||
struct fastrpc_ioctl_invoke_async __user *inv;
|
||||
compat_uint_t sc = 0;
|
||||
int err = 0, len = 0;
|
||||
|
||||
inv32 = compat_ptr(arg);
|
||||
err = get_user(sc, &inv32->inv.sc);
|
||||
if (err)
|
||||
return err;
|
||||
len = REMOTE_SCALARS_LENGTH(sc);
|
||||
VERIFY(err, NULL != (inv = compat_alloc_user_space(
|
||||
sizeof(*inv) + len * sizeof(union remote_arg))));
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(inv32,
|
||||
inv, cmd));
|
||||
if (err)
|
||||
return err;
|
||||
return filp->f_op->unlocked_ioctl(filp,
|
||||
FASTRPC_IOCTL_INVOKE_CRC, (unsigned long)inv);
|
||||
}
|
||||
|
||||
static int compat_get_fastrpc_ioctl_invoke2(
|
||||
struct compat_fastrpc_ioctl_invoke2 __user *inv32,
|
||||
struct fastrpc_ioctl_invoke2 __user **inva,
|
||||
unsigned int cmd)
|
||||
{
|
||||
int err = 0;
|
||||
compat_uptr_t pparam;
|
||||
compat_uint_t req, size;
|
||||
struct fastrpc_ioctl_invoke2 __user *inv2_user = NULL;
|
||||
struct fastrpc_ioctl_invoke_async __user *asyncinv_user;
|
||||
|
||||
err = get_user(req, &inv32->req);
|
||||
err |= get_user(pparam, &inv32->invparam);
|
||||
err |= get_user(size, &inv32->size);
|
||||
if (err)
|
||||
goto bail;
|
||||
|
||||
switch (req) {
|
||||
case FASTRPC_INVOKE2_ASYNC:
|
||||
{
|
||||
struct compat_fastrpc_ioctl_invoke_async __user *lasync32;
|
||||
compat_uint_t sc = 0;
|
||||
int len = 0;
|
||||
|
||||
VERIFY(err, size == sizeof(*lasync32));
|
||||
if (err) {
|
||||
err = -EBADE;
|
||||
goto bail;
|
||||
}
|
||||
lasync32 = compat_ptr(pparam);
|
||||
err = get_user(sc, &lasync32->inv.sc);
|
||||
if (err)
|
||||
goto bail;
|
||||
len = REMOTE_SCALARS_LENGTH(sc);
|
||||
VERIFY(err, NULL != (inv2_user = compat_alloc_user_space(
|
||||
sizeof(*inv2_user) + sizeof(*asyncinv_user) +
|
||||
len * sizeof(union remote_arg))));
|
||||
if (err) {
|
||||
err = -EFAULT;
|
||||
goto bail;
|
||||
}
|
||||
asyncinv_user =
|
||||
(struct fastrpc_ioctl_invoke_async __user *)(inv2_user + 1);
|
||||
VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(lasync32,
|
||||
asyncinv_user, req));
|
||||
if (err)
|
||||
goto bail;
|
||||
err |= put_user(req, &inv2_user->req);
|
||||
err |= put_user((uintptr_t __user)asyncinv_user,
|
||||
&inv2_user->invparam);
|
||||
err |= put_user(sizeof(*asyncinv_user), &inv2_user->size);
|
||||
if (err)
|
||||
goto bail;
|
||||
break;
|
||||
}
|
||||
case FASTRPC_INVOKE2_ASYNC_RESPONSE:
|
||||
{
|
||||
VERIFY(err,
|
||||
size == sizeof(struct fastrpc_ioctl_async_response));
|
||||
if (err) {
|
||||
err = -EBADE;
|
||||
goto bail;
|
||||
}
|
||||
VERIFY(err, NULL != (inv2_user = compat_alloc_user_space(
|
||||
sizeof(*inv2_user))));
|
||||
if (err) {
|
||||
err = -EFAULT;
|
||||
goto bail;
|
||||
}
|
||||
err |= put_user(req, &inv2_user->req);
|
||||
err |=
|
||||
put_user(pparam, &inv2_user->invparam);
|
||||
err |= put_user(size, &inv2_user->size);
|
||||
if (err)
|
||||
goto bail;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
err = -EBADRQC;
|
||||
break;
|
||||
}
|
||||
*inva = inv2_user;
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_fastrpc_ioctl_invoke2(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct compat_fastrpc_ioctl_invoke2 __user *inv32;
|
||||
struct fastrpc_ioctl_invoke2 __user *inv;
|
||||
int err = 0;
|
||||
|
||||
inv32 = compat_ptr(arg);
|
||||
VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke2(inv32,
|
||||
&inv, cmd));
|
||||
if (err)
|
||||
return err;
|
||||
return filp->f_op->unlocked_ioctl(filp,
|
||||
FASTRPC_IOCTL_INVOKE2, (unsigned long)inv);
|
||||
}
|
||||
|
||||
static int compat_get_fastrpc_ioctl_mmap(
|
||||
struct compat_fastrpc_ioctl_mmap __user *map32,
|
||||
struct fastrpc_ioctl_mmap __user *map)
|
||||
{
|
||||
compat_uint_t u;
|
||||
compat_int_t i;
|
||||
compat_size_t s;
|
||||
compat_uptr_t p;
|
||||
int err;
|
||||
|
||||
err = get_user(i, &map32->fd);
|
||||
err |= put_user(i, &map->fd);
|
||||
err |= get_user(u, &map32->flags);
|
||||
err |= put_user(u, &map->flags);
|
||||
err |= get_user(p, &map32->vaddrin);
|
||||
err |= put_user(p, (uintptr_t *)&map->vaddrin);
|
||||
err |= get_user(s, &map32->size);
|
||||
err |= put_user(s, &map->size);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_get_fastrpc_ioctl_mmap_64(
|
||||
struct compat_fastrpc_ioctl_mmap_64 __user *map32,
|
||||
struct fastrpc_ioctl_mmap __user *map)
|
||||
{
|
||||
compat_uint_t u;
|
||||
compat_int_t i;
|
||||
compat_size_t s;
|
||||
compat_u64 p;
|
||||
int err;
|
||||
|
||||
err = get_user(i, &map32->fd);
|
||||
err |= put_user(i, &map->fd);
|
||||
err |= get_user(u, &map32->flags);
|
||||
err |= put_user(u, &map->flags);
|
||||
err |= get_user(p, &map32->vaddrin);
|
||||
err |= put_user(p, &map->vaddrin);
|
||||
err |= get_user(s, &map32->size);
|
||||
err |= put_user(s, &map->size);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_put_fastrpc_ioctl_mmap(
|
||||
struct compat_fastrpc_ioctl_mmap __user *map32,
|
||||
struct fastrpc_ioctl_mmap __user *map)
|
||||
{
|
||||
compat_uptr_t p;
|
||||
int err;
|
||||
|
||||
err = get_user(p, &map->vaddrout);
|
||||
err |= put_user(p, &map32->vaddrout);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_put_fastrpc_ioctl_mmap_64(
|
||||
struct compat_fastrpc_ioctl_mmap_64 __user *map32,
|
||||
struct fastrpc_ioctl_mmap __user *map)
|
||||
{
|
||||
compat_u64 p;
|
||||
int err;
|
||||
|
||||
err = get_user(p, &map->vaddrout);
|
||||
err |= put_user(p, &map32->vaddrout);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_get_fastrpc_ioctl_munmap(
|
||||
struct compat_fastrpc_ioctl_munmap __user *unmap32,
|
||||
struct fastrpc_ioctl_munmap __user *unmap)
|
||||
{
|
||||
compat_uptr_t p;
|
||||
compat_size_t s;
|
||||
int err;
|
||||
|
||||
err = get_user(p, &unmap32->vaddrout);
|
||||
err |= put_user(p, &unmap->vaddrout);
|
||||
err |= get_user(s, &unmap32->size);
|
||||
err |= put_user(s, &unmap->size);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_get_fastrpc_ioctl_munmap_64(
|
||||
struct compat_fastrpc_ioctl_munmap_64 __user *unmap32,
|
||||
struct fastrpc_ioctl_munmap __user *unmap)
|
||||
{
|
||||
compat_u64 p;
|
||||
compat_size_t s;
|
||||
int err;
|
||||
|
||||
err = get_user(p, &unmap32->vaddrout);
|
||||
err |= put_user(p, &unmap->vaddrout);
|
||||
err |= get_user(s, &unmap32->size);
|
||||
err |= put_user(s, &unmap->size);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_get_fastrpc_ioctl_perf(
|
||||
struct compat_fastrpc_ioctl_perf __user *perf32,
|
||||
struct fastrpc_ioctl_perf __user *perf)
|
||||
{
|
||||
compat_uptr_t p;
|
||||
int err;
|
||||
|
||||
err = get_user(p, &perf32->data);
|
||||
err |= put_user(p, &perf->data);
|
||||
err |= get_user(p, &perf32->keys);
|
||||
err |= put_user(p, &perf->keys);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_get_fastrpc_ioctl_control(
|
||||
struct compat_fastrpc_ioctl_control __user *ctrl32,
|
||||
struct fastrpc_ioctl_control __user *ctrl)
|
||||
{
|
||||
compat_uptr_t p;
|
||||
int err;
|
||||
|
||||
err = get_user(p, &ctrl32->req);
|
||||
err |= put_user(p, &ctrl->req);
|
||||
if (p == FASTRPC_CONTROL_LATENCY) {
|
||||
err |= get_user(p, &ctrl32->lp.enable);
|
||||
err |= put_user(p, &ctrl->lp.enable);
|
||||
err |= get_user(p, &ctrl32->lp.latency);
|
||||
err |= put_user(p, &ctrl->lp.latency);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_get_fastrpc_ioctl_init(
|
||||
struct compat_fastrpc_ioctl_init_attrs __user *init32,
|
||||
struct fastrpc_ioctl_init_attrs __user *init,
|
||||
unsigned int cmd)
|
||||
{
|
||||
compat_uint_t u;
|
||||
compat_uptr_t p;
|
||||
compat_int_t i;
|
||||
int err;
|
||||
|
||||
err = get_user(u, &init32->init.flags);
|
||||
err |= put_user(u, &init->init.flags);
|
||||
err |= get_user(p, &init32->init.file);
|
||||
err |= put_user(p, &init->init.file);
|
||||
err |= get_user(i, &init32->init.filelen);
|
||||
err |= put_user(i, &init->init.filelen);
|
||||
err |= get_user(i, &init32->init.filefd);
|
||||
err |= put_user(i, &init->init.filefd);
|
||||
err |= get_user(p, &init32->init.mem);
|
||||
err |= put_user(p, &init->init.mem);
|
||||
err |= get_user(i, &init32->init.memlen);
|
||||
err |= put_user(i, &init->init.memlen);
|
||||
err |= get_user(i, &init32->init.memfd);
|
||||
err |= put_user(i, &init->init.memfd);
|
||||
|
||||
err |= put_user(0, &init->attrs);
|
||||
if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
|
||||
err |= get_user(i, &init32->attrs);
|
||||
err |= put_user(i, (compat_uptr_t *)&init->attrs);
|
||||
}
|
||||
|
||||
err |= put_user(0, &init->siglen);
|
||||
if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
|
||||
err |= get_user(i, &init32->siglen);
|
||||
err |= put_user(i, (compat_uptr_t *)&init->siglen);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_put_fastrpc_ioctl_get_dsp_info(
|
||||
struct compat_fastrpc_ioctl_remote_dsp_capability __user *info32,
|
||||
struct fastrpc_ioctl_remote_dsp_capability __user *info)
|
||||
{
|
||||
compat_uint_t u;
|
||||
int err = 0;
|
||||
|
||||
err |= get_user(u, &info->capability);
|
||||
err |= put_user(u, &info32->capability);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int fastrpc_setmode(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
return filp->f_op->unlocked_ioctl(filp, cmd,
|
||||
(unsigned long)compat_ptr(arg));
|
||||
}
|
||||
|
||||
static int compat_fastrpc_control(struct file *filp,
|
||||
unsigned long arg)
|
||||
{
|
||||
int err = 0;
|
||||
struct compat_fastrpc_ioctl_control __user *ctrl32;
|
||||
struct fastrpc_ioctl_control __user *ctrl;
|
||||
compat_uptr_t p;
|
||||
|
||||
ctrl32 = compat_ptr(arg);
|
||||
VERIFY(err, NULL != (ctrl = compat_alloc_user_space(
|
||||
sizeof(*ctrl))));
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32,
|
||||
ctrl));
|
||||
if (err)
|
||||
return err;
|
||||
err = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_CONTROL,
|
||||
(unsigned long)ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
err = get_user(p, &ctrl32->req);
|
||||
if (err)
|
||||
return err;
|
||||
if (p == FASTRPC_CONTROL_KALLOC) {
|
||||
err = get_user(p, &ctrl->kalloc.kalloc_support);
|
||||
err |= put_user(p, &ctrl32->kalloc.kalloc_support);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_fastrpc_getperf(struct file *filp,
|
||||
unsigned long arg)
|
||||
{
|
||||
int err = 0;
|
||||
struct compat_fastrpc_ioctl_perf __user *perf32;
|
||||
struct fastrpc_ioctl_perf *perf;
|
||||
compat_uint_t u;
|
||||
long ret;
|
||||
|
||||
perf32 = compat_ptr(arg);
|
||||
VERIFY(err, NULL != (perf = compat_alloc_user_space(
|
||||
sizeof(*perf))));
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
VERIFY(err, 0 == compat_get_fastrpc_ioctl_perf(perf32,
|
||||
perf));
|
||||
if (err)
|
||||
return err;
|
||||
ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETPERF,
|
||||
(unsigned long)perf);
|
||||
if (ret)
|
||||
return ret;
|
||||
err = get_user(u, &perf->numkeys);
|
||||
err |= put_user(u, &perf32->numkeys);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int compat_fastrpc_get_dsp_info(struct file *filp,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct compat_fastrpc_ioctl_remote_dsp_capability __user *info32;
|
||||
struct fastrpc_ioctl_remote_dsp_capability *info;
|
||||
compat_uint_t u;
|
||||
long ret;
|
||||
int err = 0;
|
||||
|
||||
info32 = compat_ptr(arg);
|
||||
VERIFY(err, NULL != (info = compat_alloc_user_space(
|
||||
sizeof(*info))));
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
|
||||
err = get_user(u, &info32->domain);
|
||||
err |= put_user(u, &info->domain);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ret = filp->f_op->unlocked_ioctl(filp,
|
||||
FASTRPC_IOCTL_GET_DSP_INFO,
|
||||
(unsigned long)info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
err = compat_put_fastrpc_ioctl_get_dsp_info(info32, info);
|
||||
return err;
|
||||
}
|
||||
|
||||
long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!filp->f_op || !filp->f_op->unlocked_ioctl)
|
||||
return -ENOTTY;
|
||||
|
||||
switch (cmd) {
|
||||
case COMPAT_FASTRPC_IOCTL_INVOKE:
|
||||
case COMPAT_FASTRPC_IOCTL_INVOKE_FD:
|
||||
case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS:
|
||||
case COMPAT_FASTRPC_IOCTL_INVOKE_CRC:
|
||||
{
|
||||
return compat_fastrpc_ioctl_invoke(filp, cmd, arg);
|
||||
}
|
||||
case COMPAT_FASTRPC_IOCTL_INVOKE2:
|
||||
{
|
||||
return compat_fastrpc_ioctl_invoke2(filp, cmd, arg);
|
||||
}
|
||||
case COMPAT_FASTRPC_IOCTL_MMAP:
|
||||
{
|
||||
struct compat_fastrpc_ioctl_mmap __user *map32;
|
||||
struct fastrpc_ioctl_mmap __user *map;
|
||||
long ret;
|
||||
|
||||
map32 = compat_ptr(arg);
|
||||
VERIFY(err, NULL != (map = compat_alloc_user_space(
|
||||
sizeof(*map))));
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap(map32, map));
|
||||
if (err)
|
||||
return err;
|
||||
ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MMAP,
|
||||
(unsigned long)map);
|
||||
if (ret)
|
||||
return ret;
|
||||
VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap(map32, map));
|
||||
return err;
|
||||
}
|
||||
case COMPAT_FASTRPC_IOCTL_MMAP_64:
|
||||
{
|
||||
struct compat_fastrpc_ioctl_mmap_64 __user *map32;
|
||||
struct fastrpc_ioctl_mmap __user *map;
|
||||
long ret;
|
||||
|
||||
map32 = compat_ptr(arg);
|
||||
VERIFY(err, NULL != (map = compat_alloc_user_space(
|
||||
sizeof(*map))));
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap_64(map32, map));
|
||||
if (err)
|
||||
return err;
|
||||
ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MMAP_64,
|
||||
(unsigned long)map);
|
||||
if (ret)
|
||||
return ret;
|
||||
VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap_64(map32, map));
|
||||
return err;
|
||||
}
|
||||
case COMPAT_FASTRPC_IOCTL_MUNMAP:
|
||||
{
|
||||
struct compat_fastrpc_ioctl_munmap __user *unmap32;
|
||||
struct fastrpc_ioctl_munmap __user *unmap;
|
||||
|
||||
unmap32 = compat_ptr(arg);
|
||||
VERIFY(err, NULL != (unmap = compat_alloc_user_space(
|
||||
sizeof(*unmap))));
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap(unmap32,
|
||||
unmap));
|
||||
if (err)
|
||||
return err;
|
||||
return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MUNMAP,
|
||||
(unsigned long)unmap);
|
||||
}
|
||||
case COMPAT_FASTRPC_IOCTL_MUNMAP_64:
|
||||
{
|
||||
struct compat_fastrpc_ioctl_munmap_64 __user *unmap32;
|
||||
struct fastrpc_ioctl_munmap __user *unmap;
|
||||
|
||||
unmap32 = compat_ptr(arg);
|
||||
VERIFY(err, NULL != (unmap = compat_alloc_user_space(
|
||||
sizeof(*unmap))));
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap_64(unmap32,
|
||||
unmap));
|
||||
if (err)
|
||||
return err;
|
||||
return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MUNMAP_64,
|
||||
(unsigned long)unmap);
|
||||
}
|
||||
case COMPAT_FASTRPC_IOCTL_INIT:
|
||||
/* fall through */
|
||||
case COMPAT_FASTRPC_IOCTL_INIT_ATTRS:
|
||||
{
|
||||
struct compat_fastrpc_ioctl_init_attrs __user *init32;
|
||||
struct fastrpc_ioctl_init_attrs __user *init;
|
||||
|
||||
init32 = compat_ptr(arg);
|
||||
VERIFY(err, NULL != (init = compat_alloc_user_space(
|
||||
sizeof(*init))));
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
VERIFY(err, 0 == compat_get_fastrpc_ioctl_init(init32,
|
||||
init, cmd));
|
||||
if (err)
|
||||
return err;
|
||||
return filp->f_op->unlocked_ioctl(filp,
|
||||
FASTRPC_IOCTL_INIT_ATTRS, (unsigned long)init);
|
||||
}
|
||||
case FASTRPC_IOCTL_GETINFO:
|
||||
{
|
||||
compat_uptr_t __user *info32;
|
||||
uint32_t __user *info;
|
||||
compat_uint_t u;
|
||||
long ret;
|
||||
|
||||
info32 = compat_ptr(arg);
|
||||
VERIFY(err, NULL != (info = compat_alloc_user_space(
|
||||
sizeof(*info))));
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
err = get_user(u, info32);
|
||||
err |= put_user(u, info);
|
||||
if (err)
|
||||
return err;
|
||||
ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETINFO,
|
||||
(unsigned long)info);
|
||||
if (ret)
|
||||
return ret;
|
||||
err = get_user(u, info);
|
||||
err |= put_user(u, info32);
|
||||
return err;
|
||||
}
|
||||
case FASTRPC_IOCTL_SETMODE:
|
||||
return fastrpc_setmode(filp, cmd, arg);
|
||||
case COMPAT_FASTRPC_IOCTL_CONTROL:
|
||||
{
|
||||
return compat_fastrpc_control(filp, arg);
|
||||
}
|
||||
case COMPAT_FASTRPC_IOCTL_GETPERF:
|
||||
{
|
||||
return compat_fastrpc_getperf(filp, arg);
|
||||
}
|
||||
case COMPAT_FASTRPC_IOCTL_GET_DSP_INFO:
|
||||
{
|
||||
return compat_fastrpc_get_dsp_info(filp, arg);
|
||||
}
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
17
drivers/char/adsprpc_compat.h
Normal file
17
drivers/char/adsprpc_compat.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2014, 2018-2019 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#ifndef ADSPRPC_COMPAT_H
|
||||
#define ADSPRPC_COMPAT_H
|
||||
|
||||
#if IS_ENABLED(CONFIG_COMPAT)
|
||||
|
||||
long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
#else
|
||||
|
||||
#define compat_fastrpc_device_ioctl NULL
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* ADSPRPC_COMPAT_H */
|
381
drivers/char/adsprpc_shared.h
Normal file
381
drivers/char/adsprpc_shared.h
Normal file
@ -0,0 +1,381 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#ifndef ADSPRPC_SHARED_H
|
||||
#define ADSPRPC_SHARED_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define FASTRPC_IOCTL_INVOKE _IOWR('R', 1, struct fastrpc_ioctl_invoke)
|
||||
#define FASTRPC_IOCTL_MMAP _IOWR('R', 2, struct fastrpc_ioctl_mmap)
|
||||
#define FASTRPC_IOCTL_MUNMAP _IOWR('R', 3, struct fastrpc_ioctl_munmap)
|
||||
#define FASTRPC_IOCTL_MMAP_64 _IOWR('R', 14, struct fastrpc_ioctl_mmap_64)
|
||||
#define FASTRPC_IOCTL_MUNMAP_64 _IOWR('R', 15, struct fastrpc_ioctl_munmap_64)
|
||||
#define FASTRPC_IOCTL_INVOKE_FD _IOWR('R', 4, struct fastrpc_ioctl_invoke_fd)
|
||||
#define FASTRPC_IOCTL_SETMODE _IOWR('R', 5, uint32_t)
|
||||
#define FASTRPC_IOCTL_INIT _IOWR('R', 6, struct fastrpc_ioctl_init)
|
||||
#define FASTRPC_IOCTL_INVOKE_ATTRS \
|
||||
_IOWR('R', 7, struct fastrpc_ioctl_invoke_attrs)
|
||||
#define FASTRPC_IOCTL_GETINFO _IOWR('R', 8, uint32_t)
|
||||
#define FASTRPC_IOCTL_GETPERF _IOWR('R', 9, struct fastrpc_ioctl_perf)
|
||||
#define FASTRPC_IOCTL_INIT_ATTRS _IOWR('R', 10, struct fastrpc_ioctl_init_attrs)
|
||||
#define FASTRPC_IOCTL_INVOKE_CRC _IOWR('R', 11, struct fastrpc_ioctl_invoke_crc)
|
||||
#define FASTRPC_IOCTL_CONTROL _IOWR('R', 12, struct fastrpc_ioctl_control)
|
||||
#define FASTRPC_IOCTL_MUNMAP_FD _IOWR('R', 13, struct fastrpc_ioctl_munmap_fd)
|
||||
#define FASTRPC_IOCTL_GET_DSP_INFO \
|
||||
_IOWR('R', 17, struct fastrpc_ioctl_remote_dsp_capability)
|
||||
#define FASTRPC_IOCTL_INVOKE2 _IOWR('R', 18, struct fastrpc_ioctl_invoke2)
|
||||
|
||||
|
||||
#define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp"
|
||||
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
|
||||
#define DEVICE_NAME "adsprpc-smd"
|
||||
#define DEVICE_NAME_SECURE "adsprpc-smd-secure"
|
||||
|
||||
/* Set for buffers that have no virtual mapping in userspace */
|
||||
#define FASTRPC_ATTR_NOVA 0x1
|
||||
|
||||
/* Set for buffers that are NOT dma coherent */
|
||||
#define FASTRPC_ATTR_NON_COHERENT 0x2
|
||||
|
||||
/* Set for buffers that are dma coherent */
|
||||
#define FASTRPC_ATTR_COHERENT 0x4
|
||||
|
||||
/* Fastrpc attribute for keeping the map persistent */
|
||||
#define FASTRPC_ATTR_KEEP_MAP 0x8
|
||||
|
||||
/* Fastrpc attribute for no mapping of fd */
|
||||
#define FASTRPC_ATTR_NOMAP (16)
|
||||
|
||||
/*
|
||||
* Fastrpc attribute to skip flush by fastrpc
|
||||
*/
|
||||
#define FASTRPC_ATTR_FORCE_NOFLUSH (32)
|
||||
|
||||
/*
|
||||
* Fastrpc attribute to skip invalidate by fastrpc
|
||||
*/
|
||||
#define FASTRPC_ATTR_FORCE_NOINVALIDATE (64)
|
||||
|
||||
/* Driver should operate in parallel with the co-processor */
|
||||
#define FASTRPC_MODE_PARALLEL 0
|
||||
|
||||
/* Driver should operate in serial mode with the co-processor */
|
||||
#define FASTRPC_MODE_SERIAL 1
|
||||
|
||||
/* Driver should operate in profile mode with the co-processor */
|
||||
#define FASTRPC_MODE_PROFILE 2
|
||||
|
||||
/* Set FastRPC session ID to 1 */
|
||||
#define FASTRPC_MODE_SESSION 4
|
||||
|
||||
/* INIT a new process or attach to guestos */
|
||||
#define FASTRPC_INIT_ATTACH 0
|
||||
#define FASTRPC_INIT_CREATE 1
|
||||
#define FASTRPC_INIT_CREATE_STATIC 2
|
||||
#define FASTRPC_INIT_ATTACH_SENSORS 3
|
||||
|
||||
/* Retrives number of input buffers from the scalars parameter */
|
||||
#define REMOTE_SCALARS_INBUFS(sc) (((sc) >> 16) & 0x0ff)
|
||||
|
||||
/* Retrives number of output buffers from the scalars parameter */
|
||||
#define REMOTE_SCALARS_OUTBUFS(sc) (((sc) >> 8) & 0x0ff)
|
||||
|
||||
/* Retrives number of input handles from the scalars parameter */
|
||||
#define REMOTE_SCALARS_INHANDLES(sc) (((sc) >> 4) & 0x0f)
|
||||
|
||||
/* Retrives number of output handles from the scalars parameter */
|
||||
#define REMOTE_SCALARS_OUTHANDLES(sc) ((sc) & 0x0f)
|
||||
|
||||
#define REMOTE_SCALARS_LENGTH(sc) (REMOTE_SCALARS_INBUFS(sc) +\
|
||||
REMOTE_SCALARS_OUTBUFS(sc) +\
|
||||
REMOTE_SCALARS_INHANDLES(sc) +\
|
||||
REMOTE_SCALARS_OUTHANDLES(sc))
|
||||
|
||||
#define REMOTE_SCALARS_MAKEX(attr, method, in, out, oin, oout) \
|
||||
((((uint32_t) (attr) & 0x7) << 29) | \
|
||||
(((uint32_t) (method) & 0x1f) << 24) | \
|
||||
(((uint32_t) (in) & 0xff) << 16) | \
|
||||
(((uint32_t) (out) & 0xff) << 8) | \
|
||||
(((uint32_t) (oin) & 0x0f) << 4) | \
|
||||
((uint32_t) (oout) & 0x0f))
|
||||
|
||||
#define REMOTE_SCALARS_MAKE(method, in, out) \
|
||||
REMOTE_SCALARS_MAKEX(0, method, in, out, 0, 0)
|
||||
|
||||
|
||||
#ifndef VERIFY_PRINT_ERROR
|
||||
#define VERIFY_EPRINTF(format, args) (void)0
|
||||
#endif
|
||||
|
||||
#ifndef VERIFY_PRINT_INFO
|
||||
#define VERIFY_IPRINTF(args) (void)0
|
||||
#endif
|
||||
|
||||
#ifndef VERIFY
|
||||
#define __STR__(x) #x ":"
|
||||
#define __TOSTR__(x) __STR__(x)
|
||||
#define __FILE_LINE__ __FILE__ ":" __TOSTR__(__LINE__)
|
||||
|
||||
#define VERIFY(err, val) \
|
||||
do {\
|
||||
VERIFY_IPRINTF(__FILE_LINE__"info: calling: " #val "\n");\
|
||||
if ((val) == 0) {\
|
||||
(err) = (err) == 0 ? -1 : (err);\
|
||||
VERIFY_EPRINTF(__FILE_LINE__"error: %d: " #val "\n", (err));\
|
||||
} else {\
|
||||
VERIFY_IPRINTF(__FILE_LINE__"info: passed: " #val "\n");\
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define remote_arg64_t union remote_arg64
|
||||
|
||||
struct remote_buf64 {
|
||||
uint64_t pv;
|
||||
uint64_t len;
|
||||
};
|
||||
|
||||
struct remote_dma_handle64 {
|
||||
int fd;
|
||||
uint32_t offset;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
union remote_arg64 {
|
||||
struct remote_buf64 buf;
|
||||
struct remote_dma_handle64 dma;
|
||||
uint32_t h;
|
||||
};
|
||||
|
||||
#define remote_arg_t union remote_arg
|
||||
|
||||
struct remote_buf {
|
||||
void *pv; /* buffer pointer */
|
||||
size_t len; /* length of buffer */
|
||||
};
|
||||
|
||||
struct remote_dma_handle {
|
||||
int fd;
|
||||
uint32_t offset;
|
||||
};
|
||||
|
||||
union remote_arg {
|
||||
struct remote_buf buf; /* buffer info */
|
||||
struct remote_dma_handle dma;
|
||||
uint32_t h; /* remote handle */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_invoke {
|
||||
uint32_t handle; /* remote handle */
|
||||
uint32_t sc; /* scalars describing the data */
|
||||
remote_arg_t *pra; /* remote arguments list */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_invoke_fd {
|
||||
struct fastrpc_ioctl_invoke inv;
|
||||
int *fds; /* fd list */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_invoke_attrs {
|
||||
struct fastrpc_ioctl_invoke inv;
|
||||
int *fds; /* fd list */
|
||||
unsigned int *attrs; /* attribute list */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_invoke_crc {
|
||||
struct fastrpc_ioctl_invoke inv;
|
||||
int *fds; /* fd list */
|
||||
unsigned int *attrs; /* attribute list */
|
||||
unsigned int *crc;
|
||||
};
|
||||
|
||||
struct fastrpc_async_job {
|
||||
uint32_t isasyncjob; /* flag to distinguish async job */
|
||||
uint64_t jobid; /* job id generated by user */
|
||||
uint32_t reserved; /* reserved */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_invoke_async {
|
||||
struct fastrpc_ioctl_invoke inv;
|
||||
int *fds; /* fd list */
|
||||
unsigned int *attrs; /* attribute list */
|
||||
unsigned int *crc;
|
||||
struct fastrpc_async_job *job; /* async job*/
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_async_response {
|
||||
uint64_t jobid;/* job id generated by user */
|
||||
int result; /* result from DSP */
|
||||
};
|
||||
|
||||
enum fastrpc_invoke2_type {
|
||||
FASTRPC_INVOKE2_ASYNC = 1,
|
||||
FASTRPC_INVOKE2_ASYNC_RESPONSE = 2,
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_invoke2 {
|
||||
uint32_t req; /* type of invocation request */
|
||||
uintptr_t invparam; /* invocation request param */
|
||||
uint32_t size; /* size of invocation param */
|
||||
int err; /* reserved */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_init {
|
||||
uint32_t flags; /* one of FASTRPC_INIT_* macros */
|
||||
uintptr_t file; /* pointer to elf file */
|
||||
uint32_t filelen; /* elf file length */
|
||||
int32_t filefd; /* ION fd for the file */
|
||||
uintptr_t mem; /* mem for the PD */
|
||||
uint32_t memlen; /* mem length */
|
||||
int32_t memfd; /* ION fd for the mem */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_init_attrs {
|
||||
struct fastrpc_ioctl_init init;
|
||||
int attrs;
|
||||
unsigned int siglen;
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_munmap {
|
||||
uintptr_t vaddrout; /* address to unmap */
|
||||
size_t size; /* size */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_munmap_64 {
|
||||
uint64_t vaddrout; /* address to unmap */
|
||||
size_t size; /* size */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_mmap {
|
||||
int fd; /* ion fd */
|
||||
uint32_t flags; /* flags for dsp to map with */
|
||||
uintptr_t vaddrin; /* optional virtual address */
|
||||
size_t size; /* size */
|
||||
uintptr_t vaddrout; /* dsps virtual address */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_mmap_64 {
|
||||
int fd; /* ion fd */
|
||||
uint32_t flags; /* flags for dsp to map with */
|
||||
uint64_t vaddrin; /* optional virtual address */
|
||||
size_t size; /* size */
|
||||
uint64_t vaddrout; /* dsps virtual address */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_munmap_fd {
|
||||
int fd; /* fd */
|
||||
uint32_t flags; /* control flags */
|
||||
uintptr_t va; /* va */
|
||||
ssize_t len; /* length */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_perf { /* kernel performance data */
|
||||
uintptr_t data;
|
||||
uint32_t numkeys;
|
||||
uintptr_t keys;
|
||||
};
|
||||
|
||||
enum fastrpc_control_type {
|
||||
FASTRPC_CONTROL_LATENCY = 1,
|
||||
FASTRPC_CONTROL_SMMU = 2,
|
||||
FASTRPC_CONTROL_KALLOC = 3,
|
||||
FASTRPC_CONTROL_WAKELOCK = 4,
|
||||
};
|
||||
|
||||
struct fastrpc_ctrl_latency {
|
||||
uint32_t enable; /* latency control enable */
|
||||
uint32_t latency; /* latency request in us */
|
||||
};
|
||||
|
||||
struct fastrpc_ctrl_kalloc {
|
||||
uint32_t kalloc_support; /* Remote memory allocation from kernel */
|
||||
};
|
||||
|
||||
struct fastrpc_ctrl_wakelock {
|
||||
uint32_t enable; /* wakelock control enable */
|
||||
};
|
||||
|
||||
struct fastrpc_ioctl_control {
|
||||
uint32_t req;
|
||||
union {
|
||||
struct fastrpc_ctrl_latency lp;
|
||||
struct fastrpc_ctrl_kalloc kalloc;
|
||||
struct fastrpc_ctrl_wakelock wp;
|
||||
};
|
||||
};
|
||||
|
||||
#define FASTRPC_MAX_DSP_ATTRIBUTES (9)
|
||||
#define ASYNC_FASTRPC_CAP (8)
|
||||
|
||||
struct fastrpc_ioctl_remote_dsp_capability {
|
||||
uint32_t domain;
|
||||
uint32_t attribute_ID;
|
||||
uint32_t capability;
|
||||
};
|
||||
|
||||
struct smq_null_invoke {
|
||||
uint64_t ctx; /* invoke caller context */
|
||||
uint32_t handle; /* handle to invoke */
|
||||
uint32_t sc; /* scalars structure describing the data */
|
||||
};
|
||||
|
||||
struct smq_phy_page {
|
||||
uint64_t addr; /* physical address */
|
||||
uint64_t size; /* size of contiguous region */
|
||||
};
|
||||
|
||||
struct smq_invoke_buf {
|
||||
int num; /* number of contiguous regions */
|
||||
int pgidx; /* index to start of contiguous region */
|
||||
};
|
||||
|
||||
struct smq_invoke {
|
||||
struct smq_null_invoke header;
|
||||
struct smq_phy_page page; /* remote arg and list of pages address */
|
||||
};
|
||||
|
||||
struct smq_msg {
|
||||
uint32_t pid; /* process group id */
|
||||
uint32_t tid; /* thread id */
|
||||
struct smq_invoke invoke;
|
||||
};
|
||||
|
||||
struct smq_invoke_rsp {
|
||||
uint64_t ctx; /* invoke caller context */
|
||||
int retval; /* invoke return value */
|
||||
};
|
||||
|
||||
enum fastrpc_response_flags {
|
||||
NORMAL_RESPONSE = 0,
|
||||
EARLY_RESPONSE = 1,
|
||||
USER_EARLY_SIGNAL = 2,
|
||||
COMPLETE_SIGNAL = 3
|
||||
};
|
||||
|
||||
struct smq_invoke_rspv2 {
|
||||
uint64_t ctx; /* invoke caller context */
|
||||
int retval; /* invoke return value */
|
||||
uint32_t flags; /* early response flags */
|
||||
uint32_t early_wake_time; /* user predicted early wakeup time in us */
|
||||
uint32_t version; /* Version number for validation */
|
||||
};
|
||||
|
||||
static inline struct smq_invoke_buf *smq_invoke_buf_start(remote_arg64_t *pra,
|
||||
uint32_t sc)
|
||||
{
|
||||
unsigned int len = REMOTE_SCALARS_LENGTH(sc);
|
||||
|
||||
return (struct smq_invoke_buf *)(&pra[len]);
|
||||
}
|
||||
|
||||
static inline struct smq_phy_page *smq_phy_page_start(uint32_t sc,
|
||||
struct smq_invoke_buf *buf)
|
||||
{
|
||||
unsigned int nTotal = REMOTE_SCALARS_LENGTH(sc);
|
||||
|
||||
return (struct smq_phy_page *)(&buf[nTotal]);
|
||||
}
|
||||
|
||||
#endif
|
@ -321,6 +321,20 @@ config HW_RANDOM_HISI_V2
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config HW_RANDOM_MSM_LEGACY
|
||||
tristate "QTI MSM Random Number Generator support (LEGACY)"
|
||||
depends on HW_RANDOM && ARCH_QCOM
|
||||
select CRYPTO_AES
|
||||
select CRYPTO_ECB
|
||||
help
|
||||
This driver provides kernel-side support for the Random Number
|
||||
Generator hardware found on QTI MSM SoCs.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called msm_rng.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config HW_RANDOM_ST
|
||||
tristate "ST Microelectronics HW Random Number Generator support"
|
||||
depends on HW_RANDOM && ARCH_STI
|
||||
|
@ -30,6 +30,7 @@ obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_HISI_V2) += hisi-trng-v2.o
|
||||
obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
|
||||
obj-$(CONFIG_HW_RANDOM_MSM_LEGACY) += msm_rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o
|
||||
|
484
drivers/char/hw_random/msm_rng.c
Normal file
484
drivers/char/hw_random/msm_rng.c
Normal file
@ -0,0 +1,484 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2011-2013, 2015, 2017-2020 The Linux Foundation. All rights
|
||||
* reserved.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/hw_random.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/qrng.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <crypto/internal/rng.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/sched/signal.h>
|
||||
|
||||
#define DRIVER_NAME "msm_rng"
|
||||
|
||||
/* Device specific register offsets */
|
||||
#define PRNG_DATA_OUT_OFFSET 0x0000
|
||||
#define PRNG_STATUS_OFFSET 0x0004
|
||||
#define PRNG_LFSR_CFG_OFFSET 0x0100
|
||||
#define PRNG_CONFIG_OFFSET 0x0104
|
||||
|
||||
/* Device specific register masks and config values */
|
||||
#define PRNG_LFSR_CFG_MASK 0xFFFF0000
|
||||
#define PRNG_LFSR_CFG_CLOCKS 0x0000DDDD
|
||||
#define PRNG_CONFIG_MASK 0xFFFFFFFD
|
||||
#define PRNG_HW_ENABLE 0x00000002
|
||||
|
||||
#define MAX_HW_FIFO_DEPTH 16 /* FIFO is 16 words deep */
|
||||
#define MAX_HW_FIFO_SIZE (MAX_HW_FIFO_DEPTH * 4) /* FIFO is 32 bits wide */
|
||||
|
||||
#define RETRY_MAX_CNT 5 /* max retry times to read register */
|
||||
#define RETRY_DELAY_INTERVAL 440 /* retry delay interval in us */
|
||||
|
||||
struct msm_rng_device {
|
||||
struct platform_device *pdev;
|
||||
void __iomem *base;
|
||||
struct clk *prng_clk;
|
||||
struct mutex rng_lock;
|
||||
struct icc_path *icc_path;
|
||||
};
|
||||
|
||||
static struct msm_rng_device msm_rng_device_info;
|
||||
static struct msm_rng_device *msm_rng_dev_cached;
|
||||
static struct mutex cached_rng_lock;
|
||||
static long msm_rng_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
long ret = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case QRNG_IOCTL_RESET_BUS_BANDWIDTH:
|
||||
pr_debug("calling msm_rng_bus_scale(LOW)\n");
|
||||
ret = icc_set_bw(msm_rng_device_info.icc_path, 0, 0);
|
||||
if (ret)
|
||||
pr_err("failed qrng_reset_bus_bw, ret = %ld\n", ret);
|
||||
break;
|
||||
default:
|
||||
pr_err("Unsupported IOCTL call\n");
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* This function calls hardware random bit generator directory and retuns it
|
||||
* back to caller
|
||||
*
|
||||
*/
|
||||
static int msm_rng_direct_read(struct msm_rng_device *msm_rng_dev,
|
||||
void *data, size_t max)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
void __iomem *base;
|
||||
size_t currsize = 0;
|
||||
u32 val = 0;
|
||||
u32 *retdata = data;
|
||||
int ret;
|
||||
int failed = 0;
|
||||
|
||||
pdev = msm_rng_dev->pdev;
|
||||
base = msm_rng_dev->base;
|
||||
|
||||
/* no room for word data */
|
||||
if (max < 4)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&msm_rng_dev->rng_lock);
|
||||
|
||||
if (msm_rng_dev->icc_path) {
|
||||
ret = icc_set_bw(msm_rng_dev->icc_path, 0, 300000);
|
||||
if (ret) {
|
||||
pr_err("bus_scale_client_update_req failed\n");
|
||||
goto bus_err;
|
||||
}
|
||||
}
|
||||
/* enable PRNG clock */
|
||||
if (msm_rng_dev->prng_clk) {
|
||||
ret = clk_prepare_enable(msm_rng_dev->prng_clk);
|
||||
if (ret) {
|
||||
pr_err("failed to enable prng clock\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* read random data from h/w */
|
||||
do {
|
||||
/* check status bit if data is available */
|
||||
if (!(readl_relaxed(base + PRNG_STATUS_OFFSET)
|
||||
& 0x00000001)) {
|
||||
if (failed++ == RETRY_MAX_CNT) {
|
||||
if (currsize == 0)
|
||||
pr_err("Data not available\n");
|
||||
break;
|
||||
}
|
||||
udelay(RETRY_DELAY_INTERVAL);
|
||||
} else {
|
||||
|
||||
/* read FIFO */
|
||||
val = readl_relaxed(base + PRNG_DATA_OUT_OFFSET);
|
||||
|
||||
/* write data back to callers pointer */
|
||||
*(retdata++) = val;
|
||||
currsize += 4;
|
||||
/* make sure we stay on 32bit boundary */
|
||||
if ((max - currsize) < 4)
|
||||
break;
|
||||
}
|
||||
|
||||
} while (currsize < max);
|
||||
|
||||
/* vote to turn off clock */
|
||||
if (msm_rng_dev->prng_clk)
|
||||
clk_disable_unprepare(msm_rng_dev->prng_clk);
|
||||
err:
|
||||
if (msm_rng_dev->icc_path) {
|
||||
ret = icc_set_bw(msm_rng_dev->icc_path, 0, 0);
|
||||
if (ret)
|
||||
pr_err("bus_scale_client_update_req failed\n");
|
||||
}
|
||||
bus_err:
|
||||
mutex_unlock(&msm_rng_dev->rng_lock);
|
||||
|
||||
val = 0L;
|
||||
return currsize;
|
||||
}
|
||||
static int msm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
|
||||
{
|
||||
struct msm_rng_device *msm_rng_dev;
|
||||
int rv = 0;
|
||||
|
||||
msm_rng_dev = (struct msm_rng_device *)rng->priv;
|
||||
rv = msm_rng_direct_read(msm_rng_dev, data, max);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static struct hwrng msm_rng = {
|
||||
.name = DRIVER_NAME,
|
||||
.read = msm_rng_read,
|
||||
.quality = 1024,
|
||||
};
|
||||
|
||||
static int msm_rng_enable_hw(struct msm_rng_device *msm_rng_dev)
|
||||
{
|
||||
unsigned long val = 0;
|
||||
unsigned long reg_val = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (msm_rng_dev->icc_path) {
|
||||
ret = icc_set_bw(msm_rng_dev->icc_path, 0, 30000);
|
||||
if (ret)
|
||||
pr_err("bus_scale_client_update_req failed\n");
|
||||
}
|
||||
/* Enable the PRNG CLK */
|
||||
if (msm_rng_dev->prng_clk) {
|
||||
ret = clk_prepare_enable(msm_rng_dev->prng_clk);
|
||||
if (ret) {
|
||||
dev_err(&(msm_rng_dev->pdev)->dev,
|
||||
"failed to enable clock in probe\n");
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable PRNG h/w only if it is NOT ON */
|
||||
val = readl_relaxed(msm_rng_dev->base + PRNG_CONFIG_OFFSET) &
|
||||
PRNG_HW_ENABLE;
|
||||
/* PRNG H/W is not ON */
|
||||
if (val != PRNG_HW_ENABLE) {
|
||||
val = readl_relaxed(msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET);
|
||||
val &= PRNG_LFSR_CFG_MASK;
|
||||
val |= PRNG_LFSR_CFG_CLOCKS;
|
||||
writel_relaxed(val, msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET);
|
||||
|
||||
/* The PRNG CONFIG register should be first written */
|
||||
mb();
|
||||
|
||||
reg_val = readl_relaxed(msm_rng_dev->base + PRNG_CONFIG_OFFSET)
|
||||
& PRNG_CONFIG_MASK;
|
||||
reg_val |= PRNG_HW_ENABLE;
|
||||
writel_relaxed(reg_val, msm_rng_dev->base + PRNG_CONFIG_OFFSET);
|
||||
|
||||
/* The PRNG clk should be disabled only after we enable the
|
||||
* PRNG h/w by writing to the PRNG CONFIG register.
|
||||
*/
|
||||
mb();
|
||||
}
|
||||
if (msm_rng_dev->prng_clk)
|
||||
clk_disable_unprepare(msm_rng_dev->prng_clk);
|
||||
|
||||
if (msm_rng_dev->icc_path) {
|
||||
ret = icc_set_bw(msm_rng_dev->icc_path, 0, 0);
|
||||
if (ret)
|
||||
pr_err("bus_scale_client_update_req failed\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations msm_rng_fops = {
|
||||
.unlocked_ioctl = msm_rng_ioctl,
|
||||
};
|
||||
static struct class *msm_rng_class;
|
||||
static struct cdev msm_rng_cdev;
|
||||
|
||||
static int msm_rng_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct msm_rng_device *msm_rng_dev = NULL;
|
||||
void __iomem *base = NULL;
|
||||
bool configure_qrng = true;
|
||||
int error = 0;
|
||||
struct device *dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "invalid address\n");
|
||||
error = -EFAULT;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
msm_rng_dev = kzalloc(sizeof(struct msm_rng_device), GFP_KERNEL);
|
||||
if (!msm_rng_dev) {
|
||||
error = -ENOMEM;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
base = ioremap(res->start, resource_size(res));
|
||||
if (!base) {
|
||||
dev_err(&pdev->dev, "ioremap failed\n");
|
||||
error = -ENOMEM;
|
||||
goto err_iomap;
|
||||
}
|
||||
msm_rng_dev->base = base;
|
||||
|
||||
/* create a handle for clock control */
|
||||
if (pdev->dev.of_node) {
|
||||
if (of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,no-clock-support"))
|
||||
msm_rng_dev->prng_clk = NULL;
|
||||
else
|
||||
msm_rng_dev->prng_clk = clk_get(&pdev->dev,
|
||||
"km_clk_src");
|
||||
}
|
||||
|
||||
if (IS_ERR(msm_rng_dev->prng_clk)) {
|
||||
dev_err(&pdev->dev, "failed to register clock source\n");
|
||||
error = -ENODEV;
|
||||
goto err_clk_get;
|
||||
}
|
||||
|
||||
/* save away pdev and register driver data */
|
||||
msm_rng_dev->pdev = pdev;
|
||||
platform_set_drvdata(pdev, msm_rng_dev);
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
msm_rng_dev->icc_path = of_icc_get(&pdev->dev, "data_path");
|
||||
msm_rng_device_info.icc_path = msm_rng_dev->icc_path;
|
||||
if (IS_ERR(msm_rng_dev->icc_path)) {
|
||||
error = PTR_ERR(msm_rng_dev->icc_path);
|
||||
dev_err(&pdev->dev, "get icc path err %d\n", error);
|
||||
goto err_icc_get;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable rng h/w for the targets which can access the entire
|
||||
* address space of PRNG.
|
||||
*/
|
||||
if ((pdev->dev.of_node) && (of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,no-qrng-config")))
|
||||
configure_qrng = false;
|
||||
if (configure_qrng) {
|
||||
error = msm_rng_enable_hw(msm_rng_dev);
|
||||
if (error)
|
||||
goto err_icc_get;
|
||||
}
|
||||
|
||||
mutex_init(&msm_rng_dev->rng_lock);
|
||||
mutex_init(&cached_rng_lock);
|
||||
|
||||
/* register with hwrng framework */
|
||||
msm_rng.priv = (unsigned long) msm_rng_dev;
|
||||
error = hwrng_register(&msm_rng);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register hwrng\n");
|
||||
goto err_reg_hwrng;
|
||||
}
|
||||
error = register_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME, &msm_rng_fops);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register chrdev\n");
|
||||
goto err_reg_chrdev;
|
||||
}
|
||||
|
||||
msm_rng_class = class_create(THIS_MODULE, "msm-rng");
|
||||
if (IS_ERR(msm_rng_class)) {
|
||||
pr_err("class_create failed\n");
|
||||
error = PTR_ERR(msm_rng_class);
|
||||
goto err_create_cls;
|
||||
}
|
||||
|
||||
dev = device_create(msm_rng_class, NULL, MKDEV(QRNG_IOC_MAGIC, 0),
|
||||
NULL, "msm-rng");
|
||||
if (IS_ERR(dev)) {
|
||||
pr_err("Device create failed\n");
|
||||
error = PTR_ERR(dev);
|
||||
goto err_create_dev;
|
||||
}
|
||||
cdev_init(&msm_rng_cdev, &msm_rng_fops);
|
||||
msm_rng_dev_cached = msm_rng_dev;
|
||||
return error;
|
||||
|
||||
err_create_dev:
|
||||
class_destroy(msm_rng_class);
|
||||
err_create_cls:
|
||||
unregister_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME);
|
||||
err_reg_chrdev:
|
||||
hwrng_unregister(&msm_rng);
|
||||
err_reg_hwrng:
|
||||
if (msm_rng_dev->icc_path)
|
||||
icc_put(msm_rng_dev->icc_path);
|
||||
err_icc_get:
|
||||
if (msm_rng_dev->prng_clk)
|
||||
clk_put(msm_rng_dev->prng_clk);
|
||||
err_clk_get:
|
||||
iounmap(msm_rng_dev->base);
|
||||
err_iomap:
|
||||
kzfree(msm_rng_dev);
|
||||
err_exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int msm_rng_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct msm_rng_device *msm_rng_dev = platform_get_drvdata(pdev);
|
||||
|
||||
unregister_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME);
|
||||
hwrng_unregister(&msm_rng);
|
||||
if (msm_rng_dev->prng_clk)
|
||||
clk_put(msm_rng_dev->prng_clk);
|
||||
iounmap(msm_rng_dev->base);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
if (msm_rng_dev->icc_path)
|
||||
icc_put(msm_rng_dev->icc_path);
|
||||
|
||||
kzfree(msm_rng_dev);
|
||||
msm_rng_dev_cached = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qrng_get_random(struct crypto_rng *tfm, const u8 *src,
|
||||
unsigned int slen, u8 *rdata,
|
||||
unsigned int dlen)
|
||||
{
|
||||
int sizeread = 0;
|
||||
int rv = -EFAULT;
|
||||
|
||||
if (!msm_rng_dev_cached) {
|
||||
pr_err("%s: msm_rng_dev is not initialized\n", __func__);
|
||||
rv = -ENODEV;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
if (!rdata) {
|
||||
pr_err("%s: data buffer is null\n", __func__);
|
||||
rv = -EINVAL;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
if (signal_pending(current) ||
|
||||
mutex_lock_interruptible(&cached_rng_lock)) {
|
||||
pr_err("%s: mutex lock interrupted\n", __func__);
|
||||
rv = -ERESTARTSYS;
|
||||
goto err_exit;
|
||||
}
|
||||
sizeread = msm_rng_direct_read(msm_rng_dev_cached, rdata, dlen);
|
||||
|
||||
if (sizeread == dlen)
|
||||
rv = 0;
|
||||
|
||||
mutex_unlock(&cached_rng_lock);
|
||||
err_exit:
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
static int qrng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rng_alg rng_algs[] = { {
|
||||
.generate = qrng_get_random,
|
||||
.seed = qrng_reset,
|
||||
.seedsize = 0,
|
||||
.base = {
|
||||
.cra_name = "qrng",
|
||||
.cra_driver_name = "fips_hw_qrng",
|
||||
.cra_priority = 300,
|
||||
.cra_ctxsize = 0,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
} };
|
||||
|
||||
static const struct of_device_id qrng_match[] = {
|
||||
{.compatible = "qcom,msm-rng"},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver rng_driver = {
|
||||
.probe = msm_rng_probe,
|
||||
.remove = msm_rng_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = qrng_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init msm_rng_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
msm_rng_dev_cached = NULL;
|
||||
ret = platform_driver_register(&rng_driver);
|
||||
if (ret) {
|
||||
pr_err("%s: platform_driver_register error:%d\n",
|
||||
__func__, ret);
|
||||
goto err_exit;
|
||||
}
|
||||
ret = crypto_register_rngs(rng_algs, ARRAY_SIZE(rng_algs));
|
||||
if (ret) {
|
||||
pr_err("%s: crypto_register_algs error:%d\n",
|
||||
__func__, ret);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
err_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
module_init(msm_rng_init);
|
||||
|
||||
static void __exit msm_rng_exit(void)
|
||||
{
|
||||
crypto_unregister_rngs(rng_algs, ARRAY_SIZE(rng_algs));
|
||||
platform_driver_unregister(&rng_driver);
|
||||
}
|
||||
|
||||
module_exit(msm_rng_exit);
|
||||
|
||||
MODULE_DESCRIPTION("QTI MSM Random Number Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -978,13 +978,13 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
||||
|
||||
if (wait_startup(chip, 0) != 0) {
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
goto err_start;
|
||||
}
|
||||
|
||||
/* Take control of the TPM's interrupt hardware and shut it off */
|
||||
rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
goto err_start;
|
||||
|
||||
intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
|
||||
TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
|
||||
@ -993,21 +993,21 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
||||
|
||||
rc = tpm_chip_start(chip);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
goto err_start;
|
||||
|
||||
rc = tpm2_probe(chip);
|
||||
tpm_chip_stop(chip);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
goto err_probe;
|
||||
|
||||
rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
goto err_probe;
|
||||
|
||||
priv->manufacturer_id = vendor;
|
||||
|
||||
rc = tpm_tis_read8(priv, TPM_RID(0), &rid);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
goto err_probe;
|
||||
|
||||
dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
|
||||
(chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
|
||||
@ -1016,13 +1016,13 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
||||
probe = probe_itpm(chip);
|
||||
if (probe < 0) {
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
goto err_probe;
|
||||
}
|
||||
|
||||
/* Figure out the capabilities */
|
||||
rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
goto err_probe;
|
||||
|
||||
dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
|
||||
intfcaps);
|
||||
@ -1056,7 +1056,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
||||
if (tpm_get_timeouts(chip)) {
|
||||
dev_err(dev, "Could not get TPM timeouts and durations\n");
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
goto err_probe;
|
||||
}
|
||||
|
||||
if (irq) {
|
||||
@ -1070,15 +1070,18 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
||||
}
|
||||
}
|
||||
|
||||
tpm_chip_stop(chip);
|
||||
|
||||
rc = tpm_chip_register(chip);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
|
||||
if (chip->ops->clk_enable != NULL)
|
||||
chip->ops->clk_enable(chip, false);
|
||||
goto err_start;
|
||||
|
||||
return 0;
|
||||
out_err:
|
||||
|
||||
err_probe:
|
||||
tpm_chip_stop(chip);
|
||||
|
||||
err_start:
|
||||
if ((chip->ops != NULL) && (chip->ops->clk_enable != NULL))
|
||||
chip->ops->clk_enable(chip, false);
|
||||
|
||||
|
@ -23,6 +23,15 @@ config COMMON_CLK
|
||||
menu "Common Clock Framework"
|
||||
depends on COMMON_CLK
|
||||
|
||||
config COMMON_CLK_QCOM_DEBUG
|
||||
bool "QCOM clock debug features"
|
||||
depends on DEBUG_FS && QGKI
|
||||
help
|
||||
Support for QCOM debug features. These features include
|
||||
modifications to existing debugfs nodes to make them writable (e.g.
|
||||
clk_enable_count, clk_rate), as well as new debugfs nodes (e.g.
|
||||
clk_enabled_list, debug_suspend, trace_clocks).
|
||||
|
||||
config COMMON_CLK_WM831X
|
||||
tristate "Clock driver for WM831x/2x PMICs"
|
||||
depends on MFD_WM831X
|
||||
|
@ -295,6 +295,9 @@ static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent,
|
||||
unsigned long parent_rate, best = 0, now, maxdiv;
|
||||
unsigned long parent_rate_saved = *best_parent_rate;
|
||||
|
||||
if (!hw || !parent)
|
||||
return -EINVAL;
|
||||
|
||||
if (!rate)
|
||||
rate = 1;
|
||||
|
||||
@ -508,6 +511,7 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev,
|
||||
/* register the clock */
|
||||
hw = &div->hw;
|
||||
ret = clk_hw_register(dev, hw);
|
||||
hw->init = NULL;
|
||||
if (ret) {
|
||||
kfree(div);
|
||||
hw = ERR_PTR(ret);
|
||||
|
@ -98,6 +98,7 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
|
||||
ret = clk_hw_register(dev, hw);
|
||||
else
|
||||
ret = of_clk_hw_register(np, hw);
|
||||
hw->init = NULL;
|
||||
if (ret) {
|
||||
kfree(fix);
|
||||
hw = ERR_PTR(ret);
|
||||
|
@ -89,6 +89,7 @@ struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
|
||||
ret = clk_hw_register(dev, hw);
|
||||
else if (np)
|
||||
ret = of_clk_hw_register(np, hw);
|
||||
hw->init = NULL;
|
||||
if (ret) {
|
||||
kfree(fixed);
|
||||
hw = ERR_PTR(ret);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user