mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-06-17 19:05:29 +08:00

* target: add phytium support * kernel/video: add phytium platform ARM GPU support * config: add EFI support to phytium armv8 * target: phytium: remove rtl8821cs driver * target: phytium: refresh dts
214 lines
4.9 KiB
C
214 lines
4.9 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef PHYTIUM_SPI_HEADER_H
|
|
#define PHYTIUM_SPI_HEADER_H
|
|
|
|
#include <linux/io.h>
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/gpio.h>
|
|
|
|
#define CTRLR0 0x00
|
|
#define SSIENR 0x08
|
|
#define SER 0x10
|
|
#define BAUDR 0x14
|
|
#define TXFLTR 0x18
|
|
#define TXFLR 0x20
|
|
#define RXFLR 0x24
|
|
#define SR 0x28
|
|
#define IMR 0x2c
|
|
#define ISR 0x30
|
|
#define RISR 0x34
|
|
#define ICR 0x48
|
|
#define DMACR 0x4C
|
|
#define DMATDLR 0x50
|
|
#define DMARDLR 0x54
|
|
#define DR 0x60
|
|
#define GCSR 0x100
|
|
|
|
#define FRF_OFFSET 4
|
|
#define MODE_OFFSET 6
|
|
#define TMOD_OFFSET 8
|
|
|
|
#define TMOD_MASK (0x3 << TMOD_OFFSET)
|
|
#define TMOD_TR 0x0
|
|
#define TMOD_TO 0x1
|
|
#define TMOD_RO 0x2
|
|
|
|
#define INT_TXEI (1 << 0)
|
|
#define INT_TXOI (1 << 1)
|
|
#define INT_RXUI (1 << 2)
|
|
#define INT_RXOI (1 << 3)
|
|
|
|
/* Bit fields in SR, 7 bits */
|
|
#define SR_MASK 0x7f /* cover 7 bits */
|
|
#define SR_BUSY (1 << 0)
|
|
#define SR_TF_NOT_FULL (1 << 1)
|
|
#define SR_TF_EMPT (1 << 2)
|
|
#define SR_RF_NOT_EMPT (1 << 3)
|
|
#define SR_RF_FULL (1 << 4)
|
|
#define SR_TX_ERR (1 << 5)
|
|
#define SR_DCOL (1 << 6)
|
|
|
|
/* Bit fields in DMACR */
|
|
#define SPI_DMA_RDMAE (1 << 0)
|
|
#define SPI_DMA_TDMAE (1 << 1)
|
|
|
|
#define SPI_WAIT_RETRIES 5
|
|
|
|
struct phytium_spi;
|
|
|
|
struct phytium_spi_dma_ops {
|
|
int (*dma_init)(struct device *dev, struct phytium_spi *fts);
|
|
void (*dma_exit)(struct phytium_spi *fts);
|
|
int (*dma_setup)(struct phytium_spi *fts, struct spi_transfer *xfer);
|
|
bool (*can_dma)(struct spi_controller *master, struct spi_device *spi,
|
|
struct spi_transfer *xfer);
|
|
int (*dma_transfer)(struct phytium_spi *fts, struct spi_transfer *xfer);
|
|
void (*dma_stop)(struct phytium_spi *fts);
|
|
};
|
|
|
|
struct phytium_spi {
|
|
struct spi_master *master;
|
|
char name[16];
|
|
|
|
void __iomem *regs;
|
|
bool global_cs;
|
|
bool dma_en;
|
|
unsigned long paddr;
|
|
int irq;
|
|
u32 fifo_len;
|
|
u32 max_freq;
|
|
|
|
u32 reg_io_width;
|
|
u16 bus_num;
|
|
u16 num_cs;
|
|
int *cs;
|
|
|
|
size_t len;
|
|
void *tx;
|
|
void *tx_end;
|
|
void *rx;
|
|
void *rx_end;
|
|
u8 n_bytes;
|
|
int dma_mapped;
|
|
struct clk *clk;
|
|
irqreturn_t (*transfer_handler)(struct phytium_spi *fts);
|
|
u32 current_freq; /* frequency in hz */
|
|
|
|
/* DMA info */
|
|
struct dma_chan *txchan;
|
|
u32 txburst;
|
|
struct dma_chan *rxchan;
|
|
u32 rxburst;
|
|
u32 dma_sg_burst;
|
|
unsigned long dma_chan_busy;
|
|
dma_addr_t dma_addr; /* phy address of the Data register */
|
|
const struct phytium_spi_dma_ops *dma_ops;
|
|
struct completion dma_completion;
|
|
};
|
|
|
|
static inline u32 phytium_readl(struct phytium_spi *fts, u32 offset)
|
|
{
|
|
return __raw_readl(fts->regs + offset);
|
|
}
|
|
|
|
static inline u16 phytium_readw(struct phytium_spi *fts, u32 offset)
|
|
{
|
|
return __raw_readw(fts->regs + offset);
|
|
}
|
|
|
|
static inline void phytium_writel(struct phytium_spi *fts, u32 offset, u32 val)
|
|
{
|
|
__raw_writel(val, fts->regs + offset);
|
|
}
|
|
|
|
static inline void phytium_writew(struct phytium_spi *fts, u32 offset, u16 val)
|
|
{
|
|
__raw_writew(val, fts->regs + offset);
|
|
}
|
|
|
|
static inline u32 phytium_read_io_reg(struct phytium_spi *fts, u32 offset)
|
|
{
|
|
switch (fts->reg_io_width) {
|
|
case 2:
|
|
return phytium_readw(fts, offset);
|
|
case 4:
|
|
default:
|
|
return phytium_readl(fts, offset);
|
|
}
|
|
}
|
|
|
|
static inline void phytium_write_io_reg(struct phytium_spi *fts, u32 offset, u32 val)
|
|
{
|
|
switch (fts->reg_io_width) {
|
|
case 2:
|
|
phytium_writew(fts, offset, val);
|
|
break;
|
|
case 4:
|
|
default:
|
|
phytium_writel(fts, offset, val);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static inline void spi_enable_chip(struct phytium_spi *fts, int enable)
|
|
{
|
|
phytium_writel(fts, SSIENR, (enable ? 1 : 0));
|
|
}
|
|
|
|
static inline void spi_set_clk(struct phytium_spi *fts, u16 div)
|
|
{
|
|
phytium_writel(fts, BAUDR, div);
|
|
}
|
|
|
|
static inline void spi_mask_intr(struct phytium_spi *fts, u32 mask)
|
|
{
|
|
u32 new_mask;
|
|
|
|
new_mask = phytium_readl(fts, IMR) & ~mask;
|
|
phytium_writel(fts, IMR, new_mask);
|
|
}
|
|
|
|
static inline void spi_umask_intr(struct phytium_spi *fts, u32 mask)
|
|
{
|
|
u32 new_mask;
|
|
|
|
new_mask = phytium_readl(fts, IMR) | mask;
|
|
phytium_writel(fts, IMR, new_mask);
|
|
}
|
|
|
|
static inline void spi_global_cs(struct phytium_spi *fts)
|
|
{
|
|
u32 global_cs_en, mask, setmask;
|
|
|
|
mask = GENMASK(fts->num_cs-1, 0) << fts->num_cs;
|
|
setmask = ~GENMASK(fts->num_cs-1, 0);
|
|
global_cs_en = (phytium_readl(fts, GCSR) | mask) & setmask;
|
|
|
|
phytium_writel(fts, GCSR, global_cs_en);
|
|
}
|
|
|
|
static inline void spi_reset_chip(struct phytium_spi *fts)
|
|
{
|
|
spi_enable_chip(fts, 0);
|
|
if (fts->global_cs)
|
|
spi_global_cs(fts);
|
|
spi_mask_intr(fts, 0xff);
|
|
spi_enable_chip(fts, 1);
|
|
}
|
|
|
|
static inline void spi_shutdown_chip(struct phytium_spi *fts)
|
|
{
|
|
spi_enable_chip(fts, 0);
|
|
spi_set_clk(fts, 0);
|
|
fts->current_freq = 0;
|
|
}
|
|
|
|
extern int phytium_spi_add_host(struct device *dev, struct phytium_spi *fts);
|
|
extern void phytium_spi_remove_host(struct phytium_spi *fts);
|
|
extern int phytium_spi_suspend_host(struct phytium_spi *fts);
|
|
extern int phytium_spi_resume_host(struct phytium_spi *fts);
|
|
extern void phytium_spi_dmaops_set(struct phytium_spi *fts);
|
|
extern int phytium_spi_check_status(struct phytium_spi *fts, bool raw);
|
|
|
|
#endif /* PHYTIUM_SPI_HEADER_H */
|