From 1b26bab12e85e8b0d382d6775e40d14445249574 Mon Sep 17 00:00:00 2001 From: Daniel Kochmański Date: Fri, 29 May 2015 16:55:43 +0200 Subject: mmc: Protect `mmc_initialize` from initialising mmc multiple times `mmc_initialize` might be called multiple times leading to the mmc-controllers being initialised twice, and initialising the `mmc_devices` list head twice which may lead to memory leaks. Signed-off-by: Daniel Kochmański CC: Roy Spliet Cc: Ian Campbell CC: Pantelis Antoniou Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/mmc/mmc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index da47037a306..f12546ac519 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1762,6 +1762,11 @@ static void do_preinit(void) int mmc_initialize(bd_t *bis) { + static int initialized = 0; + if (initialized) /* Avoid initializing mmc multiple times */ + return 0; + initialized = 1; + INIT_LIST_HEAD (&mmc_devices); cur_dev_num = 0; -- cgit v1.2.3 From 645c48f50eab307a9879a82c4d066e74114ec78a Mon Sep 17 00:00:00 2001 From: Daniel Kochmański Date: Fri, 29 May 2015 16:55:41 +0200 Subject: sunxi: Create helper function veryfing valid boot signature on MMC This patch extracts checking for valid SD card "eGON.BT0" signature from `board_mmc_init` into function `sunxi_mmc_has_egon_boot_signature`. Buffer for mmc sector is allocated and freed at runtime. `panic` is triggered on malloc failure. Signed-off-by: Daniel Kochmański CC: Roy Spliet Cc: Ian Campbell [hdegoede@redhat.com: Small bugfix to make it work for devs other then mmc0] Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/include/asm/arch-sunxi/mmc.h | 1 + board/sunxi/board.c | 8 ++------ drivers/mmc/sunxi_mmc.c | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h index cb52e648731..3da360b177d 100644 --- a/arch/arm/include/asm/arch-sunxi/mmc.h +++ b/arch/arm/include/asm/arch-sunxi/mmc.h @@ -127,4 +127,5 @@ struct sunxi_mmc { #define SUNXI_MMC_COMMON_RESET (1 << 18) struct mmc *sunxi_mmc_init(int sdc_no); +int sunxi_mmc_has_egon_boot_signature(struct mmc *mmc); #endif /* _SUNXI_MMC_H */ diff --git a/board/sunxi/board.c b/board/sunxi/board.c index ed60e74808f..76e4b9bcc1e 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -299,12 +299,8 @@ int board_mmc_init(bd_t *bis) * Both mmc0 and mmc2 are bootable, figure out where we're booting * from. Try mmc0 first, just like the brom does. */ - if (mmc_getcd(mmc0) && mmc_init(mmc0) == 0 && - mmc0->block_dev.block_read(0, 16, 1, buf) == 1) { - buf[12] = 0; - if (strcmp(&buf[4], "eGON.BT0") == 0) - return 0; - } + if (sunxi_mmc_has_egon_boot_signature(mmc0)) + return 0; /* no bootable card in mmc0, so we must be booting from mmc2, swap */ mmc0->block_dev.dev = 1; diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index e7ab828a8f1..f9b9493c892 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -433,6 +433,23 @@ static int sunxi_mmc_getcd(struct mmc *mmc) return !gpio_get_value(cd_pin); } +int sunxi_mmc_has_egon_boot_signature(struct mmc *mmc) +{ + char *buf = malloc(512); + int valid_signature = 0; + + if (buf == NULL) + panic("Failed to allocate memory\n"); + + if (mmc_getcd(mmc) && mmc_init(mmc) == 0 && + mmc->block_dev.block_read(mmc->block_dev.dev, 16, 1, buf) == 1 && + strncmp(&buf[4], "eGON.BT0", 8) == 0) + valid_signature = 1; + + free(buf); + return valid_signature; +} + static const struct mmc_ops sunxi_mmc_ops = { .send_cmd = sunxi_mmc_send_cmd, .set_ios = sunxi_mmc_set_ios, -- cgit v1.2.3 From b41972e7d17fb920cc50db5b363209685b1251e5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 14 Jun 2015 16:48:56 +0200 Subject: sunxi: musb: Move vbus check to sunxi_musb_enable This way it can be re-checked on "usb reset". Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/usb/musb-new/sunxi.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index c123d61af2c..ee018c7e6e7 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -201,6 +201,8 @@ static bool enabled = false; static int sunxi_musb_enable(struct musb *musb) { + int ret; + pr_debug("%s():\n", __func__); if (enabled) @@ -209,8 +211,14 @@ static int sunxi_musb_enable(struct musb *musb) /* select PIO mode */ musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0); - if (is_host_enabled(musb)) + if (is_host_enabled(musb)) { + ret = sunxi_usb_phy_vbus_detect(0); + if (ret) { + printf("A charger is plugged into the OTG: "); + return -ENODEV; + } sunxi_usb_phy_power_on(0); /* port power on */ + } USBC_ForceVbusValidToHigh(musb->mregs); @@ -237,18 +245,9 @@ static void sunxi_musb_disable(struct musb *musb) static int sunxi_musb_init(struct musb *musb) { struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - int err; pr_debug("%s():\n", __func__); - if (is_host_enabled(musb)) { - err = sunxi_usb_phy_vbus_detect(0); - if (err) { - eprintf("Error: A charger is plugged into the OTG\n"); - return -EIO; - } - } - musb->isr = sunxi_musb_interrupt; setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); -- cgit v1.2.3 From 71cbe0d681d4288d090a404273ce6b0c1c14b617 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 14 Jun 2015 17:40:37 +0200 Subject: sunxi: musb: Add id pin support When in host mode check if there is a host cable inserted into the otg port by checking the id pin. If there is no host cable return an error to make usb_lowlevel_init() exit early, rather then waiting for 1 second for a device which will never show up. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- configs/Ippo_q8h_v1_2_a33_1024x600_defconfig | 1 + configs/Ippo_q8h_v1_2_defconfig | 1 + configs/Ippo_q8h_v5_defconfig | 1 + drivers/usb/musb-new/sunxi.c | 5 +++++ 4 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/configs/Ippo_q8h_v1_2_a33_1024x600_defconfig b/configs/Ippo_q8h_v1_2_a33_1024x600_defconfig index 012a25bc671..fda7683a7b8 100644 --- a/configs/Ippo_q8h_v1_2_a33_1024x600_defconfig +++ b/configs/Ippo_q8h_v1_2_a33_1024x600_defconfig @@ -5,6 +5,7 @@ CONFIG_DRAM_CLK=480 CONFIG_DRAM_ZQ=15291 CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE" CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT" +CONFIG_USB0_ID_DET="PH8" CONFIG_AXP_GPIO=y CONFIG_VIDEO_LCD_MODE="x:1024,y:600,depth:18,pclk_khz:51000,le:159,ri:160,up:22,lo:12,hs:1,vs:1,sync:3,vmode:0" CONFIG_VIDEO_LCD_DCLK_PHASE=0 diff --git a/configs/Ippo_q8h_v1_2_defconfig b/configs/Ippo_q8h_v1_2_defconfig index 783467b8981..490cbe2be8e 100644 --- a/configs/Ippo_q8h_v1_2_defconfig +++ b/configs/Ippo_q8h_v1_2_defconfig @@ -5,6 +5,7 @@ CONFIG_DRAM_CLK=432 CONFIG_DRAM_ZQ=63306 CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE" CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT" +CONFIG_USB0_ID_DET="PH8" CONFIG_AXP_GPIO=y CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:87,ri:167,up:31,lo:13,hs:1,vs:1,sync:3,vmode:0" CONFIG_VIDEO_LCD_DCLK_PHASE=0 diff --git a/configs/Ippo_q8h_v5_defconfig b/configs/Ippo_q8h_v5_defconfig index 29e3c895105..aa1eb691e70 100644 --- a/configs/Ippo_q8h_v5_defconfig +++ b/configs/Ippo_q8h_v5_defconfig @@ -5,6 +5,7 @@ CONFIG_DRAM_CLK=480 CONFIG_DRAM_ZQ=63351 CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE" CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT" +CONFIG_USB0_ID_DET="PH8" CONFIG_AXP_GPIO=y CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:87,ri:168,up:31,lo:13,hs:1,vs:1,sync:3,vmode:0" CONFIG_VIDEO_LCD_DCLK_PHASE=0 diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index ee018c7e6e7..cafb48039e3 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -217,6 +217,11 @@ static int sunxi_musb_enable(struct musb *musb) printf("A charger is plugged into the OTG: "); return -ENODEV; } + ret = sunxi_usb_phy_id_detect(0); + if (ret == 1) { + printf("No host cable detected: "); + return -ENODEV; + } sunxi_usb_phy_power_on(0); /* port power on */ } -- cgit v1.2.3 From d42faf3198262710d17548950e1ab41413e8b7f9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 17 Jun 2015 15:49:26 +0200 Subject: sunxi: musb: Move musb config and platdata to the sunxi-musb glue Move the musb config and platdata to the sunxi-musb glue, which is where it really belongs. This is preparation patch for adding device-model support for the sunxi-musb-host code. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- arch/arm/include/asm/arch-sunxi/usb_phy.h | 7 +++++++ board/sunxi/board.c | 28 ++----------------------- drivers/usb/musb-new/sunxi.c | 35 ++++++++++++++++++++++--------- 3 files changed, 34 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/arch/arm/include/asm/arch-sunxi/usb_phy.h b/arch/arm/include/asm/arch-sunxi/usb_phy.h index 5a9cacb6f4a..17d31b8e31c 100644 --- a/arch/arm/include/asm/arch-sunxi/usb_phy.h +++ b/arch/arm/include/asm/arch-sunxi/usb_phy.h @@ -19,3 +19,10 @@ void sunxi_usb_phy_power_off(int index); int sunxi_usb_phy_vbus_detect(int index); int sunxi_usb_phy_id_detect(int index); void sunxi_usb_phy_enable_squelch_detect(int index, int enable); + +/* Not really phy related, but we have to declare this somewhere ... */ +#if defined(CONFIG_MUSB_HOST) || defined(CONFIG_MUSB_GADGET) +void sunxi_musb_board_init(void); +#else +#define sunxi_musb_board_init() +#endif diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 7220af34542..afed6a31cab 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #if defined CONFIG_VIDEO_LCD_PANEL_I2C && !(defined CONFIG_SPL_BUILD) @@ -449,28 +448,6 @@ void sunxi_board_init(void) } #endif -#if defined(CONFIG_MUSB_HOST) || defined(CONFIG_MUSB_GADGET) -extern const struct musb_platform_ops sunxi_musb_ops; - -static struct musb_hdrc_config musb_config = { - .multipoint = 1, - .dyn_fifo = 1, - .num_eps = 6, - .ram_bits = 11, -}; - -static struct musb_hdrc_platform_data musb_plat = { -#if defined(CONFIG_MUSB_HOST) - .mode = MUSB_HOST, -#else - .mode = MUSB_PERIPHERAL, -#endif - .config = &musb_config, - .power = 250, - .platform_ops = &sunxi_musb_ops, -}; -#endif - #ifdef CONFIG_USB_GADGET int g_dnl_board_usb_cable_connected(void) { @@ -533,9 +510,8 @@ int misc_init_r(void) if (ret) return ret; #endif -#if defined(CONFIG_MUSB_HOST) || defined(CONFIG_MUSB_GADGET) - musb_register(&musb_plat, NULL, (void *)SUNXI_USB0_BASE); -#endif + sunxi_musb_board_init(); + return 0; } #endif diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index cafb48039e3..cbd2954c41f 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -26,17 +26,9 @@ #include #include #include +#include #include "linux-compat.h" #include "musb_core.h" -#ifdef CONFIG_AXP152_POWER -#include -#endif -#ifdef CONFIG_AXP209_POWER -#include -#endif -#ifdef CONFIG_AXP221_POWER -#include -#endif /****************************************************************************** ****************************************************************************** @@ -277,8 +269,31 @@ static int sunxi_musb_init(struct musb *musb) return 0; } -const struct musb_platform_ops sunxi_musb_ops = { +static const struct musb_platform_ops sunxi_musb_ops = { .init = sunxi_musb_init, .enable = sunxi_musb_enable, .disable = sunxi_musb_disable, }; + +static struct musb_hdrc_config musb_config = { + .multipoint = 1, + .dyn_fifo = 1, + .num_eps = 6, + .ram_bits = 11, +}; + +static struct musb_hdrc_platform_data musb_plat = { +#if defined(CONFIG_MUSB_HOST) + .mode = MUSB_HOST, +#else + .mode = MUSB_PERIPHERAL, +#endif + .config = &musb_config, + .power = 250, + .platform_ops = &sunxi_musb_ops, +}; + +void sunxi_musb_board_init(void) +{ + musb_register(&musb_plat, NULL, (void *)SUNXI_USB0_BASE); +} -- cgit v1.2.3 From 91183babea8f36d7bea40ecbc3862913ca0eae65 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 17 Jun 2015 17:44:58 +0200 Subject: sunxi: musb: Use device-model for musb host mode Modify the sunxi musb glue to use the device-model for musb host mode. This allows using musb in host mode together with other host drivers such as ehci / ohci, which is esp. useful on boards which use the musb controller in host-only mode, these boards have e.g. an usb-a receptacle or an usb to sata converter attached to the musb controller. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- arch/arm/Kconfig | 2 +- drivers/usb/musb-new/sunxi.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0e899cd0d94..3355b3bcaa5 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -648,7 +648,7 @@ config ARCH_SUNXI select DM_GPIO select DM_ETH select DM_SERIAL - select DM_USB if !USB_MUSB_SUNXI + select DM_USB select OF_CONTROL select OF_SEPARATE select SPL_DISABLE_OF_CONTROL diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index cbd2954c41f..6109011dca0 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -26,9 +26,12 @@ #include #include #include +#include +#include #include #include "linux-compat.h" #include "musb_core.h" +#include "musb_uboot.h" /****************************************************************************** ****************************************************************************** @@ -293,7 +296,61 @@ static struct musb_hdrc_platform_data musb_plat = { .platform_ops = &sunxi_musb_ops, }; +#ifdef CONFIG_MUSB_HOST +int musb_usb_probe(struct udevice *dev) +{ + struct musb_host_data *host = dev_get_priv(dev); + struct usb_bus_priv *priv = dev_get_uclass_priv(dev); + + priv->desc_before_addr = true; + + if (!host->host) { + host->host = musb_init_controller(&musb_plat, NULL, + (void *)SUNXI_USB0_BASE); + if (!host->host) { + printf("Failed to init the controller\n"); + return -EIO; + } + } + + printf("MUSB OTG in host-mode\n"); + + return musb_lowlevel_init(host); +} + +int musb_usb_remove(struct udevice *dev) +{ + struct musb_host_data *host = dev_get_priv(dev); + + musb_stop(host->host); + + return 0; +} + +U_BOOT_DRIVER(usb_musb) = { + .name = "sunxi-musb", + .id = UCLASS_USB, + .probe = musb_usb_probe, + .remove = musb_usb_remove, + .ops = &musb_usb_ops, + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct musb_host_data), +}; +#endif + void sunxi_musb_board_init(void) { +#ifdef CONFIG_MUSB_HOST + struct udevice *dev; + + /* + * Bind the driver directly for now as musb linux kernel support is + * still pending upstream so our dts files do not have the necessary + * nodes yet. TODO: Remove this as soon as the dts nodes are in place + * and bind by compatible instead. + */ + device_bind_driver(dm_root(), "sunxi-musb", "sunxi-musb", &dev); +#else musb_register(&musb_plat, NULL, (void *)SUNXI_USB0_BASE); +#endif } -- cgit v1.2.3 From 56a2085410d507c00d4bc374f9af10816638df24 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 18 Jun 2015 22:45:34 +0200 Subject: sunxi: musb: Improve output during probing When we return an error the usb core will print an error-message, so in this case do not print anything. Signed-off-by: Hans de Goede Reviewed-by: Marek Vasut Acked-by: Ian Campbell --- drivers/usb/musb-new/sunxi.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 6109011dca0..3542326238d 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -301,21 +301,22 @@ int musb_usb_probe(struct udevice *dev) { struct musb_host_data *host = dev_get_priv(dev); struct usb_bus_priv *priv = dev_get_uclass_priv(dev); + int ret; priv->desc_before_addr = true; if (!host->host) { host->host = musb_init_controller(&musb_plat, NULL, (void *)SUNXI_USB0_BASE); - if (!host->host) { - printf("Failed to init the controller\n"); + if (!host->host) return -EIO; - } } - printf("MUSB OTG in host-mode\n"); + ret = musb_lowlevel_init(host); + if (ret == 0) + printf("MUSB OTG\n"); - return musb_lowlevel_init(host); + return ret; } int musb_usb_remove(struct udevice *dev) -- cgit v1.2.3 From 9ecce9707b05189a762fc87c8483408d175774df Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 18 Jun 2015 18:21:33 +0200 Subject: sunxi: musb: Stop treating not having a vbus-det gpio as an error On some boards the otg is wired up in host-only mode in this case we have no vbus-det gpio. Stop logging an error from sunxi_usb_phy_vbus_detect() in this case, and stop treating sunxi_usb_phy_vbus_detect() returning a negative errno, as if a charger is plugged into the otg port. Signed-off-by: Hans de Goede Reviewed-by: Marek Vasut Acked-by: Ian Campbell --- arch/arm/cpu/armv7/sunxi/usb_phy.c | 4 +--- drivers/usb/musb-new/sunxi.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/arch/arm/cpu/armv7/sunxi/usb_phy.c b/arch/arm/cpu/armv7/sunxi/usb_phy.c index 5e82ddc505d..4d63a7449d7 100644 --- a/arch/arm/cpu/armv7/sunxi/usb_phy.c +++ b/arch/arm/cpu/armv7/sunxi/usb_phy.c @@ -237,10 +237,8 @@ int sunxi_usb_phy_vbus_detect(int index) struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; int err, retries = 3; - if (phy->gpio_vbus_det < 0) { - eprintf("Error: invalid vbus detection pin\n"); + if (phy->gpio_vbus_det < 0) return phy->gpio_vbus_det; - } err = gpio_get_value(phy->gpio_vbus_det); /* diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 3542326238d..3a29b18e5f4 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -208,7 +208,7 @@ static int sunxi_musb_enable(struct musb *musb) if (is_host_enabled(musb)) { ret = sunxi_usb_phy_vbus_detect(0); - if (ret) { + if (ret == 1) { printf("A charger is plugged into the OTG: "); return -ENODEV; } -- cgit v1.2.3