xilinx zynq7000, ad9361与spi驱动移植问题
心上枫叶红 2018-07-23 11:47:50 各位大神请教一下。我用的是xilinux zynq7000的板子。我现在,需要移植SPI驱动和ADI的AD9361驱动进去。添加spidev.c驱动执行到init函数之后probe函数就没执行了。在/sys/bus/spi/drivers目录下有spidev驱动。但是/dev目录下一直没有设备文件。而且ad9361编译之后在报错好像就是因为是spi驱动的问题。我想知道这是怎么回事?谢谢
spidev.c的部分驱动
static int spidev_probe(struct spi_device *spi)
{
printk("========================enter spi0_probe======================\n");
struct spidev_data *spidev;
int status;
unsigned long minor;
/*
* spidev should never be referenced in DT without a specific
* compatible string, it is a Linux implementation thing
* rather than a description of the hardware.
*/
if (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) {
dev_err(&spi->dev, "buggy DT: spidev listed directly in DT\n");
WARN_ON(spi->dev.of_node &&
!of_match_device(spidev_dt_ids, &spi->dev));
}
/* Allocate driver data */
spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
if (!spidev)
return -ENOMEM;
/* Initialize the driver data */
spidev->spi = spi;
spin_lock_init(&spidev->spi_lock);
mutex_init(&spidev->buf_lock);
INIT_LIST_HEAD(&spidev->device_entry);
/* If we can allocate a minor number, hook up this device.
* Reusing minors is fine so long as udev or mdev is working.
*/
mutex_lock(&device_list_lock);
minor = find_first_zero_bit(minors, N_SPI_MINORS);
if (minor < N_SPI_MINORS) {
struct device *dev;
spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
dev = device_create(spidev_class, &spi->dev, spidev->devt,
spidev, "spidev%d.%d",
spi->master->bus_num, spi->chip_select);
status = PTR_ERR_OR_ZERO(dev);
} else {
dev_dbg(&spi->dev, "no minor number available!\n");
status = -ENODEV;
}
if (status == 0) {
set_bit(minor, minors);
list_add(&spidev->device_entry, &device_list);
}
mutex_unlock(&device_list_lock);
spidev->speed_hz = spi->max_speed_hz;
if (status == 0)
spi_set_drvdata(spi, spidev);
else
kfree(spidev);
return status;
}
static int spidev_remove(struct spi_device *spi)
{
struct spidev_data *spidev = spi_get_drvdata(spi);
printk("========================enter spi remove======================\n");
/* make sure ops on existing fds can abort cleanly */
spin_lock_irq(&spidev->spi_lock);
spidev->spi = NULL;
spin_unlock_irq(&spidev->spi_lock);
/* prevent new opens */
mutex_lock(&device_list_lock);
list_del(&spidev->device_entry);
device_destroy(spidev_class, spidev->devt);
clear_bit(MINOR(spidev->devt), minors);
if (spidev->users == 0)
kfree(spidev);
mutex_unlock(&device_list_lock);
return 0;
}
static struct spi_driver spidev_spi_driver = {
.driver = {
.name = "spidev",
.of_match_table = of_match_ptr(spidev_dt_ids),
},
.probe = spidev_probe,
.remove = spidev_remove,
/* NOTE: suspend/resume methods are not necessary here.
* We don't do anything except pass the requests to/from
* the underlying controller. The refrigerator handles
* most issues; the controller driver handles the rest.
*/
};
/*-------------------------------------------------------------------------*/
static int __init spidev_init(void)
{
int status;
/* Claim our 256 reserved device numbers. Then register a class
* that will key udev/mdev to add/remove /dev nodes. Last, register
* the driver which manages those device numbers.
*/
BUILD_BUG_ON(N_SPI_MINORS > 256);
status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);
if (status < 0)
return status;
spidev_class = class_create(THIS_MODULE, "spidev");
if (IS_ERR(spidev_class)) {
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
return PTR_ERR(spidev_class);
}
status = spi_register_driver(&spidev_spi_driver);
if (status < 0) {
class_destroy(spidev_class);
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
}
printk("==============:%d:==========spi0_init out ======================\n",status);
return status;
}
module_init(spidev_init);
内核打印信息::
bootconsole [earlycon0] disabled
bootconsole [earlycon0] disabled
xdevcfg f8007000.devcfg: ioremap 0xf8007000 to f08b0000
[drm] Initialized drm 1.1.0 20060810
brd: module loaded
loop: module loaded
==============:0:==========spi0_init out ======================
m25p80 spi0.0: SPI-NOR-UniqueID 0000000000000000000000000000000000
m25p80 spi0.0: m25p80 (2048 Kbytes)
4 ofpart partitions found on MTD device spi0.0
Creating 4 MTD partitions on "spi0.0":
0x000000000000-0x000000500000 : "boot"
mtd: partition "boot" extends beyond the end of device "spi0.0" -- size truncated to 0x200000
0x000000500000-0x000000520000 : "bootenv"
mtd: partition "bootenv" is out of reach -- disabled
0x000000520000-0x000000fa0000 : "kernel"
mtd: partition "kernel" is out of reach -- disabled
0x000000fa0000-0x000000200000 : "spare"
mtd: partition "spare" is out of reach -- disabled
CAN device driver interface
libphy: MACB_mii_bus: probed
macb e000b000.ethernet eth0: Cadence GEM rev 0x00020118 at 0xe000b000 irq 146 (00:0a:35:00:1e:53)
Generic PHY e000b000.etherne:00: attached PHY driver [Generic PHY] (mii_bus:phy_addr=e000b000.etherne:00, irq=-1)
e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ehci-pci: EHCI PCI platform driver
usbcore: registered new interface driver usb-storage
mousedev: PS/2 mouse device common for all mice
i2c /dev entries driver
EDAC MC: ECC not enabled
Xilinx Zynq CpuIdle Driver started
sdhci: Secure Digital Host Controller Interface driver
sdhci: Copyright(c) Pierre Ossman
sdhci-pltfm: SDHCI platform and OF driver helper
mmc0: SDHCI controller on e0101000.sdhci [e0101000.sdhci] using ADMA
ledtrig-cpu: registered to indicate activity on CPUs
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
ad9361 spi32766.0: ad9361_probe : enter (ad9361)
ad9361 spi32766.0: ---------------gpio:0--------------------------!
ad9361 spi32766.0: --------------------------1----------------!
ad9361 spi32766.0: SPI transfer timed out
ad9361 spi32766.0: Write Error -110
ad9361 spi32766.0: SPI transfer timed out
ad9361 spi32766.0: Write Error -110
ad9361 spi32766.0: ad9361_reset: by SPI, this may cause unpredicted behavior!
ad9361 spi32766.0: SPI transfer timed out
ad9361 spi32766.0: Read Error -110
ad9361 spi32766.0: ad9361_probe : Unsupported PRODUCT_ID 0xFFFFFF92
NET: Registered protocol family 10
sit: IPv6 over IPv4 tunneling driver
NET: Registered protocol family 17
can: controller area network core (rev 20120528 abi 9)
NET: Registered protocol family 29
can: raw protocol (rev 20120528)
can: broadcast manager protocol (rev 20120528 t)
can: netlink gateway (rev 20130117) max_hops=1
zynq_pm_remap_ocm: OCM pool is not available
zynq_pm_suspend_init: Unable to map OCM.
Registering SWP/SWPB emulation handler
hctosys: unable to open rtc device (rtc0)
这里ad9361的部分驱动代码:
static int ad9361_reset(struct ad9361_rf_phy *phy)
{
dev_err(&phy->spi->dev, " ---------------gpio:%d--------------------------!\n",phy->pdata->reset_gpio);
if (phy->pdata->reset_gpio) {
dev_err(&phy->spi->dev, " --------------------------in----------------!\n");
gpiod_set_value(phy->pdata->reset_gpio, 0);
mdelay(1);
gpiod_set_value(phy->pdata->reset_gpio, 1);
mdelay(1);
dev_dbg(&phy->spi->dev, "%s: by GPIO", __func__);
return 0;
}
dev_err(&phy->spi->dev, " --------------------------1----------------!\n");
/* SPI Soft Reset was removed from the register map, since it doesn't
* work reliably. Without a prober HW reset randomness may happen.
* Please specify a RESET GPIO.
*/
ad9361_spi_write(phy->spi, REG_SPI_CONF, SOFT_RESET | _SOFT_RESET);
ad9361_spi_write(phy->spi, REG_SPI_CONF, 0x0);
dev_err(&phy->spi->dev,
"%s: by SPI, this may cause unpredicted behavior!", __func__);
return -ENODEV;
}
static int ad9361_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct ad9361_rf_phy *phy;
struct clk *clk = NULL;
int ret, rev;
dev_info(&spi->dev, "%s : enter (%s)", __func__,
spi_get_device_id(spi)->name);
clk = devm_clk_get(&spi->dev, NULL);
if (IS_ERR(clk)) {
return -EPROBE_DEFER;
}
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*phy));
if (indio_dev == NULL)
return -ENOMEM;
phy = iio_priv(indio_dev);
phy->indio_dev = indio_dev;
phy->spi = spi;
phy->clk_refin = clk;
phy->pdata = ad9361_phy_parse_dt(indio_dev, &spi->dev);
if (phy->pdata == NULL)
return -EINVAL;
phy->pdata->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(phy->pdata->reset_gpio))
return PTR_ERR(phy->pdata->reset_gpio);
/* Optional: next three used for MCS synchronization */
phy->pdata->sync_gpio = devm_gpiod_get_optional(&spi->dev, "sync",
GPIOD_OUT_LOW);
if (IS_ERR(phy->pdata->sync_gpio))
return PTR_ERR(phy->pdata->sync_gpio);
phy->pdata->cal_sw1_gpio = devm_gpiod_get_optional(&spi->dev, "cal-sw1",
GPIOD_OUT_LOW);
if (IS_ERR(phy->pdata->cal_sw1_gpio))
return PTR_ERR(phy->pdata->cal_sw1_gpio);
phy->pdata->cal_sw2_gpio = devm_gpiod_get_optional(&spi->dev, "cal-sw2",
GPIOD_OUT_LOW);
if (IS_ERR(phy->pdata->cal_sw2_gpio))
return PTR_ERR(phy->pdata->cal_sw2_gpio);
phy->current_table = -1;
phy->bypass_tx_fir = true;
phy->bypass_rx_fir = true;
phy->rate_governor = 1;
phy->rfdc_track_en = true;
phy->bbdc_track_en = true;
phy->quad_track_en = true;
phy->gt_info = ad9361_adi_gt_info;
ad9361_request_gt(phy, NULL);
ad9361_reset(phy);
ret = ad9361_spi_read(spi, REG_PRODUCT_ID);
if ((ret & PRODUCT_ID_MASK) != PRODUCT_ID_9361) {
dev_err(&spi->dev, "%s : Unsupported PRODUCT_ID 0x%X",
__func__, ret);
return -ENODEV;
}
rev = ret & REV_MASK;
if (spi_get_device_id(spi)->driver_data == ID_AD9364) {
phy->pdata->rx2tx2 = false;
phy->pdata->rx1tx1_mode_use_rx_num = 1;
phy->pdata->rx1tx1_mode_use_tx_num = 1;
}
.....................................