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:
parent
44d4de5105
commit
423f0095c7
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user