MDM9x25 Flashless boot&IPC over HSIC

概述

以EXYNOS加MDM9x25爲例,連接示意圖如下:
這裏寫圖片描述
Exynos5433需要這幾個GPIO以及HSIC,給MDM9x25上電,下載MDM9x25的binary,efs同步以及MDM9x25出錯的時候的ramdump collection等工作。
下面按如下步驟來介紹每個部分所需的代碼移植,修改以及流程。
- MDM9x25啓動,控制GPIO配置
- MDM9x25代碼下載以及efs同步過程
- MDM9x25代碼下載以及efs同步過程
- MDM9x25的錯誤處理流程以及ramdump collect過程
- AP與MDM9x25的IPC通信相關模塊

MDM9x25的啓動,控制部分代碼移植修改

KERNEL代碼部分:

(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 support
ccflags-$(CONFIG_ESOC_DEBUG)   := -DDEBUG
obj-$(CONFIG_ESOC) += esoc_bus.o
obj-$(CONFIG_ESOC_DEV) += esoc_dev.o
obj-$(CONFIG_ESOC_CLIENT)  += esoc_client.o
obj-$(CONFIG_ESOC_MDM_4x)  += esoc-mdm-4x.o
obj-$(CONFIG_ESOC_MDM_DRV) += esoc-mdm-drv.o
obj-$(CONFIG_MDM_HSIC_PM)  += mdm_hsic_pm.o

這裏寫圖片描述

esoc-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 -l
ls -l
--w------- root root 4096 2015-01-13 16:35 bind
lrwxrwxrwx 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 unbind
int 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同步的
};

Bootloader部分代碼修改:

    需要在cmdline裏邊添加“androidboot.baseband=mdm”來選擇合適的MDM。
//在esoc-mdm-4x.c文件裏邊查看如下部分
static struct of_device_id mdm_dt_match[] = {
    { .compatible = "qcom,ext-mdm9x25",
        .data = &mdm9x25_ops, },
    {},
};
MODULE_DEVICE_TABLE(of, mdm_dt_match);

static int __init get_baseband(char *str)
{
    if(!strncasecmp(str, "mdm2", 4)) {
        strcpy(mdm_dt_match->compatible, "qcom,ext-mdm9x35");
        mdm_dt_match->data = &mdm9x35_ops;
    } else if(!strncasecmp(str, "mdm", 3)) {
        strcpy(mdm_dt_match->compatible, "qcom,ext-mdm9x25");
        mdm_dt_match->data = &mdm9x25_ops;
    }
    pr_emerg("%s: %s\n", __func__, mdm_dt_match->compatible);

    return 0;
}
__setup("androidboot.baseband=", get_baseband);

Framework層代碼:

(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.rc
on 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_wait

on early-init
    symlink /data/tombstones /tombstones

service mdm_helper /system/bin/mdm_helper
    class core
    onrestart setprop ro.service.mdm_helper_restarted "true"
#    disabled

service mdm_helper_proxy /system/bin/mdm_helper_proxy
    class core
    disabled

on property:ro.mdm_helper_proxy_req=true
    start mdm_helper_proxy

MDM9x25 HSIC bringup:上電流程

(1) mdm上電:

//vendor/qcom/proprietary/mdm_helper的代碼,會啓動如下兩個service
service mdm_helper /system/bin/mdm_helper
    class core
    onrestart setprop ro.service.mdm_helper_restarted "true"
    disabled
service 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_STATUS

MDM9x25 HSIC初始化以及binary下載或者ramdump collect

modem 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_HELLO
01-01 23:45:52.880  3357  3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_HELLO
01-01 23:45:52.880  3357  3357 I kickstart: EVENT: !@ SENDING --> SAHARA_HELLO_RESPONSE
01-01 23:45:52.880  3357  3357 E kickstart: Wrote to /sys/power/wake_lock
01-01 23:45:52.880  3357  3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-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_DATA
01-01 23:45:52.880  3357  3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.890  3357  3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.900  3357  3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.910  3357  3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.910  3357  3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.940  3470  3470 W System.err: remove failed: ENOENT (No such file or directory) : /data/system/users/userlist.xml.bak
01-01 23:45:52.960  3357  3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.960  3357  3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.960  3357  3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.960  3357  3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_READ_DATA
01-01 23:45:52.970  3357  3357 I kickstart: EVENT: !@ RECEIVED <-- SAHARA_END_IMAGE_TX
01-01 23:45:52.970  3357  3357 I kickstart: EVENT: !@ SENDING --> SAHARA_DONE
01-01 23:45:52.970  3357  3357 E kickstart: !@ 275556 bytes transferred in 0.084783 seconds
01-01 23:45:52.970  3357  3357 I kickstart: EVENT: !@ STATE <-- SAHARA_WAIT_DONE_RESP
01-01 23:45:52.970  3357  3357 E kickstart: Wrote to /sys/power/wake_unlock
01-01 23:45:52.970  3357  3357 I kickstart: EVENT: !@ STATE <-- SAHARA_WAIT_HELLO

Memory dump的流程:
這裏寫圖片描述
這裏寫圖片描述
下載ramdump的時候log如下,可以看到和上圖的流程一樣

01-01 23:45:52.850  3357  3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk
01-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 seconds
01-01 23:45:52.850  3357  3357 E kickstart: Opening file '/cpdump/MSGRAM.BIN' for writing
01-01 23:45:52.850  3357  3357 I kickstart: EVENT: !@ SENDING --> SAHARA_MEMORY_READ
01-01 23:45:52.850  3357  3357 I kickstart: EVENT: !@ Sent SAHARA_MEMORY_READ, address 0xFC428000, length 0x4000
01-01 23:45:52.860  3357  3357 I kickstart: WARNING: function: sahara_start:588 !@ Received: 16384 bytes
01-01 23:45:52.860  3357  3357 I kickstart: WARNING: function: sahara_start:593 !@ Writing to disk
01-01 23:45:52.860  3357  3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk
01-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 seconds
01-01 23:45:52.860  3357  3357 E kickstart: Opening file '/cpdump/DATARAM.BIN' for writing
01-01 23:45:52.860  3357  3357 I kickstart: EVENT: !@ SENDING --> SAHARA_MEMORY_READ
01-01 23:45:52.860  3357  3357 I kickstart: EVENT: !@ Sent SAHARA_MEMORY_READ, address 0xFC190000, length 0x10000
01-01 23:45:52.860  3357  3357 I kickstart: WARNING: function: sahara_start:588 !@ Received: 65536 bytes
01-01 23:45:52.860  3357  3357 I kickstart: WARNING: function: sahara_start:593 !@ Writing to disk
01-01 23:45:52.860  3357  3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk
01-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 seconds
01-01 23:45:52.860  3357  3357 E kickstart: Opening file '/cpdump/CODERAM.BIN' for writing
01-01 23:45:52.860  3357  3357 I kickstart: EVENT: !@ SENDING --> SAHARA_MEMORY_READ
01-01 23:45:52.860  3357  3357 I kickstart: EVENT: !@ Sent SAHARA_MEMORY_READ, address 0xFC100000, length 0x20000
01-01 23:45:52.860  3357  3357 I kickstart: WARNING: function: sahara_start:588 !@ Received: 131072 bytes
01-01 23:45:52.860  3357  3357 I kickstart: WARNING: function: sahara_start:593 !@ Writing to disk
01-01 23:45:52.860  3357  3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk
01-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 seconds
01-01 23:45:52.860  3357  3357 E kickstart: Opening file '/cpdump/OCIMEM.BIN' for writing
01-01 23:45:52.860  3357  3357 I kickstart: EVENT: !@ SENDING --> SAHARA_MEMORY_READ
01-01 23:45:52.860  3357  3357 I kickstart: EVENT: !@ Sent SAHARA_MEMORY_READ, address 0xFE800000, length 0x8800
01-01 23:45:52.870  3357  3357 I kickstart: WARNING: function: sahara_start:588 !@ Received: 34816 bytes
01-01 23:45:52.870  3357  3357 I kickstart: WARNING: function: sahara_start:593 !@ Writing to disk
01-01 23:45:52.870  3357  3357 I kickstart: WARNING: function: sahara_start:602 !@ Successfully wrote to disk
01-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 seconds
01-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

MDM代碼下載,efs同步過程

代碼添加及修改:

  • KERNEL代碼: kernel/drivers/usb/misc/ks_bridge.c
  • APP層代碼: android/vendor/qcom/proprietary/ks目錄

用戶層及內核代碼,功能流程:
AP,CP通過HSIC連接的方式,一個特點是CP本身沒有Flash等固態存儲媒介來保存本身的Binary。
所以在每次啓動的時候AP都需要通過HSIC來發送MDM的Binary過去。所以通過hsic建立usb連接,並完成下載。efs同步也需要通過hsic建立usb連接。

MDM代碼模塊

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章