以EXYNOS加MDM9x25为例,连接示意图如下: Exynos5433需要这几个GPIO以及HSIC,给MDM9x25上电,下载MDM9x25的binary,efs同步以及MDM9x25出错的时候的ramdump collection等工作。 下面按如下步骤来介绍每个部分所需的代码移植,修改以及流程。 - MDM9x25启动,控制GPIO配置 - MDM9x25代码下载以及efs同步过程 - MDM9x25代码下载以及efs同步过程 - MDM9x25的错误处理流程以及ramdump collect过程 - AP与MDM9x25的ipC通信相关模块
(1) device tree添加相关的设置
mdm_pdata { compatible = "qcom,ext-mdm9x25"; pinctrl-names = "default"; pinctrl-0 = <&ap2mdm_errfatal &ap2mdm_soft_reset &ap2mdm_hostrdy &ap2mdm_status &ap2mdm_hsic_ready>; qcom,ramdump-delay-ms = <2000>; qcom,ramdump-timeout-ms = <120000>; qcom,sfr-query; qcom,sysmon-subsys-id = <20>; qcom,support-shutdown; qcom,mdm2ap-errfatal-gpio = <&gpa2 6 0xf>; qcom,ap2mdm-errfatal-gpio = <&gPR3 4 0x1>; qcom,mdm2ap-status-gpio = <&gpa2 3 0xf>; qcom,ap2mdm-status-gpio = <&gpf1 2 0x1>; qcom,ap2mdm-soft-reset-gpio = <&gpf5 1 0x1>; qcom,mdm2ap-pblrdy-gpio = <&gpa3 0 0xf>; qcom,ap2mdm-vddmin-gpio = <&gpf4 6 0x1>; qcom,mdm2ap-vddmin-gpio = <&gpa2 5 0x0>; qcom,ap2mdm-hsic-ready-gpio = <&gpg2 1 0x1>; }; mdmpm_pdata { compatible = "qcom,mdm-hsic-pm"; qcom,ap2mdm-hostrdy-gpio = <&gpf5 0 0x1>; qcom,mdm2ap-devicerdy-gpio = <&gpa1 2 0x0>; qcom,mdm2ap-hostwake-gpio = <&gpa3 1 0xf>; reg = <0x15510000 0x100>, /* EHCI */ <0x15530000 0x100>, /* PHY */ <0x105C0704 0xC>, /* PMU */ <0x156E0204 0xC>; /* USB phy clk */ }; pinctrl@15690000{ ap2mdm_errfatal: ap2mdm_errfatal { samsung,pins = "gpr3-4"; samsung,pin-function = <0x1>; /* OUT */ samsung,pin-pud = <1>; /* PULL DOWN */ samsung,pin-drv = <0>; }; }; pinctrl@11090000{ ap2mdm_soft_reset: ap2mdm_soft_reset { samsung,pins = "gpf5-1"; samsung,pin-function = <0x1>; /* OUT */ samsung,pin-pud = <0>; /* No PULL */ samsung,pin-drv = <0>; }; ap2mdm_hostrdy: ap2mdm_hostrdy { samsung,pins = "gpf5-0"; samsung,pin-function = <0x1>; /* OUT */ samsung,pin-pud = <1>; /* PULL DOWN */ samsung,pin-drv = <0>; }; ap2mdm_status: ap2mdm_status { samsung,pins = "gpf1-2"; samsung,pin-function = <0x1>; /* OUT */ samsung,pin-pud = <0>; /* No PULL */ samsung,pin-drv = <0>; }; }; pinctrl@14CC0000{ ap2mdm_hsic_ready: ap2mdm_hsic_ready { samsung,pins = "gpg2-1"; samsung,pin-function = <0x1>; /* OUT */ samsung,pin-pud = <1>; /* PULL DOWN */ samsung,pin-drv = <0>; }; };(2) kernel/exynos54xx/drivers/esoc目录添加,并使能如下feature。
//以下是esoc文件夹下的Makefile文件,要使能的feature是//CONFIG_ESOC,CONFIG_ESOC_DEV,CONFIG_ESOC_MDM_4x,CONFIG_ESOC_MDM_DRV,//CONFIG_MDM_HSIC_PM这几个。# generic external soc control supportccflags-$(CONFIG_ESOC_DEBUG) := -DDEBUGobj-$(CONFIG_ESOC) += esoc_bus.oobj-$(CONFIG_ESOC_DEV) += esoc_dev.oobj-$(CONFIG_ESOC_CLIENT) += esoc_client.oobj-$(CONFIG_ESOC_MDM_4x) += esoc-mdm-4x.oobj-$(CONFIG_ESOC_MDM_DRV) += esoc-mdm-drv.oobj-$(CONFIG_MDM_HSIC_PM) += mdm_hsic_pm.oesoc-mdm-4x.c文件: 1) mdm_probe()->mdm9x25_setup_hw()初始化ap2mdm_errfatal,ap2mdm_hostrdy 等几个GPIO。这个过程比较简单不再赘述。 2) mdm9x25_setup_hw()->esoc_clink_register()创建/dev/esoc-0文件让mem_helper能够检查几个gpio状态,并初始化esoc_clink和mdm_ctrl结构。
int esoc_clink_register(){ ... dev->bus = &esoc_bus_type; dev->parent = &esoc_bus; dev_set_name(dev, "esoc%d", id); err = device_register(dev); ...}esoc_bus为device类型,定义和注册如下,所以上面dev->parent = &esoc_bus的话,device_register(dev)之后会在/sys/devices/esoc-bus目录下生成dev的名字对应的节点。struct device esoc_bus = { .init_name = "esoc-bus"};device_register(&esoc_bus);看一下dev->bus = &esoc_bus_type;这句。这个其实会负责/dev/esoc-0 字符设备然后设置相应的file_Operation等的。然后还可以通过bus_find_device(),根据esoc_bus_type来找对应的dev。struct bus_type esoc_bus_type = { .name = "esoc", .match = esoc_bus_match, .dev_attrs = esoc_clink_attrs,};bus_register(&esoc_bus_type);//注册esoc_bus_type之后,就会在/sys/bus/下生成esoc目录。//之后在esoc_dev_init函数里边生成class,创建字符设备等,关键一步还是注册bus_register_notifier。这样以esoc_bus_type为dev->bus的设备注册的时候都会调用对应的函数。int __init esoc_dev_init(void){ esoc_class = class_create(THIS_MODULE, "esoc-dev");//在sys/class下生成esoc-dev esoc_major = register_chrdev(0, "esoc", &esoc_dev_fops); ret = bus_register_notifier(&esoc_bus_type, &esoc_dev_notifier);}static struct notifier_block esoc_dev_notifier = { .notifier_call = esoc_dev_notifier_call,};//添加设备的时候,查看bus,并调用相应的notifier函数的过程在:drivers/base/core.c文件中的//device_add()函数中。/* /* Notify clients of device addition. This call must come * after dpm_sysfs_add() and before kobject_uevent(). */ if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_ADD_DEVICE, dev);*///这样在esoc_clink_register()函数中注册dev的话,因为这个dev->bus是esoc_bus_type就会调用到下面的函数,生成/dev/esoc-0,相应的设备号创建和file_operation的定义也可以很容易看到。//esoc_dev_notifier_call()->esoc_clink_add_device()int esoc_clink_add_device(struct device *dev, void *dummy){ struct esoc_udev *esoc_udev; struct esoc_clink *esoc_clink = to_esoc_clink(dev); esoc_udev = get_free_esoc_udev(esoc_clink); if (IS_ERR(esoc_udev)) return PTR_ERR(esoc_udev); //下面创建/dev/esoc-0 esoc_udev->dev = device_create(esoc_class, &esoc_clink->dev, MKDEV(esoc_major, esoc_clink->id), esoc_clink, "esoc-%d", esoc_clink->id); if (IS_ERR(esoc_udev->dev)) { pr_err("failed to create user device/n"); goto dev_err; } return 0;dev_err: return_esoc_udev(esoc_udev); return -ENODEV;}static const struct file_operations esoc_dev_fops = { .owner = THIS_MODULE, .open = esoc_dev_open, .unlocked_ioctl = esoc_dev_ioctl, .release = esoc_dev_release,};esoc-mdm-drv.c文件:
int __init esoc_ssr_init(void){ pr_err("[MIF] %s", __func__);#if defined(CONFIG_MACH_TRLTE_LDU) || defined(CONFIG_MACH_TBLTE_LDU) pr_err("%s LDU doesn't have modem, skip esoc drv register", __func__); return 0;#endif return esoc_drv_register(&esoc_ssr_drv);}//在注册driver的过程中,bus和probe需要被赋值。这样在driver_register的过程中,会调用到bus->match函数,也就是esoc_bus_match()函数来和dev进行匹配(过程是driver_register()->bus_add_driver()->driver_attach()->__driver_attach()->driver_match_device(),因为drv->bus->p->drivers_autoprobe默认是1,所以如果不改动的话,就会调用的相应bus的match函数,如果匹配成功的话,就会调用driver_probe_device()函数等,调用自己的probe函数)。int esoc_drv_register(struct esoc_drv *driver){ int ret; driver->driver.bus = &esoc_bus_type; driver->driver.probe = esoc_bus_probe; //bus->match函数匹配成功就会调用这个probe函数 ret = driver_register(&driver->driver); // if (ret) return ret; return 0;}struct bus_type esoc_bus_type = { .name = "esoc", .match = esoc_bus_match, //这个match比较compat_table里边的名字和esoc_link.name。由于esoc_link.name定义成了 //MDM9x25_LABEL也就是MDM9x25,所以下面的drv也必须匹配才能调用probe函数 .dev_attrs = esoc_clink_attrs,};static struct esoc_drv esoc_ssr_drv = { .owner = THIS_MODULE, .probe = esoc_ssr_probe, .compat_table = compat_table, .compat_entries = ARRAY_SIZE(compat_table), .driver = { .name = "mdm-4x", },};static struct esoc_compat compat_table[] = { { .name = "MDM9x25", .data = NULL, }, { .name = "MDM9x35", .data = NULL, },};struct bus_type esoc_bus_type = { .name = "esoc", .match = esoc_bus_match, .dev_attrs = esoc_clink_attrs,};struct bus_type esoc_bus_type = { .name = "esoc", .match = esoc_bus_match, .dev_attrs = esoc_clink_attrs,};上面的执行完之后,就会生成/sys/bus/esoc/drivers/mdm-4x
root@royceltectc:/sys/bus/esoc/drivers/mdm-4x # ls -lls -l--w------- root root 4096 2015-01-13 16:35 bindlrwxrwxrwx root root 2015-01-13 16:35 esoc0 -> ../../../../devices/qcom,mdm1.50/esoc0--w------- root root 4096 2015-01-13 16:35 uevent--w------- root root 4096 2015-01-13 16:35 unbindint esoc_ssr_probe(struct esoc_clink *esoc_clink){ int ret; struct mdm_drv *mdm_drv; struct esoc_eng *esoc_eng; pr_info("[MIF] %s/n", __func__); mdm_drv = devm_kzalloc(&esoc_clink->dev, sizeof(*mdm_drv), GFP_KERNEL); if (IS_ERR(mdm_drv)) return PTR_ERR(mdm_drv); esoc_eng = &mdm_drv->cmd_eng; esoc_eng->handle_clink_evt = mdm_handle_clink_evt; ret = esoc_clink_register_cmd_eng(esoc_clink, esoc_eng); if (ret) { dev_err(&esoc_clink->dev, "failed to register cmd engine/n"); return ret; } //设置subsystem restart的函数,具体看下面函数体。 ret = mdm_register_ssr(esoc_clink); if (ret) goto ssr_err; mdm_drv->mdm_queue = alloc_workqueue("mdm_drv_queue", 0, 0); if (!mdm_drv->mdm_queue) { dev_err(&esoc_clink->dev, "could not create mdm_queue/n"); goto queue_err; } //设置drv_data为mdm_drv,然后初始化mdm_drv。 esoc_set_drv_data(esoc_clink, mdm_drv); init_completion(&mdm_drv->boot_done); init_completion(&mdm_drv->req_eng_wait); INIT_WORK(&mdm_drv->ssr_work, mdm_ssr_fn); mdm_drv->esoc_clink = esoc_clink; mdm_drv->mode = PWR_OFF; mdm_drv->boot_fail = false; //设置重启通知函数 mdm_drv->esoc_restart.notifier_call = esoc_msm_restart_handler; ret = register_reboot_notifier(&mdm_drv->esoc_restart); if (ret) dev_err(&esoc_clink->dev, "register for reboot failed/n"); return 0;queue_err: esoc_clink_unregister_ssr(esoc_clink);ssr_err: esoc_clink_unregister_cmd_eng(esoc_clink, esoc_eng); return ret;}/////////////////////////////////////////////////////mdm_register_ssr()->esoc_clink_register_ssr()->subsys_register()struct subsys_device *subsys_register(struct subsys_desc *desc){ struct subsys_device *subsys; int ret; subsys = kzalloc(sizeof(*subsys), GFP_KERNEL); if (!subsys) return ERR_PTR(-ENOMEM); subsys->desc = desc; subsys->owner = desc->owner; subsys->dev.parent = desc->dev; subsys->dev.bus = &subsys_bus_type; subsys->dev.release = subsys_device_release; subsys->notify = subsys_notif_add_subsys(desc->name); snprintf(subsys->wlname, sizeof(subsys->wlname), "ssr(%s)", desc->name); wake_lock_init(&subsys->wake_lock, WAKE_LOCK_SUSPEND, subsys->wlname); INIT_WORK(&subsys->work, subsystem_restart_wq_func); spin_lock_init(&subsys->track.s_lock); subsys->id = ida_simple_get(&subsys_ida, 0, 0, GFP_KERNEL); if (subsys->id < 0) { ret = subsys->id; goto err_ida; } dev_set_name(&subsys->dev, "subsys%d", subsys->id); mutex_init(&subsys->track.lock); ret = subsys_debugfs_add(subsys); if (ret) goto err_debugfs; //生成/sys/devices/qcom,mdm1.50/esoc0/subsys0 ,link到 //sys/bus/msm_subsys/devices/sybsys0 ret = device_register(&subsys->dev); if (ret) { device_unregister(&subsys->dev); goto err_register; } //生成/dev/subsys_esoc0,并设置file_operations。 ret = subsys_misc_device_add(subsys); if (ret) { put_device(&subsys->dev); goto err_register; } return subsys;err_register: subsys_debugfs_remove(subsys);err_debugfs: mutex_destroy(&subsys->track.lock); ida_simple_remove(&subsys_ida, subsys->id);err_ida: wake_lock_destroy(&subsys->wake_lock); kfree(subsys); return ERR_PTR(ret);}(2) arch/arm/mach-xx/subsystem_restart.c文件:
前面已经讲过在esoc_clink_register_ssr()的时候,创建/dev/subsys_esoc0。subsys_register()->subsys_misc_device_add()对应的file_operation是:static const struct file_operations subsys_device_fops = { .owner = THIS_MODULE, .open = subsys_device_open, .release = subsys_device_close,};//subsys_device_open()这个是用来做subsystem power up的。//subsys_device_open()->subsystem_get()->subsys_start()->subsys->desc->powerup()//由于static int mdm_register_ssr(struct esoc_clink *esoc_clink){ esoc_clink->subsys.shutdown = mdm_subsys_shutdown; esoc_clink->subsys.ramdump = mdm_subsys_ramdumps; esoc_clink->subsys.powerup = mdm_subsys_powerup; esoc_clink->subsys.crash_shutdown = mdm_crash_shutdown; return esoc_clink_register_ssr(esoc_clink);}所以subsys_device_open()最用调用mdm_subsys_powerup()去给mdm上电。(3) kernel/exynos54xx/drivers/usb/misc/ks_bridge.c文件修改,识别hsic的device id并创建/dev/ks_bridge节点,用来下载binary, 下载modem ramdump以及做efs sync操作。
ksb_init()->usb_register(&ksb_usb_driver);//usb驱动定义static struct usb_driver ksb_usb_driver = { .name = "ks_bridge", .probe = ksb_usb_probe, .disconnect = ksb_usb_disconnect, .suspend = ksb_usb_suspend, .resume = ksb_usb_resume, .reset_resume = ksb_usb_resume, .id_table = ksb_usb_ids, .supports_autosuspend = 1,};static const struct usb_device_id ksb_usb_ids[] = { { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9008, 0), //0x9008 ks_hsic_bridge设备号 .driver_info = (unsigned long)&ksb_fboot_dev, }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9048, 2), .driver_info = (unsigned long)&ksb_efs_hsic_dev, }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x904C, 2), .driver_info = (unsigned long)&ksb_efs_hsic_dev, }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9075, 2), .driver_info = (unsigned long)&ksb_efs_hsic_dev, }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9079, 2), .driver_info = (unsigned long)&ksb_efs_usb_dev, }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x908A, 2), .driver_info = (unsigned long)&ksb_efs_hsic_dev, }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x908E, 3), .driver_info = (unsigned long)&ksb_efs_hsic_dev, }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909C, 2), .driver_info = (unsigned long)&ksb_efs_hsic_dev, }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909D, 2), .driver_info = (unsigned long)&ksb_efs_hsic_dev, }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909E, 3), .driver_info = (unsigned long)&ksb_efs_hsic_dev, }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909F, 2), .driver_info = (unsigned long)&ksb_efs_hsic_dev, }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x90A0, 2), .driver_info = (unsigned long)&ksb_efs_hsic_dev, }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x90A4, 3), .driver_info = (unsigned long)&ksb_efs_hsic_dev, }, {} /* terminating entry */};static struct ksb_dev_info ksb_fboot_dev[] = { { .name = "ks_hsic_bridge", //用来下载binary,接收modem ramdump的/dev/ks_hsic_bridge }, { .name = "ks_usb_bridge", },};static struct ksb_dev_info ksb_efs_hsic_dev = { .name = "efs_hsic_bridge", // /dev/efs_hsic_bridge做efs同步的};(1) vendor/qcom/proprietary/mdm_helper目录添加 (2) vendor/qcom/proprietary/ks目录添加 (3) android/device/samsung/trelte_common/init.trelte.rc添加如下代码,启动mdm_helper和mdm_helper_proxy和设置下载目录等:
//init.xx.rcon fs mkdir /data/tombstones 0771 system system#MDM requirement mkdir /dev/block/modem symlink /dev/block/platform/15540000.dwmmc0/by-name/m9kefs1 /dev/block/modem/m9kefs1 symlink /dev/block/platform/15540000.dwmmc0/by-name/m9kefs2 /dev/block/modem/m9kefs2 symlink /dev/block/platform/15540000.dwmmc0/by-name/m9kefs3 /dev/block/modem/m9kefs3 symlink /dev/block/platform/15540000.dwmmc0/by-name/ /dev/block/modem/dump_path chown system radio /dev/block/modem/m9kefs1 chmod 0775 /dev/block/modem/m9kefs1 chown system radio /dev/block/modem/m9kefs2 chmod 0775 /dev/block/modem/m9kefs2 chown system radio /dev/block/modem/m9kefs3 chmod 0775 /dev/block/modem/m9kefs3 chown system radio /dev/block/modem/dump_path chmod 0775 /dev/block/modem/dump_path mkdir /firmware 0771 system system mount vfat /dev/block/mmcblk0p13 /firmware ro shortname=lower fmask=0133,dmask=0022 chown system system /tombstones chmod 0775 /tombstones mkdir /tombstones/modem 0775 system system mkdir /tombstones/lpass 0775 system system mkdir /tombstones/wcnss 0775 system system mkdir /tombstones/dsps 0775 system system rmdir /tombstones/qcks mkdir /tombstones/qcks 771 system system rmdir /tombstones/efs mkdir /tombstones/efs 771 system system rmdir /tombstones/mdm mkdir /tombstones/mdm 0771 system system chown system radio /dev/block/platform/15540000.dw_mmc0/by-name chmod 0775 /dev/block/platform/15540000.dw_mmc0/by-name write /sys/module/rmnet_usb/parameters/mux_enabled 1 write /sys/module/rmnet_usb/parameters/no_fwd_rmnet_links 8 write /sys/module/rmnet_usb/parameters/no_rmnet_insts_per_dev 17 write /sys/module/rmnet_usb/parameters/rmnet_data_init 1 # Allow QMUX daemon to assign port open wait time chown radio radio /sys/devices/virtual/hsicctl/hsicctl0/modem_wait write /sys/module/rmnet_usb/parameters/mux_enabled 1 write /sys/module/rmnet_usb/parameters/no_fwd_rmnet_links 8 write /sys/module/rmnet_usb/parameters/no_rmnet_insts_per_dev 17 write /sys/module/rmnet_usb/parameters/rmnet_data_init 1 # Allow QMUX daemon to assign port open wait time chown radio radio /sys/devices/virtual/hsicctl/hsicctl0/modem_waiton early-init symlink /data/tombstones /tombstonesservice mdm_helper /system/bin/mdm_helper class core onrestart setprop ro.service.mdm_helper_restarted "true"# disabledservice mdm_helper_proxy /system/bin/mdm_helper_proxy class core disabledon property:ro.mdm_helper_proxy_req=true start mdm_helper_proxy(1) mdm上电:
//vendor/qcom/proprietary/mdm_helper的代码,会启动如下两个serviceservice mdm_helper /system/bin/mdm_helper class core onrestart setprop ro.service.mdm_helper_restarted "true" disabledservice mdm_helper_proxy /system/bin/mdm_helper_proxy class core disabled/**********************************mdm_helper service和mdm_helper_proxy会用waitqueue方式做一个同步。因为下载binary和其他的操作都是mdm_helper流程做,如果mdm_helper服务先启动,就必须等到mdm_helper_proxy实际给mdm上电之后mdm_helper服务才能进行下载binary和其他操作。***********************************/1) mdm_helper_proxy是通过打开/dev/subsys_esoc0实际给mdm上电的,这个在上面的subsystem_restart.c文件中已经讲过。modem_proxy_routine()->打开/dev/subsys_esoc0之后就每0.5秒醒来一次,继续睡眠:static void* modem_proxy_routine(void *arg){ struct mdm_device *dev = (struct mdm_device*)arg; char powerup_node[MAX_PATH_LEN]; int fd; snprintf(powerup_node, sizeof(powerup_node), "/dev/subsys_%s", dev->esoc_node); fd = open(powerup_node, O_RDONLY); if (fd < 0) { ALOGE("%s: Proxy thread failed to open esoc node: %s", dev->mdm_name, powerup_node); } do { sleep(50000); } while(1); return NULL;}2) mdm_helper在哪里等待mdm上电完成并继续做接下来的事情呢?modem_state_machine()->dev->ops.power_up()->mdm9k_powerup():int mdm9k_powerup(struct mdm_device *dev){ ..... if (ioctl(dev->device_descriptor, //打开的是/dev/esoc-0 ESOC_WAIT_FOR_REQ, &request) < 0) { ALOGE("%s: REQ_ENG: ESOC_WAIT_FOR_REQ ioctl failed", dev->mdm_name); return RET_FAILED; } .....}根据打开的节点和cmd,会跑到esoc_dev_ioctl里边static long esoc_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg){ ..... case ESOC_WAIT_FOR_REQ: if (esoc_clink->req_eng != &uhandle->eng) return -EACCES; pr_err("esoc REQ enginer waiting on request/n"); err = wait_event_interruptible(esoc_udev->req_wait,//这里就是等待mdm上电的地方 !kfifo_is_empty(&esoc_udev->req_fifo)); pr_err("esoc REQ engine released from wait/n"); if (!err) { pr_err("esoc REQ engine reading from req fifo/n"); err = kfifo_out_spinlocked(&esoc_udev->req_fifo, &req, sizeof(req), &esoc_udev->req_fifo_lock); if (err != sizeof(req)) { pr_err("read from clink %s req q failed/n", esoc_clink->name); return -EIO; } pr_err("esoc REQ engine processing request/n"); put_user(req, (unsigned long __user *)uarg); } return err; break; ....}mdm_helper_proxy在上电成功之后,mdm会拉高pbl管脚,因为之前已经设置了中断,会跑到中断函数mdm_pblrdy_change()。调用顺序是mdm_pblrdy_change()->esoc_clink_queue_request()->esoc_udev_handle_clink_req()->wake_up_interruptible(&esoc_udev->req_wait) 这个应该就是唤醒mdm_helper服务的地方。
<4>[ 9.766662] [4: mdm_helper: 3137] <3>@BATAUTERR@esoc REQ enginer waiting on request//打印完esoc REQ enginer waiting on request之后mdm_helper进入睡眠//在mdm_helper_proxy给mdm上电,检测到pbl之<6>[ 10.186900] [6:mdm_helper_prox: 3257] ext-mdm qcom,mdm1.50: Powering on modem for the first time<6>[ 10.186918] [6:mdm_helper_prox: 3257] ext-mdm qcom,mdm1.50: mdm_toggle_soft_reset<6>[ 10.207415] [0:irq/570-mdm pbl: 1767] ext-mdm qcom,mdm1.50: pbl ready 1://这里就是检测到pbl变高的时候中断函数打印的<3>[ 10.207438] [0:irq/570-mdm pbl: 1767] ext-mdm qcom,mdm1.50: Signaling request engine for images<4>[ 10.207455] [0:irq/570-mdm pbl: 1767] <3>@BATAUTERR@releasing esoc REQ enginer from wait//后面mdm_helper等待的waitqueue被唤醒,继续执行下载代码或者接受ramdump的操作<4>[ 10.207508] [4: mdm_helper: 3137] <3>@BATAUTERR@esoc REQ engine released from wait<4>[ 10.207534] [4: mdm_helper: 3137] <3>@BATAUTERR@esoc REQ engine reading from req fifo<4>[ 10.207556] [4: mdm_helper: 3137] <3>@BATAUTERR@esoc REQ engine processing request<12>[ 10.207988] [4: mdm_helper: 3137] [ALOG] MDM9x35: Setting up HSIC boot link<12>[ 10.208157] [4: mdm_helper: 3137] [ALOG] MDM9x35: configure_Flashless_boot_dev: Initiating HSIC unbind<6>[ 10.208539] [4: mdm_helper: 3137] s5p-ehci 15510000.usb: remove, state 1<7>[ 10.208571] [4: mdm_helper: 3137] s5p-ehci 15510000.usb: roothub graceful disconnect<6>[ 10.208605] [4: mdm_helper: 3137] usb usb1: USB disconnect, device number 1<6>[ 10.208626] [4: mdm_helper: 3137] usb 1-2: USB disconnect, device number 2<7>[ 10.208651] [4: mdm_helper: 3137] usb 1-2: unregistering device<7>[ 10.208672] [4: mdm_helper: 3137] usb 1-2: unregistering interface 1-2:1.0<7>[ 10.210592] [1: mdm_helper: 3137] usb 1-2: usb_disable_device nuking all URBs<7>[ 10.211908] [3: mdm_helper: 3137] usb usb1: unregistering device<7>[ 10.211925] [3: mdm_helper: 3137] usb usb1: unregistering interface 1-0:1.0<7>[ 10.212353] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: shutdown urb ffffffc0b77ccb40 ep1in-intr<7>[ 10.213146] [3: mdm_helper: 3137] usb usb1: usb_disable_device nuking all URBs<6>[ 10.214606] [0: mc_log: 3126] MobiCore mcd: 501|SCRYPTO DRV [INFO]: FIPS ECDSA selftest passed.<6>[ 10.255958] [6:mdm_helper_prox: 3257] ext-mdm qcom,mdm1.50: pblrdy i:0<6>[ 10.255984] [6:mdm_helper_prox: 3257] ext-mdm qcom,mdm1.50: Set qcom,ap2mdm-hostrdy-gpio to 1 //给mdm上电之后还要拉高ap2mdm-hostrdy-gpio这个gpio。这个管脚一般也表示成AP2MDM_STATUSmodem crash触发mdm_errfatal()中断处理函数,然后就是mdm_handle_clink_evt()->mdm_ssr_fn()->subsystem_restart_dev()然后在dev->restart_leve=RESET_SUBSYS_COUPLED的时候,就会再跑到subsystem_restart_wq_func()->mdm_subsys_ramdumps()->mdm_cmd_exe()的ESOC_EXE_DEBUG里, mdm->debug = 1 后重启cp,等在ramdump collection弄完。 cp重启的时候,会拉高PBL端口,触发mdm_pblrdy_change中断函数,在函数里边检查mdm->debug。等于1的话,就会跑到esoc_clink_queue_request(ESOC_REQ_DEBUG, esoc)->esoc_udev_handle_clink_req()中设置req_fifo的值,并wake_up_interruptible(&esoc_udev->req_wait)。这会唤醒esoc_dev_ioctl中case ESOC_WAIT_FOR_REQ的wait_event_interruptible。并返回req_fifod的值(ESOC_REQ_DEBUG)给应用层。由于modem_state_machine()在开机后会停留在MDM_HELPER_STATE_POST_POWERUP state,每隔一段时间会跑进mdm9k_monitor()函数,用ESOC_WAIT_FOR_REQ读返回值。上面说了重启之后,就会返回ESOC_REQ_DEBUG。所以会赋值dev->required_action = MDM_REQUIRED_ACTION_RAMDUMPS,跑到modem_state_machine()函数的MDM_HELPER_STATE_RAMDUMP状态里边,开始collect_ramdumps。
if (ioctl(dev->device_descriptor, ESOC_WAIT_FOR_REQ, &request) < 0)之后mdm9k_powerup()会跑到configure_flashless_boot_dev(),函数如下:
static int configure_flashless_boot_dev(struct mdm_device *dev, int mode){ struct mdm_private_data *pdata = NULL; int cmd = ESOC_IMG_XFER_RETRY; int req = 0; int rcode, fd; int i; if (!dev) { ALOGE("Device structure passed in as NULL"); return RET_FAILED; } pdata = (struct mdm_private_data*)dev->private_data; if(!pdata) { ALOGE("%s: %s: Private data is null", dev->mdm_name, __func__); return RET_FAILED; } if(!strncmp(dev->mdm_link, LINK_HSIC, 5)) { if (mode == MODE_BOOT || mode == MODE_RAMDUMP) { //boot或者modem crash需要下载ramdump的时候 ALOGI("%s: Setting up %s boot link", dev->mdm_name, dev->mdm_link); for (i = 0; i < NUM_LINK_RETRIES; ++i) { if (pdata->peripheral_cmd) { ALOGI("%s: %s: Initiating HSIC unbind", dev->mdm_name, __func__); pdata->peripheral_cmd(dev, PERIPHERAL_CMD_UNBIND); } if (ioctl(dev->device_descriptor, ESOC_NOTIFY, &cmd) < 0) { ALOGE("%s: :%s: Failed to reset mdm", dev->mdm_name, __func__); return RET_FAILED; } if (ioctl(dev->device_descriptor, ESOC_WAIT_FOR_REQ, &req) < 0) { ALOGE("%s: %s:wait for image xfer fail", dev->mdm_name, __func__); return RET_FAILED; } if (req != ESOC_REQ_IMG && (mode != MODE_RAMDUMP)) { ALOGE("%s: %s: Unnexpected request: %d", dev->mdm_name, __func__, req); continue; } usleep(500000); if (pdata->peripheral_cmd) { ALOGI("%s: %s: Initiating HSIC bind", dev->mdm_name, __func__); pdata->peripheral_cmd(dev, PERIPHERAL_CMD_BIND); } rcode = WaitForCOMport( pdata->flashless_boot_device, 5, 0); if (rcode == RET_SUCCESS) break; } if (rcode != RET_SUCCESS) { ALOGE("%s: %s: Failed to setup HSIC link", dev->mdm_name, __func__); return RET_FAILED; } } else if (mode == MODE_RUNTIME) {//系统启动之后做efs sync等 ALOGI("%s: Setting up %s link for efs_sync", dev->mdm_name, dev->mdm_link); peripheral_reset(dev); ALOGI("%s: Sending boot status notification to HSIC", dev->mdm_name);#if 1 if (ioctl(dev->device_descriptor, ESOC_SET_HSIC_READY) < 0) { ALOGE("%s: %s:hsic_ready failed", dev->mdm_name, __func__); return RET_FAILED; }#else for (i = 0; i < MAX_HSIC_NOTIFICATION_RETRIES; i++) { fd = open(HSIC_NOTIFICATION_NODE, O_WRONLY); if (fd < 0) { if (i >= MAX_HSIC_NOTIFICATION_RETRIES / -1) { ALOGE("%s: node open fail: %s", dev->mdm_name, strerror(errno) ); return RET_FAILED; } usleep(100000); } else { rcode = write(fd, "1", sizeof(char)); close(fd); if (rcode < 0) { ALOGE("%s:node write err: %s", dev->mdm_name, strerror(errno) ); return RET_FAILED; } else { ALOGI("%s: Notification sent", dev->mdm_name); break; } } }#endif } } else { ALOGE("%s: Link %s not supported by mdm-helper", dev->mdm_name, dev->mdm_link); return RET_FAILED; } return RET_SUCCESS;}configure_flashless_boot_dev()函数负责检查建立hsic通道,这个函数中如果是boot或者ramdump状态,会走如下步骤: (1) hsic unbind:
pdata->peripheral_cmd(dev,PERIPHERAL_CMD_UNBIND); //这个会跑到mdm_hsic_peripheral_cmd()里边执行如下操作: case PERIPHERAL_CMD_UNBIND: //transport_unbind_node = "/sys/bus/platform/drivers/s5p-ehci/unbind" //transport_unbind_command = "15510000.usb" fd = open(pdata->transport_unbind_node, O_WRONLY); if (fd < 0) { ALOGE("Failed to open bind node : %s", strerror(errno)); goto error; } if(write(fd, pdata->transport_unbind_command, strlen(pdata->transport_unbind_command)) < 0) { ALOGE("Failed to write to bind node: %s", strerror(errno)); goto error; } break;一般输出如下log
<12>[10.208157] [4:mdm_helper: 3137] [ALOG] MDM9x35: configure_flashless_boot_dev: Initiating HSIC unbind<6>[10.208539] [4:mdm_helper: 3137] s5p-ehci 15510000.usb: remove, state 1<7>[10.208571] [4:mdm_helper: 3137] s5p-ehci 15510000.usb: roothub graceful disconnect<6>[10.208605] [4:mdm_helper: 3137] usb usb1: USB disconnect, device number 1<6>[10.208626] [4:mdm_helper: 3137] usb 1-2: USB disconnect, device number 2<7>[10.208651] [4:mdm_helper: 3137] usb 1-2: unregistering device<7>[10.208672] [4:mdm_helper: 3137] usb 1-2: unregistering interface 1-2:1.0<7>[10.210592] [1:mdm_helper: 3137] usb 1-2: usb_disable_device nuking all URBs<7>[10.211908] [3:mdm_helper: 3137] usb usb1: unregistering device<7>[10.211925] [3:mdm_helper: 3137] usb usb1: unregistering interface 1-0:1.0<7>[10.212353] [3:mdm_helper: 3137] s5p-ehci 15510000.usb: shutdown urb ffffffc0b77ccb40 ep1in-intr<7>[10.213146] [3:mdm_helper: 3137] usb usb1: usb_disable_device nuking all URBs(2) ioctl(dev->device_descriptor, ESOC_NOTIFY, &cmd) 这里cmd是ESOC_IMG_XFER_RETRY,所以看mdm_notify函数中的case ESOC_IMG_XFER_RETRY,是在重启mdm。当然后面紧跟的 ioctl(dev->device_descriptor,ESOC_WAIT_FOR_REQ,&req) < 0)跟上面说的一样,在等待mdm重启完毕,modem的pbl被拉高。 跟上面重启的时候一样,也是输入如下log
<6>[10.255958] [6:mdm_helper_prox:3257] ext-mdm qcom,mdm1.50: pblrdy i:0<6>[10.255984] [6:mdm_helper_prox:3257] ext-mdm qcom,mdm1.50: Set qcom,ap2mdm-hostrdy-gpio to 1...<7>[10.306512] [3:mdm_helper: 3137] s5p-ehci 15510000.usb: stop<7>[10.307539] [3:mdm_helper: 3137] s5p-ehci 15510000.usb: reset command 0010b06 park=3 ithresh=1 period=512 Reset HALT<7>[10.307761] [3:mdm_helper: 3137] s5p-ehci 15510000.usb: irq normal 9 err 0 iaa 4 (lost 0)<7>[10.307776] [3:mdm_helper: 3137] s5p-ehci 15510000.usb: complete 9 unlink 0<7>[10.307791] [3mdm_helper: 3137] s5p-ehci 15510000.usb: ehci_stop completed status 1000 Halt<6>[10.307902] [3:mdm_helper: 3137] s5p-ehci 15510000.usb: USB bus 1 deregistered<7>[10.307981] [3:mdm_helper: 3137] samsung-usb2phy 15530000.usb2phy: samsung_usb2phy_shutdown: End of setting for shutdown<6>[10.308455] [3:mdm_helper: 3137] ext-mdm qcom,mdm1.50: mdm_toggle_soft_reset<4>[10.317728] [3:mdm_helper: 3137] <3>@BATAUTERR@esoc REQ enginer waiting on request...<4>[10.329003] [3:mdm_helper: 3137] <3>@BATAUTERR@esoc REQ engine released from wait<4>[10.329013] [3:mdm_helper: 3137] <3>@BATAUTERR@esoc REQ engine reading from req fifo<4>[10.329023] [3:mdm_helper: 3137] <3>@BATAUTERR@esoc REQ engine processing request(3) hsic bind操作: 和上面unbind差不多: pdata->peripheral_cmd(dev, PERIPHERAL_CMD_BIND) unbind hsic -> mdm重启成功 -> hsic bind之后,就可以找检测到modem hsic,并根据其idVendor和idProduct初始化usb设备。像如下Log,由于modem已经准备进入下载模式或者ramdump collection模式,所以检测到的usb设备号需要和ks_bridge.c文件中的设备号一样才能创建ks_hsic_bridge节点。
static struct ksb_dev_info ksb_fboot_dev[] = { { .name = "ks_hsic_bridge", }, { .name = "ks_usb_bridge", },};static const struct usb_device_id ksb_usb_ids[] = { { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9008, 0), .driver_info = (unsigned long)&ksb_fboot_dev, }, ...}以下可以看到bind之后检测到usb设备号的过程
<12>[ 10.829278] [3: mdm_helper: 3137] [ALOG] MDM9x35: configure_flashless_boot_dev: Initiating HSIC bind<3>[ 10.829789] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: s5p_ehci_probe<7>[ 10.829817] [3: mdm_helper: 3137] of_get_named_gpio_flags: can't parse gpios property<3>[ 10.829989] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: can not find l2-retention value<6>[ 10.830115] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: IP clock gating is N/A<7>[ 10.831096] [3: mdm_helper: 3137] samsung-usb2phy 15530000.usb2phy: Can't configure specified phy mode<7>[ 10.831145] [3: mdm_helper: 3137] samsung-usb2phy 15530000.usb2phy: end of samsung_usb2phy_init<6>[ 10.831174] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: EHCI Host Controller<6>[ 10.831255] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: new USB bus registered, assigned bus number 1<7>[ 10.831312] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: reset hcs_params 0x1212 dbg=0 cc=1 pcc=2 ordered ports=2<7>[ 10.831341] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: reset hcc_params a026 thresh 2 uframes 256/512/1024 park<7>[ 10.831617] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: park 3<7>[ 10.831659] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: reset command 0080b02 park=3 ithresh=8 period=1024 Reset HALT<6>[ 10.831750] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: irq 254, io mem 0x15510000<7>[ 10.831786] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: init command 0010b05 park=3 ithresh=1 period=512 RUN<6>[ 10.845956] [3: mdm_helper: 3137] s5p-ehci 15510000.usb: USB 2.0 started, EHCI 1.00<7>[ 10.846591] [3: mdm_helper: 3137] usb usb1: default language 0x0409<7>[ 10.846774] [3: mdm_helper: 3137] usb usb1: udev 1, busnum 1, minor = 0<6>[ 10.846797] [3: mdm_helper: 3137] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002<6>[ 10.846820] [3: mdm_helper: 3137] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1<6>[ 10.846843] [3: mdm_helper: 3137] usb usb1: Product: EHCI Host Controller<6>[ 10.846864] [3: mdm_helper: 3137] usb usb1: Manufacturer: linux 3.10.61-5726939-eng ehci_hcd<6>[ 10.846885] [3: mdm_helper: 3137] usb usb1: SerialNumber: 15510000.usb<7>[ 10.848957] [3: mdm_helper: 3137] usb usb1: usb_probe_device<7>[ 10.848992] [3: mdm_helper: 3137] usb usb1: configuration #1 chosen from 1 choice<7>[ 10.849108] [3: mdm_helper: 3137] usb usb1: adding 1-0:1.0 (config #1, interface 0)<7>[ 10.849929] [3: mdm_helper: 3137] hub 1-0:1.0: usb_probe_interface<7>[ 10.849965] [3: mdm_helper: 3137] hub 1-0:1.0: usb_probe_interface - got id<6>[ 10.850005] [3: mdm_helper: 3137] hub 1-0:1.0: USB hub found<6>[ 10.850102] [3: mdm_helper: 3137] hub 1-0:1.0: 2 ports detected<7>[ 10.850133] [3: mdm_helper: 3137] hub 1-0:1.0: standalone hub<7>[ 10.850155] [3: mdm_helper: 3137] hub 1-0:1.0: individual port power switching<7>[ 10.850176] [3: mdm_helper: 3137] hub 1-0:1.0: individual port over-current protection<7>[ 10.850198] [3: mdm_helper: 3137] hub 1-0:1.0: power on to power good time: 20ms<7>[ 10.850302] [3: mdm_helper: 3137] hub 1-0:1.0: local power source is good<7>[ 10.850730] [3: mdm_helper: 3137] hub 1-0:1.0: enabling power on all ports<12>[ 10.851554] [3: mdm_helper: 3137] [ALOG] Testing if port "/dev/ks_hsic_bridge" exists<12>[ 10.851813] [3: mdm_helper: 3137] [ALOG] Couldn't find "/dev/ks_hsic_bridge", 1 of 5...<7>[ 10.976052] [1: khubd: 686] hub 1-0:1.0: state 7 ports 2 chg 0004 evt 0000<6>[ 10.976151] [1: khubd: 686] hub 1-0:1.0: port 2, status 0501, change 0000, 480 Mb/s<7>[ 11.036044] [1: khubd: 686] s5p-ehci 15510000.usb: port 2 reset complete, port enabled<7>[ 11.036083] [1: khubd: 686] s5p-ehci 15510000.usb: GetStatus port:2 status 001005 0 ACK POWER sig=se0 PE CONNECT<7>[ 11.037397] [4: main: 3171] SELinux: initialized (dev tmpfs, type tmpfs), uses transition SIDs<6>[ 11.096075] [1: khubd: 686] usb 1-2: new high-speed USB device number 2 using s5p-ehci<7>[ 11.127606] [0: khubd: 686] usb 1-2: default language 0x0409<7>[ 11.128296] [1: khubd: 686] usb 1-2: udev 2, busnum 1, minor = 1//以下就是到的modem的hsic设备号。<6>[ 11.128323] [1: khubd: 686] usb 1-2: New USB device found, idVendor=05c6, idProduct=9008<6>[ 11.128346] [1: khubd: 686] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0<6>[ 11.128367] [1: khubd: 686] usb 1-2: Product: QHSUSB__BULK<6>[ 11.128390] [1: khubd: 686] usb 1-2: Manufacturer: Qualcomm CDMA Technologies MSM<7>[ 11.129616] [1: khubd: 686] usb 1-2: usb_probe_device<7>[ 11.129651] [1: khubd: 686] usb 1-2: configuration #1 chosen from 1 choice<7>[ 11.130061] [1: khubd: 686] usb 1-2: adding 1-2:1.0 (config #1, interface 0)<7>[ 11.130791] [1: khubd: 686] ks_bridge 1-2:1.0: usb_probe_interface<7>[ 11.130824] [1: khubd: 686] ks_bridge 1-2:1.0: usb_probe_interface - got id<6>[ 11.132053] [2: khubd: 686] usb 1-2: usb dev connected...(4) loadSahara() 走下载binary或者下载ramdump的流程,流程都是按照sahara协议走的。 下载binary的流程:
传一个binary的log,和上图的流程一样01-01 23:45:52.880 3357 3357 I kickstart: EVENT: !@ STATE <-- SAHARA_WAIT_HELLO01-01 23:45:52.880 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_HELLO01-01 23:45:52.880 3357 3357 I kickstart: EVENT: !@ SENDING --> SAHARA_HELLO_RESPONSE01-01 23:45:52.880 3357 3357 E kickstart: Wrote to /sys/power/wake_lock01-01 23:45:52.880 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA01-01 23:45:52.880 3357 3357 E kickstart: !@ Requested ID 25, file: "/firmware/image/tz.mbn"01-01 23:45:52.880 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA01-01 23:45:52.880 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA01-01 23:45:52.890 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA01-01 23:45:52.900 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA01-01 23:45:52.910 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA01-01 23:45:52.910 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA01-01 23:45:52.940 3470 3470 W System.err: remove failed: ENOENT (No such file or directory) : /data/system/users/userlist.xml.bak01-01 23:45:52.960 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA01-01 23:45:52.960 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA01-01 23:45:52.960 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA01-01 23:45:52.960 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA01-01 23:45:52.970 3357 3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_END_IMAGE_TX01-01 23:45:52.970 3357 3357 I kickstart: EVENT: !@ SENDING --> SAHARA_DONE01-01 23:45:52.970 3357 3357 E kickstart: !@ 275556 bytes transferred in 0.084783 seconds01-01 23:45:52.970 3357 3357 I kickstart: EVENT: !@ STATE <-- SAHARA_WAIT_DONE_RESP01-01 23:45:52.970 3357 3357 E kickstart: Wrote to /sys/power/wake_unlock01-01 23:45:52.970 3357 3357 I kickstart: EVENT: !@ STATE <-- SAHARA_WAIT_HELLOMemory dump的流程: 下载ramdump的时候log如下,可以看到和上图的流程一样
01-01 23:45:52.850 3357 3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk01-01 23:45:52.850 3357 3357 E kickstart: !@ Received file 'LPM.BIN'01-01 23:45:52.850 3357 3357 E kickstart: !@ 16384 bytes transferred in 0.003022 seconds01-01 23:45:52.850 3357 3357 E kickstart: Opening file '/cpdump/MSGRAM.BIN' for writing01-01 23:45:52.850 3357 3357 I kickstart: EVENT: !@ SENDING --> SAHARA_MEMORY_READ01-01 23:45:52.850 3357 3357 I kickstart: EVENT: !@ Sent SAHARA_MEMORY_READ, address 0xFC428000, length 0x400001-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:588 !@ Received: 16384 bytes01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:593 !@ Writing to disk01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk01-01 23:45:52.860 3357 3357 E kickstart: !@ Received file 'MSGRAM.BIN'01-01 23:45:52.860 3357 3357 E kickstart: !@ 16384 bytes transferred in 0.002020 seconds01-01 23:45:52.860 3357 3357 E kickstart: Opening file '/cpdump/DATARAM.BIN' for writing01-01 23:45:52.860 3357 3357 I kickstart: EVENT: !@ SENDING --> SAHARA_MEMORY_READ01-01 23:45:52.860 3357 3357 I kickstart: EVENT: !@ Sent SAHARA_MEMORY_READ, address 0xFC190000, length 0x1000001-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:588 !@ Received: 65536 bytes01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:593 !@ Writing to disk01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk01-01 23:45:52.860 3357 3357 E kickstart: !@ Received file 'DATARAM.BIN'01-01 23:45:52.860 3357 3357 E kickstart: !@ 65536 bytes transferred in 0.002780 seconds01-01 23:45:52.860 3357 3357 E kickstart: Opening file '/cpdump/CODERAM.BIN' for writing01-01 23:45:52.860 3357 3357 I kickstart: EVENT: !@ SENDING --> SAHARA_MEMORY_READ01-01 23:45:52.860 3357 3357 I kickstart: EVENT: !@ Sent SAHARA_MEMORY_READ, address 0xFC100000, length 0x2000001-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:588 !@ Received: 131072 bytes01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:593 !@ Writing to disk01-01 23:45:52.860 3357 3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk01-01 23:45:52.860 3357 3357 E kickstart: !@ Received file 'CODERAM.BIN'01-01 23:45:52.860 3357 3357 E kickstart: !@ 131072 bytes transferred in 0.004864 seconds01-01 23:45:52.860 3357 3357 E kickstart: Opening file '/cpdump/OCIMEM.BIN' for writing01-01 23:45:52.860 3357 3357 I kickstart: EVENT: !@ SENDING --> SAHARA_MEMORY_READ01-01 23:45:52.860 3357 3357 I kickstart: EVENT: !@ Sent SAHARA_MEMORY_READ, address 0xFE800000, length 0x880001-01 23:45:52.870 3357 3357 I kickstart: WARNING: function: sahara_start:588 !@ Received: 34816 bytes01-01 23:45:52.870 3357 3357 I kickstart: WARNING: function: sahara_start:593 !@ Writing to disk01-01 23:45:52.870 3357 3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk01-01 23:45:52.870 3357 3357 E kickstart: !@ Received file 'OCIMEM.BIN'01-01 23:45:52.870 3357 3357 E kickstart: !@ 34816 bytes transferred in 0.001515 seconds01-01 23:45:52.870 3357 3357 E kickstart: !@ Successfully downloaded files from target 01-01 23:45:52.880 3357 3357 E kickstart: Wrote to /sys/power/wake_unlock代码添加及修改:
KERNEL代码: kernel/drivers/usb/misc/ks_bridge.cAPP层代码: android/vendor/qcom/proprietary/ks目录用户层及内核代码,功能流程: AP,CP通过HSIC连接的方式,一个特点是CP本身没有Flash等固态存储媒介来保存本身的Binary。 所以在每次启动的时候AP都需要通过HSIC来发送MDM的Binary过去。所以通过hsic建立usb连接,并完成下载。efs同步也需要通过hsic建立usb连接。
新闻热点
疑难解答