Skip to content

Commit

Permalink
Merge tag 'pmdomain-v6.15' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/ulfh/linux-pm

Pull pmdomain updates from Ulf Hansson:
 "pmdomain core:
   - Add dev_pm_genpd_rpm_always_on() to support more fine-grained PM

  pmdomain providers:
   - arm: Remove redundant state verification for the SCMI PM domain
   - bcm: Add system-wakeup support for bcm2835 via GENPD_FLAG_ACTIVE_WAKEUP
   - rockchip: Add support for regulators
   - rockchip: Use SMC call to properly inform firmware
   - sunxi: Add V853 ppu support
   - thead: Add support for RISC-V TH1520 power-domains

  firmware:
   - Add support for the AON firmware protocol for RISC-V THEAD

  cpuidle-psci:
   - Update section in MAINTAINERS for cpuidle-psci
   - Add trace support for PSCI domain-idlestates"

* tag 'pmdomain-v6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm: (29 commits)
  firmware: thead: add CONFIG_MAILBOX dependency
  firmware: thead,th1520-aon: Fix use after free in th1520_aon_init()
  pmdomain: arm: scmi_pm_domain: Remove redundant state verification
  pmdomain: thead: fix TH1520_AON_PROTOCOL dependency
  pmdomain: thead: Add power-domain driver for TH1520
  dt-bindings: power: Add TH1520 SoC power domains
  firmware: thead: Add AON firmware protocol driver
  dt-bindings: firmware: thead,th1520: Add support for firmware node
  pmdomain: rockchip: add regulator dependency
  pmdomain: rockchip: add regulator support
  pmdomain: rockchip: fix rockchip_pd_power error handling
  pmdomain: rockchip: reduce indentation in rockchip_pd_power
  pmdomain: rockchip: forward rockchip_do_pmu_set_power_domain errors
  pmdomain: rockchip: cleanup mutex handling in rockchip_pd_power
  dt-bindings: power: rockchip: add regulator support
  pmdomain: rockchip: Fix build error
  pmdomain: imx: gpcv2: use proper helper for property detection
  MAINTAINERS: Update section for cpuidle-psci
  pmdomain: rockchip: Check if SMC could be handled by TA
  cpuidle: psci: Add trace for PSCI domain idle
  ...
  • Loading branch information
Linus Torvalds committed Mar 26, 2025
2 parents 0163c88 + 51f0b89 commit 2a2274e
Show file tree
Hide file tree
Showing 29 changed files with 1,032 additions and 83 deletions.
53 changes: 53 additions & 0 deletions Documentation/devicetree/bindings/firmware/thead,th1520-aon.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/firmware/thead,th1520-aon.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: T-HEAD TH1520 AON (Always-On) Firmware

description: |
The Always-On (AON) subsystem in the TH1520 SoC is responsible for managing
low-power states, system wakeup events, and power management tasks. It is
designed to operate independently in a dedicated power domain, allowing it to
remain functional even during the SoC's deep sleep states.
At the heart of the AON subsystem is the E902, a low-power core that executes
firmware responsible for coordinating tasks such as power domain control,
clock management, and system wakeup signaling. Communication between the main
SoC and the AON subsystem is handled through a mailbox interface, which
enables message-based interactions with the AON firmware.
maintainers:
- Michal Wilczynski <m.wilczynski@samsung.com>

properties:
compatible:
const: thead,th1520-aon

mboxes:
maxItems: 1

mbox-names:
items:
- const: aon

"#power-domain-cells":
const: 1

required:
- compatible
- mboxes
- mbox-names
- "#power-domain-cells"

additionalProperties: false

examples:
- |
aon: aon {
compatible = "thead,th1520-aon";
mboxes = <&mbox_910t 1>;
mbox-names = "aon";
#power-domain-cells = <1>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ properties:
compatible:
enum:
- allwinner,sun20i-d1-ppu
- allwinner,sun8i-v853-ppu

reg:
maxItems: 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ $defs:
A number of phandles to clocks that need to be enabled
while power domain switches state.
domain-supply:
description: domain regulator supply.

pm_qos:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
Expand Down
7 changes: 7 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -6103,9 +6103,11 @@ F: include/linux/platform_data/cpuidle-exynos.h
CPUIDLE DRIVER - ARM PSCI
M: Lorenzo Pieralisi <lpieralisi@kernel.org>
M: Sudeep Holla <sudeep.holla@arm.com>
M: Ulf Hansson <ulf.hansson@linaro.org>
L: linux-pm@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm.git
F: drivers/cpuidle/cpuidle-psci.c

CPUIDLE DRIVER - ARM PSCI PM DOMAIN
Expand Down Expand Up @@ -20510,15 +20512,20 @@ L: linux-riscv@lists.infradead.org
S: Maintained
T: git https://github.com/pdp7/linux.git
F: Documentation/devicetree/bindings/clock/thead,th1520-clk-ap.yaml
F: Documentation/devicetree/bindings/firmware/thead,th1520-aon.yaml
F: Documentation/devicetree/bindings/mailbox/thead,th1520-mbox.yaml
F: Documentation/devicetree/bindings/net/thead,th1520-gmac.yaml
F: Documentation/devicetree/bindings/pinctrl/thead,th1520-pinctrl.yaml
F: arch/riscv/boot/dts/thead/
F: drivers/clk/thead/clk-th1520-ap.c
F: drivers/firmware/thead,th1520-aon.c
F: drivers/mailbox/mailbox-th1520.c
F: drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c
F: drivers/pinctrl/pinctrl-th1520.c
F: drivers/pmdomain/thead/
F: include/dt-bindings/clock/thead,th1520-clk-ap.h
F: include/dt-bindings/power/thead,th1520-power.h
F: include/linux/firmware/thead/thead,th1520-aon.h

RNBD BLOCK DRIVERS
M: Md. Haris Iqbal <haris.iqbal@ionos.com>
Expand Down
3 changes: 3 additions & 0 deletions drivers/cpuidle/cpuidle-psci.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/syscore_ops.h>

#include <asm/cpuidle.h>
#include <trace/events/power.h>

#include "cpuidle-psci.h"
#include "dt_idle_states.h"
Expand Down Expand Up @@ -74,7 +75,9 @@ static __cpuidle int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
if (!state)
state = states[idx];

trace_psci_domain_idle_enter(dev->cpu, state, s2idle);
ret = psci_cpu_suspend_enter(state) ? -1 : idx;
trace_psci_domain_idle_exit(dev->cpu, state, s2idle);

if (s2idle)
dev_pm_genpd_resume(pd_dev);
Expand Down
10 changes: 10 additions & 0 deletions drivers/firmware/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@ config SYSFB_SIMPLEFB

If unsure, say Y.

config TH1520_AON_PROTOCOL
tristate "Always-On firmware protocol"
depends on ARCH_THEAD || COMPILE_TEST
depends on MAILBOX
help
Power, clock, and resource management capabilities on the TH1520 SoC are
managed by the E902 core. Firmware running on this core communicates with
the kernel through the Always-On protocol, using hardware mailbox as a medium.
Say yes if you need such capabilities.

config TI_SCI_PROTOCOL
tristate "TI System Control Interface (TISCI) Message Protocol"
depends on TI_MESSAGE_MANAGER
Expand Down
1 change: 1 addition & 0 deletions drivers/firmware/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o
obj-$(CONFIG_SYSFB) += sysfb.o
obj-$(CONFIG_SYSFB_SIMPLEFB) += sysfb_simplefb.o
obj-$(CONFIG_TH1520_AON_PROTOCOL) += thead,th1520-aon.o
obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o
Expand Down
250 changes: 250 additions & 0 deletions drivers/firmware/thead,th1520-aon.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 Alibaba Group Holding Limited.
* Copyright (c) 2024 Samsung Electronics Co., Ltd.
* Author: Michal Wilczynski <m.wilczynski@samsung.com>
*/

#include <linux/device.h>
#include <linux/firmware/thead/thead,th1520-aon.h>
#include <linux/mailbox_client.h>
#include <linux/mailbox_controller.h>
#include <linux/slab.h>

#define MAX_RX_TIMEOUT (msecs_to_jiffies(3000))
#define MAX_TX_TIMEOUT 500

struct th1520_aon_chan {
struct mbox_chan *ch;
struct th1520_aon_rpc_ack_common ack_msg;
struct mbox_client cl;
struct completion done;

/* make sure only one RPC is performed at a time */
struct mutex transaction_lock;
};

struct th1520_aon_msg_req_set_resource_power_mode {
struct th1520_aon_rpc_msg_hdr hdr;
u16 resource;
u16 mode;
u16 reserved[10];
} __packed __aligned(1);

/*
* This type is used to indicate error response for most functions.
*/
enum th1520_aon_error_codes {
LIGHT_AON_ERR_NONE = 0, /* Success */
LIGHT_AON_ERR_VERSION = 1, /* Incompatible API version */
LIGHT_AON_ERR_CONFIG = 2, /* Configuration error */
LIGHT_AON_ERR_PARM = 3, /* Bad parameter */
LIGHT_AON_ERR_NOACCESS = 4, /* Permission error (no access) */
LIGHT_AON_ERR_LOCKED = 5, /* Permission error (locked) */
LIGHT_AON_ERR_UNAVAILABLE = 6, /* Unavailable (out of resources) */
LIGHT_AON_ERR_NOTFOUND = 7, /* Not found */
LIGHT_AON_ERR_NOPOWER = 8, /* No power */
LIGHT_AON_ERR_IPC = 9, /* Generic IPC error */
LIGHT_AON_ERR_BUSY = 10, /* Resource is currently busy/active */
LIGHT_AON_ERR_FAIL = 11, /* General I/O failure */
LIGHT_AON_ERR_LAST
};

static int th1520_aon_linux_errmap[LIGHT_AON_ERR_LAST] = {
0, /* LIGHT_AON_ERR_NONE */
-EINVAL, /* LIGHT_AON_ERR_VERSION */
-EINVAL, /* LIGHT_AON_ERR_CONFIG */
-EINVAL, /* LIGHT_AON_ERR_PARM */
-EACCES, /* LIGHT_AON_ERR_NOACCESS */
-EACCES, /* LIGHT_AON_ERR_LOCKED */
-ERANGE, /* LIGHT_AON_ERR_UNAVAILABLE */
-EEXIST, /* LIGHT_AON_ERR_NOTFOUND */
-EPERM, /* LIGHT_AON_ERR_NOPOWER */
-EPIPE, /* LIGHT_AON_ERR_IPC */
-EBUSY, /* LIGHT_AON_ERR_BUSY */
-EIO, /* LIGHT_AON_ERR_FAIL */
};

static inline int th1520_aon_to_linux_errno(int errno)
{
if (errno >= LIGHT_AON_ERR_NONE && errno < LIGHT_AON_ERR_LAST)
return th1520_aon_linux_errmap[errno];

return -EIO;
}

static void th1520_aon_rx_callback(struct mbox_client *c, void *rx_msg)
{
struct th1520_aon_chan *aon_chan =
container_of(c, struct th1520_aon_chan, cl);
struct th1520_aon_rpc_msg_hdr *hdr =
(struct th1520_aon_rpc_msg_hdr *)rx_msg;
u8 recv_size = sizeof(struct th1520_aon_rpc_msg_hdr) + hdr->size;

if (recv_size != sizeof(struct th1520_aon_rpc_ack_common)) {
dev_err(c->dev, "Invalid ack size, not completing\n");
return;
}

memcpy(&aon_chan->ack_msg, rx_msg, recv_size);
complete(&aon_chan->done);
}

/**
* th1520_aon_call_rpc() - Send an RPC request to the TH1520 AON subsystem
* @aon_chan: Pointer to the AON channel structure
* @msg: Pointer to the message (RPC payload) that will be sent
*
* This function sends an RPC message to the TH1520 AON subsystem via mailbox.
* It takes the provided @msg buffer, formats it with version and service flags,
* then blocks until the RPC completes or times out. The completion is signaled
* by the `aon_chan->done` completion, which is waited upon for a duration
* defined by `MAX_RX_TIMEOUT`.
*
* Return:
* * 0 on success
* * -ETIMEDOUT if the RPC call times out
* * A negative error code if the mailbox send fails or if AON responds with
* a non-zero error code (converted via th1520_aon_to_linux_errno()).
*/
int th1520_aon_call_rpc(struct th1520_aon_chan *aon_chan, void *msg)
{
struct th1520_aon_rpc_msg_hdr *hdr = msg;
int ret;

mutex_lock(&aon_chan->transaction_lock);
reinit_completion(&aon_chan->done);

RPC_SET_VER(hdr, TH1520_AON_RPC_VERSION);
RPC_SET_SVC_ID(hdr, hdr->svc);
RPC_SET_SVC_FLAG_MSG_TYPE(hdr, RPC_SVC_MSG_TYPE_DATA);
RPC_SET_SVC_FLAG_ACK_TYPE(hdr, RPC_SVC_MSG_NEED_ACK);

ret = mbox_send_message(aon_chan->ch, msg);
if (ret < 0) {
dev_err(aon_chan->cl.dev, "RPC send msg failed: %d\n", ret);
goto out;
}

if (!wait_for_completion_timeout(&aon_chan->done, MAX_RX_TIMEOUT)) {
dev_err(aon_chan->cl.dev, "RPC send msg timeout\n");
mutex_unlock(&aon_chan->transaction_lock);
return -ETIMEDOUT;
}

ret = aon_chan->ack_msg.err_code;

out:
mutex_unlock(&aon_chan->transaction_lock);

return th1520_aon_to_linux_errno(ret);
}
EXPORT_SYMBOL_GPL(th1520_aon_call_rpc);

/**
* th1520_aon_power_update() - Change power state of a resource via TH1520 AON
* @aon_chan: Pointer to the AON channel structure
* @rsrc: Resource ID whose power state needs to be updated
* @power_on: Boolean indicating whether the resource should be powered on (true)
* or powered off (false)
*
* This function requests the TH1520 AON subsystem to set the power mode of the
* given resource (@rsrc) to either on or off. It constructs the message in
* `struct th1520_aon_msg_req_set_resource_power_mode` and then invokes
* th1520_aon_call_rpc() to make the request. If the AON call fails, an error
* message is logged along with the specific return code.
*
* Return:
* * 0 on success
* * A negative error code in case of failures (propagated from
* th1520_aon_call_rpc()).
*/
int th1520_aon_power_update(struct th1520_aon_chan *aon_chan, u16 rsrc,
bool power_on)
{
struct th1520_aon_msg_req_set_resource_power_mode msg = {};
struct th1520_aon_rpc_msg_hdr *hdr = &msg.hdr;
int ret;

hdr->svc = TH1520_AON_RPC_SVC_PM;
hdr->func = TH1520_AON_PM_FUNC_SET_RESOURCE_POWER_MODE;
hdr->size = TH1520_AON_RPC_MSG_NUM;

RPC_SET_BE16(&msg.resource, 0, rsrc);
RPC_SET_BE16(&msg.resource, 2,
(power_on ? TH1520_AON_PM_PW_MODE_ON :
TH1520_AON_PM_PW_MODE_OFF));

ret = th1520_aon_call_rpc(aon_chan, &msg);
if (ret)
dev_err(aon_chan->cl.dev, "failed to power %s resource %d ret %d\n",
power_on ? "up" : "off", rsrc, ret);

return ret;
}
EXPORT_SYMBOL_GPL(th1520_aon_power_update);

/**
* th1520_aon_init() - Initialize TH1520 AON firmware protocol interface
* @dev: Device pointer for the AON subsystem
*
* This function initializes the TH1520 AON firmware protocol interface by:
* - Allocating and initializing the AON channel structure
* - Setting up the mailbox client
* - Requesting the AON mailbox channel
* - Initializing synchronization primitives
*
* Return:
* * Valid pointer to th1520_aon_chan structure on success
* * ERR_PTR(-ENOMEM) if memory allocation fails
* * ERR_PTR() with other negative error codes from mailbox operations
*/
struct th1520_aon_chan *th1520_aon_init(struct device *dev)
{
struct th1520_aon_chan *aon_chan;
struct mbox_client *cl;
int ret;

aon_chan = kzalloc(sizeof(*aon_chan), GFP_KERNEL);
if (!aon_chan)
return ERR_PTR(-ENOMEM);

cl = &aon_chan->cl;
cl->dev = dev;
cl->tx_block = true;
cl->tx_tout = MAX_TX_TIMEOUT;
cl->rx_callback = th1520_aon_rx_callback;

aon_chan->ch = mbox_request_channel_byname(cl, "aon");
if (IS_ERR(aon_chan->ch)) {
dev_err(dev, "Failed to request aon mbox chan\n");
ret = PTR_ERR(aon_chan->ch);
kfree(aon_chan);
return ERR_PTR(ret);
}

mutex_init(&aon_chan->transaction_lock);
init_completion(&aon_chan->done);

return aon_chan;
}
EXPORT_SYMBOL_GPL(th1520_aon_init);

/**
* th1520_aon_deinit() - Clean up TH1520 AON firmware protocol interface
* @aon_chan: Pointer to the AON channel structure to clean up
*
* This function cleans up resources allocated by th1520_aon_init():
* - Frees the mailbox channel
* - Frees the AON channel
*/
void th1520_aon_deinit(struct th1520_aon_chan *aon_chan)
{
mbox_free_channel(aon_chan->ch);
kfree(aon_chan);
}
EXPORT_SYMBOL_GPL(th1520_aon_deinit);

MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
MODULE_DESCRIPTION("T-HEAD TH1520 Always-On firmware protocol library");
MODULE_LICENSE("GPL");
Loading

0 comments on commit 2a2274e

Please sign in to comment.