This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

GPIO as SPI Chip Select

Other Parts Discussed in Thread: ADS7846, DM3730

Hi,


I am struggling to find information about using GPIO pin as chip select for SPI bus 2.

I chip_select is a GPIO pin and I am not sure how I can do that. Its own pins are used for other devices but I have to use this bus for IO Extender whose chip select is connected to processor GPIO pin but others are wired direct to McSPI2

Any help in this would be great.


Thanks

Ali

  • Hi Ali,

    You have to pass your GPIO no to ".controller_data" member from SPI.

    GPIO banks and number generation are depends on what device you have used.

    Ex:

            .modalias = "spidev",
            .mode = SPI_MODE_0,
            .max_speed_hz = 30000000,       /* max sample rate at 3V */
            .bus_num = 1,
            .chip_select = 1,
            .controller_data = (void *) 1, // GPIO no : GP0[0] ie

    //        .controller_data = (void *) 21, // GPIO no : GP1[5] = 1*16 +5 => bank no * no of gpio per bank + gpio pin
        },

  • Hi Titus,

    Thanks for the quick response there. I am having to write an SPI driver for XRA1405 IO Expander. Its wired direct to SPI2 but CS of XRA1405 is wired to GPIO 138.

    On SPI2 I have also got touchscreen using SPI2's internel CS0.

    I am not sure how this would work is there any guide you can point me to or any example...

    I have tried to search but could not find anything.

    This is what I have now hope it is correct, before I start coding for the driver.

    static struct spi_board_info HAWK_III_spi_board_info[] = {
        [0] = {
            .modalias        = "ads7846",
            .bus_num        = 2,
            .chip_select        = 0,
            .max_speed_hz        = 1500000,
            .controller_data    = &ads7846_mcspi_config,
            .irq            = OMAP_GPIO_IRQ(HAWK_III_TS_GPIO),
            .platform_data        = &ads7846_config,
        },
        [1]={
            .modalias            = "xra1405",
            .bus_num            = 2,
            .chip_select        = 1,
            .max_speed_hz        = 1500000,
            .controller_data    = (void *)138,
            .irq                = OMAP_GPIO_IRQ(HAWK_III_EXPANDER_IRQ_GPIO),
        },
    };

  • Hi Ali,

    Your configurations seems to be okay.

    Are you facing any issues ?

    Also please make sure that you have access for GPIO 138  ie you have done PINMUX correctly for the GPIO 138.

  • Hi Titus,


    Thanks for the reply. Yes pin mux is ok for GPIO 138. Just check that. Also the McSPI2_CS1 is shared between three devices via GPIO CS pins which are GPIO 138, 136, 55

    Am i correct in saying that if I define .controller_data as

    struct select_device {

    shared_devices device;

    unsigned char cs_gpio;

    }

    enum shared_devices {

    DEVICE1, // All are same IO Extender cards

    DEVICE2,

    DEVICE3

    }

    .controller_data = &select_device;

    This way when I read and write to a device by checking which one needs to be spoken to and toggle the appropriate GPIO line or is there a better way to do it.

  • Hi Ali,

    What processor are you using ?

    Please refer to the following TI E2E thread for SPI configuring.

    http://e2e.ti.com/support/embedded/linux/f/354/p/356928/1254237.aspx

  • Hi Titus,

    I am using DM3730.

  • Hi Ali,

    Why do you want to replace GPIO for dedicated CS pin ?

    Are you using that pin for any other purpose  (different peripheral USB2 or GPIO or PWM or MM2_TXEN) ?

    Also the McSPI2_CS1 is shared between three devices via GPIO CS pins which are GPIO 138, 136, 55

    BTW, sorry. I'm not able to understand what you meant the above statement.

    I thought that you are using GPIO_138 pin as CS for McSPI2, then how about GPIO136 and 55 ?

  • Hi Titus,

    I don't think I have explained this properly. Here is what I have.

    I am using McSPI2 which has internal two chip selects. One of them McSPI2_CS0 is used for Touch Screen and the other is not connected to any thing McSPI2_CS1.

    I have three slave devices which are Two IO Extenders (XRA1405) and one CAN device. The CS of all these are connected to the GPIO pins on DM3730. For two IO extenders its GPIO 138 and 136 and for CAN its 55.

    I hope I have got this right. Please let me know if not clear.

    Regards

  • Hi Titus,

    I am not sure what is going on here but I dont seem to get a clock going when I transmit / receive on SPI. I can see the data being transmitted on the scope but no clock.

    Any idea's what it could be. I have tried all modes on SPI with and without SPI_CS_HIGH and nothing seems to generate anything on the clock.

    This is the same clock which is used by the touch screen ADS7846. That works fine. When I use the touch on touchscreen I see the clock appear on SPI device I am trying to talk to but when I specifically transmit on SPI bus to the slave device (IO Expander) I can see data being transmitted but no clock.

    Any help would be great

    Regards

    Ali

  • Hi Ali,

    This is the same clock which is used by the touch screen ADS7846. That works fine. When I use the touch on touchscreen I see the clock appear on SPI device I am trying to talk to but when I specifically transmit on SPI bus to the slave device (IO Expander) I can see data being transmitted but no clock.

    Have you checked the status of SPI CS of IO expander and  SPI CS of touch screen while accessing that device ?

    Please check the SPI CS of IO expander which is configured through GPIO.

    Please make sure that you have not done the multilple pinmux for the same pin.

  • Hi Titus,

    I have looked at that and it seems OK. I am sure its a stupid mistake of some CS bit in the register. I am just struggling to print the register contents of MCSPI_CHxCONF

    This is what I have in my code.

    static struct spi_board_info HAWK_III_spi_board_info[] = {
        [0] = {
            .modalias        = "ads7846",
            .bus_num        = 2,
            .chip_select        = 0,
            .max_speed_hz        = 1500000,
            .controller_data    = &ads7846_mcspi_config,
            .irq            = OMAP_GPIO_IRQ(HAWK_III_TS_GPIO),
            .platform_data        = &ads7846_config,
        },
        [1] = {
                .modalias            = "xra1405",
                .bus_num            = 2,
                .chip_select        = 1,
                .max_speed_hz        = 1500000,
                .controller_data    = &xra1405_mcspi_config,
                .irq                = OMAP_GPIO_IRQ(HAWK_III_EXPANDER_IRQ_GPIO),
                .platform_data        = &xra1405_config,
        },
    };

    static struct omap2_mcspi_device_config ads7846_mcspi_config = {
        .turbo_mode    = 0,
        .single_channel    = 1,    /* 0: slave, 1: master */
    };

    static struct omap2_mcspi_device_config xra1405_mcspi_config = {
        .turbo_mode    = 0,
        .single_channel    = 1,    /* 0: slave, 1: master */
    };

    ********************* DRIVER ROUTINE ******************

    static int __devinit xra1405_probe(struct spi_device *spi)
    {
        struct xra1405 *ts;
        struct xra1405_platform_data *pdata = spi->dev.platform_data;
        struct device *dev;
        int ret,i,j;
        int read = 30;
        u16 val = 0x10;

        /* bits_per_word cannot be configured in platform data */
        spi->bits_per_word = 8;
        spi->mode = SPI_MODE_0;

        ret = spi_setup(spi);



        if (ret < 0)
            return ret;

        ts = kzalloc(sizeof(struct xra1405), GFP_KERNEL);
        if (!ts)
            return -ENOMEM;

        dev_set_drvdata(&spi->dev, ts);
        ts->pdata = pdata;
        ts->spi = spi;
        ts->read = xra1405_spi_read;
        ts->write = xra1405_spi_write;

        mutex_init(&ts->lock);
        init_waitqueue_head(&ts->wait);

        ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;


        if(ret) goto exit_destroy;

        for(j=0; j<10; j++)
        {
            for (i=0; i<22; i++)
            {
                read = xra1405_spi_read(&spi->dev, (i << 1));
                read = xra1405_spi_write(&spi->dev, (i << 1), 0x10);
            }
        }
        return ret;
        exit_destroy:
            dev_set_drvdata(dev, NULL);
            mutex_destroy(&ts->lock);
            return ret;
    }

    static void null_wait_for_sync(void)
    {
    }



    /* A read from the XRA1405 means two transfers; here, one message each */
    struct ser_message {
        u8            command;
        u8            rx_byte;
        struct spi_message    msg;
        struct spi_transfer    xfer[2];
    };
    static int xra1405_spi_read(struct device *dev, unsigned int reg)
    {

        struct spi_device *spi = to_spi_device(dev);
        struct xra1405 *ts = dev_get_drvdata(dev);
        struct ser_message *req;
        int status;



        req = kzalloc(sizeof *req, GFP_KERNEL);
        if (!req)
            return -ENOMEM;

        spi_message_init(&req->msg);
        req->command = 0x80 | reg;

        req->xfer[0].tx_buf = &req->command;
        req->xfer[0].len = 1;
        spi_message_add_tail(&req->xfer[0], &req->msg);

        req->xfer[1].rx_buf = &req->rx_byte;
        req->xfer[1].len = 1;
        req->xfer[1].delay_usecs = 100;
        spi_message_add_tail(&req->xfer[1], &req->msg);

        mutex_lock(&ts->lock);
        status = spi_sync(spi, &req->msg);
        mutex_unlock(&ts->lock);

        if (status)
        {
            printk(KERN_INFO "SPI READ ERROR");
            return status;
        }
        printk(KERN_INFO "Received Byte %d ",req->rx_byte);
        kfree(req);
        return status;
    }


    static int xra1405_spi_write(struct device *dev, unsigned int reg,
                    unsigned int val)
    {


    struct spi_device *spi = to_spi_device(dev);
        struct xra1405 *ts = dev_get_drvdata(dev);
        struct ser_message *req;
        int status;


        req = kzalloc(sizeof *req, GFP_KERNEL);
        if (!req)
            return -ENOMEM;

        spi_message_init(&req->msg);
        req->command = reg;

        req->xfer[0].tx_buf = &req->command;
        req->xfer[0].len = 1;
        spi_message_add_tail(&req->xfer[0], &req->msg);

        req->xfer[1].tx_buf = &val;
        req->xfer[1].len = 1;
        spi_message_add_tail(&req->xfer[1], &req->msg);


        mutex_lock(&ts->lock);
        status = spi_sync(spi, &req->msg);
        mutex_unlock(&ts->lock);

        if (status)
        {
            printk(KERN_INFO "SPI Write ERROR");
            return status;
        }
        printk(KERN_INFO "Written Byte %d",val);
        kfree(req);
        return status;

    }

  • Hi Titus,

    I am struggling the read the SPI registers to see what is happening to my SPI bus. I can see data being transmitted but no clock. Is there anything I can look up on to read the CHCONF and CTRL registers.

    Thanks

    Ali