usb port on the back side how is that implemented ?

fvdw
Posts: 777
Joined: Wed Mar 18, 2009 11:13 pm

Re: usb port on the back side how is that implemented ?

Post by fvdw » Sat Oct 01, 2011 11:20 am

Mijzelf wrote:Again I did a grep on lacie_usb_storage_id on the Lacie sources. lacie_usb_storage_id is only written twice, once in it's declaration/initialisation in lacie/lacie-helper.c

Code: Select all

struct lacie_usb_storage_id *lacie_usb_storage_id = NULL;
EXPORT_SYMBOL(lacie_usb_storage_id);
and once in arch/arm/mach-feroceon-kw/netspace-v2-setup.c

Code: Select all

static void __init netspace_v2_usb_storage_id_init(void)
{
        lacie_usb_storage_id = &netspace_v2_usb_storage_id;
}
On all other places it's only read. So its value cannot be reset. Unless somehow the object lacie_usb_storage_id is located in a module, in which case the netspace_v2_board_init() function is also in a module. (netspace_v2_board_init() is directly dependent on etspace_v2_usb_storage_id_init(), which is dependent on lacie_usb_storage_id). i
When it's in a module it will be set to zero on loading of the module, and when netspace_v2_usb_storage_id_init() is not called it will stay that way.
You can check if lacie_usb_storage_id is in a module by looking at system.map. If it's there, it is in the kernel.
(I include lacie helper in the kernel and let it be compiled by changing the make file of mach-kirkwood. The header is also include in netspace_setup file (otherwise it complains the function is not declared, of course))

When using g_file_storage as a module calls to storage_id are present in that module. But why does it give no problems when initializing the udc platform at kernel boot and then after booting loading this module ?
I will look in the system map as you mention,
PS adding a call to this storage-id init function when loading udc platform device is easy.
Mijzelf wrote:
fvdw wrote:I also fond it strange that Linux File_stor gadget is mentioned and not the strings defined, it seems that it is overwritten, how ??
Beats me. lacie_usb_storage_id is zero, or points to

Code: Select all

/* USB storage id's */
                
static struct lacie_usb_storage_id netspace_v2_usb_storage_id = {
        .idVendor       = 0x059f,
        .idProduct      = 0x1030,
        .manufacturer   = "LaCie S.A.",
        .product        = "Network Space v2 NAS",
};      
So a part of this memory block should be overwritten, and not with garbage, but with pointers to more or less sane data. Don't think so.
Is it possible that you made a mistake in your copy/paste in file_storage.c, so that

Code: Select all

 if (lacie_usb_storage_id) {
      device_desc.idVendor =
         cpu_to_le16(lacie_usb_storage_id->idVendor);
      device_desc.idProduct =
         cpu_to_le16(lacie_usb_storage_id->idProduct);
   }
is executed, while

Code: Select all

if (lacie_usb_storage_id && lacie_usb_storage_id->manufacturer)
      snprintf(manufacturer, sizeof(manufacturer),
          "%s", lacie_usb_storage_id->manufacturer);
isn't? An extra if(){} around the last block, or a goto in between?

Having said that, I don't think this is the actual problem. AFAIK Windows should accept the device as long as it exposes itself as a mass storage device. (Maybe except when it uses a VID&PID, known by Windows, which is definitely not a mass storage device.). So the original values in file_storage.c should work, and the only reason Lacie changed them was to get a box which nicely identifies itself as a Lacie box.
No, the copy past was done correctly, I double checked it, the extra (){} is not required as it is a single function call, it is also there in lacie gpl code of file_storage.c in exact the same way.
I agree that this is in principle only to show, that when attached, that is the nwsp2 device. We will see if the extra call of the storage _id function will cure this problem.
Mijzelf wrote: That error -16 is a bigger problem. As I said before, I think it is because the hardware is not released. Now I thought, you release the EHCI driver, but what about OHCI? In ehci_hcd_init() is a check and a warning that ehci_hcd should be loaded before ohci_ or uhci_hdc. So I suppose they should be unloaded prior to ehci, in order to let it release.
I checked the config file of the kernel, this is the relevant part

Code: Select all

# CONFIG_HID_ZEROPLUS is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
As can be seen HCD en OHCI are enabled but as far as I can see they are not initialized in the setup file of the nwsp2. If that is so does they need to be unloaded ??
ps for me unloading is unregistering the platform device, for this I defined this function, but maybe more is needed

Code: Select all

void kirkwood_ehci_unload(void)
{
	platform_device_unregister(&kirkwood_ehci);
	printk(" orion-ehci unloaded \n");
}
edit---

for loading it again a copy of the init function is used, I have no idea what the kirkwood_clk_ctrl command is doing and if it is needed or not. As said it is a copy of the init function used at boot to load the ehci platform

Code: Select all

void kirkwood_ehci_load(void)
{
 	kirkwood_clk_ctrl |= CGC_USB0;
        platform_device_register(&kirkwood_ehci);
	printk(" orion-ehci loaded \n");
}
below a full copy of the EHCI section of common.c as used in mach-kirkwood (including the changes made so far to be able to load the udc platform)

Code: Select all

/*****************************************************************************
 * EHCI
 ****************************************************************************/
static struct orion_ehci_data kirkwood_ehci_data = {
	.dram		= &kirkwood_mbus_dram_info,
	.phy_version	= EHCI_PHY_NA,
};

static u64 ehci_dmamask = 0xffffffffUL;


/*****************************************************************************
 * EHCI0
 ****************************************************************************/
static struct resource kirkwood_usb_resources[] = {
	{
		.start	= USB_PHYS_BASE,
		.end	= USB_PHYS_BASE + 0x0fff,
		.flags	= IORESOURCE_MEM,
	}, {
		.start	= IRQ_KIRKWOOD_USB,
		.end	= IRQ_KIRKWOOD_USB,
		.flags	= IORESOURCE_IRQ,
	},
};

static struct platform_device kirkwood_ehci = {
	.name		= "orion-ehci",
	.id		= 0,
	.dev		= {
		.dma_mask		= &ehci_dmamask,
		.coherent_dma_mask	= 0xffffffff,
		.platform_data		= &kirkwood_ehci_data,
	        .release     = mv_usb_release,
	},
	.resource	= kirkwood_usb_resources,
	.num_resources	= ARRAY_SIZE(kirkwood_usb_resources),
};

void __init kirkwood_ehci_init(void)
{
	kirkwood_clk_ctrl |= CGC_USB0;
        platform_device_register(&kirkwood_ehci);
}

void kirkwood_ehci_unload(void)
{
	platform_device_unregister(&kirkwood_ehci);
	printk(" orion-ehci unloaded \n");
}

void kirkwood_ehci_load(void)
{
 	kirkwood_clk_ctrl |= CGC_USB0;
        platform_device_register(&kirkwood_ehci);
	printk(" orion-ehci loaded \n");
}

static struct fsl_usb2_platform_data kirkwood_otg_data = {
	.operating_mode = FSL_USB2_DR_DEVICE,
	.phy_mode       = FSL_USB2_PHY_UTMI,
};
static u64 otg_dmamask = DMA_BIT_MASK(32);

/* OTG gadget device */
struct platform_device kirkwood_otg = {
	.name   = "fsl-usb2-udc",
	.id     = -1,
	.dev    = {
		.dma_mask      = &otg_dmamask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
		.platform_data     = &kirkwood_otg_data,
 	         .release     = mv_usb_release,
	},
	.resource    = kirkwood_usb_resources,
	.num_resources = ARRAY_SIZE(kirkwood_usb_resources),
};

void __init kirkwood_otg_init(void)
{
	kirkwood_clk_ctrl |= CGC_USB0;
	platform_device_register(&kirkwood_otg);
}

void kirkwood_otg_unload(void)
{
	platform_device_unregister(&kirkwood_otg);
	printk(" fsl-usb2-udc unloaded \n");
}

void kirkwood_otg_load(void)
{
	kirkwood_clk_ctrl |= CGC_USB0;
	platform_device_register(&kirkwood_otg);
	printk(" fsl-usb2-udc loaded \n");
}
mv_usb_release in platform otg definition is just a dummy function, doing nothing, but without unloading udc gives an error message that no release function is designed, I tried the release function as present in th gpl code but that crashes the kernel....so I made it a dummy function for the time being. The function is actally called when unloading udc (the printk is in the kernel output)

Code: Select all

static struct platform_device *mv_usb_pdev[1];

static void mv_usb_release(struct device *dev)
{
    struct platform_device  *pdev = to_platform_device(dev);

    /* normally not freed */
    printk("mv_usb_release\n");
/* dummy function for the moment as the original did not work and gave kernel errors */

}

Mijzelf
Posts: 6251
Joined: Mon Jun 16, 2008 10:45 am

Re: usb port on the back side how is that implemented ?

Post by Mijzelf » Sat Oct 01, 2011 3:19 pm

About ohci: You can easily check if ohci is available. Just plugin an usb1.1 device. A keyboard or mouse will do. It will not even be detected if no ohci is available. (Unless there is some hub in between which does the 1.1 to 2.0 conversion).

About mv_usb_release(): I looked at the function in Lacie GPL, and it doesn't do anything important. Just freeing up some memory. So when you use your dummy function, the worst thing what can happen is a small memory leak, each time it's called.

About kirkwood_clk_ctrl:
/*
* Default clock control bits. Any bit _not_ set in this variable
* will be cleared from the hardware after platform devices have been
* registered. Some reserved bits must be set to 1.
*/
unsigned int kirkwood_clk_ctrl = CGC_DUNIT | CGC_RESERVED;
It is used in kirkwood_clock_gate() in common.c. I think it has something to do with not generating clock signals for controllers which aren't used anyway. (To save some energy?). I *think* this function is only called once, so if you don't register your usb controller in the init function, I think you should enable the clock generator, else there will be no clock, when you enable the controller later:

Code: Select all

extern unsigned int kirkwood_clk_ctrl;

static void __init netspace_v2_init(void)
{
        /*
         * Basic setup. Needs to be called early.
         */
        kirkwood_init();
        kirkwood_mpp_conf(netspace_v2_mpp_config);
        
        if (machine_is_netspace_max_v2())
                lacie_v2_hdd_power_init(2);
        else
                lacie_v2_hdd_power_init(1);

        /* kirkwood_ehci_init(); disabled */
        kirkwood_clk_ctrl |= CGC_USB0;

        kirkwood_ge00_init(&netspace_v2_ge00_data);
<snip>
I think I lost the overview somewhere.
* You can use the NS2 both in device mode and in host mode, but only if you choose for it on boot. Which is, enable it in netspace_v2_init()?
* You cannot switch mode later. You can switch off the current mode, but enabling the other gives an error -16. True? In both directions? Did you try to boot in one mode, switch it off, and then enable the same mode?

fvdw
Posts: 777
Joined: Wed Mar 18, 2009 11:13 pm

Re: usb port on the back side how is that implemented ?

Post by fvdw » Sat Oct 01, 2011 5:55 pm

Thanks for explaining Mijzelf everyday I learn something new here

thinkOHCI and HCD are not laoded as there is no init function (registration).
mv_usb_release, i thought the same but you could ask yourself why marvell want to free this memory.
clock-trl , only once is enough then indeed it is easier to put it in netspace setup fle and take it out all the functions in common.c
Mijzelf wrote:
I think I lost the overview somewhere.
* You can use the NS2 both in device mode and in host mode, but only if you choose for it on boot. Which is, enable it in netspace_v2_init()?
* You cannot switch mode later. You can switch off the current mode, but enabling the other gives an error -16. True? In both directions? Did you try to boot in one mode, switch it off, and then enable the same mode?
The overview, I don't remember myself anymore all problems with the options I tried.... need to do them again and make some notes I guess. Anyhow this is what I remember

Initialization of both during boot in the kernel
This gives error -16 message in kernel output at boot for both when the platform is probed for a driver. So you can not have them both at same time it seems. (Is alos the conclusion when you study the gpl code, always one is unloaded before the other on is loaded).

Initialization of ehci at boot and udc not.
Then ehci is loaded and probed and driver for front port usb ports loaded during boot.
Unloading ehci then after boot seems to go ok and also loading udc, however it gives when then trying to load g_file_storage.ko module the error no such device (after changing the probe method , I believe it now gives the -16 error). So in this setup you can not get the back side port working

Initialization of udc at boot and ehci not.
Then after boot loading g_file_storage.ko as module goes fine and the back side usb port is working and visible as drive on the windows PC (after using mode_switch)
Unloading kernel module and reloading is possible. But unloading udc platform and then loading ehci gives an oops error or -16 , I don't remember. So in this setup you can not get the front port working

Initialization none of them at boot and register/unregister them after boot.
I tried that but do not remember the problems.

Loading them as modules after boot
I also tried the option to compile ehci and udc both as module and load those after boot. But also that did not give a situation in which you could switch from one to the other with using only one kernel. For instance I remember
that loading after boot fsl-usb2-udc using insmod and then g-file-storage module, gave no error but then the windows PC come up with the unknown device issue
Loading ehci as module works but unloading it again the kernel doesn't like..I forgot what error this gave.

You could live with starting up the system and having front side ports enable and then switch to back side port mode. Or just the other way around. And then if you want to revert back force a reboot. Not ideal but workable.
Unfortunate until now I could not make a kernel that could do the switch from one mode to the other without a problem.

Mijzelf
Posts: 6251
Joined: Mon Jun 16, 2008 10:45 am

Re: usb port on the back side how is that implemented ?

Post by Mijzelf » Sun Oct 02, 2011 11:26 am

fvdw wrote:everyday I learn something new here
Me too!

Where did you find the kernelthread which does 'the action' in the Lacie GPL? The only thing I can find is function device_vbus_notify() in /lacie/drivers/gpio-usb.c. But that only triggers userspace, as far as I can see.

fvdw
Posts: 777
Joined: Wed Mar 18, 2009 11:13 pm

Re: usb port on the back side how is that implemented ?

Post by fvdw » Sun Oct 02, 2011 11:33 am

its in usb.c in the folder arch/arm/mach-ferocean-kw

Mijzelf
Posts: 6251
Joined: Mon Jun 16, 2008 10:45 am

Re: usb port on the back side how is that implemented ?

Post by Mijzelf » Mon Oct 03, 2011 6:41 pm

fvdw wrote:its in usb.c in the folder arch/arm/mach-ferocean-kw
I don't think this is the mechanism which is actually used on the Lacie.

This code generates a file /proc/usbconf/0, which contains either 'host' or 'device'. You can change the contents by echoing the value into it. This works. (I didn't test if it actually switches the function).
When I supply 5V to the device port, this files switches too. So there is a connection between this interface and the 'actual action'.
However, by supplying and releasing 5V to the device port, I can switch as often as I want. By echoing into this file I can either. But when I've switched once by echoing in the file, the box crashes as soon as I supply 5V.

Strange crash by the way. I lost my ssh shell. According to nmap all ports are still open. When trying to get the webinterface, the browser connects, but it gets no answer to it's request.
It looks like the kernelpart of TCP/IP is still running, but userspace is dead. The same for ssh.

fvdw
Posts: 777
Joined: Wed Mar 18, 2009 11:13 pm

Re: usb port on the back side how is that implemented ?

Post by fvdw » Mon Oct 03, 2011 7:39 pm

Mijzelf wrote: I don't think this is the mechanism which is actually used on the Lacie.
mmm..
things like

static char usb_dev_name[] = "mv_udc";
static char usb_host_name[] = "ehci_marvell";
static char usb_bus_name[] = "platform";

combined with Functions like mv_usb_pdevice_register(int devnum) and mv_usb_pdevice_unregister(int devnum)

and the printk's
printk("Register Marvell USB EHCI %s controller #%d\n", isHost ? "Host" : "Gadget", devnum);
printk("Can't register Marvell USB EHCI controller #%d, status=%d\n", devnum, status);
printk("Unregister USB platform device %s (USB port %d)\n", pdev->name, devnum);

give me the impression that it is used for the swap. In userspace "host" or "device" is written to the process and then the kernel swaps the platform/drivers accordingly..or ??

below the full code, maybe you gpl file is different.

Code: Select all

#include <linux/autoconf.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include <linux/ctype.h>
                                                                                                                             
#include <asm/io.h>
#include <asm/irq.h>


#include "mvDebug.h"
#include "ctrlEnv/mvCtrlEnvLib.h"
#include "ctrlEnv/sys/mvSysUsb.h"
#include "usb/mvUsb.h"

extern u32 mvIsUsbHost;

#define MV_USB_DMA_MASK     0xffffffff

static char usb_dev_name[]  = "mv_udc";
static char usb_host_name[] = "ehci_marvell";
static char usb_bus_name[]  = "platform";

struct usbconf_data_t
{
    int devnum;
    spinlock_t lock;
};

static struct usbconf_data_t usbconf_dev[MV_USB_MAX_CHAN];
static struct proc_dir_entry *usbconf_proc_dir, *usbconf_proc_entry[MV_USB_MAX_CHAN];
static struct platform_device *mv_usb_pdev[MV_USB_MAX_CHAN];

static int mv_usb_pdevice_register(int devnum);
static void mv_usb_pdevice_unregister(int devnum);
static void mv_usb_release(struct device *dev);

static int proc_read_usbconf(char *page, char **start, off_t off, int count, int *eof, void *data)
{
    struct usbconf_data_t *usbconf = (struct usbconf_data_t *) data;

    return sprintf(page, "%s\n",
                   test_bit(usbconf->devnum, (unsigned long *) &mvIsUsbHost) ?
                   "host" : "device");
}

static int proc_write_usbconf(struct file *file, const char *buffer, unsigned long count, void *data)
{
    struct usbconf_data_t *usbconf = (struct usbconf_data_t *) data;
    char userval[PAGE_SIZE];
    int i;
    int len = min(count, PAGE_SIZE);

    if (len <= 0)
        return -EINVAL;

    if (copy_from_user(userval, buffer, len))
        return -EFAULT;

    userval[len-1] = '\0';
    for (i=0; i<len; i++)
        userval[i] = tolower(userval[i]);

    if (strcmp(userval, "host") == 0)
    {
        if (test_bit(usbconf->devnum, (unsigned long *) &mvIsUsbHost))
            goto exit;
        set_bit(usbconf->devnum, (unsigned long *) &mvIsUsbHost);
    }
    else if (strcmp(userval, "device") == 0)
    {
        if (!test_bit(usbconf->devnum, (unsigned long *) &mvIsUsbHost))
            goto exit;
        clear_bit(usbconf->devnum, (unsigned long *) &mvIsUsbHost);
    }
    else
        return -EINVAL;

    /* FIXME: How clean USB stack and reset USB ports properly */

    spin_lock(&usbconf->lock);
    mv_usb_pdevice_unregister(usbconf->devnum);
    mv_usb_pdevice_register(usbconf->devnum);
    spin_unlock(&usbconf->lock);

exit:
    return len;
}

static int mv_usb_pdevice_register(int devnum)
{
    int status, isHost;
    struct platform_device *pdev;

    if (MV_FALSE == mvCtrlPwrClckGet(USB_UNIT_ID, devnum))
    {
        printk("\nWarning Integrated USB %d is Powered Off\n", devnum);
        status = -ENODEV;
        goto exit_error;
    }
    isHost = mvIsUsbHost & (1 << devnum);

    status = mvUsbInit(devnum, isHost);

    mv_usb_pdev[devnum] = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
    if (!mv_usb_pdev[devnum])
    {
        printk("Can't allocate platform_device structure - %d bytes\n",
               sizeof(struct platform_device));
        status = -ENOMEM;
        goto exit_error;
    }
    pdev = mv_usb_pdev[devnum];

    pdev->name = isHost? usb_host_name : usb_dev_name;
    pdev->id = PCI_VENDOR_ID_MARVELL | (MV_USB_VERSION << 16) | (devnum << 24);
    pdev->num_resources = 2;
    pdev->resource = (struct resource*) kzalloc(2*sizeof(struct resource), GFP_KERNEL);
    if (!pdev->resource)
    {
        printk("Can't allocate 2 resource structure - %d bytes\n",
               2*sizeof(struct resource));
        status = -ENOMEM;
        goto exit_free_pdev;
    }
    pdev->resource[0].start = (INTER_REGS_BASE | MV_USB_CORE_CAP_LENGTH_REG(dev));
    pdev->resource[0].end = ((INTER_REGS_BASE | MV_USB_CORE_CAP_LENGTH_REG(dev)) + 4096);
    pdev->resource[0].flags = IORESOURCE_DMA;
    pdev->resource[1].start = IRQ_USB_CTRL(devnum);
    pdev->resource[1].flags = IORESOURCE_IRQ;

    pdev->dev.dma_mask = kmalloc(sizeof(u64), GFP_KERNEL);
    *pdev->dev.dma_mask = MV_USB_DMA_MASK;
    pdev->dev.coherent_dma_mask  = ~0;
    pdev->dev.release = mv_usb_release;
    strncpy(pdev->dev.bus_id, usb_bus_name, BUS_ID_SIZE);

    status = platform_device_register(pdev);
    if (status)
        goto exit_free_resource;

    printk("Register Marvell USB EHCI %s controller #%d\n",
           isHost ? "Host" : "Gadget", devnum);

    return 0;

exit_free_resource:
    kfree(pdev->dev.dma_mask);
    kfree(pdev->resource);
exit_free_pdev:
    kfree(pdev);
    mv_usb_pdev[devnum] = NULL;
exit_error:
    printk("Can't register Marvell USB EHCI controller #%d, status=%d\n",
           devnum, status);

    return status;
}

static void mv_usb_pdevice_unregister(int devnum)
{
    struct platform_device *pdev = mv_usb_pdev[devnum];

    if (!pdev)
        return;

    printk("Unregister USB platform device %s (USB port %d)\n",
           pdev->name, devnum);

    platform_device_unregister(pdev);
    mv_usb_pdev[devnum] = NULL;
}

static void mv_usb_release(struct device *dev)
{
    struct platform_device  *pdev = to_platform_device(dev);

    /* normally not freed */
    printk("mv_usb_release\n");

    kfree(pdev->resource);
    kfree(pdev->dev.dma_mask);
    kfree(pdev);
}

static int __init mv_usb_init(void)
{
    int ret, fail = 0;
    int devnum, devmax;
    char devnum_str[3];

    usbconf_proc_dir = proc_mkdir("usbconf", NULL);
    if (!usbconf_proc_dir)
        return -ENOMEM;

    for(devnum = 0; devnum < MV_USB_MAX_CHAN; devnum++)
    {
        ret = mv_usb_pdevice_register(devnum);
        if (ret)
        {
            fail++;
            continue;
        }
        snprintf(devnum_str, sizeof(devnum_str), "%d", devnum);
        usbconf_proc_entry[devnum] =
            create_proc_entry(devnum_str, 0644, usbconf_proc_dir);
        if (!usbconf_proc_entry[devnum])
            return -ENOMEM;

        usbconf_dev[devnum].devnum = devnum;
        spin_lock_init(&usbconf_dev[devnum].lock);
        usbconf_proc_entry[devnum]->data = &usbconf_dev[devnum];
        usbconf_proc_entry[devnum]->read_proc = proc_read_usbconf;
        usbconf_proc_entry[devnum]->write_proc = proc_write_usbconf;
        usbconf_proc_entry[devnum]->owner = THIS_MODULE;
    }    
    return fail;
}

subsys_initcall(mv_usb_init);

Mijzelf
Posts: 6251
Joined: Mon Jun 16, 2008 10:45 am

Re: usb port on the back side how is that implemented ?

Post by Mijzelf » Mon Oct 03, 2011 9:00 pm

Yes that is the code. And I agree that it looks like *the code*. But it interferes badly with the voltage switch.

When I switch to device mode by voltage, dmesg says:

Code: Select all

USB: ehci_marvell_remove
ehci_marvell ehci_marvell.70059: remove, state 1
usb usb1: USB disconnect, address 1
ehci_marvell ehci_marvell.70059: USB bus 1 deregistered
Unregister USB platform device ehci_marvell (USB port 0)
mv_usb_release
Register Marvell USB EHCI Gadget controller #0
mv_udc: version 05-July-2006 loaded
USB-0 Gadget driver probed
USB gadget device #0: vbus_gpp_no = 255
USB init: CAP_REGS=0xf1050100, DEV_REGS=0xf1050140, MAX_EP=4
USB EP_QH: Base=ff005000 (0xc995000), Aligned(2048)=ff005000, Size=512
USB dTD(48): Base=ff006000 (0x8528000), Aligned(32)=ff006000, Size=1536, Scratch=c9096c00
USB Init: Wait for RESET completed
USB Init: RESET completed
device_init: pDev=0xc9096800, pXD(32)=0xc9096000, pSCRATCH(32)=0xcf7b6e00, pTempXD=0xcb059640
g_file_storage gadget: LUN0 storage type : disk
g_file_storage gadget: File-backed Storage Gadget, version: 28 November 2005
g_file_storage gadget: Number of LUNs=1
g_file_storage gadget-lun0: ro=0, file: /media/internal_6/images/1
registered Marvell USB-0 gadget driver g_file_storage
When I do the same echoing

Code: Select all

Unregister USB platform device ehci_marvell (USB port 0)
USB: ehci_marvell_remove
ehci_marvell ehci_marvell.70059: remove, state 1
usb usb1: USB disconnect, address 1
ehci_marvell ehci_marvell.70059: USB bus 1 deregistered
mv_usb_release
Register Marvell USB EHCI Gadget controller #0
mv_udc: version 05-July-2006 loaded
USB-0 Gadget driver probed
USB gadget device #0: vbus_gpp_no = 255
USB init: CAP_REGS=0xf1050100, DEV_REGS=0xf1050140, MAX_EP=4
USB EP_QH: Base=ff005000 (0x85ed000), Aligned(2048)=ff005000, Size=512
USB dTD(48): Base=ff006000 (0x8ad9000), Aligned(32)=ff006000, Size=1536, Scratch=c8016800
USB Init: Wait for RESET completed
USB Init: RESET completed
device_init: pDev=0xc91ab800, pXD(32)=0xc8016400, pSCRATCH(32)=0xc8938600, pTempXD=0xc8b5a220
So the voltage switch does something before and after the actions of usb.c

The same is true the other way: voltage to host:

Code: Select all

unregistered Marvell USB 0 gadget driver g_file_storage
mv_udc: version 05-July-2006 unloaded
mv_usb_gadget_remove: mv_dev=cfc2e800, driver=00000000
USB shutdown: usb_dev_ptr=c9096800
_usb_device_shutdown: free service_ptr = 0xcb059700
 loop1: p1 p2
Unregister USB platform device mv_udc (USB port 0)
mv_usb_release
Register Marvell USB EHCI Host controller #0
ehci_marvell ehci_marvell.70059: Marvell Orion EHCI
ehci_marvell ehci_marvell.70059: new USB bus registered, assigned bus number 1
ehci_marvell ehci_marvell.70059: irq 19, io base 0xf1050100
ehci_marvell ehci_marvell.70059: USB 2.0 started, EHCI 1.00, driver 10 Dec 2004
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
echo switch to host:

Code: Select all

Unregister USB platform device mv_udc (USB port 0)
mv_usb_gadget_remove: mv_dev=cfe7a800, driver=00000000
USB shutdown: usb_dev_ptr=c91ab800
_usb_device_shutdown: free service_ptr = 0xc8b5ade0
mv_usb_release
ehci_marvell ehci_marvell.70059: Marvell Orion EHCI
ehci_marvell ehci_marvell.70059: new USB bus registered, assigned bus number 1
ehci_marvell ehci_marvell.70059: irq 19, io base 0xf1050100
ehci_marvell ehci_marvell.70059: USB 2.0 started, EHCI 1.00, driver 10 Dec 2004
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
Register Marvell USB EHCI Host controller #0
Have a look at the sequence of founding an USB hub and registering the host controller.

A grep learns that "Register Marvell USB EHCI" *must* come from this usb.c (unless it's generated dynamicly, somewhere).

fvdw
Posts: 777
Joined: Wed Mar 18, 2009 11:13 pm

Re: usb port on the back side how is that implemented ?

Post by fvdw » Mon Oct 03, 2011 9:42 pm

:shock: this is getting complicated...need some time to digest this and make a plan of attack (if any)

Mijzelf
Posts: 6251
Joined: Mon Jun 16, 2008 10:45 am

Re: usb port on the back side how is that implemented ?

Post by Mijzelf » Tue Oct 04, 2011 9:52 am

I found the usermode part of the switch. Grepping on proc/usbconf I found /usr/lib/python2.6/site-packages/unicorn/storage/usb.py:

Code: Select all

class USBService(object):
    """manage usb services: host or device"""
    host_control = KModule('ehci_hcd')
    host_classes = [ KModule('usb_storage'), KModule('usblp') ]
    device_storage = KModule('g_file_storage')
    device_control = KModule('mv_udc')

    stack_mode = '/proc/usbconf/0'
    mode_select = '/sys/devices/platform/gpio-usb/mode_switch'
    vbus_enable = '/sys/devices/platform/gpio-usb/host_vbus'
    serial = None

    def start_device(self, target):
        write_config(self.stack_mode, 'device')
        self.device_control.insert([])

        args = [ 'use_directio=yes' ]
        if self.serial:
            args.append('serial=%s' % self.serial)
        for img in target.images:
            args.append('file=%s' % img.path())
        self.device_storage.insert(args)
        write_config(self.mode_select, '1')

    def stop_device(self):
        self.device_storage.remove()
        self.device_control.remove()

    def start_host(self):
        write_config(self.stack_mode, 'host')
        self.host_control.insert([])
        write_config(self.mode_select, '0')
        #write_config(self.vbus_enable, '1')

    def stop_host(self, controler=True):
        # for all usb disk
        disks = Disk.find(bus=unicode('usb'))
        for dsk in disks:
            logging.debug("unmounting disk %s:", dsk)
            # unmount each volume
            volumes = Volume.find(disk=dsk)
            for vlm in volumes:
                logging.debug("unmount volume %s:", vlm)
                vlm.unmount()

        #write_config(self.vbus_enable, '0')
        # unload usb class modules to assure devices are freed
        for mdl in self.host_classes:
            mdl.remove()
        if controler:
            self.host_control.remove()

service = USBService()

fvdw
Posts: 777
Joined: Wed Mar 18, 2009 11:13 pm

Re: usb port on the back side how is that implemented ?

Post by fvdw » Tue Oct 04, 2011 6:19 pm

8-) cool, but it doesn not give me ant clue how to unload and load these platforms properly :?

this part for example in your previous post

Code: Select all

unregistered Marvell USB 0 gadget driver g_file_storage
mv_udc: version 05-July-2006 unloaded
mv_usb_gadget_remove: mv_dev=cfc2e800, driver=00000000
USB shutdown: usb_dev_ptr=c9096800
_usb_device_shutdown: free service_ptr = 0xcb059700
loop1: p1 p2
Unregister USB platform device mv_udc (USB port 0)
or this part

Code: Select all

Unregister USB platform device ehci_marvell (USB port 0)
USB: ehci_marvell_remove
ehci_marvell ehci_marvell.70059: remove, state 1
usb usb1: USB disconnect, address 1
ehci_marvell ehci_marvell.70059: USB bus 1 deregistered
mv_usb_release
indicates that unregistering and unloading is not the same thing...

Mijzelf
Posts: 6251
Joined: Mon Jun 16, 2008 10:45 am

Re: usb port on the back side how is that implemented ?

Post by Mijzelf » Tue Oct 04, 2011 6:40 pm

No? Python is not my strongest point (understatement), but I'll try. To start the device mode, the 'subfunctions' stop_host and start_device have to be executed.

Code: Select all

   def stop_host(self, controler=True):
        # for all usb disk
        disks = Disk.find(bus=unicode('usb'))
        for dsk in disks:
            logging.debug("unmounting disk %s:", dsk)
            # unmount each volume
            volumes = Volume.find(disk=dsk)
            for vlm in volumes:
                logging.debug("unmount volume %s:", vlm)
                vlm.unmount()

        #write_config(self.vbus_enable, '0')
        # unload usb class modules to assure devices are freed
        for mdl in self.host_classes:
            mdl.remove()
        if controler:
            self.host_control.remove()
Get a list of all USB disks
For each disk get a list of al 'volumes' (partitions, I suppose)
For each volume, umount
Unload the modules usb_storage and usblp
Unload module ehci_hcd

Code: Select all

    def start_device(self, target):
        write_config(self.stack_mode, 'device')
        self.device_control.insert([])

        args = [ 'use_directio=yes' ]
        if self.serial:
            args.append('serial=%s' % self.serial)
        for img in target.images:
            args.append('file=%s' % img.path())
        self.device_storage.insert(args)
        write_config(self.mode_select, '1')
echo device >/proc/usbconf/0
insmod mv_udc
build an args set from serial and target(?)
insmod g_file_storage args
echo 1 >/sys/devices/platform/gpio-usb/mode_switch
fvdw wrote:indicates that unregistering and unloading is not the same thing...
I don't see any 'unloading' in this log?

fvdw
Posts: 777
Joined: Wed Mar 18, 2009 11:13 pm

Re: usb port on the back side how is that implemented ?

Post by fvdw » Tue Oct 04, 2011 7:48 pm

Yes thats seems more or less what this script does.
what I didn't try yet was to compile beside ehci as module also usb_storage and usblp as module and to unload those as well before unloading ehci and then loading fsl_usb2_udc
That is worth a try I guess.

Mijzelf wrote:
fvdw wrote:indicates that unregistering and unloading is not the same thing...
I don't see any 'unloading' in this log?
in your post for example this output was given
unregistered Marvell USB 0 gadget driver g_file_storage
mv_udc: version 05-July-2006 unloaded
mv_usb_gadget_remove: mv_dev=cfc2e800, driver=00000000
USB shutdown: usb_dev_ptr=c9096800
_usb_device_shutdown: free service_ptr = 0xcb059700
loop1: p1 p2
Unregister USB platform device mv_udc (USB port 0)
The second line mentions "mv_udc: version 05-July-2006 unloaded"
The last line mentions Unregister USB platform device Mv_udc (usb port 0)
Maybe the unloading is caused by unregistering the gadget driver (g_file_storage) or it is just unloading mv-udc as module

fvdw
Posts: 777
Joined: Wed Mar 18, 2009 11:13 pm

Re: usb port on the back side how is that implemented ?

Post by fvdw » Tue Oct 04, 2011 10:02 pm

this evening I recompiled the linux-2.6.39.4 kernel for the nwsp2, with help of "ltree" I found out what the problem was that made it fail to boot (the problem was no mv_sata driver enabled :mrgreen: they moved in the config file to anther position and was not taken over automatic from oldconfig :cry: ) Now it boots fine and it is listing more info in dmesg regarding usb

Code: Select all

Linux version 2.6.39.4-fvdw2 (root@fvdwsl-nwsp2.local) (gcc version 4.2.3) #5 PREEMPT Tue Oct 4 22:33:19 GMT+1 2011
CPU: Feroceon 88FR131 [56251311] revision 1 (ARMv5TE), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: LaCie Network Space v2

<snip>


ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
orion-ehci orion-ehci.0: Marvell Orion EHCI
orion-ehci orion-ehci.0: new USB bus registered, assigned bus number 1
orion-ehci orion-ehci.0: irq 19, io mem 0xf1050000
orion-ehci orion-ehci.0: USB 2.0 started, EHCI 1.00
usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: Marvell Orion EHCI
usb usb1: Manufacturer: Linux 2.6.39.4-fvdw2 ehci_hcd
usb usb1: SerialNumber: orion-ehci.0
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
the usb usb1 lines were not there in linux-2.6.33.1. Of course this can mean nothing but I noticed that the netspace_v2 setup file looks more sophisticated in 2.6.39.4
So i will give it try to get fsl_usb2_udc integrated in this kernel to see if there unload/loading etc will go better.
I rather spend the time at this more recent kernel then sticking with 2.6.33.1 although that kernel served me well

moonshadow88
Posts: 5
Joined: Wed Aug 31, 2011 10:52 am

Re: usb port on the back side how is that implemented ?

Post by moonshadow88 » Wed Oct 05, 2011 6:05 am

tell me if you need testing!

Post Reply