/****************************************Copyright (c)**************************************************
** Guangzou ZLG-MCU Development Co.,LTD.
** graduate school
** http://www.zlgmcu.com
**
**--------------File Info-------------------------------------------------------------------------------
** File name: spi.c
** Last modified Date: 2005-04-29
** Last Version: 1.0
** Descriptions: This is a Kernel module for uClinux 2.4.x .
** This module let uClinux 2.4.x can use spi.
**------------------------------------------------------------------------------------------------------
** Created by: Chenmingji
** Created date: 2005-04-29
** Version: 1.0
** Descriptions: The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**
********************************************************************************************************/
#define IN_SPI
#include "config.h"
/********************************************************************************************************
function announce
********************************************************************************************************/
#if 0
static loff_t spi_llseek(struct file *filp, loff_t off, int whence);
#endif
static ssize_t spi_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos);
static ssize_t spi_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
static int spi_open(struct inode *inode, struct file *filp);
static int spi_release(struct inode *inode, struct file *filp);
static int spi_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long param);
int spi_init(void);
void spi_cleanup(void);
/********************************************************************************************************
define announce
********************************************************************************************************/
#define MAJOR_NR major
module_init(spi_init);
module_exit(spi_cleanup);
MODULE_PARM(major, "i");
MODULE_LICENSE("Proprietary");
MODULE_DESCRIPTION("Guangzou ZLG-MCU Development Co.,LTD.\ngraduate school\nhttp://www.zlgmcu.com");
MODULE_SUPPORTED_DEVICE("uClinux2.4.x LPC2200 spi");
MODULE_AUTHOR("chenmingji");
/*********************************************************************************************************
** "全局和静态变量在这里定义"
** global variables and static variables define here
********************************************************************************************************/
typedef struct Spi_Dev
{
u32 BaseAddr;
unsigned int usage; /* device using count */
struct semaphore sem; /* mutual exclusion semaphore */
} Spi_Dev;
static int major = SPI_MAJOR_NR;
static u32 PinSel0Save, PinSel1Save;
Spi_Dev SpiDevices[MAX_SPI];
/********************************************************************************************************/
static struct file_operations spi_fops = /* driver info */
{
owner: THIS_MODULE,
#if 0
llseek: spi_llseek,
#endif
write: spi_write,
read: spi_read,
ioctl: spi_ioctl,
open: spi_open,
release: spi_release,
};
#if 0
/*********************************************************************************************************
** Function name: spi_llseek
** Descriptions: move read and write point
** Input: filp: pointer of file
** off: ofset
** whence: move mode
** 0: seek set
** 1: seek file' current point
** 2: seek file' end
** Output : new point
** Created by: Chenmingji
** Created Date: 2005-4-29
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
static loff_t spi_llseek(struct file *filp, loff_t off, int whence)
{
return 0;
}
#endif
/*********************************************************************************************************
** Function name: spi_read
** Descriptions: read device
** Input: filp: pointer of file
** buf: buf for save data
** count: size for read
** f_pos: *f_pos = read point
** Output : read size
** Created by: Chenmingji
** Created Date: 2005-4-29
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
static ssize_t spi_read(struct file *filp, char *buf, size_t count,
loff_t *f_pos)
{
size_t i;
unsigned int temp;
Spi_Dev *dep;
if (!access_ok(VERIFY_WRITE, (void *)buf, _IOC_SIZE(cmd)))
{
return -EFAULT;
}
dep = filp->private_data;
i = count;
do
{
outl(0, dep->BaseAddr + S0PDR - S0PCR);
while (1)
{
temp = inl(dep->BaseAddr + S0PSR - S0PCR);
if ((temp & (1 << 7)) != 0)
{
break;
}
if (temp != 0)
{
goto end;
}
}
temp = inl(dep->BaseAddr + S0PDR - S0PCR);
put_user(temp, (u8 *)buf);
buf++;
} while (--i != 0);
end:
return count - i;
}
/*********************************************************************************************************
** Function name: spi_write
** Descriptions: write device
** Input: filp: pointer of file
** buf: buf to write data
** count: size for read
** f_pos: *f_pos = read point
** Output : write size
** Created by: Chenmingji
** Created Date: 2005-4-29
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
static ssize_t spi_write(struct file *filp, const char *buf, size_t count,
loff_t *f_pos)
{
size_t i;
unsigned int temp;
Spi_Dev *dep;
if (!access_ok(VERIFY_READ, (void *)buf, count))
{
return -EFAULT;
}
dep = filp->private_data;
i = count;
do
{
get_user(temp, (u8 *)buf);
outl(temp, dep->BaseAddr + S0PDR - S0PCR);
while (1)
{
temp = inl(dep->BaseAddr + S0PSR - S0PCR);
if ((temp & (1 << 7)) != 0)
{
break;
}
if (temp != 0)
{
goto end;
}
}
inl(dep->BaseAddr + S0PDR - S0PCR);
buf++;
} while (--i != 0);
end:
return count - i;
}
/*********************************************************************************************************
** Function name: spi_open
** Descriptions: open device
** Input:inode: information of device
** filp: pointer of fil