xref: /linux/arch/powerpc/include/asm/pmac_pfunc.h (revision 3eb66e91a25497065c5322b1268cbc3953642227)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2b8b572e1SStephen Rothwell #ifndef __PMAC_PFUNC_H__
3b8b572e1SStephen Rothwell #define __PMAC_PFUNC_H__
4b8b572e1SStephen Rothwell 
5b8b572e1SStephen Rothwell #include <linux/types.h>
6b8b572e1SStephen Rothwell #include <linux/list.h>
7b8b572e1SStephen Rothwell 
8b8b572e1SStephen Rothwell /* Flags in command lists */
9b8b572e1SStephen Rothwell #define PMF_FLAGS_ON_INIT		0x80000000u
10b8b572e1SStephen Rothwell #define PMF_FLGAS_ON_TERM		0x40000000u
11b8b572e1SStephen Rothwell #define PMF_FLAGS_ON_SLEEP		0x20000000u
12b8b572e1SStephen Rothwell #define PMF_FLAGS_ON_WAKE		0x10000000u
13b8b572e1SStephen Rothwell #define PMF_FLAGS_ON_DEMAND		0x08000000u
14b8b572e1SStephen Rothwell #define PMF_FLAGS_INT_GEN		0x04000000u
15b8b572e1SStephen Rothwell #define PMF_FLAGS_HIGH_SPEED		0x02000000u
16b8b572e1SStephen Rothwell #define PMF_FLAGS_LOW_SPEED		0x01000000u
17b8b572e1SStephen Rothwell #define PMF_FLAGS_SIDE_EFFECTS		0x00800000u
18b8b572e1SStephen Rothwell 
19b8b572e1SStephen Rothwell /*
20b8b572e1SStephen Rothwell  * Arguments to a platform function call.
21b8b572e1SStephen Rothwell  *
22b8b572e1SStephen Rothwell  * NOTE: By convention, pointer arguments point to an u32
23b8b572e1SStephen Rothwell  */
24b8b572e1SStephen Rothwell struct pmf_args {
25b8b572e1SStephen Rothwell 	union {
26b8b572e1SStephen Rothwell 		u32 v;
27b8b572e1SStephen Rothwell 		u32 *p;
28b8b572e1SStephen Rothwell 	} u[4];
29b8b572e1SStephen Rothwell 	unsigned int count;
30b8b572e1SStephen Rothwell };
31b8b572e1SStephen Rothwell 
32b8b572e1SStephen Rothwell /*
33b8b572e1SStephen Rothwell  * A driver capable of interpreting commands provides a handlers
34b8b572e1SStephen Rothwell  * structure filled with whatever handlers are implemented by this
35b8b572e1SStephen Rothwell  * driver. Non implemented handlers are left NULL.
36b8b572e1SStephen Rothwell  *
37b8b572e1SStephen Rothwell  * PMF_STD_ARGS are the same arguments that are passed to the parser
38b8b572e1SStephen Rothwell  * and that gets passed back to the various handlers.
39b8b572e1SStephen Rothwell  *
40b8b572e1SStephen Rothwell  * Interpreting a given function always start with a begin() call which
41b8b572e1SStephen Rothwell  * returns an instance data to be passed around subsequent calls, and
42b8b572e1SStephen Rothwell  * ends with an end() call. This allows the low level driver to implement
43b8b572e1SStephen Rothwell  * locking policy or per-function instance data.
44b8b572e1SStephen Rothwell  *
45b8b572e1SStephen Rothwell  * For interrupt capable functions, irq_enable() is called when a client
46b8b572e1SStephen Rothwell  * registers, and irq_disable() is called when the last client unregisters
47b8b572e1SStephen Rothwell  * Note that irq_enable & irq_disable are called within a semaphore held
48b8b572e1SStephen Rothwell  * by the core, thus you should not try to register yourself to some other
49b8b572e1SStephen Rothwell  * pmf interrupt during those calls.
50b8b572e1SStephen Rothwell  */
51b8b572e1SStephen Rothwell 
52b8b572e1SStephen Rothwell #define PMF_STD_ARGS	struct pmf_function *func, void *instdata, \
53b8b572e1SStephen Rothwell 		        struct pmf_args *args
54b8b572e1SStephen Rothwell 
55b8b572e1SStephen Rothwell struct pmf_function;
56b8b572e1SStephen Rothwell 
57b8b572e1SStephen Rothwell struct pmf_handlers {
58b8b572e1SStephen Rothwell 	void * (*begin)(struct pmf_function *func, struct pmf_args *args);
59b8b572e1SStephen Rothwell 	void (*end)(struct pmf_function *func, void *instdata);
60b8b572e1SStephen Rothwell 
61b8b572e1SStephen Rothwell 	int (*irq_enable)(struct pmf_function *func);
62b8b572e1SStephen Rothwell 	int (*irq_disable)(struct pmf_function *func);
63b8b572e1SStephen Rothwell 
64b8b572e1SStephen Rothwell 	int (*write_gpio)(PMF_STD_ARGS, u8 value, u8 mask);
65b8b572e1SStephen Rothwell 	int (*read_gpio)(PMF_STD_ARGS, u8 mask, int rshift, u8 xor);
66b8b572e1SStephen Rothwell 
67b8b572e1SStephen Rothwell 	int (*write_reg32)(PMF_STD_ARGS, u32 offset, u32 value, u32 mask);
68b8b572e1SStephen Rothwell 	int (*read_reg32)(PMF_STD_ARGS, u32 offset);
69b8b572e1SStephen Rothwell 	int (*write_reg16)(PMF_STD_ARGS, u32 offset, u16 value, u16 mask);
70b8b572e1SStephen Rothwell 	int (*read_reg16)(PMF_STD_ARGS, u32 offset);
71b8b572e1SStephen Rothwell 	int (*write_reg8)(PMF_STD_ARGS, u32 offset, u8 value, u8 mask);
72b8b572e1SStephen Rothwell 	int (*read_reg8)(PMF_STD_ARGS, u32 offset);
73b8b572e1SStephen Rothwell 
74b8b572e1SStephen Rothwell 	int (*delay)(PMF_STD_ARGS, u32 duration);
75b8b572e1SStephen Rothwell 
76b8b572e1SStephen Rothwell 	int (*wait_reg32)(PMF_STD_ARGS, u32 offset, u32 value, u32 mask);
77b8b572e1SStephen Rothwell 	int (*wait_reg16)(PMF_STD_ARGS, u32 offset, u16 value, u16 mask);
78b8b572e1SStephen Rothwell 	int (*wait_reg8)(PMF_STD_ARGS, u32 offset, u8 value, u8 mask);
79b8b572e1SStephen Rothwell 
80b8b572e1SStephen Rothwell 	int (*read_i2c)(PMF_STD_ARGS, u32 len);
81b8b572e1SStephen Rothwell 	int (*write_i2c)(PMF_STD_ARGS, u32 len, const u8 *data);
82b8b572e1SStephen Rothwell 	int (*rmw_i2c)(PMF_STD_ARGS, u32 masklen, u32 valuelen, u32 totallen,
83b8b572e1SStephen Rothwell 		       const u8 *maskdata, const u8 *valuedata);
84b8b572e1SStephen Rothwell 
85b8b572e1SStephen Rothwell 	int (*read_cfg)(PMF_STD_ARGS, u32 offset, u32 len);
86b8b572e1SStephen Rothwell 	int (*write_cfg)(PMF_STD_ARGS, u32 offset, u32 len, const u8 *data);
87b8b572e1SStephen Rothwell 	int (*rmw_cfg)(PMF_STD_ARGS, u32 offset, u32 masklen, u32 valuelen,
88b8b572e1SStephen Rothwell 		       u32 totallen, const u8 *maskdata, const u8 *valuedata);
89b8b572e1SStephen Rothwell 
90b8b572e1SStephen Rothwell 	int (*read_i2c_sub)(PMF_STD_ARGS, u8 subaddr, u32 len);
91b8b572e1SStephen Rothwell 	int (*write_i2c_sub)(PMF_STD_ARGS, u8 subaddr, u32 len, const u8 *data);
92b8b572e1SStephen Rothwell 	int (*set_i2c_mode)(PMF_STD_ARGS, int mode);
93b8b572e1SStephen Rothwell 	int (*rmw_i2c_sub)(PMF_STD_ARGS, u8 subaddr, u32 masklen, u32 valuelen,
94b8b572e1SStephen Rothwell 			   u32 totallen, const u8 *maskdata,
95b8b572e1SStephen Rothwell 			   const u8 *valuedata);
96b8b572e1SStephen Rothwell 
97b8b572e1SStephen Rothwell 	int (*read_reg32_msrx)(PMF_STD_ARGS, u32 offset, u32 mask, u32 shift,
98b8b572e1SStephen Rothwell 			       u32 xor);
99b8b572e1SStephen Rothwell 	int (*read_reg16_msrx)(PMF_STD_ARGS, u32 offset, u32 mask, u32 shift,
100b8b572e1SStephen Rothwell 			       u32 xor);
101b8b572e1SStephen Rothwell 	int (*read_reg8_msrx)(PMF_STD_ARGS, u32 offset, u32 mask, u32 shift,
102b8b572e1SStephen Rothwell 			      u32 xor);
103b8b572e1SStephen Rothwell 
104b8b572e1SStephen Rothwell 	int (*write_reg32_slm)(PMF_STD_ARGS, u32 offset, u32 shift, u32 mask);
105b8b572e1SStephen Rothwell 	int (*write_reg16_slm)(PMF_STD_ARGS, u32 offset, u32 shift, u32 mask);
106b8b572e1SStephen Rothwell 	int (*write_reg8_slm)(PMF_STD_ARGS, u32 offset, u32 shift, u32 mask);
107b8b572e1SStephen Rothwell 
108b8b572e1SStephen Rothwell 	int (*mask_and_compare)(PMF_STD_ARGS, u32 len, const u8 *maskdata,
109b8b572e1SStephen Rothwell 				const u8 *valuedata);
110b8b572e1SStephen Rothwell 
111b8b572e1SStephen Rothwell 	struct module *owner;
112b8b572e1SStephen Rothwell };
113b8b572e1SStephen Rothwell 
114b8b572e1SStephen Rothwell 
115b8b572e1SStephen Rothwell /*
116b8b572e1SStephen Rothwell  * Drivers who expose platform functions register at init time, this
117b8b572e1SStephen Rothwell  * causes the platform functions for that device node to be parsed in
118b8b572e1SStephen Rothwell  * advance and associated with the device. The data structures are
119b8b572e1SStephen Rothwell  * partially public so a driver can walk the list of platform functions
120b8b572e1SStephen Rothwell  * and eventually inspect the flags
121b8b572e1SStephen Rothwell  */
122b8b572e1SStephen Rothwell struct pmf_device;
123b8b572e1SStephen Rothwell 
124b8b572e1SStephen Rothwell struct pmf_function {
125b8b572e1SStephen Rothwell 	/* All functions for a given driver are linked */
126b8b572e1SStephen Rothwell 	struct list_head	link;
127b8b572e1SStephen Rothwell 
128b8b572e1SStephen Rothwell 	/* Function node & driver data */
129b8b572e1SStephen Rothwell 	struct device_node	*node;
130b8b572e1SStephen Rothwell 	void			*driver_data;
131b8b572e1SStephen Rothwell 
132b8b572e1SStephen Rothwell 	/* For internal use by core */
133b8b572e1SStephen Rothwell 	struct pmf_device	*dev;
134b8b572e1SStephen Rothwell 
135b8b572e1SStephen Rothwell 	/* The name is the "xxx" in "platform-do-xxx", this is how
136b8b572e1SStephen Rothwell 	 * platform functions are identified by this code. Some functions
137b8b572e1SStephen Rothwell 	 * only operate for a given target, in which case the phandle is
138b8b572e1SStephen Rothwell 	 * here (or 0 if the filter doesn't apply)
139b8b572e1SStephen Rothwell 	 */
140b8b572e1SStephen Rothwell 	const char		*name;
141b8b572e1SStephen Rothwell 	u32			phandle;
142b8b572e1SStephen Rothwell 
143b8b572e1SStephen Rothwell 	/* The flags for that function. You can have several functions
144b8b572e1SStephen Rothwell 	 * with the same name and different flag
145b8b572e1SStephen Rothwell 	 */
146b8b572e1SStephen Rothwell 	u32			flags;
147b8b572e1SStephen Rothwell 
148b8b572e1SStephen Rothwell 	/* The actual tokenized function blob */
149b8b572e1SStephen Rothwell 	const void		*data;
150b8b572e1SStephen Rothwell 	unsigned int		length;
151b8b572e1SStephen Rothwell 
152b8b572e1SStephen Rothwell 	/* Interrupt clients */
153b8b572e1SStephen Rothwell 	struct list_head	irq_clients;
154b8b572e1SStephen Rothwell 
155b8b572e1SStephen Rothwell 	/* Refcounting */
156b8b572e1SStephen Rothwell 	struct kref		ref;
157b8b572e1SStephen Rothwell };
158b8b572e1SStephen Rothwell 
159b8b572e1SStephen Rothwell /*
160b8b572e1SStephen Rothwell  * For platform functions that are interrupts, one can register
161b8b572e1SStephen Rothwell  * irq_client structures. You canNOT use the same structure twice
162b8b572e1SStephen Rothwell  * as it contains a link member. Also, the callback is called with
163b8b572e1SStephen Rothwell  * a spinlock held, you must not call back into any of the pmf_* functions
164b8b572e1SStephen Rothwell  * from within that callback
165b8b572e1SStephen Rothwell  */
166b8b572e1SStephen Rothwell struct pmf_irq_client {
167b8b572e1SStephen Rothwell 	void			(*handler)(void *data);
168b8b572e1SStephen Rothwell 	void			*data;
169b8b572e1SStephen Rothwell 	struct module		*owner;
170b8b572e1SStephen Rothwell 	struct list_head	link;
171b8b572e1SStephen Rothwell 	struct pmf_function	*func;
172b8b572e1SStephen Rothwell };
173b8b572e1SStephen Rothwell 
174b8b572e1SStephen Rothwell 
175b8b572e1SStephen Rothwell /*
176b8b572e1SStephen Rothwell  * Register/Unregister a function-capable driver and its handlers
177b8b572e1SStephen Rothwell  */
178b8b572e1SStephen Rothwell extern int pmf_register_driver(struct device_node *np,
179b8b572e1SStephen Rothwell 			      struct pmf_handlers *handlers,
180b8b572e1SStephen Rothwell 			      void *driverdata);
181b8b572e1SStephen Rothwell 
182b8b572e1SStephen Rothwell extern void pmf_unregister_driver(struct device_node *np);
183b8b572e1SStephen Rothwell 
184b8b572e1SStephen Rothwell 
185b8b572e1SStephen Rothwell /*
186b8b572e1SStephen Rothwell  * Register/Unregister interrupt clients
187b8b572e1SStephen Rothwell  */
188b8b572e1SStephen Rothwell extern int pmf_register_irq_client(struct device_node *np,
189b8b572e1SStephen Rothwell 				   const char *name,
190b8b572e1SStephen Rothwell 				   struct pmf_irq_client *client);
191b8b572e1SStephen Rothwell 
192b8b572e1SStephen Rothwell extern void pmf_unregister_irq_client(struct pmf_irq_client *client);
193b8b572e1SStephen Rothwell 
194b8b572e1SStephen Rothwell /*
195b8b572e1SStephen Rothwell  * Called by the handlers when an irq happens
196b8b572e1SStephen Rothwell  */
197b8b572e1SStephen Rothwell extern void pmf_do_irq(struct pmf_function *func);
198b8b572e1SStephen Rothwell 
199b8b572e1SStephen Rothwell 
200b8b572e1SStephen Rothwell /*
201b8b572e1SStephen Rothwell  * Low level call to platform functions.
202b8b572e1SStephen Rothwell  *
203b8b572e1SStephen Rothwell  * The phandle can filter on the target object for functions that have
204b8b572e1SStephen Rothwell  * multiple targets, the flags allow you to restrict the call to a given
205b8b572e1SStephen Rothwell  * combination of flags.
206b8b572e1SStephen Rothwell  *
207b8b572e1SStephen Rothwell  * The args array contains as many arguments as is required by the function,
208b8b572e1SStephen Rothwell  * this is dependent on the function you are calling, unfortunately Apple
209b8b572e1SStephen Rothwell  * mechanism provides no way to encode that so you have to get it right at
210b8b572e1SStephen Rothwell  * the call site. Some functions require no args, in which case, you can
211b8b572e1SStephen Rothwell  * pass NULL.
212b8b572e1SStephen Rothwell  *
213b8b572e1SStephen Rothwell  * You can also pass NULL to the name. This will match any function that has
214b8b572e1SStephen Rothwell  * the appropriate combination of flags & phandle or you can pass 0 to the
215b8b572e1SStephen Rothwell  * phandle to match any
216b8b572e1SStephen Rothwell  */
217b8b572e1SStephen Rothwell extern int pmf_do_functions(struct device_node *np, const char *name,
218b8b572e1SStephen Rothwell 			    u32 phandle, u32 flags, struct pmf_args *args);
219b8b572e1SStephen Rothwell 
220b8b572e1SStephen Rothwell 
221b8b572e1SStephen Rothwell 
222b8b572e1SStephen Rothwell /*
223b8b572e1SStephen Rothwell  * High level call to a platform function.
224b8b572e1SStephen Rothwell  *
225b8b572e1SStephen Rothwell  * This one looks for the platform-xxx first so you should call it to the
226b8b572e1SStephen Rothwell  * actual target if any. It will fallback to platform-do-xxx if it can't
227b8b572e1SStephen Rothwell  * find one. It will also exclusively target functions that have
228b8b572e1SStephen Rothwell  * the "OnDemand" flag.
229b8b572e1SStephen Rothwell  */
230b8b572e1SStephen Rothwell 
231b8b572e1SStephen Rothwell extern int pmf_call_function(struct device_node *target, const char *name,
232b8b572e1SStephen Rothwell 			     struct pmf_args *args);
233b8b572e1SStephen Rothwell 
234b8b572e1SStephen Rothwell 
235b8b572e1SStephen Rothwell /*
236b8b572e1SStephen Rothwell  * For low latency interrupt usage, you can lookup for on-demand functions
237b8b572e1SStephen Rothwell  * using the functions below
238b8b572e1SStephen Rothwell  */
239b8b572e1SStephen Rothwell 
240b8b572e1SStephen Rothwell extern struct pmf_function *pmf_find_function(struct device_node *target,
241b8b572e1SStephen Rothwell 					      const char *name);
242b8b572e1SStephen Rothwell 
243b8b572e1SStephen Rothwell extern struct pmf_function * pmf_get_function(struct pmf_function *func);
244b8b572e1SStephen Rothwell extern void pmf_put_function(struct pmf_function *func);
245b8b572e1SStephen Rothwell 
246b8b572e1SStephen Rothwell extern int pmf_call_one(struct pmf_function *func, struct pmf_args *args);
247b8b572e1SStephen Rothwell 
248*f91d5998SMathieu Malaterre int pmac_pfunc_base_install(void);
249b8b572e1SStephen Rothwell 
250b8b572e1SStephen Rothwell /* Suspend/resume code called by via-pmu directly for now */
251b8b572e1SStephen Rothwell extern void pmac_pfunc_base_suspend(void);
252b8b572e1SStephen Rothwell extern void pmac_pfunc_base_resume(void);
253b8b572e1SStephen Rothwell 
254b8b572e1SStephen Rothwell #endif /* __PMAC_PFUNC_H__ */
255