From 1113a79b2a31a9051b3a1afd3edbbdf013f88833 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Wed, 14 Dec 2011 08:16:03 +0200 Subject: USB: ULPI: switch argument type from u8 to unsigned There is no benefit in using u8, so switch to unsigned to reduce the binary image size (by 20 bytes). Signed-off-by: Igor Grinberg Acked-by: Simon Glass diff --git a/drivers/usb/ulpi/ulpi.c b/drivers/usb/ulpi/ulpi.c index 805e29d..1371aa6 100644 --- a/drivers/usb/ulpi/ulpi.c +++ b/drivers/usb/ulpi/ulpi.c @@ -79,9 +79,9 @@ int ulpi_init(u32 ulpi_viewport) return ulpi_integrity_check(ulpi_viewport); } -int ulpi_select_transceiver(u32 ulpi_viewport, u8 speed) +int ulpi_select_transceiver(u32 ulpi_viewport, unsigned speed) { - u8 tspeed = ULPI_FC_FULL_SPEED; + u32 tspeed = ULPI_FC_FULL_SPEED; u32 val; switch (speed) { @@ -127,9 +127,9 @@ int ulpi_set_pd(u32 ulpi_viewport, int enable) return ulpi_write(ulpi_viewport, reg, val); } -int ulpi_opmode_sel(u32 ulpi_viewport, u8 opmode) +int ulpi_opmode_sel(u32 ulpi_viewport, unsigned opmode) { - u8 topmode = ULPI_FC_OPMODE_NORMAL; + u32 topmode = ULPI_FC_OPMODE_NORMAL; u32 val; switch (opmode) { @@ -154,7 +154,7 @@ int ulpi_opmode_sel(u32 ulpi_viewport, u8 opmode) return ulpi_write(ulpi_viewport, &ulpi->function_ctrl, val); } -int ulpi_serial_mode_enable(u32 ulpi_viewport, u8 smode) +int ulpi_serial_mode_enable(u32 ulpi_viewport, unsigned smode) { switch (smode) { case ULPI_IFACE_6_PIN_SERIAL_MODE: diff --git a/include/usb/ulpi.h b/include/usb/ulpi.h index d871290..dc78a59 100644 --- a/include/usb/ulpi.h +++ b/include/usb/ulpi.h @@ -41,7 +41,7 @@ int ulpi_init(u32 ulpi_viewport); * ULPI_FC_LOW_SPEED, ULPI_FC_FS4LS * returns 0 on success, ULPI_ERROR on failure. */ -int ulpi_select_transceiver(u32 ulpi_viewport, u8 speed); +int ulpi_select_transceiver(u32 ulpi_viewport, unsigned speed); /* * Enable/disable VBUS. @@ -66,7 +66,7 @@ int ulpi_set_pd(u32 ulpi_viewport, int enable); * * returns 0 on success, ULPI_ERROR on failure. */ -int ulpi_opmode_sel(u32 ulpi_viewport, u8 opmode); +int ulpi_opmode_sel(u32 ulpi_viewport, unsigned opmode); /* * Switch to Serial Mode. @@ -78,7 +78,7 @@ int ulpi_opmode_sel(u32 ulpi_viewport, u8 opmode); * Switches immediately to Serial Mode. * To return from Serial Mode, STP line needs to be asserted. */ -int ulpi_serial_mode_enable(u32 ulpi_viewport, u8 smode); +int ulpi_serial_mode_enable(u32 ulpi_viewport, unsigned smode); /* * Put PHY into low power mode. -- cgit v0.10.2 From 4256101f8ca908438ddbb5bd649274dbfd936f22 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Mon, 12 Dec 2011 12:08:33 +0200 Subject: USB: ULPI: clean a mixup of return types Clean a mixup between u32 and int as a return type for functions returning error values. Use int as it is native (and widely used) return type. Signed-off-by: Igor Grinberg Acked-by: Simon Glass diff --git a/drivers/usb/ulpi/ulpi-viewport.c b/drivers/usb/ulpi/ulpi-viewport.c index fa2e004..490fb0e 100644 --- a/drivers/usb/ulpi/ulpi-viewport.c +++ b/drivers/usb/ulpi/ulpi-viewport.c @@ -98,7 +98,7 @@ static int ulpi_request(u32 ulpi_viewport, u32 value) return err; } -u32 ulpi_write(u32 ulpi_viewport, u8 *reg, u32 value) +int ulpi_write(u32 ulpi_viewport, u8 *reg, u32 value) { u32 val = ULPI_RWRUN | ULPI_RWCTRL | ((u32)reg << 16) | (value & 0xff); @@ -107,7 +107,7 @@ u32 ulpi_write(u32 ulpi_viewport, u8 *reg, u32 value) u32 ulpi_read(u32 ulpi_viewport, u8 *reg) { - u32 err; + int err; u32 val = ULPI_RWRUN | ((u32)reg << 16); err = ulpi_request(ulpi_viewport, val); diff --git a/drivers/usb/ulpi/ulpi.c b/drivers/usb/ulpi/ulpi.c index 1371aa6..f3f293f 100644 --- a/drivers/usb/ulpi/ulpi.c +++ b/drivers/usb/ulpi/ulpi.c @@ -39,8 +39,8 @@ static struct ulpi_regs *ulpi = (struct ulpi_regs *)0; static int ulpi_integrity_check(u32 ulpi_viewport) { - u32 err, val, tval = ULPI_TEST_VALUE; - int i; + u32 val, tval = ULPI_TEST_VALUE; + int err, i; /* Use the 'special' test value to check all bits */ for (i = 0; i < 2; i++, tval <<= 1) { @@ -171,7 +171,7 @@ int ulpi_serial_mode_enable(u32 ulpi_viewport, unsigned smode) int ulpi_suspend(u32 ulpi_viewport) { - u32 err; + int err; err = ulpi_write(ulpi_viewport, &ulpi->function_ctrl_clear, ULPI_FC_SUSPENDM); @@ -214,7 +214,7 @@ int ulpi_reset_wait(u32) __attribute__((weak, alias("__ulpi_reset_wait"))); int ulpi_reset(u32 ulpi_viewport) { - u32 err; + int err; err = ulpi_write(ulpi_viewport, &ulpi->function_ctrl_set, ULPI_FC_RESET); diff --git a/include/usb/ulpi.h b/include/usb/ulpi.h index dc78a59..802f077 100644 --- a/include/usb/ulpi.h +++ b/include/usb/ulpi.h @@ -108,7 +108,7 @@ int ulpi_reset(u32 ulpi_viewport); * * returns 0 on success, ULPI_ERROR on failure. */ -u32 ulpi_write(u32 ulpi_viewport, u8 *reg, u32 value); +int ulpi_write(u32 ulpi_viewport, u8 *reg, u32 value); /* * Read the ULPI PHY register content via the viewport. -- cgit v0.10.2 From cf9f95f29390c2cdce80bab86d24b002c8d08f58 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Mon, 12 Dec 2011 12:08:34 +0200 Subject: USB: ULPI: increase error case verbosity Add the argument value to the error message. Signed-off-by: Igor Grinberg Acked-by: Simon Glass diff --git a/drivers/usb/ulpi/ulpi.c b/drivers/usb/ulpi/ulpi.c index f3f293f..6202227 100644 --- a/drivers/usb/ulpi/ulpi.c +++ b/drivers/usb/ulpi/ulpi.c @@ -92,8 +92,8 @@ int ulpi_select_transceiver(u32 ulpi_viewport, unsigned speed) tspeed = speed; break; default: - printf("ULPI: %s: wrong transceiver speed specified, " - "falling back to full speed\n", __func__); + printf("ULPI: %s: wrong transceiver speed specified: %u, " + "falling back to full speed\n", __func__, speed); } val = ulpi_read(ulpi_viewport, &ulpi->function_ctrl); @@ -140,8 +140,8 @@ int ulpi_opmode_sel(u32 ulpi_viewport, unsigned opmode) topmode = opmode; break; default: - printf("ULPI: %s: wrong OpMode specified, " - "falling back to OpMode Normal\n", __func__); + printf("ULPI: %s: wrong OpMode specified: %u, " + "falling back to OpMode Normal\n", __func__, opmode); } val = ulpi_read(ulpi_viewport, &ulpi->function_ctrl); @@ -161,8 +161,8 @@ int ulpi_serial_mode_enable(u32 ulpi_viewport, unsigned smode) case ULPI_IFACE_3_PIN_SERIAL_MODE: break; default: - printf("ULPI: %s: unrecognized Serial Mode specified\n", - __func__); + printf("ULPI: %s: unrecognized Serial Mode specified: %u\n", + __func__, smode); return ULPI_ERROR; } -- cgit v0.10.2 From d70a560fd77b8a357257c7baa0a24b326c097bc3 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Mon, 12 Dec 2011 12:08:35 +0200 Subject: README: add documentation for CONFIG_USB_ULPI* Add documentation for CONFIG_USB_ULPI and CONFIG_USB_ULPI_VIEWPORT configuration options. Signed-off-by: Igor Grinberg diff --git a/README b/README index ff72e47..6fe1e0f 100644 --- a/README +++ b/README @@ -1185,6 +1185,14 @@ The following options need to be configured: for your device - CONFIG_USBD_PRODUCTID 0xFFFF +- ULPI Layer Support: + The ULPI (UTMI Low Pin (count) Interface) PHYs are supported via + the generic ULPI layer. The generic layer accesses the ULPI PHY + via the platform viewport, so you need both the genric layer and + the viewport enabled. Currently only Chipidea/ARC based + viewport is supported. + To enable the ULPI layer support, define CONFIG_USB_ULPI and + CONFIG_USB_ULPI_VIEWPORT in your board configuration file. - MMC Support: The MMC controller on the Intel PXA is supported. To -- cgit v0.10.2 From ddc7e541ae62f29d85b35cdf8d12c7322d353d51 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Thu, 15 Dec 2011 10:32:12 +0100 Subject: usb:gadget:s5p Enable the USB Gadget framework at Exynos4210 (C210 Universal) This commit enables support for USB Gadgets on the Exynos4210 (C210 Universal) reference target. Signed-off-by: Lukasz Majewski Signed-off-by: Kyungmin Park Cc: Minkyu Kang CC: Remy Bohmer diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h index 4464d27..6d97b99 100644 --- a/arch/arm/include/asm/arch-exynos/cpu.h +++ b/arch/arm/include/asm/arch-exynos/cpu.h @@ -46,6 +46,7 @@ #define EXYNOS4_ADC_BASE 0x13910000 #define EXYNOS4_PWMTIMER_BASE 0x139D0000 #define EXYNOS4_MODEM_BASE 0x13A00000 +#define EXYNOS4_USBPHY_CONTROL 0x10020704 #ifndef __ASSEMBLY__ #include diff --git a/board/samsung/universal_c210/universal.c b/board/samsung/universal_c210/universal.c index f9b8a76..8393e4f 100644 --- a/board/samsung/universal_c210/universal.c +++ b/board/samsung/universal_c210/universal.c @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include DECLARE_GLOBAL_DATA_PTR; @@ -253,3 +256,48 @@ int board_mmc_init(bd_t *bis) } #endif + +#ifdef CONFIG_USB_GADGET +static int s5pc210_phy_control(int on) +{ + int ret; + struct pmic *p = get_pmic(); + + if (pmic_probe(p)) + return -1; + + if (on) { + ret |= pmic_set_output(p, + MAX8998_REG_BUCK_ACTIVE_DISCHARGE3, + MAX8998_SAFEOUT1, LDO_ON); + ret |= pmic_set_output(p, MAX8998_REG_ONOFF1, + MAX8998_LDO3, LDO_ON); + ret |= pmic_set_output(p, MAX8998_REG_ONOFF2, + MAX8998_LDO8, LDO_ON); + + } else { + ret |= pmic_set_output(p, MAX8998_REG_ONOFF2, + MAX8998_LDO8, LDO_OFF); + ret |= pmic_set_output(p, MAX8998_REG_ONOFF1, + MAX8998_LDO3, LDO_OFF); + ret |= pmic_set_output(p, + MAX8998_REG_BUCK_ACTIVE_DISCHARGE3, + MAX8998_SAFEOUT1, LDO_OFF); + } + + if (ret) { + puts("MAX8998 LDO setting error!\n"); + return -1; + } + + return 0; +} + +struct s3c_plat_otg_data s5pc210_otg_data = { + .phy_control = s5pc210_phy_control, + .regs_phy = EXYNOS4_USBPHY_BASE, + .regs_otg = EXYNOS4_USBOTG_BASE, + .usb_phy_ctrl = EXYNOS4_USBPHY_CONTROL, + .usb_flags = PHY0_SLEEP, +}; +#endif diff --git a/include/configs/s5pc210_universal.h b/include/configs/s5pc210_universal.h index b36ad3a..be000cb 100644 --- a/include/configs/s5pc210_universal.h +++ b/include/configs/s5pc210_universal.h @@ -262,4 +262,8 @@ #define CONFIG_PMIC_I2C #define CONFIG_PMIC_MAX8998 +#define CONFIG_USB_GADGET +#define CONFIG_USB_GADGET_S3C_UDC_OTG +#define CONFIG_USB_GADGET_DUALSPEED + #endif /* __CONFIG_H */ diff --git a/include/max8998_pmic.h b/include/max8998_pmic.h index bf28820..10c892a 100644 --- a/include/max8998_pmic.h +++ b/include/max8998_pmic.h @@ -76,6 +76,7 @@ enum { #define MAX8998_LDO3 (1 << 2) #define MAX8998_LDO8 (1 << 5) +#define MAX8998_SAFEOUT1 (1 << 4) #define MAX8998_I2C_ADDR (0xCC >> 1) -- cgit v0.10.2 From b2fb47f1873ae812ce33129996a22b11a36d0aa9 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 15 Dec 2011 08:40:51 -0700 Subject: USB: Use (get|put)_unaligned for accessing wMaxPacketSize In 9792987721c7980453fe6447c3fa6593b44f8458 Stefan describes a usecase where the previous behavior of leaving wMaxPacketSize be unaligned caused fatal problems. The initial fix for this problem was incomplete however as it showed another cases of non-aligned access that previously worked implicitly. This switches to making sure that all access of wMaxPacketSize are done via (get|put)_unaligned. In order to maintain a level of readability to the code in some cases we now use a variable for the value of wMaxPacketSize and in others, a macro. Cc: Minkyu Kang Cc: Remy Bohmer OpenRISC: Tested-by: Stefan Kristiansson Beagleboard xM, Pandaboard run-tested, s5p_goni build-tested. Signed-off-by: Tom Rini diff --git a/common/cmd_usb.c b/common/cmd_usb.c index d4ec2a2..320667f 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -240,7 +241,7 @@ void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc) printf("Interrupt"); break; } - printf(" MaxPacket %d", epdesc->wMaxPacketSize); + printf(" MaxPacket %d", get_unaligned(&epdesc->wMaxPacketSize)); if ((epdesc->bmAttributes & 0x03) == 0x3) printf(" Interval %dms", epdesc->bInterval); printf("\n"); diff --git a/common/usb.c b/common/usb.c index 4418c70..63a11c8 100644 --- a/common/usb.c +++ b/common/usb.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #ifdef CONFIG_4xx @@ -279,30 +280,32 @@ usb_set_maxpacket_ep(struct usb_device *dev, int if_idx, int ep_idx) { int b; struct usb_endpoint_descriptor *ep; + u16 ep_wMaxPacketSize; ep = &dev->config.if_desc[if_idx].ep_desc[ep_idx]; b = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + ep_wMaxPacketSize = get_unaligned(&ep->wMaxPacketSize); if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */ - dev->epmaxpacketout[b] = ep->wMaxPacketSize; - dev->epmaxpacketin[b] = ep->wMaxPacketSize; + dev->epmaxpacketout[b] = ep_wMaxPacketSize; + dev->epmaxpacketin[b] = ep_wMaxPacketSize; USB_PRINTF("##Control EP epmaxpacketout/in[%d] = %d\n", b, dev->epmaxpacketin[b]); } else { if ((ep->bEndpointAddress & 0x80) == 0) { /* OUT Endpoint */ - if (ep->wMaxPacketSize > dev->epmaxpacketout[b]) { - dev->epmaxpacketout[b] = ep->wMaxPacketSize; + if (ep_wMaxPacketSize > dev->epmaxpacketout[b]) { + dev->epmaxpacketout[b] = ep_wMaxPacketSize; USB_PRINTF("##EP epmaxpacketout[%d] = %d\n", b, dev->epmaxpacketout[b]); } } else { /* IN Endpoint */ - if (ep->wMaxPacketSize > dev->epmaxpacketin[b]) { - dev->epmaxpacketin[b] = ep->wMaxPacketSize; + if (ep_wMaxPacketSize > dev->epmaxpacketin[b]) { + dev->epmaxpacketin[b] = ep_wMaxPacketSize; USB_PRINTF("##EP epmaxpacketin[%d] = %d\n", b, dev->epmaxpacketin[b]); } @@ -333,6 +336,7 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno) struct usb_descriptor_header *head; int index, ifno, epno, curr_if_num; int i; + u16 ep_wMaxPacketSize; ifno = -1; epno = -1; @@ -378,8 +382,15 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno) dev->config.if_desc[ifno].no_of_ep++; memcpy(&dev->config.if_desc[ifno].ep_desc[epno], &buffer[index], buffer[index]); - le16_to_cpus(&(dev->config.if_desc[ifno].ep_desc[epno].\ - wMaxPacketSize)); + ep_wMaxPacketSize = get_unaligned(&dev->config.\ + if_desc[ifno].\ + ep_desc[epno].\ + wMaxPacketSize); + put_unaligned(le16_to_cpu(ep_wMaxPacketSize), + &dev->config.\ + if_desc[ifno].\ + ep_desc[epno].\ + wMaxPacketSize); USB_PRINTF("if %d, ep %d\n", ifno, epno); break; default: diff --git a/drivers/serial/usbtty.c b/drivers/serial/usbtty.c index e2e87fe..a263b2c 100644 --- a/drivers/serial/usbtty.c +++ b/drivers/serial/usbtty.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "usbtty.h" #include "usb_cdc_acm.h" #include "usbdescriptors.h" @@ -626,6 +627,9 @@ static void usbtty_init_strings (void) usb_strings = usbtty_string_table; } +#define init_wMaxPacketSize(x) le16_to_cpu(get_unaligned(\ + &ep_descriptor_ptrs[(x) - 1]->wMaxPacketSize)); + static void usbtty_init_instances (void) { int i; @@ -688,14 +692,12 @@ static void usbtty_init_instances (void) endpoint_instance[i].rcv_attributes = ep_descriptor_ptrs[i - 1]->bmAttributes; - endpoint_instance[i].rcv_packetSize = - le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize); + endpoint_instance[i].rcv_packetSize = init_wMaxPacketSize(i); endpoint_instance[i].tx_attributes = ep_descriptor_ptrs[i - 1]->bmAttributes; - endpoint_instance[i].tx_packetSize = - le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize); + endpoint_instance[i].tx_packetSize = init_wMaxPacketSize(i); endpoint_instance[i].tx_attributes = ep_descriptor_ptrs[i - 1]->bmAttributes; diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 1896489..5b8776e 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "gadget_chips.h" #define isdigit(c) ('0' <= (c) && (c) <= '9') @@ -127,7 +128,7 @@ static int ep_matches( * where it's an output parameter representing the full speed limit. * the usb spec fixes high speed bulk maxpacket at 512 bytes. */ - max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize); + max = 0x7ff & le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)); switch (type) { case USB_ENDPOINT_XFER_INT: /* INT: limit 64 bytes full speed, 1024 high speed */ @@ -143,7 +144,8 @@ static int ep_matches( return 0; /* BOTH: "high bandwidth" works only at high speed */ - if ((desc->wMaxPacketSize & __constant_cpu_to_le16(3<<11))) { + if ((get_unaligned(&desc->wMaxPacketSize) & + __constant_cpu_to_le16(3<<11))) { if (!gadget->is_dualspeed) return 0; /* configure your hardware with enough buffering!! */ @@ -176,7 +178,7 @@ static int ep_matches( /* min() doesn't work on bitfields with gcc-3.5 */ if (size > 64) size = 64; - desc->wMaxPacketSize = cpu_to_le16(size); + put_unaligned(cpu_to_le16(size), &desc->wMaxPacketSize); } return 1; } diff --git a/drivers/usb/gadget/s3c_udc_otg.c b/drivers/usb/gadget/s3c_udc_otg.c index 5a3ac78..901fac9 100644 --- a/drivers/usb/gadget/s3c_udc_otg.c +++ b/drivers/usb/gadget/s3c_udc_otg.c @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -586,7 +587,8 @@ static int s3c_ep_enable(struct usb_ep *_ep, if (!_ep || !desc || ep->desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || ep->bEndpointAddress != desc->bEndpointAddress - || ep_maxpacket(ep) < le16_to_cpu(desc->wMaxPacketSize)) { + || ep_maxpacket(ep) < + le16_to_cpu(get_unaligned(&desc->wMaxPacketSize))) { DEBUG("%s: bad ep or descriptor\n", __func__); return -EINVAL; @@ -603,8 +605,8 @@ static int s3c_ep_enable(struct usb_ep *_ep, /* hardware _could_ do smaller, but driver doesn't */ if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK - && le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(ep)) - || !desc->wMaxPacketSize) { + && le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)) != + ep_maxpacket(ep)) || !get_unaligned(&desc->wMaxPacketSize)) { DEBUG("%s: bad %s maxpacket\n", __func__, _ep->name); return -ERANGE; @@ -620,7 +622,7 @@ static int s3c_ep_enable(struct usb_ep *_ep, ep->stopped = 0; ep->desc = desc; ep->pio_irqs = 0; - ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); + ep->ep.maxpacket = le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)); /* Reset halt state */ s3c_udc_set_nak(ep); diff --git a/include/usbdescriptors.h b/include/usbdescriptors.h index 392fcf5..2dec3b9 100644 --- a/include/usbdescriptors.h +++ b/include/usbdescriptors.h @@ -199,7 +199,7 @@ struct usb_endpoint_descriptor { u8 bmAttributes; u16 wMaxPacketSize; u8 bInterval; -} __attribute__ ((packed)) __attribute__ ((aligned(2))); +} __attribute__ ((packed)); struct usb_interface_descriptor { u8 bLength; -- cgit v0.10.2