diff mbox

[U-Boot,v2,3/3] arm: odroid: usb: add support for usb host including ethernet

Message ID 1413827523-8341-3-git-send-email-suriyan.r@gmail.com
State Changes Requested
Delegated to: Minkyu Kang
Headers show

Commit Message

Suriyan Ramasami Oct. 20, 2014, 5:52 p.m. UTC
This change adds support for enabling the USB host features of the board.
This includes the USB3503A hub and the SMC LAN9730 ethernet controller
as well.

Credit goes to Tushar Berara for the function set_usb_ethaddr().

Signed-off-by: Suriyan Ramasami <suriyan.r@gmail.com>

---
v2:
 * Removed an unneeded header file from ehci-exynos.c
 * Fix indentation in the dts file
---
 arch/arm/dts/exynos4412-odroid.dts      | 11 +++++++
 arch/arm/include/asm/arch-exynos/cpu.h  |  2 ++
 arch/arm/include/asm/arch-exynos/ehci.h | 13 ++++++++
 board/samsung/odroid/odroid.c           | 55 +++++++++++++++++++++++++++++++++
 drivers/usb/host/ehci-exynos.c          | 51 +++++++++++++++++++++++++-----
 include/configs/odroid.h                | 13 ++++++++
 6 files changed, 137 insertions(+), 8 deletions(-)

Comments

Minkyu Kang Oct. 24, 2014, 4:58 a.m. UTC | #1
Dear Suriyan Ramasami,

On 21/10/14 02:52, Suriyan Ramasami wrote:
> This change adds support for enabling the USB host features of the board.
> This includes the USB3503A hub and the SMC LAN9730 ethernet controller
> as well.
> 
> Credit goes to Tushar Berara for the function set_usb_ethaddr().
> 
> Signed-off-by: Suriyan Ramasami <suriyan.r@gmail.com>
> 
> ---
> v2:
>  * Removed an unneeded header file from ehci-exynos.c
>  * Fix indentation in the dts file
> ---
>  arch/arm/dts/exynos4412-odroid.dts      | 11 +++++++
>  arch/arm/include/asm/arch-exynos/cpu.h  |  2 ++
>  arch/arm/include/asm/arch-exynos/ehci.h | 13 ++++++++
>  board/samsung/odroid/odroid.c           | 55 +++++++++++++++++++++++++++++++++
>  drivers/usb/host/ehci-exynos.c          | 51 +++++++++++++++++++++++++-----
>  include/configs/odroid.h                | 13 ++++++++
>  6 files changed, 137 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm/dts/exynos4412-odroid.dts b/arch/arm/dts/exynos4412-odroid.dts
> index 24d0bf1..ac5fece 100644
> --- a/arch/arm/dts/exynos4412-odroid.dts
> +++ b/arch/arm/dts/exynos4412-odroid.dts
> @@ -67,4 +67,15 @@
>  		div = <0x3>;
>  		index = <4>;
>  	};
> +
> +	ehci@12580000 {
> +		compatible = "samsung,exynos-ehci";
> +		reg = <0x12580000 0x100>;
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		phy {
> +			compatible = "samsung,exynos-usb-phy";
> +			reg = <0x125B0000 0x100>;
> +		};
> +	};
>  };
> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
> index ba71714..fda21fb 100644
> --- a/arch/arm/include/asm/arch-exynos/cpu.h
> +++ b/arch/arm/include/asm/arch-exynos/cpu.h
> @@ -18,6 +18,8 @@
>  
>  #define EXYNOS4_GPIO_PART3_BASE		0x03860000
>  #define EXYNOS4_PRO_ID			0x10000000
> +#define EXYNOS4_GUID_LOW		0x10000014
> +#define EXYNOS4_GUID_HIGH		0x10000018
>  #define EXYNOS4_SYSREG_BASE		0x10010000
>  #define EXYNOS4_POWER_BASE		0x10020000
>  #define EXYNOS4_SWRESET			0x10020400
> diff --git a/arch/arm/include/asm/arch-exynos/ehci.h b/arch/arm/include/asm/arch-exynos/ehci.h
> index d2d70bd..3800fa9 100644
> --- a/arch/arm/include/asm/arch-exynos/ehci.h
> +++ b/arch/arm/include/asm/arch-exynos/ehci.h
> @@ -12,6 +12,13 @@
>  
>  #define CLK_24MHZ		5
>  
> +#define PHYPWR_NORMAL_MASK_PHY0                 (0x39 << 0)
> +#define PHYPWR_NORMAL_MASK_PHY1                 (0x7 << 6)
> +#define PHYPWR_NORMAL_MASK_HSIC0                (0x7 << 9)
> +#define PHYPWR_NORMAL_MASK_HSIC1                (0x7 << 12)
> +#define RSTCON_HOSTPHY_SWRST                    (0xf << 3)
> +#define RSTCON_SWRST                            (0x1 << 0)
> +
>  #define HOST_CTRL0_PHYSWRSTALL			(1 << 31)
>  #define HOST_CTRL0_COMMONON_N			(1 << 9)
>  #define HOST_CTRL0_SIDDQ			(1 << 6)
> @@ -61,6 +68,12 @@ struct exynos_usb_phy {
>  	unsigned int usbotgtune;
>  };
>  
> +struct exynos4412_usb_phy {
> +	unsigned int usbphyctrl;
> +	unsigned int usbphyclk;
> +	unsigned int usbphyrstcon;
> +};
> +
>  /* Switch on the VBUS power. */
>  int board_usb_vbus_init(void);
>  
> diff --git a/board/samsung/odroid/odroid.c b/board/samsung/odroid/odroid.c
> index 5edb250..6c78b67 100644
> --- a/board/samsung/odroid/odroid.c
> +++ b/board/samsung/odroid/odroid.c
> @@ -453,9 +453,64 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
>  	.usb_phy_ctrl	= EXYNOS4X12_USBPHY_CONTROL,
>  	.usb_flags	= PHY0_SLEEP,
>  };
> +#endif
> +
> +#if defined(CONFIG_USB_GADGET) || defined(CONFIG_CMD_USB)
> +
> +#ifdef CONFIG_CMD_USB
> +static void set_usb_ethaddr(void)
> +{
> +	int i;
> +	uchar mac[6];
> +	unsigned int guid_high = readl(EXYNOS4_GUID_HIGH);
> +	unsigned int guid_low = readl(EXYNOS4_GUID_LOW);

We don't allow direct access.
Is it special register? I can't find this register on TRM.
If so you can make inline function at cpu.h instead.

> +
> +	for (i = 0; i < 2; i++)
> +		mac[i] = (guid_high >> (8 * (1 - i))) & 0xFF;
> +
> +	for (i = 0; i < 4; i++)
> +		mac[i+2] = (guid_low >> (8 * (3 - i))) & 0xFF;

please add space. i + 2

> +
> +	/* mark it as not multicast and outside official 80211 MAC namespace */
> +	mac[0] = (mac[0] & ~0x1) | 0x2;
> +
> +	eth_setenv_enetaddr("ethaddr", mac);
> +	eth_setenv_enetaddr("usbethaddr", mac);
> +}
> +#endif
>  
>  int board_usb_init(int index, enum usb_init_type init)
>  {
> +#ifdef CONFIG_CMD_USB
> +	struct pmic *p_pmic;
> +
> +	/* Set Ref freq 0 => 24MHz, 1 => 26MHz*/
> +	/* Odroid Us have it at 24MHz, Odroid Xs at 26MHz */
> +	if (gd->board_type == ODROID_TYPE_U3)
> +		gpio_direction_output(EXYNOS4X12_GPIO_X30, 0);
> +	else
> +		gpio_direction_output(EXYNOS4X12_GPIO_X30, 1);
> +
> +	/* Disconnect, Reset, Connect */
> +	gpio_direction_output(EXYNOS4X12_GPIO_X34, 0);
> +	gpio_direction_output(EXYNOS4X12_GPIO_X35, 0);
> +	gpio_direction_output(EXYNOS4X12_GPIO_X35, 1);
> +	gpio_direction_output(EXYNOS4X12_GPIO_X34, 1);
> +
> +	/* Power off and on BUCK8 for LAN9730 */
> +	debug("LAN9730 - Turning power buck 8 OFF and ON.\n");
> +
> +	p_pmic = pmic_get("MAX77686_PMIC");
> +	if (p_pmic && !pmic_probe(p_pmic)) {
> +		max77686_set_buck_mode(p_pmic, 8, OPMODE_OFF);
> +		max77686_set_buck_voltage(p_pmic, 8, 750000);
> +		max77686_set_buck_voltage(p_pmic, 8, 3300000);
> +		max77686_set_buck_mode(p_pmic, 8, OPMODE_ON);
> +	}
> +
> +	set_usb_ethaddr();
> +#endif
> +
>  	debug("USB_udc_probe\n");
>  	return s3c_udc_probe(&s5pc210_otg_data);
>  }
> diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
> index edd91a8..9c479b1 100644
> --- a/drivers/usb/host/ehci-exynos.c
> +++ b/drivers/usb/host/ehci-exynos.c
> @@ -85,15 +85,10 @@ static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos)
>  }
>  #endif
>  
> -/* Setup the EHCI host controller. */
> -static void setup_usb_phy(struct exynos_usb_phy *usb)
> +static void exynos5_setup_usb_phy(struct exynos_usb_phy *usb)
>  {
>  	u32 hsic_ctrl;
>  
> -	set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
> -
> -	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
> -
>  	clrbits_le32(&usb->usbphyctrl0,
>  			HOST_CTRL0_FSEL_MASK |
>  			HOST_CTRL0_COMMONON_N |
> @@ -150,8 +145,32 @@ static void setup_usb_phy(struct exynos_usb_phy *usb)
>  			EHCICTRL_ENAINCR16);
>  }
>  
> -/* Reset the EHCI host controller. */
> -static void reset_usb_phy(struct exynos_usb_phy *usb)
> +static void exynos4412_setup_usb_phy(struct exynos4412_usb_phy *usb)
> +{
> +	writel(CLK_24MHZ, &usb->usbphyclk);
> +
> +	clrbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
> +		PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
> +		PHYPWR_NORMAL_MASK_PHY0));
> +
> +	setbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
> +	udelay(10);
> +	clrbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
> +}
> +
> +static void setup_usb_phy(struct exynos_usb_phy *usb)
> +{
> +	set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
> +
> +	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
> +
> +	if (cpu_is_exynos5())
> +		exynos5_setup_usb_phy(usb);
> +	else if (proid_is_exynos4412())

please don't mix cpu_is.. and proid_is...

it should be

if (cpu_is_exynos5()) {
}
else if (cpu_is_exynos4()) {
    if (proid_is_exynos4412()) {
    }
}

> +		exynos4412_setup_usb_phy((struct exynos4412_usb_phy *)usb);
> +}
> +
> +static void exynos5_reset_usb_phy(struct exynos_usb_phy *usb)
>  {
>  	u32 hsic_ctrl;
>  
> @@ -171,6 +190,22 @@ static void reset_usb_phy(struct exynos_usb_phy *usb)
>  
>  	setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
>  	setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
> +}
> +
> +static void exynos4412_reset_usb_phy(struct exynos4412_usb_phy *usb)
> +{
> +	setbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
> +		PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
> +		PHYPWR_NORMAL_MASK_PHY0));
> +}
> +
> +/* Reset the EHCI host controller. */
> +static void reset_usb_phy(struct exynos_usb_phy *usb)
> +{
> +	if (cpu_is_exynos5())
> +		exynos5_reset_usb_phy(usb);
> +	else if (proid_is_exynos4412())

ditto.

> +		exynos4412_reset_usb_phy((struct exynos4412_usb_phy *)usb);
>  
>  	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE);
>  }
> diff --git a/include/configs/odroid.h b/include/configs/odroid.h
> index b928af8..807e96b 100644
> --- a/include/configs/odroid.h
> +++ b/include/configs/odroid.h
> @@ -198,6 +198,19 @@
>  
>  #define CONFIG_CMD_GPIO
>  
> +/* USB */
> +#define CONFIG_CMD_USB
> +#define CONFIG_USB_EHCI
> +#define CONFIG_USB_EHCI_EXYNOS
> +#define CONFIG_USB_STORAGE
> +
> +#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS	3
> +#define CONFIG_CMD_NET
> +#define CONFIG_CMD_PING
> +#define CONFIG_CMD_DHCP
> +#define CONFIG_USB_HOST_ETHER
> +#define CONFIG_USB_ETHER_SMSC95XX
> +
>  /*
>   * Supported Odroid boards: X3, U3
>   * TODO: Add Odroid X support
> 

Thanks,
Minkyu Kang.
Suriyan Ramasami Oct. 24, 2014, 4:08 p.m. UTC | #2
Hello Minkyu Kang,


On Thu, Oct 23, 2014 at 9:58 PM, Minkyu Kang <mk7.kang@samsung.com> wrote:
> Dear Suriyan Ramasami,
>
> On 21/10/14 02:52, Suriyan Ramasami wrote:
>> This change adds support for enabling the USB host features of the board.
>> This includes the USB3503A hub and the SMC LAN9730 ethernet controller
>> as well.
>>
>> Credit goes to Tushar Berara for the function set_usb_ethaddr().
>>
>> Signed-off-by: Suriyan Ramasami <suriyan.r@gmail.com>
>>
>> ---
>> v2:
>>  * Removed an unneeded header file from ehci-exynos.c
>>  * Fix indentation in the dts file
>> ---
>>  arch/arm/dts/exynos4412-odroid.dts      | 11 +++++++
>>  arch/arm/include/asm/arch-exynos/cpu.h  |  2 ++
>>  arch/arm/include/asm/arch-exynos/ehci.h | 13 ++++++++
>>  board/samsung/odroid/odroid.c           | 55 +++++++++++++++++++++++++++++++++
>>  drivers/usb/host/ehci-exynos.c          | 51 +++++++++++++++++++++++++-----
>>  include/configs/odroid.h                | 13 ++++++++
>>  6 files changed, 137 insertions(+), 8 deletions(-)
>>
>> diff --git a/arch/arm/dts/exynos4412-odroid.dts b/arch/arm/dts/exynos4412-odroid.dts
>> index 24d0bf1..ac5fece 100644
>> --- a/arch/arm/dts/exynos4412-odroid.dts
>> +++ b/arch/arm/dts/exynos4412-odroid.dts
>> @@ -67,4 +67,15 @@
>>               div = <0x3>;
>>               index = <4>;
>>       };
>> +
>> +     ehci@12580000 {
>> +             compatible = "samsung,exynos-ehci";
>> +             reg = <0x12580000 0x100>;
>> +             #address-cells = <1>;
>> +             #size-cells = <1>;
>> +             phy {
>> +                     compatible = "samsung,exynos-usb-phy";
>> +                     reg = <0x125B0000 0x100>;
>> +             };
>> +     };
>>  };
>> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
>> index ba71714..fda21fb 100644
>> --- a/arch/arm/include/asm/arch-exynos/cpu.h
>> +++ b/arch/arm/include/asm/arch-exynos/cpu.h
>> @@ -18,6 +18,8 @@
>>
>>  #define EXYNOS4_GPIO_PART3_BASE              0x03860000
>>  #define EXYNOS4_PRO_ID                       0x10000000
>> +#define EXYNOS4_GUID_LOW             0x10000014
>> +#define EXYNOS4_GUID_HIGH            0x10000018
>>  #define EXYNOS4_SYSREG_BASE          0x10010000
>>  #define EXYNOS4_POWER_BASE           0x10020000
>>  #define EXYNOS4_SWRESET                      0x10020400
>> diff --git a/arch/arm/include/asm/arch-exynos/ehci.h b/arch/arm/include/asm/arch-exynos/ehci.h
>> index d2d70bd..3800fa9 100644
>> --- a/arch/arm/include/asm/arch-exynos/ehci.h
>> +++ b/arch/arm/include/asm/arch-exynos/ehci.h
>> @@ -12,6 +12,13 @@
>>
>>  #define CLK_24MHZ            5
>>
>> +#define PHYPWR_NORMAL_MASK_PHY0                 (0x39 << 0)
>> +#define PHYPWR_NORMAL_MASK_PHY1                 (0x7 << 6)
>> +#define PHYPWR_NORMAL_MASK_HSIC0                (0x7 << 9)
>> +#define PHYPWR_NORMAL_MASK_HSIC1                (0x7 << 12)
>> +#define RSTCON_HOSTPHY_SWRST                    (0xf << 3)
>> +#define RSTCON_SWRST                            (0x1 << 0)
>> +
>>  #define HOST_CTRL0_PHYSWRSTALL                       (1 << 31)
>>  #define HOST_CTRL0_COMMONON_N                        (1 << 9)
>>  #define HOST_CTRL0_SIDDQ                     (1 << 6)
>> @@ -61,6 +68,12 @@ struct exynos_usb_phy {
>>       unsigned int usbotgtune;
>>  };
>>
>> +struct exynos4412_usb_phy {
>> +     unsigned int usbphyctrl;
>> +     unsigned int usbphyclk;
>> +     unsigned int usbphyrstcon;
>> +};
>> +
>>  /* Switch on the VBUS power. */
>>  int board_usb_vbus_init(void);
>>
>> diff --git a/board/samsung/odroid/odroid.c b/board/samsung/odroid/odroid.c
>> index 5edb250..6c78b67 100644
>> --- a/board/samsung/odroid/odroid.c
>> +++ b/board/samsung/odroid/odroid.c
>> @@ -453,9 +453,64 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
>>       .usb_phy_ctrl   = EXYNOS4X12_USBPHY_CONTROL,
>>       .usb_flags      = PHY0_SLEEP,
>>  };
>> +#endif
>> +
>> +#if defined(CONFIG_USB_GADGET) || defined(CONFIG_CMD_USB)
>> +
>> +#ifdef CONFIG_CMD_USB
>> +static void set_usb_ethaddr(void)
>> +{
>> +     int i;
>> +     uchar mac[6];
>> +     unsigned int guid_high = readl(EXYNOS4_GUID_HIGH);
>> +     unsigned int guid_low = readl(EXYNOS4_GUID_LOW);
>
> We don't allow direct access.
> Is it special register? I can't find this register on TRM.
> If so you can make inline function at cpu.h instead.
>

This register is not in the TRM. This register is possibly documented
in the TRM for the Exynos5250. Through experimentation I found that it
behaves the same on Exynos4412 prime as well - I checked this with one
X2, 1 U2 and 2 U3s, and they do indeed do the job of being unique and
hence can be used to generate the mac address which will be unique
across all U2s/U3s/X2s and possibly other Exynos SoCs like Exynos4212
etc.

Regarding direct access, I am a bit confused. In odroid.c I see quite
a many places which is doing a readl() of registers. Here we are
readl(addr) into guid_* similarly, and cooking up a mac address in a
local char array.

I fail to see your point. Can you please elaborate more, so I can comprehend?

>> +
>> +     for (i = 0; i < 2; i++)
>> +             mac[i] = (guid_high >> (8 * (1 - i))) & 0xFF;
>> +
>> +     for (i = 0; i < 4; i++)
>> +             mac[i+2] = (guid_low >> (8 * (3 - i))) & 0xFF;
>
> please add space. i + 2
>

Shall do so.

>> +
>> +     /* mark it as not multicast and outside official 80211 MAC namespace */
>> +     mac[0] = (mac[0] & ~0x1) | 0x2;
>> +
>> +     eth_setenv_enetaddr("ethaddr", mac);
>> +     eth_setenv_enetaddr("usbethaddr", mac);
>> +}
>> +#endif
>>
>>  int board_usb_init(int index, enum usb_init_type init)
>>  {
>> +#ifdef CONFIG_CMD_USB
>> +     struct pmic *p_pmic;
>> +
>> +     /* Set Ref freq 0 => 24MHz, 1 => 26MHz*/
>> +     /* Odroid Us have it at 24MHz, Odroid Xs at 26MHz */
>> +     if (gd->board_type == ODROID_TYPE_U3)
>> +             gpio_direction_output(EXYNOS4X12_GPIO_X30, 0);
>> +     else
>> +             gpio_direction_output(EXYNOS4X12_GPIO_X30, 1);
>> +
>> +     /* Disconnect, Reset, Connect */
>> +     gpio_direction_output(EXYNOS4X12_GPIO_X34, 0);
>> +     gpio_direction_output(EXYNOS4X12_GPIO_X35, 0);
>> +     gpio_direction_output(EXYNOS4X12_GPIO_X35, 1);
>> +     gpio_direction_output(EXYNOS4X12_GPIO_X34, 1);
>> +
>> +     /* Power off and on BUCK8 for LAN9730 */
>> +     debug("LAN9730 - Turning power buck 8 OFF and ON.\n");
>> +
>> +     p_pmic = pmic_get("MAX77686_PMIC");
>> +     if (p_pmic && !pmic_probe(p_pmic)) {
>> +             max77686_set_buck_mode(p_pmic, 8, OPMODE_OFF);
>> +             max77686_set_buck_voltage(p_pmic, 8, 750000);
>> +             max77686_set_buck_voltage(p_pmic, 8, 3300000);
>> +             max77686_set_buck_mode(p_pmic, 8, OPMODE_ON);
>> +     }
>> +
>> +     set_usb_ethaddr();
>> +#endif
>> +
>>       debug("USB_udc_probe\n");
>>       return s3c_udc_probe(&s5pc210_otg_data);
>>  }
>> diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
>> index edd91a8..9c479b1 100644
>> --- a/drivers/usb/host/ehci-exynos.c
>> +++ b/drivers/usb/host/ehci-exynos.c
>> @@ -85,15 +85,10 @@ static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos)
>>  }
>>  #endif
>>
>> -/* Setup the EHCI host controller. */
>> -static void setup_usb_phy(struct exynos_usb_phy *usb)
>> +static void exynos5_setup_usb_phy(struct exynos_usb_phy *usb)
>>  {
>>       u32 hsic_ctrl;
>>
>> -     set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
>> -
>> -     set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
>> -
>>       clrbits_le32(&usb->usbphyctrl0,
>>                       HOST_CTRL0_FSEL_MASK |
>>                       HOST_CTRL0_COMMONON_N |
>> @@ -150,8 +145,32 @@ static void setup_usb_phy(struct exynos_usb_phy *usb)
>>                       EHCICTRL_ENAINCR16);
>>  }
>>
>> -/* Reset the EHCI host controller. */
>> -static void reset_usb_phy(struct exynos_usb_phy *usb)
>> +static void exynos4412_setup_usb_phy(struct exynos4412_usb_phy *usb)
>> +{
>> +     writel(CLK_24MHZ, &usb->usbphyclk);
>> +
>> +     clrbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
>> +             PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
>> +             PHYPWR_NORMAL_MASK_PHY0));
>> +
>> +     setbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
>> +     udelay(10);
>> +     clrbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
>> +}
>> +
>> +static void setup_usb_phy(struct exynos_usb_phy *usb)
>> +{
>> +     set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
>> +
>> +     set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
>> +
>> +     if (cpu_is_exynos5())
>> +             exynos5_setup_usb_phy(usb);
>> +     else if (proid_is_exynos4412())
>
> please don't mix cpu_is.. and proid_is...
>
> it should be
>
> if (cpu_is_exynos5()) {
> }
> else if (cpu_is_exynos4()) {
>     if (proid_is_exynos4412()) {
>     }
> }
>

OK, I shall do so.

>> +             exynos4412_setup_usb_phy((struct exynos4412_usb_phy *)usb);
>> +}
>> +
>> +static void exynos5_reset_usb_phy(struct exynos_usb_phy *usb)
>>  {
>>       u32 hsic_ctrl;
>>
>> @@ -171,6 +190,22 @@ static void reset_usb_phy(struct exynos_usb_phy *usb)
>>
>>       setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
>>       setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
>> +}
>> +
>> +static void exynos4412_reset_usb_phy(struct exynos4412_usb_phy *usb)
>> +{
>> +     setbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
>> +             PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
>> +             PHYPWR_NORMAL_MASK_PHY0));
>> +}
>> +
>> +/* Reset the EHCI host controller. */
>> +static void reset_usb_phy(struct exynos_usb_phy *usb)
>> +{
>> +     if (cpu_is_exynos5())
>> +             exynos5_reset_usb_phy(usb);
>> +     else if (proid_is_exynos4412())
>
> ditto.
>

OK, shall change this as well.

Thanks for taking a look!
- Suriyan

>> +             exynos4412_reset_usb_phy((struct exynos4412_usb_phy *)usb);
>>
>>       set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE);
>>  }
>> diff --git a/include/configs/odroid.h b/include/configs/odroid.h
>> index b928af8..807e96b 100644
>> --- a/include/configs/odroid.h
>> +++ b/include/configs/odroid.h
>> @@ -198,6 +198,19 @@
>>
>>  #define CONFIG_CMD_GPIO
>>
>> +/* USB */
>> +#define CONFIG_CMD_USB
>> +#define CONFIG_USB_EHCI
>> +#define CONFIG_USB_EHCI_EXYNOS
>> +#define CONFIG_USB_STORAGE
>> +
>> +#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS   3
>> +#define CONFIG_CMD_NET
>> +#define CONFIG_CMD_PING
>> +#define CONFIG_CMD_DHCP
>> +#define CONFIG_USB_HOST_ETHER
>> +#define CONFIG_USB_ETHER_SMSC95XX
>> +
>>  /*
>>   * Supported Odroid boards: X3, U3
>>   * TODO: Add Odroid X support
>>
>
> Thanks,
> Minkyu Kang.
Przemyslaw Marczak Oct. 27, 2014, 11:08 a.m. UTC | #3
Hello Suriyan,

On 10/24/2014 06:08 PM, Suriyan Ramasami wrote:
> Hello Minkyu Kang,
>
>
> On Thu, Oct 23, 2014 at 9:58 PM, Minkyu Kang <mk7.kang@samsung.com> wrote:
>> Dear Suriyan Ramasami,
>>
>> On 21/10/14 02:52, Suriyan Ramasami wrote:
>>> This change adds support for enabling the USB host features of the board.
>>> This includes the USB3503A hub and the SMC LAN9730 ethernet controller
>>> as well.
>>>
>>> Credit goes to Tushar Berara for the function set_usb_ethaddr().
>>>
>>> Signed-off-by: Suriyan Ramasami <suriyan.r@gmail.com>
>>>
>>> ---
>>> v2:
>>>   * Removed an unneeded header file from ehci-exynos.c
>>>   * Fix indentation in the dts file
>>> ---
>>>   arch/arm/dts/exynos4412-odroid.dts      | 11 +++++++
>>>   arch/arm/include/asm/arch-exynos/cpu.h  |  2 ++
>>>   arch/arm/include/asm/arch-exynos/ehci.h | 13 ++++++++
>>>   board/samsung/odroid/odroid.c           | 55 +++++++++++++++++++++++++++++++++
>>>   drivers/usb/host/ehci-exynos.c          | 51 +++++++++++++++++++++++++-----
>>>   include/configs/odroid.h                | 13 ++++++++
>>>   6 files changed, 137 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/arch/arm/dts/exynos4412-odroid.dts b/arch/arm/dts/exynos4412-odroid.dts
>>> index 24d0bf1..ac5fece 100644
>>> --- a/arch/arm/dts/exynos4412-odroid.dts
>>> +++ b/arch/arm/dts/exynos4412-odroid.dts
>>> @@ -67,4 +67,15 @@
>>>                div = <0x3>;
>>>                index = <4>;
>>>        };
>>> +
>>> +     ehci@12580000 {
>>> +             compatible = "samsung,exynos-ehci";
>>> +             reg = <0x12580000 0x100>;
>>> +             #address-cells = <1>;
>>> +             #size-cells = <1>;
>>> +             phy {
>>> +                     compatible = "samsung,exynos-usb-phy";
>>> +                     reg = <0x125B0000 0x100>;
>>> +             };
>>> +     };
>>>   };
>>> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
>>> index ba71714..fda21fb 100644
>>> --- a/arch/arm/include/asm/arch-exynos/cpu.h
>>> +++ b/arch/arm/include/asm/arch-exynos/cpu.h
>>> @@ -18,6 +18,8 @@
>>>
>>>   #define EXYNOS4_GPIO_PART3_BASE              0x03860000
>>>   #define EXYNOS4_PRO_ID                       0x10000000
>>> +#define EXYNOS4_GUID_LOW             0x10000014
>>> +#define EXYNOS4_GUID_HIGH            0x10000018
>>>   #define EXYNOS4_SYSREG_BASE          0x10010000
>>>   #define EXYNOS4_POWER_BASE           0x10020000
>>>   #define EXYNOS4_SWRESET                      0x10020400
>>> diff --git a/arch/arm/include/asm/arch-exynos/ehci.h b/arch/arm/include/asm/arch-exynos/ehci.h
>>> index d2d70bd..3800fa9 100644
>>> --- a/arch/arm/include/asm/arch-exynos/ehci.h
>>> +++ b/arch/arm/include/asm/arch-exynos/ehci.h
>>> @@ -12,6 +12,13 @@
>>>
>>>   #define CLK_24MHZ            5
>>>
>>> +#define PHYPWR_NORMAL_MASK_PHY0                 (0x39 << 0)
>>> +#define PHYPWR_NORMAL_MASK_PHY1                 (0x7 << 6)
>>> +#define PHYPWR_NORMAL_MASK_HSIC0                (0x7 << 9)
>>> +#define PHYPWR_NORMAL_MASK_HSIC1                (0x7 << 12)
>>> +#define RSTCON_HOSTPHY_SWRST                    (0xf << 3)
>>> +#define RSTCON_SWRST                            (0x1 << 0)
>>> +
>>>   #define HOST_CTRL0_PHYSWRSTALL                       (1 << 31)
>>>   #define HOST_CTRL0_COMMONON_N                        (1 << 9)
>>>   #define HOST_CTRL0_SIDDQ                     (1 << 6)
>>> @@ -61,6 +68,12 @@ struct exynos_usb_phy {
>>>        unsigned int usbotgtune;
>>>   };
>>>
>>> +struct exynos4412_usb_phy {
>>> +     unsigned int usbphyctrl;
>>> +     unsigned int usbphyclk;
>>> +     unsigned int usbphyrstcon;
>>> +};
>>> +
>>>   /* Switch on the VBUS power. */
>>>   int board_usb_vbus_init(void);
>>>
>>> diff --git a/board/samsung/odroid/odroid.c b/board/samsung/odroid/odroid.c
>>> index 5edb250..6c78b67 100644
>>> --- a/board/samsung/odroid/odroid.c
>>> +++ b/board/samsung/odroid/odroid.c
>>> @@ -453,9 +453,64 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
>>>        .usb_phy_ctrl   = EXYNOS4X12_USBPHY_CONTROL,
>>>        .usb_flags      = PHY0_SLEEP,
>>>   };
>>> +#endif
>>> +
>>> +#if defined(CONFIG_USB_GADGET) || defined(CONFIG_CMD_USB)
>>> +
>>> +#ifdef CONFIG_CMD_USB
>>> +static void set_usb_ethaddr(void)
>>> +{
>>> +     int i;
>>> +     uchar mac[6];
>>> +     unsigned int guid_high = readl(EXYNOS4_GUID_HIGH);
>>> +     unsigned int guid_low = readl(EXYNOS4_GUID_LOW);
>>
>> We don't allow direct access.
>> Is it special register? I can't find this register on TRM.
>> If so you can make inline function at cpu.h instead.
>>
>
> This register is not in the TRM. This register is possibly documented
> in the TRM for the Exynos5250. Through experimentation I found that it
> behaves the same on Exynos4412 prime as well - I checked this with one
> X2, 1 U2 and 2 U3s, and they do indeed do the job of being unique and
> hence can be used to generate the mac address which will be unique
> across all U2s/U3s/X2s and possibly other Exynos SoCs like Exynos4212
> etc.
>

Those register addresses are not documented anywhere. So use of them is 
not a good idea and can cause unpredictable results, even if was tested 
on a few devices.

> Regarding direct access, I am a bit confused. In odroid.c I see quite
> a many places which is doing a readl() of registers. Here we are
> readl(addr) into guid_* similarly, and cooking up a mac address in a
> local char array.
>
> I fail to see your point. Can you please elaborate more, so I can comprehend?
>

The MAC address is defined by IEEE standard, so we can't use magic 
numbers from undefined registers.
I see two ways to do it:
- put the MAC into environment
- use of UUID generator from: lib/uuid.c

On the Odroid you will get the hardware acceleration, because the 
hardware random number generator is enabled.

>>> +
>>> +     for (i = 0; i < 2; i++)
>>> +             mac[i] = (guid_high >> (8 * (1 - i))) & 0xFF;
>>> +
>>> +     for (i = 0; i < 4; i++)
>>> +             mac[i+2] = (guid_low >> (8 * (3 - i))) & 0xFF;
>>
>> please add space. i + 2
>>
>
> Shall do so.
>
>>> +
>>> +     /* mark it as not multicast and outside official 80211 MAC namespace */
>>> +     mac[0] = (mac[0] & ~0x1) | 0x2;
>>> +
>>> +     eth_setenv_enetaddr("ethaddr", mac);
>>> +     eth_setenv_enetaddr("usbethaddr", mac);
>>> +}
>>> +#endif
>>>
>>>   int board_usb_init(int index, enum usb_init_type init)
>>>   {
>>> +#ifdef CONFIG_CMD_USB
>>> +     struct pmic *p_pmic;
>>> +
>>> +     /* Set Ref freq 0 => 24MHz, 1 => 26MHz*/
>>> +     /* Odroid Us have it at 24MHz, Odroid Xs at 26MHz */
>>> +     if (gd->board_type == ODROID_TYPE_U3)
>>> +             gpio_direction_output(EXYNOS4X12_GPIO_X30, 0);
>>> +     else
>>> +             gpio_direction_output(EXYNOS4X12_GPIO_X30, 1);
>>> +
>>> +     /* Disconnect, Reset, Connect */
>>> +     gpio_direction_output(EXYNOS4X12_GPIO_X34, 0);
>>> +     gpio_direction_output(EXYNOS4X12_GPIO_X35, 0);
>>> +     gpio_direction_output(EXYNOS4X12_GPIO_X35, 1);
>>> +     gpio_direction_output(EXYNOS4X12_GPIO_X34, 1);
>>> +
>>> +     /* Power off and on BUCK8 for LAN9730 */
>>> +     debug("LAN9730 - Turning power buck 8 OFF and ON.\n");
>>> +
>>> +     p_pmic = pmic_get("MAX77686_PMIC");
>>> +     if (p_pmic && !pmic_probe(p_pmic)) {
>>> +             max77686_set_buck_mode(p_pmic, 8, OPMODE_OFF);
>>> +             max77686_set_buck_voltage(p_pmic, 8, 750000);
>>> +             max77686_set_buck_voltage(p_pmic, 8, 3300000);
>>> +             max77686_set_buck_mode(p_pmic, 8, OPMODE_ON);
>>> +     }
>>> +
>>> +     set_usb_ethaddr();
>>> +#endif
>>> +
>>>        debug("USB_udc_probe\n");
>>>        return s3c_udc_probe(&s5pc210_otg_data);
>>>   }
>>> diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
>>> index edd91a8..9c479b1 100644
>>> --- a/drivers/usb/host/ehci-exynos.c
>>> +++ b/drivers/usb/host/ehci-exynos.c
>>> @@ -85,15 +85,10 @@ static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos)
>>>   }
>>>   #endif
>>>
>>> -/* Setup the EHCI host controller. */
>>> -static void setup_usb_phy(struct exynos_usb_phy *usb)
>>> +static void exynos5_setup_usb_phy(struct exynos_usb_phy *usb)
>>>   {
>>>        u32 hsic_ctrl;
>>>
>>> -     set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
>>> -
>>> -     set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
>>> -
>>>        clrbits_le32(&usb->usbphyctrl0,
>>>                        HOST_CTRL0_FSEL_MASK |
>>>                        HOST_CTRL0_COMMONON_N |
>>> @@ -150,8 +145,32 @@ static void setup_usb_phy(struct exynos_usb_phy *usb)
>>>                        EHCICTRL_ENAINCR16);
>>>   }
>>>
>>> -/* Reset the EHCI host controller. */
>>> -static void reset_usb_phy(struct exynos_usb_phy *usb)
>>> +static void exynos4412_setup_usb_phy(struct exynos4412_usb_phy *usb)
>>> +{
>>> +     writel(CLK_24MHZ, &usb->usbphyclk);
>>> +
>>> +     clrbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
>>> +             PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
>>> +             PHYPWR_NORMAL_MASK_PHY0));
>>> +
>>> +     setbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
>>> +     udelay(10);
>>> +     clrbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
>>> +}
>>> +
>>> +static void setup_usb_phy(struct exynos_usb_phy *usb)
>>> +{
>>> +     set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
>>> +
>>> +     set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
>>> +
>>> +     if (cpu_is_exynos5())
>>> +             exynos5_setup_usb_phy(usb);
>>> +     else if (proid_is_exynos4412())
>>
>> please don't mix cpu_is.. and proid_is...
>>
>> it should be
>>
>> if (cpu_is_exynos5()) {
>> }
>> else if (cpu_is_exynos4()) {
>>      if (proid_is_exynos4412()) {
>>      }
>> }
>>
>
> OK, I shall do so.
>
>>> +             exynos4412_setup_usb_phy((struct exynos4412_usb_phy *)usb);
>>> +}
>>> +
>>> +static void exynos5_reset_usb_phy(struct exynos_usb_phy *usb)
>>>   {
>>>        u32 hsic_ctrl;
>>>
>>> @@ -171,6 +190,22 @@ static void reset_usb_phy(struct exynos_usb_phy *usb)
>>>
>>>        setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
>>>        setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
>>> +}
>>> +
>>> +static void exynos4412_reset_usb_phy(struct exynos4412_usb_phy *usb)
>>> +{
>>> +     setbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
>>> +             PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
>>> +             PHYPWR_NORMAL_MASK_PHY0));
>>> +}
>>> +
>>> +/* Reset the EHCI host controller. */
>>> +static void reset_usb_phy(struct exynos_usb_phy *usb)
>>> +{
>>> +     if (cpu_is_exynos5())
>>> +             exynos5_reset_usb_phy(usb);
>>> +     else if (proid_is_exynos4412())
>>
>> ditto.
>>
>
> OK, shall change this as well.
>
> Thanks for taking a look!
> - Suriyan
>
>>> +             exynos4412_reset_usb_phy((struct exynos4412_usb_phy *)usb);
>>>
>>>        set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE);
>>>   }
>>> diff --git a/include/configs/odroid.h b/include/configs/odroid.h
>>> index b928af8..807e96b 100644
>>> --- a/include/configs/odroid.h
>>> +++ b/include/configs/odroid.h
>>> @@ -198,6 +198,19 @@
>>>
>>>   #define CONFIG_CMD_GPIO
>>>
>>> +/* USB */
>>> +#define CONFIG_CMD_USB
>>> +#define CONFIG_USB_EHCI
>>> +#define CONFIG_USB_EHCI_EXYNOS
>>> +#define CONFIG_USB_STORAGE
>>> +
>>> +#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS   3
>>> +#define CONFIG_CMD_NET
>>> +#define CONFIG_CMD_PING
>>> +#define CONFIG_CMD_DHCP
>>> +#define CONFIG_USB_HOST_ETHER
>>> +#define CONFIG_USB_ETHER_SMSC95XX
>>> +
>>>   /*
>>>    * Supported Odroid boards: X3, U3
>>>    * TODO: Add Odroid X support
>>>
>>
>> Thanks,
>> Minkyu Kang.

Best regards,
Minkyu Kang Oct. 27, 2014, 1:03 p.m. UTC | #4
Dear Suriyan Ramasami,

On 25/10/14 01:08, Suriyan Ramasami wrote:
> Hello Minkyu Kang,
> 
> 
> On Thu, Oct 23, 2014 at 9:58 PM, Minkyu Kang <mk7.kang@samsung.com> wrote:
>> Dear Suriyan Ramasami,
>>
>> On 21/10/14 02:52, Suriyan Ramasami wrote:
>>> This change adds support for enabling the USB host features of the board.
>>> This includes the USB3503A hub and the SMC LAN9730 ethernet controller
>>> as well.
>>>
>>> Credit goes to Tushar Berara for the function set_usb_ethaddr().
>>>
>>> Signed-off-by: Suriyan Ramasami <suriyan.r@gmail.com>
>>>
>>> ---
>>> v2:
>>>  * Removed an unneeded header file from ehci-exynos.c
>>>  * Fix indentation in the dts file
>>> ---
>>>  arch/arm/dts/exynos4412-odroid.dts      | 11 +++++++
>>>  arch/arm/include/asm/arch-exynos/cpu.h  |  2 ++
>>>  arch/arm/include/asm/arch-exynos/ehci.h | 13 ++++++++
>>>  board/samsung/odroid/odroid.c           | 55 +++++++++++++++++++++++++++++++++
>>>  drivers/usb/host/ehci-exynos.c          | 51 +++++++++++++++++++++++++-----
>>>  include/configs/odroid.h                | 13 ++++++++
>>>  6 files changed, 137 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/arch/arm/dts/exynos4412-odroid.dts b/arch/arm/dts/exynos4412-odroid.dts
>>> index 24d0bf1..ac5fece 100644
>>> --- a/arch/arm/dts/exynos4412-odroid.dts
>>> +++ b/arch/arm/dts/exynos4412-odroid.dts
>>> @@ -67,4 +67,15 @@
>>>               div = <0x3>;
>>>               index = <4>;
>>>       };
>>> +
>>> +     ehci@12580000 {
>>> +             compatible = "samsung,exynos-ehci";
>>> +             reg = <0x12580000 0x100>;
>>> +             #address-cells = <1>;
>>> +             #size-cells = <1>;
>>> +             phy {
>>> +                     compatible = "samsung,exynos-usb-phy";
>>> +                     reg = <0x125B0000 0x100>;
>>> +             };
>>> +     };
>>>  };
>>> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
>>> index ba71714..fda21fb 100644
>>> --- a/arch/arm/include/asm/arch-exynos/cpu.h
>>> +++ b/arch/arm/include/asm/arch-exynos/cpu.h
>>> @@ -18,6 +18,8 @@
>>>
>>>  #define EXYNOS4_GPIO_PART3_BASE              0x03860000
>>>  #define EXYNOS4_PRO_ID                       0x10000000
>>> +#define EXYNOS4_GUID_LOW             0x10000014
>>> +#define EXYNOS4_GUID_HIGH            0x10000018
>>>  #define EXYNOS4_SYSREG_BASE          0x10010000
>>>  #define EXYNOS4_POWER_BASE           0x10020000
>>>  #define EXYNOS4_SWRESET                      0x10020400
>>> diff --git a/arch/arm/include/asm/arch-exynos/ehci.h b/arch/arm/include/asm/arch-exynos/ehci.h
>>> index d2d70bd..3800fa9 100644
>>> --- a/arch/arm/include/asm/arch-exynos/ehci.h
>>> +++ b/arch/arm/include/asm/arch-exynos/ehci.h
>>> @@ -12,6 +12,13 @@
>>>
>>>  #define CLK_24MHZ            5
>>>
>>> +#define PHYPWR_NORMAL_MASK_PHY0                 (0x39 << 0)
>>> +#define PHYPWR_NORMAL_MASK_PHY1                 (0x7 << 6)
>>> +#define PHYPWR_NORMAL_MASK_HSIC0                (0x7 << 9)
>>> +#define PHYPWR_NORMAL_MASK_HSIC1                (0x7 << 12)
>>> +#define RSTCON_HOSTPHY_SWRST                    (0xf << 3)
>>> +#define RSTCON_SWRST                            (0x1 << 0)
>>> +
>>>  #define HOST_CTRL0_PHYSWRSTALL                       (1 << 31)
>>>  #define HOST_CTRL0_COMMONON_N                        (1 << 9)
>>>  #define HOST_CTRL0_SIDDQ                     (1 << 6)
>>> @@ -61,6 +68,12 @@ struct exynos_usb_phy {
>>>       unsigned int usbotgtune;
>>>  };
>>>
>>> +struct exynos4412_usb_phy {
>>> +     unsigned int usbphyctrl;
>>> +     unsigned int usbphyclk;
>>> +     unsigned int usbphyrstcon;
>>> +};
>>> +
>>>  /* Switch on the VBUS power. */
>>>  int board_usb_vbus_init(void);
>>>
>>> diff --git a/board/samsung/odroid/odroid.c b/board/samsung/odroid/odroid.c
>>> index 5edb250..6c78b67 100644
>>> --- a/board/samsung/odroid/odroid.c
>>> +++ b/board/samsung/odroid/odroid.c
>>> @@ -453,9 +453,64 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
>>>       .usb_phy_ctrl   = EXYNOS4X12_USBPHY_CONTROL,
>>>       .usb_flags      = PHY0_SLEEP,
>>>  };
>>> +#endif
>>> +
>>> +#if defined(CONFIG_USB_GADGET) || defined(CONFIG_CMD_USB)
>>> +
>>> +#ifdef CONFIG_CMD_USB
>>> +static void set_usb_ethaddr(void)
>>> +{
>>> +     int i;
>>> +     uchar mac[6];
>>> +     unsigned int guid_high = readl(EXYNOS4_GUID_HIGH);
>>> +     unsigned int guid_low = readl(EXYNOS4_GUID_LOW);
>>
>> We don't allow direct access.
>> Is it special register? I can't find this register on TRM.
>> If so you can make inline function at cpu.h instead.
>>
> 
> This register is not in the TRM. This register is possibly documented
> in the TRM for the Exynos5250. Through experimentation I found that it
> behaves the same on Exynos4412 prime as well - I checked this with one
> X2, 1 U2 and 2 U3s, and they do indeed do the job of being unique and
> hence can be used to generate the mac address which will be unique
> across all U2s/U3s/X2s and possibly other Exynos SoCs like Exynos4212
> etc.
> 
> Regarding direct access, I am a bit confused. In odroid.c I see quite
> a many places which is doing a readl() of registers. Here we are
> readl(addr) into guid_* similarly, and cooking up a mac address in a
> local char array.
> 
> I fail to see your point. Can you please elaborate more, so I can comprehend?
> 

Samsung SoCs always get the address of register using accessor functions(samsung_get_base_xxx).

Thanks,
Minkyu Kang.
Suriyan Ramasami Oct. 27, 2014, 7:34 p.m. UTC | #5
Hello Przemyslaw Marczak,

On Mon, Oct 27, 2014 at 4:08 AM, Przemyslaw Marczak
<p.marczak@samsung.com> wrote:
> Hello Suriyan,
>
>
> On 10/24/2014 06:08 PM, Suriyan Ramasami wrote:
>>
>> Hello Minkyu Kang,
>>
>>
>> On Thu, Oct 23, 2014 at 9:58 PM, Minkyu Kang <mk7.kang@samsung.com> wrote:
>>>
>>> Dear Suriyan Ramasami,
>>>
>>> On 21/10/14 02:52, Suriyan Ramasami wrote:
>>>>
>>>> This change adds support for enabling the USB host features of the
>>>> board.
>>>> This includes the USB3503A hub and the SMC LAN9730 ethernet controller
>>>> as well.
>>>>
>>>> Credit goes to Tushar Berara for the function set_usb_ethaddr().
>>>>
>>>> Signed-off-by: Suriyan Ramasami <suriyan.r@gmail.com>
>>>>
>>>> ---
>>>> v2:
>>>>   * Removed an unneeded header file from ehci-exynos.c
>>>>   * Fix indentation in the dts file
>>>> ---
>>>>   arch/arm/dts/exynos4412-odroid.dts      | 11 +++++++
>>>>   arch/arm/include/asm/arch-exynos/cpu.h  |  2 ++
>>>>   arch/arm/include/asm/arch-exynos/ehci.h | 13 ++++++++
>>>>   board/samsung/odroid/odroid.c           | 55
>>>> +++++++++++++++++++++++++++++++++
>>>>   drivers/usb/host/ehci-exynos.c          | 51
>>>> +++++++++++++++++++++++++-----
>>>>   include/configs/odroid.h                | 13 ++++++++
>>>>   6 files changed, 137 insertions(+), 8 deletions(-)
>>>>
>>>> diff --git a/arch/arm/dts/exynos4412-odroid.dts
>>>> b/arch/arm/dts/exynos4412-odroid.dts
>>>> index 24d0bf1..ac5fece 100644
>>>> --- a/arch/arm/dts/exynos4412-odroid.dts
>>>> +++ b/arch/arm/dts/exynos4412-odroid.dts
>>>> @@ -67,4 +67,15 @@
>>>>                div = <0x3>;
>>>>                index = <4>;
>>>>        };
>>>> +
>>>> +     ehci@12580000 {
>>>> +             compatible = "samsung,exynos-ehci";
>>>> +             reg = <0x12580000 0x100>;
>>>> +             #address-cells = <1>;
>>>> +             #size-cells = <1>;
>>>> +             phy {
>>>> +                     compatible = "samsung,exynos-usb-phy";
>>>> +                     reg = <0x125B0000 0x100>;
>>>> +             };
>>>> +     };
>>>>   };
>>>> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h
>>>> b/arch/arm/include/asm/arch-exynos/cpu.h
>>>> index ba71714..fda21fb 100644
>>>> --- a/arch/arm/include/asm/arch-exynos/cpu.h
>>>> +++ b/arch/arm/include/asm/arch-exynos/cpu.h
>>>> @@ -18,6 +18,8 @@
>>>>
>>>>   #define EXYNOS4_GPIO_PART3_BASE              0x03860000
>>>>   #define EXYNOS4_PRO_ID                       0x10000000
>>>> +#define EXYNOS4_GUID_LOW             0x10000014
>>>> +#define EXYNOS4_GUID_HIGH            0x10000018
>>>>   #define EXYNOS4_SYSREG_BASE          0x10010000
>>>>   #define EXYNOS4_POWER_BASE           0x10020000
>>>>   #define EXYNOS4_SWRESET                      0x10020400
>>>> diff --git a/arch/arm/include/asm/arch-exynos/ehci.h
>>>> b/arch/arm/include/asm/arch-exynos/ehci.h
>>>> index d2d70bd..3800fa9 100644
>>>> --- a/arch/arm/include/asm/arch-exynos/ehci.h
>>>> +++ b/arch/arm/include/asm/arch-exynos/ehci.h
>>>> @@ -12,6 +12,13 @@
>>>>
>>>>   #define CLK_24MHZ            5
>>>>
>>>> +#define PHYPWR_NORMAL_MASK_PHY0                 (0x39 << 0)
>>>> +#define PHYPWR_NORMAL_MASK_PHY1                 (0x7 << 6)
>>>> +#define PHYPWR_NORMAL_MASK_HSIC0                (0x7 << 9)
>>>> +#define PHYPWR_NORMAL_MASK_HSIC1                (0x7 << 12)
>>>> +#define RSTCON_HOSTPHY_SWRST                    (0xf << 3)
>>>> +#define RSTCON_SWRST                            (0x1 << 0)
>>>> +
>>>>   #define HOST_CTRL0_PHYSWRSTALL                       (1 << 31)
>>>>   #define HOST_CTRL0_COMMONON_N                        (1 << 9)
>>>>   #define HOST_CTRL0_SIDDQ                     (1 << 6)
>>>> @@ -61,6 +68,12 @@ struct exynos_usb_phy {
>>>>        unsigned int usbotgtune;
>>>>   };
>>>>
>>>> +struct exynos4412_usb_phy {
>>>> +     unsigned int usbphyctrl;
>>>> +     unsigned int usbphyclk;
>>>> +     unsigned int usbphyrstcon;
>>>> +};
>>>> +
>>>>   /* Switch on the VBUS power. */
>>>>   int board_usb_vbus_init(void);
>>>>
>>>> diff --git a/board/samsung/odroid/odroid.c
>>>> b/board/samsung/odroid/odroid.c
>>>> index 5edb250..6c78b67 100644
>>>> --- a/board/samsung/odroid/odroid.c
>>>> +++ b/board/samsung/odroid/odroid.c
>>>> @@ -453,9 +453,64 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
>>>>        .usb_phy_ctrl   = EXYNOS4X12_USBPHY_CONTROL,
>>>>        .usb_flags      = PHY0_SLEEP,
>>>>   };
>>>> +#endif
>>>> +
>>>> +#if defined(CONFIG_USB_GADGET) || defined(CONFIG_CMD_USB)
>>>> +
>>>> +#ifdef CONFIG_CMD_USB
>>>> +static void set_usb_ethaddr(void)
>>>> +{
>>>> +     int i;
>>>> +     uchar mac[6];
>>>> +     unsigned int guid_high = readl(EXYNOS4_GUID_HIGH);
>>>> +     unsigned int guid_low = readl(EXYNOS4_GUID_LOW);
>>>
>>>
>>> We don't allow direct access.
>>> Is it special register? I can't find this register on TRM.
>>> If so you can make inline function at cpu.h instead.
>>>
>>
>> This register is not in the TRM. This register is possibly documented
>> in the TRM for the Exynos5250. Through experimentation I found that it
>> behaves the same on Exynos4412 prime as well - I checked this with one
>> X2, 1 U2 and 2 U3s, and they do indeed do the job of being unique and
>> hence can be used to generate the mac address which will be unique
>> across all U2s/U3s/X2s and possibly other Exynos SoCs like Exynos4212
>> etc.
>>
>
> Those register addresses are not documented anywhere. So use of them is not
> a good idea and can cause unpredictable results, even if was tested on a few
> devices.
>

OK, fair enough. I thought somehow it would be documented in the
Samsung internal user manual. I guess it is not!

>> Regarding direct access, I am a bit confused. In odroid.c I see quite
>> a many places which is doing a readl() of registers. Here we are
>> readl(addr) into guid_* similarly, and cooking up a mac address in a
>> local char array.
>>
>> I fail to see your point. Can you please elaborate more, so I can
>> comprehend?
>>
>
> The MAC address is defined by IEEE standard, so we can't use magic numbers
> from undefined registers.

I am aware of that. In the code by Tushar Behera you will see that he
does mark it - "not multicast and outside official 80211 MAC
namespace".

> I see two ways to do it:
> - put the MAC into environment
> - use of UUID generator from: lib/uuid.c
>
> On the Odroid you will get the hardware acceleration, because the hardware
> random number generator is enabled.
>

Let me research a bit - if a random MAC address can indeed be cooked
up. If not, as you suggest, we can leave it as an onus on the user to
set it in the env. (which is what is being done currently).

Do you have any pointers in using the hardware random generator in the
Odroid? That does seem promising.

>
>>>> +
>>>> +     for (i = 0; i < 2; i++)
>>>> +             mac[i] = (guid_high >> (8 * (1 - i))) & 0xFF;
>>>> +
>>>> +     for (i = 0; i < 4; i++)
>>>> +             mac[i+2] = (guid_low >> (8 * (3 - i))) & 0xFF;
>>>
>>>
>>> please add space. i + 2
>>>
>>
>> Shall do so.
>>
>>>> +
>>>> +     /* mark it as not multicast and outside official 80211 MAC
>>>> namespace */
>>>> +     mac[0] = (mac[0] & ~0x1) | 0x2;
>>>> +
>>>> +     eth_setenv_enetaddr("ethaddr", mac);
>>>> +     eth_setenv_enetaddr("usbethaddr", mac);
>>>> +}
>>>> +#endif
>>>>
>>>>   int board_usb_init(int index, enum usb_init_type init)
>>>>   {
>>>> +#ifdef CONFIG_CMD_USB
>>>> +     struct pmic *p_pmic;
>>>> +
>>>> +     /* Set Ref freq 0 => 24MHz, 1 => 26MHz*/
>>>> +     /* Odroid Us have it at 24MHz, Odroid Xs at 26MHz */
>>>> +     if (gd->board_type == ODROID_TYPE_U3)
>>>> +             gpio_direction_output(EXYNOS4X12_GPIO_X30, 0);
>>>> +     else
>>>> +             gpio_direction_output(EXYNOS4X12_GPIO_X30, 1);
>>>> +
>>>> +     /* Disconnect, Reset, Connect */
>>>> +     gpio_direction_output(EXYNOS4X12_GPIO_X34, 0);
>>>> +     gpio_direction_output(EXYNOS4X12_GPIO_X35, 0);
>>>> +     gpio_direction_output(EXYNOS4X12_GPIO_X35, 1);
>>>> +     gpio_direction_output(EXYNOS4X12_GPIO_X34, 1);
>>>> +
>>>> +     /* Power off and on BUCK8 for LAN9730 */
>>>> +     debug("LAN9730 - Turning power buck 8 OFF and ON.\n");
>>>> +
>>>> +     p_pmic = pmic_get("MAX77686_PMIC");
>>>> +     if (p_pmic && !pmic_probe(p_pmic)) {
>>>> +             max77686_set_buck_mode(p_pmic, 8, OPMODE_OFF);
>>>> +             max77686_set_buck_voltage(p_pmic, 8, 750000);
>>>> +             max77686_set_buck_voltage(p_pmic, 8, 3300000);
>>>> +             max77686_set_buck_mode(p_pmic, 8, OPMODE_ON);
>>>> +     }
>>>> +
>>>> +     set_usb_ethaddr();
>>>> +#endif
>>>> +
>>>>        debug("USB_udc_probe\n");
>>>>        return s3c_udc_probe(&s5pc210_otg_data);
>>>>   }
>>>> diff --git a/drivers/usb/host/ehci-exynos.c
>>>> b/drivers/usb/host/ehci-exynos.c
>>>> index edd91a8..9c479b1 100644
>>>> --- a/drivers/usb/host/ehci-exynos.c
>>>> +++ b/drivers/usb/host/ehci-exynos.c
>>>> @@ -85,15 +85,10 @@ static int exynos_usb_parse_dt(const void *blob,
>>>> struct exynos_ehci *exynos)
>>>>   }
>>>>   #endif
>>>>
>>>> -/* Setup the EHCI host controller. */
>>>> -static void setup_usb_phy(struct exynos_usb_phy *usb)
>>>> +static void exynos5_setup_usb_phy(struct exynos_usb_phy *usb)
>>>>   {
>>>>        u32 hsic_ctrl;
>>>>
>>>> -     set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
>>>> -
>>>> -     set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
>>>> -
>>>>        clrbits_le32(&usb->usbphyctrl0,
>>>>                        HOST_CTRL0_FSEL_MASK |
>>>>                        HOST_CTRL0_COMMONON_N |
>>>> @@ -150,8 +145,32 @@ static void setup_usb_phy(struct exynos_usb_phy
>>>> *usb)
>>>>                        EHCICTRL_ENAINCR16);
>>>>   }
>>>>
>>>> -/* Reset the EHCI host controller. */
>>>> -static void reset_usb_phy(struct exynos_usb_phy *usb)
>>>> +static void exynos4412_setup_usb_phy(struct exynos4412_usb_phy *usb)
>>>> +{
>>>> +     writel(CLK_24MHZ, &usb->usbphyclk);
>>>> +
>>>> +     clrbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
>>>> +             PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
>>>> +             PHYPWR_NORMAL_MASK_PHY0));
>>>> +
>>>> +     setbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST |
>>>> RSTCON_SWRST));
>>>> +     udelay(10);
>>>> +     clrbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST |
>>>> RSTCON_SWRST));
>>>> +}
>>>> +
>>>> +static void setup_usb_phy(struct exynos_usb_phy *usb)
>>>> +{
>>>> +     set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
>>>> +
>>>> +     set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
>>>> +
>>>> +     if (cpu_is_exynos5())
>>>> +             exynos5_setup_usb_phy(usb);
>>>> +     else if (proid_is_exynos4412())
>>>
>>>
>>> please don't mix cpu_is.. and proid_is...
>>>
>>> it should be
>>>
>>> if (cpu_is_exynos5()) {
>>> }
>>> else if (cpu_is_exynos4()) {
>>>      if (proid_is_exynos4412()) {
>>>      }
>>> }
>>>
>>
>> OK, I shall do so.
>>
>>>> +             exynos4412_setup_usb_phy((struct exynos4412_usb_phy
>>>> *)usb);
>>>> +}
>>>> +
>>>> +static void exynos5_reset_usb_phy(struct exynos_usb_phy *usb)
>>>>   {
>>>>        u32 hsic_ctrl;
>>>>
>>>> @@ -171,6 +190,22 @@ static void reset_usb_phy(struct exynos_usb_phy
>>>> *usb)
>>>>
>>>>        setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
>>>>        setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
>>>> +}
>>>> +
>>>> +static void exynos4412_reset_usb_phy(struct exynos4412_usb_phy *usb)
>>>> +{
>>>> +     setbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
>>>> +             PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
>>>> +             PHYPWR_NORMAL_MASK_PHY0));
>>>> +}
>>>> +
>>>> +/* Reset the EHCI host controller. */
>>>> +static void reset_usb_phy(struct exynos_usb_phy *usb)
>>>> +{
>>>> +     if (cpu_is_exynos5())
>>>> +             exynos5_reset_usb_phy(usb);
>>>> +     else if (proid_is_exynos4412())
>>>
>>>
>>> ditto.
>>>
>>
>> OK, shall change this as well.
>>
>> Thanks for taking a look!
>> - Suriyan
>>
>>>> +             exynos4412_reset_usb_phy((struct exynos4412_usb_phy
>>>> *)usb);
>>>>
>>>>        set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE);
>>>>   }
>>>> diff --git a/include/configs/odroid.h b/include/configs/odroid.h
>>>> index b928af8..807e96b 100644
>>>> --- a/include/configs/odroid.h
>>>> +++ b/include/configs/odroid.h
>>>> @@ -198,6 +198,19 @@
>>>>
>>>>   #define CONFIG_CMD_GPIO
>>>>
>>>> +/* USB */
>>>> +#define CONFIG_CMD_USB
>>>> +#define CONFIG_USB_EHCI
>>>> +#define CONFIG_USB_EHCI_EXYNOS
>>>> +#define CONFIG_USB_STORAGE
>>>> +
>>>> +#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS   3
>>>> +#define CONFIG_CMD_NET
>>>> +#define CONFIG_CMD_PING
>>>> +#define CONFIG_CMD_DHCP
>>>> +#define CONFIG_USB_HOST_ETHER
>>>> +#define CONFIG_USB_ETHER_SMSC95XX
>>>> +
>>>>   /*
>>>>    * Supported Odroid boards: X3, U3
>>>>    * TODO: Add Odroid X support
>>>>
>>>
>>> Thanks,
>>> Minkyu Kang.
>
>

Thanks!
- Suriyan

> Best regards,
> --
> Przemyslaw Marczak
> Samsung R&D Institute Poland
> Samsung Electronics
> p.marczak@samsung.com
Suriyan Ramasami Oct. 27, 2014, 7:36 p.m. UTC | #6
Hello Minkyu Kang,


On Mon, Oct 27, 2014 at 6:03 AM, Minkyu Kang <mk7.kang@samsung.com> wrote:
> Dear Suriyan Ramasami,
>
> On 25/10/14 01:08, Suriyan Ramasami wrote:
>> Hello Minkyu Kang,
>>
>>
>> On Thu, Oct 23, 2014 at 9:58 PM, Minkyu Kang <mk7.kang@samsung.com> wrote:
>>> Dear Suriyan Ramasami,
>>>
>>> On 21/10/14 02:52, Suriyan Ramasami wrote:
>>>> This change adds support for enabling the USB host features of the board.
>>>> This includes the USB3503A hub and the SMC LAN9730 ethernet controller
>>>> as well.
>>>>
>>>> Credit goes to Tushar Berara for the function set_usb_ethaddr().
>>>>
>>>> Signed-off-by: Suriyan Ramasami <suriyan.r@gmail.com>
>>>>
>>>> ---
>>>> v2:
>>>>  * Removed an unneeded header file from ehci-exynos.c
>>>>  * Fix indentation in the dts file
>>>> ---
>>>>  arch/arm/dts/exynos4412-odroid.dts      | 11 +++++++
>>>>  arch/arm/include/asm/arch-exynos/cpu.h  |  2 ++
>>>>  arch/arm/include/asm/arch-exynos/ehci.h | 13 ++++++++
>>>>  board/samsung/odroid/odroid.c           | 55 +++++++++++++++++++++++++++++++++
>>>>  drivers/usb/host/ehci-exynos.c          | 51 +++++++++++++++++++++++++-----
>>>>  include/configs/odroid.h                | 13 ++++++++
>>>>  6 files changed, 137 insertions(+), 8 deletions(-)
>>>>
>>>> diff --git a/arch/arm/dts/exynos4412-odroid.dts b/arch/arm/dts/exynos4412-odroid.dts
>>>> index 24d0bf1..ac5fece 100644
>>>> --- a/arch/arm/dts/exynos4412-odroid.dts
>>>> +++ b/arch/arm/dts/exynos4412-odroid.dts
>>>> @@ -67,4 +67,15 @@
>>>>               div = <0x3>;
>>>>               index = <4>;
>>>>       };
>>>> +
>>>> +     ehci@12580000 {
>>>> +             compatible = "samsung,exynos-ehci";
>>>> +             reg = <0x12580000 0x100>;
>>>> +             #address-cells = <1>;
>>>> +             #size-cells = <1>;
>>>> +             phy {
>>>> +                     compatible = "samsung,exynos-usb-phy";
>>>> +                     reg = <0x125B0000 0x100>;
>>>> +             };
>>>> +     };
>>>>  };
>>>> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
>>>> index ba71714..fda21fb 100644
>>>> --- a/arch/arm/include/asm/arch-exynos/cpu.h
>>>> +++ b/arch/arm/include/asm/arch-exynos/cpu.h
>>>> @@ -18,6 +18,8 @@
>>>>
>>>>  #define EXYNOS4_GPIO_PART3_BASE              0x03860000
>>>>  #define EXYNOS4_PRO_ID                       0x10000000
>>>> +#define EXYNOS4_GUID_LOW             0x10000014
>>>> +#define EXYNOS4_GUID_HIGH            0x10000018
>>>>  #define EXYNOS4_SYSREG_BASE          0x10010000
>>>>  #define EXYNOS4_POWER_BASE           0x10020000
>>>>  #define EXYNOS4_SWRESET                      0x10020400
>>>> diff --git a/arch/arm/include/asm/arch-exynos/ehci.h b/arch/arm/include/asm/arch-exynos/ehci.h
>>>> index d2d70bd..3800fa9 100644
>>>> --- a/arch/arm/include/asm/arch-exynos/ehci.h
>>>> +++ b/arch/arm/include/asm/arch-exynos/ehci.h
>>>> @@ -12,6 +12,13 @@
>>>>
>>>>  #define CLK_24MHZ            5
>>>>
>>>> +#define PHYPWR_NORMAL_MASK_PHY0                 (0x39 << 0)
>>>> +#define PHYPWR_NORMAL_MASK_PHY1                 (0x7 << 6)
>>>> +#define PHYPWR_NORMAL_MASK_HSIC0                (0x7 << 9)
>>>> +#define PHYPWR_NORMAL_MASK_HSIC1                (0x7 << 12)
>>>> +#define RSTCON_HOSTPHY_SWRST                    (0xf << 3)
>>>> +#define RSTCON_SWRST                            (0x1 << 0)
>>>> +
>>>>  #define HOST_CTRL0_PHYSWRSTALL                       (1 << 31)
>>>>  #define HOST_CTRL0_COMMONON_N                        (1 << 9)
>>>>  #define HOST_CTRL0_SIDDQ                     (1 << 6)
>>>> @@ -61,6 +68,12 @@ struct exynos_usb_phy {
>>>>       unsigned int usbotgtune;
>>>>  };
>>>>
>>>> +struct exynos4412_usb_phy {
>>>> +     unsigned int usbphyctrl;
>>>> +     unsigned int usbphyclk;
>>>> +     unsigned int usbphyrstcon;
>>>> +};
>>>> +
>>>>  /* Switch on the VBUS power. */
>>>>  int board_usb_vbus_init(void);
>>>>
>>>> diff --git a/board/samsung/odroid/odroid.c b/board/samsung/odroid/odroid.c
>>>> index 5edb250..6c78b67 100644
>>>> --- a/board/samsung/odroid/odroid.c
>>>> +++ b/board/samsung/odroid/odroid.c
>>>> @@ -453,9 +453,64 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
>>>>       .usb_phy_ctrl   = EXYNOS4X12_USBPHY_CONTROL,
>>>>       .usb_flags      = PHY0_SLEEP,
>>>>  };
>>>> +#endif
>>>> +
>>>> +#if defined(CONFIG_USB_GADGET) || defined(CONFIG_CMD_USB)
>>>> +
>>>> +#ifdef CONFIG_CMD_USB
>>>> +static void set_usb_ethaddr(void)
>>>> +{
>>>> +     int i;
>>>> +     uchar mac[6];
>>>> +     unsigned int guid_high = readl(EXYNOS4_GUID_HIGH);
>>>> +     unsigned int guid_low = readl(EXYNOS4_GUID_LOW);
>>>
>>> We don't allow direct access.
>>> Is it special register? I can't find this register on TRM.
>>> If so you can make inline function at cpu.h instead.
>>>
>>
>> This register is not in the TRM. This register is possibly documented
>> in the TRM for the Exynos5250. Through experimentation I found that it
>> behaves the same on Exynos4412 prime as well - I checked this with one
>> X2, 1 U2 and 2 U3s, and they do indeed do the job of being unique and
>> hence can be used to generate the mac address which will be unique
>> across all U2s/U3s/X2s and possibly other Exynos SoCs like Exynos4212
>> etc.
>>
>> Regarding direct access, I am a bit confused. In odroid.c I see quite
>> a many places which is doing a readl() of registers. Here we are
>> readl(addr) into guid_* similarly, and cooking up a mac address in a
>> local char array.
>>
>> I fail to see your point. Can you please elaborate more, so I can comprehend?
>>
>
> Samsung SoCs always get the address of register using accessor functions(samsung_get_base_xxx).
>

Ah! I see your point.

Unfortunately, use of these beloved registers has been thwarted by
Przemyslaw Marczak.

Regards
- Suriyan

> Thanks,
> Minkyu Kang.
>
Przemyslaw Marczak Oct. 28, 2014, 7:47 a.m. UTC | #7
Hello Suriyan Ramasami,

On 10/27/2014 08:34 PM, Suriyan Ramasami wrote:
> Hello Przemyslaw Marczak,
>
> On Mon, Oct 27, 2014 at 4:08 AM, Przemyslaw Marczak
> <p.marczak@samsung.com> wrote:
>> Hello Suriyan,
>>
>>
>> On 10/24/2014 06:08 PM, Suriyan Ramasami wrote:
>>>
>>> Hello Minkyu Kang,
>>>
>>>
>>> On Thu, Oct 23, 2014 at 9:58 PM, Minkyu Kang <mk7.kang@samsung.com> wrote:
>>>>
>>>> Dear Suriyan Ramasami,
>>>>
>>>> On 21/10/14 02:52, Suriyan Ramasami wrote:
>>>>>
>>>>> This change adds support for enabling the USB host features of the
>>>>> board.
>>>>> This includes the USB3503A hub and the SMC LAN9730 ethernet controller
>>>>> as well.
>>>>>
>>>>> Credit goes to Tushar Berara for the function set_usb_ethaddr().
>>>>>
>>>>> Signed-off-by: Suriyan Ramasami <suriyan.r@gmail.com>
>>>>>
>>>>> ---
>>>>> v2:
>>>>>    * Removed an unneeded header file from ehci-exynos.c
>>>>>    * Fix indentation in the dts file
>>>>> ---
>>>>>    arch/arm/dts/exynos4412-odroid.dts      | 11 +++++++
>>>>>    arch/arm/include/asm/arch-exynos/cpu.h  |  2 ++
>>>>>    arch/arm/include/asm/arch-exynos/ehci.h | 13 ++++++++
>>>>>    board/samsung/odroid/odroid.c           | 55
>>>>> +++++++++++++++++++++++++++++++++
>>>>>    drivers/usb/host/ehci-exynos.c          | 51
>>>>> +++++++++++++++++++++++++-----
>>>>>    include/configs/odroid.h                | 13 ++++++++
>>>>>    6 files changed, 137 insertions(+), 8 deletions(-)
>>>>>
>>>>> diff --git a/arch/arm/dts/exynos4412-odroid.dts
>>>>> b/arch/arm/dts/exynos4412-odroid.dts
>>>>> index 24d0bf1..ac5fece 100644
>>>>> --- a/arch/arm/dts/exynos4412-odroid.dts
>>>>> +++ b/arch/arm/dts/exynos4412-odroid.dts
>>>>> @@ -67,4 +67,15 @@
>>>>>                 div = <0x3>;
>>>>>                 index = <4>;
>>>>>         };
>>>>> +
>>>>> +     ehci@12580000 {
>>>>> +             compatible = "samsung,exynos-ehci";
>>>>> +             reg = <0x12580000 0x100>;
>>>>> +             #address-cells = <1>;
>>>>> +             #size-cells = <1>;
>>>>> +             phy {
>>>>> +                     compatible = "samsung,exynos-usb-phy";
>>>>> +                     reg = <0x125B0000 0x100>;
>>>>> +             };
>>>>> +     };
>>>>>    };
>>>>> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h
>>>>> b/arch/arm/include/asm/arch-exynos/cpu.h
>>>>> index ba71714..fda21fb 100644
>>>>> --- a/arch/arm/include/asm/arch-exynos/cpu.h
>>>>> +++ b/arch/arm/include/asm/arch-exynos/cpu.h
>>>>> @@ -18,6 +18,8 @@
>>>>>
>>>>>    #define EXYNOS4_GPIO_PART3_BASE              0x03860000
>>>>>    #define EXYNOS4_PRO_ID                       0x10000000
>>>>> +#define EXYNOS4_GUID_LOW             0x10000014
>>>>> +#define EXYNOS4_GUID_HIGH            0x10000018
>>>>>    #define EXYNOS4_SYSREG_BASE          0x10010000
>>>>>    #define EXYNOS4_POWER_BASE           0x10020000
>>>>>    #define EXYNOS4_SWRESET                      0x10020400
>>>>> diff --git a/arch/arm/include/asm/arch-exynos/ehci.h
>>>>> b/arch/arm/include/asm/arch-exynos/ehci.h
>>>>> index d2d70bd..3800fa9 100644
>>>>> --- a/arch/arm/include/asm/arch-exynos/ehci.h
>>>>> +++ b/arch/arm/include/asm/arch-exynos/ehci.h
>>>>> @@ -12,6 +12,13 @@
>>>>>
>>>>>    #define CLK_24MHZ            5
>>>>>
>>>>> +#define PHYPWR_NORMAL_MASK_PHY0                 (0x39 << 0)
>>>>> +#define PHYPWR_NORMAL_MASK_PHY1                 (0x7 << 6)
>>>>> +#define PHYPWR_NORMAL_MASK_HSIC0                (0x7 << 9)
>>>>> +#define PHYPWR_NORMAL_MASK_HSIC1                (0x7 << 12)
>>>>> +#define RSTCON_HOSTPHY_SWRST                    (0xf << 3)
>>>>> +#define RSTCON_SWRST                            (0x1 << 0)
>>>>> +
>>>>>    #define HOST_CTRL0_PHYSWRSTALL                       (1 << 31)
>>>>>    #define HOST_CTRL0_COMMONON_N                        (1 << 9)
>>>>>    #define HOST_CTRL0_SIDDQ                     (1 << 6)
>>>>> @@ -61,6 +68,12 @@ struct exynos_usb_phy {
>>>>>         unsigned int usbotgtune;
>>>>>    };
>>>>>
>>>>> +struct exynos4412_usb_phy {
>>>>> +     unsigned int usbphyctrl;
>>>>> +     unsigned int usbphyclk;
>>>>> +     unsigned int usbphyrstcon;
>>>>> +};
>>>>> +
>>>>>    /* Switch on the VBUS power. */
>>>>>    int board_usb_vbus_init(void);
>>>>>
>>>>> diff --git a/board/samsung/odroid/odroid.c
>>>>> b/board/samsung/odroid/odroid.c
>>>>> index 5edb250..6c78b67 100644
>>>>> --- a/board/samsung/odroid/odroid.c
>>>>> +++ b/board/samsung/odroid/odroid.c
>>>>> @@ -453,9 +453,64 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
>>>>>         .usb_phy_ctrl   = EXYNOS4X12_USBPHY_CONTROL,
>>>>>         .usb_flags      = PHY0_SLEEP,
>>>>>    };
>>>>> +#endif
>>>>> +
>>>>> +#if defined(CONFIG_USB_GADGET) || defined(CONFIG_CMD_USB)
>>>>> +
>>>>> +#ifdef CONFIG_CMD_USB
>>>>> +static void set_usb_ethaddr(void)
>>>>> +{
>>>>> +     int i;
>>>>> +     uchar mac[6];
>>>>> +     unsigned int guid_high = readl(EXYNOS4_GUID_HIGH);
>>>>> +     unsigned int guid_low = readl(EXYNOS4_GUID_LOW);
>>>>
>>>>
>>>> We don't allow direct access.
>>>> Is it special register? I can't find this register on TRM.
>>>> If so you can make inline function at cpu.h instead.
>>>>
>>>
>>> This register is not in the TRM. This register is possibly documented
>>> in the TRM for the Exynos5250. Through experimentation I found that it
>>> behaves the same on Exynos4412 prime as well - I checked this with one
>>> X2, 1 U2 and 2 U3s, and they do indeed do the job of being unique and
>>> hence can be used to generate the mac address which will be unique
>>> across all U2s/U3s/X2s and possibly other Exynos SoCs like Exynos4212
>>> etc.
>>>
>>
>> Those register addresses are not documented anywhere. So use of them is not
>> a good idea and can cause unpredictable results, even if was tested on a few
>> devices.
>>
>
> OK, fair enough. I thought somehow it would be documented in the
> Samsung internal user manual. I guess it is not!
>
I checked some of the Exynos4 and Exynos5 documentation, and 
unfortunately I didn't found any information about those registers.
Maybe there is some meaning of them, but rather for the vendor, than for 
the user.

>>> Regarding direct access, I am a bit confused. In odroid.c I see quite
>>> a many places which is doing a readl() of registers. Here we are
>>> readl(addr) into guid_* similarly, and cooking up a mac address in a
>>> local char array.
>>>
>>> I fail to see your point. Can you please elaborate more, so I can
>>> comprehend?
>>>
>>
>> The MAC address is defined by IEEE standard, so we can't use magic numbers
>> from undefined registers.
>
> I am aware of that. In the code by Tushar Behera you will see that he
> does mark it - "not multicast and outside official 80211 MAC
> namespace".
>

Ok, but this is an open source code, and I assume that it should keeps 
some of the standards?

>> I see two ways to do it:
>> - put the MAC into environment
>> - use of UUID generator from: lib/uuid.c
>>
>> On the Odroid you will get the hardware acceleration, because the hardware
>> random number generator is enabled.
>>
>
> Let me research a bit - if a random MAC address can indeed be cooked
> up. If not, as you suggest, we can leave it as an onus on the user to
> set it in the env. (which is what is being done currently).
>
> Do you have any pointers in using the hardware random generator in the
> Odroid? That does seem promising.
>

The random MAC in the meaning that 3-bytes for the vendor and 3 random 
generated(unique) - for the automation.
But the environment variable with MAC is simpler to do and don't require 
  hardcode the vendor's 3 bytes of MAC.

Please look into the lib/uuid.c:
- gen_rand_uuid()
- gen_rand_uuid_str()
This is also used by "gpt" command.
If you enable CONFIG_CMD_UUID, then you can see how it works on the console.

>>
>>>>> +
>>>>> +     for (i = 0; i < 2; i++)
>>>>> +             mac[i] = (guid_high >> (8 * (1 - i))) & 0xFF;
>>>>> +
>>>>> +     for (i = 0; i < 4; i++)
>>>>> +             mac[i+2] = (guid_low >> (8 * (3 - i))) & 0xFF;
>>>>
>>>>
>>>> please add space. i + 2
>>>>
>>>
>>> Shall do so.
>>>
>>>>> +
>>>>> +     /* mark it as not multicast and outside official 80211 MAC
>>>>> namespace */
>>>>> +     mac[0] = (mac[0] & ~0x1) | 0x2;
>>>>> +
>>>>> +     eth_setenv_enetaddr("ethaddr", mac);
>>>>> +     eth_setenv_enetaddr("usbethaddr", mac);
>>>>> +}
>>>>> +#endif
>>>>>
>>>>>    int board_usb_init(int index, enum usb_init_type init)
>>>>>    {
>>>>> +#ifdef CONFIG_CMD_USB
>>>>> +     struct pmic *p_pmic;
>>>>> +
>>>>> +     /* Set Ref freq 0 => 24MHz, 1 => 26MHz*/
>>>>> +     /* Odroid Us have it at 24MHz, Odroid Xs at 26MHz */
>>>>> +     if (gd->board_type == ODROID_TYPE_U3)
>>>>> +             gpio_direction_output(EXYNOS4X12_GPIO_X30, 0);
>>>>> +     else
>>>>> +             gpio_direction_output(EXYNOS4X12_GPIO_X30, 1);
>>>>> +
>>>>> +     /* Disconnect, Reset, Connect */
>>>>> +     gpio_direction_output(EXYNOS4X12_GPIO_X34, 0);
>>>>> +     gpio_direction_output(EXYNOS4X12_GPIO_X35, 0);
>>>>> +     gpio_direction_output(EXYNOS4X12_GPIO_X35, 1);
>>>>> +     gpio_direction_output(EXYNOS4X12_GPIO_X34, 1);
>>>>> +
>>>>> +     /* Power off and on BUCK8 for LAN9730 */
>>>>> +     debug("LAN9730 - Turning power buck 8 OFF and ON.\n");
>>>>> +
>>>>> +     p_pmic = pmic_get("MAX77686_PMIC");
>>>>> +     if (p_pmic && !pmic_probe(p_pmic)) {
>>>>> +             max77686_set_buck_mode(p_pmic, 8, OPMODE_OFF);
>>>>> +             max77686_set_buck_voltage(p_pmic, 8, 750000);
>>>>> +             max77686_set_buck_voltage(p_pmic, 8, 3300000);
>>>>> +             max77686_set_buck_mode(p_pmic, 8, OPMODE_ON);
>>>>> +     }
>>>>> +
>>>>> +     set_usb_ethaddr();
>>>>> +#endif
>>>>> +
>>>>>         debug("USB_udc_probe\n");
>>>>>         return s3c_udc_probe(&s5pc210_otg_data);
>>>>>    }
>>>>> diff --git a/drivers/usb/host/ehci-exynos.c
>>>>> b/drivers/usb/host/ehci-exynos.c
>>>>> index edd91a8..9c479b1 100644
>>>>> --- a/drivers/usb/host/ehci-exynos.c
>>>>> +++ b/drivers/usb/host/ehci-exynos.c
>>>>> @@ -85,15 +85,10 @@ static int exynos_usb_parse_dt(const void *blob,
>>>>> struct exynos_ehci *exynos)
>>>>>    }
>>>>>    #endif
>>>>>
>>>>> -/* Setup the EHCI host controller. */
>>>>> -static void setup_usb_phy(struct exynos_usb_phy *usb)
>>>>> +static void exynos5_setup_usb_phy(struct exynos_usb_phy *usb)
>>>>>    {
>>>>>         u32 hsic_ctrl;
>>>>>
>>>>> -     set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
>>>>> -
>>>>> -     set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
>>>>> -
>>>>>         clrbits_le32(&usb->usbphyctrl0,
>>>>>                         HOST_CTRL0_FSEL_MASK |
>>>>>                         HOST_CTRL0_COMMONON_N |
>>>>> @@ -150,8 +145,32 @@ static void setup_usb_phy(struct exynos_usb_phy
>>>>> *usb)
>>>>>                         EHCICTRL_ENAINCR16);
>>>>>    }
>>>>>
>>>>> -/* Reset the EHCI host controller. */
>>>>> -static void reset_usb_phy(struct exynos_usb_phy *usb)
>>>>> +static void exynos4412_setup_usb_phy(struct exynos4412_usb_phy *usb)
>>>>> +{
>>>>> +     writel(CLK_24MHZ, &usb->usbphyclk);
>>>>> +
>>>>> +     clrbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
>>>>> +             PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
>>>>> +             PHYPWR_NORMAL_MASK_PHY0));
>>>>> +
>>>>> +     setbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST |
>>>>> RSTCON_SWRST));
>>>>> +     udelay(10);
>>>>> +     clrbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST |
>>>>> RSTCON_SWRST));
>>>>> +}
>>>>> +
>>>>> +static void setup_usb_phy(struct exynos_usb_phy *usb)
>>>>> +{
>>>>> +     set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
>>>>> +
>>>>> +     set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
>>>>> +
>>>>> +     if (cpu_is_exynos5())
>>>>> +             exynos5_setup_usb_phy(usb);
>>>>> +     else if (proid_is_exynos4412())
>>>>
>>>>
>>>> please don't mix cpu_is.. and proid_is...
>>>>
>>>> it should be
>>>>
>>>> if (cpu_is_exynos5()) {
>>>> }
>>>> else if (cpu_is_exynos4()) {
>>>>       if (proid_is_exynos4412()) {
>>>>       }
>>>> }
>>>>
>>>
>>> OK, I shall do so.
>>>
>>>>> +             exynos4412_setup_usb_phy((struct exynos4412_usb_phy
>>>>> *)usb);
>>>>> +}
>>>>> +
>>>>> +static void exynos5_reset_usb_phy(struct exynos_usb_phy *usb)
>>>>>    {
>>>>>         u32 hsic_ctrl;
>>>>>
>>>>> @@ -171,6 +190,22 @@ static void reset_usb_phy(struct exynos_usb_phy
>>>>> *usb)
>>>>>
>>>>>         setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
>>>>>         setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
>>>>> +}
>>>>> +
>>>>> +static void exynos4412_reset_usb_phy(struct exynos4412_usb_phy *usb)
>>>>> +{
>>>>> +     setbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
>>>>> +             PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
>>>>> +             PHYPWR_NORMAL_MASK_PHY0));
>>>>> +}
>>>>> +
>>>>> +/* Reset the EHCI host controller. */
>>>>> +static void reset_usb_phy(struct exynos_usb_phy *usb)
>>>>> +{
>>>>> +     if (cpu_is_exynos5())
>>>>> +             exynos5_reset_usb_phy(usb);
>>>>> +     else if (proid_is_exynos4412())
>>>>
>>>>
>>>> ditto.
>>>>
>>>
>>> OK, shall change this as well.
>>>
>>> Thanks for taking a look!
>>> - Suriyan
>>>
>>>>> +             exynos4412_reset_usb_phy((struct exynos4412_usb_phy
>>>>> *)usb);
>>>>>
>>>>>         set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE);
>>>>>    }
>>>>> diff --git a/include/configs/odroid.h b/include/configs/odroid.h
>>>>> index b928af8..807e96b 100644
>>>>> --- a/include/configs/odroid.h
>>>>> +++ b/include/configs/odroid.h
>>>>> @@ -198,6 +198,19 @@
>>>>>
>>>>>    #define CONFIG_CMD_GPIO
>>>>>
>>>>> +/* USB */
>>>>> +#define CONFIG_CMD_USB
>>>>> +#define CONFIG_USB_EHCI
>>>>> +#define CONFIG_USB_EHCI_EXYNOS
>>>>> +#define CONFIG_USB_STORAGE
>>>>> +
>>>>> +#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS   3
>>>>> +#define CONFIG_CMD_NET
>>>>> +#define CONFIG_CMD_PING
>>>>> +#define CONFIG_CMD_DHCP
>>>>> +#define CONFIG_USB_HOST_ETHER
>>>>> +#define CONFIG_USB_ETHER_SMSC95XX
>>>>> +
>>>>>    /*
>>>>>     * Supported Odroid boards: X3, U3
>>>>>     * TODO: Add Odroid X support
>>>>>
>>>>
>>>> Thanks,
>>>> Minkyu Kang.
>>
>>
>
> Thanks!
> - Suriyan
>
>> Best regards,
>> --
>> Przemyslaw Marczak
>> Samsung R&D Institute Poland
>> Samsung Electronics
>> p.marczak@samsung.com
>

Best regards,
Albert ARIBAUD Oct. 28, 2014, 8:08 a.m. UTC | #8
Hello Przemyslaw,

On Tue, 28 Oct 2014 08:47:47 +0100, Przemyslaw Marczak
<p.marczak@samsung.com> wrote:
> Hello Suriyan Ramasami,

> >> The MAC address is defined by IEEE standard, so we can't use magic numbers
> >> from undefined registers.
> >
> > I am aware of that. In the code by Tushar Behera you will see that he
> > does mark it - "not multicast and outside official 80211 MAC
> > namespace".
> >
> 
> Ok, but this is an open source code, and I assume that it should keeps 
> some of the standards?

At least the code could and should make sure the Locally Administered
flag is set in the randomly generated MAC -- that would keep the MAC
standard and ensure it won't conflict with universally administered
(iow, 'normal') MAC addresses.

Amicalement,
diff mbox

Patch

diff --git a/arch/arm/dts/exynos4412-odroid.dts b/arch/arm/dts/exynos4412-odroid.dts
index 24d0bf1..ac5fece 100644
--- a/arch/arm/dts/exynos4412-odroid.dts
+++ b/arch/arm/dts/exynos4412-odroid.dts
@@ -67,4 +67,15 @@ 
 		div = <0x3>;
 		index = <4>;
 	};
+
+	ehci@12580000 {
+		compatible = "samsung,exynos-ehci";
+		reg = <0x12580000 0x100>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		phy {
+			compatible = "samsung,exynos-usb-phy";
+			reg = <0x125B0000 0x100>;
+		};
+	};
 };
diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
index ba71714..fda21fb 100644
--- a/arch/arm/include/asm/arch-exynos/cpu.h
+++ b/arch/arm/include/asm/arch-exynos/cpu.h
@@ -18,6 +18,8 @@ 
 
 #define EXYNOS4_GPIO_PART3_BASE		0x03860000
 #define EXYNOS4_PRO_ID			0x10000000
+#define EXYNOS4_GUID_LOW		0x10000014
+#define EXYNOS4_GUID_HIGH		0x10000018
 #define EXYNOS4_SYSREG_BASE		0x10010000
 #define EXYNOS4_POWER_BASE		0x10020000
 #define EXYNOS4_SWRESET			0x10020400
diff --git a/arch/arm/include/asm/arch-exynos/ehci.h b/arch/arm/include/asm/arch-exynos/ehci.h
index d2d70bd..3800fa9 100644
--- a/arch/arm/include/asm/arch-exynos/ehci.h
+++ b/arch/arm/include/asm/arch-exynos/ehci.h
@@ -12,6 +12,13 @@ 
 
 #define CLK_24MHZ		5
 
+#define PHYPWR_NORMAL_MASK_PHY0                 (0x39 << 0)
+#define PHYPWR_NORMAL_MASK_PHY1                 (0x7 << 6)
+#define PHYPWR_NORMAL_MASK_HSIC0                (0x7 << 9)
+#define PHYPWR_NORMAL_MASK_HSIC1                (0x7 << 12)
+#define RSTCON_HOSTPHY_SWRST                    (0xf << 3)
+#define RSTCON_SWRST                            (0x1 << 0)
+
 #define HOST_CTRL0_PHYSWRSTALL			(1 << 31)
 #define HOST_CTRL0_COMMONON_N			(1 << 9)
 #define HOST_CTRL0_SIDDQ			(1 << 6)
@@ -61,6 +68,12 @@  struct exynos_usb_phy {
 	unsigned int usbotgtune;
 };
 
+struct exynos4412_usb_phy {
+	unsigned int usbphyctrl;
+	unsigned int usbphyclk;
+	unsigned int usbphyrstcon;
+};
+
 /* Switch on the VBUS power. */
 int board_usb_vbus_init(void);
 
diff --git a/board/samsung/odroid/odroid.c b/board/samsung/odroid/odroid.c
index 5edb250..6c78b67 100644
--- a/board/samsung/odroid/odroid.c
+++ b/board/samsung/odroid/odroid.c
@@ -453,9 +453,64 @@  struct s3c_plat_otg_data s5pc210_otg_data = {
 	.usb_phy_ctrl	= EXYNOS4X12_USBPHY_CONTROL,
 	.usb_flags	= PHY0_SLEEP,
 };
+#endif
+
+#if defined(CONFIG_USB_GADGET) || defined(CONFIG_CMD_USB)
+
+#ifdef CONFIG_CMD_USB
+static void set_usb_ethaddr(void)
+{
+	int i;
+	uchar mac[6];
+	unsigned int guid_high = readl(EXYNOS4_GUID_HIGH);
+	unsigned int guid_low = readl(EXYNOS4_GUID_LOW);
+
+	for (i = 0; i < 2; i++)
+		mac[i] = (guid_high >> (8 * (1 - i))) & 0xFF;
+
+	for (i = 0; i < 4; i++)
+		mac[i+2] = (guid_low >> (8 * (3 - i))) & 0xFF;
+
+	/* mark it as not multicast and outside official 80211 MAC namespace */
+	mac[0] = (mac[0] & ~0x1) | 0x2;
+
+	eth_setenv_enetaddr("ethaddr", mac);
+	eth_setenv_enetaddr("usbethaddr", mac);
+}
+#endif
 
 int board_usb_init(int index, enum usb_init_type init)
 {
+#ifdef CONFIG_CMD_USB
+	struct pmic *p_pmic;
+
+	/* Set Ref freq 0 => 24MHz, 1 => 26MHz*/
+	/* Odroid Us have it at 24MHz, Odroid Xs at 26MHz */
+	if (gd->board_type == ODROID_TYPE_U3)
+		gpio_direction_output(EXYNOS4X12_GPIO_X30, 0);
+	else
+		gpio_direction_output(EXYNOS4X12_GPIO_X30, 1);
+
+	/* Disconnect, Reset, Connect */
+	gpio_direction_output(EXYNOS4X12_GPIO_X34, 0);
+	gpio_direction_output(EXYNOS4X12_GPIO_X35, 0);
+	gpio_direction_output(EXYNOS4X12_GPIO_X35, 1);
+	gpio_direction_output(EXYNOS4X12_GPIO_X34, 1);
+
+	/* Power off and on BUCK8 for LAN9730 */
+	debug("LAN9730 - Turning power buck 8 OFF and ON.\n");
+
+	p_pmic = pmic_get("MAX77686_PMIC");
+	if (p_pmic && !pmic_probe(p_pmic)) {
+		max77686_set_buck_mode(p_pmic, 8, OPMODE_OFF);
+		max77686_set_buck_voltage(p_pmic, 8, 750000);
+		max77686_set_buck_voltage(p_pmic, 8, 3300000);
+		max77686_set_buck_mode(p_pmic, 8, OPMODE_ON);
+	}
+
+	set_usb_ethaddr();
+#endif
+
 	debug("USB_udc_probe\n");
 	return s3c_udc_probe(&s5pc210_otg_data);
 }
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index edd91a8..9c479b1 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -85,15 +85,10 @@  static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos)
 }
 #endif
 
-/* Setup the EHCI host controller. */
-static void setup_usb_phy(struct exynos_usb_phy *usb)
+static void exynos5_setup_usb_phy(struct exynos_usb_phy *usb)
 {
 	u32 hsic_ctrl;
 
-	set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
-
-	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
-
 	clrbits_le32(&usb->usbphyctrl0,
 			HOST_CTRL0_FSEL_MASK |
 			HOST_CTRL0_COMMONON_N |
@@ -150,8 +145,32 @@  static void setup_usb_phy(struct exynos_usb_phy *usb)
 			EHCICTRL_ENAINCR16);
 }
 
-/* Reset the EHCI host controller. */
-static void reset_usb_phy(struct exynos_usb_phy *usb)
+static void exynos4412_setup_usb_phy(struct exynos4412_usb_phy *usb)
+{
+	writel(CLK_24MHZ, &usb->usbphyclk);
+
+	clrbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
+		PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
+		PHYPWR_NORMAL_MASK_PHY0));
+
+	setbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
+	udelay(10);
+	clrbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
+}
+
+static void setup_usb_phy(struct exynos_usb_phy *usb)
+{
+	set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
+
+	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
+
+	if (cpu_is_exynos5())
+		exynos5_setup_usb_phy(usb);
+	else if (proid_is_exynos4412())
+		exynos4412_setup_usb_phy((struct exynos4412_usb_phy *)usb);
+}
+
+static void exynos5_reset_usb_phy(struct exynos_usb_phy *usb)
 {
 	u32 hsic_ctrl;
 
@@ -171,6 +190,22 @@  static void reset_usb_phy(struct exynos_usb_phy *usb)
 
 	setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
 	setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
+}
+
+static void exynos4412_reset_usb_phy(struct exynos4412_usb_phy *usb)
+{
+	setbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
+		PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
+		PHYPWR_NORMAL_MASK_PHY0));
+}
+
+/* Reset the EHCI host controller. */
+static void reset_usb_phy(struct exynos_usb_phy *usb)
+{
+	if (cpu_is_exynos5())
+		exynos5_reset_usb_phy(usb);
+	else if (proid_is_exynos4412())
+		exynos4412_reset_usb_phy((struct exynos4412_usb_phy *)usb);
 
 	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE);
 }
diff --git a/include/configs/odroid.h b/include/configs/odroid.h
index b928af8..807e96b 100644
--- a/include/configs/odroid.h
+++ b/include/configs/odroid.h
@@ -198,6 +198,19 @@ 
 
 #define CONFIG_CMD_GPIO
 
+/* USB */
+#define CONFIG_CMD_USB
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_EXYNOS
+#define CONFIG_USB_STORAGE
+
+#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS	3
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_SMSC95XX
+
 /*
  * Supported Odroid boards: X3, U3
  * TODO: Add Odroid X support