MSM8909 + Android5.1.1 SPI driver development (PSAM part)

Source: Internet
Author: User

MSM8909 + Android5.1.1 SPI driver development (PSAM part)

MSM8909 + Android5.1.1SPI driver development (PSAM part)

 

1. PSAM Hardware Design

 

Figure 1

CS chip selection Signal

SCK clock signal

Data input from the MISO master device and output from the device

Data output from the MOSI master device and input from the device

 

2. PSAM Software Design

 

Figure 2

 

(1) PSAM Application

You only need to call the API function.

 

(2) PSAM API

The main task of the API is to power on M0, set the SPI read/write mode, set the number of bytes of SPI read/write, and the working frequency of SPI.

 

(3) SPI driver

After receiving the SPI parameter set by the API, do the corresponding work.

 

(4) M0 firmware

The main work of TDA8007 and TDA8007 is completed by the M0 firmware, including the protocol.

 

3. component configuration

Kernelarcharmconfigsmsm8909-1gb-CB03-perf_defconfig configuration file, make sure the following options are set as follows:

CONFIG_SPI = y

CONFIG_SPI_QUP = y

CONFIG_SPI_SPIDEV = m.

 

This file is used for the user version, and for the eng file, change the msm8909-1gb-CB03_defconfig file.

 

4. Device Tree Configuration

Set layers of the Device Tree nodes in PSAM

 

Figure 3

The green rectangle must be modified in the PSAM section.

 

4.1 kernelarcharmootdtsqcommsm8909-cb03.dtsi added SPI2 Controller Device Node

 

aliases {              /* smdtty devices */              smd1= &smdtty_apps_fm;              smd2= &smdtty_apps_riva_bt_acl;              smd3= &smdtty_apps_riva_bt_cmd;              smd5= &smdtty_apps_riva_ant_cmd;              smd6= &smdtty_apps_riva_ant_data;              smd7= &smdtty_data1;              smd8= &smdtty_data4;              smd11= &smdtty_data11;              smd21= &smdtty_data21;              smd36= &smdtty_loopback;               sdhc1= &sdhc_1; /* SDC1 eMMC slot */              sdhc2= &sdhc_2; /* SDC2 SD card slot */              //spi0= &spi_0; /* SPI0 controller device */              spi2 = &spi_2; /* SPI2 controller device */               i2c5 = &i2c_5; /* I2c5 cntroller device */              //i2c3= &i2c_3; /* I2C3 controller */              i2c1= &i2c_1; /* I2C1 controller */              i2c2= &i2c_2; /* I2C2 NFC qup2 device */              i2c4= &i2c_4; /* I2C4 controller device */              i2c6= &i2c_6; /* I2c6 cntroller device */       };

Add spi2 = & spi_2;/* SPI2 controller device */, comment out i2c3 = & i2c_3; and remove i2c_3 information in the msm8909-qrd-skue-cb03.dtsi File

 

 

Added node information of the SPI2 controller.

 

spi_2: spi@78b7000 { /* BLSP1 QUP3 */                compatible =qcom,spi-qup-v2;                #address-cells = <1>;               #size-cells = <0>;                reg-names =spi_physical, spi_bam_physical;                reg = <0x78b7000 0x600>,                      <0x78840000x23000>;                interrupt-names =spi_irq, spi_bam_irq;                interrupts = <0 97 0>,<0 238 0>;                spi-max-frequency =<19200000>;                pinctrl-names =spi_default, spi_sleep;                pinctrl-0 =<&spi2_default &spi2_cs0_active>;                pinctrl-1 = <&spi2_sleep&spi2_cs0_sleep>;                clocks = <&clock_gccclk_gcc_blsp1_ahb_clk>,                         <&clock_gccclk_gcc_blsp1_qup3_spi_apps_clk>;                clock-names =iface_clk, core_clk;                qcom,infinite-mode = <0>;                qcom,use-bam;                qcom,use-pinctrl;                qcom,ver-reg-exists;                qcom,bam-consumer-pipe-index =<8>;                qcom,bam-producer-pipe-index =<9>;                qcom,master-id = <86>;       };

For latest detail please follow/kernel/Documentation/devicetree/bindings/spi/spi_qsd.txt

 

 

Here, SPI2 2 refers to the bus number corresponding to the SPI controller and corresponds to bus_num, a member of the spi_maste struct.

 

 

4.2 kernelarcharmootdtsqcommsm8909-pinctrl-cb03.dtsi adds SP2 controller pin control settings.

For Pin control Documentation, see/kernel/Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt

 

spi2_active {                        /* MOSI, MISO, CLK */                        qcom,pins = <&gp0>, <&gp 1>, <&gp 3>;                        qcom,num-grp-pins =<3>;                        qcom,pin-func =<1>;                        label =spi2-active;                        /* active state */                        spi2_default:spi2_default {                                drive-strength= <12>; /* 12 MA */                                bias-disable =<0>; /* No PULL */                       };                };                 spi2_suspend {                        /* MOSI, MISO, CLK */                        qcom,pins = <&gp0>, <&gp 1>, <&gp 3>;                        qcom,num-grp-pins =<3>;                        qcom,pin-func =<0>;                        label =spi2-suspend;                        /* suspended state */                        spi2_sleep: spi2_sleep{                                drive-strength= <2>; /* 2 MA */                                bias-pull-down; /* pull down */                        };                };                spi2_cs0_active {                        /* CS */                        qcom,pins = <&gp2>;                        qcom,num-grp-pins =<1>;                       qcom,pin-func =<1>;                        label =spi2-cs0-active;                        spi2_cs0_active:cs0_active {                                drive-strength= <2>;                                bias-disable =<0>;                       };                };                  spi2_cs0_suspend {                        /* CS */                        qcom,pins = <&gp2>;                        qcom,num-grp-pins =<1>;                        qcom,pin-func =<0>;                       label =spi2-cs0-suspend;                        spi2_cs0_sleep:cs0_sleep {                                drive-strength= <2>;                                bias-disable =<0>;                        };                };

 

4.3 kernelarcharmootdtsqcommsm8909-qrd-skue-cb03.dtsi added SPI slave device node Information mounted to the SPI2 Controller

 

Spi @ 78b7000 {spidev @ 0 {compatible = nxp, lpc1114; // The NXP manufacturer's lpc1114 device reg = <0>; spi-max-frequency = <1000000>; qcom, psam_en_gpio = <& msm_gpio 23 0> ;};};

Here, the value 0 after spidev @ 0 indicates the SPI slave device selected by the SPI pin, which corresponds to the struct spi_master struct member num_chipselect. So why do we use cs0. First, let's look at the pins corresponding to the SPI controller we use.

 

 

Figure 4

Why is the N of CS_N 0? Let's take a look:

 

Figure 5

We know that BSP1 ~ You can use the extended CS1, CS2, and CS3 to select an SPI slave device. Of course, CS0, that is, BSP1 ~ 3. Corresponding SPI0 ~ SPI2 controller, each supporting up to four SPI slave devices, BSP4 ~ 6. Only one SPI slave device can be mounted, and only CS0 can be used for chip selection.

 

5. Drive code control

5.1 PSAM_EN Control

Create a PSAM power control struct

 

struct psam_control_data {       /*system */       structspi_device *client;             /*dtsi */       intpsam_en_gpio;};

 

In the spidev_probe () function, the default initialization PSAM_EN is low. The control code is as follows:

 

static bool parse_psam_control_dtsi(structdevice *dev, struct psam_control_data *psam_data){       //enumof_gpio_flags dummy;       structdevice_node *node = dev->of_node;       intret;             psam_data->psam_en_gpio= of_get_named_gpio_flags(node,                                                 qcom,psam_en_gpio,0, NULL);              if(psam_data->psam_en_gpio < 0)              {                                         returnERR_PTR(psam_data->psam_en_gpio);              }              else{                     ret= gpio_request(psam_data->psam_en_gpio, psam_en_gpio);                     if(ret < 0){                            pr_err(Failedto request psam_en_gpio, ERRNO:%d, ret);                            gotofree_gpio;                     }                     gpio_direction_output(psam_data->psam_en_gpio,0);              } free_gpio:       gpio_free(psam_data->psam_en_gpio);       returntrue;}

 

When the PSAM application is enabled, the application layer uses ioctl (fd, SPI_IOC_SPI_IOC_ENABLE, & sam_enable) to control power-on. It calls spidev_ioctl () under spidev. c and adds a case

 

case SPI_IOC_SPI_IOC_ENABLE:              retval= __get_user(tmp, (u8 __user *)arg);               if(retval == 0) {                     psam_power_control(tmp);              }              break;

Add SPI_IOC_SPI_IOC_ENABLE in spidev. h as follows:

 

 

#define SPI_IOC_SPI_IOC_ENABLE _IOW(SPI_IOC_MAGIC, 5, __u32)
The source code of the psam_power_control () function is as follows:

 

 

static bool psam_power_control( bool on){       intret;        psam_control->psam_en_gpio= of_get_named_gpio_flags(psam_control->client->dev.of_node,                                                 qcom,psam_en_gpio,0, NULL);              if(psam_control->psam_en_gpio < 0)                     returnERR_PTR(psam_control->psam_en_gpio);              else{                     ret= gpio_request(psam_control->psam_en_gpio, psam_en_gpio);                     if(ret < 0){                            pr_err(Failedto request psam_en_gpio, ERRNO:%d, ret);                            gotofree_gpio;                     }                     gpio_direction_output(psam_control->psam_en_gpio,on);              } free_gpio:       gpio_free(psam_control->psam_en_gpio);        returnret;}

5.2 The SPI slave device node attribute compatible must be consistent with the spidev_spi_driver in spidev. c.

 

For more information, see section 2.3.

 

static const struct of_device_idspidev_dt_ids[] = {       //{.compatible = rohm,dh2228fv },       {.compatible = nxp,lpc1114 },       {},}; MODULE_DEVICE_TABLE(of, spidev_dt_ids); static struct spi_driver spidev_spi_driver= {       .driver= {              .name=        spidev,              .owner=       THIS_MODULE,              .of_match_table= of_match_ptr(spidev_dt_ids),       },       .probe= spidev_probe,       .remove=     spidev_remove,        /*NOTE:  suspend/resume methods are notnecessary here.        * We don't do anything except pass therequests to/from        * the underlying controller.  The refrigerator handles        * most issues; the controller driver handlesthe rest.        */};


 

5.3 CPOL and CPHA polarity settings

We use CPOL to indicate the initial level of the clock signal. If CPOL is 0, the initial status of the clock signal is low. If CPOL is 1, the initial level of the clock signal is high. In addition, we use CPHA to represent the sampling data along the clock, and CPHA is 0 to indicate the sampling data along the first clock variation, when CPHA is set to 1, data needs to be sampled along the second clock variation. The kernel uses a combination of CPOL and CPHA to express the current working mode required by SPI:

CPOL = 0, CPHA = 1 Mode 0

CPOL = 0, CPHA = 1 Mode 1

CPOL = 1, CPHA = 0 Mode 2

CPOL = 1, CPHA = 1 Mode 3

 

Here we use mode 1 in the SPI device CPOL and CPHA, so we also use mode 1 in the SPI controller.

 

Module_init (spidev_init );

The code for spidev_init () is as follows:

 

if (busnum != -1 && chipselect !=-1) {              structspi_board_info chip = {                                   .modalias     = spidev,                                   .mode           = spimode,                                   .bus_num     = busnum,                                   .chip_select  = chipselect,                                   .max_speed_hz   = maxspeed,              };               structspi_master *master;               master= spi_busnum_to_master(busnum);              if(!master) {                     status= -ENODEV;                     gotoerror_busnum;              }               /*We create a virtual device that will sit on the bus */              spi= spi_new_device(master, &chip);


 

 

5.4

6. SPI test code

In the kernelDocumentationspi folder, the SPI test program is used, in which spidev_test.c is used to test self-reception. Create an spi folder under systemextras, copy spidev_test.c to the spi folder, and create an Android. mk file with the following content:

 

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS)LOCAL_MODULE := spidev_testLOCAL_SRC_FILES := spidev_test.cLOCAL_MODULE_TAGS := optionalinclude $(BUILD_EXECUTABLE)

 

Go to the spi directory and run the "mm" command to compile the generated Executable File spidev_test in the out argetproductmsm8909symbolssystemin directory. Then we can use the adb push command to copy the file to a directory on the device and run it with./spidev_test. If the prompt is insufficient, run the chmod 777 spidev_test command.

 

This program can be used to test whether the spi device driver is normal, but whether it can drive the SPI slave device also needs to increase the corresponding control according to the specific slave device.

 

7. Problems encountered and Solutions

7.1/sys/class/spi_master cannot find spi2

 

Comment out the i2c3 = & i2c_3 of the kernelarcharmootdtsqcommsm8909-cb03.dtsi and you will see it.

 

aliases {       …              //spi0 = &spi_0; /* SPI0 controllerdevice */              spi2= &spi_2; /* SPI0 controller device */               i2c5 = &i2c_5; /* I2c5 cntroller device */              //i2c3 = &i2c_3; /* I2C3 controller */              i2c1= &i2c_1; /* I2C1 controller */              i2c2= &i2c_2; /* I2C2 NFC qup2 device */              i2c4= &i2c_4; /* I2C4 controller device */              i2c6= &i2c_6; /* I2c6 cntroller device */       };


 

7.2/sys/class/spidev cannot see the SPI slave device mounted under the SPI2 Controller

(1) Modify under Spidev. c

 

static const struct of_device_idspidev_dt_ids[] = {       //{.compatible = rohm,dh2228fv },       {.compatible = nxp,lpc1114 },       {},};

 

(2) kernelarcharmootdtsqcommsm8909-cb03.dtsi spi_2: spi @ 78b7000 node added from the device Node

 

spi@78b7000 {                 spidev@0{                     compatible= nxp,lpc1114;                     reg= <0>;                     spi-max-frequency= <1000000>;                     qcom,psam_en_gpio= <&msm_gpio 23 0>;              };       };

As long as the names of the two locations are the same.

 

 

7.3 application layer open () device/dev/spidev2.0 failed

Add the following content in systemcore ootdir init_CB03.rc to modify permissions.

 

chmod 0666 /dev/spidev2.0

 

7.4 Test of spontaneous auto-reception failed with write () and read () at the application layer

You can use the ioctl method of spidev_test that comes with the system to test self-reception. However, if you use write (), the returned value is 0. The correct value should be the number of bytes actually written, the current reason does not know, related post: http://bbs.csdn.net/topics/391858635? Page = 1 # post-400571674.

 

The API layer of PSAM can only use ioctl.

 

7.5 The SPI operating frequency is too low

Through the psam api, I set the SPI controller to work at 200 kHZ. The spi_qsd of the SPI controller prompts that the frequency is too low and changed to 1 MHz.

 

7.6 TDA8007 power-on to the PSAM card failed

We use our actual PSAM program for testing. According to the debugging information, we can see that the card slot selection command is normal, but no data is returned when the PSAM card is powered by 5 V.

 

Figure 6

Change the SW1 drop-down to 3.3V.

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.