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
afa8f0cd
Commit
afa8f0cd
authored
Sep 01, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'spi/topic/efm32' into spi-next
parents
2f2613b0
d8851a0d
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
572 additions
and
0 deletions
+572
-0
Documentation/devicetree/bindings/spi/efm32-spi.txt
Documentation/devicetree/bindings/spi/efm32-spi.txt
+34
-0
drivers/spi/Kconfig
drivers/spi/Kconfig
+7
-0
drivers/spi/Makefile
drivers/spi/Makefile
+1
-0
drivers/spi/spi-efm32.c
drivers/spi/spi-efm32.c
+516
-0
include/linux/platform_data/efm32-spi.h
include/linux/platform_data/efm32-spi.h
+14
-0
No files found.
Documentation/devicetree/bindings/spi/efm32-spi.txt
0 → 100644
View file @
afa8f0cd
* Energy Micro EFM32 SPI
Required properties:
- #address-cells: see spi-bus.txt
- #size-cells: see spi-bus.txt
- compatible: should be "efm32,spi"
- reg: Offset and length of the register set for the controller
- interrupts: pair specifying rx and tx irq
- clocks: phandle to the spi clock
- cs-gpios: see spi-bus.txt
- location: Value to write to the ROUTE register's LOCATION bitfield to configure the pinmux for the device, see datasheet for values.
Example:
spi1: spi@0x4000c400 { /* USART1 */
#address-cells = <1>;
#size-cells = <0>;
compatible = "efm32,spi";
reg = <0x4000c400 0x400>;
interrupts = <15 16>;
clocks = <&cmu 20>;
cs-gpios = <&gpio 51 1>; // D3
location = <1>;
status = "ok";
ks8851@0 {
compatible = "ks8851";
spi-max-frequency = <6000000>;
reg = <0>;
interrupt-parent = <&boardfpga>;
interrupts = <4>;
status = "ok";
};
};
drivers/spi/Kconfig
View file @
afa8f0cd
...
...
@@ -164,6 +164,13 @@ config SPI_DAVINCI
help
SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
config SPI_EFM32
tristate "EFM32 SPI controller"
depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST)
select SPI_BITBANG
help
Driver for the spi controller found on Energy Micro's EFM32 SoCs.
config SPI_EP93XX
tristate "Cirrus Logic EP93xx SPI controller"
depends on ARCH_EP93XX || COMPILE_TEST
...
...
drivers/spi/Makefile
View file @
afa8f0cd
...
...
@@ -28,6 +28,7 @@ obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o
obj-$(CONFIG_SPI_DW_MMIO)
+=
spi-dw-mmio.o
obj-$(CONFIG_SPI_DW_PCI)
+=
spi-dw-midpci.o
spi-dw-midpci-objs
:=
spi-dw-pci.o spi-dw-mid.o
obj-$(CONFIG_SPI_EFM32)
+=
spi-efm32.o
obj-$(CONFIG_SPI_EP93XX)
+=
spi-ep93xx.o
obj-$(CONFIG_SPI_FALCON)
+=
spi-falcon.o
obj-$(CONFIG_SPI_FSL_CPM)
+=
spi-fsl-cpm.o
...
...
drivers/spi/spi-efm32.c
0 → 100644
View file @
afa8f0cd
/*
* Copyright (C) 2012-2013 Uwe Kleine-Koenig for Pengutronix
*
* 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/kernel.h>
#include <linux/io.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_data/efm32-spi.h>
#define DRIVER_NAME "efm32-spi"
#define MASK_VAL(mask, val) ((val << __ffs(mask)) & mask)
#define REG_CTRL 0x00
#define REG_CTRL_SYNC 0x0001
#define REG_CTRL_CLKPOL 0x0100
#define REG_CTRL_CLKPHA 0x0200
#define REG_CTRL_MSBF 0x0400
#define REG_CTRL_TXBIL 0x1000
#define REG_FRAME 0x04
#define REG_FRAME_DATABITS__MASK 0x000f
#define REG_FRAME_DATABITS(n) ((n) - 3)
#define REG_CMD 0x0c
#define REG_CMD_RXEN 0x0001
#define REG_CMD_RXDIS 0x0002
#define REG_CMD_TXEN 0x0004
#define REG_CMD_TXDIS 0x0008
#define REG_CMD_MASTEREN 0x0010
#define REG_STATUS 0x10
#define REG_STATUS_TXENS 0x0002
#define REG_STATUS_TXC 0x0020
#define REG_STATUS_TXBL 0x0040
#define REG_STATUS_RXDATAV 0x0080
#define REG_CLKDIV 0x14
#define REG_RXDATAX 0x18
#define REG_RXDATAX_RXDATA__MASK 0x01ff
#define REG_RXDATAX_PERR 0x4000
#define REG_RXDATAX_FERR 0x8000
#define REG_TXDATA 0x34
#define REG_IF 0x40
#define REG_IF_TXBL 0x0002
#define REG_IF_RXDATAV 0x0004
#define REG_IFS 0x44
#define REG_IFC 0x48
#define REG_IEN 0x4c
#define REG_ROUTE 0x54
#define REG_ROUTE_RXPEN 0x0001
#define REG_ROUTE_TXPEN 0x0002
#define REG_ROUTE_CLKPEN 0x0008
#define REG_ROUTE_LOCATION__MASK 0x0700
#define REG_ROUTE_LOCATION(n) MASK_VAL(REG_ROUTE_LOCATION__MASK, (n))
struct
efm32_spi_ddata
{
struct
spi_bitbang
bitbang
;
spinlock_t
lock
;
struct
clk
*
clk
;
void
__iomem
*
base
;
unsigned
int
rxirq
,
txirq
;
struct
efm32_spi_pdata
pdata
;
/* irq data */
struct
completion
done
;
const
u8
*
tx_buf
;
u8
*
rx_buf
;
unsigned
tx_len
,
rx_len
;
/* chip selects */
unsigned
csgpio
[];
};
#define ddata_to_dev(ddata) (&(ddata->bitbang.master->dev))
#define efm32_spi_vdbg(ddata, format, arg...) \
dev_vdbg(ddata_to_dev(ddata), format, ##arg)
static
void
efm32_spi_write32
(
struct
efm32_spi_ddata
*
ddata
,
u32
value
,
unsigned
offset
)
{
writel_relaxed
(
value
,
ddata
->
base
+
offset
);
}
static
u32
efm32_spi_read32
(
struct
efm32_spi_ddata
*
ddata
,
unsigned
offset
)
{
return
readl_relaxed
(
ddata
->
base
+
offset
);
}
static
void
efm32_spi_chipselect
(
struct
spi_device
*
spi
,
int
is_on
)
{
struct
efm32_spi_ddata
*
ddata
=
spi_master_get_devdata
(
spi
->
master
);
int
value
=
!
(
spi
->
mode
&
SPI_CS_HIGH
)
==
!
(
is_on
==
BITBANG_CS_ACTIVE
);
gpio_set_value
(
ddata
->
csgpio
[
spi
->
chip_select
],
value
);
}
static
int
efm32_spi_setup_transfer
(
struct
spi_device
*
spi
,
struct
spi_transfer
*
t
)
{
struct
efm32_spi_ddata
*
ddata
=
spi_master_get_devdata
(
spi
->
master
);
unsigned
bpw
=
t
->
bits_per_word
?:
spi
->
bits_per_word
;
unsigned
speed
=
t
->
speed_hz
?:
spi
->
max_speed_hz
;
unsigned
long
clkfreq
=
clk_get_rate
(
ddata
->
clk
);
u32
clkdiv
;
efm32_spi_write32
(
ddata
,
REG_CTRL_SYNC
|
REG_CTRL_MSBF
|
(
spi
->
mode
&
SPI_CPHA
?
REG_CTRL_CLKPHA
:
0
)
|
(
spi
->
mode
&
SPI_CPOL
?
REG_CTRL_CLKPOL
:
0
),
REG_CTRL
);
efm32_spi_write32
(
ddata
,
REG_FRAME_DATABITS
(
bpw
),
REG_FRAME
);
if
(
2
*
speed
>=
clkfreq
)
clkdiv
=
0
;
else
clkdiv
=
64
*
(
DIV_ROUND_UP
(
2
*
clkfreq
,
speed
)
-
4
);
if
(
clkdiv
>
(
1U
<<
21
))
return
-
EINVAL
;
efm32_spi_write32
(
ddata
,
clkdiv
,
REG_CLKDIV
);
efm32_spi_write32
(
ddata
,
REG_CMD_MASTEREN
,
REG_CMD
);
efm32_spi_write32
(
ddata
,
REG_CMD_RXEN
|
REG_CMD_TXEN
,
REG_CMD
);
return
0
;
}
static
void
efm32_spi_tx_u8
(
struct
efm32_spi_ddata
*
ddata
)
{
u8
val
=
0
;
if
(
ddata
->
tx_buf
)
{
val
=
*
ddata
->
tx_buf
;
ddata
->
tx_buf
++
;
}
ddata
->
tx_len
--
;
efm32_spi_write32
(
ddata
,
val
,
REG_TXDATA
);
efm32_spi_vdbg
(
ddata
,
"%s: tx 0x%x
\n
"
,
__func__
,
val
);
}
static
void
efm32_spi_rx_u8
(
struct
efm32_spi_ddata
*
ddata
)
{
u32
rxdata
=
efm32_spi_read32
(
ddata
,
REG_RXDATAX
);
efm32_spi_vdbg
(
ddata
,
"%s: rx 0x%x
\n
"
,
__func__
,
rxdata
);
if
(
ddata
->
rx_buf
)
{
*
ddata
->
rx_buf
=
rxdata
;
ddata
->
rx_buf
++
;
}
ddata
->
rx_len
--
;
}
static
void
efm32_spi_filltx
(
struct
efm32_spi_ddata
*
ddata
)
{
while
(
ddata
->
tx_len
&&
ddata
->
tx_len
+
2
>
ddata
->
rx_len
&&
efm32_spi_read32
(
ddata
,
REG_STATUS
)
&
REG_STATUS_TXBL
)
{
efm32_spi_tx_u8
(
ddata
);
}
}
static
int
efm32_spi_txrx_bufs
(
struct
spi_device
*
spi
,
struct
spi_transfer
*
t
)
{
struct
efm32_spi_ddata
*
ddata
=
spi_master_get_devdata
(
spi
->
master
);
int
ret
=
-
EBUSY
;
spin_lock_irq
(
&
ddata
->
lock
);
if
(
ddata
->
tx_buf
||
ddata
->
rx_buf
)
goto
out_unlock
;
ddata
->
tx_buf
=
t
->
tx_buf
;
ddata
->
rx_buf
=
t
->
rx_buf
;
ddata
->
tx_len
=
ddata
->
rx_len
=
t
->
len
*
DIV_ROUND_UP
(
t
->
bits_per_word
,
8
);
efm32_spi_filltx
(
ddata
);
init_completion
(
&
ddata
->
done
);
efm32_spi_write32
(
ddata
,
REG_IF_TXBL
|
REG_IF_RXDATAV
,
REG_IEN
);
spin_unlock_irq
(
&
ddata
->
lock
);
wait_for_completion
(
&
ddata
->
done
);
spin_lock_irq
(
&
ddata
->
lock
);
ret
=
t
->
len
-
max
(
ddata
->
tx_len
,
ddata
->
rx_len
);
efm32_spi_write32
(
ddata
,
0
,
REG_IEN
);
ddata
->
tx_buf
=
ddata
->
rx_buf
=
NULL
;
out_unlock:
spin_unlock_irq
(
&
ddata
->
lock
);
return
ret
;
}
static
irqreturn_t
efm32_spi_rxirq
(
int
irq
,
void
*
data
)
{
struct
efm32_spi_ddata
*
ddata
=
data
;
irqreturn_t
ret
=
IRQ_NONE
;
spin_lock
(
&
ddata
->
lock
);
while
(
ddata
->
rx_len
>
0
&&
efm32_spi_read32
(
ddata
,
REG_STATUS
)
&
REG_STATUS_RXDATAV
)
{
efm32_spi_rx_u8
(
ddata
);
ret
=
IRQ_HANDLED
;
}
if
(
!
ddata
->
rx_len
)
{
u32
ien
=
efm32_spi_read32
(
ddata
,
REG_IEN
);
ien
&=
~
REG_IF_RXDATAV
;
efm32_spi_write32
(
ddata
,
ien
,
REG_IEN
);
complete
(
&
ddata
->
done
);
}
spin_unlock
(
&
ddata
->
lock
);
return
ret
;
}
static
irqreturn_t
efm32_spi_txirq
(
int
irq
,
void
*
data
)
{
struct
efm32_spi_ddata
*
ddata
=
data
;
efm32_spi_vdbg
(
ddata
,
"%s: txlen = %u, rxlen = %u, if=0x%08x, stat=0x%08x
\n
"
,
__func__
,
ddata
->
tx_len
,
ddata
->
rx_len
,
efm32_spi_read32
(
ddata
,
REG_IF
),
efm32_spi_read32
(
ddata
,
REG_STATUS
));
spin_lock
(
&
ddata
->
lock
);
efm32_spi_filltx
(
ddata
);
efm32_spi_vdbg
(
ddata
,
"%s: txlen = %u, rxlen = %u
\n
"
,
__func__
,
ddata
->
tx_len
,
ddata
->
rx_len
);
if
(
!
ddata
->
tx_len
)
{
u32
ien
=
efm32_spi_read32
(
ddata
,
REG_IEN
);
ien
&=
~
REG_IF_TXBL
;
efm32_spi_write32
(
ddata
,
ien
,
REG_IEN
);
efm32_spi_vdbg
(
ddata
,
"disable TXBL
\n
"
);
}
spin_unlock
(
&
ddata
->
lock
);
return
IRQ_HANDLED
;
}
static
const
struct
efm32_spi_pdata
efm32_spi_pdata_default
=
{
.
location
=
1
,
};
static
u32
efm32_spi_get_configured_location
(
struct
efm32_spi_ddata
*
ddata
)
{
u32
reg
=
efm32_spi_read32
(
ddata
,
REG_ROUTE
);
return
(
reg
&
REG_ROUTE_LOCATION__MASK
)
>>
__ffs
(
REG_ROUTE_LOCATION__MASK
);
}
static
int
efm32_spi_probe_dt
(
struct
platform_device
*
pdev
,
struct
spi_master
*
master
,
struct
efm32_spi_ddata
*
ddata
)
{
struct
device_node
*
np
=
pdev
->
dev
.
of_node
;
u32
location
;
int
ret
;
if
(
!
np
)
return
1
;
ret
=
of_property_read_u32
(
np
,
"location"
,
&
location
);
if
(
!
ret
)
{
dev_dbg
(
&
pdev
->
dev
,
"using location %u
\n
"
,
location
);
}
else
{
/* default to location configured in hardware */
location
=
efm32_spi_get_configured_location
(
ddata
);
dev_info
(
&
pdev
->
dev
,
"fall back to location %u
\n
"
,
location
);
}
ddata
->
pdata
.
location
=
location
;
/* spi core takes care about the bus number using an alias */
master
->
bus_num
=
-
1
;
return
0
;
}
static
int
efm32_spi_probe
(
struct
platform_device
*
pdev
)
{
struct
efm32_spi_ddata
*
ddata
;
struct
resource
*
res
;
int
ret
;
struct
spi_master
*
master
;
struct
device_node
*
np
=
pdev
->
dev
.
of_node
;
unsigned
int
num_cs
,
i
;
num_cs
=
of_gpio_named_count
(
np
,
"cs-gpios"
);
master
=
spi_alloc_master
(
&
pdev
->
dev
,
sizeof
(
*
ddata
)
+
num_cs
*
sizeof
(
unsigned
));
if
(
!
master
)
{
dev_dbg
(
&
pdev
->
dev
,
"failed to allocate spi master controller
\n
"
);
return
-
ENOMEM
;
}
platform_set_drvdata
(
pdev
,
master
);
master
->
dev
.
of_node
=
pdev
->
dev
.
of_node
;
master
->
num_chipselect
=
num_cs
;
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
SPI_CS_HIGH
;
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
4
,
16
);
ddata
=
spi_master_get_devdata
(
master
);
ddata
->
bitbang
.
master
=
spi_master_get
(
master
);
ddata
->
bitbang
.
chipselect
=
efm32_spi_chipselect
;
ddata
->
bitbang
.
setup_transfer
=
efm32_spi_setup_transfer
;
ddata
->
bitbang
.
txrx_bufs
=
efm32_spi_txrx_bufs
;
spin_lock_init
(
&
ddata
->
lock
);
ddata
->
clk
=
devm_clk_get
(
&
pdev
->
dev
,
NULL
);
if
(
IS_ERR
(
ddata
->
clk
))
{
ret
=
PTR_ERR
(
ddata
->
clk
);
dev_err
(
&
pdev
->
dev
,
"failed to get clock: %d
\n
"
,
ret
);
goto
err
;
}
for
(
i
=
0
;
i
<
num_cs
;
++
i
)
{
ret
=
of_get_named_gpio
(
np
,
"cs-gpios"
,
i
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"failed to get csgpio#%u (%d)
\n
"
,
i
,
ret
);
goto
err
;
}
ddata
->
csgpio
[
i
]
=
ret
;
dev_dbg
(
&
pdev
->
dev
,
"csgpio#%u = %u
\n
"
,
i
,
ddata
->
csgpio
[
i
]);
ret
=
devm_gpio_request_one
(
&
pdev
->
dev
,
ddata
->
csgpio
[
i
],
GPIOF_OUT_INIT_LOW
,
DRIVER_NAME
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"failed to configure csgpio#%u (%d)
\n
"
,
i
,
ret
);
goto
err
;
}
}
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
res
)
{
ret
=
-
ENODEV
;
dev_err
(
&
pdev
->
dev
,
"failed to determine base address
\n
"
);
goto
err
;
}
if
(
resource_size
(
res
)
<
60
)
{
ret
=
-
EINVAL
;
dev_err
(
&
pdev
->
dev
,
"memory resource too small
\n
"
);
goto
err
;
}
ddata
->
base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
ddata
->
base
))
{
ret
=
PTR_ERR
(
ddata
->
base
);
goto
err
;
}
ret
=
platform_get_irq
(
pdev
,
0
);
if
(
ret
<=
0
)
{
dev_err
(
&
pdev
->
dev
,
"failed to get rx irq (%d)
\n
"
,
ret
);
goto
err
;
}
ddata
->
rxirq
=
ret
;
ret
=
platform_get_irq
(
pdev
,
1
);
if
(
ret
<=
0
)
ret
=
ddata
->
rxirq
+
1
;
ddata
->
txirq
=
ret
;
ret
=
clk_prepare_enable
(
ddata
->
clk
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"failed to enable clock (%d)
\n
"
,
ret
);
goto
err
;
}
ret
=
efm32_spi_probe_dt
(
pdev
,
master
,
ddata
);
if
(
ret
>
0
)
{
/* not created by device tree */
const
struct
efm32_spi_pdata
*
pdata
=
dev_get_platdata
(
&
pdev
->
dev
);
if
(
pdata
)
ddata
->
pdata
=
*
pdata
;
else
ddata
->
pdata
.
location
=
efm32_spi_get_configured_location
(
ddata
);
master
->
bus_num
=
pdev
->
id
;
}
else
if
(
ret
<
0
)
{
goto
err_disable_clk
;
}
efm32_spi_write32
(
ddata
,
0
,
REG_IEN
);
efm32_spi_write32
(
ddata
,
REG_ROUTE_TXPEN
|
REG_ROUTE_RXPEN
|
REG_ROUTE_CLKPEN
|
REG_ROUTE_LOCATION
(
ddata
->
pdata
.
location
),
REG_ROUTE
);
ret
=
request_irq
(
ddata
->
rxirq
,
efm32_spi_rxirq
,
0
,
DRIVER_NAME
" rx"
,
ddata
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"failed to register rxirq (%d)
\n
"
,
ret
);
goto
err_disable_clk
;
}
ret
=
request_irq
(
ddata
->
txirq
,
efm32_spi_txirq
,
0
,
DRIVER_NAME
" tx"
,
ddata
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"failed to register txirq (%d)
\n
"
,
ret
);
goto
err_free_rx_irq
;
}
ret
=
spi_bitbang_start
(
&
ddata
->
bitbang
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"spi_bitbang_start failed (%d)
\n
"
,
ret
);
free_irq
(
ddata
->
txirq
,
ddata
);
err_free_rx_irq:
free_irq
(
ddata
->
rxirq
,
ddata
);
err_disable_clk:
clk_disable_unprepare
(
ddata
->
clk
);
err:
spi_master_put
(
master
);
kfree
(
master
);
}
return
ret
;
}
static
int
efm32_spi_remove
(
struct
platform_device
*
pdev
)
{
struct
spi_master
*
master
=
platform_get_drvdata
(
pdev
);
struct
efm32_spi_ddata
*
ddata
=
spi_master_get_devdata
(
master
);
efm32_spi_write32
(
ddata
,
0
,
REG_IEN
);
free_irq
(
ddata
->
txirq
,
ddata
);
free_irq
(
ddata
->
rxirq
,
ddata
);
clk_disable_unprepare
(
ddata
->
clk
);
spi_master_put
(
master
);
kfree
(
master
);
return
0
;
}
static
const
struct
of_device_id
efm32_spi_dt_ids
[]
=
{
{
.
compatible
=
"efm32,spi"
,
},
{
/* sentinel */
}
};
MODULE_DEVICE_TABLE
(
of
,
efm32_spi_dt_ids
);
static
struct
platform_driver
efm32_spi_driver
=
{
.
probe
=
efm32_spi_probe
,
.
remove
=
efm32_spi_remove
,
.
driver
=
{
.
name
=
DRIVER_NAME
,
.
owner
=
THIS_MODULE
,
.
of_match_table
=
efm32_spi_dt_ids
,
},
};
module_platform_driver
(
efm32_spi_driver
);
MODULE_AUTHOR
(
"Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"
);
MODULE_DESCRIPTION
(
"EFM32 SPI driver"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_ALIAS
(
"platform:"
DRIVER_NAME
);
include/linux/platform_data/efm32-spi.h
0 → 100644
View file @
afa8f0cd
#ifndef __LINUX_PLATFORM_DATA_EFM32_SPI_H__
#define __LINUX_PLATFORM_DATA_EFM32_SPI_H__
#include <linux/types.h>
/**
* struct efm32_spi_pdata
* @location: pinmux location for the I/O pins (to be written to the ROUTE
* register)
*/
struct
efm32_spi_pdata
{
u8
location
;
};
#endif
/* ifndef __LINUX_PLATFORM_DATA_EFM32_SPI_H__ */
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