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.

Linux/AM5726: SPI fails in U-Boot

Part Number: AM5726
Other Parts Discussed in Thread: SYSCONFIG

Tool/software: Linux

Good Day

I have a issue testing SPI from U-boot. I have scoured the forums for some sort of idea. Here is my issue

I have a design where I have to read some registers from an ADC connected to McSPI0 and McSPI1 buses (CS = 0)

I have read similar experiences but not 100% fixed

When using the

#define OMAP3_MCSPI1_BASE    0x48098000        // Base Address For McSPI0

Calling spi_claim_bus(); the U-boot enters and get stuck in "spi_reset()" function.

I did manage to change the

OMAP3_MCSPI1_BASE    from 0x48098000 to 0x48098100

and at that point the "spi_reset()" execute correctly. (Did not test yet if the SPI actually works)

But I can "claim" the bus, "release" the bus and then "free" the "slave"

But then I have to access the next SPI bus McSPI2

#define OMAP3_MCSPI2_BASE    0x480A8000        // Base Address For McSPI1

Does not matter if I change the Base address to  0x480A8100 or not

This loop then cause the U-boot to fail and reboot!!!! ( and this is in the spi_reset())

Serial print of sequence :

//////////////////////////////////////////////////////////////////////////

//*****************************************************//                   
//**                 SPI Routine                     **//
//*****************************************************//                    
//** Check if AD7768 on SPI Bus 0 is present: Pass   **//                    
//** Check if AD7768 on SPI Bus 1 is present:data abort
                       
pc : [<fef75c3a>]             lr : [<fef62e41>]                                 
reloc pc : [<8081ec3a>]               lr : [<8080be41>]                         
sp : fdf23050  ip : 00000000        fp : 00000017                               
r10: 8084cb50  r9 : fdf36ec0        r8 : fdf38930                               
r7 : 000f4240  r6 : fef98367        r5 : 00000001  r4 : fdf38930                
r3 : 4809a000  r2 : 00000000        r1 : 00000000  r0 : fdf38930                
Flags: nZcv  IRQs off  FIQs off  Mode SVC_32
                                  
Resetting CPU ...                                                                                                                                         
resetting ...

/////////////////////////////////////////////////////////////////////////////////////////////////

1) Am I missing something obvious????

2) Has someone used the SPI in the u-boot for eeprom or other hardware and is there some sample code to refer to?

Thanks Guys...

BTW.. As standard the SPI operates correctly once the Main OS load..thus the SPI and devices are correctly.. Thus I am a bit baffled why the addresses and function dont work as in the ompa3_spi.c

  • Hi Gert van der Merwe,

    It is not good idea to change the OMAP3_MCSPI1_BASE address because this address is related with the hardware and processor registry.
    The proper addresses for McSPI base addresses in AM572x are:
    #define OMAP3_MCSPI1_BASE 0x48098000
    #define OMAP3_MCSPI2_BASE 0x4809A000
    #define OMAP3_MCSPI3_BASE 0x480B8000
    #define OMAP3_MCSPI4_BASE 0x480BA000

    For more details about McSPI registry addresses refer to AM572x TRM section 24.4.6 MCSPI Register Manual at:
    www.ti.com/.../spruhz6j.pdf

    BR
    Tsvetolin Shulev
  • Good Day Tsvetolin

    I agree that to change the base address is not really the correct thing to do..
    But if you read the Manual that you refer to the Base addresses are as indicated in the OMAP3 ..
    But as you also can see from the manual the system and all relevant registers referred to in the manual starts with an offset.
    If you look in the OMAP3 for the AM33xx base map they are also offset with 0x100 from original Register Manual Base address.

    I agree that I still don't want to "cheat" and force the offset. .But as it stands now...

    1) If I use the base map as it suppose to be ... Code execution stops working the moment the call is made for the "Soft Reset" as the code wants to access the address of (Base + 0x10) but SysConfig.Softreset is located at (Base + 0x100 + 0x10)

    2) If I do change the base map to the 0x100 offset then the 1st McSPI works and I can write the "Soft Reset"
    The moment I want to claim the 2nd McSPI (with or without) the base offset the system crashes as indicated by my serial output in my original post.
  • The register addresses are fixed and can not be changed. They are specific for each processor but for some processors are identical but for others differs. Each register address is described in the TRM by base address and offset added to the base.
    You can find some details about soft reset and initialization after that in the TRM section 24.4.5.1.1.2 at:
    www.ti.com/.../spruhz6j.pdf

    BR
    Tsvetolin Shulev
  • Good Day all

    Yes I understand that the Base address is 0x48098000 and the OMAP3 base address are correct as per the Datasheet. When I write a "soft reset" the address the u-boot is writing to is 0x48098010 (tested and verified) - This should be 0x48098110.

    Thus as you can see there is a 0x100 offset missing somewhere

    I think this discussion is getting of topic

    My questions was
    1) Am I missing something where the offset or the address pointers are misaligned...?????
    2) Did someone else here managed to get their McSPI 1 and 2 going for SPI usage.

    Kind Regards
    Gert
  • It looks like the driver has not been updated for AM57xx. From the code
    #if defined(CONFIG_AM33XX) || defined(CONFIG_AM43XX)
    #define OMAP3_MCSPI1_BASE 0x48030100
    #define OMAP3_MCSPI2_BASE 0x481A0100
    #else
    #define OMAP3_MCSPI1_BASE 0x48098000
    #define OMAP3_MCSPI2_BASE 0x4809A000
    #define OMAP3_MCSPI3_BASE 0x480B8000
    #define OMAP3_MCSPI4_BASE 0x480BA000
    #endif

    #define OMAP4_MCSPI_REG_OFFSET 0x100

    For AM57xx the base address is incorrect. You should keep the changes you made, for now. I've filed a ticket in our internal bug tracking system for the software team.

    Steve K.
  • Which SDK is this? The latest few use device-tree and a driver model. I looked later in the driver and found
    static struct omap2_mcspi_platform_config omap2_pdata = {
    .regs_offset = 0,
    };

    static struct omap2_mcspi_platform_config omap4_pdata = {
    .regs_offset = OMAP4_MCSPI_REG_OFFSET,
    };

    static const struct udevice_id omap3_spi_ids[] = {
    { .compatible = "ti,omap2-mcspi", .data = (ulong)&omap2_pdata },
    { .compatible = "ti,omap4-mcspi", .data = (ulong)&omap4_pdata },
    { }
    };

    So if you have the
    { .compatible = "ti,omap4-mcspi", .data = (ulong)&omap4_pdata },

    In your .dts file for your mcspi node, it would work just fine.

    Steve K.
  • Good Day Steve

    Thanks for the reply and I do appreciate the feedback.. Yes.. Initially I did use the V3 SDK and did notice a difference in the V3 and V4 of the SDK.. I then copied the V4 SDK OMAP3_SPI.c and used that.. I did notice there is a OMPA4 offset declaration but I could not see where this is referenced and the U-boot is made aware of this.. (i.e. #define or something to tell the environment to use the .regs_offset of OMPA4).. Thus at this stage I am still using the modified base address and thus far it has not failed me..

    Accessing the MCSPI 1 is also not producing any errors but the moment I try to claim MCSPI 2 the system crashes and reboots.. Still have to investigate

    Currently I do see my expected data on the SCK and MOSI on the MCSPI 1 but I do not see any response from the intended SPI device. .At this stage I do suspect the PIN_MUX or something like that as I think the SPI device and the CPU has a pin clash / fighting .. Still under investigation....

    As our Kernel application in regards to the SPI device is working I do think that the issue is around the low level PIN_MUX, DTS and OMPA3_SPI.c .. but As I can not find any reference source code to establish if I am correct it is sort of a trail and error at the moment...

    Thanks again for the assistance up to this point from the Team Steve and Tsvetolin

    Kind Regards
    Gert

    PS... When I measure the MISO pin I measure 0xFF.. But the return from the function is 0x00 .. Thi sis what indicates to me the PIN_MUX might be wrong

  • Hi All....

    Got the McSPI now working on McSPI1.. When switching to McSPI 2 the system still crashes

    The issue was the OMAP3_SPI.c file where the Mux logic is wrong.. I fixed that and the SPI worked .. I measure with an oscilloscope and the transmit is working as well as the response from the SPI device.. Great

    Whoooooo!!!!!!!

    Now.. the data that I expect is not read correctly and if I

    printf  ((u16 *)rxp)[i] = (u16)readl(rx) from the read function the value is still 0x0000

    This indicate to me that the read function is not correct ... or the address offsets are not working correctly...

    Has anyone used the U-boot McSPI functions successfully with OMAP3_SPI as I think the Address issue is what is killing the SPI at the moment

  • Can you post your mcspi device-tree node and pin mux for mcspi1 and mcspi2?

    Steve K.
  • Good Day Steve

    I will include 3 sets of firmware .. The DTS, Pin Mux and the section of code that is required to read the ADC - SPI

    SPI Function:

    static int read_spi(unsigned char bus_no,unsigned char cs)
    {
        struct spi_slave *slave;
        unsigned int    mode = 0;
          int  j;
                  
        static unsigned short tx_data[2] = {0x8A00};
        static unsigned short rx_data[2] = {0xAA55};               // Load some value in RxData to check if Value is updated later in function
        
        slave = spi_setup_slave(bus_no, cs,100000, mode); // 100Khz

        if (!slave)
            {
             printf("Invalid device %d:%d\n", bus_no, cs);
              return 1;
            }

        spi_claim_bus(slave);    
        
        for (j = 0; j <= 1; j++)    
          {    
            if(spi_xfer(slave, 1*16, tx_data,rx_data, SPI_XFER_BEGIN | SPI_XFER_END) != 0)
                           {
                     printf("Error during SPI transaction\n");
                        return 1;
                    }
          }

        spi_release_bus(slave);
        spi_free_slave(slave);

        if(rx_data[0] != 0x0006)
          {
              printf("0x%04x", rx_data[0]);
            return 1;
          }

        return 0;
    }

    DTS

    spi1_pins_default: spi1_pins_default
            {
                pinctrl-single,pins = <
                0x3a4 (PIN_OUTPUT_PULLUP | MUX_MODE0)        // SPI1_SCK = GPIO7_7  (Ball A25) - Clock     - Output
                0x3a8 (PIN_OUTPUT_PULLUP | MUX_MODE0)        // SPI1_SDI = GPIO7_8  (Ball F16) - MOSI     - Output
                0x3ac (PIN_INPUT_PULLUP  | MUX_MODE0)        // SPI1_SDO = GPIO7_9  (Ball B25) - MISO     - Input
                0x3b0 (PIN_OUTPUT_PULLUP | MUX_MODE0)        // SPI1_CS  = GPIO7_10 (Ball A24) - Chip Select - Output
            >;
            };
            
        spi2_pins_default: spi2_pins_default
            {
                pinctrl-single,pins = <
                0x3c0 (PIN_OUTPUT_PULLUP | MUX_MODE0)        // SPI2_SCK = GPIO7_14  (Ball A25) - Clock     - Output
                0x3c4 (PIN_OUTPUT_PULLUP | MUX_MODE0)        // SPI2_SDI = GPIO7_15  (Ball F16) - MOSI     - Output
                0x3c8 (PIN_INPUT_PULLUP  | MUX_MODE0)        // SPI2_SDO = GPIO7_16  (Ball B25) - MISO     - Input
                0x3d0 (PIN_OUTPUT_PULLUP | MUX_MODE0)        // SPI2_CS  = GPIO7_17  (Ball A24) - Chip Select - Output
            >;
            };

    // Added for the SPI1 define    //
    &mcspi1 {
        status="okay";
        pinctrl-names = "default";
        pinctrl-0 = <&spi1_pins_default>;
        ti,pindir-d0-out-d1-in=<1>;

        spidev@1 {
            spi-max-frequency = <100000>;
            reg = <0>;
            compatible = "ti,omap4-mcspi"; //"rohm,dh2228fv";
        
        };
    };

    // Added for the SPI2 define    //
    &mcspi2 {
        status="okay";
        pinctrl-names = "default";
        pinctrl-0 = <&spi2_pins_default>;
        ti,pindir-d0-out-d1-in=<1>;
        spidev@1 {
            spi-max-frequency = <100000>;
            reg = <0>;
            compatible = "ti,omap4-mcspi"; // "rohm,dh2228fv";
        };
    };

    PinMux

    // This define the PIN Mux for the SPI bus
        {SPI1_SCLK, (M0 | PIN_OUTPUT_PULLUP)},            /* spi1_sclk.gpio7_7 */
        {SPI1_D1,   (M0 | PIN_INPUT_PULLUP)},            /* spi1_d1.gpio7_8 */
        {SPI1_D0,   (M0 | PIN_OUTPUT_PULLUP)},            /* spi1_d0.gpio7_9 */
        {SPI1_CS0,  (M0 | PIN_OUTPUT)},                /* spi1_cs0.gpio7_10 */

        {SPI2_SCLK, (M0 | PIN_OUTPUT_PULLUP)},            /* spi2_sclk.gpio7_14 */
        {SPI2_D1,   (M0 | PIN_INPUT_PULLUP)},            /* spi2_d1.gpio7_15 */
        {SPI2_D0,   (M0 | PIN_OUTPUT_PULLUP)},            /* spi2_d0.gpio7_16 */
        {SPI2_CS0,  (M0 | PIN_OUTPUT)},                /* spi2_cs0.gpio7_17 */

    //**********************************************************************************************//

    In the OMAP_SPI.c the address offset is not set

    static struct omap2_mcspi_platform_config omap2_pdata = {
        .regs_offset = 0,
    };

    static struct omap2_mcspi_platform_config omap4_pdata = {
        .regs_offset = OMAP4_MCSPI_REG_OFFSET,
    };

    static const struct udevice_id omap3_spi_ids[] = {
        { .compatible = "ti,omap2-mcspi", .data = (ulong)&omap2_pdata },
        { .compatible = "ti,omap4-mcspi", .data = (ulong)&omap4_pdata },
        { }
    };

    is never locked correctly and thus without adding the 0x100 to the base address the system is referencing a wrong address waiting for status bits to be cleared or set in the SPI Config or status

    by changing

    #define OMAP3_MCSPI1_BASE    0x48098000

    to

    #define OMAP3_MCSPI1_BASE    0x48098100

    The SPI is sending and receiving.. But I think due to this change the

    MCSPI_RXx

    Address Offset 0x13C + (0x14 * x)                                                  // Index x = 0 to 3
    Physical Address  0x4809 813C + (0x14 * x)

                                      0x4809 A13C + (0x14 * x)

                                      0x480B 813C + (0x14 * x)

                                      0x480B A13C + (0x14 * x)
    Is now incorrect and I read 0x0000 as the reference to the Rx data is now incorrect...

    Kind Regards

    Gert van der Merwe

  • Before I try to recreate this, can you change the
    compatible = "ti,omap4-mcspi"; //"rohm,dh2228fv";
    To
    compatible = "spidev";

    In your device nodes. I've noticed the dra7 dts files match what I expect to work, without changing addresses in the driver.

    Steve K.
  • Good Day Steve

    I have changed the requested compatible reference as you suggested. .and also reset the base address as per the original address reference

    Once started the system boots and the moment it engages the SPI it stops working .. ie waiting for SPI Tx empty register....... And then nothing more

    If I add the 0x100 to the base address the units operates as expected again

    In regards to the "compatible" changes.. I can not see any improvement ..as the return value from the address is still 0x000.

    If you want I can upload the main.c, dts, mux_data and omap3_spi for your reference????

    Regards
    Gert
  • Please upload main.c, dts, and mux_data. I want to debug with the driver in the SDK so you don't have to upload that.

    Steve K.
  • Hi Steve

    These are the file I have been editing to see and get my SPI working

    am57xx-beagle-x15.dts.c
    /*
     * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     */
    /dts-v1/;
    
    #include "dra74x.dtsi"
    #include <dt-bindings/gpio/gpio.h>
    #include <dt-bindings/interrupt-controller/irq.h>
    
    / {
    	model = "TI AM5728 BeagleBoard-X15";
    	compatible = "ti,am572x-beagle-x15", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7";
    	
    	chosen {
    		stdout-path = &uart3;
    	};
    
    	aliases {
    		rtc0 = &mcp_rtc;
    		rtc1 = &tps659038_rtc;
    		rtc2 = &rtc;
    		//display0 = &hdmi0;
    	};
    
    	memory {
    		device_type = "memory";
    		reg = <0x80000000 0x80000000>;
    	};
    
    	vdd_3v3: fixedregulator-vdd_3v3 {
    		compatible = "regulator-fixed";
    		regulator-name = "vdd_3v3";
    		vin-supply = <&regen1>;
    		regulator-min-microvolt = <3300000>;
    		regulator-max-microvolt = <3300000>;
    	};
    
    	vtt_fixed: fixedregulator-vtt {
    		/* TPS51200 */
    		compatible = "regulator-fixed";
    		regulator-name = "vtt_fixed";
    		vin-supply = <&smps3_reg>;
    		regulator-min-microvolt = <3300000>;
    		regulator-max-microvolt = <3300000>;
    		regulator-always-on;
    		regulator-boot-on;
    		enable-active-high;
    		gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>;
    	};
    			
    	led		// This is for the Heartbeat LED on the Numen - GPIO5_4
    	   {
    		compatible = "gpio-leds";
    		pinctrl-names = "default";
    		pinctrl-0 = <&led_pins>;
    
    		led@0 {
    			label = "Numen:usr0";
    			gpios = <&gpio5 4 GPIO_ACTIVE_HIGH>;
    			linux,default-trigger = "heartbeat";
    			default-state = "off";
    		};
    	   };
    	gpio_fan: gpio_fan {
    		/* Based on 5v 500mA AFB02505HHB */
    		compatible = "gpio-fan";
    		gpios =  <&tps659038_gpio 2 GPIO_ACTIVE_HIGH>;
    		gpio-fan,speed-map = <0     0>,
    				     <13000 1>;
    		#cooling-cells = <2>;
    	};
    
    	extcon_usb1: extcon_usb1 {
    		compatible = "linux,extcon-usb-gpio";
    		id-gpio = <&gpio7 25 GPIO_ACTIVE_HIGH>;
    		pinctrl-names = "default";
    		pinctrl-0 = <&extcon_usb1_pins>;
    	};
    
    	extcon_usb2: extcon_usb2 {
    		compatible = "linux,extcon-usb-gpio";
    		id-gpio = <&gpio7 24 GPIO_ACTIVE_HIGH>;
    		pinctrl-names = "default";
    		pinctrl-0 = <&extcon_usb2_pins>;
    	};
    
    };
    
    &dra7_pmx_core {
    	
    	led_pins: led_pins
    		{
    			pinctrl-single,pins = <
    			0x210 (PIN_OUTPUT | MUX_MODE14)	//* gpio5_4 
    		>;
    		};
    
    	spi1_pins_default: spi1_pins_default
    		{
    			pinctrl-single,pins = <
    			0x3a4 (PIN_OUTPUT_PULLUP | MUX_MODE0)		// SPI1_SCK = GPIO7_7  (Ball A25) - Clock 	- Output
    			0x3a8 (PIN_OUTPUT_PULLUP | MUX_MODE0)		// SPI1_SDI = GPIO7_8  (Ball F16) - MOSI 	- Output
    			0x3ac (PIN_INPUT_PULLUP  | MUX_MODE0)		// SPI1_SDO = GPIO7_9  (Ball B25) - MISO 	- Input
    			0x3b0 (PIN_OUTPUT_PULLUP | MUX_MODE0)		// SPI1_CS  = GPIO7_10 (Ball A24) - Chip Select - Output
    		>;
    		};
    		
    	spi2_pins_default: spi2_pins_default
    		{
    			pinctrl-single,pins = <
    			0x3c0 (PIN_OUTPUT_PULLUP | MUX_MODE0)		// SPI2_SCK = GPIO7_14  (Ball A25) - Clock 	- Output
    			0x3c4 (PIN_OUTPUT_PULLUP | MUX_MODE0)		// SPI2_SDI = GPIO7_15  (Ball F16) - MOSI 	- Output
    			0x3c8 (PIN_INPUT_PULLUP  | MUX_MODE0)		// SPI2_SDO = GPIO7_16  (Ball B25) - MISO 	- Input
    			0x3d0 (PIN_OUTPUT_PULLUP | MUX_MODE0)		// SPI2_CS  = GPIO7_17  (Ball A24) - Chip Select - Output
    		>;
    		};
    	
    	i2c1_pins_default: i2c1_pins_default 
    		{
    		pinctrl-single,pins = <
    			0x400 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c1_sda.sda */
    			0x404 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c1_scl.scl */
    		>;
    		};
    
    	i2c3_pins_default: i2c3_pins_default {
    		pinctrl-single,pins = <
    			0x2a4 (PIN_INPUT | MUX_MODE10)	/* mcasp1_aclkx.i2c3_sda */
    			0x2a8 (PIN_INPUT | MUX_MODE10)	/* mcasp1_fsx.i2c3_scl */
    		>;
    	};
    
    	uart3_pins_default: uart3_pins_default {
    		pinctrl-single,pins = <
    			0x3f8 (PIN_INPUT_SLEW | MUX_MODE2) /* uart2_ctsn.uart3_rxd */
    			0x3fc (PIN_INPUT_SLEW | MUX_MODE1) /* uart2_rtsn.uart3_txd */
    		>;
    	};
    
    	mmc1_pins_default: mmc1_pins_default {
    		pinctrl-single,pins = <
    			0x36c (PIN_INPUT | MUX_MODE14)	/* mmc1sdcd.gpio219 */
    			0x354 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */
    			0x358 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */
    			0x35c (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */
    			0x360 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */
    			0x364 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */
    			0x368 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */
    		>;
    	};
    
    	mmc2_pins_default: mmc2_pins_default {
    		pinctrl-single,pins = <
    			0x9c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */
    			0xb0 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
    			0xa0 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */
    			0xa4 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */
    			0xa8 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */
    			0xac (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */
    			0x8c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */
    			0x90 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */
    			0x94 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */
    			0x98 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */
    		>;
    	};
    
    	mmc2_pins_hs: mmc2_pins_hs {
    		pinctrl-single,pins = <
    			0x9c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */
    			0xb0 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
    			0xa0 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */
    			0xa4 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */
    			0xa8 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */
    			0xac (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */
    			0x8c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */
    			0x90 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */
    			0x94 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */
    			0x98 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */
    		>;
    	};
    
    	mmc2_pins_ddr_3_3v: pinmux_mmc2_ddr_3_3v_pins {
    		pinctrl-single,pins = <
    			0x9c (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a23.mmc2_clk */
    			0xb0 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
    			0xa0 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */
    			0xa4 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */
    			0xa8 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */
    			0xac (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */
    			0x8c (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */
    			0x90 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */
    			0x94 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */
    			0x98 (PIN_INPUT_PULLUP | MANUAL_MODE | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */
    		>;
    	};
    
    	cpsw_pins_default: cpsw_pins_default {
    		pinctrl-single,pins = <
    			/* Slave 1 */
    			0x250 (PIN_OUTPUT | MUX_MODE0)	/* rgmii1_tclk */
    			0x254 (PIN_OUTPUT | MUX_MODE0)	/* rgmii1_tctl */
    			0x258 (PIN_OUTPUT | MUX_MODE0)	/* rgmii1_td3 */
    			0x25c (PIN_OUTPUT | MUX_MODE0)	/* rgmii1_td2 */
    			0x260 (PIN_OUTPUT | MUX_MODE0)	/* rgmii1_td1 */
    			0x264 (PIN_OUTPUT | MUX_MODE0)	/* rgmii1_td0 */
    			0x268 (PIN_INPUT | MUX_MODE0)	/* rgmii1_rclk */
    			0x26c (PIN_INPUT | MUX_MODE0)	/* rgmii1_rctl */
    			0x270 (PIN_INPUT | MUX_MODE0)	/* rgmii1_rd3 */
    			0x274 (PIN_INPUT | MUX_MODE0)	/* rgmii1_rd2 */
    			0x278 (PIN_INPUT | MUX_MODE0)	/* rgmii1_rd1 */
    			0x27c (PIN_INPUT | MUX_MODE0)	/* rgmii1_rd0 */
    
    			/* Slave 2 */
    			0x198 (PIN_OUTPUT | MUX_MODE3)	/* rgmii2_tclk */
    			0x19c (PIN_OUTPUT | MUX_MODE3)	/* rgmii2_tctl */
    			0x1a0 (PIN_OUTPUT | MUX_MODE3)	/* rgmii2_td3 */
    			0x1a4 (PIN_OUTPUT | MUX_MODE3)	/* rgmii2_td2 */
    			0x1a8 (PIN_OUTPUT | MUX_MODE3)	/* rgmii2_td1 */
    			0x1ac (PIN_OUTPUT | MUX_MODE3)	/* rgmii2_td0 */
    			0x1b0 (PIN_INPUT | MUX_MODE3)	/* rgmii2_rclk */
    			0x1b4 (PIN_INPUT | MUX_MODE3)	/* rgmii2_rctl */
    			0x1b8 (PIN_INPUT | MUX_MODE3)	/* rgmii2_rd3 */
    			0x1bc (PIN_INPUT | MUX_MODE3)	/* rgmii2_rd2 */
    			0x1c0 (PIN_INPUT | MUX_MODE3)	/* rgmii2_rd1 */
    			0x1c4 (PIN_INPUT | MUX_MODE3)	/* rgmii2_rd0 */
    		>;
    
    	};
    
    	cpsw_pins_sleep: cpsw_pins_sleep {
    		pinctrl-single,pins = <
    			/* Slave 1 */
    			0x250 (PIN_INPUT | MUX_MODE15)
    			0x254 (PIN_INPUT | MUX_MODE15)
    			0x258 (PIN_INPUT | MUX_MODE15)
    			0x25c (PIN_INPUT | MUX_MODE15)
    			0x260 (PIN_INPUT | MUX_MODE15)
    			0x264 (PIN_INPUT | MUX_MODE15)
    			0x268 (PIN_INPUT | MUX_MODE15)
    			0x26c (PIN_INPUT | MUX_MODE15)
    			0x270 (PIN_INPUT | MUX_MODE15)
    			0x274 (PIN_INPUT | MUX_MODE15)
    			0x278 (PIN_INPUT | MUX_MODE15)
    			0x27c (PIN_INPUT | MUX_MODE15)
    
    			/* Slave 2 */
    			0x198 (PIN_INPUT | MUX_MODE15)
    			0x19c (PIN_INPUT | MUX_MODE15)
    			0x1a0 (PIN_INPUT | MUX_MODE15)
    			0x1a4 (PIN_INPUT | MUX_MODE15)
    			0x1a8 (PIN_INPUT | MUX_MODE15)
    			0x1ac (PIN_INPUT | MUX_MODE15)
    			0x1b0 (PIN_INPUT | MUX_MODE15)
    			0x1b4 (PIN_INPUT | MUX_MODE15)
    			0x1b8 (PIN_INPUT | MUX_MODE15)
    			0x1bc (PIN_INPUT | MUX_MODE15)
    			0x1c0 (PIN_INPUT | MUX_MODE15)
    			0x1c4 (PIN_INPUT | MUX_MODE15)
    		>;
    	};
    
    	davinci_mdio_pins_default: davinci_mdio_pins_default {
    		pinctrl-single,pins = <
    			/* MDIO */
    			0x23c (PIN_OUTPUT_PULLUP | MUX_MODE0)	/* mdio_mclk */
    			0x240 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mdio_d */
    		>;
    	};
    
    	davinci_mdio_pins_sleep: davinci_mdio_pins_sleep {
    		pinctrl-single,pins = <
    			0x23c (PIN_INPUT | MUX_MODE15)
    			0x240 (PIN_INPUT | MUX_MODE15)
    		>;
    	};
    
    	tps659038_pins_default: tps659038_pins_default {
    		pinctrl-single,pins = <
    			0x418 (PIN_INPUT_PULLUP | MUX_MODE14)	/* wakeup0.gpio1_0 */
    		>;
    	};
    
    	mcp79410_pins_default: mcp79410_pins_default {
    		pinctrl-single,pins = <
    			0x424 (PIN_INPUT_PULLUP | MUX_MODE1)	/* wakeup3.sys_nirq1 */
    		>;
    	};
    
    	usb1_pins: pinmux_usb1_pins {
    		pinctrl-single,pins = <
    			0x280 (PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */
    		>;
    	};
    
    	extcon_usb1_pins: extcon_usb1_pins {
    		pinctrl-single,pins = <
    			0x3ec (PIN_INPUT_PULLUP | MUX_MODE14) /* uart1_rtsn.gpio7_25 */
    		>;
    	};
    
    	extcon_usb2_pins: extcon_usb2_pins {
    		pinctrl-single,pins = <
    			0x3e8 (PIN_INPUT_PULLUP | MUX_MODE14) /* uart1_ctsn.gpio7_24 */
    		>;
    	};
    
    };
    &dra7_iodelay_core {
    	mmc2_iodelay_ddr_3_3v_conf: mmc2_iodelay_ddr_3_3v_conf {
    		pinctrl-single,pins = <
    			0x18c (A_DELAY(0) | G_DELAY(120))	/* CFG_GPMC_A19_IN */
    			0x190 (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_A19_OEN */
    			0x194 (A_DELAY(174) | G_DELAY(0))	/* CFG_GPMC_A19_OUT */
    			0x1a4 (A_DELAY(265) | G_DELAY(360))	/* CFG_GPMC_A20_IN */
    			0x1a8 (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_A20_OEN */
    			0x1ac (A_DELAY(168) | G_DELAY(0))	/* CFG_GPMC_A20_OUT */
    			0x1b0 (A_DELAY(0) | G_DELAY(120))	/* CFG_GPMC_A21_IN */
    			0x1b4 (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_A21_OEN */
    			0x1b8 (A_DELAY(136) | G_DELAY(0))	/* CFG_GPMC_A21_OUT */
    			0x1bc (A_DELAY(0) | G_DELAY(120))	/* CFG_GPMC_A22_IN */
    			0x1c0 (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_A22_OEN */
    			0x1c4 (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_A22_OUT */
    			0x1c8 (A_DELAY(287) | G_DELAY(420))	/* CFG_GPMC_A23_IN */
    			0x1d0 (A_DELAY(879) | G_DELAY(0))	/* CFG_GPMC_A23_OUT */
    			0x1d4 (A_DELAY(144) | G_DELAY(240))	/* CFG_GPMC_A24_IN */
    			0x1d8 (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_A24_OEN */
    			0x1dc (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_A24_OUT */
    			0x1e0 (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_A25_IN */
    			0x1e4 (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_A25_OEN */
    			0x1e8 (A_DELAY(34) | G_DELAY(0))	/* CFG_GPMC_A25_OUT */
    			0x1ec (A_DELAY(0) | G_DELAY(120))	/* CFG_GPMC_A26_IN */
    			0x1f0 (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_A26_OEN */
    			0x1f4 (A_DELAY(120) | G_DELAY(0))	/* CFG_GPMC_A26_OUT */
    			0x1f8 (A_DELAY(120) | G_DELAY(180))	/* CFG_GPMC_A27_IN */
    			0x1fc (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_A27_OEN */
    			0x200 (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_A27_OUT */
    			0x360 (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_CS1_IN */
    			0x364 (A_DELAY(0) | G_DELAY(0))		/* CFG_GPMC_CS1_OEN */
    			0x368 (A_DELAY(11) | G_DELAY(0))	/* CFG_GPMC_CS1_OUT */
    		>;
    	};
    };
    
    
    // Added for the SPI1 define	//
    &mcspi1 {
    	status="okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&spi1_pins_default>;
    	ti,pindir-d0-out-d1-in=<1>;
    
    	spidev@1 {
    		spi-max-frequency = <100000>;
    		reg = <0>;
    		compatible = "spidev"; //"rohm,dh2228fv"; //"ti,omap4-mcspi";
    	
    	};
    };
    
    // Added for the SPI2 define	//
    &mcspi2 {
    	status="okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&spi2_pins_default>;
    	ti,pindir-d0-out-d1-in=<1>;
    	spidev@1 {
    		spi-max-frequency = <100000>;
    		reg = <0>;
    		compatible = "spidev"; //"rohm,dh2228fv"; //"ti,omap4-mcspi";
    	};
    };
    
    &i2c1 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&i2c1_pins_default>;
    	clock-frequency = <400000>;
    
    	tps659038: tps659038@58 {
    		compatible = "ti,tps659038";
    		reg = <0x58>;
    		interrupt-parent = <&gpio1>;
    		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
    
    		pinctrl-names = "default";
    		pinctrl-0 = <&tps659038_pins_default>;
    
    		#interrupt-cells = <2>;
    		interrupt-controller;
    
    		ti,system-power-controller;
    
    		tps659038_pmic {
    			compatible = "ti,tps659038-pmic";
    
    			regulators {
    				smps12_reg: smps12 {
    					/* VDD_MPU */
    					regulator-name = "smps12";
    					regulator-min-microvolt = < 850000>;
    					regulator-max-microvolt = <1250000>;
    					regulator-always-on;
    					regulator-boot-on;
    				};
    
    				smps3_reg: smps3 {
    					/* VDD_DDR */
    					regulator-name = "smps3";
    					regulator-min-microvolt = <1350000>;
    					regulator-max-microvolt = <1350000>;
    					regulator-always-on;
    					regulator-boot-on;
    				};
    
    				smps45_reg: smps45 {
    					/* VDD_DSPEVE, VDD_IVA, VDD_GPU */
    					regulator-name = "smps45";
    					regulator-min-microvolt = < 850000>;
    					regulator-max-microvolt = <1150000>;
    					regulator-always-on;
    					regulator-boot-on;
    				};
    
    				smps6_reg: smps6 {
    					/* VDD_CORE */
    					regulator-name = "smps6";
    					regulator-min-microvolt = <850000>;
    					regulator-max-microvolt = <1030000>;
    					regulator-always-on;
    					regulator-boot-on;
    				};
    
    				/* SMPS7 unused */
    
    				smps8_reg: smps8 {
    					/* VDD_1V8 */
    					regulator-name = "smps8";
    					regulator-min-microvolt = <1800000>;
    					regulator-max-microvolt = <1800000>;
    					regulator-always-on;
    					regulator-boot-on;
    				};
    
    				/* SMPS9 unused */
    
    				ldo1_reg: ldo1 {
    					/* VDD_SD  */
    					regulator-name = "ldo1";
    					regulator-min-microvolt = <1800000>;
    					regulator-max-microvolt = <3300000>;
    					regulator-always-on;
    					regulator-boot-on;
    				};
    
    				ldo2_reg: ldo2 {
    					/* VDD_SHV5 */
    					regulator-name = "ldo2";
    					regulator-min-microvolt = <3300000>;
    					regulator-max-microvolt = <3300000>;
    					regulator-always-on;
    					regulator-boot-on;
    				};
    
    				ldo3_reg: ldo3 {
    					/* VDDA_1V8_PHY */
    					regulator-name = "ldo3";
    					regulator-min-microvolt = <1800000>;
    					regulator-max-microvolt = <1800000>;
    					regulator-always-on;
    					regulator-boot-on;
    				};
    
    				ldo9_reg: ldo9 {
    					/* VDD_RTC */
    					regulator-name = "ldo9";
    					regulator-min-microvolt = <1050000>;
    					regulator-max-microvolt = <1050000>;
    					regulator-always-on;
    					regulator-boot-on;
    				};
    
    				ldoln_reg: ldoln {
    					/* VDDA_1V8_PLL */
    					regulator-name = "ldoln";
    					regulator-min-microvolt = <1800000>;
    					regulator-max-microvolt = <1800000>;
    					regulator-always-on;
    					regulator-boot-on;
    				};
    
    				ldousb_reg: ldousb {
    					/* VDDA_3V_USB: VDDA_USBHS33 */
    					regulator-name = "ldousb";
    					regulator-min-microvolt = <3300000>;
    					regulator-max-microvolt = <3300000>;
    					regulator-boot-on;
    				};
    
    				regen1: regen1 {
    					/* VDD_3V3_ON */
    					regulator-name = "regen1";
    					regulator-boot-on;
    					regulator-always-on;
    				};
    			};
    		};
    
    		tps659038_rtc: tps659038_rtc {
    			compatible = "ti,palmas-rtc";
    			interrupt-parent = <&tps659038>;
    			interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
    			wakeup-source;
    		};
    
    		tps659038_pwr_button: tps659038_pwr_button {
    			compatible = "ti,palmas-pwrbutton";
    			interrupt-parent = <&tps659038>;
    			interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
    			wakeup-source;
    			ti,palmas-long-press-seconds = <12>;
    		};
    
    		tps659038_gpio: tps659038_gpio {
    			compatible = "ti,palmas-gpio";
    			gpio-controller;
    			#gpio-cells = <2>;
    		};
    	};
    };
    
    &i2c3 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&i2c3_pins_default>;
    	clock-frequency = <400000>;
    
    	mcp_rtc: rtc@6f {
    		compatible = "microchip,mcp7941x";
    		reg = <0x6f>;
    		interrupts = <GIC_SPI 2 IRQ_TYPE_EDGE_RISING>;  /* IRQ_SYS_1N */
    
    		pinctrl-names = "default";
    		pinctrl-0 = <&mcp79410_pins_default>;
    
    		vcc-supply = <&vdd_3v3>;
    		wakeup-source;
    	};
    };
    
    &gpio7 {
    	ti,no-reset-on-init;
    	ti,no-idle-on-init;
    };
    
    &cpu0 {
    	cpu0-supply = <&smps12_reg>;
    	voltage-tolerance = <1>;
    };
    
    &uart3 {
    	status = "okay";
    	interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
    			      <&dra7_pmx_core 0x3f8>;
    
    	pinctrl-names = "default";
    	pinctrl-0 = <&uart3_pins_default>;
    };
    
    &mac {
    	status = "okay";
    	pinctrl-names = "default", "sleep";
    	pinctrl-0 = <&cpsw_pins_default>;
    	pinctrl-1 = <&cpsw_pins_sleep>;
    	dual_emac;
    };
    
    &cpsw_emac0 {
    	phy_id = <&davinci_mdio>, <1>;
    	phy-mode = "rgmii";
    	dual_emac_res_vlan = <1>;
    };
    
    &cpsw_emac1 {
    	phy_id = <&davinci_mdio>, <2>;
    	phy-mode = "rgmii";
    	dual_emac_res_vlan = <2>;
    };
    
    &davinci_mdio {
    	pinctrl-names = "default", "sleep";
    	pinctrl-0 = <&davinci_mdio_pins_default>;
    	pinctrl-1 = <&davinci_mdio_pins_sleep>;
    };
    
    &mmc1 {
    	status = "okay";
    
    	pinctrl-names = "default";
    	pinctrl-0 = <&mmc1_pins_default>;
    
    	vmmc-supply = <&ldo1_reg>;
    	vmmc_aux-supply = <&vdd_3v3>;
    	pbias-supply = <&pbias_mmc_reg>;
    	bus-width = <4>;
    	cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; /* gpio 219 */
    };
    
    &mmc2 {
    	status = "okay";
    
    	pinctrl-names = "default", "hs", "ddr_1_8v";
    	pinctrl-0 = <&mmc2_pins_default>;
    	pinctrl-1 = <&mmc2_pins_hs>;
    	pinctrl-2 = <&mmc2_pins_ddr_3_3v &mmc2_iodelay_ddr_3_3v_conf>;
    
    	vmmc-supply = <&vdd_3v3>;
    	bus-width = <8>;
    	iov = <3300000>;
    	ti,non-removable;
    	cap-mmc-dual-data-rate;
    	max-frequency = <96000000>;
    	/delete-property/ mmc-hs200-1_8v;
    };
    
    &sata {
    	status = "okay";
    };
    
    &usb2_phy1 {
    	phy-supply = <&ldousb_reg>;
    };
    
    &usb2_phy2 {
    	phy-supply = <&ldousb_reg>;
    };
    
    &usb1 {
    	dr_mode = "host";
    	pinctrl-names = "default";
    	pinctrl-0 = <&usb1_pins>;
    };
    
    &omap_dwc3_1 {
    	extcon = <&extcon_usb1>;
    };
    
    &omap_dwc3_2 {
    	extcon = <&extcon_usb2>;
    };
    
    &usb2 {
    	dr_mode = "peripheral";
    };
    
    &cpu_trips {
    	cpu_alert1: cpu_alert1 {
    		temperature = <50000>; /* millicelsius */
    		hysteresis = <2000>; /* millicelsius */
    		type = "active";
    	};
    };
    
    &cpu_cooling_maps 
    {
     map1
      {
       trip = <&cpu_alert1>;
       cooling-device = <&gpio_fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
      };
    };
    
    &thermal_zones
    {
     board_thermal: board_thermal
      {
       polling-delay-passive = <1250>;	/* milliseconds */
       polling-delay = <1500>; 		/* milliseconds */
       
       board_trips: trips
        {
    	board_alert0: board_alert 
    	 {
    	  temperature = <40000>; 	/* millicelsius */
    	  hysteresis = <2000>; 		/* millicelsius */
    	  type = "active";
    	 };
    
    			board_crit: board_crit {
    				temperature = <105000>; /* millicelsius */
    				hysteresis = <0>; /* millicelsius */
    				type = "critical";
    			};
    		};
    
    		board_cooling_maps: cooling-maps {
    			map0 {
    				trip = <&board_alert0>;
    				cooling-device =
    				  <&gpio_fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
    			};
    		};
           };
    };
    
    &dss
    {
     status = "ok";
     vdda_video-supply = <&ldoln_reg>;
    };
    
    
    8322.omap3_spi.c
    /*
     * Copyright (C) 2016 Jagan Teki <jteki@openedev.com>
     *		      Christophe Ricard <christophe.ricard@gmail.com>
     *
     * Copyright (C) 2010 Dirk Behme <dirk.behme@googlemail.com>
     *
     * Driver for McSPI controller on OMAP3. Based on davinci_spi.c
     * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
     *
     * Copyright (C) 2007 Atmel Corporation
     *
     * Parts taken from linux/drivers/spi/omap2_mcspi.c
     * Copyright (C) 2005, 2006 Nokia Corporation
     *
     * Modified by Ruslan Araslanov <ruslan.araslanov@vitecmm.com>
     *
     * SPDX-License-Identifier:	GPL-2.0+
     */
    
    #include <common.h>
    #include <dm.h>
    #include <spi.h>
    #include <malloc.h>
    #include <asm/io.h>
    
    DECLARE_GLOBAL_DATA_PTR;
    
    #if defined(CONFIG_AM33XX) || defined(CONFIG_AM43XX)
    #define OMAP3_MCSPI1_BASE	0x48030100
    #define OMAP3_MCSPI2_BASE	0x481A0100
    #else
    #define OMAP3_MCSPI1_BASE	0x48098100	//0x48098000
    #define OMAP3_MCSPI2_BASE	0x4809A100	//0x4809A000
    #define OMAP3_MCSPI3_BASE	0x480B8100	//0x480B8000
    #define OMAP3_MCSPI4_BASE	0x480BA100	//0x480BA000
    #endif
    
    #define OMAP4_MCSPI_REG_OFFSET	0x100
    
    struct omap2_mcspi_platform_config {
    	unsigned int regs_offset;
    };
    
    /* per-register bitmasks */
    #define OMAP3_MCSPI_SYSCONFIG_SMARTIDLE (2 << 3)
    #define OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP BIT(2)
    #define OMAP3_MCSPI_SYSCONFIG_AUTOIDLE	BIT(0)
    #define OMAP3_MCSPI_SYSCONFIG_SOFTRESET BIT(1)
    
    #define OMAP3_MCSPI_SYSSTATUS_RESETDONE BIT(0)
    
    #define OMAP3_MCSPI_MODULCTRL_SINGLE	BIT(0)
    #define OMAP3_MCSPI_MODULCTRL_MS	BIT(2)
    #define OMAP3_MCSPI_MODULCTRL_STEST	BIT(3)
    
    #define OMAP3_MCSPI_CHCONF_PHA		BIT(0)
    #define OMAP3_MCSPI_CHCONF_POL		BIT(1)
    #define OMAP3_MCSPI_CHCONF_CLKD_MASK	GENMASK(5, 2)
    #define OMAP3_MCSPI_CHCONF_EPOL		BIT(6)
    #define OMAP3_MCSPI_CHCONF_WL_MASK	GENMASK(11, 7)
    #define OMAP3_MCSPI_CHCONF_TRM_RX_ONLY	BIT(12)
    #define OMAP3_MCSPI_CHCONF_TRM_TX_ONLY	BIT(13)
    #define OMAP3_MCSPI_CHCONF_TRM_MASK	GENMASK(13, 12)
    #define OMAP3_MCSPI_CHCONF_DMAW		BIT(14)
    #define OMAP3_MCSPI_CHCONF_DMAR		BIT(15)
    #define OMAP3_MCSPI_CHCONF_DPE0		BIT(16)
    #define OMAP3_MCSPI_CHCONF_DPE1		BIT(17)
    #define OMAP3_MCSPI_CHCONF_IS		BIT(18)
    #define OMAP3_MCSPI_CHCONF_TURBO	BIT(19)
    #define OMAP3_MCSPI_CHCONF_FORCE	BIT(20)
    
    #define OMAP3_MCSPI_CHSTAT_RXS		BIT(0)
    #define OMAP3_MCSPI_CHSTAT_TXS		BIT(1)
    #define OMAP3_MCSPI_CHSTAT_EOT		BIT(2)
    
    #define OMAP3_MCSPI_SYST_SPIDATDIR_1	BIT(9)
    #define OMAP3_MCSPI_SYST_SPIDATDIR_0	BIT(8)
    #define OMAP3_MCSPI_SYST_SPIEN_3	BIT(3)
    #define OMAP3_MCSPI_SYST_SPIEN_2	BIT(2)
    #define OMAP3_MCSPI_SYST_SPIEN_1	BIT(1)
    #define OMAP3_MCSPI_SYST_SPIEN_0	BIT(0)
    
    #define OMAP3_MCSPI_CHCTRL_EN		BIT(0)
    #define OMAP3_MCSPI_CHCTRL_DIS		(0 << 0)
    
    #define OMAP3_MCSPI_WAKEUPENABLE_WKEN	BIT(0)
    #define MCSPI_PINDIR_D0_IN_D1_OUT	0
    #define MCSPI_PINDIR_D0_OUT_D1_IN	1
    
    #define OMAP3_MCSPI_MAX_FREQ		48000000
    #define SPI_WAIT_TIMEOUT		10
    
    /* OMAP3 McSPI registers */
    struct mcspi_channel {
    	unsigned int chconf;		/* 0x2C, 0x40, 0x54, 0x68 */
    	unsigned int chstat;		/* 0x30, 0x44, 0x58, 0x6C */
    	unsigned int chctrl;		/* 0x34, 0x48, 0x5C, 0x70 */
    	unsigned int tx;		/* 0x38, 0x4C, 0x60, 0x74 */
    	unsigned int rx;		/* 0x3C, 0x50, 0x64, 0x78 */
    };
    
    struct mcspi {
    	unsigned char res1[0x10];
    	unsigned int sysconfig;		/* 0x10 */
    	unsigned int sysstatus;		/* 0x14 */
    	unsigned int irqstatus;		/* 0x18 */
    	unsigned int irqenable;		/* 0x1C */
    	unsigned int wakeupenable;	/* 0x20 */
    	unsigned int syst;		/* 0x24 */
    	unsigned int modulctrl;		/* 0x28 */
    	struct mcspi_channel channel[4];
    	/* channel0: 0x2C - 0x3C, bus 0 & 1 & 2 & 3 */
    	/* channel1: 0x40 - 0x50, bus 0 & 1 */
    	/* channel2: 0x54 - 0x64, bus 0 & 1 */
    	/* channel3: 0x68 - 0x78, bus 0 */
    };
    
    struct omap3_spi_priv {
    #ifndef CONFIG_DM_SPI
    	struct spi_slave slave;
    #endif
    	struct mcspi *regs;
    	unsigned int cs;
    	unsigned int freq;
    	unsigned int mode;
    	unsigned int wordlen;
    	unsigned int pin_dir:1;
    };
    
    static void omap3_spi_write_chconf(struct omap3_spi_priv *priv, int val)
    {
    	writel(val, &priv->regs->channel[priv->cs].chconf);
    	/* Flash post writes to make immediate effect */
    	readl(&priv->regs->channel[priv->cs].chconf);
    }
    
    static void omap3_spi_set_enable(struct omap3_spi_priv *priv, int enable)
    {
    	writel(enable, &priv->regs->channel[priv->cs].chctrl);
    	/* Flash post writes to make immediate effect */
    	readl(&priv->regs->channel[priv->cs].chctrl);
    }
    
    static int omap3_spi_write(struct omap3_spi_priv *priv, unsigned int len,
    			   const void *txp, unsigned long flags)
    {
    
    	ulong start;
    	int i, chconf;
    
    	chconf = readl(&priv->regs->channel[priv->cs].chconf);
    	
    	// Enable the channel
    	omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_EN);
    
    	chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
    	chconf |= (priv->wordlen - 1) << 7;
    	chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY;
    	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
    	omap3_spi_write_chconf(priv, chconf);
    
    	for (i = 0; i < len; i++) {
    		// wait till TX register is empty (TXS == 1)
    		start = get_timer(0);
    		while (!(readl(&priv->regs->channel[priv->cs].chstat) &
    			 OMAP3_MCSPI_CHSTAT_TXS)) {
    			if (get_timer(start) > SPI_WAIT_TIMEOUT) {
    				printf("SPI TXS timed out, status=0x%08x\n",
    					readl(&priv->regs->channel[priv->cs].chstat));
    				return -1;
    			}
    		}
    		// Write the data
    		unsigned int *tx = &priv->regs->channel[priv->cs].tx;
    		if (priv->wordlen > 16)
    			writel(((u32 *)txp)[i], tx);
    		else if (priv->wordlen > 8)
    			writel(((u16 *)txp)[i], tx);
    		else
    			writel(((u8 *)txp)[i], tx);
    	}
    
    	// wait to finish of transfer
    	while ((readl(&priv->regs->channel[priv->cs].chstat) &
    			(OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS)) !=
    			(OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS))
    		;
    
    	// Disable the channel otherwise the next immediate RX will get affected
    	omap3_spi_set_enable(priv,OMAP3_MCSPI_CHCTRL_DIS);
    
    	if (flags & SPI_XFER_END) {
    
    		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
    		omap3_spi_write_chconf(priv, chconf);
    	}
    	return 0;
    }
    
    static int omap3_spi_read(struct omap3_spi_priv *priv, unsigned int len,
    			  void *rxp, unsigned long flags)
    {
    	int i, chconf;
    	ulong start;
    
    	chconf = readl(&priv->regs->channel[priv->cs].chconf);
    
    	// Enable the channel
    	omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_EN);
    
    	chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
    	chconf |= (priv->wordlen - 1) << 7;
    	chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY;
    	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
    	omap3_spi_write_chconf(priv, chconf);
    
    	writel(0, &priv->regs->channel[priv->cs].tx);
    
    	for (i = 0; i < len; i++) {
    		start = get_timer(0);
    		// Wait till RX register contains data (RXS == 1)
    		while (!(readl(&priv->regs->channel[priv->cs].chstat) &
    			 OMAP3_MCSPI_CHSTAT_RXS)) {
    			if (get_timer(start) > SPI_WAIT_TIMEOUT) {
    				printf("SPI RXS timed out, status=0x%08x\n",
    					readl(&priv->regs->channel[priv->cs].chstat));
    				return -1;
    			}
    		}
    
    		// Disable the channel to prevent furher receiving
    		if (i == (len - 1))
    			omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_DIS);
    
    		// Read the data
    		unsigned int *rx = &priv->regs->channel[priv->cs].rx;
    		if (priv->wordlen > 16)
    			((u32 *)rxp)[i] = readl(rx);
    		else if (priv->wordlen > 8)
    			((u16 *)rxp)[i] = (u16)readl(rx);
    		else
    			((u8 *)rxp)[i] = (u8)readl(rx);
    	}
    
    	if (flags & SPI_XFER_END) {
    		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
    		omap3_spi_write_chconf(priv, chconf);
    	}
    
    	return 0;
    
    }
    
    /*McSPI Transmit Receive Mode*/
    static int omap3_spi_txrx(struct omap3_spi_priv *priv, unsigned int len, const void *txp, void *rxp, unsigned long flags)
    {
    	ulong start;
    	int i = 0, chconf;
    
    	chconf = readl(&priv->regs->channel[priv->cs].chconf);
    
    	/*Enable SPI channel*/
    	omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_EN);
    
    	/*set TRANSMIT-RECEIVE Mode*/
    	chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK); 	// Clear Bit 12 & 13 for TRx & clear Word length
    	chconf |= (priv->wordlen - 1) << 7;					// Set word length
    	chconf |= OMAP3_MCSPI_CHCONF_FORCE;					// Force CS Low
    	omap3_spi_write_chconf(priv, chconf);					// Write register
    
    	/*Shift in and out 1 byte at time*/
    	for (i=0; i < len; i++)
    	  {
    		/* Write: wait for TX empty (TXS == 1)*/
    		start = get_timer(0);
    		while (!(readl(&priv->regs->channel[priv->cs].chstat) & OMAP3_MCSPI_CHSTAT_TXS))
    		 {
    			if (get_timer(start) > SPI_WAIT_TIMEOUT) 
    			{
    				printf("SPI trx TXS timed out, status=0x%08x\n",
    					readl(&priv->regs->channel[priv->cs].chstat));
    				return -1;
    			}
    		}
    		/* Write the data */
    		unsigned int *tx = &priv->regs->channel[priv->cs].tx;
    		if (priv->wordlen > 16)		writel(((u32 *)txp)[i], tx);
    		else if (priv->wordlen > 8)	writel(((u16 *)txp)[i], tx);
    		else				writel(((u8 *)txp)[i], tx);
    	
    		/*Read: wait for RX containing data (RXS == 1)*/
    		start = get_timer(0);
    		while (!(readl(&priv->regs->channel[priv->cs].chstat) & OMAP3_MCSPI_CHSTAT_RXS))
    		   {
    			if (get_timer(start) > SPI_WAIT_TIMEOUT) 
    			  {
    				printf("SPI trx RXS timed out, status=0x%08x\n", readl(&priv->regs->channel[priv->cs].chstat));
    				return -1;
    			  }
    		   }
    		/* Read the data */
    		unsigned int *rx = &priv->regs->channel[priv->cs].rx;
    		if (priv->wordlen > 16)		((u32 *)rxp)[i] = readl(rx);
    		else if (priv->wordlen > 8)	((u16 *)rxp)[i] = (u16)readl(rx);
    		else				((u8 *)rxp)[i] = (u8)readl(rx);
    	}
    	
    
    
    	/* Disable the channel */
    	omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_DIS);
    
    	/*if transfer must be terminated disable the channel*/
    //	if (flags & SPI_XFER_END) 
    //	{
    		//set CS high
    		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
    		omap3_spi_write_chconf(priv, chconf);
    //	}
    	return 0;
    }
    
    static int _spi_xfer(struct omap3_spi_priv *priv, unsigned int bitlen, const void *dout, void *din, unsigned long flags)
    {
    	unsigned int len;
    	int ret = -1;
    
    	if (priv->wordlen < 4 || priv->wordlen > 32)
    	 {
    	  printf("omap3_spi: invalid wordlen %d\n", priv->wordlen);
    	  return -1;
    	 }
    
    	if (bitlen % priv->wordlen)
    	  return -1;
    
    	len = bitlen / priv->wordlen;
    	
    	if (bitlen == 0) 
    	  {	 /* only change CS */
    		int chconf = readl(&priv->regs->channel[priv->cs].chconf);
    
    		if (flags & SPI_XFER_BEGIN) 
    		{ 
    			omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_EN);
    			chconf |= OMAP3_MCSPI_CHCONF_FORCE;
    			omap3_spi_write_chconf(priv, chconf);
    		}
    		if (flags & SPI_XFER_END) 
    		{
    			chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
    			omap3_spi_write_chconf(priv, chconf);
    			omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_DIS);
    		}
    		ret = 0;
    	  } 
    	else
    	  {
    		if (dout != NULL && din != NULL)
    			ret = omap3_spi_txrx(priv, len, dout, din, flags);
    		else if (dout != NULL)
    			ret = omap3_spi_write(priv, len, dout, flags);
    		else if (din != NULL)
    			ret = omap3_spi_read(priv, len, din, flags);
    	  }
    	return ret;
    }
    
    static void _omap3_spi_set_speed(struct omap3_spi_priv *priv)
    {
    	uint32_t confr, div = 0;
    
    	confr = readl(&priv->regs->channel[priv->cs].chconf);
    
    	/* Calculate clock divisor. Valid range: 0x0 - 0xC ( /1 - /4096 ) */
    	if (priv->freq) 
    	   {
    	     while (div <= 0xC && (OMAP3_MCSPI_MAX_FREQ / (1 << div)) > priv->freq)
    	        div++;
    	   }
    	else 
    	   {
    		 div = 0xC;
    	   }
    
    	/* set clock divisor */
    	confr &= ~OMAP3_MCSPI_CHCONF_CLKD_MASK;
    	confr |= div << 2;
    
    	omap3_spi_write_chconf(priv, confr);
    }
    
    static void _omap3_spi_set_mode(struct omap3_spi_priv *priv)
    {
    	uint32_t confr;
    
    	confr = readl(&priv->regs->channel[priv->cs].chconf);
    
    	/* standard 4-wire master mode:  SCK, MOSI/out, MISO/in, nCS
    	 * REVISIT: this controller could support SPI_3WIRE mode.
    	 */
    	//if (priv->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT)
    	//  {
    	//	  confr &= ~OMAP3_MCSPI_CHCONF_IS;		// Clear Bit for SPI Receive data on SPIDAT[0]
    	//	  confr &= ~OMAP3_MCSPI_CHCONF_DPE1;		// Clear Bit for SPIDAT[1] = SPI Transmit on line
    	//	  confr |= OMAP3_MCSPI_CHCONF_DPE0;		// Clear Bit for SPIDAT[0] = SPI Receive 
    	//  }
    	//else
    	//  {
    		confr &= ~OMAP3_MCSPI_CHCONF_DPE0;		// Clear Bit for SPIDAT[0] = SPI Transmit
    		confr |= OMAP3_MCSPI_CHCONF_DPE1;		// Set Bit for SPIDAT[1] = SPI No Transmition on this line
    		confr |= OMAP3_MCSPI_CHCONF_IS;			// Set Bit for IS = SPI Receive data on SPIDAT[1]
    	// }
    
    	/* set SPI mode 0..3 */
    	confr &= ~(OMAP3_MCSPI_CHCONF_POL | OMAP3_MCSPI_CHCONF_PHA);	// Clear bit to be set 
    	if (priv->mode & SPI_CPHA)					
    		confr |= OMAP3_MCSPI_CHCONF_PHA;			// Latch to Even Number of SPICLK
    	if (priv->mode & SPI_CPOL)
    		confr |= OMAP3_MCSPI_CHCONF_POL;			// SPICLK Polarity
    
    	/* set chipselect polarity; manage with FORCE */
    	if (!(priv->mode & SPI_CS_HIGH))
    		confr |= OMAP3_MCSPI_CHCONF_EPOL; /* active-low; normal */
    	else
    		confr &= ~OMAP3_MCSPI_CHCONF_EPOL;
    
    	/* Transmit & receive mode */
    	confr &= ~OMAP3_MCSPI_CHCONF_TRM_MASK; // Set bits to 0 for Transceive mode (TRx)
    
    	omap3_spi_write_chconf(priv, confr);
    }
    
    static void _omap3_spi_set_wordlen(struct omap3_spi_priv *priv)
    {
    	unsigned int confr;
    
    	/* McSPI individual channel configuration */
    	confr = readl(&priv->regs->channel[priv->wordlen].chconf);
    
    	/* wordlength */
    	confr &= ~OMAP3_MCSPI_CHCONF_WL_MASK;
    	confr |= (priv->wordlen - 1) << 7;
    
    	omap3_spi_write_chconf(priv, confr);
    }
    
    static void spi_reset(struct mcspi *regs)
    {
    	unsigned int tmp;
    
    
    	writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, &regs->sysconfig);
    	do {
    		tmp = readl(&regs->sysstatus);
    		//printf(" We wait for %02X :", &regs->sysstatus);
    
    	} while (!(tmp & OMAP3_MCSPI_SYSSTATUS_RESETDONE));
    
    	writel(OMAP3_MCSPI_SYSCONFIG_AUTOIDLE |
    	       OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP |
    	       OMAP3_MCSPI_SYSCONFIG_SMARTIDLE, &regs->sysconfig);
    
    	writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &regs->wakeupenable);
    }
    
    static void _omap3_spi_claim_bus(struct omap3_spi_priv *priv)
    {
    	unsigned int conf;
    
    	spi_reset(priv->regs);
    
    	/*
    	 * setup when switching from (reset default) slave mode
    	 * to single-channel master mode
    	 */
    	// We need to set up the McSPI as
    	// 1) Single - Do not chnage this = 0
    	// 2) Master Salve - Change from 1 to 0
    	// 2) System Test - Do not Chnage this = 0
    	
    	conf = readl(&priv->regs->modulctrl);
    	conf &= ~(OMAP3_MCSPI_MODULCTRL_STEST | OMAP3_MCSPI_MODULCTRL_MS); // Original Setup
    	conf |= OMAP3_MCSPI_MODULCTRL_SINGLE;
    
    	writel(conf, &priv->regs->modulctrl);
    }
    
    #ifndef CONFIG_DM_SPI
    
    static inline struct omap3_spi_priv *to_omap3_spi(struct spi_slave *slave)
    {
    	return container_of(slave, struct omap3_spi_priv, slave);
    }
    
    void spi_init(void)
    {
    /* do nothing */
    }
    
    void spi_free_slave(struct spi_slave *slave)
    {
    	struct omap3_spi_priv *priv = to_omap3_spi(slave);
    
    	free(priv);
    }
    
    int spi_claim_bus(struct spi_slave *slave)
    {
    	struct omap3_spi_priv *priv = to_omap3_spi(slave);
    
    	_omap3_spi_claim_bus(priv);
    	_omap3_spi_set_wordlen(priv);
    	_omap3_spi_set_mode(priv);
    	_omap3_spi_set_speed(priv);
    
    	return 0;
    }
    
    void spi_release_bus(struct spi_slave *slave)
    {
    	struct omap3_spi_priv *priv = to_omap3_spi(slave);
    
    	/* Reset the SPI hardware */
    	spi_reset(priv->regs);
    }
    
    struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
    				     unsigned int max_hz, unsigned int mode)
    {
    	struct omap3_spi_priv *priv;
    	struct mcspi *regs;
    
    	/*
    	 * OMAP3 McSPI (MultiChannel SPI) has 4 busses (modules)
    	 * with different number of chip selects (CS, channels):
    	 * McSPI1 has 4 CS (bus 0, cs 0 - 3)
    	 * McSPI2 has 2 CS (bus 1, cs 0 - 1)
    	 * McSPI3 has 2 CS (bus 2, cs 0 - 1)
    	 * McSPI4 has 1 CS (bus 3, cs 0)
    	 */
    
    	switch (bus) 
    	{
    		case 0:
    		 regs = (struct mcspi *)OMAP3_MCSPI1_BASE;
    		 break;
    		case 1:
    		 regs = (struct mcspi *)OMAP3_MCSPI2_BASE;
    		 break;
    		case 2:
    		 regs = (struct mcspi *)OMAP3_MCSPI3_BASE;
    		 break;
    		case 3:
    		 regs = (struct mcspi *)OMAP3_MCSPI4_BASE;
    		 break;
    		default:
    		 printf("SPI error: unsupported bus %i.  Supported busses 0 - 3\n", bus);
    		 return NULL;
    	}
    
    	if (((bus == 0) && (cs > 3)) ||
    	    ((bus == 1) && (cs > 1)) ||
    	    ((bus == 2) && (cs > 1)) ||
    	    ((bus == 3) && (cs > 0))) {
    		printf("SPI error: unsupported chip select %i on bus %i\n", cs, bus);
    		return NULL;
    	}
    
    	if (max_hz > OMAP3_MCSPI_MAX_FREQ) {
    		printf("SPI error: unsupported frequency %i Hz. Max frequency is 48 MHz\n",
    		       max_hz);
    		return NULL;
    	}
    
    	if (mode > SPI_MODE_3) {
    		printf("SPI error: unsupported SPI mode %i\n", mode);
    		return NULL;
    	}
    
    	priv = spi_alloc_slave(struct omap3_spi_priv, bus, cs);
    	if (!priv) {
    		printf("SPI error: malloc of SPI structure failed\n");
    		return NULL;
    	}
    
    	priv->regs = regs;
    	priv->cs = cs;
    	priv->freq = max_hz;
    	priv->mode = mode;
    	priv->wordlen = priv->slave.wordlen;
    #if 0
    	/* Please migrate to DM_SPI support for this feature. */
    	priv->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
    #endif
    
    	return &priv->slave;
    }
    
    int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, void *din, unsigned long flags)
    {
    	struct omap3_spi_priv *priv = to_omap3_spi(slave);
    
    	return _spi_xfer(priv, bitlen, dout, din, flags);
    }
    
    #else
    
    static int omap3_spi_claim_bus(struct udevice *dev)
    {
    	struct udevice *bus = dev->parent;
    	struct omap3_spi_priv *priv = dev_get_priv(bus);
    	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
    
    	priv->cs = slave_plat->cs;
    	_omap3_spi_claim_bus(priv);
    
    	return 0;
    }
    
    static int omap3_spi_release_bus(struct udevice *dev)
    {
    	struct udevice *bus = dev->parent;
    	struct omap3_spi_priv *priv = dev_get_priv(bus);
    
    	/* Reset the SPI hardware */
    	spi_reset(priv->regs);
    
    	return 0;
    }
    
    static int omap3_spi_set_wordlen(struct udevice *dev, unsigned int wordlen)
    {
    	struct udevice *bus = dev->parent;
    	struct omap3_spi_priv *priv = dev_get_priv(bus);
    	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
    
    	priv->cs = slave_plat->cs;
    	priv->wordlen = wordlen;
    	_omap3_spi_set_wordlen(priv);
    
    	return 0;
    }
    
    static int omap3_spi_probe(struct udevice *dev)
    {
    	struct omap3_spi_priv *priv = dev_get_priv(dev);
    	const void *blob = gd->fdt_blob;
    	int node = dev_of_offset(dev);
    
    	struct omap2_mcspi_platform_config* data =	(struct omap2_mcspi_platform_config*)dev_get_driver_data(dev);
    
    	priv->regs = (struct mcspi *)(devfdt_get_addr(dev) + data->regs_offset);
    	if (fdtdec_get_bool(blob, node, "ti,pindir-d0-out-d1-in"))	priv->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
    	else								priv->pin_dir = MCSPI_PINDIR_D0_IN_D1_OUT;
    
    	priv->pin_dir = MCSPI_PINDIR_D0_IN_D1_OUT;
    	priv->wordlen = SPI_DEFAULT_WORDLEN;
    	return 0;
    }
    
    static int omap3_spi_xfer(struct udevice *dev, unsigned int bitlen,
    			    const void *dout, void *din, unsigned long flags)
    {
    	struct udevice *bus = dev->parent;
    	struct omap3_spi_priv *priv = dev_get_priv(bus);
    
    	return _spi_xfer(priv, bitlen, dout, din, flags);
    }
    
    static int omap3_spi_set_speed(struct udevice *dev, unsigned int speed)
    {
    	struct udevice *bus = dev->parent;
    	struct omap3_spi_priv *priv = dev_get_priv(bus);
    	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
    
    	priv->cs = slave_plat->cs;
    	priv->freq = slave_plat->max_hz;
    	_omap3_spi_set_speed(priv);
    
    	return 0;
    }
    
    static int omap3_spi_set_mode(struct udevice *dev, uint mode)
    {
    	struct udevice *bus = dev->parent;
    	struct omap3_spi_priv *priv = dev_get_priv(bus);
    	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
    
    	priv->cs = slave_plat->cs;
    	priv->mode = slave_plat->mode;
    	_omap3_spi_set_mode(priv);
    
    	return 0;
    }
    
    static const struct dm_spi_ops omap3_spi_ops = {
    	.claim_bus      = omap3_spi_claim_bus,
    	.release_bus    = omap3_spi_release_bus,
    	.set_wordlen    = omap3_spi_set_wordlen,
    	.xfer	    	= omap3_spi_xfer,
    	.set_speed      = omap3_spi_set_speed,
    	.set_mode	= omap3_spi_set_mode,
    	/*
    	 * cs_info is not needed, since we require all chip selects to be
    	 * in the device tree explicitly
    	 */
    };
    
    static struct omap2_mcspi_platform_config omap2_pdata = {
    	.regs_offset = 0,
    };
    
    static struct omap2_mcspi_platform_config omap4_pdata = {
    	.regs_offset = OMAP4_MCSPI_REG_OFFSET,
    };
    
    static const struct udevice_id omap3_spi_ids[] = {
    	{ .compatible = "ti,omap2-mcspi", .data = (ulong)&omap2_pdata },
    	{ .compatible = "ti,omap4-mcspi", .data = (ulong)&omap4_pdata },
    	{ }
    };
    
    U_BOOT_DRIVER(omap3_spi) = {
    	.name   = "omap3_spi",
    	.id     = UCLASS_SPI,
    	.of_match = omap3_spi_ids,
    	.probe = omap3_spi_probe,
    	.ops    = &omap3_spi_ops,
    	.priv_auto_alloc_size = sizeof(struct omap3_spi_priv),
    };
    #endif
    
    3146.main.c
    //******************************************************************************************************//
    //**																			Main.C																											**//
    //******************************************************************************************************//
    /* #define	DEBUG	*/
    
    #include <common.h>
    #include <autoboot.h>
    #include <cli.h>
    #include <console.h>
    #include <version.h>
    #include <spi.h>
    
    DECLARE_GLOBAL_DATA_PTR;
    
    static int read_spi(unsigned char bus_no,unsigned char cs);
    
    /*
     * Board-specific Platform code can reimplement show_boot_progress () if needed
     */
    __weak void show_boot_progress(int val) {}
    
    static void run_preboot_environment_command(void)
    {
    #ifdef CONFIG_PREBOOT
    	char *p;
    
    	p = getenv("preboot");
    	if (p != NULL)
    	  {
    	     # ifdef CONFIG_AUTOBOOT_KEYED
    		int prev = disable_ctrlc(1);	/* disable Control C checking */
    	     # endif
    		run_command_list(p, -1, 0);
    
    	     # ifdef CONFIG_AUTOBOOT_KEYED
    		disable_ctrlc(prev);	/* restore Control C checking */
    	     # endif
    	  }
    #endif /* CONFIG_PREBOOT */
    }
    
    /* We come here after U-Boot is initialised and ready to process commands */
    void main_loop(void)
    {
    	const char *s;
    
    	bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
    
    #ifndef CONFIG_SYS_GENERIC_BOARD
    	puts("Warning: Your board does not use generic board. Please read\n");
    	puts("doc/README.generic-board and take action. Boards not\n");
    	puts("upgraded by the late 2014 may break or be removed.\n");
    #endif
    
    #ifdef CONFIG_VERSION_VARIABLE
    	setenv("ver", version_string);  /* set version variable */
    #endif /* CONFIG_VERSION_VARIABLE */
    
    	cli_init();
    
    	run_preboot_environment_command();
    
    #if defined(CONFIG_UPDATE_TFTP)
    	update_tftp(0UL, NULL, NULL);
    #endif /* CONFIG_UPDATE_TFTP */
    
    #if 1
    printf("\n\n");
    	printf("//*****************************************************//\n");
    	printf("//**      Start of U-Boot - P.O.S.T     					  **//\n");
    	printf("//*****************************************************//\n");
    
    	int	bus_no;
    	unsigned char bit_status = 0;
    	
    //******************************************************************************************************//
    //**	This code will test for the SPI bus acitvity to check for the ADC connection							      **//
    //******************************************************************************************************//
    //**	 We have 2 x SPI AD7768 on BUS_0 and BUS_1, CS_0.The Devices IS / Revision is located		        **//
    //**     @ Address 0x0A and the Expected ID should be 0x06                                            **//
    //******************************************************************************************************//
    	printf("//*****************************************************//\n");
    	printf("//**                 SPI Routine                     **//\n");
    	printf("//*****************************************************//\n");
    
    	spi_init();	
    	for(bus_no = 0; bus_no <= 1; bus_no++)
    	{
    		bus_no = 0;
    		printf("//** Check if SPI Bus %d is present:", bus_no);
    
    		if (read_spi(bus_no,0))
    		{
    			printf(" Fail**//\n");	
    			bit_status |= (1<<(bus_no + 3));						// set bit 3 and 4 in bit_status	
    		}
    		else
    		{
    			printf(" Pass**//\n");
    		}
    
    		}
    	printf("//*****************************************************//\n");
    	printf("//**                End of P.O.S.T Test              **//\n");
    	printf("//*****************************************************//\n");
    	
    	//******************************************************************************************************//
    	//**                   Save the Bit_status in Env for the OS to read when booted	                    **//
    	//******************************************************************************************************//
    	//setenv("bit_flag", "0");
    	setenv_hex("bit_status", bit_status);
    	saveenv();
    	//******************************************************************************************************//
    #endif
    	
    	s = bootdelay_process();
    	if (cli_process_fdt(&s))
    		cli_secure_boot_cmd(s);
    
    	autoboot_command(s);
    
    	cli_loop();
    	panic("No CLI available");
    }		
    
    static int read_spi(unsigned char bus_no,unsigned char cs)
    {
    	struct spi_slave *slave;
    	unsigned int    mode = 0;
      	int  j;
    		  	
    	static unsigned short tx_data[2] = {0x8A00};
        	static unsigned short rx_data[2] = {0xAA55};
    	
    	slave = spi_setup_slave(bus_no, cs,100000, mode); // 100Khz 
    
    	if (!slave) 
    		{
    	 	printf("Invalid device %d:%d\n", bus_no, cs);
    	  	return 1;
    		}
    
    	//	We need to read the SPI AD7768 ID address @ 0x0A and we should receive 0x06
    	spi_claim_bus(slave);	
    	
    	for (j = 0; j <= 1; j++)	
    	  {	
    		if(spi_xfer(slave, 1*16, tx_data,rx_data, SPI_XFER_BEGIN | SPI_XFER_END) != 0) 
           	    		{
    			 	printf("Error during SPI transaction\n");
    	        		return 1;
    		        }
    	  }
    
    	spi_release_bus(slave);
    	spi_free_slave(slave);
    
    	if(rx_data[0] != 0x0006)
    	  {
      	    printf("0x%04x", rx_data[0]);
    	    return 1;
    	  }
    
    	return 0;
    }
    
    6761.mux_data.h