4922049993
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmPCczkACgkQONu9yGCS aT4tnRAAsW8h/ohmhP+O2lQ9Ekw6s9VB6KB4aJzLhQXqIZlrzk2DP3CiLxQ7DkFc AcHwFYq+sERo8O7dK6pbCW0zNvLUpbK2wJhwMHujJfSUFboXX85NR6u90U67pBKS p+yVkDSx8LNc7c676xQ7ey5rO1K2fQQ266gexjI9WOkjIFOfplVkZ7tkvt51VwAD mNvOQsZdCE6xs+T3t9YMOtAx3wW8vl1wW3QDWCHznQwOJiMEjfNEOUY/+xELnnWz DVONWPHTFNKQHZwIuVUFZdNuORq5WXoIaMZdaEFkhuOtRMnQ9l+wi8iMxX8zkgBn Ji/dPu3GdAZsJU4/rXHkY2AeZV1oJc3NLYmevoRZirTqMQCqyM+blif7Rf34kBi7 6jlGPWOjyMNe58shfHmjWTl/u4pMDoYOnm5XO+1oL+2Xg8QWCucqAlfPFB3uMh6n aL4ymzo5QRy1+tx8v7o1NOjnGWydvYn3O4fwJVkYTFaJZZr9EI7gpTmEBw/gwfuf 4TH6BC++Ai/8vgKUhpdnWuTrjomWalPTcPBgQYG4gD7ak2TM1rmgMaCl/THUe36R zPC8m2sIXKeI4zGi8TeqTgaRvFSKJnuEmVo5OPkG98fZkjekCzWHp0q1+PG2Ecy8 Mu2/AOnwb1aSfOJh2Qajoke/Wed0U6qszop8C/jPRh8D1uTmRbI= =sOTj -----END PGP SIGNATURE----- Merge 5.10.163 into android12-5.10-lts Changes in 5.10.163 usb: musb: remove extra check in musb_gadget_vbus_draw arm64: dts: qcom: ipq6018-cp01-c1: use BLSPI1 pins arm64: dts: qcom: msm8996: fix GPU OPP table ARM: dts: qcom: apq8064: fix coresight compatible arm64: dts: qcom: sdm630: fix UART1 pin bias arm64: dts: qcom: sdm845-cheza: fix AP suspend pin bias arm64: dts: qcom: msm8916: Drop MSS fallback compatible objtool, kcsan: Add volatile read/write instrumentation to whitelist ARM: dts: stm32: Drop stm32mp15xc.dtsi from Avenger96 ARM: dts: stm32: Fix AV96 WLAN regulator gpio property drivers: soc: ti: knav_qmss_queue: Mark knav_acc_firmwares as static soc: qcom: llcc: make irq truly optional soc: qcom: apr: make code more reuseable soc: qcom: apr: Add check for idr_alloc and of_property_read_string_index arm: dts: spear600: Fix clcd interrupt soc: ti: knav_qmss_queue: Use pm_runtime_resume_and_get instead of pm_runtime_get_sync soc: ti: knav_qmss_queue: Fix PM disable depth imbalance in knav_queue_probe soc: ti: smartreflex: Fix PM disable depth imbalance in omap_sr_probe perf: arm_dsu: Fix hotplug callback leak in dsu_pmu_init() perf/smmuv3: Fix hotplug callback leak in arm_smmu_pmu_init() arm64: dts: ti: k3-am65-main: Drop dma-coherent in crypto node arm64: dts: ti: k3-j721e-main: Drop dma-coherent in crypto node arm64: dts: mt2712e: Fix unit_address_vs_reg warning for oscillators arm64: dts: mt2712e: Fix unit address for pinctrl node arm64: dts: mt2712-evb: Fix vproc fixed regulators unit names arm64: dts: mt2712-evb: Fix usb vbus regulators unit names arm64: dts: mediatek: pumpkin-common: Fix devicetree warnings arm64: dts: mediatek: mt6797: Fix 26M oscillator unit name ARM: dts: dove: Fix assigned-addresses for every PCIe Root Port ARM: dts: armada-370: Fix assigned-addresses for every PCIe Root Port ARM: dts: armada-xp: Fix assigned-addresses for every PCIe Root Port ARM: dts: armada-375: Fix assigned-addresses for every PCIe Root Port ARM: dts: armada-38x: Fix assigned-addresses for every PCIe Root Port ARM: dts: armada-39x: Fix assigned-addresses for every PCIe Root Port ARM: dts: turris-omnia: Add ethernet aliases ARM: dts: turris-omnia: Add switch port 6 node arm64: dts: armada-3720-turris-mox: Add missing interrupt for RTC pstore/ram: Fix error return code in ramoops_probe() ARM: mmp: fix timer_read delay pstore: Avoid kcore oops by vmap()ing with VM_IOREMAP tpm/tpm_ftpm_tee: Fix error handling in ftpm_mod_init() tpm/tpm_crb: Fix error message in __crb_relinquish_locality() sched/fair: Cleanup task_util and capacity type sched/uclamp: Fix relationship between uclamp and migration margin cpuidle: dt: Return the correct numbers of parsed idle states alpha: fix syscall entry in !AUDUT_SYSCALL case PM: hibernate: Fix mistake in kerneldoc comment fs: don't audit the capability check in simple_xattr_list() cpufreq: qcom-hw: Fix memory leak in qcom_cpufreq_hw_read_lut() selftests/ftrace: event_triggers: wait longer for test_event_enable perf: Fix possible memleak in pmu_dev_alloc() lib/debugobjects: fix stat count and optimize debug_objects_mem_init platform/x86: huawei-wmi: fix return value calculation timerqueue: Use rb_entry_safe() in timerqueue_getnext() proc: fixup uptime selftest lib/fonts: fix undefined behavior in bit shift for get_default_font ocfs2: fix memory leak in ocfs2_stack_glue_init() MIPS: vpe-mt: fix possible memory leak while module exiting MIPS: vpe-cmp: fix possible memory leak while module exiting selftests/efivarfs: Add checking of the test return value PNP: fix name memory leak in pnp_alloc_dev() perf/x86/intel/uncore: Fix reference count leak in hswep_has_limit_sbox() perf/x86/intel/uncore: Fix reference count leak in snr_uncore_mmio_map() perf/x86/intel/uncore: Fix reference count leak in __uncore_imc_init_box() platform/chrome: cros_usbpd_notify: Fix error handling in cros_usbpd_notify_init() irqchip: gic-pm: Use pm_runtime_resume_and_get() in gic_probe() EDAC/i10nm: fix refcount leak in pci_get_dev_wrapper() nfsd: don't call nfsd_file_put from client states seqfile display genirq/irqdesc: Don't try to remove non-existing sysfs files cpufreq: amd_freq_sensitivity: Add missing pci_dev_put() libfs: add DEFINE_SIMPLE_ATTRIBUTE_SIGNED for signed value lib/notifier-error-inject: fix error when writing -errno to debugfs file docs: fault-injection: fix non-working usage of negative values debugfs: fix error when writing negative value to atomic_t debugfs file ocfs2: ocfs2_mount_volume does cleanup job before return error ocfs2: rewrite error handling of ocfs2_fill_super ocfs2: fix memory leak in ocfs2_mount_volume() rapidio: fix possible name leaks when rio_add_device() fails rapidio: rio: fix possible name leak in rio_register_mport() clocksource/drivers/sh_cmt: Make sure channel clock supply is enabled clocksource/drivers/sh_cmt: Access registers according to spec futex: Move to kernel/futex/ futex: Resend potentially swallowed owner death notification cpu/hotplug: Make target_store() a nop when target == state clocksource/drivers/timer-ti-dm: Fix missing clk_disable_unprepare in dmtimer_systimer_init_clock() ACPICA: Fix use-after-free in acpi_ut_copy_ipackage_to_ipackage() uprobes/x86: Allow to probe a NOP instruction with 0x66 prefix x86/xen: Fix memory leak in xen_smp_intr_init{_pv}() x86/xen: Fix memory leak in xen_init_lock_cpu() xen/privcmd: Fix a possible warning in privcmd_ioctl_mmap_resource() PM: runtime: Improve path in rpm_idle() when no callback PM: runtime: Do not call __rpm_callback() from rpm_idle() platform/x86: mxm-wmi: fix memleak in mxm_wmi_call_mx[ds|mx]() platform/x86: intel_scu_ipc: fix possible name leak in __intel_scu_ipc_register() MIPS: BCM63xx: Add check for NULL for clk in clk_enable MIPS: OCTEON: warn only once if deprecated link status is being used fs: sysv: Fix sysv_nblocks() returns wrong value rapidio: fix possible UAF when kfifo_alloc() fails eventfd: change int to __u64 in eventfd_signal() ifndef CONFIG_EVENTFD relay: fix type mismatch when allocating memory in relay_create_buf() hfs: Fix OOB Write in hfs_asc2mac rapidio: devices: fix missing put_device in mport_cdev_open wifi: ath9k: hif_usb: fix memory leak of urbs in ath9k_hif_usb_dealloc_tx_urbs() wifi: ath9k: hif_usb: Fix use-after-free in ath9k_hif_usb_reg_in_cb() wifi: rtl8xxxu: Fix reading the vendor of combo chips drm/bridge: adv7533: remove dynamic lane switching from adv7533 bridge libbpf: Fix use-after-free in btf_dump_name_dups libbpf: Fix null-pointer dereference in find_prog_by_sec_insn() pata_ipx4xx_cf: Fix unsigned comparison with less than zero media: coda: jpeg: Add check for kmalloc media: i2c: ad5820: Fix error path venus: pm_helpers: Fix error check in vcodec_domains_get() media: exynos4-is: Use v4l2_async_notifier_add_fwnode_remote_subdev media: exynos4-is: don't rely on the v4l2_async_subdev internals can: kvaser_usb: do not increase tx statistics when sending error message frames can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device can: kvaser_usb: kvaser_usb_leaf: Rename {leaf,usbcan}_cmd_error_event to {leaf,usbcan}_cmd_can_error_event can: kvaser_usb: kvaser_usb_leaf: Handle CMD_ERROR_EVENT can: kvaser_usb_leaf: Set Warning state even without bus errors can: kvaser_usb_leaf: Fix improved state not being reported can: kvaser_usb_leaf: Fix wrong CAN state after stopping can: kvaser_usb_leaf: Fix bogus restart events can: kvaser_usb: Add struct kvaser_usb_busparams can: kvaser_usb: Compare requested bittiming parameters with actual parameters in do_set_{,data}_bittiming drm/rockchip: lvds: fix PM usage counter unbalance in poweron clk: renesas: r9a06g032: Repair grave increment error spi: Update reference to struct spi_controller drm/panel/panel-sitronix-st7701: Remove panel on DSI attach failure ima: Fix fall-through warnings for Clang ima: Handle -ESTALE returned by ima_filter_rule_match() drm/msm/hdmi: switch to drm_bridge_connector drm/msm/hdmi: drop unused GPIO support bpf: Fix slot type check in check_stack_write_var_off media: vivid: fix compose size exceed boundary media: platform: exynos4-is: fix return value check in fimc_md_probe() bpf: propagate precision in ALU/ALU64 operations bpf: Check the other end of slot_type for STACK_SPILL bpf: propagate precision across all frames, not just the last one clk: qcom: gcc-sm8250: Use retention mode for USB GDSCs mtd: Fix device name leak when register device failed in add_mtd_device() Input: joystick - fix Kconfig warning for JOYSTICK_ADC wifi: rsi: Fix handling of 802.3 EAPOL frames sent via control port media: camss: Clean up received buffers on failed start of streaming net, proc: Provide PROC_FS=n fallback for proc_create_net_single_write() rxrpc: Fix ack.bufferSize to be 0 when generating an ack drm/radeon: Add the missed acpi_put_table() to fix memory leak drm/mediatek: Modify dpi power on/off sequence. ASoC: pxa: fix null-pointer dereference in filter() regulator: core: fix unbalanced of node refcount in regulator_dev_lookup() amdgpu/pm: prevent array underflow in vega20_odn_edit_dpm_table() drm/fourcc: Add packed 10bit YUV 4:2:0 format drm/fourcc: Fix vsub/hsub for Q410 and Q401 integrity: Fix memory leakage in keyring allocation error path ima: Fix misuse of dereference of pointer in template_desc_init_fields() wifi: ath10k: Fix return value in ath10k_pci_init() mtd: lpddr2_nvm: Fix possible null-ptr-deref Input: elants_i2c - properly handle the reset GPIO when power is off media: vidtv: Fix use-after-free in vidtv_bridge_dvb_init() media: solo6x10: fix possible memory leak in solo_sysfs_init() media: platform: exynos4-is: Fix error handling in fimc_md_init() media: videobuf-dma-contig: use dma_mmap_coherent inet: add READ_ONCE(sk->sk_bound_dev_if) in inet_csk_bind_conflict() bpf: Move skb->len == 0 checks into __bpf_redirect HID: hid-sensor-custom: set fixed size for custom attributes ALSA: pcm: fix undefined behavior in bit shift for SNDRV_PCM_RATE_KNOT ALSA: seq: fix undefined behavior in bit shift for SNDRV_SEQ_FILTER_USE_EVENT regulator: core: use kfree_const() to free space conditionally clk: rockchip: Fix memory leak in rockchip_clk_register_pll() drm/amdgpu: fix pci device refcount leak bonding: fix link recovery in mode 2 when updelay is nonzero mtd: maps: pxa2xx-flash: fix memory leak in probe drbd: fix an invalid memory access caused by incorrect use of list iterator ASoC: qcom: Add checks for devm_kcalloc media: vimc: Fix wrong function called when vimc_init() fails media: imon: fix a race condition in send_packet() clk: imx: replace osc_hdmi with dummy pinctrl: pinconf-generic: add missing of_node_put() media: dvb-core: Fix ignored return value in dvb_register_frontend() media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer() media: s5p-mfc: Add variant data for MFC v7 hardware for Exynos 3250 SoC drm/tegra: Add missing clk_disable_unprepare() in tegra_dc_probe() ASoC: dt-bindings: wcd9335: fix reset line polarity in example ASoC: mediatek: mtk-btcvsd: Add checks for write and read of mtk_btcvsd_snd NFSv4.2: Clear FATTR4_WORD2_SECURITY_LABEL when done decoding NFSv4.2: Fix a memory stomp in decode_attr_security_label NFSv4.2: Fix initialisation of struct nfs4_label NFSv4: Fix a deadlock between nfs4_open_recover_helper() and delegreturn NFS: Fix an Oops in nfs_d_automount() ALSA: asihpi: fix missing pci_disable_device() wifi: iwlwifi: mvm: fix double free on tx path. ASoC: mediatek: mt8173: Fix debugfs registration for components ASoC: mediatek: mt8173: Enable IRQ when pdata is ready drm/amd/pm/smu11: BACO is supported when it's in BACO state drm/radeon: Fix PCI device refcount leak in radeon_atrm_get_bios() drm/amdgpu: Fix PCI device refcount leak in amdgpu_atrm_get_bios() ASoC: pcm512x: Fix PM disable depth imbalance in pcm512x_probe netfilter: conntrack: set icmpv6 redirects as RELATED bpf, sockmap: Fix repeated calls to sock_put() when msg has more_data bpf, sockmap: Fix data loss caused by using apply_bytes on ingress redirect bonding: uninitialized variable in bond_miimon_inspect() spi: spidev: mask SPI_CS_HIGH in SPI_IOC_RD_MODE wifi: mac80211: fix memory leak in ieee80211_if_add() wifi: cfg80211: Fix not unregister reg_pdev when load_builtin_regdb_keys() fails wifi: mt76: fix coverity overrun-call in mt76_get_txpower() regulator: core: fix module refcount leak in set_supply() clk: qcom: clk-krait: fix wrong div2 functions hsr: Add a rcu-read lock to hsr_forward_skb(). net: hsr: generate supervision frame without HSR/PRP tag hsr: Disable netpoll. hsr: Synchronize sending frames to have always incremented outgoing seq nr. hsr: Synchronize sequence number updates. configfs: fix possible memory leak in configfs_create_dir() regulator: core: fix resource leak in regulator_register() hwmon: (jc42) Convert register access and caching to regmap/regcache hwmon: (jc42) Restore the min/max/critical temperatures on resume bpf, sockmap: fix race in sock_map_free() ALSA: pcm: Set missing stop_operating flag at undoing trigger start media: saa7164: fix missing pci_disable_device() ALSA: mts64: fix possible null-ptr-defer in snd_mts64_interrupt xprtrdma: Fix regbuf data not freed in rpcrdma_req_create() SUNRPC: Fix missing release socket in rpc_sockname() NFSv4.x: Fail client initialisation if state manager thread can't run mmc: alcor: fix return value check of mmc_add_host() mmc: moxart: fix return value check of mmc_add_host() mmc: mxcmmc: fix return value check of mmc_add_host() mmc: pxamci: fix return value check of mmc_add_host() mmc: rtsx_usb_sdmmc: fix return value check of mmc_add_host() mmc: toshsd: fix return value check of mmc_add_host() mmc: vub300: fix return value check of mmc_add_host() mmc: wmt-sdmmc: fix return value check of mmc_add_host() mmc: atmel-mci: fix return value check of mmc_add_host() mmc: omap_hsmmc: fix return value check of mmc_add_host() mmc: meson-gx: fix return value check of mmc_add_host() mmc: via-sdmmc: fix return value check of mmc_add_host() mmc: wbsd: fix return value check of mmc_add_host() mmc: mmci: fix return value check of mmc_add_host() media: c8sectpfe: Add of_node_put() when breaking out of loop media: coda: Add check for dcoda_iram_alloc media: coda: Add check for kmalloc clk: samsung: Fix memory leak in _samsung_clk_register_pll() spi: spi-gpio: Don't set MOSI as an input if not 3WIRE mode wifi: rtl8xxxu: Add __packed to struct rtl8723bu_c2h wifi: rtl8xxxu: Fix the channel width reporting wifi: brcmfmac: Fix error return code in brcmf_sdio_download_firmware() blktrace: Fix output non-blktrace event when blk_classic option enabled clk: socfpga: clk-pll: Remove unused variable 'rc' clk: socfpga: use clk_hw_register for a5/c5 clk: socfpga: Fix memory leak in socfpga_gate_init() net: vmw_vsock: vmci: Check memcpy_from_msg() net: defxx: Fix missing err handling in dfx_init() net: stmmac: selftests: fix potential memleak in stmmac_test_arpoffload() drivers: net: qlcnic: Fix potential memory leak in qlcnic_sriov_init() of: overlay: fix null pointer dereferencing in find_dup_cset_node_entry() and find_dup_cset_prop() ethernet: s2io: don't call dev_kfree_skb() under spin_lock_irqsave() net: farsync: Fix kmemleak when rmmods farsync net/tunnel: wait until all sk_user_data reader finish before releasing the sock net: apple: mace: don't call dev_kfree_skb() under spin_lock_irqsave() net: apple: bmac: don't call dev_kfree_skb() under spin_lock_irqsave() net: emaclite: don't call dev_kfree_skb() under spin_lock_irqsave() net: ethernet: dnet: don't call dev_kfree_skb() under spin_lock_irqsave() hamradio: don't call dev_kfree_skb() under spin_lock_irqsave() net: amd: lance: don't call dev_kfree_skb() under spin_lock_irqsave() net: amd-xgbe: Fix logic around active and passive cables net: amd-xgbe: Check only the minimum speed for active/passive cables can: tcan4x5x: Remove invalid write in clear_interrupts net: lan9303: Fix read error execution path ntb_netdev: Use dev_kfree_skb_any() in interrupt context sctp: sysctl: make extra pointers netns aware Bluetooth: btusb: don't call kfree_skb() under spin_lock_irqsave() Bluetooth: hci_qca: don't call kfree_skb() under spin_lock_irqsave() Bluetooth: hci_ll: don't call kfree_skb() under spin_lock_irqsave() Bluetooth: hci_h5: don't call kfree_skb() under spin_lock_irqsave() Bluetooth: hci_bcsp: don't call kfree_skb() under spin_lock_irqsave() Bluetooth: hci_core: don't call kfree_skb() under spin_lock_irqsave() Bluetooth: RFCOMM: don't call kfree_skb() under spin_lock_irqsave() stmmac: fix potential division by 0 apparmor: fix a memleak in multi_transaction_new() apparmor: fix lockdep warning when removing a namespace apparmor: Fix abi check to include v8 abi crypto: sun8i-ss - use dma_addr instead u32 crypto: nitrox - avoid double free on error path in nitrox_sriov_init() scsi: core: Fix a race between scsi_done() and scsi_timeout() apparmor: Use pointer to struct aa_label for lbs_cred PCI: dwc: Fix n_fts[] array overrun RDMA/core: Fix order of nldev_exit call PCI: pci-epf-test: Register notifier if only core_init_notifier is enabled f2fs: Fix the race condition of resize flag between resizefs crypto: rockchip - do not do custom power management crypto: rockchip - do not store mode globally crypto: rockchip - add fallback for cipher crypto: rockchip - add fallback for ahash crypto: rockchip - better handle cipher key crypto: rockchip - remove non-aligned handling crypto: rockchip - delete unneeded variable initialization crypto: rockchip - rework by using crypto_engine apparmor: Fix memleak in alloc_ns() f2fs: fix normal discard process RDMA/siw: Fix immediate work request flush to completion queue RDMA/nldev: Return "-EAGAIN" if the cm_id isn't from expected port RDMA/siw: Set defined status for work completion with undefined status scsi: scsi_debug: Fix a warning in resp_write_scat() crypto: ccree - Remove debugfs when platform_driver_register failed crypto: cryptd - Use request context instead of stack for sub-request crypto: hisilicon/qm - add missing pci_dev_put() in q_num_set() RDMA/hns: Repacing 'dseg_len' by macros in fill_ext_sge_inl_data() RDMA/hns: Fix ext_sge num error when post send PCI: Check for alloc failure in pci_request_irq() RDMA/hfi: Decrease PCI device reference count in error path crypto: ccree - Make cc_debugfs_global_fini() available for module init function RDMA/hns: fix memory leak in hns_roce_alloc_mr() RDMA/rxe: Fix NULL-ptr-deref in rxe_qp_do_cleanup() when socket create failed scsi: hpsa: Fix possible memory leak in hpsa_init_one() crypto: tcrypt - Fix multibuffer skcipher speed test mem leak padata: Always leave BHs disabled when running ->parallel() padata: Fix list iterator in padata_do_serial() scsi: mpt3sas: Fix possible resource leaks in mpt3sas_transport_port_add() scsi: hpsa: Fix error handling in hpsa_add_sas_host() scsi: hpsa: Fix possible memory leak in hpsa_add_sas_device() scsi: scsi_debug: Fix a warning in resp_verify() scsi: scsi_debug: Fix a warning in resp_report_zones() scsi: fcoe: Fix possible name leak when device_register() fails scsi: scsi_debug: Fix possible name leak in sdebug_add_host_helper() scsi: ipr: Fix WARNING in ipr_init() scsi: fcoe: Fix transport not deattached when fcoe_if_init() fails scsi: snic: Fix possible UAF in snic_tgt_create() RDMA/nldev: Add checks for nla_nest_start() in fill_stat_counter_qps() f2fs: avoid victim selection from previous victim section RDMA/nldev: Fix failure to send large messages crypto: amlogic - Remove kcalloc without check crypto: omap-sham - Use pm_runtime_resume_and_get() in omap_sham_probe() riscv/mm: add arch hook arch_clear_hugepage_flags RDMA/hfi1: Fix error return code in parse_platform_config() RDMA/srp: Fix error return code in srp_parse_options() orangefs: Fix sysfs not cleanup when dev init failed RDMA/hns: Fix PBL page MTR find RDMA/hns: Fix page size cap from firmware crypto: img-hash - Fix variable dereferenced before check 'hdev->req' hwrng: amd - Fix PCI device refcount leak hwrng: geode - Fix PCI device refcount leak IB/IPoIB: Fix queue count inconsistency for PKEY child interfaces drivers: dio: fix possible memory leak in dio_init() serial: tegra: Read DMA status before terminating class: fix possible memory leak in __class_register() vfio: platform: Do not pass return buffer to ACPI _RST method uio: uio_dmem_genirq: Fix missing unlock in irq configuration uio: uio_dmem_genirq: Fix deadlock between irq config and handling usb: fotg210-udc: Fix ages old endianness issues staging: vme_user: Fix possible UAF in tsi148_dma_list_add usb: typec: Check for ops->exit instead of ops->enter in altmode_exit usb: typec: tcpci: fix of node refcount leak in tcpci_register_port() usb: typec: tipd: Fix spurious fwnode_handle_put in error path serial: amba-pl011: avoid SBSA UART accessing DMACR register serial: pl011: Do not clear RX FIFO & RX interrupt in unthrottle. serial: pch: Fix PCI device refcount leak in pch_request_dma() tty: serial: clean up stop-tx part in altera_uart_tx_chars() tty: serial: altera_uart_{r,t}x_chars() need only uart_port serial: altera_uart: fix locking in polling mode serial: sunsab: Fix error handling in sunsab_init() test_firmware: fix memory leak in test_firmware_init() misc: ocxl: fix possible name leak in ocxl_file_register_afu() ocxl: fix pci device refcount leak when calling get_function_0() misc: tifm: fix possible memory leak in tifm_7xx1_switch_media() misc: sgi-gru: fix use-after-free error in gru_set_context_option, gru_fault and gru_handle_user_call_os firmware: raspberrypi: fix possible memory leak in rpi_firmware_probe() cxl: fix possible null-ptr-deref in cxl_guest_init_afu|adapter() cxl: fix possible null-ptr-deref in cxl_pci_init_afu|adapter() iio: temperature: ltc2983: make bulk write buffer DMA-safe genirq: Add IRQF_NO_AUTOEN for request_irq/nmi() iio:imu:adis: Use IRQF_NO_AUTOEN instead of irq request then disable iio: adis: handle devices that cannot unmask the drdy pin iio: adis: stylistic changes iio:imu:adis: Move exports into IIO_ADISLIB namespace iio: adis: add '__adis_enable_irq()' implementation counter: stm32-lptimer-cnt: fix the check on arr and cmp registers update usb: roles: fix of node refcount leak in usb_role_switch_is_parent() usb: gadget: f_hid: optional SETUP/SET_REPORT mode usb: gadget: f_hid: fix f_hidg lifetime vs cdev usb: gadget: f_hid: fix refcount leak on error path drivers: mcb: fix resource leak in mcb_probe() mcb: mcb-parse: fix error handing in chameleon_parse_gdd() chardev: fix error handling in cdev_device_add() i2c: pxa-pci: fix missing pci_disable_device() on error in ce4100_i2c_probe staging: rtl8192u: Fix use after free in ieee80211_rx() staging: rtl8192e: Fix potential use-after-free in rtllib_rx_Monitor() vme: Fix error not catched in fake_init() gpiolib: Get rid of redundant 'else' gpiolib: cdev: fix NULL-pointer dereferences i2c: mux: reg: check return value after calling platform_get_resource() i2c: ismt: Fix an out-of-bounds bug in ismt_access() usb: storage: Add check for kcalloc tracing/hist: Fix issue of losting command info in error_log samples: vfio-mdev: Fix missing pci_disable_device() in mdpy_fb_probe() thermal/drivers/imx8mm_thermal: Validate temperature range fbdev: ssd1307fb: Drop optional dependency fbdev: pm2fb: fix missing pci_disable_device() fbdev: via: Fix error in via_core_init() fbdev: vermilion: decrease reference count in error path fbdev: uvesafb: Fixes an error handling path in uvesafb_probe() HSI: omap_ssi_core: fix unbalanced pm_runtime_disable() HSI: omap_ssi_core: fix possible memory leak in ssi_probe() power: supply: fix residue sysfs file in error handle route of __power_supply_register() perf trace: Return error if a system call doesn't exist perf trace: Use macro RAW_SYSCALL_ARGS_NUM to replace number perf trace: Handle failure when trace point folder is missed perf symbol: correction while adjusting symbol HSI: omap_ssi_core: Fix error handling in ssi_init() power: supply: fix null pointer dereferencing in power_supply_get_battery_info RDMA/siw: Fix pointer cast warning iommu/sun50i: Fix reset release iommu/sun50i: Consider all fault sources for reset iommu/sun50i: Fix R/W permission check iommu/sun50i: Fix flush size phy: usb: s2 WoL wakeup_count not incremented for USB->Eth devices include/uapi/linux/swab: Fix potentially missing __always_inline pwm: tegra: Improve required rate calculation dmaengine: idxd: Fix crc_val field for completion record rtc: rtc-cmos: Do not check ACPI_FADT_LOW_POWER_S0 rtc: cmos: Fix event handler registration ordering issue rtc: cmos: Fix wake alarm breakage rtc: cmos: fix build on non-ACPI platforms rtc: cmos: Call cmos_wake_setup() from cmos_do_probe() rtc: cmos: Call rtc_wake_setup() from cmos_do_probe() rtc: cmos: Eliminate forward declarations of some functions rtc: cmos: Rename ACPI-related functions rtc: cmos: Disable ACPI RTC event on removal rtc: snvs: Allow a time difference on clock register read rtc: pcf85063: Fix reading alarm iommu/amd: Fix pci device refcount leak in ppr_notifier() iommu/fsl_pamu: Fix resource leak in fsl_pamu_probe() macintosh: fix possible memory leak in macio_add_one_device() macintosh/macio-adb: check the return value of ioremap() powerpc/52xx: Fix a resource leak in an error handling path cxl: Fix refcount leak in cxl_calc_capp_routing powerpc/xmon: Enable breakpoints on 8xx powerpc/xmon: Fix -Wswitch-unreachable warning in bpt_cmds powerpc/xive: add missing iounmap() in error path in xive_spapr_populate_irq_data() kbuild: remove unneeded mkdir for external modules_install kbuild: unify modules(_install) for in-tree and external modules kbuild: refactor single builds of *.ko powerpc/perf: callchain validate kernel stack pointer bounds powerpc/83xx/mpc832x_rdb: call platform_device_put() in error case in of_fsl_spi_probe() powerpc/hv-gpci: Fix hv_gpci event list selftests/powerpc: Fix resource leaks iommu/sun50i: Remove IOMMU_DOMAIN_IDENTITY pwm: sifive: Call pwm_sifive_update_clock() while mutex is held remoteproc: sysmon: fix memory leak in qcom_add_sysmon_subdev() remoteproc: qcom_q6v5_pas: disable wakeup on probe fail or remove remoteproc: qcom_q6v5_pas: detach power domains on remove remoteproc: qcom_q6v5_pas: Fix missing of_node_put() in adsp_alloc_memory_region() powerpc/eeh: Drop redundant spinlock initialization powerpc/pseries/eeh: use correct API for error log size netfilter: flowtable: really fix NAT IPv6 offload rtc: st-lpc: Add missing clk_disable_unprepare in st_rtc_probe() rtc: pic32: Move devm_rtc_allocate_device earlier in pic32_rtc_probe() rtc: pcf85063: fix pcf85063_clkout_control NFSD: Remove spurious cb_setup_err tracepoint nfsd: under NFSv4.1, fix double svc_xprt_put on rpc_create failure net: macsec: fix net device access prior to holding a lock mISDN: hfcsusb: don't call dev_kfree_skb/kfree_skb() under spin_lock_irqsave() mISDN: hfcpci: don't call dev_kfree_skb/kfree_skb() under spin_lock_irqsave() mISDN: hfcmulti: don't call dev_kfree_skb/kfree_skb() under spin_lock_irqsave() nfc: pn533: Clear nfc_target before being used r6040: Fix kmemleak in probe and remove net: switch to storing KCOV handle directly in sk_buff net: add inline function skb_csum_is_sctp net: igc: use skb_csum_is_sctp instead of protocol check net: add a helper to avoid issues with HW TX timestamping and SO_TXTIME igc: Enhance Qbv scheduling by using first flag bit igc: Use strict cycles for Qbv scheduling igc: Add checking for basetime less than zero igc: recalculate Qbv end_time by considering cycle time igc: Lift TAPRIO schedule restriction igc: Set Qbv start_time and end_time to end_time if not being configured in GCL rtc: mxc_v2: Add missing clk_disable_unprepare() selftests: devlink: fix the fd redirect in dummy_reporter_test openvswitch: Fix flow lookup to use unmasked key skbuff: Account for tail adjustment during pull operations mailbox: zynq-ipi: fix error handling while device_register() fails net_sched: reject TCF_EM_SIMPLE case for complex ematch module rxrpc: Fix missing unlock in rxrpc_do_sendmsg() myri10ge: Fix an error handling path in myri10ge_probe() net: stream: purge sk_error_queue in sk_stream_kill_queues() rcu: Fix __this_cpu_read() lockdep warning in rcu_force_quiescent_state() arm64: make is_ttbrX_addr() noinstr-safe video: hyperv_fb: Avoid taking busy spinlock on panic path x86/hyperv: Remove unregister syscore call from Hyper-V cleanup binfmt_misc: fix shift-out-of-bounds in check_special_flags fs: jfs: fix shift-out-of-bounds in dbAllocAG udf: Avoid double brelse() in udf_rename() fs: jfs: fix shift-out-of-bounds in dbDiscardAG ACPICA: Fix error code path in acpi_ds_call_control_method() nilfs2: fix shift-out-of-bounds/overflow in nilfs_sb2_bad_offset() nilfs2: fix shift-out-of-bounds due to too large exponent of block size acct: fix potential integer overflow in encode_comp_t() hfs: fix OOB Read in __hfs_brec_find drm/etnaviv: add missing quirks for GC300 brcmfmac: return error when getting invalid max_flowrings from dongle wifi: ath9k: verify the expected usb_endpoints are present wifi: ar5523: Fix use-after-free on ar5523_cmd() timed out ASoC: codecs: rt298: Add quirk for KBL-R RVP platform ipmi: fix memleak when unload ipmi driver drm/amd/display: prevent memory leak qed (gcc13): use u16 for fid to be big enough bpf: make sure skb->len != 0 when redirecting to a tunneling device net: ethernet: ti: Fix return type of netcp_ndo_start_xmit() hamradio: baycom_epp: Fix return type of baycom_send_packet() wifi: brcmfmac: Fix potential shift-out-of-bounds in brcmf_fw_alloc_request() igb: Do not free q_vector unless new one was allocated drm/amdgpu: Fix type of second parameter in trans_msg() callback drm/amdgpu: Fix type of second parameter in odn_edit_dpm_table() callback s390/ctcm: Fix return type of ctc{mp,}m_tx() s390/netiucv: Fix return type of netiucv_tx() s390/lcs: Fix return type of lcs_start_xmit() drm/msm: Use drm_mode_copy() drm/rockchip: Use drm_mode_copy() drm/sti: Use drm_mode_copy() drivers/md/md-bitmap: check the return value of md_bitmap_get_counter() md/raid1: stop mdx_raid1 thread when raid1 array run failed drm/amd/display: fix array index out of bound error in bios parser net: add atomic_long_t to net_device_stats fields mrp: introduce active flags to prevent UAF when applicant uninit ppp: associate skb with a device at tx bpf: Prevent decl_tag from being referenced in func_proto arg ethtool: avoiding integer overflow in ethtool_phys_id() media: dvb-frontends: fix leak of memory fw media: dvbdev: adopts refcnt to avoid UAF media: dvb-usb: fix memory leak in dvb_usb_adapter_init() blk-mq: fix possible memleak when register 'hctx' failed libbpf: Avoid enum forward-declarations in public API in C++ mode regulator: core: fix use_count leakage when handling boot-on mmc: f-sdh30: Add quirks for broken timeout clock capability mmc: renesas_sdhi: better reset from HS400 mode media: si470x: Fix use-after-free in si470x_int_in_callback() clk: st: Fix memory leak in st_of_quadfs_setup() hugetlbfs: fix null-ptr-deref in hugetlbfs_parse_param() drm/fsl-dcu: Fix return type of fsl_dcu_drm_connector_mode_valid() drm/sti: Fix return type of sti_{dvo,hda,hdmi}_connector_mode_valid() orangefs: Fix kmemleak in orangefs_prepare_debugfs_help_string() orangefs: Fix kmemleak in orangefs_{kernel,client}_debug_init() hwmon: (jc42) Fix missing unlock on error in jc42_write() ALSA/ASoC: hda: move/rename snd_hdac_ext_stop_streams to hdac_stream.c ALSA: hda: add snd_hdac_stop_streams() helper ASoC: Intel: Skylake: Fix driver hang during shutdown ASoC: mediatek: mt8173-rt5650-rt5514: fix refcount leak in mt8173_rt5650_rt5514_dev_probe() ASoC: audio-graph-card: fix refcount leak of cpu_ep in __graph_for_each_link() ASoC: rockchip: pdm: Add missing clk_disable_unprepare() in rockchip_pdm_runtime_resume() ASoC: wm8994: Fix potential deadlock ASoC: rockchip: spdif: Add missing clk_disable_unprepare() in rk_spdif_runtime_resume() ASoC: rt5670: Remove unbalanced pm_runtime_put() LoadPin: Ignore the "contents" argument of the LSM hooks pstore: Switch pmsg_lock to an rt_mutex to avoid priority inversion perf debug: Set debug_peo_args and redirect_to_stderr variable to correct values in perf_quiet_option() afs: Fix lost servers_outstanding count pstore: Make sure CONFIG_PSTORE_PMSG selects CONFIG_RT_MUTEXES ima: Simplify ima_lsm_copy_rule ALSA: usb-audio: add the quirk for KT0206 device ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB ALSA: hda/hdmi: Add HP Device 0x8711 to force connect list usb: dwc3: Fix race between dwc3_set_mode and __dwc3_set_mode usb: dwc3: core: defer probe on ulpi_read_id timeout HID: wacom: Ensure bootloader PID is usable in hidraw mode HID: mcp2221: don't connect hidraw reiserfs: Add missing calls to reiserfs_security_free() iio: adc: ad_sigma_delta: do not use internal iio_dev lock iio: adc128s052: add proper .data members in adc128_of_match table regulator: core: fix deadlock on regulator enable gcov: add support for checksum field ovl: fix use inode directly in rcu-walk mode media: dvbdev: fix build warning due to comments media: dvbdev: fix refcnt bug pwm: tegra: Fix 32 bit build usb: dwc3: qcom: Fix memory leak in dwc3_qcom_interconnect_init cifs: fix oops during encryption nvme-pci: fix doorbell buffer value endianness nvme-pci: fix mempool alloc size nvme-pci: fix page size checks ata: ahci: Fix PCS quirk application for suspend nvme: fix the NVME_CMD_EFFECTS_CSE_MASK definition nvmet: don't defer passthrough commands with trivial effects to the workqueue objtool: Fix SEGFAULT powerpc/rtas: avoid device tree lookups in rtas_os_term() powerpc/rtas: avoid scheduling in rtas_os_term() HID: multitouch: fix Asus ExpertBook P2 P2451FA trackpoint HID: plantronics: Additional PIDs for double volume key presses quirk pstore/zone: Use GFP_ATOMIC to allocate zone buffer hfsplus: fix bug causing custom uid and gid being unable to be assigned with mount binfmt: Fix error return code in load_elf_fdpic_binary() ovl: Use ovl mounter's fsuid and fsgid in ovl_link() ALSA: line6: correct midi status byte when receiving data from podxt ALSA: line6: fix stack overflow in line6_midi_transmit pnode: terminate at peers of source md: fix a crash in mempool_free mm, compaction: fix fast_isolate_around() to stay within boundaries f2fs: should put a page when checking the summary info mmc: vub300: fix warning - do not call blocking ops when !TASK_RUNNING tpm: acpi: Call acpi_put_table() to fix memory leak tpm: tpm_crb: Add the missed acpi_put_table() to fix memory leak tpm: tpm_tis: Add the missed acpi_put_table() to fix memory leak SUNRPC: Don't leak netobj memory when gss_read_proxy_verf() fails kcsan: Instrument memcpy/memset/memmove with newer Clang ASoC: Intel/SOF: use set_stream() instead of set_tdm_slots() for HDAudio ASoC/SoundWire: dai: expand 'stream' concept beyond SoundWire net/mlx5e: Fix nullptr in mlx5e_tc_add_fdb_flow() wifi: rtlwifi: remove always-true condition pointed out by GCC 12 wifi: rtlwifi: 8192de: correct checking of IQK reload torture: Exclude "NOHZ tick-stop error" from fatal errors rcu: Prevent lockdep-RCU splats on lock acquisition/release net/af_packet: add VLAN support for AF_PACKET SOCK_RAW GSO net/af_packet: make sure to pull mac header media: stv0288: use explicitly signed char soc: qcom: Select REMAP_MMIO for LLCC driver kest.pl: Fix grub2 menu handling for rebooting ktest.pl minconfig: Unset configs instead of just removing them jbd2: use the correct print format arm64: dts: qcom: sdm845-db845c: correct SPI2 pins drive strength mmc: sdhci-sprd: Disable CLK_AUTO when the clock is less than 400K btrfs: fix resolving backrefs for inline extent followed by prealloc ARM: ux500: do not directly dereference __iomem arm64: dts: qcom: sdm850-lenovo-yoga-c630: correct I2C12 pins drive strength selftests: Use optional USERCFLAGS and USERLDFLAGS PM/devfreq: governor: Add a private governor_data for governor cpufreq: Init completion before kobject_init_and_add() ALSA: patch_realtek: Fix Dell Inspiron Plus 16 ALSA: hda/realtek: Apply dual codec fixup for Dell Latitude laptops dm cache: Fix ABBA deadlock between shrink_slab and dm_cache_metadata_abort dm thin: Fix ABBA deadlock between shrink_slab and dm_pool_abort_metadata dm thin: Use last transaction's pmd->root when commit failed dm thin: resume even if in FAIL mode dm thin: Fix UAF in run_timer_softirq() dm integrity: Fix UAF in dm_integrity_dtr() dm clone: Fix UAF in clone_dtr() dm cache: Fix UAF in destroy() dm cache: set needs_check flag after aborting metadata tracing/hist: Fix out-of-bound write on 'action_data.var_ref_idx' perf/core: Call LSM hook after copying perf_event_attr KVM: nVMX: Inject #GP, not #UD, if "generic" VMXON CR0/CR4 check fails x86/microcode/intel: Do not retry microcode reloading on the APs ftrace/x86: Add back ftrace_expected for ftrace bug reports x86/kprobes: Fix kprobes instruction boudary check with CONFIG_RETHUNK tracing/hist: Fix wrong return value in parse_action_params() tracing: Fix infinite loop in tracing_read_pipe on overflowed print_trace_line staging: media: tegra-video: fix chan->mipi value on error ARM: 9256/1: NWFPE: avoid compiler-generated __aeabi_uldivmod media: dvb-core: Fix double free in dvb_register_device() media: dvb-core: Fix UAF due to refcount races at releasing cifs: fix confusing debug message cifs: fix missing display of three mount options rtc: ds1347: fix value written to century register md/bitmap: Fix bitmap chunk size overflow issues efi: Add iMac Pro 2017 to uefi skip cert quirk wifi: wilc1000: sdio: fix module autoloading ASoC: jz4740-i2s: Handle independent FIFO flush bits ipmi: fix long wait in unload when IPMI disconnect mtd: spi-nor: Check for zero erase size in spi_nor_find_best_erase_type() ima: Fix a potential NULL pointer access in ima_restore_measurement_list ipmi: fix use after free in _ipmi_destroy_user() PCI: Fix pci_device_is_present() for VFs by checking PF PCI/sysfs: Fix double free in error path crypto: n2 - add missing hash statesize driver core: Fix bus_type.match() error handling in __driver_attach() iommu/amd: Fix ivrs_acpihid cmdline parsing code remoteproc: core: Do pm_relax when in RPROC_OFFLINE state parisc: led: Fix potential null-ptr-deref in start_task() device_cgroup: Roll back to original exceptions after copy failure drm/connector: send hotplug uevent on connector cleanup drm/vmwgfx: Validate the box size for the snooped cursor drm/i915/dsi: fix VBT send packet port selection for dual link DSI drm/ingenic: Fix missing platform_driver_unregister() call in ingenic_drm_init() ext4: silence the warning when evicting inode with dioread_nolock ext4: add inode table check in __ext4_get_inode_loc to aovid possible infinite loop ext4: fix use-after-free in ext4_orphan_cleanup ext4: fix undefined behavior in bit shift for ext4_check_flag_values ext4: add EXT4_IGET_BAD flag to prevent unexpected bad inode ext4: add helper to check quota inums ext4: fix bug_on in __es_tree_search caused by bad quota inode ext4: fix reserved cluster accounting in __es_remove_extent() ext4: check and assert if marking an no_delete evicting inode dirty ext4: fix bug_on in __es_tree_search caused by bad boot loader inode ext4: init quota for 'old.inode' in 'ext4_rename' ext4: fix delayed allocation bug in ext4_clu_mapped for bigalloc + inline ext4: fix corruption when online resizing a 1K bigalloc fs ext4: fix error code return to user-space in ext4_get_branch() ext4: avoid BUG_ON when creating xattrs ext4: fix inode leak in ext4_xattr_inode_create() on an error path ext4: initialize quota before expanding inode in setproject ioctl ext4: avoid unaccounted block allocation when expanding inode ext4: allocate extended attribute value in vmalloc area drm/amdgpu: handle polaris10/11 overlap asics (v2) drm/amdgpu: make display pinning more flexible (v2) ARM: renumber bits related to _TIF_WORK_MASK perf/x86/intel/uncore: Generalize I/O stacks to PMON mapping procedure perf/x86/intel/uncore: Clear attr_update properly btrfs: replace strncpy() with strscpy() x86/mce: Get rid of msr_ops x86/MCE/AMD: Clear DFR errors found in THR handler media: s5p-mfc: Fix to handle reference queue during finishing media: s5p-mfc: Clear workbit to handle error condition media: s5p-mfc: Fix in register read and write for H264 perf probe: Use dwarf_attr_integrate as generic DWARF attr accessor perf probe: Fix to get the DW_AT_decl_file and DW_AT_call_file as unsinged data x86/kprobes: Convert to insn_decode() x86/kprobes: Fix optprobe optimization check with CONFIG_RETHUNK staging: media: tegra-video: fix device_node use after free ravb: Fix "failed to switch device to config mode" message during unbind riscv/stacktrace: Fix stack output without ra on the stack top riscv: stacktrace: Fixup ftrace_graph_ret_addr retp argument ext4: goto right label 'failed_mount3a' ext4: correct inconsistent error msg in nojournal mode mm/highmem: Lift memcpy_[to|from]_page to core ext4: use memcpy_to_page() in pagecache_write() fs: ext4: initialize fsdata in pagecache_write() ext4: move functions in super.c ext4: simplify ext4 error translation ext4: fix various seppling typos ext4: fix leaking uninitialized memory in fast-commit journal ext4: use kmemdup() to replace kmalloc + memcpy mbcache: don't reclaim used entries mbcache: add functions to delete entry if unused ext4: remove EA inode entry from mbcache on inode eviction ext4: unindent codeblock in ext4_xattr_block_set() ext4: fix race when reusing xattr blocks mbcache: automatically delete entries from cache on freeing ext4: fix deadlock due to mbcache entry corruption SUNRPC: ensure the matching upcall is in-flight upon downcall bpf: pull before calling skb_postpull_rcsum() drm/panfrost: Fix GEM handle creation ref-counting vmxnet3: correctly report csum_level for encapsulated packet veth: Fix race with AF_XDP exposing old or uninitialized descriptors nfsd: shut down the NFSv4 state objects before the filecache net: hns3: add interrupts re-initialization while doing VF FLR net: sched: fix memory leak in tcindex_set_parms qlcnic: prevent ->dcb use-after-free on qlcnic_dcb_enable() failure nfc: Fix potential resource leaks vhost/vsock: Fix error handling in vhost_vsock_init() vringh: fix range used in iotlb_translate() vhost: fix range used in translate_desc() net/mlx5: Add forgotten cleanup calls into mlx5_init_once() error path net/mlx5: Avoid recovery in probe flows net/mlx5e: IPoIB, Don't allow CQE compression to be turned on by default net/mlx5e: Fix hw mtu initializing at XDP SQ allocation net: amd-xgbe: add missed tasklet_kill net: phy: xgmiitorgmii: Fix refcount leak in xgmiitorgmii_probe RDMA/mlx5: Fix validation of max_rd_atomic caps for DC drm/meson: Reduce the FIFO lines held when AFBC is not used filelock: new helper: vfs_inode_has_locks ceph: switch to vfs_inode_has_locks() to fix file lock bug gpio: sifive: Fix refcount leak in sifive_gpio_probe net: sched: atm: dont intepret cls results when asked to drop net: sched: cbq: dont intepret cls results when asked to drop netfilter: ipset: fix hash:net,port,net hang with /0 subnet netfilter: ipset: Rework long task execution when adding/deleting entries perf tools: Fix resources leak in perf_data__open_dir() drivers/net/bonding/bond_3ad: return when there's no aggregator usb: rndis_host: Secure rndis_query check against int overflow drm/i915: unpin on error in intel_vgpu_shadow_mm_pin() caif: fix memory leak in cfctrl_linkup_request() udf: Fix extension of the last extent in the file ASoC: Intel: bytcr_rt5640: Add quirk for the Advantech MICA-071 tablet nvme: fix multipath crash caused by flush request when blktrace is enabled x86/bugs: Flush IBP in ib_prctl_set() nfsd: fix handling of readdir in v4root vs. mount upcall timeout fbdev: matroxfb: G200eW: Increase max memory from 1 MB to 16 MB riscv: uaccess: fix type of 0 variable on error in get_user() drm/i915/gvt: fix gvt debugfs destroy drm/i915/gvt: fix vgpu debugfs clean in remove ext4: don't allow journal inode to have encrypt flag selftests: set the BUILD variable to absolute path hfs/hfsplus: use WARN_ON for sanity check hfs/hfsplus: avoid WARN_ON() for sanity check, use proper error handling mbcache: Avoid nesting of cache->c_list_lock under bit locks efi: random: combine bootloader provided RNG seed with RNG protocol output io_uring: Fix unsigned 'res' comparison with zero in io_fixup_rw_res() parisc: Align parisc MADV_XXX constants with all other architectures ext4: disable fast-commit of encrypted dir operations ext4: don't set up encryption key during jbd2 transaction fsl_lpuart: Don't enable interrupts too early serial: fixup backport of "serial: Deassert Transmit Enable on probe in driver-specific way" mptcp: mark ops structures as ro_after_init mptcp: remove MPTCP 'ifdef' in TCP SYN cookies mptcp: dedicated request sock for subflow in v6 mptcp: use proper req destructor for IPv6 net: sched: disallow noqueue for qdisc classes net/ulp: prevent ULP without clone op from entering the LISTEN status ALSA: pcm: Move rwsem lock inside snd_ctl_elem_read to prevent UAF ALSA: hda/hdmi: Add a HP device 0x8715 to force connect list ALSA: hda - Enable headset mic on another Dell laptop with ALC3254 Linux 5.10.163 Change-Id: I9026971760be8484f1e1fa607f9f91243cc87785 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
1164 lines
28 KiB
C
1164 lines
28 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* SuperH Timer Support - CMT
|
|
*
|
|
* Copyright (C) 2008 Magnus Damm
|
|
*/
|
|
|
|
#include <linux/clk.h>
|
|
#include <linux/clockchips.h>
|
|
#include <linux/clocksource.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/err.h>
|
|
#include <linux/init.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/io.h>
|
|
#include <linux/iopoll.h>
|
|
#include <linux/ioport.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/pm_domain.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/sh_timer.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/spinlock.h>
|
|
|
|
#ifdef CONFIG_SUPERH
|
|
#include <asm/platform_early.h>
|
|
#endif
|
|
|
|
struct sh_cmt_device;
|
|
|
|
/*
|
|
* The CMT comes in 5 different identified flavours, depending not only on the
|
|
* SoC but also on the particular instance. The following table lists the main
|
|
* characteristics of those flavours.
|
|
*
|
|
* 16B 32B 32B-F 48B R-Car Gen2
|
|
* -----------------------------------------------------------------------------
|
|
* Channels 2 1/4 1 6 2/8
|
|
* Control Width 16 16 16 16 32
|
|
* Counter Width 16 32 32 32/48 32/48
|
|
* Shared Start/Stop Y Y Y Y N
|
|
*
|
|
* The r8a73a4 / R-Car Gen2 version has a per-channel start/stop register
|
|
* located in the channel registers block. All other versions have a shared
|
|
* start/stop register located in the global space.
|
|
*
|
|
* Channels are indexed from 0 to N-1 in the documentation. The channel index
|
|
* infers the start/stop bit position in the control register and the channel
|
|
* registers block address. Some CMT instances have a subset of channels
|
|
* available, in which case the index in the documentation doesn't match the
|
|
* "real" index as implemented in hardware. This is for instance the case with
|
|
* CMT0 on r8a7740, which is a 32-bit variant with a single channel numbered 0
|
|
* in the documentation but using start/stop bit 5 and having its registers
|
|
* block at 0x60.
|
|
*
|
|
* Similarly CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing 32-bit
|
|
* channels only, is a 48-bit gen2 CMT with the 48-bit channels unavailable.
|
|
*/
|
|
|
|
enum sh_cmt_model {
|
|
SH_CMT_16BIT,
|
|
SH_CMT_32BIT,
|
|
SH_CMT_48BIT,
|
|
SH_CMT0_RCAR_GEN2,
|
|
SH_CMT1_RCAR_GEN2,
|
|
};
|
|
|
|
struct sh_cmt_info {
|
|
enum sh_cmt_model model;
|
|
|
|
unsigned int channels_mask;
|
|
|
|
unsigned long width; /* 16 or 32 bit version of hardware block */
|
|
u32 overflow_bit;
|
|
u32 clear_bits;
|
|
|
|
/* callbacks for CMSTR and CMCSR access */
|
|
u32 (*read_control)(void __iomem *base, unsigned long offs);
|
|
void (*write_control)(void __iomem *base, unsigned long offs,
|
|
u32 value);
|
|
|
|
/* callbacks for CMCNT and CMCOR access */
|
|
u32 (*read_count)(void __iomem *base, unsigned long offs);
|
|
void (*write_count)(void __iomem *base, unsigned long offs, u32 value);
|
|
};
|
|
|
|
struct sh_cmt_channel {
|
|
struct sh_cmt_device *cmt;
|
|
|
|
unsigned int index; /* Index in the documentation */
|
|
unsigned int hwidx; /* Real hardware index */
|
|
|
|
void __iomem *iostart;
|
|
void __iomem *ioctrl;
|
|
|
|
unsigned int timer_bit;
|
|
unsigned long flags;
|
|
u32 match_value;
|
|
u32 next_match_value;
|
|
u32 max_match_value;
|
|
raw_spinlock_t lock;
|
|
struct clock_event_device ced;
|
|
struct clocksource cs;
|
|
u64 total_cycles;
|
|
bool cs_enabled;
|
|
};
|
|
|
|
struct sh_cmt_device {
|
|
struct platform_device *pdev;
|
|
|
|
const struct sh_cmt_info *info;
|
|
|
|
void __iomem *mapbase;
|
|
struct clk *clk;
|
|
unsigned long rate;
|
|
unsigned int reg_delay;
|
|
|
|
raw_spinlock_t lock; /* Protect the shared start/stop register */
|
|
|
|
struct sh_cmt_channel *channels;
|
|
unsigned int num_channels;
|
|
unsigned int hw_channels;
|
|
|
|
bool has_clockevent;
|
|
bool has_clocksource;
|
|
};
|
|
|
|
#define SH_CMT16_CMCSR_CMF (1 << 7)
|
|
#define SH_CMT16_CMCSR_CMIE (1 << 6)
|
|
#define SH_CMT16_CMCSR_CKS8 (0 << 0)
|
|
#define SH_CMT16_CMCSR_CKS32 (1 << 0)
|
|
#define SH_CMT16_CMCSR_CKS128 (2 << 0)
|
|
#define SH_CMT16_CMCSR_CKS512 (3 << 0)
|
|
#define SH_CMT16_CMCSR_CKS_MASK (3 << 0)
|
|
|
|
#define SH_CMT32_CMCSR_CMF (1 << 15)
|
|
#define SH_CMT32_CMCSR_OVF (1 << 14)
|
|
#define SH_CMT32_CMCSR_WRFLG (1 << 13)
|
|
#define SH_CMT32_CMCSR_STTF (1 << 12)
|
|
#define SH_CMT32_CMCSR_STPF (1 << 11)
|
|
#define SH_CMT32_CMCSR_SSIE (1 << 10)
|
|
#define SH_CMT32_CMCSR_CMS (1 << 9)
|
|
#define SH_CMT32_CMCSR_CMM (1 << 8)
|
|
#define SH_CMT32_CMCSR_CMTOUT_IE (1 << 7)
|
|
#define SH_CMT32_CMCSR_CMR_NONE (0 << 4)
|
|
#define SH_CMT32_CMCSR_CMR_DMA (1 << 4)
|
|
#define SH_CMT32_CMCSR_CMR_IRQ (2 << 4)
|
|
#define SH_CMT32_CMCSR_CMR_MASK (3 << 4)
|
|
#define SH_CMT32_CMCSR_DBGIVD (1 << 3)
|
|
#define SH_CMT32_CMCSR_CKS_RCLK8 (4 << 0)
|
|
#define SH_CMT32_CMCSR_CKS_RCLK32 (5 << 0)
|
|
#define SH_CMT32_CMCSR_CKS_RCLK128 (6 << 0)
|
|
#define SH_CMT32_CMCSR_CKS_RCLK1 (7 << 0)
|
|
#define SH_CMT32_CMCSR_CKS_MASK (7 << 0)
|
|
|
|
static u32 sh_cmt_read16(void __iomem *base, unsigned long offs)
|
|
{
|
|
return ioread16(base + (offs << 1));
|
|
}
|
|
|
|
static u32 sh_cmt_read32(void __iomem *base, unsigned long offs)
|
|
{
|
|
return ioread32(base + (offs << 2));
|
|
}
|
|
|
|
static void sh_cmt_write16(void __iomem *base, unsigned long offs, u32 value)
|
|
{
|
|
iowrite16(value, base + (offs << 1));
|
|
}
|
|
|
|
static void sh_cmt_write32(void __iomem *base, unsigned long offs, u32 value)
|
|
{
|
|
iowrite32(value, base + (offs << 2));
|
|
}
|
|
|
|
static const struct sh_cmt_info sh_cmt_info[] = {
|
|
[SH_CMT_16BIT] = {
|
|
.model = SH_CMT_16BIT,
|
|
.width = 16,
|
|
.overflow_bit = SH_CMT16_CMCSR_CMF,
|
|
.clear_bits = ~SH_CMT16_CMCSR_CMF,
|
|
.read_control = sh_cmt_read16,
|
|
.write_control = sh_cmt_write16,
|
|
.read_count = sh_cmt_read16,
|
|
.write_count = sh_cmt_write16,
|
|
},
|
|
[SH_CMT_32BIT] = {
|
|
.model = SH_CMT_32BIT,
|
|
.width = 32,
|
|
.overflow_bit = SH_CMT32_CMCSR_CMF,
|
|
.clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF),
|
|
.read_control = sh_cmt_read16,
|
|
.write_control = sh_cmt_write16,
|
|
.read_count = sh_cmt_read32,
|
|
.write_count = sh_cmt_write32,
|
|
},
|
|
[SH_CMT_48BIT] = {
|
|
.model = SH_CMT_48BIT,
|
|
.channels_mask = 0x3f,
|
|
.width = 32,
|
|
.overflow_bit = SH_CMT32_CMCSR_CMF,
|
|
.clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF),
|
|
.read_control = sh_cmt_read32,
|
|
.write_control = sh_cmt_write32,
|
|
.read_count = sh_cmt_read32,
|
|
.write_count = sh_cmt_write32,
|
|
},
|
|
[SH_CMT0_RCAR_GEN2] = {
|
|
.model = SH_CMT0_RCAR_GEN2,
|
|
.channels_mask = 0x60,
|
|
.width = 32,
|
|
.overflow_bit = SH_CMT32_CMCSR_CMF,
|
|
.clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF),
|
|
.read_control = sh_cmt_read32,
|
|
.write_control = sh_cmt_write32,
|
|
.read_count = sh_cmt_read32,
|
|
.write_count = sh_cmt_write32,
|
|
},
|
|
[SH_CMT1_RCAR_GEN2] = {
|
|
.model = SH_CMT1_RCAR_GEN2,
|
|
.channels_mask = 0xff,
|
|
.width = 32,
|
|
.overflow_bit = SH_CMT32_CMCSR_CMF,
|
|
.clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF),
|
|
.read_control = sh_cmt_read32,
|
|
.write_control = sh_cmt_write32,
|
|
.read_count = sh_cmt_read32,
|
|
.write_count = sh_cmt_write32,
|
|
},
|
|
};
|
|
|
|
#define CMCSR 0 /* channel register */
|
|
#define CMCNT 1 /* channel register */
|
|
#define CMCOR 2 /* channel register */
|
|
|
|
#define CMCLKE 0x1000 /* CLK Enable Register (R-Car Gen2) */
|
|
|
|
static inline u32 sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
|
|
{
|
|
if (ch->iostart)
|
|
return ch->cmt->info->read_control(ch->iostart, 0);
|
|
else
|
|
return ch->cmt->info->read_control(ch->cmt->mapbase, 0);
|
|
}
|
|
|
|
static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, u32 value)
|
|
{
|
|
u32 old_value = sh_cmt_read_cmstr(ch);
|
|
|
|
if (value != old_value) {
|
|
if (ch->iostart) {
|
|
ch->cmt->info->write_control(ch->iostart, 0, value);
|
|
udelay(ch->cmt->reg_delay);
|
|
} else {
|
|
ch->cmt->info->write_control(ch->cmt->mapbase, 0, value);
|
|
udelay(ch->cmt->reg_delay);
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
|
|
{
|
|
return ch->cmt->info->read_control(ch->ioctrl, CMCSR);
|
|
}
|
|
|
|
static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch, u32 value)
|
|
{
|
|
u32 old_value = sh_cmt_read_cmcsr(ch);
|
|
|
|
if (value != old_value) {
|
|
ch->cmt->info->write_control(ch->ioctrl, CMCSR, value);
|
|
udelay(ch->cmt->reg_delay);
|
|
}
|
|
}
|
|
|
|
static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
|
|
{
|
|
return ch->cmt->info->read_count(ch->ioctrl, CMCNT);
|
|
}
|
|
|
|
static inline int sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value)
|
|
{
|
|
/* Tests showed that we need to wait 3 clocks here */
|
|
unsigned int cmcnt_delay = DIV_ROUND_UP(3 * ch->cmt->reg_delay, 2);
|
|
u32 reg;
|
|
|
|
if (ch->cmt->info->model > SH_CMT_16BIT) {
|
|
int ret = read_poll_timeout_atomic(sh_cmt_read_cmcsr, reg,
|
|
!(reg & SH_CMT32_CMCSR_WRFLG),
|
|
1, cmcnt_delay, false, ch);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
ch->cmt->info->write_count(ch->ioctrl, CMCNT, value);
|
|
udelay(cmcnt_delay);
|
|
return 0;
|
|
}
|
|
|
|
static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch, u32 value)
|
|
{
|
|
u32 old_value = ch->cmt->info->read_count(ch->ioctrl, CMCOR);
|
|
|
|
if (value != old_value) {
|
|
ch->cmt->info->write_count(ch->ioctrl, CMCOR, value);
|
|
udelay(ch->cmt->reg_delay);
|
|
}
|
|
}
|
|
|
|
static u32 sh_cmt_get_counter(struct sh_cmt_channel *ch, u32 *has_wrapped)
|
|
{
|
|
u32 v1, v2, v3;
|
|
u32 o1, o2;
|
|
|
|
o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->info->overflow_bit;
|
|
|
|
/* Make sure the timer value is stable. Stolen from acpi_pm.c */
|
|
do {
|
|
o2 = o1;
|
|
v1 = sh_cmt_read_cmcnt(ch);
|
|
v2 = sh_cmt_read_cmcnt(ch);
|
|
v3 = sh_cmt_read_cmcnt(ch);
|
|
o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->info->overflow_bit;
|
|
} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
|
|
|| (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
|
|
|
|
*has_wrapped = o1;
|
|
return v2;
|
|
}
|
|
|
|
static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start)
|
|
{
|
|
unsigned long flags;
|
|
u32 value;
|
|
|
|
/* start stop register shared by multiple timer channels */
|
|
raw_spin_lock_irqsave(&ch->cmt->lock, flags);
|
|
value = sh_cmt_read_cmstr(ch);
|
|
|
|
if (start)
|
|
value |= 1 << ch->timer_bit;
|
|
else
|
|
value &= ~(1 << ch->timer_bit);
|
|
|
|
sh_cmt_write_cmstr(ch, value);
|
|
raw_spin_unlock_irqrestore(&ch->cmt->lock, flags);
|
|
}
|
|
|
|
static int sh_cmt_enable(struct sh_cmt_channel *ch)
|
|
{
|
|
int ret;
|
|
|
|
pm_runtime_get_sync(&ch->cmt->pdev->dev);
|
|
dev_pm_syscore_device(&ch->cmt->pdev->dev, true);
|
|
|
|
/* enable clock */
|
|
ret = clk_enable(ch->cmt->clk);
|
|
if (ret) {
|
|
dev_err(&ch->cmt->pdev->dev, "ch%u: cannot enable clock\n",
|
|
ch->index);
|
|
goto err0;
|
|
}
|
|
|
|
/* make sure channel is disabled */
|
|
sh_cmt_start_stop_ch(ch, 0);
|
|
|
|
/* configure channel, periodic mode and maximum timeout */
|
|
if (ch->cmt->info->width == 16) {
|
|
sh_cmt_write_cmcsr(ch, SH_CMT16_CMCSR_CMIE |
|
|
SH_CMT16_CMCSR_CKS512);
|
|
} else {
|
|
sh_cmt_write_cmcsr(ch, SH_CMT32_CMCSR_CMM |
|
|
SH_CMT32_CMCSR_CMTOUT_IE |
|
|
SH_CMT32_CMCSR_CMR_IRQ |
|
|
SH_CMT32_CMCSR_CKS_RCLK8);
|
|
}
|
|
|
|
sh_cmt_write_cmcor(ch, 0xffffffff);
|
|
ret = sh_cmt_write_cmcnt(ch, 0);
|
|
|
|
if (ret || sh_cmt_read_cmcnt(ch)) {
|
|
dev_err(&ch->cmt->pdev->dev, "ch%u: cannot clear CMCNT\n",
|
|
ch->index);
|
|
ret = -ETIMEDOUT;
|
|
goto err1;
|
|
}
|
|
|
|
/* enable channel */
|
|
sh_cmt_start_stop_ch(ch, 1);
|
|
return 0;
|
|
err1:
|
|
/* stop clock */
|
|
clk_disable(ch->cmt->clk);
|
|
|
|
err0:
|
|
return ret;
|
|
}
|
|
|
|
static void sh_cmt_disable(struct sh_cmt_channel *ch)
|
|
{
|
|
/* disable channel */
|
|
sh_cmt_start_stop_ch(ch, 0);
|
|
|
|
/* disable interrupts in CMT block */
|
|
sh_cmt_write_cmcsr(ch, 0);
|
|
|
|
/* stop clock */
|
|
clk_disable(ch->cmt->clk);
|
|
|
|
dev_pm_syscore_device(&ch->cmt->pdev->dev, false);
|
|
pm_runtime_put(&ch->cmt->pdev->dev);
|
|
}
|
|
|
|
/* private flags */
|
|
#define FLAG_CLOCKEVENT (1 << 0)
|
|
#define FLAG_CLOCKSOURCE (1 << 1)
|
|
#define FLAG_REPROGRAM (1 << 2)
|
|
#define FLAG_SKIPEVENT (1 << 3)
|
|
#define FLAG_IRQCONTEXT (1 << 4)
|
|
|
|
static void sh_cmt_clock_event_program_verify(struct sh_cmt_channel *ch,
|
|
int absolute)
|
|
{
|
|
u32 value = ch->next_match_value;
|
|
u32 new_match;
|
|
u32 delay = 0;
|
|
u32 now = 0;
|
|
u32 has_wrapped;
|
|
|
|
now = sh_cmt_get_counter(ch, &has_wrapped);
|
|
ch->flags |= FLAG_REPROGRAM; /* force reprogram */
|
|
|
|
if (has_wrapped) {
|
|
/* we're competing with the interrupt handler.
|
|
* -> let the interrupt handler reprogram the timer.
|
|
* -> interrupt number two handles the event.
|
|
*/
|
|
ch->flags |= FLAG_SKIPEVENT;
|
|
return;
|
|
}
|
|
|
|
if (absolute)
|
|
now = 0;
|
|
|
|
do {
|
|
/* reprogram the timer hardware,
|
|
* but don't save the new match value yet.
|
|
*/
|
|
new_match = now + value + delay;
|
|
if (new_match > ch->max_match_value)
|
|
new_match = ch->max_match_value;
|
|
|
|
sh_cmt_write_cmcor(ch, new_match);
|
|
|
|
now = sh_cmt_get_counter(ch, &has_wrapped);
|
|
if (has_wrapped && (new_match > ch->match_value)) {
|
|
/* we are changing to a greater match value,
|
|
* so this wrap must be caused by the counter
|
|
* matching the old value.
|
|
* -> first interrupt reprograms the timer.
|
|
* -> interrupt number two handles the event.
|
|
*/
|
|
ch->flags |= FLAG_SKIPEVENT;
|
|
break;
|
|
}
|
|
|
|
if (has_wrapped) {
|
|
/* we are changing to a smaller match value,
|
|
* so the wrap must be caused by the counter
|
|
* matching the new value.
|
|
* -> save programmed match value.
|
|
* -> let isr handle the event.
|
|
*/
|
|
ch->match_value = new_match;
|
|
break;
|
|
}
|
|
|
|
/* be safe: verify hardware settings */
|
|
if (now < new_match) {
|
|
/* timer value is below match value, all good.
|
|
* this makes sure we won't miss any match events.
|
|
* -> save programmed match value.
|
|
* -> let isr handle the event.
|
|
*/
|
|
ch->match_value = new_match;
|
|
break;
|
|
}
|
|
|
|
/* the counter has reached a value greater
|
|
* than our new match value. and since the
|
|
* has_wrapped flag isn't set we must have
|
|
* programmed a too close event.
|
|
* -> increase delay and retry.
|
|
*/
|
|
if (delay)
|
|
delay <<= 1;
|
|
else
|
|
delay = 1;
|
|
|
|
if (!delay)
|
|
dev_warn(&ch->cmt->pdev->dev, "ch%u: too long delay\n",
|
|
ch->index);
|
|
|
|
} while (delay);
|
|
}
|
|
|
|
static void __sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta)
|
|
{
|
|
if (delta > ch->max_match_value)
|
|
dev_warn(&ch->cmt->pdev->dev, "ch%u: delta out of range\n",
|
|
ch->index);
|
|
|
|
ch->next_match_value = delta;
|
|
sh_cmt_clock_event_program_verify(ch, 0);
|
|
}
|
|
|
|
static void sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta)
|
|
{
|
|
unsigned long flags;
|
|
|
|
raw_spin_lock_irqsave(&ch->lock, flags);
|
|
__sh_cmt_set_next(ch, delta);
|
|
raw_spin_unlock_irqrestore(&ch->lock, flags);
|
|
}
|
|
|
|
static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
|
|
{
|
|
struct sh_cmt_channel *ch = dev_id;
|
|
|
|
/* clear flags */
|
|
sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) &
|
|
ch->cmt->info->clear_bits);
|
|
|
|
/* update clock source counter to begin with if enabled
|
|
* the wrap flag should be cleared by the timer specific
|
|
* isr before we end up here.
|
|
*/
|
|
if (ch->flags & FLAG_CLOCKSOURCE)
|
|
ch->total_cycles += ch->match_value + 1;
|
|
|
|
if (!(ch->flags & FLAG_REPROGRAM))
|
|
ch->next_match_value = ch->max_match_value;
|
|
|
|
ch->flags |= FLAG_IRQCONTEXT;
|
|
|
|
if (ch->flags & FLAG_CLOCKEVENT) {
|
|
if (!(ch->flags & FLAG_SKIPEVENT)) {
|
|
if (clockevent_state_oneshot(&ch->ced)) {
|
|
ch->next_match_value = ch->max_match_value;
|
|
ch->flags |= FLAG_REPROGRAM;
|
|
}
|
|
|
|
ch->ced.event_handler(&ch->ced);
|
|
}
|
|
}
|
|
|
|
ch->flags &= ~FLAG_SKIPEVENT;
|
|
|
|
if (ch->flags & FLAG_REPROGRAM) {
|
|
ch->flags &= ~FLAG_REPROGRAM;
|
|
sh_cmt_clock_event_program_verify(ch, 1);
|
|
|
|
if (ch->flags & FLAG_CLOCKEVENT)
|
|
if ((clockevent_state_shutdown(&ch->ced))
|
|
|| (ch->match_value == ch->next_match_value))
|
|
ch->flags &= ~FLAG_REPROGRAM;
|
|
}
|
|
|
|
ch->flags &= ~FLAG_IRQCONTEXT;
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
static int sh_cmt_start(struct sh_cmt_channel *ch, unsigned long flag)
|
|
{
|
|
int ret = 0;
|
|
unsigned long flags;
|
|
|
|
raw_spin_lock_irqsave(&ch->lock, flags);
|
|
|
|
if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
|
|
ret = sh_cmt_enable(ch);
|
|
|
|
if (ret)
|
|
goto out;
|
|
ch->flags |= flag;
|
|
|
|
/* setup timeout if no clockevent */
|
|
if (ch->cmt->num_channels == 1 &&
|
|
flag == FLAG_CLOCKSOURCE && (!(ch->flags & FLAG_CLOCKEVENT)))
|
|
__sh_cmt_set_next(ch, ch->max_match_value);
|
|
out:
|
|
raw_spin_unlock_irqrestore(&ch->lock, flags);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void sh_cmt_stop(struct sh_cmt_channel *ch, unsigned long flag)
|
|
{
|
|
unsigned long flags;
|
|
unsigned long f;
|
|
|
|
raw_spin_lock_irqsave(&ch->lock, flags);
|
|
|
|
f = ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE);
|
|
ch->flags &= ~flag;
|
|
|
|
if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
|
|
sh_cmt_disable(ch);
|
|
|
|
/* adjust the timeout to maximum if only clocksource left */
|
|
if ((flag == FLAG_CLOCKEVENT) && (ch->flags & FLAG_CLOCKSOURCE))
|
|
__sh_cmt_set_next(ch, ch->max_match_value);
|
|
|
|
raw_spin_unlock_irqrestore(&ch->lock, flags);
|
|
}
|
|
|
|
static struct sh_cmt_channel *cs_to_sh_cmt(struct clocksource *cs)
|
|
{
|
|
return container_of(cs, struct sh_cmt_channel, cs);
|
|
}
|
|
|
|
static u64 sh_cmt_clocksource_read(struct clocksource *cs)
|
|
{
|
|
struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
|
|
u32 has_wrapped;
|
|
|
|
if (ch->cmt->num_channels == 1) {
|
|
unsigned long flags;
|
|
u64 value;
|
|
u32 raw;
|
|
|
|
raw_spin_lock_irqsave(&ch->lock, flags);
|
|
value = ch->total_cycles;
|
|
raw = sh_cmt_get_counter(ch, &has_wrapped);
|
|
|
|
if (unlikely(has_wrapped))
|
|
raw += ch->match_value + 1;
|
|
raw_spin_unlock_irqrestore(&ch->lock, flags);
|
|
|
|
return value + raw;
|
|
}
|
|
|
|
return sh_cmt_get_counter(ch, &has_wrapped);
|
|
}
|
|
|
|
static int sh_cmt_clocksource_enable(struct clocksource *cs)
|
|
{
|
|
int ret;
|
|
struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
|
|
|
|
WARN_ON(ch->cs_enabled);
|
|
|
|
ch->total_cycles = 0;
|
|
|
|
ret = sh_cmt_start(ch, FLAG_CLOCKSOURCE);
|
|
if (!ret)
|
|
ch->cs_enabled = true;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void sh_cmt_clocksource_disable(struct clocksource *cs)
|
|
{
|
|
struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
|
|
|
|
WARN_ON(!ch->cs_enabled);
|
|
|
|
sh_cmt_stop(ch, FLAG_CLOCKSOURCE);
|
|
ch->cs_enabled = false;
|
|
}
|
|
|
|
static void sh_cmt_clocksource_suspend(struct clocksource *cs)
|
|
{
|
|
struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
|
|
|
|
if (!ch->cs_enabled)
|
|
return;
|
|
|
|
sh_cmt_stop(ch, FLAG_CLOCKSOURCE);
|
|
dev_pm_genpd_suspend(&ch->cmt->pdev->dev);
|
|
}
|
|
|
|
static void sh_cmt_clocksource_resume(struct clocksource *cs)
|
|
{
|
|
struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
|
|
|
|
if (!ch->cs_enabled)
|
|
return;
|
|
|
|
dev_pm_genpd_resume(&ch->cmt->pdev->dev);
|
|
sh_cmt_start(ch, FLAG_CLOCKSOURCE);
|
|
}
|
|
|
|
static int sh_cmt_register_clocksource(struct sh_cmt_channel *ch,
|
|
const char *name)
|
|
{
|
|
struct clocksource *cs = &ch->cs;
|
|
|
|
cs->name = name;
|
|
cs->rating = 125;
|
|
cs->read = sh_cmt_clocksource_read;
|
|
cs->enable = sh_cmt_clocksource_enable;
|
|
cs->disable = sh_cmt_clocksource_disable;
|
|
cs->suspend = sh_cmt_clocksource_suspend;
|
|
cs->resume = sh_cmt_clocksource_resume;
|
|
cs->mask = CLOCKSOURCE_MASK(ch->cmt->info->width);
|
|
cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
|
|
|
|
dev_info(&ch->cmt->pdev->dev, "ch%u: used as clock source\n",
|
|
ch->index);
|
|
|
|
clocksource_register_hz(cs, ch->cmt->rate);
|
|
return 0;
|
|
}
|
|
|
|
static struct sh_cmt_channel *ced_to_sh_cmt(struct clock_event_device *ced)
|
|
{
|
|
return container_of(ced, struct sh_cmt_channel, ced);
|
|
}
|
|
|
|
static void sh_cmt_clock_event_start(struct sh_cmt_channel *ch, int periodic)
|
|
{
|
|
sh_cmt_start(ch, FLAG_CLOCKEVENT);
|
|
|
|
if (periodic)
|
|
sh_cmt_set_next(ch, ((ch->cmt->rate + HZ/2) / HZ) - 1);
|
|
else
|
|
sh_cmt_set_next(ch, ch->max_match_value);
|
|
}
|
|
|
|
static int sh_cmt_clock_event_shutdown(struct clock_event_device *ced)
|
|
{
|
|
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
|
|
|
|
sh_cmt_stop(ch, FLAG_CLOCKEVENT);
|
|
return 0;
|
|
}
|
|
|
|
static int sh_cmt_clock_event_set_state(struct clock_event_device *ced,
|
|
int periodic)
|
|
{
|
|
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
|
|
|
|
/* deal with old setting first */
|
|
if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced))
|
|
sh_cmt_stop(ch, FLAG_CLOCKEVENT);
|
|
|
|
dev_info(&ch->cmt->pdev->dev, "ch%u: used for %s clock events\n",
|
|
ch->index, periodic ? "periodic" : "oneshot");
|
|
sh_cmt_clock_event_start(ch, periodic);
|
|
return 0;
|
|
}
|
|
|
|
static int sh_cmt_clock_event_set_oneshot(struct clock_event_device *ced)
|
|
{
|
|
return sh_cmt_clock_event_set_state(ced, 0);
|
|
}
|
|
|
|
static int sh_cmt_clock_event_set_periodic(struct clock_event_device *ced)
|
|
{
|
|
return sh_cmt_clock_event_set_state(ced, 1);
|
|
}
|
|
|
|
static int sh_cmt_clock_event_next(unsigned long delta,
|
|
struct clock_event_device *ced)
|
|
{
|
|
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
|
|
|
|
BUG_ON(!clockevent_state_oneshot(ced));
|
|
if (likely(ch->flags & FLAG_IRQCONTEXT))
|
|
ch->next_match_value = delta - 1;
|
|
else
|
|
sh_cmt_set_next(ch, delta - 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void sh_cmt_clock_event_suspend(struct clock_event_device *ced)
|
|
{
|
|
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
|
|
|
|
dev_pm_genpd_suspend(&ch->cmt->pdev->dev);
|
|
clk_unprepare(ch->cmt->clk);
|
|
}
|
|
|
|
static void sh_cmt_clock_event_resume(struct clock_event_device *ced)
|
|
{
|
|
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
|
|
|
|
clk_prepare(ch->cmt->clk);
|
|
dev_pm_genpd_resume(&ch->cmt->pdev->dev);
|
|
}
|
|
|
|
static int sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
|
|
const char *name)
|
|
{
|
|
struct clock_event_device *ced = &ch->ced;
|
|
int irq;
|
|
int ret;
|
|
|
|
irq = platform_get_irq(ch->cmt->pdev, ch->index);
|
|
if (irq < 0)
|
|
return irq;
|
|
|
|
ret = request_irq(irq, sh_cmt_interrupt,
|
|
IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
|
|
dev_name(&ch->cmt->pdev->dev), ch);
|
|
if (ret) {
|
|
dev_err(&ch->cmt->pdev->dev, "ch%u: failed to request irq %d\n",
|
|
ch->index, irq);
|
|
return ret;
|
|
}
|
|
|
|
ced->name = name;
|
|
ced->features = CLOCK_EVT_FEAT_PERIODIC;
|
|
ced->features |= CLOCK_EVT_FEAT_ONESHOT;
|
|
ced->rating = 125;
|
|
ced->cpumask = cpu_possible_mask;
|
|
ced->set_next_event = sh_cmt_clock_event_next;
|
|
ced->set_state_shutdown = sh_cmt_clock_event_shutdown;
|
|
ced->set_state_periodic = sh_cmt_clock_event_set_periodic;
|
|
ced->set_state_oneshot = sh_cmt_clock_event_set_oneshot;
|
|
ced->suspend = sh_cmt_clock_event_suspend;
|
|
ced->resume = sh_cmt_clock_event_resume;
|
|
|
|
/* TODO: calculate good shift from rate and counter bit width */
|
|
ced->shift = 32;
|
|
ced->mult = div_sc(ch->cmt->rate, NSEC_PER_SEC, ced->shift);
|
|
ced->max_delta_ns = clockevent_delta2ns(ch->max_match_value, ced);
|
|
ced->max_delta_ticks = ch->max_match_value;
|
|
ced->min_delta_ns = clockevent_delta2ns(0x1f, ced);
|
|
ced->min_delta_ticks = 0x1f;
|
|
|
|
dev_info(&ch->cmt->pdev->dev, "ch%u: used for clock events\n",
|
|
ch->index);
|
|
clockevents_register_device(ced);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sh_cmt_register(struct sh_cmt_channel *ch, const char *name,
|
|
bool clockevent, bool clocksource)
|
|
{
|
|
int ret;
|
|
|
|
if (clockevent) {
|
|
ch->cmt->has_clockevent = true;
|
|
ret = sh_cmt_register_clockevent(ch, name);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
if (clocksource) {
|
|
ch->cmt->has_clocksource = true;
|
|
sh_cmt_register_clocksource(ch, name);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
|
|
unsigned int hwidx, bool clockevent,
|
|
bool clocksource, struct sh_cmt_device *cmt)
|
|
{
|
|
u32 value;
|
|
int ret;
|
|
|
|
/* Skip unused channels. */
|
|
if (!clockevent && !clocksource)
|
|
return 0;
|
|
|
|
ch->cmt = cmt;
|
|
ch->index = index;
|
|
ch->hwidx = hwidx;
|
|
ch->timer_bit = hwidx;
|
|
|
|
/*
|
|
* Compute the address of the channel control register block. For the
|
|
* timers with a per-channel start/stop register, compute its address
|
|
* as well.
|
|
*/
|
|
switch (cmt->info->model) {
|
|
case SH_CMT_16BIT:
|
|
ch->ioctrl = cmt->mapbase + 2 + ch->hwidx * 6;
|
|
break;
|
|
case SH_CMT_32BIT:
|
|
case SH_CMT_48BIT:
|
|
ch->ioctrl = cmt->mapbase + 0x10 + ch->hwidx * 0x10;
|
|
break;
|
|
case SH_CMT0_RCAR_GEN2:
|
|
case SH_CMT1_RCAR_GEN2:
|
|
ch->iostart = cmt->mapbase + ch->hwidx * 0x100;
|
|
ch->ioctrl = ch->iostart + 0x10;
|
|
ch->timer_bit = 0;
|
|
|
|
/* Enable the clock supply to the channel */
|
|
value = ioread32(cmt->mapbase + CMCLKE);
|
|
value |= BIT(hwidx);
|
|
iowrite32(value, cmt->mapbase + CMCLKE);
|
|
break;
|
|
}
|
|
|
|
if (cmt->info->width == (sizeof(ch->max_match_value) * 8))
|
|
ch->max_match_value = ~0;
|
|
else
|
|
ch->max_match_value = (1 << cmt->info->width) - 1;
|
|
|
|
ch->match_value = ch->max_match_value;
|
|
raw_spin_lock_init(&ch->lock);
|
|
|
|
ret = sh_cmt_register(ch, dev_name(&cmt->pdev->dev),
|
|
clockevent, clocksource);
|
|
if (ret) {
|
|
dev_err(&cmt->pdev->dev, "ch%u: registration failed\n",
|
|
ch->index);
|
|
return ret;
|
|
}
|
|
ch->cs_enabled = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sh_cmt_map_memory(struct sh_cmt_device *cmt)
|
|
{
|
|
struct resource *mem;
|
|
|
|
mem = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 0);
|
|
if (!mem) {
|
|
dev_err(&cmt->pdev->dev, "failed to get I/O memory\n");
|
|
return -ENXIO;
|
|
}
|
|
|
|
cmt->mapbase = ioremap(mem->start, resource_size(mem));
|
|
if (cmt->mapbase == NULL) {
|
|
dev_err(&cmt->pdev->dev, "failed to remap I/O memory\n");
|
|
return -ENXIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct platform_device_id sh_cmt_id_table[] = {
|
|
{ "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] },
|
|
{ "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] },
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
|
|
|
|
static const struct of_device_id sh_cmt_of_table[] __maybe_unused = {
|
|
{
|
|
/* deprecated, preserved for backward compatibility */
|
|
.compatible = "renesas,cmt-48",
|
|
.data = &sh_cmt_info[SH_CMT_48BIT]
|
|
},
|
|
{
|
|
/* deprecated, preserved for backward compatibility */
|
|
.compatible = "renesas,cmt-48-gen2",
|
|
.data = &sh_cmt_info[SH_CMT0_RCAR_GEN2]
|
|
},
|
|
{
|
|
.compatible = "renesas,r8a7740-cmt1",
|
|
.data = &sh_cmt_info[SH_CMT_48BIT]
|
|
},
|
|
{
|
|
.compatible = "renesas,sh73a0-cmt1",
|
|
.data = &sh_cmt_info[SH_CMT_48BIT]
|
|
},
|
|
{
|
|
.compatible = "renesas,rcar-gen2-cmt0",
|
|
.data = &sh_cmt_info[SH_CMT0_RCAR_GEN2]
|
|
},
|
|
{
|
|
.compatible = "renesas,rcar-gen2-cmt1",
|
|
.data = &sh_cmt_info[SH_CMT1_RCAR_GEN2]
|
|
},
|
|
{
|
|
.compatible = "renesas,rcar-gen3-cmt0",
|
|
.data = &sh_cmt_info[SH_CMT0_RCAR_GEN2]
|
|
},
|
|
{
|
|
.compatible = "renesas,rcar-gen3-cmt1",
|
|
.data = &sh_cmt_info[SH_CMT1_RCAR_GEN2]
|
|
},
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(of, sh_cmt_of_table);
|
|
|
|
static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
|
|
{
|
|
unsigned int mask, i;
|
|
unsigned long rate;
|
|
int ret;
|
|
|
|
cmt->pdev = pdev;
|
|
raw_spin_lock_init(&cmt->lock);
|
|
|
|
if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
|
|
cmt->info = of_device_get_match_data(&pdev->dev);
|
|
cmt->hw_channels = cmt->info->channels_mask;
|
|
} else if (pdev->dev.platform_data) {
|
|
struct sh_timer_config *cfg = pdev->dev.platform_data;
|
|
const struct platform_device_id *id = pdev->id_entry;
|
|
|
|
cmt->info = (const struct sh_cmt_info *)id->driver_data;
|
|
cmt->hw_channels = cfg->channels_mask;
|
|
} else {
|
|
dev_err(&cmt->pdev->dev, "missing platform data\n");
|
|
return -ENXIO;
|
|
}
|
|
|
|
/* Get hold of clock. */
|
|
cmt->clk = clk_get(&cmt->pdev->dev, "fck");
|
|
if (IS_ERR(cmt->clk)) {
|
|
dev_err(&cmt->pdev->dev, "cannot get clock\n");
|
|
return PTR_ERR(cmt->clk);
|
|
}
|
|
|
|
ret = clk_prepare(cmt->clk);
|
|
if (ret < 0)
|
|
goto err_clk_put;
|
|
|
|
/* Determine clock rate. */
|
|
ret = clk_enable(cmt->clk);
|
|
if (ret < 0)
|
|
goto err_clk_unprepare;
|
|
|
|
rate = clk_get_rate(cmt->clk);
|
|
if (!rate) {
|
|
ret = -EINVAL;
|
|
goto err_clk_disable;
|
|
}
|
|
|
|
/* We shall wait 2 input clks after register writes */
|
|
if (cmt->info->model >= SH_CMT_48BIT)
|
|
cmt->reg_delay = DIV_ROUND_UP(2UL * USEC_PER_SEC, rate);
|
|
cmt->rate = rate / (cmt->info->width == 16 ? 512 : 8);
|
|
|
|
/* Map the memory resource(s). */
|
|
ret = sh_cmt_map_memory(cmt);
|
|
if (ret < 0)
|
|
goto err_clk_disable;
|
|
|
|
/* Allocate and setup the channels. */
|
|
cmt->num_channels = hweight8(cmt->hw_channels);
|
|
cmt->channels = kcalloc(cmt->num_channels, sizeof(*cmt->channels),
|
|
GFP_KERNEL);
|
|
if (cmt->channels == NULL) {
|
|
ret = -ENOMEM;
|
|
goto err_unmap;
|
|
}
|
|
|
|
/*
|
|
* Use the first channel as a clock event device and the second channel
|
|
* as a clock source. If only one channel is available use it for both.
|
|
*/
|
|
for (i = 0, mask = cmt->hw_channels; i < cmt->num_channels; ++i) {
|
|
unsigned int hwidx = ffs(mask) - 1;
|
|
bool clocksource = i == 1 || cmt->num_channels == 1;
|
|
bool clockevent = i == 0;
|
|
|
|
ret = sh_cmt_setup_channel(&cmt->channels[i], i, hwidx,
|
|
clockevent, clocksource, cmt);
|
|
if (ret < 0)
|
|
goto err_unmap;
|
|
|
|
mask &= ~(1 << hwidx);
|
|
}
|
|
|
|
clk_disable(cmt->clk);
|
|
|
|
platform_set_drvdata(pdev, cmt);
|
|
|
|
return 0;
|
|
|
|
err_unmap:
|
|
kfree(cmt->channels);
|
|
iounmap(cmt->mapbase);
|
|
err_clk_disable:
|
|
clk_disable(cmt->clk);
|
|
err_clk_unprepare:
|
|
clk_unprepare(cmt->clk);
|
|
err_clk_put:
|
|
clk_put(cmt->clk);
|
|
return ret;
|
|
}
|
|
|
|
static int sh_cmt_probe(struct platform_device *pdev)
|
|
{
|
|
struct sh_cmt_device *cmt = platform_get_drvdata(pdev);
|
|
int ret;
|
|
|
|
if (!is_sh_early_platform_device(pdev)) {
|
|
pm_runtime_set_active(&pdev->dev);
|
|
pm_runtime_enable(&pdev->dev);
|
|
}
|
|
|
|
if (cmt) {
|
|
dev_info(&pdev->dev, "kept as earlytimer\n");
|
|
goto out;
|
|
}
|
|
|
|
cmt = kzalloc(sizeof(*cmt), GFP_KERNEL);
|
|
if (cmt == NULL)
|
|
return -ENOMEM;
|
|
|
|
ret = sh_cmt_setup(cmt, pdev);
|
|
if (ret) {
|
|
kfree(cmt);
|
|
pm_runtime_idle(&pdev->dev);
|
|
return ret;
|
|
}
|
|
if (is_sh_early_platform_device(pdev))
|
|
return 0;
|
|
|
|
out:
|
|
if (cmt->has_clockevent || cmt->has_clocksource)
|
|
pm_runtime_irq_safe(&pdev->dev);
|
|
else
|
|
pm_runtime_idle(&pdev->dev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sh_cmt_remove(struct platform_device *pdev)
|
|
{
|
|
return -EBUSY; /* cannot unregister clockevent and clocksource */
|
|
}
|
|
|
|
static struct platform_driver sh_cmt_device_driver = {
|
|
.probe = sh_cmt_probe,
|
|
.remove = sh_cmt_remove,
|
|
.driver = {
|
|
.name = "sh_cmt",
|
|
.of_match_table = of_match_ptr(sh_cmt_of_table),
|
|
},
|
|
.id_table = sh_cmt_id_table,
|
|
};
|
|
|
|
static int __init sh_cmt_init(void)
|
|
{
|
|
return platform_driver_register(&sh_cmt_device_driver);
|
|
}
|
|
|
|
static void __exit sh_cmt_exit(void)
|
|
{
|
|
platform_driver_unregister(&sh_cmt_device_driver);
|
|
}
|
|
|
|
#ifdef CONFIG_SUPERH
|
|
sh_early_platform_init("earlytimer", &sh_cmt_device_driver);
|
|
#endif
|
|
|
|
subsys_initcall(sh_cmt_init);
|
|
module_exit(sh_cmt_exit);
|
|
|
|
MODULE_AUTHOR("Magnus Damm");
|
|
MODULE_DESCRIPTION("SuperH CMT Timer Driver");
|
|
MODULE_LICENSE("GPL v2");
|