Commit 9dd649c6 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-ci-v4.10-rc1' of...

Merge tag 'usb-ci-v4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb into usb-next

Peter writes:

- Adding ULPI PHY support for imx53
- Properly mark little endian descriptors for udc
parents 75e9ebec 3be3251d
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/usb/chipidea.h> #include <linux/usb/chipidea.h>
#include <linux/usb/of.h>
#include <linux/clk.h> #include <linux/clk.h>
#include "ci.h" #include "ci.h"
...@@ -146,6 +147,9 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev) ...@@ -146,6 +147,9 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
if (of_find_property(np, "external-vbus-divider", NULL)) if (of_find_property(np, "external-vbus-divider", NULL))
data->evdo = 1; data->evdo = 1;
if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI)
data->ulpi = 1;
return data; return data;
} }
......
...@@ -19,6 +19,7 @@ struct imx_usbmisc_data { ...@@ -19,6 +19,7 @@ struct imx_usbmisc_data {
unsigned int disable_oc:1; /* over current detect disabled */ unsigned int disable_oc:1; /* over current detect disabled */
unsigned int oc_polarity:1; /* over current polarity if oc enabled */ unsigned int oc_polarity:1; /* over current polarity if oc enabled */
unsigned int evdo:1; /* set external vbus divider option */ unsigned int evdo:1; /* set external vbus divider option */
unsigned int ulpi:1; /* connected to an ULPI phy */
}; };
int imx_usbmisc_init(struct imx_usbmisc_data *); int imx_usbmisc_init(struct imx_usbmisc_data *);
......
...@@ -365,7 +365,7 @@ static int add_td_to_list(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq, ...@@ -365,7 +365,7 @@ static int add_td_to_list(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq,
if (hwreq->req.length == 0 if (hwreq->req.length == 0
|| hwreq->req.length % hwep->ep.maxpacket) || hwreq->req.length % hwep->ep.maxpacket)
mul++; mul++;
node->ptr->token |= mul << __ffs(TD_MULTO); node->ptr->token |= cpu_to_le32(mul << __ffs(TD_MULTO));
} }
temp = (u32) (hwreq->req.dma + hwreq->req.actual); temp = (u32) (hwreq->req.dma + hwreq->req.actual);
...@@ -504,7 +504,7 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) ...@@ -504,7 +504,7 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
if (hwreq->req.length == 0 if (hwreq->req.length == 0
|| hwreq->req.length % hwep->ep.maxpacket) || hwreq->req.length % hwep->ep.maxpacket)
mul++; mul++;
hwep->qh.ptr->cap |= mul << __ffs(QH_MULT); hwep->qh.ptr->cap |= cpu_to_le32(mul << __ffs(QH_MULT));
} }
ret = hw_ep_prime(ci, hwep->num, hwep->dir, ret = hw_ep_prime(ci, hwep->num, hwep->dir,
...@@ -529,7 +529,7 @@ static void free_pending_td(struct ci_hw_ep *hwep) ...@@ -529,7 +529,7 @@ static void free_pending_td(struct ci_hw_ep *hwep)
static int reprime_dtd(struct ci_hdrc *ci, struct ci_hw_ep *hwep, static int reprime_dtd(struct ci_hdrc *ci, struct ci_hw_ep *hwep,
struct td_node *node) struct td_node *node)
{ {
hwep->qh.ptr->td.next = node->dma; hwep->qh.ptr->td.next = cpu_to_le32(node->dma);
hwep->qh.ptr->td.token &= hwep->qh.ptr->td.token &=
cpu_to_le32(~(TD_STATUS_HALTED | TD_STATUS_ACTIVE)); cpu_to_le32(~(TD_STATUS_HALTED | TD_STATUS_ACTIVE));
......
...@@ -22,11 +22,11 @@ ...@@ -22,11 +22,11 @@
/* DMA layout of transfer descriptors */ /* DMA layout of transfer descriptors */
struct ci_hw_td { struct ci_hw_td {
/* 0 */ /* 0 */
u32 next; __le32 next;
#define TD_TERMINATE BIT(0) #define TD_TERMINATE BIT(0)
#define TD_ADDR_MASK (0xFFFFFFEUL << 5) #define TD_ADDR_MASK (0xFFFFFFEUL << 5)
/* 1 */ /* 1 */
u32 token; __le32 token;
#define TD_STATUS (0x00FFUL << 0) #define TD_STATUS (0x00FFUL << 0)
#define TD_STATUS_TR_ERR BIT(3) #define TD_STATUS_TR_ERR BIT(3)
#define TD_STATUS_DT_ERR BIT(5) #define TD_STATUS_DT_ERR BIT(5)
...@@ -36,7 +36,7 @@ struct ci_hw_td { ...@@ -36,7 +36,7 @@ struct ci_hw_td {
#define TD_IOC BIT(15) #define TD_IOC BIT(15)
#define TD_TOTAL_BYTES (0x7FFFUL << 16) #define TD_TOTAL_BYTES (0x7FFFUL << 16)
/* 2 */ /* 2 */
u32 page[5]; __le32 page[5];
#define TD_CURR_OFFSET (0x0FFFUL << 0) #define TD_CURR_OFFSET (0x0FFFUL << 0)
#define TD_FRAME_NUM (0x07FFUL << 0) #define TD_FRAME_NUM (0x07FFUL << 0)
#define TD_RESERVED_MASK (0x0FFFUL << 0) #define TD_RESERVED_MASK (0x0FFFUL << 0)
...@@ -45,18 +45,18 @@ struct ci_hw_td { ...@@ -45,18 +45,18 @@ struct ci_hw_td {
/* DMA layout of queue heads */ /* DMA layout of queue heads */
struct ci_hw_qh { struct ci_hw_qh {
/* 0 */ /* 0 */
u32 cap; __le32 cap;
#define QH_IOS BIT(15) #define QH_IOS BIT(15)
#define QH_MAX_PKT (0x07FFUL << 16) #define QH_MAX_PKT (0x07FFUL << 16)
#define QH_ZLT BIT(29) #define QH_ZLT BIT(29)
#define QH_MULT (0x0003UL << 30) #define QH_MULT (0x0003UL << 30)
#define QH_ISO_MULT(x) ((x >> 11) & 0x03) #define QH_ISO_MULT(x) ((x >> 11) & 0x03)
/* 1 */ /* 1 */
u32 curr; __le32 curr;
/* 2 - 8 */ /* 2 - 8 */
struct ci_hw_td td; struct ci_hw_td td;
/* 9 */ /* 9 */
u32 RESERVED; __le32 RESERVED;
struct usb_ctrlrequest setup; struct usb_ctrlrequest setup;
} __attribute__ ((packed, aligned(4))); } __attribute__ ((packed, aligned(4)));
......
...@@ -46,11 +46,23 @@ ...@@ -46,11 +46,23 @@
#define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08 #define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
#define MX53_USB_OTG_PHY_CTRL_1_OFFSET 0x0c #define MX53_USB_OTG_PHY_CTRL_1_OFFSET 0x0c
#define MX53_USB_CTRL_1_OFFSET 0x10
#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK (0x11 << 2)
#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI BIT(2)
#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK (0x11 << 6)
#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
#define MX53_USB_UH2_CTRL_OFFSET 0x14 #define MX53_USB_UH2_CTRL_OFFSET 0x14
#define MX53_USB_UH3_CTRL_OFFSET 0x18 #define MX53_USB_UH3_CTRL_OFFSET 0x18
#define MX53_USB_CLKONOFF_CTRL_OFFSET 0x24
#define MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF BIT(21)
#define MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF BIT(22)
#define MX53_BM_OVER_CUR_DIS_H1 BIT(5) #define MX53_BM_OVER_CUR_DIS_H1 BIT(5)
#define MX53_BM_OVER_CUR_DIS_OTG BIT(8) #define MX53_BM_OVER_CUR_DIS_OTG BIT(8)
#define MX53_BM_OVER_CUR_DIS_UHx BIT(30) #define MX53_BM_OVER_CUR_DIS_UHx BIT(30)
#define MX53_USB_CTRL_1_UH2_ULPI_EN BIT(26)
#define MX53_USB_CTRL_1_UH3_ULPI_EN BIT(27)
#define MX53_USB_UHx_CTRL_WAKE_UP_EN BIT(7)
#define MX53_USB_UHx_CTRL_ULPI_INT_EN BIT(8)
#define MX53_USB_PHYCTRL1_PLLDIV_MASK 0x3 #define MX53_USB_PHYCTRL1_PLLDIV_MASK 0x3
#define MX53_USB_PLL_DIV_24_MHZ 0x01 #define MX53_USB_PLL_DIV_24_MHZ 0x01
...@@ -199,31 +211,77 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data) ...@@ -199,31 +211,77 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
val |= MX53_USB_PLL_DIV_24_MHZ; val |= MX53_USB_PLL_DIV_24_MHZ;
writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET); writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
if (data->disable_oc) { spin_lock_irqsave(&usbmisc->lock, flags);
spin_lock_irqsave(&usbmisc->lock, flags);
switch (data->index) { switch (data->index) {
case 0: case 0:
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET; reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG; val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
break; writel(val, reg);
case 1: }
break;
case 1:
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET; reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1; val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
break; writel(val, reg);
case 2: }
break;
case 2:
if (data->ulpi) {
/* set USBH2 into ULPI-mode. */
reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN;
/* select ULPI clock */
val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK;
val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI;
writel(val, reg);
/* Set interrupt wake up enable */
reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
| MX53_USB_UHx_CTRL_ULPI_INT_EN;
writel(val, reg);
/* Disable internal 60Mhz clock */
reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
writel(val, reg);
}
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET; reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx; val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
break; writel(val, reg);
case 3: }
break;
case 3:
if (data->ulpi) {
/* set USBH3 into ULPI-mode. */
reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
val = readl(reg) | MX53_USB_CTRL_1_UH3_ULPI_EN;
/* select ULPI clock */
val &= ~MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK;
val |= MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI;
writel(val, reg);
/* Set interrupt wake up enable */
reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET; reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx; val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
break; | MX53_USB_UHx_CTRL_ULPI_INT_EN;
writel(val, reg);
/* Disable internal 60Mhz clock */
reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
writel(val, reg);
} }
if (reg && val) if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
writel(val, reg); writel(val, reg);
spin_unlock_irqrestore(&usbmisc->lock, flags); }
break;
} }
spin_unlock_irqrestore(&usbmisc->lock, flags);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment