通过OTG接口进入Android系统,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;

}

阅读(11925) | 评论(0) | 转发(4) |

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值