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
b29bc3df
Commit
b29bc3df
authored
Sep 01, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'spi/topic/bitbang' into spi-next
parents
c3dbe2b7
2e29db40
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
113 additions
and
193 deletions
+113
-193
drivers/spi/spi-altera.c
drivers/spi/spi-altera.c
+0
-12
drivers/spi/spi-bitbang.c
drivers/spi/spi-bitbang.c
+113
-147
drivers/spi/spi-nuc900.c
drivers/spi/spi-nuc900.c
+0
-13
drivers/spi/spi-xilinx.c
drivers/spi/spi-xilinx.c
+0
-16
include/linux/spi/spi_bitbang.h
include/linux/spi/spi_bitbang.h
+0
-5
No files found.
drivers/spi/spi-altera.c
View file @
b29bc3df
...
...
@@ -103,16 +103,6 @@ static void altera_spi_chipsel(struct spi_device *spi, int value)
}
}
static
int
altera_spi_setupxfer
(
struct
spi_device
*
spi
,
struct
spi_transfer
*
t
)
{
return
0
;
}
static
int
altera_spi_setup
(
struct
spi_device
*
spi
)
{
return
0
;
}
static
inline
unsigned
int
hw_txbyte
(
struct
altera_spi
*
hw
,
int
count
)
{
if
(
hw
->
tx
)
{
...
...
@@ -224,7 +214,6 @@ static int altera_spi_probe(struct platform_device *pdev)
master
->
bus_num
=
pdev
->
id
;
master
->
num_chipselect
=
16
;
master
->
mode_bits
=
SPI_CS_HIGH
;
master
->
setup
=
altera_spi_setup
;
hw
=
spi_master_get_devdata
(
master
);
platform_set_drvdata
(
pdev
,
hw
);
...
...
@@ -233,7 +222,6 @@ static int altera_spi_probe(struct platform_device *pdev)
hw
->
bitbang
.
master
=
spi_master_get
(
master
);
if
(
!
hw
->
bitbang
.
master
)
return
err
;
hw
->
bitbang
.
setup_transfer
=
altera_spi_setupxfer
;
hw
->
bitbang
.
chipselect
=
altera_spi_chipsel
;
hw
->
bitbang
.
txrx_bufs
=
altera_spi_txrx
;
...
...
drivers/spi/spi-bitbang.c
View file @
b29bc3df
...
...
@@ -255,150 +255,140 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
* Drivers can provide word-at-a-time i/o primitives, or provide
* transfer-at-a-time ones to leverage dma or fifo hardware.
*/
static
void
bitbang_work
(
struct
work_struct
*
work
)
static
int
spi_bitbang_prepare_hardware
(
struct
spi_master
*
spi
)
{
struct
spi_bitbang
*
bitbang
=
container_of
(
work
,
struct
spi_bitbang
,
work
);
struct
spi_bitbang
*
bitbang
;
unsigned
long
flags
;
struct
spi_message
*
m
,
*
_m
;
bitbang
=
spi_master_get_devdata
(
spi
);
spin_lock_irqsave
(
&
bitbang
->
lock
,
flags
);
bitbang
->
busy
=
1
;
list_for_each_entry_safe
(
m
,
_m
,
&
bitbang
->
queue
,
queue
)
{
struct
spi_device
*
spi
;
unsigned
nsecs
;
struct
spi_transfer
*
t
=
NULL
;
unsigned
tmp
;
unsigned
cs_change
;
int
status
;
int
do_setup
=
-
1
;
list_del
(
&
m
->
queue
);
spin_unlock_irqrestore
(
&
bitbang
->
lock
,
flags
);
/* FIXME this is made-up ... the correct value is known to
* word-at-a-time bitbang code, and presumably chipselect()
* should enforce these requirements too?
*/
nsecs
=
100
;
spin_unlock_irqrestore
(
&
bitbang
->
lock
,
flags
);
spi
=
m
->
spi
;
tmp
=
0
;
cs_change
=
1
;
status
=
0
;
return
0
;
}
list_for_each_entry
(
t
,
&
m
->
transfers
,
transfer_list
)
{
/* override speed or wordsize? */
if
(
t
->
speed_hz
||
t
->
bits_per_word
)
do_setup
=
1
;
/* init (-1) or override (1) transfer params */
if
(
do_setup
!=
0
)
{
status
=
bitbang
->
setup_transfer
(
spi
,
t
);
if
(
status
<
0
)
break
;
if
(
do_setup
==
-
1
)
do_setup
=
0
;
}
/* set up default clock polarity, and activate chip;
* this implicitly updates clock and spi modes as
* previously recorded for this device via setup().
* (and also deselects any other chip that might be
* selected ...)
*/
if
(
cs_change
)
{
bitbang
->
chipselect
(
spi
,
BITBANG_CS_ACTIVE
);
ndelay
(
nsecs
);
}
cs_change
=
t
->
cs_change
;
if
(
!
t
->
tx_buf
&&
!
t
->
rx_buf
&&
t
->
len
)
{
status
=
-
EINVAL
;
break
;
}
static
int
spi_bitbang_transfer_one
(
struct
spi_master
*
master
,
struct
spi_message
*
m
)
{
struct
spi_bitbang
*
bitbang
;
unsigned
nsecs
;
struct
spi_transfer
*
t
=
NULL
;
unsigned
cs_change
;
int
status
;
int
do_setup
=
-
1
;
struct
spi_device
*
spi
=
m
->
spi
;
bitbang
=
spi_master_get_devdata
(
master
);
/* FIXME this is made-up ... the correct value is known to
* word-at-a-time bitbang code, and presumably chipselect()
* should enforce these requirements too?
*/
nsecs
=
100
;
/* transfer data. the lower level code handles any
* new dma mappings it needs. our caller always gave
* us dma-safe buffers.
*/
if
(
t
->
len
)
{
/* REVISIT dma API still needs a designated
* DMA_ADDR_INVALID; ~0 might be better.
*/
if
(
!
m
->
is_dma_mapped
)
t
->
rx_dma
=
t
->
tx_dma
=
0
;
status
=
bitbang
->
txrx_bufs
(
spi
,
t
);
}
if
(
status
>
0
)
m
->
actual_length
+=
status
;
if
(
status
!=
t
->
len
)
{
/* always report some kind of error */
if
(
status
>=
0
)
status
=
-
EREMOTEIO
;
cs_change
=
1
;
status
=
0
;
list_for_each_entry
(
t
,
&
m
->
transfers
,
transfer_list
)
{
/* override speed or wordsize? */
if
(
t
->
speed_hz
||
t
->
bits_per_word
)
do_setup
=
1
;
/* init (-1) or override (1) transfer params */
if
(
do_setup
!=
0
)
{
status
=
bitbang
->
setup_transfer
(
spi
,
t
);
if
(
status
<
0
)
break
;
}
status
=
0
;
/* protocol tweaks before next transfer */
if
(
t
->
delay_usecs
)
udelay
(
t
->
delay_usecs
);
if
(
cs_change
&&
!
list_is_last
(
&
t
->
transfer_list
,
&
m
->
transfers
))
{
/* sometimes a short mid-message deselect of the chip
* may be needed to terminate a mode or command
*/
ndelay
(
nsecs
);
bitbang
->
chipselect
(
spi
,
BITBANG_CS_INACTIVE
);
ndelay
(
nsecs
);
}
if
(
do_setup
==
-
1
)
do_setup
=
0
;
}
m
->
status
=
status
;
m
->
complete
(
m
->
context
);
/* set up default clock polarity, and activate chip;
* this implicitly updates clock and spi modes as
* previously recorded for this device via setup().
* (and also deselects any other chip that might be
* selected ...)
*/
if
(
cs_change
)
{
bitbang
->
chipselect
(
spi
,
BITBANG_CS_ACTIVE
);
ndelay
(
nsecs
);
}
cs_change
=
t
->
cs_change
;
if
(
!
t
->
tx_buf
&&
!
t
->
rx_buf
&&
t
->
len
)
{
status
=
-
EINVAL
;
break
;
}
/*
normally deactivate chipselect ... unless no error and
*
cs_change has hinted that the next message will probably
*
be for this chip too
.
/*
transfer data. the lower level code handles any
*
new dma mappings it needs. our caller always gave
*
us dma-safe buffers
.
*/
if
(
!
(
status
==
0
&&
cs_change
))
{
if
(
t
->
len
)
{
/* REVISIT dma API still needs a designated
* DMA_ADDR_INVALID; ~0 might be better.
*/
if
(
!
m
->
is_dma_mapped
)
t
->
rx_dma
=
t
->
tx_dma
=
0
;
status
=
bitbang
->
txrx_bufs
(
spi
,
t
);
}
if
(
status
>
0
)
m
->
actual_length
+=
status
;
if
(
status
!=
t
->
len
)
{
/* always report some kind of error */
if
(
status
>=
0
)
status
=
-
EREMOTEIO
;
break
;
}
status
=
0
;
/* protocol tweaks before next transfer */
if
(
t
->
delay_usecs
)
udelay
(
t
->
delay_usecs
);
if
(
cs_change
&&
!
list_is_last
(
&
t
->
transfer_list
,
&
m
->
transfers
))
{
/* sometimes a short mid-message deselect of the chip
* may be needed to terminate a mode or command
*/
ndelay
(
nsecs
);
bitbang
->
chipselect
(
spi
,
BITBANG_CS_INACTIVE
);
ndelay
(
nsecs
);
}
}
m
->
status
=
status
;
spin_lock_irqsave
(
&
bitbang
->
lock
,
flags
);
/* normally deactivate chipselect ... unless no error and
* cs_change has hinted that the next message will probably
* be for this chip too.
*/
if
(
!
(
status
==
0
&&
cs_change
))
{
ndelay
(
nsecs
);
bitbang
->
chipselect
(
spi
,
BITBANG_CS_INACTIVE
);
ndelay
(
nsecs
);
}
bitbang
->
busy
=
0
;
spin_unlock_irqrestore
(
&
bitbang
->
lock
,
flags
);
spi_finalize_current_message
(
master
);
return
status
;
}
/**
* spi_bitbang_transfer - default submit to transfer queue
*/
int
spi_bitbang_transfer
(
struct
spi_device
*
spi
,
struct
spi_message
*
m
)
static
int
spi_bitbang_unprepare_hardware
(
struct
spi_master
*
spi
)
{
struct
spi_bitbang
*
bitbang
;
struct
spi_bitbang
*
bitbang
;
unsigned
long
flags
;
int
status
=
0
;
m
->
actual_length
=
0
;
m
->
status
=
-
EINPROGRESS
;
bitbang
=
spi_master_get_devdata
(
spi
->
master
);
bitbang
=
spi_master_get_devdata
(
spi
);
spin_lock_irqsave
(
&
bitbang
->
lock
,
flags
);
if
(
!
spi
->
max_speed_hz
)
status
=
-
ENETDOWN
;
else
{
list_add_tail
(
&
m
->
queue
,
&
bitbang
->
queue
);
queue_work
(
bitbang
->
workqueue
,
&
bitbang
->
work
);
}
bitbang
->
busy
=
0
;
spin_unlock_irqrestore
(
&
bitbang
->
lock
,
flags
);
return
status
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
spi_bitbang_transfer
);
/*----------------------------------------------------------------------*/
...
...
@@ -428,20 +418,22 @@ EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
int
spi_bitbang_start
(
struct
spi_bitbang
*
bitbang
)
{
struct
spi_master
*
master
=
bitbang
->
master
;
int
status
;
if
(
!
master
||
!
bitbang
->
chipselect
)
return
-
EINVAL
;
INIT_WORK
(
&
bitbang
->
work
,
bitbang_work
);
spin_lock_init
(
&
bitbang
->
lock
);
INIT_LIST_HEAD
(
&
bitbang
->
queue
);
if
(
!
master
->
mode_bits
)
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
bitbang
->
flags
;
if
(
!
master
->
transfer
)
master
->
transfer
=
spi_bitbang_transfer
;
if
(
master
->
transfer
||
master
->
transfer_one_message
)
return
-
EINVAL
;
master
->
prepare_transfer_hardware
=
spi_bitbang_prepare_hardware
;
master
->
unprepare_transfer_hardware
=
spi_bitbang_unprepare_hardware
;
master
->
transfer_one_message
=
spi_bitbang_transfer_one
;
if
(
!
bitbang
->
txrx_bufs
)
{
bitbang
->
use_dma
=
0
;
bitbang
->
txrx_bufs
=
spi_bitbang_bufs
;
...
...
@@ -452,34 +444,12 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
master
->
setup
=
spi_bitbang_setup
;
master
->
cleanup
=
spi_bitbang_cleanup
;
}
}
else
if
(
!
master
->
setup
)
return
-
EINVAL
;
if
(
master
->
transfer
==
spi_bitbang_transfer
&&
!
bitbang
->
setup_transfer
)
return
-
EINVAL
;
/* this task is the only thing to touch the SPI bits */
bitbang
->
busy
=
0
;
bitbang
->
workqueue
=
create_singlethread_workqueue
(
dev_name
(
master
->
dev
.
parent
));
if
(
bitbang
->
workqueue
==
NULL
)
{
status
=
-
EBUSY
;
goto
err1
;
}
/* driver may get busy before register() returns, especially
* if someone registered boardinfo for devices
*/
status
=
spi_register_master
(
master
);
if
(
status
<
0
)
goto
err2
;
return
status
;
err2:
destroy_workqueue
(
bitbang
->
workqueue
);
err1:
return
status
;
return
spi_register_master
(
master
);
}
EXPORT_SYMBOL_GPL
(
spi_bitbang_start
);
...
...
@@ -490,10 +460,6 @@ int spi_bitbang_stop(struct spi_bitbang *bitbang)
{
spi_unregister_master
(
bitbang
->
master
);
WARN_ON
(
!
list_empty
(
&
bitbang
->
queue
));
destroy_workqueue
(
bitbang
->
workqueue
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
spi_bitbang_stop
);
...
...
drivers/spi/spi-nuc900.c
View file @
b29bc3df
...
...
@@ -174,17 +174,6 @@ static void nuc900_spi_gobusy(struct nuc900_spi *hw)
spin_unlock_irqrestore
(
&
hw
->
lock
,
flags
);
}
static
int
nuc900_spi_setupxfer
(
struct
spi_device
*
spi
,
struct
spi_transfer
*
t
)
{
return
0
;
}
static
int
nuc900_spi_setup
(
struct
spi_device
*
spi
)
{
return
0
;
}
static
inline
unsigned
int
hw_txbyte
(
struct
nuc900_spi
*
hw
,
int
count
)
{
return
hw
->
tx
?
hw
->
tx
[
count
]
:
0
;
...
...
@@ -377,10 +366,8 @@ static int nuc900_spi_probe(struct platform_device *pdev)
master
->
num_chipselect
=
hw
->
pdata
->
num_cs
;
master
->
bus_num
=
hw
->
pdata
->
bus_num
;
hw
->
bitbang
.
master
=
hw
->
master
;
hw
->
bitbang
.
setup_transfer
=
nuc900_spi_setupxfer
;
hw
->
bitbang
.
chipselect
=
nuc900_spi_chipsel
;
hw
->
bitbang
.
txrx_bufs
=
nuc900_spi_txrx
;
hw
->
bitbang
.
master
->
setup
=
nuc900_spi_setup
;
hw
->
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
hw
->
res
==
NULL
)
{
...
...
drivers/spi/spi-xilinx.c
View file @
b29bc3df
...
...
@@ -233,21 +233,6 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi,
return
0
;
}
static
int
xilinx_spi_setup
(
struct
spi_device
*
spi
)
{
/* always return 0, we can not check the number of bits.
* There are cases when SPI setup is called before any driver is
* there, in that case the SPI core defaults to 8 bits, which we
* do not support in some cases. But if we return an error, the
* SPI device would not be registered and no driver can get hold of it
* When the driver is there, it will call SPI setup again with the
* correct number of bits per transfer.
* If a driver setups with the wrong bit number, it will fail when
* it tries to do a transfer
*/
return
0
;
}
static
void
xilinx_spi_fill_tx_fifo
(
struct
xilinx_spi
*
xspi
)
{
u8
sr
;
...
...
@@ -375,7 +360,6 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
xspi
->
bitbang
.
chipselect
=
xilinx_spi_chipselect
;
xspi
->
bitbang
.
setup_transfer
=
xilinx_spi_setup_transfer
;
xspi
->
bitbang
.
txrx_bufs
=
xilinx_spi_txrx_bufs
;
xspi
->
bitbang
.
master
->
setup
=
xilinx_spi_setup
;
init_completion
(
&
xspi
->
done
);
if
(
!
request_mem_region
(
mem
->
start
,
resource_size
(
mem
),
...
...
include/linux/spi/spi_bitbang.h
View file @
b29bc3df
...
...
@@ -4,11 +4,7 @@
#include <linux/workqueue.h>
struct
spi_bitbang
{
struct
workqueue_struct
*
workqueue
;
struct
work_struct
work
;
spinlock_t
lock
;
struct
list_head
queue
;
u8
busy
;
u8
use_dma
;
u8
flags
;
/* extra spi->mode support */
...
...
@@ -41,7 +37,6 @@ struct spi_bitbang {
*/
extern
int
spi_bitbang_setup
(
struct
spi_device
*
spi
);
extern
void
spi_bitbang_cleanup
(
struct
spi_device
*
spi
);
extern
int
spi_bitbang_transfer
(
struct
spi_device
*
spi
,
struct
spi_message
*
m
);
extern
int
spi_bitbang_setup_transfer
(
struct
spi_device
*
spi
,
struct
spi_transfer
*
t
);
...
...
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