Commit 0415052d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'devprop-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull device properties framework updates from Rafael Wysocki:
 "These add helpers for counting items in a property array and extend
  the "software nodes" support to be more convenient for representing
  device properties supplied by drivers and make the intel_cht_int33fe
  driver use that.

  Specifics:

   - Add helpers to count items in a property array (Andy Shevchenko).

   - Extend "software nodes" support to be more convenient for
     representing device properties supplied by drivers (Heikki
     Krogerus).

   - Add device_find_child_by_name() helper to the driver core (Heikki
     Krogerus).

   - Extend device connection code to also look for references provided
     via fwnode pointers (Heikki Krogerus).

   - Start to register proper struct device objects for USB Type-C muxes
     and orientation switches (Heikki Krogerus).

   - Update the intel_cht_int33fe driver to describe devices in a more
     general way with the help of "software nodes" (Heikki Krogerus)"

* tag 'devprop-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  device property: Add helpers to count items in an array
  platform/x86: intel_cht_int33fe: Replacing the old connections with references
  platform/x86: intel_cht_int33fe: Supply fwnodes for the external dependencies
  platform/x86: intel_cht_int33fe: Provide fwnode for the USB connector
  platform/x86: intel_cht_int33fe: Provide software nodes for the devices
  platform/x86: intel_cht_int33fe: Remove unused fusb302 device property
  platform/x86: intel_cht_int33fe: Register max17047 in its own function
  usb: typec: Registering real device entries for the muxes
  device connection: Find connections also by checking the references
  device property: Introduce fwnode_find_reference()
  ACPI / property: Don't limit named child node matching to data nodes
  driver core: Add helper device_find_child_by_name()
  software node: Add software_node_get_reference_args()
  software node: Use kobject name when finding child nodes by name
  software node: Add support for static node descriptors
  software node: Simplify software_node_release() function
  software node: Allow node creation without properties
parents 4b470452 33ee09cd
......@@ -600,15 +600,29 @@ static struct fwnode_handle *
acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
const char *childname)
{
char name[ACPI_PATH_SEGMENT_LENGTH];
struct fwnode_handle *child;
struct acpi_buffer path;
acpi_status status;
/*
* Find first matching named child node of this fwnode.
* For ACPI this will be a data only sub-node.
*/
fwnode_for_each_child_node(fwnode, child)
if (acpi_data_node_match(child, childname))
path.length = sizeof(name);
path.pointer = name;
fwnode_for_each_child_node(fwnode, child) {
if (is_acpi_data_node(child)) {
if (acpi_data_node_match(child, childname))
return child;
continue;
}
status = acpi_get_name(ACPI_HANDLE_FWNODE(child),
ACPI_SINGLE_NAME, &path);
if (ACPI_FAILURE(status))
break;
if (!strncmp(name, childname, ACPI_NAMESEG_SIZE))
return child;
}
return NULL;
}
......
......@@ -2474,6 +2474,34 @@ struct device *device_find_child(struct device *parent, void *data,
}
EXPORT_SYMBOL_GPL(device_find_child);
/**
* device_find_child_by_name - device iterator for locating a child device.
* @parent: parent struct device
* @name: name of the child device
*
* This is similar to the device_find_child() function above, but it
* returns a reference to a device that has the name @name.
*
* NOTE: you will need to drop the reference with put_device() after use.
*/
struct device *device_find_child_by_name(struct device *parent,
const char *name)
{
struct klist_iter i;
struct device *child;
if (!parent)
return NULL;
klist_iter_init(&parent->p->klist_children, &i);
while ((child = next_device(&i)))
if (!strcmp(dev_name(child), name) && get_device(child))
break;
klist_iter_exit(&i);
return child;
}
EXPORT_SYMBOL_GPL(device_find_child_by_name);
int __init devices_init(void)
{
devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
......
......@@ -38,6 +38,28 @@ fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id,
return NULL;
}
static void *
fwnode_devcon_match(struct fwnode_handle *fwnode, const char *con_id,
void *data, devcon_match_fn_t match)
{
struct device_connection con = { };
void *ret;
int i;
for (i = 0; ; i++) {
con.fwnode = fwnode_find_reference(fwnode, con_id, i);
if (IS_ERR(con.fwnode))
break;
ret = match(&con, -1, data);
fwnode_handle_put(con.fwnode);
if (ret)
return ret;
}
return NULL;
}
/**
* device_connection_find_match - Find physical connection to a device
* @dev: Device with the connection
......@@ -65,6 +87,10 @@ void *device_connection_find_match(struct device *dev, const char *con_id,
ret = fwnode_graph_devcon_match(fwnode, con_id, data, match);
if (ret)
return ret;
ret = fwnode_devcon_match(fwnode, con_id, data, match);
if (ret)
return ret;
}
mutex_lock(&devcon_lock);
......
......@@ -484,6 +484,30 @@ int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode,
}
EXPORT_SYMBOL_GPL(fwnode_property_get_reference_args);
/**
* fwnode_find_reference - Find named reference to a fwnode_handle
* @fwnode: Firmware node where to look for the reference
* @name: The name of the reference
* @index: Index of the reference
*
* @index can be used when the named reference holds a table of references.
*
* Returns pointer to the reference fwnode, or ERR_PTR. Caller is responsible to
* call fwnode_handle_put() on the returned fwnode pointer.
*/
struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode,
const char *name,
unsigned int index)
{
struct fwnode_reference_args args;
int ret;
ret = fwnode_property_get_reference_args(fwnode, name, NULL, 0, index,
&args);
return ret ? ERR_PTR(ret) : args.fwnode;
}
EXPORT_SYMBOL_GPL(fwnode_find_reference);
/**
* device_remove_properties - Remove properties from a device object.
* @dev: Device whose properties to remove.
......
This diff is collapsed.
This diff is collapsed.
......@@ -101,7 +101,7 @@ static void *usb_role_switch_match(struct device_connection *con, int ep,
struct device *dev;
if (con->fwnode) {
if (!fwnode_property_present(con->fwnode, con->id))
if (con->id && !fwnode_property_present(con->fwnode, con->id))
return NULL;
dev = class_find_device(role_class, NULL, con->fwnode,
......
......@@ -35,4 +35,19 @@ extern const struct device_type typec_port_dev_type;
#define is_typec_altmode(_dev_) (_dev_->type == &typec_altmode_dev_type)
#define is_typec_port(_dev_) (_dev_->type == &typec_port_dev_type)
extern struct class typec_mux_class;
struct typec_switch {
struct device dev;
typec_switch_set_fn_t set;
};
struct typec_mux {
struct device dev;
typec_mux_set_fn_t set;
};
#define to_typec_switch(_dev_) container_of(_dev_, struct typec_switch, dev)
#define to_typec_mux(_dev_) container_of(_dev_, struct typec_mux, dev)
#endif /* __USB_TYPEC_ALTMODE_H__ */
......@@ -1646,13 +1646,25 @@ static int __init typec_init(void)
if (ret)
return ret;
ret = class_register(&typec_mux_class);
if (ret)
goto err_unregister_bus;
typec_class = class_create(THIS_MODULE, "typec");
if (IS_ERR(typec_class)) {
bus_unregister(&typec_bus);
return PTR_ERR(typec_class);
ret = PTR_ERR(typec_class);
goto err_unregister_mux_class;
}
return 0;
err_unregister_mux_class:
class_unregister(&typec_mux_class);
err_unregister_bus:
bus_unregister(&typec_bus);
return ret;
}
subsys_initcall(typec_init);
......@@ -1661,6 +1673,7 @@ static void __exit typec_exit(void)
class_destroy(typec_class);
ida_destroy(&typec_index_ida);
bus_unregister(&typec_bus);
class_unregister(&typec_mux_class);
}
module_exit(typec_exit);
......
......@@ -15,35 +15,47 @@
#include <linux/slab.h>
#include <linux/usb/typec_mux.h>
static DEFINE_MUTEX(switch_lock);
static DEFINE_MUTEX(mux_lock);
static LIST_HEAD(switch_list);
static LIST_HEAD(mux_list);
#include "bus.h"
static int name_match(struct device *dev, const void *name)
{
return !strcmp((const char *)name, dev_name(dev));
}
static bool dev_name_ends_with(struct device *dev, const char *suffix)
{
const char *name = dev_name(dev);
const int name_len = strlen(name);
const int suffix_len = strlen(suffix);
if (suffix_len > name_len)
return false;
return strcmp(name + (name_len - suffix_len), suffix) == 0;
}
static int switch_fwnode_match(struct device *dev, const void *fwnode)
{
return dev_fwnode(dev) == fwnode && dev_name_ends_with(dev, "-switch");
}
static void *typec_switch_match(struct device_connection *con, int ep,
void *data)
{
struct typec_switch *sw;
if (!con->fwnode) {
list_for_each_entry(sw, &switch_list, entry)
if (!strcmp(con->endpoint[ep], dev_name(sw->dev)))
return sw;
return ERR_PTR(-EPROBE_DEFER);
}
struct device *dev;
/*
* With OF graph the mux node must have a boolean device property named
* "orientation-switch".
*/
if (con->id && !fwnode_property_present(con->fwnode, con->id))
return NULL;
if (con->fwnode) {
if (con->id && !fwnode_property_present(con->fwnode, con->id))
return NULL;
list_for_each_entry(sw, &switch_list, entry)
if (dev_fwnode(sw->dev) == con->fwnode)
return sw;
dev = class_find_device(&typec_mux_class, NULL, con->fwnode,
switch_fwnode_match);
} else {
dev = class_find_device(&typec_mux_class, NULL,
con->endpoint[ep], name_match);
}
return con->id ? ERR_PTR(-EPROBE_DEFER) : NULL;
return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER);
}
/**
......@@ -59,14 +71,10 @@ struct typec_switch *typec_switch_get(struct device *dev)
{
struct typec_switch *sw;
mutex_lock(&switch_lock);
sw = device_connection_find_match(dev, "orientation-switch", NULL,
typec_switch_match);
if (!IS_ERR_OR_NULL(sw)) {
WARN_ON(!try_module_get(sw->dev->driver->owner));
get_device(sw->dev);
}
mutex_unlock(&switch_lock);
if (!IS_ERR_OR_NULL(sw))
WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
return sw;
}
......@@ -81,28 +89,64 @@ EXPORT_SYMBOL_GPL(typec_switch_get);
void typec_switch_put(struct typec_switch *sw)
{
if (!IS_ERR_OR_NULL(sw)) {
module_put(sw->dev->driver->owner);
put_device(sw->dev);
module_put(sw->dev.parent->driver->owner);
put_device(&sw->dev);
}
}
EXPORT_SYMBOL_GPL(typec_switch_put);
static void typec_switch_release(struct device *dev)
{
kfree(to_typec_switch(dev));
}
static const struct device_type typec_switch_dev_type = {
.name = "orientation_switch",
.release = typec_switch_release,
};
/**
* typec_switch_register - Register USB Type-C orientation switch
* @sw: USB Type-C orientation switch
* @parent: Parent device
* @desc: Orientation switch description
*
* This function registers a switch that can be used for routing the correct
* data pairs depending on the cable plug orientation from the USB Type-C
* connector to the USB controllers. USB Type-C plugs can be inserted
* right-side-up or upside-down.
*/
int typec_switch_register(struct typec_switch *sw)
struct typec_switch *
typec_switch_register(struct device *parent,
const struct typec_switch_desc *desc)
{
mutex_lock(&switch_lock);
list_add_tail(&sw->entry, &switch_list);
mutex_unlock(&switch_lock);
struct typec_switch *sw;
int ret;
if (!desc || !desc->set)
return ERR_PTR(-EINVAL);
sw = kzalloc(sizeof(*sw), GFP_KERNEL);
if (!sw)
return ERR_PTR(-ENOMEM);
return 0;
sw->set = desc->set;
device_initialize(&sw->dev);
sw->dev.parent = parent;
sw->dev.fwnode = desc->fwnode;
sw->dev.class = &typec_mux_class;
sw->dev.type = &typec_switch_dev_type;
sw->dev.driver_data = desc->drvdata;
dev_set_name(&sw->dev, "%s-switch", dev_name(parent));
ret = device_add(&sw->dev);
if (ret) {
dev_err(parent, "failed to register switch (%d)\n", ret);
put_device(&sw->dev);
return ERR_PTR(ret);
}
return sw;
}
EXPORT_SYMBOL_GPL(typec_switch_register);
......@@ -114,28 +158,44 @@ EXPORT_SYMBOL_GPL(typec_switch_register);
*/
void typec_switch_unregister(struct typec_switch *sw)
{
mutex_lock(&switch_lock);
list_del(&sw->entry);
mutex_unlock(&switch_lock);
if (!IS_ERR_OR_NULL(sw))
device_unregister(&sw->dev);
}
EXPORT_SYMBOL_GPL(typec_switch_unregister);
void typec_switch_set_drvdata(struct typec_switch *sw, void *data)
{
dev_set_drvdata(&sw->dev, data);
}
EXPORT_SYMBOL_GPL(typec_switch_set_drvdata);
void *typec_switch_get_drvdata(struct typec_switch *sw)
{
return dev_get_drvdata(&sw->dev);
}
EXPORT_SYMBOL_GPL(typec_switch_get_drvdata);
/* ------------------------------------------------------------------------- */
static int mux_fwnode_match(struct device *dev, const void *fwnode)
{
return dev_fwnode(dev) == fwnode && dev_name_ends_with(dev, "-mux");
}
static void *typec_mux_match(struct device_connection *con, int ep, void *data)
{
const struct typec_altmode_desc *desc = data;
struct typec_mux *mux;
int nval;
struct device *dev;
bool match;
int nval;
u16 *val;
int i;
if (!con->fwnode) {
list_for_each_entry(mux, &mux_list, entry)
if (!strcmp(con->endpoint[ep], dev_name(mux->dev)))
return mux;
return ERR_PTR(-EPROBE_DEFER);
dev = class_find_device(&typec_mux_class, NULL,
con->endpoint[ep], name_match);
return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER);
}
/*
......@@ -180,11 +240,10 @@ static void *typec_mux_match(struct device_connection *con, int ep, void *data)
return NULL;
find_mux:
list_for_each_entry(mux, &mux_list, entry)
if (dev_fwnode(mux->dev) == con->fwnode)
return mux;
dev = class_find_device(&typec_mux_class, NULL, con->fwnode,
mux_fwnode_match);
return ERR_PTR(-EPROBE_DEFER);
return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER);
}
/**
......@@ -202,14 +261,10 @@ struct typec_mux *typec_mux_get(struct device *dev,
{
struct typec_mux *mux;
mutex_lock(&mux_lock);
mux = device_connection_find_match(dev, "mode-switch", (void *)desc,
typec_mux_match);
if (!IS_ERR_OR_NULL(mux)) {
WARN_ON(!try_module_get(mux->dev->driver->owner));
get_device(mux->dev);
}
mutex_unlock(&mux_lock);
if (!IS_ERR_OR_NULL(mux))
WARN_ON(!try_module_get(mux->dev.parent->driver->owner));
return mux;
}
......@@ -224,28 +279,63 @@ EXPORT_SYMBOL_GPL(typec_mux_get);
void typec_mux_put(struct typec_mux *mux)
{
if (!IS_ERR_OR_NULL(mux)) {
module_put(mux->dev->driver->owner);
put_device(mux->dev);
module_put(mux->dev.parent->driver->owner);
put_device(&mux->dev);
}
}
EXPORT_SYMBOL_GPL(typec_mux_put);
static void typec_mux_release(struct device *dev)
{
kfree(to_typec_mux(dev));
}
static const struct device_type typec_mux_dev_type = {
.name = "mode_switch",
.release = typec_mux_release,
};
/**
* typec_mux_register - Register Multiplexer routing USB Type-C pins
* @mux: USB Type-C Connector Multiplexer/DeMultiplexer
* @parent: Parent device
* @desc: Multiplexer description
*
* USB Type-C connectors can be used for alternate modes of operation besides
* USB when Accessory/Alternate Modes are supported. With some of those modes,
* the pins on the connector need to be reconfigured. This function registers
* multiplexer switches routing the pins on the connector.
*/
int typec_mux_register(struct typec_mux *mux)
struct typec_mux *
typec_mux_register(struct device *parent, const struct typec_mux_desc *desc)
{
mutex_lock(&mux_lock);
list_add_tail(&mux->entry, &mux_list);
mutex_unlock(&mux_lock);
struct typec_mux *mux;
int ret;
if (!desc || !desc->set)
return ERR_PTR(-EINVAL);
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
if (!mux)
return ERR_PTR(-ENOMEM);
mux->set = desc->set;
device_initialize(&mux->dev);
mux->dev.parent = parent;
mux->dev.fwnode = desc->fwnode;
mux->dev.class = &typec_mux_class;
mux->dev.type = &typec_mux_dev_type;
mux->dev.driver_data = desc->drvdata;
dev_set_name(&mux->dev, "%s-mux", dev_name(parent));
ret = device_add(&mux->dev);
if (ret) {
dev_err(parent, "failed to register mux (%d)\n", ret);
put_device(&mux->dev);
return ERR_PTR(ret);
}
return 0;
return mux;
}
EXPORT_SYMBOL_GPL(typec_mux_register);
......@@ -257,8 +347,24 @@ EXPORT_SYMBOL_GPL(typec_mux_register);
*/
void typec_mux_unregister(struct typec_mux *mux)
{
mutex_lock(&mux_lock);
list_del(&mux->entry);
mutex_unlock(&mux_lock);
if (!IS_ERR_OR_NULL(mux))
device_unregister(&mux->dev);
}
EXPORT_SYMBOL_GPL(typec_mux_unregister);
void typec_mux_set_drvdata(struct typec_mux *mux, void *data)
{
dev_set_drvdata(&mux->dev, data);
}
EXPORT_SYMBOL_GPL(typec_mux_set_drvdata);
void *typec_mux_get_drvdata(struct typec_mux *mux)
{
return dev_get_drvdata(&mux->dev);
}
EXPORT_SYMBOL_GPL(typec_mux_get_drvdata);
struct class typec_mux_class = {
.name = "typec_mux",
.owner = THIS_MODULE,
};
......@@ -23,8 +23,8 @@
struct pi3usb30532 {
struct i2c_client *client;
struct mutex lock; /* protects the cached conf register */
struct typec_switch sw;
struct typec_mux mux;
struct typec_switch *sw;
struct typec_mux *mux;
u8 conf;
};
......@@ -48,7 +48,7 @@ static int pi3usb30532_set_conf(struct pi3usb30532 *pi, u8 new_conf)
static int pi3usb30532_sw_set(struct typec_switch *sw,
enum typec_orientation orientation)
{
struct pi3usb30532 *pi = container_of(sw, struct pi3usb30532, sw);
struct pi3usb30532 *pi = typec_switch_get_drvdata(sw);
u8 new_conf;
int ret;
......@@ -75,7 +75,7 @@ static int pi3usb30532_sw_set(struct typec_switch *sw,
static int pi3usb30532_mux_set(struct typec_mux *mux, int state)
{
struct pi3usb30532 *pi = container_of(mux, struct pi3usb30532, mux);
struct pi3usb30532 *pi = typec_mux_get_drvdata(mux);
u8 new_conf;
int ret;
......@@ -113,6 +113,8 @@ static int pi3usb30532_mux_set(struct typec_mux *mux, int state)
static int pi3usb30532_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct typec_switch_desc sw_desc;
struct typec_mux_desc mux_desc;
struct pi3usb30532 *pi;
int ret;
......@@ -121,10 +123,6 @@ static int pi3usb30532_probe(struct i2c_client *client)
return -ENOMEM;
pi->client = client;
pi->sw.dev = dev;
pi->sw.set = pi3usb30532_sw_set;
pi->mux.dev = dev;
pi->mux.set = pi3usb30532_mux_set;
mutex_init(&pi->lock);
ret = i2c_smbus_read_byte_data(client, PI3USB30532_CONF);
......@@ -134,17 +132,27 @@ static int pi3usb30532_probe(struct i2c_client *client)
}
pi->conf = ret;
ret = typec_switch_register(&pi->sw);
if (ret) {
dev_err(dev, "Error registering typec switch: %d\n", ret);
return ret;
sw_desc.drvdata = pi;
sw_desc.fwnode = dev->fwnode;
sw_desc.set = pi3usb30532_sw_set;
pi->sw = typec_switch_register(dev, &sw_desc);
if (IS_ERR(pi->sw)) {
dev_err(dev, "Error registering typec switch: %ld\n",
PTR_ERR(pi->sw));
return PTR_ERR(pi->sw);
}
ret = typec_mux_register(&pi->mux);
if (ret) {
typec_switch_unregister(&pi->sw);
dev_err(dev, "Error registering typec mux: %d\n", ret);
return ret;
mux_desc.drvdata = pi;
mux_desc.fwnode = dev->fwnode;
mux_desc.set = pi3usb30532_mux_set;
pi->mux = typec_mux_register(dev, &mux_desc);
if (IS_ERR(pi->mux)) {
typec_switch_unregister(pi->sw);
dev_err(dev, "Error registering typec mux: %ld\n",
PTR_ERR(pi->mux));
return PTR_ERR(pi->mux);
}
i2c_set_clientdata(client, pi);
......@@ -155,8 +163,8 @@ static int pi3usb30532_remove(struct i2c_client *client)
{
struct pi3usb30532 *pi = i2c_get_clientdata(client);
typec_mux_unregister(&pi->mux);
typec_switch_unregister(&pi->sw);
typec_mux_unregister(pi->mux);
typec_switch_unregister(pi->sw);
return 0;
}
......
......@@ -1255,6 +1255,8 @@ extern int device_for_each_child_reverse(struct device *dev, void *data,
int (*fn)(struct device *dev, void *data));
extern struct device *device_find_child(struct device *dev, void *data,
int (*match)(struct device *dev, void *data));
extern struct device *device_find_child_by_name(struct device *parent,
const char *name);
extern int device_rename(struct device *dev, const char *new_name);
extern int device_move(struct device *dev, struct device *new_parent,
enum dpm_order dpm_order);
......
......@@ -76,6 +76,10 @@ int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode,
unsigned int nargs, unsigned int index,
struct fwnode_reference_args *args);
struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode,
const char *name,
unsigned int index);
struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode);
struct fwnode_handle *fwnode_get_next_parent(
struct fwnode_handle *fwnode);
......@@ -141,6 +145,26 @@ static inline int device_property_read_u64(struct device *dev,
return device_property_read_u64_array(dev, propname, val, 1);
}
static inline int device_property_count_u8(struct device *dev, const char *propname)
{
return device_property_read_u8_array(dev, propname, NULL, 0);
}
static inline int device_property_count_u16(struct device *dev, const char *propname)
{
return device_property_read_u16_array(dev, propname, NULL, 0);
}
static inline int device_property_count_u32(struct device *dev, const char *propname)
{
return device_property_read_u32_array(dev, propname, NULL, 0);
}
static inline int device_property_count_u64(struct device *dev, const char *propname)
{
return device_property_read_u64_array(dev, propname, NULL, 0);
}
static inline bool fwnode_property_read_bool(const struct fwnode_handle *fwnode,
const char *propname)
{
......@@ -171,6 +195,30 @@ static inline int fwnode_property_read_u64(const struct fwnode_handle *fwnode,
return fwnode_property_read_u64_array(fwnode, propname, val, 1);
}
static inline int fwnode_property_count_u8(const struct fwnode_handle *fwnode,
const char *propname)
{
return fwnode_property_read_u8_array(fwnode, propname, NULL, 0);
}
static inline int fwnode_property_count_u16(const struct fwnode_handle *fwnode,
const char *propname)
{
return fwnode_property_read_u16_array(fwnode, propname, NULL, 0);
}
static inline int fwnode_property_count_u32(const struct fwnode_handle *fwnode,
const char *propname)
{
return fwnode_property_read_u32_array(fwnode, propname, NULL, 0);
}
static inline int fwnode_property_count_u64(const struct fwnode_handle *fwnode,
const char *propname)
{
return fwnode_property_read_u64_array(fwnode, propname, NULL, 0);
}
/**
* struct property_entry - "Built-in" device property representation.
* @name: Name of the property.
......@@ -329,7 +377,54 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
/* -------------------------------------------------------------------------- */
/* Software fwnode support - when HW description is incomplete or missing */
struct software_node;
/**
* struct software_node_ref_args - Reference with additional arguments
* @node: Reference to a software node
* @nargs: Number of elements in @args array
* @args: Integer arguments
*/
struct software_node_ref_args {
const struct software_node *node;
unsigned int nargs;
u64 args[NR_FWNODE_REFERENCE_ARGS];
};
/**
* struct software_node_reference - Named software node reference property
* @name: Name of the property
* @nrefs: Number of elements in @refs array
* @refs: Array of references with optional arguments
*/
struct software_node_reference {
const char *name;
unsigned int nrefs;
const struct software_node_ref_args *refs;
};
/**
* struct software_node - Software node description
* @name: Name of the software node
* @parent: Parent of the software node
* @properties: Array of device properties
* @references: Array of software node reference properties
*/
struct software_node {
const char *name;
const struct software_node *parent;
const struct property_entry *properties;
const struct software_node_reference *references;
};
bool is_software_node(const struct fwnode_handle *fwnode);
const struct software_node *to_software_node(struct fwnode_handle *fwnode);
struct fwnode_handle *software_node_fwnode(const struct software_node *node);
int software_node_register_nodes(const struct software_node *nodes);
void software_node_unregister_nodes(const struct software_node *nodes);
int software_node_register(const struct software_node *node);
int software_node_notify(struct device *dev, unsigned long action);
......
......@@ -3,54 +3,48 @@
#ifndef __USB_TYPEC_MUX
#define __USB_TYPEC_MUX
#include <linux/list.h>
#include <linux/usb/typec.h>
struct device;
struct typec_mux;
struct typec_switch;
struct fwnode_handle;
/**
* struct typec_switch - USB Type-C cable orientation switch
* @dev: Switch device
* @entry: List entry
* @set: Callback to the driver for setting the orientation
*
* USB Type-C pin flipper switch routing the correct data pairs from the
* connector to the USB controller depending on the orientation of the cable
* plug.
*/
struct typec_switch {
struct device *dev;
struct list_head entry;
int (*set)(struct typec_switch *sw, enum typec_orientation orientation);
};
typedef int (*typec_switch_set_fn_t)(struct typec_switch *sw,
enum typec_orientation orientation);
/**
* struct typec_switch - USB Type-C connector pin mux
* @dev: Mux device
* @entry: List entry
* @set: Callback to the driver for setting the state of the mux
*
* Pin Multiplexer/DeMultiplexer switch routing the USB Type-C connector pins to
* different components depending on the requested mode of operation. Used with
* Accessory/Alternate modes.
*/
struct typec_mux {
struct device *dev;
struct list_head entry;
int (*set)(struct typec_mux *mux, int state);
struct typec_switch_desc {
struct fwnode_handle *fwnode;
typec_switch_set_fn_t set;
void *drvdata;
};
struct typec_switch *typec_switch_get(struct device *dev);
void typec_switch_put(struct typec_switch *sw);
int typec_switch_register(struct typec_switch *sw);
struct typec_switch *
typec_switch_register(struct device *parent,
const struct typec_switch_desc *desc);
void typec_switch_unregister(struct typec_switch *sw);
void typec_switch_set_drvdata(struct typec_switch *sw, void *data);
void *typec_switch_get_drvdata(struct typec_switch *sw);
typedef int (*typec_mux_set_fn_t)(struct typec_mux *mux, int state);
struct typec_mux_desc {
struct fwnode_handle *fwnode;
typec_mux_set_fn_t set;
void *drvdata;
};
struct typec_mux *
typec_mux_get(struct device *dev, const struct typec_altmode_desc *desc);
void typec_mux_put(struct typec_mux *mux);
int typec_mux_register(struct typec_mux *mux);
struct typec_mux *
typec_mux_register(struct device *parent, const struct typec_mux_desc *desc);
void typec_mux_unregister(struct typec_mux *mux);
void typec_mux_set_drvdata(struct typec_mux *mux, void *data);
void *typec_mux_get_drvdata(struct typec_mux *mux);
#endif /* __USB_TYPEC_MUX */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment