Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
3ec3090c
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
3ec3090c
编写于
2月 14, 2013
作者:
S
Samuel Ortiz
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'usbhost17-for-mfd' of
git://github.com/rogerq/linux
into for-next
Signed-off-by:
N
Samuel Ortiz
<
sameo@linux.intel.com
>
上级
0030f654
ab3f2a86
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
470 addition
and
338 deletion
+470
-338
drivers/mfd/omap-usb-host.c
drivers/mfd/omap-usb-host.c
+332
-226
drivers/mfd/omap-usb-tll.c
drivers/mfd/omap-usb-tll.c
+134
-109
drivers/usb/host/ehci-omap.c
drivers/usb/host/ehci-omap.c
+3
-3
include/linux/platform_data/usb-omap.h
include/linux/platform_data/usb-omap.h
+1
-0
未找到文件。
drivers/mfd/omap-usb-host.c
浏览文件 @
3ec3090c
...
@@ -23,7 +23,6 @@
...
@@ -23,7 +23,6 @@
#include <linux/delay.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
#include <linux/gpio.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/platform_data/usb-omap.h>
#include <linux/platform_data/usb-omap.h>
...
@@ -91,21 +90,23 @@
...
@@ -91,21 +90,23 @@
struct
usbhs_hcd_omap
{
struct
usbhs_hcd_omap
{
int
nports
;
struct
clk
**
utmi_clk
;
struct
clk
**
hsic60m_clk
;
struct
clk
**
hsic480m_clk
;
struct
clk
*
xclk60mhsp1_ck
;
struct
clk
*
xclk60mhsp1_ck
;
struct
clk
*
xclk60mhsp2_ck
;
struct
clk
*
xclk60mhsp2_ck
;
struct
clk
*
utmi_p1_fck
;
struct
clk
*
utmi_p1_gfclk
;
struct
clk
*
usbhost_p1_fck
;
struct
clk
*
utmi_p2_gfclk
;
struct
clk
*
utmi_p2_fck
;
struct
clk
*
usbhost_p2_fck
;
struct
clk
*
init_60m_fclk
;
struct
clk
*
init_60m_fclk
;
struct
clk
*
ehci_logic_fck
;
struct
clk
*
ehci_logic_fck
;
void
__iomem
*
uhh_base
;
void
__iomem
*
uhh_base
;
struct
usbhs_omap_platform_data
plat
data
;
struct
usbhs_omap_platform_data
*
p
data
;
u32
usbhs_rev
;
u32
usbhs_rev
;
spinlock_t
lock
;
};
};
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
...
@@ -184,19 +185,13 @@ static struct platform_device *omap_usbhs_alloc_child(const char *name,
...
@@ -184,19 +185,13 @@ static struct platform_device *omap_usbhs_alloc_child(const char *name,
static
int
omap_usbhs_alloc_children
(
struct
platform_device
*
pdev
)
static
int
omap_usbhs_alloc_children
(
struct
platform_device
*
pdev
)
{
{
struct
device
*
dev
=
&
pdev
->
dev
;
struct
device
*
dev
=
&
pdev
->
dev
;
struct
usbhs_hcd_omap
*
omap
;
struct
usbhs_omap_platform_data
*
pdata
=
dev
->
platform_data
;
struct
ehci_hcd_omap_platform_data
*
ehci_data
;
struct
ohci_hcd_omap_platform_data
*
ohci_data
;
struct
platform_device
*
ehci
;
struct
platform_device
*
ehci
;
struct
platform_device
*
ohci
;
struct
platform_device
*
ohci
;
struct
resource
*
res
;
struct
resource
*
res
;
struct
resource
resources
[
2
];
struct
resource
resources
[
2
];
int
ret
;
int
ret
;
omap
=
platform_get_drvdata
(
pdev
);
ehci_data
=
omap
->
platdata
.
ehci_data
;
ohci_data
=
omap
->
platdata
.
ohci_data
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"ehci"
);
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"ehci"
);
if
(
!
res
)
{
if
(
!
res
)
{
dev_err
(
dev
,
"EHCI get resource IORESOURCE_MEM failed
\n
"
);
dev_err
(
dev
,
"EHCI get resource IORESOURCE_MEM failed
\n
"
);
...
@@ -213,8 +208,8 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
...
@@ -213,8 +208,8 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
}
}
resources
[
1
]
=
*
res
;
resources
[
1
]
=
*
res
;
ehci
=
omap_usbhs_alloc_child
(
OMAP_EHCI_DEVICE
,
resources
,
2
,
ehci_
data
,
ehci
=
omap_usbhs_alloc_child
(
OMAP_EHCI_DEVICE
,
resources
,
2
,
p
data
,
sizeof
(
*
ehci_
data
),
dev
);
sizeof
(
*
p
data
),
dev
);
if
(
!
ehci
)
{
if
(
!
ehci
)
{
dev_err
(
dev
,
"omap_usbhs_alloc_child failed
\n
"
);
dev_err
(
dev
,
"omap_usbhs_alloc_child failed
\n
"
);
...
@@ -238,8 +233,8 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
...
@@ -238,8 +233,8 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
}
}
resources
[
1
]
=
*
res
;
resources
[
1
]
=
*
res
;
ohci
=
omap_usbhs_alloc_child
(
OMAP_OHCI_DEVICE
,
resources
,
2
,
ohci_
data
,
ohci
=
omap_usbhs_alloc_child
(
OMAP_OHCI_DEVICE
,
resources
,
2
,
p
data
,
sizeof
(
*
ohci_
data
),
dev
);
sizeof
(
*
p
data
),
dev
);
if
(
!
ohci
)
{
if
(
!
ohci
)
{
dev_err
(
dev
,
"omap_usbhs_alloc_child failed
\n
"
);
dev_err
(
dev
,
"omap_usbhs_alloc_child failed
\n
"
);
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
...
@@ -278,31 +273,52 @@ static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
...
@@ -278,31 +273,52 @@ static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
static
int
usbhs_runtime_resume
(
struct
device
*
dev
)
static
int
usbhs_runtime_resume
(
struct
device
*
dev
)
{
{
struct
usbhs_hcd_omap
*
omap
=
dev_get_drvdata
(
dev
);
struct
usbhs_hcd_omap
*
omap
=
dev_get_drvdata
(
dev
);
struct
usbhs_omap_platform_data
*
pdata
=
&
omap
->
plat
data
;
struct
usbhs_omap_platform_data
*
pdata
=
omap
->
p
data
;
unsigned
long
flags
;
int
i
,
r
;
dev_dbg
(
dev
,
"usbhs_runtime_resume
\n
"
);
dev_dbg
(
dev
,
"usbhs_runtime_resume
\n
"
);
if
(
!
pdata
)
{
dev_dbg
(
dev
,
"missing platform_data
\n
"
);
return
-
ENODEV
;
}
omap_tll_enable
();
omap_tll_enable
();
spin_lock_irqsave
(
&
omap
->
lock
,
flags
);
if
(
omap
->
ehci_logic_fck
&&
!
IS_ERR
(
omap
->
ehci_logic_fck
))
if
(
!
IS_ERR
(
omap
->
ehci_logic_fck
))
clk_enable
(
omap
->
ehci_logic_fck
);
clk_enable
(
omap
->
ehci_logic_fck
);
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
0
]))
for
(
i
=
0
;
i
<
omap
->
nports
;
i
++
)
{
clk_enable
(
omap
->
usbhost_p1_fck
);
switch
(
pdata
->
port_mode
[
i
])
{
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
1
]))
case
OMAP_EHCI_PORT_MODE_HSIC
:
clk_enable
(
omap
->
usbhost_p2_fck
);
if
(
!
IS_ERR
(
omap
->
hsic60m_clk
[
i
]))
{
r
=
clk_enable
(
omap
->
hsic60m_clk
[
i
]);
if
(
r
)
{
dev_err
(
dev
,
"Can't enable port %d hsic60m clk:%d
\n
"
,
i
,
r
);
}
}
clk_enable
(
omap
->
utmi_p1_fck
);
if
(
!
IS_ERR
(
omap
->
hsic480m_clk
[
i
]))
{
clk_enable
(
omap
->
utmi_p2_fck
);
r
=
clk_enable
(
omap
->
hsic480m_clk
[
i
]);
if
(
r
)
{
dev_err
(
dev
,
"Can't enable port %d hsic480m clk:%d
\n
"
,
i
,
r
);
}
}
/* Fall through as HSIC mode needs utmi_clk */
spin_unlock_irqrestore
(
&
omap
->
lock
,
flags
);
case
OMAP_EHCI_PORT_MODE_TLL
:
if
(
!
IS_ERR
(
omap
->
utmi_clk
[
i
]))
{
r
=
clk_enable
(
omap
->
utmi_clk
[
i
]);
if
(
r
)
{
dev_err
(
dev
,
"Can't enable port %d clk : %d
\n
"
,
i
,
r
);
}
}
break
;
default:
break
;
}
}
return
0
;
return
0
;
}
}
...
@@ -310,51 +326,122 @@ static int usbhs_runtime_resume(struct device *dev)
...
@@ -310,51 +326,122 @@ static int usbhs_runtime_resume(struct device *dev)
static
int
usbhs_runtime_suspend
(
struct
device
*
dev
)
static
int
usbhs_runtime_suspend
(
struct
device
*
dev
)
{
{
struct
usbhs_hcd_omap
*
omap
=
dev_get_drvdata
(
dev
);
struct
usbhs_hcd_omap
*
omap
=
dev_get_drvdata
(
dev
);
struct
usbhs_omap_platform_data
*
pdata
=
&
omap
->
plat
data
;
struct
usbhs_omap_platform_data
*
pdata
=
omap
->
p
data
;
unsigned
long
flags
;
int
i
;
dev_dbg
(
dev
,
"usbhs_runtime_suspend
\n
"
);
dev_dbg
(
dev
,
"usbhs_runtime_suspend
\n
"
);
if
(
!
pdata
)
{
for
(
i
=
0
;
i
<
omap
->
nports
;
i
++
)
{
dev_dbg
(
dev
,
"missing platform_data
\n
"
);
switch
(
pdata
->
port_mode
[
i
])
{
return
-
ENODEV
;
case
OMAP_EHCI_PORT_MODE_HSIC
:
}
if
(
!
IS_ERR
(
omap
->
hsic60m_clk
[
i
]))
clk_disable
(
omap
->
hsic60m_clk
[
i
]);
spin_lock_irqsave
(
&
omap
->
lock
,
flags
);
if
(
!
IS_ERR
(
omap
->
hsic480m_clk
[
i
]))
clk_disable
(
omap
->
hsic480m_clk
[
i
]);
/* Fall through as utmi_clks were used in HSIC mode */
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
0
]))
case
OMAP_EHCI_PORT_MODE_TLL
:
clk_disable
(
omap
->
usbhost_p1_fck
);
if
(
!
IS_ERR
(
omap
->
utmi_clk
[
i
]))
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
1
]))
clk_disable
(
omap
->
utmi_clk
[
i
]);
clk_disable
(
omap
->
usbhost_p2_fck
);
break
;
default:
clk_disable
(
omap
->
utmi_p2_fck
);
break
;
clk_disable
(
omap
->
utmi_p1_fck
);
}
}
if
(
omap
->
ehci_logic_fck
&&
!
IS_ERR
(
omap
->
ehci_logic_fck
))
if
(
!
IS_ERR
(
omap
->
ehci_logic_fck
))
clk_disable
(
omap
->
ehci_logic_fck
);
clk_disable
(
omap
->
ehci_logic_fck
);
spin_unlock_irqrestore
(
&
omap
->
lock
,
flags
);
omap_tll_disable
();
omap_tll_disable
();
return
0
;
return
0
;
}
}
static
unsigned
omap_usbhs_rev1_hostconfig
(
struct
usbhs_hcd_omap
*
omap
,
unsigned
reg
)
{
struct
usbhs_omap_platform_data
*
pdata
=
omap
->
pdata
;
int
i
;
for
(
i
=
0
;
i
<
omap
->
nports
;
i
++
)
{
switch
(
pdata
->
port_mode
[
i
])
{
case
OMAP_USBHS_PORT_MODE_UNUSED
:
reg
&=
~
(
OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS
<<
i
);
break
;
case
OMAP_EHCI_PORT_MODE_PHY
:
if
(
pdata
->
single_ulpi_bypass
)
break
;
if
(
i
==
0
)
reg
&=
~
OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS
;
else
reg
&=
~
(
OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS
<<
(
i
-
1
));
break
;
default:
if
(
pdata
->
single_ulpi_bypass
)
break
;
if
(
i
==
0
)
reg
|=
OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS
;
else
reg
|=
OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS
<<
(
i
-
1
);
break
;
}
}
if
(
pdata
->
single_ulpi_bypass
)
{
/* bypass ULPI only if none of the ports use PHY mode */
reg
|=
OMAP_UHH_HOSTCONFIG_ULPI_BYPASS
;
for
(
i
=
0
;
i
<
omap
->
nports
;
i
++
)
{
if
(
is_ehci_phy_mode
(
pdata
->
port_mode
[
i
]))
{
reg
&=
OMAP_UHH_HOSTCONFIG_ULPI_BYPASS
;
break
;
}
}
}
return
reg
;
}
static
unsigned
omap_usbhs_rev2_hostconfig
(
struct
usbhs_hcd_omap
*
omap
,
unsigned
reg
)
{
struct
usbhs_omap_platform_data
*
pdata
=
omap
->
pdata
;
int
i
;
for
(
i
=
0
;
i
<
omap
->
nports
;
i
++
)
{
/* Clear port mode fields for PHY mode */
reg
&=
~
(
OMAP4_P1_MODE_CLEAR
<<
2
*
i
);
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
i
])
||
(
is_ohci_port
(
pdata
->
port_mode
[
i
])))
reg
|=
OMAP4_P1_MODE_TLL
<<
2
*
i
;
else
if
(
is_ehci_hsic_mode
(
pdata
->
port_mode
[
i
]))
reg
|=
OMAP4_P1_MODE_HSIC
<<
2
*
i
;
}
return
reg
;
}
static
void
omap_usbhs_init
(
struct
device
*
dev
)
static
void
omap_usbhs_init
(
struct
device
*
dev
)
{
{
struct
usbhs_hcd_omap
*
omap
=
dev_get_drvdata
(
dev
);
struct
usbhs_hcd_omap
*
omap
=
dev_get_drvdata
(
dev
);
struct
usbhs_omap_platform_data
*
pdata
=
&
omap
->
platdata
;
struct
usbhs_omap_platform_data
*
pdata
=
omap
->
pdata
;
unsigned
long
flags
;
unsigned
reg
;
unsigned
reg
;
dev_dbg
(
dev
,
"starting TI HSUSB Controller
\n
"
);
dev_dbg
(
dev
,
"starting TI HSUSB Controller
\n
"
);
if
(
pdata
->
ehci_data
->
phy_reset
)
{
if
(
pdata
->
phy_reset
)
{
if
(
gpio_is_valid
(
pdata
->
ehci_data
->
reset_gpio_port
[
0
]))
if
(
gpio_is_valid
(
pdata
->
reset_gpio_port
[
0
]))
gpio_request_one
(
pdata
->
ehci_data
->
reset_gpio_port
[
0
],
gpio_request_one
(
pdata
->
reset_gpio_port
[
0
],
GPIOF_OUT_INIT_LOW
,
"USB1 PHY reset"
);
GPIOF_OUT_INIT_LOW
,
"USB1 PHY reset"
);
if
(
gpio_is_valid
(
pdata
->
ehci_data
->
reset_gpio_port
[
1
]))
if
(
gpio_is_valid
(
pdata
->
reset_gpio_port
[
1
]))
gpio_request_one
(
pdata
->
ehci_data
->
reset_gpio_port
[
1
],
gpio_request_one
(
pdata
->
reset_gpio_port
[
1
],
GPIOF_OUT_INIT_LOW
,
"USB2 PHY reset"
);
GPIOF_OUT_INIT_LOW
,
"USB2 PHY reset"
);
/* Hold the PHY in RESET for enough time till DIR is high */
/* Hold the PHY in RESET for enough time till DIR is high */
...
@@ -362,9 +449,6 @@ static void omap_usbhs_init(struct device *dev)
...
@@ -362,9 +449,6 @@ static void omap_usbhs_init(struct device *dev)
}
}
pm_runtime_get_sync
(
dev
);
pm_runtime_get_sync
(
dev
);
spin_lock_irqsave
(
&
omap
->
lock
,
flags
);
omap
->
usbhs_rev
=
usbhs_read
(
omap
->
uhh_base
,
OMAP_UHH_REVISION
);
dev_dbg
(
dev
,
"OMAP UHH_REVISION 0x%x
\n
"
,
omap
->
usbhs_rev
);
reg
=
usbhs_read
(
omap
->
uhh_base
,
OMAP_UHH_HOSTCONFIG
);
reg
=
usbhs_read
(
omap
->
uhh_base
,
OMAP_UHH_HOSTCONFIG
);
/* setup ULPI bypass and burst configurations */
/* setup ULPI bypass and burst configurations */
...
@@ -374,89 +458,51 @@ static void omap_usbhs_init(struct device *dev)
...
@@ -374,89 +458,51 @@ static void omap_usbhs_init(struct device *dev)
reg
|=
OMAP4_UHH_HOSTCONFIG_APP_START_CLK
;
reg
|=
OMAP4_UHH_HOSTCONFIG_APP_START_CLK
;
reg
&=
~
OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN
;
reg
&=
~
OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN
;
if
(
is_omap_usbhs_rev1
(
omap
))
{
switch
(
omap
->
usbhs_rev
)
{
if
(
pdata
->
port_mode
[
0
]
==
OMAP_USBHS_PORT_MODE_UNUSED
)
case
OMAP_USBHS_REV1
:
reg
&=
~
OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS
;
omap_usbhs_rev1_hostconfig
(
omap
,
reg
);
if
(
pdata
->
port_mode
[
1
]
==
OMAP_USBHS_PORT_MODE_UNUSED
)
break
;
reg
&=
~
OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS
;
if
(
pdata
->
port_mode
[
2
]
==
OMAP_USBHS_PORT_MODE_UNUSED
)
reg
&=
~
OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS
;
/* Bypass the TLL module for PHY mode operation */
if
(
pdata
->
single_ulpi_bypass
)
{
dev_dbg
(
dev
,
"OMAP3 ES version <= ES2.1
\n
"
);
if
(
is_ehci_phy_mode
(
pdata
->
port_mode
[
0
])
||
is_ehci_phy_mode
(
pdata
->
port_mode
[
1
])
||
is_ehci_phy_mode
(
pdata
->
port_mode
[
2
]))
reg
&=
~
OMAP_UHH_HOSTCONFIG_ULPI_BYPASS
;
else
reg
|=
OMAP_UHH_HOSTCONFIG_ULPI_BYPASS
;
}
else
{
dev_dbg
(
dev
,
"OMAP3 ES version > ES2.1
\n
"
);
if
(
is_ehci_phy_mode
(
pdata
->
port_mode
[
0
]))
reg
&=
~
OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS
;
else
reg
|=
OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS
;
if
(
is_ehci_phy_mode
(
pdata
->
port_mode
[
1
]))
reg
&=
~
OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS
;
else
reg
|=
OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS
;
if
(
is_ehci_phy_mode
(
pdata
->
port_mode
[
2
]))
reg
&=
~
OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS
;
else
reg
|=
OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS
;
}
}
else
if
(
is_omap_usbhs_rev2
(
omap
))
{
/* Clear port mode fields for PHY mode*/
reg
&=
~
OMAP4_P1_MODE_CLEAR
;
reg
&=
~
OMAP4_P2_MODE_CLEAR
;
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
0
])
||
case
OMAP_USBHS_REV2
:
(
is_ohci_port
(
pdata
->
port_mode
[
0
])))
omap_usbhs_rev2_hostconfig
(
omap
,
reg
);
reg
|=
OMAP4_P1_MODE_TLL
;
break
;
else
if
(
is_ehci_hsic_mode
(
pdata
->
port_mode
[
0
]))
reg
|=
OMAP4_P1_MODE_HSIC
;
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
1
])
||
default:
/* newer revisions */
(
is_ohci_port
(
pdata
->
port_mode
[
1
])))
omap_usbhs_rev2_hostconfig
(
omap
,
reg
);
reg
|=
OMAP4_P2_MODE_TLL
;
break
;
else
if
(
is_ehci_hsic_mode
(
pdata
->
port_mode
[
1
]))
reg
|=
OMAP4_P2_MODE_HSIC
;
}
}
usbhs_write
(
omap
->
uhh_base
,
OMAP_UHH_HOSTCONFIG
,
reg
);
usbhs_write
(
omap
->
uhh_base
,
OMAP_UHH_HOSTCONFIG
,
reg
);
dev_dbg
(
dev
,
"UHH setup done, uhh_hostconfig=%x
\n
"
,
reg
);
dev_dbg
(
dev
,
"UHH setup done, uhh_hostconfig=%x
\n
"
,
reg
);
spin_unlock_irqrestore
(
&
omap
->
lock
,
flags
);
pm_runtime_put_sync
(
dev
);
pm_runtime_put_sync
(
dev
);
if
(
pdata
->
ehci_data
->
phy_reset
)
{
if
(
pdata
->
phy_reset
)
{
/* Hold the PHY in RESET for enough time till
/* Hold the PHY in RESET for enough time till
* PHY is settled and ready
* PHY is settled and ready
*/
*/
udelay
(
10
);
udelay
(
10
);
if
(
gpio_is_valid
(
pdata
->
ehci_data
->
reset_gpio_port
[
0
]))
if
(
gpio_is_valid
(
pdata
->
reset_gpio_port
[
0
]))
gpio_set_value_cansleep
gpio_set_value_cansleep
(
pdata
->
ehci_data
->
reset_gpio_port
[
0
],
1
);
(
pdata
->
reset_gpio_port
[
0
],
1
);
if
(
gpio_is_valid
(
pdata
->
ehci_data
->
reset_gpio_port
[
1
]))
if
(
gpio_is_valid
(
pdata
->
reset_gpio_port
[
1
]))
gpio_set_value_cansleep
gpio_set_value_cansleep
(
pdata
->
ehci_data
->
reset_gpio_port
[
1
],
1
);
(
pdata
->
reset_gpio_port
[
1
],
1
);
}
}
}
}
static
void
omap_usbhs_deinit
(
struct
device
*
dev
)
static
void
omap_usbhs_deinit
(
struct
device
*
dev
)
{
{
struct
usbhs_hcd_omap
*
omap
=
dev_get_drvdata
(
dev
);
struct
usbhs_hcd_omap
*
omap
=
dev_get_drvdata
(
dev
);
struct
usbhs_omap_platform_data
*
pdata
=
&
omap
->
plat
data
;
struct
usbhs_omap_platform_data
*
pdata
=
omap
->
p
data
;
if
(
pdata
->
ehci_data
->
phy_reset
)
{
if
(
pdata
->
phy_reset
)
{
if
(
gpio_is_valid
(
pdata
->
ehci_data
->
reset_gpio_port
[
0
]))
if
(
gpio_is_valid
(
pdata
->
reset_gpio_port
[
0
]))
gpio_free
(
pdata
->
ehci_data
->
reset_gpio_port
[
0
]);
gpio_free
(
pdata
->
reset_gpio_port
[
0
]);
if
(
gpio_is_valid
(
pdata
->
ehci_data
->
reset_gpio_port
[
1
]))
if
(
gpio_is_valid
(
pdata
->
reset_gpio_port
[
1
]))
gpio_free
(
pdata
->
ehci_data
->
reset_gpio_port
[
1
]);
gpio_free
(
pdata
->
reset_gpio_port
[
1
]);
}
}
}
}
...
@@ -474,137 +520,185 @@ static int usbhs_omap_probe(struct platform_device *pdev)
...
@@ -474,137 +520,185 @@ static int usbhs_omap_probe(struct platform_device *pdev)
struct
resource
*
res
;
struct
resource
*
res
;
int
ret
=
0
;
int
ret
=
0
;
int
i
;
int
i
;
bool
need_logic_fck
;
if
(
!
pdata
)
{
if
(
!
pdata
)
{
dev_err
(
dev
,
"Missing platform data
\n
"
);
dev_err
(
dev
,
"Missing platform data
\n
"
);
ret
=
-
ENOMEM
;
return
-
ENODEV
;
goto
end_probe
;
}
}
omap
=
kzalloc
(
sizeof
(
*
omap
),
GFP_KERNEL
);
omap
=
devm_kzalloc
(
dev
,
sizeof
(
*
omap
),
GFP_KERNEL
);
if
(
!
omap
)
{
if
(
!
omap
)
{
dev_err
(
dev
,
"Memory allocation failed
\n
"
);
dev_err
(
dev
,
"Memory allocation failed
\n
"
);
ret
=
-
ENOMEM
;
return
-
ENOMEM
;
goto
end_probe
;
}
}
spin_lock_init
(
&
omap
->
lock
);
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"uhh"
);
omap
->
uhh_base
=
devm_request_and_ioremap
(
dev
,
res
);
for
(
i
=
0
;
i
<
OMAP3_HS_USB_PORTS
;
i
++
)
if
(
!
omap
->
uhh_base
)
{
omap
->
platdata
.
port_mode
[
i
]
=
pdata
->
port_mode
[
i
];
dev_err
(
dev
,
"Resource request/ioremap failed
\n
"
);
return
-
EADDRNOTAVAIL
;
}
omap
->
platdata
.
ehci_data
=
pdata
->
ehci_data
;
omap
->
pdata
=
pdata
;
omap
->
platdata
.
ohci_data
=
pdata
->
ohci_data
;
pm_runtime_enable
(
dev
);
pm_runtime_enable
(
dev
);
platform_set_drvdata
(
pdev
,
omap
);
pm_runtime_get_sync
(
dev
);
omap
->
usbhs_rev
=
usbhs_read
(
omap
->
uhh_base
,
OMAP_UHH_REVISION
);
/* we need to call runtime suspend before we update omap->nports
* to prevent unbalanced clk_disable()
*/
pm_runtime_put_sync
(
dev
);
/*
* If platform data contains nports then use that
* else make out number of ports from USBHS revision
*/
if
(
pdata
->
nports
)
{
omap
->
nports
=
pdata
->
nports
;
}
else
{
switch
(
omap
->
usbhs_rev
)
{
case
OMAP_USBHS_REV1
:
omap
->
nports
=
3
;
break
;
case
OMAP_USBHS_REV2
:
omap
->
nports
=
2
;
break
;
default:
omap
->
nports
=
OMAP3_HS_USB_PORTS
;
dev_dbg
(
dev
,
"USB HOST Rev:0x%d not recognized, assuming %d ports
\n
"
,
omap
->
usbhs_rev
,
omap
->
nports
);
break
;
}
}
i
=
sizeof
(
struct
clk
*
)
*
omap
->
nports
;
omap
->
utmi_clk
=
devm_kzalloc
(
dev
,
i
,
GFP_KERNEL
);
omap
->
hsic480m_clk
=
devm_kzalloc
(
dev
,
i
,
GFP_KERNEL
);
omap
->
hsic60m_clk
=
devm_kzalloc
(
dev
,
i
,
GFP_KERNEL
);
for
(
i
=
0
;
i
<
OMAP3_HS_USB_PORTS
;
i
++
)
if
(
!
omap
->
utmi_clk
||
!
omap
->
hsic480m_clk
||
!
omap
->
hsic60m_clk
)
{
dev_err
(
dev
,
"Memory allocation failed
\n
"
);
ret
=
-
ENOMEM
;
goto
err_mem
;
}
need_logic_fck
=
false
;
for
(
i
=
0
;
i
<
omap
->
nports
;
i
++
)
{
if
(
is_ehci_phy_mode
(
i
)
||
is_ehci_tll_mode
(
i
)
||
if
(
is_ehci_phy_mode
(
i
)
||
is_ehci_tll_mode
(
i
)
||
is_ehci_hsic_mode
(
i
))
{
is_ehci_hsic_mode
(
i
))
need_logic_fck
|=
true
;
}
omap
->
ehci_logic_fck
=
ERR_PTR
(
-
EINVAL
);
if
(
need_logic_fck
)
{
omap
->
ehci_logic_fck
=
clk_get
(
dev
,
"ehci_logic_fck"
);
omap
->
ehci_logic_fck
=
clk_get
(
dev
,
"ehci_logic_fck"
);
if
(
IS_ERR
(
omap
->
ehci_logic_fck
))
{
if
(
IS_ERR
(
omap
->
ehci_logic_fck
))
{
ret
=
PTR_ERR
(
omap
->
ehci_logic_fck
);
ret
=
PTR_ERR
(
omap
->
ehci_logic_fck
);
dev_warn
(
dev
,
"ehci_logic_fck failed:%d
\n
"
,
dev_dbg
(
dev
,
"ehci_logic_fck failed:%d
\n
"
,
ret
);
ret
);
}
}
break
;
}
}
omap
->
utmi_p1_
fc
k
=
clk_get
(
dev
,
"utmi_p1_gfclk"
);
omap
->
utmi_p1_
gfcl
k
=
clk_get
(
dev
,
"utmi_p1_gfclk"
);
if
(
IS_ERR
(
omap
->
utmi_p1_
fc
k
))
{
if
(
IS_ERR
(
omap
->
utmi_p1_
gfcl
k
))
{
ret
=
PTR_ERR
(
omap
->
utmi_p1_
fc
k
);
ret
=
PTR_ERR
(
omap
->
utmi_p1_
gfcl
k
);
dev_err
(
dev
,
"utmi_p1_gfclk failed error:%d
\n
"
,
ret
);
dev_err
(
dev
,
"utmi_p1_gfclk failed error:%d
\n
"
,
ret
);
goto
err_end
;
goto
err_p1_gfclk
;
}
omap
->
utmi_p2_gfclk
=
clk_get
(
dev
,
"utmi_p2_gfclk"
);
if
(
IS_ERR
(
omap
->
utmi_p2_gfclk
))
{
ret
=
PTR_ERR
(
omap
->
utmi_p2_gfclk
);
dev_err
(
dev
,
"utmi_p2_gfclk failed error:%d
\n
"
,
ret
);
goto
err_p2_gfclk
;
}
}
omap
->
xclk60mhsp1_ck
=
clk_get
(
dev
,
"xclk60mhsp1_ck"
);
omap
->
xclk60mhsp1_ck
=
clk_get
(
dev
,
"xclk60mhsp1_ck"
);
if
(
IS_ERR
(
omap
->
xclk60mhsp1_ck
))
{
if
(
IS_ERR
(
omap
->
xclk60mhsp1_ck
))
{
ret
=
PTR_ERR
(
omap
->
xclk60mhsp1_ck
);
ret
=
PTR_ERR
(
omap
->
xclk60mhsp1_ck
);
dev_err
(
dev
,
"xclk60mhsp1_ck failed error:%d
\n
"
,
ret
);
dev_err
(
dev
,
"xclk60mhsp1_ck failed error:%d
\n
"
,
ret
);
goto
err_utmi_p1_fck
;
goto
err_xclk60mhsp1
;
}
omap
->
utmi_p2_fck
=
clk_get
(
dev
,
"utmi_p2_gfclk"
);
if
(
IS_ERR
(
omap
->
utmi_p2_fck
))
{
ret
=
PTR_ERR
(
omap
->
utmi_p2_fck
);
dev_err
(
dev
,
"utmi_p2_gfclk failed error:%d
\n
"
,
ret
);
goto
err_xclk60mhsp1_ck
;
}
}
omap
->
xclk60mhsp2_ck
=
clk_get
(
dev
,
"xclk60mhsp2_ck"
);
omap
->
xclk60mhsp2_ck
=
clk_get
(
dev
,
"xclk60mhsp2_ck"
);
if
(
IS_ERR
(
omap
->
xclk60mhsp2_ck
))
{
if
(
IS_ERR
(
omap
->
xclk60mhsp2_ck
))
{
ret
=
PTR_ERR
(
omap
->
xclk60mhsp2_ck
);
ret
=
PTR_ERR
(
omap
->
xclk60mhsp2_ck
);
dev_err
(
dev
,
"xclk60mhsp2_ck failed error:%d
\n
"
,
ret
);
dev_err
(
dev
,
"xclk60mhsp2_ck failed error:%d
\n
"
,
ret
);
goto
err_utmi_p2_fck
;
goto
err_xclk60mhsp2
;
}
omap
->
usbhost_p1_fck
=
clk_get
(
dev
,
"usb_host_hs_utmi_p1_clk"
);
if
(
IS_ERR
(
omap
->
usbhost_p1_fck
))
{
ret
=
PTR_ERR
(
omap
->
usbhost_p1_fck
);
dev_err
(
dev
,
"usbhost_p1_fck failed error:%d
\n
"
,
ret
);
goto
err_xclk60mhsp2_ck
;
}
omap
->
usbhost_p2_fck
=
clk_get
(
dev
,
"usb_host_hs_utmi_p2_clk"
);
if
(
IS_ERR
(
omap
->
usbhost_p2_fck
))
{
ret
=
PTR_ERR
(
omap
->
usbhost_p2_fck
);
dev_err
(
dev
,
"usbhost_p2_fck failed error:%d
\n
"
,
ret
);
goto
err_usbhost_p1_fck
;
}
}
omap
->
init_60m_fclk
=
clk_get
(
dev
,
"init_60m_fclk"
);
omap
->
init_60m_fclk
=
clk_get
(
dev
,
"init_60m_fclk"
);
if
(
IS_ERR
(
omap
->
init_60m_fclk
))
{
if
(
IS_ERR
(
omap
->
init_60m_fclk
))
{
ret
=
PTR_ERR
(
omap
->
init_60m_fclk
);
ret
=
PTR_ERR
(
omap
->
init_60m_fclk
);
dev_err
(
dev
,
"init_60m_fclk failed error:%d
\n
"
,
ret
);
dev_err
(
dev
,
"init_60m_fclk failed error:%d
\n
"
,
ret
);
goto
err_usbhost_p2_fck
;
goto
err_init60m
;
}
for
(
i
=
0
;
i
<
omap
->
nports
;
i
++
)
{
char
clkname
[
30
];
/* clock names are indexed from 1*/
snprintf
(
clkname
,
sizeof
(
clkname
),
"usb_host_hs_utmi_p%d_clk"
,
i
+
1
);
/* If a clock is not found we won't bail out as not all
* platforms have all clocks and we can function without
* them
*/
omap
->
utmi_clk
[
i
]
=
clk_get
(
dev
,
clkname
);
if
(
IS_ERR
(
omap
->
utmi_clk
[
i
]))
dev_dbg
(
dev
,
"Failed to get clock : %s : %ld
\n
"
,
clkname
,
PTR_ERR
(
omap
->
utmi_clk
[
i
]));
snprintf
(
clkname
,
sizeof
(
clkname
),
"usb_host_hs_hsic480m_p%d_clk"
,
i
+
1
);
omap
->
hsic480m_clk
[
i
]
=
clk_get
(
dev
,
clkname
);
if
(
IS_ERR
(
omap
->
hsic480m_clk
[
i
]))
dev_dbg
(
dev
,
"Failed to get clock : %s : %ld
\n
"
,
clkname
,
PTR_ERR
(
omap
->
hsic480m_clk
[
i
]));
snprintf
(
clkname
,
sizeof
(
clkname
),
"usb_host_hs_hsic60m_p%d_clk"
,
i
+
1
);
omap
->
hsic60m_clk
[
i
]
=
clk_get
(
dev
,
clkname
);
if
(
IS_ERR
(
omap
->
hsic60m_clk
[
i
]))
dev_dbg
(
dev
,
"Failed to get clock : %s : %ld
\n
"
,
clkname
,
PTR_ERR
(
omap
->
hsic60m_clk
[
i
]));
}
}
if
(
is_ehci_phy_mode
(
pdata
->
port_mode
[
0
]))
{
if
(
is_ehci_phy_mode
(
pdata
->
port_mode
[
0
]))
{
/* for OMAP3
, the clk set paretn
fails */
/* for OMAP3
, clk_set_parent
fails */
ret
=
clk_set_parent
(
omap
->
utmi_p1_
fc
k
,
ret
=
clk_set_parent
(
omap
->
utmi_p1_
gfcl
k
,
omap
->
xclk60mhsp1_ck
);
omap
->
xclk60mhsp1_ck
);
if
(
ret
!=
0
)
if
(
ret
!=
0
)
dev_
err
(
dev
,
"xclk60mhsp1_ck set parent"
dev_
dbg
(
dev
,
"xclk60mhsp1_ck set parent failed: %d
\n
"
,
"failed error:%d
\n
"
,
ret
);
ret
);
}
else
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
0
]))
{
}
else
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
0
]))
{
ret
=
clk_set_parent
(
omap
->
utmi_p1_
fc
k
,
ret
=
clk_set_parent
(
omap
->
utmi_p1_
gfcl
k
,
omap
->
init_60m_fclk
);
omap
->
init_60m_fclk
);
if
(
ret
!=
0
)
if
(
ret
!=
0
)
dev_
err
(
dev
,
"init_60m_fclk set parent"
dev_
dbg
(
dev
,
"P0 init_60m_fclk set parent failed: %d
\n
"
,
"failed error:%d
\n
"
,
ret
);
ret
);
}
}
if
(
is_ehci_phy_mode
(
pdata
->
port_mode
[
1
]))
{
if
(
is_ehci_phy_mode
(
pdata
->
port_mode
[
1
]))
{
ret
=
clk_set_parent
(
omap
->
utmi_p2_
fc
k
,
ret
=
clk_set_parent
(
omap
->
utmi_p2_
gfcl
k
,
omap
->
xclk60mhsp2_ck
);
omap
->
xclk60mhsp2_ck
);
if
(
ret
!=
0
)
if
(
ret
!=
0
)
dev_
err
(
dev
,
"xclk60mhsp2_ck set parent"
dev_
dbg
(
dev
,
"xclk60mhsp2_ck set parent failed: %d
\n
"
,
"failed error:%d
\n
"
,
ret
);
ret
);
}
else
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
1
]))
{
}
else
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
1
]))
{
ret
=
clk_set_parent
(
omap
->
utmi_p2_
fc
k
,
ret
=
clk_set_parent
(
omap
->
utmi_p2_
gfcl
k
,
omap
->
init_60m_fclk
);
omap
->
init_60m_fclk
);
if
(
ret
!=
0
)
if
(
ret
!=
0
)
dev_err
(
dev
,
"init_60m_fclk set parent"
dev_dbg
(
dev
,
"P1 init_60m_fclk set parent failed: %d
\n
"
,
"failed error:%d
\n
"
,
ret
);
ret
);
}
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"uhh"
);
if
(
!
res
)
{
dev_err
(
dev
,
"UHH EHCI get resource failed
\n
"
);
ret
=
-
ENODEV
;
goto
err_init_60m_fclk
;
}
omap
->
uhh_base
=
ioremap
(
res
->
start
,
resource_size
(
res
));
if
(
!
omap
->
uhh_base
)
{
dev_err
(
dev
,
"UHH ioremap failed
\n
"
);
ret
=
-
ENOMEM
;
goto
err_init_60m_fclk
;
}
}
platform_set_drvdata
(
pdev
,
omap
);
omap_usbhs_init
(
dev
);
omap_usbhs_init
(
dev
);
ret
=
omap_usbhs_alloc_children
(
pdev
);
ret
=
omap_usbhs_alloc_children
(
pdev
);
if
(
ret
)
{
if
(
ret
)
{
...
@@ -612,39 +706,41 @@ static int usbhs_omap_probe(struct platform_device *pdev)
...
@@ -612,39 +706,41 @@ static int usbhs_omap_probe(struct platform_device *pdev)
goto
err_alloc
;
goto
err_alloc
;
}
}
goto
end_probe
;
return
0
;
err_alloc:
err_alloc:
omap_usbhs_deinit
(
&
pdev
->
dev
);
omap_usbhs_deinit
(
&
pdev
->
dev
);
iounmap
(
omap
->
uhh_base
);
err_init_60m_fclk:
for
(
i
=
0
;
i
<
omap
->
nports
;
i
++
)
{
clk_put
(
omap
->
init_60m_fclk
);
if
(
!
IS_ERR
(
omap
->
utmi_clk
[
i
]))
clk_put
(
omap
->
utmi_clk
[
i
]);
err_usbhost_p2_fck:
if
(
!
IS_ERR
(
omap
->
hsic60m_clk
[
i
]))
clk_put
(
omap
->
usbhost_p2_fck
);
clk_put
(
omap
->
hsic60m_clk
[
i
]);
if
(
!
IS_ERR
(
omap
->
hsic480m_clk
[
i
]))
clk_put
(
omap
->
hsic480m_clk
[
i
]);
}
err_usbhost_p1_fck:
clk_put
(
omap
->
init_60m_fclk
);
clk_put
(
omap
->
usbhost_p1_fck
);
err_
xclk60mhsp2_ck
:
err_
init60m
:
clk_put
(
omap
->
xclk60mhsp2_ck
);
clk_put
(
omap
->
xclk60mhsp2_ck
);
err_utmi_p2_fck:
err_xclk60mhsp2:
clk_put
(
omap
->
utmi_p2_fck
);
err_xclk60mhsp1_ck:
clk_put
(
omap
->
xclk60mhsp1_ck
);
clk_put
(
omap
->
xclk60mhsp1_ck
);
err_
utmi_p1_fck
:
err_
xclk60mhsp1
:
clk_put
(
omap
->
utmi_p
1_fc
k
);
clk_put
(
omap
->
utmi_p
2_gfcl
k
);
err_end:
err_p2_gfclk:
clk_put
(
omap
->
utmi_p1_gfclk
);
err_p1_gfclk:
if
(
!
IS_ERR
(
omap
->
ehci_logic_fck
))
clk_put
(
omap
->
ehci_logic_fck
);
clk_put
(
omap
->
ehci_logic_fck
);
err_mem:
pm_runtime_disable
(
dev
);
pm_runtime_disable
(
dev
);
kfree
(
omap
);
end_probe:
return
ret
;
return
ret
;
}
}
...
@@ -657,19 +753,29 @@ static int usbhs_omap_probe(struct platform_device *pdev)
...
@@ -657,19 +753,29 @@ static int usbhs_omap_probe(struct platform_device *pdev)
static
int
usbhs_omap_remove
(
struct
platform_device
*
pdev
)
static
int
usbhs_omap_remove
(
struct
platform_device
*
pdev
)
{
{
struct
usbhs_hcd_omap
*
omap
=
platform_get_drvdata
(
pdev
);
struct
usbhs_hcd_omap
*
omap
=
platform_get_drvdata
(
pdev
);
int
i
;
omap_usbhs_deinit
(
&
pdev
->
dev
);
omap_usbhs_deinit
(
&
pdev
->
dev
);
iounmap
(
omap
->
uhh_base
);
for
(
i
=
0
;
i
<
omap
->
nports
;
i
++
)
{
if
(
!
IS_ERR
(
omap
->
utmi_clk
[
i
]))
clk_put
(
omap
->
utmi_clk
[
i
]);
if
(
!
IS_ERR
(
omap
->
hsic60m_clk
[
i
]))
clk_put
(
omap
->
hsic60m_clk
[
i
]);
if
(
!
IS_ERR
(
omap
->
hsic480m_clk
[
i
]))
clk_put
(
omap
->
hsic480m_clk
[
i
]);
}
clk_put
(
omap
->
init_60m_fclk
);
clk_put
(
omap
->
init_60m_fclk
);
clk_put
(
omap
->
u
sbhost_p2_fc
k
);
clk_put
(
omap
->
u
tmi_p1_gfcl
k
);
clk_put
(
omap
->
u
sbhost_p1_fc
k
);
clk_put
(
omap
->
u
tmi_p2_gfcl
k
);
clk_put
(
omap
->
xclk60mhsp2_ck
);
clk_put
(
omap
->
xclk60mhsp2_ck
);
clk_put
(
omap
->
utmi_p2_fck
);
clk_put
(
omap
->
xclk60mhsp1_ck
);
clk_put
(
omap
->
xclk60mhsp1_ck
);
clk_put
(
omap
->
utmi_p1_fck
);
if
(
!
IS_ERR
(
omap
->
ehci_logic_fck
))
clk_put
(
omap
->
ehci_logic_fck
);
clk_put
(
omap
->
ehci_logic_fck
);
pm_runtime_disable
(
&
pdev
->
dev
);
pm_runtime_disable
(
&
pdev
->
dev
);
kfree
(
omap
);
return
0
;
return
0
;
}
}
...
@@ -685,7 +791,7 @@ static struct platform_driver usbhs_omap_driver = {
...
@@ -685,7 +791,7 @@ static struct platform_driver usbhs_omap_driver = {
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
usbhsomap_dev_pm_ops
,
.
pm
=
&
usbhsomap_dev_pm_ops
,
},
},
.
remove
=
__exit_p
(
usbhs_omap_remove
)
,
.
remove
=
usbhs_omap_remove
,
};
};
MODULE_AUTHOR
(
"Keshava Munegowda <keshava_mgowda@ti.com>"
);
MODULE_AUTHOR
(
"Keshava Munegowda <keshava_mgowda@ti.com>"
);
...
...
drivers/mfd/omap-usb-tll.c
浏览文件 @
3ec3090c
...
@@ -54,10 +54,13 @@
...
@@ -54,10 +54,13 @@
#define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num)
#define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num)
#define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT 24
#define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT 24
#define OMAP_TLL_CHANNEL_CONF_DRVVBUS (1 << 16)
#define OMAP_TLL_CHANNEL_CONF_CHRGVBUS (1 << 15)
#define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11)
#define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11)
#define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10)
#define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10)
#define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9)
#define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9)
#define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8)
#define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8)
#define OMAP_TLL_CHANNEL_CONF_MODE_TRANSPARENT_UTMI (2 << 1)
#define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS (1 << 1)
#define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS (1 << 1)
#define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0)
#define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0)
...
@@ -92,21 +95,25 @@
...
@@ -92,21 +95,25 @@
#define OMAP_USBTLL_REV1 0x00000015
/* OMAP3 */
#define OMAP_USBTLL_REV1 0x00000015
/* OMAP3 */
#define OMAP_USBTLL_REV2 0x00000018
/* OMAP 3630 */
#define OMAP_USBTLL_REV2 0x00000018
/* OMAP 3630 */
#define OMAP_USBTLL_REV3 0x00000004
/* OMAP4 */
#define OMAP_USBTLL_REV3 0x00000004
/* OMAP4 */
#define OMAP_USBTLL_REV4 0x00000006
/* OMAP5 */
#define is_ehci_tll_mode(x) (x == OMAP_EHCI_PORT_MODE_TLL)
#define is_ehci_tll_mode(x) (x == OMAP_EHCI_PORT_MODE_TLL)
/* only PHY and UNUSED modes don't need TLL */
#define omap_usb_mode_needs_tll(x) ((x) != OMAP_USBHS_PORT_MODE_UNUSED &&\
(x) != OMAP_EHCI_PORT_MODE_PHY)
struct
usbtll_omap
{
struct
usbtll_omap
{
struct
clk
*
usbtll_p1_fck
;
int
nch
;
/* num. of channels */
struct
clk
*
usbtll_p2_fck
;
struct
usbhs_omap_platform_data
*
pdata
;
struct
usbtll_omap_platform_data
platdata
;
struct
clk
**
ch_clk
;
/* secure the register updates */
spinlock_t
lock
;
};
};
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
const
char
usbtll_driver_name
[]
=
USBTLL_DRIVER_NAME
;
static
const
char
usbtll_driver_name
[]
=
USBTLL_DRIVER_NAME
;
struct
platform_device
*
tll_pdev
;
static
struct
device
*
tll_dev
;
static
DEFINE_SPINLOCK
(
tll_lock
);
/* serialize access to tll_dev */
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
...
@@ -203,84 +210,84 @@ static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
...
@@ -203,84 +210,84 @@ static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
static
int
usbtll_omap_probe
(
struct
platform_device
*
pdev
)
static
int
usbtll_omap_probe
(
struct
platform_device
*
pdev
)
{
{
struct
device
*
dev
=
&
pdev
->
dev
;
struct
device
*
dev
=
&
pdev
->
dev
;
struct
usb
tll_omap_platform_data
*
pdata
=
dev
->
platform_data
;
struct
usb
hs_omap_platform_data
*
pdata
=
dev
->
platform_data
;
void
__iomem
*
base
;
void
__iomem
*
base
;
struct
resource
*
res
;
struct
resource
*
res
;
struct
usbtll_omap
*
tll
;
struct
usbtll_omap
*
tll
;
unsigned
reg
;
unsigned
reg
;
unsigned
long
flags
;
int
ret
=
0
;
int
ret
=
0
;
int
i
,
ver
,
count
;
int
i
,
ver
;
bool
needs_tll
;
dev_dbg
(
dev
,
"starting TI HSUSB TLL Controller
\n
"
);
dev_dbg
(
dev
,
"starting TI HSUSB TLL Controller
\n
"
);
tll
=
kzalloc
(
sizeof
(
struct
usbtll_omap
),
GFP_KERNEL
);
tll
=
devm_kzalloc
(
dev
,
sizeof
(
struct
usbtll_omap
),
GFP_KERNEL
);
if
(
!
tll
)
{
if
(
!
tll
)
{
dev_err
(
dev
,
"Memory allocation failed
\n
"
);
dev_err
(
dev
,
"Memory allocation failed
\n
"
);
ret
=
-
ENOMEM
;
return
-
ENOMEM
;
goto
end
;
}
}
spin_lock_init
(
&
tll
->
lock
);
if
(
!
pdata
)
{
dev_err
(
dev
,
"Platform data missing
\n
"
);
for
(
i
=
0
;
i
<
OMAP3_HS_USB_PORTS
;
i
++
)
return
-
ENODEV
;
tll
->
platdata
.
port_mode
[
i
]
=
pdata
->
port_mode
[
i
];
tll
->
usbtll_p1_fck
=
clk_get
(
dev
,
"usb_tll_hs_usb_ch0_clk"
);
if
(
IS_ERR
(
tll
->
usbtll_p1_fck
))
{
ret
=
PTR_ERR
(
tll
->
usbtll_p1_fck
);
dev_err
(
dev
,
"usbtll_p1_fck failed error:%d
\n
"
,
ret
);
goto
err_tll
;
}
}
tll
->
usbtll_p2_fck
=
clk_get
(
dev
,
"usb_tll_hs_usb_ch1_clk"
);
tll
->
pdata
=
pdata
;
if
(
IS_ERR
(
tll
->
usbtll_p2_fck
))
{
ret
=
PTR_ERR
(
tll
->
usbtll_p2_fck
);
dev_err
(
dev
,
"usbtll_p2_fck failed error:%d
\n
"
,
ret
);
goto
err_usbtll_p1_fck
;
}
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
res
)
{
base
=
devm_request_and_ioremap
(
dev
,
res
);
dev_err
(
dev
,
"usb tll get resource failed
\n
"
);
ret
=
-
ENODEV
;
goto
err_usbtll_p2_fck
;
}
base
=
ioremap
(
res
->
start
,
resource_size
(
res
));
if
(
!
base
)
{
if
(
!
base
)
{
dev_err
(
dev
,
"TLL ioremap failed
\n
"
)
;
ret
=
-
EADDRNOTAVAIL
;
ret
=
-
ENOMEM
;
dev_err
(
dev
,
"Resource request/ioremap failed:%d
\n
"
,
ret
)
;
goto
err_usbtll_p2_fck
;
return
ret
;
}
}
platform_set_drvdata
(
pdev
,
tll
);
platform_set_drvdata
(
pdev
,
tll
);
pm_runtime_enable
(
dev
);
pm_runtime_enable
(
dev
);
pm_runtime_get_sync
(
dev
);
pm_runtime_get_sync
(
dev
);
spin_lock_irqsave
(
&
tll
->
lock
,
flags
);
ver
=
usbtll_read
(
base
,
OMAP_USBTLL_REVISION
);
ver
=
usbtll_read
(
base
,
OMAP_USBTLL_REVISION
);
switch
(
ver
)
{
switch
(
ver
)
{
case
OMAP_USBTLL_REV1
:
case
OMAP_USBTLL_REV1
:
case
OMAP_USBTLL_REV
2
:
case
OMAP_USBTLL_REV
4
:
count
=
OMAP_TLL_CHANNEL_COUNT
;
tll
->
nch
=
OMAP_TLL_CHANNEL_COUNT
;
break
;
break
;
case
OMAP_USBTLL_REV2
:
case
OMAP_USBTLL_REV3
:
case
OMAP_USBTLL_REV3
:
count
=
OMAP_REV2_TLL_CHANNEL_COUNT
;
tll
->
nch
=
OMAP_REV2_TLL_CHANNEL_COUNT
;
break
;
break
;
default:
default:
dev_err
(
dev
,
"TLL version failed
\n
"
);
tll
->
nch
=
OMAP_TLL_CHANNEL_COUNT
;
ret
=
-
ENODEV
;
dev_dbg
(
dev
,
goto
err_ioremap
;
"USB TLL Rev : 0x%x not recognized, assuming %d channels
\n
"
,
ver
,
tll
->
nch
);
break
;
}
}
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
0
])
||
tll
->
ch_clk
=
devm_kzalloc
(
dev
,
sizeof
(
struct
clk
*
[
tll
->
nch
]),
is_ehci_tll_mode
(
pdata
->
port_mode
[
1
])
||
GFP_KERNEL
);
is_ehci_tll_mode
(
pdata
->
port_mode
[
2
])
||
if
(
!
tll
->
ch_clk
)
{
is_ohci_port
(
pdata
->
port_mode
[
0
])
||
ret
=
-
ENOMEM
;
is_ohci_port
(
pdata
->
port_mode
[
1
])
||
dev_err
(
dev
,
"Couldn't allocate memory for channel clocks
\n
"
);
is_ohci_port
(
pdata
->
port_mode
[
2
]))
{
goto
err_clk_alloc
;
}
for
(
i
=
0
;
i
<
tll
->
nch
;
i
++
)
{
char
clkname
[]
=
"usb_tll_hs_usb_chx_clk"
;
snprintf
(
clkname
,
sizeof
(
clkname
),
"usb_tll_hs_usb_ch%d_clk"
,
i
);
tll
->
ch_clk
[
i
]
=
clk_get
(
dev
,
clkname
);
if
(
IS_ERR
(
tll
->
ch_clk
[
i
]))
dev_dbg
(
dev
,
"can't get clock : %s
\n
"
,
clkname
);
}
needs_tll
=
false
;
for
(
i
=
0
;
i
<
tll
->
nch
;
i
++
)
needs_tll
|=
omap_usb_mode_needs_tll
(
pdata
->
port_mode
[
i
]);
if
(
needs_tll
)
{
/* Program Common TLL register */
/* Program Common TLL register */
reg
=
usbtll_read
(
base
,
OMAP_TLL_SHARED_CONF
);
reg
=
usbtll_read
(
base
,
OMAP_TLL_SHARED_CONF
);
...
@@ -292,7 +299,7 @@ static int usbtll_omap_probe(struct platform_device *pdev)
...
@@ -292,7 +299,7 @@ static int usbtll_omap_probe(struct platform_device *pdev)
usbtll_write
(
base
,
OMAP_TLL_SHARED_CONF
,
reg
);
usbtll_write
(
base
,
OMAP_TLL_SHARED_CONF
,
reg
);
/* Enable channels now */
/* Enable channels now */
for
(
i
=
0
;
i
<
count
;
i
++
)
{
for
(
i
=
0
;
i
<
tll
->
nch
;
i
++
)
{
reg
=
usbtll_read
(
base
,
OMAP_TLL_CHANNEL_CONF
(
i
));
reg
=
usbtll_read
(
base
,
OMAP_TLL_CHANNEL_CONF
(
i
));
if
(
is_ohci_port
(
pdata
->
port_mode
[
i
]))
{
if
(
is_ohci_port
(
pdata
->
port_mode
[
i
]))
{
...
@@ -308,6 +315,15 @@ static int usbtll_omap_probe(struct platform_device *pdev)
...
@@ -308,6 +315,15 @@ static int usbtll_omap_probe(struct platform_device *pdev)
reg
&=
~
(
OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
reg
&=
~
(
OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
|
OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
|
OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
|
OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE
);
|
OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE
);
}
else
if
(
pdata
->
port_mode
[
i
]
==
OMAP_EHCI_PORT_MODE_HSIC
)
{
/*
* HSIC Mode requires UTMI port configurations
*/
reg
|=
OMAP_TLL_CHANNEL_CONF_DRVVBUS
|
OMAP_TLL_CHANNEL_CONF_CHRGVBUS
|
OMAP_TLL_CHANNEL_CONF_MODE_TRANSPARENT_UTMI
|
OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
;
}
else
{
}
else
{
continue
;
continue
;
}
}
...
@@ -320,25 +336,18 @@ static int usbtll_omap_probe(struct platform_device *pdev)
...
@@ -320,25 +336,18 @@ static int usbtll_omap_probe(struct platform_device *pdev)
}
}
}
}
err_ioremap:
spin_unlock_irqrestore
(
&
tll
->
lock
,
flags
);
iounmap
(
base
);
pm_runtime_put_sync
(
dev
);
pm_runtime_put_sync
(
dev
);
tll_pdev
=
pdev
;
/* only after this can omap_tll_enable/disable work */
if
(
!
ret
)
spin_lock
(
&
tll_lock
);
goto
end
;
tll_dev
=
dev
;
pm_runtime_disable
(
dev
);
spin_unlock
(
&
tll_lock
);
err_usbtll_p2_fck:
clk_put
(
tll
->
usbtll_p2_fck
);
err_usbtll_p1_fck:
return
0
;
clk_put
(
tll
->
usbtll_p1_fck
);
err_tll:
err_clk_alloc:
kfree
(
tll
);
pm_runtime_put_sync
(
dev
);
pm_runtime_disable
(
dev
);
end:
return
ret
;
return
ret
;
}
}
...
@@ -351,36 +360,42 @@ static int usbtll_omap_probe(struct platform_device *pdev)
...
@@ -351,36 +360,42 @@ static int usbtll_omap_probe(struct platform_device *pdev)
static
int
usbtll_omap_remove
(
struct
platform_device
*
pdev
)
static
int
usbtll_omap_remove
(
struct
platform_device
*
pdev
)
{
{
struct
usbtll_omap
*
tll
=
platform_get_drvdata
(
pdev
);
struct
usbtll_omap
*
tll
=
platform_get_drvdata
(
pdev
);
int
i
;
spin_lock
(
&
tll_lock
);
tll_dev
=
NULL
;
spin_unlock
(
&
tll_lock
);
for
(
i
=
0
;
i
<
tll
->
nch
;
i
++
)
if
(
!
IS_ERR
(
tll
->
ch_clk
[
i
]))
clk_put
(
tll
->
ch_clk
[
i
]);
clk_put
(
tll
->
usbtll_p2_fck
);
clk_put
(
tll
->
usbtll_p1_fck
);
pm_runtime_disable
(
&
pdev
->
dev
);
pm_runtime_disable
(
&
pdev
->
dev
);
kfree
(
tll
);
return
0
;
return
0
;
}
}
static
int
usbtll_runtime_resume
(
struct
device
*
dev
)
static
int
usbtll_runtime_resume
(
struct
device
*
dev
)
{
{
struct
usbtll_omap
*
tll
=
dev_get_drvdata
(
dev
);
struct
usbtll_omap
*
tll
=
dev_get_drvdata
(
dev
);
struct
usb
tll_omap_platform_data
*
pdata
=
&
tll
->
plat
data
;
struct
usb
hs_omap_platform_data
*
pdata
=
tll
->
p
data
;
unsigned
long
flags
;
int
i
;
dev_dbg
(
dev
,
"usbtll_runtime_resume
\n
"
);
dev_dbg
(
dev
,
"usbtll_runtime_resume
\n
"
);
if
(
!
pdata
)
{
for
(
i
=
0
;
i
<
tll
->
nch
;
i
++
)
{
dev_dbg
(
dev
,
"missing platform_data
\n
"
);
if
(
omap_usb_mode_needs_tll
(
pdata
->
port_mode
[
i
]))
{
return
-
ENODEV
;
int
r
;
}
spin_lock_irqsave
(
&
tll
->
lock
,
flags
);
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
0
]))
if
(
IS_ERR
(
tll
->
ch_clk
[
i
]))
clk_enable
(
tll
->
usbtll_p1_fck
);
continue
;
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
1
]))
clk_enable
(
tll
->
usbtll_p2_fck
);
spin_unlock_irqrestore
(
&
tll
->
lock
,
flags
);
r
=
clk_enable
(
tll
->
ch_clk
[
i
]);
if
(
r
)
{
dev_err
(
dev
,
"Error enabling ch %d clock: %d
\n
"
,
i
,
r
);
}
}
}
return
0
;
return
0
;
}
}
...
@@ -388,25 +403,17 @@ static int usbtll_runtime_resume(struct device *dev)
...
@@ -388,25 +403,17 @@ static int usbtll_runtime_resume(struct device *dev)
static
int
usbtll_runtime_suspend
(
struct
device
*
dev
)
static
int
usbtll_runtime_suspend
(
struct
device
*
dev
)
{
{
struct
usbtll_omap
*
tll
=
dev_get_drvdata
(
dev
);
struct
usbtll_omap
*
tll
=
dev_get_drvdata
(
dev
);
struct
usb
tll_omap_platform_data
*
pdata
=
&
tll
->
plat
data
;
struct
usb
hs_omap_platform_data
*
pdata
=
tll
->
p
data
;
unsigned
long
flags
;
int
i
;
dev_dbg
(
dev
,
"usbtll_runtime_suspend
\n
"
);
dev_dbg
(
dev
,
"usbtll_runtime_suspend
\n
"
);
if
(
!
pdata
)
{
for
(
i
=
0
;
i
<
tll
->
nch
;
i
++
)
{
dev_dbg
(
dev
,
"missing platform_data
\n
"
);
if
(
omap_usb_mode_needs_tll
(
pdata
->
port_mode
[
i
]))
{
return
-
ENODEV
;
if
(
!
IS_ERR
(
tll
->
ch_clk
[
i
]))
clk_disable
(
tll
->
ch_clk
[
i
]);
}
}
}
spin_lock_irqsave
(
&
tll
->
lock
,
flags
);
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
0
]))
clk_disable
(
tll
->
usbtll_p1_fck
);
if
(
is_ehci_tll_mode
(
pdata
->
port_mode
[
1
]))
clk_disable
(
tll
->
usbtll_p2_fck
);
spin_unlock_irqrestore
(
&
tll
->
lock
,
flags
);
return
0
;
return
0
;
}
}
...
@@ -429,21 +436,39 @@ static struct platform_driver usbtll_omap_driver = {
...
@@ -429,21 +436,39 @@ static struct platform_driver usbtll_omap_driver = {
int
omap_tll_enable
(
void
)
int
omap_tll_enable
(
void
)
{
{
if
(
!
tll_pdev
)
{
int
ret
;
pr_err
(
"missing omap usbhs tll platform_data
\n
"
);
return
-
ENODEV
;
spin_lock
(
&
tll_lock
);
if
(
!
tll_dev
)
{
pr_err
(
"%s: OMAP USB TLL not initialized
\n
"
,
__func__
);
ret
=
-
ENODEV
;
}
else
{
ret
=
pm_runtime_get_sync
(
tll_dev
);
}
}
return
pm_runtime_get_sync
(
&
tll_pdev
->
dev
);
spin_unlock
(
&
tll_lock
);
return
ret
;
}
}
EXPORT_SYMBOL_GPL
(
omap_tll_enable
);
EXPORT_SYMBOL_GPL
(
omap_tll_enable
);
int
omap_tll_disable
(
void
)
int
omap_tll_disable
(
void
)
{
{
if
(
!
tll_pdev
)
{
int
ret
;
pr_err
(
"missing omap usbhs tll platform_data
\n
"
);
return
-
ENODEV
;
spin_lock
(
&
tll_lock
);
if
(
!
tll_dev
)
{
pr_err
(
"%s: OMAP USB TLL not initialized
\n
"
,
__func__
);
ret
=
-
ENODEV
;
}
else
{
ret
=
pm_runtime_put_sync
(
tll_dev
);
}
}
return
pm_runtime_put_sync
(
&
tll_pdev
->
dev
);
spin_unlock
(
&
tll_lock
);
return
ret
;
}
}
EXPORT_SYMBOL_GPL
(
omap_tll_disable
);
EXPORT_SYMBOL_GPL
(
omap_tll_disable
);
...
...
drivers/usb/host/ehci-omap.c
浏览文件 @
3ec3090c
...
@@ -107,7 +107,7 @@ static int omap_ehci_init(struct usb_hcd *hcd)
...
@@ -107,7 +107,7 @@ static int omap_ehci_init(struct usb_hcd *hcd)
{
{
struct
ehci_hcd
*
ehci
=
hcd_to_ehci
(
hcd
);
struct
ehci_hcd
*
ehci
=
hcd_to_ehci
(
hcd
);
int
rc
;
int
rc
;
struct
ehci_hcd
_omap_platform_data
*
pdata
;
struct
usbhs
_omap_platform_data
*
pdata
;
pdata
=
hcd
->
self
.
controller
->
platform_data
;
pdata
=
hcd
->
self
.
controller
->
platform_data
;
...
@@ -151,7 +151,7 @@ static int omap_ehci_init(struct usb_hcd *hcd)
...
@@ -151,7 +151,7 @@ static int omap_ehci_init(struct usb_hcd *hcd)
}
}
static
void
disable_put_regulator
(
static
void
disable_put_regulator
(
struct
ehci_hcd
_omap_platform_data
*
pdata
)
struct
usbhs
_omap_platform_data
*
pdata
)
{
{
int
i
;
int
i
;
...
@@ -176,7 +176,7 @@ static void disable_put_regulator(
...
@@ -176,7 +176,7 @@ static void disable_put_regulator(
static
int
ehci_hcd_omap_probe
(
struct
platform_device
*
pdev
)
static
int
ehci_hcd_omap_probe
(
struct
platform_device
*
pdev
)
{
{
struct
device
*
dev
=
&
pdev
->
dev
;
struct
device
*
dev
=
&
pdev
->
dev
;
struct
ehci_hcd_omap_platform_data
*
pdata
=
dev
->
platform_data
;
struct
usbhs_omap_platform_data
*
pdata
=
dev
->
platform_data
;
struct
resource
*
res
;
struct
resource
*
res
;
struct
usb_hcd
*
hcd
;
struct
usb_hcd
*
hcd
;
void
__iomem
*
regs
;
void
__iomem
*
regs
;
...
...
include/linux/platform_data/usb-omap.h
浏览文件 @
3ec3090c
...
@@ -55,6 +55,7 @@ struct ohci_hcd_omap_platform_data {
...
@@ -55,6 +55,7 @@ struct ohci_hcd_omap_platform_data {
};
};
struct
usbhs_omap_platform_data
{
struct
usbhs_omap_platform_data
{
int
nports
;
enum
usbhs_omap_port_mode
port_mode
[
OMAP3_HS_USB_PORTS
];
enum
usbhs_omap_port_mode
port_mode
[
OMAP3_HS_USB_PORTS
];
int
reset_gpio_port
[
OMAP3_HS_USB_PORTS
];
int
reset_gpio_port
[
OMAP3_HS_USB_PORTS
];
struct
regulator
*
regulator
[
OMAP3_HS_USB_PORTS
];
struct
regulator
*
regulator
[
OMAP3_HS_USB_PORTS
];
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录