Android4.0.3 USB OTG底层插入上报过程分析(1)
生活随笔
收集整理的這篇文章主要介紹了
Android4.0.3 USB OTG底层插入上报过程分析(1)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
下面的兩個宏是PM8058的MMP11(R15),MMP12(P15)管腳。
#define EXT_CHG_VALID_MPP 10
#define EXT_CHG_VALID_MPP_2 11
static struct pm8xxx_mpp_init_info isl_mpp[] = {
?? ?PM8058_MPP_INIT(EXT_CHG_VALID_MPP, D_INPUT,
?? ??? ?PM8058_MPP_DIG_LEVEL_S3, DIN_TO_INT),
?? ?PM8058_MPP_INIT(EXT_CHG_VALID_MPP_2, D_BI_DIR,
?? ??? ?PM8058_MPP_DIG_LEVEL_S3, BI_PULLUP_10KOHM),
};
//配置管腳功能函數
#if defined(CONFIG_SMB137B_CHARGER) || defined(CONFIG_SMB137B_CHARGER_MODULE)
static int smb137b_detection_setup(void)
{
?? ?int ret = 0, i;
?? ?for (i = 0; i < ARRAY_SIZE(isl_mpp); i++) {
?? ??? ?ret = pm8xxx_mpp_config(isl_mpp[i].mpp,&isl_mpp[i].config);
?? ?}
?? ?return ret;
}
static struct smb137b_platform_data smb137b_data __initdata = {
?? ?.chg_detection_config = smb137b_detection_setup,
?? ?.valid_n_gpio = PM8058_MPP_PM_TO_SYS(10),
?? ?.batt_mah_rating = 950,
};
static struct i2c_board_info smb137b_charger_i2c_info[] __initdata = {
?? ?{
?? ??? ?I2C_BOARD_INFO("smb137b", 0x08),
?? ??? ?.irq = PM8058_IRQ_BASE + PM8058_CBLPWR_IRQ,//計算后的irq值=464
?? ??? ?.platform_data = &smb137b_data,
?? ?},
};
#endif
static int __devinit smb137b_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
?? ?/*配置usb檢測管腳*/
?? ?if (pdata->chg_detection_config)
?? ??? ?ret = pdata->chg_detection_config();
?? ?/*用該檢測gpio引腳前,申請該GPIO*/
?? ?ret = gpio_request(pdata->valid_n_gpio, "smb137b_charger_valid");
?? ?/*申請中斷,該中斷號碼為464*/
?? ?ret = request_threaded_irq(client->irq, NULL,smb137b_valid_handler,
?? ??? ??? ??? ??? ?IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
?? ??? ??? ??? ??? ?"smb137b_charger_valid", client);
?? ?/*先讀取一次檢測管腳值*/
?? ?ret = gpio_get_value_cansleep(smb137b_chg->valid_n_gpio);
?? ?if (!ret) {
?? ??? ?/*上報usb的插入狀態*/
?? ??? ?msm_charger_notify_event(smb137b_chg->adapter_hw_chg[0],CHG_INSERTED_EVENT);
?? ??? ?smb137b_chg->usb_status = SMB137B_PRESENT;
?? ?}
}
/*以后的處理都是在中斷中進行處理*/
static irqreturn_t smb137b_valid_handler(int irq, void *dev_id)
{
?? ?struct smb137b_data *smb137b_chg;
?? ?smb137b_chg = i2c_get_clientdata(client);
?? ?smb137b_chg->current_hw_chg = smb137b_chg->adapter_hw_chg[0];
?? ?
?? ?/*讀出檢測管腳的電平值*/
?? ?val = gpio_get_value_cansleep(smb137b_chg->valid_n_gpio);
?? ?if (val) {
?? ??? ?if (smb137b_chg->usb_status != SMB137B_ABSENT) {
?? ??? ??? ?smb137b_chg->usb_status = SMB137B_ABSENT;
?? ??? ??? ?/*如果為高電平,通知usb移出*/
?? ??? ??? ?msm_charger_notify_event(smb137b_chg->current_hw_chg,CHG_REMOVED_EVENT);
?? ??? ?}
?? ?} else if (smb137b_chg->usb_status == SMB137B_ABSENT) {
?? ??? ??? ?smb137b_chg->usb_status = SMB137B_PRESENT;
?? ??? ??? ?/*如果為高電平,通知usb插入*/
?? ??? ??? ?msm_charger_notify_event(smb137b_chg->current_hw_chg,CHG_INSERTED_EVENT);
?? ??? ?}
}
下面進入發通知流程繼續跟蹤
int msm_charger_notify_event(struct msm_hardware_charger *hw_chg,
?? ??? ?enum msm_hardware_charger_event event)
{
?? ?/*把該消息加入循環隊列中*/
?? ?msm_chg_enqueue_event(hw_chg, event);
?? ?
?? ?/*調度work*/
?? ?queue_work(msm_chg.event_wq_thread, &msm_chg.queue_work);
?? ?return 0;
}
下面的兩行是在static int __init msm_charger_init(void)函數中進行初始化的:
INIT_WORK(&msm_chg.queue_work, process_events);
msm_chg.event_wq_thread = create_workqueue("msm_charger_eventd");? ?
該work的處理函數如下:
static void process_events(struct work_struct *work)
{
?? ?struct msm_charger_event *event;
?? ?int rc;
?? ?/*循環處理等待隊列中的消息*/
?? ?do {
?? ??? ?rc = msm_chg_dequeue_event(&event);
?? ??? ?if (!rc)
?? ??? ??? ?/*對單個的event進行處理*/
?? ??? ??? ?handle_event(event->hw_chg, event->event);
?? ?} while (!rc);
}
下面進入具體的handle_event函數分析:
static void handle_event(struct msm_hardware_charger *hw_chg, int event)
{
?? ?struct msm_hardware_charger_priv *priv = NULL;
?? ?if (hw_chg)
?? ??? ?priv = hw_chg->charger_private;
?? ?switch (event) {
?? ??? ?case CHG_INSERTED_EVENT:
?? ??? ??? ?if (hw_chg->type == CHG_TYPE_USB) {
?? ??? ??? ??? ?.................
?? ??? ??? ??? ?priv->hw_chg_state = CHG_PRESENT_STATE;
?? ??? ??? ??? ?/*上報usb插入事件*/
?? ??? ??? ??? ?notify_usb_of_the_plugin_event(priv, 1);
?? ??? ??? ??? ?.........................
?? ??? ??? ?break;
?? ??? ?case CHG_REMOVED_EVENT:
?? ??? ??? ?if (hw_chg->type == CHG_TYPE_USB) {
?? ??? ??? ??? ?...............
?? ??? ??? ??? ?usb_chg_current = 0;
?? ??? ??? ??? ?/*上報usb移出事件*/
?? ??? ??? ??? ?notify_usb_of_the_plugin_event(priv, 0);
?? ??? ??? ??? ?........................
?? ??? ??? ?}
?? ??? ??? ?break;
}
/*進入notify_usb_of_the_plugin_event函數繼續跟蹤*/
static void notify_usb_of_the_plugin_event(struct msm_hardware_charger_priv
?? ??? ?*hw_chg, int plugin)
{
?? ?plugin = !!plugin;
?? ?if (plugin == 1 && usb_notified_of_insertion == 0) {
?? ??? ?usb_notified_of_insertion = 1;
?? ??? ?if (notify_vbus_state_func_ptr) {
?? ??? ??? ?/*調用回調函數*/
?? ??? ??? ?(*notify_vbus_state_func_ptr) (plugin);
?? ?}
?? ?if (plugin == 0 && usb_notified_of_insertion == 1) {
?? ??? ?if (notify_vbus_state_func_ptr) {
?? ??? ??? ?(*notify_vbus_state_func_ptr) (plugin);
?? ??? ?}?
?? ??? ?usb_notified_of_insertion = 0;
?? ?}
}
/*下面進入回調函數的跟蹤*/
/*在板級初始化時定義了一個全局函數指針*/
notify_vbus_state notify_vbus_state_func_ptr;
/*該函數指針在該回調函數中賦值*/
static int msm_hsusb_pmic_vbus_notif_init(void (*callback)(int online),
?? ??? ??? ??? ??? ??? ??? ??? ?int init)
{
?? ?int ret = -ENOTSUPP;
?? ?if (machine_is_msm8x60_s9000() || pmic_id_notif_supported)) {
?? ??? ?if (init)
?? ??? ??? ?ret = msm_charger_register_vbus_sn(callback);
?? ??? ?else {
?? ??? ??? ?msm_charger_unregister_vbus_sn(callback);
?? ??? ??? ?ret = 0;
?? ??? ?}
?? ?}?
}
int msm_charger_register_vbus_sn(void (*callback)(int))
{
?? ?notify_vbus_state_func_ptr = callback;
?? ?return 0;
}
/*該回調函數注冊的時機如下*/
#if defined(CONFIG_USB_GADGET_MSM_72K) || defined(CONFIG_USB_EHCI_MSM_72K)
static struct msm_otg_platform_data msm_otg_pdata = {
?? ?................
#ifdef CONFIG_BATTERY_MSM8X60
?? ?.pmic_vbus_notif_init?? ?= msm_hsusb_pmic_vbus_notif_init,
#endif
?? ?.........................
};
#endif
/*把該平臺數據賦值給平臺設備*/
msm_device_otg.dev.platform_data = &msm_otg_pdata;
/*注冊該平臺設備*/
static struct platform_device *surf_devices[] __initdata = {
#if defined(CONFIG_USB_GADGET_MSM_72K) || defined(CONFIG_USB_EHCI_HCD)
?? ?&msm_device_otg,
#endif
}
static void __init msm8x60_init(struct msm_board_data *board_data)
{
?? ?platform_add_devices(surf_devices,ARRAY_SIZE(surf_devices));
}
static int __init msm_otg_probe(struct platform_device *pdev)
{
?? ?..............
?? ?/*初始化work工作隊列*/
?? ?INIT_WORK(&dev->sm_work, msm_otg_sm_work);
?? ?dev->wq = alloc_workqueue("k_otg", WQ_NON_REENTRANT, 0);
?? ?..................
?? ?/*調用回調函數,為全局函數指針賦值*/
?? ?if (dev->pdata->pmic_vbus_notif_init) {
?? ??? ?ret = dev->pdata->pmic_vbus_notif_init
?? ??? ??? ?(&msm_otg_set_vbus_state, 1);
?? ??? ?if (!ret) {
?? ??? ??? ?dev->pmic_vbus_notif_supp = 1;
?? ??? ?}?
?? ?}
?? ?...............
?? ?.......................
}
/*然后用該函數上報plug的值*/
void msm_otg_set_vbus_state(int online)
{
?? ?struct msm_otg *dev = the_msm_otg;
?? ?/*如果上報插入事件,就設置B_SESS_VLD標志位*/
?? ?if (online)
?? ??? ?set_bit(B_SESS_VLD, &dev->inputs);
?? ?/*如果上報移除事件,就清除B_SESS_VLD標志位*/
?? ?else
?? ??? ?clear_bit(B_SESS_VLD, &dev->inputs);
?? ?
?? ?/*獲得wakelock鎖*/
?? ?wake_lock(&dev->wlock);
?? ?
?? ?/*調度工作隊列中的work*/
?? ?queue_work(dev->wq, &dev->sm_work);
}
/*下面進入work繼續跟蹤*/
static void msm_otg_sm_work(struct work_struct *w)
{
?? ?enum usb_otg_state state;
?? ?state = dev->otg.state;
?? ?switch (state) {
?? ??? ?case OTG_STATE_UNDEFINED:
?? ??? ??? ?if (!dev->otg.host || !is_host())
?? ??? ??? ?{
?? ??? ??? ??? ?set_bit(ID, &dev->inputs);
?? ??? ??? ?}
?? ??? ??? ?if (dev->otg.gadget && is_b_sess_vld())
?? ??? ??? ?{
?? ??? ??? ??? ?set_bit(B_SESS_VLD, &dev->inputs);
?? ??? ??? ?}
?? ??? ??? ?if ((test_bit(ID, &dev->inputs)) && !test_bit(ID_A, &dev->inputs)) {
?? ??? ??? ??? ?/*改變otg的狀態機狀態為OTG_STATE_B_IDLE*/
?? ??? ??? ??? ?dev->otg.state = OTG_STATE_B_IDLE;
?? ??? ??? ?}?
?? ??? ??? ?work = 1;
?? ??? ??? ?break;
?? ??? ?case OTG_STATE_B_IDLE:
?? ??? ??? ?if (test_bit(B_SESS_VLD, &dev->inputs) && !test_bit(ID_B, &dev->inputs)) {
?? ??? ??? ?/*改變otg的狀態機狀態為OTG_STATE_B_PERIPHERAL*/
?? ??? ??? ?dev->otg.state = OTG_STATE_B_PERIPHERAL;
?? ??? ??? ?msm_otg_set_power(&dev->otg, 0);
?? ??? ??? ?
?? ??? ??? ?/*啟動外圍設備*/
?? ??? ??? ?msm_otg_start_peripheral(&dev->otg, 1);
?? ??? ?}?
?? ??? ?break;
?? ?/*如果work為1,則繼續調度work*/
?? ?if (work)
?? ??? ?queue_work(dev->wq, &dev->sm_work);
}
/*上面的work牽涉到兩個函數,通過寄存器的值判斷,設置相應的位域*/
static int is_host(void)
{
?? ?struct msm_otg *dev = the_msm_otg;
?? ?if (dev->pdata->otg_mode == OTG_ID)
?? ?{
?? ??? ?/*讀出該寄存器的第8位,如果讀出的為1,則返回0,即該設備為B device*/
?? ??? ?return (OTGSC_ID & readl(USB_OTGSC)) ? 0 : 1;
?? ?}
}
static int is_b_sess_vld(void)
{
?? ?struct msm_otg *dev = the_msm_otg;
?? ?if (dev->pdata->otg_mode == OTG_ID)
?? ?{
?? ??? ?/*讀出該寄存器的第11位,如果為1,則返回1,該寄存器在spec中說明如下:Indicates that the Vbus is above the B session valid threshold.*/
?? ??? ?return (OTGSC_BSV & readl(USB_OTGSC)) ? 1 : 0;
?? ?}
}
/*下面進入msm_otg_start_peripheral函數進行分析*/
static void msm_otg_start_peripheral(struct otg_transceiver *xceiv, int on)
{
?? ?struct msm_otg *dev = container_of(xceiv, struct msm_otg, otg);
?? ?if (on) {
?? ??? ?usb_gadget_vbus_connect(xceiv->gadget);
?? ?}?
}
/*設置gadget的vbus*/
static inline int usb_gadget_vbus_connect(struct usb_gadget *gadget)
{
?? ?if (!gadget->ops->vbus_session)
?? ??? ?return -EOPNOTSUPP;
?? ?return gadget->ops->vbus_session(gadget, 1);
}
/*調用底層gadget的回調函數*/
gadget->ops->vbus_session(gadget, 1);
/*下面是該回調函數的結構體*/
static const struct usb_gadget_ops msm72k_ops = {
?? ?.get_frame?? ?= msm72k_get_frame,
?? ?/*該回調函數*/
?? ?.vbus_session?? ?= msm72k_udc_vbus_session,
?? ?.vbus_draw?? ?= msm72k_udc_vbus_draw,
?? ?.pullup?? ??? ?= msm72k_pullup,
?? ?.wakeup?? ??? ?= msm72k_wakeup,
?? ?.set_selfpowered = msm72k_set_selfpowered,
};
/*回調函數的注冊過程如下*/
static int msm72k_probe(struct platform_device *pdev)
{
?? ?ui = kzalloc(sizeof(struct usb_info), GFP_KERNEL);
?? ?ui->gadget.ops = &msm72k_ops;
}
/*看下vbus的回調函數*/
static int msm72k_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
{
?? ?/*設置vbus的狀態*/
?? ?msm_hsusb_set_vbus_state(is_active);
?? ?return 0;
}
/*繼續跟蹤設置vbus的狀態*/
void msm_hsusb_set_vbus_state(int online)
{
?? ?struct usb_info *ui = the_usb_info;
?? ?/*根據傳入的狀態設置usb的狀態位*/
?? ?if (online) {
?? ??? ?ui->usb_state = USB_STATE_POWERED;
?? ??? ?ui->flags |= USB_FLAG_VBUS_ONLINE;
?? ?} else {
?? ??? ?ui->gadget.speed = USB_SPEED_UNKNOWN;
?? ??? ?ui->usb_state = USB_STATE_NOTATTACHED;
?? ??? ?ui->flags |= USB_FLAG_VBUS_OFFLINE;
?? ?}
?? ?
?? ?/*調度usb的工作隊列*/
?? ?if (in_interrupt()) {
?? ??? ?schedule_work(&ui->work);
?? ?} else {
?? ??? ?usb_do_work(&ui->work);
?? ??? ?return;
?? ?}
}
/*在usb_do_work中會進入一個大的狀態機循環*/
static void usb_do_work(struct work_struct *w)
{
?? ?struct usb_info *ui = container_of(w, struct usb_info, work);
?? ?struct msm_otg *otg = to_msm_otg(ui->xceiv);
?? ?unsigned long iflags;
?? ?unsigned flags, _vbus;
?? ?for (;;) {
?? ??? ?spin_lock_irqsave(&ui->lock, iflags);
?? ??? ?flags = ui->flags;
?? ??? ?ui->flags = 0;
?? ??? ?_vbus = is_usb_online(ui);
?? ??? ?spin_unlock_irqrestore(&ui->lock, iflags);
?? ??? ?/* give up if we have nothing to do */
?? ??? ?if (flags == 0)
?? ??? ??? ?break;
?? ??? ?switch (ui->state) {
?? ??? ?case USB_STATE_IDLE:
?? ??? ??? ?if (flags & USB_FLAG_START) {
?? ??? ??? ??? ?int ret;
?? ??? ??? ??? ?/*重啟設備控制器*/
?? ??? ??? ??? ?usb_reset(ui);
?? ??? ??? ??? ?
?? ??? ??? ??? ?/*申請中斷處理函數*/
?? ??? ??? ??? ?ret = request_irq(otg->irq, usb_interrupt,IRQF_SHARED,ui->pdev->name, ui);
?? ??? ??? ??? ?ui->irq = otg->irq;
?? ??? ??? ??? ?
?? ??? ??? ??? ?/*改變設備狀態*/
?? ??? ??? ??? ?ui->state = USB_STATE_ONLINE;
?? ??? ??? ??? ?usb_do_work_check_vbus(ui);
?? ??? ??? ??? ?
?? ??? ??? ??? ?/*使能D+數據線上的上拉電阻*/
?? ??? ??? ??? ?msm72k_pullup_internal(&ui->gadget, 1);
?? ??? ??? ?break;
?? ??? ?case USB_STATE_ONLINE:
?? ??? ??? ?if (flags & USB_FLAG_SUSPEND) {
?? ??? ??? ??? ?int maxpower = usb_get_max_power(ui);
?? ??? ??? ??? ?otg_set_power(ui->xceiv, 0);
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ??? ?if (flags & USB_FLAG_CONFIGURED) {
?? ??? ??? ??? ?int maxpower = usb_get_max_power(ui);
?? ??? ??? ??? ?switch_set_state(&ui->sdev,atomic_read(&ui->configured));
?? ??? ??? ??? ?ui->chg_current = maxpower;
?? ??? ??? ??? ?otg_set_power(ui->xceiv, maxpower);
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ??? ?if (flags & USB_FLAG_RESET) {
?? ??? ??? ??? ?msm72k_pullup_internal(&ui->gadget, 0);
?? ??? ??? ??? ?usb_reset(ui);
?? ??? ??? ??? ?msm72k_pullup_internal(&ui->gadget, 1);
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ??? ?break;
?? ??? ?case USB_STATE_OFFLINE:
?? ??? ??? ?if ((flags & USB_FLAG_VBUS_ONLINE) && _vbus) {
?? ??? ??? ??? ?/*重啟設備控制器*/
?? ??? ??? ??? ?usb_reset(ui);
?? ??? ??? ??? ?/*改變設備狀態*/
?? ??? ??? ??? ?ui->state = USB_STATE_ONLINE;
?? ??? ??? ??? ?usb_do_work_check_vbus(ui);
?? ??? ??? ??? ?/*申請中斷處理函數*/
?? ??? ??? ??? ?ret = request_irq(otg->irq, usb_interrupt,IRQF_SHARED,ui->pdev->name, ui);
?? ??? ??? ??? ?ui->irq = otg->irq;
?? ??? ??? ??? ?/*使能D+數據線上的上拉電阻*/
?? ??? ??? ??? ?msm72k_pullup_internal(&ui->gadget, 1);
?? ??? ??? ?}
?? ??? ??? ?break;
?? ??? ?}
?? ?}
}
/*中斷函數的實時處理*/
static irqreturn_t usb_interrupt(int irq, void *data)
{
?? ?struct usb_info *ui = data;
?? ?unsigned n;
?? ?unsigned long flags;
?? ?n = readl(USB_USBSTS);
?? ?writel(n, USB_USBSTS);
?? ?
?? ?/*端口變化探測*/
?? ?if (n & STS_PCI) {
?? ??? ?msm_hsusb_set_speed(ui);
?? ??? ?if (atomic_read(&ui->configured)) {
?? ??? ??? ?ui->usb_state = USB_STATE_CONFIGURED;
?? ??? ??? ?ui->flags = USB_FLAG_CONFIGURED;
?? ??? ??? ?ui->driver->resume(&ui->gadget);
?? ??? ??? ?schedule_work(&ui->work);
?? ??? ?} else {
?? ??? ??? ?msm_hsusb_set_state(USB_STATE_DEFAULT);
?? ??? ?}
?? ?}
?? ?/*usb重啟*/
?? ?if (n & STS_URI) {
?? ??? ?dev_dbg(&ui->pdev->dev, "reset\n");
?? ??? ?ui->gadget.speed = USB_SPEED_UNKNOWN;
?? ??? ?msm_hsusb_set_state(USB_STATE_DEFAULT);
?? ??? ?......................
?? ?}
?? ?/*usb掛起狀態*/
?? ?if (n & STS_SLI) {
?? ??? ?dev_dbg(&ui->pdev->dev, "suspend\n");
?? ??? ?ui->usb_state = USB_STATE_SUSPENDED;
?? ??? ?ui->flags = USB_FLAG_SUSPEND;
?? ??? ?ui->driver->suspend(&ui->gadget);
?? ??? ?schedule_work(&ui->work);
?? ?}
?? ?/*usb事務傳輸完成中斷*/
?? ?if (n & STS_UI) {
?? ??? ?n = readl(USB_ENDPTSETUPSTAT);
?? ??? ?if (n & EPT_RX(0))
?? ??? ??? ?handle_setup(ui);
?? ??? ?n = readl(USB_ENDPTCOMPLETE);
?? ??? ?writel(n, USB_ENDPTCOMPLETE);
?? ??? ?while (n) {
?? ??? ??? ?unsigned bit = __ffs(n);
?? ??? ??? ?handle_endpoint(ui, bit);
?? ??? ??? ?n = n & (~(1 << bit));
?? ??? ?}
?? ?}
?? ?return IRQ_HANDLED;
}
#define EXT_CHG_VALID_MPP 10
#define EXT_CHG_VALID_MPP_2 11
static struct pm8xxx_mpp_init_info isl_mpp[] = {
?? ?PM8058_MPP_INIT(EXT_CHG_VALID_MPP, D_INPUT,
?? ??? ?PM8058_MPP_DIG_LEVEL_S3, DIN_TO_INT),
?? ?PM8058_MPP_INIT(EXT_CHG_VALID_MPP_2, D_BI_DIR,
?? ??? ?PM8058_MPP_DIG_LEVEL_S3, BI_PULLUP_10KOHM),
};
//配置管腳功能函數
#if defined(CONFIG_SMB137B_CHARGER) || defined(CONFIG_SMB137B_CHARGER_MODULE)
static int smb137b_detection_setup(void)
{
?? ?int ret = 0, i;
?? ?for (i = 0; i < ARRAY_SIZE(isl_mpp); i++) {
?? ??? ?ret = pm8xxx_mpp_config(isl_mpp[i].mpp,&isl_mpp[i].config);
?? ?}
?? ?return ret;
}
static struct smb137b_platform_data smb137b_data __initdata = {
?? ?.chg_detection_config = smb137b_detection_setup,
?? ?.valid_n_gpio = PM8058_MPP_PM_TO_SYS(10),
?? ?.batt_mah_rating = 950,
};
static struct i2c_board_info smb137b_charger_i2c_info[] __initdata = {
?? ?{
?? ??? ?I2C_BOARD_INFO("smb137b", 0x08),
?? ??? ?.irq = PM8058_IRQ_BASE + PM8058_CBLPWR_IRQ,//計算后的irq值=464
?? ??? ?.platform_data = &smb137b_data,
?? ?},
};
#endif
static int __devinit smb137b_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
?? ?/*配置usb檢測管腳*/
?? ?if (pdata->chg_detection_config)
?? ??? ?ret = pdata->chg_detection_config();
?? ?/*用該檢測gpio引腳前,申請該GPIO*/
?? ?ret = gpio_request(pdata->valid_n_gpio, "smb137b_charger_valid");
?? ?/*申請中斷,該中斷號碼為464*/
?? ?ret = request_threaded_irq(client->irq, NULL,smb137b_valid_handler,
?? ??? ??? ??? ??? ?IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
?? ??? ??? ??? ??? ?"smb137b_charger_valid", client);
?? ?/*先讀取一次檢測管腳值*/
?? ?ret = gpio_get_value_cansleep(smb137b_chg->valid_n_gpio);
?? ?if (!ret) {
?? ??? ?/*上報usb的插入狀態*/
?? ??? ?msm_charger_notify_event(smb137b_chg->adapter_hw_chg[0],CHG_INSERTED_EVENT);
?? ??? ?smb137b_chg->usb_status = SMB137B_PRESENT;
?? ?}
}
/*以后的處理都是在中斷中進行處理*/
static irqreturn_t smb137b_valid_handler(int irq, void *dev_id)
{
?? ?struct smb137b_data *smb137b_chg;
?? ?smb137b_chg = i2c_get_clientdata(client);
?? ?smb137b_chg->current_hw_chg = smb137b_chg->adapter_hw_chg[0];
?? ?
?? ?/*讀出檢測管腳的電平值*/
?? ?val = gpio_get_value_cansleep(smb137b_chg->valid_n_gpio);
?? ?if (val) {
?? ??? ?if (smb137b_chg->usb_status != SMB137B_ABSENT) {
?? ??? ??? ?smb137b_chg->usb_status = SMB137B_ABSENT;
?? ??? ??? ?/*如果為高電平,通知usb移出*/
?? ??? ??? ?msm_charger_notify_event(smb137b_chg->current_hw_chg,CHG_REMOVED_EVENT);
?? ??? ?}
?? ?} else if (smb137b_chg->usb_status == SMB137B_ABSENT) {
?? ??? ??? ?smb137b_chg->usb_status = SMB137B_PRESENT;
?? ??? ??? ?/*如果為高電平,通知usb插入*/
?? ??? ??? ?msm_charger_notify_event(smb137b_chg->current_hw_chg,CHG_INSERTED_EVENT);
?? ??? ?}
}
下面進入發通知流程繼續跟蹤
int msm_charger_notify_event(struct msm_hardware_charger *hw_chg,
?? ??? ?enum msm_hardware_charger_event event)
{
?? ?/*把該消息加入循環隊列中*/
?? ?msm_chg_enqueue_event(hw_chg, event);
?? ?
?? ?/*調度work*/
?? ?queue_work(msm_chg.event_wq_thread, &msm_chg.queue_work);
?? ?return 0;
}
下面的兩行是在static int __init msm_charger_init(void)函數中進行初始化的:
INIT_WORK(&msm_chg.queue_work, process_events);
msm_chg.event_wq_thread = create_workqueue("msm_charger_eventd");? ?
該work的處理函數如下:
static void process_events(struct work_struct *work)
{
?? ?struct msm_charger_event *event;
?? ?int rc;
?? ?/*循環處理等待隊列中的消息*/
?? ?do {
?? ??? ?rc = msm_chg_dequeue_event(&event);
?? ??? ?if (!rc)
?? ??? ??? ?/*對單個的event進行處理*/
?? ??? ??? ?handle_event(event->hw_chg, event->event);
?? ?} while (!rc);
}
下面進入具體的handle_event函數分析:
static void handle_event(struct msm_hardware_charger *hw_chg, int event)
{
?? ?struct msm_hardware_charger_priv *priv = NULL;
?? ?if (hw_chg)
?? ??? ?priv = hw_chg->charger_private;
?? ?switch (event) {
?? ??? ?case CHG_INSERTED_EVENT:
?? ??? ??? ?if (hw_chg->type == CHG_TYPE_USB) {
?? ??? ??? ??? ?.................
?? ??? ??? ??? ?priv->hw_chg_state = CHG_PRESENT_STATE;
?? ??? ??? ??? ?/*上報usb插入事件*/
?? ??? ??? ??? ?notify_usb_of_the_plugin_event(priv, 1);
?? ??? ??? ??? ?.........................
?? ??? ??? ?break;
?? ??? ?case CHG_REMOVED_EVENT:
?? ??? ??? ?if (hw_chg->type == CHG_TYPE_USB) {
?? ??? ??? ??? ?...............
?? ??? ??? ??? ?usb_chg_current = 0;
?? ??? ??? ??? ?/*上報usb移出事件*/
?? ??? ??? ??? ?notify_usb_of_the_plugin_event(priv, 0);
?? ??? ??? ??? ?........................
?? ??? ??? ?}
?? ??? ??? ?break;
}
/*進入notify_usb_of_the_plugin_event函數繼續跟蹤*/
static void notify_usb_of_the_plugin_event(struct msm_hardware_charger_priv
?? ??? ?*hw_chg, int plugin)
{
?? ?plugin = !!plugin;
?? ?if (plugin == 1 && usb_notified_of_insertion == 0) {
?? ??? ?usb_notified_of_insertion = 1;
?? ??? ?if (notify_vbus_state_func_ptr) {
?? ??? ??? ?/*調用回調函數*/
?? ??? ??? ?(*notify_vbus_state_func_ptr) (plugin);
?? ?}
?? ?if (plugin == 0 && usb_notified_of_insertion == 1) {
?? ??? ?if (notify_vbus_state_func_ptr) {
?? ??? ??? ?(*notify_vbus_state_func_ptr) (plugin);
?? ??? ?}?
?? ??? ?usb_notified_of_insertion = 0;
?? ?}
}
/*下面進入回調函數的跟蹤*/
/*在板級初始化時定義了一個全局函數指針*/
notify_vbus_state notify_vbus_state_func_ptr;
/*該函數指針在該回調函數中賦值*/
static int msm_hsusb_pmic_vbus_notif_init(void (*callback)(int online),
?? ??? ??? ??? ??? ??? ??? ??? ?int init)
{
?? ?int ret = -ENOTSUPP;
?? ?if (machine_is_msm8x60_s9000() || pmic_id_notif_supported)) {
?? ??? ?if (init)
?? ??? ??? ?ret = msm_charger_register_vbus_sn(callback);
?? ??? ?else {
?? ??? ??? ?msm_charger_unregister_vbus_sn(callback);
?? ??? ??? ?ret = 0;
?? ??? ?}
?? ?}?
}
int msm_charger_register_vbus_sn(void (*callback)(int))
{
?? ?notify_vbus_state_func_ptr = callback;
?? ?return 0;
}
/*該回調函數注冊的時機如下*/
#if defined(CONFIG_USB_GADGET_MSM_72K) || defined(CONFIG_USB_EHCI_MSM_72K)
static struct msm_otg_platform_data msm_otg_pdata = {
?? ?................
#ifdef CONFIG_BATTERY_MSM8X60
?? ?.pmic_vbus_notif_init?? ?= msm_hsusb_pmic_vbus_notif_init,
#endif
?? ?.........................
};
#endif
/*把該平臺數據賦值給平臺設備*/
msm_device_otg.dev.platform_data = &msm_otg_pdata;
/*注冊該平臺設備*/
static struct platform_device *surf_devices[] __initdata = {
#if defined(CONFIG_USB_GADGET_MSM_72K) || defined(CONFIG_USB_EHCI_HCD)
?? ?&msm_device_otg,
#endif
}
static void __init msm8x60_init(struct msm_board_data *board_data)
{
?? ?platform_add_devices(surf_devices,ARRAY_SIZE(surf_devices));
}
static int __init msm_otg_probe(struct platform_device *pdev)
{
?? ?..............
?? ?/*初始化work工作隊列*/
?? ?INIT_WORK(&dev->sm_work, msm_otg_sm_work);
?? ?dev->wq = alloc_workqueue("k_otg", WQ_NON_REENTRANT, 0);
?? ?..................
?? ?/*調用回調函數,為全局函數指針賦值*/
?? ?if (dev->pdata->pmic_vbus_notif_init) {
?? ??? ?ret = dev->pdata->pmic_vbus_notif_init
?? ??? ??? ?(&msm_otg_set_vbus_state, 1);
?? ??? ?if (!ret) {
?? ??? ??? ?dev->pmic_vbus_notif_supp = 1;
?? ??? ?}?
?? ?}
?? ?...............
?? ?.......................
}
/*然后用該函數上報plug的值*/
void msm_otg_set_vbus_state(int online)
{
?? ?struct msm_otg *dev = the_msm_otg;
?? ?/*如果上報插入事件,就設置B_SESS_VLD標志位*/
?? ?if (online)
?? ??? ?set_bit(B_SESS_VLD, &dev->inputs);
?? ?/*如果上報移除事件,就清除B_SESS_VLD標志位*/
?? ?else
?? ??? ?clear_bit(B_SESS_VLD, &dev->inputs);
?? ?
?? ?/*獲得wakelock鎖*/
?? ?wake_lock(&dev->wlock);
?? ?
?? ?/*調度工作隊列中的work*/
?? ?queue_work(dev->wq, &dev->sm_work);
}
/*下面進入work繼續跟蹤*/
static void msm_otg_sm_work(struct work_struct *w)
{
?? ?enum usb_otg_state state;
?? ?state = dev->otg.state;
?? ?switch (state) {
?? ??? ?case OTG_STATE_UNDEFINED:
?? ??? ??? ?if (!dev->otg.host || !is_host())
?? ??? ??? ?{
?? ??? ??? ??? ?set_bit(ID, &dev->inputs);
?? ??? ??? ?}
?? ??? ??? ?if (dev->otg.gadget && is_b_sess_vld())
?? ??? ??? ?{
?? ??? ??? ??? ?set_bit(B_SESS_VLD, &dev->inputs);
?? ??? ??? ?}
?? ??? ??? ?if ((test_bit(ID, &dev->inputs)) && !test_bit(ID_A, &dev->inputs)) {
?? ??? ??? ??? ?/*改變otg的狀態機狀態為OTG_STATE_B_IDLE*/
?? ??? ??? ??? ?dev->otg.state = OTG_STATE_B_IDLE;
?? ??? ??? ?}?
?? ??? ??? ?work = 1;
?? ??? ??? ?break;
?? ??? ?case OTG_STATE_B_IDLE:
?? ??? ??? ?if (test_bit(B_SESS_VLD, &dev->inputs) && !test_bit(ID_B, &dev->inputs)) {
?? ??? ??? ?/*改變otg的狀態機狀態為OTG_STATE_B_PERIPHERAL*/
?? ??? ??? ?dev->otg.state = OTG_STATE_B_PERIPHERAL;
?? ??? ??? ?msm_otg_set_power(&dev->otg, 0);
?? ??? ??? ?
?? ??? ??? ?/*啟動外圍設備*/
?? ??? ??? ?msm_otg_start_peripheral(&dev->otg, 1);
?? ??? ?}?
?? ??? ?break;
?? ?/*如果work為1,則繼續調度work*/
?? ?if (work)
?? ??? ?queue_work(dev->wq, &dev->sm_work);
}
/*上面的work牽涉到兩個函數,通過寄存器的值判斷,設置相應的位域*/
static int is_host(void)
{
?? ?struct msm_otg *dev = the_msm_otg;
?? ?if (dev->pdata->otg_mode == OTG_ID)
?? ?{
?? ??? ?/*讀出該寄存器的第8位,如果讀出的為1,則返回0,即該設備為B device*/
?? ??? ?return (OTGSC_ID & readl(USB_OTGSC)) ? 0 : 1;
?? ?}
}
static int is_b_sess_vld(void)
{
?? ?struct msm_otg *dev = the_msm_otg;
?? ?if (dev->pdata->otg_mode == OTG_ID)
?? ?{
?? ??? ?/*讀出該寄存器的第11位,如果為1,則返回1,該寄存器在spec中說明如下:Indicates that the Vbus is above the B session valid threshold.*/
?? ??? ?return (OTGSC_BSV & readl(USB_OTGSC)) ? 1 : 0;
?? ?}
}
/*下面進入msm_otg_start_peripheral函數進行分析*/
static void msm_otg_start_peripheral(struct otg_transceiver *xceiv, int on)
{
?? ?struct msm_otg *dev = container_of(xceiv, struct msm_otg, otg);
?? ?if (on) {
?? ??? ?usb_gadget_vbus_connect(xceiv->gadget);
?? ?}?
}
/*設置gadget的vbus*/
static inline int usb_gadget_vbus_connect(struct usb_gadget *gadget)
{
?? ?if (!gadget->ops->vbus_session)
?? ??? ?return -EOPNOTSUPP;
?? ?return gadget->ops->vbus_session(gadget, 1);
}
/*調用底層gadget的回調函數*/
gadget->ops->vbus_session(gadget, 1);
/*下面是該回調函數的結構體*/
static const struct usb_gadget_ops msm72k_ops = {
?? ?.get_frame?? ?= msm72k_get_frame,
?? ?/*該回調函數*/
?? ?.vbus_session?? ?= msm72k_udc_vbus_session,
?? ?.vbus_draw?? ?= msm72k_udc_vbus_draw,
?? ?.pullup?? ??? ?= msm72k_pullup,
?? ?.wakeup?? ??? ?= msm72k_wakeup,
?? ?.set_selfpowered = msm72k_set_selfpowered,
};
/*回調函數的注冊過程如下*/
static int msm72k_probe(struct platform_device *pdev)
{
?? ?ui = kzalloc(sizeof(struct usb_info), GFP_KERNEL);
?? ?ui->gadget.ops = &msm72k_ops;
}
/*看下vbus的回調函數*/
static int msm72k_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
{
?? ?/*設置vbus的狀態*/
?? ?msm_hsusb_set_vbus_state(is_active);
?? ?return 0;
}
/*繼續跟蹤設置vbus的狀態*/
void msm_hsusb_set_vbus_state(int online)
{
?? ?struct usb_info *ui = the_usb_info;
?? ?/*根據傳入的狀態設置usb的狀態位*/
?? ?if (online) {
?? ??? ?ui->usb_state = USB_STATE_POWERED;
?? ??? ?ui->flags |= USB_FLAG_VBUS_ONLINE;
?? ?} else {
?? ??? ?ui->gadget.speed = USB_SPEED_UNKNOWN;
?? ??? ?ui->usb_state = USB_STATE_NOTATTACHED;
?? ??? ?ui->flags |= USB_FLAG_VBUS_OFFLINE;
?? ?}
?? ?
?? ?/*調度usb的工作隊列*/
?? ?if (in_interrupt()) {
?? ??? ?schedule_work(&ui->work);
?? ?} else {
?? ??? ?usb_do_work(&ui->work);
?? ??? ?return;
?? ?}
}
/*在usb_do_work中會進入一個大的狀態機循環*/
static void usb_do_work(struct work_struct *w)
{
?? ?struct usb_info *ui = container_of(w, struct usb_info, work);
?? ?struct msm_otg *otg = to_msm_otg(ui->xceiv);
?? ?unsigned long iflags;
?? ?unsigned flags, _vbus;
?? ?for (;;) {
?? ??? ?spin_lock_irqsave(&ui->lock, iflags);
?? ??? ?flags = ui->flags;
?? ??? ?ui->flags = 0;
?? ??? ?_vbus = is_usb_online(ui);
?? ??? ?spin_unlock_irqrestore(&ui->lock, iflags);
?? ??? ?/* give up if we have nothing to do */
?? ??? ?if (flags == 0)
?? ??? ??? ?break;
?? ??? ?switch (ui->state) {
?? ??? ?case USB_STATE_IDLE:
?? ??? ??? ?if (flags & USB_FLAG_START) {
?? ??? ??? ??? ?int ret;
?? ??? ??? ??? ?/*重啟設備控制器*/
?? ??? ??? ??? ?usb_reset(ui);
?? ??? ??? ??? ?
?? ??? ??? ??? ?/*申請中斷處理函數*/
?? ??? ??? ??? ?ret = request_irq(otg->irq, usb_interrupt,IRQF_SHARED,ui->pdev->name, ui);
?? ??? ??? ??? ?ui->irq = otg->irq;
?? ??? ??? ??? ?
?? ??? ??? ??? ?/*改變設備狀態*/
?? ??? ??? ??? ?ui->state = USB_STATE_ONLINE;
?? ??? ??? ??? ?usb_do_work_check_vbus(ui);
?? ??? ??? ??? ?
?? ??? ??? ??? ?/*使能D+數據線上的上拉電阻*/
?? ??? ??? ??? ?msm72k_pullup_internal(&ui->gadget, 1);
?? ??? ??? ?break;
?? ??? ?case USB_STATE_ONLINE:
?? ??? ??? ?if (flags & USB_FLAG_SUSPEND) {
?? ??? ??? ??? ?int maxpower = usb_get_max_power(ui);
?? ??? ??? ??? ?otg_set_power(ui->xceiv, 0);
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ??? ?if (flags & USB_FLAG_CONFIGURED) {
?? ??? ??? ??? ?int maxpower = usb_get_max_power(ui);
?? ??? ??? ??? ?switch_set_state(&ui->sdev,atomic_read(&ui->configured));
?? ??? ??? ??? ?ui->chg_current = maxpower;
?? ??? ??? ??? ?otg_set_power(ui->xceiv, maxpower);
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ??? ?if (flags & USB_FLAG_RESET) {
?? ??? ??? ??? ?msm72k_pullup_internal(&ui->gadget, 0);
?? ??? ??? ??? ?usb_reset(ui);
?? ??? ??? ??? ?msm72k_pullup_internal(&ui->gadget, 1);
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ??? ?break;
?? ??? ?case USB_STATE_OFFLINE:
?? ??? ??? ?if ((flags & USB_FLAG_VBUS_ONLINE) && _vbus) {
?? ??? ??? ??? ?/*重啟設備控制器*/
?? ??? ??? ??? ?usb_reset(ui);
?? ??? ??? ??? ?/*改變設備狀態*/
?? ??? ??? ??? ?ui->state = USB_STATE_ONLINE;
?? ??? ??? ??? ?usb_do_work_check_vbus(ui);
?? ??? ??? ??? ?/*申請中斷處理函數*/
?? ??? ??? ??? ?ret = request_irq(otg->irq, usb_interrupt,IRQF_SHARED,ui->pdev->name, ui);
?? ??? ??? ??? ?ui->irq = otg->irq;
?? ??? ??? ??? ?/*使能D+數據線上的上拉電阻*/
?? ??? ??? ??? ?msm72k_pullup_internal(&ui->gadget, 1);
?? ??? ??? ?}
?? ??? ??? ?break;
?? ??? ?}
?? ?}
}
/*中斷函數的實時處理*/
static irqreturn_t usb_interrupt(int irq, void *data)
{
?? ?struct usb_info *ui = data;
?? ?unsigned n;
?? ?unsigned long flags;
?? ?n = readl(USB_USBSTS);
?? ?writel(n, USB_USBSTS);
?? ?
?? ?/*端口變化探測*/
?? ?if (n & STS_PCI) {
?? ??? ?msm_hsusb_set_speed(ui);
?? ??? ?if (atomic_read(&ui->configured)) {
?? ??? ??? ?ui->usb_state = USB_STATE_CONFIGURED;
?? ??? ??? ?ui->flags = USB_FLAG_CONFIGURED;
?? ??? ??? ?ui->driver->resume(&ui->gadget);
?? ??? ??? ?schedule_work(&ui->work);
?? ??? ?} else {
?? ??? ??? ?msm_hsusb_set_state(USB_STATE_DEFAULT);
?? ??? ?}
?? ?}
?? ?/*usb重啟*/
?? ?if (n & STS_URI) {
?? ??? ?dev_dbg(&ui->pdev->dev, "reset\n");
?? ??? ?ui->gadget.speed = USB_SPEED_UNKNOWN;
?? ??? ?msm_hsusb_set_state(USB_STATE_DEFAULT);
?? ??? ?......................
?? ?}
?? ?/*usb掛起狀態*/
?? ?if (n & STS_SLI) {
?? ??? ?dev_dbg(&ui->pdev->dev, "suspend\n");
?? ??? ?ui->usb_state = USB_STATE_SUSPENDED;
?? ??? ?ui->flags = USB_FLAG_SUSPEND;
?? ??? ?ui->driver->suspend(&ui->gadget);
?? ??? ?schedule_work(&ui->work);
?? ?}
?? ?/*usb事務傳輸完成中斷*/
?? ?if (n & STS_UI) {
?? ??? ?n = readl(USB_ENDPTSETUPSTAT);
?? ??? ?if (n & EPT_RX(0))
?? ??? ??? ?handle_setup(ui);
?? ??? ?n = readl(USB_ENDPTCOMPLETE);
?? ??? ?writel(n, USB_ENDPTCOMPLETE);
?? ??? ?while (n) {
?? ??? ??? ?unsigned bit = __ffs(n);
?? ??? ??? ?handle_endpoint(ui, bit);
?? ??? ??? ?n = n & (~(1 << bit));
?? ??? ?}
?? ?}
?? ?return IRQ_HANDLED;
}
總結
以上是生活随笔為你收集整理的Android4.0.3 USB OTG底层插入上报过程分析(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sd 卡驱动--基于高通平台
- 下一篇: Android 5.0 SEAndroi