2 * otg.c - ChipIdea USB IP core OTG driver
4 * Copyright (C) 2013 Freescale Semiconductor, Inc.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
14 * This file mainly handles otgsc register, it may include OTG operation
18 #include <linux/usb/otg.h>
19 #include <linux/usb/gadget.h>
20 #include <linux/usb/chipidea.h>
27 * ci_otg_role - pick role based on ID pin state
30 enum ci_role
ci_otg_role(struct ci_hdrc
*ci
)
32 u32 sts
= hw_read(ci
, OP_OTGSC
, ~0);
33 enum ci_role role
= sts
& OTGSC_ID
40 void ci_handle_vbus_change(struct ci_hdrc
*ci
)
47 otgsc
= hw_read(ci
, OP_OTGSC
, ~0);
49 if (otgsc
& OTGSC_BSV
)
50 usb_gadget_vbus_connect(&ci
->gadget
);
52 usb_gadget_vbus_disconnect(&ci
->gadget
);
55 #define CI_VBUS_STABLE_TIMEOUT_MS 5000
56 static void ci_handle_id_switch(struct ci_hdrc
*ci
)
58 enum ci_role role
= ci_otg_role(ci
);
60 if (role
!= ci
->role
) {
61 dev_dbg(ci
->dev
, "switching from %s to %s\n",
62 ci_role(ci
)->name
, ci
->roles
[role
]->name
);
65 /* wait vbus lower than OTGSC_BSV */
66 hw_wait_reg(ci
, OP_OTGSC
, OTGSC_BSV
, 0,
67 CI_VBUS_STABLE_TIMEOUT_MS
);
68 ci_role_start(ci
, role
);
72 * ci_otg_work - perform otg (vbus/id) event handle
75 static void ci_otg_work(struct work_struct
*work
)
77 struct ci_hdrc
*ci
= container_of(work
, struct ci_hdrc
, work
);
81 ci_handle_id_switch(ci
);
82 } else if (ci
->b_sess_valid_event
) {
83 ci
->b_sess_valid_event
= false;
84 ci_handle_vbus_change(ci
);
86 dev_err(ci
->dev
, "unexpected event occurs at %s\n", __func__
);
93 * ci_hdrc_otg_init - initialize otg struct
96 int ci_hdrc_otg_init(struct ci_hdrc
*ci
)
98 INIT_WORK(&ci
->work
, ci_otg_work
);
99 ci
->wq
= create_singlethread_workqueue("ci_otg");
101 dev_err(ci
->dev
, "can't create workqueue\n");
109 * ci_hdrc_otg_destroy - destroy otg struct
112 void ci_hdrc_otg_destroy(struct ci_hdrc
*ci
)
115 flush_workqueue(ci
->wq
);
116 destroy_workqueue(ci
->wq
);
118 ci_disable_otg_interrupt(ci
, OTGSC_INT_EN_BITS
);
119 ci_clear_otg_interrupt(ci
, OTGSC_INT_STATUS_BITS
);