- 论坛徽章:
- 0
|
本帖最后由 zhanghonghu84 于 2010-03-30 10:24 编辑
小菜鸟最近在写一个SPI接口的AD驱动,用的是AD7888,主芯片是at91sam9260,在文件board-sam9260ek.c中,把结构体改成如下了
static struct spi_board_info ek_spi_devices[] = {
/*
#if !defined(CONFIG_MMC_AT91)
{ // DataFlash chip
.modalias = "mtd_dataflash",
// .chip_select = 1,
.chip_select = 0, //zhh
.max_speed_hz = 15 * 1000 * 1000,
.bus_num = 0,
},
#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
{ // DataFlash card
.modalias = "mtd_dataflash",
.chip_select = 0,
.max_speed_hz = 15 * 1000 * 1000,
.bus_num = 0,
},
#endif
#endif
*/
#if defined(CONFIG_AD788
{ /* spi ad */
.modalias = "ad7888",
.chip_select = 0,
.max_speed_hz = 15 * 1000 * 1000,
.bus_num = 0,
.mode = SPI_MODE_0,
},
#endif
#if defined(CONFIG_MMC_SPI)
{ /* DataFlash card */
.modalias = "mmc_spi",
.chip_select = 1,
.max_speed_hz = 15 * 1000 * 1000,
.bus_num = 0,
},
#endif
#if defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
{ /* AT73C213 DAC */
.modalias = "at73c213",
.chip_select = 0,
.max_speed_hz = 10 * 1000 * 1000,
.bus_num = 1,
.mode = SPI_MODE_1,
.platform_data = &at73c213_data,
},
#endif
};
然后参照其他的驱动,自己编写了一个AD7888的驱动,如下
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
/*
DONTC ZERO ADD2 ADD1 ADD0 REF PM1 PM0
Bit Mnemonic Comment
7 DONTC Don’t Care. The value written to this bit of the Control Register is a don’t care, i.e., it doesn’t matter if the bit is
0 or 1.
6 ZERO A zero must be written to this bit to ensure correct operation of the AD7888.
5 ADD2 These three address bits are loaded at the end of the present conversion sequence and select which analog input
4 ADD1 channel is converted for the next conversion. The selected input channel is decoded as shown in Table II.
3 ADD0
2 REF Reference Bit. With a 0 in this bit, the on-chip reference is enabled. With a 1 in this bit, the on-chip reference
is disabled. To obtain best performance from the AD7888, the internal reference should be disabled when
using an externally applied reference source. (See On-Chip Reference section.)
1, 0 PM1, PM0 Power Management Bits. These two bits decode the mode of operation of the AD7888 as shown in Table III.
PM1 PM0 MODE
0 0 Normal Operation. In this mode, the AD7888
remains in full power mode regardless of the
status of any of the logic inputs. This mode
allows the fastest possible throughput rate from
the AD7888.
0 1 Full Shutdown. In this mode, the AD7888 is
in full shutdown mode with all circuitry on the
AD7888, including the on-chip reference, entering
its power-down mode. The AD7888 retains
the information in the control Register bits
while in full shutdown. The part remains in full
shutdown until these bits are changed.
1 0 Autoshutdown. In this mode, the AD7888
automatically enters full shutdown mode at the
end of each conversion. Wake-up time from full
shutdown is 5 μs and the user should ensure that
5 μs have elapsed before attempting to perform
a valid conversion on the part in this mode.
1 1 Autostandby. In this standby mode, portions
of the AD7888 are powered down but the onchip
reference voltage remains powered up. The
REF bit should be 0 to ensure the on-chip reference
is enabled. This mode is similar to autoshutdown
but allows the part to power-up
much faster.
*/
/*
bit7 0
bit6 0
bit5/4/3 地址
bit2 0 我们采用内部参考电压 参考电压为2.5V
bit1/0 0/0 为了简便,采用正常模式,
*/
// AD通道定义
#define AD_ADD1_REG 0x00
#define AD_ADD2_REG 0x08
#define AD_ADD3_REG 0x10
#define AD_ADD4_REG 0x18
#define AD_ADD5_REG 0x20
#define AD_ADD6_REG 0x28
#define AD_ADD7_REG 0x30
#define AD_ADD8_REG 0x38
#define MAX_AD_CHANNEL 8 // the max channel num
//global
char ad7888_rx_buf[MAX_AD_CHANNEL];
int ad7888_tx_buf[MAX_AD_CHANNEL];
/*
* NOTE: this is an *AD* driver.
* Handle SPI chips with the drivers/spi/
*
*/
struct ad7888_data {
struct spi_device *spi;
struct mutex lock;
};
/*******************************************************************************
* Function Name : void ad7888_init(void)
* Description : ad7888 init
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void ad7888_init(void)
{
}
/*******************************************************************************
* Function Name : void ad7888_exit(void)
* Description : ad7888 exit
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void ad7888_exit(void)
{
}
/*******************************************************************************
* Function Name : static int ad7888_read_reg(struct spi_device *spi, int reg)
* Description : depend on the channel to read ad7888 ad data
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static int ad7888_read_reg(struct spi_device *spi, int reg)
{
char buf[2];
buf[0] = reg;
buf[1] = 0;
spi_write_then_read(spi, buf, 1, buf, 2);
return buf[1] << 8 | buf[0];
}
/*******************************************************************************
* Function Name : static int ad7888_read_reg(struct spi_device *spi, int reg)
* Description : depend on the channel to read ad7888 ad data
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static int ad7888_probe(struct spi_device *spi)
{
struct ad7888_data *ts = NULL;
int ret;
/* Chip description 暂时不加*/
//AD7888 上升沿接收数据,下降沿发送数据,选择模式0,16位数据(前4为0),MSB在前 默认可以不写
spi->mode = SPI_MODE_0;
spi->bits_per_word = 8;
ret = spi_setup(spi);
if (ret < 0)
return ret;
ts = kzalloc(sizeof(struct ad7888_data), GFP_KERNEL);
if (!ts)
{
ret = -ENOMEM;
return ret;
}
mutex_init(&ts->lock);
ts->spi = spi_dev_get(spi);
dev_set_drvdata(&spi->dev, ts);
/* Ping the chip ... the status register is pretty portable,
* unlike probing manufacturer IDs. We do expect that system
* firmware didn't write it in the past few milliseconds!
*/
/*
ret = spi_w8r16(spi, AD_ADD8_REG);
if (ret <= 0) {
dev_dbg(&spi->dev, "rdsr --> %d (%02x)\n", ret, ret);
ret = -ENXIO;
goto fail;
}
*/
// 注册设备
// ret = device_register(&ts->spi->dev);
// if (ret)
// goto fail;
fail:
dev_dbg(&spi->dev, "probe err %d\n", ret);
dev_set_drvdata(&spi->dev, NULL);
mutex_destroy(&ts->lock);
kfree(ts);
return ret;
}
static int ad7888_remove(struct spi_device *spi)
{
struct ad7888_data *ts;
ts = dev_get_drvdata(&spi->dev);
if (ts == NULL)
return -ENODEV;
dev_set_drvdata(&spi->dev, NULL);
mutex_destroy(&ts->lock);
// 注册设备
// device_unregister(&ts->spi->dev);
kfree(ts);
return 0;
}
static struct spi_driver ad7888_spi_driver = {
.probe = ad7888_probe,
.remove = ad7888_remove,
.driver = {
.name = "ad7888",
.owner = THIS_MODULE,
.bus = &spi_bus_type,
},
};
static int __init ad7888_spi_init(void)
{
ad7888_init();
return spi_register_driver(&ad7888_spi_driver);
}
static void __exit ad7888_spi_exit(void)
{
ad7888_exit();
spi_unregister_driver(&ad7888_spi_driver);
}
module_init(ad7888_spi_init);
module_exit(ad7888_spi_exit);
编译进去启动后,在/sys里面
#ls /sys/bus/spi/devices/spi1.0/
/sys/bus/spi/devices/spi1.0/bus/ /sys/bus/spi/devices/spi1.0/subsystem/
/sys/bus/spi/devices/spi1.0/driver/ /sys/bus/spi/devices/spi1.0/uevent
/sys/bus/spi/devices/spi1.0/modalias
# cat /sys/bus/spi/devices/spi1.0/modalias
ad7888
# ls /sys/bus/spi/drivers/
ad7888 mmc_spi spidev
#
device和driver都找到了,但是我不知道probe函数怎么写,
以下是spi相关的
/**
* struct spi_driver - Host side "protocol" driver
* @probe: Binds this driver to the spi device. Drivers can verify
* that the device is actually present, and may need to configure
* characteristics (such as bits_per_word) which weren't needed for
* the initial configuration done during system setup.
* @remove: Unbinds this driver from the spi device
* @shutdown: Standard shutdown callback used during system state
* transitions such as powerdown/halt and kexec
* @suspend: Standard suspend callback used during system state transitions
* @resume: Standard resume callback used during system state transitions
* @driver: SPI device drivers should initialize the name and owner
* field of this structure.
*
* This represents the kind of device driver that uses SPI messages to
* interact with the hardware at the other end of a SPI link. It's called
* a "protocol" driver because it works through messages rather than talking
* directly to SPI hardware (which is what the underlying SPI controller
* driver does to pass those messages). These protocols are defined in the
* specification for the device(s) supported by the driver.
*
* As a rule, those device protocols represent the lowest level interface
* supported by a driver, and it will support upper level interfaces too.
* Examples of such upper levels include frameworks like MTD, networking,
* MMC, RTC, filesystem character device nodes, and hardware monitoring.
*/
struct spi_driver {
int (*probe)(struct spi_device *spi);
int (*remove)(struct spi_device *spi);
void (*shutdown)(struct spi_device *spi);
int (*suspend)(struct spi_device *spi, pm_message_t mesg);
int (*resume)(struct spi_device *spi);
struct device_driver driver;
};
按照注释
@probe: Binds this driver to the spi device. Drivers can verify
* that the device is actually present, and may need to configure
* characteristics (such as bits_per_word) which weren't needed for
* the initial configuration done during system setup.
它主要有2个作用,把这个驱动绑定到具体的SPI设备上,并能探测到存在的SPI设备,可能会配置一些在系统启动配置不了的参数。
以下是我写的probe函数
/*******************************************************************************
* Function Name : static int ad7888_read_reg(struct spi_device *spi, int reg)
* Description : depend on the channel to read ad7888 ad data
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static int ad7888_probe(struct spi_device *spi)
{
struct ad7888_data *ts = NULL;
int ret;
/* Chip description 暂时不加*/
//AD7888 上升沿接收数据,下降沿发送数据,选择模式0,16位数据(前4为0),MSB在前 默认可以不写
spi->mode = SPI_MODE_0;
spi->bits_per_word = 8;
ret = spi_setup(spi);
if (ret < 0)
return ret;
ts = kzalloc(sizeof(struct ad7888_data), GFP_KERNEL);
if (!ts)
{
ret = -ENOMEM;
return ret;
}
mutex_init(&ts->lock);
ts->spi = spi_dev_get(spi);
dev_set_drvdata(&spi->dev, ts);
/* Ping the chip ... the status register is pretty portable,
* unlike probing manufacturer IDs. We do expect that system
* firmware didn't write it in the past few milliseconds!
*/
/*
ret = spi_w8r16(spi, AD_ADD8_REG);
if (ret <= 0) {
dev_dbg(&spi->dev, "rdsr --> %d (%02x)\n", ret, ret);
ret = -ENXIO;
goto fail;
}
*/
// 注册设备
// ret = device_register(&ts->spi->dev);
// if (ret)
// goto fail;
fail:
dev_dbg(&spi->dev, "probe err %d\n", ret);
dev_set_drvdata(&spi->dev, NULL);
mutex_destroy(&ts->lock);
kfree(ts);
return ret;
}
各位指教一二,看probe函数还要哪些? |
|