I think you are making this much more difficult than it needs to be. The standard linux SPI device works fine for talking to any slave device. What you need to do is to connect one device to CS0 and the other device to CS1, and then tell the (one) driver to use one or the other chip select when you open() the slave. If you had two drivers controlling the same SPI hardware, then you could interleave register accesses! You don't want to do that. You want each SPI read, write, or ioctl to access one of your devices in an atomic manner.

If the standard SPI driver you are using does not support anything but CS0, then you need to add support for the other chip select.


On 10/28/2014 7:16 PM, [email protected] wrote:


On Saturday, October 25, 2014 4:43:02 PM UTC-7, [email protected] wrote:

    *Background*

    I have a Beagle Bone Black cape with both a Nordic nRF51822 and TI
    CC2520. Both of these devices are on the SPI0 bus. I have kernel
    drivers that work for each separately on Debian 3.8.13.

    *Goal*

    I would like to be able to load both kernel drivers at the same
    time and have them share the SPI bus.

    *Issue*

    While I have figured out how to make each kernel driver take
    control of the SPI0 bus when loaded separately, I can't seem to
    get them to each have access when loaded together. I'm far from an
    expert on device tree overlays and am not sure how to glue
    everything together so that the kernel drives are successfully loaded.

    Here is my code so far in the kernel driver that pertains to
    creating the SPI device for the nRF51822. I create a struct
    spi_driver with config information and then call
    module_spi_driver() to init, etc. (copied from
    /linux/drivers/net/ieee802154/cc2520.c). The probe() function
    callback sets up a character device and configures some GPIOs
    (that code needs to be updated to work with device tree, but for
    now it should be fine).


    |
    staticintnrf51822_spi_probe(structspi_device *spi_device)
    {
        ERR(KERN_INFO,"Inserting SPI protocol driver.\n");
        nrf51822_spi_device =spi_device;

        //
        // Create a buffer to move data over the character device
        //
        ...

    //
    // Setup the interrupt from the nRF51822
    //
        ...

    //
    // Configure the character device in /dev
    //
        ...

    return0;
    }

    staticintnrf51822_spi_remove(structspi_device *spi_device)
    {
        ERR(KERN_INFO,"Removing SPI protocol driver.");
        nrf51822_spi_device =NULL;

        // Free memory and close things
    }


    staticconststructspi_device_id nrf51822_ids[]={
    {"nrf51822",},
    {},
    };
    MODULE_DEVICE_TABLE(spi,nrf51822_ids);


    staticconststructof_device_id nrf51822_of_ids[]={
    {.compatible ="brad,nrf51822",},
    {},
    };
    MODULE_DEVICE_TABLE(of,nrf51822_of_ids);


    // Configure SPI
    staticstructspi_driver nrf51822_spi_driver ={
    .driver ={
    .name =nrf51822_name,
    .owner =THIS_MODULE,
    .bus =&spi_bus_type,
    .of_match_table =of_match_ptr(nrf51822_of_ids),
    },
    .id_table =nrf51822_ids,
    .probe =nrf51822_spi_probe,
    .remove =nrf51822_spi_remove,
    };

    // This I believe will load this driver correctly
    // and cause it to be probed when it is needed.
    module_spi_driver(nrf51822_spi_driver);

    MODULE_LICENSE("GPL");
    MODULE_AUTHOR(DRIVER_AUTHOR);
    MODULE_DESCRIPTION(DRIVER_DESC);
    |

    And here is my attempt at a device overlay. I'm only claiming a
    single GPIO which I use as an interrupt from the nRF51822 back to
    the beagle bone.

    |
    /dts-v1/;
    /plugin/;

    / {
        compatible = "ti,beaglebone", "ti,beaglebone-black";

            /*identification */
            part-number = "BB-BONE-NRF51822";
            version = "00A0";

            /*state the resources thiscape uses */
            exclusive-use =
                    /*the pin header uses */

                    /*GPIO */
                    "P9.16",       /*InterruptfromNRF51822 */

                    /*the hardware ip uses */
                    "gpio1_19";


            fragment@0 {
                    target = <&am33xx_pinmux>;
                    __overlay__ {
                            bb_cc2520_gpio_pins:
    pinmux_bb_2520_gpio_pins {
                                compatible = "nrf51822";
                        pinctrl-single,pins = <
                                        /*GPIO */
                                        0x04C 0x2F
    /*ehrpwm1b.gpio1_19,INPUT |MODE7 */
                                >;
                            };
                    };
            };

            fragment@1 {
                    target = <&ocp>;
                    __overlay__ {
        nrf51822 {
                                    compatible = "brad,nrf51822";

                                    /*the power control gpio */
                                    interrupt-gpio = <&gpio1 19 0x0>;

                                    /*the muxing */
                                    pinctrl-names ="default";
                                    pinctrl-0=<&nrf51822_pins>;
    };
    };
    };
    };
    |

    The end effect is that my probe() function in the kernel driver is
    never called, even after loading the overlay and kernel module.

    How do I set things up so that two kernel modules can both use
    SPI0? Has anyone tried this? Everything I've looked at appears to
    assume only one device is attached to the SPI bus so it can
    specify the SPI pins in its .dts file (but I could be wrong about
    that).

    Thanks for any help or direction.


You don't say where your got the drivers, I couldn't find either in linux-3.16.1. Under normal use spi0 will be controlled by spi/spi-omap2-mcspi.c, as indicated by its inclusion of the compatible entry "ti,omap4-mcspi". See am33xx.dtsi for the definition of this term.
By using modprobe, etc. you are bypassing this logic.
I believe you may need a master driver that will control the bus, and slave drivers that can manage each device. They could communicate using some kind of message passing.
--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected] <mailto:[email protected]>.
For more options, visit https://groups.google.com/d/optout.

--
For more options, visit http://beagleboard.org/discuss
--- You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to