FPGA ICE65L08XX Driver:SPI2UART SPI2GPIO SPI2I2C SPI2DPRAM

This commit is contained in:
root 2010-07-16 15:11:09 +08:00
parent 052ebff0c7
commit ae45c0b308
15 changed files with 4160 additions and 1 deletions

1
.gitignore vendored
View File

@ -29,6 +29,7 @@
*.lzma
*.patch
*.gcno
Untitled Project.*
#
# Top-level generic files

View File

@ -287,6 +287,21 @@ struct rk2818_i2c_platform_data default_i2c1_data = {
.cfg_gpio = rk2818_i2c1_cfg_gpio,
};
struct rk2818_i2c_platform_data default_i2c2_data = {
.bus_num = 2,
.flags = 0,
.slave_addr = 0xff,
.scl_rate = 400*1000,
};
struct rk2818_i2c_platform_data default_i2c3_data = {
.bus_num = 3,
.flags = 0,
.slave_addr = 0xff,
.scl_rate = 400*1000,
};
static struct i2c_board_info __initdata board_i2c0_devices[] = {
#if defined (CONFIG_RK1000_CONTROL)
{
@ -358,12 +373,27 @@ static struct i2c_board_info __initdata board_i2c1_devices[] = {
{},
};
static struct i2c_board_info __initdata board_i2c2_devices[] = {
};
static struct i2c_board_info __initdata board_i2c3_devices[] = {
};
/*****************************************************************************************
* SPI devices
*author: lhh
*****************************************************************************************/
static struct spi_board_info board_spi_devices[] = {
#if defined(CONFIG_SPI_FPGA)
{ /* fpga ice65l08xx */
.modalias = "spi_fpga",
.chip_select = 1,
.max_speed_hz = 8 * 1000 * 1000,
.bus_num = 0,
.mode = SPI_MODE_0,
},
#endif
#if defined(CONFIG_ENC28J60)
{ /* net chip */
.modalias = "enc28j60",
@ -424,6 +454,12 @@ static struct platform_device *devices[] __initdata = {
#ifdef CONFIG_I2C1_RK2818
&rk2818_device_i2c1,
#endif
#ifdef CONFIG_SPI_I2C
&rk2818_device_i2c2,
#endif
#ifdef CONFIG_SPI_I2C
&rk2818_device_i2c3,
#endif
#ifdef CONFIG_SDMMC0_RK2818
&rk2818_device_sdmmc0,
#endif
@ -506,6 +542,12 @@ static void __init machine_rk2818_board_init(void)
#ifdef CONFIG_I2C1_RK2818
i2c_register_board_info(default_i2c1_data.bus_num, board_i2c1_devices,
ARRAY_SIZE(board_i2c1_devices));
#endif
#ifdef CONFIG_SPI_I2C
i2c_register_board_info(default_i2c2_data.bus_num, board_i2c2_devices,
ARRAY_SIZE(board_i2c2_devices));
i2c_register_board_info(default_i2c3_data.bus_num, board_i2c3_devices,
ARRAY_SIZE(board_i2c3_devices));
#endif
platform_add_devices(devices, ARRAY_SIZE(devices));
spi_register_board_info(board_spi_devices, ARRAY_SIZE(board_spi_devices));

View File

@ -285,6 +285,21 @@ struct rk2818_i2c_platform_data default_i2c1_data = {
.cfg_gpio = rk2818_i2c1_cfg_gpio,
};
struct rk2818_i2c_platform_data default_i2c2_data = {
.bus_num = 2,
.flags = 0,
.slave_addr = 0xff,
.scl_rate = 400*1000,
};
struct rk2818_i2c_platform_data default_i2c3_data = {
.bus_num = 3,
.flags = 0,
.slave_addr = 0xff,
.scl_rate = 400*1000,
};
static struct i2c_board_info __initdata board_i2c0_devices[] = {
#if defined (CONFIG_RK1000_CONTROL)
{
@ -352,16 +367,39 @@ static struct i2c_board_info __initdata board_i2c1_devices[] = {
.addr = 0x79,
.flags = 0,
},
#endif
#if defined (CONFIG_GS_MMA7660)
{
.type = "gs_mma7660",
.addr = 0x4c,
.flags = 0,
.irq = RK2818_PIN_PE3,
},
#endif
{},
};
static struct i2c_board_info __initdata board_i2c2_devices[] = {
};
static struct i2c_board_info __initdata board_i2c3_devices[] = {
};
/*****************************************************************************************
* SPI devices
*author: lhh
*****************************************************************************************/
static struct spi_board_info board_spi_devices[] = {
#if defined(CONFIG_SPI_FPGA)
{ /* fpga ice65l08xx */
.modalias = "spi_fpga",
.chip_select = 1,
.max_speed_hz = 8 * 1000 * 1000,
.bus_num = 0,
.mode = SPI_MODE_0,
},
#endif
#if defined(CONFIG_ENC28J60)
{ /* net chip */
.modalias = "enc28j60",
@ -422,6 +460,12 @@ static struct platform_device *devices[] __initdata = {
#ifdef CONFIG_I2C1_RK2818
&rk2818_device_i2c1,
#endif
#ifdef CONFIG_SPI_I2C
&rk2818_device_i2c2,
#endif
#ifdef CONFIG_SPI_I2C
&rk2818_device_i2c3,
#endif
#ifdef CONFIG_SDMMC0_RK2818
&rk2818_device_sdmmc0,
#endif
@ -504,6 +548,12 @@ static void __init machine_rk2818_board_init(void)
#ifdef CONFIG_I2C1_RK2818
i2c_register_board_info(default_i2c1_data.bus_num, board_i2c1_devices,
ARRAY_SIZE(board_i2c1_devices));
#endif
#ifdef CONFIG_SPI_I2C
i2c_register_board_info(default_i2c2_data.bus_num, board_i2c2_devices,
ARRAY_SIZE(board_i2c2_devices));
i2c_register_board_info(default_i2c3_data.bus_num, board_i2c3_devices,
ARRAY_SIZE(board_i2c3_devices));
#endif
platform_add_devices(devices, ARRAY_SIZE(devices));
spi_register_board_info(board_spi_devices, ARRAY_SIZE(board_spi_devices));

View File

@ -169,7 +169,20 @@ struct platform_device rk2818_device_i2c1 = {
.platform_data = &default_i2c1_data,
},
};
struct platform_device rk2818_device_i2c2 = {
.name = "fpga_i2c",
.id = 2,
.dev = {
.platform_data = &default_i2c2_data,
},
};
struct platform_device rk2818_device_i2c3 = {
.name = "fpga_i2c",
.id = 3,
.dev = {
.platform_data = &default_i2c3_data,
},
};
struct platform_device rk2818_device_uart0 = {
.name = "rk2818_serial",
.id = 0,

View File

@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig"
source "drivers/spi/Kconfig"
source "drivers/fpga/Kconfig"
source "drivers/pps/Kconfig"
source "drivers/gpio/Kconfig"

View File

@ -45,6 +45,7 @@ obj-$(CONFIG_SCSI) += scsi/
obj-$(CONFIG_ATA) += ata/
obj-$(CONFIG_MTD) += mtd/
obj-$(CONFIG_SPI) += spi/
obj-$(CONFIG_SPI_FPGA) += fpga/
obj-y += net/
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_FUSION) += message/

86
drivers/fpga/Kconfig Normal file
View File

@ -0,0 +1,86 @@
#
# FPGA driver configuration
#
# NOTE: This FPGA(ice65l08xx) support spi2uart,spi2gpio,spi2i2c and spi2dpram.
#
menuconfig SPI_FPGA
bool "SPI FPGA(ice65l08xx) support"
#depends on SPI && SPIM_RK2818
help
This fpga(ice65l08xx) is used for spi2uart,spi2gpio,spi2i2c,spi2dpram.
if SPI_FPGA
config SPI_FPGA_INIT
tristate "spi fpga init support"
depends on SPI && SPIM_RK2818
help
fpga driver for spi init.
if SPI_FPGA_INIT
config SPI_FPGA_INIT_DEBUG
boolean "Debug support for spi fpga init drivers"
depends on DEBUG_KERNEL
help
Say "yes" to enable debug messaging in spi fpga init drivers.
endif
config SPI_UART
tristate "spi to uart support"
depends on SPI && SPIM_RK2818
help
fpga driver for spi to uart.
if SPI_UART
config SPI_UART_DEBUG
boolean "Debug support for spi to uart drivers"
depends on DEBUG_KERNEL
help
Say "yes" to enable debug messaging in spi to uart drivers.
endif
config SPI_GPIO
tristate "spi to gpio support"
depends on SPI && SPIM_RK2818
help
fpga driver for spi to gpio.
if SPI_GPIO
config SPI_GPIO_DEBUG
boolean "Debug support for spi to gpio drivers"
depends on DEBUG_KERNEL
help
Say "yes" to enable debug messaging in spi to gpio drivers.
endif
config SPI_I2C
tristate "spi to i2c support"
depends on SPI && SPIM_RK2818
help
fpga driver for spi to i2c.
if SPI_I2C
config SPI_I2C_DEBUG
boolean "Debug support for spi to i2c drivers"
depends on DEBUG_KERNEL
help
Say "yes" to enable debug messaging in spi to i2c drivers.
endif
config SPI_DPRAM
tristate "spi to dpram support"
depends on SPI && SPIM_RK2818
help
fpga driver for spi to dpram.
if SPI_DPRAM
config SPI_DPRAM_DEBUG
boolean "Debug support for spi to dpram drivers"
depends on DEBUG_KERNEL
help
Say "yes" to enable debug messaging in spi to dpram drivers.
endif
endif

10
drivers/fpga/Makefile Normal file
View File

@ -0,0 +1,10 @@
#
# Makefile for fpga(ice65l08xx) drivers.
#
# fpga drivers
obj-$(CONFIG_SPI_FPGA_INIT) += spi_fpga_init.o
obj-$(CONFIG_SPI_UART) += spi_uart.o
obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
obj-$(CONFIG_SPI_I2C) += spi_i2c.o
obj-$(CONFIG_SPI_DPRAM) += spi_dpram.o

654
drivers/fpga/spi_dpram.c Normal file
View File

@ -0,0 +1,654 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/serial_reg.h>
#include <linux/circ_buf.h>
#include <linux/gfp.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <mach/gpio.h>
#include <mach/iomux.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/miscdevice.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <mach/rk2818_iomap.h>
#include "spi_fpga.h"
#if defined(CONFIG_SPI_DPRAM_DEBUG)
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
#define SPI_DPRAM_TEST 0
/*****RAM0 for bp write and ap read*****/
#define SPI_DPRAM_BPWRITE_START 0
#define SPI_DPRAM_BPWRITE_END 0x0fff
#define SPI_DPRAM_BPWRITE_SIZE 0x1000 // 4K*16bits
/*****RAM1 for ap write and bp read*****/
#define SPI_DPRAM_APWRITE_START 0x1000
#define SPI_DPRAM_APWRITE_END 0x17ff
#define SPI_DPRAM_APWRITE_SIZE 0x0800 // 2K*16bits
/*****RAM2 for log of bp write and ap read*****/
#define SPI_DPRAM_LOG_BPWRITE_START 0x2000
#define SPI_DPRAM_LOG_BPWRITE_END 0x23ff
#define SPI_DPRAM_LOG_BPWRITE_SIZE 0x0400 // 1K*16bits
/*****RAM3 for log of ap write and bp read*****/
#define SPI_DPRAM_LOG_APWRITE_START 0x3000
#define SPI_DPRAM_LOG_APWRITE_END 0x33ff
#define SPI_DPRAM_LOG_APWRITE_SIZE 0x0400 // 1K*16bits
/*
#define BP_SEND_IN_PTR 0x3FEE
#define BP_SEND_OUT_PTR 0x3FF0
#define BP_READ_IN_PTR 0x3FF2
#define BP_READ_OUT_PTR 0x3FF4
#define BP_SEND_IN_PTR 0x3FF6
#define BP_SEND_OUT_PTR 0x3FF8
#define BP_READ_IN_PTR 0x3FFA
#define BP_READ_OUT_PTR 0x3FFC
#define BP_SEND_AP_Mailbox£º0x3ffe
#define AP_SEND_BP_Mailbox£º0x3fff
*/
#define SPI_DPRAM_PTR0_BPWRITE_APREAD 0X3fee
#define SPI_DPRAM_PTR0_APWRITE_BPREAD 0X3ff0
#define SPI_DPRAM_PTR1_BPWRITE_APREAD 0x3ff2
#define SPI_DPRAM_PTR1_APWRITE_BPREAD 0x3ff4
#define SPI_DPRAM_PTR2_BPWRITE_APREAD 0x3ff6
#define SPI_DPRAM_PTR2_APWRITE_BPREAD 0x3ff8
#define SPI_DPRAM_PTR3_BPWRITE_APREAD 0x3ffa
#define SPI_DPRAM_PTR3_APWRITE_BPREAD 0x3ffc
#define SPI_DPRAM_MAILBOX_BPWRITE 0x3ffe
#define SPI_DPRAM_MAILBOX_APWRITE 0x3fff
/*mailbox comminication's definition*/
#define MAILBOX_BPWRITE_DATA 0x01
#define MAILBOX_BPREAD_DATA 0x02
#define MAILBOX_APSEND_IRQ 0x03
#define MAILBOX_APSEND_ACK 0x04
#define TRUE 1
#define FALSE 0
static int spi_dpram_write_buf(struct spi_dpram *dpram, unsigned short int addr, unsigned char *buf, unsigned int len)
{
struct spi_fpga_port *port = container_of(dpram, struct spi_fpga_port, dpram);
unsigned char opt = ((ICE_SEL_DPRAM & ICE_SEL_DPRAM_NOMAL) | ICE_SEL_DPRAM_WRITE);
unsigned char *tx_buf = port->dpram.ptx;
int ret;
*(port->dpram.ptx) = opt;
*(port->dpram.ptx+1) = ((addr << 1) >> 8) & 0xff;
*(port->dpram.ptx+2) = ((addr << 1) & 0xff);
memcpy((port->dpram.ptx + 3), buf, len);
DBG("%s:tx_buf=0x%x,port->dpram.ptx=0x%x,opt=0x%x,addr=0x%x,len=%d\n",__FUNCTION__,(int)tx_buf, (int)port->dpram.ptx, opt, addr&0xffff, len);
ret = spi_write(port->spi, tx_buf, len+3);
if(ret)
printk("spi_write err!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n\n");
return 0;
}
static int spi_dpram_read_buf(struct spi_dpram *dpram, unsigned short int addr, unsigned char *buf, unsigned int len)
{
struct spi_fpga_port *port = container_of(dpram, struct spi_fpga_port, dpram);
unsigned char opt = ((ICE_SEL_DPRAM & ICE_SEL_DPRAM_NOMAL & ICE_SEL_DPRAM_READ));
unsigned char tx_buf[3];
unsigned char stat;
tx_buf[0] = opt;
tx_buf[1] = ((addr << 1) >> 8) & 0xff;
tx_buf[2] = ((addr << 1) & 0xff);
stat = spi_write_then_read(port->spi, tx_buf, sizeof(tx_buf), buf, len);
if(stat)
{
printk("%s:spi_write_then_read is error!,err=%d\n\n",__FUNCTION__,stat);
return -1;
}
DBG("%s:opt=0x%x,addr=0x%x,len=%d\n",__FUNCTION__, opt, addr&0xffff, len);
return 0;
}
int spi_dpram_write_ptr(struct spi_dpram *dpram, unsigned short int addr, unsigned int size)
{
int ret;
//int i;
struct spi_fpga_port *port = container_of(dpram, struct spi_fpga_port, dpram);
unsigned char opt = ((ICE_SEL_DPRAM & ICE_SEL_DPRAM_NOMAL) | ICE_SEL_DPRAM_WRITE);
unsigned char tx_buf[5];
tx_buf[0] = opt;
tx_buf[1] = ((addr << 1) >> 8) & 0xff;
tx_buf[2] = ((addr << 1) & 0xff);
tx_buf[3] = (size>>8);
tx_buf[4] = (size&0xff);
//for(i=0;i<5;i++)
//{
// printk("%s:tx_buf[%d]=0x%x\n",__FUNCTION__,i,tx_buf[i]);
//}
ret = spi_write(port->spi, tx_buf, sizeof(tx_buf));
if(ret)
{
printk("%s:spi_write err!\n",__FUNCTION__);
return -1;
}
return 0;
}
int spi_dpram_read_ptr(struct spi_dpram *dpram, unsigned short int addr)
{
int ret;
struct spi_fpga_port *port = container_of(dpram, struct spi_fpga_port, dpram);
unsigned char opt = ((ICE_SEL_DPRAM & ICE_SEL_DPRAM_NOMAL & ICE_SEL_DPRAM_READ));
unsigned char tx_buf[3],rx_buf[2];
tx_buf[0] = opt;
tx_buf[1] = ((addr << 1) >> 8) & 0xff;
tx_buf[2] = ((addr << 1) & 0xff);
ret = spi_write_then_read(port->spi, tx_buf, sizeof(tx_buf), rx_buf, sizeof(rx_buf));
if(ret)
{
printk("%s:spi_write_then_read err!\n",__FUNCTION__);
return -1;
}
ret = (rx_buf[0] << 8) | rx_buf[1];
return (ret&0xffff);
}
int spi_dpram_write_mailbox(struct spi_dpram *dpram, unsigned int mailbox)
{
int ret;
struct spi_fpga_port *port = container_of(dpram, struct spi_fpga_port, dpram);
unsigned char opt = ((ICE_SEL_DPRAM & ICE_SEL_DPRAM_NOMAL) | ICE_SEL_DPRAM_WRITE);
unsigned char tx_buf[5];
tx_buf[0] = opt;
tx_buf[1] = ((SPI_DPRAM_MAILBOX_APWRITE << 1) >> 8) & 0xff;
tx_buf[2] = ((SPI_DPRAM_MAILBOX_APWRITE << 1) & 0xff);
tx_buf[3] = mailbox>>8;
tx_buf[4] = mailbox&0xff;
ret = spi_write(port->spi, tx_buf, sizeof(tx_buf));
if(ret)
{
printk("%s:spi_write err!\n",__FUNCTION__);
return -1;
}
return 0;
}
int spi_dpram_read_mailbox(struct spi_dpram *dpram)
{
int ret;
struct spi_fpga_port *port = container_of(dpram, struct spi_fpga_port, dpram);
unsigned char opt = ((ICE_SEL_DPRAM & ICE_SEL_DPRAM_NOMAL & ICE_SEL_DPRAM_READ));
unsigned char tx_buf[3],rx_buf[2];
tx_buf[0] = opt;
tx_buf[1] = ((SPI_DPRAM_MAILBOX_BPWRITE << 1) >> 8) & 0xff;
tx_buf[2] = ((SPI_DPRAM_MAILBOX_BPWRITE << 1) & 0xff);
ret = spi_write_then_read(port->spi, tx_buf, sizeof(tx_buf), rx_buf, sizeof(rx_buf));
if(ret)
{
printk("%s:spi_write_then_read err!\n",__FUNCTION__);
return -1;
}
return ((rx_buf[0]<<8) | rx_buf[1]);
}
static void spi_dpram_handle_busy(struct spi_device *spi)
{
}
static void spi_dpram_busy_work_handler(struct work_struct *work)
{
struct spi_fpga_port *port =
container_of(work, struct spi_fpga_port, dpram.spi_dpram_busy_work);
spi_dpram_handle_busy(port->spi);
}
static irqreturn_t spi_dpram_busy_irq(int irq, void *dev_id)
{
struct spi_fpga_port *port = dev_id;
DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
/*
* Can't do anything in interrupt context because we need to
* block (spi_sync() is blocking) so fire of the interrupt
* handling workqueue.
* Remember that we access ICE65LXX registers through SPI bus
* via spi_sync() call.
*/
queue_work(port->dpram.spi_dpram_busy_workqueue, &port->dpram.spi_dpram_busy_work);
return IRQ_HANDLED;
}
#if SPI_DPRAM_TEST
#define DPRAM_TEST_LEN 512 //8bit
unsigned char buf_test_dpram[DPRAM_TEST_LEN];
void spi_dpram_work_handler(struct work_struct *work)
{
int i;
int ret;
struct spi_fpga_port *port =
container_of(work, struct spi_fpga_port, dpram.spi_dpram_work);
printk("*************test spi_dpram now***************\n");
for(i=0; i<(DPRAM_TEST_LEN>>1); i++)
{
buf_test_dpram[2*i] = (0xa000+i)>>8;
buf_test_dpram[2*i+1] = (0xa000+i)&0xff;
}
#if 0
//RAM0
for(i=0;i<(SPI_DPRAM_BPWRITE_SIZE/(DPRAM_TEST_LEN>>1));i++)
{
spi_dpram_read_buf(&port->dpram, SPI_DPRAM_BPWRITE_START+(i*DPRAM_TEST_LEN>>1), port->dpram.prx, DPRAM_TEST_LEN);
}
for(i=0;i<DPRAM_TEST_LEN;i++)
{
ret = (*(port->dpram.prx+2*i)<<8) | (*(port->dpram.prx+2*i+1));
if(ret != 0xa000+i)
printk("prx[%d]=0x%x ram[%d]=0x%x\n",i,ret&0xffff,i,0xa000+i);
}
#endif
#if 0
//RAM1
for(i=0;i<(SPI_DPRAM_APWRITE_SIZE/(DPRAM_TEST_LEN>>1));i++)
{
port->dpram.write_dpram(&port->dpram, ((DPRAM_TEST_LEN*i)>>1)+SPI_DPRAM_APWRITE_START, buf_test_dpram, sizeof(buf_test_dpram));
mdelay(1);
}
for(i=0;i<DPRAM_TEST_LEN;i++)
printk("buf_test_dpram[%d]=0x%x\n",i,buf_test_dpram[i]);
DBG("\n");
#endif
#if 0
//RAM2
for(i=0;i<(SPI_DPRAM_LOG_BPWRITE_SIZE/(DPRAM_TEST_LEN>>1));i++)
{
spi_dpram_read_buf(&port->dpram, SPI_DPRAM_LOG_BPWRITE_START+(i*DPRAM_TEST_LEN>>1), port->dpram.prx, DPRAM_TEST_LEN);
}
for(i=0;i<DPRAM_TEST_LEN;i++)
{
ret = (*(port->dpram.prx+2*i)<<8) | (*(port->dpram.prx+2*i+1));
if(ret != 0xc000+i)
printk("prx[%d]=0x%x ram[%d]=0x%x\n",i,ret&0xffff,i,0xc000+i);
}
#endif
#if 0
//RAM3
for(i=0;i<(SPI_DPRAM_LOG_APWRITE_SIZE/(DPRAM_TEST_LEN>>1));i++)
{
spi_dpram_write_buf(&port->dpram, ((DPRAM_TEST_LEN*i)>>1)+SPI_DPRAM_LOG_APWRITE_START, buf_test_dpram, sizeof(buf_test_dpram));
mdelay(1);
}
for(i=0;i<DPRAM_TEST_LEN;i++)
printk("buf_test_dpram[%d]=0x%x\n",i,buf_test_dpram[i]);
DBG("\n");
#endif
#if 1
port->dpram.write_ptr(&port->dpram, SPI_DPRAM_PTR0_APWRITE_BPREAD, SPI_DPRAM_PTR0_APWRITE_BPREAD);
port->dpram.write_ptr(&port->dpram, SPI_DPRAM_PTR1_APWRITE_BPREAD, SPI_DPRAM_PTR1_APWRITE_BPREAD);
port->dpram.write_ptr(&port->dpram, SPI_DPRAM_PTR2_APWRITE_BPREAD, SPI_DPRAM_PTR2_APWRITE_BPREAD);
port->dpram.write_ptr(&port->dpram, SPI_DPRAM_PTR3_APWRITE_BPREAD, SPI_DPRAM_PTR3_APWRITE_BPREAD);
port->dpram.write_mailbox(&port->dpram, SPI_DPRAM_MAILBOX_APWRITE);
ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR0_BPWRITE_APREAD);
if(ret != SPI_DPRAM_PTR0_BPWRITE_APREAD)
{
//ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR0_BPWRITE_APREAD);
//if(ret != SPI_DPRAM_PTR0_BPWRITE_APREAD)
printk("SPI_DPRAM_PTR0_BPWRITE_APREAD(0x%x)=0x%x\n",SPI_DPRAM_PTR0_BPWRITE_APREAD,ret);
}
ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR1_BPWRITE_APREAD);
if(ret != SPI_DPRAM_PTR1_BPWRITE_APREAD)
{
//ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR1_BPWRITE_APREAD);
//if(ret != SPI_DPRAM_PTR1_BPWRITE_APREAD)
printk("SPI_DPRAM_PTR1_BPWRITE_APREAD(0x%x)=0x%x\n",SPI_DPRAM_PTR1_BPWRITE_APREAD,ret);
}
ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR2_BPWRITE_APREAD);
if(ret != SPI_DPRAM_PTR2_BPWRITE_APREAD)
{
//ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR2_BPWRITE_APREAD);
//if(ret != SPI_DPRAM_PTR2_BPWRITE_APREAD)
printk("SPI_DPRAM_PTR2_BPWRITE_APREAD(0x%x)=0x%x\n",SPI_DPRAM_PTR2_BPWRITE_APREAD,ret);
}
ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR3_BPWRITE_APREAD);
if(ret != SPI_DPRAM_PTR3_BPWRITE_APREAD)
{
//ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR3_BPWRITE_APREAD);
//if(ret != SPI_DPRAM_PTR3_BPWRITE_APREAD)
printk("SPI_DPRAM_PTR3_BPWRITE_APREAD(0x%x)=0x%x\n",SPI_DPRAM_PTR3_BPWRITE_APREAD,ret);
}
mdelay(10);
ret = port->dpram.read_mailbox(&port->dpram);
if(ret != SPI_DPRAM_MAILBOX_BPWRITE)
{
//ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_MAILBOX_BPWRITE);
//if(ret != SPI_DPRAM_MAILBOX_BPWRITE)
printk("SPI_DPRAM_MAILBOX_BPWRITE(0x%x)=0x%x\n",SPI_DPRAM_MAILBOX_BPWRITE,ret);
}
#endif
}
static void spi_testdpram_timer(unsigned long data)
{
struct spi_fpga_port *port = (struct spi_fpga_port *)data;
port->dpram.dpram_timer.expires = jiffies + msecs_to_jiffies(1000);
add_timer(&port->dpram.dpram_timer);
//schedule_work(&port->gpio.spi_gpio_work);
queue_work(port->dpram.spi_dpram_workqueue, &port->dpram.spi_dpram_work);
}
#endif
int spi_dpram_handle_irq(struct spi_device *spi)
{
struct spi_fpga_port *port = spi_get_drvdata(spi);
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
#if 0
unsigned char mbox = port->dpram.read_mailbox(&port->dpram);
unsigned int len;
switch(mbox)
{
case MAILBOX_BPWRITE_DATA:
len = port->dpram.read_ptr(&port->dpram,SPI_DPRAM_PTR0_BPWRITE_APREAD);
port->dpram.read_dpram(&port->dpram, SPI_DPRAM_BPWRITE_START, port->dpram.prx, len);
port->dpram.rec_len += len;
break;
case MAILBOX_BPREAD_DATA:
port->dpram.apwrite_en = TRUE;
break;
default:
break;
}
#endif
return 0;
}
static int dpr_open(struct inode *inode, struct file *filp)
{
struct spi_fpga_port *port = pFpgaPort;
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
filp->private_data = port;
port->dpram.rec_len = 0;
port->dpram.send_len = 0;
port->dpram.apwrite_en = TRUE;
return nonseekable_open(inode, filp);
}
static int dpr_close(struct inode *inode, struct file *filp)
{
struct spi_fpga_port *port = pFpgaPort;
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
filp->private_data = NULL;
return 0;
}
static ssize_t dpr_read (struct file *filp, char __user *buffer, size_t count, loff_t *ppos)
{
//int ret;
struct spi_fpga_port *port = filp->private_data;
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
while(port->dpram.rec_len == 0)
{
if( filp->f_flags&O_NONBLOCK )
return -EAGAIN;
if(wait_event_interruptible(port->dpram.recq, (port->dpram.rec_len != 0)))
{
printk("%s:NO data in dpram!\n",__FUNCTION__);
return -ERESTARTSYS;
}
}
/*read data from buffer*/
if(copy_to_user((char*)buffer, (char *)port->dpram.prx, port->dpram.rec_len))
{
printk("%s:copy_to_user err!\n",__FUNCTION__);
return -EFAULT;
}
count = port->dpram.rec_len;
port->dpram.rec_len = 0;
return count;
}
static ssize_t dpr_write (struct file *filp, const char __user *buffer, size_t count, loff_t *ppos)
{
struct spi_fpga_port *port = filp->private_data;
//int ret;
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
while(port->dpram.apwrite_en == FALSE)
{
if(filp->f_flags & O_NONBLOCK)
return -EAGAIN;
if(wait_event_interruptible(port->dpram.sendq, (port->dpram.apwrite_en == TRUE)))
return -ERESTARTSYS;
}
if(count > port->dpram.max_send_len)
{
count = port->dpram.max_send_len;
printk("%s:count is large than max_send_len(%d),and only %d's bytes is valid!\n",__FUNCTION__,count,count);
}
if(copy_from_user((char *)port->dpram.ptx,buffer,count))
{
printk("%s:copy_from_user err!\n",__FUNCTION__);
return -EFAULT;
}
port->dpram.write_dpram(&port->dpram, SPI_DPRAM_APWRITE_START, port->dpram.ptx, count);
port->dpram.apwrite_en = FALSE; //clear apwrite_en after wirte data to dpram
port->dpram.write_mailbox(&port->dpram, MAILBOX_APSEND_IRQ); //send irq to bp after ap write data to dpram
return count;
}
unsigned int dpr_poll(struct file *filp, struct poll_table_struct * wait)
{
unsigned int mask = 0;
struct spi_fpga_port *port = filp->private_data;
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
return mask;
}
static struct file_operations dpr_fops={
.owner= THIS_MODULE,
.open= dpr_open,
.release= dpr_close,
.read= dpr_read,
.write= dpr_write,
.poll = dpr_poll,
};
int spi_dpram_register(struct spi_fpga_port *port)
{
char b[28];
int ret;
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
port->dpram.prx = (char *)kzalloc(sizeof(char)*((SPI_DPRAM_BPWRITE_SIZE<<1)+6), GFP_KERNEL);
if(port->dpram.prx == NULL)
{
printk("port->dpram.prx kzalloc err!!!\n");
return -ENOMEM;
}
port->dpram.ptx = (char *)kzalloc(sizeof(char)*((SPI_DPRAM_APWRITE_SIZE<<1)+6), GFP_KERNEL);
if(port->dpram.ptx == NULL)
{
printk("port->dpram.ptx kzalloc err!!!\n");
return -ENOMEM;
}
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
sprintf(b, "spi_dpram_busy_workqueue");
port->dpram.spi_dpram_busy_workqueue = create_freezeable_workqueue(b);
if (!port->dpram.spi_dpram_busy_workqueue) {
printk("cannot create workqueue\n");
return -EBUSY;
}
INIT_WORK(&port->dpram.spi_dpram_busy_work, spi_dpram_busy_work_handler);
#if SPI_DPRAM_TEST
sprintf(b, "spi_dpram_workqueue");
port->dpram.spi_dpram_workqueue = create_freezeable_workqueue(b);
if (!port->dpram.spi_dpram_workqueue) {
printk("cannot create workqueue\n");
return -EBUSY;
}
INIT_WORK(&port->dpram.spi_dpram_work, spi_dpram_work_handler);
setup_timer(&port->dpram.dpram_timer, spi_testdpram_timer, (unsigned long)port);
port->dpram.dpram_timer.expires = jiffies+2000;//>1000ms
add_timer(&port->dpram.dpram_timer);
#endif
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
//init the struct spi_dpram
init_waitqueue_head(&port->dpram.recq);
init_waitqueue_head(&port->dpram.sendq);
port->dpram.rec_len = 0;
port->dpram.send_len = 0;
port->dpram.apwrite_en = TRUE;
port->dpram.max_rec_len = SPI_DPRAM_BPWRITE_SIZE;
port->dpram.max_send_len = SPI_DPRAM_APWRITE_SIZE;
port->dpram.miscdev.minor = MISC_DYNAMIC_MINOR;
port->dpram.miscdev.name = "spi_dpram";//spi_fpga
port->dpram.miscdev.fops = &dpr_fops;
ret = misc_register(&port->dpram.miscdev);
if(ret)
{
printk("misc_register err!!!\n");
goto err0;
}
port->dpram.write_dpram = spi_dpram_write_buf;
port->dpram.read_dpram = spi_dpram_read_buf;
port->dpram.write_ptr = spi_dpram_write_ptr;
port->dpram.read_ptr = spi_dpram_read_ptr;
port->dpram.write_mailbox = spi_dpram_write_mailbox;
port->dpram.read_mailbox = spi_dpram_read_mailbox;
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
ret = gpio_request(SPI_DPRAM_BUSY_PIN, NULL);
if (ret) {
printk("%s:failed to request fpga busy gpio\n",__FUNCTION__);
goto err1;
}
gpio_pull_updown(SPI_DPRAM_BUSY_PIN,GPIOPullUp);
ret = request_irq(gpio_to_irq(SPI_DPRAM_BUSY_PIN),spi_dpram_busy_irq,IRQF_TRIGGER_RISING,NULL,port);
if(ret)
{
printk("unable to request fpga busy_gpio irq\n");
goto err2;
}
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
return 0;
err2:
free_irq(gpio_to_irq(SPI_DPRAM_BUSY_PIN),NULL);
err1:
gpio_free(SPI_DPRAM_BUSY_PIN);
err0:
kfree(port->dpram.prx);
kfree(port->dpram.ptx);
return ret;
}
int spi_dpram_unregister(struct spi_fpga_port *port)
{
return 0;
}

495
drivers/fpga/spi_fpga.h Normal file
View File

@ -0,0 +1,495 @@
/*
defines of FPGA chip ICE65L08's register
*/
#ifndef SPI_UART_H
#define SPI_UART_H
#define SPI_FPGA_INT_PIN RK2818_PIN_PA4
#define SPI_DPRAM_BUSY_PIN RK2818_PIN_PA2
#define SPI_FPGA_STANDBY_PIN RK2818_PIN_PH7
struct uart_icount {
__u32 cts;
__u32 dsr;
__u32 rng;
__u32 dcd;
__u32 rx;
__u32 tx;
__u32 frame;
__u32 overrun;
__u32 parity;
__u32 brk;
};
struct spi_uart
{
struct workqueue_struct *spi_uart_workqueue;
struct work_struct spi_uart_work;
struct timer_list uart_timer;
struct tty_struct *tty;
struct kref kref;
struct mutex open_lock;
struct task_struct *in_spi_uart_irq;
struct circ_buf xmit;
struct uart_icount icount;
spinlock_t write_lock;
spinlock_t irq_lock;
unsigned int index;
unsigned int opened;
unsigned int regs_offset;
unsigned int uartclk;
unsigned int mctrl;
unsigned int read_status_mask;
unsigned int ignore_status_mask;
unsigned char x_char;
unsigned char ier;
unsigned char lcr;
};
struct spi_gpio
{
struct workqueue_struct *spi_gpio_workqueue;
struct work_struct spi_gpio_work;
struct timer_list gpio_timer;
};
struct spi_i2c
{
struct workqueue_struct *spi_i2c_workqueue;
struct work_struct spi_i2c_work;
struct timer_list i2c_timer;
struct i2c_adapter *adapter;
struct i2c_client *client;
spinlock_t i2c_lock ;
unsigned char interrupt;
unsigned char i2c_data_width[2];
unsigned int speed[2];
};
struct spi_dpram
{
struct workqueue_struct *spi_dpram_workqueue;
struct work_struct spi_dpram_work;
struct workqueue_struct *spi_dpram_busy_workqueue;
struct work_struct spi_dpram_busy_work;
struct timer_list dpram_timer;
unsigned char *prx;
unsigned char *ptx;
unsigned int rec_len;
unsigned int send_len;
unsigned int max_rec_len;
unsigned int max_send_len;
volatile int apwrite_en;
unsigned short int dpram_addr;
struct semaphore rec_sem;
struct semaphore send_sem;
wait_queue_head_t recq, sendq;
struct miscdevice miscdev;
int (*write_dpram)(struct spi_dpram *, unsigned short int addr, unsigned char *buf, unsigned int len);
int (*read_dpram)(struct spi_dpram *, unsigned short int addr, unsigned char *buf, unsigned int len);
int (*write_ptr)(struct spi_dpram *, unsigned short int addr, unsigned int size);
int (*read_ptr)(struct spi_dpram *, unsigned short int addr);
int (*write_mailbox)(struct spi_dpram *, unsigned int mailbox);
int (*read_mailbox)(struct spi_dpram *);
};
struct spi_fpga_port {
const char *name;
struct spi_device *spi;
struct mutex spi_lock;
struct workqueue_struct *fpga_irq_workqueue;
struct work_struct fpga_irq_work;
struct timer_list fpga_timer;
/*spi2uart*/
#ifdef CONFIG_SPI_UART
struct spi_uart uart;
#endif
/*spi2gpio*/
#ifdef CONFIG_SPI_GPIO
struct spi_gpio gpio;
#endif
/*spi2i2c*/
#ifdef CONFIG_SPI_I2C
struct spi_i2c i2c;
#endif
/*spi2dpram*/
#ifdef CONFIG_SPI_DPRAM
struct spi_dpram dpram;
#endif
};
#define ICE_CC72 0
#define ICE_CC196 1
#define FPGA_TYPE ICE_CC196
#define SEL_UART 0
#define SEL_GPIO 1
#define SEL_I2C 2
#define SEL_DPRAM 3
/* CMD */
#define ICE_SEL_UART (SEL_UART<<6)
#define ICE_SEL_GPIO (SEL_GPIO<<6)
#define ICE_SEL_I2C (SEL_I2C<<6)
#define ICE_SEL_DPRAM (SEL_DPRAM<<6)
#define ICE_SEL_WRITE (~(1<<5))
#define ICE_SEL_READ (1<<5)
#define ICE_SEL_UART_CH(ch) ((ch&0x03)<<3)
#define ICE_SEL_READ_INT_TYPE (3<<3)
/*read int type*/
#define ICE_INT_TYPE_UART0 (~(1<<0))
#define ICE_INT_TYPE_UART1 (~(1<<1))
#define ICE_INT_TYPE_UART2 (~(1<<2))
#define ICE_INT_TYPE_I2C2 (~(1<<3))
#define ICE_INT_TYPE_I2C3 (~(1<<4))
#define ICE_INT_TYPE_GPIO (~(1<<5))
#define ICE_INT_TYPE_DPRAM (~(1<<6))
#define ICE_INT_I2C_ACK (~(1<<0))
#define ICE_INT_I2C_READ (~(1<<1))
#define ICE_INT_I2C_WRITE (~(1<<2))
/*spi to uart*/
#define ICE_RXFIFO_FULL (1<<8)
#define ICE_RXFIFO_NOT_FULL (~(1<<8))
#define ICE_RXFIFO_EMPTY (1<<9)
#define ICE_RXFIFO_NOT_EMPTY (~(1<<9))
#define ICE_TXFIFO_FULL (1<<10)
#define ICE_TXFIFO_NOT_FULL (~(1<<10))
#define ICE_TXFIFO_EMPTY (1<<11)
#define ICE_TXFIFO_NOT_EMPTY (~(1<<11))
/*spi to gpio*/
#define ICE_SEL_GPIO0 (0X00<<3) //INT/GPIO0
#define ICE_SEL_GPIO1 (0X02<<2) //GPIO1
#define ICE_SEL_GPIO2 (0X03<<2)
#define ICE_SEL_GPIO3 (0X04<<2)
#define ICE_SEL_GPIO4 (0X05<<2)
#define ICE_SEL_GPIO5 (0X06<<2)
#define ICE_SEL_GPIO0_TYPE (0X00)
#define ICE_SEL_GPIO0_DIR (0X01)
#define ICE_SEL_GPIO0_DATA (0X02)
#define ICE_SEL_GPIO0_INT_EN (0X03)
#define ICE_SEL_GPIO0_INT_TRI (0X04)
#define ICE_SEL_GPIO0_INT_STATE (0X05)
#define ICE_SEL_GPIO_DIR (0X01)
#define ICE_SEL_GPIO_DATA (0X02)
/*spi to i2c*/
typedef enum I2C_ch
{
I2C_CH0,
I2C_CH1,
I2C_CH2,
I2C_CH3
}eI2C_ch_t;
#define ICE_SEL_I2C_START (0<<0)
#define ICE_SEL_I2C_STOP (1<<0)
#define ICE_SEL_I2C_RESTART (2<<0)
#define ICE_SEL_I2C_TRANS (3<<0)
#define ICE_SEL_I2C_SMASK (~(3<<0))
#define ICE_SEL_I2C_CH2 (0<<2)
#define ICE_SEL_I2C_CH3 (1<<2)
#define ICE_SEL_I2C_DEFMODE (0<<3)
#define ICE_SEL_I2C_FIFO (1<<3)
#define ICE_SEL_I2C_SPEED (2<<3)
#define ICE_SEL_I2C_INT (3<<3)
#define ICE_SEL_I2C_MMASK (~(3<<3))
#define ICE_I2C_SLAVE_WRITE (0<<0)
#define ICE_I2C_SLAVE_READ (1<<0)
#define ICE_SEL_I2C_W8BIT (0<<2)
#define ICE_SEL_I2C_W16BIT (1<<2)
#define ICE_SEL_I2C_DWIDTH (2<<2)
#define ICE_I2C_AD_ACK (~(1<<0))
#define ICE_I2C_WRITE_ACK (~(1<<1))
#define ICE_I2C_READ_ACK (~(1<<2))
#define ICE_SEL_I2C_CH2_8BIT (0<<2)
#define ICE_SEL_I2C_CH2_16BIT (1<<2)
#define ICE_SEL_I2C_CH2_MIX (2<<2)
#define ICE_SEL_I2C_CH3_8BIT (4<<2)
#define ICE_SEL_I2C_CH3_16BIT (5<<2)
#define ICE_SEL_I2C_CH3_MIX (6<<2)
#define ICE_SEL_I2C_RD_A (7<<2)
#define ICE_SEL_I2C_MASK (7<<2)
#define ICE_SEL_I2C_ACK3 (1<<1)
#define ICE_SEL_I2C_ACK2 (0<<1)
#define INT_I2C_WRITE_ACK (2)
#define INT_I2C_WRITE_NACK (3)
#define INT_I2C_READ_ACK (4)
#define INT_I2C_READ_NACK (5)
#define INT_I2C_WRITE_MASK (~(1<<1))
#define INT_I2C_READ_MASK (~(1<<2))
#define ICE_SET_10K_I2C_SPEED (0x01)
#define ICE_SET_100K_I2C_SPEED (0x02)
#define ICE_SET_200K_I2C_SPEED (0x04)
#define ICE_SET_300K_I2C_SPEED (0x08)
#define ICE_SET_400K_I2C_SPEED (0x10)
/*spi to dpram*/
#define ICE_SEL_DPRAM_NOMAL (~(1<<5))
#define ICE_SEL_DPRAM_SEM (1<<5)
#define ICE_SEL_DPRAM_READ (~(1<<4))
#define ICE_SEL_DPRAM_WRITE (1<<4)
#define ICE_SEL_DPRAM_BL1 (0)
#define ICE_SEL_DPRAM_BL32 (1)
#define ICE_SEL_DPRAM_BL64 (2)
#define ICE_SEL_DPRAM_BL128 (3)
#define ICE_SEL_DPRAM_FULL (4)
#define ICE_SEL_SEM_WRITE (0x7F)
#define ICE_SEL_SEM_READ (0xBF)
#define ICE_SEL_SEM_WRRD (0x3F)
typedef void (*pSpiFunc)(void); //定义函数指针, 用于调用绝对地址
typedef void (*pSpiFuncIntr)(int,void *);
typedef struct
{
pSpiFuncIntr gpio_vector;
void *gpio_devid;
}SPI_GPIO_PDATA;
typedef enum eSpiGpioTypeSel
{
SPI_GPIO0_IS_GPIO = 0,
SPI_GPIO0_IS_INT,
}eSpiGpioTypeSel_t;
typedef enum eSpiGpioPinInt
{
SPI_GPIO_INT_DISABLE = 0,
SPI_GPIO_INT_ENABLE,
}eSpiGpioPinInt_t;
typedef enum eSpiGpioIntType
{
SPI_GPIO_EDGE_FALLING = 0,
SPI_GPIO_EDGE_RISING,
}eSpiGpioIntType_t;
typedef enum eSpiGpioPinDirection
{
SPI_GPIO_IN = 0,
SPI_GPIO_OUT,
}eSpiGpioPinDirection_t;
typedef enum eSpiGpioPinLevel
{
SPI_GPIO_LOW = 0,
SPI_GPIO_HIGH,
SPI_GPIO_LEVEL_ERR,
}eSpiGpioPinLevel_t;
#if (FPGA_TYPE == ICE_CC72)
typedef enum eSpiGpioPinNum
{
SPI_GPIO_P0_00 = 0, //GPIO0[0]
SPI_GPIO_P0_01,
SPI_GPIO_P0_02,
SPI_GPIO_P0_03,
SPI_GPIO_P0_04,
SPI_GPIO_P0_05,
SPI_GPIO_P2_00,
SPI_GPIO_P2_01,
SPI_GPIO_P2_02,
SPI_GPIO_P2_03,
SPI_GPIO_P2_04,
SPI_GPIO_P2_05,
SPI_GPIO_P2_06,
SPI_GPIO_P2_07,
SPI_GPIO_P2_08,
SPI_GPIO_P2_09 = 15, //GPIO0[15],the last interrupt/gpio pin
SPI_GPIO_P3_00 = 16, //GPIO1[0]
SPI_GPIO_P3_01,
SPI_GPIO_P3_02,
SPI_GPIO_P3_03,
SPI_GPIO_P3_04,
SPI_GPIO_P3_05,
SPI_GPIO_P3_06,
SPI_GPIO_P3_07,
SPI_GPIO_P3_08,
SPI_GPIO_P3_09,
SPI_GPIO_P0_06 = 26,
SPI_GPIO_I2C3_SCL,
SPI_GPIO_I2C3_SDA,
SPI_GPIO_I2C4_SCL,
SPI_GPIO_I2C4_SDA,
}eSpiGpioPinNum_t;
#elif (FPGA_TYPE == ICE_CC196)
typedef enum eSpiGpioPinNum
{
//GPIO0/INT
SPI_GPIO_P6_00 = 0, //HS_DET input
SPI_GPIO_P6_01,
SPI_GPIO_P6_02,
SPI_GPIO_P6_03,
SPI_GPIO_P6_04, //CM3605_POUT_L_INT input
SPI_GPIO_P6_05,
SPI_GPIO_P6_06, //CHG_OK input
SPI_GPIO_P6_07, //HP_HOOK input
SPI_GPIO_P6_08,
SPI_GPIO_P6_09,
SPI_GPIO_P6_10, //DEFSEL input
SPI_GPIO_P6_11, //FLASH_WP_INT input
SPI_GPIO_P6_12, //LOW_BATT_INT input
SPI_GPIO_P6_13, //DC_DET input
SPI_GPIO_P3_08,
SPI_GPIO_P3_09 = 15,
//GPIO1
SPI_GPIO_P1_00 = 16, //LCD_ON output
SPI_GPIO_P1_01, //LCD_PWR_CTRL output
SPI_GPIO_P1_02, //SD_POW_ON output
SPI_GPIO_P1_03, //WL_RST_N/WIFI_EN output
SPI_GPIO_P1_04, //HARDO,input
SPI_GPIO_P1_05, //SENSOR_PWDN output
SPI_GPIO_P1_06, //BT_PWR_EN output
SPI_GPIO_P1_07, //BT_RST output
SPI_GPIO_P1_08, //BT_WAKE_B output
SPI_GPIO_P1_09, //LCD_DISP_ON output
SPI_GPIO_P1_10, //WM_PWR_EN output
SPI_GPIO_P1_11, //HARD1,input
SPI_GPIO_P1_12, //VIB_MOTO output
SPI_GPIO_P1_13, //KEYLED_EN output
SPI_GPIO_P1_14, //CAM_RST output
SPI_GPIO_P1_15 = 31, //WL_WAKE_B output
//GPIO2
SPI_GPIO_P2_00 = 32, //Y+YD input
SPI_GPIO_P2_01, //Y-YU input
SPI_GPIO_P2_02, //AP_TD_UNDIFED input
SPI_GPIO_P2_03, //AP_PW_EN_TD output
SPI_GPIO_P2_04, //AP_RESET_TD output
SPI_GPIO_P2_05, //AP_SHUTDOWN_TD_PMU output
SPI_GPIO_P2_06, //AP_RESET_CMMB output
SPI_GPIO_P2_07, //AP_CHECK_TD_STATUS input
SPI_GPIO_P2_08, //CHARGE_CURRENT_SEL output
SPI_GPIO_P2_09, //AP_PWD_CMMB output
SPI_GPIO_P2_10, //X-XL input
SPI_GPIO_P2_11, //X+XR input
SPI_GPIO_P2_12, //LCD_RESET output
SPI_GPIO_P2_13, //USB_PWR_EN output
SPI_GPIO_P2_14, //WL_HOST_WAKE_B output
SPI_GPIO_P2_15 = 47, //TOUCH_SCREEN_RST output
//GPIO3
SPI_GPIO_P0_00 = 48, //
SPI_GPIO_P0_01,
SPI_GPIO_P0_02,
SPI_GPIO_P0_03,
SPI_GPIO_P0_04,
SPI_GPIO_P0_05,
SPI_GPIO_P0_06,
SPI_GPIO_P0_07,
SPI_GPIO_P0_08,
SPI_GPIO_P0_09, //FPGA小板该引脚未引出 C5
SPI_GPIO_P0_10,
SPI_GPIO_P0_11,
SPI_GPIO_P0_12,
SPI_GPIO_P0_13,
SPI_GPIO_P0_14,
SPI_GPIO_P0_15 = 63,
//GPIO4
SPI_GPIO_P4_00 = 64,
SPI_GPIO_P4_01,
SPI_GPIO_P4_02,
SPI_GPIO_P4_03,
SPI_GPIO_P4_04,
SPI_GPIO_P4_05,
SPI_GPIO_P4_06, //CHARGER_INT_END input
SPI_GPIO_P4_07, //CM3605_PWD output
SPI_GPIO_P3_00,
SPI_GPIO_P3_01,
SPI_GPIO_P3_02,
SPI_GPIO_P3_03,
SPI_GPIO_P3_04,
SPI_GPIO_P3_05,
SPI_GPIO_P3_06,
SPI_GPIO_P3_07 = 79,
//GPIO5
SPI_GPIO_P4_08 = 80, //CM3605_PS_SHUTDOWN
SPI_GPIO_P0_TXD2, //temp
}eSpiGpioPinNum_t;
#endif
typedef enum eSpiGpioPinIntIsr
{
SPI_GPIO_IS_INT = 0,
SPI_GPIO_NO_INT,
}eSpiGpioPinIntIsr_t;
extern struct spi_fpga_port *pFpgaPort;
extern unsigned int spi_in(struct spi_fpga_port *port, int reg, int type);
extern void spi_out(struct spi_fpga_port *port, int reg, int value, int type);
#if defined(CONFIG_SPI_UART)
extern void spi_uart_handle_irq(struct spi_device *spi);
extern int spi_uart_register(struct spi_fpga_port *port);
extern int spi_uart_unregister(struct spi_fpga_port *port);
#endif
#if defined(CONFIG_SPI_GPIO)
extern int spi_gpio_int_sel(eSpiGpioPinNum_t PinNum,eSpiGpioTypeSel_t type);
extern int spi_gpio_set_pindirection(eSpiGpioPinNum_t PinNum,eSpiGpioPinDirection_t direction);
extern int spi_gpio_set_pinlevel(eSpiGpioPinNum_t PinNum, eSpiGpioPinLevel_t PinLevel);
extern eSpiGpioPinLevel_t spi_gpio_get_pinlevel(eSpiGpioPinNum_t PinNum);
extern int spi_gpio_enable_int(eSpiGpioPinNum_t PinNum);
extern int spi_gpio_disable_int(eSpiGpioPinNum_t PinNum);
extern int spi_gpio_set_int_trigger(eSpiGpioPinNum_t PinNum,eSpiGpioIntType_t IntType);
extern int spi_gpio_read_iir(void);
extern int spi_request_gpio_irq(eSpiGpioPinNum_t PinNum, pSpiFunc Routine, eSpiGpioIntType_t IntType,void *dev_id);
extern int spi_free_gpio_irq(eSpiGpioPinNum_t PinNum);
extern int spi_gpio_handle_irq(struct spi_device *spi);
extern int spi_gpio_init(void);
extern int spi_gpio_register(struct spi_fpga_port *port);
extern int spi_gpio_unregister(struct spi_fpga_port *port);
#endif
#if defined(CONFIG_SPI_I2C)
extern int spi_i2c_handle_irq(struct spi_fpga_port *port,unsigned char channel);
extern int spi_i2c_register(struct spi_fpga_port *port);
extern int spi_i2c_unregister(struct spi_fpga_port *port);
#endif
#if defined(CONFIG_SPI_DPRAM)
extern int spi_dpram_handle_irq(struct spi_device *spi);
extern int spi_dpram_register(struct spi_fpga_port *port);
extern int spi_dpram_unregister(struct spi_fpga_port *port);
#endif
#endif

View File

@ -0,0 +1,434 @@
/*
* linux/drivers/fpga/spi_fpga_init.c - spi fpga init driver
*
* Copyright (C) 2010 ROCKCHIP, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*/
/*
* Note: fpga ice65l08xx is used for spi2uart,spi2gpio,spi2i2c and spi2dpram.
* this driver is the entry of all modules's drivers,should be run at first.
* the struct for fpga is build in the driver,and it is important.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/serial_reg.h>
#include <linux/circ_buf.h>
#include <linux/gfp.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <mach/gpio.h>
#include <mach/iomux.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/miscdevice.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <mach/rk2818_iomap.h>
#include "spi_fpga.h"
#if defined(CONFIG_SPI_FPGA_INIT_DEBUG)
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
struct spi_fpga_port *pFpgaPort;
/*------------------------spi¶ÁдµÄ»ù±¾º¯Êý-----------------------*/
unsigned int spi_in(struct spi_fpga_port *port, int reg, int type)
{
unsigned char index = 0;
unsigned char tx_buf[1], rx_buf[2], n_rx=2, stat=0;
unsigned int result=0;
//printk("index1=%d\n",index);
switch(type)
{
#if defined(CONFIG_SPI_UART)
case SEL_UART:
index = port->uart.index;
reg = (((reg) | ICE_SEL_UART) | ICE_SEL_READ | ICE_SEL_UART_CH(index));
tx_buf[0] = reg & 0xff;
rx_buf[0] = 0;
rx_buf[1] = 0;
stat = spi_write_then_read(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf), rx_buf, n_rx);
result = rx_buf[1];
DBG("%s,SEL_UART reg=0x%x,result=0x%x\n",__FUNCTION__,reg&0xff,result&0xff);
break;
#endif
#if defined(CONFIG_SPI_GPIO)
case SEL_GPIO:
reg = (((reg) | ICE_SEL_GPIO) | ICE_SEL_READ );
tx_buf[0] = reg & 0xff;
rx_buf[0] = 0;
rx_buf[1] = 0;
stat = spi_write_then_read(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf), rx_buf, n_rx);
result = (rx_buf[0] << 8) | rx_buf[1];
DBG("%s,SEL_GPIO reg=0x%x,result=0x%x\n",__FUNCTION__,reg&0xff,result&0xffff);
break;
#endif
#if defined(CONFIG_SPI_I2C)
case SEL_I2C:
reg = (((reg) | ICE_SEL_I2C) & ICE_SEL_READ );
tx_buf[0] = reg & 0xff;
rx_buf[0] = 0;
rx_buf[1] = 0;
stat = spi_write_then_read(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf), rx_buf, n_rx);
result = (rx_buf[0] << 8) | rx_buf[1];
DBG("%s,SEL_I2C reg=0x%x,result=0x%x [0x%x] [0x%x]\n",__FUNCTION__,reg&0xff,result&0xffff,rx_buf[0],rx_buf[1]);
break;
#endif
#if defined(CONFIG_SPI_DPRAM)
case SEL_DPRAM:
reg = (((reg) | ICE_SEL_DPRAM) & ICE_SEL_DPRAM_READ );
tx_buf[0] = reg & 0xff;
rx_buf[0] = 0;
rx_buf[1] = 0;
stat = spi_write_then_read(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf), rx_buf, n_rx);
result = (rx_buf[0] << 8) | rx_buf[1];
DBG("%s,SEL_GPIO reg=0x%x,result=0x%x\n",__FUNCTION__,reg&0xff,result&0xffff);
break;
#endif
default:
printk("Can not support this type!\n");
break;
}
return result;
}
void spi_out(struct spi_fpga_port *port, int reg, int value, int type)
{
unsigned char index = 0;
unsigned char tx_buf[3];
//printk("index2=%d,",index);
switch(type)
{
#if defined(CONFIG_SPI_UART)
case SEL_UART:
index = port->uart.index;
reg = ((((reg) | ICE_SEL_UART) & ICE_SEL_WRITE) | ICE_SEL_UART_CH(index));
tx_buf[0] = reg & 0xff;
tx_buf[1] = (value>>8) & 0xff;
tx_buf[2] = value & 0xff;
spi_write(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf));
DBG("%s,SEL_UART reg=0x%x,value=0x%x\n",__FUNCTION__,reg&0xff,value&0xffff);
break;
#endif
#if defined(CONFIG_SPI_GPIO)
case SEL_GPIO:
reg = (((reg) | ICE_SEL_GPIO) & ICE_SEL_WRITE );
tx_buf[0] = reg & 0xff;
tx_buf[1] = (value>>8) & 0xff;
tx_buf[2] = value & 0xff;
spi_write(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf));
DBG("%s,SEL_GPIO reg=0x%x,value=0x%x\n",__FUNCTION__,reg&0xff,value&0xffff);
break;
#endif
#if defined(CONFIG_SPI_I2C)
case SEL_I2C:
reg = (((reg) | ICE_SEL_I2C) & ICE_SEL_WRITE);
tx_buf[0] = reg & 0xff;
tx_buf[1] = (value>>8) & 0xff;
tx_buf[2] = value & 0xff;
spi_write(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf));
DBG("%s,SEL_I2C reg=0x%x,value=0x%x\n",__FUNCTION__,reg&0xff,value&0xffff);
break;
#endif
#if defined(CONFIG_SPI_DPRAM)
case SEL_DPRAM:
reg = (((reg) | ICE_SEL_DPRAM) | ICE_SEL_DPRAM_WRITE );
tx_buf[0] = reg & 0xff;
tx_buf[1] = (value>>8) & 0xff;
tx_buf[2] = value & 0xff;
spi_write(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf));
DBG("%s,SEL_DPRAM reg=0x%x,value=0x%x\n",__FUNCTION__,reg&0xff,value&0xffff);
break;
#endif
default:
printk("Can not support this type!\n");
break;
}
}
static void spi_fpga_irq_work_handler(struct work_struct *work)
{
struct spi_fpga_port *port =
container_of(work, struct spi_fpga_port, fpga_irq_work);
struct spi_device *spi = port->spi;
int ret,uart_ch,gpio_ch;
DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
ret = spi_in(port, ICE_SEL_READ_INT_TYPE, SEL_UART);
if((ret | ICE_INT_TYPE_UART0) == ICE_INT_TYPE_UART0)
{
#if defined(CONFIG_SPI_UART)
uart_ch = 0;
printk("Enter::%s,LINE=%d,uart_ch=%d,uart.index=%d\n",__FUNCTION__,__LINE__,uart_ch,port->uart.index);
port->uart.index = uart_ch;
spi_uart_handle_irq(spi);
#endif
}
else if((ret | ICE_INT_TYPE_GPIO) == ICE_INT_TYPE_GPIO)
{
gpio_ch = 0;
printk("Enter::%s,LINE=%d,gpio_ch=%d\n",__FUNCTION__,__LINE__,gpio_ch);
#if defined(CONFIG_SPI_GPIO)
spi_gpio_handle_irq(spi);
#endif
}
else if((ret | ICE_INT_TYPE_I2C2) == ICE_INT_TYPE_I2C2)
{
#if defined(CONFIG_SPI_I2C)
spi_i2c_handle_irq(port,0);
#endif
}
else if((ret | ICE_INT_TYPE_I2C3) == ICE_INT_TYPE_I2C3)
{
#if defined(CONFIG_SPI_I2C)
spi_i2c_handle_irq(port,1);
#endif
}
else if((ret | ICE_INT_TYPE_DPRAM) == ICE_INT_TYPE_DPRAM)
{
#if defined(CONFIG_SPI_DPRAM)
spi_dpram_handle_irq(spi);
#endif
}
else
{
printk("%s:NO such INT TYPE\n",__FUNCTION__);
}
DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
}
static irqreturn_t spi_fpga_irq(int irq, void *dev_id)
{
struct spi_fpga_port *port = dev_id;
DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
/*
* Can't do anything in interrupt context because we need to
* block (spi_sync() is blocking) so fire of the interrupt
* handling workqueue.
* Remember that we access ICE65LXX registers through SPI bus
* via spi_sync() call.
*/
//schedule_work(&port->fpga_irq_work);
queue_work(port->fpga_irq_workqueue, &port->fpga_irq_work);
return IRQ_HANDLED;
}
static int spi_open_sysclk(int set)
{
int ret;
ret = gpio_request(SPI_FPGA_STANDBY_PIN, NULL);
if (ret) {
printk("%s:failed to request standby pin\n",__FUNCTION__);
return ret;
}
rk2818_mux_api_set(GPIOH7_HSADCCLK_SEL_NAME,IOMUXB_GPIO1_D7);
gpio_direction_output(SPI_FPGA_STANDBY_PIN,set);
return 0;
}
static int __devinit spi_fpga_probe(struct spi_device * spi)
{
struct spi_fpga_port *port;
int ret;
char b[12];
DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
/*
* bits_per_word cannot be configured in platform data
*/
spi->bits_per_word = 8;
ret = spi_setup(spi);
if (ret < 0)
return ret;
port = kzalloc(sizeof(struct spi_fpga_port), GFP_KERNEL);
if (!port)
return -ENOMEM;
DBG("port=0x%x\n",(int)port);
mutex_init(&port->spi_lock);
spi_open_sysclk(GPIO_HIGH);
sprintf(b, "fpga_irq_workqueue");
port->fpga_irq_workqueue = create_freezeable_workqueue(b);
if (!port->fpga_irq_workqueue) {
printk("cannot create workqueue\n");
return -EBUSY;
}
INIT_WORK(&port->fpga_irq_work, spi_fpga_irq_work_handler);
#if defined(CONFIG_SPI_UART)
ret = spi_uart_register(port);
if(ret)
{
spi_uart_unregister(port);
printk("%s:ret=%d,fail to spi_uart_register\n",__FUNCTION__,ret);
return ret;
}
#endif
#if defined(CONFIG_SPI_GPIO)
ret = spi_gpio_register(port);
if(ret)
{
spi_gpio_unregister(port);
printk("%s:ret=%d,fail to spi_gpio_register\n",__FUNCTION__,ret);
return ret;
}
#endif
#if 0 //defined(CONFIG_SPI_I2C)
printk("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
ret = spi_i2c_register(port);
printk("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
if(ret)
{
spi_i2c_unregister(port);
printk("%s:ret=%d,fail to spi_i2c_register\n",__FUNCTION__,ret);
return ret;
}
#endif
#if defined(CONFIG_SPI_DPRAM)
ret = spi_dpram_register(port);
if(ret)
{
spi_dpram_unregister(port);
printk("%s:ret=%d,fail to spi_dpram_register\n",__FUNCTION__,ret);
return ret;
}
#endif
port->spi = spi;
spi_set_drvdata(spi, port);
ret = gpio_request(SPI_FPGA_INT_PIN, NULL);
if (ret) {
printk("%s:failed to request fpga intterupt gpio\n",__FUNCTION__);
goto err1;
}
gpio_pull_updown(SPI_FPGA_INT_PIN,GPIOPullUp);
ret = request_irq(gpio_to_irq(SPI_FPGA_INT_PIN),spi_fpga_irq,IRQF_TRIGGER_RISING,NULL,port);
if(ret)
{
printk("unable to request spi_uart irq\n");
goto err2;
}
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
pFpgaPort = port;
#if defined(CONFIG_SPI_GPIO)
spi_gpio_init();
#endif
return 0;
err2:
free_irq(gpio_to_irq(SPI_FPGA_INT_PIN),NULL);
err1:
gpio_free(SPI_FPGA_INT_PIN);
return ret;
}
static int __devexit spi_fpga_remove(struct spi_device *spi)
{
//struct spi_fpga_port *port = dev_get_drvdata(&spi->dev);
return 0;
}
#ifdef CONFIG_PM
static int spi_fpga_suspend(struct spi_device *spi, pm_message_t state)
{
//struct spi_fpga_port *port = dev_get_drvdata(&spi->dev);
return 0;
}
static int spi_fpga_resume(struct spi_device *spi)
{
//struct spi_fpga_port *port = dev_get_drvdata(&spi->dev);
return 0;
}
#else
#define spi_fpga_suspend NULL
#define spi_fpga_resume NULL
#endif
static struct spi_driver spi_fpga_driver = {
.driver = {
.name = "spi_fpga",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = spi_fpga_probe,
.remove = __devexit_p(spi_fpga_remove),
.suspend = spi_fpga_suspend,
.resume = spi_fpga_resume,
};
static int __init spi_fpga_init(void)
{
return spi_register_driver(&spi_fpga_driver);
}
static void __exit spi_fpga_exit(void)
{
spi_unregister_driver(&spi_fpga_driver);
}
module_init(spi_fpga_init);
module_exit(spi_fpga_exit);
MODULE_DESCRIPTION("Driver for spi2uart,spi2gpio,spi2i2c.");
MODULE_AUTHOR("luowei <lw@rock-chips.com>");
MODULE_LICENSE("GPL");

740
drivers/fpga/spi_gpio.c Normal file
View File

@ -0,0 +1,740 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/serial_reg.h>
#include <linux/circ_buf.h>
#include <linux/gfp.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <mach/gpio.h>
#include <mach/iomux.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/miscdevice.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <mach/rk2818_iomap.h>
#include "spi_fpga.h"
#if defined(CONFIG_SPI_GPIO_DEBUG)
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
#define SPI_GPIO_TEST 0
#define HIGH_SPI_TEST 1
spinlock_t gpio_lock;
spinlock_t gpio_state_lock;
spinlock_t gpio_irq_lock;
static unsigned short int gGpio0State = 0;
#define SPI_GPIO_IRQ_NUM 16
static SPI_GPIO_PDATA g_spiGpioVectorTable[SPI_GPIO_IRQ_NUM] = \
{{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}};
static void spi_gpio_write_reg(int reg, int PinNum, int set)
{
unsigned int old_set;
unsigned int new_set;
struct spi_fpga_port *port = pFpgaPort;
PinNum = PinNum % 16;
//mutex_lock(&port->spi_lock);
old_set= spi_in(port, reg, SEL_GPIO);
if(1 == set)
new_set = old_set | (1 << PinNum );
else
new_set = old_set & (~(1 << PinNum ));
spi_out(port, reg, new_set, SEL_GPIO);
//mutex_unlock(&port->spi_lock);
}
static int spi_gpio_read_reg(int reg)
{
int ret = 0;
struct spi_fpga_port *port = pFpgaPort;
//mutex_lock(&port->spi_lock);
ret = spi_in(port, reg, SEL_GPIO);
//mutex_unlock(&port->spi_lock);
return ret;
}
static int get_gpio_addr(eSpiGpioPinNum_t PinNum)
{
int gpio = PinNum / 16;
int reg = -1;
switch(gpio)
{
case 0:
reg = ICE_SEL_GPIO0;
break;
case 1:
reg = ICE_SEL_GPIO1;
break;
case 2:
reg = ICE_SEL_GPIO2;
break;
case 3:
reg = ICE_SEL_GPIO3;
break;
case 4:
reg = ICE_SEL_GPIO4;
break;
case 5:
reg = ICE_SEL_GPIO5;
break;
default:
break;
}
return reg;
}
int spi_gpio_int_sel(eSpiGpioPinNum_t PinNum,eSpiGpioTypeSel_t type)
{
int reg = get_gpio_addr(PinNum);
//struct spi_fpga_port *port = pFpgaPort;
if(ICE_SEL_GPIO0 == reg)
{
reg |= ICE_SEL_GPIO0_TYPE;
spin_lock(&gpio_state_lock);
if(SPI_GPIO0_IS_INT == type)
gGpio0State |= (1 << PinNum );
else
gGpio0State &= (~(1 << PinNum ));
spin_unlock(&gpio_state_lock);
DBG("%s,PinNum=%d,GPIO[%d]:type=%d\n",__FUNCTION__,PinNum,PinNum/16,type);
//mutex_lock(&port->spi_lock);
spi_gpio_write_reg(reg, PinNum, type);
//mutex_unlock(&port->spi_lock);
return 0;
}
else
{
printk("%s:error\n",__FUNCTION__);
return -1;
}
}
int spi_gpio_set_pindirection(eSpiGpioPinNum_t PinNum,eSpiGpioPinDirection_t direction)
{
int reg = get_gpio_addr(PinNum);
//struct spi_fpga_port *port = pFpgaPort;
if(reg == -1)
{
printk("%s:error\n",__FUNCTION__);
return -1;
}
if(ICE_SEL_GPIO0 == reg)
{
reg |= ICE_SEL_GPIO0_DIR;
spin_lock(&gpio_state_lock);
if((gGpio0State & (1 << PinNum )) != 0)
{
printk("Fail to set direction because it is int pin!\n");
return -1;
}
spin_unlock(&gpio_state_lock);
DBG("%s,PinNum=%d,direction=%d,GPIO[%d]:PinNum/16=%d\n",__FUNCTION__,PinNum,direction,PinNum/16,PinNum%16);
//mutex_lock(&port->spi_lock);
spi_gpio_write_reg(reg, PinNum, direction);
//mutex_unlock(&port->spi_lock);
}
else
{
reg |= ICE_SEL_GPIO_DIR;
DBG("%s,PinNum=%d,direction=%d,GPIO[%d]:PinNum/16=%d\n",__FUNCTION__,PinNum,direction,PinNum/16,PinNum%16);
//mutex_lock(&port->spi_lock);
spi_gpio_write_reg(reg, PinNum, direction);
//mutex_unlock(&port->spi_lock);
}
return 0;
}
int spi_gpio_set_pinlevel(eSpiGpioPinNum_t PinNum, eSpiGpioPinLevel_t PinLevel)
{
int reg = get_gpio_addr(PinNum);
//struct spi_fpga_port *port = pFpgaPort;
if(reg == -1)
{
printk("%s:error\n",__FUNCTION__);
return -1;
}
if(ICE_SEL_GPIO0 == reg)
{
reg |= ICE_SEL_GPIO0_DATA;
spin_lock(&gpio_state_lock);
if((gGpio0State & (1 << PinNum )) != 0)
{
printk("Fail to set PinLevel because PinNum=%d is int pin!\n",PinNum);
return -1;
}
spin_unlock(&gpio_state_lock);
DBG("%s,PinNum=%d,GPIO[%d]:PinNum/16=%d,PinLevel=%d\n",__FUNCTION__,PinNum,PinNum/16,PinNum%16,PinLevel);
//mutex_lock(&port->spi_lock);
spi_gpio_write_reg(reg, PinNum, PinLevel);
//mutex_unlock(&port->spi_lock);
}
else
{
reg |= ICE_SEL_GPIO_DATA;
DBG("%s,PinNum=%d,GPIO[%d]:PinNum/16=%d,PinLevel=%d\n",__FUNCTION__,PinNum,PinNum/16,PinNum%16,PinLevel);
//mutex_lock(&port->spi_lock);
spi_gpio_write_reg(reg, PinNum, PinLevel);
//mutex_unlock(&port->spi_lock);
}
return 0;
}
eSpiGpioPinLevel_t spi_gpio_get_pinlevel(eSpiGpioPinNum_t PinNum)
{
int ret = 0;
int reg = get_gpio_addr(PinNum);
int level = 0;
//struct spi_fpga_port *port = pFpgaPort;
if(reg == -1)
{
printk("%s:error\n",__FUNCTION__);
return SPI_GPIO_LEVEL_ERR;
}
if(ICE_SEL_GPIO0 == reg)
{
reg |= ICE_SEL_GPIO0_DATA;
spin_lock(&gpio_state_lock);
if((gGpio0State & (1 << PinNum )) != 0)
{
printk("Fail to get PinLevel because it is int pin!\n");
return SPI_GPIO_LEVEL_ERR;
}
spin_unlock(&gpio_state_lock);
//mutex_lock(&port->spi_lock);
ret = spi_gpio_read_reg(reg);
//mutex_unlock(&port->spi_lock);
}
else
{
reg |= ICE_SEL_GPIO_DATA;
//mutex_lock(&port->spi_lock);
ret = spi_gpio_read_reg(reg);
//mutex_unlock(&port->spi_lock);
}
if((ret & (1 << (PinNum%16) )) == 0)
level = SPI_GPIO_LOW;
else
level = SPI_GPIO_HIGH;
DBG("%s,PinNum=%d,ret=0x%x,GPIO[%d]:PinNum/16=%d,PinLevel=%d\n\n",__FUNCTION__,PinNum,ret,PinNum/16,PinNum%16,level);
return level;
}
int spi_gpio_enable_int(eSpiGpioPinNum_t PinNum)
{
int reg = get_gpio_addr(PinNum);
//struct spi_fpga_port *port = pFpgaPort;
if(ICE_SEL_GPIO0 == reg)
{
reg |= ICE_SEL_GPIO0_INT_EN;
spin_lock(&gpio_state_lock);
if((gGpio0State & (1 << PinNum )) == 0)
{
printk("Fail to enable int because it is gpio pin!\n");
return -1;
}
spin_unlock(&gpio_state_lock);
DBG("%s,PinNum=%d,IntEn=%d\n",__FUNCTION__,PinNum,SPI_GPIO_INT_ENABLE);
//mutex_lock(&port->spi_lock);
spi_gpio_write_reg(reg, PinNum, SPI_GPIO_INT_ENABLE);
//mutex_unlock(&port->spi_lock);
}
else
{
printk("%s:error\n",__FUNCTION__);
return -1;
}
return 0;
}
int spi_gpio_disable_int(eSpiGpioPinNum_t PinNum)
{
int reg = get_gpio_addr(PinNum);
//struct spi_fpga_port *port = pFpgaPort;
if(ICE_SEL_GPIO0 == reg)
{
reg |= ICE_SEL_GPIO0_INT_EN;
spin_lock(&gpio_state_lock);
if((gGpio0State & (1 << PinNum )) == 0)
{
printk("Fail to enable int because it is gpio pin!\n");
return -1;
}
spin_unlock(&gpio_state_lock);
DBG("%s,PinNum=%d,IntEn=%d\n",__FUNCTION__,PinNum,SPI_GPIO_INT_DISABLE);
//mutex_lock(&port->spi_lock);
spi_gpio_write_reg(reg, PinNum, SPI_GPIO_INT_DISABLE);
//mutex_unlock(&port->spi_lock);
}
else
{
printk("%s:error\n",__FUNCTION__);
return -1;
}
return 0;
}
int spi_gpio_set_int_trigger(eSpiGpioPinNum_t PinNum,eSpiGpioIntType_t IntType)
{
int reg = get_gpio_addr(PinNum);
//struct spi_fpga_port *port = pFpgaPort;
if(ICE_SEL_GPIO0 == reg)
{
reg |= ICE_SEL_GPIO0_INT_TRI;
spin_lock(&gpio_state_lock);
if((gGpio0State & (1 << PinNum )) == 0)
{
printk("Fail to enable int because it is gpio pin!\n");
return -1;
}
spin_unlock(&gpio_state_lock);
DBG("%s,PinNum=%d,IntType=%d\n",__FUNCTION__,PinNum,IntType);
//mutex_lock(&port->spi_lock);
spi_gpio_write_reg(reg, PinNum, IntType);
//mutex_unlock(&port->spi_lock);
}
else
{
printk("%s:error\n",__FUNCTION__);
return -1;
}
return 0;
}
int spi_gpio_read_iir(void)
{
int reg = ICE_SEL_GPIO0 | ICE_SEL_GPIO0_INT_STATE;
int ret = 0;
ret = spi_gpio_read_reg(reg);
DBG("%s,IntState=%d\n",__FUNCTION__,ret);
return ret;
}
int spi_request_gpio_irq(eSpiGpioPinNum_t PinNum, pSpiFunc Routine, eSpiGpioIntType_t IntType,void *dev_id)
{
if(PinNum >= SPI_GPIO_IRQ_NUM)
return -1;
DBG("Enter::%s,LINE=%d,PinNum=%d\n",__FUNCTION__,__LINE__,PinNum);
if(spi_gpio_int_sel(PinNum,SPI_GPIO0_IS_INT))
return -1;
if(spi_gpio_set_int_trigger(PinNum,IntType))
return -1;
spin_lock(&gpio_irq_lock);
if(g_spiGpioVectorTable[PinNum].gpio_vector)
return -1;
g_spiGpioVectorTable[PinNum].gpio_vector = (pSpiFuncIntr)Routine;
g_spiGpioVectorTable[PinNum].gpio_devid= dev_id;
spin_unlock(&gpio_irq_lock);
if(spi_gpio_enable_int(PinNum))
return -1;
return 0;
}
int spi_free_gpio_irq(eSpiGpioPinNum_t PinNum)
{
spi_gpio_disable_int(PinNum);
spin_lock(&gpio_irq_lock);
g_spiGpioVectorTable[PinNum].gpio_vector = NULL;
g_spiGpioVectorTable[PinNum].gpio_devid= NULL;
spin_unlock(&gpio_irq_lock);
return 0;
}
int spi_gpio_handle_irq(struct spi_device *spi)
{
int gpio_iir, i;
#if 1
gpio_iir = spi_gpio_read_iir() & 0xffff;
if(gpio_iir == 0xffff)
return -1;
//spin_lock(&gpio_state_lock);
DBG("gpio_iir=0x%x\n",gpio_iir);
for(i=0; i<SPI_GPIO_IRQ_NUM; i++)
{
if(((gpio_iir & (1 << i)) == 0) && ((gGpio0State & (1 << i)) != 0))
{
if(g_spiGpioVectorTable[i].gpio_vector)
{
g_spiGpioVectorTable[i].gpio_vector(i,g_spiGpioVectorTable[i].gpio_devid);
DBG("spi_gpio_irq=%d\n",i);
}
}
}
//spin_unlock(&gpio_state_lock);
#endif
return 0;
}
int spi_gpio_init(void)
{
int i,ret;
struct spi_fpga_port *port = pFpgaPort;
#if HIGH_SPI_TEST
printk("*************test spi communication now***************\n");
printk("%s:LINE=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
for(i=0;i<0xff;i++)
{
spi_out(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), i, SEL_GPIO);//all gpio is input
ret = spi_in(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;
if(i != ret)
printk("err:i=0x%x but ret=0x%x\n",i,ret);
}
#endif
#if (FPGA_TYPE == ICE_CC72)
for(i=0; i<16; i++)
{
DBG("i=%d\n\n",i);
spi_gpio_int_sel(i,SPI_GPIO0_IS_GPIO);
spi_gpio_set_pinlevel(i, SPI_GPIO_LOW);
spi_gpio_set_pindirection(i, SPI_GPIO_OUT);
}
/*
for(i=6; i<16; i++)
{
DBG("i=%d\n\n",i);
spi_gpio_int_sel(i,SPI_GPIO0_IS_INT);
spi_gpio_set_int_trigger(i,SPI_GPIO_EDGE_FALLING);
spi_gpio_disable_int(i);
}
*/
for(i=16; i<32; i++)
{
spi_gpio_set_pinlevel(i, SPI_GPIO_LOW);
spi_gpio_set_pindirection(i, SPI_GPIO_OUT);
}
//spi_out(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DATA), 0, SEL_GPIO);//all gpio is zero
//spi_out(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), 0, SEL_GPIO);//all gpio is input
#elif (FPGA_TYPE == ICE_CC196)
#if 0
for(i=0;i<82;i++)
{
if(i<16)
spi_gpio_int_sel(i,SPI_GPIO0_IS_GPIO);
spi_gpio_set_pindirection(i, SPI_GPIO_OUT);
}
while(1)
{
if(TestGpioPinLevel == 0)
TestGpioPinLevel = 1;
else
TestGpioPinLevel = 0;
for(i=0;i<82;i++)
{
spi_gpio_set_pinlevel(i, TestGpioPinLevel);
ret = spi_gpio_get_pinlevel(i);
if(ret != TestGpioPinLevel)
DBG("PinNum=%d,set_pinlevel=%d,get_pinlevel=%d\n\n",i,TestGpioPinLevel,ret);
}
mdelay(10);
DBG("%s:LINE=%d\n",__FUNCTION__,__LINE__);
}
#endif
#if 0
DBG("%s:LINE=%d\n",__FUNCTION__,__LINE__);
spi_out(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO0_TYPE), 0x0000, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO0_TYPE), SEL_GPIO) & 0xffff;
if(ret != 0x0000)
DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
spi_out(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO_DATA), 0x0000, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff;
if(ret != 0x0000)
DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
spi_out(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO_DIR), 0xffff, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;
if(ret != 0xffff)
DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
spi_out(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DATA), 0x0224, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff;
if(ret != 0x0224)
DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
spi_out(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), 0xf7ef, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;
if(ret != 0xf7ef)
DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
spi_out(port, (ICE_SEL_GPIO2 | ICE_SEL_GPIO_DATA), 0x2008, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO2 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff;
if(ret != 0x2008)
DBG("%s:Line=%d,set=0x2008,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
spi_out(port, (ICE_SEL_GPIO2 | ICE_SEL_GPIO_DIR), 0xf378, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;
if(ret != 0xf378)
DBG("%s:Line=%d,set=0xf378,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
spi_out(port, (ICE_SEL_GPIO3 | ICE_SEL_GPIO_DATA), 0x0000, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO3 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff;
if(ret != 0x0000)
DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
spi_out(port, (ICE_SEL_GPIO3 | ICE_SEL_GPIO_DIR), 0xffff, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO3 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;
if(ret != 0xffff)
DBG("%s:Line=%d,set=0xffff,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
spi_out(port, (ICE_SEL_GPIO4 | ICE_SEL_GPIO_DATA), 0x0000, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO4 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff;
if(ret != 0x0000)
DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
spi_out(port, (ICE_SEL_GPIO4 | ICE_SEL_GPIO_DIR), 0xffbf, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO4 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;
if(ret != 0xffbf)
DBG("%s:Line=%d,set=0xffbf,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
spi_out(port, (ICE_SEL_GPIO5 | ICE_SEL_GPIO_DATA), 0x0000, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO5 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff;
if(ret != 0x0000)
DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
spi_out(port, (ICE_SEL_GPIO5 | ICE_SEL_GPIO_DIR), 0xffff, SEL_GPIO);
ret = spi_in(port, (ICE_SEL_GPIO5 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;
if(ret != 0xffff)
DBG("%s:Line=%d,set=0xffff,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
#else
spi_gpio_set_pinlevel(SPI_GPIO_P1_00, SPI_GPIO_LOW); //LCD_ON output
spi_gpio_set_pindirection(SPI_GPIO_P1_00, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P1_01, SPI_GPIO_LOW); //LCD_PWR_CTRL output
spi_gpio_set_pindirection(SPI_GPIO_P1_01, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P1_02, SPI_GPIO_HIGH); //SD_POW_ON output
spi_gpio_set_pindirection(SPI_GPIO_P1_02, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P1_03, SPI_GPIO_LOW); //WL_RST_N/WIFI_EN output
spi_gpio_set_pindirection(SPI_GPIO_P1_03, SPI_GPIO_OUT);
spi_gpio_set_pindirection(SPI_GPIO_P1_04, SPI_GPIO_IN); //HARDO,input
spi_gpio_set_pinlevel(SPI_GPIO_P1_05, SPI_GPIO_HIGH); //SENSOR_PWDN output
spi_gpio_set_pindirection(SPI_GPIO_P1_05, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P1_06, SPI_GPIO_LOW); //BT_PWR_EN output
spi_gpio_set_pindirection(SPI_GPIO_P1_06, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P1_07, SPI_GPIO_LOW); //BT_RST output
spi_gpio_set_pindirection(SPI_GPIO_P1_07, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P1_08, SPI_GPIO_LOW); //BT_WAKE_B output
spi_gpio_set_pindirection(SPI_GPIO_P1_08, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P1_09, SPI_GPIO_HIGH); //LCD_DISP_ON output
spi_gpio_set_pindirection(SPI_GPIO_P1_09, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P1_10, SPI_GPIO_LOW); //WM_PWR_EN output
spi_gpio_set_pindirection(SPI_GPIO_P1_10, SPI_GPIO_OUT);
spi_gpio_set_pindirection(SPI_GPIO_P1_11, SPI_GPIO_IN); //HARD1,input
spi_gpio_set_pinlevel(SPI_GPIO_P1_12, SPI_GPIO_LOW); //VIB_MOTO output
spi_gpio_set_pindirection(SPI_GPIO_P1_12, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P1_13, SPI_GPIO_HIGH); //KEYLED_EN output
spi_gpio_set_pindirection(SPI_GPIO_P1_13, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P1_14, SPI_GPIO_LOW); //CAM_RST output
spi_gpio_set_pindirection(SPI_GPIO_P1_14, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P1_15, SPI_GPIO_LOW); //WL_WAKE_B output
spi_gpio_set_pindirection(SPI_GPIO_P1_15, SPI_GPIO_OUT);
spi_gpio_set_pindirection(SPI_GPIO_P2_00, SPI_GPIO_IN); //Y+YD input
spi_gpio_set_pindirection(SPI_GPIO_P2_01, SPI_GPIO_IN); //Y-YU input
spi_gpio_set_pindirection(SPI_GPIO_P2_02, SPI_GPIO_IN); //AP_TD_UNDIFED input
spi_gpio_set_pinlevel(SPI_GPIO_P2_03, SPI_GPIO_HIGH); //AP_PW_EN_TD output
spi_gpio_set_pindirection(SPI_GPIO_P2_03, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P2_04, SPI_GPIO_LOW); //AP_RESET_TD output
spi_gpio_set_pindirection(SPI_GPIO_P2_04, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P2_05, SPI_GPIO_LOW); //AP_SHUTDOWN_TD_PMU output
spi_gpio_set_pindirection(SPI_GPIO_P2_05, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P2_06, SPI_GPIO_LOW); //AP_RESET_CMMB output
spi_gpio_set_pindirection(SPI_GPIO_P2_06, SPI_GPIO_OUT);
spi_gpio_set_pindirection(SPI_GPIO_P2_07, SPI_GPIO_IN); //AP_CHECK_TD_STATUS input
spi_gpio_set_pinlevel(SPI_GPIO_P2_08, SPI_GPIO_LOW); //CHARGE_CURRENT_SEL output
spi_gpio_set_pindirection(SPI_GPIO_P2_08, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P2_09, SPI_GPIO_LOW); //AP_PWD_CMMB output
spi_gpio_set_pindirection(SPI_GPIO_P2_09, SPI_GPIO_OUT);
spi_gpio_set_pindirection(SPI_GPIO_P2_10, SPI_GPIO_IN); //X-XL input
spi_gpio_set_pindirection(SPI_GPIO_P2_11, SPI_GPIO_IN); //X+XR input
spi_gpio_set_pinlevel(SPI_GPIO_P2_12, SPI_GPIO_LOW); //LCD_RESET output
spi_gpio_set_pindirection(SPI_GPIO_P2_12, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P2_13, SPI_GPIO_HIGH); //USB_PWR_EN output
spi_gpio_set_pindirection(SPI_GPIO_P2_13, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P2_14, SPI_GPIO_LOW); //WL_HOST_WAKE_B output
spi_gpio_set_pindirection(SPI_GPIO_P2_14, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P2_15, SPI_GPIO_LOW); //TOUCH_SCREEN_RST output
spi_gpio_set_pindirection(SPI_GPIO_P2_15, SPI_GPIO_OUT);
spi_gpio_set_pindirection(SPI_GPIO_P4_06, SPI_GPIO_IN); //CHARGER_INT_END input
spi_gpio_set_pinlevel(SPI_GPIO_P4_07, SPI_GPIO_LOW); //TOUCH_SCREEN_RST output
spi_gpio_set_pindirection(SPI_GPIO_P4_07, SPI_GPIO_OUT);
spi_gpio_set_pinlevel(SPI_GPIO_P4_08, SPI_GPIO_LOW); //CM3605_PS_SHUTDOWN
spi_gpio_set_pindirection(SPI_GPIO_P4_08, SPI_GPIO_OUT);
#endif
#endif
return 0;
}
#if SPI_GPIO_TEST
volatile int TestGpioPinLevel = 0;
void spi_gpio_work_handler(struct work_struct *work)
{
struct spi_fpga_port *port =
container_of(work, struct spi_fpga_port, gpio.spi_gpio_work);
int i,ret;
printk("*************test spi_gpio now***************\n");
if(TestGpioPinLevel == 0)
TestGpioPinLevel = 1;
else
TestGpioPinLevel = 0;
#if (FPGA_TYPE == ICE_CC72)
for(i=0;i<32;i++)
{
spi_gpio_set_pinlevel(i, TestGpioPinLevel);
ret = spi_gpio_get_pinlevel(i);
if(ret != TestGpioPinLevel)
DBG("PinNum=%d,set_pinlevel=%d,get_pinlevel=%d\n",i,TestGpioPinLevel,ret);
//spi_gpio_set_pindirection(i, SPI_GPIO_OUT);
}
#elif (FPGA_TYPE == ICE_CC196)
for(i=0;i<16;i++)
{
if(i<16)
spi_gpio_int_sel(i,SPI_GPIO0_IS_GPIO);
spi_gpio_set_pindirection(i, SPI_GPIO_OUT);
}
for(i=0;i<81;i++)
{
spi_gpio_set_pinlevel(i, TestGpioPinLevel);
ret = spi_gpio_get_pinlevel(i);
if(ret != TestGpioPinLevel)
printk("err:PinNum=%d,set_pinlevel=%d but get_pinlevel=%d\n\n",i,TestGpioPinLevel,ret);
}
DBG("%s:LINE=%d\n",__FUNCTION__,__LINE__);
#endif
}
static void spi_testgpio_timer(unsigned long data)
{
struct spi_fpga_port *port = (struct spi_fpga_port *)data;
port->gpio.gpio_timer.expires = jiffies + msecs_to_jiffies(1000);
add_timer(&port->gpio.gpio_timer);
//schedule_work(&port->gpio.spi_gpio_work);
queue_work(port->gpio.spi_gpio_workqueue, &port->gpio.spi_gpio_work);
}
#endif
int spi_gpio_register(struct spi_fpga_port *port)
{
#if SPI_GPIO_TEST
char b[20];
sprintf(b, "spi_gpio_workqueue");
port->gpio.spi_gpio_workqueue = create_freezeable_workqueue(b);
if (!port->gpio.spi_gpio_workqueue) {
printk("cannot create spi_gpio workqueue\n");
return -EBUSY;
}
INIT_WORK(&port->gpio.spi_gpio_work, spi_gpio_work_handler);
setup_timer(&port->gpio.gpio_timer, spi_testgpio_timer, (unsigned long)port);
port->gpio.gpio_timer.expires = jiffies+2000;//>1000ms
add_timer(&port->gpio.gpio_timer);
#endif
spin_lock_init(&gpio_lock);
spin_lock_init(&gpio_state_lock);
spin_lock_init(&gpio_irq_lock);
DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);
return 0;
}
int spi_gpio_unregister(struct spi_fpga_port *port)
{
return 0;
}
MODULE_DESCRIPTION("Driver for spi2gpio.");
MODULE_AUTHOR("luowei <lw@rock-chips.com>");
MODULE_LICENSE("GPL");

445
drivers/fpga/spi_i2c.c Normal file
View File

@ -0,0 +1,445 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/serial_reg.h>
#include <linux/circ_buf.h>
#include <linux/gfp.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <mach/gpio.h>
#include <mach/iomux.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/miscdevice.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <mach/board.h>
#include <mach/rk2818_iomap.h>
#include "spi_fpga.h"
#if defined(CONFIG_SPI_I2C_DEBUG)
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
#define SPI_I2C_TEST 0
#define MAXMSGLEN 16
#define DRV_NAME "fpga_i2c"
struct spi_i2c_data {
struct device *dev;
struct i2c_adapter adapter;
unsigned long scl_rate;
spinlock_t i2c_lock;
};
int spi_i2c_handle_irq(struct spi_fpga_port *port,unsigned char channel)
{
int reg;
int ret;
if(channel == 0)
reg = ICE_SEL_I2C_INT|ICE_SEL_I2C_CH2;
else
reg = ICE_SEL_I2C_INT|ICE_SEL_I2C_CH3;
port->i2c.interrupt = 0;
ret = spi_in(port,reg,SEL_I2C);
if(ret == INT_I2C_READ_ACK)
port->i2c.interrupt = INT_I2C_READ_ACK;
else if(ret == INT_I2C_READ_NACK)
{
printk("Error::read no ack!!check the I2C slave device \n");
}
else if(ret == INT_I2C_WRITE_ACK)
port->i2c.interrupt = INT_I2C_WRITE_ACK;
else if(ret == INT_I2C_WRITE_NACK)
{
printk("Error::write no ack!!check the I2C slave device \n");
}
else
printk("Error:ack value error!!check the I2C slave device \n");
return port->i2c.interrupt;
}
int spi_i2c_select_speed(int speed)
{
int result = 0;
switch(speed)
{
case 10:
result = ICE_SET_10K_I2C_SPEED;
break;
case 100:
result = ICE_SET_100K_I2C_SPEED;
break;
case 200:
result = ICE_SET_200K_I2C_SPEED;
break;
case 300:
result = ICE_SET_300K_I2C_SPEED;
break;
case 400:
result = ICE_SET_400K_I2C_SPEED;
break;
default:
break;
}
return result;
}
int spi_i2c_readbuf(struct spi_fpga_port *port ,struct i2c_msg *pmsg)
{
unsigned int reg ;
unsigned int len,i;
unsigned int slaveaddr;
unsigned int speed;
unsigned int channel = 0 ;
unsigned int result;
slaveaddr = pmsg->addr;
len = pmsg->len;
speed = spi_i2c_select_speed(pmsg->scl_rate);
if(pmsg->channel == I2C_CH2)
channel = ICE_SEL_I2C_CH2;
else if(pmsg->channel == I2C_CH3)
channel = ICE_SEL_I2C_CH3;
else
{
printk("Error:try to read form error i2c channel\n");
return 0;
}
if(pmsg->read_type == 0)
{
//slaveaddr ;
slaveaddr = slaveaddr<<1;
reg = channel |ICE_SEL_I2C_START;
spi_out(port,reg,slaveaddr,SEL_I2C);
//speed;
reg = channel |ICE_SEL_I2C_SPEED|ICE_SEL_I2C_TRANS;
spi_out(port,reg,speed,SEL_I2C);
//len;
reg = channel |ICE_SEL_I2C_FIFO |ICE_SEL_I2C_TRANS;
spi_out(port,reg,len,SEL_I2C);
reg = channel |ICE_SEL_I2C_TRANS;
//data;
for(i = 0 ;i < len;i++)
{
if(i == len-1)
reg = channel |ICE_SEL_I2C_STOP;
spi_out(port,reg,pmsg->buf[i],SEL_I2C);
}
}
//slaveaddr
slaveaddr = slaveaddr|ICE_I2C_SLAVE_READ;
if(pmsg->read_type == 0)
reg = channel |ICE_SEL_I2C_RESTART;
else
reg = channel |ICE_SEL_I2C_START;
spi_out(port,reg,slaveaddr,SEL_I2C);
//speed;
reg = channel |ICE_SEL_I2C_SPEED|ICE_SEL_I2C_TRANS;
spi_out(port,reg,speed,SEL_I2C);
//len;
reg = channel |ICE_SEL_I2C_FIFO |ICE_SEL_I2C_TRANS;
spi_out(port,reg,len,SEL_I2C);
i=50;
while(i--)
{
if(port->i2c.interrupt == INT_I2C_READ_ACK)
{
for(i = 0;i<len;i++)
{
result = spi_in(port,reg,SEL_I2C);
pmsg->buf[i] = result & 0xFF;
}
spin_lock(&port->i2c.i2c_lock);
port->i2c.interrupt &= INT_I2C_READ_MASK;
spin_unlock(&port->i2c.i2c_lock);
break;
}
}
for(i = 0;i<len;i++)
DBG("pmsg->buf[%d] = 0x%x \n",i,pmsg->buf[i]);
return pmsg->len;
}
int spi_i2c_writebuf(struct spi_fpga_port *port ,struct i2c_msg *pmsg)
{
unsigned int reg ;
unsigned int len,i;
unsigned int slaveaddr;
unsigned int speed;
unsigned int channel = 0;
slaveaddr = pmsg->addr;
len = pmsg->len;
speed = spi_i2c_select_speed(pmsg->scl_rate);
if(pmsg->channel == I2C_CH2)
channel = ICE_SEL_I2C_CH2;
else if(pmsg->channel == I2C_CH3)
channel = ICE_SEL_I2C_CH3;
else
{
printk("Error: try to write the error i2c channel\n");
return 0;
}
//slaveaddr ;
slaveaddr = slaveaddr<<1;
reg = channel |ICE_SEL_I2C_START;
spi_out(port,reg,slaveaddr,SEL_I2C);
//speed;
reg = channel |ICE_SEL_I2C_SPEED|ICE_SEL_I2C_TRANS;
spi_out(port,reg,speed,SEL_I2C);
//len;
reg = channel |ICE_SEL_I2C_FIFO |ICE_SEL_I2C_TRANS;
spi_out(port,reg,len,SEL_I2C);
reg = channel |ICE_SEL_I2C_TRANS;
//data;
for(i = 0 ;i < len;i++)
{
if(i == len-1)
reg = channel|ICE_SEL_I2C_STOP;
spi_out(port,reg,pmsg->buf[i],SEL_I2C);
}
i = 50;
while(i--)
{
if(port->i2c.interrupt == INT_I2C_WRITE_ACK)
{
spin_lock(&port->i2c.i2c_lock);
port->i2c.interrupt &= INT_I2C_WRITE_MASK;
spin_unlock(&port->i2c.i2c_lock);
break;
}
}
DBG("wait num= %d,port->i2c.interrupt = 0x%x\n",i,port->i2c.interrupt);
return pmsg->len;
}
#if defined(CONFIG_SPI_I2C_DEBUG)
unsigned short rda5400[][2] =
{
{0x3f,0x0000},//page 0
{0x0B,0x3200},// pll_cal_eachtime
{0x0E,0x5200},// rxfilter_op_cal_bit_dr rxfilter_sys_cal_bit_dr
{0x13,0x016D},// fts_cap=01, for high nak rate at high temperature¡£
{0x16,0x9C23},// Load8.5pf crystal,2.2pf cap
{0x17,0xBB12},// xtal_cpuclk_en,*
{0x19,0xEE18},// rxfilter_bp_mode rxfilter_tuning_cap_for die
{0x1A,0x59EE},// rmx_lo_reg=1011, tmx_iqswap
{0x1C,0x008F},//
{0x30,0x002B},//
{0x3B,0x33EA},// rxfilter_imgrej_lo
{0x3E,0x0040},// tmx_lo_reg set to1
{0x3f,0x0001},//page 1
{0x02,0x0001},// rxfilter_sys_cal_polarity
{0x04,0xE41E},// ldo_ictrl<5bit> set to 1
{0x05,0xBC00},// ldo_ictrl<5bit> set to 1
{0x06,0x262D},//
{0x0B,0x001F},// vco_bit=111
{0x10,0x0100},// thermo power setting
{0x13,0x001C},// pre_sca=1100
{0x19,0x001C},// lo_buff=1100, improve RF per formance at high temp
{0x1a,0x1404},
{0x1E,0x2A48},// resetn_ex_selfgen_enable=0, for 32K is no need when poweron
{0x27,0x0070},// power table setting, maxpower
{0x26,0x3254},// power table setting
{0x25,0x2180},// power table settings
{0x24,0x0000},// power table setting
{0x23,0x0000},// power table setting
{0x22,0x0000},// power table setting
{0x21,0x0000},// power table setting
{0x20,0x0000},// power table setting
{0x37,0x0600},// padrv_cal_bypass
{0x3A,0x06E0},// dcdc setting
{0x3f,0x0000},//page 0
};
int spi_i2c_16bit_test(struct spi_fpga_port *port)
{
u8 i2c_buf[8];
int len = 2;
int i ;
struct i2c_msg msg[1] =
{
{0x16,0,len+2,i2c_buf,200,3,0}
};
for(i = 0;i < (sizeof(rda5400)/sizeof(rda5400[0]));i++)
{
i2c_buf[0] = 0x22;
i2c_buf[1] = rda5400[i][0];
i2c_buf[1] = rda5400[i][1]>>8;
i2c_buf[2] = rda5400[i][1]&0xFF;
spi_i2c_writebuf(port, msg);
msg[0].len = 2;
spi_i2c_readbuf(port, msg);
}
return 0;
}
int spi_i2c_8bit_test(struct spi_fpga_port *port)
{
u8 i2c_buf[8];
int len = 2;
int i ;
struct i2c_msg msg[1] =
{
{0x16,0,len+1,i2c_buf,200,2,0}
};
for(i = 0;i < (sizeof(rda5400)/sizeof(rda5400[0]));i++)
{
i2c_buf[0] = rda5400[i][0];
i2c_buf[1] = rda5400[i][1]>>8;
i2c_buf[2] = rda5400[i][1]&0xFF;
spi_i2c_writebuf(port, msg);
msg[0].len = 1;
spi_i2c_readbuf(port, msg);
}
return 0;
}
int spi_i2c_test(void )
{
struct spi_fpga_port *port = pFpgaPort;
printk("IN::************spi_i2c_test********\r\n");
spi_i2c_8bit_test(port);
spi_i2c_16bit_test(port);
printk("OUT::************spi_i2c_test********\r\n");
return 0;
}
#endif
int spi_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *pmsg, int num)
{
struct spi_fpga_port *port = pFpgaPort;
printk("%s:line=%d,channel = %d\n",__FUNCTION__,__LINE__,adapter->nr);
if(pmsg->len > MAXMSGLEN)
return 0;
if(pmsg->flags)
spi_i2c_readbuf(port,pmsg);
else
spi_i2c_writebuf(port,pmsg);
return pmsg->len;
return 0;
}
static unsigned int spi_i2c_func(struct i2c_adapter *adapter)
{
return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL);
}
static const struct i2c_algorithm spi_i2c_algorithm = {
.master_xfer = spi_i2c_xfer,
.functionality = spi_i2c_func,
};
static int spi_i2c_probe(struct platform_device *pdev)
{
int ret;
struct spi_i2c_data *i2c;
struct rk2818_i2c_platform_data *pdata;
DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
pdata = pdev->dev.platform_data;
if(!pdata)
{
dev_err(&pdev->dev,"no platform data\n");
return -EINVAL;
}
i2c = kzalloc(sizeof(struct spi_i2c_data),GFP_KERNEL);
if(!i2c)
{
dev_err(&pdev->dev,"no memory for state\n");
return -ENOMEM;
}
strlcpy(i2c->adapter.name,DRV_NAME,sizeof(i2c->adapter.name));
i2c->adapter.owner = THIS_MODULE;
i2c->adapter.algo = &spi_i2c_algorithm;
i2c->adapter.class = I2C_CLASS_HWMON;
i2c->dev = &pdev->dev;
i2c->adapter.algo_data = i2c;
i2c->adapter.dev.parent = &pdev->dev;
i2c->adapter.nr = pdata->bus_num;
ret = i2c_add_numbered_adapter(&i2c->adapter);
if(ret < 0){
dev_err(&pdev->dev,"fail to add bus to i2c core fpga\n");
kfree(i2c);
return ret;
}
platform_set_drvdata(pdev,i2c);
printk("Enter::%s,LINE=%d i2c->adap.nr = %d ************************\n",__FUNCTION__,__LINE__,i2c->adapter.nr);
#if defined(CONFIG_SPI_I2C_DEBUG)
#endif
return 0;
}
static int spi_i2c_remove(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver spi_i2c_driver = {
.probe = spi_i2c_probe,
.remove = spi_i2c_remove,
.driver = {
.owner = THIS_MODULE,
.name = DRV_NAME,
},
};
static int __init spi_i2c_adap_init(void)
{
printk(" *************Enter::%s,LINE=%d ************\n",__FUNCTION__,__LINE__);
return platform_driver_register(&spi_i2c_driver);
}
static void __exit spi_i2c_adap_exit(void)
{
platform_driver_unregister(&spi_i2c_driver);
}
subsys_initcall(spi_i2c_adap_init);
module_exit(spi_i2c_adap_exit);
MODULE_DESCRIPTION("Driver for spi2i2c.");
MODULE_AUTHOR("swj <swj@rock-chips.com>");
MODULE_LICENSE("GPL");

1184
drivers/fpga/spi_uart.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -512,6 +512,8 @@ struct i2c_msg {
__u16 len; /* msg length */
__u8 *buf; /* pointer to msg data */
__u32 scl_rate;
__u16 channel;
__u16 read_type;
};
/* To determine what functionality is present */