From 3de7b83017bd93d521dc29f475f4c8fc5d61e518 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Mon, 7 Sep 2020 01:04:52 +0200 Subject: firmware: arm_scmi: Constify static scmi-ops These are never modified, so make them const to allow the compiler to put them in read-only memory. Link: https://lore.kernel.org/r/20200906230452.33410-4-rikard.falkeborn@gmail.com Signed-off-by: Rikard Falkeborn Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/clock.c | 2 +- drivers/firmware/arm_scmi/common.h | 2 +- drivers/firmware/arm_scmi/mailbox.c | 2 +- drivers/firmware/arm_scmi/notify.c | 2 +- drivers/firmware/arm_scmi/perf.c | 2 +- drivers/firmware/arm_scmi/power.c | 2 +- drivers/firmware/arm_scmi/reset.c | 2 +- drivers/firmware/arm_scmi/sensors.c | 2 +- drivers/firmware/arm_scmi/smc.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index 75e39882746e..a3b90be28009 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -318,7 +318,7 @@ scmi_clock_info_get(const struct scmi_handle *handle, u32 clk_id) return clk; } -static struct scmi_clk_ops clk_ops = { +static const struct scmi_clk_ops clk_ops = { .count_get = scmi_clock_count_get, .info_get = scmi_clock_info_get, .rate_get = scmi_clock_rate_get, diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index c113e578cc6c..233700a42bff 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -210,7 +210,7 @@ struct scmi_transport_ops { * @max_msg_size: Maximum size of data per message that can be handled. */ struct scmi_desc { - struct scmi_transport_ops *ops; + const struct scmi_transport_ops *ops; int max_rx_timeout_ms; int max_msg; int max_msg_size; diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c index 6998dc86b5ce..cc2de207fe10 100644 --- a/drivers/firmware/arm_scmi/mailbox.c +++ b/drivers/firmware/arm_scmi/mailbox.c @@ -181,7 +181,7 @@ mailbox_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) return shmem_poll_done(smbox->shmem, xfer); } -static struct scmi_transport_ops scmi_mailbox_ops = { +static const struct scmi_transport_ops scmi_mailbox_ops = { .chan_available = mailbox_chan_available, .chan_setup = mailbox_chan_setup, .chan_free = mailbox_chan_free, diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c index 4731daaacd19..2754f9d01636 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -1421,7 +1421,7 @@ static void scmi_protocols_late_init(struct work_struct *work) * notify_ops are attached to the handle so that can be accessed * directly from an scmi_driver to register its own notifiers. */ -static struct scmi_notify_ops notify_ops = { +static const struct scmi_notify_ops notify_ops = { .register_event_notifier = scmi_register_notifier, .unregister_event_notifier = scmi_unregister_notifier, }; diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index 3e1e87012c95..a3e7b1bfab00 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -748,7 +748,7 @@ static bool scmi_fast_switch_possible(const struct scmi_handle *handle, return dom->fc_info && dom->fc_info->level_set_addr; } -static struct scmi_perf_ops perf_ops = { +static const struct scmi_perf_ops perf_ops = { .limits_set = scmi_perf_limits_set, .limits_get = scmi_perf_limits_get, .level_set = scmi_perf_level_set, diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index 46f213644c49..32bcf5821ea9 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -184,7 +184,7 @@ static char *scmi_power_name_get(const struct scmi_handle *handle, u32 domain) return dom->name; } -static struct scmi_power_ops power_ops = { +static const struct scmi_power_ops power_ops = { .num_domains_get = scmi_power_num_domains_get, .name_get = scmi_power_name_get, .state_set = scmi_power_state_set, diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c index 3691bafca057..4e2dc5fc43d9 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -194,7 +194,7 @@ scmi_reset_domain_deassert(const struct scmi_handle *handle, u32 domain) return scmi_domain_reset(handle, domain, 0, ARCH_COLD_RESET); } -static struct scmi_reset_ops reset_ops = { +static const struct scmi_reset_ops reset_ops = { .num_domains_get = scmi_reset_num_domains_get, .name_get = scmi_reset_name_get, .latency_get = scmi_reset_latency_get, diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index 1af0ad362e82..7d83680198de 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -275,7 +275,7 @@ static int scmi_sensor_count_get(const struct scmi_handle *handle) return si->num_sensors; } -static struct scmi_sensor_ops sensor_ops = { +static const struct scmi_sensor_ops sensor_ops = { .count_get = scmi_sensor_count_get, .info_get = scmi_sensor_info_get, .trip_point_config = scmi_sensor_trip_point_config, diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c index a1537d123e38..1a03c3ec0230 100644 --- a/drivers/firmware/arm_scmi/smc.c +++ b/drivers/firmware/arm_scmi/smc.c @@ -137,7 +137,7 @@ smc_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) return shmem_poll_done(scmi_info->shmem, xfer); } -static struct scmi_transport_ops scmi_smc_ops = { +static const struct scmi_transport_ops scmi_smc_ops = { .chan_available = smc_chan_available, .chan_setup = smc_chan_setup, .chan_free = smc_chan_free, -- cgit v1.2.3 From a8803055127afb87640974adedac60435592b86d Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 7 Sep 2020 18:46:55 +0100 Subject: firmware: arm_scmi: Add system power protocol support Add bare protocol support for SCMI system power protocol as needed by an OSPM agent: basic initialization and SYSTEM_POWER_STATE_NOTIFIER core notification support. No event-handling logic is attached to such notification.. Link: https://lore.kernel.org/r/20200907174657.32466-2-cristian.marussi@arm.com Signed-off-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/Makefile | 2 +- drivers/firmware/arm_scmi/system.c | 136 +++++++++++++++++++++++++++++++++++++ include/linux/scmi_protocol.h | 18 +++++ 3 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/arm_scmi/system.c (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index 6f9cbc4aef22..643f2320f976 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -5,5 +5,5 @@ scmi-driver-y = driver.o notify.o scmi-transport-y = shmem.o scmi-transport-$(CONFIG_MAILBOX) += mailbox.o scmi-transport-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smc.o -scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o +scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c new file mode 100644 index 000000000000..aa1e74f066a0 --- /dev/null +++ b/drivers/firmware/arm_scmi/system.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * System Control and Management Interface (SCMI) System Power Protocol + * + * Copyright (C) 2020 ARM Ltd. + */ + +#define pr_fmt(fmt) "SCMI Notifications SYSTEM - " fmt + +#include + +#include "common.h" +#include "notify.h" + +#define SCMI_SYSTEM_NUM_SOURCES 1 + +enum scmi_system_protocol_cmd { + SYSTEM_POWER_STATE_NOTIFY = 0x5, +}; + +struct scmi_system_power_state_notify { + __le32 notify_enable; +}; + +struct scmi_system_power_state_notifier_payld { + __le32 agent_id; + __le32 flags; + __le32 system_state; +}; + +struct scmi_system_info { + u32 version; +}; + +static int scmi_system_request_notify(const struct scmi_handle *handle, + bool enable) +{ + int ret; + struct scmi_xfer *t; + struct scmi_system_power_state_notify *notify; + + ret = scmi_xfer_get_init(handle, SYSTEM_POWER_STATE_NOTIFY, + SCMI_PROTOCOL_SYSTEM, sizeof(*notify), 0, &t); + if (ret) + return ret; + + notify = t->tx.buf; + notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; + + ret = scmi_do_xfer(handle, t); + + scmi_xfer_put(handle, t); + return ret; +} + +static int scmi_system_set_notify_enabled(const struct scmi_handle *handle, + u8 evt_id, u32 src_id, bool enable) +{ + int ret; + + ret = scmi_system_request_notify(handle, enable); + if (ret) + pr_debug("FAIL_ENABLE - evt[%X] - ret:%d\n", evt_id, ret); + + return ret; +} + +static void *scmi_system_fill_custom_report(const struct scmi_handle *handle, + u8 evt_id, ktime_t timestamp, + const void *payld, size_t payld_sz, + void *report, u32 *src_id) +{ + const struct scmi_system_power_state_notifier_payld *p = payld; + struct scmi_system_power_state_notifier_report *r = report; + + if (evt_id != SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER || + sizeof(*p) != payld_sz) + return NULL; + + r->timestamp = timestamp; + r->agent_id = le32_to_cpu(p->agent_id); + r->flags = le32_to_cpu(p->flags); + r->system_state = le32_to_cpu(p->system_state); + *src_id = 0; + + return r; +} + +static const struct scmi_event system_events[] = { + { + .id = SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER, + .max_payld_sz = + sizeof(struct scmi_system_power_state_notifier_payld), + .max_report_sz = + sizeof(struct scmi_system_power_state_notifier_report), + }, +}; + +static const struct scmi_event_ops system_event_ops = { + .set_notify_enabled = scmi_system_set_notify_enabled, + .fill_custom_report = scmi_system_fill_custom_report, +}; + +static int scmi_system_protocol_init(struct scmi_handle *handle) +{ + u32 version; + struct scmi_system_info *pinfo; + + scmi_version_get(handle, SCMI_PROTOCOL_SYSTEM, &version); + + dev_dbg(handle->dev, "System Power Version %d.%d\n", + PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); + + pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL); + if (!pinfo) + return -ENOMEM; + + scmi_register_protocol_events(handle, + SCMI_PROTOCOL_SYSTEM, SCMI_PROTO_QUEUE_SZ, + &system_event_ops, + system_events, + ARRAY_SIZE(system_events), + SCMI_SYSTEM_NUM_SOURCES); + + pinfo->version = version; + handle->system_priv = pinfo; + + return 0; +} + +static int __init scmi_system_init(void) +{ + return scmi_protocol_register(SCMI_PROTOCOL_SYSTEM, + &scmi_system_protocol_init); +} +subsys_initcall(scmi_system_init); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 05570afc7f74..4b10093ad671 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -292,6 +292,7 @@ struct scmi_handle { void *sensor_priv; void *reset_priv; void *notify_priv; + void *system_priv; }; enum scmi_std_protocol { @@ -304,6 +305,15 @@ enum scmi_std_protocol { SCMI_PROTOCOL_RESET = 0x16, }; +enum scmi_system_events { + SCMI_SYSTEM_SHUTDOWN, + SCMI_SYSTEM_COLDRESET, + SCMI_SYSTEM_WARMRESET, + SCMI_SYSTEM_POWERUP, + SCMI_SYSTEM_SUSPEND, + SCMI_SYSTEM_MAX +}; + struct scmi_device { u32 id; u8 protocol_id; @@ -378,6 +388,7 @@ enum scmi_notification_events { SCMI_EVENT_SENSOR_TRIP_POINT_EVENT = 0x0, SCMI_EVENT_RESET_ISSUED = 0x0, SCMI_EVENT_BASE_ERROR_EVENT = 0x0, + SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER = 0x0, }; struct scmi_power_state_changed_report { @@ -387,6 +398,13 @@ struct scmi_power_state_changed_report { unsigned int power_state; }; +struct scmi_system_power_state_notifier_report { + ktime_t timestamp; + unsigned int agent_id; + unsigned int flags; + unsigned int system_state; +}; + struct scmi_perf_limits_report { ktime_t timestamp; unsigned int agent_id; -- cgit v1.2.3 From 481f6ccf399b4e3c8ff6d2cc2b7b1a384d86b2ad Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 7 Sep 2020 18:46:56 +0100 Subject: firmware: arm_scmi: Add SCMI device for system power protocol Add SCMI device for system power protocol by just adding the name "syspower" to the list of supported core protocol devices. Link: https://lore.kernel.org/r/20200907174657.32466-3-cristian.marussi@arm.com Signed-off-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 03ec74242c14..dbec34423f72 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -730,6 +730,7 @@ struct scmi_prot_devnames { static struct scmi_prot_devnames devnames[] = { { SCMI_PROTOCOL_POWER, { "genpd" },}, + { SCMI_PROTOCOL_SYSTEM, { "syspower" },}, { SCMI_PROTOCOL_PERF, { "cpufreq" },}, { SCMI_PROTOCOL_CLOCK, { "clocks" },}, { SCMI_PROTOCOL_SENSOR, { "hwmon" },}, -- cgit v1.2.3 From 6ed6c558234f0b6c22e47a3c2feddce3d02324dd Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 8 Sep 2020 12:26:11 +0100 Subject: firmware: arm_scmi: Fix NULL pointer dereference in mailbox_chan_free scmi_mailbox is obtained from cinfo->transport_info and the first call to mailbox_chan_free frees the channel and sets cinfo->transport_info to NULL. Care is taken to check for non NULL smbox->chan but smbox can itself be NULL. Fix it by checking for it without which, kernel crashes with below NULL pointer dereference and eventually kernel panic. Unable to handle kernel NULL pointer dereference at virtual address 0000000000000038 Modules linked in: scmi_module(-) Hardware name: ARM LTD ARM Juno Development Platform/ARM Juno Development Platform, BIOS EDK II Sep 2 2020 pstate: 80000005 (Nzcv daif -PAN -UAO BTYPE=--) pc : mailbox_chan_free+0x2c/0x70 [scmi_module] lr : idr_for_each+0x6c/0xf8 Call trace: mailbox_chan_free+0x2c/0x70 [scmi_module] idr_for_each+0x6c/0xf8 scmi_remove+0xa8/0xf0 [scmi_module] platform_drv_remove+0x34/0x58 device_release_driver_internal+0x118/0x1f0 driver_detach+0x58/0xe8 bus_remove_driver+0x64/0xe0 driver_unregister+0x38/0x68 platform_driver_unregister+0x1c/0x28 scmi_driver_exit+0x38/0x44 [scmi_module] ---[ end trace 17bde19f50436de9 ]--- Kernel panic - not syncing: Fatal exception SMP: stopping secondary CPUs Kernel Offset: 0x1d0000 from 0xffff800010000000 PHYS_OFFSET: 0x80000000 CPU features: 0x0240022,25806004 Memory Limit: none ---[ end Kernel panic - not syncing: Fatal exception ]--- Link: https://lore.kernel.org/r/20200908112611.31515-1-sudeep.holla@arm.com Fixes: 5c8a47a5a91d ("firmware: arm_scmi: Make scmi core independent of the transport type") Cc: Cristian Marussi Cc: Viresh Kumar Tested-by: Cristian Marussi Reviewed-by: Cristian Marussi Reviewed-by: Viresh Kumar Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/mailbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c index cc2de207fe10..4626404be541 100644 --- a/drivers/firmware/arm_scmi/mailbox.c +++ b/drivers/firmware/arm_scmi/mailbox.c @@ -110,7 +110,7 @@ static int mailbox_chan_free(int id, void *p, void *data) struct scmi_chan_info *cinfo = p; struct scmi_mailbox *smbox = cinfo->transport_info; - if (!IS_ERR(smbox->chan)) { + if (smbox && !IS_ERR(smbox->chan)) { mbox_free_channel(smbox->chan); cinfo->transport_info = NULL; smbox->chan = NULL; -- cgit v1.2.3 From 71b610825f4b2130901c7b6fbf4063f03350bcb9 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 11 Sep 2020 21:47:08 -0700 Subject: firmware: ti_sci: allow frequency change for disabled clocks by default If a clock is disabled, its frequency should be allowed to change as it is no longer in use. Add a flag towards this to the firmware clock API handler routines. Acked-by: Nishanth Menon Tested-by: Tomi Valkeinen Signed-off-by: Tero Kristo Signed-off-by: Santosh Shilimkar --- drivers/firmware/ti_sci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 53cee17d0115..39890665a975 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -1124,7 +1124,8 @@ static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id, static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle, u32 dev_id, u32 clk_id) { - return ti_sci_set_clock_state(handle, dev_id, clk_id, 0, + return ti_sci_set_clock_state(handle, dev_id, clk_id, + MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE, MSG_CLOCK_SW_STATE_UNREQ); } @@ -1143,7 +1144,8 @@ static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle, static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle, u32 dev_id, u32 clk_id) { - return ti_sci_set_clock_state(handle, dev_id, clk_id, 0, + return ti_sci_set_clock_state(handle, dev_id, clk_id, + MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE, MSG_CLOCK_SW_STATE_AUTO); } -- cgit v1.2.3 From e2314cf5af30d5e87cbf89fdef1a0fe4efee4552 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 8 Sep 2020 18:07:01 +0800 Subject: firmware: imx: scu-pd: ignore power domain not owned Should not register power domain that not owned by current partition. Alought power domains will not be registered when power on failure, we have to let CPU waste more cycles. Whether power on or owned check, both need communicate with SCU, but with owned check, we no need to run more code path to save CPU cycles. Signed-off-by: Peng Fan Reviewed-by: Leonard Crestez Signed-off-by: Shawn Guo --- drivers/firmware/imx/scu-pd.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/firmware') diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index af3d6d9ead28..946eea292b52 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -46,6 +46,7 @@ #include #include +#include #include #include #include @@ -256,6 +257,9 @@ imx_scu_add_pm_domain(struct device *dev, int idx, struct imx_sc_pm_domain *sc_pd; int ret; + if (!imx_sc_rm_is_resource_owned(pm_ipc_handle, pd_ranges->rsrc + idx)) + return NULL; + sc_pd = devm_kzalloc(dev, sizeof(*sc_pd), GFP_KERNEL); if (!sc_pd) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From 6825f17c950ca5691a057fa71bb1b649b7434014 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 23 Jun 2020 15:33:57 +0100 Subject: firmware: smccc: Export both smccc functions We need to export both arm_smccc_1_1_get_conduit and arm_smccc_get_version to allow several modules make use of them. Arm FFA, Arm SCMI and PTP drivers are few drivers that are planning to use these functions. Let us export them in preparation to add support for SCMI as module. Link: https://lore.kernel.org/r/20200907195046.56615-2-sudeep.holla@arm.com Signed-off-by: Sudeep Holla --- drivers/firmware/smccc/smccc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/firmware') diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c index 4e80921ee212..00c88b809c0c 100644 --- a/drivers/firmware/smccc/smccc.c +++ b/drivers/firmware/smccc/smccc.c @@ -24,8 +24,10 @@ enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void) return smccc_conduit; } +EXPORT_SYMBOL_GPL(arm_smccc_1_1_get_conduit); u32 arm_smccc_get_version(void) { return smccc_version; } +EXPORT_SYMBOL_GPL(arm_smccc_get_version); -- cgit v1.2.3 From 5a2f0a0bdf201e2183904b6217f9c74774c961a8 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 7 Sep 2020 12:00:04 +0100 Subject: firmware: arm_scmi: Move scmi bus init and exit calls into the driver In preparation to enable building scmi as a single module, let us move the scmi bus {de-,}initialisation call into the driver. The main reason for this is to keep it simple instead of maintaining it as separate modules and dealing with all possible initcall races and deferred probe handling. We can move it as separate modules if needed in future. Link: https://lore.kernel.org/r/20200907195046.56615-3-sudeep.holla@arm.com Tested-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/bus.c | 6 ++---- drivers/firmware/arm_scmi/common.h | 3 +++ drivers/firmware/arm_scmi/driver.c | 16 +++++++++++++++- 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index db55c43a2cbd..1377ec76a45d 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -230,7 +230,7 @@ static void scmi_devices_unregister(void) bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister); } -static int __init scmi_bus_init(void) +int __init scmi_bus_init(void) { int retval; @@ -240,12 +240,10 @@ static int __init scmi_bus_init(void) return retval; } -subsys_initcall(scmi_bus_init); -static void __exit scmi_bus_exit(void) +void __exit scmi_bus_exit(void) { scmi_devices_unregister(); bus_unregister(&scmi_bus_type); ida_destroy(&scmi_bus_id); } -module_exit(scmi_bus_exit); diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 233700a42bff..a940c6cf1e51 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -156,6 +156,9 @@ void scmi_setup_protocol_implemented(const struct scmi_handle *handle, int scmi_base_protocol_init(struct scmi_handle *h); +int __init scmi_bus_init(void); +void __exit scmi_bus_exit(void); + /* SCMI Transport */ /** * struct scmi_chan_info - Structure representing a SCMI channel information diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index dbec34423f72..8f60c6a97cc3 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -929,7 +929,21 @@ static struct platform_driver scmi_driver = { .remove = scmi_remove, }; -module_platform_driver(scmi_driver); +static int __init scmi_driver_init(void) +{ + scmi_bus_init(); + + return platform_driver_register(&scmi_driver); +} +module_init(scmi_driver_init); + +static void __exit scmi_driver_exit(void) +{ + scmi_bus_exit(); + + platform_driver_unregister(&scmi_driver); +} +module_exit(scmi_driver_exit); MODULE_ALIAS("platform: arm-scmi"); MODULE_AUTHOR("Sudeep Holla "); -- cgit v1.2.3 From 1eaf18e35a783a007ef03e09f1dfc3de81eace7c Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 7 Sep 2020 12:06:01 +0100 Subject: firmware: arm_scmi: Move scmi protocols registration into the driver In preparation to enable building SCMI as a single module, let us move the SCMI protocol registration call into the driver. This enables us to also add unregistration of the SCMI protocols. The main reason for this is to keep it simple instead of maintaining it as separate modules and dealing with all possible initcall races and deferred probe handling. We can move it as separate modules if needed in future. Link: https://lore.kernel.org/r/20200907195046.56615-4-sudeep.holla@arm.com Tested-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/clock.c | 7 +------ drivers/firmware/arm_scmi/common.h | 21 +++++++++++++++++++++ drivers/firmware/arm_scmi/driver.c | 16 +++++++++++++++- drivers/firmware/arm_scmi/perf.c | 7 +------ drivers/firmware/arm_scmi/power.c | 7 +------ drivers/firmware/arm_scmi/reset.c | 7 +------ drivers/firmware/arm_scmi/sensors.c | 7 +------ drivers/firmware/arm_scmi/system.c | 7 +------ 8 files changed, 42 insertions(+), 37 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index a3b90be28009..c1cfe3ee3d55 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -364,9 +364,4 @@ static int scmi_clock_protocol_init(struct scmi_handle *handle) return 0; } -static int __init scmi_clock_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_CLOCK, - &scmi_clock_protocol_init); -} -subsys_initcall(scmi_clock_init); +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_CLOCK, clock) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index a940c6cf1e51..37fb583f1bf5 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -159,6 +159,27 @@ int scmi_base_protocol_init(struct scmi_handle *h); int __init scmi_bus_init(void); void __exit scmi_bus_exit(void); +#define DECLARE_SCMI_REGISTER_UNREGISTER(func) \ + int __init scmi_##func##_register(void); \ + void __exit scmi_##func##_unregister(void) +DECLARE_SCMI_REGISTER_UNREGISTER(clock); +DECLARE_SCMI_REGISTER_UNREGISTER(perf); +DECLARE_SCMI_REGISTER_UNREGISTER(power); +DECLARE_SCMI_REGISTER_UNREGISTER(reset); +DECLARE_SCMI_REGISTER_UNREGISTER(sensors); +DECLARE_SCMI_REGISTER_UNREGISTER(system); + +#define DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(id, name) \ +int __init scmi_##name##_register(void) \ +{ \ + return scmi_protocol_register((id), &scmi_##name##_protocol_init); \ +} \ +\ +void __exit scmi_##name##_unregister(void) \ +{ \ + scmi_protocol_unregister((id)); \ +} + /* SCMI Transport */ /** * struct scmi_chan_info - Structure representing a SCMI channel information diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 8f60c6a97cc3..c5dea87edf8f 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -933,14 +933,28 @@ static int __init scmi_driver_init(void) { scmi_bus_init(); + scmi_clock_register(); + scmi_perf_register(); + scmi_power_register(); + scmi_reset_register(); + scmi_sensors_register(); + scmi_system_register(); + return platform_driver_register(&scmi_driver); } -module_init(scmi_driver_init); +subsys_initcall(scmi_driver_init); static void __exit scmi_driver_exit(void) { scmi_bus_exit(); + scmi_clock_unregister(); + scmi_perf_unregister(); + scmi_power_unregister(); + scmi_reset_unregister(); + scmi_sensors_unregister(); + scmi_system_unregister(); + platform_driver_unregister(&scmi_driver); } module_exit(scmi_driver_exit); diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index a3e7b1bfab00..ed475b40bd08 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -890,9 +890,4 @@ static int scmi_perf_protocol_init(struct scmi_handle *handle) return 0; } -static int __init scmi_perf_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_PERF, - &scmi_perf_protocol_init); -} -subsys_initcall(scmi_perf_init); +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_PERF, perf) diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index 32bcf5821ea9..1f37258e9bee 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -301,9 +301,4 @@ static int scmi_power_protocol_init(struct scmi_handle *handle) return 0; } -static int __init scmi_power_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_POWER, - &scmi_power_protocol_init); -} -subsys_initcall(scmi_power_init); +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_POWER, power) diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c index 4e2dc5fc43d9..f063cfe17e02 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -313,9 +313,4 @@ static int scmi_reset_protocol_init(struct scmi_handle *handle) return 0; } -static int __init scmi_reset_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_RESET, - &scmi_reset_protocol_init); -} -subsys_initcall(scmi_reset_init); +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_RESET, reset) diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index 7d83680198de..9703cf6356a0 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -365,9 +365,4 @@ static int scmi_sensors_protocol_init(struct scmi_handle *handle) return 0; } -static int __init scmi_sensors_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_SENSOR, - &scmi_sensors_protocol_init); -} -subsys_initcall(scmi_sensors_init); +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_SENSOR, sensors) diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c index aa1e74f066a0..283e12d5f24b 100644 --- a/drivers/firmware/arm_scmi/system.c +++ b/drivers/firmware/arm_scmi/system.c @@ -128,9 +128,4 @@ static int scmi_system_protocol_init(struct scmi_handle *handle) return 0; } -static int __init scmi_system_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_SYSTEM, - &scmi_system_protocol_init); -} -subsys_initcall(scmi_system_init); +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_SYSTEM, system) -- cgit v1.2.3 From 66d90f6ecee755e9c19a119c9255e80091165498 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 7 Sep 2020 12:09:23 +0100 Subject: firmware: arm_scmi: Enable building as a single module Now, with all the plumbing in place to enable building scmi as a module instead of built-in modules, let us enable the same. Link: https://lore.kernel.org/r/20200907195046.56615-5-sudeep.holla@arm.com Tested-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/Kconfig | 2 +- drivers/firmware/Makefile | 2 +- drivers/firmware/arm_scmi/Makefile | 4 +++- include/linux/scmi_protocol.h | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index fbd785dd0513..afdbebba628a 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -7,7 +7,7 @@ menu "Firmware Drivers" config ARM_SCMI_PROTOCOL - bool "ARM System Control and Management Interface (SCMI) Message Protocol" + tristate "ARM System Control and Management Interface (SCMI) Message Protocol" depends on ARM || ARM64 || COMPILE_TEST depends on MAILBOX help diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 99510be9f5ed..5e013b6a3692 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o -obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/ +obj-y += arm_scmi/ obj-y += broadcom/ obj-y += meson/ obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index 643f2320f976..bc0d54f8e861 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -1,9 +1,11 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o scmi-transport.o scmi-bus-y = bus.o scmi-driver-y = driver.o notify.o scmi-transport-y = shmem.o scmi-transport-$(CONFIG_MAILBOX) += mailbox.o scmi-transport-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smc.o scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o +scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \ + $(scmi-transport-y) +obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 4b10093ad671..9cd312a1ff92 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -345,7 +345,7 @@ struct scmi_driver { #define to_scmi_driver(d) container_of(d, struct scmi_driver, driver) -#ifdef CONFIG_ARM_SCMI_PROTOCOL +#if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL) int scmi_driver_register(struct scmi_driver *driver, struct module *owner, const char *mod_name); void scmi_driver_unregister(struct scmi_driver *driver); -- cgit v1.2.3 From 0ebdf11699d0491c0a1eee5bb5d920f4f36810ba Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 17 Sep 2020 12:07:51 +0200 Subject: firmware: tegra: Enable BPMP support on Tegra234 Enable support for the BPMP on Tegra234 to avoid relying on Tegra194 being enabled to pull in the needed OF device ID table entry. On simulation platforms the BPMP hasn't booted up yet by the time we probe the BPMP driver and the BPMP hasn't had a chance to mark the doorbell as ringable by the CCPLEX. This corresponding check in the BPMP driver will therefore fail. Work around this by disabling the check on simulation platforms. Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/firmware/tegra/bpmp.c | 3 ++- drivers/mailbox/tegra-hsp.c | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c index 4d93d8925e14..0742a90cb844 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c @@ -856,7 +856,8 @@ static const struct tegra_bpmp_soc tegra210_soc = { static const struct of_device_id tegra_bpmp_match[] = { #if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \ - IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) + IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \ + IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC) { .compatible = "nvidia,tegra186-bpmp", .data = &tegra186_soc }, #endif #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c index 834b35dc3b13..e07091d71986 100644 --- a/drivers/mailbox/tegra-hsp.c +++ b/drivers/mailbox/tegra-hsp.c @@ -13,6 +13,8 @@ #include #include +#include + #include #include "mailbox.h" @@ -322,7 +324,12 @@ static int tegra_hsp_doorbell_startup(struct mbox_chan *chan) if (!ccplex) return -ENODEV; - if (!tegra_hsp_doorbell_can_ring(db)) + /* + * On simulation platforms the BPMP hasn't had a chance yet to mark + * the doorbell as ringable by the CCPLEX, so we want to skip extra + * checks here. + */ + if (tegra_is_silicon() && !tegra_hsp_doorbell_can_ring(db)) return -ENODEV; spin_lock_irqsave(&hsp->lock, flags); -- cgit v1.2.3