| /* 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__ */ |