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
45b15d98
Commit
45b15d98
authored
Mar 30, 2014
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branches 'spi/topic/xilinx' and 'spi/topic/xtfpga' into spi-next
parents
b1ad487c
6ff8672a
be8dde46
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
205 additions
and
20 deletions
+205
-20
Documentation/devicetree/bindings/spi/spi-xtensa-xtfpga.txt
Documentation/devicetree/bindings/spi/spi-xtensa-xtfpga.txt
+9
-0
MAINTAINERS
MAINTAINERS
+6
-0
drivers/spi/Kconfig
drivers/spi/Kconfig
+13
-0
drivers/spi/Makefile
drivers/spi/Makefile
+1
-0
drivers/spi/spi-xilinx.c
drivers/spi/spi-xilinx.c
+6
-20
drivers/spi/spi-xtensa-xtfpga.c
drivers/spi/spi-xtensa-xtfpga.c
+170
-0
No files found.
Documentation/devicetree/bindings/spi/spi-xtensa-xtfpga.txt
0 → 100644
View file @
45b15d98
Cadence Xtensa XTFPGA platform SPI controller.
This simple SPI master controller is built into xtfpga bitstreams and is used
to control daughterboard audio codec.
Required properties:
- compatible: should be "cdns,xtfpga-spi".
- reg: physical base address of the controller and length of memory mapped
region.
MAINTAINERS
View file @
45b15d98
...
...
@@ -9782,6 +9782,12 @@ L: linux-serial@vger.kernel.org
S: Maintained
F: drivers/tty/serial/uartlite.c
XTENSA XTFPGA PLATFORM SUPPORT
M: Max Filippov <jcmvbkbc@gmail.com>
L: linux-xtensa@linux-xtensa.org
S: Maintained
F: drivers/spi/spi-xtensa-xtfpga.c
YAM DRIVER FOR AX.25
M: Jean-Paul Roubelat <jpr@f6fbb.org>
L: linux-hams@vger.kernel.org
...
...
drivers/spi/Kconfig
View file @
45b15d98
...
...
@@ -538,6 +538,19 @@ config SPI_XILINX
Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)"
config SPI_XTENSA_XTFPGA
tristate "Xtensa SPI controller for xtfpga"
depends on (XTENSA && XTENSA_PLATFORM_XTFPGA) || COMPILE_TEST
select SPI_BITBANG
help
SPI driver for xtfpga SPI master controller.
This simple SPI master controller is built into xtfpga bitstreams
and is used to control daughterboard audio codec. It always transfers
16 bit words in SPI mode 0, automatically asserting CS on transfer
start and deasserting on end.
config SPI_NUC900
tristate "Nuvoton NUC900 series SPI"
depends on ARCH_W90X900
...
...
drivers/spi/Makefile
View file @
45b15d98
...
...
@@ -81,3 +81,4 @@ obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o
obj-$(CONFIG_SPI_TXX9)
+=
spi-txx9.o
obj-$(CONFIG_SPI_XCOMM)
+=
spi-xcomm.o
obj-$(CONFIG_SPI_XILINX)
+=
spi-xilinx.o
obj-$(CONFIG_SPI_XTENSA_XTFPGA)
+=
spi-xtensa-xtfpga.o
drivers/spi/spi-xilinx.c
View file @
45b15d98
...
...
@@ -87,10 +87,10 @@ struct xilinx_spi {
const
u8
*
tx_ptr
;
/* pointer in the Rx buffer */
int
remaining_bytes
;
/* the number of bytes left to transfer */
u8
bits_per_word
;
unsigned
int
(
*
read_fn
)
(
void
__iomem
*
);
void
(
*
write_fn
)
(
u32
,
void
__iomem
*
);
void
(
*
tx_fn
)
(
struct
xilinx_spi
*
);
void
(
*
rx_fn
)
(
struct
xilinx_spi
*
);
unsigned
int
(
*
read_fn
)(
void
__iomem
*
);
void
(
*
write_fn
)(
u32
,
void
__iomem
*
);
void
(
*
tx_fn
)(
struct
xilinx_spi
*
);
void
(
*
rx_fn
)(
struct
xilinx_spi
*
);
};
static
void
xspi_write32
(
u32
val
,
void
__iomem
*
addr
)
...
...
@@ -208,26 +208,11 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
}
/* spi_bitbang requires custom setup_transfer() to be defined if there is a
* custom txrx_bufs(). We have nothing to setup here as the SPI IP block
* supports 8 or 16 bits per word which cannot be changed in software.
* SPI clock can't be changed in software either.
* Check for correct bits per word. Chip select delay calculations could be
* added here as soon as bitbang_work() can be made aware of the delay value.
* custom txrx_bufs().
*/
static
int
xilinx_spi_setup_transfer
(
struct
spi_device
*
spi
,
struct
spi_transfer
*
t
)
{
struct
xilinx_spi
*
xspi
=
spi_master_get_devdata
(
spi
->
master
);
u8
bits_per_word
;
bits_per_word
=
(
t
&&
t
->
bits_per_word
)
?
t
->
bits_per_word
:
spi
->
bits_per_word
;
if
(
bits_per_word
!=
xspi
->
bits_per_word
)
{
dev_err
(
&
spi
->
dev
,
"%s, unsupported bits_per_word=%d
\n
"
,
__func__
,
bits_per_word
);
return
-
EINVAL
;
}
return
0
;
}
...
...
@@ -406,6 +391,7 @@ static int xilinx_spi_probe(struct platform_device *pdev)
xspi
->
write_fn
=
xspi_write32_be
;
}
master
->
bits_per_word_mask
=
SPI_BPW_MASK
(
bits_per_word
);
xspi
->
bits_per_word
=
bits_per_word
;
if
(
xspi
->
bits_per_word
==
8
)
{
xspi
->
tx_fn
=
xspi_tx8
;
...
...
drivers/spi/spi-xtensa-xtfpga.c
0 → 100644
View file @
45b15d98
/*
* Xtensa xtfpga SPI controller driver
*
* Copyright (c) 2014 Cadence Design Systems Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#define XTFPGA_SPI_NAME "xtfpga_spi"
#define XTFPGA_SPI_START 0x0
#define XTFPGA_SPI_BUSY 0x4
#define XTFPGA_SPI_DATA 0x8
#define BUSY_WAIT_US 100
struct
xtfpga_spi
{
struct
spi_bitbang
bitbang
;
void
__iomem
*
regs
;
u32
data
;
unsigned
data_sz
;
};
static
inline
void
xtfpga_spi_write32
(
const
struct
xtfpga_spi
*
spi
,
unsigned
addr
,
u32
val
)
{
iowrite32
(
val
,
spi
->
regs
+
addr
);
}
static
inline
unsigned
int
xtfpga_spi_read32
(
const
struct
xtfpga_spi
*
spi
,
unsigned
addr
)
{
return
ioread32
(
spi
->
regs
+
addr
);
}
static
inline
void
xtfpga_spi_wait_busy
(
struct
xtfpga_spi
*
xspi
)
{
unsigned
i
;
for
(
i
=
0
;
xtfpga_spi_read32
(
xspi
,
XTFPGA_SPI_BUSY
)
&&
i
<
BUSY_WAIT_US
;
++
i
)
udelay
(
1
);
WARN_ON_ONCE
(
i
==
BUSY_WAIT_US
);
}
static
u32
xtfpga_spi_txrx_word
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
v
,
u8
bits
)
{
struct
xtfpga_spi
*
xspi
=
spi_master_get_devdata
(
spi
->
master
);
xspi
->
data
=
(
xspi
->
data
<<
bits
)
|
(
v
&
GENMASK
(
bits
-
1
,
0
));
xspi
->
data_sz
+=
bits
;
if
(
xspi
->
data_sz
>=
16
)
{
xtfpga_spi_write32
(
xspi
,
XTFPGA_SPI_DATA
,
xspi
->
data
>>
(
xspi
->
data_sz
-
16
));
xspi
->
data_sz
-=
16
;
xtfpga_spi_write32
(
xspi
,
XTFPGA_SPI_START
,
1
);
xtfpga_spi_wait_busy
(
xspi
);
xtfpga_spi_write32
(
xspi
,
XTFPGA_SPI_START
,
0
);
}
return
0
;
}
static
void
xtfpga_spi_chipselect
(
struct
spi_device
*
spi
,
int
is_on
)
{
struct
xtfpga_spi
*
xspi
=
spi_master_get_devdata
(
spi
->
master
);
WARN_ON
(
xspi
->
data_sz
!=
0
);
xspi
->
data_sz
=
0
;
}
static
int
xtfpga_spi_probe
(
struct
platform_device
*
pdev
)
{
struct
xtfpga_spi
*
xspi
;
struct
resource
*
mem
;
int
ret
;
struct
spi_master
*
master
;
master
=
spi_alloc_master
(
&
pdev
->
dev
,
sizeof
(
struct
xtfpga_spi
));
if
(
!
master
)
return
-
ENOMEM
;
master
->
flags
=
SPI_MASTER_NO_RX
;
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
1
,
16
);
master
->
bus_num
=
pdev
->
dev
.
id
;
master
->
dev
.
of_node
=
pdev
->
dev
.
of_node
;
xspi
=
spi_master_get_devdata
(
master
);
xspi
->
bitbang
.
master
=
master
;
xspi
->
bitbang
.
chipselect
=
xtfpga_spi_chipselect
;
xspi
->
bitbang
.
txrx_word
[
SPI_MODE_0
]
=
xtfpga_spi_txrx_word
;
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
mem
)
{
dev_err
(
&
pdev
->
dev
,
"No memory resource
\n
"
);
ret
=
-
ENODEV
;
goto
err
;
}
xspi
->
regs
=
devm_ioremap_resource
(
&
pdev
->
dev
,
mem
);
if
(
IS_ERR
(
xspi
->
regs
))
{
ret
=
PTR_ERR
(
xspi
->
regs
);
goto
err
;
}
xtfpga_spi_write32
(
xspi
,
XTFPGA_SPI_START
,
0
);
usleep_range
(
1000
,
2000
);
if
(
xtfpga_spi_read32
(
xspi
,
XTFPGA_SPI_BUSY
))
{
dev_err
(
&
pdev
->
dev
,
"Device stuck in busy state
\n
"
);
ret
=
-
EBUSY
;
goto
err
;
}
ret
=
spi_bitbang_start
(
&
xspi
->
bitbang
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"spi_bitbang_start failed
\n
"
);
goto
err
;
}
platform_set_drvdata
(
pdev
,
master
);
return
0
;
err:
spi_master_put
(
master
);
return
ret
;
}
static
int
xtfpga_spi_remove
(
struct
platform_device
*
pdev
)
{
struct
spi_master
*
master
=
platform_get_drvdata
(
pdev
);
struct
xtfpga_spi
*
xspi
=
spi_master_get_devdata
(
master
);
spi_bitbang_stop
(
&
xspi
->
bitbang
);
spi_master_put
(
master
);
return
0
;
}
MODULE_ALIAS
(
"platform:"
XTFPGA_SPI_NAME
);
#ifdef CONFIG_OF
static
const
struct
of_device_id
xtfpga_spi_of_match
[]
=
{
{
.
compatible
=
"cdns,xtfpga-spi"
,
},
{}
};
MODULE_DEVICE_TABLE
(
of
,
xtfpga_spi_of_match
);
#endif
static
struct
platform_driver
xtfpga_spi_driver
=
{
.
probe
=
xtfpga_spi_probe
,
.
remove
=
xtfpga_spi_remove
,
.
driver
=
{
.
name
=
XTFPGA_SPI_NAME
,
.
owner
=
THIS_MODULE
,
.
of_match_table
=
of_match_ptr
(
xtfpga_spi_of_match
),
},
};
module_platform_driver
(
xtfpga_spi_driver
);
MODULE_AUTHOR
(
"Max Filippov <jcmvbkbc@gmail.com>"
);
MODULE_DESCRIPTION
(
"xtensa xtfpga SPI driver"
);
MODULE_LICENSE
(
"GPL"
);
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