diff options
Diffstat (limited to 'drivers/firmware/arm_scmi/common.h')
| -rw-r--r-- | drivers/firmware/arm_scmi/common.h | 133 | 
1 files changed, 112 insertions, 21 deletions
| diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index c0fb45e7c3e8..228bf4a71d23 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -4,7 +4,7 @@   * driver common header file containing some definitions, structures   * and function prototypes used in all the different SCMI protocols.   * - * Copyright (C) 2018 ARM Ltd. + * Copyright (C) 2018-2021 ARM Ltd.   */  #ifndef _SCMI_COMMON_H  #define _SCMI_COMMON_H @@ -14,11 +14,14 @@  #include <linux/device.h>  #include <linux/errno.h>  #include <linux/kernel.h> +#include <linux/module.h>  #include <linux/scmi_protocol.h>  #include <linux/types.h>  #include <asm/unaligned.h> +#include "notify.h" +  #define PROTOCOL_REV_MINOR_MASK	GENMASK(15, 0)  #define PROTOCOL_REV_MAJOR_MASK	GENMASK(31, 16)  #define PROTOCOL_REV_MAJOR(x)	(u16)(FIELD_GET(PROTOCOL_REV_MAJOR_MASK, (x))) @@ -141,22 +144,92 @@ struct scmi_xfer {  	struct completion *async_done;  }; -void scmi_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer); -int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer); -int scmi_do_xfer_with_response(const struct scmi_handle *h, -			       struct scmi_xfer *xfer); -int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id, -		       size_t tx_size, size_t rx_size, struct scmi_xfer **p); -void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle, -			    struct scmi_xfer *xfer); +struct scmi_xfer_ops; + +/** + * struct scmi_protocol_handle  - Reference to an initialized protocol instance + * + * @dev: A reference to the associated SCMI instance device (handle->dev). + * @xops: A reference to a struct holding refs to the core xfer operations that + *	  can be used by the protocol implementation to generate SCMI messages. + * @set_priv: A method to set protocol private data for this instance. + * @get_priv: A method to get protocol private data previously set. + * + * This structure represents a protocol initialized against specific SCMI + * instance and it will be used as follows: + * - as a parameter fed from the core to the protocol initialization code so + *   that it can access the core xfer operations to build and generate SCMI + *   messages exclusively for the specific underlying protocol instance. + * - as an opaque handle fed by an SCMI driver user when it tries to access + *   this protocol through its own protocol operations. + *   In this case this handle will be returned as an opaque object together + *   with the related protocol operations when the SCMI driver tries to access + *   the protocol. + */ +struct scmi_protocol_handle { +	struct device *dev; +	const struct scmi_xfer_ops *xops; +	int (*set_priv)(const struct scmi_protocol_handle *ph, void *priv); +	void *(*get_priv)(const struct scmi_protocol_handle *ph); +}; + +/** + * struct scmi_xfer_ops  - References to the core SCMI xfer operations. + * @version_get: Get this version protocol. + * @xfer_get_init: Initialize one struct xfer if any xfer slot is free. + * @reset_rx_to_maxsz: Reset rx size to max transport size. + * @do_xfer: Do the SCMI transfer. + * @do_xfer_with_response: Do the SCMI transfer waiting for a response. + * @xfer_put: Free the xfer slot. + * + * Note that all this operations expect a protocol handle as first parameter; + * they then internally use it to infer the underlying protocol number: this + * way is not possible for a protocol implementation to forge messages for + * another protocol. + */ +struct scmi_xfer_ops { +	int (*version_get)(const struct scmi_protocol_handle *ph, u32 *version); +	int (*xfer_get_init)(const struct scmi_protocol_handle *ph, u8 msg_id, +			     size_t tx_size, size_t rx_size, +			     struct scmi_xfer **p); +	void (*reset_rx_to_maxsz)(const struct scmi_protocol_handle *ph, +				  struct scmi_xfer *xfer); +	int (*do_xfer)(const struct scmi_protocol_handle *ph, +		       struct scmi_xfer *xfer); +	int (*do_xfer_with_response)(const struct scmi_protocol_handle *ph, +				     struct scmi_xfer *xfer); +	void (*xfer_put)(const struct scmi_protocol_handle *ph, +			 struct scmi_xfer *xfer); +}; + +struct scmi_revision_info * +scmi_revision_area_get(const struct scmi_protocol_handle *ph);  int scmi_handle_put(const struct scmi_handle *handle);  struct scmi_handle *scmi_handle_get(struct device *dev);  void scmi_set_handle(struct scmi_device *scmi_dev); -int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version); -void scmi_setup_protocol_implemented(const struct scmi_handle *handle, +void scmi_setup_protocol_implemented(const struct scmi_protocol_handle *ph,  				     u8 *prot_imp); -int scmi_base_protocol_init(struct scmi_handle *h); +typedef int (*scmi_prot_init_ph_fn_t)(const struct scmi_protocol_handle *); + +/** + * struct scmi_protocol  - Protocol descriptor + * @id: Protocol ID. + * @owner: Module reference if any. + * @instance_init: Mandatory protocol initialization function. + * @instance_deinit: Optional protocol de-initialization function. + * @ops: Optional reference to the operations provided by the protocol and + *	 exposed in scmi_protocol.h. + * @events: An optional reference to the events supported by this protocol. + */ +struct scmi_protocol { +	const u8				id; +	struct module				*owner; +	const scmi_prot_init_ph_fn_t		instance_init; +	const scmi_prot_init_ph_fn_t		instance_deinit; +	const void				*ops; +	const struct scmi_protocol_events	*events; +};  int __init scmi_bus_init(void);  void __exit scmi_bus_exit(void); @@ -164,6 +237,7 @@ 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(base);  DECLARE_SCMI_REGISTER_UNREGISTER(clock);  DECLARE_SCMI_REGISTER_UNREGISTER(perf);  DECLARE_SCMI_REGISTER_UNREGISTER(power); @@ -172,17 +246,25 @@ DECLARE_SCMI_REGISTER_UNREGISTER(sensors);  DECLARE_SCMI_REGISTER_UNREGISTER(voltage);  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)); \ +#define DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(name, proto)	\ +static const struct scmi_protocol *__this_proto = &(proto);	\ +								\ +int __init scmi_##name##_register(void)				\ +{								\ +	return scmi_protocol_register(__this_proto);		\ +}								\ +								\ +void __exit scmi_##name##_unregister(void)			\ +{								\ +	scmi_protocol_unregister(__this_proto);			\  } +const struct scmi_protocol *scmi_protocol_get(int protocol_id); +void scmi_protocol_put(int protocol_id); + +int scmi_protocol_acquire(const struct scmi_handle *handle, u8 protocol_id); +void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id); +  /* SCMI Transport */  /**   * struct scmi_chan_info - Structure representing a SCMI channel information @@ -227,6 +309,11 @@ struct scmi_transport_ops {  	bool (*poll_done)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer);  }; +int scmi_protocol_device_request(const struct scmi_device_id *id_table); +void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table); +struct scmi_device *scmi_child_dev_find(struct device *parent, +					int prot_id, const char *name); +  /**   * struct scmi_desc - Description of SoC integration   * @@ -265,4 +352,8 @@ void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem);  bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,  		     struct scmi_xfer *xfer); +void scmi_notification_instance_data_set(const struct scmi_handle *handle, +					 void *priv); +void *scmi_notification_instance_data_get(const struct scmi_handle *handle); +  #endif /* _SCMI_COMMON_H */ | 
