Changes in 5.10.201 iov_iter, x86: Be consistent about the __user tag on copy_mc_to_user() sched/uclamp: Ignore (util == 0) optimization in feec() when p_util_max = 0 vfs: fix readahead(2) on block devices x86/srso: Fix SBPB enablement for (possible) future fixed HW futex: Don't include process MM in futex key on no-MMU x86/boot: Fix incorrect startup_gdt_descr.size pstore/platform: Add check for kstrdup genirq/matrix: Exclude managed interrupts in irq_matrix_allocated() i40e: fix potential memory leaks in i40e_remove() udp: add missing WRITE_ONCE() around up->encap_rcv tcp: call tcp_try_undo_recovery when an RTOd TFO SYNACK is ACKed overflow: Implement size_t saturating arithmetic helpers gve: Use size_add() in call to struct_size() mlxsw: Use size_mul() in call to struct_size() tipc: Use size_add() in calls to struct_size() net: spider_net: Use size_add() in call to struct_size() wifi: rtw88: debug: Fix the NULL vs IS_ERR() bug for debugfs_create_file() wifi: mt76: mt7603: rework/fix rx pse hang check tcp_metrics: add missing barriers on delete tcp_metrics: properly set tp->snd_ssthresh in tcp_init_metrics() tcp_metrics: do not create an entry from tcp_init_metrics() wifi: rtlwifi: fix EDCA limit set by BT coexistence can: dev: can_restart(): don't crash kernel if carrier is OK can: dev: can_restart(): fix race condition between controller restart and netif_carrier_on() PM / devfreq: rockchip-dfi: Make pmu regmap mandatory thermal: core: prevent potential string overflow r8169: use tp_to_dev instead of open code r8169: fix rare issue with broken rx after link-down on RTL8125 chtls: fix tp->rcv_tstamp initialization tcp: fix cookie_init_timestamp() overflows ACPI: sysfs: Fix create_pnp_modalias() and create_of_modalias() ipv6: avoid atomic fragment on GSO packets net: add DEV_STATS_READ() helper ipvlan: properly track tx_errors regmap: debugfs: Fix a erroneous check after snprintf() clk: qcom: clk-rcg2: Fix clock rate overflow for high parent frequencies clk: qcom: mmcc-msm8998: Add hardware clockgating registers to some clks clk: qcom: mmcc-msm8998: Don't check halt bit on some branch clks clk: qcom: mmcc-msm8998: Set bimc_smmu_gdsc always on clk: qcom: mmcc-msm8998: Fix the SMMU GDSC clk: qcom: gcc-sm8150: use ARRAY_SIZE instead of specifying num_parents clk: qcom: gcc-sm8150: Fix gcc_sdcc2_apps_clk_src clk: imx: Select MXC_CLK for CLK_IMX8QXP clk: imx: imx8mq: correct error handling path clk: asm9260: use parent index to link the reference clock clk: linux/clk-provider.h: fix kernel-doc warnings and typos spi: nxp-fspi: use the correct ioremap function clk: keystone: pll: fix a couple NULL vs IS_ERR() checks clk: ti: Add ti_dt_clk_name() helper to use clock-output-names clk: ti: Update pll and clockdomain clocks to use ti_dt_clk_name() clk: ti: Update component clocks to use ti_dt_clk_name() clk: ti: change ti_clk_register[_omap_hw]() API clk: ti: fix double free in of_ti_divider_clk_setup() clk: npcm7xx: Fix incorrect kfree clk: mediatek: clk-mt6765: Add check for mtk_alloc_clk_data clk: mediatek: clk-mt6779: Add check for mtk_alloc_clk_data clk: mediatek: clk-mt6797: Add check for mtk_alloc_clk_data clk: mediatek: clk-mt7629-eth: Add check for mtk_alloc_clk_data clk: mediatek: clk-mt7629: Add check for mtk_alloc_clk_data clk: mediatek: clk-mt2701: Add check for mtk_alloc_clk_data clk: qcom: config IPQ_APSS_6018 should depend on QCOM_SMEM platform/x86: wmi: Fix probe failure when failing to register WMI devices platform/x86: wmi: remove unnecessary initializations platform/x86: wmi: Fix opening of char device hwmon: (axi-fan-control) Support temperature vs pwm points hwmon: (axi-fan-control) Fix possible NULL pointer dereference hwmon: (coretemp) Fix potentially truncated sysfs attribute name drm/rockchip: vop: Fix reset of state in duplicate state crtc funcs drm/rockchip: vop: Fix call to crtc reset helper drm/radeon: possible buffer overflow drm/bridge: tc358768: Fix use of uninitialized variable drm/bridge: tc358768: Disable non-continuous clock mode drm/bridge: tc358768: Fix bit updates drm/mediatek: Fix iommu fault during crtc enabling drm/rockchip: cdn-dp: Fix some error handling paths in cdn_dp_probe() arm64/arm: xen: enlighten: Fix KPTI checks drm/rockchip: Fix type promotion bug in rockchip_gem_iommu_map() xen-pciback: Consider INTx disabled when MSI/MSI-X is enabled arm64: dts: qcom: msm8916: Fix iommu local address range arm64: dts: qcom: sdm845-mtp: fix WiFi configuration ARM: dts: qcom: mdm9615: populate vsdcc fixed regulator soc: qcom: llcc: Handle a second device without data corruption firmware: ti_sci: Mark driver as non removable clk: scmi: Free scmi_clk allocated when the clocks with invalid info are skipped selftests/pidfd: Fix ksft print formats selftests/resctrl: Ensure the benchmark commands fits to its array crypto: hisilicon/hpre - Fix a erroneous check after snprintf() hwrng: geode - fix accessing registers libnvdimm/of_pmem: Use devm_kstrdup instead of kstrdup and check its return value nd_btt: Make BTT lanes preemptible crypto: caam/qi2 - fix Chacha20 + Poly1305 self test failure crypto: caam/jr - fix Chacha20 + Poly1305 self test failure crypto: qat - mask device capabilities with soft straps crypto: qat - increase size of buffers hid: cp2112: Fix duplicate workqueue initialization ARM: 9321/1: memset: cast the constant byte to unsigned char ext4: move 'ix' sanity check to corrent position ASoC: fsl: mpc5200_dma.c: Fix warning of Function parameter or member not described IB/mlx5: Fix rdma counter binding for RAW QP RDMA/hns: Fix uninitialized ucmd in hns_roce_create_qp_common() RDMA/hns: Fix signed-unsigned mixed comparisons ASoC: fsl: Fix PM disable depth imbalance in fsl_easrc_probe scsi: ufs: core: Leave space for '\0' in utf8 desc string RDMA/hfi1: Workaround truncation compilation error hid: cp2112: Fix IRQ shutdown stopping polling for all IRQs on chip sh: bios: Revive earlyprintk support Revert "HID: logitech-hidpp: add a module parameter to keep firmware gestures" HID: logitech-hidpp: Remove HIDPP_QUIRK_NO_HIDINPUT quirk HID: logitech-hidpp: Don't restart IO, instead defer hid_connect() only HID: logitech-hidpp: Revert "Don't restart communication if not necessary" HID: logitech-hidpp: Move get_wireless_feature_index() check to hidpp_connect_event() ASoC: Intel: Skylake: Fix mem leak when parsing UUIDs fails padata: Convert from atomic_t to refcount_t on parallel_data->refcnt padata: Fix refcnt handling in padata_free_shell() ASoC: ams-delta.c: use component after check mfd: core: Un-constify mfd_cell.of_reg mfd: core: Ensure disabled devices are skipped without aborting mfd: dln2: Fix double put in dln2_probe leds: pwm: Don't disable the PWM when the LED should be off leds: trigger: ledtrig-cpu:: Fix 'output may be truncated' issue for 'cpu' tty: tty_jobctrl: fix pid memleak in disassociate_ctty() livepatch: Fix missing newline character in klp_resolve_symbols() usb: dwc2: fix possible NULL pointer dereference caused by driver concurrency dmaengine: ti: edma: handle irq_of_parse_and_map() errors misc: st_core: Do not call kfree_skb() under spin_lock_irqsave() tools: iio: privatize globals and functions in iio_generic_buffer.c file tools: iio: iio_generic_buffer: Fix some integer type and calculation tools: iio: iio_generic_buffer ensure alignment USB: usbip: fix stub_dev hub disconnect dmaengine: pxa_dma: Remove an erroneous BUG_ON() in pxad_free_desc() f2fs: fix to initialize map.m_pblk in f2fs_precache_extents() interconnect: qcom: sc7180: Retire DEFINE_QBCM interconnect: qcom: sc7180: Set ACV enable_mask modpost: fix tee MODULE_DEVICE_TABLE built on big-endian host powerpc/40x: Remove stale PTE_ATOMIC_UPDATES macro powerpc/xive: Fix endian conversion size powerpc/imc-pmu: Use the correct spinlock initializer. powerpc/pseries: fix potential memory leak in init_cpu_associativity() xhci: Loosen RPM as default policy to cover for AMD xHC 1.1 usb: host: xhci-plat: fix possible kernel oops while resuming perf machine: Avoid out of bounds LBR memory read perf hist: Add missing puts to hist__account_cycles i3c: Fix potential refcount leak in i3c_master_register_new_i3c_devs rtc: pcf85363: fix wrong mask/val parameters in regmap_update_bits call pcmcia: cs: fix possible hung task and memory leak pccardd() pcmcia: ds: fix refcount leak in pcmcia_device_add() pcmcia: ds: fix possible name leak in error path in pcmcia_device_add() media: i2c: max9286: Fix some redundant of_node_put() calls media: bttv: fix use after free error due to btv->timeout timer media: s3c-camif: Avoid inappropriate kfree() media: vidtv: psi: Add check for kstrdup media: vidtv: mux: Add check and kfree for kstrdup media: cedrus: Fix clock/reset sequence media: dvb-usb-v2: af9035: fix missing unlock regmap: prevent noinc writes from clobbering cache pwm: sti: Avoid conditional gotos pwm: sti: Reduce number of allocations and drop usage of chip_data pwm: brcmstb: Utilize appropriate clock APIs in suspend/resume Input: synaptics-rmi4 - fix use after free in rmi_unregister_function() llc: verify mac len before reading mac header hsr: Prevent use after free in prp_create_tagged_frame() tipc: Change nla_policy for bearer-related names to NLA_NUL_STRING inet: shrink struct flowi_common dccp: Call security_inet_conn_request() after setting IPv4 addresses. dccp/tcp: Call security_inet_conn_request() after setting IPv6 addresses. net: r8169: Disable multicast filter for RTL8168H and RTL8107E Fix termination state for idr_for_each_entry_ul() net: stmmac: xgmac: Enable support for multiple Flexible PPS outputs net/smc: fix dangling sock under state SMC_APPFINCLOSEWAIT net/smc: allow cdc msg send rather than drop it with NULL sndbuf_desc net/smc: put sk reference if close work was canceled tg3: power down device only on SYSTEM_POWER_OFF r8169: respect userspace disabling IFF_MULTICAST netfilter: xt_recent: fix (increase) ipv6 literal buffer length netfilter: nft_redir: use `struct nf_nat_range2` throughout and deduplicate eval call-backs netfilter: nat: fix ipv6 nat redirect with mapped and scoped addresses x86: Share definition of __is_canonical_address() x86/sev-es: Allow copy_from_kernel_nofault() in earlier boot drm/syncobj: fix DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE spi: spi-zynq-qspi: add spi-mem to driver kconfig dependencies fbdev: imsttfb: Fix error path of imsttfb_probe() fbdev: imsttfb: fix a resource leak in probe fbdev: fsl-diu-fb: mark wr_reg_wa() static tracing/kprobes: Fix the order of argument descriptions Revert "mmc: core: Capture correct oemid-bits for eMMC cards" btrfs: use u64 for buffer sizes in the tree search ioctls Linux 5.10.201 Change-Id: I0ce874e25eb6aeebf5826d6ef843fdbbf55d7c7d Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
218 lines
5.1 KiB
C
218 lines
5.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* System Control and Power Interface (SCMI) Protocol based clock driver
|
|
*
|
|
* Copyright (C) 2018-2020 ARM Ltd.
|
|
*/
|
|
|
|
#include <linux/clk-provider.h>
|
|
#include <linux/device.h>
|
|
#include <linux/err.h>
|
|
#include <linux/of.h>
|
|
#include <linux/module.h>
|
|
#include <linux/scmi_protocol.h>
|
|
#include <asm/div64.h>
|
|
|
|
static const struct scmi_clk_proto_ops *clk_ops;
|
|
|
|
struct scmi_clk {
|
|
u32 id;
|
|
struct clk_hw hw;
|
|
const struct scmi_clock_info *info;
|
|
const struct scmi_protocol_handle *ph;
|
|
};
|
|
|
|
#define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
|
|
|
|
static unsigned long scmi_clk_recalc_rate(struct clk_hw *hw,
|
|
unsigned long parent_rate)
|
|
{
|
|
int ret;
|
|
u64 rate;
|
|
struct scmi_clk *clk = to_scmi_clk(hw);
|
|
|
|
ret = clk_ops->rate_get(clk->ph, clk->id, &rate);
|
|
if (ret)
|
|
return 0;
|
|
return rate;
|
|
}
|
|
|
|
static long scmi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
|
|
unsigned long *parent_rate)
|
|
{
|
|
u64 fmin, fmax, ftmp;
|
|
struct scmi_clk *clk = to_scmi_clk(hw);
|
|
|
|
/*
|
|
* We can't figure out what rate it will be, so just return the
|
|
* rate back to the caller. scmi_clk_recalc_rate() will be called
|
|
* after the rate is set and we'll know what rate the clock is
|
|
* running at then.
|
|
*/
|
|
if (clk->info->rate_discrete)
|
|
return rate;
|
|
|
|
fmin = clk->info->range.min_rate;
|
|
fmax = clk->info->range.max_rate;
|
|
if (rate <= fmin)
|
|
return fmin;
|
|
else if (rate >= fmax)
|
|
return fmax;
|
|
|
|
ftmp = rate - fmin;
|
|
ftmp += clk->info->range.step_size - 1; /* to round up */
|
|
do_div(ftmp, clk->info->range.step_size);
|
|
|
|
return ftmp * clk->info->range.step_size + fmin;
|
|
}
|
|
|
|
static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
|
unsigned long parent_rate)
|
|
{
|
|
struct scmi_clk *clk = to_scmi_clk(hw);
|
|
|
|
return clk_ops->rate_set(clk->ph, clk->id, rate);
|
|
}
|
|
|
|
static int scmi_clk_enable(struct clk_hw *hw)
|
|
{
|
|
struct scmi_clk *clk = to_scmi_clk(hw);
|
|
|
|
return clk_ops->enable(clk->ph, clk->id);
|
|
}
|
|
|
|
static void scmi_clk_disable(struct clk_hw *hw)
|
|
{
|
|
struct scmi_clk *clk = to_scmi_clk(hw);
|
|
|
|
clk_ops->disable(clk->ph, clk->id);
|
|
}
|
|
|
|
static const struct clk_ops scmi_clk_ops = {
|
|
.recalc_rate = scmi_clk_recalc_rate,
|
|
.round_rate = scmi_clk_round_rate,
|
|
.set_rate = scmi_clk_set_rate,
|
|
/*
|
|
* We can't provide enable/disable callback as we can't perform the same
|
|
* in atomic context. Since the clock framework provides standard API
|
|
* clk_prepare_enable that helps cases using clk_enable in non-atomic
|
|
* context, it should be fine providing prepare/unprepare.
|
|
*/
|
|
.prepare = scmi_clk_enable,
|
|
.unprepare = scmi_clk_disable,
|
|
};
|
|
|
|
static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk)
|
|
{
|
|
int ret;
|
|
unsigned long min_rate, max_rate;
|
|
|
|
struct clk_init_data init = {
|
|
.flags = CLK_GET_RATE_NOCACHE,
|
|
.num_parents = 0,
|
|
.ops = &scmi_clk_ops,
|
|
.name = sclk->info->name,
|
|
};
|
|
|
|
sclk->hw.init = &init;
|
|
ret = devm_clk_hw_register(dev, &sclk->hw);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (sclk->info->rate_discrete) {
|
|
int num_rates = sclk->info->list.num_rates;
|
|
|
|
if (num_rates <= 0)
|
|
return -EINVAL;
|
|
|
|
min_rate = sclk->info->list.rates[0];
|
|
max_rate = sclk->info->list.rates[num_rates - 1];
|
|
} else {
|
|
min_rate = sclk->info->range.min_rate;
|
|
max_rate = sclk->info->range.max_rate;
|
|
}
|
|
|
|
clk_hw_set_rate_range(&sclk->hw, min_rate, max_rate);
|
|
return ret;
|
|
}
|
|
|
|
static int scmi_clocks_probe(struct scmi_device *sdev)
|
|
{
|
|
int idx, count, err;
|
|
struct clk_hw **hws;
|
|
struct clk_hw_onecell_data *clk_data;
|
|
struct device *dev = &sdev->dev;
|
|
struct device_node *np = dev->of_node;
|
|
const struct scmi_handle *handle = sdev->handle;
|
|
struct scmi_protocol_handle *ph;
|
|
|
|
if (!handle)
|
|
return -ENODEV;
|
|
|
|
clk_ops = handle->devm_get_protocol(sdev, SCMI_PROTOCOL_CLOCK, &ph);
|
|
if (IS_ERR(clk_ops))
|
|
return PTR_ERR(clk_ops);
|
|
|
|
count = clk_ops->count_get(ph);
|
|
if (count < 0) {
|
|
dev_err(dev, "%pOFn: invalid clock output count\n", np);
|
|
return -EINVAL;
|
|
}
|
|
|
|
clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, count),
|
|
GFP_KERNEL);
|
|
if (!clk_data)
|
|
return -ENOMEM;
|
|
|
|
clk_data->num = count;
|
|
hws = clk_data->hws;
|
|
|
|
for (idx = 0; idx < count; idx++) {
|
|
struct scmi_clk *sclk;
|
|
|
|
sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL);
|
|
if (!sclk)
|
|
return -ENOMEM;
|
|
|
|
sclk->info = clk_ops->info_get(ph, idx);
|
|
if (!sclk->info) {
|
|
dev_dbg(dev, "invalid clock info for idx %d\n", idx);
|
|
devm_kfree(dev, sclk);
|
|
continue;
|
|
}
|
|
|
|
sclk->id = idx;
|
|
sclk->ph = ph;
|
|
|
|
err = scmi_clk_ops_init(dev, sclk);
|
|
if (err) {
|
|
dev_err(dev, "failed to register clock %d\n", idx);
|
|
devm_kfree(dev, sclk);
|
|
hws[idx] = NULL;
|
|
} else {
|
|
dev_dbg(dev, "Registered clock:%s\n", sclk->info->name);
|
|
hws[idx] = &sclk->hw;
|
|
}
|
|
}
|
|
|
|
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
|
|
clk_data);
|
|
}
|
|
|
|
static const struct scmi_device_id scmi_id_table[] = {
|
|
{ SCMI_PROTOCOL_CLOCK, "clocks" },
|
|
{ },
|
|
};
|
|
MODULE_DEVICE_TABLE(scmi, scmi_id_table);
|
|
|
|
static struct scmi_driver scmi_clocks_driver = {
|
|
.name = "scmi-clocks",
|
|
.probe = scmi_clocks_probe,
|
|
.id_table = scmi_id_table,
|
|
};
|
|
module_scmi_driver(scmi_clocks_driver);
|
|
|
|
MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
|
|
MODULE_DESCRIPTION("ARM SCMI clock driver");
|
|
MODULE_LICENSE("GPL v2");
|