diff options
Diffstat (limited to 'drivers/usb/renesas_usbhs')
-rw-r--r-- | drivers/usb/renesas_usbhs/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/common.c | 86 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.c | 20 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.h | 20 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 21 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_host.c | 11 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/pipe.c | 118 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/pipe.h | 3 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/rcar3.c | 54 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/rcar3.h | 3 |
11 files changed, 177 insertions, 163 deletions
diff --git a/drivers/usb/renesas_usbhs/Kconfig b/drivers/usb/renesas_usbhs/Kconfig index ebc99ee076ce..b26d7c339c05 100644 --- a/drivers/usb/renesas_usbhs/Kconfig +++ b/drivers/usb/renesas_usbhs/Kconfig @@ -5,7 +5,7 @@ config USB_RENESAS_USBHS tristate 'Renesas USBHS controller' depends on USB_GADGET - depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST + depends on ARCH_RENESAS || SUPERH || COMPILE_TEST depends on EXTCON || !EXTCON # if EXTCON=m, USBHS cannot be built-in default n help diff --git a/drivers/usb/renesas_usbhs/Makefile b/drivers/usb/renesas_usbhs/Makefile index 9e47f477b6d2..d787d05f6546 100644 --- a/drivers/usb/renesas_usbhs/Makefile +++ b/drivers/usb/renesas_usbhs/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs.o -renesas_usbhs-y := common.o mod.o pipe.o fifo.o rcar2.o +renesas_usbhs-y := common.o mod.o pipe.o fifo.o rcar2.o rcar3.o ifneq ($(CONFIG_USB_RENESAS_USBHS_HCD),) renesas_usbhs-y += mod_host.o diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index d82fa36c3465..baeb7d23bf24 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -25,6 +25,7 @@ #include <linux/sysfs.h> #include "common.h" #include "rcar2.h" +#include "rcar3.h" /* * image of renesas_usbhs @@ -302,37 +303,37 @@ static void usbhsc_set_buswait(struct usbhs_priv *priv) */ /* commonly used on old SH-Mobile SoCs */ -static u32 usbhsc_default_pipe_type[] = { - USB_ENDPOINT_XFER_CONTROL, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, +static struct renesas_usbhs_driver_pipe_config usbhsc_default_pipe[] = { + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_CONTROL, 64, 0x00, false), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_ISOC, 1024, 0x08, false), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_ISOC, 1024, 0x18, false), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0x28, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0x38, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0x48, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_INT, 64, 0x04, false), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_INT, 64, 0x05, false), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_INT, 64, 0x06, false), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_INT, 64, 0x07, false), }; /* commonly used on newer SH-Mobile and R-Car SoCs */ -static u32 usbhsc_new_pipe_type[] = { - USB_ENDPOINT_XFER_CONTROL, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, +static struct renesas_usbhs_driver_pipe_config usbhsc_new_pipe[] = { + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_CONTROL, 64, 0x00, false), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_ISOC, 1024, 0x08, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_ISOC, 1024, 0x28, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0x48, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0x58, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0x68, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_INT, 64, 0x04, false), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_INT, 64, 0x05, false), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_INT, 64, 0x06, false), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0x78, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0x88, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0x98, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0xa8, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0xb8, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0xc8, true), + RENESAS_USBHS_PIPE(USB_ENDPOINT_XFER_BULK, 512, 0xd8, true), }; /* @@ -477,10 +478,17 @@ static const struct of_device_id usbhs_of_match[] = { .data = (void *)USBHS_TYPE_RCAR_GEN2, }, { - /* Gen3 is compatible with Gen2 */ .compatible = "renesas,usbhs-r8a7795", + .data = (void *)USBHS_TYPE_RCAR_GEN3, + }, + { + .compatible = "renesas,rcar-gen2-usbhs", .data = (void *)USBHS_TYPE_RCAR_GEN2, }, + { + .compatible = "renesas,rcar-gen3-usbhs", + .data = (void *)USBHS_TYPE_RCAR_GEN3, + }, { }, }; MODULE_DEVICE_TABLE(of, usbhs_of_match); @@ -564,10 +572,16 @@ static int usbhs_probe(struct platform_device *pdev) switch (priv->dparam.type) { case USBHS_TYPE_RCAR_GEN2: priv->pfunc = usbhs_rcar2_ops; - if (!priv->dparam.pipe_type) { - priv->dparam.pipe_type = usbhsc_new_pipe_type; - priv->dparam.pipe_size = - ARRAY_SIZE(usbhsc_new_pipe_type); + if (!priv->dparam.pipe_configs) { + priv->dparam.pipe_configs = usbhsc_new_pipe; + priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_new_pipe); + } + break; + case USBHS_TYPE_RCAR_GEN3: + priv->pfunc = usbhs_rcar3_ops; + if (!priv->dparam.pipe_configs) { + priv->dparam.pipe_configs = usbhsc_new_pipe; + priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_new_pipe); } break; default: @@ -586,9 +600,9 @@ static int usbhs_probe(struct platform_device *pdev) dfunc->notify_hotplug = usbhsc_drvcllbck_notify_hotplug; /* set default param if platform doesn't have */ - if (!priv->dparam.pipe_type) { - priv->dparam.pipe_type = usbhsc_default_pipe_type; - priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type); + if (!priv->dparam.pipe_configs) { + priv->dparam.pipe_configs = usbhsc_default_pipe; + priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_default_pipe); } if (!priv->dparam.pio_dma_border) priv->dparam.pio_dma_border = 64; /* 64byte */ diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index c0f5c652d272..b4de70ee16d3 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -46,7 +46,7 @@ static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done) return -EINVAL; } -static struct usbhs_pkt_handle usbhsf_null_handler = { +static const struct usbhs_pkt_handle usbhsf_null_handler = { .prepare = usbhsf_null_handle, .try_run = usbhsf_null_handle, }; @@ -422,12 +422,12 @@ static int usbhs_dcp_dir_switch_done(struct usbhs_pkt *pkt, int *is_done) return 0; } -struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler = { +const struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler = { .prepare = usbhs_dcp_dir_switch_to_write, .try_run = usbhs_dcp_dir_switch_done, }; -struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler = { +const struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler = { .prepare = usbhs_dcp_dir_switch_to_read, .try_run = usbhs_dcp_dir_switch_done, }; @@ -449,7 +449,7 @@ static int usbhsf_dcp_data_stage_try_push(struct usbhs_pkt *pkt, int *is_done) return pkt->handler->prepare(pkt, is_done); } -struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler = { +const struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler = { .prepare = usbhsf_dcp_data_stage_try_push, }; @@ -488,7 +488,7 @@ static int usbhsf_dcp_data_stage_prepare_pop(struct usbhs_pkt *pkt, return pkt->handler->prepare(pkt, is_done); } -struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler = { +const struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler = { .prepare = usbhsf_dcp_data_stage_prepare_pop, }; @@ -600,7 +600,7 @@ static int usbhsf_pio_prepare_push(struct usbhs_pkt *pkt, int *is_done) return usbhsf_pio_try_push(pkt, is_done); } -struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { +const struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { .prepare = usbhsf_pio_prepare_push, .try_run = usbhsf_pio_try_push, }; @@ -730,7 +730,7 @@ usbhs_fifo_read_busy: return ret; } -struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler = { +const struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler = { .prepare = usbhsf_prepare_pop, .try_run = usbhsf_pio_try_pop, }; @@ -747,7 +747,7 @@ static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done) return 0; } -struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = { +const struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = { .prepare = usbhsf_ctrl_stage_end, .try_run = usbhsf_ctrl_stage_end, }; @@ -934,7 +934,7 @@ static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done) return 0; } -struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = { +const struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = { .prepare = usbhsf_dma_prepare_push, .dma_done = usbhsf_dma_push_done, }; @@ -1182,7 +1182,7 @@ static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done) return usbhsf_dma_pop_done_with_rx_irq(pkt, is_done); } -struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler = { +const struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler = { .prepare = usbhsf_dma_prepare_pop, .try_run = usbhsf_dma_try_pop, .dma_done = usbhsf_dma_pop_done diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index c7d9b86d51bf..8b98507d7abc 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h @@ -54,7 +54,7 @@ struct usbhs_pkt_handle; struct usbhs_pkt { struct list_head node; struct usbhs_pipe *pipe; - struct usbhs_pkt_handle *handler; + const struct usbhs_pkt_handle *handler; void (*done)(struct usbhs_priv *priv, struct usbhs_pkt *pkt); struct work_struct work; @@ -86,18 +86,18 @@ void usbhs_fifo_clear_dcp(struct usbhs_pipe *pipe); /* * packet info */ -extern struct usbhs_pkt_handle usbhs_fifo_pio_push_handler; -extern struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler; -extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; +extern const struct usbhs_pkt_handle usbhs_fifo_pio_push_handler; +extern const struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler; +extern const struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; -extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; -extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; +extern const struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; +extern const struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; -extern struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler; -extern struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler; +extern const struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler; +extern const struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler; -extern struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler; -extern struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler; +extern const struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler; +extern const struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler; void usbhs_pkt_init(struct usbhs_pkt *pkt); void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 8f7a78e70975..664b263e4b20 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -561,7 +561,7 @@ static int usbhsg_pipe_disable(struct usbhsg_uep *uep) if (!pkt) break; - usbhsg_queue_pop(uep, usbhsg_pkt_to_ureq(pkt), -ECONNRESET); + usbhsg_queue_pop(uep, usbhsg_pkt_to_ureq(pkt), -ESHUTDOWN); } usbhs_pipe_disable(pipe); @@ -1042,6 +1042,8 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) struct usbhsg_gpriv *gpriv; struct usbhsg_uep *uep; struct device *dev = usbhs_priv_to_dev(priv); + struct renesas_usbhs_driver_pipe_config *pipe_configs = + usbhs_get_dparam(priv, pipe_configs); int pipe_size = usbhs_get_dparam(priv, pipe_size); int i; int ret; @@ -1111,13 +1113,16 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) gpriv->gadget.ep0 = &uep->ep; usb_ep_set_maxpacket_limit(&uep->ep, 64); uep->ep.caps.type_control = true; - } - /* init normal pipe */ - else { - usb_ep_set_maxpacket_limit(&uep->ep, 512); - uep->ep.caps.type_iso = true; - uep->ep.caps.type_bulk = true; - uep->ep.caps.type_int = true; + } else { + /* init normal pipe */ + if (pipe_configs[i].type == USB_ENDPOINT_XFER_ISOC) + uep->ep.caps.type_iso = true; + if (pipe_configs[i].type == USB_ENDPOINT_XFER_BULK) + uep->ep.caps.type_bulk = true; + if (pipe_configs[i].type == USB_ENDPOINT_XFER_INT) + uep->ep.caps.type_int = true; + usb_ep_set_maxpacket_limit(&uep->ep, + pipe_configs[i].bufsize); list_add_tail(&uep->ep.ep_list, &gpriv->gadget.ep_list); } uep->ep.caps.dir_in = true; diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index bd050359926c..1a8e4c45c4c5 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -1414,7 +1414,8 @@ static void usbhsh_pipe_init_for_host(struct usbhs_priv *priv) { struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct usbhs_pipe *pipe; - u32 *pipe_type = usbhs_get_dparam(priv, pipe_type); + struct renesas_usbhs_driver_pipe_config *pipe_configs = + usbhs_get_dparam(priv, pipe_configs); int pipe_size = usbhs_get_dparam(priv, pipe_size); int old_type, dir_in, i; @@ -1442,15 +1443,15 @@ static void usbhsh_pipe_init_for_host(struct usbhs_priv *priv) * USB_ENDPOINT_XFER_BULK -> dir in * ... */ - dir_in = (pipe_type[i] == old_type); - old_type = pipe_type[i]; + dir_in = (pipe_configs[i].type == old_type); + old_type = pipe_configs[i].type; - if (USB_ENDPOINT_XFER_CONTROL == pipe_type[i]) { + if (USB_ENDPOINT_XFER_CONTROL == pipe_configs[i].type) { pipe = usbhs_dcp_malloc(priv); usbhsh_hpriv_to_dcp(hpriv) = pipe; } else { pipe = usbhs_pipe_malloc(priv, - pipe_type[i], + pipe_configs[i].type, dir_in); } diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 4f9c3356127a..78e9dba701c4 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -44,6 +44,15 @@ char *usbhs_pipe_name(struct usbhs_pipe *pipe) return usbhsp_pipe_name[usbhs_pipe_type(pipe)]; } +static struct renesas_usbhs_driver_pipe_config +*usbhsp_get_pipe_config(struct usbhs_priv *priv, int pipe_num) +{ + struct renesas_usbhs_driver_pipe_config *pipe_configs = + usbhs_get_dparam(priv, pipe_configs); + + return &pipe_configs[pipe_num]; +} + /* * DCPCTR/PIPEnCTR functions */ @@ -232,7 +241,7 @@ static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); int timeout = 1024; - u16 val; + u16 mask = usbhs_mod_is_host(priv) ? (CSSTS | PID_MASK) : PID_MASK; /* * make sure.... @@ -256,9 +265,7 @@ static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe) usbhs_pipe_disable(pipe); do { - val = usbhsp_pipectrl_get(pipe); - val &= CSSTS | PID_MASK; - if (!val) + if (!(usbhsp_pipectrl_get(pipe) & mask)) return 0; udelay(10); @@ -384,18 +391,6 @@ void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len) /* * pipe setup */ -static int usbhsp_possible_double_buffer(struct usbhs_pipe *pipe) -{ - /* - * only ISO / BULK pipe can use double buffer - */ - if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK) || - usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC)) - return 1; - - return 0; -} - static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, int is_host, int dir_in) @@ -412,7 +407,6 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, [USB_ENDPOINT_XFER_INT] = TYPE_INT, [USB_ENDPOINT_XFER_ISOC] = TYPE_ISO, }; - int is_double = usbhsp_possible_double_buffer(pipe); if (usbhs_pipe_is_dcp(pipe)) return -EINVAL; @@ -434,10 +428,7 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK)) bfre = 0; /* FIXME */ - /* DBLB */ - if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC) || - usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK)) - dblb = (is_double) ? DBLB : 0; + /* DBLB: see usbhs_pipe_config_update() */ /* CNTMD */ if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK)) @@ -473,13 +464,13 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); - struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); struct device *dev = usbhs_priv_to_dev(priv); int pipe_num = usbhs_pipe_number(pipe); - int is_double = usbhsp_possible_double_buffer(pipe); u16 buff_size; u16 bufnmb; u16 bufnmb_cnt; + struct renesas_usbhs_driver_pipe_config *pipe_config = + usbhsp_get_pipe_config(priv, pipe_num); /* * PIPEBUF @@ -489,56 +480,13 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe) * - "Features" - "Pipe configuration" * - "Operation" - "FIFO Buffer Memory" * - "Operation" - "Pipe Control" - * - * ex) if pipe6 - pipe9 are USB_ENDPOINT_XFER_INT (SH7724) - * - * BUFNMB: PIPE - * 0: pipe0 (DCP 256byte) - * 1: - - * 2: - - * 3: - - * 4: pipe6 (INT 64byte) - * 5: pipe7 (INT 64byte) - * 6: pipe8 (INT 64byte) - * 7: pipe9 (INT 64byte) - * 8 - xx: free (for BULK, ISOC) */ - - /* - * FIXME - * - * it doesn't have good buffer allocator - * - * DCP : 256 byte - * BULK: 512 byte - * INT : 64 byte - * ISOC: 512 byte - */ - if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_CONTROL)) - buff_size = 256; - else if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT)) - buff_size = 64; - else - buff_size = 512; + buff_size = pipe_config->bufsize; + bufnmb = pipe_config->bufnum; /* change buff_size to register value */ bufnmb_cnt = (buff_size / 64) - 1; - /* BUFNMB has been reserved for INT pipe - * see above */ - if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT)) { - bufnmb = pipe_num - 2; - } else { - bufnmb = info->bufnmb_last; - info->bufnmb_last += bufnmb_cnt + 1; - - /* - * double buffer - */ - if (is_double) - info->bufnmb_last += bufnmb_cnt + 1; - } - dev_dbg(dev, "pipe : %d : buff_size 0x%x: bufnmb 0x%x\n", pipe_num, buff_size, bufnmb); @@ -549,8 +497,13 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe) void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel, u16 epnum, u16 maxp) { + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + int pipe_num = usbhs_pipe_number(pipe); + struct renesas_usbhs_driver_pipe_config *pipe_config = + usbhsp_get_pipe_config(priv, pipe_num); + u16 dblb = pipe_config->double_buf ? DBLB : 0; + if (devsel > 0xA) { - struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct device *dev = usbhs_priv_to_dev(priv); dev_err(dev, "devsel error %d\n", devsel); @@ -568,7 +521,7 @@ void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel, maxp); if (!usbhs_pipe_is_dcp(pipe)) - usbhsp_pipe_cfg_set(pipe, 0x000F, epnum); + usbhsp_pipe_cfg_set(pipe, 0x000F | DBLB, epnum | dblb); } /* @@ -708,23 +661,7 @@ void usbhs_pipe_init(struct usbhs_priv *priv, struct usbhs_pipe *pipe; int i; - /* - * FIXME - * - * driver needs good allocator. - * - * find first free buffer area (BULK, ISOC) - * (DCP, INT area is fixed) - * - * buffer number 0 - 3 have been reserved for DCP - * see - * usbhsp_to_bufnmb - */ - info->bufnmb_last = 4; usbhs_for_each_pipe_with_dcp(pipe, priv, i) { - if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT)) - info->bufnmb_last++; - usbhsp_flags_init(pipe); pipe->fifo = NULL; pipe->mod_private = NULL; @@ -851,12 +788,13 @@ int usbhs_pipe_probe(struct usbhs_priv *priv) struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); struct usbhs_pipe *pipe; struct device *dev = usbhs_priv_to_dev(priv); - u32 *pipe_type = usbhs_get_dparam(priv, pipe_type); + struct renesas_usbhs_driver_pipe_config *pipe_configs = + usbhs_get_dparam(priv, pipe_configs); int pipe_size = usbhs_get_dparam(priv, pipe_size); int i; /* This driver expects 1st pipe is DCP */ - if (pipe_type[0] != USB_ENDPOINT_XFER_CONTROL) { + if (pipe_configs[0].type != USB_ENDPOINT_XFER_CONTROL) { dev_err(dev, "1st PIPE is not DCP\n"); return -EINVAL; } @@ -876,10 +814,10 @@ int usbhs_pipe_probe(struct usbhs_priv *priv) pipe->priv = priv; usbhs_pipe_type(pipe) = - pipe_type[i] & USB_ENDPOINT_XFERTYPE_MASK; + pipe_configs[i].type & USB_ENDPOINT_XFERTYPE_MASK; dev_dbg(dev, "pipe %x\t: %s\n", - i, usbhsp_pipe_name[pipe_type[i]]); + i, usbhsp_pipe_name[pipe_configs[i].type]); } return 0; diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index b0bc7b603016..7835747f9803 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -38,7 +38,7 @@ struct usbhs_pipe { #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2) #define USBHS_PIPE_FLAGS_IS_RUNNING (1 << 3) - struct usbhs_pkt_handle *handler; + const struct usbhs_pkt_handle *handler; void *mod_private; }; @@ -46,7 +46,6 @@ struct usbhs_pipe { struct usbhs_pipe_info { struct usbhs_pipe *pipe; int size; /* array size of "pipe" */ - int bufnmb_last; /* FIXME : driver needs good allocator */ int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map); }; diff --git a/drivers/usb/renesas_usbhs/rcar3.c b/drivers/usb/renesas_usbhs/rcar3.c new file mode 100644 index 000000000000..38b01f2aeeb0 --- /dev/null +++ b/drivers/usb/renesas_usbhs/rcar3.c @@ -0,0 +1,54 @@ +/* + * Renesas USB driver R-Car Gen. 3 initialization and power control + * + * Copyright (C) 2016 Renesas Electronics Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/io.h> +#include "common.h" +#include "rcar3.h" + +#define LPSTS 0x102 +#define UGCTRL2 0x184 /* 32-bit register */ + +/* Low Power Status register (LPSTS) */ +#define LPSTS_SUSPM 0x4000 + +/* USB General control register 2 (UGCTRL2), bit[31:6] should be 0 */ +#define UGCTRL2_RESERVED_3 0x00000001 /* bit[3:0] should be B'0001 */ +#define UGCTRL2_USB0SEL_OTG 0x00000030 + +void usbhs_write32(struct usbhs_priv *priv, u32 reg, u32 data) +{ + iowrite32(data, priv->base + reg); +} + +static int usbhs_rcar3_power_ctrl(struct platform_device *pdev, + void __iomem *base, int enable) +{ + struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); + + usbhs_write32(priv, UGCTRL2, UGCTRL2_RESERVED_3 | UGCTRL2_USB0SEL_OTG); + + if (enable) + usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM); + else + usbhs_bset(priv, LPSTS, LPSTS_SUSPM, 0); + + return 0; +} + +static int usbhs_rcar3_get_id(struct platform_device *pdev) +{ + return USBHS_GADGET; +} + +const struct renesas_usbhs_platform_callback usbhs_rcar3_ops = { + .power_ctrl = usbhs_rcar3_power_ctrl, + .get_id = usbhs_rcar3_get_id, +}; diff --git a/drivers/usb/renesas_usbhs/rcar3.h b/drivers/usb/renesas_usbhs/rcar3.h new file mode 100644 index 000000000000..5f850b23ff18 --- /dev/null +++ b/drivers/usb/renesas_usbhs/rcar3.h @@ -0,0 +1,3 @@ +#include "common.h" + +extern const struct renesas_usbhs_platform_callback usbhs_rcar3_ops; |