mdm9x07 qmi及共享内存流程

AP处理器开机-> 注册驱动

ipc_router_smd_xprt.c
module_init(msm_ipc_router_smd_xprt_init); -> msm_ipc_router_smd_xprt_probe-> msm_ipc_router_smd_config_init -> msm_ipc_router_smd_driver_register -> 注册驱动
msm_ipc_router_smd_remote_probe(被调用见后续 *)

smem.c
arch_initcall(msm_smem_init); ->
msm_smem_probe-> 主要获取共享内存物理地址歧视地址(1MB)
smem_ram_phys(0x0193d000->87dff080->87d00000)->
of_platform_populate 匹配子设备(smd.c smsm.c probe 被调用) ->

smd.c
msm_smd_probe-> request_irq 主要是申请中断
smd_post_init -> smd_channel_probe_now -> smem_get_entry(13…) 失败此时 modem 还没初始化

通过PIL 从Nand flash modem 分区加载NON-HLOS.ubi 到内存地址0x82a00000)可参考MDM9X07 启动流程
https://blog.csdn.net/hesunwen/article/details/71423463

modem 启动初始化
modem_proc/core/mproc/ipc_router/src/ipc_router_init.c

void ipc_router_init(void)
{
  ...
  /* Link to Apps */
  {
    static ipc_router_xal_smdl_param_type param = 
    {
      "IPCRTR",
      SMD_APPS_MODEM,
      SMD_STANDARD_FIFO,
      SMDL_OPEN_FLAGS_MODE_PACKET,
      TRUE
    };

    ipc_router_xal_start_xport(&ipc_router_xal_smdl, (void *)&param, 0, "APPS");
  }
...
}

 
 ipc_router_xal_start_xport ->
 分配内存 xport 
 xport->ops->xport_open(xport_params, xport, &xport->handle) ->
ipc_router_xal_smdl.ipc_router_xal_smdl_open(xport_params, xport, &xport->handle) ->

 port->handle = smdl_open(param->name, 
                            param->edge, 
                            param->mode,
                            param->fifo, 
                            ipc_router_xal_smdl_notify, 
                            port);
 

/** 
 * Opens a port to the specified remote processor.
 *
 * Opens the port named \c name between the processors specified by \c edge.
 * (The current processor must be one of the two processors connected by \c
 * edge.) This function allocates the data structures for the ports in local
 * and shared memory and allocates FIFOs for receive and transmit, each of
 * size \c fsize.
 *
 * Clients may not read from or write to the port until it is opened on both
 * ends. When the other processor opens the port the \c notify callback will
 * be called with argument #SMDL_EVENT_OPEN. If the other end is already open
 * when this function is called, the open notification callback will be called
 * immediately, and may be called before this function returns.

 *
 * If a client wishes to know when the SMD port is fully open, and the other
 * end asserts its DTR signal when opening the port, the client should wait
 * for #SMDL_EVENT_OPEN. If a client wishes to know when the SMD port is fully
 * open, and the other end does not assert its DTR signal when opening the
 * port, the client should wait for #SMDL_EVENT_CTS, taking care that the
 * other end may set and clear its Clear To Send (CTS) signal to enable and
 * disable inbound flow during normal operation. If a client doesn't need to
 * know when the port is open, and merely wishes to transmit data, the client
 * should send data after opening the port. If the port is fully open, SMD
 * Lite will transmit the data immediately. If the port is not fully open, SMD
 * Lite will notify the client when data can be written (when the remote
 * processor asserts its CTS signal) by sending #SMDL_EVENT_WRITE.
 *
 * Port names uniquely identify the port connecting two processors across a
 * single edge. The same name may be used along different edges.
 *
 * @param[in]    name     The name for the port.
 * @param[in]    edge     The edge, identifying both processors, on which this
 *                        channel communicates. The edge must include the
 *                        current processor.
 * @param[in]    flags    A bitfield of flags controlling the behavior of the
 *                        port. See #SMDL_OPEN_FLAGS_NONE,
 *                        #SMDL_OPEN_FLAGS_PRIORITY_DEFAULT,
 *                        #SMDL_OPEN_FLAGS_PRIORITY_LOW,
 *                        #SMDL_OPEN_FLAGS_PRIORITY_HIGH,
 *                        #SMDL_OPEN_FLAGS_PRIORITY_IST,
 *                        #SMDL_OPEN_FLAGS_MODE_PACKET, and
 *                        #SMDL_OPEN_FLAGS_MODE_STREAMING.
 * @param[in]    fsize    The size of the FIFO. This is the physical
 *                        size in memory, which is always four bytes greater 
 *                        than the total capacity of the FIFO. In packet mode, 
 *                        the SMD packet header adds 20 bytes per packet, 
 *                        further reducing the capacity. The FIFO size must be
 *                        a multiple of 32 and must not be less than 
 *                        SMD_MIN_FIFO or greater than SMD_MAX_FIFO. If this 
 *                        parameter is 0, the default size (SMD_STANDARD_FIFO) 
 *                        will be used.
 * @param[in]    notify   The callback called when SMD needs to notify the
 *                        client of a remote event on the SMD port.
 * @param[in]    cb_data  The data passed to the notify function.
 *
 * @return       An opaque SMD handle for the opened port, or NULL if an
 *               error occured while opening the port.
 *
 * @sideeffects  Allocates the local and shared data structures for the SMD
 *               port. Signals the remote processor.
 *               Error fatal occurs when SMDL port is already open (by other
 *               processor) with a different fifo size.
 */
smdl_handle_type smdl_open
(
  const char       *name,
  smd_channel_type  edge,
  uint32            flags,
  uint32            fsize,
  smdl_callback_t   notify,
  void             *cb_data
);

 smdl_open 高通没开源  api 这么写的,此处猜测意思就是smem_alloc 13放到指定内存,然后发送中断给AP侧 通知ipc 初始化完成 ,static ipc_router_xal_smdl_param_type param 中的"IPCRTR"  与AP 侧 dts 匹配
 (通过此处改名字可以测试)

 qcom,ipc_router_modem_xprt {
      compatible = "qcom,ipc_router_smd_xprt";
         qcom,ch-name = "IPCRTR";
           qcom,xprt-remote = "modem";
        qcom,xprt-linkid = <1>;
         qcom,xprt-version = <1>;
         qcom,fragmented-data;
         qcom,disable-pil-loading;
    };
 

AP侧 中断处理函数
smd_modem_irq_handler -> do_smd_probe ->
smd_channel_probe_worker -> smd_channel_probe_now ->

smem_get_entry(13…) 获取一个元素为64的数组指针 struct smd_alloc_elm *shared

一种是nonsecure 比如smem_get_entry(419…)(获取版本号 alloc 在 bootloader中) 从0x87d0000 地址数据结构struce smem_shared 中 表heap_toc[419] 中取地址偏移量offset (最终地址也就是0x87d0000+offset 中取)
另外一种secure(partions) 比如smem_get_entry(13…)
(一般用于取remote处理器alloc的数据) 地址为0x87d0000+1M-4K 数据结构为smem_toc 表entry[1] 中取offset (获取的是一个 struct smem_partition_header) 最终地址为(0x87d0000 + offset +sizeof(struct smem_partition_header)+sizeof(struct smem_partition_allocation_header) + smem_partition_allocation_header.padding_hdr (item 第一个的情况))

static void *__smem_get_entry_secure(unsigned id,
					unsigned *size,
					unsigned to_proc,
					unsigned flags,
					bool skip_init_check,
					bool use_rspinlock)
{
....
if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset)
		return __smem_get_entry_nonsecure(id, size, skip_init_check,
								use_rspinlock);

partition_num = partitions[to_proc].partition_num;
hdr = smem_areas[0].virt_addr + partitions[to_proc].offset; 
//此处smem_areas[0].virt_addr 对于的物理地址 0x87d0000 offset 就是 0x87d0000 +1M-4K smem_toc.entry[1].offset = 0x87000=540K (这个值来源猜测是寄存器中) 
...

if (flags & SMEM_ITEM_CACHED_FLAG) {
		a_hdr_size = ALIGN(sizeof(*alloc_hdr),
				partitions[to_proc].size_cacheline);
		for (alloc_hdr = (void *)(hdr) + hdr->size - a_hdr_size;
				(void *)(alloc_hdr) > (void *)(hdr) +
					hdr->offset_free_cached;
				alloc_hdr = (void *)(alloc_hdr) -
						alloc_hdr->size - a_hdr_size) {
			if (alloc_hdr->canary != SMEM_ALLOCATION_CANARY) {
				LOG_ERR(
					"%s: SMEM corruption detected.  Partition %d to %d at %p\n",
								__func__,
								partition_num,
								to_proc,
								alloc_hdr);
				BUG();

			}
			if (alloc_hdr->smem_type == id) {
				/* 8 byte alignment to match legacy */
				*size = ALIGN(alloc_hdr->size -
						alloc_hdr->padding_data, 8);
				item = (void *)(alloc_hdr) - alloc_hdr->size;
				break;
			}
		}
	} else {
	    //注意此处 hdr->offset_free_uncached 初始化为32 sizeof(*hdr) 一样为32 在modem smdl_open 时已经修改了不然不会跑到for 循环
		for (alloc_hdr = (void *)(hdr) + sizeof(*hdr);
				(void *)(alloc_hdr) < (void *)(hdr) +
					hdr->offset_free_uncached;
				alloc_hdr = (void *)(alloc_hdr) +
						sizeof(*alloc_hdr) +
						alloc_hdr->padding_hdr +
						alloc_hdr->size) {
			if (alloc_hdr->canary != SMEM_ALLOCATION_CANARY) {
				LOG_ERR(
					"%s: SMEM corruption detected.  Partition %d to %d at %p\n",
								__func__,
								partition_num,
								to_proc,
								alloc_hdr);
				BUG();

			}
			if (alloc_hdr->smem_type == id) {
				/* 8 byte alignment to match legacy */
				*size = ALIGN(alloc_hdr->size -
						alloc_hdr->padding_data, 8);
				item = (void *)(alloc_hdr) +
						sizeof(*alloc_hdr) +
						alloc_hdr->padding_hdr;
				//第一个item 0x87d0000+540K+sizeof(*hdr)+sizeof(*alloc_hdr)+alloc_hdr->padding_hdr
				//第二个item
			0x87d0000+540K+sizeof(*hdr)+sizeof(*alloc_hdr)+alloc_hdr->padding_hdr+alloc_hdr->size +   sizeof(*alloc_hdr)+alloc_hdr->padding_hdr
			//smem_get_entry(13..) 放在在第二个item
			
			
				
				break;
			}
		}
	}
	...
}

IPCRTR 放在shared[1] 中

scan_alloc_table ->
smd_alloc_channel 分配内存 struct smd_channel *ch
platform_device_register(&ch->pdev); 注册IPCRTR设备
此时调用 msm_ipc_router_smd_remote_probe

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值