Message ID | 1460978308-8062-2-git-send-email-bhuvanchandra.dv@toradex.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, Apr 18, 2016 at 04:48:27PM +0530, Bhuvanchandra DV wrote: > +++ b/Documentation/ABI/testing/sysfs-bus-spi-spidev > @@ -0,0 +1,8 @@ > +What: /sys/bus/spi/drivers/spidev/new_id > +Date: March 2016 > +Description: > + This allows to load spidev at runtime. new_id file accepts bus > + number and chip select in 'B.C' format. > + e.g. > + To load spidev1.1 at runtime: > + $ echo 1.1 > /sys/bus/spi/drivers/spidev/new_id I would expect a new_id file to allow a new device identifier to be added to a driver at runtime but this isn't doing that, it's specifying by bus and chip select instead which is totally different to how we normally bind SPI devices. That seems likely to cause confusion down the line. I'd expect to be able to supply a DT compatible string or a Linux SPI ID.
On 04/18/2016 06:31 PM, Mark Brown wrote: > On Mon, Apr 18, 2016 at 04:48:27PM +0530, Bhuvanchandra DV wrote: > >> +++ b/Documentation/ABI/testing/sysfs-bus-spi-spidev >> @@ -0,0 +1,8 @@ >> +What: /sys/bus/spi/drivers/spidev/new_id >> +Date: March 2016 >> +Description: >> + This allows to load spidev at runtime. new_id file accepts bus >> + number and chip select in 'B.C' format. >> + e.g. >> + To load spidev1.1 at runtime: >> + $ echo 1.1 > /sys/bus/spi/drivers/spidev/new_id > > I would expect a new_id file to allow a new device identifier to be > added to a driver at runtime but this isn't doing that, it's specifying > by bus and chip select instead which is totally different to how we > normally bind SPI devices. That seems likely to cause confusion down > the line. I'd expect to be able to supply a DT compatible string or a > Linux SPI ID. SPI drivers bind to the device as configured in DT, but in case of spidev(non DT approach) the device is not available in hand to bind the driver. So tried this approach of creating the device and then bind spidev. I agree this is not a standard way we bind SPI devices. With out a device available, seems it is not possible to bind spidev in non DT approach. Please correct me if i'm wrong. >
On Wed, Apr 20, 2016 at 05:43:32PM +0530, Bhuvanchandra DV wrote: > SPI drivers bind to the device as configured in DT, but in case of > spidev(non DT approach) the device is not available in hand to bind the > driver. So tried this approach of creating the device and then bind spidev. > I agree this is not a standard way we bind SPI devices. With out a device > available, seems it is not possible to bind spidev in non DT approach. > Please correct me if i'm wrong. The DT should describe the hardware so the DT should describe whatever device is connected to the spidev, what you're trying to do is have spidev bind to these new compatible strings.
On 04/20/2016 05:47 PM, Mark Brown wrote: > On Wed, Apr 20, 2016 at 05:43:32PM +0530, Bhuvanchandra DV wrote: > >> SPI drivers bind to the device as configured in DT, but in case of >> spidev(non DT approach) the device is not available in hand to bind the >> driver. So tried this approach of creating the device and then bind spidev. >> I agree this is not a standard way we bind SPI devices. With out a device >> available, seems it is not possible to bind spidev in non DT approach. >> Please correct me if i'm wrong. > > The DT should describe the hardware so the DT should describe whatever > device is connected to the spidev, what you're trying to do is have > spidev bind to these new compatible strings. The device which i was pointing earlier is the SPI master device(spiB.C) not the external h/w device interfaced to it. Yes, DT will describe the h/w interfaced on SPI master device(spiB.C). In case of spidev we are not supposed to describe in DT as it is not a real h/w. The intention of this patchset is to completely avoid spidev in DT and load it via sysfs new_id file for selected SPI master device(spiB.C). >
On Wed, Apr 20, 2016 at 06:41:11PM +0530, Bhuvanchandra DV wrote: > On 04/20/2016 05:47 PM, Mark Brown wrote: > >The DT should describe the hardware so the DT should describe whatever > >device is connected to the spidev, what you're trying to do is have > >spidev bind to these new compatible strings. > The device which i was pointing earlier is the SPI master device(spiB.C) not > the external h/w device interfaced to it. Yes, DT will describe the h/w > interfaced on SPI master device(spiB.C). In case of spidev we are not > supposed to describe in DT as it is not a real h/w. The intention of this > patchset is to completely avoid spidev in DT and load it via sysfs new_id > file for selected SPI master device(spiB.C). This is the problem, you've not understood what spidev is. spidev is providing access to a slave device so it binds to the slave device.
diff --git a/Documentation/ABI/testing/sysfs-bus-spi-spidev b/Documentation/ABI/testing/sysfs-bus-spi-spidev new file mode 100644 index 0000000..3f6e092 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-spi-spidev @@ -0,0 +1,8 @@ +What: /sys/bus/spi/drivers/spidev/new_id +Date: March 2016 +Description: + This allows to load spidev at runtime. new_id file accepts bus + number and chip select in 'B.C' format. + e.g. + To load spidev1.1 at runtime: + $ echo 1.1 > /sys/bus/spi/drivers/spidev/new_id diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index e3c19f3..99e9842 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -667,6 +667,57 @@ static int spidev_release(struct inode *inode, struct file *filp) return 0; } +/** + * new_id_store - add a new spidevB.C instance + * @driver: target device driver + * @buf: buffer for scanning bus number and chip select + * @count: input size + * + * Adds a new dynamic spidev instance based on the requested bus number + * and chip select. + */ +static ssize_t new_id_store(struct device_driver *drv, const char *buf, + size_t count) +{ + int ret; + u32 bus, cs; + struct spi_device *spi; + struct spi_master *master; + + ret = sscanf(buf, "%u.%u", &bus, &cs); + + if (ret < 2) + return -EINVAL; + + master = spi_busnum_to_master(bus); + if (!master) + return -ENODEV; + + if (cs >= master->num_chipselect) + return -ENODEV; + + spi = spi_alloc_device(master); + if (!spi) { + dev_err(&master->dev, "Couldn't allocate spidev device\n"); + return -ENOMEM;; + } + + spi->chip_select = cs; + master->bus_num = bus; + + strlcpy(spi->modalias, "spidev", sizeof(spi->modalias)); + + ret = spi_add_device(spi); + if (ret) { + dev_err(&master->dev, "Couldn't add spidev device\n"); + spi_dev_put(spi); + return ret; + } + + return count; +} +static DRIVER_ATTR_WO(new_id); + static const struct file_operations spidev_fops = { .owner = THIS_MODULE, /* REVISIT switch to aio primitives, so that userspace @@ -817,21 +868,33 @@ static int __init spidev_init(void) 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 = PTR_ERR(spidev_class); + goto err_unregister_chrdev; } status = spi_register_driver(&spidev_spi_driver); - if (status < 0) { - class_destroy(spidev_class); - unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); - } + if (status < 0) + goto err_destroy_class; + + status = driver_create_file(&spidev_spi_driver.driver, &driver_attr_new_id); + if (status < 0) + goto err_unregister_driver; + + return status; + +err_unregister_driver: + spi_unregister_driver(&spidev_spi_driver); +err_destroy_class: + class_destroy(spidev_class); +err_unregister_chrdev: + unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); return status; } module_init(spidev_init); static void __exit spidev_exit(void) { + driver_remove_file(&spidev_spi_driver.driver, &driver_attr_new_id); spi_unregister_driver(&spidev_spi_driver); class_destroy(spidev_class); unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);