Merge tag 'usb-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 18 Aug 2018 17:21:49 +0000 (10:21 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 18 Aug 2018 17:21:49 +0000 (10:21 -0700)
Pull USB/PHY updates from Greg KH:
 "Here is the big USB and phy driver patch set for 4.19-rc1.

  Nothing huge but there was a lot of work that happened this
  development cycle:

   - lots of type-c work, with drivers graduating out of staging, and
     displayport support being added.

   - new PHY drivers

   - the normal collection of gadget driver updates and fixes

   - code churn to work on the urb handling path, using irqsave()
     everywhere in anticipation of making this codepath a lot simpler in
     the future.

   - usbserial driver fixes and reworks

   - other misc changes

  All of these have been in linux-next with no reported issues for a
  while"

* tag 'usb-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (159 commits)
  USB: serial: pl2303: add a new device id for ATEN
  usb: renesas_usbhs: Kconfig: convert to SPDX identifiers
  usb: dwc3: gadget: Check MaxPacketSize from descriptor
  usb: dwc2: Turn on uframe_sched on "stm32f4x9_fsotg" platforms
  usb: dwc2: Turn on uframe_sched on "amlogic" platforms
  usb: dwc2: Turn on uframe_sched on "his" platforms
  usb: dwc2: Turn on uframe_sched on "bcm" platforms
  usb: dwc2: gadget: ISOC's starting flow improvement
  usb: dwc2: Make dwc2_readl/writel functions endianness-agnostic.
  usb: dwc3: core: Enable AutoRetry feature in the controller
  usb: dwc3: Set default mode for dwc_usb31
  usb: gadget: udc: renesas_usb3: Add register of usb role switch
  usb: dwc2: replace ioread32/iowrite32_rep with dwc2_readl/writel_rep
  usb: dwc2: Modify dwc2_readl/writel functions prototype
  usb: dwc3: pci: Intel Merrifield can be host
  usb: dwc3: pci: Supply device properties via driver data
  arm64: dts: dwc3: description of incr burst type
  usb: dwc3: Enable undefined length INCR burst type
  usb: dwc3: add global soc bus configuration reg0
  usb: dwc3: Describe 'wakeup_work' field of struct dwc3_pci
  ...

168 files changed:
Documentation/ABI/obsolete/sysfs-class-typec [new file with mode: 0644]
Documentation/ABI/testing/configfs-usb-gadget-uvc
Documentation/ABI/testing/sysfs-bus-typec [new file with mode: 0644]
Documentation/ABI/testing/sysfs-class-typec
Documentation/ABI/testing/sysfs-driver-typec-displayport [new file with mode: 0644]
Documentation/devicetree/bindings/connector/usb-connector.txt
Documentation/devicetree/bindings/phy/brcm,sr-pcie-phy.txt [new file with mode: 0644]
Documentation/devicetree/bindings/phy/phy-mtk-tphy.txt
Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt [new file with mode: 0644]
Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt
Documentation/devicetree/bindings/usb/dwc3.txt
Documentation/devicetree/bindings/usb/npcm7xx-usb.txt [new file with mode: 0644]
Documentation/devicetree/bindings/usb/typec-tcpci.txt [new file with mode: 0644]
Documentation/devicetree/bindings/usb/usb-xhci.txt
Documentation/driver-api/usb/typec_bus.rst [new file with mode: 0644]
Documentation/usb/usb-serial.txt
MAINTAINERS
drivers/nfc/nfcmrvl/usb.c
drivers/phy/broadcom/Kconfig
drivers/phy/broadcom/Makefile
drivers/phy/broadcom/phy-bcm-sr-pcie.c [new file with mode: 0644]
drivers/phy/marvell/phy-berlin-sata.c
drivers/phy/marvell/phy-berlin-usb.c
drivers/phy/marvell/phy-mvebu-cp110-comphy.c
drivers/phy/mediatek/Makefile
drivers/phy/mediatek/phy-mtk-tphy.c
drivers/phy/qualcomm/phy-qcom-usb-hs.c
drivers/phy/renesas/Kconfig
drivers/phy/renesas/Makefile
drivers/phy/renesas/phy-rcar-gen3-pcie.c [new file with mode: 0644]
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/typec/Kconfig [deleted file]
drivers/staging/typec/Makefile [deleted file]
drivers/staging/typec/TODO [deleted file]
drivers/staging/typec/tcpci.c [deleted file]
drivers/staging/typec/tcpci.h [deleted file]
drivers/staging/typec/tcpci_rt1711h.c [deleted file]
drivers/usb/chipidea/ci_hdrc_tegra.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-wdm.c
drivers/usb/class/usblp.c
drivers/usb/class/usbtmc.c
drivers/usb/core/devio.c
drivers/usb/core/hub.c
drivers/usb/core/message.c
drivers/usb/dwc2/core.c
drivers/usb/dwc2/core.h
drivers/usb/dwc2/core_intr.c
drivers/usb/dwc2/debugfs.c
drivers/usb/dwc2/gadget.c
drivers/usb/dwc2/hcd.c
drivers/usb/dwc2/hcd.h
drivers/usb/dwc2/hcd_ddma.c
drivers/usb/dwc2/hcd_intr.c
drivers/usb/dwc2/hcd_queue.c
drivers/usb/dwc2/params.c
drivers/usb/dwc2/platform.c
drivers/usb/dwc3/Kconfig
drivers/usb/dwc3/Makefile
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/dwc3-haps.c [new file with mode: 0644]
drivers/usb/dwc3/dwc3-of-simple.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/gadget.h
drivers/usb/gadget/configfs.c
drivers/usb/gadget/function/f_mass_storage.c
drivers/usb/gadget/function/f_mass_storage.h
drivers/usb/gadget/function/f_uvc.c
drivers/usb/gadget/function/f_uvc.h
drivers/usb/gadget/function/u_uvc.h
drivers/usb/gadget/function/uvc.h
drivers/usb/gadget/function/uvc_configfs.c
drivers/usb/gadget/function/uvc_queue.h
drivers/usb/gadget/function/uvc_v4l2.c
drivers/usb/gadget/function/uvc_video.h
drivers/usb/gadget/legacy/tcm_usb_gadget.c
drivers/usb/gadget/legacy/webcam.c
drivers/usb/gadget/udc/Kconfig
drivers/usb/gadget/udc/core.c
drivers/usb/gadget/udc/renesas_usb3.c
drivers/usb/host/Kconfig
drivers/usb/host/Makefile
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-npcm7xx.c [new file with mode: 0644]
drivers/usb/host/ehci-sched.c
drivers/usb/host/u132-hcd.c
drivers/usb/host/whci/pzl.c
drivers/usb/host/xhci-dbgcap.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-rcar.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/isp1760/isp1760-hcd.c
drivers/usb/misc/adutux.c
drivers/usb/misc/appledisplay.c
drivers/usb/misc/iowarrior.c
drivers/usb/misc/ldusb.c
drivers/usb/misc/legousbtower.c
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/misc/usbtest.c
drivers/usb/misc/uss720.c
drivers/usb/mon/mon_bin.c
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_host.c
drivers/usb/renesas_usbhs/Kconfig
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/ir-usb.c
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kl5kusb105.h
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/quatech2.c
drivers/usb/serial/sierra.c
drivers/usb/serial/ssu100.c
drivers/usb/serial/symbolserial.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb_wwan.c
drivers/usb/typec/Kconfig
drivers/usb/typec/Makefile
drivers/usb/typec/altmodes/Kconfig [new file with mode: 0644]
drivers/usb/typec/altmodes/Makefile [new file with mode: 0644]
drivers/usb/typec/altmodes/displayport.c [new file with mode: 0644]
drivers/usb/typec/bus.c [new file with mode: 0644]
drivers/usb/typec/bus.h [new file with mode: 0644]
drivers/usb/typec/class.c
drivers/usb/typec/fusb302/fusb302.c
drivers/usb/typec/mux.c
drivers/usb/typec/mux/pi3usb30532.c
drivers/usb/typec/tcpci.c [new file with mode: 0644]
drivers/usb/typec/tcpci.h [new file with mode: 0644]
drivers/usb/typec/tcpci_rt1711h.c [new file with mode: 0644]
drivers/usb/typec/tcpm.c
drivers/usb/typec/tps6598x.c
drivers/usb/usb-skeleton.c
drivers/usb/usbip/vudc_dev.c
drivers/usb/wusbcore/security.c
drivers/usb/wusbcore/wa-xfer.c
drivers/uwb/hwa-rc.c
include/dt-bindings/usb/pd.h [new file with mode: 0644]
include/linux/mod_devicetable.h
include/linux/usb/hcd.h
include/linux/usb/pd.h
include/linux/usb/tcpm.h
include/linux/usb/typec.h
include/linux/usb/typec_altmode.h [new file with mode: 0644]
include/linux/usb/typec_dp.h [new file with mode: 0644]
include/linux/usb/typec_mux.h
include/uapi/linux/usb/g_uvc.h [new file with mode: 0644]
include/uapi/linux/usb/tmc.h
scripts/mod/devicetable-offsets.c
scripts/mod/file2alias.c
tools/testing/selftests/drivers/usb/usbip/usbip_test.sh

diff --git a/Documentation/ABI/obsolete/sysfs-class-typec b/Documentation/ABI/obsolete/sysfs-class-typec
new file mode 100644 (file)
index 0000000..3262351
--- /dev/null
@@ -0,0 +1,48 @@
+These files are deprecated and will be removed. The same files are available
+under /sys/bus/typec (see Documentation/ABI/testing/sysfs-bus-typec).
+
+What:          /sys/class/typec/<port|partner|cable>/<dev>/svid
+Date:          April 2017
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               The SVID (Standard or Vendor ID) assigned by USB-IF for this
+               alternate mode.
+
+What:          /sys/class/typec/<port|partner|cable>/<dev>/mode<index>/
+Date:          April 2017
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               Every supported mode will have its own directory. The name of
+               a mode will be "mode<index>" (for example mode1), where <index>
+               is the actual index to the mode VDO returned by Discover Modes
+               USB power delivery command.
+
+What:          /sys/class/typec/<port|partner|cable>/<dev>/mode<index>/description
+Date:          April 2017
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               Shows description of the mode. The description is optional for
+               the drivers, just like with the Billboard Devices.
+
+What:          /sys/class/typec/<port|partner|cable>/<dev>/mode<index>/vdo
+Date:          April 2017
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               Shows the VDO in hexadecimal returned by Discover Modes command
+               for this mode.
+
+What:          /sys/class/typec/<port|partner|cable>/<dev>/mode<index>/active
+Date:          April 2017
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               Shows if the mode is active or not. The attribute can be used
+               for entering/exiting the mode with partners and cable plugs, and
+               with the port alternate modes it can be used for disabling
+               support for specific alternate modes. Entering/exiting modes is
+               supported as synchronous operation so write(2) to the attribute
+               does not return until the enter/exit mode operation has
+               finished. The attribute is notified when the mode is
+               entered/exited so poll(2) on the attribute wakes up.
+               Entering/exiting a mode will also generate uevent KOBJ_CHANGE.
+
+               Valid values: yes, no
index 1ba0d0fda9c0b5cac32a0169790b5c87f819f808..9281e2aa38dffcef3422cbbbafbb70a0500c69cf 100644 (file)
@@ -263,3 +263,8 @@ Description:        Specific streaming header descriptors
                                        is connected
                bmInfo                  - capabilities of this video streaming
                                        interface
+
+What:          /sys/class/udc/udc.name/device/gadget/video4linux/video.name/function_name
+Date:          May 2018
+KernelVersion: 4.19
+Description:   UVC configfs function instance name
diff --git a/Documentation/ABI/testing/sysfs-bus-typec b/Documentation/ABI/testing/sysfs-bus-typec
new file mode 100644 (file)
index 0000000..205d9c9
--- /dev/null
@@ -0,0 +1,51 @@
+What:          /sys/bus/typec/devices/.../active
+Date:          July 2018
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               Shows if the mode is active or not. The attribute can be used
+               for entering/exiting the mode. Entering/exiting modes is
+               supported as synchronous operation so write(2) to the attribute
+               does not return until the enter/exit mode operation has
+               finished. The attribute is notified when the mode is
+               entered/exited so poll(2) on the attribute wakes up.
+               Entering/exiting a mode will also generate uevent KOBJ_CHANGE.
+
+               Valid values are boolean.
+
+What:          /sys/bus/typec/devices/.../description
+Date:          July 2018
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               Shows description of the mode. The description is optional for
+               the drivers, just like with the Billboard Devices.
+
+What:          /sys/bus/typec/devices/.../mode
+Date:          July 2018
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               The index number of the mode returned by Discover Modes USB
+               Power Delivery command. Depending on the alternate mode, the
+               mode index may be significant.
+
+               With some alternate modes (SVIDs), the mode index is assigned
+               for specific functionality in the specification for that
+               alternate mode.
+
+               With other alternate modes, the mode index values are not
+               assigned, and can not be therefore used for identification. When
+               the mode index is not assigned, identifying the alternate mode
+               must be done with either mode VDO or the description.
+
+What:          /sys/bus/typec/devices/.../svid
+Date:          July 2018
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               The Standard or Vendor ID (SVID) assigned by USB-IF for this
+               alternate mode.
+
+What:          /sys/bus/typec/devices/.../vdo
+Date:          July 2018
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               Shows the VDO in hexadecimal returned by Discover Modes command
+               for this mode.
index 5be552e255e9859f89f66f0302626dcd2d906652..d7647b258c3ca84255b3a95ceebb1c486dabf9f3 100644 (file)
@@ -222,70 +222,12 @@ Description:
                available. The value can be polled.
 
 
-Alternate Mode devices.
+USB Type-C port alternate mode devices.
 
-The alternate modes will have Standard or Vendor ID (SVID) assigned by USB-IF.
-The ports, partners and cable plugs can have alternate modes. A supported SVID
-will consist of a set of modes. Every SVID a port/partner/plug supports will
-have a device created for it, and every supported mode for a supported SVID will
-have its own directory under that device. Below <dev> refers to the device for
-the alternate mode.
-
-What:          /sys/class/typec/<port|partner|cable>/<dev>/svid
-Date:          April 2017
-Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
-Description:
-               The SVID (Standard or Vendor ID) assigned by USB-IF for this
-               alternate mode.
-
-What:          /sys/class/typec/<port|partner|cable>/<dev>/mode<index>/
-Date:          April 2017
-Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
-Description:
-               Every supported mode will have its own directory. The name of
-               a mode will be "mode<index>" (for example mode1), where <index>
-               is the actual index to the mode VDO returned by Discover Modes
-               USB power delivery command.
-
-What:          /sys/class/typec/<port|partner|cable>/<dev>/mode<index>/description
-Date:          April 2017
-Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
-Description:
-               Shows description of the mode. The description is optional for
-               the drivers, just like with the Billboard Devices.
-
-What:          /sys/class/typec/<port|partner|cable>/<dev>/mode<index>/vdo
-Date:          April 2017
-Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
-Description:
-               Shows the VDO in hexadecimal returned by Discover Modes command
-               for this mode.
-
-What:          /sys/class/typec/<port|partner|cable>/<dev>/mode<index>/active
-Date:          April 2017
-Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
-Description:
-               Shows if the mode is active or not. The attribute can be used
-               for entering/exiting the mode with partners and cable plugs, and
-               with the port alternate modes it can be used for disabling
-               support for specific alternate modes. Entering/exiting modes is
-               supported as synchronous operation so write(2) to the attribute
-               does not return until the enter/exit mode operation has
-               finished. The attribute is notified when the mode is
-               entered/exited so poll(2) on the attribute wakes up.
-               Entering/exiting a mode will also generate uevent KOBJ_CHANGE.
-
-               Valid values: yes, no
-
-What:          /sys/class/typec/<port>/<dev>/mode<index>/supported_roles
+What:          /sys/class/typec/<port>/<alt mode>/supported_roles
 Date:          April 2017
 Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
 Description:
                Space separated list of the supported roles.
 
-               This attribute is available for the devices describing the
-               alternate modes a port supports, and it will not be exposed with
-               the devices presenting the alternate modes the partners or cable
-               plugs support.
-
                Valid values: source, sink
diff --git a/Documentation/ABI/testing/sysfs-driver-typec-displayport b/Documentation/ABI/testing/sysfs-driver-typec-displayport
new file mode 100644 (file)
index 0000000..231471a
--- /dev/null
@@ -0,0 +1,49 @@
+What:          /sys/bus/typec/devices/.../displayport/configuration
+Date:          July 2018
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               Shows the current DisplayPort configuration for the connector.
+               Valid values are USB, source and sink. Source means DisplayPort
+               source, and sink means DisplayPort sink.
+
+               All supported configurations are listed as space separated list
+               with the active one wrapped in square brackets.
+
+               Source example:
+
+                       USB [source] sink
+
+               The configuration can be changed by writing to the file
+
+               Note. USB configuration does not equal to Exit Mode. It is
+               separate configuration defined in VESA DisplayPort Alt Mode on
+               USB Type-C Standard. Functionally it equals to the situation
+               where the mode has been exited (to exit the mode, see
+               Documentation/ABI/testing/sysfs-bus-typec, and use file
+               /sys/bus/typec/devices/.../active).
+
+What:          /sys/bus/typec/devices/.../displayport/pin_assignment
+Date:          July 2018
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               VESA DisplayPort Alt Mode on USB Type-C Standard defines six
+               different pin assignments for USB Type-C connector that are
+               labeled A, B, C, D, E, and F. The supported pin assignments are
+               listed as space separated list with the active one wrapped in
+               square brackets.
+
+               Example:
+
+                       C [D]
+
+               Pin assignment can be changed by writing to the file. It is
+               possible to set pin assignment before configuration has been
+               set, but the assignment will not be active before the
+               connector is actually configured.
+
+               Note. As of VESA DisplayPort Alt Mode on USB Type-C Standard
+               version 1.0b, pin assignments A, B, and F are deprecated. Only
+               pin assignment D can now carry simultaneously one channel of
+               USB SuperSpeed protocol. From user perspective pin assignments C
+               and E are equal, where all channels on the connector are used
+               for carrying DisplayPort protocol (allowing higher resolutions).
index e1463f14af3878b1d6913dcb10a648820b2f98b9..8855bfcfd778564b0666a92cc1cb51fe8900322f 100644 (file)
@@ -15,6 +15,33 @@ Optional properties:
 - type: size of the connector, should be specified in case of USB-A, USB-B
   non-fullsize connectors: "mini", "micro".
 
+Optional properties for usb-c-connector:
+- power-role: should be one of "source", "sink" or "dual"(DRP) if typec
+  connector has power support.
+- try-power-role: preferred power role if "dual"(DRP) can support Try.SNK
+  or Try.SRC, should be "sink" for Try.SNK or "source" for Try.SRC.
+- data-role: should be one of "host", "device", "dual"(DRD) if typec
+  connector supports USB data.
+
+Required properties for usb-c-connector with power delivery support:
+- source-pdos: An array of u32 with each entry providing supported power
+  source data object(PDO), the detailed bit definitions of PDO can be found
+  in "Universal Serial Bus Power Delivery Specification" chapter 6.4.1.2
+  Source_Capabilities Message, the order of each entry(PDO) should follow
+  the PD spec chapter 6.4.1. Required for power source and power dual role.
+  User can specify the source PDO array via PDO_FIXED/BATT/VAR() defined in
+  dt-bindings/usb/pd.h.
+- sink-pdos: An array of u32 with each entry providing supported power
+  sink data object(PDO), the detailed bit definitions of PDO can be found
+  in "Universal Serial Bus Power Delivery Specification" chapter 6.4.1.3
+  Sink Capabilities Message, the order of each entry(PDO) should follow
+  the PD spec chapter 6.4.1. Required for power sink and power dual role.
+  User can specify the sink PDO array via PDO_FIXED/BATT/VAR() defined in
+  dt-bindings/usb/pd.h.
+- op-sink-microwatt: Sink required operating power in microwatt, if source
+  can't offer the power, Capability Mismatch is set. Required for power
+  sink and power dual role.
+
 Required nodes:
 - any data bus to the connector should be modeled using the OF graph bindings
   specified in bindings/graph.txt, unless the bus is between parent node and
@@ -73,3 +100,20 @@ ccic: s2mm005@33 {
                };
        };
 };
+
+3. USB-C connector attached to a typec port controller(ptn5110), which has
+power delivery support and enables drp.
+
+typec: ptn5110@50 {
+       ...
+       usb_con: connector {
+               compatible = "usb-c-connector";
+               label = "USB-C";
+               power-role = "dual";
+               try-power-role = "sink";
+               source-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)>;
+               sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)
+                            PDO_VAR(5000, 12000, 2000)>;
+               op-sink-microwatt = <10000000>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/phy/brcm,sr-pcie-phy.txt b/Documentation/devicetree/bindings/phy/brcm,sr-pcie-phy.txt
new file mode 100644 (file)
index 0000000..e8d8228
--- /dev/null
@@ -0,0 +1,41 @@
+Broadcom Stingray PCIe PHY
+
+Required properties:
+- compatible: must be "brcm,sr-pcie-phy"
+- reg: base address and length of the PCIe SS register space
+- brcm,sr-cdru: phandle to the CDRU syscon node
+- brcm,sr-mhb: phandle to the MHB syscon node
+- #phy-cells: Must be 1, denotes the PHY index
+
+For PAXB based root complex, one can have a configuration of up to 8 PHYs
+PHY index goes from 0 to 7
+
+For the internal PAXC based root complex, PHY index is always 8
+
+Example:
+       mhb: syscon@60401000 {
+               compatible = "brcm,sr-mhb", "syscon";
+               reg = <0 0x60401000 0 0x38c>;
+       };
+
+       cdru: syscon@6641d000 {
+               compatible = "brcm,sr-cdru", "syscon";
+               reg = <0 0x6641d000 0 0x400>;
+       };
+
+       pcie_phy: phy@40000000 {
+               compatible = "brcm,sr-pcie-phy";
+               reg = <0 0x40000000 0 0x800>;
+               brcm,sr-cdru = <&cdru>;
+               brcm,sr-mhb = <&mhb>;
+               #phy-cells = <1>;
+       };
+
+       /* users of the PCIe PHY */
+
+       pcie0: pcie@48000000 {
+               ...
+               ...
+               phys = <&pcie_phy 0>;
+               phy-names = "pcie-phy";
+       };
index 0d34b2b4a6b79600906515679ec45771359d11ac..a5f7a4f0dbc1a8609270b32b761a447183222a57 100644 (file)
@@ -47,6 +47,12 @@ Required properties (port (child) node):
                        - PHY_TYPE_PCIE
                        - PHY_TYPE_SATA
 
+Optional properties (PHY_TYPE_USB2 port (child) node):
+- mediatek,eye-src     : u32, the value of slew rate calibrate
+- mediatek,eye-vrt     : u32, the selection of VRT reference voltage
+- mediatek,eye-term    : u32, the selection of HS_TX TERM reference voltage
+- mediatek,bc12        : bool, enable BC12 of u2phy if support it
+
 Example:
 
 u3phy: usb-phy@11290000 {
index 266a1bb8bb6e4f1e86bc07ded0265cfa6002239a..0c7629e88bf3ac8c02094403c19272beea966f4f 100644 (file)
@@ -12,7 +12,14 @@ Required properties:
               "qcom,sdm845-qmp-usb3-phy" for USB3 QMP V3 phy on sdm845,
               "qcom,sdm845-qmp-usb3-uni-phy" for USB3 QMP V3 UNI phy on sdm845.
 
- - reg: offset and length of register set for PHY's common serdes block.
+ - reg:
+   - For "qcom,sdm845-qmp-usb3-phy":
+     - index 0: address and length of register set for PHY's common serdes
+       block.
+     - named register "dp_com" (using reg-names): address and length of the
+       DP_COM control block.
+   - For all others:
+     - offset and length of register set for PHY's common serdes block.
 
  - #clock-cells: must be 1
     - Phy pll outputs a bunch of clocks for Tx, Rx and Pipe
@@ -60,7 +67,10 @@ Required nodes:
 
 Required properties for child node:
  - reg: list of offset and length pairs of register sets for PHY blocks -
-       tx, rx and pcs.
+       - index 0: tx
+       - index 1: rx
+       - index 2: pcs
+       - index 3: pcs_misc (optional)
 
  - #phy-cells: must be 0
 
diff --git a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt
new file mode 100644 (file)
index 0000000..63853b3
--- /dev/null
@@ -0,0 +1,24 @@
+* Renesas R-Car generation 3 PCIe PHY
+
+This file provides information on what the device node for the R-Car
+generation 3 PCIe PHY contains.
+
+Required properties:
+- compatible: "renesas,r8a77980-pcie-phy" if the device is a part of the
+             R8A77980 SoC.
+- reg: offset and length of the register block.
+- clocks: clock phandle and specifier pair.
+- power-domains: power domain phandle and specifier pair.
+- resets: reset phandle and specifier pair.
+- #phy-cells: see phy-bindings.txt in the same directory, must be <0>.
+
+Example (R-Car V3H):
+
+       pcie-phy@e65d0000 {
+               compatible = "renesas,r8a77980-pcie-phy";
+               reg = <0 0xe65d0000 0 0x8000>;
+               #phy-cells = <0>;
+               clocks = <&cpg CPG_MOD 319>;
+               power-domains = <&sysc 32>;
+               resets = <&cpg 319>;
+       };
index dbd137c079e2de33dd9bbbdfc6e2c516c4fc5eec..fb4a204da2bf197e8990d74ef56320583cfd3450 100644 (file)
@@ -10,6 +10,8 @@ Required properties:
              SoC.
              "renesas,usb2-phy-r8a77965" if the device is a part of an
              R8A77965 SoC.
+             "renesas,usb2-phy-r8a77990" if the device is a part of an
+             R8A77990 SoC.
              "renesas,usb2-phy-r8a77995" if the device is a part of an
              R8A77995 SoC.
              "renesas,rcar-gen3-usb2-phy" for a generic R-Car Gen3 compatible device.
index 7f13ebef06cb57cecce50c1b10edea421a372398..3e4c38b806ac11d485172473fbf933d1b4a206a7 100644 (file)
@@ -96,6 +96,11 @@ Optional properties:
                        enable periodic ESS TX threshold.
 
  - <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be reallocated.
+ - snps,incr-burst-type-adjustment: Value for INCR burst type of GSBUSCFG0
+                       register, undefined length INCR burst type enable and INCRx type.
+                       When just one value, which means INCRX burst mode enabled. When
+                       more than one value, which means undefined length INCR burst type
+                       enabled. The values can be 1, 4, 8, 16, 32, 64, 128 and 256.
 
  - in addition all properties from usb-xhci.txt from the current directory are
    supported as well
@@ -108,4 +113,5 @@ dwc3@4a030000 {
        reg = <0x4a030000 0xcfff>;
        interrupts = <0 92 4>
        usb-phy = <&usb2_phy>, <&usb3,phy>;
+       snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
 };
diff --git a/Documentation/devicetree/bindings/usb/npcm7xx-usb.txt b/Documentation/devicetree/bindings/usb/npcm7xx-usb.txt
new file mode 100644 (file)
index 0000000..5a0f1f1
--- /dev/null
@@ -0,0 +1,18 @@
+Nuvoton NPCM7XX SoC USB controllers:
+-----------------------------
+
+EHCI:
+-----
+
+Required properties:
+- compatible: "nuvoton,npcm750-ehci"
+- interrupts: Should contain the EHCI interrupt
+- reg:        Physical address and length of the register set for the device
+
+Example:
+
+       ehci1: usb@f0806000 {
+               compatible = "nuvoton,npcm750-ehci";
+               reg = <0xf0806000 0x1000>;
+               interrupts = <0 61 4>;
+       };
diff --git a/Documentation/devicetree/bindings/usb/typec-tcpci.txt b/Documentation/devicetree/bindings/usb/typec-tcpci.txt
new file mode 100644 (file)
index 0000000..0dd1469
--- /dev/null
@@ -0,0 +1,49 @@
+TCPCI(Typec port cotroller interface) binding
+---------------------------------------------
+
+Required properties:
+- compatible:       should be set one of following:
+                   - "nxp,ptn5110" for NXP USB PD TCPC PHY IC ptn5110.
+
+- reg:              the i2c slave address of typec port controller device.
+- interrupt-parent: the phandle to the interrupt controller which provides
+                    the interrupt.
+- interrupts:       interrupt specification for tcpci alert.
+
+Required sub-node:
+- connector: The "usb-c-connector" attached to the tcpci chip, the bindings
+  of connector node are specified in
+  Documentation/devicetree/bindings/connector/usb-connector.txt
+
+Example:
+
+ptn5110@50 {
+       compatible = "nxp,ptn5110";
+       reg = <0x50>;
+       interrupt-parent = <&gpio3>;
+       interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+
+       usb_con: connector {
+               compatible = "usb-c-connector";
+               label = "USB-C";
+               data-role = "dual";
+               power-role = "dual";
+               try-power-role = "sink";
+               source-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)>;
+               sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)
+                            PDO_VAR(5000, 12000, 2000)>;
+               op-sink-microwatt = <10000000>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@1 {
+                               reg = <1>;
+                               usb_con_ss: endpoint {
+                                       remote-endpoint = <&usb3_data_ss>;
+                               };
+                       };
+               };
+       };
+};
index bd1dd316fb231f84d02a6125d566e881600df387..ac4cd0d6195a89f6bf5619f34cd3987c20597aac 100644 (file)
@@ -14,6 +14,7 @@ Required properties:
     - "renesas,xhci-r8a7795" for r8a7795 SoC
     - "renesas,xhci-r8a7796" for r8a7796 SoC
     - "renesas,xhci-r8a77965" for r8a77965 SoC
+    - "renesas,xhci-r8a77990" for r8a77990 SoC
     - "renesas,rcar-gen2-xhci" for a generic R-Car Gen2 or RZ/G1 compatible
       device
     - "renesas,rcar-gen3-xhci" for a generic R-Car Gen3 compatible device
diff --git a/Documentation/driver-api/usb/typec_bus.rst b/Documentation/driver-api/usb/typec_bus.rst
new file mode 100644 (file)
index 0000000..d5eec17
--- /dev/null
@@ -0,0 +1,136 @@
+
+API for USB Type-C Alternate Mode drivers
+=========================================
+
+Introduction
+------------
+
+Alternate modes require communication with the partner using Vendor Defined
+Messages (VDM) as defined in USB Type-C and USB Power Delivery Specifications.
+The communication is SVID (Standard or Vendor ID) specific, i.e. specific for
+every alternate mode, so every alternate mode will need a custom driver.
+
+USB Type-C bus allows binding a driver to the discovered partner alternate
+modes by using the SVID and the mode number.
+
+USB Type-C Connector Class provides a device for every alternate mode a port
+supports, and separate device for every alternate mode the partner supports.
+The drivers for the alternate modes are bound to the partner alternate mode
+devices, and the port alternate mode devices must be handled by the port
+drivers.
+
+When a new partner alternate mode device is registered, it is linked to the
+alternate mode device of the port that the partner is attached to, that has
+matching SVID and mode. Communication between the port driver and alternate mode
+driver will happen using the same API.
+
+The port alternate mode devices are used as a proxy between the partner and the
+alternate mode drivers, so the port drivers are only expected to pass the SVID
+specific commands from the alternate mode drivers to the partner, and from the
+partners to the alternate mode drivers. No direct SVID specific communication is
+needed from the port drivers, but the port drivers need to provide the operation
+callbacks for the port alternate mode devices, just like the alternate mode
+drivers need to provide them for the partner alternate mode devices.
+
+Usage:
+------
+
+General
+~~~~~~~
+
+By default, the alternate mode drivers are responsible for entering the mode.
+It is also possible to leave the decision about entering the mode to the user
+space (See Documentation/ABI/testing/sysfs-class-typec). Port drivers should not
+enter any modes on their own.
+
+``->vdm`` is the most important callback in the operation callbacks vector. It
+will be used to deliver all the SVID specific commands from the partner to the
+alternate mode driver, and vice versa in case of port drivers. The drivers send
+the SVID specific commands to each other using :c:func:`typec_altmode_vmd()`.
+
+If the communication with the partner using the SVID specific commands results
+in need to reconfigure the pins on the connector, the alternate mode driver
+needs to notify the bus using :c:func:`typec_altmode_notify()`. The driver
+passes the negotiated SVID specific pin configuration value to the function as
+parameter. The bus driver will then configure the mux behind the connector using
+that value as the state value for the mux, and also call blocking notification
+chain to notify the external drivers about the state of the connector that need
+to know it.
+
+NOTE: The SVID specific pin configuration values must always start from
+``TYPEC_STATE_MODAL``. USB Type-C specification defines two default states for
+the connector: ``TYPEC_STATE_USB`` and ``TYPEC_STATE_SAFE``. These values are
+reserved by the bus as the first possible values for the state. When the
+alternate mode is entered, the bus will put the connector into
+``TYPEC_STATE_SAFE`` before sending Enter or Exit Mode command as defined in USB
+Type-C Specification, and also put the connector back to ``TYPEC_STATE_USB``
+after the mode has been exited.
+
+An example of working definitions for SVID specific pin configurations would
+look like this:
+
+enum {
+       ALTMODEX_CONF_A = TYPEC_STATE_MODAL,
+       ALTMODEX_CONF_B,
+       ...
+};
+
+Helper macro ``TYPEC_MODAL_STATE()`` can also be used:
+
+#define ALTMODEX_CONF_A = TYPEC_MODAL_STATE(0);
+#define ALTMODEX_CONF_B = TYPEC_MODAL_STATE(1);
+
+Notification chain
+~~~~~~~~~~~~~~~~~~
+
+The drivers for the components that the alternate modes are designed for need to
+get details regarding the results of the negotiation with the partner, and the
+pin configuration of the connector. In case of DisplayPort alternate mode for
+example, the GPU drivers will need to know those details. In case of
+Thunderbolt alternate mode, the thunderbolt drivers will need to know them, and
+so on.
+
+The notification chain is designed for this purpose. The drivers can register
+notifiers with :c:func:`typec_altmode_register_notifier()`.
+
+Cable plug alternate modes
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The alternate mode drivers are not bound to cable plug alternate mode devices,
+only to the partner alternate mode devices. If the alternate mode supports, or
+requires, a cable that responds to SOP Prime, and optionally SOP Double Prime
+messages, the driver for that alternate mode must request handle to the cable
+plug alternate modes using :c:func:`typec_altmode_get_plug()`, and take over
+their control.
+
+Driver API
+----------
+
+Alternate mode driver registering/unregistering
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/usb/typec/bus.c
+   :functions: typec_altmode_register_driver typec_altmode_unregister_driver
+
+Alternate mode driver operations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/usb/typec/bus.c
+   :functions: typec_altmode_enter typec_altmode_exit typec_altmode_attention typec_altmode_vdm typec_altmode_notify
+
+API for the port drivers
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/usb/typec/bus.c
+   :functions: typec_match_altmode
+
+Cable Plug operations
+~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/usb/typec/bus.c
+   :functions: typec_altmode_get_plug typec_altmode_put_plug
+
+Notifications
+~~~~~~~~~~~~~
+.. kernel-doc:: drivers/usb/typec/class.c
+   :functions: typec_altmode_register_notifier typec_altmode_unregister_notifier
index 349f3104fa4fc43359b74aa363450af598dd9b25..ab100d6ee43606461f32f096c0257ef2e7acea97 100644 (file)
@@ -418,15 +418,6 @@ Current status:
   why it is wise to cut down on the rate used is wise for large
   transfers until this is settled.
   
-Options supported:
-  If this driver is compiled as a module you can pass the following
-  options to it:
-  debug                        - extra verbose debugging info
-                         (default: 0; nonzero enables)
-  use_lowlatency       - use low_latency flag to speed up tty layer
-                         when reading from the device.
-                         (default: 0; nonzero enables)
-
   See http://www.uuhaus.de/linux/palmconnect.html for up-to-date
   information on this driver.
 
index e9336962d0f21fc1840bbb7f2bef774805d4277b..246afc0c2d7c95b919033aac740f36418282dfe0 100644 (file)
@@ -1665,7 +1665,8 @@ M:        Chunfeng Yun <chunfeng.yun@mediatek.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-mediatek@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-F:     drivers/phy/mediatek/phy-mtk-tphy.c
+F:     drivers/phy/mediatek/
+F:     Documentation/devicetree/bindings/phy/phy-mtk-*
 
 ARM/MICREL KS8695 ARCHITECTURE
 M:     Greg Ungerer <gerg@uclinux.org>
@@ -15117,7 +15118,7 @@ L:      linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/typec/mux/pi3usb30532.c
 
-USB TYPEC SUBSYSTEM
+USB TYPEC CLASS
 M:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
@@ -15126,6 +15127,15 @@ F:     Documentation/driver-api/usb/typec.rst
 F:     drivers/usb/typec/
 F:     include/linux/usb/typec.h
 
+USB TYPEC BUS FOR ALTERNATE MODES
+M:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
+L:     linux-usb@vger.kernel.org
+S:     Maintained
+F:     Documentation/ABI/testing/sysfs-bus-typec
+F:     Documentation/driver-api/usb/typec_bus.rst
+F:     drivers/usb/typec/altmodes/
+F:     include/linux/usb/typec_altmode.h
+
 USB UHCI DRIVER
 M:     Alan Stern <stern@rowland.harvard.edu>
 L:     linux-usb@vger.kernel.org
@@ -15156,6 +15166,7 @@ L:      linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/gadget/function/*uvc*
 F:     drivers/usb/gadget/legacy/webcam.c
+F:     include/uapi/linux/usb/g_uvc.h
 
 USB WIRELESS RNDIS DRIVER (rndis_wlan)
 M:     Jussi Kivilinna <jussi.kivilinna@iki.fi>
index bd35eab652be7cf503adc7d253ecb5ccab7d9ad0..945cc903d8f1123fd63a13c42564a3dfe7465a12 100644 (file)
@@ -160,13 +160,14 @@ static void nfcmrvl_tx_complete(struct urb *urb)
        struct nci_dev *ndev = (struct nci_dev *)skb->dev;
        struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
        struct nfcmrvl_usb_drv_data *drv_data = priv->drv_data;
+       unsigned long flags;
 
        nfc_info(priv->dev, "urb %p status %d count %d\n",
                 urb, urb->status, urb->actual_length);
 
-       spin_lock(&drv_data->txlock);
+       spin_lock_irqsave(&drv_data->txlock, flags);
        drv_data->tx_in_flight--;
-       spin_unlock(&drv_data->txlock);
+       spin_unlock_irqrestore(&drv_data->txlock, flags);
 
        kfree(urb->setup_packet);
        kfree_skb(skb);
index 97d27b0d5cc70987148800c6dcfa39e18a129e2d..8786a9674471de5a892238b7ad063a9aa7b68356 100644 (file)
@@ -80,3 +80,13 @@ config PHY_BRCM_USB
          This driver is required by the USB XHCI, EHCI and OHCI
          drivers.
          If unsure, say N.
+
+config PHY_BCM_SR_PCIE
+       tristate "Broadcom Stingray PCIe PHY driver"
+       depends on OF && (ARCH_BCM_IPROC || COMPILE_TEST)
+       select GENERIC_PHY
+       select MFD_SYSCON
+       default ARCH_BCM_IPROC
+       help
+         Enable this to support the Broadcom Stingray PCIe PHY
+         If unsure, say N.
index 13e000c1a43a5327c48274ada4bd6e7fa3b2eb91..0f60184e6662cdee48e219da866bb709c664d1f7 100644 (file)
@@ -9,3 +9,5 @@ obj-$(CONFIG_PHY_BRCM_SATA)             += phy-brcm-sata.o
 obj-$(CONFIG_PHY_BRCM_USB)             += phy-brcm-usb-dvr.o
 
 phy-brcm-usb-dvr-objs := phy-brcm-usb.o phy-brcm-usb-init.o
+
+obj-$(CONFIG_PHY_BCM_SR_PCIE)          += phy-bcm-sr-pcie.o
diff --git a/drivers/phy/broadcom/phy-bcm-sr-pcie.c b/drivers/phy/broadcom/phy-bcm-sr-pcie.c
new file mode 100644 (file)
index 0000000..c10e95f
--- /dev/null
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016-2018 Broadcom
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* we have up to 8 PAXB based RC. The 9th one is always PAXC */
+#define SR_NR_PCIE_PHYS               9
+#define SR_PAXC_PHY_IDX               (SR_NR_PCIE_PHYS - 1)
+
+#define PCIE_PIPEMUX_CFG_OFFSET       0x10c
+#define PCIE_PIPEMUX_SELECT_STRAP     0xf
+
+#define CDRU_STRAP_DATA_LSW_OFFSET    0x5c
+#define PCIE_PIPEMUX_SHIFT            19
+#define PCIE_PIPEMUX_MASK             0xf
+
+#define MHB_MEM_PW_PAXC_OFFSET        0x1c0
+#define MHB_PWR_ARR_POWERON           0x8
+#define MHB_PWR_ARR_POWEROK           0x4
+#define MHB_PWR_POWERON               0x2
+#define MHB_PWR_POWEROK               0x1
+#define MHB_PWR_STATUS_MASK           (MHB_PWR_ARR_POWERON | \
+                                      MHB_PWR_ARR_POWEROK | \
+                                      MHB_PWR_POWERON | \
+                                      MHB_PWR_POWEROK)
+
+struct sr_pcie_phy_core;
+
+/**
+ * struct sr_pcie_phy - Stingray PCIe PHY
+ *
+ * @core: pointer to the Stingray PCIe PHY core control
+ * @index: PHY index
+ * @phy: pointer to the kernel PHY device
+ */
+struct sr_pcie_phy {
+       struct sr_pcie_phy_core *core;
+       unsigned int index;
+       struct phy *phy;
+};
+
+/**
+ * struct sr_pcie_phy_core - Stingray PCIe PHY core control
+ *
+ * @dev: pointer to device
+ * @base: base register of PCIe SS
+ * @cdru: regmap to the CDRU device
+ * @mhb: regmap to the MHB device
+ * @pipemux: pipemuex strap
+ * @phys: array of PCIe PHYs
+ */
+struct sr_pcie_phy_core {
+       struct device *dev;
+       void __iomem *base;
+       struct regmap *cdru;
+       struct regmap *mhb;
+       u32 pipemux;
+       struct sr_pcie_phy phys[SR_NR_PCIE_PHYS];
+};
+
+/*
+ * PCIe PIPEMUX lookup table
+ *
+ * Each array index represents a PIPEMUX strap setting
+ * The array element represents a bitmap where a set bit means the PCIe
+ * core and associated serdes has been enabled as RC and is available for use
+ */
+static const u8 pipemux_table[] = {
+       /* PIPEMUX = 0, EP 1x16 */
+       0x00,
+       /* PIPEMUX = 1, EP 2x8 */
+       0x00,
+       /* PIPEMUX = 2, EP 4x4 */
+       0x00,
+       /* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+       0x81,
+       /* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+       0xc3,
+       /* PIPEMUX = 5, RC 8x2, all 8 cores */
+       0xff,
+       /* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
+       0xcd,
+       /* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
+       0xfd,
+       /* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
+       0xf0,
+       /* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
+       0xc0,
+       /* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
+       0x42,
+       /* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
+       0x3c,
+       /* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
+       0xfc,
+       /* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
+       0x4c,
+};
+
+/*
+ * Return true if the strap setting is valid
+ */
+static bool pipemux_strap_is_valid(u32 pipemux)
+{
+       return !!(pipemux < ARRAY_SIZE(pipemux_table));
+}
+
+/*
+ * Read the PCIe PIPEMUX from strap
+ */
+static u32 pipemux_strap_read(struct sr_pcie_phy_core *core)
+{
+       u32 pipemux;
+
+       /*
+        * Read PIPEMUX configuration register to determine the pipemux setting
+        *
+        * In the case when the value indicates using HW strap, fall back to
+        * use HW strap
+        */
+       pipemux = readl(core->base + PCIE_PIPEMUX_CFG_OFFSET);
+       pipemux &= PCIE_PIPEMUX_MASK;
+       if (pipemux == PCIE_PIPEMUX_SELECT_STRAP) {
+               regmap_read(core->cdru, CDRU_STRAP_DATA_LSW_OFFSET, &pipemux);
+               pipemux >>= PCIE_PIPEMUX_SHIFT;
+               pipemux &= PCIE_PIPEMUX_MASK;
+       }
+
+       return pipemux;
+}
+
+/*
+ * Given a PIPEMUX strap and PCIe core index, this function returns true if the
+ * PCIe core needs to be enabled
+ */
+static bool pcie_core_is_for_rc(struct sr_pcie_phy *phy)
+{
+       struct sr_pcie_phy_core *core = phy->core;
+       unsigned int core_idx = phy->index;
+
+       return !!((pipemux_table[core->pipemux] >> core_idx) & 0x1);
+}
+
+static int sr_pcie_phy_init(struct phy *p)
+{
+       struct sr_pcie_phy *phy = phy_get_drvdata(p);
+
+       /*
+        * Check whether this PHY is for root complex or not. If yes, return
+        * zero so the host driver can proceed to enumeration. If not, return
+        * an error and that will force the host driver to bail out
+        */
+       if (pcie_core_is_for_rc(phy))
+               return 0;
+
+       return -ENODEV;
+}
+
+static int sr_paxc_phy_init(struct phy *p)
+{
+       struct sr_pcie_phy *phy = phy_get_drvdata(p);
+       struct sr_pcie_phy_core *core = phy->core;
+       unsigned int core_idx = phy->index;
+       u32 val;
+
+       if (core_idx != SR_PAXC_PHY_IDX)
+               return -EINVAL;
+
+       regmap_read(core->mhb, MHB_MEM_PW_PAXC_OFFSET, &val);
+       if ((val & MHB_PWR_STATUS_MASK) != MHB_PWR_STATUS_MASK) {
+               dev_err(core->dev, "PAXC is not powered up\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static const struct phy_ops sr_pcie_phy_ops = {
+       .init = sr_pcie_phy_init,
+       .owner = THIS_MODULE,
+};
+
+static const struct phy_ops sr_paxc_phy_ops = {
+       .init = sr_paxc_phy_init,
+       .owner = THIS_MODULE,
+};
+
+static struct phy *sr_pcie_phy_xlate(struct device *dev,
+                                    struct of_phandle_args *args)
+{
+       struct sr_pcie_phy_core *core;
+       int phy_idx;
+
+       core = dev_get_drvdata(dev);
+       if (!core)
+               return ERR_PTR(-EINVAL);
+
+       phy_idx = args->args[0];
+
+       if (WARN_ON(phy_idx >= SR_NR_PCIE_PHYS))
+               return ERR_PTR(-ENODEV);
+
+       return core->phys[phy_idx].phy;
+}
+
+static int sr_pcie_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *node = dev->of_node;
+       struct sr_pcie_phy_core *core;
+       struct resource *res;
+       struct phy_provider *provider;
+       unsigned int phy_idx = 0;
+
+       core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL);
+       if (!core)
+               return -ENOMEM;
+
+       core->dev = dev;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       core->base = devm_ioremap_resource(core->dev, res);
+       if (IS_ERR(core->base))
+               return PTR_ERR(core->base);
+
+       core->cdru = syscon_regmap_lookup_by_phandle(node, "brcm,sr-cdru");
+       if (IS_ERR(core->cdru)) {
+               dev_err(core->dev, "unable to find CDRU device\n");
+               return PTR_ERR(core->cdru);
+       }
+
+       core->mhb = syscon_regmap_lookup_by_phandle(node, "brcm,sr-mhb");
+       if (IS_ERR(core->mhb)) {
+               dev_err(core->dev, "unable to find MHB device\n");
+               return PTR_ERR(core->mhb);
+       }
+
+       /* read the PCIe PIPEMUX strap setting */
+       core->pipemux = pipemux_strap_read(core);
+       if (!pipemux_strap_is_valid(core->pipemux)) {
+               dev_err(core->dev, "invalid PCIe PIPEMUX strap %u\n",
+                       core->pipemux);
+               return -EIO;
+       }
+
+       for (phy_idx = 0; phy_idx < SR_NR_PCIE_PHYS; phy_idx++) {
+               struct sr_pcie_phy *p = &core->phys[phy_idx];
+               const struct phy_ops *ops;
+
+               if (phy_idx == SR_PAXC_PHY_IDX)
+                       ops = &sr_paxc_phy_ops;
+               else
+                       ops = &sr_pcie_phy_ops;
+
+               p->phy = devm_phy_create(dev, NULL, ops);
+               if (IS_ERR(p->phy)) {
+                       dev_err(dev, "failed to create PCIe PHY\n");
+                       return PTR_ERR(p->phy);
+               }
+
+               p->core = core;
+               p->index = phy_idx;
+               phy_set_drvdata(p->phy, p);
+       }
+
+       dev_set_drvdata(dev, core);
+
+       provider = devm_of_phy_provider_register(dev, sr_pcie_phy_xlate);
+       if (IS_ERR(provider)) {
+               dev_err(dev, "failed to register PHY provider\n");
+               return PTR_ERR(provider);
+       }
+
+       dev_info(dev, "Stingray PCIe PHY driver initialized\n");
+
+       return 0;
+}
+
+static const struct of_device_id sr_pcie_phy_match_table[] = {
+       { .compatible = "brcm,sr-pcie-phy" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, sr_pcie_phy_match_table);
+
+static struct platform_driver sr_pcie_phy_driver = {
+       .driver = {
+               .name           = "sr-pcie-phy",
+               .of_match_table = sr_pcie_phy_match_table,
+       },
+       .probe  = sr_pcie_phy_probe,
+};
+module_platform_driver(sr_pcie_phy_driver);
+
+MODULE_AUTHOR("Ray Jui <ray.jui@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom Stingray PCIe PHY driver");
+MODULE_LICENSE("GPL v2");
index 2c7a57f2d595743c28d3efd66c36df2b3f37a727..c1bb6725e48f1cb548f03f3d95945afc3cb71854 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Marvell Berlin SATA PHY driver
  *
  * Copyright (C) 2014 Marvell Technology Group Ltd.
  *
  * Antoine Ténart <antoine.tenart@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
  */
 
 #include <linux/clk.h>
index 8f2b5cae360f2cb04f7789fac25c16a35a38e43c..a43df63007c5ccdf3186c59b609df4e43a4adda2 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2014 Marvell Technology Group Ltd.
  *
  * Antoine Tenart <antoine.tenart@free-electrons.com>
  * Jisheng Zhang <jszhang@marvell.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
  */
 
 #include <linux/io.h>
index 4ef429250d7b2afe05ffd4aa4201e2091d85773f..86a5f7b9448ba70a6944f5264c8bf1e58ea0fac0 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2017 Marvell
  *
  * Antoine Tenart <antoine.tenart@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
  */
 
 #include <linux/io.h>
index e5074b607d3dc12742d94d16ec52aeeab4b9a212..ee49edc97ee94d29ed2eeae0eb3293b0174ee370 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the phy drivers.
 #
index 38c281b5abbb0dfe339cf04929ee06fce6a5688e..3eb8e1bd7b78d5a23a335b2d9ca19ff0ae42f1d4 100644 (file)
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2015 MediaTek Inc.
  * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
  *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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 for more details.
- *
  */
 
 #include <dt-bindings/phy/phy.h>
 #define PA0_RG_U2PLL_FORCE_ON          BIT(15)
 #define PA0_RG_USB20_INTR_EN           BIT(5)
 
+#define U3P_USBPHYACR1         0x004
+#define PA1_RG_VRT_SEL                 GENMASK(14, 12)
+#define PA1_RG_VRT_SEL_VAL(x)  ((0x7 & (x)) << 12)
+#define PA1_RG_TERM_SEL                GENMASK(10, 8)
+#define PA1_RG_TERM_SEL_VAL(x) ((0x7 & (x)) << 8)
+
 #define U3P_USBPHYACR2         0x008
 #define PA2_RG_SIF_U2PLL_FORCE_EN      BIT(18)
 
 #define P2C_RG_AVALID                  BIT(2)
 #define P2C_RG_IDDIG                   BIT(1)
 
+#define U3P_U2PHYBC12C         0x080
+#define P2C_RG_CHGDT_EN                BIT(0)
+
 #define U3P_U3_CHIP_GPIO_CTLD          0x0c
 #define P3C_REG_IP_SW_RST              BIT(31)
 #define P3C_MCU_BUS_CK_GATE_EN         BIT(30)
@@ -296,6 +297,10 @@ struct mtk_phy_instance {
        struct clk *ref_clk;    /* reference clock of anolog phy */
        u32 index;
        u8 type;
+       int eye_src;
+       int eye_vrt;
+       int eye_term;
+       bool bc12_en;
 };
 
 struct mtk_tphy {
@@ -320,6 +325,10 @@ static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
        int fm_out;
        u32 tmp;
 
+       /* use force value */
+       if (instance->eye_src)
+               return;
+
        /* enable USB ring oscillator */
        tmp = readl(com + U3P_USBPHYACR5);
        tmp |= PA5_RG_U2_HSTX_SRCAL_EN;
@@ -826,6 +835,61 @@ static void phy_v2_banks_init(struct mtk_tphy *tphy,
        }
 }
 
+static void phy_parse_property(struct mtk_tphy *tphy,
+                               struct mtk_phy_instance *instance)
+{
+       struct device *dev = &instance->phy->dev;
+
+       if (instance->type != PHY_TYPE_USB2)
+               return;
+
+       instance->bc12_en = device_property_read_bool(dev, "mediatek,bc12");
+       device_property_read_u32(dev, "mediatek,eye-src",
+                                &instance->eye_src);
+       device_property_read_u32(dev, "mediatek,eye-vrt",
+                                &instance->eye_vrt);
+       device_property_read_u32(dev, "mediatek,eye-term",
+                                &instance->eye_term);
+       dev_dbg(dev, "bc12:%d, src:%d, vrt:%d, term:%d\n",
+               instance->bc12_en, instance->eye_src,
+               instance->eye_vrt, instance->eye_term);
+}
+
+static void u2_phy_props_set(struct mtk_tphy *tphy,
+                            struct mtk_phy_instance *instance)
+{
+       struct u2phy_banks *u2_banks = &instance->u2_banks;
+       void __iomem *com = u2_banks->com;
+       u32 tmp;
+
+       if (instance->bc12_en) {
+               tmp = readl(com + U3P_U2PHYBC12C);
+               tmp |= P2C_RG_CHGDT_EN; /* BC1.2 path Enable */
+               writel(tmp, com + U3P_U2PHYBC12C);
+       }
+
+       if (instance->eye_src) {
+               tmp = readl(com + U3P_USBPHYACR5);
+               tmp &= ~PA5_RG_U2_HSTX_SRCTRL;
+               tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(instance->eye_src);
+               writel(tmp, com + U3P_USBPHYACR5);
+       }
+
+       if (instance->eye_vrt) {
+               tmp = readl(com + U3P_USBPHYACR1);
+               tmp &= ~PA1_RG_VRT_SEL;
+               tmp |= PA1_RG_VRT_SEL_VAL(instance->eye_vrt);
+               writel(tmp, com + U3P_USBPHYACR1);
+       }
+
+       if (instance->eye_term) {
+               tmp = readl(com + U3P_USBPHYACR1);
+               tmp &= ~PA1_RG_TERM_SEL;
+               tmp |= PA1_RG_TERM_SEL_VAL(instance->eye_term);
+               writel(tmp, com + U3P_USBPHYACR1);
+       }
+}
+
 static int mtk_phy_init(struct phy *phy)
 {
        struct mtk_phy_instance *instance = phy_get_drvdata(phy);
@@ -847,6 +911,7 @@ static int mtk_phy_init(struct phy *phy)
        switch (instance->type) {
        case PHY_TYPE_USB2:
                u2_phy_instance_init(tphy, instance);
+               u2_phy_props_set(tphy, instance);
                break;
        case PHY_TYPE_USB3:
                u3_phy_instance_init(tphy, instance);
@@ -959,6 +1024,8 @@ static struct phy *mtk_phy_xlate(struct device *dev,
                return ERR_PTR(-EINVAL);
        }
 
+       phy_parse_property(tphy, instance);
+
        return instance->phy;
 }
 
index 2d0c70b5589f4fe4f325cde23c8b060340d2a69d..abbbe75070daa0263765262fd6d4395401cdba55 100644 (file)
@@ -55,6 +55,7 @@ static int qcom_usb_hs_phy_set_mode(struct phy *phy, enum phy_mode mode)
                case PHY_MODE_USB_OTG:
                case PHY_MODE_USB_HOST:
                        val |= ULPI_INT_IDGRD;
+                       /* fall through */
                case PHY_MODE_USB_DEVICE:
                        val |= ULPI_INT_SESS_VALID;
                default:
index c845facacb063e9a0bd2b244869d3c22c3409fbf..4bd390c79d214702044ed287c47194e82a1309b8 100644 (file)
@@ -8,6 +8,13 @@ config PHY_RCAR_GEN2
        help
          Support for USB PHY found on Renesas R-Car generation 2 SoCs.
 
+config PHY_RCAR_GEN3_PCIE
+       tristate "Renesas R-Car generation 3 PCIe PHY driver"
+       depends on ARCH_RENESAS
+       select GENERIC_PHY
+       help
+         Support for the PCIe PHY found on Renesas R-Car generation 3 SoCs.
+
 config PHY_RCAR_GEN3_USB2
        tristate "Renesas R-Car generation 3 USB 2.0 PHY driver"
        depends on ARCH_RENESAS
index 8b6025916a93ff3dafb3b734095c7384207fde74..4b76fc439ed66349ed4ca3b04c9789d42aee1a26 100644 (file)
@@ -1,3 +1,4 @@
 obj-$(CONFIG_PHY_RCAR_GEN2)            += phy-rcar-gen2.o
+obj-$(CONFIG_PHY_RCAR_GEN3_PCIE)       += phy-rcar-gen3-pcie.o
 obj-$(CONFIG_PHY_RCAR_GEN3_USB2)       += phy-rcar-gen3-usb2.o
 obj-$(CONFIG_PHY_RCAR_GEN3_USB3)       += phy-rcar-gen3-usb3.o
diff --git a/drivers/phy/renesas/phy-rcar-gen3-pcie.c b/drivers/phy/renesas/phy-rcar-gen3-pcie.c
new file mode 100644 (file)
index 0000000..c4e4aa2
--- /dev/null
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car Gen3 PCIe PHY driver
+ *
+ * Copyright (C) 2018 Cogent Embedded, Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#define PHY_CTRL               0x4000          /* R8A77980 only */
+
+/* PHY control register (PHY_CTRL) */
+#define PHY_CTRL_PHY_PWDN      BIT(2)
+
+struct rcar_gen3_phy {
+       struct phy *phy;
+       spinlock_t lock;
+       void __iomem *base;
+};
+
+static void rcar_gen3_phy_pcie_modify_reg(struct phy *p, unsigned int reg,
+                                         u32 clear, u32 set)
+{
+       struct rcar_gen3_phy *phy = phy_get_drvdata(p);
+       void __iomem *base = phy->base;
+       unsigned long flags;
+       u32 value;
+
+       spin_lock_irqsave(&phy->lock, flags);
+
+       value = readl(base + reg);
+       value &= ~clear;
+       value |= set;
+       writel(value, base + reg);
+
+       spin_unlock_irqrestore(&phy->lock, flags);
+}
+
+static int r8a77980_phy_pcie_power_on(struct phy *p)
+{
+       /* Power on the PCIe PHY */
+       rcar_gen3_phy_pcie_modify_reg(p, PHY_CTRL, PHY_CTRL_PHY_PWDN, 0);
+
+       return 0;
+}
+
+static int r8a77980_phy_pcie_power_off(struct phy *p)
+{
+       /* Power off the PCIe PHY */
+       rcar_gen3_phy_pcie_modify_reg(p, PHY_CTRL, 0, PHY_CTRL_PHY_PWDN);
+
+       return 0;
+}
+
+static const struct phy_ops r8a77980_phy_pcie_ops = {
+       .power_on       = r8a77980_phy_pcie_power_on,
+       .power_off      = r8a77980_phy_pcie_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static const struct of_device_id rcar_gen3_phy_pcie_match_table[] = {
+       { .compatible = "renesas,r8a77980-pcie-phy" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rcar_gen3_phy_pcie_match_table);
+
+static int rcar_gen3_phy_pcie_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct phy_provider *provider;
+       struct rcar_gen3_phy *phy;
+       struct resource *res;
+       void __iomem *base;
+       int error;
+
+       if (!dev->of_node) {
+               dev_err(dev,
+                       "This driver must only be instantiated from the device tree\n");
+               return -EINVAL;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+       if (!phy)
+               return -ENOMEM;
+
+       spin_lock_init(&phy->lock);
+
+       phy->base = base;
+
+       /*
+        * devm_phy_create() will call pm_runtime_enable(&phy->dev);
+        * And then, phy-core will manage runtime PM for this device.
+        */
+       pm_runtime_enable(dev);
+
+       phy->phy = devm_phy_create(dev, NULL, &r8a77980_phy_pcie_ops);
+       if (IS_ERR(phy->phy)) {
+               dev_err(dev, "Failed to create PCIe PHY\n");
+               error = PTR_ERR(phy->phy);
+               goto error;
+       }
+       phy_set_drvdata(phy->phy, phy);
+
+       provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(provider)) {
+               dev_err(dev, "Failed to register PHY provider\n");
+               error = PTR_ERR(provider);
+               goto error;
+       }
+
+       return 0;
+
+error:
+       pm_runtime_disable(dev);
+
+       return error;
+}
+
+static int rcar_gen3_phy_pcie_remove(struct platform_device *pdev)
+{
+       pm_runtime_disable(&pdev->dev);
+
+       return 0;
+};
+
+static struct platform_driver rcar_gen3_phy_driver = {
+       .driver = {
+               .name           = "phy_rcar_gen3_pcie",
+               .of_match_table = rcar_gen3_phy_pcie_match_table,
+       },
+       .probe  = rcar_gen3_phy_pcie_probe,
+       .remove = rcar_gen3_phy_pcie_remove,
+};
+
+module_platform_driver(rcar_gen3_phy_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas R-Car Gen3 PCIe PHY");
+MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>");
index 75a480497d22192e1010b42585336c0929d44343..af9a82f5c4b76b8e1c44c0970874ce8d6b8b9202 100644 (file)
@@ -106,8 +106,6 @@ source "drivers/staging/greybus/Kconfig"
 
 source "drivers/staging/vc04_services/Kconfig"
 
-source "drivers/staging/typec/Kconfig"
-
 source "drivers/staging/vboxvideo/Kconfig"
 
 source "drivers/staging/pi433/Kconfig"
index e84959a8a684c42e43e091a285dd3f7f3f91e07e..8479d47d78d7538383de706fbb9d20257465f4da 100644 (file)
@@ -2,7 +2,6 @@
 # Makefile for staging directory
 
 obj-y                          += media/
-obj-y                          += typec/
 obj-$(CONFIG_PRISM2_USB)       += wlan-ng/
 obj-$(CONFIG_COMEDI)           += comedi/
 obj-$(CONFIG_FB_OLPC_DCON)     += olpc_dcon/
diff --git a/drivers/staging/typec/Kconfig b/drivers/staging/typec/Kconfig
deleted file mode 100644 (file)
index e45ed08..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-menu "USB Power Delivery and Type-C drivers"
-
-if TYPEC_TCPM
-
-config TYPEC_TCPCI
-       tristate "Type-C Port Controller Interface driver"
-       depends on I2C
-       select REGMAP_I2C
-       help
-         Type-C Port Controller driver for TCPCI-compliant controller.
-
-config TYPEC_RT1711H
-       tristate "Richtek RT1711H Type-C chip driver"
-       depends on I2C
-       select TYPEC_TCPCI
-       help
-         Richtek RT1711H Type-C chip driver that works with
-         Type-C Port Controller Manager to provide USB PD and USB
-         Type-C functionalities.
-
-endif
-
-endmenu
diff --git a/drivers/staging/typec/Makefile b/drivers/staging/typec/Makefile
deleted file mode 100644 (file)
index 7803d48..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_TYPEC_TCPCI)      += tcpci.o
-obj-$(CONFIG_TYPEC_RT1711H)    += tcpci_rt1711h.o
diff --git a/drivers/staging/typec/TODO b/drivers/staging/typec/TODO
deleted file mode 100644 (file)
index 53fe2f7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-tcpci:
-- Test with real hardware
-
-Please send patches to Guenter Roeck <linux@roeck-us.net> and copy
-Heikki Krogerus <heikki.krogerus@linux.intel.com>.
diff --git a/drivers/staging/typec/tcpci.c b/drivers/staging/typec/tcpci.c
deleted file mode 100644 (file)
index 076d97e..0000000
+++ /dev/null
@@ -1,596 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2015-2017 Google, Inc
- *
- * USB Type-C Port Controller Interface.
- */
-
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/regmap.h>
-#include <linux/usb/pd.h>
-#include <linux/usb/tcpm.h>
-#include <linux/usb/typec.h>
-
-#include "tcpci.h"
-
-#define PD_RETRY_COUNT 3
-
-struct tcpci {
-       struct device *dev;
-
-       struct tcpm_port *port;
-
-       struct regmap *regmap;
-
-       bool controls_vbus;
-
-       struct tcpc_dev tcpc;
-       struct tcpci_data *data;
-};
-
-struct tcpci_chip {
-       struct tcpci *tcpci;
-       struct tcpci_data data;
-};
-
-static inline struct tcpci *tcpc_to_tcpci(struct tcpc_dev *tcpc)
-{
-       return container_of(tcpc, struct tcpci, tcpc);
-}
-
-static int tcpci_read16(struct tcpci *tcpci, unsigned int reg, u16 *val)
-{
-       return regmap_raw_read(tcpci->regmap, reg, val, sizeof(u16));
-}
-
-static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val)
-{
-       return regmap_raw_write(tcpci->regmap, reg, &val, sizeof(u16));
-}
-
-static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
-{
-       struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
-       unsigned int reg;
-       int ret;
-
-       switch (cc) {
-       case TYPEC_CC_RA:
-               reg = (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC1_SHIFT) |
-                       (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC2_SHIFT);
-               break;
-       case TYPEC_CC_RD:
-               reg = (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) |
-                       (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT);
-               break;
-       case TYPEC_CC_RP_DEF:
-               reg = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
-                       (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) |
-                       (TCPC_ROLE_CTRL_RP_VAL_DEF <<
-                        TCPC_ROLE_CTRL_RP_VAL_SHIFT);
-               break;
-       case TYPEC_CC_RP_1_5:
-               reg = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
-                       (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) |
-                       (TCPC_ROLE_CTRL_RP_VAL_1_5 <<
-                        TCPC_ROLE_CTRL_RP_VAL_SHIFT);
-               break;
-       case TYPEC_CC_RP_3_0:
-               reg = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
-                       (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) |
-                       (TCPC_ROLE_CTRL_RP_VAL_3_0 <<
-                        TCPC_ROLE_CTRL_RP_VAL_SHIFT);
-               break;
-       case TYPEC_CC_OPEN:
-       default:
-               reg = (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT) |
-                       (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT);
-               break;
-       }
-
-       ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-static int tcpci_start_drp_toggling(struct tcpc_dev *tcpc,
-                                   enum typec_cc_status cc)
-{
-       int ret;
-       struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
-       unsigned int reg = TCPC_ROLE_CTRL_DRP;
-
-       /* Handle vendor drp toggling */
-       if (tcpci->data->start_drp_toggling) {
-               ret = tcpci->data->start_drp_toggling(tcpci, tcpci->data, cc);
-               if (ret < 0)
-                       return ret;
-       }
-
-       switch (cc) {
-       default:
-       case TYPEC_CC_RP_DEF:
-               reg |= (TCPC_ROLE_CTRL_RP_VAL_DEF <<
-                       TCPC_ROLE_CTRL_RP_VAL_SHIFT);
-               break;
-       case TYPEC_CC_RP_1_5:
-               reg |= (TCPC_ROLE_CTRL_RP_VAL_1_5 <<
-                       TCPC_ROLE_CTRL_RP_VAL_SHIFT);
-               break;
-       case TYPEC_CC_RP_3_0:
-               reg |= (TCPC_ROLE_CTRL_RP_VAL_3_0 <<
-                       TCPC_ROLE_CTRL_RP_VAL_SHIFT);
-               break;
-       }
-
-       if (cc == TYPEC_CC_RD)
-               reg |= (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) |
-                          (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT);
-       else
-               reg |= (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
-                          (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT);
-       ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg);
-       if (ret < 0)
-               return ret;
-       return regmap_write(tcpci->regmap, TCPC_COMMAND,
-                           TCPC_CMD_LOOK4CONNECTION);
-}
-
-static enum typec_cc_status tcpci_to_typec_cc(unsigned int cc, bool sink)
-{
-       switch (cc) {
-       case 0x1:
-               return sink ? TYPEC_CC_RP_DEF : TYPEC_CC_RA;
-       case 0x2:
-               return sink ? TYPEC_CC_RP_1_5 : TYPEC_CC_RD;
-       case 0x3:
-               if (sink)
-                       return TYPEC_CC_RP_3_0;
-               /* fall through */
-       case 0x0:
-       default:
-               return TYPEC_CC_OPEN;
-       }
-}
-
-static int tcpci_get_cc(struct tcpc_dev *tcpc,
-                       enum typec_cc_status *cc1, enum typec_cc_status *cc2)
-{
-       struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
-       unsigned int reg;
-       int ret;
-
-       ret = regmap_read(tcpci->regmap, TCPC_CC_STATUS, &reg);
-       if (ret < 0)
-               return ret;
-
-       *cc1 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC1_SHIFT) &
-                                TCPC_CC_STATUS_CC1_MASK,
-                                reg & TCPC_CC_STATUS_TERM);
-       *cc2 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC2_SHIFT) &
-                                TCPC_CC_STATUS_CC2_MASK,
-                                reg & TCPC_CC_STATUS_TERM);
-
-       return 0;
-}
-
-static int tcpci_set_polarity(struct tcpc_dev *tcpc,
-                             enum typec_cc_polarity polarity)
-{
-       struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
-       int ret;
-
-       ret = regmap_write(tcpci->regmap, TCPC_TCPC_CTRL,
-                          (polarity == TYPEC_POLARITY_CC2) ?
-                          TCPC_TCPC_CTRL_ORIENTATION : 0);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-static int tcpci_set_vconn(struct tcpc_dev *tcpc, bool enable)
-{
-       struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
-       int ret;
-
-       /* Handle vendor set vconn */
-       if (tcpci->data->set_vconn) {
-               ret = tcpci->data->set_vconn(tcpci, tcpci->data, enable);
-               if (ret < 0)
-                       return ret;
-       }
-
-       ret = regmap_write(tcpci->regmap, TCPC_POWER_CTRL,
-                          enable ? TCPC_POWER_CTRL_VCONN_ENABLE : 0);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-static int tcpci_set_roles(struct tcpc_dev *tcpc, bool attached,
-                          enum typec_role role, enum typec_data_role data)
-{
-       struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
-       unsigned int reg;
-       int ret;
-
-       reg = PD_REV20 << TCPC_MSG_HDR_INFO_REV_SHIFT;
-       if (role == TYPEC_SOURCE)
-               reg |= TCPC_MSG_HDR_INFO_PWR_ROLE;
-       if (data == TYPEC_HOST)
-               reg |= TCPC_MSG_HDR_INFO_DATA_ROLE;
-       ret = regmap_write(tcpci->regmap, TCPC_MSG_HDR_INFO, reg);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-static int tcpci_set_pd_rx(struct tcpc_dev *tcpc, bool enable)
-{
-       struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
-       unsigned int reg = 0;
-       int ret;
-
-       if (enable)
-               reg = TCPC_RX_DETECT_SOP | TCPC_RX_DETECT_HARD_RESET;
-       ret = regmap_write(tcpci->regmap, TCPC_RX_DETECT, reg);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-static int tcpci_get_vbus(struct tcpc_dev *tcpc)
-{
-       struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
-       unsigned int reg;
-       int ret;
-
-       ret = regmap_read(tcpci->regmap, TCPC_POWER_STATUS, &reg);
-       if (ret < 0)
-               return ret;
-
-       return !!(reg & TCPC_POWER_STATUS_VBUS_PRES);
-}
-
-static int tcpci_set_vbus(struct tcpc_dev *tcpc, bool source, bool sink)
-{
-       struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
-       int ret;
-
-       /* Disable both source and sink first before enabling anything */
-
-       if (!source) {
-               ret = regmap_write(tcpci->regmap, TCPC_COMMAND,
-                                  TCPC_CMD_DISABLE_SRC_VBUS);
-               if (ret < 0)
-                       return ret;
-       }
-
-       if (!sink) {
-               ret = regmap_write(tcpci->regmap, TCPC_COMMAND,
-                                  TCPC_CMD_DISABLE_SINK_VBUS);
-               if (ret < 0)
-                       return ret;
-       }
-
-       if (source) {
-               ret = regmap_write(tcpci->regmap, TCPC_COMMAND,
-                                  TCPC_CMD_SRC_VBUS_DEFAULT);
-               if (ret < 0)
-                       return ret;
-       }
-
-       if (sink) {
-               ret = regmap_write(tcpci->regmap, TCPC_COMMAND,
-                                  TCPC_CMD_SINK_VBUS);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int tcpci_pd_transmit(struct tcpc_dev *tcpc,
-                            enum tcpm_transmit_type type,
-                            const struct pd_message *msg)
-{
-       struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
-       u16 header = msg ? le16_to_cpu(msg->header) : 0;
-       unsigned int reg, cnt;
-       int ret;
-
-       cnt = msg ? pd_header_cnt(header) * 4 : 0;
-       ret = regmap_write(tcpci->regmap, TCPC_TX_BYTE_CNT, cnt + 2);
-       if (ret < 0)
-               return ret;
-
-       ret = tcpci_write16(tcpci, TCPC_TX_HDR, header);
-       if (ret < 0)
-               return ret;
-
-       if (cnt > 0) {
-               ret = regmap_raw_write(tcpci->regmap, TCPC_TX_DATA,
-                                      &msg->payload, cnt);
-               if (ret < 0)
-                       return ret;
-       }
-
-       reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) |
-               (type << TCPC_TRANSMIT_TYPE_SHIFT);
-       ret = regmap_write(tcpci->regmap, TCPC_TRANSMIT, reg);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-static int tcpci_init(struct tcpc_dev *tcpc)
-{
-       struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
-       unsigned long timeout = jiffies + msecs_to_jiffies(2000); /* XXX */
-       unsigned int reg;
-       int ret;
-
-       while (time_before_eq(jiffies, timeout)) {
-               ret = regmap_read(tcpci->regmap, TCPC_POWER_STATUS, &reg);
-               if (ret < 0)
-                       return ret;
-               if (!(reg & TCPC_POWER_STATUS_UNINIT))
-                       break;
-               usleep_range(10000, 20000);
-       }
-       if (time_after(jiffies, timeout))
-               return -ETIMEDOUT;
-
-       /* Handle vendor init */
-       if (tcpci->data->init) {
-               ret = tcpci->data->init(tcpci, tcpci->data);
-               if (ret < 0)
-                       return ret;
-       }
-
-       /* Clear all events */
-       ret = tcpci_write16(tcpci, TCPC_ALERT, 0xffff);
-       if (ret < 0)
-               return ret;
-
-       if (tcpci->controls_vbus)
-               reg = TCPC_POWER_STATUS_VBUS_PRES;
-       else
-               reg = 0;
-       ret = regmap_write(tcpci->regmap, TCPC_POWER_STATUS_MASK, reg);
-       if (ret < 0)
-               return ret;
-
-       reg = TCPC_ALERT_TX_SUCCESS | TCPC_ALERT_TX_FAILED |
-               TCPC_ALERT_TX_DISCARDED | TCPC_ALERT_RX_STATUS |
-               TCPC_ALERT_RX_HARD_RST | TCPC_ALERT_CC_STATUS;
-       if (tcpci->controls_vbus)
-               reg |= TCPC_ALERT_POWER_STATUS;
-       return tcpci_write16(tcpci, TCPC_ALERT_MASK, reg);
-}
-
-irqreturn_t tcpci_irq(struct tcpci *tcpci)
-{
-       u16 status;
-
-       tcpci_read16(tcpci, TCPC_ALERT, &status);
-
-       /*
-        * Clear alert status for everything except RX_STATUS, which shouldn't
-        * be cleared until we have successfully retrieved message.
-        */
-       if (status & ~TCPC_ALERT_RX_STATUS)
-               tcpci_write16(tcpci, TCPC_ALERT,
-                             status & ~TCPC_ALERT_RX_STATUS);
-
-       if (status & TCPC_ALERT_CC_STATUS)
-               tcpm_cc_change(tcpci->port);
-
-       if (status & TCPC_ALERT_POWER_STATUS) {
-               unsigned int reg;
-
-               regmap_read(tcpci->regmap, TCPC_POWER_STATUS_MASK, &reg);
-
-               /*
-                * If power status mask has been reset, then the TCPC
-                * has reset.
-                */
-               if (reg == 0xff)
-                       tcpm_tcpc_reset(tcpci->port);
-               else
-                       tcpm_vbus_change(tcpci->port);
-       }
-
-       if (status & TCPC_ALERT_RX_STATUS) {
-               struct pd_message msg;
-               unsigned int cnt;
-               u16 header;
-
-               regmap_read(tcpci->regmap, TCPC_RX_BYTE_CNT, &cnt);
-
-               tcpci_read16(tcpci, TCPC_RX_HDR, &header);
-               msg.header = cpu_to_le16(header);
-
-               if (WARN_ON(cnt > sizeof(msg.payload)))
-                       cnt = sizeof(msg.payload);
-
-               if (cnt > 0)
-                       regmap_raw_read(tcpci->regmap, TCPC_RX_DATA,
-                                       &msg.payload, cnt);
-
-               /* Read complete, clear RX status alert bit */
-               tcpci_write16(tcpci, TCPC_ALERT, TCPC_ALERT_RX_STATUS);
-
-               tcpm_pd_receive(tcpci->port, &msg);
-       }
-
-       if (status & TCPC_ALERT_RX_HARD_RST)
-               tcpm_pd_hard_reset(tcpci->port);
-
-       if (status & TCPC_ALERT_TX_SUCCESS)
-               tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_SUCCESS);
-       else if (status & TCPC_ALERT_TX_DISCARDED)
-               tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_DISCARDED);
-       else if (status & TCPC_ALERT_TX_FAILED)
-               tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_FAILED);
-
-       return IRQ_HANDLED;
-}
-EXPORT_SYMBOL_GPL(tcpci_irq);
-
-static irqreturn_t _tcpci_irq(int irq, void *dev_id)
-{
-       struct tcpci_chip *chip = dev_id;
-
-       return tcpci_irq(chip->tcpci);
-}
-
-static const struct regmap_config tcpci_regmap_config = {
-       .reg_bits = 8,
-       .val_bits = 8,
-
-       .max_register = 0x7F, /* 0x80 .. 0xFF are vendor defined */
-};
-
-static const struct tcpc_config tcpci_tcpc_config = {
-       .type = TYPEC_PORT_DFP,
-       .default_role = TYPEC_SINK,
-};
-
-static int tcpci_parse_config(struct tcpci *tcpci)
-{
-       tcpci->controls_vbus = true; /* XXX */
-
-       /* TODO: Populate struct tcpc_config from ACPI/device-tree */
-       tcpci->tcpc.config = &tcpci_tcpc_config;
-
-       return 0;
-}
-
-struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data)
-{
-       struct tcpci *tcpci;
-       int err;
-
-       tcpci = devm_kzalloc(dev, sizeof(*tcpci), GFP_KERNEL);
-       if (!tcpci)
-               return ERR_PTR(-ENOMEM);
-
-       tcpci->dev = dev;
-       tcpci->data = data;
-       tcpci->regmap = data->regmap;
-
-       tcpci->tcpc.init = tcpci_init;
-       tcpci->tcpc.get_vbus = tcpci_get_vbus;
-       tcpci->tcpc.set_vbus = tcpci_set_vbus;
-       tcpci->tcpc.set_cc = tcpci_set_cc;
-       tcpci->tcpc.get_cc = tcpci_get_cc;
-       tcpci->tcpc.set_polarity = tcpci_set_polarity;
-       tcpci->tcpc.set_vconn = tcpci_set_vconn;
-       tcpci->tcpc.start_drp_toggling = tcpci_start_drp_toggling;
-
-       tcpci->tcpc.set_pd_rx = tcpci_set_pd_rx;
-       tcpci->tcpc.set_roles = tcpci_set_roles;
-       tcpci->tcpc.pd_transmit = tcpci_pd_transmit;
-
-       err = tcpci_parse_config(tcpci);
-       if (err < 0)
-               return ERR_PTR(err);
-
-       tcpci->port = tcpm_register_port(tcpci->dev, &tcpci->tcpc);
-       if (PTR_ERR_OR_ZERO(tcpci->port))
-               return ERR_CAST(tcpci->port);
-
-       return tcpci;
-}
-EXPORT_SYMBOL_GPL(tcpci_register_port);
-
-void tcpci_unregister_port(struct tcpci *tcpci)
-{
-       tcpm_unregister_port(tcpci->port);
-}
-EXPORT_SYMBOL_GPL(tcpci_unregister_port);
-
-static int tcpci_probe(struct i2c_client *client,
-                      const struct i2c_device_id *i2c_id)
-{
-       struct tcpci_chip *chip;
-       int err;
-       u16 val = 0;
-
-       chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
-       if (!chip)
-               return -ENOMEM;
-
-       chip->data.regmap = devm_regmap_init_i2c(client, &tcpci_regmap_config);
-       if (IS_ERR(chip->data.regmap))
-               return PTR_ERR(chip->data.regmap);
-
-       /* Disable chip interrupts before requesting irq */
-       err = regmap_raw_write(chip->data.regmap, TCPC_ALERT_MASK, &val,
-                              sizeof(u16));
-       if (err < 0)
-               return err;
-
-       err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
-                                       _tcpci_irq,
-                                       IRQF_ONESHOT | IRQF_TRIGGER_LOW,
-                                       dev_name(&client->dev), chip);
-       if (err < 0)
-               return err;
-
-       chip->tcpci = tcpci_register_port(&client->dev, &chip->data);
-       if (PTR_ERR_OR_ZERO(chip->tcpci))
-               return PTR_ERR(chip->tcpci);
-
-       i2c_set_clientdata(client, chip);
-       return 0;
-}
-
-static int tcpci_remove(struct i2c_client *client)
-{
-       struct tcpci_chip *chip = i2c_get_clientdata(client);
-
-       tcpci_unregister_port(chip->tcpci);
-
-       return 0;
-}
-
-static const struct i2c_device_id tcpci_id[] = {
-       { "tcpci", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, tcpci_id);
-
-#ifdef CONFIG_OF
-static const struct of_device_id tcpci_of_match[] = {
-       { .compatible = "usb,tcpci", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, tcpci_of_match);
-#endif
-
-static struct i2c_driver tcpci_i2c_driver = {
-       .driver = {
-               .name = "tcpci",
-               .of_match_table = of_match_ptr(tcpci_of_match),
-       },
-       .probe = tcpci_probe,
-       .remove = tcpci_remove,
-       .id_table = tcpci_id,
-};
-module_i2c_driver(tcpci_i2c_driver);
-
-MODULE_DESCRIPTION("USB Type-C Port Controller Interface driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/typec/tcpci.h b/drivers/staging/typec/tcpci.h
deleted file mode 100644 (file)
index 303ebde..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright 2015-2017 Google, Inc
- *
- * USB Type-C Port Controller Interface.
- */
-
-#ifndef __LINUX_USB_TCPCI_H
-#define __LINUX_USB_TCPCI_H
-
-#define TCPC_VENDOR_ID                 0x0
-#define TCPC_PRODUCT_ID                        0x2
-#define TCPC_BCD_DEV                   0x4
-#define TCPC_TC_REV                    0x6
-#define TCPC_PD_REV                    0x8
-#define TCPC_PD_INT_REV                        0xa
-
-#define TCPC_ALERT                     0x10
-#define TCPC_ALERT_VBUS_DISCNCT                BIT(11)
-#define TCPC_ALERT_RX_BUF_OVF          BIT(10)
-#define TCPC_ALERT_FAULT               BIT(9)
-#define TCPC_ALERT_V_ALARM_LO          BIT(8)
-#define TCPC_ALERT_V_ALARM_HI          BIT(7)
-#define TCPC_ALERT_TX_SUCCESS          BIT(6)
-#define TCPC_ALERT_TX_DISCARDED                BIT(5)
-#define TCPC_ALERT_TX_FAILED           BIT(4)
-#define TCPC_ALERT_RX_HARD_RST         BIT(3)
-#define TCPC_ALERT_RX_STATUS           BIT(2)
-#define TCPC_ALERT_POWER_STATUS                BIT(1)
-#define TCPC_ALERT_CC_STATUS           BIT(0)
-
-#define TCPC_ALERT_MASK                        0x12
-#define TCPC_POWER_STATUS_MASK         0x14
-#define TCPC_FAULT_STATUS_MASK         0x15
-#define TCPC_CONFIG_STD_OUTPUT         0x18
-
-#define TCPC_TCPC_CTRL                 0x19
-#define TCPC_TCPC_CTRL_ORIENTATION     BIT(0)
-
-#define TCPC_ROLE_CTRL                 0x1a
-#define TCPC_ROLE_CTRL_DRP             BIT(6)
-#define TCPC_ROLE_CTRL_RP_VAL_SHIFT    4
-#define TCPC_ROLE_CTRL_RP_VAL_MASK     0x3
-#define TCPC_ROLE_CTRL_RP_VAL_DEF      0x0
-#define TCPC_ROLE_CTRL_RP_VAL_1_5      0x1
-#define TCPC_ROLE_CTRL_RP_VAL_3_0      0x2
-#define TCPC_ROLE_CTRL_CC2_SHIFT       2
-#define TCPC_ROLE_CTRL_CC2_MASK                0x3
-#define TCPC_ROLE_CTRL_CC1_SHIFT       0
-#define TCPC_ROLE_CTRL_CC1_MASK                0x3
-#define TCPC_ROLE_CTRL_CC_RA           0x0
-#define TCPC_ROLE_CTRL_CC_RP           0x1
-#define TCPC_ROLE_CTRL_CC_RD           0x2
-#define TCPC_ROLE_CTRL_CC_OPEN         0x3
-
-#define TCPC_FAULT_CTRL                        0x1b
-
-#define TCPC_POWER_CTRL                        0x1c
-#define TCPC_POWER_CTRL_VCONN_ENABLE   BIT(0)
-
-#define TCPC_CC_STATUS                 0x1d
-#define TCPC_CC_STATUS_TOGGLING                BIT(5)
-#define TCPC_CC_STATUS_TERM            BIT(4)
-#define TCPC_CC_STATUS_CC2_SHIFT       2
-#define TCPC_CC_STATUS_CC2_MASK                0x3
-#define TCPC_CC_STATUS_CC1_SHIFT       0
-#define TCPC_CC_STATUS_CC1_MASK                0x3
-
-#define TCPC_POWER_STATUS              0x1e
-#define TCPC_POWER_STATUS_UNINIT       BIT(6)
-#define TCPC_POWER_STATUS_VBUS_DET     BIT(3)
-#define TCPC_POWER_STATUS_VBUS_PRES    BIT(2)
-
-#define TCPC_FAULT_STATUS              0x1f
-
-#define TCPC_COMMAND                   0x23
-#define TCPC_CMD_WAKE_I2C              0x11
-#define TCPC_CMD_DISABLE_VBUS_DETECT   0x22
-#define TCPC_CMD_ENABLE_VBUS_DETECT    0x33
-#define TCPC_CMD_DISABLE_SINK_VBUS     0x44
-#define TCPC_CMD_SINK_VBUS             0x55
-#define TCPC_CMD_DISABLE_SRC_VBUS      0x66
-#define TCPC_CMD_SRC_VBUS_DEFAULT      0x77
-#define TCPC_CMD_SRC_VBUS_HIGH         0x88
-#define TCPC_CMD_LOOK4CONNECTION       0x99
-#define TCPC_CMD_RXONEMORE             0xAA
-#define TCPC_CMD_I2C_IDLE              0xFF
-
-#define TCPC_DEV_CAP_1                 0x24
-#define TCPC_DEV_CAP_2                 0x26
-#define TCPC_STD_INPUT_CAP             0x28
-#define TCPC_STD_OUTPUT_CAP            0x29
-
-#define TCPC_MSG_HDR_INFO              0x2e
-#define TCPC_MSG_HDR_INFO_DATA_ROLE    BIT(3)
-#define TCPC_MSG_HDR_INFO_PWR_ROLE     BIT(0)
-#define TCPC_MSG_HDR_INFO_REV_SHIFT    1
-#define TCPC_MSG_HDR_INFO_REV_MASK     0x3
-
-#define TCPC_RX_DETECT                 0x2f
-#define TCPC_RX_DETECT_HARD_RESET      BIT(5)
-#define TCPC_RX_DETECT_SOP             BIT(0)
-
-#define TCPC_RX_BYTE_CNT               0x30
-#define TCPC_RX_BUF_FRAME_TYPE         0x31
-#define TCPC_RX_HDR                    0x32
-#define TCPC_RX_DATA                   0x34 /* through 0x4f */
-
-#define TCPC_TRANSMIT                  0x50
-#define TCPC_TRANSMIT_RETRY_SHIFT      4
-#define TCPC_TRANSMIT_RETRY_MASK       0x3
-#define TCPC_TRANSMIT_TYPE_SHIFT       0
-#define TCPC_TRANSMIT_TYPE_MASK                0x7
-
-#define TCPC_TX_BYTE_CNT               0x51
-#define TCPC_TX_HDR                    0x52
-#define TCPC_TX_DATA                   0x54 /* through 0x6f */
-
-#define TCPC_VBUS_VOLTAGE                      0x70
-#define TCPC_VBUS_SINK_DISCONNECT_THRESH       0x72
-#define TCPC_VBUS_STOP_DISCHARGE_THRESH                0x74
-#define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG         0x76
-#define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG         0x78
-
-struct tcpci;
-struct tcpci_data {
-       struct regmap *regmap;
-       int (*init)(struct tcpci *tcpci, struct tcpci_data *data);
-       int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data,
-                        bool enable);
-       int (*start_drp_toggling)(struct tcpci *tcpci, struct tcpci_data *data,
-                                 enum typec_cc_status cc);
-};
-
-struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data);
-void tcpci_unregister_port(struct tcpci *tcpci);
-irqreturn_t tcpci_irq(struct tcpci *tcpci);
-
-#endif /* __LINUX_USB_TCPCI_H */
diff --git a/drivers/staging/typec/tcpci_rt1711h.c b/drivers/staging/typec/tcpci_rt1711h.c
deleted file mode 100644 (file)
index 0173890..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2018, Richtek Technology Corporation
- *
- * Richtek RT1711H Type-C Chip Driver
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/gpio/consumer.h>
-#include <linux/usb/tcpm.h>
-#include <linux/regmap.h>
-#include "tcpci.h"
-
-#define RT1711H_VID            0x29CF
-#define RT1711H_PID            0x1711
-
-#define RT1711H_RTCTRL8                0x9B
-
-/* Autoidle timeout = (tout * 2 + 1) * 6.4ms */
-#define RT1711H_RTCTRL8_SET(ck300, ship_off, auto_idle, tout) \
-                           (((ck300) << 7) | ((ship_off) << 5) | \
-                           ((auto_idle) << 3) | ((tout) & 0x07))
-
-#define RT1711H_RTCTRL11       0x9E
-
-/* I2C timeout = (tout + 1) * 12.5ms */
-#define RT1711H_RTCTRL11_SET(en, tout) \
-                            (((en) << 7) | ((tout) & 0x0F))
-
-#define RT1711H_RTCTRL13       0xA0
-#define RT1711H_RTCTRL14       0xA1
-#define RT1711H_RTCTRL15       0xA2
-#define RT1711H_RTCTRL16       0xA3
-
-struct rt1711h_chip {
-       struct tcpci_data data;
-       struct tcpci *tcpci;
-       struct device *dev;
-};
-
-static int rt1711h_read16(struct rt1711h_chip *chip, unsigned int reg, u16 *val)
-{
-       return regmap_raw_read(chip->data.regmap, reg, val, sizeof(u16));
-}
-
-static int rt1711h_write16(struct rt1711h_chip *chip, unsigned int reg, u16 val)
-{
-       return regmap_raw_write(chip->data.regmap, reg, &val, sizeof(u16));
-}
-
-static int rt1711h_read8(struct rt1711h_chip *chip, unsigned int reg, u8 *val)
-{
-       return regmap_raw_read(chip->data.regmap, reg, val, sizeof(u8));
-}
-
-static int rt1711h_write8(struct rt1711h_chip *chip, unsigned int reg, u8 val)
-{
-       return regmap_raw_write(chip->data.regmap, reg, &val, sizeof(u8));
-}
-
-static const struct regmap_config rt1711h_regmap_config = {
-       .reg_bits = 8,
-       .val_bits = 8,
-
-       .max_register = 0xFF, /* 0x80 .. 0xFF are vendor defined */
-};
-
-static struct rt1711h_chip *tdata_to_rt1711h(struct tcpci_data *tdata)
-{
-       return container_of(tdata, struct rt1711h_chip, data);
-}
-
-static int rt1711h_init(struct tcpci *tcpci, struct tcpci_data *tdata)
-{
-       int ret;
-       struct rt1711h_chip *chip = tdata_to_rt1711h(tdata);
-
-       /* CK 300K from 320K, shipping off, auto_idle enable, tout = 32ms */
-       ret = rt1711h_write8(chip, RT1711H_RTCTRL8,
-                            RT1711H_RTCTRL8_SET(0, 1, 1, 2));
-       if (ret < 0)
-               return ret;
-
-       /* I2C reset : (val + 1) * 12.5ms */
-       ret = rt1711h_write8(chip, RT1711H_RTCTRL11,
-                            RT1711H_RTCTRL11_SET(1, 0x0F));
-       if (ret < 0)
-               return ret;
-
-       /* tTCPCfilter : (26.7 * val) us */
-       ret = rt1711h_write8(chip, RT1711H_RTCTRL14, 0x0F);
-       if (ret < 0)
-               return ret;
-
-       /*  tDRP : (51.2 + 6.4 * val) ms */
-       ret = rt1711h_write8(chip, RT1711H_RTCTRL15, 0x04);
-       if (ret < 0)
-               return ret;
-
-       /* dcSRC.DRP : 33% */
-       return rt1711h_write16(chip, RT1711H_RTCTRL16, 330);
-}
-
-static int rt1711h_set_vconn(struct tcpci *tcpci, struct tcpci_data *tdata,
-                            bool enable)
-{
-       struct rt1711h_chip *chip = tdata_to_rt1711h(tdata);
-
-       return rt1711h_write8(chip, RT1711H_RTCTRL8,
-                             RT1711H_RTCTRL8_SET(0, 1, !enable, 2));
-}
-
-static int rt1711h_start_drp_toggling(struct tcpci *tcpci,
-                                     struct tcpci_data *tdata,
-                                     enum typec_cc_status cc)
-{
-       struct rt1711h_chip *chip = tdata_to_rt1711h(tdata);
-       int ret;
-       unsigned int reg = 0;
-
-       switch (cc) {
-       default:
-       case TYPEC_CC_RP_DEF:
-               reg |= (TCPC_ROLE_CTRL_RP_VAL_DEF <<
-                       TCPC_ROLE_CTRL_RP_VAL_SHIFT);
-               break;
-       case TYPEC_CC_RP_1_5:
-               reg |= (TCPC_ROLE_CTRL_RP_VAL_1_5 <<
-                       TCPC_ROLE_CTRL_RP_VAL_SHIFT);
-               break;
-       case TYPEC_CC_RP_3_0:
-               reg |= (TCPC_ROLE_CTRL_RP_VAL_3_0 <<
-                       TCPC_ROLE_CTRL_RP_VAL_SHIFT);
-               break;
-       }
-
-       if (cc == TYPEC_CC_RD)
-               reg |= (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) |
-                          (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT);
-       else
-               reg |= (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
-                          (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT);
-
-       ret = rt1711h_write8(chip, TCPC_ROLE_CTRL, reg);
-       if (ret < 0)
-               return ret;
-       usleep_range(500, 1000);
-
-       return 0;
-}
-
-static irqreturn_t rt1711h_irq(int irq, void *dev_id)
-{
-       int ret;
-       u16 alert;
-       u8 status;
-       struct rt1711h_chip *chip = dev_id;
-
-       if (!chip->tcpci)
-               return IRQ_HANDLED;
-
-       ret = rt1711h_read16(chip, TCPC_ALERT, &alert);
-       if (ret < 0)
-               goto out;
-
-       if (alert & TCPC_ALERT_CC_STATUS) {
-               ret = rt1711h_read8(chip, TCPC_CC_STATUS, &status);
-               if (ret < 0)
-                       goto out;
-               /* Clear cc change event triggered by starting toggling */
-               if (status & TCPC_CC_STATUS_TOGGLING)
-                       rt1711h_write8(chip, TCPC_ALERT, TCPC_ALERT_CC_STATUS);
-       }
-
-out:
-       return tcpci_irq(chip->tcpci);
-}
-
-static int rt1711h_init_alert(struct rt1711h_chip *chip,
-                             struct i2c_client *client)
-{
-       int ret;
-
-       /* Disable chip interrupts before requesting irq */
-       ret = rt1711h_write16(chip, TCPC_ALERT_MASK, 0);
-       if (ret < 0)
-               return ret;
-
-       ret = devm_request_threaded_irq(chip->dev, client->irq, NULL,
-                                       rt1711h_irq,
-                                       IRQF_ONESHOT | IRQF_TRIGGER_LOW,
-                                       dev_name(chip->dev), chip);
-       if (ret < 0)
-               return ret;
-       enable_irq_wake(client->irq);
-       return 0;
-}
-
-static int rt1711h_sw_reset(struct rt1711h_chip *chip)
-{
-       int ret;
-
-       ret = rt1711h_write8(chip, RT1711H_RTCTRL13, 0x01);
-       if (ret < 0)
-               return ret;
-
-       usleep_range(1000, 2000);
-       return 0;
-}
-
-static int rt1711h_check_revision(struct i2c_client *i2c)
-{
-       int ret;
-
-       ret = i2c_smbus_read_word_data(i2c, TCPC_VENDOR_ID);
-       if (ret < 0)
-               return ret;
-       if (ret != RT1711H_VID) {
-               dev_err(&i2c->dev, "vid is not correct, 0x%04x\n", ret);
-               return -ENODEV;
-       }
-       ret = i2c_smbus_read_word_data(i2c, TCPC_PRODUCT_ID);
-       if (ret < 0)
-               return ret;
-       if (ret != RT1711H_PID) {
-               dev_err(&i2c->dev, "pid is not correct, 0x%04x\n", ret);
-               return -ENODEV;
-       }
-       return 0;
-}
-
-static int rt1711h_probe(struct i2c_client *client,
-                        const struct i2c_device_id *i2c_id)
-{
-       int ret;
-       struct rt1711h_chip *chip;
-
-       ret = rt1711h_check_revision(client);
-       if (ret < 0) {
-               dev_err(&client->dev, "check vid/pid fail\n");
-               return ret;
-       }
-
-       chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
-       if (!chip)
-               return -ENOMEM;
-
-       chip->data.regmap = devm_regmap_init_i2c(client,
-                                                &rt1711h_regmap_config);
-       if (IS_ERR(chip->data.regmap))
-               return PTR_ERR(chip->data.regmap);
-
-       chip->dev = &client->dev;
-       i2c_set_clientdata(client, chip);
-
-       ret = rt1711h_sw_reset(chip);
-       if (ret < 0)
-               return ret;
-
-       ret = rt1711h_init_alert(chip, client);
-       if (ret < 0)
-               return ret;
-
-       chip->data.init = rt1711h_init;
-       chip->data.set_vconn = rt1711h_set_vconn;
-       chip->data.start_drp_toggling = rt1711h_start_drp_toggling;
-       chip->tcpci = tcpci_register_port(chip->dev, &chip->data);
-       if (IS_ERR_OR_NULL(chip->tcpci))
-               return PTR_ERR(chip->tcpci);
-
-       return 0;
-}
-
-static int rt1711h_remove(struct i2c_client *client)
-{
-       struct rt1711h_chip *chip = i2c_get_clientdata(client);
-
-       tcpci_unregister_port(chip->tcpci);
-       return 0;
-}
-
-static const struct i2c_device_id rt1711h_id[] = {
-       { "rt1711h", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, rt1711h_id);
-
-#ifdef CONFIG_OF
-static const struct of_device_id rt1711h_of_match[] = {
-       { .compatible = "richtek,rt1711h", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, rt1711h_of_match);
-#endif
-
-static struct i2c_driver rt1711h_i2c_driver = {
-       .driver = {
-               .name = "rt1711h",
-               .of_match_table = of_match_ptr(rt1711h_of_match),
-       },
-       .probe = rt1711h_probe,
-       .remove = rt1711h_remove,
-       .id_table = rt1711h_id,
-};
-module_i2c_driver(rt1711h_i2c_driver);
-
-MODULE_AUTHOR("ShuFan Lee <shufan_lee@richtek.com>");
-MODULE_DESCRIPTION("RT1711H USB Type-C Port Controller Interface Driver");
-MODULE_LICENSE("GPL");
index 7f4d2b6af37a0899a89503d3d339a59deb398010..772851bee99b6bfe74396cbdf89dc9665c15a459 100644 (file)
@@ -33,11 +33,11 @@ static const struct tegra_udc_soc_info tegra30_udc_soc_info = {
 };
 
 static const struct tegra_udc_soc_info tegra114_udc_soc_info = {
-       .flags = 0,
+       .flags = CI_HDRC_REQUIRES_ALIGNED_DMA,
 };
 
 static const struct tegra_udc_soc_info tegra124_udc_soc_info = {
-       .flags = 0,
+       .flags = CI_HDRC_REQUIRES_ALIGNED_DMA,
 };
 
 static const struct of_device_id tegra_udc_of_match[] = {
index 75c4623ad779eecd64b0164a24b6d8ac86177ca3..27346d69f3938c0222fc59b467bbeb6e9ce778e7 100644 (file)
@@ -276,6 +276,7 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf)
 {
        int newctrl;
        int difference;
+       unsigned long flags;
        struct usb_cdc_notification *dr = (struct usb_cdc_notification *)buf;
        unsigned char *data = buf + sizeof(struct usb_cdc_notification);
 
@@ -303,7 +304,7 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf)
                }
 
                difference = acm->ctrlin ^ newctrl;
-               spin_lock(&acm->read_lock);
+               spin_lock_irqsave(&acm->read_lock, flags);
                acm->ctrlin = newctrl;
                acm->oldcount = acm->iocount;
 
@@ -321,7 +322,7 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf)
                        acm->iocount.parity++;
                if (difference & ACM_CTRL_OVERRUN)
                        acm->iocount.overrun++;
-               spin_unlock(&acm->read_lock);
+               spin_unlock_irqrestore(&acm->read_lock, flags);
 
                if (difference)
                        wake_up_all(&acm->wioctl);
@@ -1378,6 +1379,9 @@ made_compressed_probe:
        if (acm == NULL)
                goto alloc_fail;
 
+       tty_port_init(&acm->port);
+       acm->port.ops = &acm_port_ops;
+
        minor = acm_alloc_minor(acm);
        if (minor < 0)
                goto alloc_fail1;
@@ -1413,22 +1417,20 @@ made_compressed_probe:
                acm->out = usb_sndintpipe(usb_dev, epwrite->bEndpointAddress);
        else
                acm->out = usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress);
-       tty_port_init(&acm->port);
-       acm->port.ops = &acm_port_ops;
        init_usb_anchor(&acm->delayed);
        acm->quirks = quirks;
 
        buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
        if (!buf)
-               goto alloc_fail2;
+               goto alloc_fail1;
        acm->ctrl_buffer = buf;
 
        if (acm_write_buffers_alloc(acm) < 0)
-               goto alloc_fail4;
+               goto alloc_fail2;
 
        acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
        if (!acm->ctrlurb)
-               goto alloc_fail5;
+               goto alloc_fail3;
 
        for (i = 0; i < num_rx_buf; i++) {
                struct acm_rb *rb = &(acm->read_buffers[i]);
@@ -1437,13 +1439,13 @@ made_compressed_probe:
                rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL,
                                                                &rb->dma);
                if (!rb->base)
-                       goto alloc_fail6;
+                       goto alloc_fail4;
                rb->index = i;
                rb->instance = acm;
 
                urb = usb_alloc_urb(0, GFP_KERNEL);
                if (!urb)
-                       goto alloc_fail6;
+                       goto alloc_fail4;
 
                urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
                urb->transfer_dma = rb->dma;
@@ -1465,7 +1467,7 @@ made_compressed_probe:
 
                snd->urb = usb_alloc_urb(0, GFP_KERNEL);
                if (snd->urb == NULL)
-                       goto alloc_fail7;
+                       goto alloc_fail5;
 
                if (usb_endpoint_xfer_int(epwrite))
                        usb_fill_int_urb(snd->urb, usb_dev, acm->out,
@@ -1483,7 +1485,7 @@ made_compressed_probe:
 
        i = device_create_file(&intf->dev, &dev_attr_bmCapabilities);
        if (i < 0)
-               goto alloc_fail7;
+               goto alloc_fail5;
 
        if (h.usb_cdc_country_functional_desc) { /* export the country data */
                struct usb_cdc_country_functional_desc * cfd =
@@ -1542,7 +1544,7 @@ skip_countries:
                        &control_interface->dev);
        if (IS_ERR(tty_dev)) {
                rv = PTR_ERR(tty_dev);
-               goto alloc_fail8;
+               goto alloc_fail6;
        }
 
        if (quirks & CLEAR_HALT_CONDITIONS) {
@@ -1551,7 +1553,7 @@ skip_countries:
        }
 
        return 0;
-alloc_fail8:
+alloc_fail6:
        if (acm->country_codes) {
                device_remove_file(&acm->control->dev,
                                &dev_attr_wCountryCodes);
@@ -1560,23 +1562,21 @@ alloc_fail8:
                kfree(acm->country_codes);
        }
        device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);
-alloc_fail7:
+alloc_fail5:
        usb_set_intfdata(intf, NULL);
        for (i = 0; i < ACM_NW; i++)
                usb_free_urb(acm->wb[i].urb);
-alloc_fail6:
+alloc_fail4:
        for (i = 0; i < num_rx_buf; i++)
                usb_free_urb(acm->read_urbs[i]);
        acm_read_buffers_free(acm);
        usb_free_urb(acm->ctrlurb);
-alloc_fail5:
+alloc_fail3:
        acm_write_buffers_free(acm);
-alloc_fail4:
-       usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
 alloc_fail2:
-       acm_release_minor(acm);
+       usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
 alloc_fail1:
-       kfree(acm);
+       tty_port_put(&acm->port);
 alloc_fail:
        return rv;
 }
index a0d284ef3f40ad369cc34f093bb15723124ef4a2..bec581fb7c6361891a81a3a0aa88d3863b686f58 100644 (file)
@@ -96,6 +96,7 @@ struct wdm_device {
        struct mutex            rlock;
        wait_queue_head_t       wait;
        struct work_struct      rxwork;
+       struct work_struct      service_outs_intr;
        int                     werr;
        int                     rerr;
        int                     resp_count;
@@ -141,26 +142,26 @@ found:
 static void wdm_out_callback(struct urb *urb)
 {
        struct wdm_device *desc;
+       unsigned long flags;
+
        desc = urb->context;
-       spin_lock(&desc->iuspin);
+       spin_lock_irqsave(&desc->iuspin, flags);
        desc->werr = urb->status;
-       spin_unlock(&desc->iuspin);
+       spin_unlock_irqrestore(&desc->iuspin, flags);
        kfree(desc->outbuf);
        desc->outbuf = NULL;
        clear_bit(WDM_IN_USE, &desc->flags);
        wake_up(&desc->wait);
 }
 
-/* forward declaration */
-static int service_outstanding_interrupt(struct wdm_device *desc);
-
 static void wdm_in_callback(struct urb *urb)
 {
+       unsigned long flags;
        struct wdm_device *desc = urb->context;
        int status = urb->status;
        int length = urb->actual_length;
 
-       spin_lock(&desc->iuspin);
+       spin_lock_irqsave(&desc->iuspin, flags);
        clear_bit(WDM_RESPONDING, &desc->flags);
 
        if (status) {
@@ -209,8 +210,6 @@ static void wdm_in_callback(struct urb *urb)
                }
        }
 skip_error:
-       set_bit(WDM_READ, &desc->flags);
-       wake_up(&desc->wait);
 
        if (desc->rerr) {
                /*
@@ -219,14 +218,17 @@ skip_error:
                 * We should respond to further attempts from the device to send
                 * data, so that we can get unstuck.
                 */
-               service_outstanding_interrupt(desc);
+               schedule_work(&desc->service_outs_intr);
+       } else {
+               set_bit(WDM_READ, &desc->flags);
+               wake_up(&desc->wait);
        }
-
-       spin_unlock(&desc->iuspin);
+       spin_unlock_irqrestore(&desc->iuspin, flags);
 }
 
 static void wdm_int_callback(struct urb *urb)
 {
+       unsigned long flags;
        int rv = 0;
        int responding;
        int status = urb->status;
@@ -286,7 +288,7 @@ static void wdm_int_callback(struct urb *urb)
                goto exit;
        }
 
-       spin_lock(&desc->iuspin);
+       spin_lock_irqsave(&desc->iuspin, flags);
        responding = test_and_set_bit(WDM_RESPONDING, &desc->flags);
        if (!desc->resp_count++ && !responding
                && !test_bit(WDM_DISCONNECTING, &desc->flags)
@@ -294,7 +296,7 @@ static void wdm_int_callback(struct urb *urb)
                rv = usb_submit_urb(desc->response, GFP_ATOMIC);
                dev_dbg(&desc->intf->dev, "submit response URB %d\n", rv);
        }
-       spin_unlock(&desc->iuspin);
+       spin_unlock_irqrestore(&desc->iuspin, flags);
        if (rv < 0) {
                clear_bit(WDM_RESPONDING, &desc->flags);
                if (rv == -EPERM)
@@ -758,6 +760,21 @@ static void wdm_rxwork(struct work_struct *work)
        }
 }
 
+static void service_interrupt_work(struct work_struct *work)
+{
+       struct wdm_device *desc;
+
+       desc = container_of(work, struct wdm_device, service_outs_intr);
+
+       spin_lock_irq(&desc->iuspin);
+       service_outstanding_interrupt(desc);
+       if (!desc->resp_count) {
+               set_bit(WDM_READ, &desc->flags);
+               wake_up(&desc->wait);
+       }
+       spin_unlock_irq(&desc->iuspin);
+}
+
 /* --- hotplug --- */
 
 static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep,
@@ -779,6 +796,7 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor
        desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber);
        desc->intf = intf;
        INIT_WORK(&desc->rxwork, wdm_rxwork);
+       INIT_WORK(&desc->service_outs_intr, service_interrupt_work);
 
        rv = -EINVAL;
        if (!usb_endpoint_is_int_in(ep))
@@ -964,6 +982,7 @@ static void wdm_disconnect(struct usb_interface *intf)
        mutex_lock(&desc->wlock);
        kill_urbs(desc);
        cancel_work_sync(&desc->rxwork);
+       cancel_work_sync(&desc->service_outs_intr);
        mutex_unlock(&desc->wlock);
        mutex_unlock(&desc->rlock);
 
@@ -1006,6 +1025,7 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
                /* callback submits work - order is essential */
                kill_urbs(desc);
                cancel_work_sync(&desc->rxwork);
+               cancel_work_sync(&desc->service_outs_intr);
        }
        if (!PMSG_IS_AUTO(message)) {
                mutex_unlock(&desc->wlock);
@@ -1065,6 +1085,7 @@ static int wdm_pre_reset(struct usb_interface *intf)
        mutex_lock(&desc->wlock);
        kill_urbs(desc);
        cancel_work_sync(&desc->rxwork);
+       cancel_work_sync(&desc->service_outs_intr);
        return 0;
 }
 
index d058d7a31e7c35a32259e81e8136ce3280df3b0c..407a7a6198a25ba3bb3d078bf53adab23b5e3a34 100644 (file)
@@ -292,6 +292,7 @@ static void usblp_bulk_read(struct urb *urb)
 {
        struct usblp *usblp = urb->context;
        int status = urb->status;
+       unsigned long flags;
 
        if (usblp->present && usblp->used) {
                if (status)
@@ -299,14 +300,14 @@ static void usblp_bulk_read(struct urb *urb)
                            "nonzero read bulk status received: %d\n",
                            usblp->minor, status);
        }
-       spin_lock(&usblp->lock);
+       spin_lock_irqsave(&usblp->lock, flags);
        if (status < 0)
                usblp->rstatus = status;
        else
                usblp->rstatus = urb->actual_length;
        usblp->rcomplete = 1;
        wake_up(&usblp->rwait);
-       spin_unlock(&usblp->lock);
+       spin_unlock_irqrestore(&usblp->lock, flags);
 
        usb_free_urb(urb);
 }
@@ -315,6 +316,7 @@ static void usblp_bulk_write(struct urb *urb)
 {
        struct usblp *usblp = urb->context;
        int status = urb->status;
+       unsigned long flags;
 
        if (usblp->present && usblp->used) {
                if (status)
@@ -322,7 +324,7 @@ static void usblp_bulk_write(struct urb *urb)
                            "nonzero write bulk status received: %d\n",
                            usblp->minor, status);
        }
-       spin_lock(&usblp->lock);
+       spin_lock_irqsave(&usblp->lock, flags);
        if (status < 0)
                usblp->wstatus = status;
        else
@@ -330,7 +332,7 @@ static void usblp_bulk_write(struct urb *urb)
        usblp->no_paper = 0;
        usblp->wcomplete = 1;
        wake_up(&usblp->wwait);
-       spin_unlock(&usblp->lock);
+       spin_unlock_irqrestore(&usblp->lock, flags);
 
        usb_free_urb(urb);
 }
index 529295a17579ed25a15b76512499aa0e2735a014..83ffa5a14c3dbbc53e8b964a4101e6e4a19c57a5 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/poll.h>
 #include <linux/mutex.h>
 #include <linux/usb.h>
+#include <linux/compat.h>
 #include <linux/usb/tmc.h>
 
 
@@ -30,6 +31,8 @@
  */
 #define USBTMC_SIZE_IOBUFFER   2048
 
+/* Minimum USB timeout (in milliseconds) */
+#define USBTMC_MIN_TIMEOUT     100
 /* Default USB timeout (in milliseconds) */
 #define USBTMC_TIMEOUT         5000
 
@@ -67,6 +70,7 @@ struct usbtmc_device_data {
        const struct usb_device_id *id;
        struct usb_device *usb_dev;
        struct usb_interface *intf;
+       struct list_head file_list;
 
        unsigned int bulk_in;
        unsigned int bulk_out;
@@ -87,7 +91,6 @@ struct usbtmc_device_data {
        int            iin_interval;
        struct urb    *iin_urb;
        u16            iin_wMaxPacketSize;
-       atomic_t       srq_asserted;
 
        /* coalesced usb488_caps from usbtmc_dev_capabilities */
        __u8 usb488_caps;
@@ -104,9 +107,25 @@ struct usbtmc_device_data {
        struct mutex io_mutex;  /* only one i/o function running at a time */
        wait_queue_head_t waitq;
        struct fasync_struct *fasync;
+       spinlock_t dev_lock; /* lock for file_list */
 };
 #define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref)
 
+/*
+ * This structure holds private data for each USBTMC file handle.
+ */
+struct usbtmc_file_data {
+       struct usbtmc_device_data *data;
+       struct list_head file_elem;
+
+       u32            timeout;
+       u8             srq_byte;
+       atomic_t       srq_asserted;
+       u8             eom_val;
+       u8             term_char;
+       bool           term_char_enabled;
+};
+
 /* Forward declarations */
 static struct usb_driver usbtmc_driver;
 
@@ -122,7 +141,7 @@ static int usbtmc_open(struct inode *inode, struct file *filp)
 {
        struct usb_interface *intf;
        struct usbtmc_device_data *data;
-       int retval = 0;
+       struct usbtmc_file_data *file_data;
 
        intf = usb_find_interface(&usbtmc_driver, iminor(inode));
        if (!intf) {
@@ -130,21 +149,51 @@ static int usbtmc_open(struct inode *inode, struct file *filp)
                return -ENODEV;
        }
 
+       file_data = kzalloc(sizeof(*file_data), GFP_KERNEL);
+       if (!file_data)
+               return -ENOMEM;
+
        data = usb_get_intfdata(intf);
        /* Protect reference to data from file structure until release */
        kref_get(&data->kref);
 
+       mutex_lock(&data->io_mutex);
+       file_data->data = data;
+
+       /* copy default values from device settings */
+       file_data->timeout = USBTMC_TIMEOUT;
+       file_data->term_char = data->TermChar;
+       file_data->term_char_enabled = data->TermCharEnabled;
+       file_data->eom_val = 1;
+
+       INIT_LIST_HEAD(&file_data->file_elem);
+       spin_lock_irq(&data->dev_lock);
+       list_add_tail(&file_data->file_elem, &data->file_list);
+       spin_unlock_irq(&data->dev_lock);
+       mutex_unlock(&data->io_mutex);
+
        /* Store pointer in file structure's private data field */
-       filp->private_data = data;
+       filp->private_data = file_data;
 
-       return retval;
+       return 0;
 }
 
 static int usbtmc_release(struct inode *inode, struct file *file)
 {
-       struct usbtmc_device_data *data = file->private_data;
+       struct usbtmc_file_data *file_data = file->private_data;
 
-       kref_put(&data->kref, usbtmc_delete);
+       /* prevent IO _AND_ usbtmc_interrupt */
+       mutex_lock(&file_data->data->io_mutex);
+       spin_lock_irq(&file_data->data->dev_lock);
+
+       list_del(&file_data->file_elem);
+
+       spin_unlock_irq(&file_data->data->dev_lock);
+       mutex_unlock(&file_data->data->io_mutex);
+
+       kref_put(&file_data->data->kref, usbtmc_delete);
+       file_data->data = NULL;
+       kfree(file_data);
        return 0;
 }
 
@@ -369,10 +418,12 @@ exit:
        return rv;
 }
 
-static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data,
+static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data,
                                void __user *arg)
 {
+       struct usbtmc_device_data *data = file_data->data;
        struct device *dev = &data->intf->dev;
+       int srq_asserted = 0;
        u8 *buffer;
        u8 tag;
        __u8 stb;
@@ -381,15 +432,25 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data,
        dev_dbg(dev, "Enter ioctl_read_stb iin_ep_present: %d\n",
                data->iin_ep_present);
 
+       spin_lock_irq(&data->dev_lock);
+       srq_asserted = atomic_xchg(&file_data->srq_asserted, srq_asserted);
+       if (srq_asserted) {
+               /* a STB with SRQ is already received */
+               stb = file_data->srq_byte;
+               spin_unlock_irq(&data->dev_lock);
+               rv = put_user(stb, (__u8 __user *)arg);
+               dev_dbg(dev, "stb:0x%02x with srq received %d\n",
+                       (unsigned int)stb, rv);
+               return rv;
+       }
+       spin_unlock_irq(&data->dev_lock);
+
        buffer = kmalloc(8, GFP_KERNEL);
        if (!buffer)
                return -ENOMEM;
 
        atomic_set(&data->iin_data_valid, 0);
 
-       /* must issue read_stb before using poll or select */
-       atomic_set(&data->srq_asserted, 0);
-
        rv = usb_control_msg(data->usb_dev,
                        usb_rcvctrlpipe(data->usb_dev, 0),
                        USBTMC488_REQUEST_READ_STATUS_BYTE,
@@ -412,7 +473,7 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data,
                rv = wait_event_interruptible_timeout(
                        data->waitq,
                        atomic_read(&data->iin_data_valid) != 0,
-                       USBTMC_TIMEOUT);
+                       file_data->timeout);
                if (rv < 0) {
                        dev_dbg(dev, "wait interrupted %d\n", rv);
                        goto exit;
@@ -420,7 +481,7 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data,
 
                if (rv == 0) {
                        dev_dbg(dev, "wait timed out\n");
-                       rv = -ETIME;
+                       rv = -ETIMEDOUT;
                        goto exit;
                }
 
@@ -435,9 +496,8 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data,
                stb = buffer[2];
        }
 
-       rv = copy_to_user(arg, &stb, sizeof(stb));
-       if (rv)
-               rv = -EFAULT;
+       rv = put_user(stb, (__u8 __user *)arg);
+       dev_dbg(dev, "stb:0x%02x received %d\n", (unsigned int)stb, rv);
 
  exit:
        /* bump interrupt bTag */
@@ -505,6 +565,51 @@ static int usbtmc488_ioctl_simple(struct usbtmc_device_data *data,
        return rv;
 }
 
+/*
+ * Sends a TRIGGER Bulk-OUT command message
+ * See the USBTMC-USB488 specification, Table 2.
+ *
+ * Also updates bTag_last_write.
+ */
+static int usbtmc488_ioctl_trigger(struct usbtmc_file_data *file_data)
+{
+       struct usbtmc_device_data *data = file_data->data;
+       int retval;
+       u8 *buffer;
+       int actual;
+
+       buffer = kzalloc(USBTMC_HEADER_SIZE, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       buffer[0] = 128;
+       buffer[1] = data->bTag;
+       buffer[2] = ~data->bTag;
+
+       retval = usb_bulk_msg(data->usb_dev,
+                             usb_sndbulkpipe(data->usb_dev,
+                                             data->bulk_out),
+                             buffer, USBTMC_HEADER_SIZE,
+                             &actual, file_data->timeout);
+
+       /* Store bTag (in case we need to abort) */
+       data->bTag_last_write = data->bTag;
+
+       /* Increment bTag -- and increment again if zero */
+       data->bTag++;
+       if (!data->bTag)
+               data->bTag++;
+
+       kfree(buffer);
+       if (retval < 0) {
+               dev_err(&data->intf->dev, "%s returned %d\n",
+                       __func__, retval);
+               return retval;
+       }
+
+       return 0;
+}
+
 /*
  * Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-OUT endpoint.
  * @transfer_size: number of bytes to request from the device.
@@ -513,8 +618,10 @@ static int usbtmc488_ioctl_simple(struct usbtmc_device_data *data,
  *
  * Also updates bTag_last_write.
  */
-static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t transfer_size)
+static int send_request_dev_dep_msg_in(struct usbtmc_file_data *file_data,
+                                      size_t transfer_size)
 {
+       struct usbtmc_device_data *data = file_data->data;
        int retval;
        u8 *buffer;
        int actual;
@@ -533,9 +640,9 @@ static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t t
        buffer[5] = transfer_size >> 8;
        buffer[6] = transfer_size >> 16;
        buffer[7] = transfer_size >> 24;
-       buffer[8] = data->TermCharEnabled * 2;
+       buffer[8] = file_data->term_char_enabled * 2;
        /* Use term character? */
-       buffer[9] = data->TermChar;
+       buffer[9] = file_data->term_char;
        buffer[10] = 0; /* Reserved */
        buffer[11] = 0; /* Reserved */
 
@@ -543,7 +650,8 @@ static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t t
        retval = usb_bulk_msg(data->usb_dev,
                              usb_sndbulkpipe(data->usb_dev,
                                              data->bulk_out),
-                             buffer, USBTMC_HEADER_SIZE, &actual, USBTMC_TIMEOUT);
+                             buffer, USBTMC_HEADER_SIZE,
+                             &actual, file_data->timeout);
 
        /* Store bTag (in case we need to abort) */
        data->bTag_last_write = data->bTag;
@@ -565,6 +673,7 @@ static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t t
 static ssize_t usbtmc_read(struct file *filp, char __user *buf,
                           size_t count, loff_t *f_pos)
 {
+       struct usbtmc_file_data *file_data;
        struct usbtmc_device_data *data;
        struct device *dev;
        u32 n_characters;
@@ -576,7 +685,8 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
        size_t this_part;
 
        /* Get pointer to private data structure */
-       data = filp->private_data;
+       file_data = filp->private_data;
+       data = file_data->data;
        dev = &data->intf->dev;
 
        buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
@@ -591,7 +701,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
 
        dev_dbg(dev, "usb_bulk_msg_in: count(%zu)\n", count);
 
-       retval = send_request_dev_dep_msg_in(data, count);
+       retval = send_request_dev_dep_msg_in(file_data, count);
 
        if (retval < 0) {
                if (data->auto_abort)
@@ -610,7 +720,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
                                      usb_rcvbulkpipe(data->usb_dev,
                                                      data->bulk_in),
                                      buffer, USBTMC_SIZE_IOBUFFER, &actual,
-                                     USBTMC_TIMEOUT);
+                                     file_data->timeout);
 
                dev_dbg(dev, "usb_bulk_msg: retval(%u), done(%zu), remaining(%zu), actual(%d)\n", retval, done, remaining, actual);
 
@@ -721,6 +831,7 @@ exit:
 static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
                            size_t count, loff_t *f_pos)
 {
+       struct usbtmc_file_data *file_data;
        struct usbtmc_device_data *data;
        u8 *buffer;
        int retval;
@@ -730,7 +841,8 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
        int done;
        int this_part;
 
-       data = filp->private_data;
+       file_data = filp->private_data;
+       data = file_data->data;
 
        buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
        if (!buffer)
@@ -751,7 +863,7 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
                        buffer[8] = 0;
                } else {
                        this_part = remaining;
-                       buffer[8] = 1;
+                       buffer[8] = file_data->eom_val;
                }
 
                /* Setup IO buffer for DEV_DEP_MSG_OUT message */
@@ -781,7 +893,7 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
                                              usb_sndbulkpipe(data->usb_dev,
                                                              data->bulk_out),
                                              buffer, n_bytes,
-                                             &actual, USBTMC_TIMEOUT);
+                                             &actual, file_data->timeout);
                        if (retval != 0)
                                break;
                        n_bytes -= actual;
@@ -1138,12 +1250,91 @@ exit:
        return rv;
 }
 
+/*
+ * Get the usb timeout value
+ */
+static int usbtmc_ioctl_get_timeout(struct usbtmc_file_data *file_data,
+                               void __user *arg)
+{
+       u32 timeout;
+
+       timeout = file_data->timeout;
+
+       return put_user(timeout, (__u32 __user *)arg);
+}
+
+/*
+ * Set the usb timeout value
+ */
+static int usbtmc_ioctl_set_timeout(struct usbtmc_file_data *file_data,
+                               void __user *arg)
+{
+       u32 timeout;
+
+       if (get_user(timeout, (__u32 __user *)arg))
+               return -EFAULT;
+
+       /* Note that timeout = 0 means
+        * MAX_SCHEDULE_TIMEOUT in usb_control_msg
+        */
+       if (timeout < USBTMC_MIN_TIMEOUT)
+               return -EINVAL;
+
+       file_data->timeout = timeout;
+
+       return 0;
+}
+
+/*
+ * enables/disables sending EOM on write
+ */
+static int usbtmc_ioctl_eom_enable(struct usbtmc_file_data *file_data,
+                               void __user *arg)
+{
+       u8 eom_enable;
+
+       if (copy_from_user(&eom_enable, arg, sizeof(eom_enable)))
+               return -EFAULT;
+
+       if (eom_enable > 1)
+               return -EINVAL;
+
+       file_data->eom_val = eom_enable;
+
+       return 0;
+}
+
+/*
+ * Configure termination character for read()
+ */
+static int usbtmc_ioctl_config_termc(struct usbtmc_file_data *file_data,
+                               void __user *arg)
+{
+       struct usbtmc_termchar termc;
+
+       if (copy_from_user(&termc, arg, sizeof(termc)))
+               return -EFAULT;
+
+       if ((termc.term_char_enabled > 1) ||
+               (termc.term_char_enabled &&
+               !(file_data->data->capabilities.device_capabilities & 1)))
+               return -EINVAL;
+
+       file_data->term_char = termc.term_char;
+       file_data->term_char_enabled = termc.term_char_enabled;
+
+       return 0;
+}
+
 static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
+       struct usbtmc_file_data *file_data;
        struct usbtmc_device_data *data;
        int retval = -EBADRQC;
 
-       data = file->private_data;
+       file_data = file->private_data;
+       data = file_data->data;
+
        mutex_lock(&data->io_mutex);
        if (data->zombie) {
                retval = -ENODEV;
@@ -1175,6 +1366,26 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                retval = usbtmc_ioctl_abort_bulk_in(data);
                break;
 
+       case USBTMC_IOCTL_GET_TIMEOUT:
+               retval = usbtmc_ioctl_get_timeout(file_data,
+                                                 (void __user *)arg);
+               break;
+
+       case USBTMC_IOCTL_SET_TIMEOUT:
+               retval = usbtmc_ioctl_set_timeout(file_data,
+                                                 (void __user *)arg);
+               break;
+
+       case USBTMC_IOCTL_EOM_ENABLE:
+               retval = usbtmc_ioctl_eom_enable(file_data,
+                                                (void __user *)arg);
+               break;
+
+       case USBTMC_IOCTL_CONFIG_TERMCHAR:
+               retval = usbtmc_ioctl_config_termc(file_data,
+                                                  (void __user *)arg);
+               break;
+
        case USBTMC488_IOCTL_GET_CAPS:
                retval = copy_to_user((void __user *)arg,
                                &data->usb488_caps,
@@ -1184,7 +1395,8 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                break;
 
        case USBTMC488_IOCTL_READ_STB:
-               retval = usbtmc488_ioctl_read_stb(data, (void __user *)arg);
+               retval = usbtmc488_ioctl_read_stb(file_data,
+                                                 (void __user *)arg);
                break;
 
        case USBTMC488_IOCTL_REN_CONTROL:
@@ -1201,6 +1413,10 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                retval = usbtmc488_ioctl_simple(data, (void __user *)arg,
                                                USBTMC488_REQUEST_LOCAL_LOCKOUT);
                break;
+
+       case USBTMC488_IOCTL_TRIGGER:
+               retval = usbtmc488_ioctl_trigger(file_data);
+               break;
        }
 
 skip_io_on_zombie:
@@ -1210,14 +1426,15 @@ skip_io_on_zombie:
 
 static int usbtmc_fasync(int fd, struct file *file, int on)
 {
-       struct usbtmc_device_data *data = file->private_data;
+       struct usbtmc_file_data *file_data = file->private_data;
 
-       return fasync_helper(fd, file, on, &data->fasync);
+       return fasync_helper(fd, file, on, &file_data->data->fasync);
 }
 
 static __poll_t usbtmc_poll(struct file *file, poll_table *wait)
 {
-       struct usbtmc_device_data *data = file->private_data;
+       struct usbtmc_file_data *file_data = file->private_data;
+       struct usbtmc_device_data *data = file_data->data;
        __poll_t mask;
 
        mutex_lock(&data->io_mutex);
@@ -1229,7 +1446,7 @@ static __poll_t usbtmc_poll(struct file *file, poll_table *wait)
 
        poll_wait(file, &data->waitq, wait);
 
-       mask = (atomic_read(&data->srq_asserted)) ? EPOLLIN | EPOLLRDNORM : 0;
+       mask = (atomic_read(&file_data->srq_asserted)) ? EPOLLPRI : 0;
 
 no_poll:
        mutex_unlock(&data->io_mutex);
@@ -1243,6 +1460,9 @@ static const struct file_operations fops = {
        .open           = usbtmc_open,
        .release        = usbtmc_release,
        .unlocked_ioctl = usbtmc_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = usbtmc_ioctl,
+#endif
        .fasync         = usbtmc_fasync,
        .poll           = usbtmc_poll,
        .llseek         = default_llseek,
@@ -1276,15 +1496,33 @@ static void usbtmc_interrupt(struct urb *urb)
                }
                /* check for SRQ notification */
                if (data->iin_buffer[0] == 0x81) {
+                       unsigned long flags;
+                       struct list_head *elem;
+
                        if (data->fasync)
                                kill_fasync(&data->fasync,
-                                       SIGIO, POLL_IN);
+                                       SIGIO, POLL_PRI);
 
-                       atomic_set(&data->srq_asserted, 1);
-                       wake_up_interruptible(&data->waitq);
+                       spin_lock_irqsave(&data->dev_lock, flags);
+                       list_for_each(elem, &data->file_list) {
+                               struct usbtmc_file_data *file_data;
+
+                               file_data = list_entry(elem,
+                                                      struct usbtmc_file_data,
+                                                      file_elem);
+                               file_data->srq_byte = data->iin_buffer[1];
+                               atomic_set(&file_data->srq_asserted, 1);
+                       }
+                       spin_unlock_irqrestore(&data->dev_lock, flags);
+
+                       dev_dbg(dev, "srq received bTag %x stb %x\n",
+                               (unsigned int)data->iin_buffer[0],
+                               (unsigned int)data->iin_buffer[1]);
+                       wake_up_interruptible_all(&data->waitq);
                        goto exit;
                }
-               dev_warn(dev, "invalid notification: %x\n", data->iin_buffer[0]);
+               dev_warn(dev, "invalid notification: %x\n",
+                        data->iin_buffer[0]);
                break;
        case -EOVERFLOW:
                dev_err(dev, "overflow with length %d, actual length is %d\n",
@@ -1295,6 +1533,7 @@ static void usbtmc_interrupt(struct urb *urb)
        case -ESHUTDOWN:
        case -EILSEQ:
        case -ETIME:
+       case -EPIPE:
                /* urb terminated, clean up */
                dev_dbg(dev, "urb terminated, status: %d\n", status);
                return;
@@ -1339,7 +1578,9 @@ static int usbtmc_probe(struct usb_interface *intf,
        mutex_init(&data->io_mutex);
        init_waitqueue_head(&data->waitq);
        atomic_set(&data->iin_data_valid, 0);
-       atomic_set(&data->srq_asserted, 0);
+       INIT_LIST_HEAD(&data->file_list);
+       spin_lock_init(&data->dev_lock);
+
        data->zombie = 0;
 
        /* Initialize USBTMC bTag and other fields */
@@ -1442,17 +1683,14 @@ err_put:
 
 static void usbtmc_disconnect(struct usb_interface *intf)
 {
-       struct usbtmc_device_data *data;
-
-       dev_dbg(&intf->dev, "usbtmc_disconnect called\n");
+       struct usbtmc_device_data *data  = usb_get_intfdata(intf);
 
-       data = usb_get_intfdata(intf);
        usb_deregister_dev(intf, &usbtmc_class);
        sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp);
        sysfs_remove_group(&intf->dev.kobj, &data_attr_grp);
        mutex_lock(&data->io_mutex);
        data->zombie = 1;
-       wake_up_all(&data->waitq);
+       wake_up_interruptible_all(&data->waitq);
        mutex_unlock(&data->io_mutex);
        usbtmc_free_int(data);
        kref_put(&data->kref, usbtmc_delete);
index 476dcc5f2da3c3258b2635ab406d09acbd692966..6ce77b33da61302281dd1c49284e457ff04b73bd 100644 (file)
@@ -585,9 +585,10 @@ static void async_completed(struct urb *urb)
        struct siginfo sinfo;
        struct pid *pid = NULL;
        const struct cred *cred = NULL;
+       unsigned long flags;
        int signr;
 
-       spin_lock(&ps->lock);
+       spin_lock_irqsave(&ps->lock, flags);
        list_move_tail(&as->asynclist, &ps->async_completed);
        as->status = urb->status;
        signr = as->signr;
@@ -611,7 +612,7 @@ static void async_completed(struct urb *urb)
                cancel_bulk_urbs(ps, as->bulk_addr);
 
        wake_up(&ps->wait);
-       spin_unlock(&ps->lock);
+       spin_unlock_irqrestore(&ps->lock, flags);
 
        if (signr) {
                kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred);
index 1fb2668099663e08ffa3f5e7713ab0eaa55fb10a..462ce49f683a01da9b6ddd7045ccb358cb897ab4 100644 (file)
@@ -3660,12 +3660,54 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
        return 0;
 }
 
+/* Report wakeup requests from the ports of a resuming root hub */
+static void report_wakeup_requests(struct usb_hub *hub)
+{
+       struct usb_device       *hdev = hub->hdev;
+       struct usb_device       *udev;
+       struct usb_hcd          *hcd;
+       unsigned long           resuming_ports;
+       int                     i;
+
+       if (hdev->parent)
+               return;         /* Not a root hub */
+
+       hcd = bus_to_hcd(hdev->bus);
+       if (hcd->driver->get_resuming_ports) {
+
+               /*
+                * The get_resuming_ports() method returns a bitmap (origin 0)
+                * of ports which have started wakeup signaling but have not
+                * yet finished resuming.  During system resume we will
+                * resume all the enabled ports, regardless of any wakeup
+                * signals, which means the wakeup requests would be lost.
+                * To prevent this, report them to the PM core here.
+                */
+               resuming_ports = hcd->driver->get_resuming_ports(hcd);
+               for (i = 0; i < hdev->maxchild; ++i) {
+                       if (test_bit(i, &resuming_ports)) {
+                               udev = hub->ports[i]->child;
+                               if (udev)
+                                       pm_wakeup_event(&udev->dev, 0);
+                       }
+               }
+       }
+}
+
 static int hub_resume(struct usb_interface *intf)
 {
        struct usb_hub *hub = usb_get_intfdata(intf);
 
        dev_dbg(&intf->dev, "%s\n", __func__);
        hub_activate(hub, HUB_RESUME);
+
+       /*
+        * This should be called only for system resume, not runtime resume.
+        * We can't tell the difference here, so some wakeup requests will be
+        * reported at the wrong time or more than once.  This shouldn't
+        * matter much, so long as they do get reported.
+        */
+       report_wakeup_requests(hub);
        return 0;
 }
 
index 1a15392326fca2354d8ad0dde0d0f6b098890854..228672f2c4a15eb841809a1f3d42caa925eb5fee 100644 (file)
@@ -269,10 +269,11 @@ static void sg_clean(struct usb_sg_request *io)
 
 static void sg_complete(struct urb *urb)
 {
+       unsigned long flags;
        struct usb_sg_request *io = urb->context;
        int status = urb->status;
 
-       spin_lock(&io->lock);
+       spin_lock_irqsave(&io->lock, flags);
 
        /* In 2.5 we require hcds' endpoint queues not to progress after fault
         * reports, until the completion callback (this!) returns.  That lets
@@ -306,7 +307,7 @@ static void sg_complete(struct urb *urb)
                 * unlink pending urbs so they won't rx/tx bad data.
                 * careful: unlink can sometimes be synchronous...
                 */
-               spin_unlock(&io->lock);
+               spin_unlock_irqrestore(&io->lock, flags);
                for (i = 0, found = 0; i < io->entries; i++) {
                        if (!io->urbs[i])
                                continue;
@@ -323,7 +324,7 @@ static void sg_complete(struct urb *urb)
                        } else if (urb == io->urbs[i])
                                found = 1;
                }
-               spin_lock(&io->lock);
+               spin_lock_irqsave(&io->lock, flags);
        }
 
        /* on the last completion, signal usb_sg_wait() */
@@ -332,7 +333,7 @@ static void sg_complete(struct urb *urb)
        if (!io->count)
                complete(&io->complete);
 
-       spin_unlock(&io->lock);
+       spin_unlock_irqrestore(&io->lock, flags);
 }
 
 
index 1c36a6a9dd63bca752fa44da0d89f05abb4425cd..55d5ae2a7ec7bf805d66502f842f739926e7995b 100644 (file)
@@ -73,17 +73,17 @@ int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
        /* Backup global regs */
        gr = &hsotg->gr_backup;
 
-       gr->gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
-       gr->gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
-       gr->gahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
-       gr->gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
-       gr->grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ);
-       gr->gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
-       gr->gdfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG);
-       gr->pcgcctl1 = dwc2_readl(hsotg->regs + PCGCCTL1);
-       gr->glpmcfg = dwc2_readl(hsotg->regs + GLPMCFG);
-       gr->gi2cctl = dwc2_readl(hsotg->regs + GI2CCTL);
-       gr->pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
+       gr->gotgctl = dwc2_readl(hsotg, GOTGCTL);
+       gr->gintmsk = dwc2_readl(hsotg, GINTMSK);
+       gr->gahbcfg = dwc2_readl(hsotg, GAHBCFG);
+       gr->gusbcfg = dwc2_readl(hsotg, GUSBCFG);
+       gr->grxfsiz = dwc2_readl(hsotg, GRXFSIZ);
+       gr->gnptxfsiz = dwc2_readl(hsotg, GNPTXFSIZ);
+       gr->gdfifocfg = dwc2_readl(hsotg, GDFIFOCFG);
+       gr->pcgcctl1 = dwc2_readl(hsotg, PCGCCTL1);
+       gr->glpmcfg = dwc2_readl(hsotg, GLPMCFG);
+       gr->gi2cctl = dwc2_readl(hsotg, GI2CCTL);
+       gr->pcgcctl = dwc2_readl(hsotg, PCGCTL);
 
        gr->valid = true;
        return 0;
@@ -111,18 +111,18 @@ int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
        }
        gr->valid = false;
 
-       dwc2_writel(0xffffffff, hsotg->regs + GINTSTS);
-       dwc2_writel(gr->gotgctl, hsotg->regs + GOTGCTL);
-       dwc2_writel(gr->gintmsk, hsotg->regs + GINTMSK);
-       dwc2_writel(gr->gusbcfg, hsotg->regs + GUSBCFG);
-       dwc2_writel(gr->gahbcfg, hsotg->regs + GAHBCFG);
-       dwc2_writel(gr->grxfsiz, hsotg->regs + GRXFSIZ);
-       dwc2_writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ);
-       dwc2_writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG);
-       dwc2_writel(gr->pcgcctl1, hsotg->regs + PCGCCTL1);
-       dwc2_writel(gr->glpmcfg, hsotg->regs + GLPMCFG);
-       dwc2_writel(gr->pcgcctl, hsotg->regs + PCGCTL);
-       dwc2_writel(gr->gi2cctl, hsotg->regs + GI2CCTL);
+       dwc2_writel(hsotg, 0xffffffff, GINTSTS);
+       dwc2_writel(hsotg, gr->gotgctl, GOTGCTL);
+       dwc2_writel(hsotg, gr->gintmsk, GINTMSK);
+       dwc2_writel(hsotg, gr->gusbcfg, GUSBCFG);
+       dwc2_writel(hsotg, gr->gahbcfg, GAHBCFG);
+       dwc2_writel(hsotg, gr->grxfsiz, GRXFSIZ);
+       dwc2_writel(hsotg, gr->gnptxfsiz, GNPTXFSIZ);
+       dwc2_writel(hsotg, gr->gdfifocfg, GDFIFOCFG);
+       dwc2_writel(hsotg, gr->pcgcctl1, PCGCCTL1);
+       dwc2_writel(hsotg, gr->glpmcfg, GLPMCFG);
+       dwc2_writel(hsotg, gr->pcgcctl, PCGCTL);
+       dwc2_writel(hsotg, gr->gi2cctl, GI2CCTL);
 
        return 0;
 }
@@ -141,17 +141,17 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore)
        if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
                return -ENOTSUPP;
 
-       pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
+       pcgcctl = dwc2_readl(hsotg, PCGCTL);
        pcgcctl &= ~PCGCTL_STOPPCLK;
-       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(hsotg, pcgcctl, PCGCTL);
 
-       pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
+       pcgcctl = dwc2_readl(hsotg, PCGCTL);
        pcgcctl &= ~PCGCTL_PWRCLMP;
-       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(hsotg, pcgcctl, PCGCTL);
 
-       pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
+       pcgcctl = dwc2_readl(hsotg, PCGCTL);
        pcgcctl &= ~PCGCTL_RSTPDWNMODULE;
-       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(hsotg, pcgcctl, PCGCTL);
 
        udelay(100);
        if (restore) {
@@ -222,21 +222,21 @@ int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg)
         * Clear any pending interrupts since dwc2 will not be able to
         * clear them after entering partial_power_down.
         */
-       dwc2_writel(0xffffffff, hsotg->regs + GINTSTS);
+       dwc2_writel(hsotg, 0xffffffff, GINTSTS);
 
        /* Put the controller in low power state */
-       pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
+       pcgcctl = dwc2_readl(hsotg, PCGCTL);
 
        pcgcctl |= PCGCTL_PWRCLMP;
-       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(hsotg, pcgcctl, PCGCTL);
        ndelay(20);
 
        pcgcctl |= PCGCTL_RSTPDWNMODULE;
-       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(hsotg, pcgcctl, PCGCTL);
        ndelay(20);
 
        pcgcctl |= PCGCTL_STOPPCLK;
-       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(hsotg, pcgcctl, PCGCTL);
 
        return ret;
 }
@@ -272,39 +272,39 @@ static void dwc2_restore_essential_regs(struct dwc2_hsotg *hsotg, int rmode,
                if (!(pcgcctl & PCGCTL_P2HD_DEV_ENUM_SPD_MASK))
                        pcgcctl |= BIT(17);
        }
-       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(hsotg, pcgcctl, PCGCTL);
 
        /* Umnask global Interrupt in GAHBCFG and restore it */
-       dwc2_writel(gr->gahbcfg | GAHBCFG_GLBL_INTR_EN, hsotg->regs + GAHBCFG);
+       dwc2_writel(hsotg, gr->gahbcfg | GAHBCFG_GLBL_INTR_EN, GAHBCFG);
 
        /* Clear all pending interupts */
-       dwc2_writel(0xffffffff, hsotg->regs + GINTSTS);
+       dwc2_writel(hsotg, 0xffffffff, GINTSTS);
 
        /* Unmask restore done interrupt */
-       dwc2_writel(GINTSTS_RESTOREDONE, hsotg->regs + GINTMSK);
+       dwc2_writel(hsotg, GINTSTS_RESTOREDONE, GINTMSK);
 
        /* Restore GUSBCFG and HCFG/DCFG */
-       dwc2_writel(gr->gusbcfg, hsotg->regs + GUSBCFG);
+       dwc2_writel(hsotg, gr->gusbcfg, GUSBCFG);
 
        if (is_host) {
-               dwc2_writel(hr->hcfg, hsotg->regs + HCFG);
+               dwc2_writel(hsotg, hr->hcfg, HCFG);
                if (rmode)
                        pcgcctl |= PCGCTL_RESTOREMODE;
-               dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+               dwc2_writel(hsotg, pcgcctl, PCGCTL);
                udelay(10);
 
                pcgcctl |= PCGCTL_ESS_REG_RESTORED;
-               dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+               dwc2_writel(hsotg, pcgcctl, PCGCTL);
                udelay(10);
        } else {
-               dwc2_writel(dr->dcfg, hsotg->regs + DCFG);
+               dwc2_writel(hsotg, dr->dcfg, DCFG);
                if (!rmode)
                        pcgcctl |= PCGCTL_RESTOREMODE | PCGCTL_RSTPDWNMODULE;
-               dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+               dwc2_writel(hsotg, pcgcctl, PCGCTL);
                udelay(10);
 
                pcgcctl |= PCGCTL_ESS_REG_RESTORED;
-               dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+               dwc2_writel(hsotg, pcgcctl, PCGCTL);
                udelay(10);
        }
 }
@@ -322,42 +322,42 @@ void dwc2_hib_restore_common(struct dwc2_hsotg *hsotg, int rem_wakeup,
        u32 gpwrdn;
 
        /* Switch-on voltage to the core */
-       gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+       gpwrdn = dwc2_readl(hsotg, GPWRDN);
        gpwrdn &= ~GPWRDN_PWRDNSWTCH;
-       dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+       dwc2_writel(hsotg, gpwrdn, GPWRDN);
        udelay(10);
 
        /* Reset core */
-       gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+       gpwrdn = dwc2_readl(hsotg, GPWRDN);
        gpwrdn &= ~GPWRDN_PWRDNRSTN;
-       dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+       dwc2_writel(hsotg, gpwrdn, GPWRDN);
        udelay(10);
 
        /* Enable restore from PMU */
-       gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+       gpwrdn = dwc2_readl(hsotg, GPWRDN);
        gpwrdn |= GPWRDN_RESTORE;
-       dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+       dwc2_writel(hsotg, gpwrdn, GPWRDN);
        udelay(10);
 
        /* Disable Power Down Clamp */
-       gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+       gpwrdn = dwc2_readl(hsotg, GPWRDN);
        gpwrdn &= ~GPWRDN_PWRDNCLMP;
-       dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+       dwc2_writel(hsotg, gpwrdn, GPWRDN);
        udelay(50);
 
        if (!is_host && rem_wakeup)
                udelay(70);
 
        /* Deassert reset core */
-       gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+       gpwrdn = dwc2_readl(hsotg, GPWRDN);
        gpwrdn |= GPWRDN_PWRDNRSTN;
-       dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+       dwc2_writel(hsotg, gpwrdn, GPWRDN);
        udelay(10);
 
        /* Disable PMU interrupt */
-       gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+       gpwrdn = dwc2_readl(hsotg, GPWRDN);
        gpwrdn &= ~GPWRDN_PMUINTSEL;
-       dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+       dwc2_writel(hsotg, gpwrdn, GPWRDN);
        udelay(10);
 
        /* Set Restore Essential Regs bit in PCGCCTL register */
@@ -431,7 +431,7 @@ static bool dwc2_iddig_filter_enabled(struct dwc2_hsotg *hsotg)
                return false;
 
        /* Check if core configuration includes the IDDIG filter. */
-       ghwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4);
+       ghwcfg4 = dwc2_readl(hsotg, GHWCFG4);
        if (!(ghwcfg4 & GHWCFG4_IDDIG_FILT_EN))
                return false;
 
@@ -439,9 +439,9 @@ static bool dwc2_iddig_filter_enabled(struct dwc2_hsotg *hsotg)
         * Check if the IDDIG debounce filter is bypassed. Available
         * in core version >= 3.10a.
         */
-       gsnpsid = dwc2_readl(hsotg->regs + GSNPSID);
+       gsnpsid = dwc2_readl(hsotg, GSNPSID);
        if (gsnpsid >= DWC2_CORE_REV_3_10a) {
-               u32 gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+               u32 gotgctl = dwc2_readl(hsotg, GOTGCTL);
 
                if (gotgctl & GOTGCTL_DBNCE_FLTR_BYPASS)
                        return false;
@@ -510,8 +510,8 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
         * reset and account for this delay after the reset.
         */
        if (dwc2_iddig_filter_enabled(hsotg)) {
-               u32 gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
-               u32 gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
+               u32 gotgctl = dwc2_readl(hsotg, GOTGCTL);
+               u32 gusbcfg = dwc2_readl(hsotg, GUSBCFG);
 
                if (!(gotgctl & GOTGCTL_CONID_B) ||
                    (gusbcfg & GUSBCFG_FORCEHOSTMODE)) {
@@ -520,9 +520,9 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
        }
 
        /* Core Soft Reset */
-       greset = dwc2_readl(hsotg->regs + GRSTCTL);
+       greset = dwc2_readl(hsotg, GRSTCTL);
        greset |= GRSTCTL_CSFTRST;
-       dwc2_writel(greset, hsotg->regs + GRSTCTL);
+       dwc2_writel(hsotg, greset, GRSTCTL);
 
        if (dwc2_hsotg_wait_bit_clear(hsotg, GRSTCTL, GRSTCTL_CSFTRST, 50)) {
                dev_warn(hsotg->dev, "%s: HANG! Soft Reset timeout GRSTCTL GRSTCTL_CSFTRST\n",
@@ -594,14 +594,14 @@ void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
        if (WARN_ON(!host && hsotg->dr_mode == USB_DR_MODE_HOST))
                return;
 
-       gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
+       gusbcfg = dwc2_readl(hsotg, GUSBCFG);
 
        set = host ? GUSBCFG_FORCEHOSTMODE : GUSBCFG_FORCEDEVMODE;
        clear = host ? GUSBCFG_FORCEDEVMODE : GUSBCFG_FORCEHOSTMODE;
 
        gusbcfg &= ~clear;
        gusbcfg |= set;
-       dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
+       dwc2_writel(hsotg, gusbcfg, GUSBCFG);
 
        dwc2_wait_for_mode(hsotg, host);
        return;
@@ -627,10 +627,10 @@ static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
 
        dev_dbg(hsotg->dev, "Clearing force mode bits\n");
 
-       gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
+       gusbcfg = dwc2_readl(hsotg, GUSBCFG);
        gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
        gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
-       dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
+       dwc2_writel(hsotg, gusbcfg, GUSBCFG);
 
        if (dwc2_iddig_filter_enabled(hsotg))
                msleep(100);
@@ -670,11 +670,11 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
 void dwc2_enable_acg(struct dwc2_hsotg *hsotg)
 {
        if (hsotg->params.acg_enable) {
-               u32 pcgcctl1 = dwc2_readl(hsotg->regs + PCGCCTL1);
+               u32 pcgcctl1 = dwc2_readl(hsotg, PCGCCTL1);
 
                dev_dbg(hsotg->dev, "Enabling Active Clock Gating\n");
                pcgcctl1 |= PCGCCTL1_GATEEN;
-               dwc2_writel(pcgcctl1, hsotg->regs + PCGCCTL1);
+               dwc2_writel(hsotg, pcgcctl1, PCGCCTL1);
        }
 }
 
@@ -695,56 +695,57 @@ void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg)
        dev_dbg(hsotg->dev, "Host Global Registers\n");
        addr = hsotg->regs + HCFG;
        dev_dbg(hsotg->dev, "HCFG        @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, HCFG));
        addr = hsotg->regs + HFIR;
        dev_dbg(hsotg->dev, "HFIR        @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, HFIR));
        addr = hsotg->regs + HFNUM;
        dev_dbg(hsotg->dev, "HFNUM       @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, HFNUM));
        addr = hsotg->regs + HPTXSTS;
        dev_dbg(hsotg->dev, "HPTXSTS     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, HPTXSTS));
        addr = hsotg->regs + HAINT;
        dev_dbg(hsotg->dev, "HAINT       @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, HAINT));
        addr = hsotg->regs + HAINTMSK;
        dev_dbg(hsotg->dev, "HAINTMSK    @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, HAINTMSK));
        if (hsotg->params.dma_desc_enable) {
                addr = hsotg->regs + HFLBADDR;
                dev_dbg(hsotg->dev, "HFLBADDR @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, dwc2_readl(addr));
+                       (unsigned long)addr, dwc2_readl(hsotg, HFLBADDR));
        }
 
        addr = hsotg->regs + HPRT0;
        dev_dbg(hsotg->dev, "HPRT0       @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, HPRT0));
 
        for (i = 0; i < hsotg->params.host_channels; i++) {
                dev_dbg(hsotg->dev, "Host Channel %d Specific Registers\n", i);
                addr = hsotg->regs + HCCHAR(i);
                dev_dbg(hsotg->dev, "HCCHAR      @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, dwc2_readl(addr));
+                       (unsigned long)addr, dwc2_readl(hsotg, HCCHAR(i)));
                addr = hsotg->regs + HCSPLT(i);
                dev_dbg(hsotg->dev, "HCSPLT      @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, dwc2_readl(addr));
+                       (unsigned long)addr, dwc2_readl(hsotg, HCSPLT(i)));
                addr = hsotg->regs + HCINT(i);
                dev_dbg(hsotg->dev, "HCINT       @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, dwc2_readl(addr));
+                       (unsigned long)addr, dwc2_readl(hsotg, HCINT(i)));
                addr = hsotg->regs + HCINTMSK(i);
                dev_dbg(hsotg->dev, "HCINTMSK    @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, dwc2_readl(addr));
+                       (unsigned long)addr, dwc2_readl(hsotg, HCINTMSK(i)));
                addr = hsotg->regs + HCTSIZ(i);
                dev_dbg(hsotg->dev, "HCTSIZ      @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, dwc2_readl(addr));
+                       (unsigned long)addr, dwc2_readl(hsotg, HCTSIZ(i)));
                addr = hsotg->regs + HCDMA(i);
                dev_dbg(hsotg->dev, "HCDMA       @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, dwc2_readl(addr));
+                       (unsigned long)addr, dwc2_readl(hsotg, HCDMA(i)));
                if (hsotg->params.dma_desc_enable) {
                        addr = hsotg->regs + HCDMAB(i);
                        dev_dbg(hsotg->dev, "HCDMAB      @0x%08lX : 0x%08X\n",
-                               (unsigned long)addr, dwc2_readl(addr));
+                               (unsigned long)addr, dwc2_readl(hsotg,
+                                                               HCDMAB(i)));
                }
        }
 #endif
@@ -766,80 +767,80 @@ void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg)
        dev_dbg(hsotg->dev, "Core Global Registers\n");
        addr = hsotg->regs + GOTGCTL;
        dev_dbg(hsotg->dev, "GOTGCTL     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GOTGCTL));
        addr = hsotg->regs + GOTGINT;
        dev_dbg(hsotg->dev, "GOTGINT     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GOTGINT));
        addr = hsotg->regs + GAHBCFG;
        dev_dbg(hsotg->dev, "GAHBCFG     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GAHBCFG));
        addr = hsotg->regs + GUSBCFG;
        dev_dbg(hsotg->dev, "GUSBCFG     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GUSBCFG));
        addr = hsotg->regs + GRSTCTL;
        dev_dbg(hsotg->dev, "GRSTCTL     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GRSTCTL));
        addr = hsotg->regs + GINTSTS;
        dev_dbg(hsotg->dev, "GINTSTS     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GINTSTS));
        addr = hsotg->regs + GINTMSK;
        dev_dbg(hsotg->dev, "GINTMSK     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GINTMSK));
        addr = hsotg->regs + GRXSTSR;
        dev_dbg(hsotg->dev, "GRXSTSR     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GRXSTSR));
        addr = hsotg->regs + GRXFSIZ;
        dev_dbg(hsotg->dev, "GRXFSIZ     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GRXFSIZ));
        addr = hsotg->regs + GNPTXFSIZ;
        dev_dbg(hsotg->dev, "GNPTXFSIZ   @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GNPTXFSIZ));
        addr = hsotg->regs + GNPTXSTS;
        dev_dbg(hsotg->dev, "GNPTXSTS    @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GNPTXSTS));
        addr = hsotg->regs + GI2CCTL;
        dev_dbg(hsotg->dev, "GI2CCTL     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GI2CCTL));
        addr = hsotg->regs + GPVNDCTL;
        dev_dbg(hsotg->dev, "GPVNDCTL    @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GPVNDCTL));
        addr = hsotg->regs + GGPIO;
        dev_dbg(hsotg->dev, "GGPIO       @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GGPIO));
        addr = hsotg->regs + GUID;
        dev_dbg(hsotg->dev, "GUID        @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GUID));
        addr = hsotg->regs + GSNPSID;
        dev_dbg(hsotg->dev, "GSNPSID     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GSNPSID));
        addr = hsotg->regs + GHWCFG1;
        dev_dbg(hsotg->dev, "GHWCFG1     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GHWCFG1));
        addr = hsotg->regs + GHWCFG2;
        dev_dbg(hsotg->dev, "GHWCFG2     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GHWCFG2));
        addr = hsotg->regs + GHWCFG3;
        dev_dbg(hsotg->dev, "GHWCFG3     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GHWCFG3));
        addr = hsotg->regs + GHWCFG4;
        dev_dbg(hsotg->dev, "GHWCFG4     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GHWCFG4));
        addr = hsotg->regs + GLPMCFG;
        dev_dbg(hsotg->dev, "GLPMCFG     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GLPMCFG));
        addr = hsotg->regs + GPWRDN;
        dev_dbg(hsotg->dev, "GPWRDN      @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GPWRDN));
        addr = hsotg->regs + GDFIFOCFG;
        dev_dbg(hsotg->dev, "GDFIFOCFG   @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, GDFIFOCFG));
        addr = hsotg->regs + HPTXFSIZ;
        dev_dbg(hsotg->dev, "HPTXFSIZ    @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, HPTXFSIZ));
 
        addr = hsotg->regs + PCGCTL;
        dev_dbg(hsotg->dev, "PCGCTL      @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, dwc2_readl(addr));
+               (unsigned long)addr, dwc2_readl(hsotg, PCGCTL));
 #endif
 }
 
@@ -862,7 +863,7 @@ void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num)
 
        greset = GRSTCTL_TXFFLSH;
        greset |= num << GRSTCTL_TXFNUM_SHIFT & GRSTCTL_TXFNUM_MASK;
-       dwc2_writel(greset, hsotg->regs + GRSTCTL);
+       dwc2_writel(hsotg, greset, GRSTCTL);
 
        if (dwc2_hsotg_wait_bit_clear(hsotg, GRSTCTL, GRSTCTL_TXFFLSH, 10000))
                dev_warn(hsotg->dev, "%s:  HANG! timeout GRSTCTL GRSTCTL_TXFFLSH\n",
@@ -889,7 +890,7 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg)
                         __func__);
 
        greset = GRSTCTL_RXFFLSH;
-       dwc2_writel(greset, hsotg->regs + GRSTCTL);
+       dwc2_writel(hsotg, greset, GRSTCTL);
 
        /* Wait for RxFIFO flush done */
        if (dwc2_hsotg_wait_bit_clear(hsotg, GRSTCTL, GRSTCTL_RXFFLSH, 10000))
@@ -902,7 +903,7 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg)
 
 bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)
 {
-       if (dwc2_readl(hsotg->regs + GSNPSID) == 0xffffffff)
+       if (dwc2_readl(hsotg, GSNPSID) == 0xffffffff)
                return false;
        else
                return true;
@@ -916,10 +917,10 @@ bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)
  */
 void dwc2_enable_global_interrupts(struct dwc2_hsotg *hsotg)
 {
-       u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
+       u32 ahbcfg = dwc2_readl(hsotg, GAHBCFG);
 
        ahbcfg |= GAHBCFG_GLBL_INTR_EN;
-       dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
+       dwc2_writel(hsotg, ahbcfg, GAHBCFG);
 }
 
 /**
@@ -930,16 +931,16 @@ void dwc2_enable_global_interrupts(struct dwc2_hsotg *hsotg)
  */
 void dwc2_disable_global_interrupts(struct dwc2_hsotg *hsotg)
 {
-       u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
+       u32 ahbcfg = dwc2_readl(hsotg, GAHBCFG);
 
        ahbcfg &= ~GAHBCFG_GLBL_INTR_EN;
-       dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
+       dwc2_writel(hsotg, ahbcfg, GAHBCFG);
 }
 
 /* Returns the controller's GHWCFG2.OTG_MODE. */
 unsigned int dwc2_op_mode(struct dwc2_hsotg *hsotg)
 {
-       u32 ghwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2);
+       u32 ghwcfg2 = dwc2_readl(hsotg, GHWCFG2);
 
        return (ghwcfg2 & GHWCFG2_OP_MODE_MASK) >>
                GHWCFG2_OP_MODE_SHIFT;
@@ -988,7 +989,7 @@ int dwc2_hsotg_wait_bit_set(struct dwc2_hsotg *hsotg, u32 offset, u32 mask,
        u32 i;
 
        for (i = 0; i < timeout; i++) {
-               if (dwc2_readl(hsotg->regs + offset) & mask)
+               if (dwc2_readl(hsotg, offset) & mask)
                        return 0;
                udelay(1);
        }
@@ -1011,7 +1012,7 @@ int dwc2_hsotg_wait_bit_clear(struct dwc2_hsotg *hsotg, u32 offset, u32 mask,
        u32 i;
 
        for (i = 0; i < timeout; i++) {
-               if (!(dwc2_readl(hsotg->regs + offset) & mask))
+               if (!(dwc2_readl(hsotg, offset) & mask))
                        return 0;
                udelay(1);
        }
index 71b3b08ad516c9fb3bfbd403da1687b5825e7e14..cc9c93affa148963289d56bf8e8e083c3ac08b2d 100644 (file)
        DWC2_TRACE_SCHEDULER_VB(pr_fmt("%s: SCH: " fmt),                \
                                dev_name(hsotg->dev), ##__VA_ARGS__)
 
-#ifdef CONFIG_MIPS
-/*
- * There are some MIPS machines that can run in either big-endian
- * or little-endian mode and that use the dwc2 register without
- * a byteswap in both ways.
- * Unlike other architectures, MIPS apparently does not require a
- * barrier before the __raw_writel() to synchronize with DMA but does
- * require the barrier after the __raw_writel() to serialize a set of
- * writes. This set of operations was added specifically for MIPS and
- * should only be used there.
- */
-static inline u32 dwc2_readl(const void __iomem *addr)
-{
-       u32 value = __raw_readl(addr);
-
-       /* In order to preserve endianness __raw_* operation is used. Therefore
-        * a barrier is needed to ensure IO access is not re-ordered across
-        * reads or writes
-        */
-       mb();
-       return value;
-}
-
-static inline void dwc2_writel(u32 value, void __iomem *addr)
-{
-       __raw_writel(value, addr);
-
-       /*
-        * In order to preserve endianness __raw_* operation is used. Therefore
-        * a barrier is needed to ensure IO access is not re-ordered across
-        * reads or writes
-        */
-       mb();
-#ifdef DWC2_LOG_WRITES
-       pr_info("INFO:: wrote %08x to %p\n", value, addr);
-#endif
-}
-#else
-/* Normal architectures just use readl/write */
-static inline u32 dwc2_readl(const void __iomem *addr)
-{
-       return readl(addr);
-}
-
-static inline void dwc2_writel(u32 value, void __iomem *addr)
-{
-       writel(value, addr);
-
-#ifdef DWC2_LOG_WRITES
-       pr_info("info:: wrote %08x to %p\n", value, addr);
-#endif
-}
-#endif
-
 /* Maximum number of Endpoints/HostChannels */
 #define MAX_EPS_CHANNELS       16
 
@@ -911,6 +857,7 @@ struct dwc2_hregs_backup {
  * @gr_backup: Backup of global registers during suspend
  * @dr_backup: Backup of device registers during suspend
  * @hr_backup: Backup of host registers during suspend
+ * @needs_byte_swap:           Specifies whether the opposite endianness.
  *
  * These are for host mode:
  *
@@ -1100,6 +1047,7 @@ struct dwc2_hsotg {
 
        struct dentry *debug_root;
        struct debugfs_regset32 *regset;
+       bool needs_byte_swap;
 
        /* DWC OTG HW Release versions */
 #define DWC2_CORE_REV_2_71a    0x4f54271a
@@ -1215,6 +1163,55 @@ struct dwc2_hsotg {
 #endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
 };
 
+/* Normal architectures just use readl/write */
+static inline u32 dwc2_readl(struct dwc2_hsotg *hsotg, u32 offset)
+{
+       u32 val;
+
+       val = readl(hsotg->regs + offset);
+       if (hsotg->needs_byte_swap)
+               return swab32(val);
+       else
+               return val;
+}
+
+static inline void dwc2_writel(struct dwc2_hsotg *hsotg, u32 value, u32 offset)
+{
+       if (hsotg->needs_byte_swap)
+               writel(swab32(value), hsotg->regs + offset);
+       else
+               writel(value, hsotg->regs + offset);
+
+#ifdef DWC2_LOG_WRITES
+       pr_info("info:: wrote %08x to %p\n", value, hsotg->regs + offset);
+#endif
+}
+
+static inline void dwc2_readl_rep(struct dwc2_hsotg *hsotg, u32 offset,
+                                 void *buffer, unsigned int count)
+{
+       if (count) {
+               u32 *buf = buffer;
+
+               do {
+                       u32 x = dwc2_readl(hsotg, offset);
+                       *buf++ = x;
+               } while (--count);
+       }
+}
+
+static inline void dwc2_writel_rep(struct dwc2_hsotg *hsotg, u32 offset,
+                                  const void *buffer, unsigned int count)
+{
+       if (count) {
+               const u32 *buf = buffer;
+
+               do {
+                       dwc2_writel(hsotg, *buf++, offset);
+               } while (--count);
+       }
+}
+
 /* Reasons for halting a host channel */
 enum dwc2_halt_status {
        DWC2_HC_XFER_NO_HALT_STATUS,
@@ -1320,12 +1317,12 @@ bool dwc2_hw_is_device(struct dwc2_hsotg *hsotg);
  */
 static inline int dwc2_is_host_mode(struct dwc2_hsotg *hsotg)
 {
-       return (dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) != 0;
+       return (dwc2_readl(hsotg, GINTSTS) & GINTSTS_CURMODE_HOST) != 0;
 }
 
 static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg)
 {
-       return (dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) == 0;
+       return (dwc2_readl(hsotg, GINTSTS) & GINTSTS_CURMODE_HOST) == 0;
 }
 
 /*
index cc90b58b6b3c016fccef332e495804b907eac357..19ae2595f1c3ee4ac1614dec6c5deee8af6f100e 100644 (file)
@@ -81,11 +81,11 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg)
  */
 static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
 {
-       u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
+       u32 hprt0 = dwc2_readl(hsotg, HPRT0);
 
        if (hprt0 & HPRT0_ENACHG) {
                hprt0 &= ~HPRT0_ENA;
-               dwc2_writel(hprt0, hsotg->regs + HPRT0);
+               dwc2_writel(hsotg, hprt0, HPRT0);
        }
 }
 
@@ -97,7 +97,7 @@ static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
 static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
 {
        /* Clear interrupt */
-       dwc2_writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
+       dwc2_writel(hsotg, GINTSTS_MODEMIS, GINTSTS);
 
        dev_warn(hsotg->dev, "Mode Mismatch Interrupt: currently in %s mode\n",
                 dwc2_is_host_mode(hsotg) ? "Host" : "Device");
@@ -115,8 +115,8 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
        u32 gotgctl;
        u32 gintmsk;
 
-       gotgint = dwc2_readl(hsotg->regs + GOTGINT);
-       gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+       gotgint = dwc2_readl(hsotg, GOTGINT);
+       gotgctl = dwc2_readl(hsotg, GOTGCTL);
        dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint,
                dwc2_op_state_str(hsotg));
 
@@ -124,7 +124,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                dev_dbg(hsotg->dev,
                        " ++OTG Interrupt: Session End Detected++ (%s)\n",
                        dwc2_op_state_str(hsotg));
-               gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+               gotgctl = dwc2_readl(hsotg, GOTGCTL);
 
                if (dwc2_is_device_mode(hsotg))
                        dwc2_hsotg_disconnect(hsotg);
@@ -150,24 +150,24 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                        hsotg->lx_state = DWC2_L0;
                }
 
-               gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+               gotgctl = dwc2_readl(hsotg, GOTGCTL);
                gotgctl &= ~GOTGCTL_DEVHNPEN;
-               dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
+               dwc2_writel(hsotg, gotgctl, GOTGCTL);
        }
 
        if (gotgint & GOTGINT_SES_REQ_SUC_STS_CHNG) {
                dev_dbg(hsotg->dev,
                        " ++OTG Interrupt: Session Request Success Status Change++\n");
-               gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+               gotgctl = dwc2_readl(hsotg, GOTGCTL);
                if (gotgctl & GOTGCTL_SESREQSCS) {
                        if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS &&
                            hsotg->params.i2c_enable) {
                                hsotg->srp_success = 1;
                        } else {
                                /* Clear Session Request */
-                               gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+                               gotgctl = dwc2_readl(hsotg, GOTGCTL);
                                gotgctl &= ~GOTGCTL_SESREQ;
-                               dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
+                               dwc2_writel(hsotg, gotgctl, GOTGCTL);
                        }
                }
        }
@@ -177,7 +177,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                 * Print statements during the HNP interrupt handling
                 * can cause it to fail
                 */
-               gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+               gotgctl = dwc2_readl(hsotg, GOTGCTL);
                /*
                 * WA for 3.00a- HW is not setting cur_mode, even sometimes
                 * this does not help
@@ -197,9 +197,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                                 * interrupt does not get handled and Linux
                                 * complains loudly.
                                 */
-                               gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+                               gintmsk = dwc2_readl(hsotg, GINTMSK);
                                gintmsk &= ~GINTSTS_SOF;
-                               dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
+                               dwc2_writel(hsotg, gintmsk, GINTMSK);
 
                                /*
                                 * Call callback function with spin lock
@@ -213,9 +213,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                                hsotg->op_state = OTG_STATE_B_HOST;
                        }
                } else {
-                       gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+                       gotgctl = dwc2_readl(hsotg, GOTGCTL);
                        gotgctl &= ~(GOTGCTL_HNPREQ | GOTGCTL_DEVHNPEN);
-                       dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
+                       dwc2_writel(hsotg, gotgctl, GOTGCTL);
                        dev_dbg(hsotg->dev, "HNP Failed\n");
                        dev_err(hsotg->dev,
                                "Device Not Connected/Responding\n");
@@ -241,9 +241,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                        hsotg->op_state = OTG_STATE_A_PERIPHERAL;
                } else {
                        /* Need to disable SOF interrupt immediately */
-                       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+                       gintmsk = dwc2_readl(hsotg, GINTMSK);
                        gintmsk &= ~GINTSTS_SOF;
-                       dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
+                       dwc2_writel(hsotg, gintmsk, GINTMSK);
                        spin_unlock(&hsotg->lock);
                        dwc2_hcd_start(hsotg);
                        spin_lock(&hsotg->lock);
@@ -258,7 +258,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                dev_dbg(hsotg->dev, " ++OTG Interrupt: Debounce Done++\n");
 
        /* Clear GOTGINT */
-       dwc2_writel(gotgint, hsotg->regs + GOTGINT);
+       dwc2_writel(hsotg, gotgint, GOTGINT);
 }
 
 /**
@@ -276,12 +276,12 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
        u32 gintmsk;
 
        /* Clear interrupt */
-       dwc2_writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
+       dwc2_writel(hsotg, GINTSTS_CONIDSTSCHNG, GINTSTS);
 
        /* Need to disable SOF interrupt immediately */
-       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+       gintmsk = dwc2_readl(hsotg, GINTMSK);
        gintmsk &= ~GINTSTS_SOF;
-       dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
+       dwc2_writel(hsotg, gintmsk, GINTMSK);
 
        dev_dbg(hsotg->dev, " ++Connector ID Status Change Interrupt++  (%s)\n",
                dwc2_is_host_mode(hsotg) ? "Host" : "Device");
@@ -314,7 +314,7 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
        int ret;
 
        /* Clear interrupt */
-       dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
+       dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS);
 
        dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
                hsotg->lx_state);
@@ -351,15 +351,15 @@ static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
                return;
        }
 
-       glpmcfg = dwc2_readl(hsotg->regs + GLPMCFG);
+       glpmcfg = dwc2_readl(hsotg, GLPMCFG);
        if (dwc2_is_device_mode(hsotg)) {
                dev_dbg(hsotg->dev, "Exit from L1 state\n");
                glpmcfg &= ~GLPMCFG_ENBLSLPM;
                glpmcfg &= ~GLPMCFG_HIRD_THRES_EN;
-               dwc2_writel(glpmcfg, hsotg->regs + GLPMCFG);
+               dwc2_writel(hsotg, glpmcfg, GLPMCFG);
 
                do {
-                       glpmcfg = dwc2_readl(hsotg->regs + GLPMCFG);
+                       glpmcfg = dwc2_readl(hsotg, GLPMCFG);
 
                        if (!(glpmcfg & (GLPMCFG_COREL1RES_MASK |
                                         GLPMCFG_L1RESUMEOK | GLPMCFG_SLPSTS)))
@@ -398,7 +398,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
        int ret;
 
        /* Clear interrupt */
-       dwc2_writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
+       dwc2_writel(hsotg, GINTSTS_WKUPINT, GINTSTS);
 
        dev_dbg(hsotg->dev, "++Resume or Remote Wakeup Detected Interrupt++\n");
        dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
@@ -410,13 +410,13 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
 
        if (dwc2_is_device_mode(hsotg)) {
                dev_dbg(hsotg->dev, "DSTS=0x%0x\n",
-                       dwc2_readl(hsotg->regs + DSTS));
+                       dwc2_readl(hsotg, DSTS));
                if (hsotg->lx_state == DWC2_L2) {
-                       u32 dctl = dwc2_readl(hsotg->regs + DCTL);
+                       u32 dctl = dwc2_readl(hsotg, DCTL);
 
                        /* Clear Remote Wakeup Signaling */
                        dctl &= ~DCTL_RMTWKUPSIG;
-                       dwc2_writel(dctl, hsotg->regs + DCTL);
+                       dwc2_writel(hsotg, dctl, DCTL);
                        ret = dwc2_exit_partial_power_down(hsotg, true);
                        if (ret && (ret != -ENOTSUPP))
                                dev_err(hsotg->dev, "exit power_down failed\n");
@@ -430,11 +430,11 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
                        return;
 
                if (hsotg->lx_state != DWC2_L1) {
-                       u32 pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
+                       u32 pcgcctl = dwc2_readl(hsotg, PCGCTL);
 
                        /* Restart the Phy Clock */
                        pcgcctl &= ~PCGCTL_STOPPCLK;
-                       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+                       dwc2_writel(hsotg, pcgcctl, PCGCTL);
                        mod_timer(&hsotg->wkp_timer,
                                  jiffies + msecs_to_jiffies(71));
                } else {
@@ -450,7 +450,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
  */
 static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg)
 {
-       dwc2_writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS);
+       dwc2_writel(hsotg, GINTSTS_DISCONNINT, GINTSTS);
 
        dev_dbg(hsotg->dev, "++Disconnect Detected Interrupt++ (%s) %s\n",
                dwc2_is_host_mode(hsotg) ? "Host" : "Device",
@@ -474,7 +474,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
        int ret;
 
        /* Clear interrupt */
-       dwc2_writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
+       dwc2_writel(hsotg, GINTSTS_USBSUSP, GINTSTS);
 
        dev_dbg(hsotg->dev, "USB SUSPEND\n");
 
@@ -483,7 +483,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
                 * Check the Device status register to determine if the Suspend
                 * state is active
                 */
-               dsts = dwc2_readl(hsotg->regs + DSTS);
+               dsts = dwc2_readl(hsotg, DSTS);
                dev_dbg(hsotg->dev, "%s: DSTS=0x%0x\n", __func__, dsts);
                dev_dbg(hsotg->dev,
                        "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d HWCFG4.Hibernation=%d\n",
@@ -563,9 +563,9 @@ static void dwc2_handle_lpm_intr(struct dwc2_hsotg *hsotg)
        u32 enslpm;
 
        /* Clear interrupt */
-       dwc2_writel(GINTSTS_LPMTRANRCVD, hsotg->regs + GINTSTS);
+       dwc2_writel(hsotg, GINTSTS_LPMTRANRCVD, GINTSTS);
 
-       glpmcfg = dwc2_readl(hsotg->regs + GLPMCFG);
+       glpmcfg = dwc2_readl(hsotg, GLPMCFG);
 
        if (!(glpmcfg & GLPMCFG_LPMCAP)) {
                dev_err(hsotg->dev, "Unexpected LPM interrupt\n");
@@ -588,16 +588,16 @@ static void dwc2_handle_lpm_intr(struct dwc2_hsotg *hsotg)
                } else {
                        dev_dbg(hsotg->dev, "Entering Sleep with L1 Gating\n");
 
-                       pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
+                       pcgcctl = dwc2_readl(hsotg, PCGCTL);
                        pcgcctl |= PCGCTL_ENBL_SLEEP_GATING;
-                       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+                       dwc2_writel(hsotg, pcgcctl, PCGCTL);
                }
                /**
                 * Examine prt_sleep_sts after TL1TokenTetry period max (10 us)
                 */
                udelay(10);
 
-               glpmcfg = dwc2_readl(hsotg->regs + GLPMCFG);
+               glpmcfg = dwc2_readl(hsotg, GLPMCFG);
 
                if (glpmcfg & GLPMCFG_SLPSTS) {
                        /* Save the current state */
@@ -627,9 +627,9 @@ static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
        u32 gahbcfg;
        u32 gintmsk_common = GINTMSK_COMMON;
 
-       gintsts = dwc2_readl(hsotg->regs + GINTSTS);
-       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
-       gahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
+       gintsts = dwc2_readl(hsotg, GINTSTS);
+       gintmsk = dwc2_readl(hsotg, GINTMSK);
+       gahbcfg = dwc2_readl(hsotg, GAHBCFG);
 
        /* If any common interrupts set */
        if (gintsts & gintmsk_common)
@@ -653,9 +653,9 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
        u32 gpwrdn;
        int linestate;
 
-       gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+       gpwrdn = dwc2_readl(hsotg, GPWRDN);
        /* clear all interrupt */
-       dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+       dwc2_writel(hsotg, gpwrdn, GPWRDN);
        linestate = (gpwrdn & GPWRDN_LINESTATE_MASK) >> GPWRDN_LINESTATE_SHIFT;
        dev_dbg(hsotg->dev,
                "%s: dwc2_handle_gpwrdwn_intr called gpwrdn= %08x\n", __func__,
@@ -668,38 +668,38 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
                dev_dbg(hsotg->dev, "%s: GPWRDN_DISCONN_DET\n", __func__);
 
                /* Switch-on voltage to the core */
-               gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+               gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
                gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
-               dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+               dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
                udelay(10);
 
                /* Reset core */
-               gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+               gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
                gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
-               dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+               dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
                udelay(10);
 
                /* Disable Power Down Clamp */
-               gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+               gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
                gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
-               dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+               dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
                udelay(10);
 
                /* Deassert reset core */
-               gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+               gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
                gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
-               dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+               dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
                udelay(10);
 
                /* Disable PMU interrupt */
-               gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+               gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
                gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
-               dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+               dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
 
                /* De-assert Wakeup Logic */
-               gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+               gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
                gpwrdn_tmp &= ~GPWRDN_PMUACTV;
-               dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+               dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
 
                hsotg->hibernated = 0;
 
@@ -780,10 +780,10 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
 
        /* Reading current frame number value in device or host modes. */
        if (dwc2_is_device_mode(hsotg))
-               hsotg->frame_number = (dwc2_readl(hsotg->regs + DSTS)
+               hsotg->frame_number = (dwc2_readl(hsotg, DSTS)
                                       & DSTS_SOFFN_MASK) >> DSTS_SOFFN_SHIFT;
        else
-               hsotg->frame_number = (dwc2_readl(hsotg->regs + HFNUM)
+               hsotg->frame_number = (dwc2_readl(hsotg, HFNUM)
                                       & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT;
 
        gintsts = dwc2_read_common_intr(hsotg);
index d0bdb799755712fde000179369469f5f64571968..22d015b0424fdc9973fd3d3e5a24322909dea5e5 100644 (file)
@@ -69,7 +69,7 @@ static int testmode_show(struct seq_file *s, void *unused)
        int dctl;
 
        spin_lock_irqsave(&hsotg->lock, flags);
-       dctl = dwc2_readl(hsotg->regs + DCTL);
+       dctl = dwc2_readl(hsotg, DCTL);
        dctl &= DCTL_TSTCTL_MASK;
        dctl >>= DCTL_TSTCTL_SHIFT;
        spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -126,42 +126,41 @@ static const struct file_operations testmode_fops = {
 static int state_show(struct seq_file *seq, void *v)
 {
        struct dwc2_hsotg *hsotg = seq->private;
-       void __iomem *regs = hsotg->regs;
        int idx;
 
        seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n",
-                  dwc2_readl(regs + DCFG),
-                dwc2_readl(regs + DCTL),
-                dwc2_readl(regs + DSTS));
+                  dwc2_readl(hsotg, DCFG),
+                dwc2_readl(hsotg, DCTL),
+                dwc2_readl(hsotg, DSTS));
 
        seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n",
-                  dwc2_readl(regs + DIEPMSK), dwc2_readl(regs + DOEPMSK));
+                  dwc2_readl(hsotg, DIEPMSK), dwc2_readl(hsotg, DOEPMSK));
 
        seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n",
-                  dwc2_readl(regs + GINTMSK),
-                  dwc2_readl(regs + GINTSTS));
+                  dwc2_readl(hsotg, GINTMSK),
+                  dwc2_readl(hsotg, GINTSTS));
 
        seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n",
-                  dwc2_readl(regs + DAINTMSK),
-                  dwc2_readl(regs + DAINT));
+                  dwc2_readl(hsotg, DAINTMSK),
+                  dwc2_readl(hsotg, DAINT));
 
        seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n",
-                  dwc2_readl(regs + GNPTXSTS),
-                  dwc2_readl(regs + GRXSTSR));
+                  dwc2_readl(hsotg, GNPTXSTS),
+                  dwc2_readl(hsotg, GRXSTSR));
 
        seq_puts(seq, "\nEndpoint status:\n");
 
        for (idx = 0; idx < hsotg->num_of_eps; idx++) {
                u32 in, out;
 
-               in = dwc2_readl(regs + DIEPCTL(idx));
-               out = dwc2_readl(regs + DOEPCTL(idx));
+               in = dwc2_readl(hsotg, DIEPCTL(idx));
+               out = dwc2_readl(hsotg, DOEPCTL(idx));
 
                seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x",
                           idx, in, out);
 
-               in = dwc2_readl(regs + DIEPTSIZ(idx));
-               out = dwc2_readl(regs + DOEPTSIZ(idx));
+               in = dwc2_readl(hsotg, DIEPTSIZ(idx));
+               out = dwc2_readl(hsotg, DOEPTSIZ(idx));
 
                seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x",
                           in, out);
@@ -184,14 +183,13 @@ DEFINE_SHOW_ATTRIBUTE(state);
 static int fifo_show(struct seq_file *seq, void *v)
 {
        struct dwc2_hsotg *hsotg = seq->private;
-       void __iomem *regs = hsotg->regs;
        u32 val;
        int idx;
 
        seq_puts(seq, "Non-periodic FIFOs:\n");
-       seq_printf(seq, "RXFIFO: Size %d\n", dwc2_readl(regs + GRXFSIZ));
+       seq_printf(seq, "RXFIFO: Size %d\n", dwc2_readl(hsotg, GRXFSIZ));
 
-       val = dwc2_readl(regs + GNPTXFSIZ);
+       val = dwc2_readl(hsotg, GNPTXFSIZ);
        seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n",
                   val >> FIFOSIZE_DEPTH_SHIFT,
                   val & FIFOSIZE_STARTADDR_MASK);
@@ -199,7 +197,7 @@ static int fifo_show(struct seq_file *seq, void *v)
        seq_puts(seq, "\nPeriodic TXFIFOs:\n");
 
        for (idx = 1; idx < hsotg->num_of_eps; idx++) {
-               val = dwc2_readl(regs + DPTXFSIZN(idx));
+               val = dwc2_readl(hsotg, DPTXFSIZN(idx));
 
                seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx,
                           val >> FIFOSIZE_DEPTH_SHIFT,
@@ -228,7 +226,6 @@ static int ep_show(struct seq_file *seq, void *v)
        struct dwc2_hsotg_ep *ep = seq->private;
        struct dwc2_hsotg *hsotg = ep->parent;
        struct dwc2_hsotg_req *req;
-       void __iomem *regs = hsotg->regs;
        int index = ep->index;
        int show_limit = 15;
        unsigned long flags;
@@ -239,20 +236,20 @@ static int ep_show(struct seq_file *seq, void *v)
        /* first show the register state */
 
        seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n",
-                  dwc2_readl(regs + DIEPCTL(index)),
-                  dwc2_readl(regs + DOEPCTL(index)));
+                  dwc2_readl(hsotg, DIEPCTL(index)),
+                  dwc2_readl(hsotg, DOEPCTL(index)));
 
        seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n",
-                  dwc2_readl(regs + DIEPDMA(index)),
-                  dwc2_readl(regs + DOEPDMA(index)));
+                  dwc2_readl(hsotg, DIEPDMA(index)),
+                  dwc2_readl(hsotg, DOEPDMA(index)));
 
        seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n",
-                  dwc2_readl(regs + DIEPINT(index)),
-                  dwc2_readl(regs + DOEPINT(index)));
+                  dwc2_readl(hsotg, DIEPINT(index)),
+                  dwc2_readl(hsotg, DOEPINT(index)));
 
        seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n",
-                  dwc2_readl(regs + DIEPTSIZ(index)),
-                  dwc2_readl(regs + DOEPTSIZ(index)));
+                  dwc2_readl(hsotg, DIEPTSIZ(index)),
+                  dwc2_readl(hsotg, DOEPTSIZ(index)));
 
        seq_puts(seq, "\n");
        seq_printf(seq, "mps %d\n", ep->ep.maxpacket);
index cefc99ae69b2f489c8fa16f9fca4381ffb405bc3..220c0f9b89b0ba38fec14f088a789887425283a6 100644 (file)
@@ -47,14 +47,14 @@ static inline struct dwc2_hsotg *to_hsotg(struct usb_gadget *gadget)
        return container_of(gadget, struct dwc2_hsotg, gadget);
 }
 
-static inline void dwc2_set_bit(void __iomem *ptr, u32 val)
+static inline void dwc2_set_bit(struct dwc2_hsotg *hsotg, u32 offset, u32 val)
 {
-       dwc2_writel(dwc2_readl(ptr) | val, ptr);
+       dwc2_writel(hsotg, dwc2_readl(hsotg, offset) | val, offset);
 }
 
-static inline void dwc2_clear_bit(void __iomem *ptr, u32 val)
+static inline void dwc2_clear_bit(struct dwc2_hsotg *hsotg, u32 offset, u32 val)
 {
-       dwc2_writel(dwc2_readl(ptr) & ~val, ptr);
+       dwc2_writel(hsotg, dwc2_readl(hsotg, offset) & ~val, offset);
 }
 
 static inline struct dwc2_hsotg_ep *index_to_ep(struct dwc2_hsotg *hsotg,
@@ -129,14 +129,14 @@ static inline void dwc2_gadget_incr_frame_num(struct dwc2_hsotg_ep *hs_ep)
  */
 static void dwc2_hsotg_en_gsint(struct dwc2_hsotg *hsotg, u32 ints)
 {
-       u32 gsintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+       u32 gsintmsk = dwc2_readl(hsotg, GINTMSK);
        u32 new_gsintmsk;
 
        new_gsintmsk = gsintmsk | ints;
 
        if (new_gsintmsk != gsintmsk) {
                dev_dbg(hsotg->dev, "gsintmsk now 0x%08x\n", new_gsintmsk);
-               dwc2_writel(new_gsintmsk, hsotg->regs + GINTMSK);
+               dwc2_writel(hsotg, new_gsintmsk, GINTMSK);
        }
 }
 
@@ -147,13 +147,13 @@ static void dwc2_hsotg_en_gsint(struct dwc2_hsotg *hsotg, u32 ints)
  */
 static void dwc2_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints)
 {
-       u32 gsintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+       u32 gsintmsk = dwc2_readl(hsotg, GINTMSK);
        u32 new_gsintmsk;
 
        new_gsintmsk = gsintmsk & ~ints;
 
        if (new_gsintmsk != gsintmsk)
-               dwc2_writel(new_gsintmsk, hsotg->regs + GINTMSK);
+               dwc2_writel(hsotg, new_gsintmsk, GINTMSK);
 }
 
 /**
@@ -178,12 +178,12 @@ static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
                bit <<= 16;
 
        local_irq_save(flags);
-       daint = dwc2_readl(hsotg->regs + DAINTMSK);
+       daint = dwc2_readl(hsotg, DAINTMSK);
        if (en)
                daint |= bit;
        else
                daint &= ~bit;
-       dwc2_writel(daint, hsotg->regs + DAINTMSK);
+       dwc2_writel(hsotg, daint, DAINTMSK);
        local_irq_restore(flags);
 }
 
@@ -266,10 +266,11 @@ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
        hsotg->fifo_map = 0;
 
        /* set RX/NPTX FIFO sizes */
-       dwc2_writel(hsotg->params.g_rx_fifo_size, hsotg->regs + GRXFSIZ);
-       dwc2_writel((hsotg->params.g_rx_fifo_size << FIFOSIZE_STARTADDR_SHIFT) |
+       dwc2_writel(hsotg, hsotg->params.g_rx_fifo_size, GRXFSIZ);
+       dwc2_writel(hsotg, (hsotg->params.g_rx_fifo_size <<
+                   FIFOSIZE_STARTADDR_SHIFT) |
                    (hsotg->params.g_np_tx_fifo_size << FIFOSIZE_DEPTH_SHIFT),
-                   hsotg->regs + GNPTXFSIZ);
+                   GNPTXFSIZ);
 
        /*
         * arange all the rest of the TX FIFOs, as some versions of this
@@ -295,25 +296,25 @@ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
                          "insufficient fifo memory");
                addr += txfsz[ep];
 
-               dwc2_writel(val, hsotg->regs + DPTXFSIZN(ep));
-               val = dwc2_readl(hsotg->regs + DPTXFSIZN(ep));
+               dwc2_writel(hsotg, val, DPTXFSIZN(ep));
+               val = dwc2_readl(hsotg, DPTXFSIZN(ep));
        }
 
-       dwc2_writel(hsotg->hw_params.total_fifo_size |
+       dwc2_writel(hsotg, hsotg->hw_params.total_fifo_size |
                    addr << GDFIFOCFG_EPINFOBASE_SHIFT,
-                   hsotg->regs + GDFIFOCFG);
+                   GDFIFOCFG);
        /*
         * according to p428 of the design guide, we need to ensure that
         * all fifos are flushed before continuing
         */
 
-       dwc2_writel(GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH |
-              GRSTCTL_RXFFLSH, hsotg->regs + GRSTCTL);
+       dwc2_writel(hsotg, GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH |
+              GRSTCTL_RXFFLSH, GRSTCTL);
 
        /* wait until the fifos are both flushed */
        timeout = 100;
        while (1) {
-               val = dwc2_readl(hsotg->regs + GRSTCTL);
+               val = dwc2_readl(hsotg, GRSTCTL);
 
                if ((val & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH)) == 0)
                        break;
@@ -451,7 +452,7 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
                                struct dwc2_hsotg_req *hs_req)
 {
        bool periodic = is_ep_periodic(hs_ep);
-       u32 gnptxsts = dwc2_readl(hsotg->regs + GNPTXSTS);
+       u32 gnptxsts = dwc2_readl(hsotg, GNPTXSTS);
        int buf_pos = hs_req->req.actual;
        int to_write = hs_ep->size_loaded;
        void *data;
@@ -466,7 +467,7 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
                return 0;
 
        if (periodic && !hsotg->dedicated_fifos) {
-               u32 epsize = dwc2_readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
+               u32 epsize = dwc2_readl(hsotg, DIEPTSIZ(hs_ep->index));
                int size_left;
                int size_done;
 
@@ -507,8 +508,8 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
                        return -ENOSPC;
                }
        } else if (hsotg->dedicated_fifos && hs_ep->index != 0) {
-               can_write = dwc2_readl(hsotg->regs +
-                               DTXFSTS(hs_ep->fifo_index));
+               can_write = dwc2_readl(hsotg,
+                                      DTXFSTS(hs_ep->fifo_index));
 
                can_write &= 0xffff;
                can_write *= 4;
@@ -598,7 +599,7 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
        to_write = DIV_ROUND_UP(to_write, 4);
        data = hs_req->req.buf + buf_pos;
 
-       iowrite32_rep(hsotg->regs + EPFIFO(hs_ep->index), data, to_write);
+       dwc2_writel_rep(hsotg, EPFIFO(hs_ep->index), data, to_write);
 
        return (to_write >= can_write) ? -ENOSPC : 0;
 }
@@ -652,7 +653,7 @@ static u32 dwc2_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
 {
        u32 dsts;
 
-       dsts = dwc2_readl(hsotg->regs + DSTS);
+       dsts = dwc2_readl(hsotg, DSTS);
        dsts &= DSTS_SOFFN_MASK;
        dsts >>= DSTS_SOFFN_SHIFT;
 
@@ -915,11 +916,11 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep)
        dma_reg = hs_ep->dir_in ? DIEPDMA(index) : DOEPDMA(index);
 
        /* write descriptor chain address to control register */
-       dwc2_writel(hs_ep->desc_list_dma, hsotg->regs + dma_reg);
+       dwc2_writel(hsotg, hs_ep->desc_list_dma, dma_reg);
 
-       ctrl = dwc2_readl(hsotg->regs + depctl);
+       ctrl = dwc2_readl(hsotg, depctl);
        ctrl |= DXEPCTL_EPENA | DXEPCTL_CNAK;
-       dwc2_writel(ctrl, hsotg->regs + depctl);
+       dwc2_writel(hsotg, ctrl, depctl);
 }
 
 /**
@@ -967,11 +968,11 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
        epsize_reg = dir_in ? DIEPTSIZ(index) : DOEPTSIZ(index);
 
        dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x, ep %d, dir %s\n",
-               __func__, dwc2_readl(hsotg->regs + epctrl_reg), index,
+               __func__, dwc2_readl(hsotg, epctrl_reg), index,
                hs_ep->dir_in ? "in" : "out");
 
        /* If endpoint is stalled, we will restart request later */
-       ctrl = dwc2_readl(hsotg->regs + epctrl_reg);
+       ctrl = dwc2_readl(hsotg, epctrl_reg);
 
        if (index && ctrl & DXEPCTL_STALL) {
                dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index);
@@ -1064,13 +1065,13 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
                                                     length);
 
                /* write descriptor chain address to control register */
-               dwc2_writel(hs_ep->desc_list_dma, hsotg->regs + dma_reg);
+               dwc2_writel(hsotg, hs_ep->desc_list_dma, dma_reg);
 
                dev_dbg(hsotg->dev, "%s: %08x pad => 0x%08x\n",
                        __func__, (u32)hs_ep->desc_list_dma, dma_reg);
        } else {
                /* write size / packets */
-               dwc2_writel(epsize, hsotg->regs + epsize_reg);
+               dwc2_writel(hsotg, epsize, epsize_reg);
 
                if (using_dma(hsotg) && !continuing && (length != 0)) {
                        /*
@@ -1078,7 +1079,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
                         * already synced by dwc2_hsotg_ep_queue().
                         */
 
-                       dwc2_writel(ureq->dma, hsotg->regs + dma_reg);
+                       dwc2_writel(hsotg, ureq->dma, dma_reg);
 
                        dev_dbg(hsotg->dev, "%s: %pad => 0x%08x\n",
                                __func__, &ureq->dma, dma_reg);
@@ -1104,7 +1105,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
                ctrl |= DXEPCTL_CNAK;   /* clear NAK set by core */
 
        dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
-       dwc2_writel(ctrl, hsotg->regs + epctrl_reg);
+       dwc2_writel(hsotg, ctrl, epctrl_reg);
 
        /*
         * set these, it seems that DMA support increments past the end
@@ -1127,13 +1128,13 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
         */
 
        /* check ep is enabled */
-       if (!(dwc2_readl(hsotg->regs + epctrl_reg) & DXEPCTL_EPENA))
+       if (!(dwc2_readl(hsotg, epctrl_reg) & DXEPCTL_EPENA))
                dev_dbg(hsotg->dev,
                        "ep%d: failed to become enabled (DXEPCTL=0x%08x)?\n",
-                        index, dwc2_readl(hsotg->regs + epctrl_reg));
+                        index, dwc2_readl(hsotg, epctrl_reg));
 
        dev_dbg(hsotg->dev, "%s: DXEPCTL=0x%08x\n",
-               __func__, dwc2_readl(hsotg->regs + epctrl_reg));
+               __func__, dwc2_readl(hsotg, epctrl_reg));
 
        /* enable ep interrupts */
        dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 1);
@@ -1466,7 +1467,7 @@ static struct dwc2_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg,
  */
 int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode)
 {
-       int dctl = dwc2_readl(hsotg->regs + DCTL);
+       int dctl = dwc2_readl(hsotg, DCTL);
 
        dctl &= ~DCTL_TSTCTL_MASK;
        switch (testmode) {
@@ -1480,7 +1481,7 @@ int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode)
        default:
                return -EINVAL;
        }
-       dwc2_writel(dctl, hsotg->regs + DCTL);
+       dwc2_writel(hsotg, dctl, DCTL);
        return 0;
 }
 
@@ -1634,9 +1635,9 @@ static void dwc2_gadget_start_next_request(struct dwc2_hsotg_ep *hs_ep)
        } else {
                dev_dbg(hsotg->dev, "%s: No more ISOC-OUT requests\n",
                        __func__);
-               mask = dwc2_readl(hsotg->regs + epmsk_reg);
+               mask = dwc2_readl(hsotg, epmsk_reg);
                mask |= DOEPMSK_OUTTKNEPDISMSK;
-               dwc2_writel(mask, hsotg->regs + epmsk_reg);
+               dwc2_writel(hsotg, mask, epmsk_reg);
        }
 }
 
@@ -1773,14 +1774,14 @@ static void dwc2_hsotg_stall_ep0(struct dwc2_hsotg *hsotg)
         * taken effect, so no need to clear later.
         */
 
-       ctrl = dwc2_readl(hsotg->regs + reg);
+       ctrl = dwc2_readl(hsotg, reg);
        ctrl |= DXEPCTL_STALL;
        ctrl |= DXEPCTL_CNAK;
-       dwc2_writel(ctrl, hsotg->regs + reg);
+       dwc2_writel(hsotg, ctrl, reg);
 
        dev_dbg(hsotg->dev,
                "written DXEPCTL=0x%08x to %08x (DXEPCTL=0x%08x)\n",
-               ctrl, reg, dwc2_readl(hsotg->regs + reg));
+               ctrl, reg, dwc2_readl(hsotg, reg));
 
         /*
          * complete won't be called, so we enqueue
@@ -1825,11 +1826,11 @@ static void dwc2_hsotg_process_control(struct dwc2_hsotg *hsotg,
                switch (ctrl->bRequest) {
                case USB_REQ_SET_ADDRESS:
                        hsotg->connected = 1;
-                       dcfg = dwc2_readl(hsotg->regs + DCFG);
+                       dcfg = dwc2_readl(hsotg, DCFG);
                        dcfg &= ~DCFG_DEVADDR_MASK;
                        dcfg |= (le16_to_cpu(ctrl->wValue) <<
                                 DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK;
-                       dwc2_writel(dcfg, hsotg->regs + DCFG);
+                       dwc2_writel(hsotg, dcfg, DCFG);
 
                        dev_info(hsotg->dev, "new address %d\n", ctrl->wValue);
 
@@ -1955,16 +1956,16 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
 
                dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0);
        } else {
-               dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
-                           DXEPTSIZ_XFERSIZE(0), hsotg->regs +
+               dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
+                           DXEPTSIZ_XFERSIZE(0),
                            epsiz_reg);
        }
 
-       ctrl = dwc2_readl(hsotg->regs + epctl_reg);
+       ctrl = dwc2_readl(hsotg, epctl_reg);
        ctrl |= DXEPCTL_CNAK;  /* clear NAK set by core */
        ctrl |= DXEPCTL_EPENA; /* ensure ep enabled */
        ctrl |= DXEPCTL_USBACTEP;
-       dwc2_writel(ctrl, hsotg->regs + epctl_reg);
+       dwc2_writel(hsotg, ctrl, epctl_reg);
 }
 
 /**
@@ -2124,13 +2125,12 @@ static void dwc2_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
 {
        struct dwc2_hsotg_ep *hs_ep = hsotg->eps_out[ep_idx];
        struct dwc2_hsotg_req *hs_req = hs_ep->req;
-       void __iomem *fifo = hsotg->regs + EPFIFO(ep_idx);
        int to_read;
        int max_req;
        int read_ptr;
 
        if (!hs_req) {
-               u32 epctl = dwc2_readl(hsotg->regs + DOEPCTL(ep_idx));
+               u32 epctl = dwc2_readl(hsotg, DOEPCTL(ep_idx));
                int ptr;
 
                dev_dbg(hsotg->dev,
@@ -2139,7 +2139,7 @@ static void dwc2_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
 
                /* dump the data from the FIFO, we've nothing we can do */
                for (ptr = 0; ptr < size; ptr += 4)
-                       (void)dwc2_readl(fifo);
+                       (void)dwc2_readl(hsotg, EPFIFO(ep_idx));
 
                return;
        }
@@ -2169,7 +2169,8 @@ static void dwc2_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
         * note, we might over-write the buffer end by 3 bytes depending on
         * alignment of the data.
         */
-       ioread32_rep(fifo, hs_req->req.buf + read_ptr, to_read);
+       dwc2_readl_rep(hsotg, EPFIFO(ep_idx),
+                      hs_req->req.buf + read_ptr, to_read);
 }
 
 /**
@@ -2198,12 +2199,12 @@ static void dwc2_hsotg_change_ep_iso_parity(struct dwc2_hsotg *hsotg,
 {
        u32 ctrl;
 
-       ctrl = dwc2_readl(hsotg->regs + epctl_reg);
+       ctrl = dwc2_readl(hsotg, epctl_reg);
        if (ctrl & DXEPCTL_EOFRNUM)
                ctrl |= DXEPCTL_SETEVENFR;
        else
                ctrl |= DXEPCTL_SETODDFR;
-       dwc2_writel(ctrl, hsotg->regs + epctl_reg);
+       dwc2_writel(hsotg, ctrl, epctl_reg);
 }
 
 /*
@@ -2247,7 +2248,7 @@ static unsigned int dwc2_gadget_get_xfersize_ddma(struct dwc2_hsotg_ep *hs_ep)
  */
 static void dwc2_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
 {
-       u32 epsize = dwc2_readl(hsotg->regs + DOEPTSIZ(epnum));
+       u32 epsize = dwc2_readl(hsotg, DOEPTSIZ(epnum));
        struct dwc2_hsotg_ep *hs_ep = hsotg->eps_out[epnum];
        struct dwc2_hsotg_req *hs_req = hs_ep->req;
        struct usb_request *req = &hs_req->req;
@@ -2343,7 +2344,7 @@ static void dwc2_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
  */
 static void dwc2_hsotg_handle_rx(struct dwc2_hsotg *hsotg)
 {
-       u32 grxstsr = dwc2_readl(hsotg->regs + GRXSTSP);
+       u32 grxstsr = dwc2_readl(hsotg, GRXSTSP);
        u32 epnum, status, size;
 
        WARN_ON(using_dma(hsotg));
@@ -2374,7 +2375,7 @@ static void dwc2_hsotg_handle_rx(struct dwc2_hsotg *hsotg)
                dev_dbg(hsotg->dev,
                        "SetupDone (Frame=0x%08x, DOPEPCTL=0x%08x)\n",
                        dwc2_hsotg_read_frameno(hsotg),
-                       dwc2_readl(hsotg->regs + DOEPCTL(0)));
+                       dwc2_readl(hsotg, DOEPCTL(0)));
                /*
                 * Call dwc2_hsotg_handle_outdone here if it was not called from
                 * GRXSTS_PKTSTS_OUTDONE. That is, if the core didn't
@@ -2392,7 +2393,7 @@ static void dwc2_hsotg_handle_rx(struct dwc2_hsotg *hsotg)
                dev_dbg(hsotg->dev,
                        "SetupRX (Frame=0x%08x, DOPEPCTL=0x%08x)\n",
                        dwc2_hsotg_read_frameno(hsotg),
-                       dwc2_readl(hsotg->regs + DOEPCTL(0)));
+                       dwc2_readl(hsotg, DOEPCTL(0)));
 
                WARN_ON(hsotg->ep0_state != DWC2_EP0_SETUP);
 
@@ -2446,7 +2447,6 @@ static void dwc2_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg,
                                        unsigned int mc, unsigned int dir_in)
 {
        struct dwc2_hsotg_ep *hs_ep;
-       void __iomem *regs = hsotg->regs;
        u32 reg;
 
        hs_ep = index_to_ep(hsotg, ep, dir_in);
@@ -2472,15 +2472,15 @@ static void dwc2_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg,
        }
 
        if (dir_in) {
-               reg = dwc2_readl(regs + DIEPCTL(ep));
+               reg = dwc2_readl(hsotg, DIEPCTL(ep));
                reg &= ~DXEPCTL_MPS_MASK;
                reg |= mps;
-               dwc2_writel(reg, regs + DIEPCTL(ep));
+               dwc2_writel(hsotg, reg, DIEPCTL(ep));
        } else {
-               reg = dwc2_readl(regs + DOEPCTL(ep));
+               reg = dwc2_readl(hsotg, DOEPCTL(ep));
                reg &= ~DXEPCTL_MPS_MASK;
                reg |= mps;
-               dwc2_writel(reg, regs + DOEPCTL(ep));
+               dwc2_writel(hsotg, reg, DOEPCTL(ep));
        }
 
        return;
@@ -2496,8 +2496,8 @@ bad_mps:
  */
 static void dwc2_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx)
 {
-       dwc2_writel(GRSTCTL_TXFNUM(idx) | GRSTCTL_TXFFLSH,
-                   hsotg->regs + GRSTCTL);
+       dwc2_writel(hsotg, GRSTCTL_TXFNUM(idx) | GRSTCTL_TXFFLSH,
+                   GRSTCTL);
 
        /* wait until the fifo is flushed */
        if (dwc2_hsotg_wait_bit_clear(hsotg, GRSTCTL, GRSTCTL_TXFFLSH, 100))
@@ -2550,7 +2550,7 @@ static void dwc2_hsotg_complete_in(struct dwc2_hsotg *hsotg,
                                   struct dwc2_hsotg_ep *hs_ep)
 {
        struct dwc2_hsotg_req *hs_req = hs_ep->req;
-       u32 epsize = dwc2_readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
+       u32 epsize = dwc2_readl(hsotg, DIEPTSIZ(hs_ep->index));
        int size_left, size_done;
 
        if (!hs_req) {
@@ -2654,12 +2654,12 @@ static u32 dwc2_gadget_read_ep_interrupts(struct dwc2_hsotg *hsotg,
        u32 mask;
        u32 diepempmsk;
 
-       mask = dwc2_readl(hsotg->regs + epmsk_reg);
-       diepempmsk = dwc2_readl(hsotg->regs + DIEPEMPMSK);
+       mask = dwc2_readl(hsotg, epmsk_reg);
+       diepempmsk = dwc2_readl(hsotg, DIEPEMPMSK);
        mask |= ((diepempmsk >> idx) & 0x1) ? DIEPMSK_TXFIFOEMPTY : 0;
        mask |= DXEPINT_SETUP_RCVD;
 
-       ints = dwc2_readl(hsotg->regs + epint_reg);
+       ints = dwc2_readl(hsotg, epint_reg);
        ints &= mask;
        return ints;
 }
@@ -2684,12 +2684,12 @@ static void dwc2_gadget_handle_ep_disabled(struct dwc2_hsotg_ep *hs_ep)
        unsigned char idx = hs_ep->index;
        int dir_in = hs_ep->dir_in;
        u32 epctl_reg = dir_in ? DIEPCTL(idx) : DOEPCTL(idx);
-       int dctl = dwc2_readl(hsotg->regs + DCTL);
+       int dctl = dwc2_readl(hsotg, DCTL);
 
        dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__);
 
        if (dir_in) {
-               int epctl = dwc2_readl(hsotg->regs + epctl_reg);
+               int epctl = dwc2_readl(hsotg, epctl_reg);
 
                dwc2_hsotg_txfifo_flush(hsotg, hs_ep->fifo_index);
 
@@ -2699,17 +2699,17 @@ static void dwc2_gadget_handle_ep_disabled(struct dwc2_hsotg_ep *hs_ep)
                }
 
                if ((epctl & DXEPCTL_STALL) && (epctl & DXEPCTL_EPTYPE_BULK)) {
-                       int dctl = dwc2_readl(hsotg->regs + DCTL);
+                       int dctl = dwc2_readl(hsotg, DCTL);
 
                        dctl |= DCTL_CGNPINNAK;
-                       dwc2_writel(dctl, hsotg->regs + DCTL);
+                       dwc2_writel(hsotg, dctl, DCTL);
                }
                return;
        }
 
        if (dctl & DCTL_GOUTNAKSTS) {
                dctl |= DCTL_CGOUTNAK;
-               dwc2_writel(dctl, hsotg->regs + DCTL);
+               dwc2_writel(hsotg, dctl, DCTL);
        }
 
        if (!hs_ep->isochronous)
@@ -2750,21 +2750,14 @@ static void dwc2_gadget_handle_out_token_ep_disabled(struct dwc2_hsotg_ep *ep)
        struct dwc2_hsotg *hsotg = ep->parent;
        int dir_in = ep->dir_in;
        u32 doepmsk;
-       u32 tmp;
 
        if (dir_in || !ep->isochronous)
                return;
 
-       /*
-        * Store frame in which irq was asserted here, as
-        * it can change while completing request below.
-        */
-       tmp = dwc2_hsotg_read_frameno(hsotg);
-
        if (using_desc_dma(hsotg)) {
                if (ep->target_frame == TARGET_FRAME_INITIAL) {
                        /* Start first ISO Out */
-                       ep->target_frame = tmp;
+                       ep->target_frame = hsotg->frame_number;
                        dwc2_gadget_start_isoc_ddma(ep);
                }
                return;
@@ -2772,26 +2765,24 @@ static void dwc2_gadget_handle_out_token_ep_disabled(struct dwc2_hsotg_ep *ep)
 
        if (ep->interval > 1 &&
            ep->target_frame == TARGET_FRAME_INITIAL) {
-               u32 dsts;
                u32 ctrl;
 
-               dsts = dwc2_readl(hsotg->regs + DSTS);
-               ep->target_frame = dwc2_hsotg_read_frameno(hsotg);
+               ep->target_frame = hsotg->frame_number;
                dwc2_gadget_incr_frame_num(ep);
 
-               ctrl = dwc2_readl(hsotg->regs + DOEPCTL(ep->index));
+               ctrl = dwc2_readl(hsotg, DOEPCTL(ep->index));
                if (ep->target_frame & 0x1)
                        ctrl |= DXEPCTL_SETODDFR;
                else
                        ctrl |= DXEPCTL_SETEVENFR;
 
-               dwc2_writel(ctrl, hsotg->regs + DOEPCTL(ep->index));
+               dwc2_writel(hsotg, ctrl, DOEPCTL(ep->index));
        }
 
        dwc2_gadget_start_next_request(ep);
-       doepmsk = dwc2_readl(hsotg->regs + DOEPMSK);
+       doepmsk = dwc2_readl(hsotg, DOEPMSK);
        doepmsk &= ~DOEPMSK_OUTTKNEPDISMSK;
-       dwc2_writel(doepmsk, hsotg->regs + DOEPMSK);
+       dwc2_writel(hsotg, doepmsk, DOEPMSK);
 }
 
 /**
@@ -2812,31 +2803,29 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep)
 {
        struct dwc2_hsotg *hsotg = hs_ep->parent;
        int dir_in = hs_ep->dir_in;
-       u32 tmp;
 
        if (!dir_in || !hs_ep->isochronous)
                return;
 
        if (hs_ep->target_frame == TARGET_FRAME_INITIAL) {
 
-               tmp = dwc2_hsotg_read_frameno(hsotg);
                if (using_desc_dma(hsotg)) {
-                       hs_ep->target_frame = tmp;
+                       hs_ep->target_frame = hsotg->frame_number;
                        dwc2_gadget_incr_frame_num(hs_ep);
                        dwc2_gadget_start_isoc_ddma(hs_ep);
                        return;
                }
 
-               hs_ep->target_frame = tmp;
+               hs_ep->target_frame = hsotg->frame_number;
                if (hs_ep->interval > 1) {
-                       u32 ctrl = dwc2_readl(hsotg->regs +
+                       u32 ctrl = dwc2_readl(hsotg,
                                              DIEPCTL(hs_ep->index));
                        if (hs_ep->target_frame & 0x1)
                                ctrl |= DXEPCTL_SETODDFR;
                        else
                                ctrl |= DXEPCTL_SETEVENFR;
 
-                       dwc2_writel(ctrl, hsotg->regs + DIEPCTL(hs_ep->index));
+                       dwc2_writel(hsotg, ctrl, DIEPCTL(hs_ep->index));
                }
 
                dwc2_hsotg_complete_request(hsotg, hs_ep,
@@ -2866,10 +2855,10 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
        u32 ctrl;
 
        ints = dwc2_gadget_read_ep_interrupts(hsotg, idx, dir_in);
-       ctrl = dwc2_readl(hsotg->regs + epctl_reg);
+       ctrl = dwc2_readl(hsotg, epctl_reg);
 
        /* Clear endpoint interrupts */
-       dwc2_writel(ints, hsotg->regs + epint_reg);
+       dwc2_writel(hsotg, ints, epint_reg);
 
        if (!hs_ep) {
                dev_err(hsotg->dev, "%s:Interrupt for unconfigured ep%d(%s)\n",
@@ -2897,8 +2886,8 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
        if (ints & DXEPINT_XFERCOMPL) {
                dev_dbg(hsotg->dev,
                        "%s: XferCompl: DxEPCTL=0x%08x, DXEPTSIZ=%08x\n",
-                       __func__, dwc2_readl(hsotg->regs + epctl_reg),
-                       dwc2_readl(hsotg->regs + epsiz_reg));
+                       __func__, dwc2_readl(hsotg, epctl_reg),
+                       dwc2_readl(hsotg, epsiz_reg));
 
                /* In DDMA handle isochronous requests separately */
                if (using_desc_dma(hsotg) && hs_ep->isochronous) {
@@ -3016,7 +3005,7 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
  */
 static void dwc2_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg)
 {
-       u32 dsts = dwc2_readl(hsotg->regs + DSTS);
+       u32 dsts = dwc2_readl(hsotg, DSTS);
        int ep0_mps = 0, ep_mps = 8;
 
        /*
@@ -3087,8 +3076,8 @@ static void dwc2_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg)
        dwc2_hsotg_enqueue_setup(hsotg);
 
        dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
-               dwc2_readl(hsotg->regs + DIEPCTL0),
-               dwc2_readl(hsotg->regs + DOEPCTL0));
+               dwc2_readl(hsotg, DIEPCTL0),
+               dwc2_readl(hsotg, DOEPCTL0));
 }
 
 /**
@@ -3115,7 +3104,7 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg,
 
        if (!hsotg->dedicated_fifos)
                return;
-       size = (dwc2_readl(hsotg->regs + DTXFSTS(ep->fifo_index)) & 0xffff) * 4;
+       size = (dwc2_readl(hsotg, DTXFSTS(ep->fifo_index)) & 0xffff) * 4;
        if (size < ep->fifo_size)
                dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
 }
@@ -3216,7 +3205,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
         */
 
        /* keep other bits untouched (so e.g. forced modes are not lost) */
-       usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
+       usbcfg = dwc2_readl(hsotg, GUSBCFG);
        usbcfg &= ~(GUSBCFG_TOUTCAL_MASK | GUSBCFG_PHYIF16 | GUSBCFG_SRPCAP |
                GUSBCFG_HNPCAP | GUSBCFG_USBTRDTIM_MASK);
 
@@ -3231,12 +3220,12 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
                usbcfg |= hsotg->phyif | GUSBCFG_TOUTCAL(7) |
                        (val << GUSBCFG_USBTRDTIM_SHIFT);
        }
-       dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
+       dwc2_writel(hsotg, usbcfg, GUSBCFG);
 
        dwc2_hsotg_init_fifo(hsotg);
 
        if (!is_usb_reset)
-               dwc2_set_bit(hsotg->regs + DCTL, DCTL_SFTDISCON);
+               dwc2_set_bit(hsotg, DCTL, DCTL_SFTDISCON);
 
        dcfg |= DCFG_EPMISCNT(1);
 
@@ -3257,13 +3246,13 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
        if (hsotg->params.ipg_isoc_en)
                dcfg |= DCFG_IPG_ISOC_SUPPORDED;
 
-       dwc2_writel(dcfg,  hsotg->regs + DCFG);
+       dwc2_writel(hsotg, dcfg,  DCFG);
 
        /* Clear any pending OTG interrupts */
-       dwc2_writel(0xffffffff, hsotg->regs + GOTGINT);
+       dwc2_writel(hsotg, 0xffffffff, GOTGINT);
 
        /* Clear any pending interrupts */
-       dwc2_writel(0xffffffff, hsotg->regs + GINTSTS);
+       dwc2_writel(hsotg, 0xffffffff, GINTSTS);
        intmsk = GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT |
                GINTSTS_GOUTNAKEFF | GINTSTS_GINNAKEFF |
                GINTSTS_USBRST | GINTSTS_RESETDET |
@@ -3277,22 +3266,22 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
        if (!hsotg->params.external_id_pin_ctl)
                intmsk |= GINTSTS_CONIDSTSCHNG;
 
-       dwc2_writel(intmsk, hsotg->regs + GINTMSK);
+       dwc2_writel(hsotg, intmsk, GINTMSK);
 
        if (using_dma(hsotg)) {
-               dwc2_writel(GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN |
+               dwc2_writel(hsotg, GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN |
                            hsotg->params.ahbcfg,
-                           hsotg->regs + GAHBCFG);
+                           GAHBCFG);
 
                /* Set DDMA mode support in the core if needed */
                if (using_desc_dma(hsotg))
-                       dwc2_set_bit(hsotg->regs + DCFG, DCFG_DESCDMA_EN);
+                       dwc2_set_bit(hsotg, DCFG, DCFG_DESCDMA_EN);
 
        } else {
-               dwc2_writel(((hsotg->dedicated_fifos) ?
+               dwc2_writel(hsotg, ((hsotg->dedicated_fifos) ?
                                                (GAHBCFG_NP_TXF_EMP_LVL |
                                                 GAHBCFG_P_TXF_EMP_LVL) : 0) |
-                           GAHBCFG_GLBL_INTR_EN, hsotg->regs + GAHBCFG);
+                           GAHBCFG_GLBL_INTR_EN, GAHBCFG);
        }
 
        /*
@@ -3301,33 +3290,33 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
         * interrupts.
         */
 
-       dwc2_writel(((hsotg->dedicated_fifos && !using_dma(hsotg)) ?
+       dwc2_writel(hsotg, ((hsotg->dedicated_fifos && !using_dma(hsotg)) ?
                DIEPMSK_TXFIFOEMPTY | DIEPMSK_INTKNTXFEMPMSK : 0) |
                DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK |
                DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK,
-               hsotg->regs + DIEPMSK);
+               DIEPMSK);
 
        /*
         * don't need XferCompl, we get that from RXFIFO in slave mode. In
         * DMA mode we may need this and StsPhseRcvd.
         */
-       dwc2_writel((using_dma(hsotg) ? (DIEPMSK_XFERCOMPLMSK |
+       dwc2_writel(hsotg, (using_dma(hsotg) ? (DIEPMSK_XFERCOMPLMSK |
                DOEPMSK_STSPHSERCVDMSK) : 0) |
                DOEPMSK_EPDISBLDMSK | DOEPMSK_AHBERRMSK |
                DOEPMSK_SETUPMSK,
-               hsotg->regs + DOEPMSK);
+               DOEPMSK);
 
        /* Enable BNA interrupt for DDMA */
        if (using_desc_dma(hsotg)) {
-               dwc2_set_bit(hsotg->regs + DOEPMSK, DOEPMSK_BNAMSK);
-               dwc2_set_bit(hsotg->regs + DIEPMSK, DIEPMSK_BNAININTRMSK);
+               dwc2_set_bit(hsotg, DOEPMSK, DOEPMSK_BNAMSK);
+               dwc2_set_bit(hsotg, DIEPMSK, DIEPMSK_BNAININTRMSK);
        }
 
-       dwc2_writel(0, hsotg->regs + DAINTMSK);
+       dwc2_writel(hsotg, 0, DAINTMSK);
 
        dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
-               dwc2_readl(hsotg->regs + DIEPCTL0),
-               dwc2_readl(hsotg->regs + DOEPCTL0));
+               dwc2_readl(hsotg, DIEPCTL0),
+               dwc2_readl(hsotg, DOEPCTL0));
 
        /* enable in and out endpoint interrupts */
        dwc2_hsotg_en_gsint(hsotg, GINTSTS_OEPINT | GINTSTS_IEPINT);
@@ -3345,12 +3334,12 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
        dwc2_hsotg_ctrl_epint(hsotg, 0, 1, 1);
 
        if (!is_usb_reset) {
-               dwc2_set_bit(hsotg->regs + DCTL, DCTL_PWRONPRGDONE);
+               dwc2_set_bit(hsotg, DCTL, DCTL_PWRONPRGDONE);
                udelay(10);  /* see openiboot */
-               dwc2_clear_bit(hsotg->regs + DCTL, DCTL_PWRONPRGDONE);
+               dwc2_clear_bit(hsotg, DCTL, DCTL_PWRONPRGDONE);
        }
 
-       dev_dbg(hsotg->dev, "DCTL=0x%08x\n", dwc2_readl(hsotg->regs + DCTL));
+       dev_dbg(hsotg->dev, "DCTL=0x%08x\n", dwc2_readl(hsotg, DCTL));
 
        /*
         * DxEPCTL_USBActEp says RO in manual, but seems to be set by
@@ -3358,23 +3347,23 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
         */
 
        /* set to read 1 8byte packet */
-       dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
-              DXEPTSIZ_XFERSIZE(8), hsotg->regs + DOEPTSIZ0);
+       dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
+              DXEPTSIZ_XFERSIZE(8), DOEPTSIZ0);
 
-       dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
+       dwc2_writel(hsotg, dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
               DXEPCTL_CNAK | DXEPCTL_EPENA |
               DXEPCTL_USBACTEP,
-              hsotg->regs + DOEPCTL0);
+              DOEPCTL0);
 
        /* enable, but don't activate EP0in */
-       dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
-              DXEPCTL_USBACTEP, hsotg->regs + DIEPCTL0);
+       dwc2_writel(hsotg, dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
+              DXEPCTL_USBACTEP, DIEPCTL0);
 
        /* clear global NAKs */
        val = DCTL_CGOUTNAK | DCTL_CGNPINNAK;
        if (!is_usb_reset)
                val |= DCTL_SFTDISCON;
-       dwc2_set_bit(hsotg->regs + DCTL, val);
+       dwc2_set_bit(hsotg, DCTL, val);
 
        /* configure the core to support LPM */
        dwc2_gadget_init_lpm(hsotg);
@@ -3387,20 +3376,20 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
        dwc2_hsotg_enqueue_setup(hsotg);
 
        dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
-               dwc2_readl(hsotg->regs + DIEPCTL0),
-               dwc2_readl(hsotg->regs + DOEPCTL0));
+               dwc2_readl(hsotg, DIEPCTL0),
+               dwc2_readl(hsotg, DOEPCTL0));
 }
 
 static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
 {
        /* set the soft-disconnect bit */
-       dwc2_set_bit(hsotg->regs + DCTL, DCTL_SFTDISCON);
+       dwc2_set_bit(hsotg, DCTL, DCTL_SFTDISCON);
 }
 
 void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg)
 {
        /* remove the soft-disconnect and let's go */
-       dwc2_clear_bit(hsotg->regs + DCTL, DCTL_SFTDISCON);
+       dwc2_clear_bit(hsotg, DCTL, DCTL_SFTDISCON);
 }
 
 /**
@@ -3425,7 +3414,7 @@ static void dwc2_gadget_handle_incomplete_isoc_in(struct dwc2_hsotg *hsotg)
 
        dev_dbg(hsotg->dev, "Incomplete isoc in interrupt received:\n");
 
-       daintmsk = dwc2_readl(hsotg->regs + DAINTMSK);
+       daintmsk = dwc2_readl(hsotg, DAINTMSK);
 
        for (idx = 1; idx < hsotg->num_of_eps; idx++) {
                hs_ep = hsotg->eps_in[idx];
@@ -3433,17 +3422,17 @@ static void dwc2_gadget_handle_incomplete_isoc_in(struct dwc2_hsotg *hsotg)
                if ((BIT(idx) & ~daintmsk) || !hs_ep->isochronous)
                        continue;
 
-               epctrl = dwc2_readl(hsotg->regs + DIEPCTL(idx));
+               epctrl = dwc2_readl(hsotg, DIEPCTL(idx));
                if ((epctrl & DXEPCTL_EPENA) &&
                    dwc2_gadget_target_frame_elapsed(hs_ep)) {
                        epctrl |= DXEPCTL_SNAK;
                        epctrl |= DXEPCTL_EPDIS;
-                       dwc2_writel(epctrl, hsotg->regs + DIEPCTL(idx));
+                       dwc2_writel(hsotg, epctrl, DIEPCTL(idx));
                }
        }
 
        /* Clear interrupt */
-       dwc2_writel(GINTSTS_INCOMPL_SOIN, hsotg->regs + GINTSTS);
+       dwc2_writel(hsotg, GINTSTS_INCOMPL_SOIN, GINTSTS);
 }
 
 /**
@@ -3470,7 +3459,7 @@ static void dwc2_gadget_handle_incomplete_isoc_out(struct dwc2_hsotg *hsotg)
 
        dev_dbg(hsotg->dev, "%s: GINTSTS_INCOMPL_SOOUT\n", __func__);
 
-       daintmsk = dwc2_readl(hsotg->regs + DAINTMSK);
+       daintmsk = dwc2_readl(hsotg, DAINTMSK);
        daintmsk >>= DAINT_OUTEP_SHIFT;
 
        for (idx = 1; idx < hsotg->num_of_eps; idx++) {
@@ -3479,24 +3468,24 @@ static void dwc2_gadget_handle_incomplete_isoc_out(struct dwc2_hsotg *hsotg)
                if ((BIT(idx) & ~daintmsk) || !hs_ep->isochronous)
                        continue;
 
-               epctrl = dwc2_readl(hsotg->regs + DOEPCTL(idx));
+               epctrl = dwc2_readl(hsotg, DOEPCTL(idx));
                if ((epctrl & DXEPCTL_EPENA) &&
                    dwc2_gadget_target_frame_elapsed(hs_ep)) {
                        /* Unmask GOUTNAKEFF interrupt */
-                       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+                       gintmsk = dwc2_readl(hsotg, GINTMSK);
                        gintmsk |= GINTSTS_GOUTNAKEFF;
-                       dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
+                       dwc2_writel(hsotg, gintmsk, GINTMSK);
 
-                       gintsts = dwc2_readl(hsotg->regs + GINTSTS);
+                       gintsts = dwc2_readl(hsotg, GINTSTS);
                        if (!(gintsts & GINTSTS_GOUTNAKEFF)) {
-                               dwc2_set_bit(hsotg->regs + DCTL, DCTL_SGOUTNAK);
+                               dwc2_set_bit(hsotg, DCTL, DCTL_SGOUTNAK);
                                break;
                        }
                }
        }
 
        /* Clear interrupt */
-       dwc2_writel(GINTSTS_INCOMPL_SOOUT, hsotg->regs + GINTSTS);
+       dwc2_writel(hsotg, GINTSTS_INCOMPL_SOOUT, GINTSTS);
 }
 
 /**
@@ -3516,8 +3505,8 @@ static irqreturn_t dwc2_hsotg_irq(int irq, void *pw)
 
        spin_lock(&hsotg->lock);
 irq_retry:
-       gintsts = dwc2_readl(hsotg->regs + GINTSTS);
-       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+       gintsts = dwc2_readl(hsotg, GINTSTS);
+       gintmsk = dwc2_readl(hsotg, GINTMSK);
 
        dev_dbg(hsotg->dev, "%s: %08x %08x (%08x) retry %d\n",
                __func__, gintsts, gintsts & gintmsk, gintmsk, retry_count);
@@ -3527,7 +3516,7 @@ irq_retry:
        if (gintsts & GINTSTS_RESETDET) {
                dev_dbg(hsotg->dev, "%s: USBRstDet\n", __func__);
 
-               dwc2_writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS);
+               dwc2_writel(hsotg, GINTSTS_RESETDET, GINTSTS);
 
                /* This event must be used only if controller is suspended */
                if (hsotg->lx_state == DWC2_L2) {
@@ -3537,34 +3526,34 @@ irq_retry:
        }
 
        if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
-               u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
+               u32 usb_status = dwc2_readl(hsotg, GOTGCTL);
                u32 connected = hsotg->connected;
 
                dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
                dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
-                       dwc2_readl(hsotg->regs + GNPTXSTS));
+                       dwc2_readl(hsotg, GNPTXSTS));
 
-               dwc2_writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
+               dwc2_writel(hsotg, GINTSTS_USBRST, GINTSTS);
 
                /* Report disconnection if it is not already done. */
                dwc2_hsotg_disconnect(hsotg);
 
                /* Reset device address to zero */
-               dwc2_clear_bit(hsotg->regs + DCFG, DCFG_DEVADDR_MASK);
+               dwc2_clear_bit(hsotg, DCFG, DCFG_DEVADDR_MASK);
 
                if (usb_status & GOTGCTL_BSESVLD && connected)
                        dwc2_hsotg_core_init_disconnected(hsotg, true);
        }
 
        if (gintsts & GINTSTS_ENUMDONE) {
-               dwc2_writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
+               dwc2_writel(hsotg, GINTSTS_ENUMDONE, GINTSTS);
 
                dwc2_hsotg_irq_enumdone(hsotg);
        }
 
        if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) {
-               u32 daint = dwc2_readl(hsotg->regs + DAINT);
-               u32 daintmsk = dwc2_readl(hsotg->regs + DAINTMSK);
+               u32 daint = dwc2_readl(hsotg, DAINT);
+               u32 daintmsk = dwc2_readl(hsotg, DAINTMSK);
                u32 daint_out, daint_in;
                int ep;
 
@@ -3623,7 +3612,7 @@ irq_retry:
 
        if (gintsts & GINTSTS_ERLYSUSP) {
                dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n");
-               dwc2_writel(GINTSTS_ERLYSUSP, hsotg->regs + GINTSTS);
+               dwc2_writel(hsotg, GINTSTS_ERLYSUSP, GINTSTS);
        }
 
        /*
@@ -3639,12 +3628,12 @@ irq_retry:
                u32 daintmsk;
                struct dwc2_hsotg_ep *hs_ep;
 
-               daintmsk = dwc2_readl(hsotg->regs + DAINTMSK);
+               daintmsk = dwc2_readl(hsotg, DAINTMSK);
                daintmsk >>= DAINT_OUTEP_SHIFT;
                /* Mask this interrupt */
-               gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+               gintmsk = dwc2_readl(hsotg, GINTMSK);
                gintmsk &= ~GINTSTS_GOUTNAKEFF;
-               dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
+               dwc2_writel(hsotg, gintmsk, GINTMSK);
 
                dev_dbg(hsotg->dev, "GOUTNakEff triggered\n");
                for (idx = 1; idx < hsotg->num_of_eps; idx++) {
@@ -3653,12 +3642,12 @@ irq_retry:
                        if ((BIT(idx) & ~daintmsk) || !hs_ep->isochronous)
                                continue;
 
-                       epctrl = dwc2_readl(hsotg->regs + DOEPCTL(idx));
+                       epctrl = dwc2_readl(hsotg, DOEPCTL(idx));
 
                        if (epctrl & DXEPCTL_EPENA) {
                                epctrl |= DXEPCTL_SNAK;
                                epctrl |= DXEPCTL_EPDIS;
-                               dwc2_writel(epctrl, hsotg->regs + DOEPCTL(idx));
+                               dwc2_writel(hsotg, epctrl, DOEPCTL(idx));
                        }
                }
 
@@ -3668,7 +3657,7 @@ irq_retry:
        if (gintsts & GINTSTS_GINNAKEFF) {
                dev_info(hsotg->dev, "GINNakEff triggered\n");
 
-               dwc2_set_bit(hsotg->regs + DCTL, DCTL_CGNPINNAK);
+               dwc2_set_bit(hsotg, DCTL, DCTL_CGNPINNAK);
 
                dwc2_hsotg_dump(hsotg);
        }
@@ -3708,7 +3697,7 @@ static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
 
        if (hs_ep->dir_in) {
                if (hsotg->dedicated_fifos || hs_ep->periodic) {
-                       dwc2_set_bit(hsotg->regs + epctrl_reg, DXEPCTL_SNAK);
+                       dwc2_set_bit(hsotg, epctrl_reg, DXEPCTL_SNAK);
                        /* Wait for Nak effect */
                        if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg,
                                                    DXEPINT_INEPNAKEFF, 100))
@@ -3716,7 +3705,7 @@ static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
                                         "%s: timeout DIEPINT.NAKEFF\n",
                                         __func__);
                } else {
-                       dwc2_set_bit(hsotg->regs + DCTL, DCTL_SGNPINNAK);
+                       dwc2_set_bit(hsotg, DCTL, DCTL_SGNPINNAK);
                        /* Wait for Nak effect */
                        if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
                                                    GINTSTS_GINNAKEFF, 100))
@@ -3725,8 +3714,8 @@ static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
                                         __func__);
                }
        } else {
-               if (!(dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_GOUTNAKEFF))
-                       dwc2_set_bit(hsotg->regs + DCTL, DCTL_SGOUTNAK);
+               if (!(dwc2_readl(hsotg, GINTSTS) & GINTSTS_GOUTNAKEFF))
+                       dwc2_set_bit(hsotg, DCTL, DCTL_SGOUTNAK);
 
                /* Wait for global nak to take effect */
                if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
@@ -3736,7 +3725,7 @@ static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
        }
 
        /* Disable ep */
-       dwc2_set_bit(hsotg->regs + epctrl_reg, DXEPCTL_EPDIS | DXEPCTL_SNAK);
+       dwc2_set_bit(hsotg, epctrl_reg, DXEPCTL_EPDIS | DXEPCTL_SNAK);
 
        /* Wait for ep to be disabled */
        if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg, DXEPINT_EPDISBLD, 100))
@@ -3744,7 +3733,7 @@ static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
                         "%s: timeout DOEPCTL.EPDisable\n", __func__);
 
        /* Clear EPDISBLD interrupt */
-       dwc2_set_bit(hsotg->regs + epint_reg, DXEPINT_EPDISBLD);
+       dwc2_set_bit(hsotg, epint_reg, DXEPINT_EPDISBLD);
 
        if (hs_ep->dir_in) {
                unsigned short fifo_index;
@@ -3759,11 +3748,11 @@ static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
 
                /* Clear Global In NP NAK in Shared FIFO for non periodic ep */
                if (!hsotg->dedicated_fifos && !hs_ep->periodic)
-                       dwc2_set_bit(hsotg->regs + DCTL, DCTL_CGNPINNAK);
+                       dwc2_set_bit(hsotg, DCTL, DCTL_CGNPINNAK);
 
        } else {
                /* Remove global NAKs */
-               dwc2_set_bit(hsotg->regs + DCTL, DCTL_CGOUTNAK);
+               dwc2_set_bit(hsotg, DCTL, DCTL_CGOUTNAK);
        }
 }
 
@@ -3831,7 +3820,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
        /* note, we handle this here instead of dwc2_hsotg_set_ep_maxpacket */
 
        epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
-       epctrl = dwc2_readl(hsotg->regs + epctrl_reg);
+       epctrl = dwc2_readl(hsotg, epctrl_reg);
 
        dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n",
                __func__, epctrl, epctrl_reg);
@@ -3879,13 +3868,13 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
                hs_ep->compl_desc = 0;
                if (dir_in) {
                        hs_ep->periodic = 1;
-                       mask = dwc2_readl(hsotg->regs + DIEPMSK);
+                       mask = dwc2_readl(hsotg, DIEPMSK);
                        mask |= DIEPMSK_NAKMSK;
-                       dwc2_writel(mask, hsotg->regs + DIEPMSK);
+                       dwc2_writel(hsotg, mask, DIEPMSK);
                } else {
-                       mask = dwc2_readl(hsotg->regs + DOEPMSK);
+                       mask = dwc2_readl(hsotg, DOEPMSK);
                        mask |= DOEPMSK_OUTTKNEPDISMSK;
-                       dwc2_writel(mask, hsotg->regs + DOEPMSK);
+                       dwc2_writel(hsotg, mask, DOEPMSK);
                }
                break;
 
@@ -3920,7 +3909,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
                for (i = 1; i < hsotg->num_of_eps; ++i) {
                        if (hsotg->fifo_map & (1 << i))
                                continue;
-                       val = dwc2_readl(hsotg->regs + DPTXFSIZN(i));
+                       val = dwc2_readl(hsotg, DPTXFSIZN(i));
                        val = (val >> FIFOSIZE_DEPTH_SHIFT) * 4;
                        if (val < size)
                                continue;
@@ -3958,7 +3947,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
                 * to 4.00a (including both). Also for FS_IOT_1.00a
                 * and HS_IOT_1.00a.
                 */
-               u32 gsnpsid = dwc2_readl(hsotg->regs + GSNPSID);
+               u32 gsnpsid = dwc2_readl(hsotg, GSNPSID);
 
                if ((gsnpsid >= DWC2_CORE_REV_2_72a &&
                     gsnpsid <= DWC2_CORE_REV_4_00a) ||
@@ -3970,9 +3959,9 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
        dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n",
                __func__, epctrl);
 
-       dwc2_writel(epctrl, hsotg->regs + epctrl_reg);
+       dwc2_writel(hsotg, epctrl, epctrl_reg);
        dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x\n",
-               __func__, dwc2_readl(hsotg->regs + epctrl_reg));
+               __func__, dwc2_readl(hsotg, epctrl_reg));
 
        /* enable the endpoint interrupt */
        dwc2_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
@@ -4021,7 +4010,7 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
 
        spin_lock_irqsave(&hsotg->lock, flags);
 
-       ctrl = dwc2_readl(hsotg->regs + epctrl_reg);
+       ctrl = dwc2_readl(hsotg, epctrl_reg);
 
        if (ctrl & DXEPCTL_EPENA)
                dwc2_hsotg_ep_stop_xfr(hsotg, hs_ep);
@@ -4031,7 +4020,7 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
        ctrl |= DXEPCTL_SNAK;
 
        dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
-       dwc2_writel(ctrl, hsotg->regs + epctrl_reg);
+       dwc2_writel(hsotg, ctrl, epctrl_reg);
 
        /* disable endpoint interrupts */
        dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0);
@@ -4138,7 +4127,7 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now)
 
        if (hs_ep->dir_in) {
                epreg = DIEPCTL(index);
-               epctl = dwc2_readl(hs->regs + epreg);
+               epctl = dwc2_readl(hs, epreg);
 
                if (value) {
                        epctl |= DXEPCTL_STALL | DXEPCTL_SNAK;
@@ -4151,10 +4140,10 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now)
                            xfertype == DXEPCTL_EPTYPE_INTERRUPT)
                                epctl |= DXEPCTL_SETD0PID;
                }
-               dwc2_writel(epctl, hs->regs + epreg);
+               dwc2_writel(hs, epctl, epreg);
        } else {
                epreg = DOEPCTL(index);
-               epctl = dwc2_readl(hs->regs + epreg);
+               epctl = dwc2_readl(hs, epreg);
 
                if (value) {
                        epctl |= DXEPCTL_STALL;
@@ -4165,7 +4154,7 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now)
                            xfertype == DXEPCTL_EPTYPE_INTERRUPT)
                                epctl |= DXEPCTL_SETD0PID;
                }
-               dwc2_writel(epctl, hs->regs + epreg);
+               dwc2_writel(hs, epctl, epreg);
        }
 
        hs_ep->halted = value;
@@ -4213,29 +4202,29 @@ static void dwc2_hsotg_init(struct dwc2_hsotg *hsotg)
        u32 usbcfg;
        /* unmask subset of endpoint interrupts */
 
-       dwc2_writel(DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK |
+       dwc2_writel(hsotg, DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK |
                    DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK,
-                   hsotg->regs + DIEPMSK);
+                   DIEPMSK);
 
-       dwc2_writel(DOEPMSK_SETUPMSK | DOEPMSK_AHBERRMSK |
+       dwc2_writel(hsotg, DOEPMSK_SETUPMSK | DOEPMSK_AHBERRMSK |
                    DOEPMSK_EPDISBLDMSK | DOEPMSK_XFERCOMPLMSK,
-                   hsotg->regs + DOEPMSK);
+                   DOEPMSK);
 
-       dwc2_writel(0, hsotg->regs + DAINTMSK);
+       dwc2_writel(hsotg, 0, DAINTMSK);
 
        /* Be in disconnected state until gadget is registered */
-       dwc2_set_bit(hsotg->regs + DCTL, DCTL_SFTDISCON);
+       dwc2_set_bit(hsotg, DCTL, DCTL_SFTDISCON);
 
        /* setup fifos */
 
        dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
-               dwc2_readl(hsotg->regs + GRXFSIZ),
-               dwc2_readl(hsotg->regs + GNPTXFSIZ));
+               dwc2_readl(hsotg, GRXFSIZ),
+               dwc2_readl(hsotg, GNPTXFSIZ));
 
        dwc2_hsotg_init_fifo(hsotg);
 
        /* keep other bits untouched (so e.g. forced modes are not lost) */
-       usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
+       usbcfg = dwc2_readl(hsotg, GUSBCFG);
        usbcfg &= ~(GUSBCFG_TOUTCAL_MASK | GUSBCFG_PHYIF16 | GUSBCFG_SRPCAP |
                GUSBCFG_HNPCAP | GUSBCFG_USBTRDTIM_MASK);
 
@@ -4243,10 +4232,10 @@ static void dwc2_hsotg_init(struct dwc2_hsotg *hsotg)
        trdtim = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5;
        usbcfg |= hsotg->phyif | GUSBCFG_TOUTCAL(7) |
                (trdtim << GUSBCFG_USBTRDTIM_SHIFT);
-       dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
+       dwc2_writel(hsotg, usbcfg, GUSBCFG);
 
        if (using_dma(hsotg))
-               dwc2_set_bit(hsotg->regs + GAHBCFG, GAHBCFG_DMA_EN);
+               dwc2_set_bit(hsotg, GAHBCFG, GAHBCFG_DMA_EN);
 }
 
 /**
@@ -4536,9 +4525,9 @@ static void dwc2_hsotg_initep(struct dwc2_hsotg *hsotg,
                u32 next = DXEPCTL_NEXTEP((epnum + 1) % 15);
 
                if (dir_in)