add spi driver

This commit is contained in:
林辉辉
2010-05-11 07:34:46 +00:00
committed by 黄涛
parent 2fe0f135b9
commit 50350fb320
10 changed files with 1328 additions and 5 deletions

View File

@@ -19,6 +19,7 @@
#include <linux/input.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/spi/spi.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -136,11 +137,34 @@ static struct map_desc rk2818_io_desc[] __initdata = {
.length = 0xa0000, ///apb bus i2s i2c spi no map in this
.type = MT_DEVICE
},
};
/*****************************************************************************************
* SPI devices
*author: lhh
*****************************************************************************************/
static struct spi_board_info board_spi_devices[] = {
{ /* net chip */
.modalias = "enc28j60",
.chip_select = 1,
.max_speed_hz = 12 * 1000 * 1000,
.bus_num = 0,
.mode = SPI_MODE_0,
},
{
.modalias = "xpt2046_ts",
.chip_select = 0,
.max_speed_hz = 1000000,
.bus_num = 0,
.mode = SPI_MODE_0,
},
};
static struct platform_device *devices[] __initdata = {
&rk2818_device_uart1,
&rk2818_device_spim,
};
extern struct sys_timer rk2818_timer;
@@ -155,7 +179,10 @@ static void __init machine_rk2818_init_irq(void)
static void __init machine_rk2818_board_init(void)
{
platform_add_devices(devices, ARRAY_SIZE(devices));
spi_register_board_info(board_spi_devices, ARRAY_SIZE(board_spi_devices));
rk2818_mux_api_set(GPIOB4_SPI0CS0_MMC0D4_NAME,IOMUXA_GPIO0_B4); //IOMUXA_SPI0_CSN0);//use for gpio SPI CS0
rk2818_mux_api_set(GPIOB0_SPI0CSN1_MMC1PCA_NAME,IOMUXA_GPIO0_B0); //IOMUXA_SPI0_CSN1);//use for gpio SPI CS1
rk2818_mux_api_set(GPIOB_SPI0_MMC0_NAME,IOMUXA_SPI0);//use for SPI CLK SDI SDO
}
static void __init machine_rk2818_mapio(void)

View File

@@ -915,7 +915,7 @@ static struct clk_lookup clks[] = {
CLK("rk2818_serial.1", "uart", &uart1_clk),
CLK1(i2c0),
CLK1(i2c1),
CLK1(spi0),
CLK("rk2818_spim.0", "spi", &spi0_clk),
CLK1(spi1),
CLK1(pwm),
CLK1(timer),

View File

@@ -100,3 +100,25 @@ struct platform_device rk2818_device_uart3 = {
.resource = resources_uart3,
};
/*
* rk2818 spi master device
*/
static struct resource resources_spim[] = {
{
.start = IRQ_NR_SPIM,
.end = IRQ_NR_SPIM,
.flags = IORESOURCE_IRQ,
},
{
.start = RK2818_SPIMASTER_PHYS,
.end = RK2818_SPIMASTER_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
};
struct platform_device rk2818_device_spim = {
.name = "rk2818_spim",
.id = 0,
.num_resources = ARRAY_SIZE(resources_spim),
.resource = resources_spim,
};

View File

@@ -16,7 +16,10 @@
#ifndef __ARCH_ARM_MACH_RK2818_DEVICES_H
#define __ARCH_ARM_MACH_RK2818_DEVICES_H
extern struct platform_device rk2818_device_uart0;
extern struct platform_device rk2818_device_uart1;
extern struct platform_device rk2818_device_uart2;
extern struct platform_device rk2818_device_uart3;
extern struct platform_device rk2818_device_spim;
#endif

View File

@@ -1,4 +1,5 @@
/* arch/arm/mach-rk2818/dma.h
/*
* arch/arm/mach-rk2818/include/mach/dma.h
*
* Copyright (C) 2010 ROCKCHIP, Inc.
*

View File

@@ -37,7 +37,7 @@
#define IOMUXA_FLASH_CS67 (2)
#define IOMUXA_GPIO1_A12 (0)
#define IOMUXA_CLKIN_SSINN (1)
#define IOMUXA_FLASH_CS45 (2) (1)
#define IOMUXA_FLASH_CS45 (2)
#define IOMUXA_GPIO0_B0 (0)
#define IOMUXA_SPI0_CSN1 (1)
#define IOMUXA_SDMMC1_PWR_EN (2)

View File

@@ -248,6 +248,13 @@ config SPI_XILINX
# Add new SPI master controllers in alphabetical order above this line
#
config SPIM_RK2818
tristate "RK2818 SPI master controller core support"
depends on ARCH_RK2818 && SPI_MASTER
help
general driver for SPI controller core from DesignWare
#
# There are lots of SPI device types, with sensors and memory
# being probably the most widely used ones.

View File

@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o
obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
obj-$(CONFIG_SPIM_RK2818) += rk2818_spim.o
obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
obj-$(CONFIG_SPI_IMX) += spi_imx.o
obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o

1039
drivers/spi/rk2818_spim.c Normal file

File diff suppressed because it is too large Load Diff

223
drivers/spi/rk2818_spim.h Normal file
View File

@@ -0,0 +1,223 @@
/* drivers/spi/rk2818_spim.h
*
* Copyright (C) 2010 ROCKCHIP, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __DRIVERS_SPIM_RK2818_HEADER_H
#define __DRIVERS_SPIM_RK2818_HEADER_H
#include <linux/io.h>
/* Bit fields in CTRLR0 */
#define SPI_DFS_OFFSET 0
#define SPI_FRF_OFFSET 4
#define SPI_FRF_SPI 0x0
#define SPI_FRF_SSP 0x1
#define SPI_FRF_MICROWIRE 0x2
#define SPI_FRF_RESV 0x3
#define SPI_MODE_OFFSET 6
#define SPI_SCPH_OFFSET 6
#define SPI_SCOL_OFFSET 7
#define SPI_TMOD_OFFSET 8
#define SPI_TMOD_TR 0x0 /* xmit & recv */
#define SPI_TMOD_TO 0x1 /* xmit only */
#define SPI_TMOD_RO 0x2 /* recv only */
#define SPI_TMOD_EPROMREAD 0x3 /* eeprom read mode */
#define SPI_SLVOE_OFFSET 10
#define SPI_SRL_OFFSET 11
#define SPI_CFS_OFFSET 12
/* 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 ISR, IMR, RISR, 7 bits */
#define SPI_INT_TXEI (1 << 0)
#define SPI_INT_TXOI (1 << 1)
#define SPI_INT_RXUI (1 << 2)
#define SPI_INT_RXOI (1 << 3)
#define SPI_INT_RXFI (1 << 4)
#define SPI_INT_MSTI (1 << 5)
/* TX RX interrupt level threshhold, max can be 256 */
#define SPI_INT_THRESHOLD 32
#define SPIM_CTRLR0 0x0000
#define SPIM_CTRLR1 0x0004
#define SPIM_SPIENR 0x0008
#define SPIM_MWCR 0x000c
#define SPIM_SER 0x0010
#define SPIM_BAUDR 0x0014
#define SPIM_TXFTLR 0x0018
#define SPIM_RXFTLR 0x001c
#define SPIM_TXFLR 0x0020
#define SPIM_RXFLR 0x0024
#define SPIM_SR 0x0028
#define SPIM_IMR 0x002c
#define SPIM_ISR 0x0030
#define SPIM_RISR 0x0034
#define SPIM_TXOICR 0x0038
#define SPIM_RXOICR 0x003c
#define SPIM_RXUICR 0x0040
#define SPIM_MSTICR 0x0044
#define SPIM_ICR 0x0048
#define SPIM_DMACR 0x004c
#define SPIM_DMATDLR 0x0050
#define SPIM_DMARDLR 0x0054
#define SPIM_IDR0 0x0058
#define SPIM_COMP_VERSION 0x005c
#define SPIM_DR0 0x0060
enum rk2818_ssi_type {
SSI_MOTO_SPI = 0,
SSI_TI_SSP,
SSI_NS_MICROWIRE,
};
struct rk2818_spi {
struct spi_master *master;
struct spi_device *cur_dev;
enum rk2818_ssi_type type;
void __iomem *regs;
unsigned long paddr;
u32 iolen;
int irq;
u32 fifo_len; /* depth of the FIFO buffer */
struct clk *clock_spim; /* clk apb */
struct platform_device *pdev;
/* Driver message queue */
struct workqueue_struct *workqueue;
struct work_struct pump_messages;
spinlock_t lock;
struct list_head queue;
int busy;
int run;
/* Message Transfer pump */
struct tasklet_struct pump_transfers;
/* Current message transfer state info */
struct spi_message *cur_msg;
struct spi_transfer *cur_transfer;
struct chip_data *cur_chip;
struct chip_data *prev_chip;
size_t len;
void *tx;
void *tx_end;
void *rx;
void *rx_end;
int dma_mapped;
dma_addr_t rx_dma;
dma_addr_t tx_dma;
size_t rx_map_len;
size_t tx_map_len;
u8 n_bytes; /* current is a 1/2 bytes op */
u8 max_bits_per_word; /* maxim is 16b */
u32 dma_width;
int cs_change;
int (*write)(struct rk2818_spi *dws);
int (*read)(struct rk2818_spi *dws);
irqreturn_t (*transfer_handler)(struct rk2818_spi *dws);
void (*cs_control)(u32 command);
/* Dma info */
int dma_inited;
struct dma_chan *txchan;
struct dma_chan *rxchan;
int txdma_done;
int rxdma_done;
u64 tx_param;
u64 rx_param;
struct device *dma_dev;
dma_addr_t dma_addr;
/* Bus interface info */
void *priv;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs;
#endif
};
#define rk2818_readl(dw, off) \
__raw_readl(dw->regs + off)
#define rk2818_writel(dw,off,val) \
__raw_writel(val, dw->regs + off)
#define rk2818_readw(dw, off) \
__raw_readw(dw->regs + off)
#define rk2818_writew(dw,off,val) \
__raw_writel(val, dw->regs + off)
static inline void spi_enable_chip(struct rk2818_spi *dws, int enable)
{
rk2818_writel(dws, SPIM_SPIENR, (enable ? 1 : 0));
}
static inline void spi_set_clk(struct rk2818_spi *dws, u16 div)
{
rk2818_writel(dws, SPIM_BAUDR, div);
}
static inline void spi_chip_sel(struct rk2818_spi *dws, u16 cs)
{
if (cs > 1)
return;
if (dws->cs_control){
if(cs == 1)
dws->cs_control(2);
else
dws->cs_control(1);
}
rk2818_writel(dws, SPIM_SER, 1 << cs);
}
/* Disable IRQ bits */
static inline void spi_mask_intr(struct rk2818_spi *dws, u32 mask)
{
u32 new_mask;
new_mask = rk2818_readl(dws, SPIM_IMR) & ~mask;
rk2818_writel(dws, SPIM_IMR, new_mask);
}
/* Enable IRQ bits */
static inline void spi_umask_intr(struct rk2818_spi *dws, u32 mask)
{
u32 new_mask;
new_mask = rk2818_readl(dws, SPIM_IMR) | mask;
rk2818_writel(dws, SPIM_IMR, new_mask);
}
/*
* Each SPI slave device to work with rk2818_api controller should
* has such a structure claiming its working mode (PIO/DMA etc),
* which can be save in the "controller_data" member of the
* struct spi_device
*/
struct rk2818_spi_chip {
u8 poll_mode; /* 0 for contoller polling mode */
u8 type; /* SPI/SSP/Micrwire */
u8 enable_dma;
void (*cs_control)(u32 command);
};
#endif /* __DRIVERS_SPIM_RK2818_HEADER_H */