21,619
社区成员
发帖
与我相关
我的任务
分享
void spi_set_cs0(int value)
{
volatile unsigned int reg;
switch (value) {
//Select
case 0:
reg = ioread32(spi_addr0 + S3C_SLAVE_SEL);
reg &= ~(SPI_SLAVE_SIG_INACT);
iowrite32(reg, spi_addr0 + S3C_SLAVE_SEL);
udelay(30);
break;
//Non-Select
case 1:
reg = ioread32(spi_addr0 + S3C_SLAVE_SEL);
reg |= SPI_SLAVE_SIG_INACT;
iowrite32(reg, spi_addr0 + S3C_SLAVE_SEL);
udelay(30);
break;
}
}
void spi_init0(void)
{
volatile unsigned int reg, mode;
volatile unsigned int spi_chcfg;
volatile unsigned int gpc_tmp;
s3c_gpio_cfgpin(S3C64XX_GPC(0), S3C64XX_GPC0_SPI_MISO0);
s3c_gpio_cfgpin(S3C64XX_GPC(1), S3C64XX_GPC1_SPI_CLK0);
s3c_gpio_cfgpin(S3C64XX_GPC(2), S3C64XX_GPC2_SPI_MOSI0);
s3c_gpio_cfgpin(S3C64XX_GPC(3), S3C64XX_GPC3_SPI_nCS0);
s3c_gpio_setpull(S3C64XX_GPC(0), S3C_GPIO_PULL_NONE);
s3c_gpio_setpull(S3C64XX_GPC(1), S3C_GPIO_PULL_NONE);
s3c_gpio_setpull(S3C64XX_GPC(2), S3C_GPIO_PULL_NONE);
s3c_gpio_setpull(S3C64XX_GPC(3), S3C_GPIO_PULL_NONE);
//set GPC
gpc_tmp = ioread32(gpc_addr + 0x0);
printk("gpc_tmp = 0x%x\n", gpc_tmp);
gpc_tmp = ioread32(gpc_addr + 0x8);
printk("gpc_tmp = 0x%x\n", gpc_tmp);
iowrite32(0xf, gpc_addr + 0x4);
udelay(100);
gpc_tmp = ioread32(gpc_addr + 0x4);
printk("gpc_tmp = 0x%x\n", gpc_tmp);
//s3c6410 SPI reset
iowrite32(ioread32(spi_addr0 + S3C_CH_CFG) | SPI_CH_SW_RST, \
spi_addr0 + S3C_CH_CFG);
udelay(100);
iowrite32(ioread32(spi_addr0 + S3C_CH_CFG) & (~SPI_CH_SW_RST), \
spi_addr0 + S3C_CH_CFG);
udelay(100);
//Set transfer type
//spi_chcfg &= ~SPI_CH_HSPD_EN;
//spi_chcfg &= (~SPI_CH_HSPD_EN) | (SPI_CH_FORMAT_A | SPI_CH_RISING | SPI_CH_MASTER);
//spi_chcfg |= SPI_CH_FORMAT_A | SPI_CH_RISING | SPI_CH_MASTER;
//iowrite32(spi_chcfg, spi_addr0 + S3C_CH_CFG);
iowrite32((1 << 3)|(1 << 2)|(0 << 6), spi_addr0 + S3C_CH_CFG);
udelay(100);
//clock config
iowrite32((ioread32(S3C_PCLK_GATE) | S3C_CLKCON_PCLK_SPI0 | \
S3C_CLKCON_PCLK_SPI1), S3C_PCLK_GATE);
iowrite32((ioread32(S3C_SCLK_GATE) | S3C_CLKCON_SCLK_SPI0 | \
S3C_CLKCON_SCLK_SPI1), S3C_SCLK_GATE);
iowrite32(ioread32(S3C_CLK_SRC) | S3C_CLKSRC_MPLL_CLKSEL, S3C_CLK_SRC);
//Set spi clock to DOUT(266Mhz)
iowrite32((ioread32(S3C_CLK_SRC) & ~(0X3 << 14)) | (0x1 << 14), \
S3C_CLK_SRC);
//SPI Input Clock(88.87Mhz) = 266.66Mhz / (2 + 1)
iowrite32(((ioread32(S3C_CLK_DIV2) & ~(0XFF << 0)) | 5), S3C_CLK_DIV2);
iowrite32(ioread32(spi_addr0 + S3C_CLK_CFG) & (~SPI_ENCLK_ENABLE), \
spi_addr0 + S3C_CLK_CFG);
udelay(100);
reg = ioread32(spi_addr0 + S3C_CLK_CFG);
reg |= (0x2 << 9)|(35 << 0);
//iowrite32(reg | (0X2 << 9) | (35 << 0), spi_addr0 + S3C_CLK_CFG);
udelay(100);
iowrite32(SPI_ENCLK_ENABLE, spi_addr0 + S3C_CLK_CFG);
udelay(100);
spi_chcfg = ioread32(spi_addr0 + S3C_CLK_CFG);
printk("spi_clkcfg = 0x%x\n", spi_chcfg);
//Mode cfg
mode = SPI_MODE_CH_TSZ_BYTE | SPI_MODE_BUS_TSZ_BYTE;
//mode |= (SPI_MODE_RXDMA_OFF | SPI_MODE_TXDMA_OFF | 0x1 << 11);
mode |= (SPI_MODE_RXDMA_OFF | SPI_MODE_TXDMA_OFF);
iowrite32(mode, spi_addr0 + S3C_MODE_CFG);
udelay(100);
mode = ioread32(spi_addr0 + S3C_MODE_CFG);
printk("mode = 0x%x\n", mode);
// disable SPI Interrupt
iowrite32(SPI_INT_ALL_DISABLE, spi_addr0 + S3C_SPI_INT_EN);
//Slave_sel cfg
iowrite32(0x0, spi_addr0 + S3C_SLAVE_SEL);
}
void spi_start0(void)
{
volatile unsigned int tmp;
tmp = ioread32(spi_addr0 + S3C_CH_CFG);
tmp |= 0x3;
iowrite32(tmp, spi_addr0 + S3C_CH_CFG);
}
static unsigned short mcp3002_read_data(unsigned short cmd)
{
int i;
unsigned short tmp;
unsigned short data = 0;
tmp = cmd;
gpio_set_value(S3C64XX_GPC(3), 1);
gpio_set_value(S3C64XX_GPC(1), 0);
udelay(50);
gpio_set_value(S3C64XX_GPC(3), 0);
udelay(50);
for (i = 15; i >= 0; i--) {
gpio_set_value(S3C64XX_GPC(1), 0);
if (i > 10) {
if ((tmp >> i) & 0x01)
gpio_set_value(S3C64XX_GPC(2), 1);
else
gpio_set_value(S3C64XX_GPC(2), 0);
} else {
if (gpio_get_value(S3C64XX_GPC(0)))
data |= 1 << i;
}
ndelay(140);
gpio_set_value(S3C64XX_GPC(1), 1);
ndelay(140);
}
return data;
}
static ssize_t mcp_read(struct file *filp, char __user *buf, \
size_t count, loff_t *f_pos)
{
unsigned short cmd = 0;
unsigned short value[3];
#if 0
unsigned int spi_int;
//spi_int = SPI_INT_RX_FIFORDY_EN | SPI_INT_RX_UNDERRUN_EN | SPI_INT_RX_OVERRUN_EN | SPI_INT_TRAILING_EN;
//iowrite32(spi_int, spi_addr0 + S3C_SPI_INT_EN);
mdelay(1);
spi_start0();
spi_set_cs0(1);
udelay(140);
spi_set_cs0(0);
udelay(140);
cmd = ((1 << 6) | (1 << 5) | (0 << 4) | (1 << 3));
iowrite8(cmd, spi_addr0 + S3C_SPI_TX_DATA);
//wait_for_completion(&rx_done);
udelay(50);
value[0] = ioread8(spi_addr0 + S3C_SPI_RX_DATA);
spi_set_cs0(1);
spi_stop0();
printk(DEVICE_NAME " value[0] = 0x%x\n", rx);
#endif
#if 1
//芯片的设置请查看mcp3002第13页, 15页
cmd = ((1 << 14) | (1 << 13) | (0 << 12) | (0 << 11));
value[0] = mcp3002_read_data(cmd);
//printk(DEVICE_NAME " value[0] = 0x%x\n", value[0]);
#endif
if (copy_to_user(buf, &value[0], 2)) {
return -EFAULT;
}
return count;
}
static ssize_t mcp_write(struct file *filp, const char __user *buf, \
size_t count, loff_t *f_pos)
{
return count;
}
static int mcp_open(struct inode *inode, struct file *filp)
{
printk("mcp is opened\n");
try_module_get(THIS_MODULE);
return 0;
}
static int mcp_release(struct inode *inode, struct file *filp)
{
printk("mcp is closed\n");
module_put(THIS_MODULE);
return 0;
}
static struct file_operations mcp_fops = {
.owner = THIS_MODULE,
.open = mcp_open,
.release = mcp_release,
.write = mcp_write,
.read = mcp_read,
};
static irqreturn_t mcp_spi_irq(int irq, void *dev)
{
int err = 0;
unsigned int pend = ioread32(spi_addr0 + S3C_SPI_STATUS);
printk("===mcp irq: %d===\n", irq);
printk("pend = 0x%x\n", pend);
iowrite32(SPI_INT_ALL_DISABLE, spi_addr0 + S3C_SPI_INT_EN);
if(pend & SPI_STUS_RX_OVERRUN_ERR)
{
printk(DEVICE_NAME " RX FIFO overrun error\n");
iowrite32(SPI_PND_RX_OVERRUN_CLR, spi_addr0 + S3C_PENDING_CLR);
err = 1;
}
if(pend & SPI_STUS_RX_UNDERRUN_ERR)
{
printk(DEVICE_NAME " RX FIFO underrun error\n");
iowrite32(SPI_PND_RX_UNDERRUN_CLR, spi_addr0 + S3C_PENDING_CLR);
err = 1;
}
if(pend & SPI_STUS_TX_OVERRUN_ERR)
{
printk(DEVICE_NAME " TX FIFO overrun error\n");
iowrite32(SPI_PND_TX_OVERRUN_CLR, spi_addr0 + S3C_PENDING_CLR);
err = 1;
}
if(pend & SPI_STUS_TX_UNDERRUN_ERR)
{
printk(DEVICE_NAME " TX FIFO underrun error\n");
iowrite32(SPI_PND_TX_UNDERRUN_CLR, spi_addr0 + S3C_PENDING_CLR);
err = 1;
}
if(pend & SPI_STUS_TX_FIFORDY)
{
printk(DEVICE_NAME " TX FIFO ready\n");
}
if(pend & SPI_STUS_RX_FIFORDY)
{
printk(DEVICE_NAME " RX FIFO ready\n");
}
if(err)
{
printk("====s3c_spi_irq error===\n");
complete(&rx_done);
return IRQ_HANDLED;
}
if (pend & SPI_STUS_RX_FIFOLVL) {
rx = ioread8(spi_addr0 + S3C_SPI_RX_DATA);
complete(&rx_done);
return IRQ_HANDLED;
}
complete(&rx_done);
return IRQ_HANDLED;
}
static void spi_gpio_init(void)
{
//init mcp interface
//gpio_direction_input(S3C64XX_GPC(0));
//gpio_direction_output(S3C64XX_GPC(1), 1);
//gpio_direction_output(S3C64XX_GPC(2), 1);
//gpio_direction_output(S3C64XX_GPC(3), 1);
s3c_gpio_cfgpin(S3C64XX_GPC(0), S3C_GPIO_INPUT);
s3c_gpio_cfgpin(S3C64XX_GPC(1), S3C_GPIO_OUTPUT);
s3c_gpio_cfgpin(S3C64XX_GPC(2), S3C_GPIO_OUTPUT);
s3c_gpio_cfgpin(S3C64XX_GPC(3), S3C_GPIO_OUTPUT);
s3c_gpio_setpull(S3C64XX_GPC(0), S3C_GPIO_PULL_NONE);
s3c_gpio_setpull(S3C64XX_GPC(1), S3C_GPIO_PULL_NONE);
s3c_gpio_setpull(S3C64XX_GPC(2), S3C_GPIO_PULL_NONE);
s3c_gpio_setpull(S3C64XX_GPC(3), S3C_GPIO_PULL_NONE);
}
static int mcp_probe(struct platform_device *dev)
{
int ret;
ret = register_chrdev(SPI_MAJOR, DEVICE_NAME, &mcp_fops);
if (ret < 0)
return ret;
if (!request_mem_region(GPC_PHYS_ADDR, 0x20, DEVICE_NAME)) {
printk(KERN_ERR "mcp:IO %X is not free\n", GPC_PHYS_ADDR);
return -EBUSY;
}
if (!request_mem_region(SPI0_PHYS_ADDR, 0xff, DEVICE_NAME)) {
printk(KERN_ERR "mcp:IO %X is not free\n", SPI0_PHYS_ADDR);
return -EBUSY;
}
gpc_addr = ioremap(GPC_PHYS_ADDR, 0x20);
if (gpc_addr < 0) {
printk(KERN_ERR "mcp: ioremap failed\n");
iounmap(gpc_addr);
return -EINVAL;
}
spi_addr0 = ioremap(SPI0_PHYS_ADDR, 0xff);
if (spi_addr0 < 0) {
printk(KERN_ERR "mcp: ioremap failed\n");
iounmap(spi_addr0);
return -EINVAL;
}
/*
err = request_irq(IRQ_SPI0, mcp_spi_irq, IRQF_DISABLED, \
DEVICE_NAME, NULL);
if (err) {
printk(DEVICE_NAME " cannot request irq\n");
return -1;
}
//init_completion(&rx_done);
*/
spi_init0();
//spi_gpio_init();
return 0;
}