diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-11-11 17:31:53 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-11-11 17:31:53 -0800 |
commit | 7fd94beecaff19b346efbf6b77288ab4b0b42dbd (patch) | |
tree | 01c1354e59c8c338fd2fe65772c169022aa0ca81 /drivers/usb/renesas_usbhs/pipe.c | |
parent | 0f89fc3fd861b8c50fc8c8db5b9a640959744ac7 (diff) | |
parent | f72e3b78867142a19b77f1de0698ce8b03dc6cbd (diff) | |
download | blackbird-op-linux-7fd94beecaff19b346efbf6b77288ab4b0b42dbd.tar.gz blackbird-op-linux-7fd94beecaff19b346efbf6b77288ab4b0b42dbd.zip |
Merge tag 'gadget-for-v3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
USB gadget patches from Felipe:
"usb: gadget: patches for v3.8
renesas_usbhs implements ->pullup() method, switches over
to devm_request_irq(), adds support for DMA Engine and
got a few miscelaneous cleanups.
The NCM gadget got an endianness fix and the Ethernet
gadget a frame size fix.
We're finally removing the g_file_storage gadget and
sticking to g_mass_storage and the new tcm_usb_gadget
gadgets since that was a huge duplicaton of effort anyway.
While removing g_file_storage, we also had to fix a bunch
of defconfigs which were still pointing to the old gadget.
There's a big series getting us closer to being able to
introduce our configfs interface. The series converts
functions into loadable modules which will, eventually,
be registered to the configfs interface.
Other than that there's the usual typo fixes and miscelaneous
cleanups all over the place."
Diffstat (limited to 'drivers/usb/renesas_usbhs/pipe.c')
-rw-r--r-- | drivers/usb/renesas_usbhs/pipe.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 122526cfd32b..7926e1c700f1 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -93,6 +93,82 @@ static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val) } /* + * PIPEnTRN/PIPEnTRE functions + */ +static void usbhsp_pipe_trn_set(struct usbhs_pipe *pipe, u16 mask, u16 val) +{ + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + struct device *dev = usbhs_priv_to_dev(priv); + int num = usbhs_pipe_number(pipe); + u16 reg; + + /* + * It is impossible to calculate address, + * since PIPEnTRN addresses were mapped randomly. + */ +#define CASE_PIPExTRN(a) \ + case 0x ## a: \ + reg = PIPE ## a ## TRN; \ + break; + + switch (num) { + CASE_PIPExTRN(1); + CASE_PIPExTRN(2); + CASE_PIPExTRN(3); + CASE_PIPExTRN(4); + CASE_PIPExTRN(5); + CASE_PIPExTRN(B); + CASE_PIPExTRN(C); + CASE_PIPExTRN(D); + CASE_PIPExTRN(E); + CASE_PIPExTRN(F); + CASE_PIPExTRN(9); + CASE_PIPExTRN(A); + default: + dev_err(dev, "unknown pipe (%d)\n", num); + return; + } + __usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val); +} + +static void usbhsp_pipe_tre_set(struct usbhs_pipe *pipe, u16 mask, u16 val) +{ + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + struct device *dev = usbhs_priv_to_dev(priv); + int num = usbhs_pipe_number(pipe); + u16 reg; + + /* + * It is impossible to calculate address, + * since PIPEnTRE addresses were mapped randomly. + */ +#define CASE_PIPExTRE(a) \ + case 0x ## a: \ + reg = PIPE ## a ## TRE; \ + break; + + switch (num) { + CASE_PIPExTRE(1); + CASE_PIPExTRE(2); + CASE_PIPExTRE(3); + CASE_PIPExTRE(4); + CASE_PIPExTRE(5); + CASE_PIPExTRE(B); + CASE_PIPExTRE(C); + CASE_PIPExTRE(D); + CASE_PIPExTRE(E); + CASE_PIPExTRE(F); + CASE_PIPExTRE(9); + CASE_PIPExTRE(A); + default: + dev_err(dev, "unknown pipe (%d)\n", num); + return; + } + + __usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val); +} + +/* * PIPEBUF */ static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val) @@ -264,6 +340,31 @@ int usbhs_pipe_is_stall(struct usbhs_pipe *pipe) return (int)(pid == PID_STALL10 || pid == PID_STALL11); } +void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len) +{ + if (!usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK)) + return; + + /* + * clear and disable transfer counter for IN/OUT pipe + */ + usbhsp_pipe_tre_set(pipe, TRCLR | TRENB, TRCLR); + + /* + * Only IN direction bulk pipe can use transfer count. + * Without using this function, + * received data will break if it was large data size. + * see PIPEnTRN/PIPEnTRE for detail + */ + if (usbhs_pipe_is_dir_in(pipe)) { + int maxp = usbhs_pipe_get_maxpacket(pipe); + + usbhsp_pipe_trn_set(pipe, 0xffff, DIV_ROUND_UP(len, maxp)); + usbhsp_pipe_tre_set(pipe, TRENB, TRENB); /* enable */ + } +} + + /* * pipe setup */ |