#define DWC_DRIVER_DESC "HS OTG USB Controller driver"
static const char dwc_host20_driver_name[] = "usb20_host";
-static const char dwc_otg20_driver_name[] = "usb20_otg";
+static const char dwc_otg20_driver_name[] = "usb20_otg";
-dwc_otg_device_t* g_otgdev = NULL;
+dwc_otg_device_t *g_otgdev;
-extern int pcd_init( struct platform_device *_dev );
-extern int otg20_hcd_init( struct platform_device *_dev );
-extern int host20_hcd_init( struct platform_device *_dev );
-extern int pcd_remove( struct platform_device *_dev );
-extern void hcd_remove( struct platform_device *_dev);
-extern void dwc_otg_adp_start( dwc_otg_core_if_t * core_if, uint8_t is_host);
+extern int pcd_init(struct platform_device *_dev);
+extern int otg20_hcd_init(struct platform_device *_dev);
+extern int host20_hcd_init(struct platform_device *_dev);
+extern int pcd_remove(struct platform_device *_dev);
+extern void hcd_remove(struct platform_device *_dev);
+extern void dwc_otg_adp_start(dwc_otg_core_if_t *core_if, uint8_t is_host);
-static struct usb20otg_pdata_id usb20otg_pdata[] = {
- {
- .name = "rk3188-usb20otg",
- .pdata = &usb20otg_pdata_rk3188,
- },
- {
- .name = "rk3288-usb20otg",
- .pdata = &usb20otg_pdata_rk3288,
- },
- { },
-};
-
-static struct usb20host_pdata_id usb20host_pdata[] = {
- {
- .name = "rk3188-usb20host",
- .pdata = &usb20host_pdata_rk3188,
- },
- {
- .name = "rk3288-usb20host",
- .pdata = &usb20host_pdata_rk3288,
- },
- { },
-};
+#ifdef CONFIG_RK_USB_UART
+static u32 usb_to_uart_status;
+#endif
/*-------------------------------------------------------------------------*/
/* Encapsulate the module parameter settings */
.adp_enable = 0,
};
-
+#ifdef CONFIG_USB20_HOST
static struct dwc_otg_driver_module_params dwc_host_module_params = {
.opt = -1,
.otg_cap = DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE,
.otg_ver = -1,
.adp_enable = 0,
};
-
+#endif
/**
* This function shows the Driver Version.
/**
* Global Debug Level Mask.
*/
-uint32_t g_dbg_lvl = DBG_OFF; /* OFF */
+uint32_t g_dbg_lvl = DBG_OFF; /* OFF */
/**
* This function shows the driver Debug Level.
static DRIVER_ATTR(debuglevel, S_IRUGO | S_IWUSR, dbg_level_show,
dbg_level_store);
+extern void hcd_start(dwc_otg_core_if_t *core_if);
+extern struct usb_hub *g_dwc_otg_root_hub20;
+extern void dwc_otg_hub_disconnect_device(struct usb_hub *hub);
+
+void dwc_otg_force_host(dwc_otg_core_if_t *core_if)
+{
+ dwc_otg_device_t *otg_dev = core_if->otg_dev;
+ dctl_data_t dctl = {.d32 = 0 };
+ unsigned long flags;
+
+ if (core_if->op_state == A_HOST) {
+ printk("dwc_otg_force_host,already in A_HOST mode,everest\n");
+ return;
+ }
+ core_if->op_state = A_HOST;
+
+ cancel_delayed_work(&otg_dev->pcd->check_vbus_work);
+ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
+ dctl.b.sftdiscon = 1;
+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
+
+ local_irq_save(flags);
+ cil_pcd_stop(core_if);
+ /*
+ * Initialize the Core for Host mode.
+ */
+
+ dwc_otg_core_init(core_if);
+ dwc_otg_enable_global_interrupts(core_if);
+ cil_hcd_start(core_if);
+ local_irq_restore(flags);
+}
+
+void dwc_otg_force_device(dwc_otg_core_if_t *core_if)
+{
+ dwc_otg_device_t *otg_dev = core_if->otg_dev;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ if (core_if->op_state == B_PERIPHERAL) {
+ printk
+ ("dwc_otg_force_device,already in B_PERIPHERAL,everest\n");
+ return;
+ }
+ core_if->op_state = B_PERIPHERAL;
+ cil_hcd_stop(core_if);
+ /* dwc_otg_hub_disconnect_device(g_dwc_otg_root_hub20); */
+ otg_dev->pcd->phy_suspend = 1;
+ otg_dev->pcd->vbus_status = 0;
+ dwc_otg_pcd_start_check_vbus_work(otg_dev->pcd);
+
+ /* Reset the Controller */
+ dwc_otg_core_reset(core_if);
+
+ dwc_otg_core_init(core_if);
+ dwc_otg_disable_global_interrupts(core_if);
+ cil_pcd_start(core_if);
+
+ local_irq_restore(flags);
+}
+
+static ssize_t force_usb_mode_show(struct device_driver *drv, char *buf)
+{
+ dwc_otg_device_t *otg_dev = g_otgdev;
+ dwc_otg_core_if_t *core_if = otg_dev->core_if;
+
+ return sprintf(buf, "%d\n", core_if->usb_mode);
+}
+
+static ssize_t force_usb_mode_store(struct device_driver *drv, const char *buf,
+ size_t count)
+{
+ int new_mode = simple_strtoul(buf, NULL, 16);
+ dwc_otg_device_t *otg_dev = g_otgdev;
+ dwc_otg_core_if_t *core_if;
+ struct dwc_otg_platform_data *pldata;
+
+ if (!otg_dev)
+ return -EINVAL;
+
+ core_if = otg_dev->core_if;
+ pldata = otg_dev->pldata;
+
+ DWC_PRINTF("%s %d->%d\n", __func__, core_if->usb_mode, new_mode);
+
+ if (core_if->usb_mode == new_mode) {
+ return count;
+ }
+
+ if (pldata->phy_status == USB_PHY_SUSPEND) {
+ pldata->clock_enable(pldata, 1);
+ pldata->phy_suspend(pldata, USB_PHY_ENABLED);
+ }
+
+ switch (new_mode) {
+ case USB_MODE_FORCE_HOST:
+ if (USB_MODE_FORCE_DEVICE == core_if->usb_mode) {
+ /* device-->host */
+ core_if->usb_mode = new_mode;
+ dwc_otg_force_host(core_if);
+ } else if (USB_MODE_NORMAL == core_if->usb_mode) {
+ core_if->usb_mode = new_mode;
+ if (dwc_otg_is_host_mode(core_if))
+ dwc_otg_set_force_mode(core_if, new_mode);
+ else
+ dwc_otg_force_host(core_if);
+ }
+ break;
+
+ case USB_MODE_FORCE_DEVICE:
+ if (USB_MODE_FORCE_HOST == core_if->usb_mode) {
+ core_if->usb_mode = new_mode;
+ dwc_otg_force_device(core_if);
+ } else if (USB_MODE_NORMAL == core_if->usb_mode) {
+ core_if->usb_mode = new_mode;
+ if (dwc_otg_is_device_mode(core_if))
+ dwc_otg_set_force_mode(core_if, new_mode);
+ else
+ dwc_otg_force_device(core_if);
+ }
+ break;
+
+ case USB_MODE_NORMAL:
+ if (USB_MODE_FORCE_DEVICE == core_if->usb_mode) {
+ core_if->usb_mode = new_mode;
+ cancel_delayed_work(&otg_dev->pcd->check_vbus_work);
+ dwc_otg_set_force_mode(core_if, new_mode);
+ /* msleep(100); */
+ if (dwc_otg_is_host_mode(core_if)) {
+ dwc_otg_force_host(core_if);
+ } else {
+ dwc_otg_pcd_start_check_vbus_work(otg_dev->pcd);
+ }
+ } else if (USB_MODE_FORCE_HOST == core_if->usb_mode) {
+ core_if->usb_mode = new_mode;
+ dwc_otg_set_force_mode(core_if, new_mode);
+ /* msleep(100); */
+ if (dwc_otg_is_device_mode(core_if)) {
+ dwc_otg_force_device(core_if);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ return count;
+}
+
+static DRIVER_ATTR(force_usb_mode, S_IRUGO | S_IWUSR, force_usb_mode_show,
+ force_usb_mode_store);
static ssize_t dwc_otg_conn_en_show(struct device_driver *_drv, char *_buf)
{
- dwc_otg_device_t *otg_dev = g_otgdev;
- dwc_otg_pcd_t *_pcd = otg_dev->pcd;
- return sprintf (_buf, "%d\n", _pcd->conn_en);
+ dwc_otg_device_t *otg_dev = g_otgdev;
+ dwc_otg_pcd_t *_pcd = otg_dev->pcd;
+ return sprintf(_buf, "%d\n", _pcd->conn_en);
}
-static ssize_t dwc_otg_conn_en_store(struct device_driver *_drv, const char *_buf,
- size_t _count)
+static ssize_t dwc_otg_conn_en_store(struct device_driver *_drv,
+ const char *_buf, size_t _count)
{
- int enable = simple_strtoul(_buf, NULL, 10);
- dwc_otg_device_t *otg_dev = g_otgdev;
- dwc_otg_pcd_t *_pcd = otg_dev->pcd;
- DWC_PRINTF("%s %d->%d\n",__func__, _pcd->conn_en, enable);
-
- _pcd->conn_en = enable;
- return _count;
+ int enable = simple_strtoul(_buf, NULL, 10);
+ dwc_otg_device_t *otg_dev = g_otgdev;
+ dwc_otg_pcd_t *_pcd = otg_dev->pcd;
+ DWC_PRINTF("%s %d->%d\n", __func__, _pcd->conn_en, enable);
+
+ _pcd->conn_en = enable;
+ return _count;
}
-static DRIVER_ATTR(dwc_otg_conn_en, S_IRUGO|S_IWUSR, dwc_otg_conn_en_show, dwc_otg_conn_en_store);
+
+static DRIVER_ATTR(dwc_otg_conn_en, S_IRUGO | S_IWUSR, dwc_otg_conn_en_show,
+ dwc_otg_conn_en_store);
+
+/* used for product vbus power control, SDK not need.
+ * If dwc_otg is host mode, enable vbus power.
+ * If dwc_otg is device mode, disable vbus power.
+ * return 1 - host mode, 0 - device mode.
+ */
+int dwc_otg_usb_state(void)
+{
+ dwc_otg_device_t *otg_dev = g_otgdev;
+
+ if (otg_dev) {
+ /* op_state is A_HOST */
+ if (1 == otg_dev->core_if->op_state)
+ return 1;
+ /* op_state is B_PERIPHERAL */
+ else if (4 == otg_dev->core_if->op_state)
+ return 0;
+ else
+ return 0;
+ } else {
+ DWC_WARN("g_otgdev is NULL, maybe otg probe is failed!\n");
+ return 0;
+ }
+}
+EXPORT_SYMBOL(dwc_otg_usb_state);
+
+static ssize_t dwc_otg_op_state_show(struct device_driver *_drv, char *_buf)
+{
+ dwc_otg_device_t *otg_dev = g_otgdev;
+
+ if (otg_dev) {
+ return sprintf(_buf, "%d\n", otg_dev->core_if->op_state);
+ } else {
+ return sprintf(_buf, "%d\n", 0);
+ }
+}
+static DRIVER_ATTR(op_state, S_IRUGO, dwc_otg_op_state_show, NULL);
static ssize_t vbus_status_show(struct device_driver *_drv, char *_buf)
{
dwc_otg_device_t *otg_dev = g_otgdev;
dwc_otg_pcd_t *_pcd = otg_dev->pcd;
- return sprintf (_buf, "%d\n", _pcd->vbus_status);
+ return sprintf(_buf, "%d\n", _pcd->vbus_status);
}
+
static DRIVER_ATTR(vbus_status, S_IRUGO, vbus_status_show, NULL);
/**
* This function is called during module intialization
* to pass module parameters to the DWC_OTG CORE.
*/
-static int set_parameters(dwc_otg_core_if_t * core_if, struct dwc_otg_driver_module_params module_params)
+static int set_parameters(dwc_otg_core_if_t *core_if,
+ struct dwc_otg_driver_module_params module_params)
{
int retval = 0;
int i;
if (module_params.otg_cap != -1) {
retval +=
- dwc_otg_set_param_otg_cap(core_if,
- module_params.otg_cap);
+ dwc_otg_set_param_otg_cap(core_if, module_params.otg_cap);
}
if (module_params.dma_enable != -1) {
retval +=
dwc_otg_set_param_dma_enable(core_if,
- module_params.
- dma_enable);
+ module_params.dma_enable);
}
if (module_params.dma_desc_enable != -1) {
retval +=
dwc_otg_set_param_dma_desc_enable(core_if,
- module_params.
- dma_desc_enable);
+ module_params.dma_desc_enable);
}
if (module_params.opt != -1) {
- retval +=
- dwc_otg_set_param_opt(core_if, module_params.opt);
+ retval += dwc_otg_set_param_opt(core_if, module_params.opt);
}
if (module_params.dma_burst_size != -1) {
retval +=
dwc_otg_set_param_dma_burst_size(core_if,
- module_params.
- dma_burst_size);
+ module_params.dma_burst_size);
}
if (module_params.host_support_fs_ls_low_power != -1) {
retval +=
dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
- module_params.
- host_support_fs_ls_low_power);
+ module_params.host_support_fs_ls_low_power);
}
if (module_params.enable_dynamic_fifo != -1) {
retval +=
dwc_otg_set_param_enable_dynamic_fifo(core_if,
- module_params.
- enable_dynamic_fifo);
+ module_params.enable_dynamic_fifo);
}
if (module_params.data_fifo_size != -1) {
retval +=
dwc_otg_set_param_data_fifo_size(core_if,
- module_params.
- data_fifo_size);
+ module_params.data_fifo_size);
}
if (module_params.dev_rx_fifo_size != -1) {
retval +=
dwc_otg_set_param_dev_rx_fifo_size(core_if,
- module_params.
- dev_rx_fifo_size);
+ module_params.dev_rx_fifo_size);
}
if (module_params.dev_nperio_tx_fifo_size != -1) {
retval +=
dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
- module_params.
- dev_nperio_tx_fifo_size);
+ module_params.dev_nperio_tx_fifo_size);
}
if (module_params.host_rx_fifo_size != -1) {
retval +=
dwc_otg_set_param_host_rx_fifo_size(core_if,
- module_params.host_rx_fifo_size);
+ module_params.
+ host_rx_fifo_size);
}
if (module_params.host_nperio_tx_fifo_size != -1) {
retval +=
dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
- module_params.
- host_nperio_tx_fifo_size);
+ module_params.host_nperio_tx_fifo_size);
}
if (module_params.host_perio_tx_fifo_size != -1) {
retval +=
dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
- module_params.
- host_perio_tx_fifo_size);
+ module_params.host_perio_tx_fifo_size);
}
if (module_params.max_transfer_size != -1) {
retval +=
dwc_otg_set_param_max_transfer_size(core_if,
- module_params.
- max_transfer_size);
+ module_params.max_transfer_size);
}
if (module_params.max_packet_count != -1) {
retval +=
dwc_otg_set_param_max_packet_count(core_if,
- module_params.
- max_packet_count);
+ module_params.max_packet_count);
}
if (module_params.host_channels != -1) {
retval +=
dwc_otg_set_param_host_channels(core_if,
- module_params.
- host_channels);
+ module_params.host_channels);
}
if (module_params.dev_endpoints != -1) {
retval +=
dwc_otg_set_param_dev_endpoints(core_if,
- module_params.
- dev_endpoints);
+ module_params.dev_endpoints);
}
if (module_params.phy_type != -1) {
retval +=
- dwc_otg_set_param_phy_type(core_if,
- module_params.phy_type);
+ dwc_otg_set_param_phy_type(core_if, module_params.phy_type);
}
if (module_params.speed != -1) {
- retval +=
- dwc_otg_set_param_speed(core_if,
- module_params.speed);
+ retval += dwc_otg_set_param_speed(core_if, module_params.speed);
}
if (module_params.host_ls_low_power_phy_clk != -1) {
retval +=
dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
- module_params.
- host_ls_low_power_phy_clk);
+ module_params.host_ls_low_power_phy_clk);
}
if (module_params.phy_ulpi_ddr != -1) {
retval +=
dwc_otg_set_param_phy_ulpi_ddr(core_if,
- module_params.
- phy_ulpi_ddr);
+ module_params.phy_ulpi_ddr);
}
if (module_params.phy_ulpi_ext_vbus != -1) {
retval +=
dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
- module_params.
- phy_ulpi_ext_vbus);
+ module_params.phy_ulpi_ext_vbus);
}
if (module_params.phy_utmi_width != -1) {
retval +=
dwc_otg_set_param_phy_utmi_width(core_if,
- module_params.
- phy_utmi_width);
+ module_params.phy_utmi_width);
}
if (module_params.ulpi_fs_ls != -1) {
retval +=
}
if (module_params.ts_dline != -1) {
retval +=
- dwc_otg_set_param_ts_dline(core_if,
- module_params.ts_dline);
+ dwc_otg_set_param_ts_dline(core_if, module_params.ts_dline);
}
if (module_params.i2c_enable != -1) {
retval +=
dwc_otg_set_param_i2c_enable(core_if,
- module_params.
- i2c_enable);
+ module_params.i2c_enable);
}
if (module_params.en_multiple_tx_fifo != -1) {
retval +=
dwc_otg_set_param_en_multiple_tx_fifo(core_if,
- module_params.
- en_multiple_tx_fifo);
+ module_params.en_multiple_tx_fifo);
}
for (i = 0; i < 15; i++) {
if (module_params.dev_perio_tx_fifo_size[i] != -1) {
retval +=
dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
- module_params.
- dev_perio_tx_fifo_size
+ module_params.dev_perio_tx_fifo_size
[i], i);
}
}
for (i = 0; i < 15; i++) {
if (module_params.dev_tx_fifo_size[i] != -1) {
retval += dwc_otg_set_param_dev_tx_fifo_size(core_if,
- module_params.
- dev_tx_fifo_size
+ module_params.dev_tx_fifo_size
[i], i);
}
}
if (module_params.thr_ctl != -1) {
retval +=
- dwc_otg_set_param_thr_ctl(core_if,
- module_params.thr_ctl);
+ dwc_otg_set_param_thr_ctl(core_if, module_params.thr_ctl);
}
if (module_params.mpi_enable != -1) {
retval +=
dwc_otg_set_param_mpi_enable(core_if,
- module_params.
- mpi_enable);
+ module_params.mpi_enable);
}
if (module_params.pti_enable != -1) {
retval +=
dwc_otg_set_param_pti_enable(core_if,
- module_params.
- pti_enable);
+ module_params.pti_enable);
}
if (module_params.lpm_enable != -1) {
retval +=
dwc_otg_set_param_lpm_enable(core_if,
- module_params.
- lpm_enable);
- }
+ module_params.lpm_enable);
+ }
if (module_params.besl_enable != -1) {
retval +=
dwc_otg_set_param_besl_enable(core_if,
- module_params.
- besl_enable);
+ module_params.besl_enable);
}
if (module_params.baseline_besl != -1) {
retval +=
dwc_otg_set_param_baseline_besl(core_if,
- module_params.
- baseline_besl);
+ module_params.baseline_besl);
}
if (module_params.deep_besl != -1) {
retval +=
dwc_otg_set_param_deep_besl(core_if,
- module_params.
- deep_besl);
- }
+ module_params.deep_besl);
+ }
if (module_params.ic_usb_cap != -1) {
retval +=
dwc_otg_set_param_ic_usb_cap(core_if,
- module_params.
- ic_usb_cap);
+ module_params.ic_usb_cap);
}
if (module_params.tx_thr_length != -1) {
retval +=
dwc_otg_set_param_tx_thr_length(core_if,
- module_params.tx_thr_length);
+ module_params.
+ tx_thr_length);
}
if (module_params.rx_thr_length != -1) {
retval +=
dwc_otg_set_param_rx_thr_length(core_if,
- module_params.
- rx_thr_length);
+ module_params.rx_thr_length);
}
if (module_params.ahb_thr_ratio != -1) {
retval +=
dwc_otg_set_param_ahb_thr_ratio(core_if,
- module_params.ahb_thr_ratio);
+ module_params.
+ ahb_thr_ratio);
}
if (module_params.power_down != -1) {
retval +=
if (module_params.dev_out_nak != -1) {
retval +=
- dwc_otg_set_param_dev_out_nak(core_if,
- module_params.dev_out_nak);
+ dwc_otg_set_param_dev_out_nak(core_if,
+ module_params.dev_out_nak);
}
if (module_params.cont_on_bna != -1) {
retval +=
- dwc_otg_set_param_cont_on_bna(core_if,
- module_params.cont_on_bna);
+ dwc_otg_set_param_cont_on_bna(core_if,
+ module_params.cont_on_bna);
}
if (module_params.ahb_single != -1) {
retval +=
- dwc_otg_set_param_ahb_single(core_if,
- module_params.ahb_single);
+ dwc_otg_set_param_ahb_single(core_if,
+ module_params.ahb_single);
}
if (module_params.otg_ver != -1) {
retval +=
- dwc_otg_set_param_otg_ver(core_if,
- module_params.otg_ver);
+ dwc_otg_set_param_otg_ver(core_if, module_params.otg_ver);
}
if (module_params.adp_enable != -1) {
retval +=
dwc_otg_set_param_adp_enable(core_if,
- module_params.
- adp_enable);
+ module_params.adp_enable);
}
return retval;
}
retval = dwc_otg_handle_common_intr(dev);
if (retval != 0) {
- //S3C2410X_CLEAR_EINTPEND();
+ /* S3C2410X_CLEAR_EINTPEND(); */
}
return IRQ_RETVAL(retval);
}
+#ifdef CONFIG_USB20_HOST
/**
* This function is called when a lm_device is unregistered with the
* dwc_otg_driver. This happens, for example, when the rmmod command is
*
* @param _dev
*/
-static int host20_driver_remove( struct platform_device *_dev )
+static int host20_driver_remove(struct platform_device *_dev)
{
dwc_otg_device_t *otg_dev = dwc_get_device_platform_data(_dev);
DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
return 0;
}
-
#ifndef DWC_DEVICE_ONLY
if (otg_dev->hcd) {
hcd_remove(_dev);
* Free the IRQ
*/
if (otg_dev->common_irq_installed) {
- //free_irq(_dev->irq, otg_dev);
- free_irq(platform_get_irq(_dev,0), otg_dev );
+ /* free_irq(_dev->irq, otg_dev); */
+ free_irq(platform_get_irq(_dev, 0), otg_dev);
} else {
- DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);
+ DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n",
+ __func__);
return 0;
}
}
static const struct of_device_id usb20_host_of_match[] = {
+#ifdef CONFIG_ARM
{
- .compatible = "rockchip,rk3188_usb20_host",
- .data = &usb20host_pdata[RK3188_USB_CTLR],
- },
+ .compatible = "rockchip,rk3188_usb20_host",
+ .data = &usb20host_pdata_rk3188,
+ },
{
- .compatible = "rockchip,rk3288_usb20_host",
- .data = &usb20host_pdata[RK3288_USB_CTLR],
- },
- { },
+ .compatible = "rockchip,rk3288_usb20_host",
+ .data = &usb20host_pdata_rk3288,
+ },
+ {
+ .compatible = "rockchip,rk3036_usb20_host",
+ .data = &usb20host_pdata_rk3036,
+ },
+ {
+ .compatible = "rockchip,rk3126_usb20_host",
+ .data = &usb20host_pdata_rk3126,
+ },
+#endif
+ {},
};
+
MODULE_DEVICE_TABLE(of, usb20_host_of_match);
/**
int irq;
struct resource *res_base;
dwc_otg_device_t *dwc_otg_device;
- struct device *dev = &_dev->dev;
- struct device_node *node = _dev->dev.of_node;
+ struct device *dev = &_dev->dev;
+ struct device_node *node = _dev->dev.of_node;
struct dwc_otg_platform_data *pldata;
- struct usb20host_pdata_id *p;
const struct of_device_id *match =
- of_match_device(of_match_ptr( usb20_host_of_match ), &_dev->dev);
+ of_match_device(of_match_ptr(usb20_host_of_match), &_dev->dev);
- if (match){
- p = (struct usb20host_pdata_id *)match->data;
- }else{
- dev_err(dev, "usb20host match failed\n");
+ if (match && match->data) {
+ pldata = (void *)match->data;
+ pldata->dev = dev;
+ } else {
+ dev_err(dev, "usb20otg match failed\n");
return -EINVAL;
}
- dev->platform_data = p->pdata;
- pldata = dev->platform_data;
- pldata->dev = dev;
-
if (!node) {
dev_err(dev, "device node not found\n");
return -EINVAL;
}
- if(pldata->hw_init)
+ if (pldata->hw_init)
pldata->hw_init();
- if(pldata->clock_init){
+ if (pldata->clock_init) {
pldata->clock_init(pldata);
pldata->clock_enable(pldata, 1);
}
- if(pldata->phy_suspend)
+ if (pldata->phy_suspend)
pldata->phy_suspend(pldata, USB_PHY_ENABLED);
- if(pldata->soft_reset)
- pldata->soft_reset();
+ if (pldata->soft_reset)
+ pldata->soft_reset(pldata, RST_POR);
- res_base=platform_get_resource(_dev, IORESOURCE_MEM, 0);
+ res_base = platform_get_resource(_dev, IORESOURCE_MEM, 0);
dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t));
*/
dwc_otg_device->os_dep.base = devm_ioremap_resource(dev, res_base);
-
+
if (!dwc_otg_device->os_dep.base) {
dev_err(&_dev->dev, "ioremap() failed\n");
DWC_FREE(dwc_otg_device);
retval = -ENOMEM;
goto clk_disable;
}
- dev_dbg(&_dev->dev, "base=0x%08x\n",
- (unsigned)dwc_otg_device->os_dep.base);
+ dev_dbg(&_dev->dev, "base=0x%p\n", dwc_otg_device->os_dep.base);
+
+ /* Set device flags indicating whether the HCD supports DMA. */
+ if (!_dev->dev.dma_mask)
+ _dev->dev.dma_mask = &_dev->dev.coherent_dma_mask;
+ retval = dma_set_coherent_mask(&_dev->dev, DMA_BIT_MASK(32));
+ if (retval)
+ goto clk_disable;
/*
* Initialize driver data to point to the global DWC_otg
dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base);
-
if (!dwc_otg_device->core_if) {
dev_err(&_dev->dev, "CIL initialization failed!\n");
retval = -ENOMEM;
goto fail;
}
- dwc_otg_device->core_if->otg_dev= dwc_otg_device;
+ dwc_otg_device->core_if->otg_dev = dwc_otg_device;
/*
* Attempt to ensure this device is really a DWC_otg Controller.
* as in "OTG version 2.XX" or "OTG version 3.XX".
*/
- if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) &&
- ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {
+ if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) !=
+ 0x4F542000)
+ && ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) !=
+ 0x4F543000)) {
dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n",
dwc_otg_get_gsnpsid(dwc_otg_device->core_if));
retval = -EINVAL;
/*
* Validate parameter values.
*/
- if (set_parameters(dwc_otg_device->core_if ,dwc_host_module_params )) {
+ if (set_parameters(dwc_otg_device->core_if, dwc_host_module_params)) {
retval = -EINVAL;
goto fail;
}
-
+
/*
* Create Device Attributes in sysfs
*/
* Install the interrupt handler for the common interrupts before
* enabling common interrupts in core_init below.
*/
- irq = platform_get_irq(_dev,0);
- DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n",
- irq);
+ irq = platform_get_irq(_dev, 0);
+ DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n", irq);
retval = request_irq(irq, dwc_otg_common_irq,
- IRQF_SHARED , "dwc_otg",
- dwc_otg_device);
+ IRQF_SHARED, "dwc_otg", dwc_otg_device);
if (retval) {
DWC_ERROR("request of irq%d failed\n", irq);
retval = -EBUSY;
/*
* Initialize the DWC_otg core.
+ * In order to reduce the time of initialization,
+ * we do core soft reset after connection detected.
*/
- dwc_otg_core_init(dwc_otg_device->core_if);
-
+ dwc_otg_core_init_no_reset(dwc_otg_device->core_if);
+
/*
* Initialize the HCD
*/
goto fail;
}
+ clk_set_rate(pldata->phyclk_480m, 480000000);
/*
* Enable the global interrupt after all the interrupt
- * handlers are installed if there is no ADP support else
+ * handlers are installed if there is no ADP support else
* perform initial actions required for Internal ADP logic.
*/
- if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if))
- dwc_otg_enable_global_interrupts(dwc_otg_device->core_if);
- else
- dwc_otg_adp_start(dwc_otg_device->core_if,
- dwc_otg_is_host_mode(dwc_otg_device->core_if));
+ if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) {
+ if (pldata->phy_status == USB_PHY_ENABLED) {
+ pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
+ udelay(3);
+ pldata->clock_enable(pldata, 0);
+ }
+ /* dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); */
+ } else
+ dwc_otg_adp_start(dwc_otg_device->core_if,
+ dwc_otg_is_host_mode(dwc_otg_device->
+ core_if));
return 0;
fail:
host20_driver_remove(_dev);
clk_disable:
- if(pldata->clock_enable)
+ if (pldata->clock_enable)
pldata->clock_enable(pldata, 0);
return retval;
}
+#endif
-static int dwc_otg_driver_suspend(struct platform_device *_dev , pm_message_t state )
+static int dwc_otg_driver_suspend(struct platform_device *_dev,
+ pm_message_t state)
{
- return 0;
+ return 0;
}
-static int dwc_otg_driver_resume(struct platform_device *_dev )
+static int dwc_otg_driver_resume(struct platform_device *_dev)
{
- return 0;
+ return 0;
}
-static void dwc_otg_driver_shutdown(struct platform_device *_dev )
+static void dwc_otg_driver_shutdown(struct platform_device *_dev)
{
struct device *dev = &_dev->dev;
dwc_otg_device_t *otg_dev = dev->platform_data;
- dwc_otg_core_if_t *core_if = otg_dev->core_if;
- dctl_data_t dctl = {.d32=0};
-
- DWC_PRINTF("%s: disconnect USB %s mode\n" , __func__ ,
- dwc_otg_is_host_mode(core_if) ? "host" : "device");
- if(dwc_otg_is_host_mode(core_if))
- {
- if (core_if->hcd_cb && core_if->hcd_cb->stop)
- {
- core_if->hcd_cb->stop( core_if->hcd_cb_p);
- }
- }
- else
- {
- /* soft disconnect */
- dctl.d32 = DWC_READ_REG32( &core_if->dev_if->dev_global_regs->dctl );
- dctl.b.sftdiscon = 1;
- DWC_WRITE_REG32( &core_if->dev_if->dev_global_regs->dctl, dctl.d32 );
- }
- /* Clear any pending interrupts */
- DWC_WRITE_REG32( &core_if->core_global_regs->gintsts, 0xFFFFFFFF);
+ dwc_otg_core_if_t *core_if = otg_dev->core_if;
+ struct dwc_otg_platform_data *pldata = otg_dev->pldata;
+ dctl_data_t dctl = {.d32 = 0 };
+ dwc_otg_pcd_t *pcd = core_if->otg_dev->pcd;
-}
+ DWC_PRINTF("%s: disconnect USB %s mode\n", __func__,
+ dwc_otg_is_host_mode(core_if) ? "host" : "device");
+ if (dwc_otg_is_host_mode(core_if)) {
+ if (core_if->hcd_cb && core_if->hcd_cb->stop)
+ core_if->hcd_cb->stop(core_if->hcd_cb_p);
+ } else {
+ cancel_delayed_work_sync(&pcd->check_vbus_work);
+ /* soft disconnect */
+ dctl.d32 =
+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
+ dctl.b.sftdiscon = 1;
+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
+ dctl.d32);
+ }
+ /* Clear any pending interrupts */
+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
+
+ if (pldata->dwc_otg_uart_mode != NULL)
+ pldata->dwc_otg_uart_mode(pldata, PHY_USB_MODE);
+ if (pldata->phy_suspend != NULL)
+ pldata->phy_suspend(pldata, USB_PHY_ENABLED);
+
+}
/**
* This structure defines the methods to be called by a bus driver
* to this driver. The remove function is called when a device is
* unregistered with the bus driver.
*/
-
+#ifdef CONFIG_USB20_HOST
static struct platform_driver dwc_host_driver = {
.driver = {
- .name = (char *)dwc_host20_driver_name,
- .of_match_table = of_match_ptr(usb20_host_of_match),
- },
+ .name = (char *)dwc_host20_driver_name,
+ .of_match_table = of_match_ptr(usb20_host_of_match),
+ },
.probe = host20_driver_probe,
.remove = host20_driver_remove,
.suspend = dwc_otg_driver_suspend,
.resume = dwc_otg_driver_resume,
};
+#endif
-
+#ifdef CONFIG_USB20_OTG
/**
* This function is called when a lm_device is unregistered with the
* dwc_otg_driver. This happens, for example, when the rmmod command is
*
* @param _dev
*/
-static int otg20_driver_remove( struct platform_device *_dev )
+static int otg20_driver_remove(struct platform_device *_dev)
{
dwc_otg_device_t *otg_dev = dwc_get_device_platform_data(_dev);
* Free the IRQ
*/
if (otg_dev->common_irq_installed) {
- //free_irq(_dev->irq, otg_dev);
- free_irq(platform_get_irq(_dev,0), otg_dev );
+ /* free_irq(_dev->irq, otg_dev); */
+ free_irq(platform_get_irq(_dev, 0), otg_dev);
} else {
- DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);
+ DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n",
+ __func__);
return 0;
}
/*
* Return the memory.
*/
- if (otg_dev->os_dep.base) {
+ if (otg_dev->os_dep.base)
iounmap(otg_dev->os_dep.base);
- }
DWC_FREE(otg_dev);
/*
}
static const struct of_device_id usb20_otg_of_match[] = {
+#ifdef CONFIG_ARM
{
- .compatible = "rockchip,rk3188_usb20_otg",
- .data = &usb20otg_pdata[RK3188_USB_CTLR],
- },
+ .compatible = "rockchip,rk3188_usb20_otg",
+ .data = &usb20otg_pdata_rk3188,
+ },
{
- .compatible = "rockchip,rk3288_usb20_otg",
- .data = &usb20otg_pdata[RK3288_USB_CTLR],
- },
+ .compatible = "rockchip,rk3288_usb20_otg",
+ .data = &usb20otg_pdata_rk3288,
+ },
{
- },
+ .compatible = "rockchip,rk3036_usb20_otg",
+ .data = &usb20otg_pdata_rk3036,
+ },
+ {
+ .compatible = "rockchip,rk3126_usb20_otg",
+ .data = &usb20otg_pdata_rk3126,
+ },
+#endif
+#ifdef CONFIG_ARM64
+ {
+ .compatible = "rockchip,rk3368_usb20_otg",
+ .data = &usb20otg_pdata_rk3368,
+ },
+#endif
+ { },
};
+
MODULE_DEVICE_TABLE(of, usb20_otg_of_match);
/**
{
int retval = 0;
int irq;
+ uint32_t val;
struct resource *res_base;
dwc_otg_device_t *dwc_otg_device;
- struct device *dev = &_dev->dev;
- struct device_node *node = _dev->dev.of_node;
+ struct device *dev = &_dev->dev;
+ struct device_node *node = _dev->dev.of_node;
struct dwc_otg_platform_data *pldata;
- struct usb20otg_pdata_id *p;
const struct of_device_id *match =
- of_match_device(of_match_ptr( usb20_otg_of_match ), &_dev->dev);
+ of_match_device(of_match_ptr(usb20_otg_of_match), &_dev->dev);
- if (match){
- p = (struct usb20otg_pdata_id *)match->data;
- }else{
+ if (match && match->data) {
+ pldata = (void *)match->data;
+ pldata->dev = dev;
+ } else {
dev_err(dev, "usb20otg match failed\n");
return -EINVAL;
}
- dev->platform_data = p->pdata;
-// dev->platform_data = &usb20otg_pdata;
- pldata = dev->platform_data;
- pldata->dev = dev;
-
if (!node) {
dev_err(dev, "device node not found\n");
return -EINVAL;
}
- /*todo : move to usbdev_rk-XX.c*/
- if(pldata->hw_init)
+
+ if (pldata->hw_init)
pldata->hw_init();
-
- if(pldata->clock_init){
+
+ if (pldata->clock_init) {
pldata->clock_init(pldata);
pldata->clock_enable(pldata, 1);
}
- if(pldata->phy_suspend)
+ if (pldata->phy_suspend)
pldata->phy_suspend(pldata, USB_PHY_ENABLED);
- if(pldata->dwc_otg_uart_mode)
+
+ if (pldata->dwc_otg_uart_mode)
pldata->dwc_otg_uart_mode(pldata, PHY_USB_MODE);
- if(pldata->soft_reset)
- pldata->soft_reset();
- /*end todo*/
- res_base=platform_get_resource(_dev, IORESOURCE_MEM, 0);
+ /* do reset later, because reset need about
+ * 100ms to ensure otg id state change.
+ */
+ /*
+ if(pldata->soft_reset)
+ pldata->soft_reset();
+ */
+ /*end todo */
+
+ res_base = platform_get_resource(_dev, IORESOURCE_MEM, 0);
dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t));
if (!dwc_otg_device) {
dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n");
- retval = -ENOMEM;
+ retval = -ENOMEM;
goto clk_disable;
}
retval = -ENOMEM;
goto clk_disable;
}
- dev_dbg(&_dev->dev, "base=0x%08x\n",
- (unsigned)dwc_otg_device->os_dep.base);
+ dev_dbg(&_dev->dev, "base=0x%p\n", dwc_otg_device->os_dep.base);
+
+ /* Set device flags indicating whether the HCD supports DMA. */
+ if (!_dev->dev.dma_mask)
+ _dev->dev.dma_mask = &_dev->dev.coherent_dma_mask;
+ retval = dma_set_coherent_mask(&_dev->dev, DMA_BIT_MASK(32));
+ if (retval)
+ goto clk_disable;
/*
* Initialize driver data to point to the global DWC_otg
*/
g_otgdev = dwc_otg_device;
- pldata->privdata = dwc_otg_device;
+ pldata->privdata = dwc_otg_device;
dwc_otg_device->pldata = pldata;
dwc_set_device_platform_data(_dev, dwc_otg_device);
retval = -ENOMEM;
goto fail;
}
-
+
dwc_otg_device->core_if->otg_dev = dwc_otg_device;
/*
* Attempt to ensure this device is really a DWC_otg Controller.
* as in "OTG version 2.XX" or "OTG version 3.XX".
*/
- if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) &&
- ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {
+ if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) !=
+ 0x4F542000)
+ && ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) !=
+ 0x4F543000)) {
dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n",
dwc_otg_get_gsnpsid(dwc_otg_device->core_if));
retval = -EINVAL;
/*
* Validate parameter values.
*/
- if (set_parameters(dwc_otg_device->core_if ,dwc_otg_module_params)) {
+ if (set_parameters(dwc_otg_device->core_if, dwc_otg_module_params)) {
retval = -EINVAL;
goto fail;
}
-
+
/*
* Create Device Attributes in sysfs
*/
* Install the interrupt handler for the common interrupts before
* enabling common interrupts in core_init below.
*/
- irq = platform_get_irq(_dev,0);
- DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n",
- irq);
+ irq = platform_get_irq(_dev, 0);
+ DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n", irq);
retval = request_irq(irq, dwc_otg_common_irq,
- IRQF_SHARED , "dwc_otg",
- dwc_otg_device);
+ IRQF_SHARED, "dwc_otg", dwc_otg_device);
if (retval) {
DWC_ERROR("request of irq%d failed\n", irq);
retval = -EBUSY;
/*
* Initialize the DWC_otg core.
+ * In order to reduce the time of initialization,
+ * we do core soft reset after connection detected.
+ */
+ dwc_otg_core_init_no_reset(dwc_otg_device->core_if);
+
+ /* set otg mode
+ * 0 - USB_MODE_NORMAL
+ * 1 - USB_MODE_FORCE_HOST
+ * 2 - USB_MODE_FORCE_DEVICE
*/
- dwc_otg_core_init(dwc_otg_device->core_if);
-
+ of_property_read_u32(node, "rockchip,usb-mode", &val);
+ dwc_otg_device->core_if->usb_mode = val;
+
#ifndef DWC_HOST_ONLY
/*
* Initialize the PCD
DWC_ERROR("pcd_init failed\n");
dwc_otg_device->pcd = NULL;
goto fail;
- }
+ }
#endif
#ifndef DWC_DEVICE_ONLY
/*
#endif
/*
* Enable the global interrupt after all the interrupt
- * handlers are installed if there is no ADP support else
+ * handlers are installed if there is no ADP support else
* perform initial actions required for Internal ADP logic.
*/
- if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if))
- dwc_otg_enable_global_interrupts(dwc_otg_device->core_if);
- else
- dwc_otg_adp_start(dwc_otg_device->core_if,
- dwc_otg_is_host_mode(dwc_otg_device->core_if));
+ if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) {
+ if (dwc_otg_device->core_if->usb_mode == USB_MODE_NORMAL &&
+ pldata->phy_status == USB_PHY_ENABLED) {
+ pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
+ udelay(3);
+ pldata->clock_enable(pldata, 0);
+ }
+ /* dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); */
+ } else
+ dwc_otg_adp_start(dwc_otg_device->core_if,
+ dwc_otg_is_host_mode(dwc_otg_device->
+ core_if));
return 0;
otg20_driver_remove(_dev);
clk_disable:
- if(pldata->clock_enable)
+ if (pldata->clock_enable)
pldata->clock_enable(pldata, 0);
return retval;
}
+#ifdef CONFIG_PM
+static int dwc_otg_pm_suspend(struct device *dev)
+{
+ dwc_otg_device_t *dwc_otg_device;
+ struct dwc_otg_platform_data *pdata_otg;
+
+ dwc_otg_device = dev_get_platdata(dev);
+
+ dev_dbg(dev, "dwc_otg PM suspend\n");
+
+ if (dwc_otg_device->core_if->op_state == B_PERIPHERAL)
+ return 0;
+
+ pdata_otg = dwc_otg_device->pldata;
+ pdata_otg->phy_suspend(pdata_otg, USB_PHY_SUSPEND);
+
+ return 0;
+}
+
+static int dwc_otg_pm_resume(struct device *dev)
+{
+ dwc_otg_device_t *dwc_otg_device;
+ struct dwc_otg_platform_data *pdata_otg;
+
+ dwc_otg_device = dev_get_platdata(dev);
+
+ dev_dbg(dev, "dwc_otg PM resume\n");
+
+ if (dwc_otg_device->core_if->op_state == B_PERIPHERAL)
+ return 0;
+
+ pdata_otg = dwc_otg_device->pldata;
+ pdata_otg->phy_suspend(pdata_otg, USB_PHY_ENABLED);
+
+ return 0;
+}
+#else
+#define dwc_otg_pm_suspend NULL
+#define dwc_otg_pm_resume NULL
+#endif
+
+static const struct dev_pm_ops dwc_otg_dev_pm_ops = {
+ .suspend = dwc_otg_pm_suspend,
+ .resume = dwc_otg_pm_resume,
+};
+
static struct platform_driver dwc_otg_driver = {
.driver = {
- .name = (char *)dwc_otg20_driver_name,
- .of_match_table = of_match_ptr(usb20_otg_of_match),
- },
+ .name = (char *)dwc_otg20_driver_name,
+ .of_match_table = of_match_ptr(usb20_otg_of_match),
+#ifdef CONFIG_PM
+ .pm = &dwc_otg_dev_pm_ops,
+#endif
+ },
.probe = otg20_driver_probe,
.remove = otg20_driver_remove,
.suspend = dwc_otg_driver_suspend,
.resume = dwc_otg_driver_resume,
.shutdown = dwc_otg_driver_shutdown,
};
+#endif
+
+void rk_usb_power_up(void)
+{
+ struct dwc_otg_platform_data *pldata_otg;
+ struct dwc_otg_platform_data *pldata_host;
+ struct rkehci_platform_data *pldata_ehci;
+ if (cpu_is_rk3288()) {
+#ifdef CONFIG_RK_USB_UART
+ /* enable USB bypass UART function */
+ writel_relaxed(0x00c00000 | usb_to_uart_status,
+ RK_GRF_VIRT + RK3288_GRF_UOC0_CON3);
+#endif
+ /* unset siddq,the analog blocks are powered up */
+#ifdef CONFIG_USB20_OTG
+ pldata_otg = &usb20otg_pdata_rk3288;
+ if (pldata_otg) {
+ if (pldata_otg->phy_status == USB_PHY_SUSPEND)
+ writel_relaxed((0x01 << 13) << 16,
+ RK_GRF_VIRT +
+ RK3288_GRF_UOC0_CON0);
+ }
+#endif
+#ifdef CONFIG_USB20_HOST
+ pldata_host = &usb20host_pdata_rk3288;
+ if (pldata_host) {
+ if (pldata_host->phy_status == USB_PHY_SUSPEND)
+ writel_relaxed((0x01 << 13) << 16,
+ RK_GRF_VIRT +
+ RK3288_GRF_UOC2_CON0);
+ }
+#endif
+#ifdef CONFIG_USB_EHCI_RK
+ pldata_ehci = &rkehci_pdata_rk3288;
+ if (pldata_ehci) {
+ if (pldata_ehci->phy_status == USB_PHY_SUSPEND)
+ writel_relaxed((0x01 << 13) << 16,
+ RK_GRF_VIRT +
+ RK3288_GRF_UOC1_CON0);
+ }
+#endif
+
+ } else {
+ dwc_otg_device_t *otg_dev = g_otgdev;
+
+ if (!otg_dev)
+ return;
+
+ pldata_otg = otg_dev->pldata;
+ if (pldata_otg && pldata_otg->phy_power_down)
+ pldata_otg->phy_power_down(PHY_POWER_UP);
+ }
+}
+
+void rk_usb_power_down(void)
+{
+ struct dwc_otg_platform_data *pldata_otg;
+ struct dwc_otg_platform_data *pldata_host;
+ struct rkehci_platform_data *pldata_ehci;
+
+ if (cpu_is_rk3288()) {
+#ifdef CONFIG_RK_USB_UART
+ /* disable USB bypass UART function */
+ usb_to_uart_status =
+ readl_relaxed(RK_GRF_VIRT + RK3288_GRF_UOC0_CON3);
+ writel_relaxed(0x00c00000, RK_GRF_VIRT + RK3288_GRF_UOC0_CON3);
+#endif
+ /* set siddq,the analog blocks are powered down
+ * note:
+ * 1. Before asserting SIDDQ, ensure that VDATSRCENB0,
+ * VDATDETENB0, DCDENB0, BYPASSSEL0, ADPPRBENB0,
+ * and TESTBURNIN are set to 1'b0.
+ * 2. Before asserting SIDDQ, ensure that phy enter suspend.*/
+#ifdef CONFIG_USB20_OTG
+ pldata_otg = &usb20otg_pdata_rk3288;
+ if (pldata_otg) {
+ if (pldata_otg->phy_status == USB_PHY_SUSPEND)
+ writel_relaxed((0x01 << 13) |
+ ((0x01 << 13) << 16),
+ RK_GRF_VIRT +
+ RK3288_GRF_UOC0_CON0);
+ }
+#endif
+#ifdef CONFIG_USB20_HOST
+ pldata_host = &usb20host_pdata_rk3288;
+ if (pldata_host) {
+ if (pldata_host->phy_status == USB_PHY_SUSPEND)
+ writel_relaxed((0x01 << 13) |
+ ((0x01 << 13) << 16),
+ RK_GRF_VIRT +
+ RK3288_GRF_UOC2_CON0);
+ }
+#endif
+#ifdef CONFIG_USB_EHCI_RK
+ pldata_ehci = &rkehci_pdata_rk3288;
+ if (pldata_ehci) {
+ if (pldata_ehci->phy_status == USB_PHY_SUSPEND)
+ writel_relaxed((0x01 << 13) |
+ ((0x01 << 13) << 16),
+ RK_GRF_VIRT +
+ RK3288_GRF_UOC1_CON0);
+ }
+#endif
+ } else {
+ dwc_otg_device_t *otg_dev = g_otgdev;
+
+ if (!otg_dev)
+ return;
+
+ pldata_otg = otg_dev->pldata;
+ if (pldata_otg && pldata_otg->phy_power_down)
+ pldata_otg->phy_power_down(PHY_POWER_DOWN);
+ }
+}
+
+EXPORT_SYMBOL(rk_usb_power_up);
+EXPORT_SYMBOL(rk_usb_power_down);
/**
* This function is called when the dwc_otg_driver is installed with the
* insmod command. It registers the dwc_otg_driver structure with the
{
int retval = 0;
int error;
- //register host20
- printk(KERN_INFO "%s: version %s\n", dwc_host20_driver_name,
+
+#ifdef CONFIG_USB20_OTG
+ /* register otg20 */
+ printk(KERN_INFO "%s: version %s\n", dwc_otg20_driver_name,
DWC_DRIVER_VERSION);
- retval = platform_driver_register(&dwc_host_driver);
+ retval = platform_driver_register(&dwc_otg_driver);
if (retval < 0) {
printk(KERN_ERR "%s retval=%d\n", __func__, retval);
return retval;
}
- error = driver_create_file(&dwc_host_driver.driver, &driver_attr_version);
- error = driver_create_file(&dwc_host_driver.driver, &driver_attr_debuglevel);
+ error =
+ driver_create_file(&dwc_otg_driver.driver, &driver_attr_version);
+ error =
+ driver_create_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
+ error =
+ driver_create_file(&dwc_otg_driver.driver,
+ &driver_attr_dwc_otg_conn_en);
+ error =
+ driver_create_file(&dwc_otg_driver.driver,
+ &driver_attr_vbus_status);
+ error =
+ driver_create_file(&dwc_otg_driver.driver,
+ &driver_attr_force_usb_mode);
+ error =
+ driver_create_file(&dwc_otg_driver.driver,
+ &driver_attr_op_state);
- //register otg20
- printk(KERN_INFO "%s: version %s\n", dwc_otg20_driver_name,
+#endif
+
+ /* register host20 */
+#ifdef CONFIG_USB20_HOST
+ printk(KERN_INFO "%s: version %s\n", dwc_host20_driver_name,
DWC_DRIVER_VERSION);
- retval = platform_driver_register(&dwc_otg_driver);
+ retval = platform_driver_register(&dwc_host_driver);
if (retval < 0) {
printk(KERN_ERR "%s retval=%d\n", __func__, retval);
return retval;
}
- error = driver_create_file(&dwc_otg_driver.driver, &driver_attr_version);
- error = driver_create_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
- error = driver_create_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_conn_en);
- error = driver_create_file(&dwc_otg_driver.driver, &driver_attr_vbus_status);
-
+ error =
+ driver_create_file(&dwc_host_driver.driver, &driver_attr_version);
+ error =
+ driver_create_file(&dwc_host_driver.driver,
+ &driver_attr_debuglevel);
+#endif
return retval;
}
{
printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n");
- /*for host20*/
+#ifdef CONFIG_USB20_HOST
+ /*for host20 */
driver_remove_file(&dwc_host_driver.driver, &driver_attr_debuglevel);
driver_remove_file(&dwc_host_driver.driver, &driver_attr_version);
platform_driver_unregister(&dwc_host_driver);
printk(KERN_INFO "%s module removed\n", dwc_host20_driver_name);
+#endif
- /*for otg*/
- driver_remove_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_conn_en);
+#ifdef CONFIG_USB20_OTG
+ /*for otg */
+ driver_remove_file(&dwc_otg_driver.driver,
+ &driver_attr_dwc_otg_conn_en);
driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
driver_remove_file(&dwc_otg_driver.driver, &driver_attr_vbus_status);
+ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_force_usb_mode);
+ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_op_state);
platform_driver_unregister(&dwc_otg_driver);
printk(KERN_INFO "%s module removed\n", dwc_otg20_driver_name);
+#endif
}
module_exit(dwc_otg_driver_cleanup);
module_param_named(besl_enable, dwc_otg_module_params.besl_enable, int, 0444);
MODULE_PARM_DESC(besl_enable, "BESL Enable 0=BESL Disabled 1=BESL Enabled");
-module_param_named(baseline_besl, dwc_otg_module_params.baseline_besl, int, 0444);
+module_param_named(baseline_besl, dwc_otg_module_params.baseline_besl, int,
+ 0444);
MODULE_PARM_DESC(baseline_besl, "Set the baseline besl value");
module_param_named(deep_besl, dwc_otg_module_params.deep_besl, int, 0444);
MODULE_PARM_DESC(deep_besl, "Set the deep besl value");
- 0: Disabled (default)
- 1: Enabled
</td></tr>
-
+
<tr>
<td>en_multiple_tx_fifo</td>
<td>Specifies whether dedicatedto tx fifos are enabled for non periodic IN EPs.
<tr>
<td>thr_ctl</td>
- <td>Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of
+ <td>Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of
this parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and
Rx transfers accordingly.
The driver will automatically detect the value for this parameter if none is
- 0: LPM disabled
- 1: LPM enable (default, if available)
</td></tr>
-
+
<tr>
<td>besl_enable</td>
<td>Specifies whether to enable LPM Errata support.
The driver will automatically detect the value for this parameter if none is
specified.
- 0: LPM Errata disabled (default)
- - 1: LPM Errata enable
+ - 1: LPM Errata enable
</td></tr>
-
+
<tr>
<td>baseline_besl</td>
<td>Specifies the baseline besl value.
- Values: 0 to 15 (default 0)
</td></tr>
-
+
<tr>
<td>deep_besl</td>
<td>Specifies the deep besl value.
The driver will automatically detect the value for this parameter if none is
specified.
- 0: IC_USB disabled (default, if available)
- - 1: IC_USB enable
+ - 1: IC_USB enable
</td></tr>
<tr>
- 0: Power Down disabled (default)
- 2: Power Down enabled
</td></tr>
-
+
<tr>
<td>reload_ctl</td>
<td>Specifies whether dynamic reloading of the HFIR register is allowed during
<tr>
<td>cont_on_bna</td>
- <td>Specifies whether Enable Continue on BNA enabled or no.
+ <td>Specifies whether Enable Continue on BNA enabled or no.
After receiving BNA interrupt the core disables the endpoint,when the
- endpoint is re-enabled by the application the
+ endpoint is re-enabled by the application the
- 0: Core starts processing from the DOEPDMA descriptor (default)
- 1: Core starts processing from the descriptor which received the BNA.
This parameter is valid only when OTG_EN_DESC_DMA == 1\92b1.
<tr>
<td>ahb_single</td>
<td>This bit when programmed supports SINGLE transfers for remainder data
- in a transfer for DMA mode of operation.
+ in a transfer for DMA mode of operation.
- 0: The remainder data will be sent using INCR burst size (default)
- 1: The remainder data will be sent using SINGLE burst size.
</td></tr>
<td>Specifies whether OTG is performing as USB OTG Revision 2.0 or Revision 1.3
USB OTG device.
- 0: OTG 2.0 support disabled (default)
- - 1: OTG 2.0 support enabled
+ - 1: OTG 2.0 support enabled
</td></tr>
*/