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
0d1a619d
Commit
0d1a619d
authored
Sep 04, 2017
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'spi/topic/core' into spi-next
parents
569dbb88
9a9a047a
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
59 additions
and
24 deletions
+59
-24
drivers/spi/spi.c
drivers/spi/spi.c
+59
-24
No files found.
drivers/spi/spi.c
View file @
0d1a619d
...
...
@@ -40,9 +40,13 @@
#include <linux/ioport.h>
#include <linux/acpi.h>
#include <linux/highmem.h>
#include <linux/idr.h>
#define CREATE_TRACE_POINTS
#include <trace/events/spi.h>
#define SPI_DYN_FIRST_BUS_NUM 0
static
DEFINE_IDR
(
spi_master_idr
);
static
void
spidev_release
(
struct
device
*
dev
)
{
...
...
@@ -321,8 +325,7 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
if
(
rc
!=
-
ENODEV
)
return
rc
;
add_uevent_var
(
env
,
"MODALIAS=%s%s"
,
SPI_MODULE_PREFIX
,
spi
->
modalias
);
return
0
;
return
add_uevent_var
(
env
,
"MODALIAS=%s%s"
,
SPI_MODULE_PREFIX
,
spi
->
modalias
);
}
struct
bus_type
spi_bus_type
=
{
...
...
@@ -421,6 +424,7 @@ static LIST_HEAD(spi_controller_list);
/*
* Used to protect add/del opertion for board_info list and
* spi_controller list, and their matching process
* also used to protect object of type struct idr
*/
static
DEFINE_MUTEX
(
board_lock
);
...
...
@@ -1533,15 +1537,15 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
int
rc
;
/* Mode (clock phase/polarity/etc.) */
if
(
of_
find_property
(
nc
,
"spi-cpha"
,
NULL
))
if
(
of_
property_read_bool
(
nc
,
"spi-cpha"
))
spi
->
mode
|=
SPI_CPHA
;
if
(
of_
find_property
(
nc
,
"spi-cpol"
,
NULL
))
if
(
of_
property_read_bool
(
nc
,
"spi-cpol"
))
spi
->
mode
|=
SPI_CPOL
;
if
(
of_
find_property
(
nc
,
"spi-cs-high"
,
NULL
))
if
(
of_
property_read_bool
(
nc
,
"spi-cs-high"
))
spi
->
mode
|=
SPI_CS_HIGH
;
if
(
of_
find_property
(
nc
,
"spi-3wire"
,
NULL
))
if
(
of_
property_read_bool
(
nc
,
"spi-3wire"
))
spi
->
mode
|=
SPI_3WIRE
;
if
(
of_
find_property
(
nc
,
"spi-lsb-first"
,
NULL
))
if
(
of_
property_read_bool
(
nc
,
"spi-lsb-first"
))
spi
->
mode
|=
SPI_LSB_FIRST
;
/* Device DUAL/QUAD mode */
...
...
@@ -2052,11 +2056,10 @@ static int of_spi_register_master(struct spi_controller *ctlr)
*/
int
spi_register_controller
(
struct
spi_controller
*
ctlr
)
{
static
atomic_t
dyn_bus_id
=
ATOMIC_INIT
((
1
<<
15
)
-
1
);
struct
device
*
dev
=
ctlr
->
dev
.
parent
;
struct
boardinfo
*
bi
;
int
status
=
-
ENODEV
;
int
dynamic
=
0
;
int
id
;
if
(
!
dev
)
return
-
ENODEV
;
...
...
@@ -2072,19 +2075,28 @@ int spi_register_controller(struct spi_controller *ctlr)
*/
if
(
ctlr
->
num_chipselect
==
0
)
return
-
EINVAL
;
if
((
ctlr
->
bus_num
<
0
)
&&
ctlr
->
dev
.
of_node
)
ctlr
->
bus_num
=
of_alias_get_id
(
ctlr
->
dev
.
of_node
,
"spi"
);
/* convention: dynamically assigned bus IDs count down from the max */
/* allocate dynamic bus number using Linux idr */
if
((
ctlr
->
bus_num
<
0
)
&&
ctlr
->
dev
.
of_node
)
{
id
=
of_alias_get_id
(
ctlr
->
dev
.
of_node
,
"spi"
);
if
(
id
>=
0
)
{
ctlr
->
bus_num
=
id
;
mutex_lock
(
&
board_lock
);
id
=
idr_alloc
(
&
spi_master_idr
,
ctlr
,
ctlr
->
bus_num
,
ctlr
->
bus_num
+
1
,
GFP_KERNEL
);
mutex_unlock
(
&
board_lock
);
if
(
WARN
(
id
<
0
,
"couldn't get idr"
))
return
id
==
-
ENOSPC
?
-
EBUSY
:
id
;
}
}
if
(
ctlr
->
bus_num
<
0
)
{
/* FIXME switch to an IDR based scheme, something like
* I2C now uses, so we can't run out of "dynamic" IDs
*/
ctlr
->
bus_num
=
atomic_dec_return
(
&
dyn_bus_id
);
dynamic
=
1
;
mutex_lock
(
&
board_lock
);
id
=
idr_alloc
(
&
spi_master_idr
,
ctlr
,
SPI_DYN_FIRST_BUS_NUM
,
0
,
GFP_KERNEL
);
mutex_unlock
(
&
board_lock
);
if
(
WARN
(
id
<
0
,
"couldn't get idr"
))
return
id
;
ctlr
->
bus_num
=
id
;
}
INIT_LIST_HEAD
(
&
ctlr
->
queue
);
spin_lock_init
(
&
ctlr
->
queue_lock
);
spin_lock_init
(
&
ctlr
->
bus_lock_spinlock
);
...
...
@@ -2100,11 +2112,16 @@ int spi_register_controller(struct spi_controller *ctlr)
*/
dev_set_name
(
&
ctlr
->
dev
,
"spi%u"
,
ctlr
->
bus_num
);
status
=
device_add
(
&
ctlr
->
dev
);
if
(
status
<
0
)
if
(
status
<
0
)
{
/* free bus id */
mutex_lock
(
&
board_lock
);
idr_remove
(
&
spi_master_idr
,
ctlr
->
bus_num
);
mutex_unlock
(
&
board_lock
);
goto
done
;
dev_dbg
(
dev
,
"registered %s %s%s
\n
"
,
}
dev_dbg
(
dev
,
"registered %s %s
\n
"
,
spi_controller_is_slave
(
ctlr
)
?
"slave"
:
"master"
,
dev_name
(
&
ctlr
->
dev
)
,
dynamic
?
" (dynamic)"
:
""
);
dev_name
(
&
ctlr
->
dev
));
/* If we're using a queued driver, start the queue */
if
(
ctlr
->
transfer
)
...
...
@@ -2113,6 +2130,10 @@ int spi_register_controller(struct spi_controller *ctlr)
status
=
spi_controller_initialize_queue
(
ctlr
);
if
(
status
)
{
device_del
(
&
ctlr
->
dev
);
/* free bus id */
mutex_lock
(
&
board_lock
);
idr_remove
(
&
spi_master_idr
,
ctlr
->
bus_num
);
mutex_unlock
(
&
board_lock
);
goto
done
;
}
}
...
...
@@ -2191,19 +2212,33 @@ static int __unregister(struct device *dev, void *null)
*/
void
spi_unregister_controller
(
struct
spi_controller
*
ctlr
)
{
struct
spi_controller
*
found
;
int
dummy
;
/* First make sure that this controller was ever added */
mutex_lock
(
&
board_lock
);
found
=
idr_find
(
&
spi_master_idr
,
ctlr
->
bus_num
);
mutex_unlock
(
&
board_lock
);
if
(
found
!=
ctlr
)
{
dev_dbg
(
&
ctlr
->
dev
,
"attempting to delete unregistered controller [%s]
\n
"
,
dev_name
(
&
ctlr
->
dev
));
return
;
}
if
(
ctlr
->
queued
)
{
if
(
spi_destroy_queue
(
ctlr
))
dev_err
(
&
ctlr
->
dev
,
"queue remove failed
\n
"
);
}
mutex_lock
(
&
board_lock
);
list_del
(
&
ctlr
->
list
);
mutex_unlock
(
&
board_lock
);
dummy
=
device_for_each_child
(
&
ctlr
->
dev
,
NULL
,
__unregister
);
device_unregister
(
&
ctlr
->
dev
);
/* free bus id */
mutex_lock
(
&
board_lock
);
idr_remove
(
&
spi_master_idr
,
ctlr
->
bus_num
);
mutex_unlock
(
&
board_lock
);
}
EXPORT_SYMBOL_GPL
(
spi_unregister_controller
);
...
...
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