summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/acpi_lpss.c2
-rw-r--r--drivers/acpi/bgrt.c2
-rw-r--r--drivers/acpi/bus.c8
-rw-r--r--drivers/acpi/device_pm.c4
-rw-r--r--drivers/acpi/dptf/dptf_power.c2
-rw-r--r--drivers/acpi/internal.h2
-rw-r--r--drivers/acpi/osi.c3
-rw-r--r--drivers/acpi/power.c10
-rw-r--r--drivers/acpi/property.c117
-rw-r--r--drivers/acpi/scan.c28
-rw-r--r--drivers/acpi/spcr.c40
-rw-r--r--drivers/base/power/domain.c5
-rw-r--r--drivers/base/property.c348
-rw-r--r--drivers/cpufreq/cpufreq_stats.c2
-rw-r--r--drivers/cpufreq/intel_pstate.c2
-rw-r--r--drivers/of/property.c148
16 files changed, 494 insertions, 229 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 10347e3d73ad..e51a1e98e62f 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -576,7 +576,7 @@ static struct attribute *lpss_attrs[] = {
NULL,
};
-static struct attribute_group lpss_attr_group = {
+static const struct attribute_group lpss_attr_group = {
.attrs = lpss_attrs,
.name = "lpss_ltr",
};
diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c
index df1c629205e7..75af78361ce5 100644
--- a/drivers/acpi/bgrt.c
+++ b/drivers/acpi/bgrt.c
@@ -76,7 +76,7 @@ static struct bin_attribute *bgrt_bin_attributes[] = {
NULL,
};
-static struct attribute_group bgrt_attribute_group = {
+static const struct attribute_group bgrt_attribute_group = {
.attrs = bgrt_attributes,
.bin_attrs = bgrt_bin_attributes,
};
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 5a6fbe0fcaf2..af74b420ec83 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -409,11 +409,15 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
(driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
driver->ops.notify(adev, type);
- if (hotplug_event && ACPI_SUCCESS(acpi_hotplug_schedule(adev, type)))
+ if (!hotplug_event) {
+ acpi_bus_put_acpi_device(adev);
+ return;
+ }
+
+ if (ACPI_SUCCESS(acpi_hotplug_schedule(adev, type)))
return;
acpi_bus_put_acpi_device(adev);
- return;
err:
acpi_evaluate_ost(handle, type, ost_code, NULL);
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 28938b5a334e..2ed6935d4483 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -262,8 +262,10 @@ int acpi_bus_init_power(struct acpi_device *device)
return -EINVAL;
device->power.state = ACPI_STATE_UNKNOWN;
- if (!acpi_device_is_present(device))
+ if (!acpi_device_is_present(device)) {
+ device->flags.initialized = false;
return -ENXIO;
+ }
result = acpi_device_get_power(device, &state);
if (result)
diff --git a/drivers/acpi/dptf/dptf_power.c b/drivers/acpi/dptf/dptf_power.c
index 734642dc5008..e1c242568341 100644
--- a/drivers/acpi/dptf/dptf_power.c
+++ b/drivers/acpi/dptf/dptf_power.c
@@ -65,7 +65,7 @@ static struct attribute *dptf_power_attrs[] = {
NULL
};
-static struct attribute_group dptf_power_attribute_group = {
+static const struct attribute_group dptf_power_attribute_group = {
.attrs = dptf_power_attrs,
.name = "dptf_power"
};
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index be79f7db1850..9531d3276f65 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -111,7 +111,7 @@ int acpi_device_setup_files(struct acpi_device *dev);
void acpi_device_remove_files(struct acpi_device *dev);
void acpi_device_add_finalize(struct acpi_device *device);
void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
-bool acpi_device_is_present(struct acpi_device *adev);
+bool acpi_device_is_present(const struct acpi_device *adev);
bool acpi_device_is_battery(struct acpi_device *adev);
bool acpi_device_is_first_physical_node(struct acpi_device *adev,
const struct device *dev);
diff --git a/drivers/acpi/osi.c b/drivers/acpi/osi.c
index 849f9d2245ca..723bee58bbcf 100644
--- a/drivers/acpi/osi.c
+++ b/drivers/acpi/osi.c
@@ -265,7 +265,8 @@ static void __init acpi_osi_dmi_darwin(bool enable,
__acpi_osi_setup_darwin(enable);
}
-void __init acpi_osi_dmi_linux(bool enable, const struct dmi_system_id *d)
+static void __init acpi_osi_dmi_linux(bool enable,
+ const struct dmi_system_id *d)
{
pr_notice("DMI detected to setup _OSI(\"Linux\"): %s\n", d->ident);
osi_config.linux_dmi = 1;
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 3a6c9b741b23..1b475bc1ae16 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -352,7 +352,7 @@ static struct attribute *attrs[] = {
NULL,
};
-static struct attribute_group attr_groups[] = {
+static const struct attribute_group attr_groups[] = {
[ACPI_STATE_D0] = {
.name = "power_resources_D0",
.attrs = attrs,
@@ -371,14 +371,14 @@ static struct attribute_group attr_groups[] = {
},
};
-static struct attribute_group wakeup_attr_group = {
+static const struct attribute_group wakeup_attr_group = {
.name = "power_resources_wakeup",
.attrs = attrs,
};
static void acpi_power_hide_list(struct acpi_device *adev,
struct list_head *resources,
- struct attribute_group *attr_group)
+ const struct attribute_group *attr_group)
{
struct acpi_power_resource_entry *entry;
@@ -397,7 +397,7 @@ static void acpi_power_hide_list(struct acpi_device *adev,
static void acpi_power_expose_list(struct acpi_device *adev,
struct list_head *resources,
- struct attribute_group *attr_group)
+ const struct attribute_group *attr_group)
{
struct acpi_power_resource_entry *entry;
int ret;
@@ -425,7 +425,7 @@ static void acpi_power_expose_list(struct acpi_device *adev,
static void acpi_power_expose_hide(struct acpi_device *adev,
struct list_head *resources,
- struct attribute_group *attr_group,
+ const struct attribute_group *attr_group,
bool expose)
{
if (expose)
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 9364398204e9..917c789f953d 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -57,6 +57,7 @@ static bool acpi_nondev_subnode_extract(const union acpi_object *desc,
dn->name = link->package.elements[0].string.pointer;
dn->fwnode.type = FWNODE_ACPI_DATA;
+ dn->fwnode.ops = &acpi_fwnode_ops;
dn->parent = parent;
INIT_LIST_HEAD(&dn->data.subnodes);
@@ -1119,3 +1120,119 @@ int acpi_graph_get_remote_endpoint(struct fwnode_handle *fwnode,
return 0;
}
+
+static bool acpi_fwnode_device_is_available(struct fwnode_handle *fwnode)
+{
+ if (!is_acpi_device_node(fwnode))
+ return false;
+
+ return acpi_device_is_present(to_acpi_device_node(fwnode));
+}
+
+static bool acpi_fwnode_property_present(struct fwnode_handle *fwnode,
+ const char *propname)
+{
+ return !acpi_node_prop_get(fwnode, propname, NULL);
+}
+
+static int acpi_fwnode_property_read_int_array(struct fwnode_handle *fwnode,
+ const char *propname,
+ unsigned int elem_size,
+ void *val, size_t nval)
+{
+ enum dev_prop_type type;
+
+ switch (elem_size) {
+ case sizeof(u8):
+ type = DEV_PROP_U8;
+ break;
+ case sizeof(u16):
+ type = DEV_PROP_U16;
+ break;
+ case sizeof(u32):
+ type = DEV_PROP_U32;
+ break;
+ case sizeof(u64):
+ type = DEV_PROP_U64;
+ break;
+ default:
+ return -ENXIO;
+ }
+
+ return acpi_node_prop_read(fwnode, propname, type, val, nval);
+}
+
+static int acpi_fwnode_property_read_string_array(struct fwnode_handle *fwnode,
+ const char *propname,
+ const char **val, size_t nval)
+{
+ return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
+ val, nval);
+}
+
+static struct fwnode_handle *
+acpi_fwnode_get_named_child_node(struct fwnode_handle *fwnode,
+ const char *childname)
+{
+ struct fwnode_handle *child;
+
+ /*
+ * 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))
+ return child;
+
+ return NULL;
+}
+
+static struct fwnode_handle *
+acpi_fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode,
+ struct fwnode_handle *prev)
+{
+ struct fwnode_handle *endpoint;
+
+ endpoint = acpi_graph_get_next_endpoint(fwnode, prev);
+ if (IS_ERR(endpoint))
+ return NULL;
+
+ return endpoint;
+}
+
+static struct fwnode_handle *
+acpi_fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode)
+{
+ struct fwnode_handle *endpoint = NULL;
+
+ acpi_graph_get_remote_endpoint(fwnode, NULL, NULL, &endpoint);
+
+ return endpoint;
+}
+
+static int acpi_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
+ struct fwnode_endpoint *endpoint)
+{
+ struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
+
+ endpoint->local_fwnode = fwnode;
+
+ fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
+ fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
+
+ return 0;
+}
+
+const struct fwnode_operations acpi_fwnode_ops = {
+ .device_is_available = acpi_fwnode_device_is_available,
+ .property_present = acpi_fwnode_property_present,
+ .property_read_int_array = acpi_fwnode_property_read_int_array,
+ .property_read_string_array = acpi_fwnode_property_read_string_array,
+ .get_parent = acpi_node_get_parent,
+ .get_next_child_node = acpi_get_next_subnode,
+ .get_named_child_node = acpi_fwnode_get_named_child_node,
+ .graph_get_next_endpoint = acpi_fwnode_graph_get_next_endpoint,
+ .graph_get_remote_endpoint = acpi_fwnode_graph_get_remote_endpoint,
+ .graph_get_port_parent = acpi_node_get_parent,
+ .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint,
+};
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 09f65f57bebe..33897298f03e 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -404,10 +404,6 @@ void acpi_device_hotplug(struct acpi_device *adev, u32 src)
error = dock_notify(adev, src);
} else if (adev->flags.hotplug_notify) {
error = acpi_generic_hotplug_event(adev, src);
- if (error == -EPERM) {
- ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
- goto err_out;
- }
} else {
int (*notify)(struct acpi_device *, u32);
@@ -423,8 +419,20 @@ void acpi_device_hotplug(struct acpi_device *adev, u32 src)
else
goto out;
}
- if (!error)
+ switch (error) {
+ case 0:
ost_code = ACPI_OST_SC_SUCCESS;
+ break;
+ case -EPERM:
+ ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
+ break;
+ case -EBUSY:
+ ost_code = ACPI_OST_SC_DEVICE_BUSY;
+ break;
+ default:
+ ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
+ break;
+ }
err_out:
acpi_evaluate_ost(adev->handle, src, ost_code, NULL);
@@ -1460,6 +1468,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
device->handle = handle;
device->parent = acpi_bus_get_parent(handle);
device->fwnode.type = FWNODE_ACPI;
+ device->fwnode.ops = &acpi_fwnode_ops;
acpi_set_device_status(device, sta);
acpi_device_get_busid(device);
acpi_set_pnp_ids(handle, &device->pnp, type);
@@ -1592,13 +1601,9 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type,
return 0;
}
-bool acpi_device_is_present(struct acpi_device *adev)
+bool acpi_device_is_present(const struct acpi_device *adev)
{
- if (adev->status.present || adev->status.functional)
- return true;
-
- adev->flags.initialized = false;
- return false;
+ return adev->status.present || adev->status.functional;
}
static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
@@ -1831,6 +1836,7 @@ static void acpi_bus_attach(struct acpi_device *device)
acpi_bus_get_status(device);
/* Skip devices that are not present. */
if (!acpi_device_is_present(device)) {
+ device->flags.initialized = false;
acpi_device_clear_enumerated(device);
device->flags.power_manageable = 0;
return;
diff --git a/drivers/acpi/spcr.c b/drivers/acpi/spcr.c
index 3afa8c1fa127..4ac3e06b41d8 100644
--- a/drivers/acpi/spcr.c
+++ b/drivers/acpi/spcr.c
@@ -36,6 +36,26 @@ static bool qdf2400_erratum_44_present(struct acpi_table_header *h)
return false;
}
+/*
+ * APM X-Gene v1 and v2 UART hardware is an 16550 like device but has its
+ * register aligned to 32-bit. In addition, the BIOS also encoded the
+ * access width to be 8 bits. This function detects this errata condition.
+ */
+static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb)
+{
+ if (tb->interface_type != ACPI_DBG2_16550_COMPATIBLE)
+ return false;
+
+ if (memcmp(tb->header.oem_id, "APMC0D", ACPI_OEM_ID_SIZE))
+ return false;
+
+ if (!memcmp(tb->header.oem_table_id, "XGENESPC",
+ ACPI_OEM_TABLE_ID_SIZE) && tb->header.oem_revision == 0)
+ return true;
+
+ return false;
+}
+
/**
* parse_spcr() - parse ACPI SPCR table and add preferred console
*
@@ -74,8 +94,22 @@ int __init parse_spcr(bool earlycon)
goto done;
}
- iotype = table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY ?
- "mmio" : "io";
+ if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+ switch (table->serial_port.access_width) {
+ default:
+ pr_err("Unexpected SPCR Access Width. Defaulting to byte size\n");
+ case ACPI_ACCESS_SIZE_BYTE:
+ iotype = "mmio";
+ break;
+ case ACPI_ACCESS_SIZE_WORD:
+ iotype = "mmio16";
+ break;
+ case ACPI_ACCESS_SIZE_DWORD:
+ iotype = "mmio32";
+ break;
+ }
+ } else
+ iotype = "io";
switch (table->interface_type) {
case ACPI_DBG2_ARM_SBSA_32BIT:
@@ -115,6 +149,8 @@ int __init parse_spcr(bool earlycon)
if (qdf2400_erratum_44_present(&table->header))
uart = "qdf2400_e44";
+ if (xgene_8250_erratum_present(table))
+ iotype = "mmio32";
snprintf(opts, sizeof(opts), "%s,%s,0x%llx,%d", uart, iotype,
table->serial_port.address, baud_rate);
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 9649dce63e19..3b8210ebb50e 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1148,8 +1148,8 @@ static void genpd_syscore_switch(struct device *dev, bool suspend)
{
struct generic_pm_domain *genpd;
- genpd = genpd_lookup_dev(dev);
- if (!genpd)
+ genpd = dev_to_genpd(dev);
+ if (!pm_genpd_present(genpd))
return;
if (suspend) {
@@ -1180,6 +1180,7 @@ EXPORT_SYMBOL_GPL(pm_genpd_syscore_poweron);
#define pm_genpd_resume_noirq NULL
#define pm_genpd_freeze_noirq NULL
#define pm_genpd_thaw_noirq NULL
+#define pm_genpd_poweroff_noirq NULL
#define pm_genpd_restore_noirq NULL
#define pm_genpd_complete NULL
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 149de311a10e..692007e5a94b 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -187,6 +187,50 @@ struct fwnode_handle *dev_fwnode(struct device *dev)
}
EXPORT_SYMBOL_GPL(dev_fwnode);
+static bool pset_fwnode_property_present(struct fwnode_handle *fwnode,
+ const char *propname)
+{
+ return !!pset_prop_get(to_pset_node(fwnode), propname);
+}
+
+static int pset_fwnode_read_int_array(struct fwnode_handle *fwnode,
+ const char *propname,
+ unsigned int elem_size, void *val,
+ size_t nval)
+{
+ struct property_set *node = to_pset_node(fwnode);
+
+ if (!val)
+ return pset_prop_count_elems_of_size(node, propname, elem_size);
+
+ switch (elem_size) {
+ case sizeof(u8):
+ return pset_prop_read_u8_array(node, propname, val, nval);
+ case sizeof(u16):
+ return pset_prop_read_u16_array(node, propname, val, nval);
+ case sizeof(u32):
+ return pset_prop_read_u32_array(node, propname, val, nval);
+ case sizeof(u64):
+ return pset_prop_read_u64_array(node, propname, val, nval);
+ }
+
+ return -ENXIO;
+}
+
+static int pset_fwnode_property_read_string_array(struct fwnode_handle *fwnode,
+ const char *propname,
+ const char **val, size_t nval)
+{
+ return pset_prop_read_string_array(to_pset_node(fwnode), propname,
+ val, nval);
+}
+
+static const struct fwnode_operations pset_fwnode_ops = {
+ .property_present = pset_fwnode_property_present,
+ .property_read_int_array = pset_fwnode_read_int_array,
+ .property_read_string_array = pset_fwnode_property_read_string_array,
+};
+
/**
* device_property_present - check if a property of a device is present
* @dev: Device whose property is being checked
@@ -200,18 +244,6 @@ bool device_property_present(struct device *dev, const char *propname)
}
EXPORT_SYMBOL_GPL(device_property_present);
-static bool __fwnode_property_present(struct fwnode_handle *fwnode,
- const char *propname)
-{
- if (is_of_node(fwnode))
- return of_property_read_bool(to_of_node(fwnode), propname);
- else if (is_acpi_node(fwnode))
- return !acpi_node_prop_get(fwnode, propname, NULL);
- else if (is_pset_node(fwnode))
- return !!pset_prop_get(to_pset_node(fwnode), propname);
- return false;
-}
-
/**
* fwnode_property_present - check if a property of a firmware node is present
* @fwnode: Firmware node whose property to check
@@ -221,10 +253,11 @@ bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
{
bool ret;
- ret = __fwnode_property_present(fwnode, propname);
+ ret = fwnode_call_int_op(fwnode, property_present, propname);
if (ret == false && !IS_ERR_OR_NULL(fwnode) &&
!IS_ERR_OR_NULL(fwnode->secondary))
- ret = __fwnode_property_present(fwnode->secondary, propname);
+ ret = fwnode_call_int_op(fwnode->secondary, property_present,
+ propname);
return ret;
}
EXPORT_SYMBOL_GPL(fwnode_property_present);
@@ -398,42 +431,23 @@ int device_property_match_string(struct device *dev, const char *propname,
}
EXPORT_SYMBOL_GPL(device_property_match_string);
-#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
- (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
- : of_property_count_elems_of_size((node), (propname), sizeof(type))
-
-#define PSET_PROP_READ_ARRAY(node, propname, type, val, nval) \
- (val) ? pset_prop_read_##type##_array((node), (propname), (val), (nval)) \
- : pset_prop_count_elems_of_size((node), (propname), sizeof(type))
-
-#define FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
-({ \
- int _ret_; \
- if (is_of_node(_fwnode_)) \
- _ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_, \
- _type_, _val_, _nval_); \
- else if (is_acpi_node(_fwnode_)) \
- _ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \
- _val_, _nval_); \
- else if (is_pset_node(_fwnode_)) \
- _ret_ = PSET_PROP_READ_ARRAY(to_pset_node(_fwnode_), _propname_, \
- _type_, _val_, _nval_); \
- else \
- _ret_ = -ENXIO; \
- _ret_; \
-})
-
-#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
-({ \
- int _ret_; \
- _ret_ = FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, \
- _val_, _nval_); \
- if (_ret_ == -EINVAL && !IS_ERR_OR_NULL(_fwnode_) && \
- !IS_ERR_OR_NULL(_fwnode_->secondary)) \
- _ret_ = FWNODE_PROP_READ(_fwnode_->secondary, _propname_, _type_, \
- _proptype_, _val_, _nval_); \
- _ret_; \
-})
+static int fwnode_property_read_int_array(struct fwnode_handle *fwnode,
+ const char *propname,
+ unsigned int elem_size, void *val,
+ size_t nval)
+{
+ int ret;
+
+ ret = fwnode_call_int_op(fwnode, property_read_int_array, propname,
+ elem_size, val, nval);
+ if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
+ !IS_ERR_OR_NULL(fwnode->secondary))
+ ret = fwnode_call_int_op(
+ fwnode->secondary, property_read_int_array, propname,
+ elem_size, val, nval);
+
+ return ret;
+}
/**
* fwnode_property_read_u8_array - return a u8 array property of firmware node
@@ -456,8 +470,8 @@ EXPORT_SYMBOL_GPL(device_property_match_string);
int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
const char *propname, u8 *val, size_t nval)
{
- return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8,
- val, nval);
+ return fwnode_property_read_int_array(fwnode, propname, sizeof(u8),
+ val, nval);
}
EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
@@ -482,8 +496,8 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
const char *propname, u16 *val, size_t nval)
{
- return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16,
- val, nval);
+ return fwnode_property_read_int_array(fwnode, propname, sizeof(u16),
+ val, nval);
}
EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
@@ -508,8 +522,8 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
const char *propname, u32 *val, size_t nval)
{
- return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32,
- val, nval);
+ return fwnode_property_read_int_array(fwnode, propname, sizeof(u32),
+ val, nval);
}
EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
@@ -534,29 +548,11 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
const char *propname, u64 *val, size_t nval)
{
- return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64,
- val, nval);
+ return fwnode_property_read_int_array(fwnode, propname, sizeof(u64),
+ val, nval);
}
EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
-static int __fwnode_property_read_string_array(struct fwnode_handle *fwnode,
- const char *propname,
- const char **val, size_t nval)
-{
- if (is_of_node(fwnode))
- return val ?
- of_property_read_string_array(to_of_node(fwnode),
- propname, val, nval) :
- of_property_count_strings(to_of_node(fwnode), propname);
- else if (is_acpi_node(fwnode))
- return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
- val, nval);
- else if (is_pset_node(fwnode))
- return pset_prop_read_string_array(to_pset_node(fwnode),
- propname, val, nval);
- return -ENXIO;
-}
-
/**
* fwnode_property_read_string_array - return string array property of a node
* @fwnode: Firmware node to get the property of
@@ -581,11 +577,13 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
{
int ret;
- ret = __fwnode_property_read_string_array(fwnode, propname, val, nval);
+ ret = fwnode_call_int_op(fwnode, property_read_string_array, propname,
+ val, nval);
if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
!IS_ERR_OR_NULL(fwnode->secondary))
- ret = __fwnode_property_read_string_array(fwnode->secondary,
- propname, val, nval);
+ ret = fwnode_call_int_op(fwnode->secondary,
+ property_read_string_array, propname,
+ val, nval);
return ret;
}
EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
@@ -903,6 +901,7 @@ int device_add_properties(struct device *dev,
return PTR_ERR(p);
p->fwnode.type = FWNODE_PDATA;
+ p->fwnode.ops = &pset_fwnode_ops;
set_secondary_fwnode(dev, &p->fwnode);
return 0;
}
@@ -938,19 +937,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_parent);
*/
struct fwnode_handle *fwnode_get_parent(struct fwnode_handle *fwnode)
{
- struct fwnode_handle *parent = NULL;
-
- if (is_of_node(fwnode)) {
- struct device_node *node;
-
- node = of_get_parent(to_of_node(fwnode));
- if (node)
- parent = &node->fwnode;
- } else if (is_acpi_node(fwnode)) {
- parent = acpi_node_get_parent(fwnode);
- }
-
- return parent;
+ return fwnode_call_ptr_op(fwnode, get_parent);
}
EXPORT_SYMBOL_GPL(fwnode_get_parent);
@@ -962,18 +949,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_parent);
struct fwnode_handle *fwnode_get_next_child_node(struct fwnode_handle *fwnode,
struct fwnode_handle *child)
{
- if (is_of_node(fwnode)) {
- struct device_node *node;
-
- node = of_get_next_available_child(to_of_node(fwnode),
- to_of_node(child));
- if (node)
- return &node->fwnode;
- } else if (is_acpi_node(fwnode)) {
- return acpi_get_next_subnode(fwnode, child);
- }
-
- return NULL;
+ return fwnode_call_ptr_op(fwnode, get_next_child_node, child);
}
EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
@@ -1005,23 +981,7 @@ EXPORT_SYMBOL_GPL(device_get_next_child_node);
struct fwnode_handle *fwnode_get_named_child_node(struct fwnode_handle *fwnode,
const char *childname)
{
- struct fwnode_handle *child;
-
- /*
- * 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 (is_of_node(child)) {
- if (!of_node_cmp(to_of_node(child)->name, childname))
- return child;
- } else if (is_acpi_data_node(child)) {
- if (acpi_data_node_match(child, childname))
- return child;
- }
- }
-
- return NULL;
+ return fwnode_call_ptr_op(fwnode, get_named_child_node, childname);
}
EXPORT_SYMBOL_GPL(fwnode_get_named_child_node);
@@ -1043,8 +1003,7 @@ EXPORT_SYMBOL_GPL(device_get_named_child_node);
*/
void fwnode_handle_get(struct fwnode_handle *fwnode)
{
- if (is_of_node(fwnode))
- of_node_get(to_of_node(fwnode));
+ fwnode_call_void_op(fwnode, get);
}
EXPORT_SYMBOL_GPL(fwnode_handle_get);
@@ -1058,12 +1017,21 @@ EXPORT_SYMBOL_GPL(fwnode_handle_get);
*/
void fwnode_handle_put(struct fwnode_handle *fwnode)
{
- if (is_of_node(fwnode))
- of_node_put(to_of_node(fwnode));
+ fwnode_call_void_op(fwnode, put);
}
EXPORT_SYMBOL_GPL(fwnode_handle_put);
/**
+ * fwnode_device_is_available - check if a device is available for use
+ * @fwnode: Pointer to the fwnode of the device.
+ */
+bool fwnode_device_is_available(struct fwnode_handle *fwnode)
+{
+ return fwnode_call_int_op(fwnode, device_is_available);
+}
+EXPORT_SYMBOL_GPL(fwnode_device_is_available);
+
+/**
* device_get_child_node_count - return the number of child nodes for device
* @dev: Device to cound the child nodes for
*/
@@ -1198,26 +1166,29 @@ struct fwnode_handle *
fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode,
struct fwnode_handle *prev)
{
- struct fwnode_handle *endpoint = NULL;
-
- if (is_of_node(fwnode)) {
- struct device_node *node;
+ return fwnode_call_ptr_op(fwnode, graph_get_next_endpoint, prev);
+}
+EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
- node = of_graph_get_next_endpoint(to_of_node(fwnode),
- to_of_node(prev));
+/**
+ * fwnode_graph_get_port_parent - Return the device fwnode of a port endpoint
+ * @endpoint: Endpoint firmware node of the port
+ *
+ * Return: the firmware node of the device the @endpoint belongs to.
+ */
+struct fwnode_handle *
+fwnode_graph_get_port_parent(struct fwnode_handle *endpoint)
+{
+ struct fwnode_handle *port, *parent;
- if (node)
- endpoint = &node->fwnode;
- } else if (is_acpi_node(fwnode)) {
- endpoint = acpi_graph_get_next_endpoint(fwnode, prev);
- if (IS_ERR(endpoint))
- endpoint = NULL;
- }
+ port = fwnode_get_parent(endpoint);
+ parent = fwnode_call_ptr_op(port, graph_get_port_parent);
- return endpoint;
+ fwnode_handle_put(port);
+ return parent;
}
-EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
+EXPORT_SYMBOL_GPL(fwnode_graph_get_port_parent);
/**
* fwnode_graph_get_remote_port_parent - Return fwnode of a remote device
@@ -1228,22 +1199,12 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
struct fwnode_handle *
fwnode_graph_get_remote_port_parent(struct fwnode_handle *fwnode)
{
- struct fwnode_handle *parent = NULL;
-
- if (is_of_node(fwnode)) {
- struct device_node *node;
+ struct fwnode_handle *endpoint, *parent;
- node = of_graph_get_remote_port_parent(to_of_node(fwnode));
- if (node)
- parent = &node->fwnode;
- } else if (is_acpi_node(fwnode)) {
- int ret;
+ endpoint = fwnode_graph_get_remote_endpoint(fwnode);
+ parent = fwnode_graph_get_port_parent(endpoint);
- ret = acpi_graph_get_remote_endpoint(fwnode, &parent, NULL,
- NULL);
- if (ret)
- return NULL;
- }
+ fwnode_handle_put(endpoint);
return parent;
}
@@ -1257,23 +1218,7 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port_parent);
*/
struct fwnode_handle *fwnode_graph_get_remote_port(struct fwnode_handle *fwnode)
{
- struct fwnode_handle *port = NULL;
-
- if (is_of_node(fwnode)) {
- struct device_node *node;
-
- node = of_graph_get_remote_port(to_of_node(fwnode));
- if (node)
- port = &node->fwnode;
- } else if (is_acpi_node(fwnode)) {
- int ret;
-
- ret = acpi_graph_get_remote_endpoint(fwnode, NULL, &port, NULL);
- if (ret)
- return NULL;
- }
-
- return port;
+ return fwnode_get_next_parent(fwnode_graph_get_remote_endpoint(fwnode));
}
EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port);
@@ -1286,27 +1231,46 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port);
struct fwnode_handle *
fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode)
{
- struct fwnode_handle *endpoint = NULL;
+ return fwnode_call_ptr_op(fwnode, graph_get_remote_endpoint);
+}
+EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
- if (is_of_node(fwnode)) {
- struct device_node *node;
+/**
+ * fwnode_graph_get_remote_node - get remote parent node for given port/endpoint
+ * @fwnode: pointer to parent fwnode_handle containing graph port/endpoint
+ * @port_id: identifier of the parent port node
+ * @endpoint_id: identifier of the endpoint node
+ *
+ * Return: Remote fwnode handle associated with remote endpoint node linked
+ * to @node. Use fwnode_node_put() on it when done.
+ */
+struct fwnode_handle *fwnode_graph_get_remote_node(struct fwnode_handle *fwnode,
+ u32 port_id, u32 endpoint_id)
+{
+ struct fwnode_handle *endpoint = NULL;
- node = of_parse_phandle(to_of_node(fwnode), "remote-endpoint",
- 0);
- if (node)
- endpoint = &node->fwnode;
- } else if (is_acpi_node(fwnode)) {
+ while ((endpoint = fwnode_graph_get_next_endpoint(fwnode, endpoint))) {
+ struct fwnode_endpoint fwnode_ep;
+ struct fwnode_handle *remote;
int ret;
- ret = acpi_graph_get_remote_endpoint(fwnode, NULL, NULL,
- &endpoint);
- if (ret)
+ ret = fwnode_graph_parse_endpoint(endpoint, &fwnode_ep);
+ if (ret < 0)
+ continue;
+
+ if (fwnode_ep.port != port_id || fwnode_ep.id != endpoint_id)
+ continue;
+
+ remote = fwnode_graph_get_remote_port_parent(endpoint);
+ if (!remote)
return NULL;
+
+ return fwnode_device_is_available(remote) ? remote : NULL;
}
- return endpoint;
+ return NULL;
}
-EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
+EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_node);
/**
* fwnode_graph_parse_endpoint - parse common endpoint node properties
@@ -1320,22 +1284,8 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
int fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
struct fwnode_endpoint *endpoint)
{
- struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
-
memset(endpoint, 0, sizeof(*endpoint));
- endpoint->local_fwnode = fwnode;
-
- if (is_acpi_node(port_fwnode)) {
- fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
- fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
- } else {
- fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port);
- fwnode_property_read_u32(fwnode, "reg", &endpoint->id);
- }
-
- fwnode_handle_put(port_fwnode);
-
- return 0;
+ return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint);
}
EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index f570ead62454..d362739a71f3 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -135,7 +135,7 @@ static struct attribute *default_attrs[] = {
&trans_table.attr,
NULL
};
-static struct attribute_group stats_attr_group = {
+static const struct attribute_group stats_attr_group = {
.attrs = default_attrs,
.name = "stats"
};
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 48a98f11a84e..d6f323560da3 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1214,7 +1214,7 @@ static struct attribute *intel_pstate_attributes[] = {
NULL
};
-static struct attribute_group intel_pstate_attr_group = {
+static const struct attribute_group intel_pstate_attr_group = {
.attrs = intel_pstate_attributes,
};
diff --git a/drivers/of/property.c b/drivers/of/property.c
index 07c7c36c5ca8..eda50b4be934 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -804,3 +804,151 @@ struct device_node *of_graph_get_remote_node(const struct device_node *node,
return remote;
}
EXPORT_SYMBOL(of_graph_get_remote_node);
+
+static void of_fwnode_get(struct fwnode_handle *fwnode)
+{
+ of_node_get(to_of_node(fwnode));
+}
+
+static void of_fwnode_put(struct fwnode_handle *fwnode)
+{
+ of_node_put(to_of_node(fwnode));
+}
+
+static bool of_fwnode_device_is_available(struct fwnode_handle *fwnode)
+{
+ return of_device_is_available(to_of_node(fwnode));
+}
+
+static bool of_fwnode_property_present(struct fwnode_handle *fwnode,
+ const char *propname)
+{
+ return of_property_read_bool(to_of_node(fwnode), propname);
+}
+
+static int of_fwnode_property_read_int_array(struct fwnode_handle *fwnode,
+ const char *propname,
+ unsigned int elem_size, void *val,
+ size_t nval)
+{
+ struct device_node *node = to_of_node(fwnode);
+
+ if (!val)
+ return of_property_count_elems_of_size(node, propname,
+ elem_size);
+
+ switch (elem_size) {
+ case sizeof(u8):
+ return of_property_read_u8_array(node, propname, val, nval);
+ case sizeof(u16):
+ return of_property_read_u16_array(node, propname, val, nval);
+ case sizeof(u32):
+ return of_property_read_u32_array(node, propname, val, nval);
+ case sizeof(u64):
+ return of_property_read_u64_array(node, propname, val, nval);
+ }
+
+ return -ENXIO;
+}
+
+static int of_fwnode_property_read_string_array(struct fwnode_handle *fwnode,
+ const char *propname,
+ const char **val, size_t nval)
+{
+ struct device_node *node = to_of_node(fwnode);
+
+ return val ?
+ of_property_read_string_array(node, propname, val, nval) :
+ of_property_count_strings(node, propname);
+}
+
+static struct fwnode_handle *of_fwnode_get_parent(struct fwnode_handle *fwnode)
+{
+ return of_fwnode_handle(of_get_parent(to_of_node(fwnode)));
+}
+
+static struct fwnode_handle *
+of_fwnode_get_next_child_node(struct fwnode_handle *fwnode,
+ struct fwnode_handle *child)
+{
+ return of_fwnode_handle(of_get_next_available_child(to_of_node(fwnode),
+ to_of_node(child)));
+}
+
+static struct fwnode_handle *
+of_fwnode_get_named_child_node(struct fwnode_handle *fwnode,
+ const char *childname)
+{
+ struct device_node *node = to_of_node(fwnode);
+ struct device_node *child;
+
+ for_each_available_child_of_node(node, child)
+ if (!of_node_cmp(child->name, childname))
+ return of_fwnode_handle(child);
+
+ return NULL;
+}
+
+static struct fwnode_handle *
+of_fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode,
+ struct fwnode_handle *prev)
+{
+ return of_fwnode_handle(of_graph_get_next_endpoint(to_of_node(fwnode),
+ to_of_node(prev)));
+}
+
+static struct fwnode_handle *
+of_fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode)
+{
+ return of_fwnode_handle(of_parse_phandle(to_of_node(fwnode),
+ "remote-endpoint", 0));
+}
+
+static struct fwnode_handle *
+of_fwnode_graph_get_port_parent(struct fwnode_handle *fwnode)
+{
+ struct device_node *np;
+
+ /* Get the parent of the port */
+ np = of_get_next_parent(to_of_node(fwnode));
+ if (!np)
+ return NULL;
+
+ /* Is this the "ports" node? If not, it's the port parent. */
+ if (of_node_cmp(np->name, "ports"))
+ return of_fwnode_handle(np);
+
+ return of_fwnode_handle(of_get_next_parent(np));
+}
+
+static int of_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
+ struct fwnode_endpoint *endpoint)
+{
+ struct device_node *node = to_of_node(fwnode);
+ struct device_node *port_node = of_get_parent(node);
+
+ endpoint->local_fwnode = fwnode;
+
+ of_property_read_u32(port_node, "reg", &endpoint->port);
+ of_property_read_u32(node, "reg", &endpoint->id);
+
+ of_node_put(port_node);
+
+ return 0;
+}
+
+const struct fwnode_operations of_fwnode_ops = {
+ .get = of_fwnode_get,
+ .put = of_fwnode_put,
+ .device_is_available = of_fwnode_device_is_available,
+ .property_present = of_fwnode_property_present,
+ .property_read_int_array = of_fwnode_property_read_int_array,
+ .property_read_string_array = of_fwnode_property_read_string_array,
+ .get_parent = of_fwnode_get_parent,
+ .get_next_child_node = of_fwnode_get_next_child_node,
+ .get_named_child_node = of_fwnode_get_named_child_node,
+ .graph_get_next_endpoint = of_fwnode_graph_get_next_endpoint,
+ .graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint,
+ .graph_get_port_parent = of_fwnode_graph_get_port_parent,
+ .graph_parse_endpoint = of_fwnode_graph_parse_endpoint,
+};
OpenPOWER on IntegriCloud