146 lines
4.4 KiB
C
146 lines
4.4 KiB
C
/* 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)
|
|
{
|
|
struct spi_dw_config *info = dev->config->config_info;
|
|
|
|
set_bit_clk_ena(info->regs);
|
|
}
|
|
|
|
static inline void _clock_off(struct device *dev)
|
|
{
|
|
struct spi_dw_config *info = dev->config->config_info;
|
|
|
|
clear_bit_clk_ena(info->regs);
|
|
}
|
|
|
|
#endif /* __SPI_DW_QUARK_SE_SS_H__ */
|