Changes in 5.4.273
io_uring/unix: drop usage of io_uring socket
io_uring: drop any code related to SCM_RIGHTS
selftests: tls: use exact comparison in recv_partial
ASoC: rt5645: Make LattePanda board DMI match more precise
x86/xen: Add some null pointer checking to smp.c
MIPS: Clear Cause.BD in instruction_pointer_set
HID: multitouch: Add required quirk for Synaptics 0xcddc device
RDMA/mlx5: Relax DEVX access upon modify commands
net/iucv: fix the allocation size of iucv_path_table array
parisc/ftrace: add missing CONFIG_DYNAMIC_FTRACE check
block: sed-opal: handle empty atoms when parsing response
dm-verity, dm-crypt: align "struct bvec_iter" correctly
btrfs: fix data race at btrfs_use_block_rsv() when accessing block reserve
scsi: mpt3sas: Prevent sending diag_reset when the controller is ready
Bluetooth: rfcomm: Fix null-ptr-deref in rfcomm_check_security
firewire: core: use long bus reset on gap count error
ASoC: Intel: bytcr_rt5640: Add an extra entry for the Chuwi Vi8 tablet
Input: gpio_keys_polled - suppress deferred probe error for gpio
ASoC: wm8962: Enable oscillator if selecting WM8962_FLL_OSC
ASoC: wm8962: Enable both SPKOUTR_ENA and SPKOUTL_ENA in mono mode
ASoC: wm8962: Fix up incorrect error message in wm8962_set_fll
do_sys_name_to_handle(): use kzalloc() to fix kernel-infoleak
nbd: null check for nla_nest_start
fs/select: rework stack allocation hack for clang
aoe: fix the potential use-after-free problem in aoecmd_cfg_pkts
timekeeping: Fix cross-timestamp interpolation on counter wrap
timekeeping: Fix cross-timestamp interpolation corner case decision
timekeeping: Fix cross-timestamp interpolation for non-x86
wifi: ath10k: fix NULL pointer dereference in ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev()
b43: dma: Fix use true/false for bool type variable
wifi: b43: Stop/wake correct queue in DMA Tx path when QoS is disabled
wifi: b43: Stop/wake correct queue in PIO Tx path when QoS is disabled
b43: main: Fix use true/false for bool type
wifi: b43: Stop correct queue in DMA worker when QoS is disabled
wifi: b43: Disable QoS for bcm4331
wifi: wilc1000: fix declarations ordering
wifi: wilc1000: fix RCU usage in connect path
wifi: mwifiex: debugfs: Drop unnecessary error check for debugfs_create_dir()
sock_diag: annotate data-races around sock_diag_handlers[family]
af_unix: Annotate data-race of gc_in_progress in wait_for_unix_gc().
net: blackhole_dev: fix build warning for ethh set but not used
wifi: libertas: fix some memleaks in lbs_allocate_cmd_buffer()
arm64: dts: mediatek: mt7622: add missing "device_type" to memory nodes
bpf: Add typecast to bpf helpers to help BTF generation
bpf: Factor out bpf_spin_lock into helpers.
bpf: Mark bpf_spin_{lock,unlock}() helpers with notrace correctly
arm64: dts: qcom: db820c: Move non-soc entries out of /soc
arm64: dts: qcom: msm8996: Use node references in db820c
arm64: dts: qcom: msm8996: Move regulator consumers to db820c
arm64: dts: qcom: msm8996: Pad addresses
ACPI: processor_idle: Fix memory leak in acpi_processor_power_exit()
bus: tegra-aconnect: Update dependency to ARCH_TEGRA
iommu/amd: Mark interrupt as managed
wifi: brcmsmac: avoid function pointer casts
net: ena: cosmetic: fix line break issues
net: ena: Remove ena_select_queue
ARM: dts: arm: realview: Fix development chip ROM compatible value
ARM: dts: imx6dl-yapp4: Move phy reset into switch node
ARM: dts: imx6dl-yapp4: Fix typo in the QCA switch register address
ARM: dts: imx6dl-yapp4: Move the internal switch PHYs under the switch node
ACPI: scan: Fix device check notification handling
x86, relocs: Ignore relocations in .notes section
SUNRPC: fix some memleaks in gssx_dec_option_array
mmc: wmt-sdmmc: remove an incorrect release_mem_region() call in the .remove function
igb: move PEROUT and EXTTS isr logic to separate functions
igb: Fix missing time sync events
Bluetooth: Remove superfluous call to hci_conn_check_pending()
Bluetooth: hci_core: Fix possible buffer overflow
sr9800: Add check for usbnet_get_endpoints
bpf: Fix hashtab overflow check on 32-bit arches
bpf: Fix stackmap overflow check on 32-bit arches
ipv6: fib6_rules: flush route cache when rule is changed
net: ip_tunnel: make sure to pull inner header in ip_tunnel_rcv()
net: hns3: fix port duplex configure error in IMP reset
tcp: fix incorrect parameter validation in the do_tcp_getsockopt() function
l2tp: fix incorrect parameter validation in the pppol2tp_getsockopt() function
udp: fix incorrect parameter validation in the udp_lib_getsockopt() function
net: kcm: fix incorrect parameter validation in the kcm_getsockopt) function
net/x25: fix incorrect parameter validation in the x25_getsockopt() function
nfp: flower: handle acti_netdevs allocation failure
dm raid: fix false positive for requeue needed during reshape
dm: call the resume method on internal suspend
drm/tegra: dsi: Add missing check for of_find_device_by_node
gpu: host1x: mipi: Update tegra_mipi_request() to be node based
drm/tegra: dsi: Make use of the helper function dev_err_probe()
drm/tegra: dsi: Fix some error handling paths in tegra_dsi_probe()
drm/tegra: dsi: Fix missing pm_runtime_disable() in the error handling path of tegra_dsi_probe()
drm/tegra: output: Fix missing i2c_put_adapter() in the error handling paths of tegra_output_probe()
drm/rockchip: inno_hdmi: Fix video timing
drm: Don't treat 0 as -1 in drm_fixp2int_ceil
drm/rockchip: lvds: do not overwrite error code
dmaengine: tegra210-adma: Update dependency to ARCH_TEGRA
media: tc358743: register v4l2 async device only after successful setup
PCI/DPC: Print all TLP Prefixes, not just the first
perf record: Fix possible incorrect free in record__switch_output()
drm/amd/display: Fix potential NULL pointer dereferences in 'dcn10_set_output_transfer_func()'
perf evsel: Fix duplicate initialization of data->id in evsel__parse_sample()
media: em28xx: annotate unchecked call to media_device_register()
media: v4l2-tpg: fix some memleaks in tpg_alloc
media: v4l2-mem2mem: fix a memleak in v4l2_m2m_register_entity
media: edia: dvbdev: fix a use-after-free
clk: qcom: reset: Allow specifying custom reset delay
clk: qcom: reset: support resetting multiple bits
clk: qcom: reset: Commonize the de/assert functions
clk: qcom: reset: Ensure write completion on reset de/assertion
quota: simplify drop_dquot_ref()
quota: Fix potential NULL pointer dereference
quota: Fix rcu annotations of inode dquot pointers
PCI: switchtec: Fix an error handling path in switchtec_pci_probe()
perf thread_map: Free strlist on normal path in thread_map__new_by_tid_str()
drm/radeon/ni: Fix wrong firmware size logging in ni_init_microcode()
ALSA: seq: fix function cast warnings
perf stat: Avoid metric-only segv
media: imx: csc/scaler: fix v4l2_ctrl_handler memory leak
media: go7007: add check of return value of go7007_read_addr()
media: pvrusb2: remove redundant NULL check
media: pvrusb2: fix pvr2_stream_callback casts
clk: qcom: dispcc-sdm845: Adjust internal GDSC wait times
drm/mediatek: dsi: Fix DSI RGB666 formats and definitions
PCI: Mark 3ware-9650SE Root Port Extended Tags as broken
clk: hisilicon: hi3519: Release the correct number of gates in hi3519_clk_unregister()
drm/tegra: put drm_gem_object ref on error in tegra_fb_create
mfd: syscon: Call of_node_put() only when of_parse_phandle() takes a ref
mfd: altera-sysmgr: Call of_node_put() only when of_parse_phandle() takes a ref
crypto: arm/sha - fix function cast warnings
mtd: maps: physmap-core: fix flash size larger than 32-bit
mtd: rawnand: lpc32xx_mlc: fix irq handler prototype
ASoC: meson: axg-tdm-interface: fix mclk setup without mclk-fs
drm/amdgpu: Fix missing break in ATOM_ARG_IMM Case of atom_get_src_int()
media: pvrusb2: fix uaf in pvr2_context_set_notify
media: dvb-frontends: avoid stack overflow warnings with clang
media: go7007: fix a memleak in go7007_load_encoder
media: v4l2-core: correctly validate video and metadata ioctls
media: rename VFL_TYPE_GRABBER to _VIDEO
media: media/pci: rename VFL_TYPE_GRABBER to _VIDEO
media: ttpci: fix two memleaks in budget_av_attach
drm/mediatek: Fix a null pointer crash in mtk_drm_crtc_finish_page_flip
powerpc/hv-gpci: Fix the H_GET_PERF_COUNTER_INFO hcall return value checks
drm/msm/dpu: add division of drm_display_mode's hskew parameter
powerpc/embedded6xx: Fix no previous prototype for avr_uart_send() etc.
backlight: lm3630a: Initialize backlight_properties on init
backlight: lm3630a: Don't set bl->props.brightness in get_brightness
backlight: da9052: Fully initialize backlight_properties during probe
backlight: lm3639: Fully initialize backlight_properties during probe
backlight: lp8788: Fully initialize backlight_properties during probe
sparc32: Fix section mismatch in leon_pci_grpci
clk: Fix clk_core_get NULL dereference
ALSA: usb-audio: Stop parsing channels bits when all channels are found.
scsi: csiostor: Avoid function pointer casts
RDMA/device: Fix a race between mad_client and cm_client init
scsi: bfa: Fix function pointer type mismatch for hcb_qe->cbfn
net: sunrpc: Fix an off by one in rpc_sockaddr2uaddr()
watchdog: stm32_iwdg: initialize default timeout
NFS: Fix an off by one in root_nfs_cat()
afs: Revert "afs: Hide silly-rename files from userspace"
tty: vt: fix 20 vs 0x20 typo in EScsiignore
serial: max310x: fix syntax error in IRQ error message
tty: serial: samsung: fix tx_empty() to return TIOCSER_TEMT
kconfig: fix infinite loop when expanding a macro at the end of file
rtc: mt6397: select IRQ_DOMAIN instead of depending on it
serial: 8250_exar: Don't remove GPIO device on suspend
staging: greybus: fix get_channel_from_mode() failure path
usb: gadget: net2272: Use irqflags in the call to net2272_probe_fin
octeontx2-af: Use matching wake_up API variant in CGX command interface
s390/vtime: fix average steal time calculation
hsr: Fix uninit-value access in hsr_get_node()
packet: annotate data-races around ignore_outgoing
rds: introduce acquire/release ordering in acquire/release_in_xmit()
hsr: Handle failures in module init
net/bnx2x: Prevent access to a freed page in page_pool
octeontx2-af: Use separate handlers for interrupts
ARM: dts: sun8i-h2-plus-bananapi-m2-zero: add regulator nodes vcc-dram and vcc1v2
netfilter: nf_tables: do not compare internal table flags on updates
rcu: add a helper to report consolidated flavor QS
bpf: report RCU QS in cpumap kthread
spi: spi-mt65xx: Fix NULL pointer access in interrupt handler
regmap: Add missing map->bus check
Linux 5.4.273
Change-Id: I7b54c53c62f7ae93eddbd8d677f0d5de9547073e
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
313 lines
7.1 KiB
C
313 lines
7.1 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* System Control Driver
|
|
*
|
|
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
|
* Copyright (C) 2012 Linaro Ltd.
|
|
*
|
|
* Author: Dong Aisheng <dong.aisheng@linaro.org>
|
|
*/
|
|
|
|
#include <linux/clk.h>
|
|
#include <linux/err.h>
|
|
#include <linux/hwspinlock.h>
|
|
#include <linux/io.h>
|
|
#include <linux/init.h>
|
|
#include <linux/list.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/of_platform.h>
|
|
#include <linux/platform_data/syscon.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/regmap.h>
|
|
#include <linux/mfd/syscon.h>
|
|
#include <linux/slab.h>
|
|
|
|
static struct platform_driver syscon_driver;
|
|
|
|
static DEFINE_SPINLOCK(syscon_list_slock);
|
|
static LIST_HEAD(syscon_list);
|
|
|
|
struct syscon {
|
|
struct device_node *np;
|
|
struct regmap *regmap;
|
|
struct list_head list;
|
|
};
|
|
|
|
static const struct regmap_config syscon_regmap_config = {
|
|
.reg_bits = 32,
|
|
.val_bits = 32,
|
|
.reg_stride = 4,
|
|
};
|
|
|
|
static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
|
|
{
|
|
struct clk *clk;
|
|
struct syscon *syscon;
|
|
struct regmap *regmap;
|
|
void __iomem *base;
|
|
u32 reg_io_width;
|
|
int ret;
|
|
struct regmap_config syscon_config = syscon_regmap_config;
|
|
struct resource res;
|
|
|
|
syscon = kzalloc(sizeof(*syscon), GFP_KERNEL);
|
|
if (!syscon)
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
if (of_address_to_resource(np, 0, &res)) {
|
|
ret = -ENOMEM;
|
|
goto err_map;
|
|
}
|
|
|
|
base = ioremap(res.start, resource_size(&res));
|
|
if (!base) {
|
|
ret = -ENOMEM;
|
|
goto err_map;
|
|
}
|
|
|
|
/* Parse the device's DT node for an endianness specification */
|
|
if (of_property_read_bool(np, "big-endian"))
|
|
syscon_config.val_format_endian = REGMAP_ENDIAN_BIG;
|
|
else if (of_property_read_bool(np, "little-endian"))
|
|
syscon_config.val_format_endian = REGMAP_ENDIAN_LITTLE;
|
|
else if (of_property_read_bool(np, "native-endian"))
|
|
syscon_config.val_format_endian = REGMAP_ENDIAN_NATIVE;
|
|
|
|
/*
|
|
* search for reg-io-width property in DT. If it is not provided,
|
|
* default to 4 bytes. regmap_init_mmio will return an error if values
|
|
* are invalid so there is no need to check them here.
|
|
*/
|
|
ret = of_property_read_u32(np, "reg-io-width", ®_io_width);
|
|
if (ret)
|
|
reg_io_width = 4;
|
|
|
|
ret = of_hwspin_lock_get_id(np, 0);
|
|
if (ret > 0 || (IS_ENABLED(CONFIG_HWSPINLOCK) && ret == 0)) {
|
|
syscon_config.use_hwlock = true;
|
|
syscon_config.hwlock_id = ret;
|
|
syscon_config.hwlock_mode = HWLOCK_IRQSTATE;
|
|
} else if (ret < 0) {
|
|
switch (ret) {
|
|
case -ENOENT:
|
|
/* Ignore missing hwlock, it's optional. */
|
|
break;
|
|
default:
|
|
pr_err("Failed to retrieve valid hwlock: %d\n", ret);
|
|
/* fall-through */
|
|
case -EPROBE_DEFER:
|
|
goto err_regmap;
|
|
}
|
|
}
|
|
|
|
syscon_config.name = of_node_full_name(np);
|
|
syscon_config.reg_stride = reg_io_width;
|
|
syscon_config.val_bits = reg_io_width * 8;
|
|
syscon_config.max_register = resource_size(&res) - reg_io_width;
|
|
syscon_config.name = of_node_full_name(np);
|
|
|
|
regmap = regmap_init_mmio(NULL, base, &syscon_config);
|
|
if (IS_ERR(regmap)) {
|
|
pr_err("regmap init failed\n");
|
|
ret = PTR_ERR(regmap);
|
|
goto err_regmap;
|
|
}
|
|
|
|
if (check_clk) {
|
|
clk = of_clk_get(np, 0);
|
|
if (IS_ERR(clk)) {
|
|
ret = PTR_ERR(clk);
|
|
/* clock is optional */
|
|
if (ret != -ENOENT)
|
|
goto err_clk;
|
|
} else {
|
|
ret = regmap_mmio_attach_clk(regmap, clk);
|
|
if (ret)
|
|
goto err_attach;
|
|
}
|
|
}
|
|
|
|
syscon->regmap = regmap;
|
|
syscon->np = np;
|
|
|
|
spin_lock(&syscon_list_slock);
|
|
list_add_tail(&syscon->list, &syscon_list);
|
|
spin_unlock(&syscon_list_slock);
|
|
|
|
return syscon;
|
|
|
|
err_attach:
|
|
if (!IS_ERR(clk))
|
|
clk_put(clk);
|
|
err_clk:
|
|
regmap_exit(regmap);
|
|
err_regmap:
|
|
iounmap(base);
|
|
err_map:
|
|
kfree(syscon);
|
|
return ERR_PTR(ret);
|
|
}
|
|
|
|
static struct regmap *device_node_get_regmap(struct device_node *np,
|
|
bool check_clk)
|
|
{
|
|
struct syscon *entry, *syscon = NULL;
|
|
|
|
spin_lock(&syscon_list_slock);
|
|
|
|
list_for_each_entry(entry, &syscon_list, list)
|
|
if (entry->np == np) {
|
|
syscon = entry;
|
|
break;
|
|
}
|
|
|
|
spin_unlock(&syscon_list_slock);
|
|
|
|
if (!syscon)
|
|
syscon = of_syscon_register(np, check_clk);
|
|
|
|
if (IS_ERR(syscon))
|
|
return ERR_CAST(syscon);
|
|
|
|
return syscon->regmap;
|
|
}
|
|
|
|
struct regmap *device_node_to_regmap(struct device_node *np)
|
|
{
|
|
return device_node_get_regmap(np, false);
|
|
}
|
|
EXPORT_SYMBOL_GPL(device_node_to_regmap);
|
|
|
|
struct regmap *syscon_node_to_regmap(struct device_node *np)
|
|
{
|
|
if (!of_device_is_compatible(np, "syscon"))
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
return device_node_get_regmap(np, true);
|
|
}
|
|
EXPORT_SYMBOL_GPL(syscon_node_to_regmap);
|
|
|
|
struct regmap *syscon_regmap_lookup_by_compatible(const char *s)
|
|
{
|
|
struct device_node *syscon_np;
|
|
struct regmap *regmap;
|
|
|
|
syscon_np = of_find_compatible_node(NULL, NULL, s);
|
|
if (!syscon_np)
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
regmap = syscon_node_to_regmap(syscon_np);
|
|
of_node_put(syscon_np);
|
|
|
|
return regmap;
|
|
}
|
|
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible);
|
|
|
|
struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
|
|
const char *property)
|
|
{
|
|
struct device_node *syscon_np;
|
|
struct regmap *regmap;
|
|
|
|
if (property)
|
|
syscon_np = of_parse_phandle(np, property, 0);
|
|
else
|
|
syscon_np = np;
|
|
|
|
if (!syscon_np)
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
regmap = syscon_node_to_regmap(syscon_np);
|
|
|
|
if (property)
|
|
of_node_put(syscon_np);
|
|
|
|
return regmap;
|
|
}
|
|
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle);
|
|
|
|
struct regmap *syscon_regmap_lookup_by_phandle_args(struct device_node *np,
|
|
const char *property,
|
|
int arg_count,
|
|
unsigned int *out_args)
|
|
{
|
|
struct device_node *syscon_np;
|
|
struct of_phandle_args args;
|
|
struct regmap *regmap;
|
|
unsigned int index;
|
|
int rc;
|
|
|
|
rc = of_parse_phandle_with_fixed_args(np, property, arg_count,
|
|
0, &args);
|
|
if (rc)
|
|
return ERR_PTR(rc);
|
|
|
|
syscon_np = args.np;
|
|
if (!syscon_np)
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
regmap = syscon_node_to_regmap(syscon_np);
|
|
for (index = 0; index < arg_count; index++)
|
|
out_args[index] = args.args[index];
|
|
of_node_put(syscon_np);
|
|
|
|
return regmap;
|
|
}
|
|
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle_args);
|
|
|
|
static int syscon_probe(struct platform_device *pdev)
|
|
{
|
|
struct device *dev = &pdev->dev;
|
|
struct syscon_platform_data *pdata = dev_get_platdata(dev);
|
|
struct syscon *syscon;
|
|
struct regmap_config syscon_config = syscon_regmap_config;
|
|
struct resource *res;
|
|
void __iomem *base;
|
|
|
|
syscon = devm_kzalloc(dev, sizeof(*syscon), GFP_KERNEL);
|
|
if (!syscon)
|
|
return -ENOMEM;
|
|
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
if (!res)
|
|
return -ENOENT;
|
|
|
|
base = devm_ioremap(dev, res->start, resource_size(res));
|
|
if (!base)
|
|
return -ENOMEM;
|
|
|
|
syscon_config.max_register = res->end - res->start - 3;
|
|
if (pdata)
|
|
syscon_config.name = pdata->label;
|
|
syscon->regmap = devm_regmap_init_mmio(dev, base, &syscon_config);
|
|
if (IS_ERR(syscon->regmap)) {
|
|
dev_err(dev, "regmap init failed\n");
|
|
return PTR_ERR(syscon->regmap);
|
|
}
|
|
|
|
platform_set_drvdata(pdev, syscon);
|
|
|
|
dev_dbg(dev, "regmap %pR registered\n", res);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct platform_device_id syscon_ids[] = {
|
|
{ "syscon", },
|
|
{ }
|
|
};
|
|
|
|
static struct platform_driver syscon_driver = {
|
|
.driver = {
|
|
.name = "syscon",
|
|
},
|
|
.probe = syscon_probe,
|
|
.id_table = syscon_ids,
|
|
};
|
|
|
|
static int __init syscon_init(void)
|
|
{
|
|
return platform_driver_register(&syscon_driver);
|
|
}
|
|
postcore_initcall(syscon_init);
|