add iomux for spi

This commit is contained in:
cmc
2010-12-07 16:08:45 +08:00
parent 3d1cce5d1f
commit 2dc337889e
4 changed files with 77 additions and 27 deletions

View File

@@ -775,6 +775,18 @@ static void __init rk29_board_iomux_init(void)
rk29_mux_api_set(GPIO2B4_UART3CTSN_I2C3SDA_NAME, GPIO2L_UART3_CTS_N);
#endif
#endif
#ifdef CONFIG_SPIM0_RK29
rk29_mux_api_set(GPIO2C0_SPI0CLK_NAME, GPIO2H_SPI0_CLK);
rk29_mux_api_set(GPIO2C1_SPI0CSN0_NAME, GPIO2H_SPI0_CSN0);
rk29_mux_api_set(GPIO2C2_SPI0TXD_NAME, GPIO2H_SPI0_TXD);
rk29_mux_api_set(GPIO2C3_SPI0RXD_NAME, GPIO2H_SPI0_RXD);
#endif
#ifdef CONFIG_SPIM1_RK29
rk29_mux_api_set(GPIO2C4_SPI1CLK_NAME, GPIO2H_SPI1_CLK);
rk29_mux_api_set(GPIO2C5_SPI1CSN0_NAME, GPIO2H_SPI1_CSN0);
rk29_mux_api_set(GPIO2C6_SPI1TXD_NAME, GPIO2H_SPI1_TXD);
rk29_mux_api_set(GPIO2C7_SPI1RXD_NAME, GPIO2H_SPI1_RXD);
#endif
}
static struct platform_device *devices[] __initdata = {
@@ -870,13 +882,13 @@ struct spi_cs_gpio rk29xx_spi1_cs_gpios[SPI_CHIPSELECT_NUM] = {
.name = "spi1 cs1",
.cs_gpio = RK29_PIN1_PA3,
.cs_iomux_name = GPIO1A3_EMMCDETECTN_SPI1CS1_NAME,//if no iomux,set it NULL
.cs_iomux_mode = GPIO1L_SPI0_CSN1,
.cs_iomux_mode = GPIO1L_SPI1_CSN1,
}
};
static int spi_io_init(struct spi_cs_gpio *cs_gpios, int cs_num)
{
#if 0
#if 1
int i,j,ret;
//cs
@@ -901,7 +913,7 @@ static int spi_io_init(struct spi_cs_gpio *cs_gpios, int cs_num)
static int spi_io_deinit(struct spi_cs_gpio *cs_gpios, int cs_num)
{
#if 0
#if 1
int i;
if (cs_gpios) {

2
arch/arm/mach-rk29/include/mach/iomux.h Normal file → Executable file
View File

@@ -584,7 +584,7 @@
#define GPIO2D2_I2S0LRCKRX_MIITXERR_NAME "gpio2d2_i2s0lrckrx_miitxerr_name"
#define GPIO2D1_I2S0SCLK_MIICRS_NAME "gpio2d1_i2s0sclk_miicrs_name"
#define GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME "gpio2d0_i2s0clk_miirxclkin_name"
#define GPIO2C7_SPI1TXD_NAME "gpio2c7_spi1txd_name"
#define GPIO2C7_SPI1RXD_NAME "gpio2c7_spi1rxd_name"
#define GPIO2C6_SPI1TXD_NAME "gpio2c6_spi1txd_name"
#define GPIO2C5_SPI1CSN0_NAME "gpio2c5_spi1csn0_name"
#define GPIO2C4_SPI1CLK_NAME "gpio2c4_spi1clk_name"

2
arch/arm/mach-rk29/iomux.c Normal file → Executable file
View File

@@ -117,7 +117,7 @@ MUX_CFG(GPIO2D3_I2S0SDI_MIICOL_NAME, GPIO2H, 22, 2, 0, DEFAULT)
MUX_CFG(GPIO2D2_I2S0LRCKRX_MIITXERR_NAME, GPIO2H, 20, 2, 0, DEFAULT)
MUX_CFG(GPIO2D1_I2S0SCLK_MIICRS_NAME, GPIO2H, 18, 2, 0, DEFAULT)
MUX_CFG(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H, 16, 2, 0, DEFAULT)
MUX_CFG(GPIO2C7_SPI1TXD_NAME, GPIO2H, 14, 2, 0, DEFAULT)
MUX_CFG(GPIO2C7_SPI1RXD_NAME, GPIO2H, 14, 2, 0, DEFAULT)
MUX_CFG(GPIO2C6_SPI1TXD_NAME, GPIO2H, 12, 2, 0, DEFAULT)
MUX_CFG(GPIO2C5_SPI1CSN0_NAME, GPIO2H, 10, 2, 0, DEFAULT)
MUX_CFG(GPIO2C4_SPI1CLK_NAME, GPIO2H, 8, 2, 0, DEFAULT)

View File

@@ -24,7 +24,7 @@
#include <linux/dma-mapping.h>
#include <asm/dma.h>
#include "rk29xx_spim.h"
#include "rk29_spim.h"
#include <linux/spi/spi.h>
#include <mach/board.h>
@@ -88,6 +88,28 @@ struct chip_data {
#define RXBUSY (1<<2)
#define TXBUSY (1<<3)
static void spi_dump_regs(struct rk29xx_spi *dws) {
printk("MRST SPI0 registers:\n");
printk("=================================\n");
printk("CTRL0: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_CTRLR0));
printk("CTRL1: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_CTRLR1));
printk("SSIENR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_ENR));
printk("SER: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_SER));
printk("BAUDR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_BAUDR));
printk("TXFTLR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_TXFTLR));
printk("RXFTLR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_RXFTLR));
printk("TXFLR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_TXFLR));
printk("RXFLR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_RXFLR));
printk("SR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_SR));
printk("IMR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_IMR));
printk("ISR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_ISR));
printk("DMACR: \t\t0x%08x\n", rk29xx_readl(dws, SPIM_DMACR));
printk("DMATDLR: \t0x%08x\n", rk29xx_readl(dws, SPIM_DMATDLR));
printk("DMARDLR: \t0x%08x\n", rk29xx_readl(dws, SPIM_DMARDLR));
printk("=================================\n");
}
#ifdef CONFIG_DEBUG_FS
static int spi_show_regs_open(struct inode *inode, struct file *file)
{
@@ -220,9 +242,11 @@ static void flush(struct rk29xx_spi *dws)
wait_till_not_busy(dws);
}
#if 0
static void spi_cs_control(struct rk29xx_spi *dws, u32 cs, u8 flag)
{
#if 1
return;
#else
struct rk29xx_spi_platform_data *pdata = dws->master->dev.platform_data;
struct spi_cs_gpio *cs_gpios = pdata->chipselect_gpios;
@@ -230,8 +254,8 @@ static void spi_cs_control(struct rk29xx_spi *dws, u32 cs, u8 flag)
gpio_direction_output(cs_gpios[cs].cs_gpio, GPIO_HIGH);
else
gpio_direction_output(cs_gpios[cs].cs_gpio, GPIO_LOW);
#endif
}
#endif
static int null_writer(struct rk29xx_spi *dws)
{
@@ -261,6 +285,8 @@ static int null_reader(struct rk29xx_spi *dws)
static int u8_writer(struct rk29xx_spi *dws)
{
spi_dump_regs(dws);
DBG("tx: 0x%02x\n", *(u8 *)(dws->tx));
if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL)
|| (dws->tx == dws->tx_end))
return 0;
@@ -353,12 +379,14 @@ static void rk29_spi_dma_txcb(void *buf_id,
struct rk29xx_spi *dws = buf_id;
unsigned long flags;
DBG("func: %s, line: %d\n", __FUNCTION__, __LINE__);
spin_lock_irqsave(&dws->lock, flags);
if (res == RK29_RES_OK)
dws->state &= ~TXBUSY;
else
dev_err(&dws->master->dev, "DmaAbrtTx-%d \n", size);
dev_err(&dws->master->dev, "DmaAbrtTx-%d, size: %d \n", res, size);
/* If the other done */
if (!(dws->state & RXBUSY))
@@ -421,7 +449,7 @@ static int map_dma_buffers(struct rk29xx_spi *dws)
return -1;
}
if (rk29_dma_devconfig(dws->tx_dmach, RK29_DMASRC_MEM,
(unsigned long)dws->sfr_start + SPIM_TXDR)) {
dws->sfr_start + SPIM_TXDR)) {
dev_err(&dws->master->dev, "rk29_dma_devconfig fail\n");
return -1;
}
@@ -434,7 +462,7 @@ static int map_dma_buffers(struct rk29xx_spi *dws)
return -1;
}
if (rk29_dma_devconfig(dws->rx_dmach, RK29_DMASRC_HW,
(unsigned long)dws->sfr_start + SPIM_RXDR)) {
dws->sfr_start + SPIM_RXDR)) {
dev_err(&dws->master->dev, "rk29_dma_devconfig fail\n");
return -1;
}
@@ -464,7 +492,7 @@ static void giveback(struct rk29xx_spi *dws)
struct spi_transfer,
transfer_list);
if (!last_transfer->cs_change)
if (!last_transfer->cs_change && dws->cs_control)
dws->cs_control(dws,msg->spi->chip_select, MRST_SPI_DEASSERT);
msg->state = NULL;
@@ -501,7 +529,7 @@ static void transfer_complete(struct rk29xx_spi *dws)
static irqreturn_t interrupt_transfer(struct rk29xx_spi *dws)
{
u16 irq_status, irq_mask = 0x3f;
u16 irq_status, irq_mask = 0x1f;
u32 int_level = dws->fifo_len / 2;
u32 left;
@@ -563,7 +591,7 @@ static void spi_chip_sel(struct rk29xx_spi *dws, u16 cs)
return;
if (dws->cs_control){
dws->cs_control(dws, cs, 1);
dws->cs_control(dws, cs, MRST_SPI_ASSERT);
}
rk29xx_writel(dws, SPIM_SER, 1 << cs);
}
@@ -593,8 +621,7 @@ static void pump_transfers(unsigned long data)
chip = dws->cur_chip;
spi = message->spi;
if (unlikely(!chip->clk_div))
//chip->clk_div = clk_get_rate(dws->clock_spim) / chip->speed_hz;
chip->clk_div = 40000000 / chip->speed_hz;
chip->clk_div = clk_get_rate(dws->clock_spim) / chip->speed_hz;
if (message->state == ERROR_STATE) {
message->status = -EIO;
goto early_exit;
@@ -769,6 +796,7 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)
unsigned long val;
int ms;
int iRet;
int burst;
u8 bits = 0;
u8 spi_dfs = 0;
u8 cs_change = 0;
@@ -795,7 +823,7 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)
chip = dws->cur_chip;
spi = message->spi;
if (unlikely(!chip->clk_div))
chip->clk_div = 40000000 / chip->speed_hz;
chip->clk_div = clk_get_rate(dws->clock_spim) / chip->speed_hz;
if (message->state == ERROR_STATE) {
message->status = -EIO;
goto err_out;
@@ -936,10 +964,18 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)
}
INIT_COMPLETION(dws->xfer_completion);
spi_dump_regs(dws);
DBG("dws->tx_dmach: %d, dws->rx_dmach: %d, transfer->tx_dma: 0x%x\n", dws->tx_dmach, dws->rx_dmach, (unsigned int)transfer->tx_dma);
if (transfer->tx_buf != NULL) {
dws->state |= TXBUSY;
if (rk29_dma_config(dws->tx_dmach, 1)) {
if (transfer->len & 0x3) {
burst = 1;
}
else {
burst = 4;
}
if (rk29_dma_config(dws->tx_dmach, burst)) {
dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);
goto err_out;
}
@@ -979,10 +1015,10 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)
}
/* millisecs to xfer 'len' bytes @ 'cur_speed' */
ms = transfer->len * 8 * 1000 / dws->cur_chip->speed_hz;
ms = transfer->len * 8 / dws->cur_chip->speed_hz;
ms += 10;
val = msecs_to_jiffies(ms) + 500;
val = msecs_to_jiffies(ms) + 10;
if (!wait_for_completion_timeout(&dws->xfer_completion, val)) {
if (transfer->rx_buf != NULL && (dws->state & RXBUSY)) {
rk29_dma_ctrl(dws->rx_dmach, RK29_DMAOP_FLUSH);
@@ -1118,7 +1154,7 @@ static void msg_giveback(struct rk29xx_spi *dws)
struct spi_transfer,
transfer_list);
if (!last_transfer->cs_change)
if (!last_transfer->cs_change && dws->cs_control)
dws->cs_control(dws,msg->spi->chip_select,MRST_SPI_DEASSERT);
msg->state = NULL;
@@ -1511,7 +1547,7 @@ static int rk29xx_spi_setup(struct spi_device *spi)
if (!chip)
return -ENOMEM;
chip->cs_control = NULL;
chip->cs_control = spi_cs_control;
chip->enable_dma = 1; //0;
}
@@ -1570,6 +1606,7 @@ static int rk29xx_spi_setup(struct spi_device *spi)
| (chip->tmode << SPI_TMOD_OFFSET);
spi_set_ctldata(spi, chip);
DBG("RK29XX_SPI_SETUP: CRO: 0x%x ???????????????????\n", chip->cr0);
return 0;
}
@@ -1661,9 +1698,7 @@ static void spi_hw_init(struct rk29xx_spi *dws)
{
spi_enable_chip(dws, 0);
spi_mask_intr(dws, 0xff);
spi_enable_chip(dws, 1);
flush(dws);
/*
* Try to detect the FIFO depth if not set by interface driver,
* the depth could be from 2 to 32 from HW spec
@@ -1679,6 +1714,9 @@ static void spi_hw_init(struct rk29xx_spi *dws)
dws->fifo_len = (fifo == 31) ? 0 : fifo;
rk29xx_writew(dws, SPIM_TXFTLR, 0);
}
spi_enable_chip(dws, 1);
flush(dws);
}
/* cpufreq driver support */
@@ -1833,7 +1871,7 @@ static int __init rk29xx_spim_probe(struct platform_device *pdev)
dev_err(&master->dev, "rk29xx spim failed to init cpufreq support\n");
goto err_queue_alloc;
}
DBG(KERN_INFO "rk29xx_spim: driver initialized\n");
DBG(KERN_INFO "rk29xx_spim: driver initialized, fifo_len: %d\n", dws->fifo_len);
mrst_spi_debugfs_init(dws);
return 0;