-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAl7zdl0ACgkQONu9yGCS aT4fAg/7Bg+JHOdJpdSb4FLMjpWHnjOMJ4ICMEfEPS9vJR41HpAaC8LdI3PBZdOZ ujEdX3ia1p3N/bnnHwVPFaycWQ6Z9TItoj6gzCLqjzVzdKJKXEx8uQFY0KWt+w4R 0orn1acd+bqMLhnRrJqMEhmRG3Y6IrkWXYr/qDC6OuZDgigtHC46mX0IdQiUomFd As9x1cr6+j27zOf8iwyNNXWo5AL2VFR7zDhlfR+sllN6Tn90AhumFoES8GL+ylfu OybF5LH4l9gOiFwvI7gTeihJoJOyh/cKP0glnDzRIZVIFv96At3cDt5GiRxkqbYw u1bo5X5xPxJogN9SLUi4O6pnrmQmuK27zJcI43TDfdRguSzXWzZclyNQ9d3zqmvJ QCmCsQkZst4K4SGg4UE2Wb6Gi51lsmV4OKll7eh61I87e8J7t7r8I5HRDdNCLzuf 3biqYn8f6307ME59fniVlQSynMt8B9lxyTS6hkYN/iCf753jHKdJRy97JcXugiCo DUoMCNchLDg5LH9TWq6k96rCklaVGPkp8HO/davMAc5Xn+YgPqE/ZpO7hH0nCLBE Fc0bvddiebXI5NrxIXu20vajQWi5YuVw5JWUBvcK6aONluwRomCvTIPRT1SZZiaK 5Cm5lyDGK3yYC0Dz++QzATVtNEOAkUOWgLpgOenrUVPtCtgDOrk= =cQWB -----END PGP SIGNATURE----- Merge 5.4.49 into android-5.4-stable Changes in 5.4.49 power: supply: bq24257_charger: Replace depends on REGMAP_I2C with select clk: sunxi: Fix incorrect usage of round_down() ASoC: tegra: tegra_wm8903: Support nvidia, headset property i2c: piix4: Detect secondary SMBus controller on AMD AM4 chipsets ASoC: SOF: imx8: Fix randbuild error iio: pressure: bmp280: Tolerate IRQ before registering remoteproc: Fix IDR initialisation in rproc_alloc() clk: qcom: msm8916: Fix the address location of pll->config_reg ASoC: fsl_esai: Disable exception interrupt before scheduling tasklet backlight: lp855x: Ensure regulators are disabled on probe failure ARM: dts: renesas: Fix IOMMU device node names ASoC: davinci-mcasp: Fix dma_chan refcnt leak when getting dma type ARM: integrator: Add some Kconfig selections ARM: dts: stm32: Add missing ethernet PHY reset on AV96 scsi: core: free sgtables in case command setup fails scsi: qedi: Check for buffer overflow in qedi_set_path() arm64: dts: meson: fixup SCP sram nodes ALSA: hda/realtek - Introduce polarity for micmute LED GPIO ALSA: isa/wavefront: prevent out of bounds write in ioctl PCI: Allow pci_resize_resource() for devices on root bus scsi: qla2xxx: Fix issue with adapter's stopping state Input: edt-ft5x06 - fix get_default register write access powerpc/kasan: Fix stack overflow by increasing THREAD_SHIFT rtc: mc13xxx: fix a double-unlock issue iio: bmp280: fix compensation of humidity f2fs: report delalloc reserve as non-free in statfs for project quota i2c: pxa: clear all master action bits in i2c_pxa_stop_message() remoteproc: qcom_q6v5_mss: map/unmap mpss segments before/after use clk: samsung: Mark top ISP and CAM clocks on Exynos542x as critical usblp: poison URBs upon disconnect serial: 8250: Fix max baud limit in generic 8250 port misc: fastrpc: Fix an incomplete memory release in fastrpc_rpmsg_probe() misc: fastrpc: fix potential fastrpc_invoke_ctx leak dm mpath: switch paths in dm_blk_ioctl() code path arm64: dts: armada-3720-turris-mox: forbid SDR104 on SDIO for FCC purposes arm64: dts: armada-3720-turris-mox: fix SFP binding arm64: dts: juno: Fix GIC child nodes pinctrl: ocelot: Fix GPIO interrupt decoding on Jaguar2 clk: renesas: cpg-mssr: Fix STBCR suspend/resume handling ASoC: SOF: Do nothing when DSP PM callbacks are not set arm64: dts: fvp: Fix GIC child nodes PCI: aardvark: Don't blindly enable ASPM L0s and don't write to read-only register ps3disk: use the default segment boundary arm64: dts: fvp/juno: Fix node address fields vfio/pci: fix memory leaks in alloc_perm_bits() coresight: tmc: Fix TMC mode read in tmc_read_prepare_etb() RDMA/mlx5: Add init2init as a modify command scsi: hisi_sas: Do not reset phy timer to wait for stray phy up PCI: pci-bridge-emul: Fix PCIe bit conflicts m68k/PCI: Fix a memory leak in an error handling path gpio: dwapb: Call acpi_gpiochip_free_interrupts() on GPIO chip de-registration usb: gadget: core: sync interrupt before unbind the udc powerpc/ptdump: Add _PAGE_COHERENT flag mfd: wm8994: Fix driver operation if loaded as modules scsi: cxgb3i: Fix some leaks in init_act_open() clk: zynqmp: fix memory leak in zynqmp_register_clocks scsi: lpfc: Fix lpfc_nodelist leak when processing unsolicited event scsi: vhost: Notify TCM about the maximum sg entries supported per command clk: clk-flexgen: fix clock-critical handling IB/mlx5: Fix DEVX support for MLX5_CMD_OP_INIT2INIT_QP command powerpc/perf/hv-24x7: Fix inconsistent output values incase multiple hv-24x7 events run nfsd: Fix svc_xprt refcnt leak when setup callback client failed PCI: vmd: Filter resource type bits from shadow register RDMA/core: Fix several reference count leaks. cifs: set up next DFS target before generic_ip_connect() ASoC: qcom: q6asm-dai: kCFI fix powerpc/crashkernel: Take "mem=" option into account pwm: img: Call pm_runtime_put() in pm_runtime_get_sync() failed case sparc32: mm: Don't try to free page-table pages if ctor() fails yam: fix possible memory leak in yam_init_driver NTB: ntb_pingpong: Choose doorbells based on port number NTB: Fix the default port and peer numbers for legacy drivers mksysmap: Fix the mismatch of '.L' symbols in System.map apparmor: fix introspection of of task mode for unconfined tasks net: dsa: lantiq_gswip: fix and improve the unsupported interface error apparmor: check/put label on apparmor_sk_clone_security() f2fs: handle readonly filesystem in f2fs_ioc_shutdown() ASoC: meson: add missing free_irq() in error path bpf, sockhash: Fix memory leak when unlinking sockets in sock_hash_free scsi: sr: Fix sr_probe() missing deallocate of device minor scsi: ibmvscsi: Don't send host info in adapter info MAD after LPM apparmor: fix nnp subset test for unconfined x86/purgatory: Disable various profiling and sanitizing options staging: greybus: fix a missing-check bug in gb_lights_light_config() arm64: dts: mt8173: fix unit name warnings scsi: qedi: Do not flush offload work if ARP not resolved arm64: dts: qcom: msm8916: remove unit name for thermal trip points ARM: dts: sun8i-h2-plus-bananapi-m2-zero: Fix led polarity RDMA/mlx5: Fix udata response upon SRQ creation gpio: dwapb: Append MODULE_ALIAS for platform driver scsi: qedf: Fix crash when MFW calls for protocol stats while function is still probing pinctrl: rza1: Fix wrong array assignment of rza1l_swio_entries virtiofs: schedule blocking async replies in separate worker arm64: dts: qcom: fix pm8150 gpio interrupts firmware: qcom_scm: fix bogous abuse of dma-direct internals staging: gasket: Fix mapping refcnt leak when put attribute fails staging: gasket: Fix mapping refcnt leak when register/store fails ALSA: usb-audio: Improve frames size computation ALSA: usb-audio: Fix racy list management in output queue s390/qdio: put thinint indicator after early error tty: hvc: Fix data abort due to race in hvc_open slimbus: ngd: get drvdata from correct device clk: meson: meson8b: Fix the first parent of vid_pll_in_sel clk: meson: meson8b: Fix the polarity of the RESET_N lines clk: meson: meson8b: Fix the vclk_div{1, 2, 4, 6, 12}_en gate bits gpio: pca953x: fix handling of automatic address incrementing thermal/drivers/ti-soc-thermal: Avoid dereferencing ERR_PTR clk: meson: meson8b: Don't rely on u-boot to init all GP_PLL registers ASoC: max98373: reorder max98373_reset() in resume soundwire: slave: don't init debugfs on device registration error HID: intel-ish-hid: avoid bogus uninitialized-variable warning usb: dwc3: gadget: Properly handle ClearFeature(halt) usb: dwc3: gadget: Properly handle failed kick_transfer staging: wilc1000: Increase the size of wid_list array staging: sm750fb: add missing case while setting FB_VISUAL PCI: v3-semi: Fix a memory leak in v3_pci_probe() error handling paths i2c: pxa: fix i2c_pxa_scream_blue_murder() debug output serial: amba-pl011: Make sure we initialize the port.lock spinlock drivers: base: Fix NULL pointer exception in __platform_driver_probe() if a driver developer is foolish PCI: rcar: Fix incorrect programming of OB windows PCI/ASPM: Allow ASPM on links to PCIe-to-PCI/PCI-X Bridges scsi: qla2xxx: Fix warning after FC target reset ALSA: firewire-lib: fix invalid assignment to union data for directional parameter power: supply: lp8788: Fix an error handling path in 'lp8788_charger_probe()' power: supply: smb347-charger: IRQSTAT_D is volatile ASoC: SOF: core: fix error return code in sof_probe_continue() arm64: dts: msm8996: Fix CSI IRQ types scsi: target: loopback: Fix READ with data and sensebytes scsi: mpt3sas: Fix double free warnings SoC: rsnd: add interrupt support for SSI BUSIF buffer ASoC: ux500: mop500: Fix some refcounted resources issues ASoC: ti: omap-mcbsp: Fix an error handling path in 'asoc_mcbsp_probe()' pinctrl: rockchip: fix memleak in rockchip_dt_node_to_map dlm: remove BUG() before panic() USB: ohci-sm501: fix error return code in ohci_hcd_sm501_drv_probe() clk: ti: composite: fix memory leak PCI: Fix pci_register_host_bridge() device_register() error handling powerpc/64: Don't initialise init_task->thread.regs tty: n_gsm: Fix SOF skipping tty: n_gsm: Fix waking up upper tty layer when room available ALSA: usb-audio: Add duplex sound support for USB devices using implicit feedback HID: Add quirks for Trust Panora Graphic Tablet PCI/PM: Assume ports without DLL Link Active train links in 100 ms habanalabs: increase timeout during reset ipmi: use vzalloc instead of kmalloc for user creation powerpc/64s/exception: Fix machine check no-loss idle wakeup powerpc/pseries/ras: Fix FWNMI_VALID off by one drivers: phy: sr-usb: do not use internal fsm for USB2 phy init powerpc/ps3: Fix kexec shutdown hang vfio-pci: Mask cap zero usb/ohci-platform: Fix a warning when hibernating drm/msm/mdp5: Fix mdp5_init error path for failed mdp5_kms allocation ASoC: Intel: bytcr_rt5640: Add quirk for Toshiba Encore WT8-A tablet USB: host: ehci-mxc: Add error handling in ehci_mxc_drv_probe() tty: n_gsm: Fix bogus i++ in gsm_data_kick fpga: dfl: afu: Corrected error handling levels clk: samsung: exynos5433: Add IGNORE_UNUSED flag to sclk_i2s1 RDMA/hns: Bugfix for querying qkey RDMA/hns: Fix cmdq parameter of querying pf timer resource scsi: target: tcmu: Userspace must not complete queued commands firmware: imx: scu: Fix possible memory leak in imx_scu_probe() fuse: fix copy_file_range cache issues fuse: copy_file_range should truncate cache arm64: tegra: Fix ethernet phy-mode for Jetson Xavier arm64: tegra: Fix flag for 64-bit resources in 'ranges' property powerpc/64s/pgtable: fix an undefined behaviour dm zoned: return NULL if dmz_get_zone_for_reclaim() fails to find a zone PCI/PTM: Inherit Switch Downstream Port PTM settings from Upstream Port PCI: dwc: Fix inner MSI IRQ domain registration PCI: amlogic: meson: Don't use FAST_LINK_MODE to set up link IB/cma: Fix ports memory leak in cma_configfs watchdog: da9062: No need to ping manually before setting timeout usb: dwc2: gadget: move gadget resume after the core is in L0 state USB: gadget: udc: s3c2410_udc: Remove pointless NULL check in s3c2410_udc_nuke usb: gadget: lpc32xx_udc: don't dereference ep pointer before null check usb: gadget: fix potential double-free in m66592_probe. usb: gadget: Fix issue with config_ep_by_speed function scripts: headers_install: Exit with error on config leak RDMA/iw_cxgb4: cleanup device debugfs entries on ULD remove x86/apic: Make TSC deadline timer detection message visible mfd: stmfx: Reset chip on resume as supply was disabled mfd: stmfx: Fix stmfx_irq_init error path mfd: stmfx: Disable IRQ in suspend to avoid spurious interrupt powerpc/32s: Don't warn when mapping RO data ROX. ASoC: fix incomplete error-handling in img_i2s_in_probe. scsi: target: tcmu: Fix a use after free in tcmu_check_expired_queue_cmd() clk: bcm2835: Fix return type of bcm2835_register_gate scsi: ufs-qcom: Fix scheduling while atomic issue KVM: PPC: Book3S HV: Ignore kmemleak false positives KVM: PPC: Book3S: Fix some RCU-list locks clk: sprd: return correct type of value for _sprd_pll_recalc_rate clk: ast2600: Fix AHB clock divider for A1 misc: xilinx-sdfec: improve get_user_pages_fast() error handling /dev/mem: Revoke mappings when a driver claims the region net: sunrpc: Fix off-by-one issues in 'rpc_ntop6' NFSv4.1 fix rpc_call_done assignment for BIND_CONN_TO_SESSION of: Fix a refcounting bug in __of_attach_node_sysfs() input: i8042 - Remove special PowerPC handling powerpc/4xx: Don't unmap NULL mbase extcon: adc-jack: Fix an error handling path in 'adc_jack_probe()' ASoC: fsl_asrc_dma: Fix dma_chan leak when config DMA channel failed vfio/mdev: Fix reference count leak in add_mdev_supported_type rtc: rv3028: Add missed check for devm_regmap_init_i2c() mailbox: zynqmp-ipi: Fix NULL vs IS_ERR() check in zynqmp_ipi_mbox_probe() rxrpc: Adjust /proc/net/rxrpc/calls to display call->debug_id not user_ID openrisc: Fix issue with argument clobbering for clone/fork drm/nouveau/disp/gm200-: fix NV_PDISP_SOR_HDMI2_CTRL(n) selection ceph: don't return -ESTALE if there's still an open file nfsd4: make drc_slab global, not per-net gfs2: Allow lock_nolock mount to specify jid=X scsi: iscsi: Fix reference count leak in iscsi_boot_create_kobj scsi: ufs: Don't update urgent bkops level when toggling auto bkops pinctrl: imxl: Fix an error handling path in 'imx1_pinctrl_core_probe()' pinctrl: freescale: imx: Fix an error handling path in 'imx_pinctrl_probe()' nfsd: safer handling of corrupted c_type drm/amd/display: Revalidate bandwidth before commiting DC updates crypto: omap-sham - add proper load balancing support for multicore geneve: change from tx_error to tx_dropped on missing metadata lib/zlib: remove outdated and incorrect pre-increment optimization include/linux/bitops.h: avoid clang shift-count-overflow warnings selftests/vm/pkeys: fix alloc_random_pkey() to make it really random blktrace: use errno instead of bi_status blktrace: fix endianness in get_pdu_int() blktrace: fix endianness for blk_log_remap() gfs2: fix use-after-free on transaction ail lists net: marvell: Fix OF_MDIO config check ntb_perf: pass correct struct device to dma_alloc_coherent ntb_tool: pass correct struct device to dma_alloc_coherent NTB: ntb_tool: reading the link file should not end in a NULL byte NTB: Revert the change to use the NTB device dev for DMA allocations NTB: perf: Don't require one more memory window than number of peers NTB: perf: Fix support for hardware that doesn't have port numbers NTB: perf: Fix race condition when run with ntb_test NTB: ntb_test: Fix bug when counting remote files i2c: icy: Fix build with CONFIG_AMIGA_PCMCIA=n drivers/perf: hisi: Fix wrong value for all counters enable selftests/net: in timestamping, strncpy needs to preserve null byte f2fs: don't return vmalloc() memory from f2fs_kmalloc() afs: Fix memory leak in afs_put_sysnames() ASoC: core: only convert non DPCM link to DPCM link ASoC: SOF: nocodec: conditionally set dpcm_capture/dpcm_playback flags ASoC: Intel: bytcr_rt5640: Add quirk for Toshiba Encore WT10-A tablet ASoC: rt5645: Add platform-data for Asus T101HA bpf/sockmap: Fix kernel panic at __tcp_bpf_recvmsg bpf, sockhash: Synchronize delete from bucket list on map free tracing/probe: Fix bpf_task_fd_query() for kprobes and uprobes drm/sun4i: hdmi ddc clk: Fix size of m divider libbpf: Handle GCC noreturn-turned-volatile quirk scsi: acornscsi: Fix an error handling path in acornscsi_probe() x86/idt: Keep spurious entries unset in system_vectors net/filter: Permit reading NET in load_bytes_relative when MAC not set nvme-pci: use simple suspend when a HMB is enabled nfs: set invalid blocks after NFSv4 writes xdp: Fix xsk_generic_xmit errno iavf: fix speed reporting over virtchnl bpf: Fix memlock accounting for sock_hash usb/xhci-plat: Set PM runtime as active on resume usb: host: ehci-platform: add a quirk to avoid stuck usb/ehci-platform: Set PM runtime as active on resume perf report: Fix NULL pointer dereference in hists__fprintf_nr_sample_events() perf stat: Fix NULL pointer dereference ext4: stop overwrite the errcode in ext4_setup_super bcache: fix potential deadlock problem in btree_gc_coalesce powerpc: Fix kernel crash in show_instructions() w/DEBUG_VIRTUAL afs: Fix non-setting of mtime when writing into mmap afs: afs_write_end() should change i_size under the right lock afs: Fix EOF corruption afs: Always include dir in bulk status fetch from afs_do_lookup() afs: Set error flag rather than return error from file status decode afs: Fix the mapping of the UAEOVERFLOW abort code bnxt_en: Return from timer if interface is not in open state. scsi: ufs-bsg: Fix runtime PM imbalance on error block: Fix use-after-free in blkdev_get() mvpp2: remove module bugfix arm64: hw_breakpoint: Don't invoke overflow handler on uaccess watchpoints libata: Use per port sync for detach drm: encoder_slave: fix refcouting error for modules ext4: fix partial cluster initialization when splitting extent ext4: avoid utf8_strncasecmp() with unstable name drm/dp_mst: Reformat drm_dp_check_act_status() a bit drm/qxl: Use correct notify port address when creating cursor ring drm/amdgpu: Replace invalid device ID with a valid device ID selinux: fix double free jbd2: clean __jbd2_journal_abort_hard() and __journal_abort_soft() ext4: avoid race conditions when remounting with options that change dax drm/dp_mst: Increase ACT retry timeout to 3s drm/amd/display: Use swap() where appropriate x86/boot/compressed: Relax sed symbol type regex for LLVM ld.lld block: nr_sects_write(): Disable preemption on seqcount write net/mlx5: DR, Fix freeing in dr_create_rc_qp() f2fs: split f2fs_d_compare() from f2fs_match_name() f2fs: avoid utf8_strncasecmp() with unstable name s390: fix syscall_get_error for compat processes drm/i915: Fix AUX power domain toggling across TypeC mode resets drm/msm: Check for powered down HW in the devfreq callbacks drm/i915/gem: Avoid iterating an empty list drm/i915: Whitelist context-local timestamp in the gen9 cmdparser drm/connector: notify userspace on hotplug after register complete drm/amd/display: Use kvfree() to free coeff in build_regamma() drm/i915/icl+: Fix hotplug interrupt disabling after storm detection Revert "drm/amd/display: disable dcn20 abm feature for bring up" crypto: algif_skcipher - Cap recv SG list at ctx->used crypto: algboss - don't wait during notifier callback tracing/probe: Fix memleak in fetch_op_data operations kprobes: Fix to protect kick_kprobe_optimizer() by kprobe_mutex kretprobe: Prevent triggering kretprobe from within kprobe_flush_task e1000e: Do not wake up the system via WOL if device wakeup is disabled net: octeon: mgmt: Repair filling of RX ring pwm: jz4740: Enhance precision in calculation of duty cycle sched/rt, net: Use CONFIG_PREEMPTION.patch net: core: device_rename: Use rwsem instead of a seqcount Linux 5.4.49 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I93723d3c14b5de06aafb4e59a9e35a1d74389757
640 lines
16 KiB
C
640 lines
16 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Qualcomm SCM driver
|
|
*
|
|
* Copyright (c) 2010,2015, The Linux Foundation. All rights reserved.
|
|
* Copyright (C) 2015 Linaro Ltd.
|
|
*/
|
|
#include <linux/platform_device.h>
|
|
#include <linux/init.h>
|
|
#include <linux/cpumask.h>
|
|
#include <linux/export.h>
|
|
#include <linux/dma-mapping.h>
|
|
#include <linux/module.h>
|
|
#include <linux/types.h>
|
|
#include <linux/qcom_scm.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/of_platform.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/reset-controller.h>
|
|
|
|
#include "qcom_scm.h"
|
|
|
|
static bool download_mode = IS_ENABLED(CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT);
|
|
module_param(download_mode, bool, 0);
|
|
|
|
#define SCM_HAS_CORE_CLK BIT(0)
|
|
#define SCM_HAS_IFACE_CLK BIT(1)
|
|
#define SCM_HAS_BUS_CLK BIT(2)
|
|
|
|
struct qcom_scm {
|
|
struct device *dev;
|
|
struct clk *core_clk;
|
|
struct clk *iface_clk;
|
|
struct clk *bus_clk;
|
|
struct reset_controller_dev reset;
|
|
|
|
u64 dload_mode_addr;
|
|
};
|
|
|
|
struct qcom_scm_current_perm_info {
|
|
__le32 vmid;
|
|
__le32 perm;
|
|
__le64 ctx;
|
|
__le32 ctx_size;
|
|
__le32 unused;
|
|
};
|
|
|
|
struct qcom_scm_mem_map_info {
|
|
__le64 mem_addr;
|
|
__le64 mem_size;
|
|
};
|
|
|
|
static struct qcom_scm *__scm;
|
|
|
|
static int qcom_scm_clk_enable(void)
|
|
{
|
|
int ret;
|
|
|
|
ret = clk_prepare_enable(__scm->core_clk);
|
|
if (ret)
|
|
goto bail;
|
|
|
|
ret = clk_prepare_enable(__scm->iface_clk);
|
|
if (ret)
|
|
goto disable_core;
|
|
|
|
ret = clk_prepare_enable(__scm->bus_clk);
|
|
if (ret)
|
|
goto disable_iface;
|
|
|
|
return 0;
|
|
|
|
disable_iface:
|
|
clk_disable_unprepare(__scm->iface_clk);
|
|
disable_core:
|
|
clk_disable_unprepare(__scm->core_clk);
|
|
bail:
|
|
return ret;
|
|
}
|
|
|
|
static void qcom_scm_clk_disable(void)
|
|
{
|
|
clk_disable_unprepare(__scm->core_clk);
|
|
clk_disable_unprepare(__scm->iface_clk);
|
|
clk_disable_unprepare(__scm->bus_clk);
|
|
}
|
|
|
|
/**
|
|
* qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
|
|
* @entry: Entry point function for the cpus
|
|
* @cpus: The cpumask of cpus that will use the entry point
|
|
*
|
|
* Set the cold boot address of the cpus. Any cpu outside the supported
|
|
* range would be removed from the cpu present mask.
|
|
*/
|
|
int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
|
|
{
|
|
return __qcom_scm_set_cold_boot_addr(entry, cpus);
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
|
|
|
|
/**
|
|
* qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
|
|
* @entry: Entry point function for the cpus
|
|
* @cpus: The cpumask of cpus that will use the entry point
|
|
*
|
|
* Set the Linux entry point for the SCM to transfer control to when coming
|
|
* out of a power down. CPU power down may be executed on cpuidle or hotplug.
|
|
*/
|
|
int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
|
|
{
|
|
return __qcom_scm_set_warm_boot_addr(__scm->dev, entry, cpus);
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
|
|
|
|
/**
|
|
* qcom_scm_cpu_power_down() - Power down the cpu
|
|
* @flags - Flags to flush cache
|
|
*
|
|
* This is an end point to power down cpu. If there was a pending interrupt,
|
|
* the control would return from this function, otherwise, the cpu jumps to the
|
|
* warm boot entry point set for this cpu upon reset.
|
|
*/
|
|
void qcom_scm_cpu_power_down(u32 flags)
|
|
{
|
|
__qcom_scm_cpu_power_down(flags);
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_cpu_power_down);
|
|
|
|
/**
|
|
* qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
|
|
*
|
|
* Return true if HDCP is supported, false if not.
|
|
*/
|
|
bool qcom_scm_hdcp_available(void)
|
|
{
|
|
int ret = qcom_scm_clk_enable();
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP,
|
|
QCOM_SCM_CMD_HDCP);
|
|
|
|
qcom_scm_clk_disable();
|
|
|
|
return ret > 0 ? true : false;
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_hdcp_available);
|
|
|
|
/**
|
|
* qcom_scm_hdcp_req() - Send HDCP request.
|
|
* @req: HDCP request array
|
|
* @req_cnt: HDCP request array count
|
|
* @resp: response buffer passed to SCM
|
|
*
|
|
* Write HDCP register(s) through SCM.
|
|
*/
|
|
int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
|
|
{
|
|
int ret = qcom_scm_clk_enable();
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp);
|
|
qcom_scm_clk_disable();
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_hdcp_req);
|
|
|
|
/**
|
|
* qcom_scm_pas_supported() - Check if the peripheral authentication service is
|
|
* available for the given peripherial
|
|
* @peripheral: peripheral id
|
|
*
|
|
* Returns true if PAS is supported for this peripheral, otherwise false.
|
|
*/
|
|
bool qcom_scm_pas_supported(u32 peripheral)
|
|
{
|
|
int ret;
|
|
|
|
ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
|
|
QCOM_SCM_PAS_IS_SUPPORTED_CMD);
|
|
if (ret <= 0)
|
|
return false;
|
|
|
|
return __qcom_scm_pas_supported(__scm->dev, peripheral);
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_pas_supported);
|
|
|
|
/**
|
|
* qcom_scm_pas_init_image() - Initialize peripheral authentication service
|
|
* state machine for a given peripheral, using the
|
|
* metadata
|
|
* @peripheral: peripheral id
|
|
* @metadata: pointer to memory containing ELF header, program header table
|
|
* and optional blob of data used for authenticating the metadata
|
|
* and the rest of the firmware
|
|
* @size: size of the metadata
|
|
*
|
|
* Returns 0 on success.
|
|
*/
|
|
int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)
|
|
{
|
|
dma_addr_t mdata_phys;
|
|
void *mdata_buf;
|
|
int ret;
|
|
|
|
/*
|
|
* During the scm call memory protection will be enabled for the meta
|
|
* data blob, so make sure it's physically contiguous, 4K aligned and
|
|
* non-cachable to avoid XPU violations.
|
|
*/
|
|
mdata_buf = dma_alloc_coherent(__scm->dev, size, &mdata_phys,
|
|
GFP_KERNEL);
|
|
if (!mdata_buf) {
|
|
dev_err(__scm->dev, "Allocation of metadata buffer failed.\n");
|
|
return -ENOMEM;
|
|
}
|
|
memcpy(mdata_buf, metadata, size);
|
|
|
|
ret = qcom_scm_clk_enable();
|
|
if (ret)
|
|
goto free_metadata;
|
|
|
|
ret = __qcom_scm_pas_init_image(__scm->dev, peripheral, mdata_phys);
|
|
|
|
qcom_scm_clk_disable();
|
|
|
|
free_metadata:
|
|
dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_pas_init_image);
|
|
|
|
/**
|
|
* qcom_scm_pas_mem_setup() - Prepare the memory related to a given peripheral
|
|
* for firmware loading
|
|
* @peripheral: peripheral id
|
|
* @addr: start address of memory area to prepare
|
|
* @size: size of the memory area to prepare
|
|
*
|
|
* Returns 0 on success.
|
|
*/
|
|
int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)
|
|
{
|
|
int ret;
|
|
|
|
ret = qcom_scm_clk_enable();
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = __qcom_scm_pas_mem_setup(__scm->dev, peripheral, addr, size);
|
|
qcom_scm_clk_disable();
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_pas_mem_setup);
|
|
|
|
/**
|
|
* qcom_scm_pas_auth_and_reset() - Authenticate the given peripheral firmware
|
|
* and reset the remote processor
|
|
* @peripheral: peripheral id
|
|
*
|
|
* Return 0 on success.
|
|
*/
|
|
int qcom_scm_pas_auth_and_reset(u32 peripheral)
|
|
{
|
|
int ret;
|
|
|
|
ret = qcom_scm_clk_enable();
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = __qcom_scm_pas_auth_and_reset(__scm->dev, peripheral);
|
|
qcom_scm_clk_disable();
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_pas_auth_and_reset);
|
|
|
|
/**
|
|
* qcom_scm_pas_shutdown() - Shut down the remote processor
|
|
* @peripheral: peripheral id
|
|
*
|
|
* Returns 0 on success.
|
|
*/
|
|
int qcom_scm_pas_shutdown(u32 peripheral)
|
|
{
|
|
int ret;
|
|
|
|
ret = qcom_scm_clk_enable();
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = __qcom_scm_pas_shutdown(__scm->dev, peripheral);
|
|
qcom_scm_clk_disable();
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_pas_shutdown);
|
|
|
|
static int qcom_scm_pas_reset_assert(struct reset_controller_dev *rcdev,
|
|
unsigned long idx)
|
|
{
|
|
if (idx != 0)
|
|
return -EINVAL;
|
|
|
|
return __qcom_scm_pas_mss_reset(__scm->dev, 1);
|
|
}
|
|
|
|
static int qcom_scm_pas_reset_deassert(struct reset_controller_dev *rcdev,
|
|
unsigned long idx)
|
|
{
|
|
if (idx != 0)
|
|
return -EINVAL;
|
|
|
|
return __qcom_scm_pas_mss_reset(__scm->dev, 0);
|
|
}
|
|
|
|
static const struct reset_control_ops qcom_scm_pas_reset_ops = {
|
|
.assert = qcom_scm_pas_reset_assert,
|
|
.deassert = qcom_scm_pas_reset_deassert,
|
|
};
|
|
|
|
int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
|
|
{
|
|
return __qcom_scm_restore_sec_cfg(__scm->dev, device_id, spare);
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_restore_sec_cfg);
|
|
|
|
int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size)
|
|
{
|
|
return __qcom_scm_iommu_secure_ptbl_size(__scm->dev, spare, size);
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_size);
|
|
|
|
int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
|
|
{
|
|
return __qcom_scm_iommu_secure_ptbl_init(__scm->dev, addr, size, spare);
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init);
|
|
|
|
int qcom_scm_qsmmu500_wait_safe_toggle(bool en)
|
|
{
|
|
return __qcom_scm_qsmmu500_wait_safe_toggle(__scm->dev, en);
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_qsmmu500_wait_safe_toggle);
|
|
|
|
int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val)
|
|
{
|
|
return __qcom_scm_io_readl(__scm->dev, addr, val);
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_io_readl);
|
|
|
|
int qcom_scm_io_writel(phys_addr_t addr, unsigned int val)
|
|
{
|
|
return __qcom_scm_io_writel(__scm->dev, addr, val);
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_io_writel);
|
|
|
|
static void qcom_scm_set_download_mode(bool enable)
|
|
{
|
|
bool avail;
|
|
int ret = 0;
|
|
|
|
avail = __qcom_scm_is_call_available(__scm->dev,
|
|
QCOM_SCM_SVC_BOOT,
|
|
QCOM_SCM_SET_DLOAD_MODE);
|
|
if (avail) {
|
|
ret = __qcom_scm_set_dload_mode(__scm->dev, enable);
|
|
} else if (__scm->dload_mode_addr) {
|
|
ret = __qcom_scm_io_writel(__scm->dev, __scm->dload_mode_addr,
|
|
enable ? QCOM_SCM_SET_DLOAD_MODE : 0);
|
|
} else {
|
|
dev_err(__scm->dev,
|
|
"No available mechanism for setting download mode\n");
|
|
}
|
|
|
|
if (ret)
|
|
dev_err(__scm->dev, "failed to set download mode: %d\n", ret);
|
|
}
|
|
|
|
static int qcom_scm_find_dload_address(struct device *dev, u64 *addr)
|
|
{
|
|
struct device_node *tcsr;
|
|
struct device_node *np = dev->of_node;
|
|
struct resource res;
|
|
u32 offset;
|
|
int ret;
|
|
|
|
tcsr = of_parse_phandle(np, "qcom,dload-mode", 0);
|
|
if (!tcsr)
|
|
return 0;
|
|
|
|
ret = of_address_to_resource(tcsr, 0, &res);
|
|
of_node_put(tcsr);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = of_property_read_u32_index(np, "qcom,dload-mode", 1, &offset);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
*addr = res.start + offset;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* qcom_scm_is_available() - Checks if SCM is available
|
|
*/
|
|
bool qcom_scm_is_available(void)
|
|
{
|
|
return !!__scm;
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_is_available);
|
|
|
|
int qcom_scm_set_remote_state(u32 state, u32 id)
|
|
{
|
|
return __qcom_scm_set_remote_state(__scm->dev, state, id);
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_set_remote_state);
|
|
|
|
/**
|
|
* qcom_scm_assign_mem() - Make a secure call to reassign memory ownership
|
|
* @mem_addr: mem region whose ownership need to be reassigned
|
|
* @mem_sz: size of the region.
|
|
* @srcvm: vmid for current set of owners, each set bit in
|
|
* flag indicate a unique owner
|
|
* @newvm: array having new owners and corresponding permission
|
|
* flags
|
|
* @dest_cnt: number of owners in next set.
|
|
*
|
|
* Return negative errno on failure or 0 on success with @srcvm updated.
|
|
*/
|
|
int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
|
|
unsigned int *srcvm,
|
|
const struct qcom_scm_vmperm *newvm,
|
|
unsigned int dest_cnt)
|
|
{
|
|
struct qcom_scm_current_perm_info *destvm;
|
|
struct qcom_scm_mem_map_info *mem_to_map;
|
|
phys_addr_t mem_to_map_phys;
|
|
phys_addr_t dest_phys;
|
|
dma_addr_t ptr_phys;
|
|
size_t mem_to_map_sz;
|
|
size_t dest_sz;
|
|
size_t src_sz;
|
|
size_t ptr_sz;
|
|
int next_vm;
|
|
__le32 *src;
|
|
void *ptr;
|
|
int ret, i, b;
|
|
unsigned long srcvm_bits = *srcvm;
|
|
|
|
src_sz = hweight_long(srcvm_bits) * sizeof(*src);
|
|
mem_to_map_sz = sizeof(*mem_to_map);
|
|
dest_sz = dest_cnt * sizeof(*destvm);
|
|
ptr_sz = ALIGN(src_sz, SZ_64) + ALIGN(mem_to_map_sz, SZ_64) +
|
|
ALIGN(dest_sz, SZ_64);
|
|
|
|
ptr = dma_alloc_coherent(__scm->dev, ptr_sz, &ptr_phys, GFP_KERNEL);
|
|
if (!ptr)
|
|
return -ENOMEM;
|
|
|
|
/* Fill source vmid detail */
|
|
src = ptr;
|
|
i = 0;
|
|
for_each_set_bit(b, &srcvm_bits, BITS_PER_LONG)
|
|
src[i++] = cpu_to_le32(b);
|
|
|
|
/* Fill details of mem buff to map */
|
|
mem_to_map = ptr + ALIGN(src_sz, SZ_64);
|
|
mem_to_map_phys = ptr_phys + ALIGN(src_sz, SZ_64);
|
|
mem_to_map->mem_addr = cpu_to_le64(mem_addr);
|
|
mem_to_map->mem_size = cpu_to_le64(mem_sz);
|
|
|
|
next_vm = 0;
|
|
/* Fill details of next vmid detail */
|
|
destvm = ptr + ALIGN(mem_to_map_sz, SZ_64) + ALIGN(src_sz, SZ_64);
|
|
dest_phys = ptr_phys + ALIGN(mem_to_map_sz, SZ_64) + ALIGN(src_sz, SZ_64);
|
|
for (i = 0; i < dest_cnt; i++, destvm++, newvm++) {
|
|
destvm->vmid = cpu_to_le32(newvm->vmid);
|
|
destvm->perm = cpu_to_le32(newvm->perm);
|
|
destvm->ctx = 0;
|
|
destvm->ctx_size = 0;
|
|
next_vm |= BIT(newvm->vmid);
|
|
}
|
|
|
|
ret = __qcom_scm_assign_mem(__scm->dev, mem_to_map_phys, mem_to_map_sz,
|
|
ptr_phys, src_sz, dest_phys, dest_sz);
|
|
dma_free_coherent(__scm->dev, ptr_sz, ptr, ptr_phys);
|
|
if (ret) {
|
|
dev_err(__scm->dev,
|
|
"Assign memory protection call failed %d\n", ret);
|
|
return -EINVAL;
|
|
}
|
|
|
|
*srcvm = next_vm;
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(qcom_scm_assign_mem);
|
|
|
|
static int qcom_scm_probe(struct platform_device *pdev)
|
|
{
|
|
struct qcom_scm *scm;
|
|
unsigned long clks;
|
|
int ret;
|
|
|
|
scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL);
|
|
if (!scm)
|
|
return -ENOMEM;
|
|
|
|
ret = qcom_scm_find_dload_address(&pdev->dev, &scm->dload_mode_addr);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
clks = (unsigned long)of_device_get_match_data(&pdev->dev);
|
|
|
|
scm->core_clk = devm_clk_get(&pdev->dev, "core");
|
|
if (IS_ERR(scm->core_clk)) {
|
|
if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER)
|
|
return PTR_ERR(scm->core_clk);
|
|
|
|
if (clks & SCM_HAS_CORE_CLK) {
|
|
dev_err(&pdev->dev, "failed to acquire core clk\n");
|
|
return PTR_ERR(scm->core_clk);
|
|
}
|
|
|
|
scm->core_clk = NULL;
|
|
}
|
|
|
|
scm->iface_clk = devm_clk_get(&pdev->dev, "iface");
|
|
if (IS_ERR(scm->iface_clk)) {
|
|
if (PTR_ERR(scm->iface_clk) == -EPROBE_DEFER)
|
|
return PTR_ERR(scm->iface_clk);
|
|
|
|
if (clks & SCM_HAS_IFACE_CLK) {
|
|
dev_err(&pdev->dev, "failed to acquire iface clk\n");
|
|
return PTR_ERR(scm->iface_clk);
|
|
}
|
|
|
|
scm->iface_clk = NULL;
|
|
}
|
|
|
|
scm->bus_clk = devm_clk_get(&pdev->dev, "bus");
|
|
if (IS_ERR(scm->bus_clk)) {
|
|
if (PTR_ERR(scm->bus_clk) == -EPROBE_DEFER)
|
|
return PTR_ERR(scm->bus_clk);
|
|
|
|
if (clks & SCM_HAS_BUS_CLK) {
|
|
dev_err(&pdev->dev, "failed to acquire bus clk\n");
|
|
return PTR_ERR(scm->bus_clk);
|
|
}
|
|
|
|
scm->bus_clk = NULL;
|
|
}
|
|
|
|
scm->reset.ops = &qcom_scm_pas_reset_ops;
|
|
scm->reset.nr_resets = 1;
|
|
scm->reset.of_node = pdev->dev.of_node;
|
|
ret = devm_reset_controller_register(&pdev->dev, &scm->reset);
|
|
if (ret)
|
|
return ret;
|
|
|
|
/* vote for max clk rate for highest performance */
|
|
ret = clk_set_rate(scm->core_clk, INT_MAX);
|
|
if (ret)
|
|
return ret;
|
|
|
|
__scm = scm;
|
|
__scm->dev = &pdev->dev;
|
|
|
|
__qcom_scm_init();
|
|
|
|
/*
|
|
* If requested enable "download mode", from this point on warmboot
|
|
* will cause the the boot stages to enter download mode, unless
|
|
* disabled below by a clean shutdown/reboot.
|
|
*/
|
|
if (download_mode)
|
|
qcom_scm_set_download_mode(true);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void qcom_scm_shutdown(struct platform_device *pdev)
|
|
{
|
|
/* Clean shutdown, disable download mode to allow normal restart */
|
|
if (download_mode)
|
|
qcom_scm_set_download_mode(false);
|
|
}
|
|
|
|
static const struct of_device_id qcom_scm_dt_match[] = {
|
|
{ .compatible = "qcom,scm-apq8064",
|
|
/* FIXME: This should have .data = (void *) SCM_HAS_CORE_CLK */
|
|
},
|
|
{ .compatible = "qcom,scm-apq8084", .data = (void *)(SCM_HAS_CORE_CLK |
|
|
SCM_HAS_IFACE_CLK |
|
|
SCM_HAS_BUS_CLK)
|
|
},
|
|
{ .compatible = "qcom,scm-ipq4019" },
|
|
{ .compatible = "qcom,scm-msm8660", .data = (void *) SCM_HAS_CORE_CLK },
|
|
{ .compatible = "qcom,scm-msm8960", .data = (void *) SCM_HAS_CORE_CLK },
|
|
{ .compatible = "qcom,scm-msm8916", .data = (void *)(SCM_HAS_CORE_CLK |
|
|
SCM_HAS_IFACE_CLK |
|
|
SCM_HAS_BUS_CLK)
|
|
},
|
|
{ .compatible = "qcom,scm-msm8974", .data = (void *)(SCM_HAS_CORE_CLK |
|
|
SCM_HAS_IFACE_CLK |
|
|
SCM_HAS_BUS_CLK)
|
|
},
|
|
{ .compatible = "qcom,scm-msm8996" },
|
|
{ .compatible = "qcom,scm" },
|
|
{}
|
|
};
|
|
MODULE_DEVICE_TABLE(of, qcom_scm_dt_match);
|
|
|
|
static struct platform_driver qcom_scm_driver = {
|
|
.driver = {
|
|
.name = "qcom_scm",
|
|
.of_match_table = qcom_scm_dt_match,
|
|
},
|
|
.probe = qcom_scm_probe,
|
|
.shutdown = qcom_scm_shutdown,
|
|
};
|
|
|
|
static int __init qcom_scm_init(void)
|
|
{
|
|
return platform_driver_register(&qcom_scm_driver);
|
|
}
|
|
subsys_initcall(qcom_scm_init);
|
|
|
|
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. SCM driver");
|
|
MODULE_LICENSE("GPL v2");
|