Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
5293fea2
Commit
5293fea2
authored
Nov 02, 2015
by
Rafael J. Wysocki
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'device-properties' into acpi-pci
parents
02715e86
205ad97f
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
760 additions
and
194 deletions
+760
-194
drivers/acpi/device_sysfs.c
drivers/acpi/device_sysfs.c
+108
-12
drivers/acpi/property.c
drivers/acpi/property.c
+358
-69
drivers/acpi/scan.c
drivers/acpi/scan.c
+0
-20
drivers/base/property.c
drivers/base/property.c
+76
-12
drivers/dma/acpi-dma.c
drivers/dma/acpi-dma.c
+17
-8
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib-acpi.c
+109
-44
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.c
+1
-2
drivers/gpio/gpiolib.h
drivers/gpio/gpiolib.h
+9
-1
include/acpi/acpi_bus.h
include/acpi/acpi_bus.h
+31
-2
include/linux/acpi.h
include/linux/acpi.h
+46
-24
include/linux/fwnode.h
include/linux/fwnode.h
+1
-0
include/linux/property.h
include/linux/property.h
+4
-0
No files found.
drivers/acpi/device_sysfs.c
View file @
5293fea2
...
...
@@ -26,6 +26,106 @@
#include "internal.h"
static
ssize_t
acpi_object_path
(
acpi_handle
handle
,
char
*
buf
)
{
struct
acpi_buffer
path
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
int
result
;
result
=
acpi_get_name
(
handle
,
ACPI_FULL_PATHNAME
,
&
path
);
if
(
result
)
return
result
;
result
=
sprintf
(
buf
,
"%s
\n
"
,
(
char
*
)
path
.
pointer
);
kfree
(
path
.
pointer
);
return
result
;
}
struct
acpi_data_node_attr
{
struct
attribute
attr
;
ssize_t
(
*
show
)(
struct
acpi_data_node
*
,
char
*
);
ssize_t
(
*
store
)(
struct
acpi_data_node
*
,
const
char
*
,
size_t
count
);
};
#define DATA_NODE_ATTR(_name) \
static struct acpi_data_node_attr data_node_##_name = \
__ATTR(_name, 0444, data_node_show_##_name, NULL)
static
ssize_t
data_node_show_path
(
struct
acpi_data_node
*
dn
,
char
*
buf
)
{
return
acpi_object_path
(
dn
->
handle
,
buf
);
}
DATA_NODE_ATTR
(
path
);
static
struct
attribute
*
acpi_data_node_default_attrs
[]
=
{
&
data_node_path
.
attr
,
NULL
};
#define to_data_node(k) container_of(k, struct acpi_data_node, kobj)
#define to_attr(a) container_of(a, struct acpi_data_node_attr, attr)
static
ssize_t
acpi_data_node_attr_show
(
struct
kobject
*
kobj
,
struct
attribute
*
attr
,
char
*
buf
)
{
struct
acpi_data_node
*
dn
=
to_data_node
(
kobj
);
struct
acpi_data_node_attr
*
dn_attr
=
to_attr
(
attr
);
return
dn_attr
->
show
?
dn_attr
->
show
(
dn
,
buf
)
:
-
ENXIO
;
}
static
const
struct
sysfs_ops
acpi_data_node_sysfs_ops
=
{
.
show
=
acpi_data_node_attr_show
,
};
static
void
acpi_data_node_release
(
struct
kobject
*
kobj
)
{
struct
acpi_data_node
*
dn
=
to_data_node
(
kobj
);
complete
(
&
dn
->
kobj_done
);
}
static
struct
kobj_type
acpi_data_node_ktype
=
{
.
sysfs_ops
=
&
acpi_data_node_sysfs_ops
,
.
default_attrs
=
acpi_data_node_default_attrs
,
.
release
=
acpi_data_node_release
,
};
static
void
acpi_expose_nondev_subnodes
(
struct
kobject
*
kobj
,
struct
acpi_device_data
*
data
)
{
struct
list_head
*
list
=
&
data
->
subnodes
;
struct
acpi_data_node
*
dn
;
if
(
list_empty
(
list
))
return
;
list_for_each_entry
(
dn
,
list
,
sibling
)
{
int
ret
;
init_completion
(
&
dn
->
kobj_done
);
ret
=
kobject_init_and_add
(
&
dn
->
kobj
,
&
acpi_data_node_ktype
,
kobj
,
dn
->
name
);
if
(
ret
)
acpi_handle_err
(
dn
->
handle
,
"Failed to expose (%d)
\n
"
,
ret
);
else
acpi_expose_nondev_subnodes
(
&
dn
->
kobj
,
&
dn
->
data
);
}
}
static
void
acpi_hide_nondev_subnodes
(
struct
acpi_device_data
*
data
)
{
struct
list_head
*
list
=
&
data
->
subnodes
;
struct
acpi_data_node
*
dn
;
if
(
list_empty
(
list
))
return
;
list_for_each_entry_reverse
(
dn
,
list
,
sibling
)
{
acpi_hide_nondev_subnodes
(
&
dn
->
data
);
kobject_put
(
&
dn
->
kobj
);
}
}
/**
* create_pnp_modalias - Create hid/cid(s) string for modalias and uevent
* @acpi_dev: ACPI device object.
...
...
@@ -323,20 +423,12 @@ static ssize_t acpi_device_adr_show(struct device *dev,
}
static
DEVICE_ATTR
(
adr
,
0444
,
acpi_device_adr_show
,
NULL
);
static
ssize_t
acpi_device_path_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
static
ssize_t
acpi_device_path_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
acpi_device
*
acpi_dev
=
to_acpi_device
(
dev
);
struct
acpi_buffer
path
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
int
result
;
result
=
acpi_get_name
(
acpi_dev
->
handle
,
ACPI_FULL_PATHNAME
,
&
path
);
if
(
result
)
goto
end
;
result
=
sprintf
(
buf
,
"%s
\n
"
,
(
char
*
)
path
.
pointer
);
kfree
(
path
.
pointer
);
end:
return
result
;
return
acpi_object_path
(
acpi_dev
->
handle
,
buf
);
}
static
DEVICE_ATTR
(
path
,
0444
,
acpi_device_path_show
,
NULL
);
...
...
@@ -475,6 +567,8 @@ int acpi_device_setup_files(struct acpi_device *dev)
&
dev_attr_real_power_state
);
}
acpi_expose_nondev_subnodes
(
&
dev
->
dev
.
kobj
,
&
dev
->
data
);
end:
return
result
;
}
...
...
@@ -485,6 +579,8 @@ int acpi_device_setup_files(struct acpi_device *dev)
*/
void
acpi_device_remove_files
(
struct
acpi_device
*
dev
)
{
acpi_hide_nondev_subnodes
(
&
dev
->
data
);
if
(
dev
->
flags
.
power_manageable
)
{
device_remove_file
(
&
dev
->
dev
,
&
dev_attr_power_state
);
if
(
dev
->
power
.
flags
.
power_resources
)
...
...
drivers/acpi/property.c
View file @
5293fea2
...
...
@@ -19,11 +19,133 @@
#include "internal.h"
static
int
acpi_data_get_property_array
(
struct
acpi_device_data
*
data
,
const
char
*
name
,
acpi_object_type
type
,
const
union
acpi_object
**
obj
);
/* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
static
const
u8
prp_uuid
[
16
]
=
{
0x14
,
0xd8
,
0xff
,
0xda
,
0xba
,
0x6e
,
0x8c
,
0x4d
,
0x8a
,
0x91
,
0xbc
,
0x9b
,
0xbf
,
0x4a
,
0xa3
,
0x01
};
/* ACPI _DSD data subnodes UUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
static
const
u8
ads_uuid
[
16
]
=
{
0xe6
,
0xe3
,
0xb8
,
0xdb
,
0x86
,
0x58
,
0xa6
,
0x4b
,
0x87
,
0x95
,
0x13
,
0x19
,
0xf5
,
0x2a
,
0x96
,
0x6b
};
static
bool
acpi_enumerate_nondev_subnodes
(
acpi_handle
scope
,
const
union
acpi_object
*
desc
,
struct
acpi_device_data
*
data
);
static
bool
acpi_extract_properties
(
const
union
acpi_object
*
desc
,
struct
acpi_device_data
*
data
);
static
bool
acpi_nondev_subnode_ok
(
acpi_handle
scope
,
const
union
acpi_object
*
link
,
struct
list_head
*
list
)
{
struct
acpi_buffer
buf
=
{
ACPI_ALLOCATE_BUFFER
};
struct
acpi_data_node
*
dn
;
acpi_handle
handle
;
acpi_status
status
;
dn
=
kzalloc
(
sizeof
(
*
dn
),
GFP_KERNEL
);
if
(
!
dn
)
return
false
;
dn
->
name
=
link
->
package
.
elements
[
0
].
string
.
pointer
;
dn
->
fwnode
.
type
=
FWNODE_ACPI_DATA
;
INIT_LIST_HEAD
(
&
dn
->
data
.
subnodes
);
status
=
acpi_get_handle
(
scope
,
link
->
package
.
elements
[
1
].
string
.
pointer
,
&
handle
);
if
(
ACPI_FAILURE
(
status
))
goto
fail
;
status
=
acpi_evaluate_object_typed
(
handle
,
NULL
,
NULL
,
&
buf
,
ACPI_TYPE_PACKAGE
);
if
(
ACPI_FAILURE
(
status
))
goto
fail
;
if
(
acpi_extract_properties
(
buf
.
pointer
,
&
dn
->
data
))
dn
->
handle
=
handle
;
/*
* The scope for the subnode object lookup is the one of the namespace
* node (device) containing the object that has returned the package.
* That is, it's the scope of that object's parent.
*/
status
=
acpi_get_parent
(
handle
,
&
scope
);
if
(
ACPI_SUCCESS
(
status
)
&&
acpi_enumerate_nondev_subnodes
(
scope
,
buf
.
pointer
,
&
dn
->
data
))
dn
->
handle
=
handle
;
if
(
dn
->
handle
)
{
dn
->
data
.
pointer
=
buf
.
pointer
;
list_add_tail
(
&
dn
->
sibling
,
list
);
return
true
;
}
acpi_handle_debug
(
handle
,
"Invalid properties/subnodes data, skipping
\n
"
);
fail:
ACPI_FREE
(
buf
.
pointer
);
kfree
(
dn
);
return
false
;
}
static
int
acpi_add_nondev_subnodes
(
acpi_handle
scope
,
const
union
acpi_object
*
links
,
struct
list_head
*
list
)
{
bool
ret
=
false
;
int
i
;
for
(
i
=
0
;
i
<
links
->
package
.
count
;
i
++
)
{
const
union
acpi_object
*
link
;
link
=
&
links
->
package
.
elements
[
i
];
/* Only two elements allowed, both must be strings. */
if
(
link
->
package
.
count
==
2
&&
link
->
package
.
elements
[
0
].
type
==
ACPI_TYPE_STRING
&&
link
->
package
.
elements
[
1
].
type
==
ACPI_TYPE_STRING
&&
acpi_nondev_subnode_ok
(
scope
,
link
,
list
))
ret
=
true
;
}
return
ret
;
}
static
bool
acpi_enumerate_nondev_subnodes
(
acpi_handle
scope
,
const
union
acpi_object
*
desc
,
struct
acpi_device_data
*
data
)
{
int
i
;
/* Look for the ACPI data subnodes UUID. */
for
(
i
=
0
;
i
<
desc
->
package
.
count
;
i
+=
2
)
{
const
union
acpi_object
*
uuid
,
*
links
;
uuid
=
&
desc
->
package
.
elements
[
i
];
links
=
&
desc
->
package
.
elements
[
i
+
1
];
/*
* The first element must be a UUID and the second one must be
* a package.
*/
if
(
uuid
->
type
!=
ACPI_TYPE_BUFFER
||
uuid
->
buffer
.
length
!=
16
||
links
->
type
!=
ACPI_TYPE_PACKAGE
)
break
;
if
(
memcmp
(
uuid
->
buffer
.
pointer
,
ads_uuid
,
sizeof
(
ads_uuid
)))
continue
;
return
acpi_add_nondev_subnodes
(
scope
,
links
,
&
data
->
subnodes
);
}
return
false
;
}
static
bool
acpi_property_value_ok
(
const
union
acpi_object
*
value
)
{
...
...
@@ -81,8 +203,8 @@ static void acpi_init_of_compatible(struct acpi_device *adev)
const
union
acpi_object
*
of_compatible
;
int
ret
;
ret
=
acpi_d
ev_get_property_array
(
adev
,
"compatible"
,
ACPI_TYPE_STRING
,
&
of_compatible
);
ret
=
acpi_d
ata_get_property_array
(
&
adev
->
data
,
"compatible"
,
ACPI_TYPE_STRING
,
&
of_compatible
);
if
(
ret
)
{
ret
=
acpi_dev_get_property
(
adev
,
"compatible"
,
ACPI_TYPE_STRING
,
&
of_compatible
);
...
...
@@ -100,34 +222,13 @@ static void acpi_init_of_compatible(struct acpi_device *adev)
adev
->
flags
.
of_compatible_ok
=
1
;
}
void
acpi_init_properties
(
struct
acpi_device
*
adev
)
static
bool
acpi_extract_properties
(
const
union
acpi_object
*
desc
,
struct
acpi_device_data
*
data
)
{
struct
acpi_buffer
buf
=
{
ACPI_ALLOCATE_BUFFER
};
bool
acpi_of
=
false
;
struct
acpi_hardware_id
*
hwid
;
const
union
acpi_object
*
desc
;
acpi_status
status
;
int
i
;
/*
* Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
* Device Tree compatible properties for this device.
*/
list_for_each_entry
(
hwid
,
&
adev
->
pnp
.
ids
,
list
)
{
if
(
!
strcmp
(
hwid
->
id
,
ACPI_DT_NAMESPACE_HID
))
{
acpi_of
=
true
;
break
;
}
}
status
=
acpi_evaluate_object_typed
(
adev
->
handle
,
"_DSD"
,
NULL
,
&
buf
,
ACPI_TYPE_PACKAGE
);
if
(
ACPI_FAILURE
(
status
))
goto
out
;
desc
=
buf
.
pointer
;
if
(
desc
->
package
.
count
%
2
)
goto
fail
;
return
false
;
/* Look for the device properties UUID. */
for
(
i
=
0
;
i
<
desc
->
package
.
count
;
i
+=
2
)
{
...
...
@@ -154,18 +255,50 @@ void acpi_init_properties(struct acpi_device *adev)
if
(
!
acpi_properties_format_valid
(
properties
))
break
;
adev
->
data
.
pointer
=
buf
.
pointer
;
adev
->
data
.
properties
=
properties
;
data
->
properties
=
properties
;
return
true
;
}
if
(
acpi_of
)
acpi_init_of_compatible
(
adev
);
return
false
;
}
void
acpi_init_properties
(
struct
acpi_device
*
adev
)
{
struct
acpi_buffer
buf
=
{
ACPI_ALLOCATE_BUFFER
};
struct
acpi_hardware_id
*
hwid
;
acpi_status
status
;
bool
acpi_of
=
false
;
INIT_LIST_HEAD
(
&
adev
->
data
.
subnodes
);
/*
* Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
* Device Tree compatible properties for this device.
*/
list_for_each_entry
(
hwid
,
&
adev
->
pnp
.
ids
,
list
)
{
if
(
!
strcmp
(
hwid
->
id
,
ACPI_DT_NAMESPACE_HID
))
{
acpi_of
=
true
;
break
;
}
}
status
=
acpi_evaluate_object_typed
(
adev
->
handle
,
"_DSD"
,
NULL
,
&
buf
,
ACPI_TYPE_PACKAGE
);
if
(
ACPI_FAILURE
(
status
))
goto
out
;
if
(
acpi_extract_properties
(
buf
.
pointer
,
&
adev
->
data
))
{
adev
->
data
.
pointer
=
buf
.
pointer
;
if
(
acpi_of
)
acpi_init_of_compatible
(
adev
);
}
if
(
acpi_enumerate_nondev_subnodes
(
adev
->
handle
,
buf
.
pointer
,
&
adev
->
data
))
adev
->
data
.
pointer
=
buf
.
pointer
;
fail:
dev_dbg
(
&
adev
->
dev
,
"Returned _DSD data is not valid, skipping
\n
"
);
ACPI_FREE
(
buf
.
pointer
);
if
(
!
adev
->
data
.
pointer
)
{
acpi_handle_debug
(
adev
->
handle
,
"Invalid _DSD data, skipping
\n
"
);
ACPI_FREE
(
buf
.
pointer
);
}
out:
if
(
acpi_of
&&
!
adev
->
flags
.
of_compatible_ok
)
...
...
@@ -173,8 +306,25 @@ void acpi_init_properties(struct acpi_device *adev)
ACPI_DT_NAMESPACE_HID
" requires 'compatible' property
\n
"
);
}
static
void
acpi_destroy_nondev_subnodes
(
struct
list_head
*
list
)
{
struct
acpi_data_node
*
dn
,
*
next
;
if
(
list_empty
(
list
))
return
;
list_for_each_entry_safe_reverse
(
dn
,
next
,
list
,
sibling
)
{
acpi_destroy_nondev_subnodes
(
&
dn
->
data
.
subnodes
);
wait_for_completion
(
&
dn
->
kobj_done
);
list_del
(
&
dn
->
sibling
);
ACPI_FREE
((
void
*
)
dn
->
data
.
pointer
);
kfree
(
dn
);
}
}
void
acpi_free_properties
(
struct
acpi_device
*
adev
)
{
acpi_destroy_nondev_subnodes
(
&
adev
->
data
.
subnodes
);
ACPI_FREE
((
void
*
)
adev
->
data
.
pointer
);
adev
->
data
.
of_compatible
=
NULL
;
adev
->
data
.
pointer
=
NULL
;
...
...
@@ -182,8 +332,8 @@ void acpi_free_properties(struct acpi_device *adev)
}
/**
* acpi_d
ev
_get_property - return an ACPI property with given name
* @
adev: ACPI device to get property
* acpi_d
ata
_get_property - return an ACPI property with given name
* @
data: ACPI device deta object to get the property from
* @name: Name of the property
* @type: Expected property type
* @obj: Location to store the property value (if not %NULL)
...
...
@@ -192,26 +342,27 @@ void acpi_free_properties(struct acpi_device *adev)
* object at the location pointed to by @obj if found.
*
* Callers must not attempt to free the returned objects. These objects will be
* freed by the ACPI core automatically during the removal of @
adev
.
* freed by the ACPI core automatically during the removal of @
data
.
*
* Return: %0 if property with @name has been found (success),
* %-EINVAL if the arguments are invalid,
* %-ENODATA if the property doesn't exist,
* %-EPROTO if the property value type doesn't match @type.
*/
int
acpi_dev_get_property
(
struct
acpi_device
*
adev
,
const
char
*
name
,
acpi_object_type
type
,
const
union
acpi_object
**
obj
)
static
int
acpi_data_get_property
(
struct
acpi_device_data
*
data
,
const
char
*
name
,
acpi_object_type
type
,
const
union
acpi_object
**
obj
)
{
const
union
acpi_object
*
properties
;
int
i
;
if
(
!
adev
||
!
name
)
if
(
!
data
||
!
name
)
return
-
EINVAL
;
if
(
!
adev
->
data
.
pointer
||
!
adev
->
data
.
properties
)
if
(
!
data
->
pointer
||
!
data
->
properties
)
return
-
ENODATA
;
properties
=
adev
->
data
.
properties
;
properties
=
data
->
properties
;
for
(
i
=
0
;
i
<
properties
->
package
.
count
;
i
++
)
{
const
union
acpi_object
*
propname
,
*
propvalue
;
const
union
acpi_object
*
property
;
...
...
@@ -232,11 +383,50 @@ int acpi_dev_get_property(struct acpi_device *adev, const char *name,
}
return
-
ENODATA
;
}
/**
* acpi_dev_get_property - return an ACPI property with given name.
* @adev: ACPI device to get the property from.
* @name: Name of the property.
* @type: Expected property type.
* @obj: Location to store the property value (if not %NULL).
*/
int
acpi_dev_get_property
(
struct
acpi_device
*
adev
,
const
char
*
name
,
acpi_object_type
type
,
const
union
acpi_object
**
obj
)
{
return
adev
?
acpi_data_get_property
(
&
adev
->
data
,
name
,
type
,
obj
)
:
-
EINVAL
;
}
EXPORT_SYMBOL_GPL
(
acpi_dev_get_property
);
static
struct
acpi_device_data
*
acpi_device_data_of_node
(
struct
fwnode_handle
*
fwnode
)
{
if
(
fwnode
->
type
==
FWNODE_ACPI
)
{
struct
acpi_device
*
adev
=
to_acpi_device_node
(
fwnode
);
return
&
adev
->
data
;
}
else
if
(
fwnode
->
type
==
FWNODE_ACPI_DATA
)
{
struct
acpi_data_node
*
dn
=
to_acpi_data_node
(
fwnode
);
return
&
dn
->
data
;
}
return
NULL
;
}
/**
* acpi_node_prop_get - return an ACPI property with given name.
* @fwnode: Firmware node to get the property from.
* @propname: Name of the property.
* @valptr: Location to store a pointer to the property value (if not %NULL).
*/
int
acpi_node_prop_get
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
void
**
valptr
)
{
return
acpi_data_get_property
(
acpi_device_data_of_node
(
fwnode
),
propname
,
ACPI_TYPE_ANY
,
(
const
union
acpi_object
**
)
valptr
);
}
/**
* acpi_d
ev
_get_property_array - return an ACPI array property with given name
* @adev: ACPI d
evice to get property
* acpi_d
ata
_get_property_array - return an ACPI array property with given name
* @adev: ACPI d
ata object to get the property from
* @name: Name of the property
* @type: Expected type of array elements
* @obj: Location to store a pointer to the property value (if not NULL)
...
...
@@ -245,7 +435,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property);
* ACPI object at the location pointed to by @obj if found.
*
* Callers must not attempt to free the returned objects. Those objects will be
* freed by the ACPI core automatically during the removal of @
adev
.
* freed by the ACPI core automatically during the removal of @
data
.
*
* Return: %0 if array property (package) with @name has been found (success),
* %-EINVAL if the arguments are invalid,
...
...
@@ -253,14 +443,15 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property);
* %-EPROTO if the property is not a package or the type of its elements
* doesn't match @type.
*/
int
acpi_dev_get_property_array
(
struct
acpi_device
*
adev
,
const
char
*
name
,
acpi_object_type
type
,
const
union
acpi_object
**
obj
)
static
int
acpi_data_get_property_array
(
struct
acpi_device_data
*
data
,
const
char
*
name
,
acpi_object_type
type
,
const
union
acpi_object
**
obj
)
{
const
union
acpi_object
*
prop
;
int
ret
,
i
;
ret
=
acpi_d
ev_get_property
(
adev
,
name
,
ACPI_TYPE_PACKAGE
,
&
prop
);
ret
=
acpi_d
ata_get_property
(
data
,
name
,
ACPI_TYPE_PACKAGE
,
&
prop
);
if
(
ret
)
return
ret
;
...
...
@@ -275,12 +466,11 @@ int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
return
0
;
}
EXPORT_SYMBOL_GPL
(
acpi_dev_get_property_array
);
/**
* acpi_d
ev
_get_property_reference - returns handle to the referenced object
* @
adev: ACPI device to get
property
* @name: Name of the property
* acpi_d
ata
_get_property_reference - returns handle to the referenced object
* @
data: ACPI device data object containing the
property
* @
prop
name: Name of the property
* @index: Index of the reference to return
* @args: Location to store the returned reference with optional arguments
*
...
...
@@ -294,16 +484,16 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property_array);
*
* Return: %0 on success, negative error code on failure.
*/
int
acpi_dev_get_property_reference
(
struct
acpi_device
*
adev
,
const
char
*
name
,
size_t
index
,
struct
acpi_reference_args
*
args
)
static
int
acpi_data_get_property_reference
(
struct
acpi_device_data
*
data
,
const
char
*
prop
name
,
size_t
index
,
struct
acpi_reference_args
*
args
)
{
const
union
acpi_object
*
element
,
*
end
;
const
union
acpi_object
*
obj
;
struct
acpi_device
*
device
;
int
ret
,
idx
=
0
;
ret
=
acpi_d
ev_get_property
(
adev
,
name
,
ACPI_TYPE_ANY
,
&
obj
);
ret
=
acpi_d
ata_get_property
(
data
,
prop
name
,
ACPI_TYPE_ANY
,
&
obj
);
if
(
ret
)
return
ret
;
...
...
@@ -378,17 +568,27 @@ int acpi_dev_get_property_reference(struct acpi_device *adev,
return
-
EPROTO
;
}
EXPORT_SYMBOL_GPL
(
acpi_dev_get_property_reference
);
int
acpi_dev_prop_get
(
struct
acpi_device
*
adev
,
const
char
*
propname
,
void
**
valptr
)
/**
* acpi_node_get_property_reference - get a handle to the referenced object.
* @fwnode: Firmware node to get the property from.
* @propname: Name of the property.
* @index: Index of the reference to return.
* @args: Location to store the returned reference with optional arguments.
*/
int
acpi_node_get_property_reference
(
struct
fwnode_handle
*
fwnode
,
const
char
*
name
,
size_t
index
,
struct
acpi_reference_args
*
args
)
{
return
acpi_dev_get_property
(
adev
,
propname
,
ACPI_TYPE_ANY
,
(
const
union
acpi_object
**
)
valptr
);
struct
acpi_device_data
*
data
=
acpi_device_data_of_node
(
fwnode
);
return
data
?
acpi_data_get_property_reference
(
data
,
name
,
index
,
args
)
:
-
EINVAL
;
}
EXPORT_SYMBOL_GPL
(
acpi_node_get_property_reference
);
int
acpi_dev_prop_read_single
(
struct
acpi_device
*
adev
,
const
char
*
propname
,
enum
dev_prop_type
proptype
,
void
*
val
)
static
int
acpi_data_prop_read_single
(
struct
acpi_device_data
*
data
,
const
char
*
propname
,
enum
dev_prop_type
proptype
,
void
*
val
)
{
const
union
acpi_object
*
obj
;
int
ret
;
...
...
@@ -397,7 +597,7 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
return
-
EINVAL
;
if
(
proptype
>=
DEV_PROP_U8
&&
proptype
<=
DEV_PROP_U64
)
{
ret
=
acpi_d
ev_get_property
(
adev
,
propname
,
ACPI_TYPE_INTEGER
,
&
obj
);
ret
=
acpi_d
ata_get_property
(
data
,
propname
,
ACPI_TYPE_INTEGER
,
&
obj
);
if
(
ret
)
return
ret
;
...
...
@@ -422,7 +622,7 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
break
;
}
}
else
if
(
proptype
==
DEV_PROP_STRING
)
{
ret
=
acpi_d
ev_get_property
(
adev
,
propname
,
ACPI_TYPE_STRING
,
&
obj
);
ret
=
acpi_d
ata_get_property
(
data
,
propname
,
ACPI_TYPE_STRING
,
&
obj
);
if
(
ret
)
return
ret
;
...
...
@@ -433,6 +633,12 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
return
ret
;
}
int
acpi_dev_prop_read_single
(
struct
acpi_device
*
adev
,
const
char
*
propname
,
enum
dev_prop_type
proptype
,
void
*
val
)
{
return
adev
?
acpi_data_prop_read_single
(
&
adev
->
data
,
propname
,
proptype
,
val
)
:
-
EINVAL
;
}
static
int
acpi_copy_property_array_u8
(
const
union
acpi_object
*
items
,
u8
*
val
,
size_t
nval
)
{
...
...
@@ -509,20 +715,22 @@ static int acpi_copy_property_array_string(const union acpi_object *items,
return
0
;
}
int
acpi_dev_prop_read
(
struct
acpi_device
*
adev
,
const
char
*
propname
,
enum
dev_prop_type
proptype
,
void
*
val
,
size_t
nval
)
static
int
acpi_data_prop_read
(
struct
acpi_device_data
*
data
,
const
char
*
propname
,
enum
dev_prop_type
proptype
,
void
*
val
,
size_t
nval
)
{
const
union
acpi_object
*
obj
;
const
union
acpi_object
*
items
;
int
ret
;
if
(
val
&&
nval
==
1
)
{
ret
=
acpi_d
ev_prop_read_single
(
adev
,
propname
,
proptype
,
val
);
ret
=
acpi_d
ata_prop_read_single
(
data
,
propname
,
proptype
,
val
);
if
(
!
ret
)
return
ret
;
}
ret
=
acpi_d
ev_get_property_array
(
adev
,
propname
,
ACPI_TYPE_ANY
,
&
obj
);
ret
=
acpi_d
ata_get_property_array
(
data
,
propname
,
ACPI_TYPE_ANY
,
&
obj
);
if
(
ret
)
return
ret
;
...
...
@@ -558,3 +766,84 @@ int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
}
return
ret
;
}
int
acpi_dev_prop_read
(
struct
acpi_device
*
adev
,
const
char
*
propname
,
enum
dev_prop_type
proptype
,
void
*
val
,
size_t
nval
)
{
return
adev
?
acpi_data_prop_read
(
&
adev
->
data
,
propname
,
proptype
,
val
,
nval
)
:
-
EINVAL
;
}
/**
* acpi_node_prop_read - retrieve the value of an ACPI property with given name.
* @fwnode: Firmware node to get the property from.
* @propname: Name of the property.
* @proptype: Expected property type.
* @val: Location to store the property value (if not %NULL).
* @nval: Size of the array pointed to by @val.
*
* If @val is %NULL, return the number of array elements comprising the value
* of the property. Otherwise, read at most @nval values to the array at the
* location pointed to by @val.
*/
int
acpi_node_prop_read
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
enum
dev_prop_type
proptype
,
void
*
val
,
size_t
nval
)
{
return
acpi_data_prop_read
(
acpi_device_data_of_node
(
fwnode
),
propname
,
proptype
,
val
,
nval
);
}
/**
* acpi_get_next_subnode - Return the next child node handle for a device.
* @dev: Device to find the next child node for.
* @child: Handle to one of the device's child nodes or a null handle.
*/
struct
fwnode_handle
*
acpi_get_next_subnode
(
struct
device
*
dev
,
struct
fwnode_handle
*
child
)
{
struct
acpi_device
*
adev
=
ACPI_COMPANION
(
dev
);
struct
list_head
*
head
,
*
next
;
if
(
!
adev
)
return
NULL
;
if
(
!
child
||
child
->
type
==
FWNODE_ACPI
)
{
head
=
&
adev
->
children
;
if
(
list_empty
(
head
))
goto
nondev
;
if
(
child
)
{
adev
=
to_acpi_device_node
(
child
);
next
=
adev
->
node
.
next
;
if
(
next
==
head
)
{
child
=
NULL
;
goto
nondev
;
}
adev
=
list_entry
(
next
,
struct
acpi_device
,
node
);
}
else
{
adev
=
list_first_entry
(
head
,
struct
acpi_device
,
node
);
}
return
acpi_fwnode_handle
(
adev
);
}
nondev:
if
(
!
child
||
child
->
type
==
FWNODE_ACPI_DATA
)
{
struct
acpi_data_node
*
dn
;
head
=
&
adev
->
data
.
subnodes
;
if
(
list_empty
(
head
))
return
NULL
;
if
(
child
)
{
dn
=
to_acpi_data_node
(
child
);
next
=
dn
->
sibling
.
next
;
if
(
next
==
head
)
return
NULL
;
dn
=
list_entry
(
next
,
struct
acpi_data_node
,
sibling
);
}
else
{
dn
=
list_first_entry
(
head
,
struct
acpi_data_node
,
sibling
);
}
return
&
dn
->
fwnode
;
}
return
NULL
;
}
drivers/acpi/scan.c
View file @
5293fea2
...
...
@@ -695,26 +695,6 @@ int acpi_device_add(struct acpi_device *device,
return
result
;
}
struct
acpi_device
*
acpi_get_next_child
(
struct
device
*
dev
,
struct
acpi_device
*
child
)
{
struct
acpi_device
*
adev
=
ACPI_COMPANION
(
dev
);
struct
list_head
*
head
,
*
next
;
if
(
!
adev
)
return
NULL
;
head
=
&
adev
->
children
;
if
(
list_empty
(
head
))
return
NULL
;
if
(
!
child
)
return
list_first_entry
(
head
,
struct
acpi_device
,
node
);
next
=
child
->
node
.
next
;
return
next
==
head
?
NULL
:
list_entry
(
next
,
struct
acpi_device
,
node
);
}
/* --------------------------------------------------------------------------
Device Enumeration
-------------------------------------------------------------------------- */
...
...
drivers/base/property.c
View file @
5293fea2
...
...
@@ -134,7 +134,7 @@ 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_
dev_prop_get
(
to_acpi_node
(
fwnode
)
,
propname
,
NULL
);
return
!
acpi_
node_prop_get
(
fwnode
,
propname
,
NULL
);
return
!!
pset_prop_get
(
to_pset
(
fwnode
),
propname
);
}
...
...
@@ -287,6 +287,28 @@ int device_property_read_string(struct device *dev, const char *propname,
}
EXPORT_SYMBOL_GPL
(
device_property_read_string
);
/**
* device_property_match_string - find a string in an array and return index
* @dev: Device to get the property of
* @propname: Name of the property holding the array
* @string: String to look for
*
* Find a given string in a string array and if it is found return the
* index back.
*
* Return: %0 if the property was found (success),
* %-EINVAL if given arguments are not valid,
* %-ENODATA if the property does not have a value,
* %-EPROTO if the property is not an array of strings,
* %-ENXIO if no suitable firmware interface is present.
*/
int
device_property_match_string
(
struct
device
*
dev
,
const
char
*
propname
,
const
char
*
string
)
{
return
fwnode_property_match_string
(
dev_fwnode
(
dev
),
propname
,
string
);
}
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))
...
...
@@ -298,8 +320,8 @@ EXPORT_SYMBOL_GPL(device_property_read_string);
_ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_, \
_type_, _val_, _nval_); \
else if (is_acpi_node(_fwnode_)) \
_ret_ = acpi_
dev_prop_read(to_acpi_node(_fwnode_), _propnam
e_, \
_proptype_,
_val_, _nval_); \
_ret_ = acpi_
node_prop_read(_fwnode_, _propname_, _proptyp
e_, \
_val_, _nval_); \
else if (is_pset(_fwnode_)) \
_ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \
_proptype_, _val_, _nval_); \
...
...
@@ -440,8 +462,8 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
propname
,
val
,
nval
)
:
of_property_count_strings
(
to_of_node
(
fwnode
),
propname
);
else
if
(
is_acpi_node
(
fwnode
))
return
acpi_
dev_prop_read
(
to_acpi_node
(
fwnode
),
propname
,
DEV_PROP_STRING
,
val
,
nval
);
return
acpi_
node_prop_read
(
fwnode
,
propname
,
DEV_PROP_STRING
,
val
,
nval
);
else
if
(
is_pset
(
fwnode
))
return
pset_prop_read_array
(
to_pset
(
fwnode
),
propname
,
DEV_PROP_STRING
,
val
,
nval
);
...
...
@@ -470,14 +492,60 @@ int fwnode_property_read_string(struct fwnode_handle *fwnode,
if
(
is_of_node
(
fwnode
))
return
of_property_read_string
(
to_of_node
(
fwnode
),
propname
,
val
);
else
if
(
is_acpi_node
(
fwnode
))
return
acpi_
dev_prop_read
(
to_acpi_node
(
fwnode
),
propname
,
DEV_PROP_STRING
,
val
,
1
);
return
acpi_
node_prop_read
(
fwnode
,
propname
,
DEV_PROP_STRING
,
val
,
1
);
return
pset_prop_read_array
(
to_pset
(
fwnode
),
propname
,
DEV_PROP_STRING
,
val
,
1
);
}
EXPORT_SYMBOL_GPL
(
fwnode_property_read_string
);
/**
* fwnode_property_match_string - find a string in an array and return index
* @fwnode: Firmware node to get the property of
* @propname: Name of the property holding the array
* @string: String to look for
*
* Find a given string in a string array and if it is found return the
* index back.
*
* Return: %0 if the property was found (success),
* %-EINVAL if given arguments are not valid,
* %-ENODATA if the property does not have a value,
* %-EPROTO if the property is not an array of strings,
* %-ENXIO if no suitable firmware interface is present.
*/
int
fwnode_property_match_string
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
const
char
*
string
)
{
const
char
**
values
;
int
nval
,
ret
,
i
;
nval
=
fwnode_property_read_string_array
(
fwnode
,
propname
,
NULL
,
0
);
if
(
nval
<
0
)
return
nval
;
values
=
kcalloc
(
nval
,
sizeof
(
*
values
),
GFP_KERNEL
);
if
(
!
values
)
return
-
ENOMEM
;
ret
=
fwnode_property_read_string_array
(
fwnode
,
propname
,
values
,
nval
);
if
(
ret
<
0
)
goto
out
;
ret
=
-
ENODATA
;
for
(
i
=
0
;
i
<
nval
;
i
++
)
{
if
(
!
strcmp
(
values
[
i
],
string
))
{
ret
=
i
;
break
;
}
}
out:
kfree
(
values
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
fwnode_property_match_string
);
/**
* device_get_next_child_node - Return the next child node handle for a device
* @dev: Device to find the next child node for.
...
...
@@ -493,11 +561,7 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev,
if
(
node
)
return
&
node
->
fwnode
;
}
else
if
(
IS_ENABLED
(
CONFIG_ACPI
))
{
struct
acpi_device
*
node
;
node
=
acpi_get_next_child
(
dev
,
to_acpi_node
(
child
));
if
(
node
)
return
acpi_fwnode_handle
(
node
);
return
acpi_get_next_subnode
(
dev
,
child
);
}
return
NULL
;
}
...
...
drivers/dma/acpi-dma.c
View file @
5293fea2
...
...
@@ -21,6 +21,7 @@
#include <linux/ioport.h>
#include <linux/acpi.h>
#include <linux/acpi_dma.h>
#include <linux/property.h>
static
LIST_HEAD
(
acpi_dma_list
);
static
DEFINE_MUTEX
(
acpi_dma_lock
);
...
...
@@ -413,21 +414,29 @@ EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_index);
* translate the names "tx" and "rx" here based on the most common case where
* the first FixedDMA descriptor is TX and second is RX.
*
* If the device has "dma-names" property the FixedDMA descriptor indices
* are retrieved based on those. Otherwise the function falls back using
* hardcoded indices.
*
* Return:
* Pointer to appropriate dma channel on success or an error pointer.
*/
struct
dma_chan
*
acpi_dma_request_slave_chan_by_name
(
struct
device
*
dev
,
const
char
*
name
)
{
size_t
index
;
if
(
!
strcmp
(
name
,
"tx"
))
index
=
0
;
else
if
(
!
strcmp
(
name
,
"rx"
))
index
=
1
;
else
return
ERR_PTR
(
-
ENODEV
);
int
index
;
index
=
device_property_match_string
(
dev
,
"dma-names"
,
name
);
if
(
index
<
0
)
{
if
(
!
strcmp
(
name
,
"tx"
))
index
=
0
;
else
if
(
!
strcmp
(
name
,
"rx"
))
index
=
1
;
else
return
ERR_PTR
(
-
ENODEV
);
}
dev_dbg
(
dev
,
"found DMA channel
\"
%s
\"
at index %d
\n
"
,
name
,
index
);
return
acpi_dma_request_slave_chan_by_index
(
dev
,
index
);
}
EXPORT_SYMBOL_GPL
(
acpi_dma_request_slave_chan_by_name
);
...
...
drivers/gpio/gpiolib-acpi.c
View file @
5293fea2
...
...
@@ -389,6 +389,8 @@ struct acpi_gpio_lookup {
struct
acpi_gpio_info
info
;
int
index
;
int
pin_index
;
bool
active_low
;
struct
acpi_device
*
adev
;
struct
gpio_desc
*
desc
;
int
n
;
};
...
...
@@ -425,6 +427,65 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
return
1
;
}
static
int
acpi_gpio_resource_lookup
(
struct
acpi_gpio_lookup
*
lookup
,
struct
acpi_gpio_info
*
info
)
{
struct
list_head
res_list
;
int
ret
;
INIT_LIST_HEAD
(
&
res_list
);
ret
=
acpi_dev_get_resources
(
lookup
->
adev
,
&
res_list
,
acpi_find_gpio
,
lookup
);
if
(
ret
<
0
)
return
ret
;
acpi_dev_free_resource_list
(
&
res_list
);
if
(
!
lookup
->
desc
)
return
-
ENOENT
;
if
(
info
)
{
*
info
=
lookup
->
info
;
if
(
lookup
->
active_low
)
info
->
active_low
=
lookup
->
active_low
;
}
return
0
;
}
static
int
acpi_gpio_property_lookup
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
int
index
,
struct
acpi_gpio_lookup
*
lookup
)
{
struct
acpi_reference_args
args
;
int
ret
;
memset
(
&
args
,
0
,
sizeof
(
args
));
ret
=
acpi_node_get_property_reference
(
fwnode
,
propname
,
index
,
&
args
);
if
(
ret
)
{
struct
acpi_device
*
adev
=
to_acpi_device_node
(
fwnode
);
if
(
!
adev
)
return
ret
;
if
(
!
acpi_get_driver_gpio_data
(
adev
,
propname
,
index
,
&
args
))
return
ret
;
}
/*
* The property was found and resolved, so need to lookup the GPIO based
* on returned args.
*/
lookup
->
adev
=
args
.
adev
;
if
(
args
.
nargs
>=
2
)
{
lookup
->
index
=
args
.
args
[
0
];
lookup
->
pin_index
=
args
.
args
[
1
];
/* 3rd argument, if present is used to specify active_low. */
if
(
args
.
nargs
>=
3
)
lookup
->
active_low
=
!!
args
.
args
[
2
];
}
return
0
;
}
/**
* acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
* @adev: pointer to a ACPI device to get GPIO from
...
...
@@ -452,8 +513,6 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
struct
acpi_gpio_info
*
info
)
{
struct
acpi_gpio_lookup
lookup
;
struct
list_head
resource_list
;
bool
active_low
=
false
;
int
ret
;
if
(
!
adev
)
...
...
@@ -463,58 +522,64 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
lookup
.
index
=
index
;
if
(
propname
)
{
struct
acpi_reference_args
args
;
dev_dbg
(
&
adev
->
dev
,
"GPIO: looking up %s
\n
"
,
propname
);
memset
(
&
args
,
0
,
sizeof
(
args
));
ret
=
acpi_dev_get_property_reference
(
adev
,
propname
,
index
,
&
args
);
if
(
ret
)
{
bool
found
=
acpi_get_driver_gpio_data
(
adev
,
propname
,
index
,
&
args
);
if
(
!
found
)
return
ERR_PTR
(
ret
);
}
ret
=
acpi_gpio_property_lookup
(
acpi_fwnode_handle
(
adev
),
propname
,
index
,
&
lookup
);
if
(
ret
)
return
ERR_PTR
(
ret
);
/*
* The property was found and resolved so need to
* lookup the GPIO based on returned args instead.
*/
adev
=
args
.
adev
;
if
(
args
.
nargs
>=
2
)
{
lookup
.
index
=
args
.
args
[
0
];
lookup
.
pin_index
=
args
.
args
[
1
];
/*
* 3rd argument, if present is used to
* specify active_low.
*/
if
(
args
.
nargs
>=
3
)
active_low
=
!!
args
.
args
[
2
];
}
dev_dbg
(
&
adev
->
dev
,
"GPIO: _DSD returned %s %zd %llu %llu %llu
\n
"
,
dev_name
(
&
adev
->
dev
),
args
.
nargs
,
args
.
args
[
0
],
args
.
args
[
1
],
args
.
args
[
2
]);
dev_dbg
(
&
adev
->
dev
,
"GPIO: _DSD returned %s %d %d %u
\n
"
,
dev_name
(
&
lookup
.
adev
->
dev
),
lookup
.
index
,
lookup
.
pin_index
,
lookup
.
active_low
);
}
else
{
dev_dbg
(
&
adev
->
dev
,
"GPIO: looking up %d in _CRS
\n
"
,
index
);
lookup
.
adev
=
adev
;
}
INIT_LIST_HEAD
(
&
resource_list
);
ret
=
acpi_dev_get_resources
(
adev
,
&
resource_list
,
acpi_find_gpio
,
&
lookup
);
if
(
ret
<
0
)
return
ERR_PTR
(
ret
);
ret
=
acpi_gpio_resource_lookup
(
&
lookup
,
info
);
return
ret
?
ERR_PTR
(
ret
)
:
lookup
.
desc
;
}
/**
* acpi_node_get_gpiod() - get a GPIO descriptor from ACPI resources
* @fwnode: pointer to an ACPI firmware node to get the GPIO information from
* @propname: Property name of the GPIO
* @index: index of GpioIo/GpioInt resource (starting from %0)
* @info: info pointer to fill in (optional)
*
* If @fwnode is an ACPI device object, call %acpi_get_gpiod_by_index() for it.
* Otherwise (ie. it is a data-only non-device object), use the property-based
* GPIO lookup to get to the GPIO resource with the relevant information and use
* that to obtain the GPIO descriptor to return.
*/
struct
gpio_desc
*
acpi_node_get_gpiod
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
int
index
,
struct
acpi_gpio_info
*
info
)
{
struct
acpi_gpio_lookup
lookup
;
struct
acpi_device
*
adev
;
int
ret
;
acpi_dev_free_resource_list
(
&
resource_list
);
adev
=
to_acpi_device_node
(
fwnode
);
if
(
adev
)
return
acpi_get_gpiod_by_index
(
adev
,
propname
,
index
,
info
);
if
(
lookup
.
desc
&&
info
)
{
*
info
=
lookup
.
info
;
if
(
active_low
)
info
->
active_low
=
active_low
;
}
if
(
!
is_acpi_data_node
(
fwnode
))
return
ERR_PTR
(
-
ENODEV
);
if
(
!
propname
)
return
ERR_PTR
(
-
EINVAL
);
memset
(
&
lookup
,
0
,
sizeof
(
lookup
));
lookup
.
index
=
index
;
ret
=
acpi_gpio_property_lookup
(
fwnode
,
propname
,
index
,
&
lookup
);
if
(
ret
)
return
ERR_PTR
(
ret
);
return
lookup
.
desc
?
lookup
.
desc
:
ERR_PTR
(
-
ENOENT
);
ret
=
acpi_gpio_resource_lookup
(
&
lookup
,
info
);
return
ret
?
ERR_PTR
(
ret
)
:
lookup
.
desc
;
}
/**
...
...
drivers/gpio/gpiolib.c
View file @
5293fea2
...
...
@@ -2093,8 +2093,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
}
else
if
(
is_acpi_node
(
fwnode
))
{
struct
acpi_gpio_info
info
;
desc
=
acpi_get_gpiod_by_index
(
to_acpi_node
(
fwnode
),
propname
,
0
,
&
info
);
desc
=
acpi_node_get_gpiod
(
fwnode
,
propname
,
0
,
&
info
);
if
(
!
IS_ERR
(
desc
))
active_low
=
info
.
active_low
;
}
...
...
drivers/gpio/gpiolib.h
View file @
5293fea2
...
...
@@ -42,6 +42,9 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
struct
gpio_desc
*
acpi_get_gpiod_by_index
(
struct
acpi_device
*
adev
,
const
char
*
propname
,
int
index
,
struct
acpi_gpio_info
*
info
);
struct
gpio_desc
*
acpi_node_get_gpiod
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
int
index
,
struct
acpi_gpio_info
*
info
);
int
acpi_gpio_count
(
struct
device
*
dev
,
const
char
*
con_id
);
#else
...
...
@@ -60,7 +63,12 @@ acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname,
{
return
ERR_PTR
(
-
ENOSYS
);
}
static
inline
struct
gpio_desc
*
acpi_node_get_gpiod
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
int
index
,
struct
acpi_gpio_info
*
info
)
{
return
ERR_PTR
(
-
ENXIO
);
}
static
inline
int
acpi_gpio_count
(
struct
device
*
dev
,
const
char
*
con_id
)
{
return
-
ENODEV
;
...
...
include/acpi/acpi_bus.h
View file @
5293fea2
...
...
@@ -343,6 +343,7 @@ struct acpi_device_data {
const
union
acpi_object
*
pointer
;
const
union
acpi_object
*
properties
;
const
union
acpi_object
*
of_compatible
;
struct
list_head
subnodes
;
};
struct
acpi_gpio_mapping
;
...
...
@@ -378,6 +379,17 @@ struct acpi_device {
void
(
*
remove
)(
struct
acpi_device
*
);
};
/* Non-device subnode */
struct
acpi_data_node
{
const
char
*
name
;
acpi_handle
handle
;
struct
fwnode_handle
fwnode
;
struct
acpi_device_data
data
;
struct
list_head
sibling
;
struct
kobject
kobj
;
struct
completion
kobj_done
;
};
static
inline
bool
acpi_check_dma
(
struct
acpi_device
*
adev
,
bool
*
coherent
)
{
bool
ret
=
false
;
...
...
@@ -412,16 +424,33 @@ static inline bool acpi_check_dma(struct acpi_device *adev, bool *coherent)
}
static
inline
bool
is_acpi_node
(
struct
fwnode_handle
*
fwnode
)
{
return
fwnode
&&
(
fwnode
->
type
==
FWNODE_ACPI
||
fwnode
->
type
==
FWNODE_ACPI_DATA
);
}
static
inline
bool
is_acpi_device_node
(
struct
fwnode_handle
*
fwnode
)
{
return
fwnode
&&
fwnode
->
type
==
FWNODE_ACPI
;
}
static
inline
struct
acpi_device
*
to_acpi_node
(
struct
fwnode_handle
*
fwnode
)
static
inline
struct
acpi_device
*
to_acpi_
device_
node
(
struct
fwnode_handle
*
fwnode
)
{
return
is_acpi_node
(
fwnode
)
?
return
is_acpi_
device_
node
(
fwnode
)
?
container_of
(
fwnode
,
struct
acpi_device
,
fwnode
)
:
NULL
;
}
static
inline
bool
is_acpi_data_node
(
struct
fwnode_handle
*
fwnode
)
{
return
fwnode
&&
fwnode
->
type
==
FWNODE_ACPI_DATA
;
}
static
inline
struct
acpi_data_node
*
to_acpi_data_node
(
struct
fwnode_handle
*
fwnode
)
{
return
is_acpi_data_node
(
fwnode
)
?
container_of
(
fwnode
,
struct
acpi_data_node
,
fwnode
)
:
NULL
;
}
static
inline
struct
fwnode_handle
*
acpi_fwnode_handle
(
struct
acpi_device
*
adev
)
{
return
&
adev
->
fwnode
;
...
...
include/linux/acpi.h
View file @
5293fea2
...
...
@@ -49,7 +49,7 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
return
adev
?
adev
->
handle
:
NULL
;
}
#define ACPI_COMPANION(dev) to_acpi_node((dev)->fwnode)
#define ACPI_COMPANION(dev) to_acpi_
device_
node((dev)->fwnode)
#define ACPI_COMPANION_SET(dev, adev) set_primary_fwnode(dev, (adev) ? \
acpi_fwnode_handle(adev) : NULL)
#define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev))
...
...
@@ -69,7 +69,7 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
static
inline
bool
has_acpi_companion
(
struct
device
*
dev
)
{
return
is_acpi_node
(
dev
->
fwnode
);
return
is_acpi_
device_
node
(
dev
->
fwnode
);
}
static
inline
void
acpi_preset_companion
(
struct
device
*
dev
,
...
...
@@ -462,7 +462,22 @@ static inline bool is_acpi_node(struct fwnode_handle *fwnode)
return
false
;
}
static
inline
struct
acpi_device
*
to_acpi_node
(
struct
fwnode_handle
*
fwnode
)
static
inline
bool
is_acpi_device_node
(
struct
fwnode_handle
*
fwnode
)
{
return
false
;
}
static
inline
struct
acpi_device
*
to_acpi_device_node
(
struct
fwnode_handle
*
fwnode
)
{
return
NULL
;
}
static
inline
bool
is_acpi_data_node
(
struct
fwnode_handle
*
fwnode
)
{
return
false
;
}
static
inline
struct
acpi_data_node
*
to_acpi_data_node
(
struct
fwnode_handle
*
fwnode
)
{
return
NULL
;
}
...
...
@@ -744,22 +759,21 @@ struct acpi_reference_args {
#ifdef CONFIG_ACPI
int
acpi_dev_get_property
(
struct
acpi_device
*
adev
,
const
char
*
name
,
acpi_object_type
type
,
const
union
acpi_object
**
obj
);
int
acpi_dev_get_property_array
(
struct
acpi_device
*
adev
,
const
char
*
name
,
acpi_object_type
type
,
const
union
acpi_object
**
obj
);
int
acpi_dev_get_property_reference
(
struct
acpi_device
*
adev
,
const
char
*
name
,
size_t
index
,
struct
acpi_reference_args
*
args
);
int
acpi_dev_prop_get
(
struct
acpi_device
*
adev
,
const
char
*
propname
,
void
**
valptr
);
int
acpi_node_get_property_reference
(
struct
fwnode_handle
*
fwnode
,
const
char
*
name
,
size_t
index
,
struct
acpi_reference_args
*
args
);
int
acpi_node_prop_get
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
void
**
valptr
);
int
acpi_dev_prop_read_single
(
struct
acpi_device
*
adev
,
const
char
*
propname
,
enum
dev_prop_type
proptype
,
void
*
val
);
int
acpi_node_prop_read
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
enum
dev_prop_type
proptype
,
void
*
val
,
size_t
nval
);
int
acpi_dev_prop_read
(
struct
acpi_device
*
adev
,
const
char
*
propname
,
enum
dev_prop_type
proptype
,
void
*
val
,
size_t
nval
);
struct
acpi_device
*
acpi_get_next_child
(
struct
device
*
dev
,
struct
acpi_device
*
child
);
struct
fwnode_handle
*
acpi_get_next_subnode
(
struct
device
*
dev
,
struct
fwnode_handle
*
subnode
);
#else
static
inline
int
acpi_dev_get_property
(
struct
acpi_device
*
adev
,
const
char
*
name
,
acpi_object_type
type
,
...
...
@@ -767,16 +781,17 @@ static inline int acpi_dev_get_property(struct acpi_device *adev,
{
return
-
ENXIO
;
}
static
inline
int
acpi_dev_get_property_array
(
struct
acpi_device
*
adev
,
const
char
*
nam
e
,
acpi_object_type
typ
e
,
const
union
acpi_object
**
obj
)
static
inline
int
acpi_node_get_property_reference
(
struct
fwnode_handle
*
fwnod
e
,
const
char
*
name
,
const
char
*
cells_nam
e
,
size_t
index
,
struct
acpi_reference_args
*
args
)
{
return
-
ENXIO
;
}
static
inline
int
acpi_dev_get_property_reference
(
struct
acpi_device
*
adev
,
const
char
*
name
,
const
char
*
cells_name
,
size_t
index
,
struct
acpi_reference_args
*
args
)
static
inline
int
acpi_node_prop_get
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
void
**
valptr
)
{
return
-
ENXIO
;
}
...
...
@@ -796,6 +811,14 @@ static inline int acpi_dev_prop_read_single(struct acpi_device *adev,
return
-
ENXIO
;
}
static
inline
int
acpi_node_prop_read
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
enum
dev_prop_type
proptype
,
void
*
val
,
size_t
nval
)
{
return
-
ENXIO
;
}
static
inline
int
acpi_dev_prop_read
(
struct
acpi_device
*
adev
,
const
char
*
propname
,
enum
dev_prop_type
proptype
,
...
...
@@ -804,12 +827,11 @@ static inline int acpi_dev_prop_read(struct acpi_device *adev,
return
-
ENXIO
;
}
static
inline
struct
acpi_device
*
acpi_get_next_child
(
struct
device
*
dev
,
struct
acpi_device
*
child
)
static
inline
struct
fwnode_handle
*
acpi_get_next_subnode
(
struct
device
*
dev
,
struct
fwnode_handle
*
subnode
)
{
return
NULL
;
}
#endif
#endif
/*_LINUX_ACPI_H*/
include/linux/fwnode.h
View file @
5293fea2
...
...
@@ -16,6 +16,7 @@ enum fwnode_type {
FWNODE_INVALID
=
0
,
FWNODE_OF
,
FWNODE_ACPI
,
FWNODE_ACPI_DATA
,
FWNODE_PDATA
,
};
...
...
include/linux/property.h
View file @
5293fea2
...
...
@@ -40,6 +40,8 @@ int device_property_read_string_array(struct device *dev, const char *propname,
const
char
**
val
,
size_t
nval
);
int
device_property_read_string
(
struct
device
*
dev
,
const
char
*
propname
,
const
char
**
val
);
int
device_property_match_string
(
struct
device
*
dev
,
const
char
*
propname
,
const
char
*
string
);
bool
fwnode_property_present
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
);
int
fwnode_property_read_u8_array
(
struct
fwnode_handle
*
fwnode
,
...
...
@@ -59,6 +61,8 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
size_t
nval
);
int
fwnode_property_read_string
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
const
char
**
val
);
int
fwnode_property_match_string
(
struct
fwnode_handle
*
fwnode
,
const
char
*
propname
,
const
char
*
string
);
struct
fwnode_handle
*
device_get_next_child_node
(
struct
device
*
dev
,
struct
fwnode_handle
*
child
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment