LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: linux-3.0.4, mv643xx_eth troubles on Pegasos2 G4
From: Gabriel Paubert @ 2011-10-18  7:19 UTC (permalink / raw)
  To: nello martuscielli; +Cc: linuxppc-dev, acrux
In-Reply-To: <CABMX=WzPuhBywZTJShnM5W1Y2cqMOr=2BuJTKecsyfCp73Ko7g@mail.gmail.com>

On Mon, Oct 17, 2011 at 11:40:54PM +0200, nello martuscielli wrote:
> i'm trying to enable marvel gigabit ethernet support but it doesn't work.
> Here my dmesg instead my config is attached.
[snipped]
> via_rhine: v1.10-LK1.5.0 2010-10-09 Written by Donald Becker
> mv643xx_eth: MV-643xx 10/100/1000 ethernet driver version 1.4
> uhci_hcd 0000:00:0c.2: irq 9, io base 0x00001040
> sysfs: cannot create duplicate filename '/class/mdio_bus/0'

I have 2 Pegasos running 3.0, but in my case mv643xx_eth is non-modular
and /sys/class/mdio_bus/0 exists and points to

../../devices/platform/mv643xx_eth.0/mdio_bus/0

which is correct as far as I can say. 

Is it a regression from 3.0 or not? Try to make it non modular and see
what happens. If it is a regression, could you try to bisect it?

I won't be close enough to the machines to do a regression
hunt myself before a week or 3 (really, maybe next week, 
I don't yet know, but for sure starting on Nov 8th).

>

> usb usb2: New USB device found, idVendor=1d6b, idProduct=0001
> ------------[ cut here ]------------
> WARNING: at fs/sysfs/dir.c:455
> Modules linked in: snd_via82xx(+) snd_ac97_codec mv643xx_eth(+)
> via_rhine(+) i2c_viapro(+) ac97_bus ohci_hcd(+) snd_mpu401_uart
> uhci_hcd(+) snd_rawmidi
> NIP: c00fa718 LR: c00fa718 CTR: 00000000
> REGS: ef271c00 TRAP: 0700   Not tainted  (3.0.4)
> MSR: 00029032 <EE,ME,CE,IR,DR>  CR: 22004428  XER: 00000000
> TASK = ef294c60[94] 'modprobe' THREAD: ef270000
> GPR00: c00fa718 ef271cb0 ef294c60 00000042 c0008904 00000001 00000000 00000000
> GPR08: c06b6bd8 00000000 22004482 ef271c70 22004422 10024440 1000ba68 00000000
> GPR16: 1000ba44 bf83e324 00000000 1000ba58 00000000 104410ec 00000a30 00000000
> GPR24: c0059210 00000124 00000000 00000001 ef271cd8 ef2ba480 ffffffef ef344000
> NIP [c00fa718] sysfs_add_one+0x88/0xa0
> LR [c00fa718] sysfs_add_one+0x88/0xa0
> Call Trace:
> [ef271cb0] [c00fa718] sysfs_add_one+0x88/0xa0 (unreliable)
> [ef271cd0] [c00faff4] sysfs_do_create_link+0x134/0x1e0
> [ef271d00] [c0392cf8] device_add+0x204/0x544
> [ef271d40] [c03d67e4] mdiobus_register+0xa4/0x198
> [ef271d60] [f26785a4] mv643xx_eth_shared_probe+0x144/0x428 [mv643xx_eth]
> [ef271d80] [c039685c] platform_drv_probe+0x20/0x30
> [ef271d90] [c0395578] driver_probe_device+0xe4/0x198
> [ef271db0] [c039569c] __driver_attach+0x70/0x98
> [ef271dd0] [c0394614] bus_for_each_dev+0x60/0x90
> [ef271e00] [c03951d0] driver_attach+0x24/0x34
> [ef271e10] [c0394d9c] bus_add_driver+0xbc/0x23c
> [ef271e30] [c0395ac8] driver_register+0xb8/0x144
> [ef271e50] [c0396bb4] platform_driver_register+0x68/0x78
> [ef271e60] [f2680024] mv643xx_eth_init_module+0x24/0x80 [mv643xx_eth]
> [ef271e80] [c000402c] do_one_initcall+0xe0/0x1c0
> [ef271eb0] [c005b438] sys_init_module+0x1600/0x17f4
> [ef271f40] [c0012df8] ret_from_syscall+0x0/0x38
> --- Exception: c01 at 0xff62ac0
>    LR = 0x10003f2c
> Instruction dump:
> 807c0000 7fe4fb78 4bfff469 3c80c060 3884f131 4bf2051d 809d0010 4bf20515
> 7c641b78 3c60c060 3863f0fe 484650f9 <0fe00000> 7fe3fb78 4bfa8009 39610020
> ---[ end trace cebed1f190337b77 ]---
> usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> usb usb2: Product: UHCI Host Controller
> usb usb2: Manufacturer: Linux 3.0.4 uhci_hcd
> usb usb2: SerialNumber: 0000:00:0c.2
> hub 2-0:1.0: USB hub found
> mii_bus 0 failed to register
> mv643xx_eth: probe of mv643xx_eth.0 failed with error -12
> hub 2-0:1.0: 2 ports detected
> ohci_hcd 0000:00:05.0: OHCI Host Controller
> ohci_hcd 0000:00:05.0: new USB bus registered, assigned bus number 3
> Unable to handle kernel paging request for data at address 0x00000000
> ohci_hcd 0000:00:05.0: irq 9, io mem 0x80000000
> Faulting instruction address: 0xf267b3a8
> Oops: Kernel access of bad area, sig: 11 [#1]
> PREEMPT CHRP
> Modules linked in: snd_via82xx(+) snd_ac97_codec mv643xx_eth(+)
> via_rhine(+) i2c_viapro(+) ac97_bus ohci_hcd(+) snd_mpu401_uart
> uhci_hcd(+) snd_rawmidi
> NIP: f267b3a8 LR: f267b3a0 CTR: c0394ff4
> REGS: ef271c90 TRAP: 0300   Tainted: G        W    (3.0.4)
> MSR: 00009032 <EE,ME,IR,DR>  CR: 84004448  XER: 00000000
> DAR: 00000000, DSISR: 40000000
> TASK = ef294c60[94] 'modprobe' THREAD: ef270000
> GPR00: 00000000 ef271d40 ef294c60 00000000 eec003c0 eec00005 ef24bb3c 00000000
> GPR08: ef24bb28 ef8a7600 ffffffff 00000001 44004442 10024440 1000ba68 00000000
> GPR16: 1000ba44 bf83e324 00000000 1000ba58 00000000 104410ec 00000a30 00000000
> GPR24: c0059210 c06b68c0 00000020 c06b68b8 fffffff4 eec00000 c06b6740 eec003c0
> NIP [f267b3a8] mv643xx_eth_probe+0x98/0x604 [mv643xx_eth]
> LR [f267b3a0] mv643xx_eth_probe+0x90/0x604 [mv643xx_eth]
> Call Trace:
> [ef271d40] [f267b394] mv643xx_eth_probe+0x84/0x604 [mv643xx_eth] (unreliable)
> [ef271d80] [c039685c] platform_drv_probe+0x20/0x30
> [ef271d90] [c0395578] driver_probe_device+0xe4/0x198
> [ef271db0] [c039569c] __driver_attach+0x70/0x98
> [ef271dd0] [c0394614] bus_for_each_dev+0x60/0x90
> [ef271e00] [c03951d0] driver_attach+0x24/0x34
> [ef271e10] [c0394d9c] bus_add_driver+0xbc/0x23c
> [ef271e30] [c0395ac8] driver_register+0xb8/0x144
> [ef271e50] [c0396bb4] platform_driver_register+0x68/0x78
> [ef271e60] [f2680034] mv643xx_eth_init_module+0x34/0x80 [mv643xx_eth]
> [ef271e80] [c000402c] do_one_initcall+0xe0/0x1c0
> [ef271eb0] [c005b438] sys_init_module+0x1600/0x17f4
> [ef271f40] [c0012df8] ret_from_syscall+0x0/0x38
> --- Exception: c01 at 0xff62ac0
>    LR = 0x10003f2c
> Instruction dump:
> 7c7d1b79 41820530 3bfd03c0 3b3b0008 7fe4fb78 7f23cb78 48001101 807e0000
> 38630008 48001505 907d03c0 817e0004
> 556b502a 396b0400 7d605a14
> usb usb3: New USB device found, idVendor=1d6b, idProduct=0001
> usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> usb usb3: Product: OHCI Host Controller
> usb usb3: Manufacturer: Linux 3.0.4 ohci_hcd
> usb usb3: SerialNumber: 0000:00:05.0
> hub 3-0:1.0: USB hub found
> hub 3-0:1.0: 3 ports detected
> vt596_smbus 0000:00:0c.4: SMBUS: Error: Host SMBus controller not
> enabled! - upgrade BIOS or use force=1
> VIA 82xx Audio 0000:00:0c.5: enabling device (0000 -> 0001)
> ---[ end trace cebed1f190337b78 ]---
> via-rhine 0000:00:0d.0: enabling device (0000 -> 0003)
> via-rhine 0000:00:0d.0: eth0: VIA Rhine II at 0x80001900,

	Regards,
	Gabriel

^ permalink raw reply

* Re: FW: P4080 device tree problems with fsl dpaa ...
From: Thomas De Schampheleire @ 2011-10-18  7:57 UTC (permalink / raw)
  To: Robert Sciuk; +Cc: linuxppc-dev
In-Reply-To: <2DD52030B5146141BEB762A11AE97C4CF6E2E7@SPQCEXC05.exfo.com>

Hi Robert,

On Mon, Oct 17, 2011 at 8:34 PM, Robert Sciuk <robert.sciuk@exfo.com> wrote=
:
>
>
>> -----Original Message-----
>> From: patrickdepinguin@gmail.com [mailto:patrickdepinguin@gmail.com] On
>> Behalf Of Thomas De Schampheleire
>> Sent: Monday, October 17, 2011 5:01 AM
>> To: Robert Sciuk
>> Cc: linuxppc-dev@lists.ozlabs.org
>> Subject: Re: FW: P4080 device tree problems with fsl dpaa ...
>>
>> Hi Robert,
>
> [my stuff snipped]
>>
>> > I have no idea what an OH binding is, what it might look like, and
>> what it entails, but I think that it might be a significant factor in
>> our not seeing a working interface. =A0Has anyone any experience with
>> dpaa device trees, and configuration? =A0Any pointers? =A0Any docs? Shot=
s
>> in the dark?
>>
>> We are using a device tree on p4080 with a dpaa configuration, yes.
>> I also don't know about the OH bindings, but I have a vague memory of
>> us having that message too, and it not being a real problem.
>>
>
> Other indicators concur with your assessment, and suggest that I back tho=
se nodes out as well.
>
>
>> What I do know is that the device tree is very easy to get wrong, and
>> that it should match your hardware precisely. I'm not using the same
>> configuration as you are (there are no MDIO devices between our phy
>> and dTSEC) so the device tree looks a little different.
>
> Would it be possible to have a look at the relevant portions of your dev =
tree?
>
>

Sure.
The following snippets are for two SGMII devices on the second FMAN:

First the ports:

// RX
                        fman1_rx2: port@8a000 {
                                compatible =3D
"fsl,p4080-fman-port-1g-rx", "fsl,fman-port-1g-rx";
                                reg =3D <0x8a000 0x1000>;
                                fsl,liodn =3D <0x2d>;
         // Logical Input/Output Device Number used by PAMU
                                cell-index =3D <2>;
         // 1G index
                        };
                        fman1_rx3: port@8b000 {
                                compatible =3D
"fsl,p4080-fman-port-1g-rx", "fsl,fman-port-1g-rx";
                                reg =3D <0x8b000 0x1000>;
                                fsl,liodn =3D <0x2e>;
         // Logical Input/Output Device Number used by PAMU
                                cell-index =3D <3>;
         // 1G index
                        };
// TX
                        fman1_tx2: port@aa000 {
                                compatible =3D
"fsl,p4080-fman-port-1g-tx", "fsl,fman-port-1g-tx";
                                reg =3D <0xaa000 0x1000>;
                                fsl,qman-channel-id =3D <0x63>;
         // Direct-HW-Portal 1: SP3
                                cell-index =3D <2>;
         // 1G index
                        };
                        fman1_tx3: port@ab000 {
                                compatible =3D
"fsl,p4080-fman-port-1g-tx", "fsl,fman-port-1g-tx";
                                reg =3D <0xab000 0x1000>;
                                fsl,qman-channel-id =3D <0x64>;
         // Direct-HW-Portal 1: SP4
                                cell-index =3D <3>;
         // 1G index
                        };

Then the TSECs:
                        enet7: ethernet@e4000 { // dTSEC3
                                compatible =3D "fsl,p4080-fman-1g-mac",
"fsl,fman-1g-mac";
                                reg =3D <0xe4000 0x1000>;
                                fixed-link =3D <7 1 1000 0 0>;
         // Use fixed settings because there is no MDIO bus between
SOC and PHY
                                local-mac-address =3D [00 BA 0B AB 00 0A];
                                fsl,port-handles =3D <&fman1_rx2
&fman1_tx2>;     // RX + TX port
                                phy-connection-type =3D "sgmii";
         // 1Gb
                                cell-index =3D <2>;
                        };
                        enet8: ethernet@e6000 { // dTSEC4
                                compatible =3D "fsl,p4080-fman-1g-mac",
"fsl,fman-1g-mac";
                                reg =3D <0xe6000 0x1000>;
                                fixed-link =3D <8 1 1000 0 0>;
         // Use fixed settings because there is no MDIO bus between
SOC and PHY
                                local-mac-address =3D [00 BA 0B AB 00 0B];
                                fsl,port-handles =3D <&fman1_rx3
&fman1_tx3>;     // RX + TX port
                                phy-connection-type =3D "sgmii";
         // 1Gb
                                cell-index =3D <3>;
                        };

The ethernet devices in the fsl,dpaa node:
                ethernet@7 {
                        compatible =3D "fsl,p4080-dpa-ethernet",
"fsl,dpa-ethernet";
                        fsl,qman-channel =3D <&qportal0>;
                        fsl,fman-mac =3D <&enet7>;
                };
                ethernet@8 {
                        compatible =3D "fsl,p4080-dpa-ethernet",
"fsl,dpa-ethernet";
                        fsl,qman-channel =3D <&qportal0>;
                        fsl,fman-mac =3D <&enet8>;


>
>>
>> Are you using the reference design or is this custom?
>
> This is a custom design, and is an ATCA blade.
>
>
>> Did you have a look at the device tree in the linux kernel sources?
>> (arch/powerpc/boot/dts/p4080.dts). Does this configuration match
>> yours? In that configuration, there are separate nodes of type
>> p4080ds-mdio, inside the main mdio node.
>
> We actually used the 36 bit tree (we plan to ship the boards with 16G ini=
tially, and up to 32G eventually). =A0I've also re-worked the tree from the=
 LTIB (System Builder) in an attempt to get this to work. =A0Our design dif=
fers significantly from the P4080DS in that there exists no MUX between the=
 bus and phy ... and there is no PIXIS FPGA to do all the clocking and star=
tup stuff.

I have to admit that I'm not an export at the DPAA part either. My
colleague who is is on holiday, unfortunately.

In our case, we needed the 'fixed-link' settings because of the
absence of an MDIO, and I also initially made the mistake of
registering the devices on the wrong FMAN.
For RX, I also had some problems receiving frames correctly. Setting
the source MAC address correctly fixed that problem.
But you seem to have problems with TX...

>
> I've modified u-boot to assign mac addresses based upon our OUI, and the =
MACs all seem to be configured properly coming out of firmware, the ifconfi=
g on the Linux side recognizes all of our 6 interfaces ...
>
>
>>
>> Is your phy configured correctly? Are there any boot messages about
>> this? Can you check its registers?
>> The same for the mdio.
>
> There is some question about the TBI initialization, and we are tracing t=
hat as we speak ...
>
>>
>> Some generic pointers:
>> * If you set CONFIG_PROC_DEVICETREE in the kernel config, you can read
>> out the device-tree at runtime in /proc/device-tree. This helps in
>> verifying whether the nodes you programmed actually appear in the
>> running system.
>
> Ack.
>
>>
>> * The /sys/devices directory can also be useful in identifying
>> potential problems for unfound devices (which does not appear to be
>> your case).
>>
>
> Ack. =A0Also using /proc/interrupts ...
>
>
>> * Can you step through the code, e.g. with a JTAG debugger? Try
>> following the transmit path in the dpaa_eth driver. Maybe something
>> errors out prematurely.
>>
>
> With some headaches ... using codewarrior, and getting assembly level tra=
cing ...

Also, did you check in the dTSEC/FMAN/BMAN for relevant counter
registers? Do you find proof that the packets make it as far as the
dTSEC? (then maybe there is a problem in the link between dTSEC and
PHY).
Are there counters in the PHY that can indicate that packets or no
packets are received?

Which version of the kernel and associated Freescale patches are you using?

How and what type of packets are you sending? Raw MAC frames, IP? Are
you using custom code, or can you try things like ping?
If you are using IP, I trust you checked the Linux configuration (like
assigning a valid IP address to the interface and making sure the
routing table is correct).

Best regards,
Thomas

^ permalink raw reply

* IRQ2 and IRQ 3
From: smitha.vanga @ 2011-10-18  8:05 UTC (permalink / raw)
  To: B07421; +Cc: linuxppc-dev
In-Reply-To: <B8D6CA50DACE9E4AAADE9A4D56FBAAE623B55D@039-SN1MPN1-005.039d.mgd.msft.net>

 
Hi ,

I want to use IRQ2 and IRQ3 in my driver. How do I add them in the device tr=
ee file.

Regard,
Smitha

Please do not print this email unless it is absolutely necessary. 

The information contained in this electronic message and any attachments to=
 this message are intended for the exclusive use of the addressee(s) and may=
 contain proprietary, confidential or privileged information. If you are not=
 the intended recipient, you should not disseminate, distribute or copy this=
 e-mail. Please notify the sender immediately and destroy all copies of this=
 message and any attachments. 

WARNING: Computer viruses can be transmitted via email. The recipient should=
 check this email and any attachments for the presence of viruses. The compa=
ny accepts no liability for any damage caused by any virus transmitted by th=
is email. 

www.wipro.com

^ permalink raw reply

* RE: IRQ2 and IRQ 3
From: smitha.vanga @ 2011-10-18  8:06 UTC (permalink / raw)
  To: B07421, R65777; +Cc: linuxppc-dev


  
Hi ,

I want to use IRQ2 and IRQ3 in my driver. How do I add them in the device tr=
ee file.

Regard,
Smitha

Please do not print this email unless it is absolutely necessary. 

The information contained in this electronic message and any attachments to=
 this message are intended for the exclusive use of the addressee(s) and may=
 contain proprietary, confidential or privileged information. If you are not=
 the intended recipient, you should not disseminate, distribute or copy this=
 e-mail. Please notify the sender immediately and destroy all copies of this=
 message and any attachments. 

WARNING: Computer viruses can be transmitted via email. The recipient should=
 check this email and any attachments for the presence of viruses. The compa=
ny accepts no liability for any damage caused by any virus transmitted by th=
is email. 

www.wipro.com

^ permalink raw reply

* RE: IRQ2 and IRQ 3
From: Bhushan Bharat-R65777 @ 2011-10-18  8:58 UTC (permalink / raw)
  To: smitha.vanga@wipro.com, Wood Scott-B07421; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <40631E9A2581F14BA60888C87A76A1FE01637C@HYD-MKD-MBX4.wipro.com>

Hi,

Is not some interrupt vector number defined for i2c in your soc specificati=
on(IIRC mpc9247 and I do not have this).

Thanks
-Bharat


> -----Original Message-----
> From: smitha.vanga@wipro.com [mailto:smitha.vanga@wipro.com]
> Sent: Tuesday, October 18, 2011 1:36 PM
> To: Wood Scott-B07421; Bhushan Bharat-R65777
> Cc: linuxppc-dev@lists.ozlabs.org
> Subject: RE: IRQ2 and IRQ 3
>=20
>=20
>=20
> Hi ,
>=20
> I want to use IRQ2 and IRQ3 in my driver. How do I add them in the device
> tree file.
>=20
> Regard,
> Smitha
>=20
> Please do not print this email unless it is absolutely necessary.
>=20
> The information contained in this electronic message and any attachments
> to this message are intended for the exclusive use of the addressee(s)
> and may contain proprietary, confidential or privileged information. If
> you are not the intended recipient, you should not disseminate,
> distribute or copy this e-mail. Please notify the sender immediately and
> destroy all copies of this message and any attachments.
>=20
> WARNING: Computer viruses can be transmitted via email. The recipient
> should check this email and any attachments for the presence of viruses.
> The company accepts no liability for any damage caused by any virus
> transmitted by this email.
>=20
> www.wipro.com

^ permalink raw reply

* RE: IRQ2 and IRQ 3
From: smitha.vanga @ 2011-10-18  9:05 UTC (permalink / raw)
  To: R65777, B07421; +Cc: linuxppc-dev
In-Reply-To: <B8D6CA50DACE9E4AAADE9A4D56FBAAE623BEB3@039-SN1MPN1-005.039d.mgd.msft.net>

Yes , there is a vector numbe defined in the specifications .

IRQ2 - 20
IRQ3 - 21

But I don't know how to specify them in the .dts file .

Regards,
Smitha
Please do not print this email unless it is absolutely necessary. 

The information contained in this electronic message and any attachments to=
 this message are intended for the exclusive use of the addressee(s) and may=
 contain proprietary, confidential or privileged information. If you are not=
 the intended recipient, you should not disseminate, distribute or copy this=
 e-mail. Please notify the sender immediately and destroy all copies of this=
 message and any attachments. 

WARNING: Computer viruses can be transmitted via email. The recipient should=
 check this email and any attachments for the presence of viruses. The compa=
ny accepts no liability for any damage caused by any virus transmitted by th=
is email. 

www.wipro.com

^ permalink raw reply

* Re: IRQ2 and IRQ 3
From: Vineeth @ 2011-10-18  9:10 UTC (permalink / raw)
  To: smitha.vanga, linuxppc-dev
In-Reply-To: <40631E9A2581F14BA60888C87A76A1FE016391@HYD-MKD-MBX4.wipro.com>

[-- Attachment #1: Type: text/plain, Size: 1471 bytes --]

interrupts <IRQ_NO,POLARITY>


 i2c@3000 {
            #address-cells = <1>;
            #size-cells = <0>;
            cell-index = <0>;
            compatible = "fsl-i2c";
            reg = <0x3000 0x100>;
            interrupts = <43 2>;
            interrupt-parent = <&mpic>;
            dfsrr;
        };




On Tue, Oct 18, 2011 at 2:35 PM, <smitha.vanga@wipro.com> wrote:

> Yes , there is a vector numbe defined in the specifications .
>
> IRQ2 - 20
> IRQ3 - 21
>
> But I don't know how to specify them in the .dts file .
>
> Regards,
> Smitha
> Please do not print this email unless it is absolutely necessary.
>
> The information contained in this electronic message and any attachments to
> this message are intended for the exclusive use of the addressee(s) and may
> contain proprietary, confidential or privileged information. If you are not
> the intended recipient, you should not disseminate, distribute or copy this
> e-mail. Please notify the sender immediately and destroy all copies of this
> message and any attachments.
>
> WARNING: Computer viruses can be transmitted via email. The recipient
> should check this email and any attachments for the presence of viruses. The
> company accepts no liability for any damage caused by any virus transmitted
> by this email.
>
> www.wipro.com
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>

[-- Attachment #2: Type: text/html, Size: 2054 bytes --]

^ permalink raw reply

* Re: [PATCH v13 0/6] flexcan: Add support for powerpc flexcan (freescale p1010)
From: Robin Holt @ 2011-10-18  9:43 UTC (permalink / raw)
  To: Kumar Gala
  Cc: netdev, U Bhaskar-B22300, socketcan-core, Robin Holt, PPC list,
	David S. Miller
In-Reply-To: <16FBAA47-5133-43A1-80CE-C6D63B79FB5D@kernel.crashing.org>

On Tue, Oct 18, 2011 at 12:44:07AM -0500, Kumar Gala wrote:
> 
> On Aug 16, 2011, at 10:32 PM, Robin Holt wrote:
> 
> > David,
> > 
> > The following set of patches have been reviewed by the above parties and
> > all comments have been integrated.  Although the patches stray from the
> > drivers/net/can directory, the diversions are related to changes for
> > the flexcan driver.
> > 
> > The patch set is based upon your net-next-2.6 tree's commit 6c37e46.
> > 
> > Could you please queue these up for the next appropriate push to Linus'
> > tree?
> > 
> > Thanks,
> > Robin Holt
> 
> Robin,
> 
> Do you remember why we went with just 'fsl,p1010-flexcan' as the device tree compatible?  Do we feel the flex can on P1010 isn't the same as on MPC5xxx? or the ARM SoCs?

The decision was due to the fact there is no true "generic" fsl.flexcan
chip free of any SOC implementation and therefore not something which
could be separately defined.  That decision was made by Grant Likely.
I will inline that email below.

Robin


On Mon, Aug 15, 2011 at 09:13:50AM -0600, Grant Likely wrote:
> On Mon, Aug 15, 2011 at 9:03 AM, Robin Holt <holt@sgi.com> wrote:
> > Grant,
> >
> > Earlier, you had asked for a more specific name for the compatible
> > property of the Freescale flexcan device.  I still have not gotten a
> > more specific answer.  Hopefully Marc can give you more details about
> > the flexcan implementations.
> 
> If there is no ip core version, then just stick with the
> fsl,<soc>-flexcan name and drop "fsl,flexcan".  Marketing may say
> flexcan is flexcan, but hardware engineers like to change things.
> Trying to be too generic in compatible values will just lead to
> problems in the future.

Thanks,
Robin

^ permalink raw reply

* Re: [PATCH v13 0/6] flexcan: Add support for powerpc flexcan (freescale p1010)
From: Kumar Gala @ 2011-10-18 11:43 UTC (permalink / raw)
  To: Robin Holt
  Cc: netdev, U Bhaskar-B22300, socketcan-core, PPC list,
	David S. Miller
In-Reply-To: <20111018094328.GC22814@sgi.com>


>> Robin,
>>=20
>> Do you remember why we went with just 'fsl,p1010-flexcan' as the =
device tree compatible?  Do we feel the flex can on P1010 isn't the same =
as on MPC5xxx? or the ARM SoCs?
>=20
> The decision was due to the fact there is no true "generic" =
fsl.flexcan
> chip free of any SOC implementation and therefore not something which
> could be separately defined.  That decision was made by Grant Likely.
> I will inline that email below.
>=20
> Robin


Thanks, I'll look into this internally at FSL.  I think its confusing as =
hell to have "fsl,p1010-flexcan" in an ARM .dts and don't think any =
reasonable ARM customer of FSL would know to put a PPC SOC name in their =
.dts.  I'll ask the HW guys what's going on so we can come up with a bit =
more generic name so we don't have to constantly change this.  Even if =
its just:

fsl,ppc-flexcan & fsl,arm-flexcan.

> On Mon, Aug 15, 2011 at 09:13:50AM -0600, Grant Likely wrote:
>> On Mon, Aug 15, 2011 at 9:03 AM, Robin Holt <holt@sgi.com> wrote:
>>> Grant,
>>>=20
>>> Earlier, you had asked for a more specific name for the compatible
>>> property of the Freescale flexcan device.  I still have not gotten a
>>> more specific answer.  Hopefully Marc can give you more details =
about
>>> the flexcan implementations.
>>=20
>> If there is no ip core version, then just stick with the
>> fsl,<soc>-flexcan name and drop "fsl,flexcan".  Marketing may say
>> flexcan is flexcan, but hardware engineers like to change things.
>> Trying to be too generic in compatible values will just lead to
>> problems in the future.
>=20
> Thanks,
> Robin

- k=

^ permalink raw reply

* Re: [PATCH v13 0/6] flexcan: Add support for powerpc flexcan (freescale p1010)
From: Marc Kleine-Budde @ 2011-10-18 11:48 UTC (permalink / raw)
  To: Kumar Gala
  Cc: netdev, U Bhaskar-B22300, linux-can, socketcan-core, Robin Holt,
	PPC list, David S. Miller
In-Reply-To: <D79CB818-C14E-4C8D-9A8D-42B39ADE20B2@kernel.crashing.org>

[-- Attachment #1: Type: text/plain, Size: 857 bytes --]

On 10/18/2011 01:43 PM, Kumar Gala wrote:
> Thanks, I'll look into this internally at FSL.  I think its confusing
> as hell to have "fsl,p1010-flexcan" in an ARM .dts and don't think
> any reasonable ARM customer of FSL would know to put a PPC SOC name
> in their .dts.  I'll ask the HW guys what's going on so we can come
> up with a bit more generic name so we don't have to constantly change
> this.  Even if its just:
> 
> fsl,ppc-flexcan & fsl,arm-flexcan.

If you talk the HW guys ask them for a name for the coldfire flexcan
core, too please ;)

cheers, Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply

* Re: [PATCH v13 0/6] flexcan: Add support for powerpc flexcan (freescale p1010)
From: Robin Holt @ 2011-10-18 12:30 UTC (permalink / raw)
  To: Kumar Gala
  Cc: netdev, U Bhaskar-B22300, socketcan-core, Robin Holt, PPC list,
	David S. Miller
In-Reply-To: <D79CB818-C14E-4C8D-9A8D-42B39ADE20B2@kernel.crashing.org>

On Tue, Oct 18, 2011 at 06:43:13AM -0500, Kumar Gala wrote:
> 
> >> Robin,
> >> 
> >> Do you remember why we went with just 'fsl,p1010-flexcan' as the device tree compatible?  Do we feel the flex can on P1010 isn't the same as on MPC5xxx? or the ARM SoCs?
> > 
> > The decision was due to the fact there is no true "generic" fsl.flexcan
> > chip free of any SOC implementation and therefore not something which
> > could be separately defined.  That decision was made by Grant Likely.
> > I will inline that email below.
> > 
> > Robin
> 
> 
> Thanks, I'll look into this internally at FSL.  I think its confusing as hell to have "fsl,p1010-flexcan" in an ARM .dts and don't think any reasonable ARM customer of FSL would know to put a PPC SOC name in their .dts.  I'll ask the HW guys what's going on so we can come up with a bit more generic name so we don't have to constantly change this.  Even if its just:

Grants argument was that there should then be a fsl,zeba-flexcan which
would define each arm based soc.  The match string could be there and
the devicetree binding would match on each equivalent.

Robin

> 
> fsl,ppc-flexcan & fsl,arm-flexcan.
> 
> > On Mon, Aug 15, 2011 at 09:13:50AM -0600, Grant Likely wrote:
> >> On Mon, Aug 15, 2011 at 9:03 AM, Robin Holt <holt@sgi.com> wrote:
> >>> Grant,
> >>> 
> >>> Earlier, you had asked for a more specific name for the compatible
> >>> property of the Freescale flexcan device.  I still have not gotten a
> >>> more specific answer.  Hopefully Marc can give you more details about
> >>> the flexcan implementations.
> >> 
> >> If there is no ip core version, then just stick with the
> >> fsl,<soc>-flexcan name and drop "fsl,flexcan".  Marketing may say
> >> flexcan is flexcan, but hardware engineers like to change things.
> >> Trying to be too generic in compatible values will just lead to
> >> problems in the future.
> > 
> > Thanks,
> > Robin
> 
> - k

^ permalink raw reply

* RE: IRQ2 and IRQ 3
From: Bhushan Bharat-R65777 @ 2011-10-18 15:03 UTC (permalink / raw)
  To: smitha.vanga@wipro.com, Wood Scott-B07421; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <40631E9A2581F14BA60888C87A76A1FE016391@HYD-MKD-MBX4.wipro.com>

Hi,=20

For detail please look at ePAPR specification.

Say i2c interrupt number is 21 then you can try
"interrupts =3D <21 8>;" in device tree.

Thanks
-Bharat

> -----Original Message-----
> From: smitha.vanga@wipro.com [mailto:smitha.vanga@wipro.com]
> Sent: Tuesday, October 18, 2011 2:35 PM
> To: Bhushan Bharat-R65777; Wood Scott-B07421
> Cc: linuxppc-dev@lists.ozlabs.org
> Subject: RE: IRQ2 and IRQ 3
>=20
> Yes , there is a vector numbe defined in the specifications .
>=20
> IRQ2 - 20
> IRQ3 - 21
>=20
> But I don't know how to specify them in the .dts file .
>=20
> Regards,
> Smitha
> Please do not print this email unless it is absolutely necessary.
>=20
> The information contained in this electronic message and any attachments
> to this message are intended for the exclusive use of the addressee(s)
> and may contain proprietary, confidential or privileged information. If
> you are not the intended recipient, you should not disseminate,
> distribute or copy this e-mail. Please notify the sender immediately and
> destroy all copies of this message and any attachments.
>=20
> WARNING: Computer viruses can be transmitted via email. The recipient
> should check this email and any attachments for the presence of viruses.
> The company accepts no liability for any damage caused by any virus
> transmitted by this email.
>=20
> www.wipro.com

^ permalink raw reply

* RE: FW: P4080 device tree problems with fsl dpaa ... RESOLVED.
From: Robert Sciuk @ 2011-10-18 21:38 UTC (permalink / raw)
  To: Thomas De Schampheleire; +Cc: linuxppc-dev
In-Reply-To: <CAAXf6LWTU_OVBLfn4Tavo6JxE5UfoN8JuCidB4fbr4-RX+XdAw@mail.gmail.com>



[snip]

>=20
> How and what type of packets are you sending? Raw MAC frames, IP? Are
> you using custom code, or can you try things like ping?
> If you are using IP, I trust you checked the Linux configuration (like
> assigning a valid IP address to the interface and making sure the
> routing table is correct).
>=20
> Best regards,
> Thomas

Thomas,

I would like to thank you for your very kind assistance on the DPAA =
problem.  We traced the problem to the connection between MAC and PHY, =
and we have resolved it by instrumenting code and comparing the TBI and =
PHY initialization from u-boot to the Linux DPA code, and replacing some =
of the "magic numbers" we found in the driver with "magic numbers" we =
know to work.  OUCH!

We spent an inordinate amount of effort in trying to understand the =
undocumented code/tree, but I am convinced that the device-tree approach =
to embedded boards is a very valuable approach, and will ultimately =
solve many more problems than it creates short term. =20

Again, your information was of great assistance, and I look forward to =
being able to pay forward the same kind of assistance in the future.

Cheers,
Rob Sciuk.

^ permalink raw reply

* Re: FW: P4080 device tree problems with fsl dpaa ... RESOLVED.
From: Thomas De Schampheleire @ 2011-10-19  6:34 UTC (permalink / raw)
  To: Robert Sciuk; +Cc: linuxppc-dev
In-Reply-To: <2DD52030B5146141BEB762A11AE97C4CF6E5E9@SPQCEXC05.exfo.com>

Hi Robert,

On Tue, Oct 18, 2011 at 11:38 PM, Robert Sciuk <robert.sciuk@exfo.com> wrot=
e:
>
>
> [snip]
>
>>
>> How and what type of packets are you sending? Raw MAC frames, IP? Are
>> you using custom code, or can you try things like ping?
>> If you are using IP, I trust you checked the Linux configuration (like
>> assigning a valid IP address to the interface and making sure the
>> routing table is correct).
>>
>> Best regards,
>> Thomas
>
> Thomas,
>
> I would like to thank you for your very kind assistance on the DPAA probl=
em. =A0We traced the problem to the connection between MAC and PHY, and we =
have resolved it by instrumenting code and comparing the TBI and PHY initia=
lization from u-boot to the Linux DPA code, and replacing some of the "magi=
c numbers" we found in the driver with "magic numbers" we know to work. =A0=
OUCH!
>
> We spent an inordinate amount of effort in trying to understand the undoc=
umented code/tree, but I am convinced that the device-tree approach to embe=
dded boards is a very valuable approach, and will ultimately solve many mor=
e problems than it creates short term.
>
> Again, your information was of great assistance, and I look forward to be=
ing able to pay forward the same kind of assistance in the future.

I'm very glad you found the issue (I was running out of ideas ;-) and
that I was able to help you in some way.
Thanks for posting back.

Good luck with the rest of your project!

Best regards,
Thomas

>
> Cheers,
> Rob Sciuk.
>
>

^ permalink raw reply

* [PATCH] powerpc/cpm: Clear muram before it is in use.
From: Kumar Gala @ 2011-10-19  7:18 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Hongjun Chen

From: Hongjun Chen <Hong-jun.Chen@freescale.com>

We need to ensure that MURAM is in a known and cleared out state before
using it as the bootloader could have utilized it from its own purposes
and left it in an unknown state.

If we don't clear it out we've seen issues with UCC ethernet:
* Multi ethernet interfaces can't work simultanously.
* Multi up/down Ethernet interfaces will halt these ports.
* UCC1 RGMII can't work when kernel boots from some hosts.

Signed-off-by: Kai.Jiang <Kai.Jiang@freescale.com>
Signed-off-by: Hongjun Chen <Hong-jun.Chen@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 arch/powerpc/sysdev/cpm_common.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index d55d0ad..8db10bb 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -3,7 +3,7 @@
  *
  * Author: Scott Wood <scottwood@freescale.com>
  *
- * Copyright 2007 Freescale Semiconductor, Inc.
+ * Copyright 2007-2008,2010 Freescale Semiconductor, Inc.
  *
  * Some parts derived from commproc.c/cpm2_common.c, which is:
  * Copyright (c) 1997 Dan error_act (dmalek@jlc.net)
@@ -146,6 +146,7 @@ unsigned long cpm_muram_alloc(unsigned long size, unsigned long align)
 	spin_lock_irqsave(&cpm_muram_lock, flags);
 	cpm_muram_info.alignment = align;
 	start = rh_alloc(&cpm_muram_info, size, "commproc");
+	memset(cpm_muram_addr(start), 0, size);
 	spin_unlock_irqrestore(&cpm_muram_lock, flags);
 
 	return start;
-- 
1.7.3.4

^ permalink raw reply related

* RE: [PATCH 3/5][v2] fsl-rio: Add two ports and rapidio message units support
From: Bounine, Alexandre @ 2011-10-19 19:54 UTC (permalink / raw)
  To: Kumar Gala, linuxppc-dev; +Cc: Andrew Morton, Liu Gang, linux-kernel
In-Reply-To: <1318514922-12672-3-git-send-email-galak@kernel.crashing.org>

On Thu, Oct 13, 2011 at 10:09 AM, Kumar Gala wrote:
>=20
> From: Liu Gang <Gang.Liu@freescale.com>
>=20
> Usually, freescale rapidio endpoint can support one 1X or two 4X LP-
> Serial
> link interfaces, and rapidio message transactions can be implemented
by
> two

Is the number of 1x ports described correctly?
Can we have two 1x ports as well?=20

> message units. This patch adds the support of two rapidio ports and
> initializes message unit 0 and message unit 1. And these ports and
> message
... skip ...
> +
> +		/* Probe the master port phy type */
> +		ccsr =3D in_be32(priv->regs_win + RIO_CCSR + i*0x20);
> +		port->phy_type =3D (ccsr & 1) ? RIO_PHY_SERIAL :
> RIO_PHY_PARALLEL;
> +		dev_info(&dev->dev, "RapidIO PHY type: %s\n",
> +				(port->phy_type =3D=3D RIO_PHY_PARALLEL) ?
> +				"parallel" :
> +				((port->phy_type =3D=3D RIO_PHY_SERIAL) ?
"serial"
> :
> +				 "unknown"));
> +		/* Checking the port training status */
> +		if (in_be32((priv->regs_win + RIO_ESCSR + i*0x20)) & 1)
{
> +			dev_err(&dev->dev, "Port %d is not ready. "
> +				"Try to restart connection...\n", i);
> +			switch (port->phy_type) {
> +			case RIO_PHY_SERIAL:
> +				/* Disable ports */
> +				out_be32(priv->regs_win
> +					+ RIO_CCSR + i*0x20, 0);
> +				/* Set 1x lane */
> +				setbits32(priv->regs_win
> +					+ RIO_CCSR + i*0x20,
0x02000000);
> +				/* Enable ports */
> +				setbits32(priv->regs_win
> +					+ RIO_CCSR + i*0x20,
0x00600000);
> +				break;
> +			case RIO_PHY_PARALLEL:
> +				/* Disable ports */
> +				out_be32(priv->regs_win
> +					+ RIO_CCSR + i*0x20,
0x22000000);
> +				/* Enable ports */
> +				out_be32(priv->regs_win
> +					+ RIO_CCSR + i*0x20,
0x44000000);
> +				break;
> +			}

Probably this may be a good moment to drop the support for parallel
link.
Especially after you renamed controller to "srio" in the device tree.

> +			msleep(100);
> +			if (in_be32((priv->regs_win
> +					+ RIO_ESCSR + i*0x20)) & 1) {
> +				dev_err(&dev->dev,
> +					"Port %d restart failed.\n", i);
> +				release_resource(&port->iores);
> +				kfree(priv);
> +				kfree(port);
> +				continue;
> +			}
> +			dev_info(&dev->dev, "Port %d restart
success!\n", i);
> +		}
> +		fsl_rio_info(&dev->dev, ccsr);
> +
... skip ...
>=20
>  struct rio_msg_regs {
> -	u32 omr;	/* 0xD_3000 - Outbound message 0 mode register
*/
> -	u32 osr;	/* 0xD_3004 - Outbound message 0 status register
*/
> +	u32 omr;
> +	u32 osr;
>  	u32 pad1;
> -	u32 odqdpar;	/* 0xD_300C - Outbound message 0 descriptor
> queue
> -			   dequeue pointer address register */
> +	u32 odqdpar;
>  	u32 pad2;
> -	u32 osar;	/* 0xD_3014 - Outbound message 0 source address
> -			   register */
> -	u32 odpr;	/* 0xD_3018 - Outbound message 0 destination
port
> -			   register */
> -	u32 odatr;	/* 0xD_301C - Outbound message 0 destination
> attributes
> -			   Register*/
> -	u32 odcr;	/* 0xD_3020 - Outbound message 0 double-word
count
> -			   register */
> +	u32 osar;
> +	u32 odpr;
> +	u32 odatr;
> +	u32 odcr;
>  	u32 pad3;
> -	u32 odqepar;	/* 0xD_3028 - Outbound message 0 descriptor
> queue
> -			   enqueue pointer address register */
> +	u32 odqepar;
>  	u32 pad4[13];
> -	u32 imr;	/* 0xD_3060 - Inbound message 0 mode register */
> -	u32 isr;	/* 0xD_3064 - Inbound message 0 status register
*/
> +	u32 imr;
> +	u32 isr;
>  	u32 pad5;
> -	u32 ifqdpar;	/* 0xD_306C - Inbound message 0 frame queue
> dequeue
> -			   pointer address register*/
> +	u32 ifqdpar;
>  	u32 pad6;
> -	u32 ifqepar;	/* 0xD_3074 - Inbound message 0 frame queue
> enqueue
> -			   pointer address register */
> -	u32 pad7[226];
> -	u32 odmr;	/* 0xD_3400 - Outbound doorbell mode register */
> -	u32 odsr;	/* 0xD_3404 - Outbound doorbell status register
*/
> +	u32 ifqepar;
> +	u32 pad7;

Do we need pad7 here?

> +};
> +
> +struct rio_dbell_regs {
> +	u32 odmr;
> +	u32 odsr;
>  	u32 res0[4];
> -	u32 oddpr;	/* 0xD_3418 - Outbound doorbell destination port
> -			   register */

... skip ...

>=20
> @@ -340,35 +327,45 @@ fsl_rio_dbell_handler(int irq, void
> *dev_instance)
>  			" sid %2.2x tid %2.2x info %4.4x\n",
>  			DBELL_SID(dmsg), DBELL_TID(dmsg),
DBELL_INF(dmsg));
>=20
> -		list_for_each_entry(dbell, &port->dbells, node) {
> -			if ((dbell->res->start <=3D DBELL_INF(dmsg)) &&
> -				(dbell->res->end >=3D DBELL_INF(dmsg))) {
> -				found =3D 1;
> -				break;
> +		for (i =3D 0; i < MAX_PORT_NUM; i++) {
> +			if (fsl_dbell->mport[i]) {
> +				list_for_each_entry(dbell,
> +					&fsl_dbell->mport[i]->dbells,
node) {
> +					if ((dbell->res->start
> +						<=3D DBELL_INF(dmsg))
> +						&& (dbell->res->end
> +						>=3D DBELL_INF(dmsg))) {
> +						found =3D 1;
> +						break;
> +					}
> +				}
> +				if (found && dbell->dinb) {
> +					dbell->dinb(fsl_dbell->mport[i],
> +						dbell->dev_id,
DBELL_SID(dmsg),
> +						DBELL_TID(dmsg),
> +						DBELL_INF(dmsg));
> +					break;
> +				}
>  			}
>  		}

Do we need to check for matching DBELL_TID and mport destID here
and scan only doorbell list attached to the right port? Otherwise this
may call service routine associated with doorbell on a wrong port.

> -		if (found) {
> -			dbell->dinb(port, dbell->dev_id,
> -					DBELL_SID(dmsg),
> -					DBELL_TID(dmsg),
DBELL_INF(dmsg));
> -		} else {
> +
> +		if (!found) {
>  			pr_debug
>  				("RIO: spurious doorbell,"
>  				" sid %2.2x tid %2.2x info %4.4x\n",
>  				DBELL_SID(dmsg), DBELL_TID(dmsg),
>  				DBELL_INF(dmsg));
>  		}
> -		setbits32(&rmu->msg_regs->dmr, DOORBELL_DMR_DI);
> -		out_be32(&rmu->msg_regs->dsr, DOORBELL_DSR_DIQI);
> +		setbits32(&fsl_dbell->dbell_regs->dmr, DOORBELL_DMR_DI);
> +		out_be32(&fsl_dbell->dbell_regs->dsr,
DOORBELL_DSR_DIQI);
>  	}
>=20
>  out:
>  	return IRQ_HANDLED;
>  }
>=20
... skip ...

> @@ -1114,50 +1104,48 @@ int fsl_rio_setup_rmu(struct rio_mport *mport,
> struct device_node *node)
>  {
>  	struct rio_priv *priv;
>  	struct fsl_rmu *rmu;
> -	struct rio_ops *ops;
> +	u64 msg_start;
> +	const u32 *msg_addr;
> +	int mlen;
> +	int aw;
>=20
> -	if (!mport || !mport->priv || !node)
> -		return -1;
> +	if (!mport || !mport->priv)
> +		return -EFAULT;
EINVAL may be better here?

> +
> +	priv =3D mport->priv;
> +
> +	if (!node) {
> +		dev_warn(priv->dev, "Can't get %s property 'fsl,rmu'\n",
> +			priv->dev->of_node->full_name);
> +		return -EFAULT;
EINVAL as well?

> +	}

Regards,

Alex.

^ permalink raw reply

* RE: [PATCH] powerpc/85xx: Setup secondary cores PIR with hard SMP id
From: Bhushan Bharat-R65777 @ 2011-10-20  3:53 UTC (permalink / raw)
  To: Kumar Gala, linuxppc-dev@ozlabs.org
In-Reply-To: <1318578771-16865-1-git-send-email-galak@kernel.crashing.org>



> -----Original Message-----
> From: linuxppc-dev-bounces+bharat.bhushan=3Dfreescale.com@lists.ozlabs.or=
g
> [mailto:linuxppc-dev-
> bounces+bharat.bhushan=3Dfreescale.com@lists.ozlabs.org] On Behalf Of Kum=
ar
> Gala
> Sent: Friday, October 14, 2011 1:23 PM
> To: linuxppc-dev@ozlabs.org
> Subject: [PATCH] powerpc/85xx: Setup secondary cores PIR with hard SMP id
>=20
> Normally logical and hard cpu ID are the same, however in same cases like
> on the P3060 they may differ.  Where the logical is 0..5, the hard id
> goes 0,1,4..7.  This can causes issues for places we utilize PIR to index
> into array like in debug exception handlers for finding the exception
> stack.

Kumar, What should be the CONFIG_NR_CPUS for this? 8 or 6 ?

Thanks
-Bharat

>=20
> Move to setting up PIR with hard_smp_processor_id fixes the issue.
>=20
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  arch/powerpc/platforms/85xx/smp.c |    9 +++++----
>  1 files changed, 5 insertions(+), 4 deletions(-)
>=20
> diff --git a/arch/powerpc/platforms/85xx/smp.c
> b/arch/powerpc/platforms/85xx/smp.c
> index d6e4746..190d111 100644
> --- a/arch/powerpc/platforms/85xx/smp.c
> +++ b/arch/powerpc/platforms/85xx/smp.c
> @@ -48,10 +48,11 @@ smp_85xx_kick_cpu(int nr)
>  	const u64 *cpu_rel_addr;
>  	__iomem u32 *bptr_vaddr;
>  	struct device_node *np;
> -	int n =3D 0;
> +	int n =3D 0, hw_cpu =3D get_hard_smp_processor_id(nr);
>  	int ioremappable;
>=20
> -	WARN_ON (nr < 0 || nr >=3D NR_CPUS);
> +	WARN_ON(nr < 0 || nr >=3D NR_CPUS);
> +	WARN_ON(hw_cpu < 0 || hw_cpu >=3D NR_CPUS);
>=20
>  	pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
>=20
> @@ -79,7 +80,7 @@ smp_85xx_kick_cpu(int nr)
>=20
>  	local_irq_save(flags);
>=20
> -	out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr);
> +	out_be32(bptr_vaddr + BOOT_ENTRY_PIR, hw_cpu);
>  #ifdef CONFIG_PPC32
>  	out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
>=20
> @@ -88,7 +89,7 @@ smp_85xx_kick_cpu(int nr)
>  				(ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
>=20
>  	/* Wait a bit for the CPU to ack. */
> -	while ((__secondary_hold_acknowledge !=3D nr) && (++n < 1000))
> +	while ((__secondary_hold_acknowledge !=3D hw_cpu) && (++n < 1000))
>  		mdelay(1);
>  #else
>  	smp_generic_kick_cpu(nr);
> --
> 1.7.3.4
>=20
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH] powerpc/85xx: Setup secondary cores PIR with hard SMP id
From: Kumar Gala @ 2011-10-20  4:02 UTC (permalink / raw)
  To: Bhushan Bharat-R65777; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <B8D6CA50DACE9E4AAADE9A4D56FBAAE6244FDF@039-SN1MPN1-005.039d.mgd.msft.net>


On Oct 19, 2011, at 10:53 PM, Bhushan Bharat-R65777 wrote:

> 
> 
>> -----Original Message-----
>> From: linuxppc-dev-bounces+bharat.bhushan=freescale.com@lists.ozlabs.org
>> [mailto:linuxppc-dev-
>> bounces+bharat.bhushan=freescale.com@lists.ozlabs.org] On Behalf Of Kumar
>> Gala
>> Sent: Friday, October 14, 2011 1:23 PM
>> To: linuxppc-dev@ozlabs.org
>> Subject: [PATCH] powerpc/85xx: Setup secondary cores PIR with hard SMP id
>> 
>> Normally logical and hard cpu ID are the same, however in same cases like
>> on the P3060 they may differ.  Where the logical is 0..5, the hard id
>> goes 0,1,4..7.  This can causes issues for places we utilize PIR to index
>> into array like in debug exception handlers for finding the exception
>> stack.
> 
> Kumar, What should be the CONFIG_NR_CPUS for this? 8 or 6 ?

8.

- k

^ permalink raw reply

* RE: [PATCH] powerpc/85xx: Setup secondary cores PIR with hard SMP id
From: Bhushan Bharat-R65777 @ 2011-10-20  5:14 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <C79C8827-F6FE-42E0-8FAF-E62A8FFD6A1F@kernel.crashing.org>



> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]
> Sent: Thursday, October 20, 2011 9:32 AM
> To: Bhushan Bharat-R65777
> Cc: linuxppc-dev@ozlabs.org
> Subject: Re: [PATCH] powerpc/85xx: Setup secondary cores PIR with hard
> SMP id
>=20
>=20
> On Oct 19, 2011, at 10:53 PM, Bhushan Bharat-R65777 wrote:
>=20
> >
> >
> >> -----Original Message-----
> >> From:
> >> linuxppc-dev-bounces+bharat.bhushan=3Dfreescale.com@lists.ozlabs.org
> >> [mailto:linuxppc-dev-
> >> bounces+bharat.bhushan=3Dfreescale.com@lists.ozlabs.org] On Behalf Of
> >> bounces+Kumar
> >> Gala
> >> Sent: Friday, October 14, 2011 1:23 PM
> >> To: linuxppc-dev@ozlabs.org
> >> Subject: [PATCH] powerpc/85xx: Setup secondary cores PIR with hard
> >> SMP id
> >>
> >> Normally logical and hard cpu ID are the same, however in same cases
> >> like on the P3060 they may differ.  Where the logical is 0..5, the
> >> hard id goes 0,1,4..7.  This can causes issues for places we utilize
> >> PIR to index into array like in debug exception handlers for finding
> >> the exception stack.
> >
> > Kumar, What should be the CONFIG_NR_CPUS for this? 8 or 6 ?
>=20
> 8.

Kumar, I am just trying to understand the impact of setting NR_CPUS =3D 8 w=
hile actual cpus are 6 only.

If I understood correctly, cpu_present, cpu_online are logical cpuid bit ma=
p. Also the PACA is allocated for nr_cpu_ids (NR_CPUS) and also indexed by =
logical cpuid. While they have knowledge of physical_cpuid.

So in this case last two entries of PACA will not be used or wasted?
I am not sure I am missing something here?

Thanks
-Bharat

^ permalink raw reply

* [RFC][PATCH 1/2] powerpc/85xx: create dts components to build up an SoC
From: Kumar Gala @ 2011-10-20  7:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: devicetree-discuss

Introduce some common components that we can utilize to build up the
various PQ3/85xx device trees.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 arch/powerpc/boot/dts/fsl/pq3-dma-0.dtsi    |   32 +++++++++++++++++++++++++++
 arch/powerpc/boot/dts/fsl/pq3-duart-0.dtsi  |    8 ++++++
 arch/powerpc/boot/dts/fsl/pq3-duart-1.dtsi  |    8 ++++++
 arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi |   32 +++++++++++++++++++++++++++
 arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi |   32 +++++++++++++++++++++++++++
 arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi |   32 +++++++++++++++++++++++++++
 arch/powerpc/boot/dts/fsl/pq3-i2c-0.dtsi    |    9 +++++++
 arch/powerpc/boot/dts/fsl/pq3-i2c-1.dtsi    |    9 +++++++
 8 files changed, 162 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/fsl/pq3-dma-0.dtsi
 create mode 100644 arch/powerpc/boot/dts/fsl/pq3-duart-0.dtsi
 create mode 100644 arch/powerpc/boot/dts/fsl/pq3-duart-1.dtsi
 create mode 100644 arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi
 create mode 100644 arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi
 create mode 100644 arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi
 create mode 100644 arch/powerpc/boot/dts/fsl/pq3-i2c-0.dtsi
 create mode 100644 arch/powerpc/boot/dts/fsl/pq3-i2c-1.dtsi

diff --git a/arch/powerpc/boot/dts/fsl/pq3-dma-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-dma-0.dtsi
new file mode 100644
index 0000000..60aa877
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/pq3-dma-0.dtsi
@@ -0,0 +1,32 @@
+&dma0 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "fsl,eloplus-dma";
+	reg = <0x21300 0x4>;
+	ranges = <0x0 0x21100 0x200>;
+	cell-index = <0>;
+	dma-channel@0 {
+		compatible = "fsl,eloplus-dma-channel";
+		reg = <0x0 0x80>;
+		cell-index = <0>;
+		interrupts = <20 2 0 0>;
+	};
+	dma-channel@80 {
+		compatible = "fsl,eloplus-dma-channel";
+		reg = <0x80 0x80>;
+		cell-index = <1>;
+		interrupts = <21 2 0 0>;
+	};
+	dma-channel@100 {
+		compatible = "fsl,eloplus-dma-channel";
+		reg = <0x100 0x80>;
+		cell-index = <2>;
+		interrupts = <22 2 0 0>;
+	};
+	dma-channel@180 {
+		compatible = "fsl,eloplus-dma-channel";
+		reg = <0x180 0x80>;
+		cell-index = <3>;
+		interrupts = <23 2 0 0>;
+	};
+};
diff --git a/arch/powerpc/boot/dts/fsl/pq3-duart-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-duart-0.dtsi
new file mode 100644
index 0000000..bac1f0d
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/pq3-duart-0.dtsi
@@ -0,0 +1,8 @@
+&serial0 {
+	cell-index = <0>;
+	device_type = "serial";
+	compatible = "ns16550";
+	reg = <0x4500 0x100>;
+	clock-frequency = <0>;
+	interrupts = <42 2 0 0>;
+};
diff --git a/arch/powerpc/boot/dts/fsl/pq3-duart-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-duart-1.dtsi
new file mode 100644
index 0000000..97bbacb
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/pq3-duart-1.dtsi
@@ -0,0 +1,8 @@
+&serial1 {
+	cell-index = <1>;
+	device_type = "serial";
+	compatible = "ns16550";
+	reg = <0x4600 0x100>;
+	clock-frequency = <0>;
+	interrupts = <42 2 0 0>;
+};
diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi
new file mode 100644
index 0000000..73fff36
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi
@@ -0,0 +1,32 @@
+&mdio0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	compatible = "fsl,etsec2-mdio";
+	reg = <0x24000 0x1000 0xb0030 0x4>;
+};
+
+&enet0 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	device_type = "network";
+	model = "eTSEC";
+	compatible = "fsl,etsec2";
+	fsl,num_rx_queues = <0x8>;
+	fsl,num_tx_queues = <0x8>;
+	fsl,magic-packet;
+	local-mac-address = [ 00 00 00 00 00 00 ];
+
+	queue-group@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb0000 0x1000>;
+		interrupts = <29 2 0 0 30 2 0 0 34 2 0 0>;
+	};
+
+	queue-group@1 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb4000 0x1000>;
+		interrupts = <17 2 0 0 18 2 0 0 24 2 0 0>;
+	};
+};
diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi
new file mode 100644
index 0000000..7ec73c4
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi
@@ -0,0 +1,32 @@
+&mdio1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	compatible = "fsl,etsec2-tbi";
+	reg = <0x25000 0x1000 0xb1030 0x4>;
+};
+
+&enet1 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	device_type = "network";
+	model = "eTSEC";
+	compatible = "fsl,etsec2";
+	fsl,num_rx_queues = <0x8>;
+	fsl,num_tx_queues = <0x8>;
+	fsl,magic-packet;
+	local-mac-address = [ 00 00 00 00 00 00 ];
+
+	queue-group@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb1000 0x1000>;
+		interrupts = <35 2 0 0 36 2 0 0 40 2 0 0>;
+	};
+
+	queue-group@1 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb5000 0x1000>;
+		interrupts = <51 2 0 0 52 2 0 0 67 2 0 0>;
+	};
+};
diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi
new file mode 100644
index 0000000..50a078a
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi
@@ -0,0 +1,32 @@
+&mdio2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	compatible = "fsl,etsec2-tbi";
+	reg = <0x26000 0x1000 0xb1030 0x4>;
+};
+
+&enet2 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	device_type = "network";
+	model = "eTSEC";
+	compatible = "fsl,etsec2";
+	fsl,num_rx_queues = <0x8>;
+	fsl,num_tx_queues = <0x8>;
+	fsl,magic-packet;
+	local-mac-address = [ 00 00 00 00 00 00 ];
+
+	queue-group@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb2000 0x1000>;
+		interrupts = <31 2 0 0 32 2 0 0 33 2 0 0>;
+	};
+
+	queue-group@1 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb6000 0x1000>;
+		interrupts = <25 2 0 0 26 2 0 0 27 2 0 0>;
+	};
+};
diff --git a/arch/powerpc/boot/dts/fsl/pq3-i2c-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-i2c-0.dtsi
new file mode 100644
index 0000000..ef75cca
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/pq3-i2c-0.dtsi
@@ -0,0 +1,9 @@
+&i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	cell-index = <0>;
+	compatible = "fsl-i2c";
+	reg = <0x3000 0x100>;
+	interrupts = <43 2 0 0>;
+	dfsrr;
+};
diff --git a/arch/powerpc/boot/dts/fsl/pq3-i2c-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-i2c-1.dtsi
new file mode 100644
index 0000000..e24043a
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/pq3-i2c-1.dtsi
@@ -0,0 +1,9 @@
+&i2c1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	cell-index = <1>;
+	compatible = "fsl-i2c";
+	reg = <0x3100 0x100>;
+	interrupts = <43 2 0 0>;
+	dfsrr;
+};
-- 
1.7.3.4

^ permalink raw reply related

* [RFC][PATCH 2/2] powerpc/85xx: Introduce a P1020 SoC device tree
From: Kumar Gala @ 2011-10-20  7:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: devicetree-discuss
In-Reply-To: <1319095467-6229-1-git-send-email-galak@kernel.crashing.org>

Create a P1020 SoC dts stub that can be included by a board that
utilizes the P1020 SoC.  The board can amend any board specific
configuration or paramaters (like locaation of CCSRBAR, PCIe
controllers, I2C components, ethernet PHY information, etc.)

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 arch/powerpc/boot/dts/p1020soc.dtsi |  262 +++++++++++++++++++++++++++++++++++
 1 files changed, 262 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/p1020soc.dtsi

diff --git a/arch/powerpc/boot/dts/p1020soc.dtsi b/arch/powerpc/boot/dts/p1020soc.dtsi
new file mode 100644
index 0000000..0abc015
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020soc.dtsi
@@ -0,0 +1,262 @@
+&lbc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	compatible = "fsl,p1020-elbc", "fsl,elbc", "simple-bus";
+	interrupts = <19 2 0 0>;
+};
+
+&pci0 {
+	compatible = "fsl,mpc8548-pcie";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0 255>;
+	clock-frequency = <33333333>;
+	interrupts = <16 2 0 0>;
+
+	pcie@0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <16 2 0 0>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x4 0x1
+			0000 0x0 0x0 0x2 &mpic 0x5 0x1
+			0000 0x0 0x0 0x3 &mpic 0x6 0x1
+			0000 0x0 0x0 0x4 &mpic 0x7 0x1
+			>;
+	};
+
+};
+
+&pci1 {
+	compatible = "fsl,mpc8548-pcie";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0 255>;
+	clock-frequency = <33333333>;
+	interrupts = <16 2 0 0>;
+
+	pcie@0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <16 2 0 0>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x0 0x1
+			0000 0x0 0x0 0x2 &mpic 0x1 0x1
+			0000 0x0 0x0 0x3 &mpic 0x2 0x1
+			0000 0x0 0x0 0x4 &mpic 0x3 0x1
+			>;
+	};
+};
+
+
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	device_type = "soc";
+	compatible = "fsl,p1020-immr", "simple-bus";
+	bus-frequency = <0>;		// Filled out by uboot.
+
+	ecm-law@0 {
+		compatible = "fsl,ecm-law";
+		reg = <0x0 0x1000>;
+		fsl,num-laws = <12>;
+	};
+
+	ecm@1000 {
+		compatible = "fsl,p1020-ecm", "fsl,ecm";
+		reg = <0x1000 0x1000>;
+		interrupts = <16 2 0 0>;
+	};
+
+	memory-controller@2000 {
+		compatible = "fsl,p1020-memory-controller";
+		reg = <0x2000 0x1000>;
+		interrupts = <16 2 0 0>;
+	};
+
+	i2c0: i2c@3000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cell-index = <0>;
+		compatible = "fsl-i2c";
+		reg = <0x3000 0x100>;
+		interrupts = <43 2 0 0>;
+		dfsrr;
+	};
+
+	i2c1: i2c@3100 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cell-index = <1>;
+		compatible = "fsl-i2c";
+		reg = <0x3100 0x100>;
+		interrupts = <43 2 0 0>;
+		dfsrr;
+	};
+
+	serial0: serial@4500 {
+	};
+
+	serial1: serial@4600 {
+	};
+
+	spi@7000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,p1020-espi", "fsl,mpc8536-espi";
+		reg = <0x7000 0x1000>;
+		interrupts = <59 0x2 0 0>;
+		fsl,espi-num-chipselects = <4>;
+	};
+
+	gpio: gpio-controller@f000 {
+		#gpio-cells = <2>;
+		compatible = "fsl,mpc8572-gpio";
+		reg = <0xf000 0x100>;
+		interrupts = <47 0x2 0 0>;
+		gpio-controller;
+	};
+
+	L2: l2-cache-controller@20000 {
+		compatible = "fsl,p1020-l2-cache-controller";
+		reg = <0x20000 0x1000>;
+		cache-line-size = <32>;	// 32 bytes
+		cache-size = <0x40000>; // L2,256K
+		interrupts = <16 2 0 0>;
+	};
+
+	dma0: dma@21300 {
+	};
+
+	mdio0: mdio@24000 {
+	};
+
+	mdio1: mdio@25000 {
+	};
+
+	mdio2: mdio@26000 {
+	};
+
+	enet0: ethernet@b0000 {
+	};
+
+	enet1: ethernet@b1000 {
+	};
+
+	enet2: ethernet@b2000 {
+	};
+
+	usb@22000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl-usb2-dr";
+		reg = <0x22000 0x1000>;
+		interrupts = <28 0x2 0 0>;
+	};
+
+	/* USB2 is shared with localbus, so it must be disabled
+	   by default. We can't put 'status = "disabled";' here
+	   since U-Boot doesn't clear the status property when
+	   it enables USB2. OTOH, U-Boot does create a new node
+	   when there isn't any. So, just comment it out.
+	usb@23000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl-usb2-dr";
+		reg = <0x23000 0x1000>;
+		interrupts = <46 0x2 0 0>;
+		phy_type = "ulpi";
+	};
+	*/
+
+	sdhci@2e000 {
+		compatible = "fsl,p1020-esdhc", "fsl,esdhc";
+		reg = <0x2e000 0x1000>;
+		interrupts = <72 0x2 0 0>;
+		/* Filled in by U-Boot */
+		clock-frequency = <0>;
+	};
+
+	crypto@30000 {
+		compatible = "fsl,sec3.3", "fsl,sec3.1", "fsl,sec3.0",
+			     "fsl,sec2.4", "fsl,sec2.2", "fsl,sec2.1",
+			     "fsl,sec2.0";
+		reg = <0x30000 0x10000>;
+		interrupts = <45 2 0 0 58 2 0 0>;
+		fsl,num-channels = <4>;
+		fsl,channel-fifo-len = <24>;
+		fsl,exec-units-mask = <0x97c>;
+		fsl,descriptor-types-mask = <0x3a30abf>;
+	};
+
+	mpic: pic@40000 {
+		interrupt-controller;
+		#address-cells = <0>;
+		#interrupt-cells = <4>;
+		reg = <0x40000 0x40000>;
+		compatible = "chrp,open-pic";
+		device_type = "open-pic";
+	};
+
+	timer@41100 {
+		compatible = "fsl,mpic-global-timer";
+		reg = <0x41100 0x100 0x41300 4>;
+		interrupts = <0 0 3 0
+			      1 0 3 0
+			      2 0 3 0
+			      3 0 3 0>;
+	};
+
+	timer@42100 {
+		compatible = "fsl,mpic-global-timer";
+		reg = <0x42100 0x100 0x42300 4>;
+		interrupts = <4 0 3 0
+			      5 0 3 0
+			      6 0 3 0
+			      7 0 3 0>;
+	};
+
+	msi@41600 {
+		compatible = "fsl,p1020-msi", "fsl,mpic-msi";
+		reg = <0x41600 0x80>;
+		msi-available-ranges = <0 0x100>;
+		interrupts = <
+			0xe0 0 0 0
+			0xe1 0 0 0
+			0xe2 0 0 0
+			0xe3 0 0 0
+			0xe4 0 0 0
+			0xe5 0 0 0
+			0xe6 0 0 0
+			0xe7 0 0 0>;
+	};
+
+	global-utilities@e0000 {	//global utilities block
+		compatible = "fsl,p1020-guts","fsl,p2020-guts";
+		reg = <0xe0000 0x1000>;
+		fsl,has-rstcr;
+	};
+};
+
+/include/ "fsl/pq3-dma-0.dtsi"
+/include/ "fsl/pq3-duart-0.dtsi"
+/include/ "fsl/pq3-duart-1.dtsi"
+/include/ "fsl/pq3-etsec2-0.dtsi"
+/include/ "fsl/pq3-etsec2-1.dtsi"
+/include/ "fsl/pq3-etsec2-2.dtsi"
+/include/ "fsl/pq3-i2c-0.dtsi"
+/include/ "fsl/pq3-i2c-1.dtsi"
-- 
1.7.3.4

^ permalink raw reply related

* Re: [PATCH v15 01/10] USB/ppc4xx: Add Synopsys DesignWare HS USB OTG Register definitions
From: Pratyush Anand @ 2011-10-20  8:42 UTC (permalink / raw)
  To: tmarri; +Cc: Mark Miesfeld, greg, linux-usb, linuxppc-dev, Fushen Chen
In-Reply-To: <1318630119-14165-1-git-send-email-tmarri@apm.com>

On Sat, Oct 15, 2011 at 3:38 AM,  <tmarri@apm.com> wrote:
> From: Tirumala Marri <tmarri@apm.com>
>
[...]

> +/*
> + * These Macros represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
> + * GNPTXFSIZ, DPTXFSIZn). Read the register into the u32 element then
> + * read out the bits using the bit elements.
> + */
> +#define DWC_RX_FIFO_DEPTH_RD(reg)      (((reg) & ((u32)0xffff << 16)) >> 16)
> +#define DWC_RX_FIFO_DEPTH_WR(reg, x)   \
> +       (((reg) & (~((u32)0xffff << 16))) | ((x) << 16))
> +#define DWC_RX_FIFO_START_ADDR_RD(reg)         ((reg) & 0xffff)
> +#define DWC_RX_FIFO_START_ADDR_WR(reg, x)      \
> +       (((reg) & (~((u32)0xffff))) | (x))
> +

These are GNPTX  and DPTX registers.
So name should be DWC_TX_FIFO_DEPTH_RD rather than DWC_RX_FIFO_DEPTH_RD.
Same for other defines.


> +/*
> + * These Macros represents the bit fields in the Non-Periodic Tx FIFO/Queue
> +

[...]

> +#define MAX_PERIO_FIFOS                        15      /* Max periodic FIFOs */
> +#define MAX_TX_FIFOS                   15      /* Max non-periodic FIFOs */
> +
> +/* Maximum number of Endpoints/HostChannels */
> +#define MAX_EPS_CHANNELS 12    /* This come from device tree or defconfig */

There could be some platform even with 16 channels (as specs permits it.)
So, please make it 16.

^ permalink raw reply

* Re: [PATCH v14 03/10] USB/ppc4xx: Add Synopsys DWC OTG Core Interface Layer (CIL)
From: Pratyush Anand @ 2011-10-20  9:12 UTC (permalink / raw)
  To: tmarri; +Cc: Mark Miesfeld, greg, linux-usb, linuxppc-dev, Fushen Chen
In-Reply-To: <1317954637-11802-1-git-send-email-tmarri@apm.com>

On Fri, Oct 7, 2011 at 8:00 AM,  <tmarri@apm.com> wrote:
> From: Tirumala Marri <tmarri@apm.com>
>

[...]

> + * Do core a soft reset of the core.  Be careful with this because it
> + * resets all the internal state machines of the core.
> + */
> +static void dwc_otg_core_reset(struct core_if *core_if)
> +{
> +       ulong global_regs = core_if->core_global_regs;
> +       u32 greset = 0;
> +       int count = 0;
> +
> +       /* Wait for AHB master IDLE state. */
> +       do {
> +               udelay(10);
> +               greset = dwc_reg_read(global_regs, DWC_GRSTCTL);
> +               if (++count > 100000) {
> +                       pr_warning("%s() HANG! AHB Idle GRSTCTL=%0x\n",
> +                                  __func__, greset);
> +                       return;
> +               }
> +       } while (greset & DWC_RSTCTL_AHB_IDLE);

As per sepcs:
Bit 31:  AHB Master Idle (AHBIdle): Indicates that the AHB Master State
Machine is in the IDLE condition.
So when this bit is 1 , AHB would be idle. So, what do you want here?
If AHB is idle, control wil return from above loop rather going ahead to execute
this function.

> +
> +       /* Core Soft Reset */
> +       count = 0;
> +       greset |= DWC_RSTCTL_SFT_RST;

[...]

> +       /* Rx FIFO */
> +       dwc_reg_write(regs, DWC_GRXFSIZ, params->dev_rx_fifo_size);
> +
> +       /* Set Periodic and Non-periodic Tx FIFO Mask bits to all 0 */
> +       core_if->p_tx_msk = 0;
> +       core_if->tx_msk = 0;
> +
> +       if (core_if->en_multiple_tx_fifo == 0) {
> +               /* Non-periodic Tx FIFO */
> +               nptxsize = DWC_RX_FIFO_DEPTH_WR(nptxsize,
> +                                               params->
> +                                               dev_nperio_tx_fifo_size);

So, if you will follow the commnet of patch 01 then , here two you will have to
rename as TX_FIFO.
Also, at all other occurances.

> +               nptxsize =
> +                   DWC_RX_FIFO_START_ADDR_WR(nptxsize,
> +                                             params->dev_rx_fifo_size);
> +               dwc_reg_write(regs, DWC_GNPTXFSIZ, nptxsize);
> +
> +               ptxsize = DWC_RX_FIFO_START_ADDR_WR(ptxsize,
> +                                                   (DWC_RX_FIFO_START_ADDR_RD
> +                                                    (nptxsize) +
> +                                                    DWC_RX_FIFO_DEPTH_RD
> +                                                    (nptxsize)));
> +               for (i = 0;
> +                    i < DWC_HWCFG4_NUM_DEV_PERIO_IN_EP_RD(core_if->hwcfg4);
> +                    i++) {


Reading hwcfg4 will give you maximum nuber of fifos provided by hardware.
But, a particular application (platform) may not need all those fifo. Since, you
have a vriable fifo_num in your param list, so why not use that?

> +                       ptxsize =
> +                           DWC_RX_FIFO_DEPTH_WR(ptxsize,
> +                                                params->
> +                                                dev_perio_tx_fifo_size[i]);
> +                       dwc_reg_write(regs, DWC_DPTX_FSIZ_DIPTXF(i), ptxsize);
> +                       ptxsize = DWC_RX_FIFO_START_ADDR_WR(ptxsize,
> +                                                  (DWC_RX_FIFO_START_ADDR_RD
> +                                                   (ptxsize) +
> +                                                   DWC_RX_FIFO_DEPTH_RD
> +                                                   (ptxsize)));
> +               }
> +       } else {
> +               nptxsize = DWC_RX_FIFO_DEPTH_WR(nptxsize,
> +                                               params->
> +                                               dev_nperio_tx_fifo_size);
> +               nptxsize =
> +                   DWC_RX_FIFO_START_ADDR_WR(nptxsize,
> +                                             params->dev_rx_fifo_size);
> +               dwc_reg_write(regs, DWC_GNPTXFSIZ, nptxsize);
> +
> +               txsize = DWC_RX_FIFO_START_ADDR_WR(txsize,
> +                                                  (DWC_RX_FIFO_START_ADDR_RD
> +                                                   (nptxsize) +
> +                                                   DWC_RX_FIFO_DEPTH_RD
> +                                                   (nptxsize)));
> +               for (i = 1;
> +                    i < DWC_HWCFG4_NUM_DEV_PERIO_IN_EP_RD(core_if->hwcfg4);
> +                    i++) {

Same as above

> +                       txsize =
> +                           DWC_RX_FIFO_DEPTH_WR(txsize,
> +                                                params->dev_tx_fifo_size[i]);
> +                       dwc_reg_write(regs, DWC_DPTX_FSIZ_DIPTXF(i - 1), txsize);
> +                       txsize = DWC_RX_FIFO_START_ADDR_WR(txsize,
> +                                                  (DWC_RX_FIFO_START_ADDR_RD
> +                                                   (txsize) +
> +                                                   DWC_RX_FIFO_DEPTH_RD
> +                                                   (txsize)));
> +               }
> +       }
> +}
> +

Regards
Pratyush

^ permalink raw reply

* Re: [PATCH v15 04/10] USB/ppc4xx: Add Synopsys DWC OTG HCD function
From: Pratyush Anand @ 2011-10-20  9:13 UTC (permalink / raw)
  To: tmarri; +Cc: Mark Miesfeld, greg, linux-usb, linuxppc-dev, Fushen Chen
In-Reply-To: <1318630133-14264-1-git-send-email-tmarri@apm.com>

On Sat, Oct 15, 2011 at 3:38 AM,  <tmarri@apm.com> wrote:
> From: Tirumala Marri <tmarri@apm.com>
>

[...]

Everything fine in this patch, except the defines of TX
regs(DWC_RX_FIFO_DEPTH_WR) has been
kept with RX.

Regards
Pratyush

^ permalink raw reply

* Re: [PATCH v15 05/10] USB/ppc4xx: Add Synopsys DWC OTG HCD interrupt function
From: Pratyush Anand @ 2011-10-20  9:25 UTC (permalink / raw)
  To: tmarri; +Cc: Mark Miesfeld, greg, linux-usb, linuxppc-dev, Fushen Chen
In-Reply-To: <1318630139-14296-1-git-send-email-tmarri@apm.com>

On Sat, Oct 15, 2011 at 3:38 AM,  <tmarri@apm.com> wrote:
> From: Tirumala Marri <tmarri@apm.com>
>
> Implements DWC OTG USB HCD interrupt service routine.
>
> Signed-off-by: Tirumala R Marri <tmarri@apm.com>
> Signed-off-by: Fushen Chen <fchen@apm.com>
> Signed-off-by: Mark Miesfeld <mmiesfeld@apm.com>
> ---
> =A0drivers/usb/dwc/hcd_intr.c | 1477 ++++++++++++++++++++++++++++++++++++=
++++++++
> =A01 files changed, 1477 insertions(+), 0 deletions(-)
> =A0create mode 100644 drivers/usb/dwc/hcd_intr.c
>
> diff --git a/drivers/usb/dwc/hcd_intr.c b/drivers/usb/dwc/hcd_intr.c
> new file mode 100644
> index 0000000..b16934d
> --- /dev/null
> +++ b/drivers/usb/dwc/hcd_intr.c
> @@ -0,0 +1,1477 @@
> +/*
> + * DesignWare HS OTG controller driver
> + * Copyright (C) 2006 Synopsys, Inc.
> + * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
> + *
> + * This program is free software: you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License version 2 for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see http://www.gnu.org/licenses
> + * or write to the Free Software Foundation, Inc., 51 Franklin Street,
> + * Suite 500, Boston, MA 02110-1335 USA.
> + *
> + * Based on Synopsys driver version 2.60a
> + * Modified by Mark Miesfeld <mmiesfeld@apm.com>
> + * Modified by Stefan Roese <sr@denx.de>, DENX Software Engineering
> + * Modified by Chuck Meade <chuck@theptrgroup.com>
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "=
AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO T=
HE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PU=
RPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. BE LIABLE FOR ANY DI=
RECT,
> + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SER=
VICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUS=
ED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR =
TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE=
 OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + *
> + */
> +
> +#include "hcd.h"
> +
> +/* This file contains the implementation of the HCD Interrupt handlers. =
=A0 =A0 =A0 =A0*/
> +static const int erratum_usb09_patched;
> +static const int deferral_on =3D 1;
> +static const int nak_deferral_delay =3D 8;
> +static const int nyet_deferral_delay =3D 1;
> +
> +/**
> + * Handles the start-of-frame interrupt in host mode. Non-periodic
> + * transactions may be queued to the DWC_otg controller for the current
> + * (micro)frame. Periodic transactions may be queued to the controller f=
or the
> + * next (micro)frame.
> + */
> +static int dwc_otg_hcd_handle_sof_intr(struct dwc_hcd *hcd)
> +{
> + =A0 =A0 =A0 u32 hfnum =3D 0;
> + =A0 =A0 =A0 struct list_head *qh_entry;
> + =A0 =A0 =A0 struct dwc_qh *qh;
> + =A0 =A0 =A0 enum dwc_transaction_type tr_type;
> + =A0 =A0 =A0 u32 gintsts =3D 0;
> +
> + =A0 =A0 =A0 hfnum =3D
> + =A0 =A0 =A0 =A0 =A0 dwc_reg_read(hcd->core_if->host_if->host_global_reg=
s,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0DWC_HFNUM);
> +
> + =A0 =A0 =A0 hcd->frame_number =3D DWC_HFNUM_FRNUM_RD(hfnum);
> +
> + =A0 =A0 =A0 /* Determine whether any periodic QHs should be executed. *=
/
> + =A0 =A0 =A0 qh_entry =3D hcd->periodic_sched_inactive.next;
> + =A0 =A0 =A0 while (qh_entry !=3D &hcd->periodic_sched_inactive) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qh =3D list_entry(qh_entry, struct dwc_qh, =
qh_list_entry);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qh_entry =3D qh_entry->next;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* If needed, move QH to the ready list t=
o be executed next
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* (micro)frame.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (dwc_frame_num_le(qh->sched_frame, hcd->=
frame_number))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 list_move(&qh->qh_list_entr=
y,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 &hcd->p=
eriodic_sched_ready);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 tr_type =3D dwc_otg_hcd_select_transactions(hcd);
> + =A0 =A0 =A0 if (tr_type !=3D DWC_OTG_TRANSACTION_NONE)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_queue_transactions(hcd, tr_type=
);
> +
> + =A0 =A0 =A0 /* Clear interrupt */
> + =A0 =A0 =A0 gintsts |=3D DWC_INTMSK_STRT_OF_FRM;
> + =A0 =A0 =A0 dwc_reg_write(gintsts_reg(hcd), 0, gintsts);
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * Handles the Rx Status Queue Level Interrupt, which indicates that the=
re is at
> + * least one packet in the Rx FIFO. =A0The packets are moved from the FI=
FO to
> + * memory if the DWC_otg controller is operating in Slave mode.
> + */
> +static int dwc_otg_hcd_handle_rx_status_q_level_intr(struct dwc_hcd *hcd=
)
> +{
> + =A0 =A0 =A0 u32 grxsts;
> + =A0 =A0 =A0 struct dwc_hc *hc;
> +
> + =A0 =A0 =A0 grxsts =3D dwc_reg_read(hcd->core_if->core_global_regs, DWC=
_GRXSTSP);
> + =A0 =A0 =A0 hc =3D hcd->hc_ptr_array[grxsts & DWC_HM_RXSTS_CHAN_NUM_RD(=
grxsts)];
> +
> + =A0 =A0 =A0 /* Packet Status */
> + =A0 =A0 =A0 switch (DWC_HM_RXSTS_PKT_STS_RD(grxsts)) {
> + =A0 =A0 =A0 case DWC_GRXSTS_PKTSTS_IN:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Read the data into the host buffer. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (DWC_HM_RXSTS_BYTE_CNT_RD(grxsts) > 0) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_read_packet(hcd->co=
re_if, hc->xfer_buff,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 DWC_HM_RXSTS_BYTE_CNT_RD(grxsts));
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Update the HC fields for=
 the next packet received. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hc->xfer_count +=3D DWC_HM_=
RXSTS_BYTE_CNT_RD(grxsts);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hc->xfer_buff +=3D DWC_HM_R=
XSTS_BYTE_CNT_RD(grxsts);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
> + =A0 =A0 =A0 case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
> + =A0 =A0 =A0 case DWC_GRXSTS_PKTSTS_CH_HALTED:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Handled in interrupt, just ignore data *=
/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 default:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("RX_STS_Q Interrupt: Unknown status =
%d\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0DWC_HM_RXSTS_PKT_STS_RD(grxs=
ts));
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * This interrupt occurs when the non-periodic Tx FIFO is half-empty. Mo=
re
> + * data packets may be written to the FIFO for OUT transfers. More reque=
sts
> + * may be written to the non-periodic request queue for IN transfers. Th=
is
> + * interrupt is enabled only in Slave mode.
> + */
> +static int dwc_otg_hcd_handle_np_tx_fifo_empty_intr(struct dwc_hcd *hcd)
> +{
> + =A0 =A0 =A0 dwc_otg_hcd_queue_transactions(hcd, DWC_OTG_TRANSACTION_NON=
_PERIODIC);
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * This interrupt occurs when the periodic Tx FIFO is half-empty. More d=
ata
> + * packets may be written to the FIFO for OUT transfers. More requests m=
ay be
> + * written to the periodic request queue for IN transfers. This interrup=
t is
> + * enabled only in Slave mode.
> + */
> +static int dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(struct dwc_hcd *h=
cd)
> +{
> + =A0 =A0 =A0 dwc_otg_hcd_queue_transactions(hcd, DWC_OTG_TRANSACTION_PER=
IODIC);
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * When the port changes to enabled it may be necessary to adjust the ph=
y clock
> + * speed.
> + */
> +static int adjusted_phy_clock_speed(struct dwc_hcd *hcd, u32 hprt0)
> +{
> + =A0 =A0 =A0 int adjusted =3D 0;
> + =A0 =A0 =A0 u32 usbcfg;
> + =A0 =A0 =A0 ulong global_regs =3D hcd->core_if->core_global_regs;
> + =A0 =A0 =A0 struct core_params *params =3D hcd->core_if->core_params;
> + =A0 =A0 =A0 ulong h_regs =3D hcd->core_if->host_if->host_global_regs;
> +
> + =A0 =A0 =A0 usbcfg =3D dwc_reg_read(global_regs, DWC_GUSBCFG);
> +
> + =A0 =A0 =A0 if (DWC_HPRT0_PRT_SPD_RD(hprt0) =3D=3D DWC_HPRT0_PRTSPD_LOW=
_SPEED ||
> + =A0 =A0 =A0 =A0 =A0 DWC_HPRT0_PRT_SPD_RD(hprt0) =3D=3D DWC_HPRT0_PRTSPD=
_FULL_SPEED) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Low power */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 u32 hcfg;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(usbcfg & DWC_USBCFG_PHYLPWRCLKSEL)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Set PHY low power clock =
select for FS/LS devices */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 usbcfg |=3D DWC_USBCFG_PHYL=
PWRCLKSEL;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_reg_write(global_regs, =
DWC_GUSBCFG, usbcfg);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 adjusted =3D 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hcfg =3D dwc_reg_read(h_regs, DWC_HCFG);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (DWC_HPRT0_PRT_SPD_RD(hprt0) =3D=3D DWC_=
HPRT0_PRTSPD_LOW_SPEED &&
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 params->host_ls_low_power_phy_clk =
=3D=3D
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM=
_6MHZ) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* 6 MHZ, check for 6 MHZ c=
lock select */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (DWC_HCFG_FSLSP_CLK_RD(h=
cfg) !=3D DWC_HCFG_6_MHZ) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hcfg =3D DW=
C_HCFG_FSLSP_CLK_RW(hcfg,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0DWC_HCFG_6_MHZ);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_reg_wri=
te(h_regs, DWC_HCFG, hcfg);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 adjusted =
=3D 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else if (DWC_HCFG_FSLSP_CLK_RD(hcfg) !=3D=
 DWC_HCFG_48_MHZ) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* 48 MHZ and clock select =
is not 48 MHZ */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hcfg =3D DWC_HCFG_FSLSP_CLK=
_RW(hcfg, DWC_HCFG_48_MHZ);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_reg_write(h_regs, DWC_H=
CFG, hcfg);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 adjusted =3D 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 } else if (usbcfg & DWC_USBCFG_PHYLPWRCLKSEL) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 usbcfg &=3D ~((u32) DWC_USBCFG_PHYLPWRCLKSE=
L);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_reg_write(global_regs, DWC_GUSBCFG, usb=
cfg);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 adjusted =3D 1;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 if (adjusted)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 schedule_work(&hcd->usb_port_reset);
> +
> + =A0 =A0 =A0 return adjusted;
> +}
> +
> +/**
> + * Helper function to handle the port enable changed interrupt when the =
port
> + * becomes enabled. =A0Checks if we need to adjust the PHY clock speed f=
or low
> + * power and =A0adjusts it if needed.
> + */
> +static void port_enabled(struct dwc_hcd *hcd, u32 hprt0)
> +{
> + =A0 =A0 =A0 if (hcd->core_if->core_params->host_support_fs_ls_low_power=
)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!adjusted_phy_clock_speed(hcd, hprt0))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hcd->flags.b.port_reset_cha=
nge =3D 1;
> +}
> +
> +/**
> + * There are multiple conditions that can cause a port interrupt. This f=
unction
> + * determines which interrupt conditions have occurred and handles them
> + * appropriately.
> + */
> +static int dwc_otg_hcd_handle_port_intr(struct dwc_hcd *hcd)
> +{
> + =A0 =A0 =A0 int retval =3D 0;
> + =A0 =A0 =A0 u32 hprt0;
> + =A0 =A0 =A0 u32 hprt0_modify;
> +
> + =A0 =A0 =A0 hprt0 =3D dwc_reg_read(hcd->core_if->host_if->hprt0, 0);
> + =A0 =A0 =A0 hprt0_modify =3D dwc_reg_read(hcd->core_if->host_if->hprt0,=
 0);
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Clear appropriate bits in HPRT0 to clear the interrupt=
 bit in
> + =A0 =A0 =A0 =A0* GINTSTS
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 hprt0_modify =3D DWC_HPRT0_PRT_ENA_RW(hprt0_modify, 0);
> + =A0 =A0 =A0 hprt0_modify =3D DWC_HPRT0_PRT_CONN_DET_RW(hprt0_modify, 0)=
;
> + =A0 =A0 =A0 hprt0_modify =3D DWC_HPRT0_PRT_ENA_DIS_CHG_RW(hprt0_modify,=
 0);
> + =A0 =A0 =A0 hprt0_modify =3D DWC_HPRT0_PRT_OVRCURR_CHG_RW(hprt0_modify,=
 0);
> +
> + =A0 =A0 =A0 /* Port connect detected interrupt */
> + =A0 =A0 =A0 if (DWC_HPRT0_PRT_CONN_DET_RD(hprt0)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Set the status flags and clear interrupt=
 */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hcd->flags.b.port_connect_status_change =3D=
 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hcd->flags.b.port_connect_status =3D 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hprt0_modify =3D DWC_HPRT0_PRT_CONN_DET_RW(=
hprt0_modify, 1);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* B-Device has connected, Delete the conne=
ction timer. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 del_timer_sync(&hcd->conn_timer);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* The Hub driver asserts a reset when it=
 sees port connect
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* status change flag
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D 1;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Port enable changed interrupt */
> + =A0 =A0 =A0 if (DWC_HPRT0_PRT_ENA_DIS_CHG_RD(hprt0)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Set the internal flag if the port was di=
sabled */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (DWC_HPRT0_PRT_ENA_RD(hprt0))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 port_enabled(hcd, hprt0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hcd->flags.b.port_enable_ch=
ange =3D 1;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Clear the interrupt */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hprt0_modify =3D DWC_HPRT0_PRT_ENA_DIS_CHG_=
RW(hprt0_modify, 1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D 1;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Overcurrent change interrupt */
> + =A0 =A0 =A0 if (DWC_HPRT0_PRT_OVRCURR_CHG_RD(hprt0)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hcd->flags.b.port_over_current_change =3D 1=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hprt0_modify =3D DWC_HPRT0_PRT_OVRCURR_CHG_=
RW(hprt0_modify, 1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D 1;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Clear the port interrupts */
> + =A0 =A0 =A0 dwc_reg_write(hcd->core_if->host_if->hprt0, 0, hprt0_modify=
);
> + =A0 =A0 =A0 return retval;
> +}
> +
> +/**
> + * Gets the actual length of a transfer after the transfer halts. halt_s=
tatus
> + * holds the reason for the halt.
> + *
> + * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE, _shor=
t_read
> + * is set to 1 upon return if less than the requested number of bytes we=
re
> + * transferred. Otherwise, _short_read is set to 0 upon return. _short_r=
ead may
> + * also be NULL on entry, in which case it remains unchanged.
> + */
> +static u32 get_actual_xfer_length(struct dwc_hc *hc, ulong regs,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct =
dwc_qtd *qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 enum dw=
c_halt_status halt_status,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 int *_s=
hort_read)
> +{
> + =A0 =A0 =A0 u32 hctsiz =3D 0;
> + =A0 =A0 =A0 u32 length;
> +
> + =A0 =A0 =A0 if (_short_read)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 *_short_read =3D 0;
> +
> + =A0 =A0 =A0 hctsiz =3D dwc_reg_read(regs, DWC_HCTSIZ);
> + =A0 =A0 =A0 if (halt_status =3D=3D DWC_OTG_HC_XFER_COMPLETE) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hc->ep_is_in) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 length =3D hc->xfer_len - D=
WC_HCTSIZ_XFER_SIZE_RD(hctsiz);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (_short_read)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *_short_rea=
d =3D
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (DW=
C_HCTSIZ_XFER_SIZE_RD(hctsiz) !=3D 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else if (hc->qh->do_split) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 length =3D qtd->ssplit_out_=
xfer_count;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 length =3D hc->xfer_len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Must use the hctsiz.pktcnt field to de=
termine how much data
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* has been transferred. This field refle=
cts the number of
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* packets that have been transferred via=
 the USB. This is
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* always an integral number of packets i=
f the transfer was
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* halted before its normal completion. (=
Can't use the
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* hctsiz.xfersize field because that ref=
lects the number of
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* bytes transferred via the AHB, not the=
 USB).
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 length =3D (hc->start_pkt_count - DWC_HCTSI=
Z_PKT_CNT_RD(hctsiz)) *
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hc->max_packet;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 return length;
> +}
> +
> +/**
> + * Updates the state of the URB after a Transfer Complete interrupt on t=
he
> + * host channel. Updates the actual_length field of the URB based on the
> + * number of bytes transferred via the host channel. Sets the URB status
> + * if the data transfer is finished.
> + */
> +static int update_urb_state_xfer_comp(struct dwc_hc *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 ulong regs, struct urb *urb,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 struct dwc_qtd *qtd, int *status)
> +{
> + =A0 =A0 =A0 int xfer_done =3D 0;
> + =A0 =A0 =A0 int short_read =3D 0;
> +
> + =A0 =A0 =A0 urb->actual_length +=3D get_actual_xfer_length(hc, regs, qt=
d,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0DWC_OTG_HC_XFER_COMPLETE,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&short_read);
> +
> + =A0 =A0 =A0 if (short_read || urb->actual_length =3D=3D urb->transfer_b=
uffer_length) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 xfer_done =3D 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (short_read && (urb->transfer_flags & UR=
B_SHORT_NOT_OK))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *status =3D -EREMOTEIO;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *status =3D 0;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 return xfer_done;
> +}
> +
> +/*
> + * Save the starting data toggle for the next transfer. The data toggle =
is
> + * saved in the QH for non-control transfers and it's saved in the QTD f=
or
> + * control transfers.
> + */
> +static void save_data_toggle(struct dwc_hc *hc, ulong regs, struct dwc_q=
td *qtd)
> +{
> + =A0 =A0 =A0 u32 hctsiz =3D 0;
> + =A0 =A0 =A0 hctsiz =3D dwc_reg_read(regs, DWC_HCTSIZ);
> +
> + =A0 =A0 =A0 if (hc->ep_type !=3D DWC_OTG_EP_TYPE_CONTROL) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct dwc_qh *qh =3D hc->qh;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (DWC_HCTSIZ_PKT_PID_RD(hctsiz) =3D=3D DW=
C_HCTSIZ_DATA0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qh->data_toggle =3D DWC_OTG=
_HC_PID_DATA0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qh->data_toggle =3D DWC_OTG=
_HC_PID_DATA1;
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (DWC_HCTSIZ_PKT_PID_RD(hctsiz) =3D=3D DW=
C_HCTSIZ_DATA0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->data_toggle =3D DWC_OT=
G_HC_PID_DATA0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->data_toggle =3D DWC_OT=
G_HC_PID_DATA1;
> + =A0 =A0 =A0 }
> +}
> +
> +/**
> + * Frees the first QTD in the QH's list if free_qtd is 1. For non-period=
ic
> + * QHs, removes the QH from the active non-periodic schedule. If any QTD=
s are
> + * still linked to the QH, the QH is added to the end of the inactive
> + * non-periodic schedule. For periodic QHs, removes the QH from the peri=
odic
> + * schedule if no more QTDs are linked to the QH.
> + */
> +static void deactivate_qh(struct dwc_hcd *hcd, struct dwc_qh *qh, int fr=
ee_qtd)
> +{
> + =A0 =A0 =A0 int continue_split =3D 0;
> + =A0 =A0 =A0 struct dwc_qtd *qtd;
> +
> + =A0 =A0 =A0 qtd =3D list_entry(qh->qtd_list.next, struct dwc_qtd, qtd_l=
ist_entry);
> + =A0 =A0 =A0 if (qtd->complete_split)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue_split =3D 1;
> + =A0 =A0 =A0 else if (qtd->isoc_split_pos =3D=3D DWC_HCSPLIT_XACTPOS_MID=
 ||
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0qtd->isoc_split_pos =3D=3D DWC_HCSPLIT_X=
ACTPOS_END)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue_split =3D 1;
> +
> + =A0 =A0 =A0 if (free_qtd) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_qtd_remove(qtd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue_split =3D 0;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 qh->channel =3D NULL;
> + =A0 =A0 =A0 qh->qtd_in_process =3D NULL;
> + =A0 =A0 =A0 dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split);
> +}
> +
> +/**
> + * Updates the state of an Isochronous URB when the transfer is stopped =
for
> + * any reason. The fields of the current entry in the frame descriptor a=
rray
> + * are set based on the transfer state and the input status. Completes t=
he
> + * Isochronous URB if all the URB frames have been completed.
> + */
> +static enum dwc_halt_status update_isoc_urb_state(struct dwc_hcd *hcd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 struct dwc_hc *hc, u32 regs,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 struct dwc_qtd *qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 enum dwc_halt_status status)
> +{
> + =A0 =A0 =A0 struct urb *urb =3D qtd->urb;
> + =A0 =A0 =A0 enum dwc_halt_status ret_val =3D status;
> + =A0 =A0 =A0 struct usb_iso_packet_descriptor *frame_desc;
> + =A0 =A0 =A0 frame_desc =3D &urb->iso_frame_desc[qtd->isoc_frame_index];
> +
> + =A0 =A0 =A0 switch (status) {
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_COMPLETE:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 frame_desc->status =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 frame_desc->actual_length =3D
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 get_actual_xfer_length(hc, regs, qt=
d, status, NULL);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_FRAME_OVERRUN:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 urb->error_count++;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hc->ep_is_in)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 frame_desc->status =3D -ENO=
SR;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 frame_desc->status =3D -ECO=
MM;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 frame_desc->actual_length =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_BABBLE_ERR:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Don't need to update actual_length in th=
is case. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 urb->error_count++;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 frame_desc->status =3D -EOVERFLOW;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_XACT_ERR:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 urb->error_count++;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 frame_desc->status =3D -EPROTO;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 frame_desc->actual_length =3D
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 get_actual_xfer_length(hc, regs, qt=
d, status, NULL);
> + =A0 =A0 =A0 default:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("%s: Unhandled halt_status (%d)\n", =
__func__, status);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 BUG();
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 if (++qtd->isoc_frame_index =3D=3D urb->number_of_packets) =
{
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* urb->status is not used for isoc trans=
fers.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* The individual frame_desc statuses are=
 used instead.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_complete_urb(hcd, urb, 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret_val =3D DWC_OTG_HC_XFER_URB_COMPLETE;
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret_val =3D DWC_OTG_HC_XFER_COMPLETE;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 return ret_val;
> +}
> +
> +/**
> + * Releases a host channel for use by other transfers. Attempts to selec=
t and
> + * queue more transactions since at least one host channel is available.
> + */
> +static void release_channel(struct dwc_hcd *hcd, struct dwc_hc *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct dwc_qtd *qtd=
,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 enum dwc_halt_statu=
s halt_status, int *must_free)
> +{
> + =A0 =A0 =A0 enum dwc_transaction_type tr_type;
> + =A0 =A0 =A0 int free_qtd;
> + =A0 =A0 =A0 int deact =3D 1;
> + =A0 =A0 =A0 struct dwc_qh *qh;
> + =A0 =A0 =A0 int retry_delay =3D 1;
> +
> + =A0 =A0 =A0 switch (halt_status) {
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_NYET:
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_NAK:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (halt_status =3D=3D DWC_OTG_HC_XFER_NYET=
)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 retry_delay =3D nyet_deferr=
al_delay;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 retry_delay =3D nak_deferra=
l_delay;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 free_qtd =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (deferral_on && hc->do_split) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qh =3D hc->qh;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (qh)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 deact =3D d=
wc_otg_hcd_qh_deferr(hcd, qh,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 retry_delay);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_URB_COMPLETE:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 free_qtd =3D 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_AHB_ERR:
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_STALL:
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_BABBLE_ERR:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 free_qtd =3D 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_XACT_ERR:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (qtd->error_count >=3D 3) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 free_qtd =3D 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_complete_urb(hc=
d, qtd->urb, -EPROTO);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 free_qtd =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_URB_DEQUEUE:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* The QTD has already been removed and t=
he QH has been
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* deactivated. Don't want to do anything=
 except release the
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* host channel and try to queue more tra=
nsfers.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto cleanup;
> + =A0 =A0 =A0 case DWC_OTG_HC_XFER_NO_HALT_STATUS:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("%s: No halt_status, channel %d\n", =
__func__,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0hc->hc_num);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 free_qtd =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 default:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 free_qtd =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 if (free_qtd)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* must_free pre-initialized to zero */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 *must_free =3D 1;
> + =A0 =A0 =A0 if (deact)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 deactivate_qh(hcd, hc->qh, free_qtd);
> +
> +cleanup:
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Release the host channel for use by other transfers. T=
he cleanup
> + =A0 =A0 =A0 =A0* function clears the channel interrupt enables and cond=
itions, so
> + =A0 =A0 =A0 =A0* there's no need to clear the Channel Halted interrupt =
separately.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 dwc_otg_hc_cleanup(hcd->core_if, hc);
> + =A0 =A0 =A0 list_add_tail(&hc->hc_list_entry, &hcd->free_hc_list);
> + =A0 =A0 =A0 hcd->available_host_channels++;
> + =A0 =A0 =A0 /* Try to queue more transfers now that there's a free chan=
nel. */
> + =A0 =A0 =A0 if (!erratum_usb09_patched) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 tr_type =3D dwc_otg_hcd_select_transactions=
(hcd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (tr_type !=3D DWC_OTG_TRANSACTION_NONE)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_queue_transacti=
ons(hcd, tr_type);
> + =A0 =A0 =A0 }
> +}
> +
> +/**
> + * Halts a host channel. If the channel cannot be halted immediately bec=
ause
> + * the request queue is full, this function ensures that the FIFO empty
> + * interrupt for the appropriate queue is enabled so that the halt reque=
st can
> + * be queued when there is space in the request queue.
> + *
> + * This function may also be called in DMA mode. In that case, the chann=
el is
> + * simply released since the core always halts the channel automatically=
 in
> + * DMA mode.
> + */
> +static void halt_channel(struct dwc_hcd *hcd, struct dwc_hc *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct dwc_qtd *qtd, enu=
m dwc_halt_status halt_status,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int *must_free)
> +{
> + =A0 =A0 =A0 if (hcd->core_if->dma_enable) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 release_channel(hcd, hc, qtd, halt_status, =
must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Slave mode processing... */
> + =A0 =A0 =A0 dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
> + =A0 =A0 =A0 if (hc->halt_on_queue) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 u32 gintmsk =3D 0;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hc->ep_type =3D=3D DWC_OTG_EP_TYPE_CONT=
ROL ||
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hc->ep_type =3D=3D DWC_OTG_EP_TYPE_=
BULK) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Make sure the Non-peri=
odic Tx FIFO empty interrupt
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* is enabled so that the=
 non-periodic schedule will
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* be processed.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gintmsk |=3D DWC_INTMSK_NP_=
TXFIFO_EMPT;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_reg_modify(gintmsk_reg(=
hcd), 0, 0, gintmsk);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Move the QH from the p=
eriodic queued schedule to
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* the periodic assigned =
schedule. This allows the
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* halt to be queued when=
 the periodic schedule is
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* processed.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 list_move(&hc->qh->qh_list_=
entry,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 &hcd->p=
eriodic_sched_assigned);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Make sure the Periodic=
 Tx FIFO Empty interrupt is
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* enabled so that the pe=
riodic schedule will be
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* processed.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gintmsk |=3D DWC_INTMSK_P_T=
XFIFO_EMPTY;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_reg_modify(gintmsk_reg(=
hcd), 0, 0, gintmsk);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> +}
> +
> +/**
> + * Performs common cleanup for non-periodic transfers after a Transfer
> + * Complete interrupt. This function should be called after any endpoint=
 type
> + * specific handling is finished to release the host channel.
> + */
> +static void complete_non_periodic_xfer(struct dwc_hcd *hcd, struct dwc_h=
c *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0ulong regs, struct dwc_qtd *qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0enum dwc_halt_status halt_status,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0int *must_free)
> +{
> + =A0 =A0 =A0 u32 hcint;
> +
> + =A0 =A0 =A0 qtd->error_count =3D 0;
> + =A0 =A0 =A0 hcint =3D dwc_reg_read(regs, DWC_HCINT);
> + =A0 =A0 =A0 if (DWC_HCINT_NYET_RESP_REC_RD(hcint)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 u32 hcint_clear =3D 0;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hcint_clear =3D DWC_HCINT_NYET_RESP_REC_RW(=
hcint_clear, 1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Got a NYET on the last transaction of =
the transfer. This
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* means that the endpoint should be in t=
he PING state at the
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* beginning of the next transfer.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hc->qh->ping_state =3D 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_reg_write(regs, DWC_HCINT, hcint_clear)=
;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Always halt and release the host channel to make it av=
ailable for
> + =A0 =A0 =A0 =A0* more transfers. There may still be more phases for a c=
ontrol
> + =A0 =A0 =A0 =A0* transfer or more data packets for a bulk transfer at t=
his point,
> + =A0 =A0 =A0 =A0* but the host channel is still halted. A channel will b=
e reassigned
> + =A0 =A0 =A0 =A0* to the transfer when the non-periodic schedule is proc=
essed after
> + =A0 =A0 =A0 =A0* the channel is released. This allows transactions to b=
e queued
> + =A0 =A0 =A0 =A0* properly via dwc_otg_hcd_queue_transactions, which als=
o enables the
> + =A0 =A0 =A0 =A0* Tx FIFO Empty interrupt if necessary.
> + =A0 =A0 =A0 =A0*
> + =A0 =A0 =A0 =A0* IN transfers in Slave mode require an explicit disable=
 to
> + =A0 =A0 =A0 =A0* halt the channel. (In DMA mode, this call simply relea=
ses
> + =A0 =A0 =A0 =A0* the channel.)
> + =A0 =A0 =A0 =A0*
> + =A0 =A0 =A0 =A0* The channel is automatically disabled by the core for =
OUT
> + =A0 =A0 =A0 =A0* transfers in Slave mode.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (hc->ep_is_in)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, halt_status, mus=
t_free);
> + =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 release_channel(hcd, hc, qtd, halt_status, =
must_free);
> +}
> +
> +/**
> + * Performs common cleanup for periodic transfers after a Transfer Compl=
ete
> + * interrupt. This function should be called after any endpoint type spe=
cific
> + * handling is finished to release the host channel.
> + */
> +static void complete_periodic_xfer(struct dwc_hcd *hcd, struct dwc_hc *h=
c,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ulon=
g regs, struct dwc_qtd *qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0enum=
 dwc_halt_status halt_status,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int =
*must_free)
> +{
> + =A0 =A0 =A0 u32 hctsiz =3D 0;
> +
> + =A0 =A0 =A0 hctsiz =3D dwc_reg_read(regs, DWC_HCTSIZ);
> + =A0 =A0 =A0 qtd->error_count =3D 0;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* For OUT transfers and 0 packet count, the Core halts t=
he channel,
> + =A0 =A0 =A0 =A0* otherwise, Flush any outstanding requests from the Tx =
queue.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (!hc->ep_is_in || (DWC_HCTSIZ_PKT_CNT_RD(hctsiz) =3D=3D =
0))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 release_channel(hcd, hc, qtd, halt_status, =
must_free);
> + =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, halt_status, mus=
t_free);
> +}
> +
> +/**
> + * Handles a host channel Transfer Complete interrupt. This handler may =
be
> + * called in either DMA mode or Slave mode.
> + */
> +static int handle_hc_xfercomp_intr(struct dwc_hcd *hcd, struct dwc_hc *h=
c,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ulon=
g regs, struct dwc_qtd *qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int =
*must_free)
> +{
> + =A0 =A0 =A0 int urb_xfer_done;
> + =A0 =A0 =A0 enum dwc_halt_status halt_status =3D DWC_OTG_HC_XFER_COMPLE=
TE;
> + =A0 =A0 =A0 struct urb *urb =3D qtd->urb;
> + =A0 =A0 =A0 int pipe_type =3D usb_pipetype(urb->pipe);
> + =A0 =A0 =A0 int status =3D -EINPROGRESS;
> + =A0 =A0 =A0 u32 hcintmsk =3D 0;
> +
> + =A0 =A0 =A0 /* Handle xfer complete on CSPLIT. */
> + =A0 =A0 =A0 if (hc->qh->do_split)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->complete_split =3D 0;
> +
> + =A0 =A0 =A0 /* Update the QTD and URB states. */
> + =A0 =A0 =A0 switch (pipe_type) {
> + =A0 =A0 =A0 case PIPE_CONTROL:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 switch (qtd->control_phase) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 case DWC_OTG_CONTROL_SETUP:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (urb->transfer_buffer_le=
ngth > 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->contro=
l_phase =3D DWC_OTG_CONTROL_DATA;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->contro=
l_phase =3D DWC_OTG_CONTROL_STATUS;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_status =3D DWC_OTG_HC_=
XFER_COMPLETE;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 case DWC_OTG_CONTROL_DATA:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 urb_xfer_done =3D update_ur=
b_state_xfer_comp(hc, regs,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0urb, qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&status);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (urb_xfer_done)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->contro=
l_phase =3D DWC_OTG_CONTROL_STATUS;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 save_data_t=
oggle(hc, regs, qtd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_status =3D DWC_OTG_HC_=
XFER_COMPLETE;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 case DWC_OTG_CONTROL_STATUS:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (status =3D=3D -EINPROGR=
ESS)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 status =3D =
0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_complete_urb(hc=
d, urb, status);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_status =3D DWC_OTG_HC_=
XFER_URB_COMPLETE;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 complete_non_periodic_xfer(hcd, hc, regs, q=
td,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0halt_status, must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case PIPE_BULK:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 urb_xfer_done =3D update_urb_state_xfer_com=
p(hc, regs, urb, qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&status);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (urb_xfer_done) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_complete_urb(hc=
d, urb, status);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_status =3D DWC_OTG_HC_=
XFER_URB_COMPLETE;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_status =3D DWC_OTG_HC_=
XFER_COMPLETE;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 save_data_toggle(hc, regs, qtd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 complete_non_periodic_xfer(hcd, hc, regs, q=
td,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0halt_status, must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case PIPE_INTERRUPT:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 update_urb_state_xfer_comp(hc, regs, urb, q=
td, &status);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Interrupt URB is done on the first tra=
nsfer complete
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* interrupt.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_complete_urb(hcd, urb, status);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 save_data_toggle(hc, regs, qtd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 complete_periodic_xfer(hcd, hc, regs, qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0DWC_OTG_HC_XFER_URB_COMPLETE, must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case PIPE_ISOCHRONOUS:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (qtd->isoc_split_pos =3D=3D DWC_HCSPLIT_=
XACTPOS_ALL) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_status =3D update_isoc=
_urb_state(hcd, hc, regs, qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 DWC_OTG_HC_XFER_COMPLETE);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 complete_periodic_xfer(hcd, hc, regs, qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0halt_status, must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* disable xfercompl */
> + =A0 =A0 =A0 hcintmsk =3D DWC_HCINTMSK_TXFER_CMPL_RW(hcintmsk, 1);
> + =A0 =A0 =A0 dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
> +
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * Handles a host channel STALL interrupt. This handler may be called in
> + * either DMA mode or Slave mode.
> + */
> +static int handle_hc_stall_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u32 regs, s=
truct dwc_qtd *qtd, int *must_free)
> +{
> + =A0 =A0 =A0 struct urb *urb =3D qtd->urb;
> + =A0 =A0 =A0 int pipe_type =3D usb_pipetype(urb->pipe);
> + =A0 =A0 =A0 u32 hcintmsk =3D 0;
> +
> + =A0 =A0 =A0 if (pipe_type =3D=3D PIPE_CONTROL)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EP=
IPE);
> +
> + =A0 =A0 =A0 if (pipe_type =3D=3D PIPE_BULK || pipe_type =3D=3D PIPE_INT=
ERRUPT) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EP=
IPE);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* USB protocol requires resetting the da=
ta toggle for bulk
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* and interrupt endpoints when a CLEAR_F=
EATURE(ENDPOINT_HALT)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* setup command is issued to the endpoin=
t. Anticipate the
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* CLEAR_FEATURE command since a STALL ha=
s occurred and reset
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* the data toggle now.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hc->qh->data_toggle =3D 0;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL, must_free=
);
> + =A0 =A0 =A0 /* disable stall */
> + =A0 =A0 =A0 hcintmsk =3D DWC_HCINTMSK_STALL_RESP_REC_RW(hcintmsk, 1);
> + =A0 =A0 =A0 dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
> +
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * Updates the state of the URB when a transfer has been stopped due to =
an
> + * abnormal condition before the transfer completes. Modifies the
> + * actual_length field of the URB to reflect the number of bytes that ha=
ve
> + * actually been transferred via the host channel.
> + */
> +static void update_urb_state_xfer_intr(struct dwc_hc *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0u32 regs, struct urb *urb,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0struct dwc_qtd *qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0enum dwc_halt_status sts)
> +{
> + =A0 =A0 =A0 u32 xfr_len =3D get_actual_xfer_length(hc, regs, qtd, sts, =
NULL);
> + =A0 =A0 =A0 urb->actual_length +=3D xfr_len;
> +}
> +
> +/**
> + * Handles a host channel NAK interrupt. This handler may be called in e=
ither
> + * DMA mode or Slave mode.
> + */
> +static int handle_hc_nak_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u32 regs, struc=
t dwc_qtd *qtd, int *must_free)
> +{
> + =A0 =A0 =A0 u32 hcintmsk =3D 0;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, c=
ontrol, and
> + =A0 =A0 =A0 =A0* interrupt. =A0Re-start the SSPLIT transfer.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (hc->do_split) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hc->complete_split)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->error_count =3D 0;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->complete_split =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_=
NAK, must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto handle_nak_done;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 switch (usb_pipetype(qtd->urb->pipe)) {
> + =A0 =A0 =A0 case PIPE_CONTROL:
> + =A0 =A0 =A0 case PIPE_BULK:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hcd->core_if->dma_enable && hc->ep_is_i=
n) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* NAK interrupts are ena=
bled on bulk/control IN
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* transfers in DMA mode =
for the sole purpose of
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* resetting the error co=
unt after a transaction error
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* occurs. The core will =
continue transferring data.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->error_count =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto handle_nak_done;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* NAK interrupts normally occur during O=
UT transfers in DMA
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* or Slave mode. For IN transfers, more =
requests will be
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* queued as request queue space is avail=
able.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->error_count =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!hc->qh->ping_state) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 update_urb_state_xfer_intr(=
hc, regs, qtd->urb, qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0DWC_OTG_HC_XFER_NAK);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 save_data_toggle(hc, regs, =
qtd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (qtd->urb->dev->speed =
=3D=3D USB_SPEED_HIGH)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hc->qh->pin=
g_state =3D 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Halt the channel so the transfer can b=
e re-started from
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* the appropriate point or the PING prot=
ocol will
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* start/continue.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_=
NAK, must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case PIPE_INTERRUPT:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->error_count =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_=
NAK, must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case PIPE_ISOCHRONOUS:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Should never get called for isochronous =
transfers. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 BUG();
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 }
> +
> +handle_nak_done:
> + =A0 =A0 =A0 /* disable nak */
> + =A0 =A0 =A0 hcintmsk =3D DWC_HCINTMSK_NAK_RESP_REC_RW(hcintmsk, 1);
> + =A0 =A0 =A0 dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
> +
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * Helper function for handle_hc_ack_intr(). =A0Sets the split values fo=
r an ACK
> + * on SSPLIT for ISOC OUT.
> + */
> +static void set_isoc_out_vals(struct dwc_hc *hc, struct dwc_qtd *qtd)
> +{
> + =A0 =A0 =A0 struct usb_iso_packet_descriptor *frame_desc;
> +
> + =A0 =A0 =A0 switch (hc->xact_pos) {
> + =A0 =A0 =A0 case DWC_HCSPLIT_XACTPOS_ALL:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case DWC_HCSPLIT_XACTPOS_END:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->isoc_split_pos =3D DWC_HCSPLIT_XACTPOS=
_ALL;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->isoc_split_offset =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case DWC_HCSPLIT_XACTPOS_BEGIN:
> + =A0 =A0 =A0 case DWC_HCSPLIT_XACTPOS_MID:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* For BEGIN or MID, calculate the length=
 for the next
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* microframe to determine the correct SS=
PLIT token, either MID
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* or END.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 frame_desc =3D &qtd->urb->iso_frame_desc[qt=
d->isoc_frame_index];
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->isoc_split_offset +=3D 188;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if ((frame_desc->length - qtd->isoc_split_o=
ffset) <=3D 188)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->isoc_split_pos =3D DWC=
_HCSPLIT_XACTPOS_END;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->isoc_split_pos =3D DWC=
_HCSPLIT_XACTPOS_MID;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 }
> +}
> +
> +/**
> + * Handles a host channel ACK interrupt. This interrupt is enabled when
> + * performing the PING protocol in Slave mode, when errors occur during
> + * either Slave mode or DMA mode, and during Start Split transactions.
> + */
> +static int handle_hc_ack_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u32 regs, struc=
t dwc_qtd *qtd, int *must_free)
> +{
> + =A0 =A0 =A0 u32 hcintmsk =3D 0;
> +
> + =A0 =A0 =A0 if (hc->do_split) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Handle ACK on SSPLIT. ACK should not occ=
ur in CSPLIT. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!hc->ep_is_in && hc->data_pid_start !=
=3D DWC_OTG_HC_PID_SETUP)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->ssplit_out_xfer_count =
=3D hc->xfer_len;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Don't need complete for isochronous out =
transfers. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(hc->ep_type =3D=3D DWC_OTG_EP_TYPE_IS=
OC && !hc->ep_is_in))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->complete_split =3D 1;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hc->ep_type =3D=3D DWC_OTG_EP_TYPE_ISOC=
 && !hc->ep_is_in)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_isoc_out_vals(hc, qtd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, =
DWC_OTG_HC_XFER_ACK,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
must_free);
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->error_count =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hc->qh->ping_state) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hc->qh->ping_state =3D 0;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Halt the channel so th=
e transfer can be re-started
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* from the appropriate p=
oint. This only happens in
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Slave mode. In DMA mod=
e, the ping_state is cleared
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* when the transfer is s=
tarted because the core
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* automatically executes=
 the PING, then the transfer.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, =
DWC_OTG_HC_XFER_ACK,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* If the ACK occurred when _not_ in the PING state, let =
the channel
> + =A0 =A0 =A0 =A0* continue transferring data after clearing the error co=
unt.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 /* disable ack */
> + =A0 =A0 =A0 hcintmsk =3D DWC_HCINTMSK_ACK_RESP_REC_RW(hcintmsk, 1);
> + =A0 =A0 =A0 dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
> +
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * Handles a host channel NYET interrupt. This interrupt should only occ=
ur on
> + * Bulk and Control OUT endpoints and for complete split transactions. I=
f a
> + * NYET occurs at the same time as a Transfer Complete interrupt, it is
> + * handled in the xfercomp interrupt handler, not here. This handler may=
 be
> + * called in either DMA mode or Slave mode.
> + */
> +static int handle_hc_nyet_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u32 regs, st=
ruct dwc_qtd *qtd, int *must_free)
> +{
> + =A0 =A0 =A0 u32 hcintmsk =3D 0;
> + =A0 =A0 =A0 u32 hcint_clear =3D 0;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* NYET on CSPLIT
> + =A0 =A0 =A0 =A0* re-do the CSPLIT immediately on non-periodic
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (hc->do_split && hc->complete_split) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hc->ep_type =3D=3D DWC_OTG_EP_TYPE_INTR=
 ||
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hc->ep_type =3D=3D DWC_OTG_EP_TYPE_=
ISOC) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 int frnum =3D
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_get_fra=
me_number(dwc_otg_hcd_to_hcd
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(hcd));
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (dwc_full_frame_num(frnu=
m) !=3D
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_full_frame_num(=
hc->qh->sched_frame)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->comple=
te_split =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channe=
l(hcd, hc, qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0DWC_OTG_HC_XFER_XACT_ERR,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto handle=
_nyet_done;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_=
NYET, must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto handle_nyet_done;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 hc->qh->ping_state =3D 1;
> + =A0 =A0 =A0 qtd->error_count =3D 0;
> + =A0 =A0 =A0 update_urb_state_xfer_intr(hc, regs, qtd->urb, qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0DWC_=
OTG_HC_XFER_NYET);
> + =A0 =A0 =A0 save_data_toggle(hc, regs, qtd);
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Halt the channel and re-start the transfer so the PING
> + =A0 =A0 =A0 =A0* protocol will start.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET, must_free)=
;
> +
> +handle_nyet_done:
> + =A0 =A0 =A0 /* disable nyet */
> + =A0 =A0 =A0 hcintmsk =3D DWC_HCINTMSK_NYET_RESP_REC_RW(hcintmsk, 1);
> + =A0 =A0 =A0 dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
> + =A0 =A0 =A0 /* clear nyet */
> + =A0 =A0 =A0 hcint_clear =3D DWC_HCINT_NYET_RESP_REC_RW(hcint_clear, 1);
> + =A0 =A0 =A0 dwc_reg_write(regs, DWC_HCINT, hcint_clear);
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * Handles a host channel babble interrupt. This handler may be called i=
n
> + * either DMA mode or Slave mode.
> + */
> +static int handle_hc_babble_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u32 regs=
, struct dwc_qtd *qtd, int *must_free)
> +{
> + =A0 =A0 =A0 u32 hcintmsk =3D 0;
> +
> + =A0 =A0 =A0 if (hc->ep_type !=3D DWC_OTG_EP_TYPE_ISOC) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EO=
VERFLOW);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_=
BABBLE_ERR,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0must_free);
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 enum dwc_halt_status halt_status;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_status =3D update_isoc_urb_state(hcd, =
hc, regs, qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 DWC_OTG_HC_XFER_BABBLE_ERR);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, halt_status, mus=
t_free);
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 /* disable bblerr */
> + =A0 =A0 =A0 hcintmsk =3D DWC_HCINTMSK_BBL_ERR_RW(hcintmsk, 1);
> + =A0 =A0 =A0 dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * Handles a host channel AHB error interrupt. This handler is only call=
ed in
> + * DMA mode.
> + */
> +static int handle_hc_ahberr_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u32 regs=
, struct dwc_qtd *qtd)
> +{
> + =A0 =A0 =A0 u32 hcchar;
> + =A0 =A0 =A0 u32 hcsplt;
> + =A0 =A0 =A0 u32 hctsiz =3D 0;
> + =A0 =A0 =A0 u32 hcdma;
> + =A0 =A0 =A0 struct urb *urb =3D qtd->urb;
> + =A0 =A0 =A0 u32 hcintmsk =3D 0;
> +
> + =A0 =A0 =A0 hcchar =3D dwc_reg_read(regs, DWC_HCCHAR);
> + =A0 =A0 =A0 hcsplt =3D dwc_reg_read(regs, DWC_HCSPLT);
> + =A0 =A0 =A0 hctsiz =3D dwc_reg_read(regs, DWC_HCTSIZ);
> + =A0 =A0 =A0 hcdma =3D dwc_reg_read(regs, DWC_HCDMA);
> +
> + =A0 =A0 =A0 pr_err("AHB ERROR, Channel %d\n", hc->hc_num);
> + =A0 =A0 =A0 pr_err(" =A0hcchar 0x%08x, hcsplt 0x%08x\n", hcchar, hcsplt=
);
> + =A0 =A0 =A0 pr_err(" =A0hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz, hcdma);
> +
> + =A0 =A0 =A0 pr_err(" =A0Device address: %d\n", usb_pipedevice(urb->pipe=
));
> + =A0 =A0 =A0 pr_err(" =A0Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe=
),
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0(usb_pipein(urb->pipe) ? "IN" : "OUT"));
> +
> + =A0 =A0 =A0 pr_err(" =A0Endpoint type: %s\n", pipetype_str(urb->pipe));
> + =A0 =A0 =A0 pr_err(" =A0Speed: %s\n", dev_speed_str(urb->dev->speed));
> + =A0 =A0 =A0 pr_err(" =A0Max packet size: %d\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0usb_maxpacket(urb->dev, urb->pipe, usb_pipeo=
ut(urb->pipe)));
> + =A0 =A0 =A0 pr_err(" =A0Data buffer length: %d\n", urb->transfer_buffer=
_length);
> + =A0 =A0 =A0 pr_err(" =A0Transfer buffer: %p, Transfer DMA: %p\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0urb->transfer_buffer, (void *)(u32) urb->tra=
nsfer_dma);
> + =A0 =A0 =A0 pr_err(" =A0Setup buffer: %p, Setup DMA: %p\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0urb->setup_packet, (void *)(u32) urb->setup_=
dma);
> + =A0 =A0 =A0 pr_err(" =A0Interval: %d\n", urb->interval);
> +
> + =A0 =A0 =A0 dwc_otg_hcd_complete_urb(hcd, urb, -EIO);
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Force a channel halt. Don't call halt_channel because =
that won't
> + =A0 =A0 =A0 =A0* write to the HCCHARn register in DMA mode to force the=
 halt.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR);
> + =A0 =A0 =A0 /* disable ahberr */
> + =A0 =A0 =A0 hcintmsk =3D DWC_HCINTMSK_AHB_ERR_RW(hcintmsk, 1);
> + =A0 =A0 =A0 dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
> +
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * Handles a host channel transaction error interrupt. This handler may =
be
> + * called in either DMA mode or Slave mode.
> + */
> +static int handle_hc_xacterr_intr(struct dwc_hcd *hcd, struct dwc_hc *hc=
,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u32 reg=
s, struct dwc_qtd *qtd, int *must_free)
> +{
> + =A0 =A0 =A0 enum dwc_halt_status status =3D DWC_OTG_HC_XFER_XACT_ERR;
> + =A0 =A0 =A0 u32 hcintmsk =3D 0;
> +
> + =A0 =A0 =A0 switch (usb_pipetype(qtd->urb->pipe)) {
> + =A0 =A0 =A0 case PIPE_CONTROL:
> + =A0 =A0 =A0 case PIPE_BULK:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->error_count++;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!hc->qh->ping_state) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 update_urb_state_xfer_intr(=
hc, regs, qtd->urb, qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0status);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 save_data_toggle(hc, regs, =
qtd);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!hc->ep_is_in && qtd->u=
rb->dev->speed =3D=3D
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 USB_SPEED_HIGH)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hc->qh->pin=
g_state =3D 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Halt the channel so the transfer can b=
e re-started from
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* the appropriate point or the PING prot=
ocol will start.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, status, must_fre=
e);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case PIPE_INTERRUPT:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->error_count++;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hc->do_split && hc->complete_split)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->complete_split =3D 0;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, status, must_fre=
e);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case PIPE_ISOCHRONOUS:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 status =3D update_isoc_urb_state(hcd, hc, r=
egs, qtd, status);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, status, must_fre=
e);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 /* Disable xacterr */
> + =A0 =A0 =A0 hcintmsk =3D DWC_HCINTMSK_TRANS_ERR_RW(hcintmsk, 1);
> + =A0 =A0 =A0 dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
> +
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * Handles a host channel frame overrun interrupt. This handler may be c=
alled
> + * in either DMA mode or Slave mode.
> + */
> +static int handle_hc_frmovrun_intr(struct dwc_hcd *hcd, struct dwc_hc *h=
c,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u32 =
regs, struct dwc_qtd *qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int =
*must_free)
> +{
> + =A0 =A0 =A0 enum dwc_halt_status status =3D DWC_OTG_HC_XFER_FRAME_OVERR=
UN;
> + =A0 =A0 =A0 u32 hcintmsk =3D 0;
> +
> + =A0 =A0 =A0 switch (usb_pipetype(qtd->urb->pipe)) {
> + =A0 =A0 =A0 case PIPE_CONTROL:
> + =A0 =A0 =A0 case PIPE_BULK:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case PIPE_INTERRUPT:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, status, must_fre=
e);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case PIPE_ISOCHRONOUS:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 status =3D update_isoc_urb_state(hcd, hc, r=
egs, qtd, status);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, status, must_fre=
e);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 /* Disable frmovrun */
> + =A0 =A0 =A0 hcintmsk =3D DWC_HCINTMSK_FRAME_OVERN_ERR_RW(hcintmsk, 1);
> + =A0 =A0 =A0 dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
> +
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * Handles a host channel data toggle error interrupt. This handler may =
be
> + * called in either DMA mode or Slave mode.
> + */
> +static int handle_hc_datatglerr_intr(struct dwc_hcd *hcd, struct dwc_hc =
*hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
u32 regs, struct dwc_qtd *qtd)
> +{
> + =A0 =A0 =A0 u32 hcintmsk =3D 0;
> +
> + =A0 =A0 =A0 if (hc->ep_is_in)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qtd->error_count =3D 0;
> + =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("Data Toggle Error on OUT transfer, =
channel "
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"%d\n", hc->hc_num);
> +
> + =A0 =A0 =A0 /* disable datatglerr */
> + =A0 =A0 =A0 hcintmsk =3D DWC_HCINTMSK_DATA_TOG_ERR_RW(hcintmsk, 1);
> + =A0 =A0 =A0 dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
> +
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/**
> + * Handles a host Channel Halted interrupt in DMA mode. This handler
> + * determines the reason the channel halted and proceeds accordingly.
> + */
> +static void handle_hc_chhltd_intr_dma(struct dwc_hcd *hcd, struct dwc_hc=
 *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 ulong regs, struct dwc_qtd *qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 int *must_free)
> +{
> + =A0 =A0 =A0 u32 hcint;
> + =A0 =A0 =A0 u32 hcintmsk =3D 0;
> +
> + =A0 =A0 =A0 if (hc->halt_status =3D=3D DWC_OTG_HC_XFER_URB_DEQUEUE ||
> + =A0 =A0 =A0 =A0 =A0 hc->halt_status =3D=3D DWC_OTG_HC_XFER_AHB_ERR) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Just release the channel. A dequeue ca=
n happen on a
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* transfer timeout. In the case of an AH=
B Error, the channel
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* was forced to halt because there's no =
way to gracefully
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* recover.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 release_channel(hcd, hc, qtd, hc->halt_stat=
us, must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Read the HCINTn register to determine the cause for the =
halt. */
> + =A0 =A0 =A0 hcint =3D dwc_reg_read(regs, DWC_HCINT);
> + =A0 =A0 =A0 hcintmsk =3D dwc_reg_read(regs, DWC_HCINTMSK);
> + =A0 =A0 =A0 if (DWC_HCINT_TXFER_CMPL_RD(hcint)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* This is here because of a possible har=
dware bug. =A0Spec
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* says that on SPLIT-ISOC OUT transfers =
in DMA mode that a HALT
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* interrupt w/ACK bit set should occur, =
but I only see the
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* XFERCOMP bit, even with it masked out.=
 =A0This is a workaround
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* for that behavior. =A0Should fix this =
when hardware is fixed.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hc->ep_type =3D=3D DWC_OTG_EP_TYPE_ISOC=
 && !hc->ep_is_in)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 handle_hc_ack_intr(hcd, hc,=
 regs, qtd, must_free);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 handle_hc_xfercomp_intr(hcd, hc, regs, qtd,=
 must_free);
> + =A0 =A0 =A0 } else if (DWC_HCINT_STALL_RESP_REC_RD(hcint)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 handle_hc_stall_intr(hcd, hc, regs, qtd, mu=
st_free);
> + =A0 =A0 =A0 } else if (DWC_HCINT_TRANS_ERR_RD(hcint)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Must handle xacterr before nak or ack.=
 Could get a xacterr
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* at the same time as either of these on=
 a BULK/CONTROL OUT
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* that started with a PING. The xacterr =
takes precedence.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 handle_hc_xacterr_intr(hcd, hc, regs, qtd, =
must_free);
> + =A0 =A0 =A0 } else if (DWC_HCINT_NYET_RESP_REC_RD(hcint)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Must handle nyet before nak or ack. Co=
uld get a nyet at the
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* same time as either of those on a BULK=
/CONTROL OUT that
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* started with a PING. The nyet takes pr=
ecedence.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 handle_hc_nyet_intr(hcd, hc, regs, qtd, mus=
t_free);
> + =A0 =A0 =A0 } else if (DWC_HCINT_BBL_ERR_RD(hcint)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 handle_hc_babble_intr(hcd, hc, regs, qtd, m=
ust_free);
> + =A0 =A0 =A0 } else if (DWC_HCINT_FRAME_OVERN_ERR_RD(hcint)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 handle_hc_frmovrun_intr(hcd, hc, regs, qtd,=
 must_free);
> + =A0 =A0 =A0 } else if (DWC_HCINT_DATA_TOG_ERR_RD(hcint)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 handle_hc_datatglerr_intr(hcd, hc, regs, qt=
d);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hc->qh->data_toggle =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd, hc->halt_status,=
 must_free);
> + =A0 =A0 =A0 } else if (DWC_HCINT_NAK_RESP_REC_RD(hcint) &&
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0!DWC_HCINTMSK_NAK_RESP_REC_RD(hcintm=
sk)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* If nak is not masked, it's because a n=
on-split IN transfer
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* is in an error state. In that case, th=
e nak is handled by
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* the nak interrupt handler, not here. H=
andle nak here for
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* BULK/CONTROL OUT transfers, which halt=
 on a NAK to allow
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* rewinding the buffer pointer.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 handle_hc_nak_intr(hcd, hc, regs, qtd, must=
_free);
> + =A0 =A0 =A0 } else if (DWC_HCINT_ACK_RESP_REC_RD(hcint) &&
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0!DWC_HCINTMSK_ACK_RESP_REC_RD(hcintm=
sk)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* If ack is not masked, it's because a n=
on-split IN transfer
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* is in an error state. In that case, th=
e ack is handled by
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* the ack interrupt handler, not here. H=
andle ack here for
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* split transfers. Start splits halt on =
ACK.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 handle_hc_ack_intr(hcd, hc, regs, qtd, must=
_free);
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hc->ep_type =3D=3D DWC_OTG_EP_TYPE_INTR=
 ||
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 hc->ep_type =3D=3D DWC_OTG_EP_TYPE_=
ISOC) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* A periodic transfer ha=
lted with no other channel
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* interrupts set. Assume=
 it was halted by the core
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* because it could not b=
e completed in its scheduled
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* (micro)frame.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 halt_channel(hcd, hc, qtd,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("%s: Channel %d, DMA=
 Mode -- ChHltd "
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"set, but re=
ason for halting is unknown, "
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"hcint 0x%08=
x, intsts 0x%08x\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0__func__, hc=
->hc_num, hcint,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dwc_reg_read=
(gintsts_reg(hcd), 0));
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> +}
> +
> +/**
> + * Handles a host channel Channel Halted interrupt.
> + *
> + * In slave mode, this handler is called only when the driver specifical=
ly
> + * requests a halt. This occurs during handling other host channel inter=
rupts
> + * (e.g. nak, xacterr, stall, nyet, etc.).
> + *
> + * In DMA mode, this is the interrupt that occurs when the core has fini=
shed
> + * processing a transfer on a channel. Other host channel interrupts (ex=
cept
> + * ahberr) are disabled in DMA mode.
> + */
> +static int handle_hc_chhltd_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ulong regs, struct dwc_qtd *qtd, int *must_=
free)
> +{
> + =A0 =A0 =A0 if (hcd->core_if->dma_enable)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 handle_hc_chhltd_intr_dma(hcd, hc, regs, qt=
d, must_free);
> + =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 release_channel(hcd, hc, qtd, hc->halt_stat=
us, must_free);
> +
> + =A0 =A0 =A0 return 1;
> +}
> +
> +/* Handles interrupt for a specific Host Channel */
> +static int dwc_otg_hcd_handle_hc_n_intr(struct dwc_hcd *hcd, u32 num)
> +{
> + =A0 =A0 =A0 int must_free =3D 0;
> + =A0 =A0 =A0 int retval =3D 0;
> + =A0 =A0 =A0 u32 hcint;
> + =A0 =A0 =A0 u32 hcintmsk =3D 0;
> + =A0 =A0 =A0 struct dwc_hc *hc;
> + =A0 =A0 =A0 ulong hc_regs;
> + =A0 =A0 =A0 struct dwc_qtd *qtd;
> +
> + =A0 =A0 =A0 hc =3D hcd->hc_ptr_array[num];
> + =A0 =A0 =A0 hc_regs =3D hcd->core_if->host_if->hc_regs[num];
> + =A0 =A0 =A0 qtd =3D list_entry(hc->qh->qtd_list.next, struct dwc_qtd, q=
td_list_entry);
> +
> + =A0 =A0 =A0 hcint =3D dwc_reg_read(hc_regs, DWC_HCINT);
> + =A0 =A0 =A0 hcintmsk =3D dwc_reg_read(hc_regs, DWC_HCINTMSK);
> +
> + =A0 =A0 =A0 hcint =3D hcint & hcintmsk;
> + =A0 =A0 =A0 if (!hcd->core_if->dma_enable && DWC_HCINT_CHAN_HALTED_RD(h=
cint)
> + =A0 =A0 =A0 =A0 =A0 && hcint !=3D 0x2)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hcint =3D DWC_HCINT_CHAN_HALTED_RW(hcint, 0=
);
> +
> + =A0 =A0 =A0 if (DWC_HCINT_TXFER_CMPL_RD(hcint)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D handle_hc_xfercomp_intr(hcd, hc=
, hc_regs,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 qtd, &must_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* If NYET occurred at same time as Xfer =
Complete, the NYET is
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* handled by the Xfer Complete interrupt=
 handler. Don't want
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* to call the NYET interrupt handler in =
this case.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 hcint =3D DWC_HCINT_NYET_RESP_REC_RW(hcint,=
 0);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 if (DWC_HCINT_CHAN_HALTED_RD(hcint))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D handle_hc_chhltd_intr(hcd, hc, =
hc_regs,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 qtd, &must_free);
> + =A0 =A0 =A0 if (DWC_HCINT_AHB_ERR_RD(hcint))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D handle_hc_ahberr_intr(hcd, hc, =
hc_regs, qtd);
> + =A0 =A0 =A0 if (DWC_HCINT_STALL_RESP_REC_RD(hcint))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D handle_hc_stall_intr(hcd, hc, h=
c_regs,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0qtd, &must_free);
> + =A0 =A0 =A0 if (DWC_HCINT_NAK_RESP_REC_RD(hcint))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D handle_hc_nak_intr(hcd, hc, hc_=
regs, qtd, &must_free);
> + =A0 =A0 =A0 if (DWC_HCINT_ACK_RESP_REC_RD(hcint))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D handle_hc_ack_intr(hcd, hc, hc_=
regs, qtd, &must_free);
> + =A0 =A0 =A0 if (DWC_HCINT_NYET_RESP_REC_RD(hcint))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D handle_hc_nyet_intr(hcd, hc, hc=
_regs,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 qtd, &must_free);
> + =A0 =A0 =A0 if (DWC_HCINT_TRANS_ERR_RD(hcint))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D handle_hc_xacterr_intr(hcd, hc,=
 hc_regs,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0qtd, &must_free);
> + =A0 =A0 =A0 if (DWC_HCINT_BBL_ERR_RD(hcint))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D handle_hc_babble_intr(hcd, hc, =
hc_regs,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 qtd, &must_free);
> + =A0 =A0 =A0 if (DWC_HCINT_FRAME_OVERN_ERR_RD(hcint))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D handle_hc_frmovrun_intr(hcd, hc=
, hc_regs,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 qtd, &must_free);
> + =A0 =A0 =A0 if (DWC_HCINT_DATA_TOG_ERR_RD(hcint))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D handle_hc_datatglerr_intr(hcd, =
hc, hc_regs, qtd);
> +
> + =A0 =A0 =A0 if (must_free)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Free the qtd here now that we are done u=
sing it. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dwc_otg_hcd_qtd_free(qtd);
> + =A0 =A0 =A0 return retval;
> +}
> +
> +/**
> + * This function returns the Host All Channel Interrupt register
> + */
> +static inline u32 dwc_otg_read_host_all_channels_intr(struct core_if
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *core_if)
> +{
> + =A0 =A0 =A0 return dwc_reg_read(core_if->host_if->host_global_regs, DWC=
_HAINT);
> +}
> +
> +/**
> + * This interrupt indicates that one or more host channels has a pending
> + * interrupt. There are multiple conditions that can cause each host cha=
nnel
> + * interrupt. This function determines which conditions have occurred fo=
r each
> + * host channel interrupt and handles them appropriately.
> + */
> +static int dwc_otg_hcd_handle_hc_intr(struct dwc_hcd *hcd)
> +{
> + =A0 =A0 =A0 u32 i;
> + =A0 =A0 =A0 int retval =3D 0;
> + =A0 =A0 =A0 u32 haint;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Clear appropriate bits in HCINTn to clear the interrup=
t bit in
> + =A0 =A0 =A0 =A0* =A0GINTSTS
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 haint =3D dwc_otg_read_host_all_channels_intr(hcd->core_if)=
;
> + =A0 =A0 =A0 for (i =3D 0; i < hcd->core_if->core_params->host_channels;=
 i++)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (DWC_HAINT_RD(haint) & (1 << i))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval |=3D dwc_otg_hcd_han=
dle_hc_n_intr(hcd, i);
> +
> + =A0 =A0 =A0 return retval;
> +}
> +
> +/* This function handles interrupts for the HCD.*/
> +int dwc_otg_hcd_handle_intr(struct dwc_hcd *hcd)
> +{
> + =A0 =A0 =A0 int ret =3D 0;
> + =A0 =A0 =A0 struct core_if *core_if =3D hcd->core_if;
> + =A0 =A0 =A0 u32 gintsts;
> +
> + =A0 =A0 =A0 /* Check if HOST Mode */
> + =A0 =A0 =A0 if (dwc_otg_is_host_mode(core_if)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 spin_lock(&hcd->lock);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 gintsts =3D dwc_otg_read_core_intr(core_if)=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!gintsts) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 spin_unlock(&hcd->lock);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return IRQ_NONE;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (gintsts & DWC_INTMSK_STRT_OF_FRM)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret |=3D dwc_otg_hcd_handle=
_sof_intr(hcd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (gintsts & DWC_INTMSK_RXFIFO_NOT_EMPT)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret |=3D dwc_otg_hcd_handle=
_rx_status_q_level_intr(hcd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (gintsts & DWC_INTMSK_NP_TXFIFO_EMPT)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret |=3D dwc_otg_hcd_handle=
_np_tx_fifo_empty_intr(hcd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (gintsts & DWC_INTMSK_HST_PORT)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret |=3D dwc_otg_hcd_handle=
_port_intr(hcd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (gintsts & DWC_INTMSK_HST_CHAN)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret |=3D dwc_otg_hcd_handle=
_hc_intr(hcd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (gintsts & DWC_INTMSK_P_TXFIFO_EMPTY)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret |=3D dwc_otg_hcd_handle=
_perio_tx_fifo_empty_intr(hcd);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 spin_unlock(&hcd->lock);
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 return ret;
> +}
> --
> 1.6.1.rc3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at =A0http://vger.kernel.org/majordomo-info.html
>

Reviewed-by: Pratyush Anand <pratyush.anand@st.com>

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox