mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
FPGA ICE65L08XX Driver:SPI2UART SPI2GPIO SPI2I2C SPI2DPRAM
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -29,6 +29,7 @@
|
||||
*.lzma
|
||||
*.patch
|
||||
*.gcno
|
||||
Untitled Project.*
|
||||
|
||||
#
|
||||
# Top-level generic files
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig"
|
||||
|
||||
source "drivers/spi/Kconfig"
|
||||
|
||||
source "drivers/fpga/Kconfig"
|
||||
|
||||
source "drivers/pps/Kconfig"
|
||||
|
||||
source "drivers/gpio/Kconfig"
|
||||
|
||||
@@ -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
86
drivers/fpga/Kconfig
Normal 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
10
drivers/fpga/Makefile
Normal 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
654
drivers/fpga/spi_dpram.c
Normal 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<6F><78>0x3ffe
|
||||
#define AP_SEND_BP_Mailbox<6F><78>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
495
drivers/fpga/spi_fpga.h
Normal 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); //<2F><><EFBFBD>庯<EFBFBD><E5BAAF>ָ<EFBFBD><D6B8>, <20><><EFBFBD>ڵ<EFBFBD><DAB5>þ<EFBFBD><C3BE>Ե<EFBFBD>ַ
|
||||
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С<41><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD> 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
|
||||
434
drivers/fpga/spi_fpga_init.c
Normal file
434
drivers/fpga/spi_fpga_init.c
Normal 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<70><69>д<EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-----------------------*/
|
||||
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
740
drivers/fpga/spi_gpio.c
Normal 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
445
drivers/fpga/spi_i2c.c
Normal 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<72><65>
|
||||
{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
1184
drivers/fpga/spi_uart.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user