mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-09-21 11:53:01 +00:00
usb: dwc3-msm: DBM refactoring
Refactoring of DBM code to allow easy support for future DBM versions. All DBM specific operation are now defined in dbm.h, and implemented in a dbm specific version module. Note that only a single instance of DBM is currently supported. Change-Id: I751300240951a84a42358c3b8b5222e73c537653 Signed-off-by: Bar Weiner <bweiner@codeaurora.org>
This commit is contained in:
parent
f82aaf71a3
commit
3bc20703e5
11
Documentation/devicetree/bindings/usb/msm-dbm.txt
Normal file
11
Documentation/devicetree/bindings/usb/msm-dbm.txt
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
MSM DBM (Device Bus Manager)
|
||||||
|
|
||||||
|
Required properties :
|
||||||
|
- compatible : should be "qcom,usb-dbm-<dbm version number>"
|
||||||
|
- reg : offset and length of the register set in the memory map.
|
||||||
|
|
||||||
|
Example MSM DBM (Device Bus Manager) device node :
|
||||||
|
dbm_1p4: dbm@f92f8000 {
|
||||||
|
compatible = "qcom,usb-dbm-1p4";
|
||||||
|
reg = <0xf92f8000 0x1000>;
|
||||||
|
};
|
|
@ -11,10 +11,6 @@ Required properties :
|
||||||
"vbus_dwc3" : vbus supply for host mode when DWC3 operating as DRD.
|
"vbus_dwc3" : vbus supply for host mode when DWC3 operating as DRD.
|
||||||
This can be left as optional if "host-only-mode" is selected in the
|
This can be left as optional if "host-only-mode" is selected in the
|
||||||
'dwc3' sub node for "DWC3-USB3 Core device".
|
'dwc3' sub node for "DWC3-USB3 Core device".
|
||||||
- qcom,dwc-usb3-msm-dbm-eps: Number of endpoints avaliable for
|
|
||||||
the DBM (Device Bus Manager). The DBM is HW unit which is part of
|
|
||||||
the MSM USB3.0 core (which also includes the Synopsys DesignWare
|
|
||||||
USB3.0 controller)
|
|
||||||
|
|
||||||
Optional properties :
|
Optional properties :
|
||||||
- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
|
- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
|
||||||
|
@ -52,6 +48,7 @@ Optional properties :
|
||||||
being reset in initialization.
|
being reset in initialization.
|
||||||
- qcom,no-suspend-resume: If present, the device will not perform any activity
|
- qcom,no-suspend-resume: If present, the device will not perform any activity
|
||||||
during suspend/resume
|
during suspend/resume
|
||||||
|
- qcom,usb-dbm : phandle for the DBM device
|
||||||
|
|
||||||
Sub nodes:
|
Sub nodes:
|
||||||
- Sub node for "DWC3- USB3 controller".
|
- Sub node for "DWC3- USB3 controller".
|
||||||
|
@ -71,6 +68,7 @@ Example MSM USB3.0 controller device node :
|
||||||
qcom,dwc_usb3-adc_tm = <&pm8941_adc_tm>;
|
qcom,dwc_usb3-adc_tm = <&pm8941_adc_tm>;
|
||||||
qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
|
qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
|
||||||
qcom,dwc-usb3-msm-qdss-tx-fifo-size = <16384>;
|
qcom,dwc-usb3-msm-qdss-tx-fifo-size = <16384>;
|
||||||
|
qcom,usb-dbm = <&dbm_1p4>;
|
||||||
|
|
||||||
qcom,msm_bus,name = "usb3";
|
qcom,msm_bus,name = "usb3";
|
||||||
qcom,msm_bus,num_cases = <2>;
|
qcom,msm_bus,num_cases = <2>;
|
||||||
|
|
|
@ -1928,12 +1928,12 @@
|
||||||
interrupt-names = "hs_phy_irq", "pmic_id_irq";
|
interrupt-names = "hs_phy_irq", "pmic_id_irq";
|
||||||
|
|
||||||
USB3_GDSC-supply = <&gdsc_usb30>;
|
USB3_GDSC-supply = <&gdsc_usb30>;
|
||||||
qcom,dwc-usb3-msm-dbm-eps = <4>;
|
|
||||||
qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
|
qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
|
||||||
qcom,dwc-usb3-msm-qdss-tx-fifo-size = <8192>;
|
qcom,dwc-usb3-msm-qdss-tx-fifo-size = <8192>;
|
||||||
qcom,otg-capability;
|
qcom,otg-capability;
|
||||||
qcom,misc-ref = <&pma8084_misc>;
|
qcom,misc-ref = <&pma8084_misc>;
|
||||||
qcom,restore-sec-cfg-for-scm-dev-id = <9>;
|
qcom,restore-sec-cfg-for-scm-dev-id = <9>;
|
||||||
|
qcom,usb-dbm = <&dbm0_1p4>;
|
||||||
|
|
||||||
qcom,msm-bus,name = "usb3";
|
qcom,msm-bus,name = "usb3";
|
||||||
qcom,msm-bus,num-cases = <2>;
|
qcom,msm-bus,num-cases = <2>;
|
||||||
|
@ -2006,6 +2006,11 @@
|
||||||
qcom,vbus-valid-override;
|
qcom,vbus-valid-override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dbm0_1p4: dbm@f92f8000 {
|
||||||
|
compatible = "qcom,usb-dbm-1p4";
|
||||||
|
reg = <0xf92f8000 0x1000>;
|
||||||
|
};
|
||||||
|
|
||||||
hsphy1: hsphy@f94f8800 {
|
hsphy1: hsphy@f94f8800 {
|
||||||
compatible = "qcom,usb-hsphy";
|
compatible = "qcom,usb-hsphy";
|
||||||
reg = <0xf94f8800 0x3ff>;
|
reg = <0xf94f8800 0x3ff>;
|
||||||
|
|
|
@ -301,9 +301,9 @@
|
||||||
|
|
||||||
vbus_dwc3-supply = <&usb3_otg>;
|
vbus_dwc3-supply = <&usb3_otg>;
|
||||||
qcom,charging-disabled;
|
qcom,charging-disabled;
|
||||||
qcom,dwc-usb3-msm-dbm-eps = <4>;
|
|
||||||
qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
|
qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
|
||||||
qcom,dwc-usb3-msm-qdss-tx-fifo-size = <8192>;
|
qcom,dwc-usb3-msm-qdss-tx-fifo-size = <8192>;
|
||||||
|
qcom,usb-dbm = <&dbm0_1p4>;
|
||||||
|
|
||||||
qcom,msm-bus,name = "usb3";
|
qcom,msm-bus,name = "usb3";
|
||||||
qcom,msm-bus,num-cases = <2>;
|
qcom,msm-bus,num-cases = <2>;
|
||||||
|
@ -343,6 +343,11 @@
|
||||||
qcom,vdd-voltage-level = <1 5 7>;
|
qcom,vdd-voltage-level = <1 5 7>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dbm0_1p4: dbm@f92f8000 {
|
||||||
|
compatible = "qcom,usb-dbm-1p4";
|
||||||
|
reg = <0xf92f8000 0x1000>;
|
||||||
|
};
|
||||||
|
|
||||||
spmi_bus: qcom,spmi@fc4c0000 {
|
spmi_bus: qcom,spmi@fc4c0000 {
|
||||||
cell-index = <0>;
|
cell-index = <0>;
|
||||||
compatible = "qcom,spmi-pmic-arb";
|
compatible = "qcom,spmi-pmic-arb";
|
||||||
|
|
|
@ -1647,11 +1647,11 @@
|
||||||
interrupt-names = "hs_phy_irq", "pmic_id_irq";
|
interrupt-names = "hs_phy_irq", "pmic_id_irq";
|
||||||
|
|
||||||
vbus_dwc3-supply = <&pm8941_mvs1>;
|
vbus_dwc3-supply = <&pm8941_mvs1>;
|
||||||
qcom,dwc-usb3-msm-dbm-eps = <4>;
|
|
||||||
qcom,misc-ref = <&pm8941_misc>;
|
qcom,misc-ref = <&pm8941_misc>;
|
||||||
dwc_usb3-adc_tm = <&pm8941_adc_tm>;
|
dwc_usb3-adc_tm = <&pm8941_adc_tm>;
|
||||||
qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
|
qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
|
||||||
qcom,dwc-usb3-msm-qdss-tx-fifo-size = <8192>;
|
qcom,dwc-usb3-msm-qdss-tx-fifo-size = <8192>;
|
||||||
|
qcom,usb-dbm = <&dbm_1p4>;
|
||||||
|
|
||||||
qcom,msm-bus,name = "usb3";
|
qcom,msm-bus,name = "usb3";
|
||||||
qcom,msm-bus,num-cases = <2>;
|
qcom,msm-bus,num-cases = <2>;
|
||||||
|
@ -1689,6 +1689,10 @@
|
||||||
qcom,vdd-voltage-level = <1 5 7>;
|
qcom,vdd-voltage-level = <1 5 7>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dbm_1p4: dbm@f92f8000 {
|
||||||
|
compatible = "qcom,usb-dbm-1p4";
|
||||||
|
reg = <0xf92f8000 0x1000>;
|
||||||
|
};
|
||||||
ehci: qcom,ehci-host@f9a55000 {
|
ehci: qcom,ehci-host@f9a55000 {
|
||||||
compatible = "qcom,ehci-host";
|
compatible = "qcom,ehci-host";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
|
|
@ -38,7 +38,7 @@ endif
|
||||||
|
|
||||||
obj-$(CONFIG_USB_DWC3) += dwc3-omap.o
|
obj-$(CONFIG_USB_DWC3) += dwc3-omap.o
|
||||||
obj-$(CONFIG_USB_DWC3) += dwc3-exynos.o
|
obj-$(CONFIG_USB_DWC3) += dwc3-exynos.o
|
||||||
obj-$(CONFIG_USB_DWC3_MSM) += dwc3-msm.o
|
obj-$(CONFIG_USB_DWC3_MSM) += dbm-1_4.o dwc3-msm.o dbm.o
|
||||||
|
|
||||||
ifneq ($(CONFIG_PCI),)
|
ifneq ($(CONFIG_PCI),)
|
||||||
obj-$(CONFIG_USB_DWC3) += dwc3-pci.o
|
obj-$(CONFIG_USB_DWC3) += dwc3-pci.o
|
||||||
|
|
428
drivers/usb/dwc3/dbm-1_4.c
Normal file
428
drivers/usb/dwc3/dbm-1_4.c
Normal file
|
@ -0,0 +1,428 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
|
||||||
|
#include "dbm.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* USB DBM Hardware registers.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DBM_EP_CFG(n) (0x00 + 4 * (n))
|
||||||
|
#define DBM_DATA_FIFO(n) (0x10 + 4 * (n))
|
||||||
|
#define DBM_DATA_FIFO_SIZE(n) (0x20 + 4 * (n))
|
||||||
|
#define DBM_DATA_FIFO_EN (0x30)
|
||||||
|
#define DBM_GEVNTADR (0x34)
|
||||||
|
#define DBM_GEVNTSIZ (0x38)
|
||||||
|
#define DBM_DBG_CNFG (0x3C)
|
||||||
|
#define DBM_HW_TRB0_EP(n) (0x40 + 4 * (n))
|
||||||
|
#define DBM_HW_TRB1_EP(n) (0x50 + 4 * (n))
|
||||||
|
#define DBM_HW_TRB2_EP(n) (0x60 + 4 * (n))
|
||||||
|
#define DBM_HW_TRB3_EP(n) (0x70 + 4 * (n))
|
||||||
|
#define DBM_PIPE_CFG (0x80)
|
||||||
|
#define DBM_SOFT_RESET (0x84)
|
||||||
|
#define DBM_GEN_CFG (0x88)
|
||||||
|
#define DBM_GEVNTADR_LSB (0x98)
|
||||||
|
#define DBM_GEVNTADR_MSB (0x9C)
|
||||||
|
#define DBM_DATA_FIFO_LSB(n) (0xA0 + 8 * (n))
|
||||||
|
#define DBM_DATA_FIFO_MSB(n) (0xA4 + 8 * (n))
|
||||||
|
|
||||||
|
#define DBM_1_4_NUM_EP 4
|
||||||
|
|
||||||
|
struct dbm_data {
|
||||||
|
void __iomem *base;
|
||||||
|
|
||||||
|
int dbm_num_eps;
|
||||||
|
u8 ep_num_mapping[DBM_1_4_NUM_EP];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dbm_data *dbm_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write register masked field with debug info.
|
||||||
|
*
|
||||||
|
* @base - DWC3 base virtual address.
|
||||||
|
* @offset - register offset.
|
||||||
|
* @mask - register bitmask.
|
||||||
|
* @val - value to write.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static inline void msm_dbm_write_reg_field(void *base, u32 offset,
|
||||||
|
const u32 mask, u32 val)
|
||||||
|
{
|
||||||
|
u32 shift = find_first_bit((void *)&mask, 32);
|
||||||
|
u32 tmp = ioread32(base + offset);
|
||||||
|
|
||||||
|
tmp &= ~mask; /* clear written bits */
|
||||||
|
val = tmp | (val << shift);
|
||||||
|
iowrite32(val, base + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Read register with debug info.
|
||||||
|
*
|
||||||
|
* @base - DWC3 base virtual address.
|
||||||
|
* @offset - register offset.
|
||||||
|
*
|
||||||
|
* @return u32
|
||||||
|
*/
|
||||||
|
static inline u32 msm_dbm_read_reg(void *base, u32 offset)
|
||||||
|
{
|
||||||
|
u32 val = ioread32(base + offset);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Write register with debug info.
|
||||||
|
*
|
||||||
|
* @base - DWC3 base virtual address.
|
||||||
|
* @offset - register offset.
|
||||||
|
* @val - value to write.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static inline void msm_dbm_write_reg(void *base, u32 offset, u32 val)
|
||||||
|
{
|
||||||
|
iowrite32(val, base + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return DBM EP number according to usb endpoint number.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int msm_dbm_find_matching_dbm_ep(u8 usb_ep)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < dbm_data->dbm_num_eps; i++)
|
||||||
|
if (dbm_data->ep_num_mapping[i] == usb_ep)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -ENODEV; /* Not found */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the DBM registers upon initialization.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int soft_reset(bool reset)
|
||||||
|
{
|
||||||
|
pr_debug("%s DBM reset\n", (reset ? "Enter" : "Exit"));
|
||||||
|
|
||||||
|
msm_dbm_write_reg_field(dbm_data->base, DBM_SOFT_RESET,
|
||||||
|
DBM_SFT_RST_MASK, reset);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Soft reset specific DBM ep.
|
||||||
|
* This function is called by the function driver upon events
|
||||||
|
* such as transfer aborting, USB re-enumeration and USB
|
||||||
|
* disconnection.
|
||||||
|
*
|
||||||
|
* @dbm_ep - DBM ep number.
|
||||||
|
* @enter_reset - should we enter a reset state or get out of it.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int dbm_ep_soft_reset(u8 dbm_ep, bool enter_reset)
|
||||||
|
{
|
||||||
|
pr_debug("%s\n", __func__);
|
||||||
|
|
||||||
|
if (dbm_ep >= dbm_data->dbm_num_eps) {
|
||||||
|
pr_err("%s: Invalid DBM ep index\n", __func__);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enter_reset) {
|
||||||
|
msm_dbm_write_reg_field(dbm_data->base, DBM_SOFT_RESET,
|
||||||
|
DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 1);
|
||||||
|
} else {
|
||||||
|
msm_dbm_write_reg_field(dbm_data->base, DBM_SOFT_RESET,
|
||||||
|
DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure a USB DBM ep to work in BAM mode.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @usb_ep - USB physical EP number.
|
||||||
|
* @producer - producer/consumer.
|
||||||
|
* @disable_wb - disable write back to system memory.
|
||||||
|
* @internal_mem - use internal USB memory for data fifo.
|
||||||
|
* @ioc - enable interrupt on completion.
|
||||||
|
*
|
||||||
|
* @return int - DBM ep number.
|
||||||
|
*/
|
||||||
|
static int ep_config(u8 usb_ep, u8 bam_pipe, bool producer, bool disable_wb,
|
||||||
|
bool internal_mem, bool ioc)
|
||||||
|
{
|
||||||
|
int dbm_ep;
|
||||||
|
u32 ep_cfg;
|
||||||
|
|
||||||
|
pr_debug("%s\n", __func__);
|
||||||
|
|
||||||
|
dbm_ep = msm_dbm_find_matching_dbm_ep(usb_ep);
|
||||||
|
|
||||||
|
if (dbm_ep < 0) {
|
||||||
|
pr_err("%s: Invalid usb ep index\n", __func__);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First, reset the dbm endpoint */
|
||||||
|
dbm_ep_soft_reset(dbm_ep, 0);
|
||||||
|
|
||||||
|
/* Set ioc bit for dbm_ep if needed */
|
||||||
|
msm_dbm_write_reg_field(dbm_data->base, DBM_DBG_CNFG,
|
||||||
|
DBM_ENABLE_IOC_MASK & 1 << dbm_ep, ioc ? 1 : 0);
|
||||||
|
|
||||||
|
ep_cfg = (producer ? DBM_PRODUCER : 0) |
|
||||||
|
(disable_wb ? DBM_DISABLE_WB : 0) |
|
||||||
|
(internal_mem ? DBM_INT_RAM_ACC : 0);
|
||||||
|
|
||||||
|
msm_dbm_write_reg_field(dbm_data->base, DBM_EP_CFG(dbm_ep),
|
||||||
|
DBM_PRODUCER | DBM_DISABLE_WB | DBM_INT_RAM_ACC, ep_cfg >> 8);
|
||||||
|
|
||||||
|
msm_dbm_write_reg_field(dbm_data->base, DBM_EP_CFG(dbm_ep), USB3_EPNUM,
|
||||||
|
usb_ep);
|
||||||
|
msm_dbm_write_reg_field(dbm_data->base, DBM_EP_CFG(dbm_ep),
|
||||||
|
DBM_BAM_PIPE_NUM, bam_pipe);
|
||||||
|
msm_dbm_write_reg_field(dbm_data->base, DBM_PIPE_CFG, 0x000000ff,
|
||||||
|
0xe4);
|
||||||
|
msm_dbm_write_reg_field(dbm_data->base, DBM_EP_CFG(dbm_ep), DBM_EN_EP,
|
||||||
|
1);
|
||||||
|
|
||||||
|
return dbm_ep;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure a USB DBM ep to work in normal mode.
|
||||||
|
*
|
||||||
|
* @usb_ep - USB ep number.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int ep_unconfig(u8 usb_ep)
|
||||||
|
{
|
||||||
|
int dbm_ep;
|
||||||
|
u32 data;
|
||||||
|
|
||||||
|
pr_debug("%s\n", __func__);
|
||||||
|
|
||||||
|
dbm_ep = msm_dbm_find_matching_dbm_ep(usb_ep);
|
||||||
|
|
||||||
|
if (dbm_ep < 0) {
|
||||||
|
pr_err("%s: Invalid usb ep index\n", __func__);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbm_data->ep_num_mapping[dbm_ep] = 0;
|
||||||
|
|
||||||
|
data = msm_dbm_read_reg(dbm_data->base, DBM_EP_CFG(dbm_ep));
|
||||||
|
data &= (~0x1);
|
||||||
|
msm_dbm_write_reg(dbm_data->base, DBM_EP_CFG(dbm_ep), data);
|
||||||
|
|
||||||
|
/* Reset the dbm endpoint */
|
||||||
|
dbm_ep_soft_reset(dbm_ep, true);
|
||||||
|
/*
|
||||||
|
* 10 usec delay is required before deasserting DBM endpoint reset
|
||||||
|
* according to hardware programming guide.
|
||||||
|
*/
|
||||||
|
udelay(10);
|
||||||
|
dbm_ep_soft_reset(dbm_ep, false);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return number of configured DBM endpoints.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int get_num_of_eps_configured(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < dbm_data->dbm_num_eps; i++)
|
||||||
|
if (dbm_data->ep_num_mapping[i])
|
||||||
|
count++;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the DBM with the USB3 core event buffer.
|
||||||
|
* This function is called by the SNPS UDC upon initialization.
|
||||||
|
*
|
||||||
|
* @addr - address of the event buffer.
|
||||||
|
* @size - size of the event buffer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int event_buffer_config(u32 addr_lo, u32 addr_hi, int size)
|
||||||
|
{
|
||||||
|
pr_debug("%s\n", __func__);
|
||||||
|
|
||||||
|
if (size < 0) {
|
||||||
|
pr_err("%s: Invalid size. size = %d", __func__, size);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizeof(phys_addr_t) > sizeof(u32)) {
|
||||||
|
msm_dbm_write_reg(dbm_data->base, DBM_GEVNTADR_LSB, addr_lo);
|
||||||
|
msm_dbm_write_reg(dbm_data->base, DBM_GEVNTADR_MSB, addr_hi);
|
||||||
|
} else {
|
||||||
|
msm_dbm_write_reg(dbm_data->base, DBM_GEVNTADR, addr_lo);
|
||||||
|
}
|
||||||
|
msm_dbm_write_reg_field(dbm_data->base, DBM_GEVNTSIZ,
|
||||||
|
DBM_GEVNTSIZ_MASK, size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int data_fifo_config(u8 dep_num, phys_addr_t addr,
|
||||||
|
u32 size, u8 dst_pipe_idx)
|
||||||
|
{
|
||||||
|
u8 dbm_ep;
|
||||||
|
dbm_ep = dst_pipe_idx;
|
||||||
|
|
||||||
|
dbm_data->ep_num_mapping[dbm_ep] = dep_num;
|
||||||
|
|
||||||
|
if (sizeof(addr) > sizeof(u32)) {
|
||||||
|
u32 lo = lower_32_bits(addr);
|
||||||
|
u32 hi = upper_32_bits(addr);
|
||||||
|
msm_dbm_write_reg(dbm_data->base,
|
||||||
|
DBM_DATA_FIFO_LSB(dbm_ep), lo);
|
||||||
|
msm_dbm_write_reg(dbm_data->base,
|
||||||
|
DBM_DATA_FIFO_MSB(dbm_ep), hi);
|
||||||
|
} else {
|
||||||
|
msm_dbm_write_reg(dbm_data->base,
|
||||||
|
DBM_DATA_FIFO(dbm_ep), addr);
|
||||||
|
}
|
||||||
|
msm_dbm_write_reg_field(dbm_data->base, DBM_DATA_FIFO_SIZE(dbm_ep),
|
||||||
|
DBM_DATA_FIFO_SIZE_MASK, size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_speed(bool speed)
|
||||||
|
{
|
||||||
|
msm_dbm_write_reg(dbm_data->base, DBM_GEN_CFG, speed >> 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void enable(void) {}
|
||||||
|
|
||||||
|
|
||||||
|
static int msm_dbm_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct dbm *dbm;
|
||||||
|
struct resource *res;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
dbm_data = devm_kzalloc(dev, sizeof(*dbm_data), GFP_KERNEL);
|
||||||
|
if (!dbm_data)
|
||||||
|
return -ENOMEM;
|
||||||
|
dbm_data->dbm_num_eps = DBM_1_4_NUM_EP;
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
if (!res) {
|
||||||
|
dev_err(&pdev->dev, "missing memory base resource\n");
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto free_dbm_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbm_data->base = devm_ioremap_nocache(&pdev->dev, res->start,
|
||||||
|
resource_size(res));
|
||||||
|
if (!dbm_data->base) {
|
||||||
|
dev_err(&pdev->dev, "ioremap failed\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto free_dbm_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dbm = devm_kzalloc(dev, sizeof(*dbm), GFP_KERNEL);
|
||||||
|
if (!dbm) {
|
||||||
|
dev_err(&pdev->dev, "not enough memory\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto free_dbm_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbm->dev = dev;
|
||||||
|
|
||||||
|
dbm->soft_reset = soft_reset;
|
||||||
|
dbm->ep_config = ep_config;
|
||||||
|
dbm->ep_unconfig = ep_unconfig;
|
||||||
|
dbm->get_num_of_eps_configured = get_num_of_eps_configured;
|
||||||
|
dbm->event_buffer_config = event_buffer_config;
|
||||||
|
dbm->data_fifo_config = data_fifo_config;
|
||||||
|
dbm->set_speed = set_speed;
|
||||||
|
dbm->enable = enable;
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, dbm);
|
||||||
|
|
||||||
|
return usb_add_dbm(dbm);
|
||||||
|
|
||||||
|
free_dbm_data:
|
||||||
|
kfree(dbm_data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msm_dbm_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct dbm *dbm = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
kfree(dbm);
|
||||||
|
kfree(dbm_data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id msm_dbm_1_4_id_table[] = {
|
||||||
|
{
|
||||||
|
.compatible = "qcom,usb-dbm-1p4",
|
||||||
|
},
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, msm_dbm_1_4_id_table);
|
||||||
|
|
||||||
|
static struct platform_driver msm_dbm_driver = {
|
||||||
|
.probe = msm_dbm_probe,
|
||||||
|
.remove = msm_dbm_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "msm-usb-dbm-1-4",
|
||||||
|
.of_match_table = of_match_ptr(msm_dbm_1_4_id_table),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module_platform_driver(msm_dbm_driver);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("MSM USB DBM 1.4 driver");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
70
drivers/usb/dwc3/dbm.c
Normal file
70
drivers/usb/dwc3/dbm.c
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
|
||||||
|
#include "dbm.h"
|
||||||
|
|
||||||
|
struct dbm_manager {
|
||||||
|
struct list_head dbm_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dbm_manager dbm_manager = {
|
||||||
|
.dbm_list = LIST_HEAD_INIT(dbm_manager.dbm_list)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct dbm *of_usb_find_dbm(struct device_node *node)
|
||||||
|
{
|
||||||
|
struct dbm *dbm;
|
||||||
|
|
||||||
|
list_for_each_entry(dbm, &dbm_manager.dbm_list, head) {
|
||||||
|
if (node != dbm->dev->of_node)
|
||||||
|
continue;
|
||||||
|
return dbm;
|
||||||
|
}
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dbm *usb_get_dbm_by_phandle(struct device *dev,
|
||||||
|
const char *phandle, u8 index)
|
||||||
|
{
|
||||||
|
struct device_node *node;
|
||||||
|
|
||||||
|
if (!dev->of_node) {
|
||||||
|
dev_dbg(dev, "device does not have a device node entry\n");
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
node = of_parse_phandle(dev->of_node, phandle, index);
|
||||||
|
if (!node) {
|
||||||
|
dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
|
||||||
|
dev->of_node->full_name);
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
return of_usb_find_dbm(node);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(usb_get_dbm_by_phandle);
|
||||||
|
|
||||||
|
|
||||||
|
int usb_add_dbm(struct dbm *x)
|
||||||
|
{
|
||||||
|
list_add_tail(&x->head, &dbm_manager.dbm_list);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(usb_add_dbm);
|
||||||
|
|
||||||
|
|
164
drivers/usb/dwc3/dbm.h
Normal file
164
drivers/usb/dwc3/dbm.h
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DBM_H
|
||||||
|
#define __DBM_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/usb/gadget.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* USB DBM Hardware registers bitmask.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/* DBM_EP_CFG */
|
||||||
|
#define DBM_EN_EP 0x00000001
|
||||||
|
#define USB3_EPNUM 0x0000003E
|
||||||
|
#define DBM_BAM_PIPE_NUM 0x000000C0
|
||||||
|
#define DBM_PRODUCER 0x00000100
|
||||||
|
#define DBM_DISABLE_WB 0x00000200
|
||||||
|
#define DBM_INT_RAM_ACC 0x00000400
|
||||||
|
|
||||||
|
/* DBM_DATA_FIFO_SIZE */
|
||||||
|
#define DBM_DATA_FIFO_SIZE_MASK 0x0000ffff
|
||||||
|
|
||||||
|
/* DBM_GEVNTSIZ */
|
||||||
|
#define DBM_GEVNTSIZ_MASK 0x0000ffff
|
||||||
|
|
||||||
|
/* DBM_DBG_CNFG */
|
||||||
|
#define DBM_ENABLE_IOC_MASK 0x0000000f
|
||||||
|
|
||||||
|
/* DBM_SOFT_RESET */
|
||||||
|
#define DBM_SFT_RST_EP0 0x00000001
|
||||||
|
#define DBM_SFT_RST_EP1 0x00000002
|
||||||
|
#define DBM_SFT_RST_EP2 0x00000004
|
||||||
|
#define DBM_SFT_RST_EP3 0x00000008
|
||||||
|
#define DBM_SFT_RST_EPS_MASK 0x0000000F
|
||||||
|
#define DBM_SFT_RST_MASK 0x80000000
|
||||||
|
#define DBM_EN_MASK 0x00000002
|
||||||
|
|
||||||
|
/* DBM TRB configurations */
|
||||||
|
#define DBM_TRB_BIT 0x80000000
|
||||||
|
#define DBM_TRB_DATA_SRC 0x40000000
|
||||||
|
#define DBM_TRB_DMA 0x20000000
|
||||||
|
#define DBM_TRB_EP_NUM(ep) (ep<<24)
|
||||||
|
|
||||||
|
|
||||||
|
struct dbm {
|
||||||
|
struct device *dev;
|
||||||
|
struct list_head head;
|
||||||
|
|
||||||
|
/* Reset the DBM registers upon initialization */
|
||||||
|
int (*soft_reset)(bool reset);
|
||||||
|
|
||||||
|
/* Configure a USB DBM ep to work in BAM mode */
|
||||||
|
int (*ep_config)(u8 usb_ep, u8 bam_pipe,
|
||||||
|
bool producer, bool disable_wb,
|
||||||
|
bool internal_mem, bool ioc);
|
||||||
|
|
||||||
|
/* Configure a USB DBM ep to work in normal mode */
|
||||||
|
int (*ep_unconfig)(u8 usb_ep);
|
||||||
|
|
||||||
|
/* Return number of configured DBM endpoints */
|
||||||
|
int (*get_num_of_eps_configured)(void);
|
||||||
|
|
||||||
|
/* Configure the DBM with the USB3 core event buffer */
|
||||||
|
int (*event_buffer_config)(u32 addr_lo, u32 addr_hi, int size);
|
||||||
|
|
||||||
|
/* Configure the DBM with the BAM's data fifo */
|
||||||
|
int (*data_fifo_config)(u8 dep_num, phys_addr_t addr,
|
||||||
|
u32 size, u8 dst_pipe_idx);
|
||||||
|
|
||||||
|
/* Configure DBM speed : hs/ss */
|
||||||
|
void (*set_speed)(bool speed);
|
||||||
|
|
||||||
|
/* Enable DBM */
|
||||||
|
void (*enable)(void);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dbm *usb_get_dbm_by_phandle(struct device *dev,
|
||||||
|
const char *phandle, u8 index);
|
||||||
|
int usb_add_dbm(struct dbm *x);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define CHECK_DBM_PTR_INT(dbm) do { \
|
||||||
|
if (!(dbm)) { \
|
||||||
|
pr_err("Can't call %s, dbp pointer == NULL\n", __func__); \
|
||||||
|
return -EPERM; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CHECK_DBM_PTR_VOID(dbm) do { \
|
||||||
|
if (!(dbm)) { \
|
||||||
|
pr_err("Can't call %s, dbp pointer == NULL\n", __func__); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static inline int dbm_soft_reset(struct dbm *dbm, bool enter_reset)
|
||||||
|
{
|
||||||
|
CHECK_DBM_PTR_INT(dbm);
|
||||||
|
return dbm->soft_reset(enter_reset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dbm_ep_config(struct dbm *dbm, u8 usb_ep, u8 bam_pipe,
|
||||||
|
bool producer, bool disable_wb, bool internal_mem,
|
||||||
|
bool ioc)
|
||||||
|
{
|
||||||
|
CHECK_DBM_PTR_INT(dbm);
|
||||||
|
return dbm->ep_config(usb_ep, bam_pipe, producer, disable_wb,
|
||||||
|
internal_mem, ioc);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dbm_ep_unconfig(struct dbm *dbm, u8 usb_ep)
|
||||||
|
{
|
||||||
|
CHECK_DBM_PTR_INT(dbm);
|
||||||
|
return dbm->ep_unconfig(usb_ep);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dbm_get_num_of_eps_configured(struct dbm *dbm)
|
||||||
|
{
|
||||||
|
CHECK_DBM_PTR_INT(dbm);
|
||||||
|
return dbm->get_num_of_eps_configured();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dbm_event_buffer_config(struct dbm *dbm, u32 addr_lo,
|
||||||
|
u32 addr_hi, int size)
|
||||||
|
{
|
||||||
|
CHECK_DBM_PTR_INT(dbm);
|
||||||
|
return dbm->event_buffer_config(addr_lo, addr_hi, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dbm_data_fifo_config(struct dbm *dbm, u8 dep_num,
|
||||||
|
phys_addr_t addr, u32 size, u8 dst_pipe_idx)
|
||||||
|
{
|
||||||
|
CHECK_DBM_PTR_INT(dbm);
|
||||||
|
return dbm->data_fifo_config(dep_num, addr, size, dst_pipe_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dbm_set_speed(struct dbm *dbm, bool speed)
|
||||||
|
{
|
||||||
|
CHECK_DBM_PTR_VOID(dbm);
|
||||||
|
dbm->set_speed(speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dbm_enable(struct dbm *dbm)
|
||||||
|
{
|
||||||
|
CHECK_DBM_PTR_VOID(dbm);
|
||||||
|
dbm->enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __DBM_H */
|
|
@ -51,6 +51,7 @@
|
||||||
#include "dwc3_otg.h"
|
#include "dwc3_otg.h"
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "gadget.h"
|
#include "gadget.h"
|
||||||
|
#include "dbm.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
/* ADC threshold values */
|
/* ADC threshold values */
|
||||||
|
@ -75,68 +76,6 @@ static bool prop_chg_detect;
|
||||||
module_param(prop_chg_detect, bool, S_IRUGO | S_IWUSR);
|
module_param(prop_chg_detect, bool, S_IRUGO | S_IWUSR);
|
||||||
MODULE_PARM_DESC(prop_chg_detect, "Enable Proprietary charger detection");
|
MODULE_PARM_DESC(prop_chg_detect, "Enable Proprietary charger detection");
|
||||||
|
|
||||||
/**
|
|
||||||
* USB DBM Hardware registers.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define DBM_BASE 0x000F8000
|
|
||||||
#define DBM_EP_CFG(n) (DBM_BASE + (0x00 + 4 * (n)))
|
|
||||||
#define DBM_DATA_FIFO(n) (DBM_BASE + (0x10 + 4 * (n)))
|
|
||||||
#define DBM_DATA_FIFO_SIZE(n) (DBM_BASE + (0x20 + 4 * (n)))
|
|
||||||
#define DBM_DATA_FIFO_EN (DBM_BASE + (0x30))
|
|
||||||
#define DBM_GEVNTADR (DBM_BASE + (0x34))
|
|
||||||
#define DBM_GEVNTSIZ (DBM_BASE + (0x38))
|
|
||||||
#define DBM_DBG_CNFG (DBM_BASE + (0x3C))
|
|
||||||
#define DBM_HW_TRB0_EP(n) (DBM_BASE + (0x40 + 4 * (n)))
|
|
||||||
#define DBM_HW_TRB1_EP(n) (DBM_BASE + (0x50 + 4 * (n)))
|
|
||||||
#define DBM_HW_TRB2_EP(n) (DBM_BASE + (0x60 + 4 * (n)))
|
|
||||||
#define DBM_HW_TRB3_EP(n) (DBM_BASE + (0x70 + 4 * (n)))
|
|
||||||
#define DBM_PIPE_CFG (DBM_BASE + (0x80))
|
|
||||||
#define DBM_SOFT_RESET (DBM_BASE + (0x84))
|
|
||||||
#define DBM_GEN_CFG (DBM_BASE + (0x88))
|
|
||||||
#define DBM_GEVNTADR_LSB (DBM_BASE + (0x98))
|
|
||||||
#define DBM_GEVNTADR_MSB (DBM_BASE + (0x9C))
|
|
||||||
#define DBM_DATA_FIFO_LSB(n) (DBM_BASE + (0xA0 + 8 * (n)))
|
|
||||||
#define DBM_DATA_FIFO_MSB(n) (DBM_BASE + (0xA4 + 8 * (n)))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* USB DBM Hardware registers bitmask.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/* DBM_EP_CFG */
|
|
||||||
#define DBM_EN_EP 0x00000001
|
|
||||||
#define USB3_EPNUM 0x0000003E
|
|
||||||
#define DBM_BAM_PIPE_NUM 0x000000C0
|
|
||||||
#define DBM_PRODUCER 0x00000100
|
|
||||||
#define DBM_DISABLE_WB 0x00000200
|
|
||||||
#define DBM_INT_RAM_ACC 0x00000400
|
|
||||||
|
|
||||||
/* DBM_DATA_FIFO_SIZE */
|
|
||||||
#define DBM_DATA_FIFO_SIZE_MASK 0x0000ffff
|
|
||||||
|
|
||||||
/* DBM_GEVNTSIZ */
|
|
||||||
#define DBM_GEVNTSIZ_MASK 0x0000ffff
|
|
||||||
|
|
||||||
/* DBM_DBG_CNFG */
|
|
||||||
#define DBM_ENABLE_IOC_MASK 0x0000000f
|
|
||||||
|
|
||||||
/* DBM_SOFT_RESET */
|
|
||||||
#define DBM_SFT_RST_EP0 0x00000001
|
|
||||||
#define DBM_SFT_RST_EP1 0x00000002
|
|
||||||
#define DBM_SFT_RST_EP2 0x00000004
|
|
||||||
#define DBM_SFT_RST_EP3 0x00000008
|
|
||||||
#define DBM_SFT_RST_EPS_MASK 0x0000000F
|
|
||||||
#define DBM_SFT_RST_MASK 0x80000000
|
|
||||||
#define DBM_EN_MASK 0x00000002
|
|
||||||
|
|
||||||
#define DBM_MAX_EPS 8
|
|
||||||
|
|
||||||
/* DBM TRB configurations */
|
|
||||||
#define DBM_TRB_BIT 0x80000000
|
|
||||||
#define DBM_TRB_DATA_SRC 0x40000000
|
|
||||||
#define DBM_TRB_DMA 0x20000000
|
|
||||||
#define DBM_TRB_EP_NUM(ep) (ep<<24)
|
|
||||||
|
|
||||||
#define USB3_PORTSC (0x430)
|
#define USB3_PORTSC (0x430)
|
||||||
#define PORT_PE (0x1 << 1)
|
#define PORT_PE (0x1 << 1)
|
||||||
/**
|
/**
|
||||||
|
@ -185,8 +124,6 @@ struct dwc3_msm {
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
struct resource *io_res;
|
struct resource *io_res;
|
||||||
struct platform_device *dwc3;
|
struct platform_device *dwc3;
|
||||||
int dbm_num_eps;
|
|
||||||
u8 ep_num_mapping[DBM_MAX_EPS];
|
|
||||||
const struct usb_ep_ops *original_ep_ops[DWC3_ENDPOINTS_NUM];
|
const struct usb_ep_ops *original_ep_ops[DWC3_ENDPOINTS_NUM];
|
||||||
struct list_head req_complete_list;
|
struct list_head req_complete_list;
|
||||||
struct clk *xo_clk;
|
struct clk *xo_clk;
|
||||||
|
@ -201,6 +138,8 @@ struct dwc3_msm {
|
||||||
|
|
||||||
struct usb_phy *hs_phy, *ss_phy;
|
struct usb_phy *hs_phy, *ss_phy;
|
||||||
|
|
||||||
|
struct dbm *dbm;
|
||||||
|
|
||||||
/* VBUS regulator if no OTG and running in host only mode */
|
/* VBUS regulator if no OTG and running in host only mode */
|
||||||
struct regulator *vbus_otg;
|
struct regulator *vbus_otg;
|
||||||
struct dwc3_ext_xceiv ext_xceiv;
|
struct dwc3_ext_xceiv ext_xceiv;
|
||||||
|
@ -394,207 +333,6 @@ static void dwc3_msm_dump_phy_info(struct dwc3_msm *mdwc)
|
||||||
PWR_EVNT_IRQ_MASK_REG));
|
PWR_EVNT_IRQ_MASK_REG));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return DBM EP number according to usb endpoint number.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static int dwc3_msm_find_matching_dbm_ep(struct dwc3_msm *mdwc, u8 usb_ep)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < mdwc->dbm_num_eps; i++)
|
|
||||||
if (mdwc->ep_num_mapping[i] == usb_ep)
|
|
||||||
return i;
|
|
||||||
|
|
||||||
return -ENODEV; /* Not found */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return number of configured DBM endpoints.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static int dwc3_msm_configured_dbm_ep_num(struct dwc3_msm *mdwc)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < mdwc->dbm_num_eps; i++)
|
|
||||||
if (mdwc->ep_num_mapping[i])
|
|
||||||
count++;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the DBM with the USB3 core event buffer.
|
|
||||||
* This function is called by the SNPS UDC upon initialization.
|
|
||||||
*
|
|
||||||
* @addr - address of the event buffer.
|
|
||||||
* @size - size of the event buffer.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static int dwc3_msm_event_buffer_config(struct dwc3_msm *mdwc,
|
|
||||||
u32 addr_lo, u32 addr_hi, u16 size)
|
|
||||||
{
|
|
||||||
dev_dbg(mdwc->dev, "%s\n", __func__);
|
|
||||||
|
|
||||||
if (sizeof(phys_addr_t) > sizeof(u32)) {
|
|
||||||
dwc3_msm_write_reg(mdwc->base, DBM_GEVNTADR_LSB, addr_lo);
|
|
||||||
dwc3_msm_write_reg(mdwc->base, DBM_GEVNTADR_MSB, addr_hi);
|
|
||||||
} else {
|
|
||||||
dwc3_msm_write_reg(mdwc->base, DBM_GEVNTADR, addr_lo);
|
|
||||||
}
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, DBM_GEVNTSIZ,
|
|
||||||
DBM_GEVNTSIZ_MASK, size);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the DBM registers upon initialization.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static int dwc3_msm_dbm_soft_reset(struct dwc3_msm *mdwc, int enter_reset)
|
|
||||||
{
|
|
||||||
dev_dbg(mdwc->dev, "%s\n", __func__);
|
|
||||||
if (enter_reset) {
|
|
||||||
dev_dbg(mdwc->dev, "enter DBM reset\n");
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
|
|
||||||
DBM_SFT_RST_MASK, 1);
|
|
||||||
} else {
|
|
||||||
dev_dbg(mdwc->dev, "exit DBM reset\n");
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
|
|
||||||
DBM_SFT_RST_MASK, 0);
|
|
||||||
/*enable DBM*/
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, QSCRATCH_GENERAL_CFG,
|
|
||||||
DBM_EN_MASK, 0x1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Soft reset specific DBM ep.
|
|
||||||
* This function is called by the function driver upon events
|
|
||||||
* such as transfer aborting, USB re-enumeration and USB
|
|
||||||
* disconnection.
|
|
||||||
*
|
|
||||||
* @dbm_ep - DBM ep number.
|
|
||||||
* @enter_reset - should we enter a reset state or get out of it.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static int dwc3_msm_dbm_ep_soft_reset(struct dwc3_msm *mdwc,
|
|
||||||
u8 dbm_ep, bool enter_reset)
|
|
||||||
{
|
|
||||||
dev_dbg(mdwc->dev, "%s\n", __func__);
|
|
||||||
|
|
||||||
if (dbm_ep >= mdwc->dbm_num_eps) {
|
|
||||||
dev_err(mdwc->dev, "%s: Invalid DBM ep index\n", __func__);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enter_reset) {
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
|
|
||||||
DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 1);
|
|
||||||
} else {
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
|
|
||||||
DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure a USB DBM ep to work in BAM mode.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @usb_ep - USB physical EP number.
|
|
||||||
* @producer - producer/consumer.
|
|
||||||
* @disable_wb - disable write back to system memory.
|
|
||||||
* @internal_mem - use internal USB memory for data fifo.
|
|
||||||
* @ioc - enable interrupt on completion.
|
|
||||||
*
|
|
||||||
* @return int - DBM ep number.
|
|
||||||
*/
|
|
||||||
static int dwc3_msm_dbm_ep_config(struct dwc3_msm *mdwc, u8 usb_ep, u8 bam_pipe,
|
|
||||||
bool producer, bool disable_wb,
|
|
||||||
bool internal_mem, bool ioc)
|
|
||||||
{
|
|
||||||
int dbm_ep;
|
|
||||||
u32 ep_cfg;
|
|
||||||
|
|
||||||
dev_dbg(mdwc->dev, "%s\n", __func__);
|
|
||||||
|
|
||||||
dbm_ep = dwc3_msm_find_matching_dbm_ep(mdwc, usb_ep);
|
|
||||||
|
|
||||||
if (dbm_ep < 0) {
|
|
||||||
dev_err(mdwc->dev,
|
|
||||||
"%s: Invalid usb ep index\n", __func__);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
/* First, reset the dbm endpoint */
|
|
||||||
dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, 0);
|
|
||||||
|
|
||||||
/* Set ioc bit for dbm_ep if needed */
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, DBM_DBG_CNFG,
|
|
||||||
DBM_ENABLE_IOC_MASK & 1 << dbm_ep, ioc ? 1 : 0);
|
|
||||||
|
|
||||||
ep_cfg = (producer ? DBM_PRODUCER : 0) |
|
|
||||||
(disable_wb ? DBM_DISABLE_WB : 0) |
|
|
||||||
(internal_mem ? DBM_INT_RAM_ACC : 0);
|
|
||||||
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep),
|
|
||||||
DBM_PRODUCER | DBM_DISABLE_WB | DBM_INT_RAM_ACC, ep_cfg >> 8);
|
|
||||||
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep), USB3_EPNUM,
|
|
||||||
usb_ep);
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep),
|
|
||||||
DBM_BAM_PIPE_NUM, bam_pipe);
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, DBM_PIPE_CFG, 0x000000ff,
|
|
||||||
0xe4);
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep), DBM_EN_EP,
|
|
||||||
1);
|
|
||||||
|
|
||||||
return dbm_ep;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure a USB DBM ep to work in normal mode.
|
|
||||||
*
|
|
||||||
* @usb_ep - USB ep number.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static int dwc3_msm_dbm_ep_unconfig(struct dwc3_msm *mdwc, u8 usb_ep)
|
|
||||||
{
|
|
||||||
int dbm_ep;
|
|
||||||
u32 data;
|
|
||||||
|
|
||||||
dev_dbg(mdwc->dev, "%s\n", __func__);
|
|
||||||
|
|
||||||
dbm_ep = dwc3_msm_find_matching_dbm_ep(mdwc, usb_ep);
|
|
||||||
|
|
||||||
if (dbm_ep < 0) {
|
|
||||||
dev_err(mdwc->dev, "%s: Invalid usb ep index\n", __func__);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
mdwc->ep_num_mapping[dbm_ep] = 0;
|
|
||||||
|
|
||||||
data = dwc3_msm_read_reg(mdwc->base, DBM_EP_CFG(dbm_ep));
|
|
||||||
data &= (~0x1);
|
|
||||||
dwc3_msm_write_reg(mdwc->base, DBM_EP_CFG(dbm_ep), data);
|
|
||||||
|
|
||||||
/* Reset the dbm endpoint */
|
|
||||||
dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, true);
|
|
||||||
/*
|
|
||||||
* 10 usec delay is required before deasserting DBM endpoint reset
|
|
||||||
* according to hardware programming guide.
|
|
||||||
*/
|
|
||||||
udelay(10);
|
|
||||||
dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, false);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure the DBM with the BAM's data fifo.
|
* Configure the DBM with the BAM's data fifo.
|
||||||
|
@ -609,31 +347,17 @@ static int dwc3_msm_dbm_ep_unconfig(struct dwc3_msm *mdwc, u8 usb_ep)
|
||||||
int msm_data_fifo_config(struct usb_ep *ep, phys_addr_t addr,
|
int msm_data_fifo_config(struct usb_ep *ep, phys_addr_t addr,
|
||||||
u32 size, u8 dst_pipe_idx)
|
u32 size, u8 dst_pipe_idx)
|
||||||
{
|
{
|
||||||
u8 dbm_ep;
|
|
||||||
struct dwc3_ep *dep = to_dwc3_ep(ep);
|
struct dwc3_ep *dep = to_dwc3_ep(ep);
|
||||||
struct dwc3 *dwc = dep->dwc;
|
struct dwc3 *dwc = dep->dwc;
|
||||||
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
|
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
|
||||||
u8 bam_pipe = dst_pipe_idx;
|
|
||||||
|
|
||||||
dev_dbg(mdwc->dev, "%s\n", __func__);
|
dev_dbg(mdwc->dev, "%s\n", __func__);
|
||||||
|
|
||||||
dbm_ep = bam_pipe;
|
return dbm_data_fifo_config(mdwc->dbm, dep->number, addr, size,
|
||||||
mdwc->ep_num_mapping[dbm_ep] = dep->number;
|
dst_pipe_idx);
|
||||||
|
|
||||||
if (sizeof(addr) > sizeof(u32)) {
|
|
||||||
u32 lo = lower_32_bits(addr);
|
|
||||||
u32 hi = upper_32_bits(addr);
|
|
||||||
dwc3_msm_write_reg(mdwc->base, DBM_DATA_FIFO_LSB(dbm_ep), lo);
|
|
||||||
dwc3_msm_write_reg(mdwc->base, DBM_DATA_FIFO_MSB(dbm_ep), hi);
|
|
||||||
} else {
|
|
||||||
dwc3_msm_write_reg(mdwc->base, DBM_DATA_FIFO(dbm_ep), addr);
|
|
||||||
}
|
|
||||||
dwc3_msm_write_reg_field(mdwc->base, DBM_DATA_FIFO_SIZE(dbm_ep),
|
|
||||||
DBM_DATA_FIFO_SIZE_MASK, size);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleanups for msm endpoint on request complete.
|
* Cleanups for msm endpoint on request complete.
|
||||||
*
|
*
|
||||||
|
@ -642,7 +366,7 @@ int msm_data_fifo_config(struct usb_ep *ep, phys_addr_t addr,
|
||||||
* @usb_ep - pointer to usb_ep instance.
|
* @usb_ep - pointer to usb_ep instance.
|
||||||
* @request - pointer to usb_request instance.
|
* @request - pointer to usb_request instance.
|
||||||
*
|
*
|
||||||
* @return int - 0 on success, negetive on error.
|
* @return int - 0 on success, negative on error.
|
||||||
*/
|
*/
|
||||||
static void dwc3_msm_req_complete_func(struct usb_ep *ep,
|
static void dwc3_msm_req_complete_func(struct usb_ep *ep,
|
||||||
struct usb_request *request)
|
struct usb_request *request)
|
||||||
|
@ -672,14 +396,14 @@ static void dwc3_msm_req_complete_func(struct usb_ep *ep,
|
||||||
dep->busy_slot++;
|
dep->busy_slot++;
|
||||||
|
|
||||||
/* Unconfigure dbm ep */
|
/* Unconfigure dbm ep */
|
||||||
dwc3_msm_dbm_ep_unconfig(mdwc, dep->number);
|
dbm_ep_unconfig(mdwc->dbm, dep->number);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is the last endpoint we unconfigured, than reset also
|
* If this is the last endpoint we unconfigured, than reset also
|
||||||
* the event buffers.
|
* the event buffers.
|
||||||
*/
|
*/
|
||||||
if (0 == dwc3_msm_configured_dbm_ep_num(mdwc))
|
if (0 == dbm_get_num_of_eps_configured(mdwc->dbm))
|
||||||
dwc3_msm_event_buffer_config(mdwc, 0, 0, 0);
|
dbm_event_buffer_config(mdwc->dbm, 0, 0, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call original complete function, notice that dwc->lock is already
|
* Call original complete function, notice that dwc->lock is already
|
||||||
|
@ -699,7 +423,7 @@ static void dwc3_msm_req_complete_func(struct usb_ep *ep,
|
||||||
* @dwc3_ep - pointer to dwc3_ep instance.
|
* @dwc3_ep - pointer to dwc3_ep instance.
|
||||||
* @req - pointer to dwc3_request instance.
|
* @req - pointer to dwc3_request instance.
|
||||||
*
|
*
|
||||||
* @return int - 0 on success, negetive on error.
|
* @return int - 0 on success, negative on error.
|
||||||
*/
|
*/
|
||||||
static int __dwc3_msm_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
static int __dwc3_msm_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
||||||
{
|
{
|
||||||
|
@ -727,7 +451,8 @@ static int __dwc3_msm_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
||||||
req->trb = trb;
|
req->trb = trb;
|
||||||
trb->bph = DBM_TRB_BIT | DBM_TRB_DMA | DBM_TRB_EP_NUM(dep->number);
|
trb->bph = DBM_TRB_BIT | DBM_TRB_DMA | DBM_TRB_EP_NUM(dep->number);
|
||||||
trb->size = DWC3_TRB_SIZE_LENGTH(req->request.length);
|
trb->size = DWC3_TRB_SIZE_LENGTH(req->request.length);
|
||||||
trb->ctrl = DWC3_TRBCTL_NORMAL | DWC3_TRB_CTRL_HWO | DWC3_TRB_CTRL_CHN;
|
trb->ctrl = DWC3_TRBCTL_NORMAL | DWC3_TRB_CTRL_HWO |
|
||||||
|
DWC3_TRB_CTRL_CHN | (req->direction ? 0 : DWC3_TRB_CTRL_CSP);
|
||||||
req->trb_dma = dwc3_trb_dma_offset(dep, trb);
|
req->trb_dma = dwc3_trb_dma_offset(dep, trb);
|
||||||
|
|
||||||
/* Second, prepare a Link TRB that points to the first TRB*/
|
/* Second, prepare a Link TRB that points to the first TRB*/
|
||||||
|
@ -770,7 +495,7 @@ static int __dwc3_msm_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
||||||
* was enabled by the ep_enable.
|
* was enabled by the ep_enable.
|
||||||
*
|
*
|
||||||
* This function prepares special structure of TRBs which
|
* This function prepares special structure of TRBs which
|
||||||
* is familier with the DBM HW, so it will possible to use
|
* is familiar with the DBM HW, so it will possible to use
|
||||||
* this endpoint in DBM mode.
|
* this endpoint in DBM mode.
|
||||||
*
|
*
|
||||||
* The TRBs prepared by this function, is one normal TRB
|
* The TRBs prepared by this function, is one normal TRB
|
||||||
|
@ -784,7 +509,7 @@ static int __dwc3_msm_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
||||||
* @request - pointer to usb_request instance.
|
* @request - pointer to usb_request instance.
|
||||||
* @gfp_flags - possible flags.
|
* @gfp_flags - possible flags.
|
||||||
*
|
*
|
||||||
* @return int - 0 on success, negetive on error.
|
* @return int - 0 on success, negative on error.
|
||||||
*/
|
*/
|
||||||
static int dwc3_msm_ep_queue(struct usb_ep *ep,
|
static int dwc3_msm_ep_queue(struct usb_ep *ep,
|
||||||
struct usb_request *request, gfp_t gfp_flags)
|
struct usb_request *request, gfp_t gfp_flags)
|
||||||
|
@ -862,13 +587,11 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep,
|
||||||
internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
|
internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
|
||||||
ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
|
ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
|
||||||
|
|
||||||
ret = dwc3_msm_dbm_ep_config(mdwc, dep->number,
|
ret = dbm_ep_config(mdwc->dbm, dep->number, bam_pipe, producer,
|
||||||
bam_pipe, producer,
|
disable_wb, internal_mem, ioc);
|
||||||
disable_wb, internal_mem, ioc);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(mdwc->dev,
|
dev_err(mdwc->dev,
|
||||||
"error %d after calling dwc3_msm_dbm_ep_config\n",
|
"error %d after calling dbm_ep_config\n", ret);
|
||||||
ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,7 +615,7 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep,
|
||||||
}
|
}
|
||||||
|
|
||||||
speed = dwc3_readl(dwc->regs, DWC3_DSTS) & DWC3_DSTS_CONNECTSPD;
|
speed = dwc3_readl(dwc->regs, DWC3_DSTS) & DWC3_DSTS_CONNECTSPD;
|
||||||
dwc3_msm_write_reg(mdwc->base, DBM_GEN_CFG, speed >> 2);
|
dbm_set_speed(mdwc->dbm, speed >> 2);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -918,10 +641,6 @@ int msm_ep_config(struct usb_ep *ep)
|
||||||
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
|
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
|
||||||
struct usb_ep_ops *new_ep_ops;
|
struct usb_ep_ops *new_ep_ops;
|
||||||
|
|
||||||
dwc3_msm_event_buffer_config(mdwc,
|
|
||||||
dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRLO(0)),
|
|
||||||
dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRHI(0)),
|
|
||||||
dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTSIZ(0)));
|
|
||||||
|
|
||||||
/* Save original ep ops for future restore*/
|
/* Save original ep ops for future restore*/
|
||||||
if (mdwc->original_ep_ops[dep->number]) {
|
if (mdwc->original_ep_ops[dep->number]) {
|
||||||
|
@ -962,7 +681,7 @@ EXPORT_SYMBOL(msm_ep_config);
|
||||||
*
|
*
|
||||||
* @ep - a pointer to some usb_ep instance
|
* @ep - a pointer to some usb_ep instance
|
||||||
*
|
*
|
||||||
* @return int - 0 on success, negetive on error.
|
* @return int - 0 on success, negative on error.
|
||||||
*/
|
*/
|
||||||
int msm_ep_unconfig(struct usb_ep *ep)
|
int msm_ep_unconfig(struct usb_ep *ep)
|
||||||
{
|
{
|
||||||
|
@ -1285,9 +1004,20 @@ static void dwc3_msm_block_reset(struct dwc3_ext_xceiv *xceiv, bool core_reset)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the DBM */
|
/* Reset the DBM */
|
||||||
dwc3_msm_dbm_soft_reset(mdwc, 1);
|
dbm_soft_reset(mdwc->dbm, 1);
|
||||||
usleep_range(1000, 1200);
|
usleep_range(1000, 1200);
|
||||||
dwc3_msm_dbm_soft_reset(mdwc, 0);
|
dbm_soft_reset(mdwc->dbm, 0);
|
||||||
|
|
||||||
|
|
||||||
|
/*enable DBM*/
|
||||||
|
dwc3_msm_write_reg_field(mdwc->base, QSCRATCH_GENERAL_CFG,
|
||||||
|
DBM_EN_MASK, 0x1);
|
||||||
|
dbm_event_buffer_config(mdwc->dbm,
|
||||||
|
dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRLO(0)),
|
||||||
|
dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRHI(0)),
|
||||||
|
dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTSIZ(0)));
|
||||||
|
dbm_enable(mdwc->dbm);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwc3_block_reset_usb_work(struct work_struct *w)
|
static void dwc3_block_reset_usb_work(struct work_struct *w)
|
||||||
|
@ -2623,21 +2353,16 @@ static int dwc3_msm_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
mdwc->io_res = res; /* used to calculate chg block offset */
|
mdwc->io_res = res; /* used to calculate chg block offset */
|
||||||
|
|
||||||
if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
|
if (of_get_property(pdev->dev.of_node, "qcom,usb-dbm", NULL)) {
|
||||||
&mdwc->dbm_num_eps)) {
|
mdwc->dbm = usb_get_dbm_by_phandle(&pdev->dev, "qcom,usb-dbm",
|
||||||
dev_err(&pdev->dev,
|
0);
|
||||||
"unable to read platform data num of dbm eps\n");
|
if (IS_ERR(mdwc->dbm)) {
|
||||||
mdwc->dbm_num_eps = DBM_MAX_EPS;
|
dev_err(&pdev->dev, "unable to get dbm device\n");
|
||||||
}
|
ret = -EPROBE_DEFER;
|
||||||
|
goto disable_ref_clk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mdwc->dbm_num_eps > DBM_MAX_EPS) {
|
|
||||||
dev_err(&pdev->dev,
|
|
||||||
"Driver doesn't support number of DBM EPs. "
|
|
||||||
"max: %d, dbm_num_eps: %d\n",
|
|
||||||
DBM_MAX_EPS, mdwc->dbm_num_eps);
|
|
||||||
ret = -ENODEV;
|
|
||||||
goto disable_ref_clk;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (of_property_read_u32(node, "qcom,dwc-usb3-msm-tx-fifo-size",
|
if (of_property_read_u32(node, "qcom,dwc-usb3-msm-tx-fifo-size",
|
||||||
&mdwc->tx_fifo_size))
|
&mdwc->tx_fifo_size))
|
||||||
|
|
Loading…
Reference in a new issue