- 论坛徽章:
- 0
|
本帖最后由 120620056 于 2012-11-22 10:36 编辑
平台:FDI3250(LPC3250)
环境:linux2.6.39.2
SSP兼SPI控制器L022
外设:8通道AD7888 只有一个可写8位寄存器
问题:照AD7887_core.c 写了一个外设驱动AD7888_core.c,发现示波器只在读驱动时CS会拉低,时钟线只在50MV时有抖动,数据进出线没有反应,spi_sync返回值为零,通道数据返回零。
板级文件:
static struct pl022_ssp_controller lpc32xx_ssp0_data = {
.bus_id = 0,
.num_chipselect = 2,
.enable_dma = 0,
};
static struct amba_device lpc32xx_ssp0_device = {
.dev = {
.coherent_dma_mask = ~0,
.init_name = "dev:ssp0",
.platform_data = &lpc32xx_ssp0_data,
},
.res = {
.start = LPC32XX_SSP0_BASE,
.end = (LPC32XX_SSP0_BASE + SZ_4K - 1),
.flags = IORESOURCE_MEM,
},
.dma_mask = ~0,
.irq = {IRQ_LPC32XX_SSP0, NO_IRQ},
};
static struct pl022_config_chip spi0_chip_info = {
.com_mode = INTERRUPT_TRANSFER,
.iface = SSP_INTERFACE_MOTOROLA_SPI,
.hierarchy = SSP_MASTER,
.slave_tx_disable = 0,
.clk_freq = {
.cpsdvsr= 2,
.scr= 8,
},
.rx_lev_trig = SSP_RX_4_OR_MORE_ELEM,
.tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC,
.ctrl_len = SSP_BITS_8,
.wait_state = SSP_MWIRE_WAIT_ZERO,
.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
.cs_control = fdi3250_spi_cs_set,
};
static int __init fdi3250_spi_devices_register(void)
{
static struct spi_board_info info[] = {
{
.modalias = "ad7888",
.max_speed_hz=2500000,
.bus_num = 0,
.chip_select = 0,
.controller_data = &spi0_chip_info,
.platform_data = &spi_ad7888,
},
};
return spi_register_board_info(info, ARRAY_SIZE(info));
}
arch_initcall(fdi3250_spi_devices_register);
static struct amba_device *amba_devs[] __initdata = {
&lpc32xx_ssp0_device,
};
static int __init fdi3250_amba_devices_register(void)
{
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
struct amba_device *d = amba_devs;
amba_device_register(d, &iomem_resource);
}
return 0;
}
device_initcall_sync(fdi3250_amba_devices_register);
驱动:
struct ad7888_platform_data {
u16 vref_mv;
bool en_dual;
bool use_onchip_ref;
};
static const struct ad7888_chip_info ad7888_chip_info_tbl[] = {
/*
119 * More devices added in future
120 */
[ID_AD7888] = {
.bits = 12,
.storagebits = 16,
.left_shift = 0,
.sign=IIO_SCAN_EL_TYPE_UNSIGNED,
.int_vref_mv = 2500,
},
};
static int ad7888_scan_direct(struct ad7888_state *st, unsigned ch)
{
int ret = spi_sync(st->spi, &st->msg[ch]);
if (ret)
return ret;
printk("ret=%d\n",ret);
return (st->data[(ch * 2)] << | st->data[(ch * 2) + 1];
}
static ssize_t ad7888_scan(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *dev_info = dev_get_drvdata(dev);
struct ad7888_state *st = dev_info->dev_data;
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
mutex_lock(&dev_info->mlock);
printk("ad7888_scan_direat\n"
ret = ad7888_scan_direct(st, this_attr->address);
mutex_unlock(&dev_info->mlock);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", (ret >> st->chip_info->left_shift) &
RES_MASK(st->chip_info->bits));
}
static IIO_DEV_ATTR_IN_RAW(0, ad7888_scan, 0);
static IIO_DEV_ATTR_IN_RAW(1, ad7888_scan, 1);
static struct attribute *ad7888_attributes[]={
&iio_dev_attr_in0_raw.dev_attr.attr,
&iio_dev_attr_in1_raw.dev_attr.attr,
NULL,
};
static const struct attribute_group ad7888_attribute_group={
.attrs=ad7888_attributes,
// .is_visible=
};
static int __devinit ad7888_probe(struct spi_device *spi)
{
printk("ad7888_probe\n"
struct ad7888_platform_data *pdata=spi->dev.platform_data;
printk("use_onchip_ref=%d\n",pdata->use_onchip_ref);
struct ad7888_state *st;
int ret,voltage_uv=0;
st=kzalloc(sizeof(*st),GFP_KERNEL);
if(st == NULL){
ret=-ENOMEM;
goto error_ret;
}
st->reg=regulator_get(&spi->dev,"vcc"
if(!IS_ERR(st->reg)){
ret=regulator_enable(st->reg);
if(ret)
goto error_put_reg;
voltage_uv=regulator_get_voltage(st->reg);
}
st->chip_info=&ad7888_chip_info_tbl[spi_get_device_id(spi)->driver_data];
spi_set_drvdata(spi,st);
atomic_set(&st->protect_ring,0);
st->spi=spi;
st->indio_dev=iio_allocate_device();
if(st->indio_dev == NULL){
ret = -ENOMEM;
goto error_disable_reg;
}
st->indio_dev->dev.parent = &spi->dev;
st->indio_dev->attrs = &ad7888_attribute_group;
st->indio_dev->dev_data = (void *)(st);
st->indio_dev->driver_module= THIS_MODULE;
st->indio_dev->modes =INDIO_DIRECT_MODE;
st->tx_cmd_buf[0]=0x00;
st->xfer[0].rx_buf = &st->data[0];
st->xfer[0].tx_buf = &st->tx_cmd_buf[0];
st->xfer[0].len=2;
spi_message_init(&st->msg[0]);
spi_message_add_tail(&st->xfer[0],&st->msg[0]);
st->tx_cmd_buf[2]=0x08;
st->xfer[1].rx_buf = &st->data[0];
st->xfer[1].tx_buf = &st->tx_cmd_buf[2];
st->xfer[1].len=2;
st->tx_cmd_buf[4]=0x00;
st->xfer[2].rx_buf = &st->data[2];
st->xfer[2].tx_buf = &st->tx_cmd_buf[4];
st->xfer[2].len=2;
spi_message_init(&st->msg[1]);
spi_message_add_tail(&st->xfer[1],&st->msg[1]);
spi_message_add_tail(&st->xfer[2],&st->msg[1]);
st->tx_cmd_buf[6]=0x08;
st->xfer[3].rx_buf = &st->data[0];
st->xfer[3].tx_buf= &st->tx_cmd_buf[6];
st->xfer[3].len=2;
spi_message_init(&st->msg[2]);
spi_message_add_tail(&st->xfer[3],&st->msg[2]);
if(pdata && pdata->use_onchip_ref)
st->int_vref_mv = st->chip_info->int_vref_mv;
printk("st->mv=%ld\n",st->int_vref_mv);
ret=iio_device_register(st->indio_dev);
return 0;
error_disable_reg:
if(!IS_ERR(st->reg))
regulator_disable(st->reg);
error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
kfree(st);
error_ret:
return ret;
}
static int ad7888_remove(struct spi_device *spi)
{
return 0;
}
static struct spi_device_id ad7888_id[]={
{"ad7888",ID_AD7888},
{}
};
static struct spi_driver ad7888_driver={
.driver={
.name="ad7888",
.bus=&spi_bus_type,
.owner=THIS_MODULE,
},
.probe=ad7888_probe,
.remove=__devexit_p(ad7888_remove),
.id_table = ad7888_id,
};
static int __init ad7888_init(void)
{
return spi_register_driver(&ad7888_driver);
}
static void __exit ad7888_exit(void)
{
spi_unregister_driver(&ad7888_driver);
}
module_init(ad7888_init);
module_exit(ad7888_exit);
MODULE_AUTHOR("xianfu_wu <wuxianfu163@163.com>"
MODULE_LICENSE("GPL"
|
|