blob: 930ac610d1bd6794b2c27f77c1efe73b720cc1ec [file] [log] [blame]
/* spi_dw_quark_se_ss.h - Designware SPI driver private definitions */
/*
* Copyright (c) 2015 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __SPI_DW_QUARK_SE_SS_H__
#define __SPI_DW_QUARK_SE_SS_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Registers:
* Some registers have been collapsed into one
* - SER is part of SSIENR
* - TXFTLR is part of RXFTLR
* This requires a little bit different access functions
* see below: write_ser(), write_rxftlr() and write_txftlr()
*/
#define DW_SPI_REG_CTRLR0 (0x00)
#define DW_SPI_REG_SSIENR (0x02)
#define DW_SPI_REG_BAUDR (0x04)
#define DW_SPI_REG_RXFTLR (0x05)
#define DW_SPI_REG_TXFLR (0x07)
#define DW_SPI_REG_RXFLR (0x08)
#define DW_SPI_REG_SR (0x09)
#define DW_SPI_REG_ISR (0x0a)
#define DW_SPI_REG_IMR (0x0b)
#define DW_SPI_REG_ICR (0x0c)
#define DW_SPI_REG_DR (0x0d)
#define DW_SPI_CTRLR0_CLK_ENA_BIT (15)
#define DW_SPI_CTRLR0_CLK_ENA_MASK BIT(DW_SPI_CTRLR0_CLK_ENA_BIT)
#define DW_SPI_QSS_SSIENR_SER(__slv) (__slv << 4)
#define DW_SPI_QSS_TXFTLR(__lvl) (__lvl << 16)
#define DW_SPI_QSS_SER_MASK (0xf0)
#define DW_SPI_QSS_RXFTLR_MASK (0x0000ffff)
#define DW_SPI_QSS_TXFTLR_MASK (0xffff0000)
#define DW_SPI_DR_WD_BIT (30)
#define DW_SPI_DR_WD_MASK BIT(DW_SPI_DR_WD_BIT)
#define DW_SPI_DR_STROBE_BIT (31)
#define DW_SPI_DR_STROBE_MASK BIT(DW_SPI_DR_STROBE_BIT)
#define DW_SPI_DR_WRITE (DW_SPI_DR_STROBE_MASK | \
DW_SPI_DR_WD_MASK)
#define DW_SPI_DR_READ (DW_SPI_DR_STROBE_MASK)
/* Register helpers
* *_b functions only used for creating proper ser one
*/
/* CTRLR0 on Quark SE SS has a CLK_ENA bit we want to keep
* as it is while writing the configuration.
* *_b function only used for creating proper ser one
*/
DEFINE_MM_REG_READ(ctrlr0_b, DW_SPI_REG_CTRLR0, 16)
DEFINE_MM_REG_WRITE(ctrlr0_b, DW_SPI_REG_CTRLR0, 16)
static inline void write_ctrlr0(u32_t data, u32_t addr)
{
write_ctrlr0_b((read_ctrlr0_b(addr) & DW_SPI_CTRLR0_CLK_ENA_MASK) |
data, addr);
}
DEFINE_MM_REG_READ(ssienr_b, DW_SPI_REG_SSIENR, 8)
DEFINE_MM_REG_WRITE(ssienr_b, DW_SPI_REG_SSIENR, 8)
static inline void write_ser(u32_t data, u32_t addr)
{
write_ssienr_b((read_ssienr_b(addr) & (~DW_SPI_QSS_SER_MASK)) |
DW_SPI_QSS_SSIENR_SER(data), addr);
}
DEFINE_MM_REG_READ(rxftlr_b, DW_SPI_REG_RXFTLR, 32)
DEFINE_MM_REG_WRITE(rxftlr_b, DW_SPI_REG_RXFTLR, 32)
DEFINE_MM_REG_READ(rxftlr, DW_SPI_REG_RXFTLR, 16)
static inline void write_rxftlr(u32_t data, u32_t addr)
{
write_rxftlr_b((read_rxftlr_b(addr) & (~DW_SPI_QSS_RXFTLR_MASK)) |
data, addr);
}
static inline void write_txftlr(u32_t data, u32_t addr)
{
write_rxftlr_b((read_rxftlr_b(addr) & (~DW_SPI_QSS_TXFTLR_MASK)) |
DW_SPI_QSS_TXFTLR(data), addr);
}
/* Quark SE SS requires to clear up all interrupts */
DEFINE_MM_REG_WRITE(icr, DW_SPI_REG_ICR, 8)
static inline void clear_interrupts(u32_t addr)
{
write_icr(0x1f, addr);
}
/* Reading and Writing Data
* Quark SE SS DW SPI controller requires more logic from the driver which:
* - needs to tell when it has been pushing in bits for TX FIFO
* - needs to tell when it will be pulling out bits from RX FIFO
*/
DEFINE_MM_REG_WRITE(dr_b, DW_SPI_REG_DR, 32)
DEFINE_MM_REG_READ(dr_b, DW_SPI_REG_DR, 32)
static inline void write_dr(u32_t data, u32_t addr)
{
write_dr_b(data | DW_SPI_DR_WRITE, addr);
}
static inline u32_t read_dr(u32_t addr)
{
write_dr_b(DW_SPI_DR_READ, addr);
__asm__("nop\n");
return read_dr_b(addr);
}
/* Internal clock gating */
DEFINE_SET_BIT_OP(clk_ena, DW_SPI_REG_CTRLR0, DW_SPI_CTRLR0_CLK_ENA_BIT)
DEFINE_CLEAR_BIT_OP(clk_ena, DW_SPI_REG_CTRLR0, DW_SPI_CTRLR0_CLK_ENA_BIT)
#define _clock_config(...)
static inline void _clock_on(struct device *dev)
{
const struct spi_dw_config *info = dev->config->config_info;
set_bit_clk_ena(info->regs);
}
static inline void _clock_off(struct device *dev)
{
const struct spi_dw_config *info = dev->config->config_info;
clear_bit_clk_ena(info->regs);
}
#ifdef __cplusplus
}
#endif
#endif /* __SPI_DW_QUARK_SE_SS_H__ */