Component Helper for Aggregate Drivers

The component helper allows drivers to collect a pile of sub-devices,including their bound drivers, into an aggregate driver. Various subsystemsalready provide functions to get hold of such components, e.g.of_clk_get_by_name(). The component helper can be used when such asubsystem-specific way to find a device is not available: The componenthelper fills the niche of aggregate drivers for specific hardware, wherefurther standardization into a subsystem would not be practical. The commonexample is when a logical device (e.g. a DRM display driver) is spread aroundthe SoC on various components (scanout engines, blending blocks, transcodersfor various outputs and so on).

The component helper also doesn’t solve runtime dependencies, e.g. for systemsuspend and resume operations. See alsodevice links.

Components are registered usingcomponent_add() and unregistered withcomponent_del(), usually from the driver’s probe and disconnect functions.

Aggregate drivers first assemble a component match list of what they needusingcomponent_match_add(). This is then registered as an aggregate driverusingcomponent_master_add_with_match(), and unregistered usingcomponent_master_del().

API

structcomponent_ops

callbacks for component drivers

Definition

struct component_ops {  int (*bind)(struct device *comp, struct device *master, void *master_data);  void (*unbind)(struct device *comp, struct device *master, void *master_data);};

Members

bind
Called throughcomponent_bind_all() when the aggregate driver isready to bind the overall driver.
unbind
Called throughcomponent_unbind_all() when the aggregate driver isready to bind the overall driver, or whencomponent_bind_all() failspart-ways through and needs to unbind some already bound components.

Description

Components are registered withcomponent_add() and unregistered withcomponent_del().

structcomponent_master_ops

callback for the aggregate driver

Definition

struct component_master_ops {  int (*bind)(struct device *master);  void (*unbind)(struct device *master);};

Members

bind

Called when all components or the aggregate driver, as specified inthe match list passed tocomponent_master_add_with_match(), areready. Usually there are 3 steps to bind an aggregate driver:

  1. Allocate a structure for the aggregate driver.
  2. Bind all components to the aggregate driver by callingcomponent_bind_all() with the aggregate driver structure as opaquepointer data.
  3. Register the aggregate driver with the subsystem to publish itsinterfaces.

Note that the lifetime of the aggregate driver does not align withany of the underlyingstructdevice instances. Therefore devm cannotbe used and all resources acquired or allocated in this callback mustbe explicitly released in theunbind callback.

unbind
Called when either the aggregate driver, usingcomponent_master_del(), or one of its components, usingcomponent_del(), is unregistered.

Description

Aggregate drivers are registered withcomponent_master_add_with_match() andunregistered withcomponent_master_del().

voidcomponent_match_add(structdevice * master, struct component_match ** matchptr, int (*compare)(structdevice *, void *), void * compare_data)

add a component match entry

Parameters

structdevice*master
device with the aggregate driver
structcomponent_match**matchptr
pointer to the list of component matches
int(*)(structdevice*,void*)compare
compare function to match against all components
void*compare_data
opaque pointer passed to thecompare function

Description

Adds a new component match to the list stored inmatchptr, which themasteraggregate driver needs to function. The list of component matches pointed tobymatchptr must be initialized to NULL before adding the first match. Thisonly matches against components added withcomponent_add().

The allocated match list inmatchptr is automatically released using devmactions.

See alsocomponent_match_add_release() andcomponent_match_add_typed().

voidcomponent_match_add_release(structdevice * master, struct component_match ** matchptr, void (*release)(structdevice *, void *), int (*compare) (structdevice *, void *), void * compare_data)

add a component match entry with release callback

Parameters

structdevice*master
device with the aggregate driver
structcomponent_match**matchptr
pointer to the list of component matches
void(*)(structdevice*,void*)release
release function forcompare_data
int(*)(structdevice*,void*)compare
compare function to match against all components
void*compare_data
opaque pointer passed to thecompare function

Description

Adds a new component match to the list stored inmatchptr, which themasteraggregate driver needs to function. The list of component matches pointed tobymatchptr must be initialized to NULL before adding the first match. Thisonly matches against components added withcomponent_add().

The allocated match list inmatchptr is automatically released using devmactions, where uponrelease will be called to free any references held bycompare_data, e.g. whencompare_data is adevice_node that must bereleased with of_node_put().

See alsocomponent_match_add() andcomponent_match_add_typed().

voidcomponent_match_add_typed(structdevice * master, struct component_match ** matchptr, int (*compare_typed)(structdevice *, int, void *), void * compare_data)

add a component match entry for a typed component

Parameters

structdevice*master
device with the aggregate driver
structcomponent_match**matchptr
pointer to the list of component matches
int(*)(structdevice*,int,void*)compare_typed
compare function to match against all typed components
void*compare_data
opaque pointer passed to thecompare function

Description

Adds a new component match to the list stored inmatchptr, which themasteraggregate driver needs to function. The list of component matches pointed tobymatchptr must be initialized to NULL before adding the first match. Thisonly matches against components added withcomponent_add_typed().

The allocated match list inmatchptr is automatically released using devmactions.

See alsocomponent_match_add_release() andcomponent_match_add_typed().

intcomponent_master_add_with_match(structdevice * dev, const structcomponent_master_ops * ops, struct component_match * match)

register an aggregate driver

Parameters

structdevice*dev
device with the aggregate driver
conststructcomponent_master_ops*ops
callbacks for the aggregate driver
structcomponent_match*match
component match list for the aggregate driver

Description

Registers a new aggregate driver consisting of the components added tomatchby calling one of thecomponent_match_add() functions. Once all components inmatch are available, it will be assembled by callingcomponent_master_ops.bind fromops. Must be unregistered by callingcomponent_master_del().

voidcomponent_master_del(structdevice * dev, const structcomponent_master_ops * ops)

unregister an aggregate driver

Parameters

structdevice*dev
device with the aggregate driver
conststructcomponent_master_ops*ops
callbacks for the aggregate driver

Description

Unregisters an aggregate driver registered withcomponent_master_add_with_match(). If necessary the aggregate driver is firstdisassembled by callingcomponent_master_ops.unbind fromops.

voidcomponent_unbind_all(structdevice * master_dev, void * data)

unbind all components of an aggregate driver

Parameters

structdevice*master_dev
device with the aggregate driver
void*data
opaque pointer, passed to all components

Description

Unbinds all components of the aggregatedev by passingdata to theircomponent_ops.unbind functions. Should be called fromcomponent_master_ops.unbind.

intcomponent_bind_all(structdevice * master_dev, void * data)

bind all components of an aggregate driver

Parameters

structdevice*master_dev
device with the aggregate driver
void*data
opaque pointer, passed to all components

Description

Binds all components of the aggregatedev by passingdata to theircomponent_ops.bind functions. Should be called fromcomponent_master_ops.bind.

intcomponent_add_typed(structdevice * dev, const structcomponent_ops * ops, int subcomponent)

register a component

Parameters

structdevice*dev
component device
conststructcomponent_ops*ops
component callbacks
intsubcomponent
nonzero identifier for subcomponents

Description

Register a new component fordev. Functions inops will be call when theaggregate driver is ready to bind the overall driver by callingcomponent_bind_all(). See alsostructcomponent_ops.

subcomponent must be nonzero and is used to differentiate between multiplecomponents registerd on the same devicedev. These components are matchusingcomponent_match_add_typed().

The component needs to be unregistered at driver unload/disconnect bycallingcomponent_del().

See alsocomponent_add().

intcomponent_add(structdevice * dev, const structcomponent_ops * ops)

register a component

Parameters

structdevice*dev
component device
conststructcomponent_ops*ops
component callbacks

Description

Register a new component fordev. Functions inops will be called when theaggregate driver is ready to bind the overall driver by callingcomponent_bind_all(). See alsostructcomponent_ops.

The component needs to be unregistered at driver unload/disconnect bycallingcomponent_del().

See alsocomponent_add_typed() for a variant that allows multipled differentcomponents on the same device.

voidcomponent_del(structdevice * dev, const structcomponent_ops * ops)

unregister a component

Parameters

structdevice*dev
component device
conststructcomponent_ops*ops
component callbacks

Description

Unregister a component added withcomponent_add(). If the component is boundinto an aggregate driver, this will force the entire aggregate driver, includingall its components, to be unbound.