162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __RPM_INTERNAL_H__
862306a36Sopenharmony_ci#define __RPM_INTERNAL_H__
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/bitmap.h>
1162306a36Sopenharmony_ci#include <linux/wait.h>
1262306a36Sopenharmony_ci#include <soc/qcom/tcs.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define TCS_TYPE_NR			4
1562306a36Sopenharmony_ci#define MAX_CMDS_PER_TCS		16
1662306a36Sopenharmony_ci#define MAX_TCS_PER_TYPE		3
1762306a36Sopenharmony_ci#define MAX_TCS_NR			(MAX_TCS_PER_TYPE * TCS_TYPE_NR)
1862306a36Sopenharmony_ci#define MAX_TCS_SLOTS			(MAX_CMDS_PER_TCS * MAX_TCS_PER_TYPE)
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct rsc_drv;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/**
2362306a36Sopenharmony_ci * struct tcs_group: group of Trigger Command Sets (TCS) to send state requests
2462306a36Sopenharmony_ci * to the controller
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * @drv:       The controller.
2762306a36Sopenharmony_ci * @type:      Type of the TCS in this group - active, sleep, wake.
2862306a36Sopenharmony_ci * @mask:      Mask of the TCSes relative to all the TCSes in the RSC.
2962306a36Sopenharmony_ci * @offset:    Start of the TCS group relative to the TCSes in the RSC.
3062306a36Sopenharmony_ci * @num_tcs:   Number of TCSes in this type.
3162306a36Sopenharmony_ci * @ncpt:      Number of commands in each TCS.
3262306a36Sopenharmony_ci * @req:       Requests that are sent from the TCS; only used for ACTIVE_ONLY
3362306a36Sopenharmony_ci *             transfers (could be on a wake/sleep TCS if we are borrowing for
3462306a36Sopenharmony_ci *             an ACTIVE_ONLY transfer).
3562306a36Sopenharmony_ci *             Start: grab drv->lock, set req, set tcs_in_use, drop drv->lock,
3662306a36Sopenharmony_ci *                    trigger
3762306a36Sopenharmony_ci *             End: get irq, access req,
3862306a36Sopenharmony_ci *                  grab drv->lock, clear tcs_in_use, drop drv->lock
3962306a36Sopenharmony_ci * @slots:     Indicates which of @cmd_addr are occupied; only used for
4062306a36Sopenharmony_ci *             SLEEP / WAKE TCSs.  Things are tightly packed in the
4162306a36Sopenharmony_ci *             case that (ncpt < MAX_CMDS_PER_TCS).  That is if ncpt = 2 and
4262306a36Sopenharmony_ci *             MAX_CMDS_PER_TCS = 16 then bit[2] = the first bit in 2nd TCS.
4362306a36Sopenharmony_ci */
4462306a36Sopenharmony_cistruct tcs_group {
4562306a36Sopenharmony_ci	struct rsc_drv *drv;
4662306a36Sopenharmony_ci	int type;
4762306a36Sopenharmony_ci	u32 mask;
4862306a36Sopenharmony_ci	u32 offset;
4962306a36Sopenharmony_ci	int num_tcs;
5062306a36Sopenharmony_ci	int ncpt;
5162306a36Sopenharmony_ci	const struct tcs_request *req[MAX_TCS_PER_TYPE];
5262306a36Sopenharmony_ci	DECLARE_BITMAP(slots, MAX_TCS_SLOTS);
5362306a36Sopenharmony_ci};
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/**
5662306a36Sopenharmony_ci * struct rpmh_request: the message to be sent to rpmh-rsc
5762306a36Sopenharmony_ci *
5862306a36Sopenharmony_ci * @msg: the request
5962306a36Sopenharmony_ci * @cmd: the payload that will be part of the @msg
6062306a36Sopenharmony_ci * @completion: triggered when request is done
6162306a36Sopenharmony_ci * @dev: the device making the request
6262306a36Sopenharmony_ci * @needs_free: check to free dynamically allocated request object
6362306a36Sopenharmony_ci */
6462306a36Sopenharmony_cistruct rpmh_request {
6562306a36Sopenharmony_ci	struct tcs_request msg;
6662306a36Sopenharmony_ci	struct tcs_cmd cmd[MAX_RPMH_PAYLOAD];
6762306a36Sopenharmony_ci	struct completion *completion;
6862306a36Sopenharmony_ci	const struct device *dev;
6962306a36Sopenharmony_ci	bool needs_free;
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/**
7362306a36Sopenharmony_ci * struct rpmh_ctrlr: our representation of the controller
7462306a36Sopenharmony_ci *
7562306a36Sopenharmony_ci * @cache: the list of cached requests
7662306a36Sopenharmony_ci * @cache_lock: synchronize access to the cache data
7762306a36Sopenharmony_ci * @dirty: was the cache updated since flush
7862306a36Sopenharmony_ci * @batch_cache: Cache sleep and wake requests sent as batch
7962306a36Sopenharmony_ci */
8062306a36Sopenharmony_cistruct rpmh_ctrlr {
8162306a36Sopenharmony_ci	struct list_head cache;
8262306a36Sopenharmony_ci	spinlock_t cache_lock;
8362306a36Sopenharmony_ci	bool dirty;
8462306a36Sopenharmony_ci	struct list_head batch_cache;
8562306a36Sopenharmony_ci};
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistruct rsc_ver {
8862306a36Sopenharmony_ci	u32 major;
8962306a36Sopenharmony_ci	u32 minor;
9062306a36Sopenharmony_ci};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/**
9362306a36Sopenharmony_ci * struct rsc_drv: the Direct Resource Voter (DRV) of the
9462306a36Sopenharmony_ci * Resource State Coordinator controller (RSC)
9562306a36Sopenharmony_ci *
9662306a36Sopenharmony_ci * @name:               Controller identifier.
9762306a36Sopenharmony_ci * @base:               Start address of the DRV registers in this controller.
9862306a36Sopenharmony_ci * @tcs_base:           Start address of the TCS registers in this controller.
9962306a36Sopenharmony_ci * @id:                 Instance id in the controller (Direct Resource Voter).
10062306a36Sopenharmony_ci * @num_tcs:            Number of TCSes in this DRV.
10162306a36Sopenharmony_ci * @rsc_pm:             CPU PM notifier for controller.
10262306a36Sopenharmony_ci *                      Used when solver mode is not present.
10362306a36Sopenharmony_ci * @cpus_in_pm:         Number of CPUs not in idle power collapse.
10462306a36Sopenharmony_ci *                      Used when solver mode and "power-domains" is not present.
10562306a36Sopenharmony_ci * @genpd_nb:           PM Domain notifier for cluster genpd notifications.
10662306a36Sopenharmony_ci * @tcs:                TCS groups.
10762306a36Sopenharmony_ci * @tcs_in_use:         S/W state of the TCS; only set for ACTIVE_ONLY
10862306a36Sopenharmony_ci *                      transfers, but might show a sleep/wake TCS in use if
10962306a36Sopenharmony_ci *                      it was borrowed for an active_only transfer.  You
11062306a36Sopenharmony_ci *                      must hold the lock in this struct (AKA drv->lock) in
11162306a36Sopenharmony_ci *                      order to update this.
11262306a36Sopenharmony_ci * @lock:               Synchronize state of the controller.  If RPMH's cache
11362306a36Sopenharmony_ci *                      lock will also be held, the order is: drv->lock then
11462306a36Sopenharmony_ci *                      cache_lock.
11562306a36Sopenharmony_ci * @tcs_wait:           Wait queue used to wait for @tcs_in_use to free up a
11662306a36Sopenharmony_ci *                      slot
11762306a36Sopenharmony_ci * @client:             Handle to the DRV's client.
11862306a36Sopenharmony_ci * @dev:                RSC device.
11962306a36Sopenharmony_ci */
12062306a36Sopenharmony_cistruct rsc_drv {
12162306a36Sopenharmony_ci	const char *name;
12262306a36Sopenharmony_ci	void __iomem *base;
12362306a36Sopenharmony_ci	void __iomem *tcs_base;
12462306a36Sopenharmony_ci	int id;
12562306a36Sopenharmony_ci	int num_tcs;
12662306a36Sopenharmony_ci	struct notifier_block rsc_pm;
12762306a36Sopenharmony_ci	struct notifier_block genpd_nb;
12862306a36Sopenharmony_ci	atomic_t cpus_in_pm;
12962306a36Sopenharmony_ci	struct tcs_group tcs[TCS_TYPE_NR];
13062306a36Sopenharmony_ci	DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR);
13162306a36Sopenharmony_ci	spinlock_t lock;
13262306a36Sopenharmony_ci	wait_queue_head_t tcs_wait;
13362306a36Sopenharmony_ci	struct rpmh_ctrlr client;
13462306a36Sopenharmony_ci	struct device *dev;
13562306a36Sopenharmony_ci	struct rsc_ver ver;
13662306a36Sopenharmony_ci	u32 *regs;
13762306a36Sopenharmony_ci};
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ciint rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg);
14062306a36Sopenharmony_ciint rpmh_rsc_write_ctrl_data(struct rsc_drv *drv,
14162306a36Sopenharmony_ci			     const struct tcs_request *msg);
14262306a36Sopenharmony_civoid rpmh_rsc_invalidate(struct rsc_drv *drv);
14362306a36Sopenharmony_civoid rpmh_rsc_write_next_wakeup(struct rsc_drv *drv);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_civoid rpmh_tx_done(const struct tcs_request *msg);
14662306a36Sopenharmony_ciint rpmh_flush(struct rpmh_ctrlr *ctrlr);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci#endif /* __RPM_INTERNAL_H__ */
149