diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/mmc.c | 5 | ||||
-rw-r--r-- | drivers/mmc/sunxi_mmc.c | 17 | ||||
-rw-r--r-- | drivers/usb/musb-new/sunxi.c | 117 |
3 files changed, 119 insertions, 20 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index da47037..f12546a 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; diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index e7ab828..f9b9493 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, diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index c123d61..3a29b18 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -26,17 +26,12 @@ #include <asm/arch/gpio.h> #include <asm/arch/usb_phy.h> #include <asm-generic/gpio.h> +#include <dm/lists.h> +#include <dm/root.h> +#include <linux/usb/musb.h> #include "linux-compat.h" #include "musb_core.h" -#ifdef CONFIG_AXP152_POWER -#include <axp152.h> -#endif -#ifdef CONFIG_AXP209_POWER -#include <axp209.h> -#endif -#ifdef CONFIG_AXP221_POWER -#include <axp221.h> -#endif +#include "musb_uboot.h" /****************************************************************************** ****************************************************************************** @@ -201,6 +196,8 @@ static bool enabled = false; static int sunxi_musb_enable(struct musb *musb) { + int ret; + pr_debug("%s():\n", __func__); if (enabled) @@ -209,8 +206,19 @@ 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 == 1) { + 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 */ + } 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); @@ -273,8 +272,86 @@ 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, +}; + +#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); + 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) + return -EIO; + } + + ret = musb_lowlevel_init(host); + if (ret == 0) + printf("MUSB OTG\n"); + + return ret; +} + +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 +} |