162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __PMAC_PFUNC_H__
362306a36Sopenharmony_ci#define __PMAC_PFUNC_H__
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/types.h>
662306a36Sopenharmony_ci#include <linux/list.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/* Flags in command lists */
962306a36Sopenharmony_ci#define PMF_FLAGS_ON_INIT		0x80000000u
1062306a36Sopenharmony_ci#define PMF_FLGAS_ON_TERM		0x40000000u
1162306a36Sopenharmony_ci#define PMF_FLAGS_ON_SLEEP		0x20000000u
1262306a36Sopenharmony_ci#define PMF_FLAGS_ON_WAKE		0x10000000u
1362306a36Sopenharmony_ci#define PMF_FLAGS_ON_DEMAND		0x08000000u
1462306a36Sopenharmony_ci#define PMF_FLAGS_INT_GEN		0x04000000u
1562306a36Sopenharmony_ci#define PMF_FLAGS_HIGH_SPEED		0x02000000u
1662306a36Sopenharmony_ci#define PMF_FLAGS_LOW_SPEED		0x01000000u
1762306a36Sopenharmony_ci#define PMF_FLAGS_SIDE_EFFECTS		0x00800000u
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/*
2062306a36Sopenharmony_ci * Arguments to a platform function call.
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * NOTE: By convention, pointer arguments point to an u32
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_cistruct pmf_args {
2562306a36Sopenharmony_ci	union {
2662306a36Sopenharmony_ci		u32 v;
2762306a36Sopenharmony_ci		u32 *p;
2862306a36Sopenharmony_ci	} u[4];
2962306a36Sopenharmony_ci	unsigned int count;
3062306a36Sopenharmony_ci};
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/*
3362306a36Sopenharmony_ci * A driver capable of interpreting commands provides a handlers
3462306a36Sopenharmony_ci * structure filled with whatever handlers are implemented by this
3562306a36Sopenharmony_ci * driver. Non implemented handlers are left NULL.
3662306a36Sopenharmony_ci *
3762306a36Sopenharmony_ci * PMF_STD_ARGS are the same arguments that are passed to the parser
3862306a36Sopenharmony_ci * and that gets passed back to the various handlers.
3962306a36Sopenharmony_ci *
4062306a36Sopenharmony_ci * Interpreting a given function always start with a begin() call which
4162306a36Sopenharmony_ci * returns an instance data to be passed around subsequent calls, and
4262306a36Sopenharmony_ci * ends with an end() call. This allows the low level driver to implement
4362306a36Sopenharmony_ci * locking policy or per-function instance data.
4462306a36Sopenharmony_ci *
4562306a36Sopenharmony_ci * For interrupt capable functions, irq_enable() is called when a client
4662306a36Sopenharmony_ci * registers, and irq_disable() is called when the last client unregisters
4762306a36Sopenharmony_ci * Note that irq_enable & irq_disable are called within a semaphore held
4862306a36Sopenharmony_ci * by the core, thus you should not try to register yourself to some other
4962306a36Sopenharmony_ci * pmf interrupt during those calls.
5062306a36Sopenharmony_ci */
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define PMF_STD_ARGS	struct pmf_function *func, void *instdata, \
5362306a36Sopenharmony_ci		        struct pmf_args *args
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistruct pmf_function;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistruct pmf_handlers {
5862306a36Sopenharmony_ci	void * (*begin)(struct pmf_function *func, struct pmf_args *args);
5962306a36Sopenharmony_ci	void (*end)(struct pmf_function *func, void *instdata);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	int (*irq_enable)(struct pmf_function *func);
6262306a36Sopenharmony_ci	int (*irq_disable)(struct pmf_function *func);
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	int (*write_gpio)(PMF_STD_ARGS, u8 value, u8 mask);
6562306a36Sopenharmony_ci	int (*read_gpio)(PMF_STD_ARGS, u8 mask, int rshift, u8 xor);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	int (*write_reg32)(PMF_STD_ARGS, u32 offset, u32 value, u32 mask);
6862306a36Sopenharmony_ci	int (*read_reg32)(PMF_STD_ARGS, u32 offset);
6962306a36Sopenharmony_ci	int (*write_reg16)(PMF_STD_ARGS, u32 offset, u16 value, u16 mask);
7062306a36Sopenharmony_ci	int (*read_reg16)(PMF_STD_ARGS, u32 offset);
7162306a36Sopenharmony_ci	int (*write_reg8)(PMF_STD_ARGS, u32 offset, u8 value, u8 mask);
7262306a36Sopenharmony_ci	int (*read_reg8)(PMF_STD_ARGS, u32 offset);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	int (*delay)(PMF_STD_ARGS, u32 duration);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	int (*wait_reg32)(PMF_STD_ARGS, u32 offset, u32 value, u32 mask);
7762306a36Sopenharmony_ci	int (*wait_reg16)(PMF_STD_ARGS, u32 offset, u16 value, u16 mask);
7862306a36Sopenharmony_ci	int (*wait_reg8)(PMF_STD_ARGS, u32 offset, u8 value, u8 mask);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	int (*read_i2c)(PMF_STD_ARGS, u32 len);
8162306a36Sopenharmony_ci	int (*write_i2c)(PMF_STD_ARGS, u32 len, const u8 *data);
8262306a36Sopenharmony_ci	int (*rmw_i2c)(PMF_STD_ARGS, u32 masklen, u32 valuelen, u32 totallen,
8362306a36Sopenharmony_ci		       const u8 *maskdata, const u8 *valuedata);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	int (*read_cfg)(PMF_STD_ARGS, u32 offset, u32 len);
8662306a36Sopenharmony_ci	int (*write_cfg)(PMF_STD_ARGS, u32 offset, u32 len, const u8 *data);
8762306a36Sopenharmony_ci	int (*rmw_cfg)(PMF_STD_ARGS, u32 offset, u32 masklen, u32 valuelen,
8862306a36Sopenharmony_ci		       u32 totallen, const u8 *maskdata, const u8 *valuedata);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	int (*read_i2c_sub)(PMF_STD_ARGS, u8 subaddr, u32 len);
9162306a36Sopenharmony_ci	int (*write_i2c_sub)(PMF_STD_ARGS, u8 subaddr, u32 len, const u8 *data);
9262306a36Sopenharmony_ci	int (*set_i2c_mode)(PMF_STD_ARGS, int mode);
9362306a36Sopenharmony_ci	int (*rmw_i2c_sub)(PMF_STD_ARGS, u8 subaddr, u32 masklen, u32 valuelen,
9462306a36Sopenharmony_ci			   u32 totallen, const u8 *maskdata,
9562306a36Sopenharmony_ci			   const u8 *valuedata);
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	int (*read_reg32_msrx)(PMF_STD_ARGS, u32 offset, u32 mask, u32 shift,
9862306a36Sopenharmony_ci			       u32 xor);
9962306a36Sopenharmony_ci	int (*read_reg16_msrx)(PMF_STD_ARGS, u32 offset, u32 mask, u32 shift,
10062306a36Sopenharmony_ci			       u32 xor);
10162306a36Sopenharmony_ci	int (*read_reg8_msrx)(PMF_STD_ARGS, u32 offset, u32 mask, u32 shift,
10262306a36Sopenharmony_ci			      u32 xor);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	int (*write_reg32_slm)(PMF_STD_ARGS, u32 offset, u32 shift, u32 mask);
10562306a36Sopenharmony_ci	int (*write_reg16_slm)(PMF_STD_ARGS, u32 offset, u32 shift, u32 mask);
10662306a36Sopenharmony_ci	int (*write_reg8_slm)(PMF_STD_ARGS, u32 offset, u32 shift, u32 mask);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	int (*mask_and_compare)(PMF_STD_ARGS, u32 len, const u8 *maskdata,
10962306a36Sopenharmony_ci				const u8 *valuedata);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	struct module *owner;
11262306a36Sopenharmony_ci};
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci/*
11662306a36Sopenharmony_ci * Drivers who expose platform functions register at init time, this
11762306a36Sopenharmony_ci * causes the platform functions for that device node to be parsed in
11862306a36Sopenharmony_ci * advance and associated with the device. The data structures are
11962306a36Sopenharmony_ci * partially public so a driver can walk the list of platform functions
12062306a36Sopenharmony_ci * and eventually inspect the flags
12162306a36Sopenharmony_ci */
12262306a36Sopenharmony_cistruct pmf_device;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistruct pmf_function {
12562306a36Sopenharmony_ci	/* All functions for a given driver are linked */
12662306a36Sopenharmony_ci	struct list_head	link;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	/* Function node & driver data */
12962306a36Sopenharmony_ci	struct device_node	*node;
13062306a36Sopenharmony_ci	void			*driver_data;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	/* For internal use by core */
13362306a36Sopenharmony_ci	struct pmf_device	*dev;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	/* The name is the "xxx" in "platform-do-xxx", this is how
13662306a36Sopenharmony_ci	 * platform functions are identified by this code. Some functions
13762306a36Sopenharmony_ci	 * only operate for a given target, in which case the phandle is
13862306a36Sopenharmony_ci	 * here (or 0 if the filter doesn't apply)
13962306a36Sopenharmony_ci	 */
14062306a36Sopenharmony_ci	const char		*name;
14162306a36Sopenharmony_ci	u32			phandle;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	/* The flags for that function. You can have several functions
14462306a36Sopenharmony_ci	 * with the same name and different flag
14562306a36Sopenharmony_ci	 */
14662306a36Sopenharmony_ci	u32			flags;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	/* The actual tokenized function blob */
14962306a36Sopenharmony_ci	const void		*data;
15062306a36Sopenharmony_ci	unsigned int		length;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	/* Interrupt clients */
15362306a36Sopenharmony_ci	struct list_head	irq_clients;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	/* Refcounting */
15662306a36Sopenharmony_ci	struct kref		ref;
15762306a36Sopenharmony_ci};
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci/*
16062306a36Sopenharmony_ci * For platform functions that are interrupts, one can register
16162306a36Sopenharmony_ci * irq_client structures. You canNOT use the same structure twice
16262306a36Sopenharmony_ci * as it contains a link member. Also, the callback is called with
16362306a36Sopenharmony_ci * a spinlock held, you must not call back into any of the pmf_* functions
16462306a36Sopenharmony_ci * from within that callback
16562306a36Sopenharmony_ci */
16662306a36Sopenharmony_cistruct pmf_irq_client {
16762306a36Sopenharmony_ci	void			(*handler)(void *data);
16862306a36Sopenharmony_ci	void			*data;
16962306a36Sopenharmony_ci	struct module		*owner;
17062306a36Sopenharmony_ci	struct list_head	link;
17162306a36Sopenharmony_ci	struct pmf_function	*func;
17262306a36Sopenharmony_ci};
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci/*
17662306a36Sopenharmony_ci * Register/Unregister a function-capable driver and its handlers
17762306a36Sopenharmony_ci */
17862306a36Sopenharmony_ciextern int pmf_register_driver(struct device_node *np,
17962306a36Sopenharmony_ci			      struct pmf_handlers *handlers,
18062306a36Sopenharmony_ci			      void *driverdata);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ciextern void pmf_unregister_driver(struct device_node *np);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/*
18662306a36Sopenharmony_ci * Register/Unregister interrupt clients
18762306a36Sopenharmony_ci */
18862306a36Sopenharmony_ciextern int pmf_register_irq_client(struct device_node *np,
18962306a36Sopenharmony_ci				   const char *name,
19062306a36Sopenharmony_ci				   struct pmf_irq_client *client);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ciextern void pmf_unregister_irq_client(struct pmf_irq_client *client);
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci/*
19562306a36Sopenharmony_ci * Called by the handlers when an irq happens
19662306a36Sopenharmony_ci */
19762306a36Sopenharmony_ciextern void pmf_do_irq(struct pmf_function *func);
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci/*
20162306a36Sopenharmony_ci * Low level call to platform functions.
20262306a36Sopenharmony_ci *
20362306a36Sopenharmony_ci * The phandle can filter on the target object for functions that have
20462306a36Sopenharmony_ci * multiple targets, the flags allow you to restrict the call to a given
20562306a36Sopenharmony_ci * combination of flags.
20662306a36Sopenharmony_ci *
20762306a36Sopenharmony_ci * The args array contains as many arguments as is required by the function,
20862306a36Sopenharmony_ci * this is dependent on the function you are calling, unfortunately Apple
20962306a36Sopenharmony_ci * mechanism provides no way to encode that so you have to get it right at
21062306a36Sopenharmony_ci * the call site. Some functions require no args, in which case, you can
21162306a36Sopenharmony_ci * pass NULL.
21262306a36Sopenharmony_ci *
21362306a36Sopenharmony_ci * You can also pass NULL to the name. This will match any function that has
21462306a36Sopenharmony_ci * the appropriate combination of flags & phandle or you can pass 0 to the
21562306a36Sopenharmony_ci * phandle to match any
21662306a36Sopenharmony_ci */
21762306a36Sopenharmony_ciextern int pmf_do_functions(struct device_node *np, const char *name,
21862306a36Sopenharmony_ci			    u32 phandle, u32 flags, struct pmf_args *args);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci/*
22362306a36Sopenharmony_ci * High level call to a platform function.
22462306a36Sopenharmony_ci *
22562306a36Sopenharmony_ci * This one looks for the platform-xxx first so you should call it to the
22662306a36Sopenharmony_ci * actual target if any. It will fallback to platform-do-xxx if it can't
22762306a36Sopenharmony_ci * find one. It will also exclusively target functions that have
22862306a36Sopenharmony_ci * the "OnDemand" flag.
22962306a36Sopenharmony_ci */
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ciextern int pmf_call_function(struct device_node *target, const char *name,
23262306a36Sopenharmony_ci			     struct pmf_args *args);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci/*
23662306a36Sopenharmony_ci * For low latency interrupt usage, you can lookup for on-demand functions
23762306a36Sopenharmony_ci * using the functions below
23862306a36Sopenharmony_ci */
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ciextern struct pmf_function *pmf_find_function(struct device_node *target,
24162306a36Sopenharmony_ci					      const char *name);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ciextern struct pmf_function * pmf_get_function(struct pmf_function *func);
24462306a36Sopenharmony_ciextern void pmf_put_function(struct pmf_function *func);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ciextern int pmf_call_one(struct pmf_function *func, struct pmf_args *args);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ciint pmac_pfunc_base_install(void);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci/* Suspend/resume code called by via-pmu directly for now */
25162306a36Sopenharmony_ciextern void pmac_pfunc_base_suspend(void);
25262306a36Sopenharmony_ciextern void pmac_pfunc_base_resume(void);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci#endif /* __PMAC_PFUNC_H__ */
255