-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmVmHpsACgkQONu9yGCS aT5uvw//SzcE0GImnHnfeN7iXtpFE9O0fhTxsjZCi8/HTXmGWPtQgWscd9y81bAd EHBVr456GXqd6KuIF+03g/r/FYinwWqK375meLfaybw1vSBP+fZttrEGqz6nTnYD yqOxw2bqgz8Xjp63UeNHD6mifpBvVtuAvzrfO1E2Ie/U1OU2uKdjRRv0iijKNeWN liOYTXaddIkVfZR0z6dVTl0hb5dPWsxNmF77kfVpKz4ALIHJcO13DlUuKtQz6Sb6 0ElmJpuonHuUxHzb8e9LLsFy3IvbBqomSscwcd0tngtdUTzhMYFIZLjg2+WQ9Ovq raMGqvS/bKsoyoTBNKL83QB2NyXQb3vkfL0NgLsq9IwDl+r96mP9ctANYGwSjhND o/4sa/fbMFzeInA8Rzh7i56RCNstOBKApJPhBzWuY0f/6b1BZpvZaONyX3fFksWO dMeYT16GgO4lhQXnG3O6mtDT8eoZ1fLf7ZdGEZ2NktcOzXYelNc4aXJke7qdlIop CVxM+Ur+juj+DJymo59a6baXjEgIROdHq83N3CZwetGviPHneGqgYc0K7ETtA33H sH/0KGYAT8SzzjMlnXB0lpjp68WViJfzzo9Wxdf2aDZbL3SdI14GPKMUeDqqeSyU 8bB2Hb4ItccRFW9RriiE3BPGnLGu7PDTkn5TgXDG/bDX54Cb5DQ= =YPzI -----END PGP SIGNATURE----- Merge 6.1.64 into android14-6.1-lts Changes in 6.1.64 locking/ww_mutex/test: Fix potential workqueue corruption lib/generic-radix-tree.c: Don't overflow in peek() perf/core: Bail out early if the request AUX area is out of bound srcu: Fix srcu_struct node grpmask overflow on 64-bit systems selftests/lkdtm: Disable CONFIG_UBSAN_TRAP in test config clocksource/drivers/timer-imx-gpt: Fix potential memory leak clocksource/drivers/timer-atmel-tcb: Fix initialization on SAM9 hardware smp,csd: Throw an error if a CSD lock is stuck for too long cpu/hotplug: Don't offline the last non-isolated CPU workqueue: Provide one lock class key per work_on_cpu() callsite x86/mm: Drop the 4 MB restriction on minimal NUMA node memory size wifi: plfxlc: fix clang-specific fortify warning wifi: mac80211_hwsim: fix clang-specific fortify warning wifi: mac80211: don't return unset power in ieee80211_get_tx_power() atl1c: Work around the DMA RX overflow issue bpf: Detect IP == ksym.end as part of BPF program wifi: ath9k: fix clang-specific fortify warnings wifi: ath10k: fix clang-specific fortify warning net: annotate data-races around sk->sk_tx_queue_mapping net: annotate data-races around sk->sk_dst_pending_confirm wifi: ath10k: Don't touch the CE interrupt registers after power up vsock: read from socket's error queue bpf: Ensure proper register state printing for cond jumps Bluetooth: btusb: Add date->evt_skb is NULL check Bluetooth: Fix double free in hci_conn_cleanup ACPI: EC: Add quirk for HP 250 G7 Notebook PC tsnep: Fix tsnep_request_irq() format-overflow warning platform/chrome: kunit: initialize lock for fake ec_dev platform/x86: thinkpad_acpi: Add battery quirk for Thinkpad X120e drm/gma500: Fix call trace when psb_gem_mm_init() fails drm/komeda: drop all currently held locks if deadlock happens drm/amdgpu: not to save bo in the case of RAS err_event_athub drm/amdkfd: Fix a race condition of vram buffer unref in svm code drm/amd: Update `update_pcie_parameters` functions to use uint8_t arguments drm/amd/display: use full update for clip size increase of large plane source string.h: add array-wrappers for (v)memdup_user() kernel: kexec: copy user-array safely kernel: watch_queue: copy user-array safely drm_lease.c: copy user-array safely drm: vmwgfx_surface.c: copy user-array safely drm/msm/dp: skip validity check for DP CTS EDID checksum drm/amd: Fix UBSAN array-index-out-of-bounds for SMU7 drm/amd: Fix UBSAN array-index-out-of-bounds for Polaris and Tonga drm/amdgpu: Fix potential null pointer derefernce drm/panel: fix a possible null pointer dereference drm/panel/panel-tpo-tpg110: fix a possible null pointer dereference drm/radeon: fix a possible null pointer dereference drm/amdgpu/vkms: fix a possible null pointer dereference drm/panel: st7703: Pick different reset sequence drm/amdkfd: Fix shift out-of-bounds issue drm/amdgpu: Fix a null pointer access when the smc_rreg pointer is NULL arm64: dts: ls208xa: use a pseudo-bus to constrain usb dma size selftests/efivarfs: create-read: fix a resource leak ASoC: soc-card: Add storage for PCI SSID ASoC: SOF: Pass PCI SSID to machine driver crypto: pcrypt - Fix hungtask for PADATA_RESET ASoC: SOF: ipc4: handle EXCEPTION_CAUGHT notification from firmware RDMA/hfi1: Use FIELD_GET() to extract Link Width scsi: hisi_sas: Set debugfs_dir pointer to NULL after removing debugfs scsi: ibmvfc: Remove BUG_ON in the case of an empty event pool fs/jfs: Add check for negative db_l2nbperpage fs/jfs: Add validity check for db_maxag and db_agpref jfs: fix array-index-out-of-bounds in dbFindLeaf jfs: fix array-index-out-of-bounds in diAlloc HID: lenovo: Detect quirk-free fw on cptkbd and stop applying workaround ARM: 9320/1: fix stack depot IRQ stack filter ALSA: hda: Fix possible null-ptr-deref when assigning a stream PCI: tegra194: Use FIELD_GET()/FIELD_PREP() with Link Width fields PCI: mvebu: Use FIELD_PREP() with Link Width atm: iphase: Do PCI error checks on own line PCI: Do error check on own line to split long "if" conditions scsi: libfc: Fix potential NULL pointer dereference in fc_lport_ptp_setup() PCI: Use FIELD_GET() to extract Link Width PCI: Extract ATS disabling to a helper function PCI: Disable ATS for specific Intel IPU E2000 devices misc: pci_endpoint_test: Add Device ID for R-Car S4-8 PCIe controller PCI: Use FIELD_GET() in Sapphire RX 5600 XT Pulse quirk ASoC: Intel: soc-acpi-cht: Add Lenovo Yoga Tab 3 Pro YT3-X90 quirk crypto: hisilicon/qm - prevent soft lockup in receive loop HID: Add quirk for Dell Pro Wireless Keyboard and Mouse KM5221W exfat: support handle zero-size directory mfd: intel-lpss: Add Intel Lunar Lake-M PCI IDs iio: adc: stm32-adc: harden against NULL pointer deref in stm32_adc_probe() thunderbolt: Apply USB 3.x bandwidth quirk only in software connection manager tty: vcc: Add check for kstrdup() in vcc_probe() usb: dwc3: core: configure TX/RX threshold for DWC3_IP soundwire: dmi-quirks: update HP Omen match f2fs: fix error handling of __get_node_page usb: gadget: f_ncm: Always set current gadget in ncm_bind() 9p/trans_fd: Annotate data-racy writes to file::f_flags 9p: v9fs_listxattr: fix %s null argument warning i3c: mipi-i3c-hci: Fix out of bounds access in hci_dma_irq_handler i2c: fix memleak in i2c_new_client_device() i2c: sun6i-p2wi: Prevent potential division by zero virtio-blk: fix implicit overflow on virtio_max_dma_size i3c: master: mipi-i3c-hci: Fix a kernel panic for accessing DAT_data. media: gspca: cpia1: shift-out-of-bounds in set_flicker media: vivid: avoid integer overflow gfs2: ignore negated quota changes gfs2: fix an oops in gfs2_permission media: cobalt: Use FIELD_GET() to extract Link Width media: ccs: Fix driver quirk struct documentation media: imon: fix access to invalid resource for the second interface drm/amd/display: Avoid NULL dereference of timing generator kgdb: Flush console before entering kgdb on panic i2c: dev: copy userspace array safely ASoC: ti: omap-mcbsp: Fix runtime PM underflow warnings drm/qxl: prevent memory leak ALSA: hda/realtek: Add quirk for ASUS UX7602ZM drm/amdgpu: fix software pci_unplug on some chips pwm: Fix double shift bug mtd: rawnand: tegra: add missing check for platform_get_irq() wifi: iwlwifi: Use FW rate for non-data frames sched/core: Optimize in_task() and in_interrupt() a bit SUNRPC: ECONNRESET might require a rebind mtd: rawnand: intel: check return value of devm_kasprintf() mtd: rawnand: meson: check return value of devm_kasprintf() NFSv4.1: fix handling NFS4ERR_DELAY when testing for session trunking SUNRPC: Add an IS_ERR() check back to where it was NFSv4.1: fix SP4_MACH_CRED protection for pnfs IO SUNRPC: Fix RPC client cleaned up the freed pipefs dentries gfs2: Silence "suspicious RCU usage in gfs2_permission" warning vhost-vdpa: fix use after free in vhost_vdpa_probe() net: set SOCK_RCU_FREE before inserting socket into hashtable ipvlan: add ipvlan_route_v6_outbound() helper tty: Fix uninit-value access in ppp_sync_receive() net: hns3: fix add VLAN fail issue net: hns3: add barrier in vf mailbox reply process net: hns3: fix incorrect capability bit display for copper port net: hns3: fix out-of-bounds access may occur when coalesce info is read via debugfs net: hns3: fix variable may not initialized problem in hns3_init_mac_addr() net: hns3: fix VF reset fail issue net: hns3: fix VF wrong speed and duplex issue tipc: Fix kernel-infoleak due to uninitialized TLV value net: mvneta: fix calls to page_pool_get_stats ppp: limit MRU to 64K xen/events: fix delayed eoi list handling ptp: annotate data-race around q->head and q->tail bonding: stop the device in bond_setup_by_slave() net: ethernet: cortina: Fix max RX frame define net: ethernet: cortina: Handle large frames net: ethernet: cortina: Fix MTU max setting af_unix: fix use-after-free in unix_stream_read_actor() netfilter: nf_conntrack_bridge: initialize err to 0 netfilter: nf_tables: fix pointer math issue in nft_byteorder_eval() net: stmmac: fix rx budget limit check net: stmmac: avoid rx queue overrun net/mlx5e: fix double free of encap_header net/mlx5e: fix double free of encap_header in update funcs net/mlx5e: Fix pedit endianness net/mlx5e: Reduce the size of icosq_str net/mlx5e: Check return value of snprintf writing to fw_version buffer net/mlx5e: Check return value of snprintf writing to fw_version buffer for representors macvlan: Don't propagate promisc change to lower dev in passthru tools/power/turbostat: Fix a knl bug tools/power/turbostat: Enable the C-state Pre-wake printing cifs: spnego: add ';' in HOST_KEY_LEN cifs: fix check of rc in function generate_smb3signingkey i915/perf: Fix NULL deref bugs with drm_dbg() calls media: venus: hfi: add checks to perform sanity on queue pointers perf intel-pt: Fix async branch flags powerpc/perf: Fix disabling BHRB and instruction sampling randstruct: Fix gcc-plugin performance mode to stay in group bpf: Fix check_stack_write_fixed_off() to correctly spill imm bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END scsi: mpt3sas: Fix loop logic scsi: megaraid_sas: Increase register read retry rount from 3 to 30 for selected registers scsi: qla2xxx: Fix system crash due to bad pointer access crypto: x86/sha - load modules based on CPU features x86/cpu/hygon: Fix the CPU topology evaluation for real KVM: x86: hyper-v: Don't auto-enable stimer on write from user-space KVM: x86: Ignore MSR_AMD64_TW_CFG access KVM: x86: Clear bit12 of ICR after APIC-write VM-exit audit: don't take task_lock() in audit_exe_compare() code path audit: don't WARN_ON_ONCE(!current->mm) in audit_exe_compare() proc: sysctl: prevent aliased sysctls from getting passed to init tty/sysrq: replace smp_processor_id() with get_cpu() tty: serial: meson: fix hard LOCKUP on crtscts mode hvc/xen: fix console unplug hvc/xen: fix error path in xen_hvc_init() to always register frontend driver hvc/xen: fix event channel handling for secondary consoles PCI/sysfs: Protect driver's D3cold preference from user space mm/damon/sysfs: remove requested targets when online-commit inputs mm/damon/sysfs: update monitoring target regions for online input commit watchdog: move softlockup_panic back to early_param mm/damon/lru_sort: avoid divide-by-zero in hot threshold calculation mm/damon/ops-common: avoid divide-by-zero during region hotness calculation mm/damon: implement a function for max nr_accesses safe calculation mm/damon/sysfs: check error from damon_sysfs_update_target() ACPI: resource: Do IRQ override on TongFang GMxXGxx regmap: Ensure range selector registers are updated after cache sync wifi: ath11k: fix temperature event locking wifi: ath11k: fix dfs radar event locking wifi: ath11k: fix htt pktlog locking wifi: ath11k: fix gtk offload status event locking mmc: meson-gx: Remove setting of CMD_CFG_ERROR genirq/generic_chip: Make irq_remove_generic_chip() irqdomain aware KEYS: trusted: tee: Refactor register SHM usage KEYS: trusted: Rollback init_trusted() consistently PCI: keystone: Don't discard .remove() callback PCI: keystone: Don't discard .probe() callback arm64: Restrict CPU_BIG_ENDIAN to GNU as or LLVM IAS 15.x or newer parisc/pdc: Add width field to struct pdc_model parisc/power: Add power soft-off when running on qemu clk: socfpga: Fix undefined behavior bug in struct stratix10_clock_data clk: qcom: ipq8074: drop the CLK_SET_RATE_PARENT flag from PLL clocks clk: qcom: ipq6018: drop the CLK_SET_RATE_PARENT flag from PLL clocks ksmbd: handle malformed smb1 message ksmbd: fix slab out of bounds write in smb_inherit_dacl() mmc: vub300: fix an error code mmc: sdhci_am654: fix start loop index for TAP value parsing mmc: Add quirk MMC_QUIRK_BROKEN_CACHE_FLUSH for Micron eMMC Q2J54A PCI/ASPM: Fix L1 substate handling in aspm_attr_store_common() PCI: kirin: Don't discard .remove() callback PCI: exynos: Don't discard .remove() callback wifi: wilc1000: use vmm_table as array in wilc struct svcrdma: Drop connection after an RDMA Read error rcu/tree: Defer setting of jiffies during stall reset arm64: dts: qcom: ipq6018: Fix hwlock index for SMEM PM: hibernate: Use __get_safe_page() rather than touching the list PM: hibernate: Clean up sync_read handling in snapshot_write_next() rcu: kmemleak: Ignore kmemleak false positives when RCU-freeing objects btrfs: don't arbitrarily slow down delalloc if we're committing arm64: dts: qcom: ipq8074: Fix hwlock index for SMEM firmware: qcom_scm: use 64-bit calling convention only when client is 64-bit ACPI: FPDT: properly handle invalid FPDT subtables arm64: dts: qcom: ipq6018: Fix tcsr_mutex register size mfd: qcom-spmi-pmic: Fix reference leaks in revid helper mfd: qcom-spmi-pmic: Fix revid implementation ima: annotate iint mutex to avoid lockdep false positive warnings ima: detect changes to the backing overlay file netfilter: nf_tables: remove catchall element in GC sync path netfilter: nf_tables: split async and sync catchall in two functions selftests/resctrl: Remove duplicate feature check from CMT test selftests/resctrl: Move _GNU_SOURCE define into Makefile selftests/resctrl: Reduce failures due to outliers in MBA/MBM tests hid: lenovo: Resend all settings on reset_resume for compact keyboards ASoC: codecs: wsa-macro: fix uninitialized stack variables with name prefix jbd2: fix potential data lost in recovering journal raced with synchronizing fs bdev quota: explicitly forbid quota files from being encrypted kernel/reboot: emergency_restart: Set correct system_state i2c: core: Run atomic i2c xfer when !preemptible tracing: Have the user copy of synthetic event address use correct context driver core: Release all resources during unbind before updating device links mcb: fix error handling for different scenarios when parsing dmaengine: stm32-mdma: correct desc prep when channel running s390/cmma: fix detection of DAT pages mm/cma: use nth_page() in place of direct struct page manipulation mm/memory_hotplug: use pfn math in place of direct struct page manipulation mtd: cfi_cmdset_0001: Byte swap OTP info i3c: master: cdns: Fix reading status register i3c: master: svc: fix race condition in ibi work thread i3c: master: svc: fix wrong data return when IBI happen during start frame i3c: master: svc: fix ibi may not return mandatory data byte i3c: master: svc: fix check wrong status register in irq handler i3c: master: svc: fix SDA keep low when polling IBIWON timeout happen parisc: Prevent booting 64-bit kernels on PA1.x machines parisc/pgtable: Do not drop upper 5 address bits of physical address parisc/power: Fix power soft-off when running on qemu xhci: Enable RPM on controllers that support low-power states fs: add ctime accessors infrastructure smb3: fix creating FIFOs when mounting with "sfu" mount option smb3: fix touch -h of symlink smb3: fix caching of ctime on setxattr smb: client: fix use-after-free bug in cifs_debug_data_proc_show() smb: client: fix potential deadlock when releasing mids cifs: reconnect helper should set reconnect for the right channel cifs: force interface update before a fresh session setup cifs: do not reset chan_max if multichannel is not supported at mount xfs: recovery should not clear di_flushiter unconditionally btrfs: zoned: wait for data BG to be finished on direct IO allocation ALSA: info: Fix potential deadlock at disconnection ALSA: hda/realtek: Enable Mute LED on HP 255 G8 ALSA: hda/realtek - Add Dell ALC295 to pin fall back table ALSA: hda/realtek - Enable internal speaker of ASUS K6500ZC ALSA: hda/realtek: Enable Mute LED on HP 255 G10 ALSA: hda/realtek: Add quirks for HP Laptops pmdomain: bcm: bcm2835-power: check if the ASB register is equal to enable pmdomain: imx: Make imx pgc power domain also set the fwnode cpufreq: stats: Fix buffer overflow detection in trans_stats() clk: visconti: remove unused visconti_pll_provider::regmap clk: visconti: Fix undefined behavior bug in struct visconti_pll_provider Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x0cb8:0xc559 bluetooth: Add device 0bda:887b to device tables bluetooth: Add device 13d3:3571 to device tables Bluetooth: btusb: Add RTW8852BE device 13d3:3570 to device tables Bluetooth: btusb: Add 0bda:b85b for Fn-Link RTL8852BE drm/amd/display: enable dsc_clk even if dsc_pg disabled cxl/region: Validate region mode vs decoder mode cxl/region: Cleanup target list on attach error cxl/region: Move region-position validation to a helper cxl/region: Do not try to cleanup after cxl_region_setup_targets() fails i3c: master: svc: add NACK check after start byte sent i3c: master: svc: fix random hot join failure since timeout error cxl: Unify debug messages when calling devm_cxl_add_port() cxl/mem: Move devm_cxl_add_endpoint() from cxl_core to cxl_mem tools/testing/cxl: Define a fixed volatile configuration to parse cxl/region: Fix x1 root-decoder granularity calculations Revert ncsi: Propagate carrier gain/loss events to the NCSI controller Revert "i2c: pxa: move to generic GPIO recovery" lsm: fix default return value for vm_enough_memory lsm: fix default return value for inode_getsecctx sbsa_gwdt: Calculate timeout with 64-bit math i2c: designware: Disable TX_EMPTY irq while waiting for block length byte s390/ap: fix AP bus crash on early config change callback invocation net: ethtool: Fix documentation of ethtool_sprintf() net: dsa: lan9303: consequently nested-lock physical MDIO net: phylink: initialize carrier state at creation i2c: i801: fix potential race in i801_block_transaction_byte_by_byte f2fs: do not return EFSCORRUPTED, but try to run online repair f2fs: avoid format-overflow warning media: lirc: drop trailing space from scancode transmit media: sharp: fix sharp encoding media: venus: hfi_parser: Add check to keep the number of codecs within range media: venus: hfi: fix the check to handle session buffer requirement media: venus: hfi: add checks to handle capabilities from firmware media: ccs: Correctly initialise try compose rectangle drm/mediatek/dp: fix memory leak on ->get_edid callback audio detection drm/mediatek/dp: fix memory leak on ->get_edid callback error path dm-verity: don't use blocking calls from tasklets nfsd: fix file memleak on client_opens_release LoongArch: Mark __percpu functions as always inline riscv: mm: Update the comment of CONFIG_PAGE_OFFSET riscv: correct pt_level name via pgtable_l5/4_enabled riscv: kprobes: allow writing to x0 mmc: sdhci-pci-gli: A workaround to allow GL9750 to enter ASPM L1.2 mm: fix for negative counter: nr_file_hugepages mm: kmem: drop __GFP_NOFAIL when allocating objcg vectors mptcp: deal with large GSO size mptcp: add validity check for sending RM_ADDR mptcp: fix setsockopt(IP_TOS) subflow locking r8169: fix network lost after resume on DASH systems r8169: add handling DASH when DASH is disabled mmc: sdhci-pci-gli: GL9750: Mask the replay timer timeout of AER media: qcom: camss: Fix pm_domain_on sequence in probe media: qcom: camss: Fix vfe_get() error jump media: qcom: camss: Fix VFE-17x vfe_disable_output() media: qcom: camss: Fix VFE-480 vfe_disable_output() media: qcom: camss: Fix missing vfe_lite clocks check media: qcom: camss: Fix invalid clock enable bit disjunction media: qcom: camss: Fix csid-gen2 for test pattern generator Revert "net: r8169: Disable multicast filter for RTL8168H and RTL8107E" ext4: apply umask if ACL support is disabled ext4: correct offset of gdb backup in non meta_bg group to update_backups ext4: mark buffer new if it is unwritten to avoid stale data exposure ext4: correct return value of ext4_convert_meta_bg ext4: correct the start block of counting reserved clusters ext4: remove gdb backup copy for meta bg in setup_new_flex_group_blocks ext4: add missed brelse in update_backups ext4: properly sync file size update after O_SYNC direct IO drm/amd/pm: Handle non-terminated overdrive commands. drm/i915: Bump GLK CDCLK frequency when driving multiple pipes drm/i915: Fix potential spectre vulnerability drm/amd/pm: Fix error of MACO flag setting code drm/amdgpu/smu13: drop compute workload workaround drm/amdgpu: don't use pci_is_thunderbolt_attached() drm/amdgpu: don't use ATRM for external devices drm/amdgpu: fix error handling in amdgpu_bo_list_get() drm/amdgpu: lower CS errors to debug severity drm/amd/display: fix a NULL pointer dereference in amdgpu_dm_i2c_xfer() drm/amd/display: Enable fast plane updates on DCN3.2 and above drm/amd/display: Change the DMCUB mailbox memory location from FB to inbox powerpc/powernv: Fix fortify source warnings in opal-prd.c tracing: Have trace_event_file have ref counters Input: xpad - add VID for Turtle Beach controllers mmc: sdhci-pci-gli: GL9755: Mask the replay timer timeout of AER cxl/port: Fix NULL pointer access in devm_cxl_add_port() RISC-V: drop error print from riscv_hartid_to_cpuid() Linux 6.1.64 Change-Id: I9284282aeae5d0f9da957a58147efe0114f8e60a Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
614 lines
16 KiB
C
614 lines
16 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __LINUX_PWM_H
|
|
#define __LINUX_PWM_H
|
|
|
|
#include <linux/err.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/of.h>
|
|
#include <linux/android_kabi.h>
|
|
|
|
struct pwm_chip;
|
|
|
|
/**
|
|
* enum pwm_polarity - polarity of a PWM signal
|
|
* @PWM_POLARITY_NORMAL: a high signal for the duration of the duty-
|
|
* cycle, followed by a low signal for the remainder of the pulse
|
|
* period
|
|
* @PWM_POLARITY_INVERSED: a low signal for the duration of the duty-
|
|
* cycle, followed by a high signal for the remainder of the pulse
|
|
* period
|
|
*/
|
|
enum pwm_polarity {
|
|
PWM_POLARITY_NORMAL,
|
|
PWM_POLARITY_INVERSED,
|
|
};
|
|
|
|
/**
|
|
* struct pwm_args - board-dependent PWM arguments
|
|
* @period: reference period
|
|
* @polarity: reference polarity
|
|
*
|
|
* This structure describes board-dependent arguments attached to a PWM
|
|
* device. These arguments are usually retrieved from the PWM lookup table or
|
|
* device tree.
|
|
*
|
|
* Do not confuse this with the PWM state: PWM arguments represent the initial
|
|
* configuration that users want to use on this PWM device rather than the
|
|
* current PWM hardware state.
|
|
*/
|
|
struct pwm_args {
|
|
u64 period;
|
|
enum pwm_polarity polarity;
|
|
};
|
|
|
|
enum {
|
|
PWMF_REQUESTED = 0,
|
|
PWMF_EXPORTED = 1,
|
|
};
|
|
|
|
/*
|
|
* struct pwm_state - state of a PWM channel
|
|
* @period: PWM period (in nanoseconds)
|
|
* @duty_cycle: PWM duty cycle (in nanoseconds)
|
|
* @polarity: PWM polarity
|
|
* @enabled: PWM enabled status
|
|
* @usage_power: If set, the PWM driver is only required to maintain the power
|
|
* output but has more freedom regarding signal form.
|
|
* If supported, the signal can be optimized, for example to
|
|
* improve EMI by phase shifting individual channels.
|
|
*/
|
|
struct pwm_state {
|
|
u64 period;
|
|
u64 duty_cycle;
|
|
enum pwm_polarity polarity;
|
|
bool enabled;
|
|
bool usage_power;
|
|
};
|
|
|
|
/**
|
|
* struct pwm_device - PWM channel object
|
|
* @label: name of the PWM device
|
|
* @flags: flags associated with the PWM device
|
|
* @hwpwm: per-chip relative index of the PWM device
|
|
* @pwm: global index of the PWM device
|
|
* @chip: PWM chip providing this PWM device
|
|
* @chip_data: chip-private data associated with the PWM device
|
|
* @args: PWM arguments
|
|
* @state: last applied state
|
|
* @last: last implemented state (for PWM_DEBUG)
|
|
*/
|
|
struct pwm_device {
|
|
const char *label;
|
|
unsigned long flags;
|
|
unsigned int hwpwm;
|
|
unsigned int pwm;
|
|
struct pwm_chip *chip;
|
|
void *chip_data;
|
|
|
|
struct pwm_args args;
|
|
struct pwm_state state;
|
|
struct pwm_state last;
|
|
|
|
ANDROID_KABI_RESERVE(1);
|
|
};
|
|
|
|
/**
|
|
* pwm_get_state() - retrieve the current PWM state
|
|
* @pwm: PWM device
|
|
* @state: state to fill with the current PWM state
|
|
*
|
|
* The returned PWM state represents the state that was applied by a previous call to
|
|
* pwm_apply_state(). Drivers may have to slightly tweak that state before programming it to
|
|
* hardware. If pwm_apply_state() was never called, this returns either the current hardware
|
|
* state (if supported) or the default settings.
|
|
*/
|
|
static inline void pwm_get_state(const struct pwm_device *pwm,
|
|
struct pwm_state *state)
|
|
{
|
|
*state = pwm->state;
|
|
}
|
|
|
|
static inline bool pwm_is_enabled(const struct pwm_device *pwm)
|
|
{
|
|
struct pwm_state state;
|
|
|
|
pwm_get_state(pwm, &state);
|
|
|
|
return state.enabled;
|
|
}
|
|
|
|
static inline void pwm_set_period(struct pwm_device *pwm, u64 period)
|
|
{
|
|
if (pwm)
|
|
pwm->state.period = period;
|
|
}
|
|
|
|
static inline u64 pwm_get_period(const struct pwm_device *pwm)
|
|
{
|
|
struct pwm_state state;
|
|
|
|
pwm_get_state(pwm, &state);
|
|
|
|
return state.period;
|
|
}
|
|
|
|
static inline void pwm_set_duty_cycle(struct pwm_device *pwm, unsigned int duty)
|
|
{
|
|
if (pwm)
|
|
pwm->state.duty_cycle = duty;
|
|
}
|
|
|
|
static inline u64 pwm_get_duty_cycle(const struct pwm_device *pwm)
|
|
{
|
|
struct pwm_state state;
|
|
|
|
pwm_get_state(pwm, &state);
|
|
|
|
return state.duty_cycle;
|
|
}
|
|
|
|
static inline enum pwm_polarity pwm_get_polarity(const struct pwm_device *pwm)
|
|
{
|
|
struct pwm_state state;
|
|
|
|
pwm_get_state(pwm, &state);
|
|
|
|
return state.polarity;
|
|
}
|
|
|
|
static inline void pwm_get_args(const struct pwm_device *pwm,
|
|
struct pwm_args *args)
|
|
{
|
|
*args = pwm->args;
|
|
}
|
|
|
|
/**
|
|
* pwm_init_state() - prepare a new state to be applied with pwm_apply_state()
|
|
* @pwm: PWM device
|
|
* @state: state to fill with the prepared PWM state
|
|
*
|
|
* This functions prepares a state that can later be tweaked and applied
|
|
* to the PWM device with pwm_apply_state(). This is a convenient function
|
|
* that first retrieves the current PWM state and the replaces the period
|
|
* and polarity fields with the reference values defined in pwm->args.
|
|
* Once the function returns, you can adjust the ->enabled and ->duty_cycle
|
|
* fields according to your needs before calling pwm_apply_state().
|
|
*
|
|
* ->duty_cycle is initially set to zero to avoid cases where the current
|
|
* ->duty_cycle value exceed the pwm_args->period one, which would trigger
|
|
* an error if the user calls pwm_apply_state() without adjusting ->duty_cycle
|
|
* first.
|
|
*/
|
|
static inline void pwm_init_state(const struct pwm_device *pwm,
|
|
struct pwm_state *state)
|
|
{
|
|
struct pwm_args args;
|
|
|
|
/* First get the current state. */
|
|
pwm_get_state(pwm, state);
|
|
|
|
/* Then fill it with the reference config */
|
|
pwm_get_args(pwm, &args);
|
|
|
|
state->period = args.period;
|
|
state->polarity = args.polarity;
|
|
state->duty_cycle = 0;
|
|
state->usage_power = false;
|
|
}
|
|
|
|
/**
|
|
* pwm_get_relative_duty_cycle() - Get a relative duty cycle value
|
|
* @state: PWM state to extract the duty cycle from
|
|
* @scale: target scale of the relative duty cycle
|
|
*
|
|
* This functions converts the absolute duty cycle stored in @state (expressed
|
|
* in nanosecond) into a value relative to the period.
|
|
*
|
|
* For example if you want to get the duty_cycle expressed in percent, call:
|
|
*
|
|
* pwm_get_state(pwm, &state);
|
|
* duty = pwm_get_relative_duty_cycle(&state, 100);
|
|
*/
|
|
static inline unsigned int
|
|
pwm_get_relative_duty_cycle(const struct pwm_state *state, unsigned int scale)
|
|
{
|
|
if (!state->period)
|
|
return 0;
|
|
|
|
return DIV_ROUND_CLOSEST_ULL((u64)state->duty_cycle * scale,
|
|
state->period);
|
|
}
|
|
|
|
/**
|
|
* pwm_set_relative_duty_cycle() - Set a relative duty cycle value
|
|
* @state: PWM state to fill
|
|
* @duty_cycle: relative duty cycle value
|
|
* @scale: scale in which @duty_cycle is expressed
|
|
*
|
|
* This functions converts a relative into an absolute duty cycle (expressed
|
|
* in nanoseconds), and puts the result in state->duty_cycle.
|
|
*
|
|
* For example if you want to configure a 50% duty cycle, call:
|
|
*
|
|
* pwm_init_state(pwm, &state);
|
|
* pwm_set_relative_duty_cycle(&state, 50, 100);
|
|
* pwm_apply_state(pwm, &state);
|
|
*
|
|
* This functions returns -EINVAL if @duty_cycle and/or @scale are
|
|
* inconsistent (@scale == 0 or @duty_cycle > @scale).
|
|
*/
|
|
static inline int
|
|
pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle,
|
|
unsigned int scale)
|
|
{
|
|
if (!scale || duty_cycle > scale)
|
|
return -EINVAL;
|
|
|
|
state->duty_cycle = DIV_ROUND_CLOSEST_ULL((u64)duty_cycle *
|
|
state->period,
|
|
scale);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* struct pwm_capture - PWM capture data
|
|
* @period: period of the PWM signal (in nanoseconds)
|
|
* @duty_cycle: duty cycle of the PWM signal (in nanoseconds)
|
|
*/
|
|
struct pwm_capture {
|
|
unsigned int period;
|
|
unsigned int duty_cycle;
|
|
};
|
|
|
|
/**
|
|
* struct pwm_ops - PWM controller operations
|
|
* @request: optional hook for requesting a PWM
|
|
* @free: optional hook for freeing a PWM
|
|
* @capture: capture and report PWM signal
|
|
* @apply: atomically apply a new PWM config
|
|
* @get_state: get the current PWM state. This function is only
|
|
* called once per PWM device when the PWM chip is
|
|
* registered.
|
|
* @owner: helps prevent removal of modules exporting active PWMs
|
|
*/
|
|
struct pwm_ops {
|
|
int (*request)(struct pwm_chip *chip, struct pwm_device *pwm);
|
|
void (*free)(struct pwm_chip *chip, struct pwm_device *pwm);
|
|
int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm,
|
|
struct pwm_capture *result, unsigned long timeout);
|
|
int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm,
|
|
const struct pwm_state *state);
|
|
int (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
|
|
struct pwm_state *state);
|
|
struct module *owner;
|
|
ANDROID_KABI_RESERVE(1);
|
|
};
|
|
|
|
/**
|
|
* struct pwm_chip - abstract a PWM controller
|
|
* @dev: device providing the PWMs
|
|
* @ops: callbacks for this PWM controller
|
|
* @base: number of first PWM controlled by this chip
|
|
* @npwm: number of PWMs controlled by this chip
|
|
* @of_xlate: request a PWM device given a device tree PWM specifier
|
|
* @of_pwm_n_cells: number of cells expected in the device tree PWM specifier
|
|
* @list: list node for internal use
|
|
* @pwms: array of PWM devices allocated by the framework
|
|
*/
|
|
struct pwm_chip {
|
|
struct device *dev;
|
|
const struct pwm_ops *ops;
|
|
int base;
|
|
unsigned int npwm;
|
|
|
|
struct pwm_device * (*of_xlate)(struct pwm_chip *pc,
|
|
const struct of_phandle_args *args);
|
|
unsigned int of_pwm_n_cells;
|
|
|
|
/* only used internally by the PWM framework */
|
|
struct list_head list;
|
|
struct pwm_device *pwms;
|
|
|
|
ANDROID_KABI_RESERVE(1);
|
|
};
|
|
|
|
#if IS_ENABLED(CONFIG_PWM)
|
|
/* PWM user APIs */
|
|
struct pwm_device *pwm_request(int pwm_id, const char *label);
|
|
void pwm_free(struct pwm_device *pwm);
|
|
int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state);
|
|
int pwm_adjust_config(struct pwm_device *pwm);
|
|
|
|
/**
|
|
* pwm_config() - change a PWM device configuration
|
|
* @pwm: PWM device
|
|
* @duty_ns: "on" time (in nanoseconds)
|
|
* @period_ns: duration (in nanoseconds) of one cycle
|
|
*
|
|
* Returns: 0 on success or a negative error code on failure.
|
|
*/
|
|
static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
|
|
int period_ns)
|
|
{
|
|
struct pwm_state state;
|
|
|
|
if (!pwm)
|
|
return -EINVAL;
|
|
|
|
if (duty_ns < 0 || period_ns < 0)
|
|
return -EINVAL;
|
|
|
|
pwm_get_state(pwm, &state);
|
|
if (state.duty_cycle == duty_ns && state.period == period_ns)
|
|
return 0;
|
|
|
|
state.duty_cycle = duty_ns;
|
|
state.period = period_ns;
|
|
return pwm_apply_state(pwm, &state);
|
|
}
|
|
|
|
/**
|
|
* pwm_enable() - start a PWM output toggling
|
|
* @pwm: PWM device
|
|
*
|
|
* Returns: 0 on success or a negative error code on failure.
|
|
*/
|
|
static inline int pwm_enable(struct pwm_device *pwm)
|
|
{
|
|
struct pwm_state state;
|
|
|
|
if (!pwm)
|
|
return -EINVAL;
|
|
|
|
pwm_get_state(pwm, &state);
|
|
if (state.enabled)
|
|
return 0;
|
|
|
|
state.enabled = true;
|
|
return pwm_apply_state(pwm, &state);
|
|
}
|
|
|
|
/**
|
|
* pwm_disable() - stop a PWM output toggling
|
|
* @pwm: PWM device
|
|
*/
|
|
static inline void pwm_disable(struct pwm_device *pwm)
|
|
{
|
|
struct pwm_state state;
|
|
|
|
if (!pwm)
|
|
return;
|
|
|
|
pwm_get_state(pwm, &state);
|
|
if (!state.enabled)
|
|
return;
|
|
|
|
state.enabled = false;
|
|
pwm_apply_state(pwm, &state);
|
|
}
|
|
|
|
/* PWM provider APIs */
|
|
int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
|
|
unsigned long timeout);
|
|
int pwm_set_chip_data(struct pwm_device *pwm, void *data);
|
|
void *pwm_get_chip_data(struct pwm_device *pwm);
|
|
|
|
int pwmchip_add(struct pwm_chip *chip);
|
|
void pwmchip_remove(struct pwm_chip *chip);
|
|
|
|
int devm_pwmchip_add(struct device *dev, struct pwm_chip *chip);
|
|
|
|
struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
|
|
unsigned int index,
|
|
const char *label);
|
|
|
|
struct pwm_device *of_pwm_xlate_with_flags(struct pwm_chip *pc,
|
|
const struct of_phandle_args *args);
|
|
struct pwm_device *of_pwm_single_xlate(struct pwm_chip *pc,
|
|
const struct of_phandle_args *args);
|
|
|
|
struct pwm_device *pwm_get(struct device *dev, const char *con_id);
|
|
void pwm_put(struct pwm_device *pwm);
|
|
|
|
struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id);
|
|
struct pwm_device *devm_fwnode_pwm_get(struct device *dev,
|
|
struct fwnode_handle *fwnode,
|
|
const char *con_id);
|
|
#else
|
|
static inline struct pwm_device *pwm_request(int pwm_id, const char *label)
|
|
{
|
|
might_sleep();
|
|
return ERR_PTR(-ENODEV);
|
|
}
|
|
|
|
static inline void pwm_free(struct pwm_device *pwm)
|
|
{
|
|
might_sleep();
|
|
}
|
|
|
|
static inline int pwm_apply_state(struct pwm_device *pwm,
|
|
const struct pwm_state *state)
|
|
{
|
|
might_sleep();
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
static inline int pwm_adjust_config(struct pwm_device *pwm)
|
|
{
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
|
|
int period_ns)
|
|
{
|
|
might_sleep();
|
|
return -EINVAL;
|
|
}
|
|
|
|
static inline int pwm_capture(struct pwm_device *pwm,
|
|
struct pwm_capture *result,
|
|
unsigned long timeout)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
static inline int pwm_enable(struct pwm_device *pwm)
|
|
{
|
|
might_sleep();
|
|
return -EINVAL;
|
|
}
|
|
|
|
static inline void pwm_disable(struct pwm_device *pwm)
|
|
{
|
|
might_sleep();
|
|
}
|
|
|
|
static inline int pwm_set_chip_data(struct pwm_device *pwm, void *data)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
static inline void *pwm_get_chip_data(struct pwm_device *pwm)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline int pwmchip_add(struct pwm_chip *chip)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
static inline int pwmchip_remove(struct pwm_chip *chip)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
static inline int devm_pwmchip_add(struct device *dev, struct pwm_chip *chip)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
static inline struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
|
|
unsigned int index,
|
|
const char *label)
|
|
{
|
|
might_sleep();
|
|
return ERR_PTR(-ENODEV);
|
|
}
|
|
|
|
static inline struct pwm_device *pwm_get(struct device *dev,
|
|
const char *consumer)
|
|
{
|
|
might_sleep();
|
|
return ERR_PTR(-ENODEV);
|
|
}
|
|
|
|
static inline void pwm_put(struct pwm_device *pwm)
|
|
{
|
|
might_sleep();
|
|
}
|
|
|
|
static inline struct pwm_device *devm_pwm_get(struct device *dev,
|
|
const char *consumer)
|
|
{
|
|
might_sleep();
|
|
return ERR_PTR(-ENODEV);
|
|
}
|
|
|
|
static inline struct pwm_device *
|
|
devm_fwnode_pwm_get(struct device *dev, struct fwnode_handle *fwnode,
|
|
const char *con_id)
|
|
{
|
|
might_sleep();
|
|
return ERR_PTR(-ENODEV);
|
|
}
|
|
#endif
|
|
|
|
static inline void pwm_apply_args(struct pwm_device *pwm)
|
|
{
|
|
struct pwm_state state = { };
|
|
|
|
/*
|
|
* PWM users calling pwm_apply_args() expect to have a fresh config
|
|
* where the polarity and period are set according to pwm_args info.
|
|
* The problem is, polarity can only be changed when the PWM is
|
|
* disabled.
|
|
*
|
|
* PWM drivers supporting hardware readout may declare the PWM device
|
|
* as enabled, and prevent polarity setting, which changes from the
|
|
* existing behavior, where all PWM devices are declared as disabled
|
|
* at startup (even if they are actually enabled), thus authorizing
|
|
* polarity setting.
|
|
*
|
|
* To fulfill this requirement, we apply a new state which disables
|
|
* the PWM device and set the reference period and polarity config.
|
|
*
|
|
* Note that PWM users requiring a smooth handover between the
|
|
* bootloader and the kernel (like critical regulators controlled by
|
|
* PWM devices) will have to switch to the atomic API and avoid calling
|
|
* pwm_apply_args().
|
|
*/
|
|
|
|
state.enabled = false;
|
|
state.polarity = pwm->args.polarity;
|
|
state.period = pwm->args.period;
|
|
state.usage_power = false;
|
|
|
|
pwm_apply_state(pwm, &state);
|
|
}
|
|
|
|
struct pwm_lookup {
|
|
struct list_head list;
|
|
const char *provider;
|
|
unsigned int index;
|
|
const char *dev_id;
|
|
const char *con_id;
|
|
unsigned int period;
|
|
enum pwm_polarity polarity;
|
|
const char *module; /* optional, may be NULL */
|
|
};
|
|
|
|
#define PWM_LOOKUP_WITH_MODULE(_provider, _index, _dev_id, _con_id, \
|
|
_period, _polarity, _module) \
|
|
{ \
|
|
.provider = _provider, \
|
|
.index = _index, \
|
|
.dev_id = _dev_id, \
|
|
.con_id = _con_id, \
|
|
.period = _period, \
|
|
.polarity = _polarity, \
|
|
.module = _module, \
|
|
}
|
|
|
|
#define PWM_LOOKUP(_provider, _index, _dev_id, _con_id, _period, _polarity) \
|
|
PWM_LOOKUP_WITH_MODULE(_provider, _index, _dev_id, _con_id, _period, \
|
|
_polarity, NULL)
|
|
|
|
#if IS_ENABLED(CONFIG_PWM)
|
|
void pwm_add_table(struct pwm_lookup *table, size_t num);
|
|
void pwm_remove_table(struct pwm_lookup *table, size_t num);
|
|
#else
|
|
static inline void pwm_add_table(struct pwm_lookup *table, size_t num)
|
|
{
|
|
}
|
|
|
|
static inline void pwm_remove_table(struct pwm_lookup *table, size_t num)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_PWM_SYSFS
|
|
void pwmchip_sysfs_export(struct pwm_chip *chip);
|
|
void pwmchip_sysfs_unexport(struct pwm_chip *chip);
|
|
#else
|
|
static inline void pwmchip_sysfs_export(struct pwm_chip *chip)
|
|
{
|
|
}
|
|
|
|
static inline void pwmchip_sysfs_unexport(struct pwm_chip *chip)
|
|
{
|
|
}
|
|
#endif /* CONFIG_PWM_SYSFS */
|
|
|
|
#endif /* __LINUX_PWM_H */
|