高通 8255 基本通信(QUP)Android侧控制方法说明

05-14 阅读 0评论

一:整体说明

高通 8255 基本通信(QUP)Android侧控制方法说明

高通 8255 基本通信(QUP)Android侧控制方法说明

高通8255芯片中,SPI IIC UART核心统一由QUP V3 进行控制

QUP V3为可编程模块,可以将不同通道配置为SPI IIC UART通路,此部分配置在QNX侧

QUP 资源可以直接被QNX使用,Android侧可以通过两种方法使用QUP资源

二:QUP资源示意图

在8255上共有 4组 QUP资源,每组对应不同通信通道和对应的gpio,各资源对应关系图如下:

高通 8255 基本通信(QUP)Android侧控制方法说明

上图中,我们可以得到信息例如:

  • 所有通道都支持 UART(64B FIFO模式)
  • QUP1_SE_6不支持API了master功能
  • QUP0_SE_0 对应的gpio_pin是20 21 22 23 
  • ...

    上图中对于QUP lane 对应gpio的关系如下

    高通 8255 基本通信(QUP)Android侧控制方法说明

    例如  QUP0_SE_0 对应的gpio_pin是20 21 22 23 ,

    如果设置为UART模式的话,pin20为CTS  pin21为RFR  pin22为TX pin23 为RX

    三:Android 控制使用QUP的方法

    如果要在Android侧使用 QUP相关资源有两种方法

    高通 8255 基本通信(QUP)Android侧控制方法说明

    参考网页:

    - Architecture (qnx.com)

    方法1:virtual devices

    QUP在QNX侧配置相关驱动,通过hypervisor提供虚拟的devices节点给Android侧使用

    高通 8255 基本通信(QUP)Android侧控制方法说明

    此方法中大致逻辑如下:

    1 硬件device通过Hypervisor 由 PVM(即QNX)直接使用driver控制

    2 PVM(QNX侧)通过Hypervisor提供VirtoBE(BackEnd后端)向GVM(即Android侧)提供接口,这样GVM使用VirtoIOFE(FrontEnd前端) 来间接使用PVM的driver

    核心逻辑:QNX直接使用QUP资源,Hypervisor作为桥梁,QNX提供driver的后端程序,Android提供driver的前端程序,即Android侧间接使用QUP资源

            相关网页:

    - Virtual devices (qnx.com)

    - Configuring vdevs (qnx.com)

    - Configuring guests (qnx.com)

    - Configuring the hypervisor host (qnx.com)

    方法2:pass-through

    QUP资源通过hypervisor直接映射到Android侧,Android侧配置相关驱动使用真实的资源

    高通 8255 基本通信(QUP)Android侧控制方法说明

     此方法中大致逻辑如下:

    1 QUP资源通过Hypervisor 直接提供给GVM(Android)侧使用

    即 Android需要提供完整的QUP驱动程序

    相关网页:

    - Configuring the hypervisor host (qnx.com)

    总结:

    上述两种方法其实包含三部分内容

    1 Android配置

    2 QNX 配置 (需要注意的是方法2 看似没有使用QNX,但因为QNX为主系统,不使用QNX应该理解为不使用VirtoDev的形式,所以对于QUP资源来说只要这路资源使用了,就需要在QNX进行配置。)

    3 Hypervisor配置

    四: pass-through配置示例

    示例要求:将gpio91 92 93 94 配置成一路passthrough的 蓝牙Uart通道

    通过上述资源图:可以确认要使用 QUP2 :QUP2_SE_3的qup资源

    高通 8255 基本通信(QUP)Android侧控制方法说明

    QNX配置:

    代码路径:/SD-AMSS4.5.5.0-ES2/tz/trustzone_images/core/settings/buses/qup_accesscontrol/qupv3/config/lemans/QUPAC_Access.c

    高通 8255 基本通信(QUP)Android侧控制方法说明

    对于结构体  QUPv3_se_security_permissions_type 各项定义:(大致含义)
    PeriphID(外设ID):指定要进行通信的外设的唯一标识符或地址。每个外设都有一个对应的唯一ID。
    ProtocolID(协议ID):指定要在 QUP 上使用的通信协议,例如 UART、I2C 或 SPI。
    Mode(模式):指定 QUP 的工作模式。常见的模式有主机模式、从设备模式、循环模式等。
    NsOwner(命名空间所有者):确定外设的命名空间所有者。它用于指示访问特定功能或资源的权限。
    bAllowFifo(是否启用FIFO):指示是否允许在数据传输过程中使用 FIFO(先进先出缓冲区)。当启用 FIFO 时,数据将被缓存,以提高传输效率。
    bLoad(是否加载):用于指示当前操作是否涉及加载配置或固件。
    bModExcl(是否独占模式):指示外设是否以独占模式进行访问。当以独占模式打开外设时,其他程序无法访问该外设。
    关于ProtocolID
    SD-AMSS4.5.5.0-ES2/tz/trustzone_images/core/settings/buses/qup_accesscontrol/qupv3/interface/QupACCommonIds.h
    /** QUPv3 protocols */
    typedef enum
    {
    QUPV3_PROTOCOL_NONE = 0,
    QUPV3_PROTOCOL_SPI = 1,
    QUPV3_PROTOCOL_UART = 2,
    QUPV3_PROTOCOL_UART_2W = QUPV3_PROTOCOL_UART,
    QUPV3_PROTOCOL_I2C = 3,
    QUPV3_PROTOCOL_I3C = 4,
    QUPV3_PROTOCOL_SPI_SLAVE = 5,
    QUPV3_PROTOCOL_AFC = 6,
    QUPV3_PROTOCOL_SPMI = 7,
    QUPV3_PROTOCOL_QSPI_HID = 8,
    QUPV3_PROTOCOL_QSPI = 9,
    QUPV3_PROTOCOL_Q2SPI = 0xE,
    QUPV3_PROTOCOL_UFCS = 0xD,
    QUPV3_PROTOCOL_I3C_IBI = 0x104,
    QUPV3_PROTOCOL_UART_4W = QUPV3_PROTOCOL_UART + 16,
    QUPV3_PROTOCOL_I2C_MM = QUPV3_PROTOCOL_I2C + 16,
    QUPV3_PROTOCOL_UINT32 = 0x7fffffff
    } QUPv3_protocol_type;
    
    关于Mode
    /** QUPv3 FIFO/DMA access modes */
    SD-AMSS4.5.5.0-ES2/tz/trustzone_images/core/settings/buses/qup_accesscontrol/qupv3/interface/QupACCommonIds.h
    typedef enum
    {
    QUPV3_MODE_FIFO = 0,
    QUPV3_MODE_CPU_DMA = 1,
    QUPV3_MODE_GSI = 2,
    QUPV3_MODE_MAX,
    QUPV3_MODE_UINT32 = 0x7fffffff
    } QUPv3_mode_type;
    
    关于NsOwner
    SD-AMSS4.5.5.0-ES2/tz/trustzone_images/core/settings/buses/qup_accesscontrol/qupv3/interface/QupACCommonIds.h
    /** Defines for QUP access ids */
    #define AC_NONE 0
    #define AC_TZ 1
    #define AC_HLOS_GSI 2
    #define AC_HLOS 3
    #define AC_HYP 4
    #define AC_SSC_Q6_ELF 5
    #define AC_ADSP_Q6_ELF 6 // Single
    #define AC_SSC_HLOS 7 // ??, may be we combine this with other SSC one //
    #define AC_CP_TOUCH 8
    #define AC_CP_BITSTREAM 9
    #define AC_CP_PIXEL 10
    #define AC_CP_NON_PIXEL 11
    #define AC_VIDEO_FW 12
    #define AC_CP_CAMERA 13
    #define AC_HLOS_UNMAPPED 14
    #define AC_MSS_MSA 15
    #define AC_MSS_NONMSA 16
    #define AC_UNMAPPED 17
    #define AC_LPASS 18
    #define AC_NON_SECURE 19 // Use this ID to assign a SE to HLOS & ADSP with QUPV3_MODE_FIFO.
    // The mode of operation can be either GSI or FIFO.
    // But not CPU DMA.
    #define AC_HLOS_MODEM 20 // For SEs assigned with AC_HLOS_MODEM
    // 1. Set to FIFO mode, if there are any UEFI use cases and if UEFI driver support only FIFO mode.
    // 2. Set to GSI mode, if there are UEFI use cases and UEFI driver supports GSI mode.
    // SW will take care of assigning this SE to GSI mode after the FW loading is done at the end of UEFI.
    #define AC_GVM_TUI 21 // Assigned to TUI GVM
    #define AC_SPSS_SP 22
    #define AC_OEM 23
    #define AC_NON_SECURE_MODEM 24
    #define AC_HOST 25
    #define AC_GVM1 26
    #define AC_GVM2 27
    #define AC_GVM3 28
    #define AC_GVM4 29
    #define BLSP_AC_LAST 30
    #define AC_DEFAULT 0xFF// Default as in retain whatever in SMMU static config table
    

    Hypervisor配置:

     相关代码路径:

    ①   /SD-QNX4.5.5.0/apps/qnx_ap/target/hypervisor/gvm/ivi/la/linux-la.config 

    ②    /SD-HQX4.5.5.0-ES2/apps_kernel/kernel_platform/qcom/proprietary/devicetree/qcom/lemans-vm-qupv3.dtsi    

    高通 8255 基本通信(QUP)Android侧控制方法说明

     代码解读:

    Hypervisor代码路径是 ①  ,需要配置的主要资源是 中断号和QUP资源

    这两项内容对应的值可以从datasheet中取得,但查询比较麻烦,

    因为Android的DTS高通厂商已经把基本信息填写好了,所以从DTS中取得更加方便,DTS路径如②

    因此可以确认

    中断号: 585

    QUP的资源Memory地址: 0x88c000 范围是0x4000

    可能疑问: 为什么DTS中锁定节点 qupv3_se17_4uart呢?

    解答:建议查看一下dts中的节点包含关系

    lemans-vm-qupv3.dtsi    源码节点包含关系如下:

    &soc {
    	/* QUPv3_0  wrapper  instance */
    	qupv3_0: qcom,qupv3_0_geni_se@9c0000 {
    		...
    		status = "ok";
    		qupv3_se0_i2c: i2c@980000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se0_spi: spi@980000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se1_i2c: i2c@984000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se1_spi: spi@984000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se2_i2c: i2c@988000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se2_spi: spi@988000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se3_i2c: i2c@98c000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se3_spi: spi@98c000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se4_i2c: i2c@990000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se4_spi: spi@990000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se5_i2c: i2c@994000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se5_spi: spi@994000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se5_2uart: qcom,qup_uart@994000 {
    			...
    			status = "disabled";
    		};
    	};
    	/* QUPv3_1  wrapper  instance */
    	qupv3_1: qcom,qupv3_1_geni_se@ac0000 {
    		...
    		status = "ok";
    		qupv3_se7_i2c: i2c@a80000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se7_spi: spi@a80000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se8_i2c: i2c@a84000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se8_spi: spi@a84000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se9_i2c: i2c@a88000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se9_spi: spi@a88000 {
    			...
    			status = "disabled";
    		};
    		/* Debug UART Instance for RUMI*/
    		qupv3_se9_2uart: qcom,qup_uart@a88000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se10_i2c: i2c@a8c000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se10_spi: spi@a8c000 {
    			...
    			status = "disabled";
    		};
    		/* Debug UART Instance */
    		qupv3_se10_2uart: qcom,qup_uart@a8c000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se11_i2c: i2c@a90000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se11_spi: spi@a90000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se12_i2c: i2c@a94000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se12_spi: spi@a94000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se12_2uart: qcom,qup_uart@a94000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se13_i2c: i2c@a98000 {
    			...
    			status = "disabled";
    		};
    	};
    	/* QUPv3_2  wrapper  instance */
    	qupv3_2: qcom,qupv3_2_geni_se@8c0000 {
    		...
    		status = "ok";
    		qupv3_se14_i2c: i2c@880000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se14_spi: spi@880000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se15_i2c: i2c@884000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se15_spi: spi@884000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se16_i2c: i2c@888000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se16_spi: spi@888000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se17_i2c: i2c@88c000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se17_spi: spi@88c000 {
    			...
    			status = "disabled";
    		};
    		/* BT UART Instance */
    		qupv3_se17_4uart: qcom,qup_uart@88c000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se18_i2c: i2c@890000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se18_spi: spi@890000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se19_i2c: i2c@894000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se19_spi: spi@894000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se20_i2c: i2c@898000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se20_spi: spi@898000 {
    			...
    			status = "disabled";
    		};
    	};
    	/* QUPv3_3  wrapper  instance */
    	qupv3_3: qcom,qupv3_3_geni_se@bc0000 {
    		...
    		status = "ok";
    		qupv3_se21_i2c: i2c@b80000 {
    			...
    			status = "disabled";
    		};
    		qupv3_se21_spi: spi@b80000 {
    			...
    			status = "disabled";
    		};
    	};
    };
    

    我这里总结了一下各节点和QUP资源的对应关系 如下:

    QUP serial engineAndroid DTS KeyWord
    QUP0_SE0qupv3_se0_xxxxx
    QUP0_SE1qupv3_se1_xxxxx
    QUP0_SE2qupv3_se2_xxxxx
    QUP0_SE3qupv3_se3_xxxxx
    QUP0_SE4qupv3_se4_xxxxx
    QUP0_SE5qupv3_se5_xxxxx
    QUP1_SE0qupv3_se7_xxxxx
    QUP1_SE1qupv3_se8_xxxxx
    QUP1_SE2qupv3_se9_xxxxx
    QUP1_SE3qupv3_se10_xxxxx
    QUP1_SE4qupv3_se11_xxxxx
    QUP1_SE5qupv3_se12_xxxxx
    QUP1_SE6qupv3_se13_xxxxx
    QUP2_SE0qupv3_se14_xxxxx
    QUP2_SE1qupv3_se15_xxxxx
    QUP2_SE2qupv3_se16_xxxxx
    QUP2_SE3qupv3_se17_xxxxx
    QUP2_SE4qupv3_se18_xxxxx
    QUP2_SE5qupv3_se19_xxxxx
    QUP2_SE6qupv3_se20_xxxxx
    QUP3_SE0qupv3_se21_xxxxx

    Android侧配置:

    对于Android侧的配置基本上就和Linux配置一样了

    基本配置逻辑如下:

    高通 8255 基本通信(QUP)Android侧控制方法说明

    ① 针对uart 的gpio的normal 和 sleep模式下的 Function及 config设定

    ② 上述 qup.dtsi中 qup节点信息设定

    ③ 需要特别注意的是,上面qup.dtsi中各子节点状态都是 disable,当需要使用的时候需要将状态更改为ok,同时便于使用需要在aliases节点中增加子节点描述

    Android侧最终使用效果:

    在Android侧最终会生成一个ttyHS0的device节点,其他操作正常通过该节点使用正常的linux或Android方法即可进行

    高通 8255 基本通信(QUP)Android侧控制方法说明


免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,人围观)

还没有评论,来说两句吧...

目录[+]