/* spi_dw_quark_se_ss.h - Designware SPI driver private definitions */ /* * Copyright (c) 2015 Intel Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __SPI_DW_QUARK_SE_SS_H__ #define __SPI_DW_QUARK_SE_SS_H__ /* 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(uint32_t data, uint32_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(uint32_t data, uint32_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(uint32_t data, uint32_t addr) { write_rxftlr_b((read_rxftlr_b(addr) & (~DW_SPI_QSS_RXFTLR_MASK)) | data, addr); } static inline void write_txftlr(uint32_t data, uint32_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(uint32_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(uint32_t data, uint32_t addr) { write_dr_b(data | DW_SPI_DR_WRITE, addr); } static inline uint32_t read_dr(uint32_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); } #endif /* __SPI_DW_QUARK_SE_SS_H__ */