Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1297c4a6 authored by Hanumant Singh's avatar Hanumant Singh
Browse files

esoc: Add support for client notifications



Allow clients to register for external soc events.

Change-Id: If96ec725ecddfb548d7e680b09bfd68be573c11c
Signed-off-by: default avatarHanumant Singh <hanumant@codeaurora.org>
parent faefe1ea
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
== Introduction ==

In case of multiple external socs each exposing more than one interface to a
primary SOC, it is possible for the different interface drivers/clients to
expect notifications regarding the state of the external soc that they are
interested in. In some cases clients may need notifications of the status of
multiple external socs. The bindings referred to below enable a client device
to register for notifications from multiple external socs.

== Esoc client devices ==

For each esoc client device, every external soc that it is associated with, is
assigned an integer id. These ids start at 0 and are contiguous. Each id
represents a unique external soc. Each external soc is additionally assigned a
name. An additional property is used to spcify the names. A mapping is
performed from the name to the id.

Required properties:
esoc-0:		A phandle pointing to the esoc node that the esoc client is
		interested in.

esoc-names:	A list of string names for all the esocs that a given client
		is interested in. Must have atleast one name corresponding to
		esoc-0.

Optional properties:
esoc-1:		A phandle to the external soc, mapping to the second name in
		esoc-names.
...
esoc-n:		A phandle to the nth external soc mapping to the nth name in
		the esoc-names

== Example ==

esoc_a {
	compatible = "esoc_mdm";
	....
	...
	..
};

esoc_b {
	compatible = "esoc_wlan";
	..
	..
};

pcie@0x0001 {
	compatible = "esoc-pcie-client"
	....
	..
	..
	esoc-names = "mdm", "wlan";
	esoc-0 = <&esoc_a>;
	esoc-1 = <&esoc_b>;
	..
	..
};
+9 −0
Original line number Diff line number Diff line
@@ -19,6 +19,15 @@ config ESOC_DEV
	  for the external soc. It can receive event notifications from the
	  control link.

config ESOC_CLIENT
	bool "ESOC client interface"
	depends on OF
	help
	  Say yes here to enable client interface for external socs.
	  Clients can specify the external soc that they are interested in
	  by using device tree phandles. Based on this, clients can register
	  for notifications from a specific soc.

config ESOC_DEBUG
	bool "ESOC debug support"
	help
+1 −0
Original line number Diff line number Diff line
@@ -3,5 +3,6 @@
ccflags-$(CONFIG_ESOC_DEBUG)	:= -DDEBUG
obj-$(CONFIG_ESOC)	+= esoc_bus.o
obj-$(CONFIG_ESOC_DEV)	+= esoc_dev.o
obj-$(CONFIG_ESOC_CLIENT)	+= esoc_client.o
obj-$(CONFIG_ESOC_MDM_4x)	+= esoc-mdm-4x.o
obj-$(CONFIG_ESOC_MDM_DRV)	+= esoc-mdm-drv.o
+13 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ struct esoc_eng {
 * @compat_data: compat data of esoc driver.
 * @subsys_desc: descriptor for subsystem restart
 * @subsys_dev: ssr device handle.
 * @np: device tree node for esoc_clink.
 */
struct esoc_clink {
	const char *name;
@@ -73,6 +74,7 @@ struct esoc_clink {
	void *compat_data;
	struct subsys_desc subsys;
	struct subsys_device *subsys_dev;
	struct device_node *np;
};

/**
@@ -125,6 +127,7 @@ int esoc_dev_init(void);
void esoc_clink_unregister(struct esoc_clink *esoc_dev);
int esoc_clink_register(struct esoc_clink *esoc_dev);
struct esoc_clink *get_esoc_clink(int id);
struct esoc_clink *get_esoc_clink_by_node(struct device_node *node);
void put_esoc_clink(struct esoc_clink *esoc_clink);
void *get_esoc_clink_data(struct esoc_clink *esoc);
void set_esoc_clink_data(struct esoc_clink *esoc, void *data);
@@ -147,4 +150,14 @@ void *esoc_get_drv_data(struct esoc_clink *esoc_clink);
int esoc_clink_register_ssr(struct esoc_clink *esoc_clink);
int esoc_clink_request_ssr(struct esoc_clink *esoc_clink);
void esoc_clink_unregister_ssr(struct esoc_clink *esoc_clink);
/* client notification */
#ifdef CONFIG_ESOC_CLIENT
void notify_esoc_clients(struct esoc_clink *esoc_clink, unsigned long evt);
#else
static inline void notify_esoc_clients(struct esoc_clink *esoc_clink,
							unsigned long evt)
{
	return;
}
#endif
#endif
+27 −0
Original line number Diff line number Diff line
@@ -101,6 +101,19 @@ static int esoc_clink_match_id(struct device *dev, void *id)
	return 0;
}

static int esoc_clink_match_node(struct device *dev, void *id)
{
	struct esoc_clink *esoc_clink = to_esoc_clink(dev);
	struct device_node *node = id;

	if (esoc_clink->np == node) {
		if (!try_module_get(esoc_clink->owner))
			return 0;
		return 1;
	}
	return 0;
}

void esoc_for_each_dev(void *data, int (*fn)(struct device *dev, void *))
{
	int ret;
@@ -123,6 +136,19 @@ struct esoc_clink *get_esoc_clink(int id)
}
EXPORT_SYMBOL(get_esoc_clink);

struct esoc_clink *get_esoc_clink_by_node(struct device_node *node)
{
	struct esoc_clink *esoc_clink;
	struct device *dev;

	dev = bus_find_device(&esoc_bus_type, NULL, node,
						esoc_clink_match_node);
	if (IS_ERR(dev))
		return NULL;
	esoc_clink = to_esoc_clink(dev);
	return esoc_clink;
}

void put_esoc_clink(struct esoc_clink *esoc_clink)
{
	module_put(esoc_clink->owner);
@@ -176,6 +202,7 @@ void esoc_clink_evt_notify(enum esoc_evt evt, struct esoc_clink *esoc_clink)
	unsigned long flags;

	spin_lock_irqsave(&esoc_clink->notify_lock, flags);
	notify_esoc_clients(esoc_clink, evt);
	if (esoc_clink->req_eng && esoc_clink->req_eng->handle_clink_evt)
		esoc_clink->req_eng->handle_clink_evt(evt, esoc_clink->req_eng);
	if (esoc_clink->cmd_eng && esoc_clink->cmd_eng->handle_clink_evt)
Loading