drivers/spi: Specify options per-port on DW driver

Generalize clock control. Make interrupt policy per-port.

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2018-02-27 07:31:05 +01:00 committed by Carles Cufí
parent 44d4de5105
commit 423f0095c7
4 changed files with 107 additions and 78 deletions

View File

@ -23,33 +23,6 @@ config SPI_DW_ARC_AUX_REGS
registers and thus their access is different than memory
mapped registers.
choice
depends on SPI_DW
prompt "DesignWare SPI interrupt management logic"
default SPI_DW_INTERRUPT_SINGLE_LINE
config SPI_DW_INTERRUPT_SINGLE_LINE
bool "Single interrupt line for all interrupts"
help
Only one line is used to trigger interrupts: RX, TX and ERROR
interrupt go all through that line, undifferentiated.
config SPI_DW_INTERRUPT_SEPARATED_LINES
bool "One line per-interrupt type (RX, TX and ERROR)"
help
Each interrupt gets a dedicated line
endchoice
config SPI_DW_CLOCK_GATE
bool "Enable clock gating"
depends on SPI_DW && SOC_QUARK_SE_C1000
select CLOCK_CONTROL
default n
config SPI_DW_CLOCK_GATE_DRV_NAME
string
depends on SPI_DW_CLOCK_GATE
default ""
config SPI_DW_FIFO_DEPTH
int "RX and TX FIFO Depth"
help
@ -57,12 +30,54 @@ config SPI_DW_FIFO_DEPTH
SSI_RX_FIFO_DEPTH of the DesignWare Synchronous
Serial Interface. Depth ranges from 2-256.
if SPI_0
config SPI_DW_PORT_0_INTERRUPT_SINGLE_LINE
bool "Single interrupt line for all interrupts"
default y
help
Only one line is used to trigger interrupts: RX, TX and ERROR
interrupt go all through that line, undifferentiated.
config SPI_DW_PORT_0_CLOCK_GATE
bool "Enable clock gating"
depends on CLOCK_CONTROL
default n
if SPI_DW_PORT_0_CLOCK_GATE
config SPI_DW_PORT_0_CLOCK_GATE_DRV_NAME
string
default ""
config SPI_DW_PORT_0_CLOCK_GATE_SUBSYS
int "Clock controller's subsystem"
depends on SPI_DW_CLOCK_GATE
endif # SPI_DW_PORT_0_CLOCK_GATE
endif # SPI_0
if SPI_1
config SPI_DW_PORT_1_INTERRUPT_SINGLE_LINE
bool "Single interrupt line for all interrupts"
default y
config SPI_DW_PORT_1_CLOCK_GATE
bool "Enable clock gating"
depends on CLOCK_CONTROL
default n
if SPI_DW_PORT_1_CLOCK_GATE
config SPI_DW_PORT_1_CLOCK_GATE_DRV_NAME
string
default ""
config SPI_DW_PORT_1_CLOCK_GATE_SUBSYS
int "Clock controller's subsystem"
depends on SPI_DW_CLOCK_GATE
endif # SPI_DW_PORT_1_CLOCK_GATE
endif # SPI_1
endif # SPI_DW

View File

@ -462,9 +462,10 @@ struct spi_dw_data spi_dw_data_port_0 = {
const struct spi_dw_config spi_dw_config_0 = {
.regs = SPI_DW_PORT_0_REGS,
#ifdef CONFIG_SPI_DW_CLOCK_GATE
.clock_data = UINT_TO_POINTER(CONFIG_SPI_0_CLOCK_GATE_SUBSYS),
#endif /* CONFIG_SPI_DW_CLOCK_GATE */
#ifdef CONFIG_SPI_DW_PORT_0_CLOCK_GATE
.clock_name = CONFIG_SPI_DW_PORT_1_CLOCK_GATE_DRV_NAME,
.clock_data = UINT_TO_POINTER(CONFIG_SPI_DW_PORT_0_CLOCK_GATE_SUBSYS),
#endif /* CONFIG_SPI_DW_PORT_0_CLOCK_GATE */
.config_func = spi_config_0_irq
};
@ -475,12 +476,12 @@ DEVICE_AND_API_INIT(spi_dw_port_0, CONFIG_SPI_0_NAME, spi_dw_init,
void spi_config_0_irq(void)
{
#ifdef CONFIG_SPI_DW_INTERRUPT_SINGLE_LINE
#ifdef CONFIG_SPI_DW_PORT_0_INTERRUPT_SINGLE_LINE
IRQ_CONNECT(SPI_DW_PORT_0_IRQ, CONFIG_SPI_0_IRQ_PRI,
spi_dw_isr, DEVICE_GET(spi_dw_port_0), SPI_DW_IRQ_FLAGS);
irq_enable(SPI_DW_PORT_0_IRQ);
_spi_int_unmask(SPI_DW_PORT_0_INT_MASK);
#else /* SPI_DW_INTERRUPT_SEPARATED_LINES */
#else
IRQ_CONNECT(IRQ_SPI0_RX_AVAIL, CONFIG_SPI_0_IRQ_PRI,
spi_dw_isr, DEVICE_GET(spi_dw_port_0), SPI_DW_IRQ_FLAGS);
IRQ_CONNECT(IRQ_SPI0_TX_REQ, CONFIG_SPI_0_IRQ_PRI,
@ -508,9 +509,10 @@ struct spi_dw_data spi_dw_data_port_1 = {
static const struct spi_dw_config spi_dw_config_1 = {
.regs = SPI_DW_PORT_1_REGS,
#ifdef CONFIG_SPI_DW_CLOCK_GATE
.clock_data = UINT_TO_POINTER(CONFIG_SPI_1_CLOCK_GATE_SUBSYS),
#endif /* CONFIG_SPI_DW_CLOCK_GATE */
#ifdef CONFIG_SPI_DW_PORT_1_CLOCK_GATE
.clock_name = CONFIG_SPI_DW_PORT_1_CLOCK_GATE_DRV_NAME,
.clock_data = UINT_TO_POINTER(CONFIG_SPI_DW_PORT_1_CLOCK_GATE_SUBSYS),
#endif /* CONFIG_SPI_DW_PORT_1_CLOCK_GATE */
.config_func = spi_config_1_irq
};
@ -521,12 +523,12 @@ DEVICE_AND_API_INIT(spi_dw_port_1, CONFIG_SPI_1_NAME, spi_dw_init,
void spi_config_1_irq(void)
{
#ifdef CONFIG_SPI_DW_INTERRUPT_SINGLE_LINE
#ifdef CONFIG_SPI_DW_PORT_1_INTERRUPT_SINGLE_LINE
IRQ_CONNECT(SPI_DW_PORT_1_IRQ, CONFIG_SPI_1_IRQ_PRI,
spi_dw_isr, DEVICE_GET(spi_dw_port_1), SPI_DW_IRQ_FLAGS);
irq_enable(SPI_DW_PORT_1_IRQ);
_spi_int_unmask(SPI_DW_PORT_1_INT_MASK);
#else /* SPI_DW_INTERRUPT_SEPARATED_LINES */
#else
IRQ_CONNECT(IRQ_SPI1_RX_AVAIL, CONFIG_SPI_1_IRQ_PRI,
spi_dw_isr, DEVICE_GET(spi_dw_port_1), SPI_DW_IRQ_FLAGS);
IRQ_CONNECT(IRQ_SPI1_TX_REQ, CONFIG_SPI_1_IRQ_PRI,

View File

@ -20,18 +20,19 @@ typedef void (*spi_dw_config_t)(void);
/* Private structures */
struct spi_dw_config {
u32_t regs;
#ifdef CONFIG_SPI_DW_CLOCK_GATE
#ifdef CONFIG_CLOCK_CONTROL
const char *clock_name;
void *clock_data;
#endif /* CONFIG_SPI_DW_CLOCK_GATE */
#endif /* CONFIG_CLOCK_CONTROL */
spi_dw_config_t config_func;
};
#include "spi_context.h"
struct spi_dw_data {
#ifdef CONFIG_SPI_DW_CLOCK_GATE
#ifdef CONFIG_CLOCK_CONTROL
struct device *clock;
#endif /* CONFIG_SPI_DW_CLOCK_GATE */
#endif /* CONFIG_CLOCK_CONTROL */
struct spi_context ctx;
u8_t dfs; /* dfs in bytes: 1,2 or 4 */
u8_t fifo_diff; /* cannot be bigger than FIFO depth */
@ -224,6 +225,52 @@ DEFINE_CLEAR_BIT_OP(ssienr, DW_SPI_REG_SSIENR, DW_SPI_SSIENR_SSIEN_BIT)
DEFINE_TEST_BIT_OP(ssienr, DW_SPI_REG_SSIENR, DW_SPI_SSIENR_SSIEN_BIT)
DEFINE_TEST_BIT_OP(sr_busy, DW_SPI_REG_SR, DW_SPI_SR_BUSY_BIT)
#ifdef CONFIG_CLOCK_CONTROL
static inline int _clock_config(struct device *dev)
{
const struct spi_dw_config *info = dev->config->config_info;
struct spi_dw_data *spi = dev->driver_data;
if (!info->clock_name || strlen(info->clock_name) == 0) {
spi->clock = NULL;
return 0;
}
spi->clock = device_get_binding(info->clock_name);
if (!spi->clock) {
return -ENODEV;
}
return 0;
}
static inline void _clock_on(struct device *dev)
{
struct spi_dw_data *spi = dev->driver_data;
if (spi->clock) {
const struct spi_dw_config *info = dev->config->config_info;
clock_control_on(spi->clock, info->clock_data);
}
}
static inline void _clock_off(struct device *dev)
{
struct spi_dw_data *spi = dev->driver_data;
if (spi->clock) {
const struct spi_dw_config *info = dev->config->config_info;
clock_control_off(spi->clock, info->clock_data);
}
}
#else
#define _clock_config(...)
#define _clock_on(...)
#define _clock_off(...)
#endif /* CONFIG_CLOCK_CONTROL */
#ifdef __cplusplus
}
#endif

View File

@ -57,41 +57,6 @@ DEFINE_MM_REG_READ(ssi_comp_version, DW_SPI_REG_SSI_COMP_VERSION, 32)
DEFINE_TEST_BIT_OP(icr, DW_SPI_REG_ICR, DW_SPI_SR_ICR_BIT)
#define clear_interrupts(addr) test_bit_icr(addr)
#ifdef CONFIG_SPI_DW_CLOCK_GATE
static inline void _clock_config(struct device *dev)
{
struct device *clk;
char *drv = CONFIG_SPI_DW_CLOCK_GATE_DRV_NAME;
clk = device_get_binding(drv);
if (clk) {
struct spi_dw_data *spi = dev->driver_data;
spi->clock = clk;
}
}
static inline void _clock_on(struct device *dev)
{
const struct spi_dw_config *info = dev->config->config_info;
struct spi_dw_data *spi = dev->driver_data;
clock_control_on(spi->clock, info->clock_data);
}
static inline void _clock_off(struct device *dev)
{
const struct spi_dw_config *info = dev->config->config_info;
struct spi_dw_data *spi = dev->driver_data;
clock_control_off(spi->clock, info->clock_data);
}
#else
#define _clock_config(...)
#define _clock_on(...)
#define _clock_off(...)
#endif /* CONFIG_SPI_DW_CLOCK_GATE */
#ifdef __cplusplus
}
#endif