mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
add spi driver
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* arch/arm/mach-rk2818/dma.h
|
||||
/*
|
||||
* arch/arm/mach-rk2818/include/mach/dma.h
|
||||
*
|
||||
* Copyright (C) 2010 ROCKCHIP, Inc.
|
||||
*
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
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
223
drivers/spi/rk2818_spim.h
Normal 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 */
|
||||
Reference in New Issue
Block a user