Merge branch 'master' of git://git.denx.de/u-boot-atmel
authorTom Rini <trini@konsulko.com>
Mon, 15 Aug 2016 21:31:23 +0000 (17:31 -0400)
committerTom Rini <trini@konsulko.com>
Mon, 15 Aug 2016 21:31:23 +0000 (17:31 -0400)
89 files changed:
arch/arm/dts/tegra186-p2771-0000-a02.dts
arch/arm/dts/tegra186-p2771-0000-b00.dts
arch/arm/dts/tegra186-p2771-0000.dtsi
arch/arm/include/asm/arch-tegra/bpmp_abi.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra/tegra_mmc.h
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/board186.c
arch/arm/mach-tegra/board2.c
arch/arm/mach-tegra/cpu.h
arch/arm/mach-tegra/dt-setup.c [new file with mode: 0644]
arch/m68k/include/asm/fec.h
arch/mips/mach-au1x00/au1x00_eth.c
arch/powerpc/cpu/mpc8260/ether_fcc.c
arch/powerpc/cpu/mpc85xx/ether_fcc.c
arch/powerpc/cpu/mpc8xx/fec.c
arch/powerpc/cpu/ppc4xx/miiphy.c
board/gdsys/405ep/io.c
board/gdsys/405ep/iocon.c
board/gdsys/405ex/io64.c
board/gdsys/mpc8308/hrcon.c
board/gdsys/mpc8308/strider.c
board/nvidia/p2771-0000/p2771-0000.c
board/nvidia/venice2/as3722_init.c
board/nvidia/venice2/as3722_init.h
common/miiphyutil.c
configs/openrisc-generic_defconfig
configs/p2771-0000-a02_defconfig
configs/p2771-0000-b00_defconfig
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/tegra/Kconfig [new file with mode: 0644]
drivers/clk/tegra/Makefile [new file with mode: 0644]
drivers/clk/tegra/tegra186-clk.c [new file with mode: 0644]
drivers/i2c/Kconfig
drivers/i2c/Makefile
drivers/i2c/tegra186_bpmp_i2c.c [new file with mode: 0644]
drivers/i2c/tegra_i2c.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/tegra186_bpmp.c [new file with mode: 0644]
drivers/mmc/tegra_mmc.c
drivers/net/4xx_enet.c
drivers/net/Kconfig
drivers/net/armada100_fec.c
drivers/net/at91_emac.c
drivers/net/bcm-sf2-eth-gmac.c
drivers/net/bcm-sf2-eth.c
drivers/net/bcm-sf2-eth.h
drivers/net/bfin_mac.c
drivers/net/davinci_emac.c
drivers/net/e1000.c
drivers/net/e1000_spi.c
drivers/net/eepro100.c
drivers/net/enc28j60.c
drivers/net/ep93xx_eth.c
drivers/net/ethoc.c
drivers/net/fsl_mcdmafec.c
drivers/net/ftmac110.c
drivers/net/lpc32xx_eth.c
drivers/net/macb.c
drivers/net/mcffec.c
drivers/net/mcfmii.c
drivers/net/mpc512x_fec.c
drivers/net/mpc5xxx_fec.c
drivers/net/mvgbe.c
drivers/net/phy/miiphybb.c
drivers/net/sh_eth.c
drivers/net/smc911x.c
drivers/pci/Kconfig
drivers/pci/pci_tegra.c
drivers/power/domain/Kconfig
drivers/power/domain/Makefile
drivers/power/domain/tegra186-power-domain.c [new file with mode: 0644]
drivers/qe/uec.c
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/tegra186-reset.c [new file with mode: 0644]
drivers/usb/eth/smsc95xx.c
include/configs/corvus.h
include/configs/openrisc-generic.h
include/configs/p2771-0000.h
include/configs/smartweb.h
include/configs/snapper9g45.h
include/configs/taurus.h
include/configs/trimslice.h
include/dm/platform_data/net_ethoc.h [new file with mode: 0644]
include/miiphy.h
scripts/coccinelle/net/mdio_register.cocci [new file with mode: 0644]

index 70f4326..36a3c21 100644 (file)
@@ -5,4 +5,28 @@
 / {
        model = "NVIDIA P2771-0000 A02";
        compatible = "nvidia,p2771-0000-a02", "nvidia,p2771-0000", "nvidia,tegra186";
+
+       sdhci@3400000 {
+               cd-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 6) GPIO_ACTIVE_LOW>;
+               power-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 5) GPIO_ACTIVE_HIGH>;
+       };
+
+       pcie-controller@10003000 {
+               status = "okay";
+
+               pci@1,0 {
+                       status = "okay";
+                       nvidia,num-lanes = <2>;
+               };
+
+               pci@2,0 {
+                       status = "disabled";
+                       nvidia,num-lanes = <1>;
+               };
+
+               pci@3,0 {
+                       status = "okay";
+                       nvidia,num-lanes = <1>;
+               };
+       };
 };
index 2384a65..0f1d0e8 100644 (file)
@@ -5,4 +5,28 @@
 / {
        model = "NVIDIA P2771-0000 B00";
        compatible = "nvidia,p2771-0000-b00", "nvidia,p2771-0000", "nvidia,tegra186";
+
+       sdhci@3400000 {
+               cd-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 5) GPIO_ACTIVE_LOW>;
+               power-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 6) GPIO_ACTIVE_HIGH>;
+       };
+
+       pcie-controller@10003000 {
+               status = "okay";
+
+               pci@1,0 {
+                       status = "okay";
+                       nvidia,num-lanes = <4>;
+               };
+
+               pci@2,0 {
+                       status = "disabled";
+                       nvidia,num-lanes = <0>;
+               };
+
+               pci@3,0 {
+                       status = "disabled";
+                       nvidia,num-lanes = <1>;
+               };
+       };
 };
index 87f0427..d867674 100644 (file)
 
        aliases {
                sdhci0 = "/sdhci@3460000";
+               sdhci1 = "/sdhci@3400000";
+               i2c0 = "/bpmp/i2c";
+               i2c1 = "/i2c@3160000";
+               i2c2 = "/i2c@c240000";
+               i2c3 = "/i2c@3180000";
+               i2c4 = "/i2c@3190000";
+               i2c5 = "/i2c@31c0000";
+               i2c6 = "/i2c@c250000";
+               i2c7 = "/i2c@31e0000";
        };
 
        memory {
                reg = <0x0 0x80000000 0x0 0x60000000>;
        };
 
+       i2c@3160000 {
+               status = "okay";
+       };
+
+       i2c@3180000 {
+               status = "okay";
+       };
+
+       i2c@3190000 {
+               status = "okay";
+       };
+
+       i2c@31c0000 {
+               status = "okay";
+       };
+
+       sdhci@3400000 {
+               status = "okay";
+               wp-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 4) GPIO_ACTIVE_HIGH>;
+               bus-width = <4>;
+       };
+
        sdhci@3460000 {
                status = "okay";
                bus-width = <8>;
        };
+
+       i2c@c240000 {
+               status = "okay";
+       };
+
+       i2c@c250000 {
+               status = "okay";
+       };
+
+       i2c@31e0000 {
+               status = "okay";
+       };
+
+       bpmp {
+               i2c {
+                       status = "okay";
+               };
+       };
 };
diff --git a/arch/arm/include/asm/arch-tegra/bpmp_abi.h b/arch/arm/include/asm/arch-tegra/bpmp_abi.h
new file mode 100644 (file)
index 0000000..7b6ad89
--- /dev/null
@@ -0,0 +1,1591 @@
+/*
+ * Copyright (c) 2014-2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _ABI_BPMP_ABI_H_
+#define _ABI_BPMP_ABI_H_
+
+#ifdef LK
+#include <stdint.h>
+#endif
+
+#ifndef __ABI_PACKED
+#define __ABI_PACKED __attribute__((packed))
+#endif
+
+#ifdef NO_GCC_EXTENSIONS
+#define EMPTY char empty;
+#define EMPTY_ARRAY 1
+#else
+#define EMPTY
+#define EMPTY_ARRAY 0
+#endif
+
+#ifndef __UNION_ANON
+#define __UNION_ANON
+#endif
+/**
+ * @file
+ */
+
+
+/**
+ * @defgroup MRQ MRQ Messages
+ * @brief Messages sent to/from BPMP via IPC
+ * @{
+ *   @defgroup MRQ_Format Message Format
+ *   @defgroup MRQ_Codes Message Request (MRQ) Codes
+ *   @defgroup MRQ_Payloads Message Payloads
+ *   @defgroup Error_Codes Error Codes
+ * @}
+ */
+
+/**
+ * @addtogroup MRQ_Format Message Format
+ * @{
+ * The CPU requests the BPMP to perform a particular service by
+ * sending it an IVC frame containing a single MRQ message. An MRQ
+ * message consists of a @ref mrq_request followed by a payload whose
+ * format depends on mrq_request::mrq.
+ *
+ * The BPMP processes the data and replies with an IVC frame (on the
+ * same IVC channel) containing and MRQ response. An MRQ response
+ * consists of a @ref mrq_response followed by a payload whose format
+ * depends on the associated mrq_request::mrq.
+ *
+ * A well-defined subset of the MRQ messages that the CPU sends to the
+ * BPMP can lead to BPMP eventually sending an MRQ message to the
+ * CPU. For example, when the CPU uses an #MRQ_THERMAL message to set
+ * a thermal trip point, the BPMP may eventually send a single
+ * #MRQ_THERMAL message of its own to the CPU indicating that the trip
+ * point has been crossed.
+ * @}
+ */
+
+/**
+ * @ingroup MRQ_Format
+ * @brief header for an MRQ message
+ *
+ * Provides the MRQ number for the MRQ message: #mrq. The remainder of
+ * the MRQ message is a payload (immediately following the
+ * mrq_request) whose format depends on mrq.
+ *
+ * @todo document the flags
+ */
+struct mrq_request {
+       /** @brief MRQ number of the request */
+       uint32_t mrq;
+       /** @brief flags for the request */
+       uint32_t flags;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Format
+ * @brief header for an MRQ response
+ *
+ *  Provides an error code for the associated MRQ message. The
+ *  remainder of the MRQ response is a payload (immediately following
+ *  the mrq_response) whose format depends on the associated
+ *  mrq_request::mrq
+ *
+ * @todo document the flags
+ */
+struct mrq_response {
+       /** @brief error code for the MRQ request itself */
+       int32_t err;
+       /** @brief flags for the response */
+       uint32_t flags;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Format
+ * Minimum needed size for an IPC message buffer
+ */
+#define MSG_MIN_SZ     128
+/**
+ * @ingroup MRQ_Format
+ *  Minimum size guaranteed for data in an IPC message buffer
+ */
+#define MSG_DATA_MIN_SZ        120
+
+/**
+ * @ingroup MRQ_Codes
+ * @name Legal MRQ codes
+ * These are the legal values for mrq_request::mrq
+ * @{
+ */
+
+#define MRQ_PING               0
+#define MRQ_QUERY_TAG          1
+#define MRQ_MODULE_LOAD                4
+#define MRQ_MODULE_UNLOAD      5
+#define MRQ_TRACE_MODIFY       7
+#define MRQ_WRITE_TRACE                8
+#define MRQ_THREADED_PING      9
+#define MRQ_MODULE_MAIL                11
+#define MRQ_DEBUGFS            19
+#define MRQ_RESET              20
+#define MRQ_I2C                        21
+#define MRQ_CLK                        22
+#define MRQ_QUERY_ABI          23
+#define MRQ_PG_READ_STATE      25
+#define MRQ_PG_UPDATE_STATE    26
+#define MRQ_THERMAL            27
+#define MRQ_CPU_VHINT          28
+#define MRQ_ABI_RATCHET                29
+#define MRQ_EMC_DVFS_LATENCY   31
+#define MRQ_TRACE_ITER         64
+
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @brief Maximum MRQ code to be sent by CPU software to
+ * BPMP. Subject to change in future
+ */
+#define MAX_CPU_MRQ_ID         64
+
+/**
+ * @addtogroup MRQ_Payloads Message Payloads
+ * @{
+ *   @defgroup Ping
+ *   @defgroup Query_Tag Query Tag
+ *   @defgroup Module Loadable Modules
+ *   @defgroup Trace
+ *   @defgroup Debugfs
+ *   @defgroup Reset
+ *   @defgroup I2C
+ *   @defgroup Clocks
+ *   @defgroup ABI_info ABI Info
+ *   @defgroup MC_Flush MC Flush
+ *   @defgroup Powergating
+ *   @defgroup Thermal
+ *   @defgroup Vhint CPU Voltage hint
+ *   @defgroup MRQ_Deprecated Deprecated MRQ messages
+ *   @defgroup EMC
+ * @}
+ */
+
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_PING
+ * @brief A simple ping
+ *
+ * * Platforms: All
+ * * Initiators: Any
+ * * Targets: Any
+ * * Request Payload: @ref mrq_ping_request
+ * * Response Payload: @ref mrq_ping_response
+ *
+ * @ingroup MRQ_Codes
+ * @def MRQ_THREADED_PING
+ * @brief A deeper ping
+ *
+ * * Platforms: All
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_ping_request
+ * * Response Payload: @ref mrq_ping_response
+ *
+ * Behavior is equivalent to a simple #MRQ_PING except that BPMP
+ * responds from a thread context (providing a slightly more robust
+ * sign of life).
+ *
+ */
+
+/**
+ * @ingroup Ping
+ * @brief request with #MRQ_PING
+ *
+ * Used by the sender of an #MRQ_PING message to request a pong from
+ * recipient. The response from the recipient is computed based on
+ * #challenge.
+ */
+struct mrq_ping_request {
+/** @brief arbitrarily chosen value */
+       uint32_t challenge;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Ping
+ * @brief response to #MRQ_PING
+ *
+ * Sent in response to an #MRQ_PING message. #reply should be the
+ * mrq_ping_request challenge left shifted by 1 with the carry-bit
+ * dropped.
+ *
+ */
+struct mrq_ping_response {
+       /** @brief response to the MRQ_PING challege */
+       uint32_t reply;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_QUERY_TAG
+ * @brief Query BPMP firmware's tag (i.e. version information)
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_query_tag_request
+ * * Response Payload: N/A
+ *
+ */
+
+/**
+ * @ingroup Query_Tag
+ * @brief request with #MRQ_QUERY_TAG
+ *
+ * Used by #MRQ_QUERY_TAG call to ask BPMP to fill in the memory
+ * pointed by #addr with BPMP firmware header.
+ *
+ * The sender is reponsible for ensuring that #addr is mapped in to
+ * the recipient's address map.
+ */
+struct mrq_query_tag_request {
+  /** @brief base address to store the firmware header */
+       uint32_t addr;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_MODULE_LOAD
+ * @brief dynamically load a BPMP code module
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_module_load_request
+ * * Response Payload: @ref mrq_module_load_response
+ *
+ * @note This MRQ is disabled on production systems
+ *
+ */
+
+/**
+ * @ingroup Module
+ * @brief request with #MRQ_MODULE_LOAD
+ *
+ * Used by #MRQ_MODULE_LOAD calls to ask the recipient to dynamically
+ * load the code located at #phys_addr and having size #size
+ * bytes. #phys_addr is treated as a void pointer.
+ *
+ * The recipient copies the code from #phys_addr to locally allocated
+ * memory prior to responding to this message.
+ *
+ * @todo document the module header format
+ *
+ * The sender is responsible for ensuring that the code is mapped in
+ * the recipient's address map.
+ *
+ */
+struct mrq_module_load_request {
+       /** @brief base address of the code to load. Treated as (void *) */
+       uint32_t phys_addr; /* (void *) */
+       /** @brief size in bytes of code to load */
+       uint32_t size;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Module
+ * @brief response to #MRQ_MODULE_LOAD
+ *
+ * @todo document mrq_response::err
+ */
+struct mrq_module_load_response {
+       /** @brief handle to the loaded module */
+       uint32_t base;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_MODULE_UNLOAD
+ * @brief unload a previously loaded code module
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_module_unload_request
+ * * Response Payload: N/A
+ *
+ * @note This MRQ is disabled on production systems
+ */
+
+/**
+ * @ingroup Module
+ * @brief request with #MRQ_MODULE_UNLOAD
+ *
+ * Used by #MRQ_MODULE_UNLOAD calls to request that a previously loaded
+ * module be unloaded.
+ */
+struct mrq_module_unload_request {
+       /** @brief handle of the module to unload */
+       uint32_t base;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_TRACE_MODIFY
+ * @brief modify the set of enabled trace events
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_trace_modify_request
+ * * Response Payload: @ref mrq_trace_modify_response
+ *
+ * @note This MRQ is disabled on production systems
+ */
+
+/**
+ * @ingroup Trace
+ * @brief request with #MRQ_TRACE_MODIFY
+ *
+ * Used by %MRQ_TRACE_MODIFY calls to enable or disable specify trace
+ * events.  #set takes precedence for any bit set in both #set and
+ * #clr.
+ */
+struct mrq_trace_modify_request {
+       /** @brief bit mask of trace events to disable */
+       uint32_t clr;
+       /** @brief bit mask of trace events to enable */
+       uint32_t set;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Trace
+ * @brief response to #MRQ_TRACE_MODIFY
+ *
+ * Sent in repsonse to an #MRQ_TRACE_MODIFY message. #mask reflects the
+ * state of which events are enabled after the recipient acted on the
+ * message.
+ *
+ */
+struct mrq_trace_modify_response {
+       /** @brief bit mask of trace event enable states */
+       uint32_t mask;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_WRITE_TRACE
+ * @brief Write trace data to a buffer
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_write_trace_request
+ * * Response Payload: @ref mrq_write_trace_response
+ *
+ * mrq_response::err depends on the @ref mrq_write_trace_request field
+ * values. err is -#BPMP_EINVAL if size is zero or area is NULL or
+ * area is in an illegal range. A positive value for err indicates the
+ * number of bytes written to area.
+ *
+ * @note This MRQ is disabled on production systems
+ */
+
+/**
+ * @ingroup Trace
+ * @brief request with #MRQ_WRITE_TRACE
+ *
+ * Used by MRQ_WRITE_TRACE calls to ask the recipient to copy trace
+ * data from the recipient's local buffer to the output buffer. #area
+ * is treated as a byte-aligned pointer in the recipient's address
+ * space.
+ *
+ * The sender is responsible for ensuring that the output
+ * buffer is mapped in the recipient's address map. The recipient is
+ * responsible for protecting its own code and data from accidental
+ * overwrites.
+ */
+struct mrq_write_trace_request {
+       /** @brief base address of output buffer */
+       uint32_t area;
+       /** @brief size in bytes of the output buffer */
+       uint32_t size;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Trace
+ * @brief response to #MRQ_WRITE_TRACE
+ *
+ * Once this response is sent, the respondent will not access the
+ * output buffer further.
+ */
+struct mrq_write_trace_response {
+       /**
+        * @brief flag whether more data remains in local buffer
+        *
+        * Value is 1 if the entire local trace buffer has been
+        * drained to the outputbuffer. Value is 0 otherwise.
+        */
+       uint32_t eof;
+} __ABI_PACKED;
+
+/** @private */
+struct mrq_threaded_ping_request {
+       uint32_t challenge;
+} __ABI_PACKED;
+
+/** @private */
+struct mrq_threaded_ping_response {
+       uint32_t reply;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_MODULE_MAIL
+ * @brief send a message to a loadable module
+ *
+ * * Platforms: All
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_module_mail_request
+ * * Response Payload: @ref mrq_module_mail_response
+ *
+ * @note This MRQ is disabled on production systems
+ */
+
+/**
+ * @ingroup Module
+ * @brief request with #MRQ_MODULE_MAIL
+ */
+struct mrq_module_mail_request {
+       /** @brief handle to the previously loaded module */
+       uint32_t base;
+       /** @brief module-specific mail payload
+        *
+        * The length of data[ ] is unknown to the BPMP core firmware
+        * but it is limited to the size of an IPC message.
+        */
+       uint8_t data[EMPTY_ARRAY];
+} __ABI_PACKED;
+
+/**
+ * @ingroup Module
+ * @brief response to #MRQ_MODULE_MAIL
+ */
+struct mrq_module_mail_response {
+       /** @brief module-specific mail payload
+        *
+        * The length of data[ ] is unknown to the BPMP core firmware
+        * but it is limited to the size of an IPC message.
+        */
+       uint8_t data[EMPTY_ARRAY];
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_DEBUGFS
+ * @brief Interact with BPMP's debugfs file nodes
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_debugfs_request
+ * * Response Payload: @ref mrq_debugfs_response
+ */
+
+/**
+ * @addtogroup Debugfs
+ * @{
+ *
+ * The BPMP firmware implements a pseudo-filesystem called
+ * debugfs. Any driver within the firmware may register with debugfs
+ * to expose an arbitrary set of "files" in the filesystem. When
+ * software on the CPU writes to a debugfs file, debugfs passes the
+ * written data to a callback provided by the driver. When software on
+ * the CPU reads a debugfs file, debugfs queries the driver for the
+ * data to return to the CPU. The intention of the debugfs filesystem
+ * is to provide information useful for debugging the system at
+ * runtime.
+ *
+ * @note The files exposed via debugfs are not part of the
+ * BPMP firmware's ABI. debugfs files may be added or removed in any
+ * given version of the firmware. Typically the semantics of a debugfs
+ * file are consistent from version to version but even that is not
+ * guaranteed.
+ *
+ * @}
+ */
+/** @ingroup Debugfs */
+enum mrq_debugfs_commands {
+       CMD_DEBUGFS_READ = 1,
+       CMD_DEBUGFS_WRITE = 2,
+       CMD_DEBUGFS_DUMPDIR = 3,
+       CMD_DEBUGFS_MAX
+};
+
+/**
+ * @ingroup Debugfs
+ * @brief parameters for CMD_DEBUGFS_READ/WRITE command
+ */
+struct cmd_debugfs_fileop_request {
+       /** @brief physical address pointing at filename */
+       uint32_t fnameaddr;
+       /** @brief length in bytes of filename buffer */
+       uint32_t fnamelen;
+       /** @brief physical address pointing to data buffer */
+       uint32_t dataaddr;
+       /** @brief length in bytes of data buffer */
+       uint32_t datalen;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ * @brief parameters for CMD_DEBUGFS_READ/WRITE command
+ */
+struct cmd_debugfs_dumpdir_request {
+       /** @brief physical address pointing to data buffer */
+       uint32_t dataaddr;
+       /** @brief length in bytes of data buffer */
+       uint32_t datalen;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ * @brief response data for CMD_DEBUGFS_READ/WRITE command
+ */
+struct cmd_debugfs_fileop_response {
+       /** @brief always 0 */
+       uint32_t reserved;
+       /** @brief number of bytes read from or written to data buffer */
+       uint32_t nbytes;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ * @brief response data for CMD_DEBUGFS_DUMPDIR command
+ */
+struct cmd_debugfs_dumpdir_response {
+       /** @brief always 0 */
+       uint32_t reserved;
+       /** @brief number of bytes read from or written to data buffer */
+       uint32_t nbytes;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ * @brief request with #MRQ_DEBUGFS.
+ *
+ * The sender of an MRQ_DEBUGFS message uses #cmd to specify a debugfs
+ * command to execute. Legal commands are the values of @ref
+ * mrq_debugfs_commands. Each command requires a specific additional
+ * payload of data.
+ *
+ * |command            |payload|
+ * |-------------------|-------|
+ * |CMD_DEBUGFS_READ   |fop    |
+ * |CMD_DEBUGFS_WRITE  |fop    |
+ * |CMD_DEBUGFS_DUMPDIR|dumpdir|
+ */
+struct mrq_debugfs_request {
+       uint32_t cmd;
+       union {
+               struct cmd_debugfs_fileop_request fop;
+               struct cmd_debugfs_dumpdir_request dumpdir;
+       } __UNION_ANON;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ */
+struct mrq_debugfs_response {
+       /** @brief always 0 */
+       int32_t reserved;
+       union {
+               /** @brief response data for CMD_DEBUGFS_READ OR
+                * CMD_DEBUGFS_WRITE command
+                */
+               struct cmd_debugfs_fileop_response fop;
+               /** @brief response data for CMD_DEBUGFS_DUMPDIR command */
+               struct cmd_debugfs_dumpdir_response dumpdir;
+       } __UNION_ANON;
+} __ABI_PACKED;
+
+/**
+ * @addtogroup Debugfs
+ * @{
+ */
+#define DEBUGFS_S_ISDIR        (1 << 9)
+#define DEBUGFS_S_IRUSR        (1 << 8)
+#define DEBUGFS_S_IWUSR        (1 << 7)
+/** @} */
+
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_RESET
+ * @brief reset an IP block
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_reset_request
+ * * Response Payload: N/A
+ */
+
+/**
+ * @ingroup Reset
+ */
+enum mrq_reset_commands {
+       CMD_RESET_ASSERT = 1,
+       CMD_RESET_DEASSERT = 2,
+       CMD_RESET_MODULE = 3,
+       CMD_RESET_MAX, /* not part of ABI and subject to change */
+};
+
+/**
+ * @ingroup Reset
+ * @brief request with MRQ_RESET
+ *
+ * Used by the sender of an #MRQ_RESET message to request BPMP to
+ * assert or or deassert a given reset line.
+ */
+struct mrq_reset_request {
+       /** @brief reset action to perform (@enum mrq_reset_commands) */
+       uint32_t cmd;
+       /** @brief id of the reset to affected */
+       uint32_t reset_id;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_I2C
+ * @brief issue an i2c transaction
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_i2c_request
+ * * Response Payload: @ref mrq_i2c_response
+ */
+
+/**
+ * @addtogroup I2C
+ * @{
+ */
+#define TEGRA_I2C_IPC_MAX_IN_BUF_SIZE  (MSG_DATA_MIN_SZ - 12)
+#define TEGRA_I2C_IPC_MAX_OUT_BUF_SIZE (MSG_DATA_MIN_SZ - 4)
+/** @} */
+
+/**
+ * @ingroup I2C
+ * @name Serial I2C flags
+ * Use these flags with serial_i2c_request::flags
+ * @{
+ */
+#define SERIALI2C_TEN           0x0010
+#define SERIALI2C_RD            0x0001
+#define SERIALI2C_STOP          0x8000
+#define SERIALI2C_NOSTART       0x4000
+#define SERIALI2C_REV_DIR_ADDR  0x2000
+#define SERIALI2C_IGNORE_NAK    0x1000
+#define SERIALI2C_NO_RD_ACK     0x0800
+#define SERIALI2C_RECV_LEN      0x0400
+/** @} */
+/** @ingroup I2C */
+enum {
+       CMD_I2C_XFER = 1
+};
+
+/**
+ * @ingroup I2C
+ * @brief serializable i2c request
+ *
+ * Instances of this structure are packed (little-endian) into
+ * cmd_i2c_xfer_request::data_buf. Each instance represents a single
+ * transaction (or a portion of a transaction with repeated starts) on
+ * an i2c bus.
+ *
+ * Because these structures are packed, some instances are likely to
+ * be misaligned. Additionally because #data is variable length, it is
+ * not possible to iterate through a serialized list of these
+ * structures without inspecting #len in each instance.  It may be
+ * easier to serialize or deserialize cmd_i2c_xfer_request::data_buf
+ * manually rather than using this structure definition.
+*/
+struct serial_i2c_request {
+       /** @brief I2C slave address */
+       uint16_t addr;
+       /** @brief bitmask of SERIALI2C_ flags */
+       uint16_t flags;
+       /** @brief length of I2C transaction in bytes */
+       uint16_t len;
+       /** @brief for write transactions only, #len bytes of data */
+       uint8_t data[];
+} __ABI_PACKED;
+
+/**
+ * @ingroup I2C
+ * @brief trigger one or more i2c transactions
+ */
+struct cmd_i2c_xfer_request {
+       /** @brief valid bus number from mach-t186/i2c-t186.h*/
+       uint32_t bus_id;
+
+       /** @brief count of valid bytes in #data_buf*/
+       uint32_t data_size;
+
+       /** @brief serialized packed instances of @ref serial_i2c_request*/
+       uint8_t data_buf[TEGRA_I2C_IPC_MAX_IN_BUF_SIZE];
+} __ABI_PACKED;
+
+/**
+ * @ingroup I2C
+ * @brief container for data read from the i2c bus
+ *
+ * Processing an cmd_i2c_xfer_request::data_buf causes BPMP to execute
+ * zero or more I2C reads. The data read from the bus is serialized
+ * into #data_buf.
+ */
+struct cmd_i2c_xfer_response {
+       /** @brief count of valid bytes in #data_buf*/
+       uint32_t data_size;
+       /** @brief i2c read data */
+       uint8_t data_buf[TEGRA_I2C_IPC_MAX_OUT_BUF_SIZE];
+} __ABI_PACKED;
+
+/**
+ * @ingroup I2C
+ * @brief request with #MRQ_I2C
+ */
+struct mrq_i2c_request {
+       /** @brief always CMD_I2C_XFER (i.e. 1) */
+       uint32_t cmd;
+       /** @brief parameters of the transfer request */
+       struct cmd_i2c_xfer_request xfer;
+} __ABI_PACKED;
+
+/**
+ * @ingroup I2C
+ * @brief response to #MRQ_I2C
+ */
+struct mrq_i2c_response {
+       struct cmd_i2c_xfer_response xfer;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_CLK
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_clk_request
+ * * Response Payload: @ref mrq_clk_response
+ * @addtogroup Clocks
+ * @{
+ */
+
+/**
+ * @name MRQ_CLK sub-commands
+ * @{
+ */
+enum {
+       CMD_CLK_GET_RATE = 1,
+       CMD_CLK_SET_RATE = 2,
+       CMD_CLK_ROUND_RATE = 3,
+       CMD_CLK_GET_PARENT = 4,
+       CMD_CLK_SET_PARENT = 5,
+       CMD_CLK_IS_ENABLED = 6,
+       CMD_CLK_ENABLE = 7,
+       CMD_CLK_DISABLE = 8,
+       CMD_CLK_GET_ALL_INFO = 14,
+       CMD_CLK_GET_MAX_CLK_ID = 15,
+       CMD_CLK_MAX,
+};
+/** @} */
+
+#define MRQ_CLK_NAME_MAXLEN    40
+#define MRQ_CLK_MAX_PARENTS    16
+
+/** @private */
+struct cmd_clk_get_rate_request {
+       EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_get_rate_response {
+       int64_t rate;
+} __ABI_PACKED;
+
+struct cmd_clk_set_rate_request {
+       int32_t unused;
+       int64_t rate;
+} __ABI_PACKED;
+
+struct cmd_clk_set_rate_response {
+       int64_t rate;
+} __ABI_PACKED;
+
+struct cmd_clk_round_rate_request {
+       int32_t unused;
+       int64_t rate;
+} __ABI_PACKED;
+
+struct cmd_clk_round_rate_response {
+       int64_t rate;
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_get_parent_request {
+       EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_get_parent_response {
+       uint32_t parent_id;
+} __ABI_PACKED;
+
+struct cmd_clk_set_parent_request {
+       uint32_t parent_id;
+} __ABI_PACKED;
+
+struct cmd_clk_set_parent_response {
+       uint32_t parent_id;
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_is_enabled_request {
+       EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_is_enabled_response {
+       int32_t state;
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_enable_request {
+       EMPTY
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_enable_response {
+       EMPTY
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_disable_request {
+       EMPTY
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_disable_response {
+       EMPTY
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_get_all_info_request {
+       EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_get_all_info_response {
+       uint32_t flags;
+       uint32_t parent;
+       uint32_t parents[MRQ_CLK_MAX_PARENTS];
+       uint8_t num_parents;
+       uint8_t name[MRQ_CLK_NAME_MAXLEN];
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_get_max_clk_id_request {
+       EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_get_max_clk_id_response {
+       uint32_t max_id;
+} __ABI_PACKED;
+/** @} */
+
+/**
+ * @ingroup Clocks
+ * @brief request with #MRQ_CLK
+ *
+ * Used by the sender of an #MRQ_CLK message to control clocks. The
+ * clk_request is split into several sub-commands. Some sub-commands
+ * require no additional data. Others have a sub-command specific
+ * payload
+ *
+ * |sub-command                 |payload                |
+ * |----------------------------|-----------------------|
+ * |CMD_CLK_GET_RATE            |-                      |
+ * |CMD_CLK_SET_RATE            |clk_set_rate           |
+ * |CMD_CLK_ROUND_RATE          |clk_round_rate         |
+ * |CMD_CLK_GET_PARENT          |-                      |
+ * |CMD_CLK_SET_PARENT          |clk_set_parent         |
+ * |CMD_CLK_IS_ENABLED          |-                      |
+ * |CMD_CLK_ENABLE              |-                      |
+ * |CMD_CLK_DISABLE             |-                      |
+ * |CMD_CLK_GET_ALL_INFO        |-                      |
+ * |CMD_CLK_GET_MAX_CLK_ID      |-                      |
+ *
+ */
+
+struct mrq_clk_request {
+       /** @brief sub-command and clock id concatenated to 32-bit word.
+        * - bits[31..24] is the sub-cmd.
+        * - bits[23..0] is the clock id
+        */
+       uint32_t cmd_and_id;
+
+       union {
+               /** @private */
+               struct cmd_clk_get_rate_request clk_get_rate;
+               struct cmd_clk_set_rate_request clk_set_rate;
+               struct cmd_clk_round_rate_request clk_round_rate;
+               /** @private */
+               struct cmd_clk_get_parent_request clk_get_parent;
+               struct cmd_clk_set_parent_request clk_set_parent;
+               /** @private */
+               struct cmd_clk_enable_request clk_enable;
+               /** @private */
+               struct cmd_clk_disable_request clk_disable;
+               /** @private */
+               struct cmd_clk_is_enabled_request clk_is_enabled;
+               /** @private */
+               struct cmd_clk_get_all_info_request clk_get_all_info;
+               /** @private */
+               struct cmd_clk_get_max_clk_id_request clk_get_max_clk_id;
+       } __UNION_ANON;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Clocks
+ * @brief response to MRQ_CLK
+ *
+ * Each sub-command supported by @ref mrq_clk_request may return
+ * sub-command-specific data. Some do and some do not as indicated in
+ * the following table
+ *
+ * |sub-command                 |payload                 |
+ * |----------------------------|------------------------|
+ * |CMD_CLK_GET_RATE            |clk_get_rate            |
+ * |CMD_CLK_SET_RATE            |clk_set_rate            |
+ * |CMD_CLK_ROUND_RATE          |clk_round_rate          |
+ * |CMD_CLK_GET_PARENT          |clk_get_parent          |
+ * |CMD_CLK_SET_PARENT          |clk_set_parent          |
+ * |CMD_CLK_IS_ENABLED          |clk_is_enabled          |
+ * |CMD_CLK_ENABLE              |-                       |
+ * |CMD_CLK_DISABLE             |-                       |
+ * |CMD_CLK_GET_ALL_INFO        |clk_get_all_info        |
+ * |CMD_CLK_GET_MAX_CLK_ID      |clk_get_max_id          |
+ *
+ */
+
+struct mrq_clk_response {
+       union {
+               struct cmd_clk_get_rate_response clk_get_rate;
+               struct cmd_clk_set_rate_response clk_set_rate;
+               struct cmd_clk_round_rate_response clk_round_rate;
+               struct cmd_clk_get_parent_response clk_get_parent;
+               struct cmd_clk_set_parent_response clk_set_parent;
+               /** @private */
+               struct cmd_clk_enable_response clk_enable;
+               /** @private */
+               struct cmd_clk_disable_response clk_disable;
+               struct cmd_clk_is_enabled_response clk_is_enabled;
+               struct cmd_clk_get_all_info_response clk_get_all_info;
+               struct cmd_clk_get_max_clk_id_response clk_get_max_clk_id;
+       } __UNION_ANON;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_QUERY_ABI
+ * @brief check if an MRQ is implemented
+ *
+ * * Platforms: All
+ * * Initiators: Any
+ * * Targets: Any
+ * * Request Payload: @ref mrq_query_abi_request
+ * * Response Payload: @ref mrq_query_abi_response
+ */
+
+/**
+ * @ingroup ABI_info
+ * @brief request with MRQ_QUERY_ABI
+ *
+ * Used by #MRQ_QUERY_ABI call to check if MRQ code #mrq is supported
+ * by the recipient.
+ */
+struct mrq_query_abi_request {
+       /** @brief MRQ code to query */
+       uint32_t mrq;
+} __ABI_PACKED;
+
+/**
+ * @ingroup ABI_info
+ * @brief response to MRQ_QUERY_ABI
+ */
+struct mrq_query_abi_response {
+       /** @brief 0 if queried MRQ is supported. Else, -#BPMP_ENODEV */
+       int32_t status;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_PG_READ_STATE
+ * @brief read the power-gating state of a partition
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_pg_read_state_request
+ * * Response Payload: @ref mrq_pg_read_state_response
+ * @addtogroup Powergating
+ * @{
+ */
+
+/**
+ * @brief request with #MRQ_PG_READ_STATE
+ *
+ * Used by MRQ_PG_READ_STATE call to read the current state of a
+ * partition.
+ */
+struct mrq_pg_read_state_request {
+       /** @brief ID of partition */
+       uint32_t partition_id;
+} __ABI_PACKED;
+
+/**
+ * @brief response to MRQ_PG_READ_STATE
+ * @todo define possible errors.
+ */
+struct mrq_pg_read_state_response {
+       /** @brief read as don't care */
+       uint32_t sram_state;
+       /** @brief state of power partition
+        * * 0 : off
+        * * 1 : on
+        */
+       uint32_t logic_state;
+} __ABI_PACKED;
+
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_PG_UPDATE_STATE
+ * @brief modify the power-gating state of a partition
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_pg_update_state_request
+ * * Response Payload: N/A
+ * @addtogroup Powergating
+ * @{
+ */
+
+/**
+ * @brief request with mrq_pg_update_state_request
+ *
+ * Used by #MRQ_PG_UPDATE_STATE call to request BPMP to change the
+ * state of a power partition #partition_id.
+ */
+struct mrq_pg_update_state_request {
+       /** @brief ID of partition */
+       uint32_t partition_id;
+       /** @brief secondary control of power partition
+        *  @details Ignored by many versions of the BPMP
+        *  firmware. For maximum compatibility, set the value
+        *  according to @logic_state
+        * *  0x1: power ON partition (@ref logic_state == 0x3)
+        * *  0x3: power OFF partition (@ref logic_state == 0x1)
+        */
+       uint32_t sram_state;
+       /** @brief controls state of power partition, legal values are
+        * *  0x1 : power OFF partition
+        * *  0x3 : power ON partition
+        */
+       uint32_t logic_state;
+       /** @brief change state of clocks of the power partition, legal values
+        * *  0x0 : do not change clock state
+        * *  0x1 : disable partition clocks (only applicable when
+        *          @ref logic_state == 0x1)
+        * *  0x3 : enable partition clocks (only applicable when
+        *          @ref logic_state == 0x3)
+        */
+       uint32_t clock_state;
+} __ABI_PACKED;
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_THERMAL
+ * @brief interact with BPMP thermal framework
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: Any
+ * * Request Payload: TODO
+ * * Response Payload: TODO
+ *
+ * @addtogroup Thermal
+ *
+ * The BPMP firmware includes a thermal framework. Drivers within the
+ * bpmp firmware register with the framework to provide thermal
+ * zones. Each thermal zone corresponds to an entity whose temperature
+ * can be measured. The framework also has a notion of trip points. A
+ * trip point consists of a thermal zone id, a temperature, and a
+ * callback routine. The framework invokes the callback when the zone
+ * hits the indicated temperature. The BPMP firmware uses this thermal
+ * framework interally to implement various temperature-dependent
+ * functions.
+ *
+ * Software on the CPU can use #MRQ_THERMAL (with payload @ref
+ * mrq_thermal_host_to_bpmp_request) to interact with the BPMP thermal
+ * framework. The CPU must It can query the number of supported zones,
+ * query zone temperatures, and set trip points.
+ *
+ * When a trip point set by the CPU gets crossed, BPMP firmware issues
+ * an IPC to the CPU having mrq_request::mrq = #MRQ_THERMAL and a
+ * payload of @ref mrq_thermal_bpmp_to_host_request.
+ * @{
+ */
+enum mrq_thermal_host_to_bpmp_cmd {
+       /**
+        * @brief Check whether the BPMP driver supports the specified
+        * request type.
+        *
+        * Host needs to supply request parameters.
+        *
+        * mrq_response::err is 0 if the specified request is
+        * supported and -#BPMP_ENODEV otherwise.
+        */
+       CMD_THERMAL_QUERY_ABI = 0,
+
+       /**
+        * @brief Get the current temperature of the specified zone.
+        *
+        * Host needs to supply request parameters.
+        *
+        * mrq_response::err is
+        * *  0: Temperature query succeeded.
+        * *  -#BPMP_EINVAL: Invalid request parameters.
+        * *  -#BPMP_ENOENT: No driver registered for thermal zone..
+        * *  -#BPMP_EFAULT: Problem reading temperature measurement.
+        */
+       CMD_THERMAL_GET_TEMP = 1,
+
+       /**
+        * @brief Enable or disable and set the lower and upper
+        *   thermal limits for a thermal trip point. Each zone has
+        *   one trip point.
+        *
+        * Host needs to supply request parameters. Once the
+        * temperature hits a trip point, the BPMP will send a message
+        * to the CPU having MRQ=MRQ_THERMAL and
+        * type=CMD_THERMAL_HOST_TRIP_REACHED
+        *
+        * mrq_response::err is
+        * *  0: Trip successfully set.
+        * *  -#BPMP_EINVAL: Invalid request parameters.
+        * *  -#BPMP_ENOENT: No driver registered for thermal zone.
+        * *  -#BPMP_EFAULT: Problem setting trip point.
+        */
+       CMD_THERMAL_SET_TRIP = 2,
+
+       /**
+        * @brief Get the number of supported thermal zones.
+        *
+        * No request parameters required.
+        *
+        * mrq_response::err is always 0, indicating success.
+        */
+       CMD_THERMAL_GET_NUM_ZONES = 3,
+
+       /** @brief: number of supported host-to-bpmp commands. May
+        * increase in future
+        */
+       CMD_THERMAL_HOST_TO_BPMP_NUM
+};
+
+enum mrq_thermal_bpmp_to_host_cmd {
+       /**
+        * @brief Indication that the temperature for a zone has
+        *   exceeded the range indicated in the thermal trip point
+        *   for the zone.
+        *
+        * BPMP needs to supply request parameters. Host only needs to
+        * acknowledge.
+        */
+       CMD_THERMAL_HOST_TRIP_REACHED = 100,
+
+       /** @brief: number of supported bpmp-to-host commands. May
+        * increase in future
+        */
+       CMD_THERMAL_BPMP_TO_HOST_NUM
+};
+
+/*
+ * Host->BPMP request data for request type CMD_THERMAL_QUERY_ABI
+ *
+ * zone: Request type for which to check existence.
+ */
+struct cmd_thermal_query_abi_request {
+       uint32_t type;
+} __ABI_PACKED;
+
+/*
+ * Host->BPMP request data for request type CMD_THERMAL_GET_TEMP
+ *
+ * zone: Number of thermal zone.
+ */
+struct cmd_thermal_get_temp_request {
+       uint32_t zone;
+} __ABI_PACKED;
+
+/*
+ * BPMP->Host reply data for request CMD_THERMAL_GET_TEMP
+ *
+ * error: 0 if request succeeded.
+ *     -BPMP_EINVAL if request parameters were invalid.
+ *      -BPMP_ENOENT if no driver was registered for the specified thermal zone.
+ *      -BPMP_EFAULT for other thermal zone driver errors.
+ * temp: Current temperature in millicelsius.
+ */
+struct cmd_thermal_get_temp_response {
+       int32_t temp;
+} __ABI_PACKED;
+
+/*
+ * Host->BPMP request data for request type CMD_THERMAL_SET_TRIP
+ *
+ * zone: Number of thermal zone.
+ * low: Temperature of lower trip point in millicelsius
+ * high: Temperature of upper trip point in millicelsius
+ * enabled: 1 to enable trip point, 0 to disable trip point
+ */
+struct cmd_thermal_set_trip_request {
+       uint32_t zone;
+       int32_t low;
+       int32_t high;
+       uint32_t enabled;
+} __ABI_PACKED;
+
+/*
+ * BPMP->Host request data for request type CMD_THERMAL_HOST_TRIP_REACHED
+ *
+ * zone: Number of thermal zone where trip point was reached.
+ */
+struct cmd_thermal_host_trip_reached_request {
+       uint32_t zone;
+} __ABI_PACKED;
+
+/*
+ * BPMP->Host reply data for request type CMD_THERMAL_GET_NUM_ZONES
+ *
+ * num: Number of supported thermal zones. The thermal zones are indexed
+ *      starting from zero.
+ */
+struct cmd_thermal_get_num_zones_response {
+       uint32_t num;
+} __ABI_PACKED;
+
+/*
+ * Host->BPMP request data.
+ *
+ * Reply type is union mrq_thermal_bpmp_to_host_response.
+ *
+ * type: Type of request. Values listed in enum mrq_thermal_type.
+ * data: Request type specific parameters.
+ */
+struct mrq_thermal_host_to_bpmp_request {
+       uint32_t type;
+       union {
+               struct cmd_thermal_query_abi_request query_abi;
+               struct cmd_thermal_get_temp_request get_temp;
+               struct cmd_thermal_set_trip_request set_trip;
+       } __UNION_ANON;
+} __ABI_PACKED;
+
+/*
+ * BPMP->Host request data.
+ *
+ * type: Type of request. Values listed in enum mrq_thermal_type.
+ * data: Request type specific parameters.
+ */
+struct mrq_thermal_bpmp_to_host_request {
+       uint32_t type;
+       union {
+               struct cmd_thermal_host_trip_reached_request host_trip_reached;
+       } __UNION_ANON;
+} __ABI_PACKED;
+
+/*
+ * Data in reply to a Host->BPMP request.
+ */
+union mrq_thermal_bpmp_to_host_response {
+       struct cmd_thermal_get_temp_response get_temp;
+       struct cmd_thermal_get_num_zones_response get_num_zones;
+} __ABI_PACKED;
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_CPU_VHINT
+ * @brief Query CPU voltage hint data
+ *
+ * * Platforms: T186
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_cpu_vhint_request
+ * * Response Payload: N/A
+ *
+ * @addtogroup Vhint CPU Voltage hint
+ * @{
+ */
+
+/**
+ * @brief request with #MRQ_CPU_VHINT
+ *
+ * Used by #MRQ_CPU_VHINT call by CCPLEX to retrieve voltage hint data
+ * from BPMP to memory space pointed by #addr. CCPLEX is responsible
+ * to allocate sizeof(cpu_vhint_data) sized block of memory and
+ * appropriately map it for BPMP before sending the request.
+ */
+struct mrq_cpu_vhint_request {
+       /** @brief IOVA address for the #cpu_vhint_data */
+       uint32_t addr; /* struct cpu_vhint_data * */
+       /** @brief ID of the cluster whose data is requested */
+       uint32_t cluster_id; /* enum cluster_id */
+} __ABI_PACKED;
+
+/**
+ * @brief description of the CPU v/f relation
+ *
+ * Used by #MRQ_CPU_VHINT call to carry data pointed by #addr of
+ * struct mrq_cpu_vhint_request
+ */
+struct cpu_vhint_data {
+       uint32_t ref_clk_hz; /**< reference frequency in Hz */
+       uint16_t pdiv; /**< post divider value */
+       uint16_t mdiv; /**< input divider value */
+       uint16_t ndiv_max; /**< fMAX expressed with max NDIV value */
+       /** table of ndiv values as a function of vINDEX (voltage index) */
+       uint16_t ndiv[80];
+       /** minimum allowed NDIV value */
+       uint16_t ndiv_min;
+       /** minimum allowed voltage hint value (as in vINDEX) */
+       uint16_t vfloor;
+       /** maximum allowed voltage hint value (as in vINDEX) */
+       uint16_t vceil;
+       /** post-multiplier for vindex value */
+       uint16_t vindex_mult;
+       /** post-divider for vindex value */
+       uint16_t vindex_div;
+       /** reserved for future use */
+       uint16_t reserved[328];
+} __ABI_PACKED;
+
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_ABI_RATCHET
+ * @brief ABI ratchet value query
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_abi_ratchet_request
+ * * Response Payload: @ref mrq_abi_ratchet_response
+ * @addtogroup ABI_info
+ * @{
+ */
+
+/**
+ * @brief an ABI compatibility mechanism
+ *
+ * BPMP_ABI_RATCHET_VALUE may increase for various reasons in a future
+ * revision of this header file.
+ * 1. That future revision deprecates some MRQ
+ * 2. That future revision introduces a breaking change to an existing
+ *    MRQ or
+ * 3. A bug is discovered in an existing implementation of the BPMP-FW
+ *    (or possibly one of its clients) which warrants deprecating that
+ *    implementation.
+ */
+#define BPMP_ABI_RATCHET_VALUE 3
+
+/**
+ * @brief request with #MRQ_ABI_RATCHET.
+ *
+ * #ratchet should be #BPMP_ABI_RATCHET_VALUE from the ABI header
+ * against which the requester was compiled.
+ *
+ * If ratchet is less than BPMP's #BPMP_ABI_RATCHET_VALUE, BPMP may
+ * reply with mrq_response::err = -#BPMP_ERANGE to indicate that
+ * BPMP-FW cannot interoperate correctly with the requester. Requester
+ * should cease further communication with BPMP.
+ *
+ * Otherwise, err shall be 0.
+ */
+struct mrq_abi_ratchet_request {
+       /** @brief requester's ratchet value */
+       uint16_t ratchet;
+};
+
+/**
+ * @brief response to #MRQ_ABI_RATCHET
+ *
+ * #ratchet shall be #BPMP_ABI_RATCHET_VALUE from the ABI header
+ * against which BPMP firwmare was compiled.
+ *
+ * If #ratchet is less than the requester's #BPMP_ABI_RATCHET_VALUE,
+ * the requster must either interoperate with BPMP according to an ABI
+ * header version with BPMP_ABI_RATCHET_VALUE = ratchet or cease
+ * communication with BPMP.
+ *
+ * If mrq_response::err is 0 and ratchet is greater than or equal to the
+ * requester's BPMP_ABI_RATCHET_VALUE, the requester should continue
+ * normal operation.
+ */
+struct mrq_abi_ratchet_response {
+       /** @brief BPMP's ratchet value */
+       uint16_t ratchet;
+};
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_EMC_DVFS_LATENCY
+ * @brief query frequency dependent EMC DVFS latency
+ *
+ * * Platforms: T186
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: N/A
+ * * Response Payload: @ref mrq_emc_dvfs_latency_response
+ * @addtogroup EMC
+ * @{
+ */
+
+/**
+ * @brief used by @ref mrq_emc_dvfs_latency_response
+ */
+struct emc_dvfs_latency {
+       /** @brief EMC frequency in kHz */
+       uint32_t freq;
+       /** @brief EMC DVFS latency in nanoseconds */
+       uint32_t latency;
+} __ABI_PACKED;
+
+#define EMC_DVFS_LATENCY_MAX_SIZE      14
+/**
+ * @brief response to #MRQ_EMC_DVFS_LATENCY
+ */
+struct mrq_emc_dvfs_latency_response {
+       /** @brief the number valid entries in #pairs */
+       uint32_t num_pairs;
+       /** @brief EMC <frequency, latency> information */
+       struct emc_dvfs_latency pairs[EMC_DVFS_LATENCY_MAX_SIZE];
+} __ABI_PACKED;
+
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_TRACE_ITER
+ * @brief manage the trace iterator
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: N/A
+ * * Response Payload: @ref mrq_trace_iter_request
+ * @addtogroup Trace
+ * @{
+ */
+enum {
+       /** @brief (re)start the tracing now. Ignore older events */
+       TRACE_ITER_INIT = 0,
+       /** @brief clobber all events in the trace buffer */
+       TRACE_ITER_CLEAN = 1
+};
+
+/**
+ * @brief request with #MRQ_TRACE_ITER
+ */
+struct mrq_trace_iter_request {
+       /** @brief TRACE_ITER_INIT or TRACE_ITER_CLEAN */
+       uint32_t cmd;
+} __ABI_PACKED;
+
+/** @} */
+
+/*
+ *  4. Enumerations
+ */
+
+/*
+ *   4.1 CPU enumerations
+ *
+ * See <mach-t186/system-t186.h>
+ *
+ *   4.2 CPU Cluster enumerations
+ *
+ * See <mach-t186/system-t186.h>
+ *
+ *   4.3 System low power state enumerations
+ *
+ * See <mach-t186/system-t186.h>
+ */
+
+/*
+ *   4.4 Clock enumerations
+ *
+ * For clock enumerations, see <mach-t186/clk-t186.h>
+ */
+
+/*
+ *   4.5 Reset enumerations
+ *
+ * For reset enumerations, see <mach-t186/reset-t186.h>
+ */
+
+/*
+ *   4.6 Thermal sensor enumerations
+ *
+ * For thermal sensor enumerations, see <mach-t186/thermal-t186.h>
+ */
+
+/**
+ * @defgroup Error_Codes
+ * Negative values for mrq_response::err generally indicate some
+ * error. The ABI defines the following error codes. Negating these
+ * defines is an exercise left to the user.
+ * @{
+ */
+/** @brief No such file or directory */
+#define BPMP_ENOENT    2
+/** @brief No MRQ handler */
+#define BPMP_ENOHANDLER        3
+/** @brief I/O error */
+#define BPMP_EIO       5
+/** @brief Bad sub-MRQ command */
+#define BPMP_EBADCMD   6
+/** @brief Not enough memory */
+#define BPMP_ENOMEM    12
+/** @brief Permission denied */
+#define BPMP_EACCES    13
+/** @brief Bad address */
+#define BPMP_EFAULT    14
+/** @brief No such device */
+#define BPMP_ENODEV    19
+/** @brief Argument is a directory */
+#define BPMP_EISDIR    21
+/** @brief Invalid argument */
+#define BPMP_EINVAL    22
+/** @brief Timeout during operation */
+#define BPMP_ETIMEDOUT  23
+/** @brief Out of range */
+#define BPMP_ERANGE    34
+/** @} */
+/** @} */
+#endif
index 75e56c4..07ef4c0 100644 (file)
@@ -9,6 +9,9 @@
 #ifndef __TEGRA_MMC_H_
 #define __TEGRA_MMC_H_
 
+#include <common.h>
+#include <clk.h>
+#include <reset.h>
 #include <fdtdec.h>
 #include <asm/gpio.h>
 
@@ -134,7 +137,10 @@ struct mmc_host {
        int id;                 /* device id/number, 0-3 */
        int enabled;            /* 1 to enable, 0 to disable */
        int width;              /* Bus Width, 1, 4 or 8 */
-#ifndef CONFIG_TEGRA186
+#ifdef CONFIG_TEGRA186
+       struct reset_ctl reset_ctl;
+       struct clk clk;
+#else
        enum periph_id mmc_id;  /* Peripheral ID: PERIPH_ID_... */
 #endif
        struct gpio_desc cd_gpio;       /* Change Detect GPIO */
index 85ae3b7..1eaf406 100644 (file)
@@ -64,8 +64,14 @@ config TEGRA210
 
 config TEGRA186
        bool "Tegra186 family"
+       select CLK
        select DM_MAILBOX
+       select DM_RESET
+       select MISC
+       select TEGRA186_BPMP
+       select TEGRA186_CLOCK
        select TEGRA186_GPIO
+       select TEGRA186_RESET
        select TEGRA_ARMV8_COMMON
        select TEGRA_HSP
        select TEGRA_IVC
index d0bf5a6..b978fec 100644 (file)
@@ -25,6 +25,7 @@ obj-y += xusb-padctl-dummy.o
 endif
 
 obj-$(CONFIG_ARM64) += arm64-mmu.o
+obj-y += dt-setup.o
 obj-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
 obj-$(CONFIG_TEGRA_GPU) += gpu.o
 obj-$(CONFIG_TEGRA_IVC) += ivc.o
index a7583d4..1b9799f 100644 (file)
@@ -41,8 +41,3 @@ int board_mmc_init(bd_t *bd)
 
        return 0;
 }
-
-int ft_system_setup(void *blob, bd_t *bd)
-{
-       return 0;
-}
index 141d6e1..9158ace 100644 (file)
@@ -397,29 +397,3 @@ ulong board_get_usable_ram_top(ulong total_size)
 {
        return CONFIG_SYS_SDRAM_BASE + usable_ram_size_below_4g();
 }
-
-/*
- * This function is called right before the kernel is booted. "blob" is the
- * device tree that will be passed to the kernel.
- */
-int ft_system_setup(void *blob, bd_t *bd)
-{
-       const char *gpu_compats[] = {
-#if defined(CONFIG_TEGRA124)
-               "nvidia,gk20a",
-#endif
-#if defined(CONFIG_TEGRA210)
-               "nvidia,gm20b",
-#endif
-       };
-       int i, ret;
-
-       /* Enable GPU node if GPU setup has been performed */
-       for (i = 0; i < ARRAY_SIZE(gpu_compats); i++) {
-               ret = tegra_gpu_enable_node(blob, gpu_compats[i]);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
index 3f38969..1154f8b 100644 (file)
@@ -16,7 +16,7 @@
 #elif defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA114) || \
        defined(CONFIG_TEGRA124) || defined(CONFIG_TEGRA210)
 #define NVBL_PLLP_KHZ  408000
-#define CSITE_KHZ      204000
+#define CSITE_KHZ      136000
 #else
 #error "Unknown Tegra chip!"
 #endif
diff --git a/arch/arm/mach-tegra/dt-setup.c b/arch/arm/mach-tegra/dt-setup.c
new file mode 100644 (file)
index 0000000..f44d9cb
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010-2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch-tegra/gpu.h>
+
+/*
+ * This function is called right before the kernel is booted. "blob" is the
+ * device tree that will be passed to the kernel.
+ */
+int ft_system_setup(void *blob, bd_t *bd)
+{
+       const char *gpu_compats[] = {
+#if defined(CONFIG_TEGRA124)
+               "nvidia,gk20a",
+#endif
+#if defined(CONFIG_TEGRA210)
+               "nvidia,gm20b",
+#endif
+       };
+       int i, ret;
+
+       /* Enable GPU node if GPU setup has been performed */
+       for (i = 0; i < ARRAY_SIZE(gpu_compats); i++) {
+               ret = tegra_gpu_enable_node(blob, gpu_compats[i]);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
index 6856aac..2799293 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef        fec_h
 #define        fec_h
 
+#include <phy.h>
+
 /* Buffer descriptors used FEC.
 */
 typedef struct cpm_buf_desc {
@@ -341,10 +343,9 @@ int fecpin_setclear(struct eth_device *dev, int setclear);
 void __mii_init(void);
 uint mii_send(uint mii_cmd);
 int mii_discover_phy(struct eth_device *dev);
-int mcffec_miiphy_read(const char *devname, unsigned char addr,
-                      unsigned char reg, unsigned short *value);
-int mcffec_miiphy_write(const char *devname, unsigned char addr,
-                       unsigned char reg, unsigned short value);
+int mcffec_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
+int mcffec_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+                       u16 value);
 #endif
 
 #endif                         /* fec_h */
index 9216860..67f4953 100644 (file)
@@ -73,9 +73,9 @@ mac_fifo_t mac_fifo[NO_OF_FIFOS];
 #define MAX_WAIT 1000
 
 #if defined(CONFIG_CMD_MII)
-int  au1x00_miiphy_read(const char *devname, unsigned char addr,
-               unsigned char reg, unsigned short * value)
+int au1x00_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+       unsigned short value = 0;
        volatile u32 *mii_control_reg = (volatile u32*)(ETH0_BASE+MAC_MII_CNTRL);
        volatile u32 *mii_data_reg = (volatile u32*)(ETH0_BASE+MAC_MII_DATA);
        u32 mii_control;
@@ -102,12 +102,12 @@ int  au1x00_miiphy_read(const char *devname, unsigned char addr,
                        return -1;
                }
        }
-       *value = *mii_data_reg;
-       return 0;
+       value = *mii_data_reg;
+       return value;
 }
 
-int  au1x00_miiphy_write(const char *devname, unsigned char addr,
-               unsigned char reg, unsigned short value)
+int au1x00_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+                       u16 value)
 {
        volatile u32 *mii_control_reg = (volatile u32*)(ETH0_BASE+MAC_MII_CNTRL);
        volatile u32 *mii_data_reg = (volatile u32*)(ETH0_BASE+MAC_MII_DATA);
@@ -290,8 +290,17 @@ int au1x00_enet_initialize(bd_t *bis){
        eth_register(dev);
 
 #if defined(CONFIG_CMD_MII)
-       miiphy_register(dev->name,
-               au1x00_miiphy_read, au1x00_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = au1x00_miiphy_read;
+       mdiodev->write = au1x00_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 #endif
 
        return 1;
index a11ad1e..072eb76 100644 (file)
@@ -379,8 +379,17 @@ int fec_initialize(bd_t *bis)
 
 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
                && defined(CONFIG_BITBANGMII)
-               miiphy_register(dev->name,
-                               bb_miiphy_read, bb_miiphy_write);
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+               mdiodev->read = bb_miiphy_read;
+               mdiodev->write = bb_miiphy_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
 #endif
        }
 
index 51f1bee..7708f05 100644 (file)
@@ -441,8 +441,17 @@ int fec_initialize(bd_t *bis)
 
 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
                && defined(CONFIG_BITBANGMII)
-               miiphy_register(dev->name,
-                               bb_miiphy_read, bb_miiphy_write);
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+               mdiodev->read = bb_miiphy_read;
+               mdiodev->write = bb_miiphy_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
 #endif
        }
 
index f1ae358..0940906 100644 (file)
@@ -6,10 +6,12 @@
  */
 
 #include <common.h>
-#include <malloc.h>
+#include <command.h>
 #include <commproc.h>
+#include <malloc.h>
 #include <net.h>
-#include <command.h>
+
+#include <phy.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -47,10 +49,9 @@ DECLARE_GLOBAL_DATA_PTR;
 static int mii_discover_phy(struct eth_device *dev);
 #endif
 
-int fec8xx_miiphy_read(const char *devname, unsigned char addr,
-               unsigned char  reg, unsigned short *value);
-int fec8xx_miiphy_write(const char *devname, unsigned char  addr,
-               unsigned char  reg, unsigned short value);
+int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
+int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+                       u16 value);
 
 static struct ether_fcc_info_s
 {
@@ -170,8 +171,17 @@ int fec_initialize(bd_t *bis)
                eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-               miiphy_register(dev->name,
-                       fec8xx_miiphy_read, fec8xx_miiphy_write);
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+               mdiodev->read = fec8xx_miiphy_read;
+               mdiodev->write = fec8xx_miiphy_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
 #endif
        }
        return 1;
@@ -894,9 +904,9 @@ void mii_init (void)
  *       Otherwise they hang in mii_send() !!! Sorry!
  *****************************************************************************/
 
-int fec8xx_miiphy_read(const char *devname, unsigned char addr,
-               unsigned char  reg, unsigned short *value)
+int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+       unsigned short value = 0;
        short rdreg;    /* register working value */
 
 #ifdef MII_DEBUG
@@ -904,15 +914,15 @@ int fec8xx_miiphy_read(const char *devname, unsigned char addr,
 #endif
        rdreg = mii_send(mk_mii_read(addr, reg));
 
-       *value = rdreg;
+       value = rdreg;
 #ifdef MII_DEBUG
-       printf ("0x%04x\n", *value);
+       printf ("0x%04x\n", value);
 #endif
-       return 0;
+       return value;
 }
 
-int fec8xx_miiphy_write(const char *devname, unsigned char  addr,
-               unsigned char  reg, unsigned short value)
+int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+                       u16 value)
 {
 #ifdef MII_DEBUG
        printf ("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
index 10147de..f0fc098 100644 (file)
@@ -318,8 +318,7 @@ static int emac_miiphy_command(u8 addr, u8 reg, int cmd, u16 value)
        return 0;
 }
 
-int emac4xx_miiphy_read (const char *devname, unsigned char addr, unsigned char reg,
-                        unsigned short *value)
+int emac4xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
        unsigned long sta_reg;
        unsigned long emac_reg;
@@ -330,17 +329,15 @@ int emac4xx_miiphy_read (const char *devname, unsigned char addr, unsigned char
                return -1;
 
        sta_reg = in_be32((void *)EMAC0_STACR + emac_reg);
-       *value = sta_reg >> 16;
-
-       return 0;
+       return sta_reg >> 16;
 }
 
 /***********************************************************/
 /* write a phy reg and return the value with a rc          */
 /***********************************************************/
 
-int emac4xx_miiphy_write (const char *devname, unsigned char addr, unsigned char reg,
-                         unsigned short value)
+int emac4xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+                        u16 value)
 {
        return emac_miiphy_command(addr, reg, EMAC_STACR_WRITE, value);
 }
index 03d796c..81b4965 100644 (file)
@@ -172,8 +172,17 @@ int last_stage_init(void)
 
        print_fpga_info();
 
-       miiphy_register(CONFIG_SYS_GBIT_MII_BUSNAME,
-               bb_miiphy_read, bb_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, CONFIG_SYS_GBIT_MII_BUSNAME, MDIO_NAME_LEN);
+       mdiodev->read = bb_miiphy_read;
+       mdiodev->write = bb_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 
        for (k = 0; k < 32; ++k)
                configure_gbit_phy(k);
index 7484624..7db0e29 100644 (file)
@@ -405,8 +405,17 @@ int last_stage_init(void)
        }
 
        if (!legacy && (feature_carrier_speed == CARRIER_SPEED_1G)) {
-               miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read,
-                               bb_miiphy_write);
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
+               mdiodev->read = bb_miiphy_read;
+               mdiodev->write = bb_miiphy_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
                for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
                        if ((mux_ch == 1) && !ch0_rgmii2_present)
                                continue;
@@ -437,8 +446,18 @@ int last_stage_init(void)
                print_fpga_info(k, false);
                osd_probe(k);
                if (feature_carrier_speed == CARRIER_SPEED_1G) {
-                       miiphy_register(bb_miiphy_buses[k].name,
-                                       bb_miiphy_read, bb_miiphy_write);
+                       int retval;
+                       struct mii_dev *mdiodev = mdio_alloc();
+                       if (!mdiodev)
+                               return -ENOMEM;
+                       strncpy(mdiodev->name, bb_miiphy_buses[k].name,
+                               MDIO_NAME_LEN);
+                       mdiodev->read = bb_miiphy_read;
+                       mdiodev->write = bb_miiphy_write;
+
+                       retval = mdio_register(mdiodev);
+                       if (retval < 0)
+                               return retval;
                        setup_88e1518(bb_miiphy_buses[k].name, 0);
                }
        }
index 3a075c4..848cdde 100644 (file)
@@ -246,8 +246,17 @@ int last_stage_init(void)
        /* setup Gbit PHYs */
        puts("TRANS: ");
        puts(str_phys);
-       miiphy_register(CONFIG_SYS_GBIT_MII_BUSNAME,
-               bb_miiphy_read, bb_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, CONFIG_SYS_GBIT_MII_BUSNAME, MDIO_NAME_LEN);
+       mdiodev->read = bb_miiphy_read;
+       mdiodev->write = bb_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 
        for (k = 0; k < 32; ++k) {
                configure_gbit_phy(CONFIG_SYS_GBIT_MII_BUSNAME, k);
@@ -255,8 +264,16 @@ int last_stage_init(void)
                putc(slash[k % 8]);
        }
 
-       miiphy_register(CONFIG_SYS_GBIT_MII1_BUSNAME,
-               bb_miiphy_read, bb_miiphy_write);
+       mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, CONFIG_SYS_GBIT_MII1_BUSNAME, MDIO_NAME_LEN);
+       mdiodev->read = bb_miiphy_read;
+       mdiodev->write = bb_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 
        for (k = 0; k < 32; ++k) {
                configure_gbit_phy(CONFIG_SYS_GBIT_MII1_BUSNAME, k);
index 880b638..f55893f 100644 (file)
@@ -162,8 +162,17 @@ int last_stage_init(void)
        }
 
        if (hw_type_cat) {
-               miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read,
-                               bb_miiphy_write);
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
+               mdiodev->read = bb_miiphy_read;
+               mdiodev->write = bb_miiphy_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
                for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
                        if ((mux_ch == 1) && !ch0_rgmii2_present)
                                continue;
@@ -199,8 +208,18 @@ int last_stage_init(void)
                osd_probe(k + 4);
 #endif
                if (hw_type_cat) {
-                       miiphy_register(bb_miiphy_buses[k].name,
-                                       bb_miiphy_read, bb_miiphy_write);
+                       int retval;
+                       struct mii_dev *mdiodev = mdio_alloc();
+                       if (!mdiodev)
+                               return -ENOMEM;
+                       strncpy(mdiodev->name, bb_miiphy_buses[k].name,
+                               MDIO_NAME_LEN);
+                       mdiodev->read = bb_miiphy_read;
+                       mdiodev->write = bb_miiphy_write;
+
+                       retval = mdio_register(mdiodev);
+                       if (retval < 0)
+                               return retval;
                        setup_88e1514(bb_miiphy_buses[k].name, 0);
                }
        }
index 121977d..b8dde5f 100644 (file)
@@ -179,8 +179,17 @@ int last_stage_init(void)
        }
 
        if (hw_type_cat) {
-               miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read,
-                               bb_miiphy_write);
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
+               mdiodev->read = bb_miiphy_read;
+               mdiodev->write = bb_miiphy_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
                for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
                        if ((mux_ch == 1) && !ch0_sgmii2_present)
                                continue;
@@ -252,8 +261,18 @@ int last_stage_init(void)
                dp501_probe(k, false);
 #endif
                if (hw_type_cat) {
-                       miiphy_register(bb_miiphy_buses[k].name,
-                                       bb_miiphy_read, bb_miiphy_write);
+                       int retval;
+                       struct mii_dev *mdiodev = mdio_alloc();
+                       if (!mdiodev)
+                               return -ENOMEM;
+                       strncpy(mdiodev->name, bb_miiphy_buses[k].name,
+                               MDIO_NAME_LEN);
+                       mdiodev->read = bb_miiphy_read;
+                       mdiodev->write = bb_miiphy_write;
+
+                       retval = mdio_register(mdiodev);
+                       if (retval < 0)
+                               return retval;
                        setup_88e1514(bb_miiphy_buses[k].name, 0);
                }
        }
index 4ba8ebc..529ed9d 100644 (file)
@@ -5,3 +5,51 @@
  */
 
 #include <common.h>
+#include <i2c.h>
+#include "../p2571/max77620_init.h"
+
+int tegra_board_init(void)
+{
+       struct udevice *dev;
+       uchar val;
+       int ret;
+
+       /* Turn on MAX77620 LDO3 to 3.3V for SD card power */
+       debug("%s: Set LDO3 for VDDIO_SDMMC_AP power to 3.3V\n", __func__);
+       ret = i2c_get_chip_for_busnum(0, MAX77620_I2C_ADDR_7BIT, 1, &dev);
+       if (ret) {
+               printf("%s: Cannot find MAX77620 I2C chip\n", __func__);
+               return ret;
+       }
+       /* 0xF2 for 3.3v, enabled: bit7:6 = 11 = enable, bit5:0 = voltage */
+       val = 0xF2;
+       ret = dm_i2c_write(dev, MAX77620_CNFG1_L3_REG, &val, 1);
+       if (ret) {
+               printf("i2c_write 0 0x3c 0x27 failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+int tegra_pcie_board_init(void)
+{
+       struct udevice *dev;
+       uchar val;
+       int ret;
+
+       /* Turn on MAX77620 LDO7 to 1.05V for PEX power */
+       debug("%s: Set LDO7 for PEX power to 1.05V\n", __func__);
+       ret = i2c_get_chip_for_busnum(0, MAX77620_I2C_ADDR_7BIT, 1, &dev);
+       if (ret) {
+               printf("%s: Cannot find MAX77620 I2C chip\n", __func__);
+               return -1;
+       }
+       /* 0xC5 for 1.05v, enabled: bit7:6 = 11 = enable, bit5:0 = voltage */
+       val = 0xC5;
+       ret = dm_i2c_write(dev, MAX77620_CNFG1_L7_REG, &val, 1);
+       if (ret)
+               printf("i2c_write 0 0x3c 0x31 failed: %d\n", ret);
+
+       return 0;
+}
index 960fea7..1770ec2 100644 (file)
@@ -32,7 +32,18 @@ void pmic_enable_cpu_vdd(void)
 {
        debug("%s entry\n", __func__);
 
-       /* Don't need to set up VDD_CORE - already done - by OTP */
+#ifdef AS3722_SD1VOLTAGE_DATA
+       /* Set up VDD_CORE, for boards where OTP is incorrect*/
+       debug("%s: Setting VDD_CORE via AS3722 reg 1\n", __func__);
+       /* Configure VDD_CORE via the AS3722 PMIC on the PWR I2C bus */
+       tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2);
+       tegra_i2c_ll_write_data(AS3722_SD1VOLTAGE_DATA, I2C_SEND_2_BYTES);
+       /*
+        * Don't write SDCONTROL - it's already 0x7F, i.e. all SDs enabled.
+        * tegra_i2c_ll_write_data(AS3722_SD1CONTROL_DATA, I2C_SEND_2_BYTES);
+        */
+       udelay(10 * 1000);
+#endif
 
        debug("%s: Setting VDD_CPU to 1.0V via AS3722 reg 0/4D\n", __func__);
        /*
index 992b11f..c6b1247 100644 (file)
 #endif
 #define AS3722_SD0CONTROL_DATA (0x0100 | AS3722_SDCONTROL_REG)
 
-#define AS3722_SD1VOLTAGE_DATA (0x3200 | AS3722_SD1VOLTAGE_REG)
+#ifdef CONFIG_TARGET_JETSON_TK1
+#define AS3722_SD1VOLTAGE_DATA (0x2800 | AS3722_SD1VOLTAGE_REG)
 #define AS3722_SD1CONTROL_DATA (0x0200 | AS3722_SDCONTROL_REG)
+#endif
 
 #define AS3722_SD6CONTROL_DATA (0x4000 | AS3722_SDCONTROL_REG)
 #define AS3722_SD6VOLTAGE_DATA (0x2800 | AS3722_SD6VOLTAGE_REG)
index 7e41957..08aa854 100644 (file)
@@ -65,79 +65,6 @@ void miiphy_init(void)
        current_mii = NULL;
 }
 
-static int legacy_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
-       unsigned short val;
-       int ret;
-       struct legacy_mii_dev *ldev = bus->priv;
-
-       ret = ldev->read(bus->name, addr, reg, &val);
-
-       return ret ? -1 : (int)val;
-}
-
-static int legacy_miiphy_write(struct mii_dev *bus, int addr, int devad,
-                               int reg, u16 val)
-{
-       struct legacy_mii_dev *ldev = bus->priv;
-
-       return ldev->write(bus->name, addr, reg, val);
-}
-
-/*****************************************************************************
- *
- * Register read and write MII access routines for the device <name>.
- * This API is now deprecated. Please use mdio_alloc and mdio_register, instead.
- */
-void miiphy_register(const char *name,
-                     int (*read)(const char *devname, unsigned char addr,
-                                  unsigned char reg, unsigned short *value),
-                     int (*write)(const char *devname, unsigned char addr,
-                                   unsigned char reg, unsigned short value))
-{
-       struct mii_dev *new_dev;
-       struct legacy_mii_dev *ldev;
-
-       BUG_ON(strlen(name) >= MDIO_NAME_LEN);
-
-       /* check if we have unique name */
-       new_dev = miiphy_get_dev_by_name(name);
-       if (new_dev) {
-               printf("miiphy_register: non unique device name '%s'\n", name);
-               return;
-       }
-
-       /* allocate memory */
-       new_dev = mdio_alloc();
-       ldev = malloc(sizeof(*ldev));
-
-       if (new_dev == NULL || ldev == NULL) {
-               printf("miiphy_register: cannot allocate memory for '%s'\n",
-                       name);
-               free(ldev);
-               mdio_free(new_dev);
-               return;
-       }
-
-       /* initalize mii_dev struct fields */
-       new_dev->read = legacy_miiphy_read;
-       new_dev->write = legacy_miiphy_write;
-       strncpy(new_dev->name, name, MDIO_NAME_LEN);
-       new_dev->name[MDIO_NAME_LEN - 1] = 0;
-       ldev->read = read;
-       ldev->write = write;
-       new_dev->priv = ldev;
-
-       debug("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n",
-              new_dev->name, ldev->read, ldev->write);
-
-       /* add it to the list */
-       list_add_tail(&new_dev->link, &mii_devs);
-
-       if (!current_mii)
-               current_mii = new_dev;
-}
-
 struct mii_dev *mdio_alloc(void)
 {
        struct mii_dev *bus;
index 14923c0..5bc81cc 100644 (file)
@@ -6,5 +6,7 @@ CONFIG_TARGET_OPENRISC_GENERIC=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
+CONFIG_NETDEVICES=y
+CONFIG_ETHOC=y
 CONFIG_SYS_NS16550=y
 # CONFIG_AUTOBOOT is not set
index 1fe25f5..5ce369c 100644 (file)
@@ -26,6 +26,12 @@ CONFIG_CMD_EXT4=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_RTL8169=y
+CONFIG_E1000=y
+CONFIG_PCI_TEGRA=y
+CONFIG_TEGRA186_BPMP_I2C=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_TEGRA186_POWER_DOMAIN=y
index 552fb6c..27393f3 100644 (file)
@@ -26,6 +26,12 @@ CONFIG_CMD_EXT4=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_RTL8169=y
+CONFIG_E1000=y
+CONFIG_PCI_TEGRA=y
+CONFIG_TEGRA186_BPMP_I2C=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_TEGRA186_POWER_DOMAIN=y
index 3da63c0..8f3b96a 100644 (file)
@@ -20,6 +20,7 @@ config SPL_CLK
          setting up clocks within SPL, and allows the same drivers to be
          used as U-Boot proper.
 
+source "drivers/clk/tegra/Kconfig"
 source "drivers/clk/uniphier/Kconfig"
 source "drivers/clk/exynos/Kconfig"
 source "drivers/clk/at91/Kconfig"
index 65de008..778d748 100644 (file)
@@ -10,6 +10,8 @@ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
 obj-$(CONFIG_SANDBOX) += clk_sandbox.o
 obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o
 obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
+
+obj-y += tegra/
 obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
 obj-$(CONFIG_CLK_EXYNOS) += exynos/
 obj-$(CONFIG_CLK_AT91) += at91/
diff --git a/drivers/clk/tegra/Kconfig b/drivers/clk/tegra/Kconfig
new file mode 100644 (file)
index 0000000..659fe02
--- /dev/null
@@ -0,0 +1,6 @@
+config TEGRA186_CLOCK
+       bool "Enable Tegra186 BPMP-based clock driver"
+       depends on TEGRA186_BPMP
+       help
+         Enable support for manipulating Tegra's on-SoC clocks via IPC
+         requests to the BPMP (Boot and Power Management Processor).
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
new file mode 100644 (file)
index 0000000..f32998c
--- /dev/null
@@ -0,0 +1,5 @@
+# Copyright (c) 2016, NVIDIA CORPORATION.
+#
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_TEGRA186_CLOCK) += tegra186-clk.o
diff --git a/drivers/clk/tegra/tegra186-clk.c b/drivers/clk/tegra/tegra186-clk.c
new file mode 100644 (file)
index 0000000..075cb46
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <misc.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+
+static ulong tegra186_clk_get_rate(struct clk *clk)
+{
+       struct mrq_clk_request req;
+       struct mrq_clk_response resp;
+       int ret;
+
+       debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
+             clk->id);
+
+       req.cmd_and_id = (CMD_CLK_GET_RATE << 24) | clk->id;
+
+       ret = misc_call(clk->dev->parent, MRQ_CLK, &req, sizeof(req), &resp,
+                       sizeof(resp));
+       if (ret < 0)
+               return ret;
+
+       return resp.clk_get_rate.rate;
+}
+
+static ulong tegra186_clk_set_rate(struct clk *clk, ulong rate)
+{
+       struct mrq_clk_request req;
+       struct mrq_clk_response resp;
+       int ret;
+
+       debug("%s(clk=%p, rate=%lu) (dev=%p, id=%lu)\n", __func__, clk, rate,
+             clk->dev, clk->id);
+
+       req.cmd_and_id = (CMD_CLK_SET_RATE << 24) | clk->id;
+       req.clk_set_rate.rate = rate;
+
+       ret = misc_call(clk->dev->parent, MRQ_CLK, &req, sizeof(req), &resp,
+                       sizeof(resp));
+       if (ret < 0)
+               return ret;
+
+       return resp.clk_set_rate.rate;
+}
+
+static int tegra186_clk_en_dis(struct clk *clk,
+                              enum mrq_reset_commands cmd)
+{
+       struct mrq_clk_request req;
+       struct mrq_clk_response resp;
+       int ret;
+
+       req.cmd_and_id = (cmd << 24) | clk->id;
+
+       ret = misc_call(clk->dev->parent, MRQ_CLK, &req, sizeof(req), &resp,
+                       sizeof(resp));
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int tegra186_clk_enable(struct clk *clk)
+{
+       debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
+             clk->id);
+
+       return tegra186_clk_en_dis(clk, CMD_CLK_ENABLE);
+}
+
+static int tegra186_clk_disable(struct clk *clk)
+{
+       debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
+             clk->id);
+
+       return tegra186_clk_en_dis(clk, CMD_CLK_DISABLE);
+}
+
+static struct clk_ops tegra186_clk_ops = {
+       .get_rate = tegra186_clk_get_rate,
+       .set_rate = tegra186_clk_set_rate,
+       .enable = tegra186_clk_enable,
+       .disable = tegra186_clk_disable,
+};
+
+static int tegra186_clk_probe(struct udevice *dev)
+{
+       debug("%s(dev=%p)\n", __func__, dev);
+
+       return 0;
+}
+
+U_BOOT_DRIVER(tegra186_clk) = {
+       .name           = "tegra186_clk",
+       .id             = UCLASS_CLK,
+       .probe          = tegra186_clk_probe,
+       .ops = &tegra186_clk_ops,
+};
index 8575a23..1537b67 100644 (file)
@@ -171,6 +171,16 @@ config SYS_I2C_MVTWSI
          Support for Marvell I2C controllers as used on the orion5x and
          kirkwood SoC families.
 
+config TEGRA186_BPMP_I2C
+       bool "Enable Tegra186 BPMP-based I2C driver"
+       depends on TEGRA186_BPMP
+       help
+         Support for Tegra I2C controllers managed by the BPMP (Boot and
+         Power Management Processor). On Tegra186, some I2C controllers are
+         directly controlled by the main CPU, whereas others are controlled
+         by the BPMP, and can only be accessed by the main CPU via IPC
+         requests to the BPMP. This driver covers the latter case.
+
 source "drivers/i2c/muxes/Kconfig"
 
 endmenu
index c5362a5..2987081 100644 (file)
@@ -42,5 +42,6 @@ obj-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o
 obj-$(CONFIG_SYS_I2C_UNIPHIER) += i2c-uniphier.o
 obj-$(CONFIG_SYS_I2C_UNIPHIER_F) += i2c-uniphier-f.o
 obj-$(CONFIG_SYS_I2C_ZYNQ) += zynq_i2c.o
+obj-$(CONFIG_TEGRA186_BPMP_I2C) += tegra186_bpmp_i2c.o
 
 obj-$(CONFIG_I2C_MUX) += muxes/
diff --git a/drivers/i2c/tegra186_bpmp_i2c.c b/drivers/i2c/tegra186_bpmp_i2c.c
new file mode 100644 (file)
index 0000000..88e8413
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <misc.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct tegra186_bpmp_i2c {
+       uint32_t bpmp_bus_id;
+};
+
+static inline void serialize_u16(uint8_t **p, uint16_t val)
+{
+       (*p)[0] = val & 0xff;
+       (*p)[1] = val >> 8;
+       (*p) += 2;
+}
+
+/* These just happen to have the same values as I2C_M_* and SERIALI2C_* */
+#define SUPPORTED_FLAGS \
+       (I2C_M_TEN | \
+       I2C_M_RD | \
+       I2C_M_STOP | \
+       I2C_M_NOSTART | \
+       I2C_M_REV_DIR_ADDR | \
+       I2C_M_IGNORE_NAK | \
+       I2C_M_NO_RD_ACK | \
+       I2C_M_RECV_LEN)
+
+static int tegra186_bpmp_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
+                                 int nmsgs)
+{
+       struct tegra186_bpmp_i2c *priv = dev_get_priv(dev);
+       struct mrq_i2c_request req;
+       struct mrq_i2c_response resp;
+       uint8_t *p;
+       int left, i, ret;
+
+       req.cmd = CMD_I2C_XFER;
+       req.xfer.bus_id = priv->bpmp_bus_id;
+       p = &req.xfer.data_buf[0];
+       left = ARRAY_SIZE(req.xfer.data_buf);
+       for (i = 0; i < nmsgs; i++) {
+               int len = 6;
+               if (!(msg[i].flags & I2C_M_RD))
+                       len += msg[i].len;
+               if ((len >= BIT(16)) || (len > left))
+                       return -ENOSPC;
+
+               if (msg[i].flags & ~SUPPORTED_FLAGS)
+                       return -EINVAL;
+
+               serialize_u16(&p, msg[i].addr);
+               serialize_u16(&p, msg[i].flags);
+               serialize_u16(&p, msg[i].len);
+               if (!(msg[i].flags & I2C_M_RD)) {
+                       memcpy(p, msg[i].buf, msg[i].len);
+                       p += msg[i].len;
+               }
+       }
+       req.xfer.data_size = p - &req.xfer.data_buf[0];
+
+       ret = misc_call(dev->parent, MRQ_I2C, &req, sizeof(req), &resp,
+                       sizeof(resp));
+       if (ret < 0)
+               return ret;
+
+       p = &resp.xfer.data_buf[0];
+       left = resp.xfer.data_size;
+       if (left > ARRAY_SIZE(resp.xfer.data_buf))
+               return -EINVAL;
+       for (i = 0; i < nmsgs; i++) {
+               if (msg[i].flags & I2C_M_RD) {
+                       memcpy(msg[i].buf, p, msg[i].len);
+                       p += msg[i].len;
+               }
+       }
+
+       return 0;
+}
+
+static int tegra186_bpmp_i2c_probe(struct udevice *dev)
+{
+       struct tegra186_bpmp_i2c *priv = dev_get_priv(dev);
+       int ret;
+       struct fdtdec_phandle_args args;
+
+       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
+                                            "nvidia,bpmp", NULL, 0, 0, &args);
+       if (ret < 0) {
+               debug("%s: fdtdec_parse_phandle_with_args() failed: %d\n",
+                     __func__, ret);
+               return ret;
+       }
+
+       priv->bpmp_bus_id = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
+                                           "nvidia,bpmp-bus-id", U32_MAX);
+       if (priv->bpmp_bus_id == U32_MAX) {
+               debug("%s: could not parse nvidia,bpmp-bus-id\n", __func__);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static const struct dm_i2c_ops tegra186_bpmp_i2c_ops = {
+       .xfer = tegra186_bpmp_i2c_xfer,
+};
+
+static const struct udevice_id tegra186_bpmp_i2c_ids[] = {
+       { .compatible = "nvidia,tegra186-bpmp-i2c" },
+       { }
+};
+
+U_BOOT_DRIVER(i2c_gpio) = {
+       .name   = "tegra186_bpmp_i2c",
+       .id     = UCLASS_I2C,
+       .of_match = tegra186_bpmp_i2c_ids,
+       .probe  = tegra186_bpmp_i2c_probe,
+       .priv_auto_alloc_size = sizeof(struct tegra186_bpmp_i2c),
+       .ops    = &tegra186_bpmp_i2c_ops,
+};
index 2fa07f9..31ba263 100644 (file)
 #include <fdtdec.h>
 #include <i2c.h>
 #include <asm/io.h>
+#ifdef CONFIG_TEGRA186
+#include <clk.h>
+#include <reset.h>
+#else
 #include <asm/arch/clock.h>
 #include <asm/arch/funcmux.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch-tegra/clk_rst.h>
+#endif
+#include <asm/arch/gpio.h>
 #include <asm/arch-tegra/tegra_i2c.h>
 
+/*
+ * FIXME: TODO: This driver contains a number of ifdef CONFIG_TEGRA186 that
+ * should not be present. These are needed because newer Tegra SoCs support
+ * only the standard clock/reset APIs, whereas older Tegra SoCs support only
+ * a custom Tegra-specific API. ASAP the older Tegra SoCs' code should be
+ * fixed to implement the standard APIs, and all drivers converted to solely
+ * use the new standard APIs, with no ifdefs.
+ */
+
 DECLARE_GLOBAL_DATA_PTR;
 
 enum i2c_type {
@@ -30,7 +44,12 @@ enum i2c_type {
 /* Information about i2c controller */
 struct i2c_bus {
        int                     id;
+#ifdef CONFIG_TEGRA186
+       struct reset_ctl        reset_ctl;
+       struct clk              clk;
+#else
        enum periph_id          periph_id;
+#endif
        int                     speed;
        int                     pinmux_config;
        struct i2c_control      *control;
@@ -62,12 +81,41 @@ static void set_packet_mode(struct i2c_bus *i2c_bus)
 static void i2c_reset_controller(struct i2c_bus *i2c_bus)
 {
        /* Reset I2C controller. */
+#ifdef CONFIG_TEGRA186
+       reset_assert(&i2c_bus->reset_ctl);
+       udelay(1);
+       reset_deassert(&i2c_bus->reset_ctl);
+       udelay(1);
+#else
        reset_periph(i2c_bus->periph_id, 1);
+#endif
 
        /* re-program config register to packet mode */
        set_packet_mode(i2c_bus);
 }
 
+#ifdef CONFIG_TEGRA186
+static int i2c_init_clock(struct i2c_bus *i2c_bus, unsigned rate)
+{
+       int ret;
+
+       ret = reset_assert(&i2c_bus->reset_ctl);
+       if (ret)
+               return ret;
+       ret = clk_enable(&i2c_bus->clk);
+       if (ret)
+               return ret;
+       ret = clk_set_rate(&i2c_bus->clk, rate);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+       ret = reset_deassert(&i2c_bus->reset_ctl);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+#endif
+
 static void i2c_init_controller(struct i2c_bus *i2c_bus)
 {
        if (!i2c_bus->speed)
@@ -78,8 +126,12 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
         * here, in section 23.3.1, but in fact we seem to need a factor of
         * 16 to get the right frequency.
         */
+#ifdef CONFIG_TEGRA186
+       i2c_init_clock(i2c_bus, i2c_bus->speed * 2 * 8);
+#else
        clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH,
                i2c_bus->speed * 2 * 8);
+#endif
 
        if (i2c_bus->type == TYPE_114) {
                /*
@@ -94,12 +146,17 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
                 * is running, we hang, and we need it for the new calc.
                 */
                int clk_div_stdfst_mode = readl(&i2c_bus->regs->clk_div) >> 16;
+               unsigned rate = CLK_MULT_STD_FAST_MODE *
+                               (clk_div_stdfst_mode + 1) * i2c_bus->speed * 2;
                debug("%s: CLK_DIV_STD_FAST_MODE setting = %d\n", __func__,
                        clk_div_stdfst_mode);
 
+#ifdef CONFIG_TEGRA186
+               i2c_init_clock(i2c_bus, rate);
+#else
                clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH,
-                       CLK_MULT_STD_FAST_MODE * (clk_div_stdfst_mode + 1) *
-                       i2c_bus->speed * 2);
+                                      rate);
+#endif
        }
 
        /* Reset I2C controller. */
@@ -112,7 +169,9 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
                setbits_le32(&dvc->ctrl3, DVC_CTRL_REG3_I2C_HW_SW_PROG_MASK);
        }
 
+#ifndef CONFIG_TEGRA186
        funcmux_select(i2c_bus->periph_id, i2c_bus->pinmux_config);
+#endif
 }
 
 static void send_packet_headers(
@@ -333,8 +392,12 @@ static int tegra_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
 static int tegra_i2c_probe(struct udevice *dev)
 {
        struct i2c_bus *i2c_bus = dev_get_priv(dev);
+#ifdef CONFIG_TEGRA186
+       int ret;
+#else
        const void *blob = gd->fdt_blob;
        int node = dev->of_offset;
+#endif
        bool is_dvc;
 
        i2c_bus->id = dev->seq;
@@ -345,6 +408,18 @@ static int tegra_i2c_probe(struct udevice *dev)
         * We don't have a binding for pinmux yet. Leave it out for now. So
         * far no one needs anything other than the default.
         */
+#ifdef CONFIG_TEGRA186
+       ret = reset_get_by_name(dev, "i2c", &i2c_bus->reset_ctl);
+       if (ret) {
+               error("reset_get_by_name() failed: %d\n", ret);
+               return ret;
+       }
+       ret = clk_get_by_name(dev, "i2c", &i2c_bus->clk);
+       if (ret) {
+               error("clk_get_by_name() failed: %d\n", ret);
+               return ret;
+       }
+#else
        i2c_bus->pinmux_config = FUNCMUX_DEFAULT;
        i2c_bus->periph_id = clock_decode_periph_id(blob, node);
 
@@ -359,6 +434,7 @@ static int tegra_i2c_probe(struct udevice *dev)
         */
        if (i2c_bus->periph_id == -1)
                return -EINVAL;
+#endif
 
        is_dvc = dev_get_driver_data(dev) == TYPE_DVC;
        if (is_dvc) {
@@ -370,7 +446,12 @@ static int tegra_i2c_probe(struct udevice *dev)
        i2c_init_controller(i2c_bus);
        debug("%s: controller bus %d at %p, periph_id %d, speed %d: ",
              is_dvc ? "dvc" : "i2c", dev->seq, i2c_bus->regs,
-             i2c_bus->periph_id, i2c_bus->speed);
+#ifndef CONFIG_TEGRA186
+             i2c_bus->periph_id,
+#else
+             -1,
+#endif
+             i2c_bus->speed);
 
        return 0;
 }
index 80c1558..4af1cbf 100644 (file)
@@ -121,6 +121,18 @@ config PCA9551_I2C_ADDR
        help
          The I2C address of the PCA9551 LED controller.
 
+config TEGRA186_BPMP
+       bool "Enable support for the Tegra186 BPMP driver"
+       depends on TEGRA186
+       help
+         The Tegra BPMP (Boot and Power Management Processor) is a separate
+         auxiliary CPU embedded into Tegra to perform power management work,
+         and controls related features such as clocks, resets, power domains,
+         PMIC I2C bus, etc. This driver provides the core low-level
+         communication path by which feature-specific drivers (such as clock)
+         can make requests to the BPMP. This driver is similar to an MFD
+         driver in the Linux kernel.
+
 config WINBOND_W83627
        bool "Enable Winbond Super I/O driver"
        help
index af541c6..dac9d10 100644 (file)
@@ -42,6 +42,7 @@ obj-$(CONFIG_SANDBOX) += spltest_sandbox.o
 endif
 endif
 obj-$(CONFIG_SANDBOX) += syscon_sandbox.o
+obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o
 obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
 obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
 obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o
diff --git a/drivers/misc/tegra186_bpmp.c b/drivers/misc/tegra186_bpmp.c
new file mode 100644 (file)
index 0000000..f4ddbea
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+#include <mailbox.h>
+#include <misc.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+#include <asm/arch-tegra/ivc.h>
+
+#define BPMP_IVC_FRAME_COUNT 1
+#define BPMP_IVC_FRAME_SIZE 128
+
+#define BPMP_FLAG_DO_ACK       BIT(0)
+#define BPMP_FLAG_RING_DOORBELL        BIT(1)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct tegra186_bpmp {
+       struct mbox_chan mbox;
+       struct tegra_ivc ivc;
+};
+
+static int tegra186_bpmp_call(struct udevice *dev, int mrq, void *tx_msg,
+                             int tx_size, void *rx_msg, int rx_size)
+{
+       struct tegra186_bpmp *priv = dev_get_priv(dev);
+       int ret, err;
+       void *ivc_frame;
+       struct mrq_request *req;
+       struct mrq_response *resp;
+       ulong start_time;
+
+       debug("%s(dev=%p, mrq=%u, tx_msg=%p, tx_size=%d, rx_msg=%p, rx_size=%d) (priv=%p)\n",
+             __func__, dev, mrq, tx_msg, tx_size, rx_msg, rx_size, priv);
+
+       if ((tx_size > BPMP_IVC_FRAME_SIZE) || (rx_size > BPMP_IVC_FRAME_SIZE))
+               return -EINVAL;
+
+       ret = tegra_ivc_write_get_next_frame(&priv->ivc, &ivc_frame);
+       if (ret) {
+               error("tegra_ivc_write_get_next_frame() failed: %d\n", ret);
+               return ret;
+       }
+
+       req = ivc_frame;
+       req->mrq = mrq;
+       req->flags = BPMP_FLAG_DO_ACK | BPMP_FLAG_RING_DOORBELL;
+       memcpy(req + 1, tx_msg, tx_size);
+
+       ret = tegra_ivc_write_advance(&priv->ivc);
+       if (ret) {
+               error("tegra_ivc_write_advance() failed: %d\n", ret);
+               return ret;
+       }
+
+       start_time = timer_get_us();
+       for (;;) {
+               ret = tegra_ivc_channel_notified(&priv->ivc);
+               if (ret) {
+                       error("tegra_ivc_channel_notified() failed: %d\n", ret);
+                       return ret;
+               }
+
+               ret = tegra_ivc_read_get_next_frame(&priv->ivc, &ivc_frame);
+               if (!ret)
+                       break;
+
+               /* Timeout 20ms; roughly 10x current max observed duration */
+               if ((timer_get_us() - start_time) > 20 * 1000) {
+                       error("tegra_ivc_read_get_next_frame() timed out (%d)\n",
+                             ret);
+                       return -ETIMEDOUT;
+               }
+       }
+
+       resp = ivc_frame;
+       err = resp->err;
+       if (!err && rx_msg && rx_size)
+               memcpy(rx_msg, resp + 1, rx_size);
+
+       ret = tegra_ivc_read_advance(&priv->ivc);
+       if (ret) {
+               error("tegra_ivc_write_advance() failed: %d\n", ret);
+               return ret;
+       }
+
+       if (err) {
+               error("BPMP responded with error %d\n", err);
+               /* err isn't a U-Boot error code, so don't that */
+               return -EIO;
+       }
+
+       return rx_size;
+}
+
+/**
+ * The BPMP exposes multiple different services. We create a sub-device for
+ * each separate type of service, since each device must be of the appropriate
+ * UCLASS.
+ */
+static int tegra186_bpmp_bind(struct udevice *dev)
+{
+       int ret;
+       struct udevice *child;
+
+       debug("%s(dev=%p)\n", __func__, dev);
+
+       ret = device_bind_driver_to_node(dev, "tegra186_clk", "tegra186_clk",
+                                        dev->of_offset, &child);
+       if (ret)
+               return ret;
+
+       ret = device_bind_driver_to_node(dev, "tegra186_reset",
+                                        "tegra186_reset", dev->of_offset,
+                                        &child);
+       if (ret)
+               return ret;
+
+       ret = device_bind_driver_to_node(dev, "tegra186_power_domain",
+                                        "tegra186_power_domain",
+                                        dev->of_offset, &child);
+       if (ret)
+               return ret;
+
+       ret = dm_scan_fdt_dev(dev);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static ulong tegra186_bpmp_get_shmem(struct udevice *dev, int index)
+{
+       int ret;
+       struct fdtdec_phandle_args args;
+       fdt_addr_t reg;
+
+       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
+                                             "shmem", NULL, 0, index, &args);
+       if (ret < 0) {
+               error("fdtdec_parse_phandle_with_args() failed: %d\n", ret);
+               return ret;
+       }
+
+       reg = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, args.node,
+                                                "reg", 0, NULL, true);
+       if (reg == FDT_ADDR_T_NONE) {
+               error("fdtdec_get_addr_size_auto_noparent() failed\n");
+               return -ENODEV;
+       }
+
+       return reg;
+}
+
+static void tegra186_bpmp_ivc_notify(struct tegra_ivc *ivc)
+{
+       struct tegra186_bpmp *priv =
+               container_of(ivc, struct tegra186_bpmp, ivc);
+       int ret;
+
+       ret = mbox_send(&priv->mbox, NULL);
+       if (ret)
+               error("mbox_send() failed: %d\n", ret);
+}
+
+static int tegra186_bpmp_probe(struct udevice *dev)
+{
+       struct tegra186_bpmp *priv = dev_get_priv(dev);
+       int ret;
+       ulong tx_base, rx_base, start_time;
+
+       debug("%s(dev=%p) (priv=%p)\n", __func__, dev, priv);
+
+       ret = mbox_get_by_index(dev, 0, &priv->mbox);
+       if (ret) {
+               error("mbox_get_by_index() failed: %d\n", ret);
+               return ret;
+       }
+
+       tx_base = tegra186_bpmp_get_shmem(dev, 0);
+       if (IS_ERR_VALUE(tx_base)) {
+               error("tegra186_bpmp_get_shmem failed for tx_base\n");
+               return tx_base;
+       }
+       rx_base = tegra186_bpmp_get_shmem(dev, 1);
+       if (IS_ERR_VALUE(rx_base)) {
+               error("tegra186_bpmp_get_shmem failed for rx_base\n");
+               return rx_base;
+       }
+       debug("shmem: rx=%lx, tx=%lx\n", rx_base, tx_base);
+
+       ret = tegra_ivc_init(&priv->ivc, rx_base, tx_base, BPMP_IVC_FRAME_COUNT,
+                            BPMP_IVC_FRAME_SIZE, tegra186_bpmp_ivc_notify);
+       if (ret) {
+               error("tegra_ivc_init() failed: %d\n", ret);
+               return ret;
+       }
+
+       tegra_ivc_channel_reset(&priv->ivc);
+       start_time = timer_get_us();
+       for (;;) {
+               ret = tegra_ivc_channel_notified(&priv->ivc);
+               if (!ret)
+                       break;
+
+               /* Timeout 100ms */
+               if ((timer_get_us() - start_time) > 100 * 1000) {
+                       error("Initial IVC reset timed out (%d)\n", ret);
+                       ret = -ETIMEDOUT;
+                       goto err_free_mbox;
+               }
+       }
+
+       return 0;
+
+err_free_mbox:
+       mbox_free(&priv->mbox);
+
+       return ret;
+}
+
+static int tegra186_bpmp_remove(struct udevice *dev)
+{
+       struct tegra186_bpmp *priv = dev_get_priv(dev);
+
+       debug("%s(dev=%p) (priv=%p)\n", __func__, dev, priv);
+
+       mbox_free(&priv->mbox);
+
+       return 0;
+}
+
+static struct misc_ops tegra186_bpmp_ops = {
+       .call = tegra186_bpmp_call,
+};
+
+static const struct udevice_id tegra186_bpmp_ids[] = {
+       { .compatible = "nvidia,tegra186-bpmp" },
+       { }
+};
+
+U_BOOT_DRIVER(tegra186_bpmp) = {
+       .name           = "tegra186_bpmp",
+       .id             = UCLASS_MISC,
+       .of_match       = tegra186_bpmp_ids,
+       .bind           = tegra186_bpmp_bind,
+       .probe          = tegra186_bpmp_probe,
+       .remove         = tegra186_bpmp_remove,
+       .ops            = &tegra186_bpmp_ops,
+       .priv_auto_alloc_size = sizeof(struct tegra186_bpmp),
+};
index 023ba3c..f0a39a6 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <bouncebuf.h>
 #include <common.h>
+#include <dm/device.h>
 #include <errno.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch-tegra/tegra_mmc.h>
 #include <mmc.h>
 
+/*
+ * FIXME: TODO: This driver contains a number of ifdef CONFIG_TEGRA186 that
+ * should not be present. These are needed because newer Tegra SoCs support
+ * only the standard clock/reset APIs, whereas older Tegra SoCs support only
+ * a custom Tegra-specific API. ASAP the older Tegra SoCs' code should be
+ * fixed to implement the standard APIs, and all drivers converted to solely
+ * use the new standard APIs, with no ifdefs.
+ */
+
 DECLARE_GLOBAL_DATA_PTR;
 
 struct mmc_host mmc_host[CONFIG_SYS_MMC_MAX_DEVICE];
@@ -360,11 +370,14 @@ static void mmc_change_clock(struct mmc_host *host, uint clock)
         */
        if (clock == 0)
                goto out;
-#ifndef CONFIG_TEGRA186
+#ifdef CONFIG_TEGRA186
+       {
+               ulong rate = clk_set_rate(&host->clk, clock);
+               div = (rate + clock - 1) / clock;
+       }
+#else
        clock_adjust_periph_pll_div(host->mmc_id, CLOCK_ID_PERIPH, clock,
                                    &div);
-#else
-       div = (20000000 + clock - 1) / clock;
 #endif
        debug("div = %d\n", div);
 
@@ -539,6 +552,9 @@ static int do_mmc_init(int dev_index, bool removable)
 {
        struct mmc_host *host;
        struct mmc *mmc;
+#ifdef CONFIG_TEGRA186
+       int ret;
+#endif
 
        /* DT should have been read & host config filled in */
        host = &mmc_host[dev_index];
@@ -550,7 +566,21 @@ static int do_mmc_init(int dev_index, bool removable)
              gpio_get_number(&host->cd_gpio));
 
        host->clock = 0;
-#ifndef CONFIG_TEGRA186
+
+#ifdef CONFIG_TEGRA186
+       ret = reset_assert(&host->reset_ctl);
+       if (ret)
+               return ret;
+       ret = clk_enable(&host->clk);
+       if (ret)
+               return ret;
+       ret = clk_set_rate(&host->clk, 20000000);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+       ret = reset_deassert(&host->reset_ctl);
+       if (ret)
+               return ret;
+#else
        clock_start_periph_pll(host->mmc_id, CLOCK_ID_PERIPH, 20000000);
 #endif
 
@@ -577,11 +607,7 @@ static int do_mmc_init(int dev_index, bool removable)
         *  (actually 52MHz)
         */
        host->cfg.f_min = 375000;
-#ifndef CONFIG_TEGRA186
        host->cfg.f_max = 48000000;
-#else
-       host->cfg.f_max = 375000;
-#endif
 
        host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
@@ -613,7 +639,27 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host,
                return -FDT_ERR_NOTFOUND;
        }
 
-#ifndef CONFIG_TEGRA186
+#ifdef CONFIG_TEGRA186
+       {
+               /*
+                * FIXME: This variable should go away when the MMC device
+                * actually is a udevice.
+                */
+               struct udevice dev;
+               int ret;
+               dev.of_offset = node;
+               ret = reset_get_by_name(&dev, "sdmmc", &host->reset_ctl);
+               if (ret) {
+                       debug("reset_get_by_index() failed: %d\n", ret);
+                       return ret;
+               }
+               ret = clk_get_by_name(&dev, "sdmmc", &host->clk);
+               if (ret) {
+                       debug("clk_get_by_index() failed: %d\n", ret);
+                       return ret;
+               }
+       }
+#else
        host->mmc_id = clock_decode_periph_id(blob, node);
        if (host->mmc_id == PERIPH_ID_NONE) {
                debug("%s: could not decode periph id\n", __func__);
index bc52ed3..b718481 100644 (file)
@@ -283,10 +283,9 @@ static void mal_err (struct eth_device *dev, unsigned long isr,
 static void emac_err (struct eth_device *dev, unsigned long isr);
 
 extern int phy_setup_aneg (char *devname, unsigned char addr);
-extern int emac4xx_miiphy_read (const char *devname, unsigned char addr,
-               unsigned char reg, unsigned short *value);
-extern int emac4xx_miiphy_write (const char *devname, unsigned char addr,
-               unsigned char reg, unsigned short value);
+int emac4xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
+int emac4xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+                        u16 value);
 
 int board_emac_count(void);
 
@@ -2015,8 +2014,17 @@ int ppc_4xx_eth_initialize (bd_t * bis)
                eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-               miiphy_register(dev->name,
-                               emac4xx_miiphy_read, emac4xx_miiphy_write);
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+               mdiodev->read = emac4xx_miiphy_read;
+               mdiodev->write = emac4xx_miiphy_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
 #endif
 
                if (0 == virgin) {
index 88d8e83..be3ed73 100644 (file)
@@ -124,6 +124,11 @@ config ETH_DESIGNWARE
          100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to
          provide the PHY (physical media interface).
 
+config ETHOC
+       bool "OpenCores 10/100 Mbps Ethernet MAC"
+       help
+         This MAC is present in OpenRISC and Xtensa XTFPGA boards.
+
 config MVPP2
        bool "Marvell Armada 375 network interface support"
        depends on ARMADA_375
index e6a6252..ba2cb1a 100644 (file)
@@ -57,18 +57,19 @@ static int armdfec_phy_timeout(u32 *reg, u32 flag, int cond)
        return !timeout;
 }
 
-static int smi_reg_read(const char *devname, u8 phy_addr, u8 phy_reg,
-                       u16 *value)
+static int smi_reg_read(struct mii_dev *bus, int phy_addr, int devad,
+                       int phy_reg)
 {
-       struct eth_device *dev = eth_get_dev_by_name(devname);
+       u16 value = 0;
+       struct eth_device *dev = eth_get_dev_by_name(bus->name);
        struct armdfec_device *darmdfec = to_darmdfec(dev);
        struct armdfec_reg *regs = darmdfec->regs;
        u32 val;
 
        if (phy_addr == PHY_ADR_REQ && phy_reg == PHY_ADR_REQ) {
                val = readl(&regs->phyadr);
-               *value = val & 0x1f;
-               return 0;
+               value = val & 0x1f;
+               return value;
        }
 
        /* check parameters */
@@ -99,15 +100,15 @@ static int smi_reg_read(const char *devname, u8 phy_addr, u8 phy_reg,
                return -1;
        }
        val = readl(&regs->smi);
-       *value = val & 0xffff;
+       value = val & 0xffff;
 
-       return 0;
+       return value;
 }
 
-static int smi_reg_write(const char *devname,
-        u8 phy_addr, u8 phy_reg, u16 value)
+static int smi_reg_write(struct mii_dev *bus, int phy_addr, int devad,
+                        int phy_reg, u16 value)
 {
-       struct eth_device *dev = eth_get_dev_by_name(devname);
+       struct eth_device *dev = eth_get_dev_by_name(bus->name);
        struct armdfec_device *darmdfec = to_darmdfec(dev);
        struct armdfec_reg *regs = darmdfec->regs;
 
@@ -711,7 +712,17 @@ int armada100_fec_register(unsigned long base_addr)
        eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-       miiphy_register(dev->name, smi_reg_read, smi_reg_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = smi_reg_read;
+       mdiodev->write = smi_reg_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 #endif
        return 0;
 
index 9151600..be3d82e 100644 (file)
@@ -159,23 +159,23 @@ at91_emac_t *get_emacbase_by_name(const char *devname)
        return (at91_emac_t *) netdev->iobase;
 }
 
-int  at91emac_mii_read(const char *devname, unsigned char addr,
-               unsigned char reg, unsigned short *value)
+int at91emac_mii_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+       unsigned short value = 0;
        at91_emac_t *emac;
 
-       emac = get_emacbase_by_name(devname);
-       at91emac_read(emac , addr, reg, value);
-       return 0;
+       emac = get_emacbase_by_name(bus->name);
+       at91emac_read(emac , addr, reg, &value);
+       return value;
 }
 
 
-int  at91emac_mii_write(const char *devname, unsigned char addr,
-               unsigned char reg, unsigned short value)
+int at91emac_mii_write(struct mii_dev *bus, int addr, int devad, int reg,
+                      u16 value)
 {
        at91_emac_t *emac;
 
-       emac = get_emacbase_by_name(devname);
+       emac = get_emacbase_by_name(bus->name);
        at91emac_write(emac, addr, reg, value);
        return 0;
 }
@@ -502,7 +502,17 @@ int at91emac_register(bd_t *bis, unsigned long iobase)
        eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-       miiphy_register(dev->name, at91emac_mii_read, at91emac_mii_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = at91emac_mii_read;
+       mdiodev->write = at91emac_mii_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 #endif
        return 1;
 }
index 977feec..f2853cf 100644 (file)
@@ -596,12 +596,10 @@ bool gmac_mii_busywait(unsigned int timeout)
        return tmp & (1 << GMAC_MII_BUSY_SHIFT);
 }
 
-int gmac_miiphy_read(const char *devname, unsigned char phyaddr,
-                       unsigned char reg, unsigned short *value)
+int gmac_miiphy_read(struct mii_dev *bus, int phyaddr, int devad, int reg)
 {
        uint32_t tmp = 0;
-
-       (void)devname;
+       u16 value = 0;
 
        /* Busy wait timeout is 1ms */
        if (gmac_mii_busywait(1000)) {
@@ -621,18 +619,16 @@ int gmac_miiphy_read(const char *devname, unsigned char phyaddr,
                return -1;
        }
 
-       *value = readl(GMAC_MII_DATA_ADDR) & 0xffff;
-       debug("MII read data 0x%x\n", *value);
-       return 0;
+       value = readl(GMAC_MII_DATA_ADDR) & 0xffff;
+       debug("MII read data 0x%x\n", value);
+       return value;
 }
 
-int gmac_miiphy_write(const char *devname, unsigned char phyaddr,
-                        unsigned char reg, unsigned short value)
+int gmac_miiphy_write(struct mii_dev *bus, int phyaddr, int devad, int reg,
+                     u16 value)
 {
        uint32_t tmp = 0;
 
-       (void)devname;
-
        /* Busy wait timeout is 1ms */
        if (gmac_mii_busywait(1000)) {
                error("%s: Prepare MII write: MII/MDIO busy\n", __func__);
index eab4c1f..e274736 100644 (file)
@@ -244,7 +244,18 @@ int bcm_sf2_eth_register(bd_t *bis, u8 dev_num)
        eth_register(dev);
 
 #ifdef CONFIG_CMD_MII
-       miiphy_register(dev->name, eth->miiphy_read, eth->miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = eth->miiphy_read;
+       mdiodev->write = eth->miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 #endif
 
        /* Initialization */
index 49a5836..6104aff 100644 (file)
@@ -54,10 +54,10 @@ struct eth_info {
        struct phy_device *port[BCM_ETH_MAX_PORT_NUM];
        int port_num;
 
-       int (*miiphy_read)(const char *devname, unsigned char phyaddr,
-                          unsigned char reg, unsigned short *value);
-       int (*miiphy_write)(const char *devname, unsigned char phyaddr,
-                           unsigned char reg, unsigned short value);
+       int (*miiphy_read)(struct mii_dev *bus, int phyaddr, int devad,
+                          int reg);
+       int (*miiphy_write)(struct mii_dev *bus, int phyaddr, int devad,
+                           int reg, u16 value);
 
        int (*mac_init)(struct eth_device *dev);
        int (*enable_mac)(void);
index 61cb1b0..26a626b 100644 (file)
@@ -13,6 +13,7 @@
 #include <command.h>
 #include <malloc.h>
 #include <miiphy.h>
+#include <linux/mdio.h>
 #include <linux/mii.h>
 
 #include <asm/blackfin.h>
@@ -72,18 +73,20 @@ static int bfin_miiphy_wait(void)
        return 0;
 }
 
-static int bfin_miiphy_read(const char *devname, uchar addr, uchar reg, ushort *val)
+static int bfin_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+       ushort val = 0;
        if (bfin_miiphy_wait())
                return 1;
        bfin_write_EMAC_STAADD(SET_PHYAD(addr) | SET_REGAD(reg) | STABUSY);
        if (bfin_miiphy_wait())
                return 1;
-       *val = bfin_read_EMAC_STADAT();
-       return 0;
+       val = bfin_read_EMAC_STADAT();
+       return val;
 }
 
-static int bfin_miiphy_write(const char *devname, uchar addr, uchar reg, ushort val)
+static int bfin_miiphy_write(struct mii_dev *bus, int addr, int devad,
+                            int reg, u16 val)
 {
        if (bfin_miiphy_wait())
                return 1;
@@ -113,7 +116,19 @@ int bfin_EMAC_initialize(bd_t *bis)
        eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-       miiphy_register(dev->name, bfin_miiphy_read, bfin_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = bfin_miiphy_read;
+       mdiodev->write = bfin_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
+
+       dev->priv = mdiodev;
 #endif
 
        return 0;
@@ -222,8 +237,9 @@ static int bfin_EMAC_recv(struct eth_device *dev)
 static int bfin_miiphy_init(struct eth_device *dev, int *opmode)
 {
        const unsigned short pins[] = CONFIG_BFIN_MAC_PINS;
-       u16 phydat;
+       int phydat;
        size_t count;
+       struct mii_dev *mdiodev = dev->priv;
 
        /* Enable PHY output */
        bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE);
@@ -236,12 +252,15 @@ static int bfin_miiphy_init(struct eth_device *dev, int *opmode)
        bfin_write_EMAC_SYSCTL(RXDWA | RXCKS | SET_MDCDIV(MDC_FREQ_TO_DIV(CONFIG_PHY_CLOCK_FREQ)));
 
        /* turn on auto-negotiation and wait for link to come up */
-       bfin_miiphy_write(dev->name, CONFIG_PHY_ADDR, MII_BMCR, BMCR_ANENABLE);
+       bfin_miiphy_write(mdiodev, CONFIG_PHY_ADDR, MDIO_DEVAD_NONE, MII_BMCR,
+                         BMCR_ANENABLE);
        count = 0;
        while (1) {
                ++count;
-               if (bfin_miiphy_read(dev->name, CONFIG_PHY_ADDR, MII_BMSR, &phydat))
-                       return -1;
+               phydat = bfin_miiphy_read(mdiodev, CONFIG_PHY_ADDR,
+                                         MDIO_DEVAD_NONE, MII_BMSR);
+               if (phydat < 0)
+                       return phydat;
                if (phydat & BMSR_LSTATUS)
                        break;
                if (count > 30000) {
@@ -252,8 +271,10 @@ static int bfin_miiphy_init(struct eth_device *dev, int *opmode)
        }
 
        /* see what kind of link we have */
-       if (bfin_miiphy_read(dev->name, CONFIG_PHY_ADDR, MII_LPA, &phydat))
-               return -1;
+       phydat = bfin_miiphy_read(mdiodev, CONFIG_PHY_ADDR, MDIO_DEVAD_NONE,
+                                 MII_LPA);
+       if (phydat < 0)
+               return phydat;
        if (phydat & LPA_DUPLEX)
                *opmode = FDMODE;
        else
index b030498..ca457b8 100644 (file)
@@ -243,11 +243,10 @@ int davinci_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
 
        if (tmp & MDIO_USERACCESS0_ACK) {
                *data = tmp & 0xffff;
-               return(1);
+               return 0;
        }
 
-       *data = -1;
-       return(0);
+       return -EIO;
 }
 
 /* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */
@@ -268,7 +267,7 @@ int davinci_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
        while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
                ;
 
-       return(1);
+       return 0;
 }
 
 /* PHY functions for a generic PHY */
@@ -390,14 +389,20 @@ static int gen_auto_negotiate(int phy_addr)
 
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-static int davinci_mii_phy_read(const char *devname, unsigned char addr, unsigned char reg, unsigned short *value)
+static int davinci_mii_phy_read(struct mii_dev *bus, int addr, int devad,
+                               int reg)
 {
-       return(davinci_eth_phy_read(addr, reg, value) ? 0 : 1);
+       unsigned short value = 0;
+       int retval = davinci_eth_phy_read(addr, reg, &value);
+       if (retval < 0)
+               return retval;
+       return value;
 }
 
-static int davinci_mii_phy_write(const char *devname, unsigned char addr, unsigned char reg, unsigned short value)
+static int davinci_mii_phy_write(struct mii_dev *bus, int addr, int devad,
+                                int reg, u16 value)
 {
-       return(davinci_eth_phy_write(addr, reg, value) ? 0 : 1);
+       return davinci_eth_phy_write(addr, reg, value);
 }
 #endif
 
@@ -883,8 +888,17 @@ int davinci_emac_initialize(void)
 
                debug("Ethernet PHY: %s\n", phy[i].name);
 
-               miiphy_register(phy[i].name, davinci_mii_phy_read,
-                                               davinci_mii_phy_write);
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, phy[i].name, MDIO_NAME_LEN);
+               mdiodev->read = davinci_mii_phy_read;
+               mdiodev->write = davinci_mii_phy_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
        }
 
 #if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
index 196989b..3332ad9 100644 (file)
@@ -5513,7 +5513,8 @@ static int do_e1000(cmd_tbl_t *cmdtp, int flag,
        struct udevice *dev;
        char name[30];
        int ret;
-#else
+#endif
+#if !defined(CONFIG_DM_ETH) || defined(CONFIG_E1000_SPI)
        struct e1000_hw *hw;
 #endif
        int cardnum;
@@ -5549,6 +5550,9 @@ static int do_e1000(cmd_tbl_t *cmdtp, int flag,
        }
 
 #ifdef CONFIG_E1000_SPI
+#ifdef CONFIG_DM_ETH
+       hw = dev_get_priv(dev);
+#endif
        /* Handle the "SPI" subcommand */
        if (!strcmp(argv[2], "spi"))
                return do_e1000_spi(cmdtp, hw, argc - 3, argv + 3);
index 576ddb8..cb5f93d 100644 (file)
@@ -94,17 +94,17 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 
        /* Make sure it has an SPI chip */
        if (hw->eeprom.type != e1000_eeprom_spi) {
-               E1000_ERR(hw->nic, "No attached SPI EEPROM found!\n");
+               E1000_ERR(hw, "No attached SPI EEPROM found!\n");
                return NULL;
        }
 
        /* Argument sanity checks */
        if (cs != 0) {
-               E1000_ERR(hw->nic, "No such SPI chip: %u\n", cs);
+               E1000_ERR(hw, "No such SPI chip: %u\n", cs);
                return NULL;
        }
        if (mode != SPI_MODE_0) {
-               E1000_ERR(hw->nic, "Only SPI MODE-0 is supported!\n");
+               E1000_ERR(hw, "Only SPI MODE-0 is supported!\n");
                return NULL;
        }
 
@@ -124,7 +124,7 @@ int spi_claim_bus(struct spi_slave *spi)
        struct e1000_hw *hw = e1000_hw_from_spi(spi);
 
        if (e1000_acquire_eeprom(hw)) {
-               E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+               E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
                return -1;
        }
 
@@ -342,41 +342,41 @@ static int do_e1000_spi_show(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
 
        /* Extra sanity checks */
        if (!length) {
-               E1000_ERR(hw->nic, "Requested zero-sized dump!\n");
+               E1000_ERR(hw, "Requested zero-sized dump!\n");
                return 1;
        }
        if ((0x10000 < length) || (0x10000 - length < offset)) {
-               E1000_ERR(hw->nic, "Can't dump past 0xFFFF!\n");
+               E1000_ERR(hw, "Can't dump past 0xFFFF!\n");
                return 1;
        }
 
        /* Allocate a buffer to hold stuff */
        buffer = malloc(length);
        if (!buffer) {
-               E1000_ERR(hw->nic, "Out of Memory!\n");
+               E1000_ERR(hw, "Out of Memory!\n");
                return 1;
        }
 
        /* Acquire the EEPROM and perform the dump */
        if (e1000_acquire_eeprom(hw)) {
-               E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+               E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
                free(buffer);
                return 1;
        }
        err = e1000_spi_eeprom_dump(hw, buffer, offset, length, true);
        e1000_release_eeprom(hw);
        if (err) {
-               E1000_ERR(hw->nic, "Interrupted!\n");
+               E1000_ERR(hw, "Interrupted!\n");
                free(buffer);
                return 1;
        }
 
        /* Now hexdump the result */
        printf("%s: ===== Intel e1000 EEPROM (0x%04hX - 0x%04hX) =====",
-                       hw->nic->name, offset, offset + length - 1);
+                       hw->name, offset, offset + length - 1);
        for (i = 0; i < length; i++) {
                if ((i & 0xF) == 0)
-                       printf("\n%s: %04hX: ", hw->nic->name, offset + i);
+                       printf("\n%s: %04hX: ", hw->name, offset + i);
                else if ((i & 0xF) == 0x8)
                        printf(" ");
                printf(" %02hx", buffer[i]);
@@ -407,29 +407,29 @@ static int do_e1000_spi_dump(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
 
        /* Extra sanity checks */
        if (!length) {
-               E1000_ERR(hw->nic, "Requested zero-sized dump!\n");
+               E1000_ERR(hw, "Requested zero-sized dump!\n");
                return 1;
        }
        if ((0x10000 < length) || (0x10000 - length < offset)) {
-               E1000_ERR(hw->nic, "Can't dump past 0xFFFF!\n");
+               E1000_ERR(hw, "Can't dump past 0xFFFF!\n");
                return 1;
        }
 
        /* Acquire the EEPROM */
        if (e1000_acquire_eeprom(hw)) {
-               E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+               E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
                return 1;
        }
 
        /* Perform the programming operation */
        if (e1000_spi_eeprom_dump(hw, dest, offset, length, true) < 0) {
-               E1000_ERR(hw->nic, "Interrupted!\n");
+               E1000_ERR(hw, "Interrupted!\n");
                e1000_release_eeprom(hw);
                return 1;
        }
 
        e1000_release_eeprom(hw);
-       printf("%s: ===== EEPROM DUMP COMPLETE =====\n", hw->nic->name);
+       printf("%s: ===== EEPROM DUMP COMPLETE =====\n", hw->name);
        return 0;
 }
 
@@ -452,19 +452,19 @@ static int do_e1000_spi_program(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
 
        /* Acquire the EEPROM */
        if (e1000_acquire_eeprom(hw)) {
-               E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+               E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
                return 1;
        }
 
        /* Perform the programming operation */
        if (e1000_spi_eeprom_program(hw, source, offset, length, true) < 0) {
-               E1000_ERR(hw->nic, "Interrupted!\n");
+               E1000_ERR(hw, "Interrupted!\n");
                e1000_release_eeprom(hw);
                return 1;
        }
 
        e1000_release_eeprom(hw);
-       printf("%s: ===== EEPROM PROGRAMMED =====\n", hw->nic->name);
+       printf("%s: ===== EEPROM PROGRAMMED =====\n", hw->name);
        return 0;
 }
 
@@ -488,19 +488,19 @@ static int do_e1000_spi_checksum(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
        length = sizeof(uint16_t) * (EEPROM_CHECKSUM_REG + 1);
        buffer = malloc(length);
        if (!buffer) {
-               E1000_ERR(hw->nic, "Unable to allocate EEPROM buffer!\n");
+               E1000_ERR(hw, "Unable to allocate EEPROM buffer!\n");
                return 1;
        }
 
        /* Acquire the EEPROM */
        if (e1000_acquire_eeprom(hw)) {
-               E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+               E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
                return 1;
        }
 
        /* Read the EEPROM */
        if (e1000_spi_eeprom_dump(hw, buffer, 0, length, true) < 0) {
-               E1000_ERR(hw->nic, "Interrupted!\n");
+               E1000_ERR(hw, "Interrupted!\n");
                e1000_release_eeprom(hw);
                return 1;
        }
@@ -514,15 +514,15 @@ static int do_e1000_spi_checksum(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
        /* Verify it! */
        if (checksum_reg == checksum) {
                printf("%s: INFO: EEPROM checksum is correct! (0x%04hx)\n",
-                               hw->nic->name, checksum);
+                               hw->name, checksum);
                e1000_release_eeprom(hw);
                return 0;
        }
 
        /* Hrm, verification failed, print an error */
-       E1000_ERR(hw->nic, "EEPROM checksum is incorrect!\n");
-       E1000_ERR(hw->nic, "  ...register was 0x%04hx, calculated 0x%04hx\n",
-                       checksum_reg, checksum);
+       E1000_ERR(hw, "EEPROM checksum is incorrect!\n");
+       E1000_ERR(hw, "  ...register was 0x%04hx, calculated 0x%04hx\n",
+                 checksum_reg, checksum);
 
        /* If they didn't ask us to update it, just return an error */
        if (!upd) {
@@ -531,11 +531,11 @@ static int do_e1000_spi_checksum(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
        }
 
        /* Ok, correct it! */
-       printf("%s: Reprogramming the EEPROM checksum...\n", hw->nic->name);
+       printf("%s: Reprogramming the EEPROM checksum...\n", hw->name);
        buffer[i] = cpu_to_le16(checksum);
        if (e1000_spi_eeprom_program(hw, &buffer[i], i * sizeof(uint16_t),
                        sizeof(uint16_t), true)) {
-               E1000_ERR(hw->nic, "Interrupted!\n");
+               E1000_ERR(hw, "Interrupted!\n");
                e1000_release_eeprom(hw);
                return 1;
        }
@@ -554,7 +554,8 @@ int do_e1000_spi(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
 
        /* Make sure it has an SPI chip */
        if (hw->eeprom.type != e1000_eeprom_spi) {
-               E1000_ERR(hw->nic, "No attached SPI EEPROM found!\n");
+               E1000_ERR(hw, "No attached SPI EEPROM found (%d)!\n",
+                         hw->eeprom.type);
                return 1;
        }
 
index d4a6386..0f350cb 100644 (file)
@@ -334,34 +334,35 @@ static struct eth_device* verify_phyaddr (const char *devname,
        return dev;
 }
 
-static int eepro100_miiphy_read(const char *devname, unsigned char addr,
-               unsigned char reg, unsigned short *value)
+static int eepro100_miiphy_read(struct mii_dev *bus, int addr, int devad,
+                               int reg)
 {
+       unsigned short value = 0;
        struct eth_device *dev;
 
-       dev = verify_phyaddr(devname, addr);
+       dev = verify_phyaddr(bus->name, addr);
        if (dev == NULL)
                return -1;
 
-       if (get_phyreg(dev, addr, reg, value) != 0) {
-               printf("%s: mii read timeout!\n", devname);
+       if (get_phyreg(dev, addr, reg, &value) != 0) {
+               printf("%s: mii read timeout!\n", bus->name);
                return -1;
        }
 
-       return 0;
+       return value;
 }
 
-static int eepro100_miiphy_write(const char *devname, unsigned char addr,
-               unsigned char reg, unsigned short value)
+static int eepro100_miiphy_write(struct mii_dev *bus, int addr, int devad,
+                                int reg, u16 value)
 {
        struct eth_device *dev;
 
-       dev = verify_phyaddr(devname, addr);
+       dev = verify_phyaddr(bus->name, addr);
        if (dev == NULL)
                return -1;
 
        if (set_phyreg(dev, addr, reg, value) != 0) {
-               printf("%s: mii write timeout!\n", devname);
+               printf("%s: mii write timeout!\n", bus->name);
                return -1;
        }
 
@@ -451,8 +452,17 @@ int eepro100_initialize (bd_t * bis)
 
 #if defined (CONFIG_MII) || defined(CONFIG_CMD_MII)
                /* register mii command access routines */
-               miiphy_register(dev->name,
-                               eepro100_miiphy_read, eepro100_miiphy_write);
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+               mdiodev->read = eepro100_miiphy_read;
+               mdiodev->write = eepro100_miiphy_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
 #endif
 
                card_number++;
index 611eabb..2fe323a 100644 (file)
@@ -742,9 +742,10 @@ static int enc_initcheck(enc_dev_t *enc, const enum enc_initstate requiredstate)
  *
  * This function is registered with miiphy_register().
  */
-int enc_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
+int enc_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg)
 {
-       struct eth_device *dev = eth_get_dev_by_name(devname);
+       u16 value = 0;
+       struct eth_device *dev = eth_get_dev_by_name(bus->name);
        enc_dev_t *enc;
 
        if (!dev || phy_adr != 0)
@@ -757,9 +758,9 @@ int enc_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
                enc_release_bus(enc);
                return -1;
        }
-       *value = enc_phy_read(enc, reg);
+       value = enc_phy_read(enc, reg);
        enc_release_bus(enc);
-       return 0;
+       return value;
 }
 
 /*
@@ -767,9 +768,10 @@ int enc_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
  *
  * This function is registered with miiphy_register().
  */
-int enc_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
+int enc_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg,
+                    u16 value)
 {
-       struct eth_device *dev = eth_get_dev_by_name(devname);
+       struct eth_device *dev = eth_get_dev_by_name(bus->name);
        enc_dev_t *enc;
 
        if (!dev || phy_adr != 0)
@@ -958,7 +960,17 @@ int enc28j60_initialize(unsigned int bus, unsigned int cs,
        sprintf(dev->name, "enc%i.%i", bus, cs);
        eth_register(dev);
 #if defined(CONFIG_CMD_MII)
-       miiphy_register(dev->name, enc_miiphy_read, enc_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = enc_miiphy_read;
+       mdiodev->write = enc_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 #endif
        return 0;
 }
index a3721c5..a94191b 100644 (file)
 #define GET_REGS(eth_dev)      (GET_PRIV(eth_dev)->regs)
 
 /* ep93xx_miiphy ops forward declarations */
-static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
-                       unsigned char const reg, unsigned short * const value);
-static int ep93xx_miiphy_write(const char * const dev, unsigned char const addr,
-                       unsigned char const reg, unsigned short const value);
+static int ep93xx_miiphy_read(struct mii_dev *bus, int addr, int devad,
+                             int reg);
+static int ep93xx_miiphy_write(struct mii_dev *bus, int addr, int devad,
+                              int reg, u16 value);
 
 #if defined(EP93XX_MAC_DEBUG)
 /**
@@ -421,7 +421,17 @@ eth_send_out:
 #if defined(CONFIG_MII)
 int ep93xx_miiphy_initialize(bd_t * const bd)
 {
-       miiphy_register("ep93xx_eth0", ep93xx_miiphy_read, ep93xx_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, "ep93xx_eth0", MDIO_NAME_LEN);
+       mdiodev->read = ep93xx_miiphy_read;
+       mdiodev->write = ep93xx_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
        return 0;
 }
 #endif
@@ -542,9 +552,10 @@ eth_init_done:
 /**
  * Read a 16-bit value from an MII register.
  */
-static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
-                       unsigned char const reg, unsigned short * const value)
+static int ep93xx_miiphy_read(struct mii_dev *bus, int addr, int devad,
+                             int reg)
 {
+       unsigned short value = 0;
        struct mac_regs *mac = (struct mac_regs *)MAC_BASE;
        int ret = -1;
        uint32_t self_ctl;
@@ -552,10 +563,9 @@ static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
        debug("+ep93xx_miiphy_read");
 
        /* Parameter checks */
-       BUG_ON(dev == NULL);
+       BUG_ON(bus->name == NULL);
        BUG_ON(addr > MII_ADDRESS_MAX);
        BUG_ON(reg > MII_REGISTER_MAX);
-       BUG_ON(value == NULL);
 
        /*
         * Save the current SelfCTL register value.  Set MAC to suppress
@@ -579,7 +589,7 @@ static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
        while (readl(&mac->miists) & MIISTS_BUSY)
                ; /* noop */
 
-       *value = (unsigned short)readl(&mac->miidata);
+       value = (unsigned short)readl(&mac->miidata);
 
        /* Restore the saved SelfCTL value and return. */
        writel(self_ctl, &mac->selfctl);
@@ -588,14 +598,16 @@ static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
        /* Fall through */
 
        debug("-ep93xx_miiphy_read");
-       return ret;
+       if (ret < 0)
+               return ret;
+       return value;
 }
 
 /**
  * Write a 16-bit value to an MII register.
  */
-static int ep93xx_miiphy_write(const char * const dev, unsigned char const addr,
-                       unsigned char const reg, unsigned short const value)
+static int ep93xx_miiphy_write(struct mii_dev *bus, int addr, int devad,
+                              int reg, u16 value)
 {
        struct mac_regs *mac = (struct mac_regs *)MAC_BASE;
        int ret = -1;
@@ -604,7 +616,7 @@ static int ep93xx_miiphy_write(const char * const dev, unsigned char const addr,
        debug("+ep93xx_miiphy_write");
 
        /* Parameter checks */
-       BUG_ON(dev == NULL);
+       BUG_ON(bus->name == NULL);
        BUG_ON(addr > MII_ADDRESS_MAX);
        BUG_ON(reg > MII_REGISTER_MAX);
 
index edb3c80..ad8c462 100644 (file)
@@ -5,19 +5,20 @@
  * Copyright (C) 2008-2009 Avionic Design GmbH
  *   Thierry Reding <thierry.reding@avionic-design.de>
  * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
+ * Copyright (C) 2016 Cadence Design Systems Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * SPDX-License-Identifier:    GPL-2.0
  */
 
 #include <common.h>
-#include <command.h>
+#include <dm/device.h>
+#include <dm/platform_data/net_ethoc.h>
+#include <linux/io.h>
 #include <malloc.h>
 #include <net.h>
 #include <miiphy.h>
-#include <asm/io.h>
 #include <asm/cache.h>
+#include <wait_bit.h>
 
 /* register offsets */
 #define        MODER           0x00
 #define        ETHOC_BD_BASE           0x400
 #define        ETHOC_TIMEOUT           (HZ / 2)
 #define        ETHOC_MII_TIMEOUT       (1 + (HZ / 5))
+#define        ETHOC_IOSIZE            0x54
 
 /**
  * struct ethoc - driver-private device structure
@@ -177,6 +179,14 @@ struct ethoc {
        u32 dty_tx;
        u32 num_rx;
        u32 cur_rx;
+       void __iomem *iobase;
+       void __iomem *packet;
+       phys_addr_t packet_phys;
+
+#ifdef CONFIG_PHYLIB
+       struct mii_dev *bus;
+       struct phy_device *phydev;
+#endif
 };
 
 /**
@@ -189,65 +199,68 @@ struct ethoc_bd {
        u32 addr;
 };
 
-static inline u32 ethoc_read(struct eth_device *dev, size_t offset)
+static inline u32 *ethoc_reg(struct ethoc *priv, size_t offset)
 {
-       return readl(dev->iobase + offset);
+       return priv->iobase + offset;
 }
 
-static inline void ethoc_write(struct eth_device *dev, size_t offset, u32 data)
+static inline u32 ethoc_read(struct ethoc *priv, size_t offset)
 {
-       writel(data, dev->iobase + offset);
+       return readl(ethoc_reg(priv, offset));
 }
 
-static inline void ethoc_read_bd(struct eth_device *dev, int index,
+static inline void ethoc_write(struct ethoc *priv, size_t offset, u32 data)
+{
+       writel(data, ethoc_reg(priv, offset));
+}
+
+static inline void ethoc_read_bd(struct ethoc *priv, int index,
                                 struct ethoc_bd *bd)
 {
        size_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd));
-       bd->stat = ethoc_read(dev, offset + 0);
-       bd->addr = ethoc_read(dev, offset + 4);
+       bd->stat = ethoc_read(priv, offset + 0);
+       bd->addr = ethoc_read(priv, offset + 4);
 }
 
-static inline void ethoc_write_bd(struct eth_device *dev, int index,
+static inline void ethoc_write_bd(struct ethoc *priv, int index,
                                  const struct ethoc_bd *bd)
 {
        size_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd));
-       ethoc_write(dev, offset + 0, bd->stat);
-       ethoc_write(dev, offset + 4, bd->addr);
+       ethoc_write(priv, offset + 0, bd->stat);
+       ethoc_write(priv, offset + 4, bd->addr);
 }
 
-static int ethoc_set_mac_address(struct eth_device *dev)
+static int ethoc_write_hwaddr_common(struct ethoc *priv, u8 *mac)
 {
-       u8 *mac = dev->enetaddr;
-
-       ethoc_write(dev, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) |
+       ethoc_write(priv, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) |
                    (mac[4] << 8) | (mac[5] << 0));
-       ethoc_write(dev, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0));
+       ethoc_write(priv, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0));
        return 0;
 }
 
-static inline void ethoc_ack_irq(struct eth_device *dev, u32 mask)
+static inline void ethoc_ack_irq(struct ethoc *priv, u32 mask)
 {
-       ethoc_write(dev, INT_SOURCE, mask);
+       ethoc_write(priv, INT_SOURCE, mask);
 }
 
-static inline void ethoc_enable_rx_and_tx(struct eth_device *dev)
+static inline void ethoc_enable_rx_and_tx(struct ethoc *priv)
 {
-       u32 mode = ethoc_read(dev, MODER);
+       u32 mode = ethoc_read(priv, MODER);
        mode |= MODER_RXEN | MODER_TXEN;
-       ethoc_write(dev, MODER, mode);
+       ethoc_write(priv, MODER, mode);
 }
 
-static inline void ethoc_disable_rx_and_tx(struct eth_device *dev)
+static inline void ethoc_disable_rx_and_tx(struct ethoc *priv)
 {
-       u32 mode = ethoc_read(dev, MODER);
+       u32 mode = ethoc_read(priv, MODER);
        mode &= ~(MODER_RXEN | MODER_TXEN);
-       ethoc_write(dev, MODER, mode);
+       ethoc_write(priv, MODER, mode);
 }
 
-static int ethoc_init_ring(struct eth_device *dev)
+static int ethoc_init_ring(struct ethoc *priv)
 {
-       struct ethoc *priv = (struct ethoc *)dev->priv;
        struct ethoc_bd bd;
+       phys_addr_t addr = priv->packet_phys;
        int i;
 
        priv->cur_tx = 0;
@@ -256,66 +269,92 @@ static int ethoc_init_ring(struct eth_device *dev)
 
        /* setup transmission buffers */
        bd.stat = TX_BD_IRQ | TX_BD_CRC;
+       bd.addr = 0;
 
        for (i = 0; i < priv->num_tx; i++) {
+               if (addr) {
+                       bd.addr = addr;
+                       addr += PKTSIZE_ALIGN;
+               }
                if (i == priv->num_tx - 1)
                        bd.stat |= TX_BD_WRAP;
 
-               ethoc_write_bd(dev, i, &bd);
+               ethoc_write_bd(priv, i, &bd);
        }
 
        bd.stat = RX_BD_EMPTY | RX_BD_IRQ;
 
        for (i = 0; i < priv->num_rx; i++) {
-               bd.addr = (u32)net_rx_packets[i];
+               if (addr) {
+                       bd.addr = addr;
+                       addr += PKTSIZE_ALIGN;
+               } else {
+                       bd.addr = virt_to_phys(net_rx_packets[i]);
+               }
                if (i == priv->num_rx - 1)
                        bd.stat |= RX_BD_WRAP;
 
-               flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN);
-               ethoc_write_bd(dev, priv->num_tx + i, &bd);
+               flush_dcache_range((ulong)net_rx_packets[i],
+                                  (ulong)net_rx_packets[i] + PKTSIZE_ALIGN);
+               ethoc_write_bd(priv, priv->num_tx + i, &bd);
        }
 
        return 0;
 }
 
-static int ethoc_reset(struct eth_device *dev)
+static int ethoc_reset(struct ethoc *priv)
 {
        u32 mode;
 
        /* TODO: reset controller? */
 
-       ethoc_disable_rx_and_tx(dev);
+       ethoc_disable_rx_and_tx(priv);
 
        /* TODO: setup registers */
 
        /* enable FCS generation and automatic padding */
-       mode = ethoc_read(dev, MODER);
+       mode = ethoc_read(priv, MODER);
        mode |= MODER_CRC | MODER_PAD;
-       ethoc_write(dev, MODER, mode);
+       ethoc_write(priv, MODER, mode);
 
        /* set full-duplex mode */
-       mode = ethoc_read(dev, MODER);
+       mode = ethoc_read(priv, MODER);
        mode |= MODER_FULLD;
-       ethoc_write(dev, MODER, mode);
-       ethoc_write(dev, IPGT, 0x15);
+       ethoc_write(priv, MODER, mode);
+       ethoc_write(priv, IPGT, 0x15);
 
-       ethoc_ack_irq(dev, INT_MASK_ALL);
-       ethoc_enable_rx_and_tx(dev);
+       ethoc_ack_irq(priv, INT_MASK_ALL);
+       ethoc_enable_rx_and_tx(priv);
        return 0;
 }
 
-static int ethoc_init(struct eth_device *dev, bd_t * bd)
+static int ethoc_init_common(struct ethoc *priv)
 {
-       struct ethoc *priv = (struct ethoc *)dev->priv;
-       printf("ethoc\n");
+       int ret = 0;
 
        priv->num_tx = 1;
        priv->num_rx = PKTBUFSRX;
-       ethoc_write(dev, TX_BD_NUM, priv->num_tx);
-       ethoc_init_ring(dev);
-       ethoc_reset(dev);
+       ethoc_write(priv, TX_BD_NUM, priv->num_tx);
+       ethoc_init_ring(priv);
+       ethoc_reset(priv);
+
+#ifdef CONFIG_PHYLIB
+       ret = phy_startup(priv->phydev);
+       if (ret) {
+               printf("Could not initialize PHY %s\n",
+                      priv->phydev->dev->name);
+               return ret;
+       }
+#endif
+       return ret;
+}
 
-       return 0;
+static void ethoc_stop_common(struct ethoc *priv)
+{
+       ethoc_disable_rx_and_tx(priv);
+#ifdef CONFIG_PHYLIB
+       phy_shutdown(priv->phydev);
+#endif
 }
 
 static int ethoc_update_rx_stats(struct ethoc_bd *bd)
@@ -353,37 +392,46 @@ static int ethoc_update_rx_stats(struct ethoc_bd *bd)
        return ret;
 }
 
-static int ethoc_rx(struct eth_device *dev, int limit)
+static int ethoc_rx_common(struct ethoc *priv, uchar **packetp)
 {
-       struct ethoc *priv = (struct ethoc *)dev->priv;
-       int count;
-
-       for (count = 0; count < limit; ++count) {
-               u32 entry;
-               struct ethoc_bd bd;
-
-               entry = priv->num_tx + (priv->cur_rx % priv->num_rx);
-               ethoc_read_bd(dev, entry, &bd);
-               if (bd.stat & RX_BD_EMPTY)
-                       break;
+       struct ethoc_bd bd;
+       u32 i = priv->cur_rx % priv->num_rx;
+       u32 entry = priv->num_tx + i;
+
+       ethoc_read_bd(priv, entry, &bd);
+       if (bd.stat & RX_BD_EMPTY)
+               return -EAGAIN;
+
+       debug("%s(): RX buffer %d, %x received\n",
+             __func__, priv->cur_rx, bd.stat);
+       if (ethoc_update_rx_stats(&bd) == 0) {
+               int size = bd.stat >> 16;
+
+               size -= 4;      /* strip the CRC */
+               if (priv->packet)
+                       *packetp = priv->packet + entry * PKTSIZE_ALIGN;
+               else
+                       *packetp = net_rx_packets[i];
+               return size;
+       } else {
+               return 0;
+       }
+}
 
-               debug("%s(): RX buffer %d, %x received\n",
-                     __func__, priv->cur_rx, bd.stat);
-               if (ethoc_update_rx_stats(&bd) == 0) {
-                       int size = bd.stat >> 16;
-                       size -= 4;      /* strip the CRC */
-                       net_process_received_packet((void *)bd.addr, size);
-               }
+static int ethoc_is_new_packet_received(struct ethoc *priv)
+{
+       u32 pending;
 
-               /* clear the buffer descriptor so it can be reused */
-               flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN);
-               bd.stat &= ~RX_BD_STATS;
-               bd.stat |= RX_BD_EMPTY;
-               ethoc_write_bd(dev, entry, &bd);
-               priv->cur_rx++;
+       pending = ethoc_read(priv, INT_SOURCE);
+       ethoc_ack_irq(priv, pending);
+       if (pending & INT_MASK_BUSY)
+               debug("%s(): packet dropped\n", __func__);
+       if (pending & INT_MASK_RX) {
+               debug("%s(): rx irq\n", __func__);
+               return 1;
        }
 
-       return count;
+       return 0;
 }
 
 static int ethoc_update_tx_stats(struct ethoc_bd *bd)
@@ -403,52 +451,57 @@ static int ethoc_update_tx_stats(struct ethoc_bd *bd)
        return 0;
 }
 
-static void ethoc_tx(struct eth_device *dev)
+static void ethoc_tx(struct ethoc *priv)
 {
-       struct ethoc *priv = (struct ethoc *)dev->priv;
        u32 entry = priv->dty_tx % priv->num_tx;
        struct ethoc_bd bd;
 
-       ethoc_read_bd(dev, entry, &bd);
+       ethoc_read_bd(priv, entry, &bd);
        if ((bd.stat & TX_BD_READY) == 0)
                (void)ethoc_update_tx_stats(&bd);
 }
 
-static int ethoc_send(struct eth_device *dev, void *packet, int length)
+static int ethoc_send_common(struct ethoc *priv, void *packet, int length)
 {
-       struct ethoc *priv = (struct ethoc *)dev->priv;
        struct ethoc_bd bd;
        u32 entry;
        u32 pending;
        int tmo;
 
        entry = priv->cur_tx % priv->num_tx;
-       ethoc_read_bd(dev, entry, &bd);
+       ethoc_read_bd(priv, entry, &bd);
        if (unlikely(length < ETHOC_ZLEN))
                bd.stat |= TX_BD_PAD;
        else
                bd.stat &= ~TX_BD_PAD;
-       bd.addr = (u32)packet;
 
-       flush_dcache_range(bd.addr, bd.addr + length);
+       if (priv->packet) {
+               void *p = priv->packet + entry * PKTSIZE_ALIGN;
+
+               memcpy(p, packet, length);
+               packet = p;
+       } else {
+               bd.addr = virt_to_phys(packet);
+       }
+       flush_dcache_range((ulong)packet, (ulong)packet + length);
        bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
        bd.stat |= TX_BD_LEN(length);
-       ethoc_write_bd(dev, entry, &bd);
+       ethoc_write_bd(priv, entry, &bd);
 
        /* start transmit */
        bd.stat |= TX_BD_READY;
-       ethoc_write_bd(dev, entry, &bd);
+       ethoc_write_bd(priv, entry, &bd);
 
        /* wait for transfer to succeed */
        tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
        while (1) {
-               pending = ethoc_read(dev, INT_SOURCE);
-               ethoc_ack_irq(dev, pending & ~INT_MASK_RX);
+               pending = ethoc_read(priv, INT_SOURCE);
+               ethoc_ack_irq(priv, pending & ~INT_MASK_RX);
                if (pending & INT_MASK_BUSY)
                        debug("%s(): packet dropped\n", __func__);
 
                if (pending & INT_MASK_TX) {
-                       ethoc_tx(dev);
+                       ethoc_tx(priv);
                        break;
                }
                if (get_timer(0) >= tmo) {
@@ -461,24 +514,290 @@ static int ethoc_send(struct eth_device *dev, void *packet, int length)
        return 0;
 }
 
+static int ethoc_free_pkt_common(struct ethoc *priv)
+{
+       struct ethoc_bd bd;
+       u32 i = priv->cur_rx % priv->num_rx;
+       u32 entry = priv->num_tx + i;
+       void *src;
+
+       ethoc_read_bd(priv, entry, &bd);
+
+       if (priv->packet)
+               src = priv->packet + entry * PKTSIZE_ALIGN;
+       else
+               src = net_rx_packets[i];
+       /* clear the buffer descriptor so it can be reused */
+       flush_dcache_range((ulong)src,
+                          (ulong)src + PKTSIZE_ALIGN);
+       bd.stat &= ~RX_BD_STATS;
+       bd.stat |= RX_BD_EMPTY;
+       ethoc_write_bd(priv, entry, &bd);
+       priv->cur_rx++;
+
+       return 0;
+}
+
+#ifdef CONFIG_PHYLIB
+
+static int ethoc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+       struct ethoc *priv = bus->priv;
+       int rc;
+
+       ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
+       ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ);
+
+       rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
+                         MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+
+       if (rc == 0) {
+               u32 data = ethoc_read(priv, MIIRX_DATA);
+
+               /* reset MII command register */
+               ethoc_write(priv, MIICOMMAND, 0);
+               return data;
+       }
+       return rc;
+}
+
+static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
+                           u16 val)
+{
+       struct ethoc *priv = bus->priv;
+       int rc;
+
+       ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
+       ethoc_write(priv, MIITX_DATA, val);
+       ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE);
+
+       rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
+                         MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+
+       if (rc == 0) {
+               /* reset MII command register */
+               ethoc_write(priv, MIICOMMAND, 0);
+       }
+       return rc;
+}
+
+static int ethoc_mdio_init(const char *name, struct ethoc *priv)
+{
+       struct mii_dev *bus = mdio_alloc();
+       int ret;
+
+       if (!bus) {
+               printf("Failed to allocate MDIO bus\n");
+               return -ENOMEM;
+       }
+
+       bus->read = ethoc_mdio_read;
+       bus->write = ethoc_mdio_write;
+       snprintf(bus->name, sizeof(bus->name), "%s", name);
+       bus->priv = priv;
+
+       ret = mdio_register(bus);
+       if (ret < 0)
+               return ret;
+
+       priv->bus = miiphy_get_dev_by_name(name);
+       return 0;
+}
+
+static int ethoc_phy_init(struct ethoc *priv, void *dev)
+{
+       struct phy_device *phydev;
+       int mask = 0xffffffff;
+
+#ifdef CONFIG_PHY_ADDR
+       mask = 1 << CONFIG_PHY_ADDR;
+#endif
+
+       phydev = phy_find_by_mask(priv->bus, mask, PHY_INTERFACE_MODE_MII);
+       if (!phydev)
+               return -ENODEV;
+
+       phy_connect_dev(phydev, dev);
+
+       phydev->supported &= PHY_BASIC_FEATURES;
+       phydev->advertising = phydev->supported;
+
+       priv->phydev = phydev;
+       phy_config(phydev);
+
+       return 0;
+}
+
+#else
+
+static inline int ethoc_mdio_init(const char *name, struct ethoc *priv)
+{
+       return 0;
+}
+
+static inline int ethoc_phy_init(struct ethoc *priv, void *dev)
+{
+       return 0;
+}
+
+#endif
+
+#ifdef CONFIG_DM_ETH
+
+static int ethoc_write_hwaddr(struct udevice *dev)
+{
+       struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+       struct ethoc *priv = dev_get_priv(dev);
+       u8 *mac = pdata->eth_pdata.enetaddr;
+
+       return ethoc_write_hwaddr_common(priv, mac);
+}
+
+static int ethoc_send(struct udevice *dev, void *packet, int length)
+{
+       return ethoc_send_common(dev_get_priv(dev), packet, length);
+}
+
+static int ethoc_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+       return ethoc_free_pkt_common(dev_get_priv(dev));
+}
+
+static int ethoc_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+       struct ethoc *priv = dev_get_priv(dev);
+
+       if (flags & ETH_RECV_CHECK_DEVICE)
+               if (!ethoc_is_new_packet_received(priv))
+                       return -EAGAIN;
+
+       return ethoc_rx_common(priv, packetp);
+}
+
+static int ethoc_start(struct udevice *dev)
+{
+       return ethoc_init_common(dev_get_priv(dev));
+}
+
+static void ethoc_stop(struct udevice *dev)
+{
+       ethoc_stop_common(dev_get_priv(dev));
+}
+
+static int ethoc_ofdata_to_platdata(struct udevice *dev)
+{
+       struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+       fdt_addr_t addr;
+
+       pdata->eth_pdata.iobase = dev_get_addr(dev);
+       addr = dev_get_addr_index(dev, 1);
+       if (addr != FDT_ADDR_T_NONE)
+               pdata->packet_base = addr;
+       return 0;
+}
+
+static int ethoc_probe(struct udevice *dev)
+{
+       struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+       struct ethoc *priv = dev_get_priv(dev);
+
+       priv->iobase = ioremap(pdata->eth_pdata.iobase, ETHOC_IOSIZE);
+       if (pdata->packet_base) {
+               priv->packet_phys = pdata->packet_base;
+               priv->packet = ioremap(pdata->packet_base,
+                                      (1 + PKTBUFSRX) * PKTSIZE_ALIGN);
+       }
+
+       ethoc_mdio_init(dev->name, priv);
+       ethoc_phy_init(priv, dev);
+
+       return 0;
+}
+
+static int ethoc_remove(struct udevice *dev)
+{
+       struct ethoc *priv = dev_get_priv(dev);
+
+#ifdef CONFIG_PHYLIB
+       free(priv->phydev);
+       mdio_unregister(priv->bus);
+       mdio_free(priv->bus);
+#endif
+       iounmap(priv->iobase);
+       return 0;
+}
+
+static const struct eth_ops ethoc_ops = {
+       .start          = ethoc_start,
+       .stop           = ethoc_stop,
+       .send           = ethoc_send,
+       .recv           = ethoc_recv,
+       .free_pkt       = ethoc_free_pkt,
+       .write_hwaddr   = ethoc_write_hwaddr,
+};
+
+static const struct udevice_id ethoc_ids[] = {
+       { .compatible = "opencores,ethoc" },
+       { }
+};
+
+U_BOOT_DRIVER(ethoc) = {
+       .name                           = "ethoc",
+       .id                             = UCLASS_ETH,
+       .of_match                       = ethoc_ids,
+       .ofdata_to_platdata             = ethoc_ofdata_to_platdata,
+       .probe                          = ethoc_probe,
+       .remove                         = ethoc_remove,
+       .ops                            = &ethoc_ops,
+       .priv_auto_alloc_size           = sizeof(struct ethoc),
+       .platdata_auto_alloc_size       = sizeof(struct ethoc_eth_pdata),
+};
+
+#else
+
+static int ethoc_init(struct eth_device *dev, bd_t *bd)
+{
+       struct ethoc *priv = (struct ethoc *)dev->priv;
+
+       return ethoc_init_common(priv);
+}
+
+static int ethoc_write_hwaddr(struct eth_device *dev)
+{
+       struct ethoc *priv = (struct ethoc *)dev->priv;
+       u8 *mac = dev->enetaddr;
+
+       return ethoc_write_hwaddr_common(priv, mac);
+}
+
+static int ethoc_send(struct eth_device *dev, void *packet, int length)
+{
+       return ethoc_send_common(dev->priv, packet, length);
+}
+
 static void ethoc_halt(struct eth_device *dev)
 {
-       ethoc_disable_rx_and_tx(dev);
+       ethoc_disable_rx_and_tx(dev->priv);
 }
 
 static int ethoc_recv(struct eth_device *dev)
 {
-       u32 pending;
+       struct ethoc *priv = (struct ethoc *)dev->priv;
+       int count;
 
-       pending = ethoc_read(dev, INT_SOURCE);
-       ethoc_ack_irq(dev, pending);
-       if (pending & INT_MASK_BUSY)
-               debug("%s(): packet dropped\n", __func__);
-       if (pending & INT_MASK_RX) {
-               debug("%s(): rx irq\n", __func__);
-               ethoc_rx(dev, PKTBUFSRX);
-       }
+       if (!ethoc_is_new_packet_received(priv))
+               return 0;
+
+       for (count = 0; count < PKTBUFSRX; ++count) {
+               uchar *packetp;
+               int size = ethoc_rx_common(priv, &packetp);
 
+               if (size < 0)
+                       break;
+               if (size > 0)
+                       net_process_received_packet(packetp, size);
+               ethoc_free_pkt_common(priv);
+       }
        return 0;
 }
 
@@ -503,9 +822,16 @@ int ethoc_initialize(u8 dev_num, int base_addr)
        dev->halt = ethoc_halt;
        dev->send = ethoc_send;
        dev->recv = ethoc_recv;
-       dev->write_hwaddr = ethoc_set_mac_address;
+       dev->write_hwaddr = ethoc_write_hwaddr;
        sprintf(dev->name, "%s-%hu", "ETHOC", dev_num);
+       priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE);
 
        eth_register(dev);
+
+       ethoc_mdio_init(dev->name, priv);
+       ethoc_phy_init(priv, dev);
+
        return 1;
 }
+
+#endif
index 792534b..15a3ce0 100644 (file)
@@ -556,8 +556,17 @@ int mcdmafec_initialize(bd_t * bis)
                eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-               miiphy_register(dev->name,
-                               mcffec_miiphy_read, mcffec_miiphy_write);
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+               mdiodev->read = mcffec_miiphy_read;
+               mdiodev->write = mcffec_miiphy_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
 #endif
 
                if (i > 0)
index 4f17015..8fa767a 100644 (file)
@@ -364,32 +364,35 @@ static int ftmac110_recv(struct eth_device *dev)
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 
-static int ftmac110_mdio_read(
-       const char *devname, uint8_t addr, uint8_t reg, uint16_t *value)
+static int ftmac110_mdio_read(struct mii_dev *bus, int addr, int devad,
+                             int reg)
 {
+       uint16_t value = 0;
        int ret = 0;
        struct eth_device *dev;
 
-       dev = eth_get_dev_by_name(devname);
+       dev = eth_get_dev_by_name(bus->name);
        if (dev == NULL) {
-               printf("%s: no such device\n", devname);
+               printf("%s: no such device\n", bus->name);
                ret = -1;
        } else {
-               *value = mdio_read(dev, addr, reg);
+               value = mdio_read(dev, addr, reg);
        }
 
-       return ret;
+       if (ret < 0)
+               return ret;
+       return value;
 }
 
-static int ftmac110_mdio_write(
-       const char *devname, uint8_t addr, uint8_t reg, uint16_t value)
+static int ftmac110_mdio_write(struct mii_dev *bus, int addr, int devad,
+                              int reg, u16 value)
 {
        int ret = 0;
        struct eth_device *dev;
 
-       dev = eth_get_dev_by_name(devname);
+       dev = eth_get_dev_by_name(bus->name);
        if (dev == NULL) {
-               printf("%s: no such device\n", devname);
+               printf("%s: no such device\n", bus->name);
                ret = -1;
        } else {
                mdio_write(dev, addr, reg, value);
@@ -468,7 +471,17 @@ int ftmac110_initialize(bd_t *bis)
        eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-       miiphy_register(dev->name, ftmac110_mdio_read, ftmac110_mdio_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = ftmac110_mdio_read;
+       mdiodev->write = ftmac110_mdio_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 #endif
 
        card_nr++;
index 6cc273c..2dd69f3 100644 (file)
@@ -226,9 +226,11 @@ DECLARE_GLOBAL_DATA_PTR;
  *
  * Returns 16bit phy register value, or 0xffff on error
  */
-static int mii_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data)
+static int mii_reg_read(struct mii_dev *bus, int phy_adr, int devad,
+                       int reg_ofs)
 {
-       struct eth_device *dev = eth_get_dev_by_name(devname);
+       u16 data = 0;
+       struct eth_device *dev = eth_get_dev_by_name(bus->name);
        struct lpc32xx_eth_device *dlpc32xx_eth = to_lpc32xx_eth(dev);
        struct lpc32xx_eth_registers *regs = dlpc32xx_eth->regs;
        u32 mind_reg;
@@ -270,12 +272,12 @@ static int mii_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data)
                return -EFAULT;
        }
 
-       *data = (u16) readl(&regs->mrdd);
+       data = (u16) readl(&regs->mrdd);
 
        debug("%s:(adr %d, off %d) => %04x\n", __func__, phy_adr,
-             reg_ofs, *data);
+             reg_ofs, data);
 
-       return 0;
+       return data;
 }
 
 /*
@@ -284,9 +286,10 @@ static int mii_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data)
  * Returns 0 if write succeed, -EINVAL on bad parameters
  * -ETIME on timeout
  */
-static int mii_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
+static int mii_reg_write(struct mii_dev *bus, int phy_adr, int devad,
+                        int reg_ofs, u16 data)
 {
-       struct eth_device *dev = eth_get_dev_by_name(devname);
+       struct eth_device *dev = eth_get_dev_by_name(bus->name);
        struct lpc32xx_eth_device *dlpc32xx_eth = to_lpc32xx_eth(dev);
        struct lpc32xx_eth_registers *regs = dlpc32xx_eth->regs;
        u32 mind_reg;
@@ -333,25 +336,6 @@ static int mii_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
 }
 #endif
 
-#if defined(CONFIG_PHYLIB)
-int lpc32xx_eth_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
-       int reg_addr)
-{
-       u16 data;
-       int ret;
-       ret = mii_reg_read(bus->name, phy_addr, reg_addr, &data);
-       if (ret)
-               return ret;
-       return data;
-}
-
-int lpc32xx_eth_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
-       int reg_addr, u16 data)
-{
-       return mii_reg_write(bus->name, phy_addr, reg_addr, data);
-}
-#endif
-
 /*
  * Provide default Ethernet buffers base address if target did not.
  * Locate buffers in SRAM at 0x00001000 to avoid cache issues and
@@ -580,8 +564,8 @@ int lpc32xx_eth_phylib_init(struct eth_device *dev, int phyid)
                printf("mdio_alloc failed\n");
                return -ENOMEM;
        }
-       bus->read = lpc32xx_eth_phy_read;
-       bus->write = lpc32xx_eth_phy_write;
+       bus->read = mii_reg_read;
+       bus->write = mii_reg_write;
        strcpy(bus->name, dev->name);
 
        ret = mdio_register(bus);
@@ -645,7 +629,17 @@ int lpc32xx_eth_initialize(bd_t *bis)
 #if defined(CONFIG_PHYLIB)
        lpc32xx_eth_phylib_init(dev, CONFIG_PHY_ADDR);
 #elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-       miiphy_register(dev->name, mii_reg_read, mii_reg_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = mii_reg_read;
+       mdiodev->write = mii_reg_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 #endif
 
        return 0;
index 0835fdc..921537f 100644 (file)
@@ -43,6 +43,8 @@
 
 #include "macb.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #define MACB_RX_BUFFER_SIZE            4096
 #define MACB_RX_RING_SIZE              (MACB_RX_BUFFER_SIZE / 128)
 #define MACB_TX_RING_SIZE              16
@@ -108,6 +110,10 @@ struct macb_device {
 #endif
        unsigned short          phy_addr;
        struct mii_dev          *bus;
+
+#ifdef CONFIG_DM_ETH
+       phy_interface_t         phy_interface;
+#endif
 };
 #ifndef CONFIG_DM_ETH
 #define to_macb(_nd) container_of(_nd, struct macb_device, netdev)
@@ -199,39 +205,41 @@ void __weak arch_get_mdio_control(const char *name)
 
 #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
 
-int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
+int macb_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg)
 {
+       u16 value = 0;
 #ifdef CONFIG_DM_ETH
-       struct udevice *dev = eth_get_dev_by_name(devname);
+       struct udevice *dev = eth_get_dev_by_name(bus->name);
        struct macb_device *macb = dev_get_priv(dev);
 #else
-       struct eth_device *dev = eth_get_dev_by_name(devname);
+       struct eth_device *dev = eth_get_dev_by_name(bus->name);
        struct macb_device *macb = to_macb(dev);
 #endif
 
        if (macb->phy_addr != phy_adr)
                return -1;
 
-       arch_get_mdio_control(devname);
-       *value = macb_mdio_read(macb, reg);
+       arch_get_mdio_control(bus->name);
+       value = macb_mdio_read(macb, reg);
 
-       return 0;
+       return value;
 }
 
-int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
+int macb_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg,
+                     u16 value)
 {
 #ifdef CONFIG_DM_ETH
-       struct udevice *dev = eth_get_dev_by_name(devname);
+       struct udevice *dev = eth_get_dev_by_name(bus->name);
        struct macb_device *macb = dev_get_priv(dev);
 #else
-       struct eth_device *dev = eth_get_dev_by_name(devname);
+       struct eth_device *dev = eth_get_dev_by_name(bus->name);
        struct macb_device *macb = to_macb(dev);
 #endif
 
        if (macb->phy_addr != phy_adr)
                return -1;
 
-       arch_get_mdio_control(devname);
+       arch_get_mdio_control(bus->name);
        macb_mdio_write(macb, reg, value);
 
        return 0;
@@ -434,7 +442,7 @@ static void macb_phy_reset(struct macb_device *macb, const char *name)
 }
 
 #ifdef CONFIG_MACB_SEARCH_PHY
-static int macb_phy_find(struct macb_device *macb)
+static int macb_phy_find(struct macb_device *macb, const char *name)
 {
        int i;
        u16 phy_id;
@@ -444,21 +452,27 @@ static int macb_phy_find(struct macb_device *macb)
                macb->phy_addr = i;
                phy_id = macb_mdio_read(macb, MII_PHYSID1);
                if (phy_id != 0xffff) {
-                       printf("%s: PHY present at %d\n", macb->netdev.name, i);
+                       printf("%s: PHY present at %d\n", name, i);
                        return 1;
                }
        }
 
        /* PHY isn't up to snuff */
-       printf("%s: PHY not found\n", macb->netdev.name);
+       printf("%s: PHY not found\n", name);
 
        return 0;
 }
 #endif /* CONFIG_MACB_SEARCH_PHY */
 
-
+#ifdef CONFIG_DM_ETH
+static int macb_phy_init(struct udevice *dev, const char *name)
+#else
 static int macb_phy_init(struct macb_device *macb, const char *name)
+#endif
 {
+#ifdef CONFIG_DM_ETH
+       struct macb_device *macb = dev_get_priv(dev);
+#endif
 #ifdef CONFIG_PHYLIB
        struct phy_device *phydev;
 #endif
@@ -470,7 +484,7 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
        arch_get_mdio_control(name);
 #ifdef CONFIG_MACB_SEARCH_PHY
        /* Auto-detect phy_addr */
-       if (!macb_phy_find(macb))
+       if (!macb_phy_find(macb, name))
                return 0;
 #endif /* CONFIG_MACB_SEARCH_PHY */
 
@@ -482,9 +496,14 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
        }
 
 #ifdef CONFIG_PHYLIB
+#ifdef CONFIG_DM_ETH
+       phydev = phy_connect(macb->bus, macb->phy_addr, dev,
+                            macb->phy_interface);
+#else
        /* need to consider other phy interface mode */
        phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev,
                             PHY_INTERFACE_MODE_RGMII);
+#endif
        if (!phydev) {
                printf("phy_connect failed\n");
                return -ENODEV;
@@ -585,8 +604,15 @@ static int gmac_init_multi_queues(struct macb_device *macb)
        return 0;
 }
 
+#ifdef CONFIG_DM_ETH
+static int _macb_init(struct udevice *dev, const char *name)
+#else
 static int _macb_init(struct macb_device *macb, const char *name)
+#endif
 {
+#ifdef CONFIG_DM_ETH
+       struct macb_device *macb = dev_get_priv(dev);
+#endif
        unsigned long paddr;
        int i;
 
@@ -634,13 +660,35 @@ static int _macb_init(struct macb_device *macb, const char *name)
                 * When the GMAC IP without GE feature, this bit is used
                 * to select interface between RMII and MII.
                 */
+#ifdef CONFIG_DM_ETH
+               if (macb->phy_interface == PHY_INTERFACE_MODE_RMII)
+                       gem_writel(macb, UR, GEM_BIT(RGMII));
+               else
+                       gem_writel(macb, UR, 0);
+#else
 #if defined(CONFIG_RGMII) || defined(CONFIG_RMII)
                gem_writel(macb, UR, GEM_BIT(RGMII));
 #else
                gem_writel(macb, UR, 0);
 #endif
+#endif
        } else {
        /* choose RMII or MII mode. This depends on the board */
+#ifdef CONFIG_DM_ETH
+#ifdef CONFIG_AT91FAMILY
+               if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) {
+                       macb_writel(macb, USRIO,
+                                   MACB_BIT(RMII) | MACB_BIT(CLKEN));
+               } else {
+                       macb_writel(macb, USRIO, MACB_BIT(CLKEN));
+               }
+#else
+               if (macb->phy_interface == PHY_INTERFACE_MODE_RMII)
+                       macb_writel(macb, USRIO, 0);
+               else
+                       macb_writel(macb, USRIO, MACB_BIT(MII));
+#endif
+#else
 #ifdef CONFIG_RMII
 #ifdef CONFIG_AT91FAMILY
        macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN));
@@ -654,9 +702,14 @@ static int _macb_init(struct macb_device *macb, const char *name)
        macb_writel(macb, USRIO, MACB_BIT(MII));
 #endif
 #endif /* CONFIG_RMII */
+#endif
        }
 
+#ifdef CONFIG_DM_ETH
+       if (!macb_phy_init(dev, name))
+#else
        if (!macb_phy_init(macb, name))
+#endif
                return -1;
 
        /* Enable TX and RX */
@@ -862,7 +915,17 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
        eth_register(netdev);
 
 #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
-       miiphy_register(netdev->name, macb_miiphy_read, macb_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, netdev->name, MDIO_NAME_LEN);
+       mdiodev->read = macb_miiphy_read;
+       mdiodev->write = macb_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
        macb->bus = miiphy_get_dev_by_name(netdev->name);
 #endif
        return 0;
@@ -873,9 +936,7 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
 
 static int macb_start(struct udevice *dev)
 {
-       struct macb_device *macb = dev_get_priv(dev);
-
-       return _macb_init(macb, dev->name);
+       return _macb_init(dev, dev->name);
 }
 
 static int macb_send(struct udevice *dev, void *packet, int length)
@@ -933,11 +994,33 @@ static int macb_eth_probe(struct udevice *dev)
        struct eth_pdata *pdata = dev_get_platdata(dev);
        struct macb_device *macb = dev_get_priv(dev);
 
+#ifdef CONFIG_DM_ETH
+       const char *phy_mode;
+
+       phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
+       if (phy_mode)
+               macb->phy_interface = phy_get_interface_by_name(phy_mode);
+       if (macb->phy_interface == -1) {
+               debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
+               return -EINVAL;
+       }
+#endif
+
        macb->regs = (void *)pdata->iobase;
 
        _macb_eth_initialize(macb);
 #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
-       miiphy_register(dev->name, macb_miiphy_read, macb_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = macb_miiphy_read;
+       mdiodev->write = macb_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
        macb->bus = miiphy_get_dev_by_name(dev->name);
 #endif
 
index fd73099..e1b06b2 100644 (file)
@@ -595,8 +595,17 @@ int mcffec_initialize(bd_t * bis)
                eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-               miiphy_register(dev->name,
-                               mcffec_miiphy_read, mcffec_miiphy_write);
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+               mdiodev->read = mcffec_miiphy_read;
+               mdiodev->write = mcffec_miiphy_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
 #endif
                if (i > 0)
                        fec_info[i - 1].next = &fec_info[i];
index 17a780c..103e365 100644 (file)
@@ -277,8 +277,7 @@ void __mii_init(void)
  *       Otherwise they hang in mii_send() !!! Sorry!
  */
 
-int mcffec_miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
-                      unsigned short *value)
+int mcffec_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
        short rdreg;            /* register working value */
 
@@ -287,28 +286,22 @@ int mcffec_miiphy_read(const char *devname, unsigned char addr, unsigned char re
 #endif
        rdreg = mii_send(mk_mii_read(addr, reg));
 
-       *value = rdreg;
-
 #ifdef MII_DEBUG
-       printf("0x%04x\n", *value);
+       printf("0x%04x\n", rdreg);
 #endif
 
-       return 0;
+       return rdreg;
 }
 
-int mcffec_miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
-                       unsigned short value)
+int mcffec_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+                       u16 value)
 {
 #ifdef MII_DEBUG
-       printf("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
+       printf("miiphy_write(0x%x) @ 0x%x = 0x%04x\n", reg, addr, value);
 #endif
 
        mii_send(mk_mii_write(addr, reg, value));
 
-#ifdef MII_DEBUG
-       printf("0x%04x\n", value);
-#endif
-
        return 0;
 }
 
index e850672..b3746fb 100644 (file)
@@ -22,8 +22,10 @@ DECLARE_GLOBAL_DATA_PTR;
 #error "CONFIG_MII has to be defined!"
 #endif
 
-int fec512x_miiphy_read(const char *devname, u8 phyAddr, u8 regAddr, u16 * retVal);
-int fec512x_miiphy_write(const char *devname, u8 phyAddr, u8 regAddr, u16 data);
+int fec512x_miiphy_read(struct mii_dev *bus, int phyAddr, int devad,
+                       int regAddr);
+int fec512x_miiphy_write(struct mii_dev *bus, int phyAddr, int devad,
+                        int regAddr, u16 data);
 int mpc512x_fec_init_phy(struct eth_device *dev, bd_t * bis);
 
 static uchar rx_buff[FEC_BUFFER_SIZE];
@@ -639,8 +641,17 @@ int mpc512x_fec_initialize (bd_t * bis)
        eth_register (dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-       miiphy_register (dev->name,
-                       fec512x_miiphy_read, fec512x_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = fec512x_miiphy_read;
+       mdiodev->write = fec512x_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 #endif
 
        /* Clean up space FEC's MIB and FIFO RAM ...*/
@@ -670,8 +681,10 @@ int mpc512x_fec_initialize (bd_t * bis)
 
 /* MII-interface related functions */
 /********************************************************************/
-int fec512x_miiphy_read(const char *devname, u8 phyAddr, u8 regAddr, u16 *retVal)
+int fec512x_miiphy_read(struct mii_dev *bus, int phyAddr, int devad,
+                       int regAddr)
 {
+       u16 retVal = 0;
        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
        volatile fec512x_t *eth = &im->fec;
        u32 reg;                /* convenient holder for the PHY register */
@@ -711,13 +724,14 @@ int fec512x_miiphy_read(const char *devname, u8 phyAddr, u8 regAddr, u16 *retVal
        /*
         * it's now safe to read the PHY's register
         */
-       *retVal = (u16) in_be32(&eth->mii_data);
+       retVal = (u16) in_be32(&eth->mii_data);
 
-       return 0;
+       return retVal;
 }
 
 /********************************************************************/
-int fec512x_miiphy_write(const char *devname, u8 phyAddr, u8 regAddr, u16 data)
+int fec512x_miiphy_write(struct mii_dev *bus, int phyAddr, int devad,
+                        int regAddr, u16 data)
 {
        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
        volatile fec512x_t *eth = &im->fec;
index e13b4cf..d75e858 100644 (file)
@@ -35,8 +35,10 @@ typedef struct {
     uint8 head[16];             /* MAC header(6 + 6 + 2) + 2(aligned) */
 } NBUF;
 
-int fec5xxx_miiphy_read(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 *retVal);
-int fec5xxx_miiphy_write(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 data);
+int fec5xxx_miiphy_read(struct mii_dev *bus, int phyAddr, int devad,
+                       int regAddr);
+int fec5xxx_miiphy_write(struct mii_dev *bus, int phyAddr, int devad,
+                        int regAddr, u16 data);
 
 static int mpc5xxx_fec_init_phy(struct eth_device *dev, bd_t * bis);
 
@@ -917,8 +919,17 @@ int mpc5xxx_fec_initialize(bd_t * bis)
        eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-       miiphy_register (dev->name,
-                       fec5xxx_miiphy_read, fec5xxx_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = fec5xxx_miiphy_read;
+       mdiodev->write = fec5xxx_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 #endif
 
        /*
@@ -941,8 +952,10 @@ int mpc5xxx_fec_initialize(bd_t * bis)
 
 /* MII-interface related functions */
 /********************************************************************/
-int fec5xxx_miiphy_read(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal)
+int fec5xxx_miiphy_read(struct mii_dev *bus, int phyAddr, int devad,
+                       int regAddr)
 {
+       uint16 retVal = 0;
        ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
        uint32 reg;             /* convenient holder for the PHY register */
        uint32 phy;             /* convenient holder for the PHY */
@@ -977,13 +990,14 @@ int fec5xxx_miiphy_read(const char *devname, uint8 phyAddr, uint8 regAddr, uint1
        /*
         * it's now safe to read the PHY's register
         */
-       *retVal = (uint16) eth->mii_data;
+       retVal = (uint16) eth->mii_data;
 
-       return 0;
+       return retVal;
 }
 
 /********************************************************************/
-int fec5xxx_miiphy_write(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 data)
+int fec5xxx_miiphy_write(struct mii_dev *bus, int phyAddr, int devad,
+                        int regAddr, u16 data)
 {
        ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
        uint32 reg;             /* convenient holder for the PHY register */
index b16be92..a1c7ea0 100644 (file)
@@ -48,9 +48,11 @@ DECLARE_GLOBAL_DATA_PTR;
  *
  * Returns 16bit phy register value, or 0xffff on error
  */
-static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
+static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
+                       int reg_ofs)
 {
-       struct eth_device *dev = eth_get_dev_by_name(devname);
+       u16 data = 0;
+       struct eth_device *dev = eth_get_dev_by_name(bus->name);
        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
        struct mvgbe_registers *regs = dmvgbe->regs;
        u32 smi_reg;
@@ -60,8 +62,8 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
        if (phy_adr == MV_PHY_ADR_REQUEST &&
                        reg_ofs == MV_PHY_ADR_REQUEST) {
                /* */
-               *data = (u16) (MVGBE_REG_RD(regs->phyadr) & PHYADR_MASK);
-               return 0;
+               data = (u16) (MVGBE_REG_RD(regs->phyadr) & PHYADR_MASK);
+               return data;
        }
        /* check parameters */
        if (phy_adr > PHYADR_MASK) {
@@ -111,12 +113,12 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
        for (timeout = 0; timeout < MVGBE_PHY_SMI_TIMEOUT; timeout++)
                ;
 
-       *data = (u16) (MVGBE_REG_RD(MVGBE_SMI_REG) & MVGBE_PHY_SMI_DATA_MASK);
+       data = (u16) (MVGBE_REG_RD(MVGBE_SMI_REG) & MVGBE_PHY_SMI_DATA_MASK);
 
        debug("%s:(adr %d, off %d) value= %04x\n", __func__, phy_adr, reg_ofs,
-             *data);
+             data);
 
-       return 0;
+       return data;
 }
 
 /*
@@ -125,9 +127,10 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
  * Returns 0 if write succeed, -EINVAL on bad parameters
  * -ETIME on timeout
  */
-static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
+static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
+                        int reg_ofs, u16 data)
 {
-       struct eth_device *dev = eth_get_dev_by_name(devname);
+       struct eth_device *dev = eth_get_dev_by_name(bus->name);
        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
        struct mvgbe_registers *regs = dmvgbe->regs;
        u32 smi_reg;
@@ -785,7 +788,17 @@ error1:
 #if defined(CONFIG_PHYLIB)
                mvgbe_phylib_init(dev, PHY_BASE_ADR + devnum);
 #elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-               miiphy_register(dev->name, smi_reg_read, smi_reg_write);
+               int retval;
+               struct mii_dev *mdiodev = mdio_alloc();
+               if (!mdiodev)
+                       return -ENOMEM;
+               strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+               mdiodev->read = smi_reg_read;
+               mdiodev->write = smi_reg_write;
+
+               retval = mdio_register(mdiodev);
+               if (retval < 0)
+                       return retval;
                /* Set phy address of the port */
                miiphy_write(dev->name, MV_PHY_ADR_REQUEST,
                                MV_PHY_ADR_REQUEST, PHY_BASE_ADR + devnum);
index 5cda0b8..af676b9 100644 (file)
@@ -230,24 +230,18 @@ static void miiphy_pre(struct bb_miiphy_bus *bus, char read,
  * Returns:
  *   0 on success
  */
-int bb_miiphy_read(const char *devname, unsigned char addr,
-                  unsigned char reg, unsigned short *value)
+int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg)
 {
        short rdreg; /* register working value */
        int v;
        int j; /* counter */
        struct bb_miiphy_bus *bus;
 
-       bus = bb_miiphy_getbus(devname);
+       bus = bb_miiphy_getbus(miidev->name);
        if (bus == NULL) {
                return -1;
        }
 
-       if (value == NULL) {
-               puts("NULL value pointer\n");
-               return -1;
-       }
-
        miiphy_pre (bus, 1, addr, reg);
 
        /* tri-state our MDIO I/O pin so we can read */
@@ -267,8 +261,7 @@ int bb_miiphy_read(const char *devname, unsigned char addr,
                        bus->set_mdc(bus, 1);
                        bus->delay(bus);
                }
-               /* There is no PHY, set value to 0xFFFF and return */
-               *value = 0xFFFF;
+               /* There is no PHY, return */
                return -1;
        }
 
@@ -294,13 +287,11 @@ int bb_miiphy_read(const char *devname, unsigned char addr,
        bus->set_mdc(bus, 1);
        bus->delay(bus);
 
-       *value = rdreg;
-
 #ifdef DEBUG
-       printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value);
+       printf("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, rdreg);
 #endif
 
-       return 0;
+       return rdreg;
 }
 
 
@@ -311,13 +302,13 @@ int bb_miiphy_read(const char *devname, unsigned char addr,
  * Returns:
  *   0 on success
  */
-int bb_miiphy_write (const char *devname, unsigned char addr,
-                    unsigned char reg, unsigned short value)
+int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,
+                   u16 value)
 {
        struct bb_miiphy_bus *bus;
        int j;                  /* counter */
 
-       bus = bb_miiphy_getbus(devname);
+       bus = bb_miiphy_getbus(miidev->name);
        if (bus == NULL) {
                /* Bus not found! */
                return -1;
index 2fa2016..79c1db2 100644 (file)
@@ -566,7 +566,17 @@ int sh_eth_initialize(bd_t *bd)
        eth_register(dev);
 
        bb_miiphy_buses[0].priv = eth;
-       miiphy_register(dev->name, bb_miiphy_read, bb_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = bb_miiphy_read;
+       mdiodev->write = bb_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 
        if (!eth_getenv_enetaddr("ethaddr", dev->enetaddr))
                puts("Please set MAC address\n");
index c85a178..feae8c0 100644 (file)
@@ -219,20 +219,27 @@ static int smc911x_rx(struct eth_device *dev)
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 /* wrapper for smc911x_eth_phy_read */
-static int smc911x_miiphy_read(const char *devname, u8 phy, u8 reg, u16 *val)
+static int smc911x_miiphy_read(struct mii_dev *bus, int phy, int devad,
+                              int reg)
 {
-       struct eth_device *dev = eth_get_dev_by_name(devname);
-       if (dev)
-               return smc911x_eth_phy_read(dev, phy, reg, val);
-       return -1;
+       u16 val = 0;
+       struct eth_device *dev = eth_get_dev_by_name(bus->name);
+       if (dev) {
+               int retval = smc911x_eth_phy_read(dev, phy, reg, &val);
+               if (retval < 0)
+                       return retval;
+               return val;
+       }
+       return -ENODEV;
 }
 /* wrapper for smc911x_eth_phy_write */
-static int smc911x_miiphy_write(const char *devname, u8 phy, u8 reg, u16 val)
+static int smc911x_miiphy_write(struct mii_dev *bus, int phy, int devad,
+                               int reg, u16 val)
 {
-       struct eth_device *dev = eth_get_dev_by_name(devname);
+       struct eth_device *dev = eth_get_dev_by_name(bus->name);
        if (dev)
                return smc911x_eth_phy_write(dev, phy, reg, val);
-       return -1;
+       return -ENODEV;
 }
 #endif
 
@@ -276,7 +283,17 @@ int smc911x_initialize(u8 dev_num, int base_addr)
        eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-       miiphy_register(dev->name, smc911x_miiphy_read, smc911x_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = smc911x_miiphy_read;
+       mdiodev->write = smc911x_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 #endif
 
        return 1;
index 26aa2b0..669e37b 100644 (file)
@@ -31,6 +31,7 @@ config PCI_SANDBOX
 config PCI_TEGRA
        bool "Tegra PCI support"
        depends on TEGRA
+       depends on (TEGRA186 && POWER_DOMAIN) || (!TEGRA186)
        help
          Enable support for the PCIe controller found on some generations of
          Tegra. Tegra20 has 2 root ports with a total of 4 lanes, Tegra30 has
index 352cdef..ea8adb9 100644 (file)
 #define pr_fmt(fmt) "tegra-pcie: " fmt
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
 #include <pci.h>
+#include <power-domain.h>
+#include <reset.h>
 
 #include <asm/io.h>
 #include <asm/gpio.h>
 
+#include <linux/list.h>
+
+#ifndef CONFIG_TEGRA186
 #include <asm/arch/clock.h>
 #include <asm/arch/powergate.h>
 #include <asm/arch-tegra/xusb-padctl.h>
-
-#include <linux/list.h>
-
 #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
+#endif
+
+/*
+ * FIXME: TODO: This driver contains a number of ifdef CONFIG_TEGRA186 that
+ * should not be present. These are needed because newer Tegra SoCs support
+ * only the standard clock/reset APIs, whereas older Tegra SoCs support only
+ * a custom Tegra-specific API. ASAP the older Tegra SoCs' code should be
+ * fixed to implement the standard APIs, and all drivers converted to solely
+ * use the new standard APIs, with no ifdefs.
+ */
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -103,6 +116,9 @@ DECLARE_GLOBAL_DATA_PTR;
 #define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222       (0x1 << 20)
 #define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1     (0x1 << 20)
 #define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411       (0x2 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_401  (0x0 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_211  (0x1 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_111  (0x2 << 20)
 
 #define AFI_FUSE                       0x104
 #define  AFI_FUSE_PCIE_T0_GEN2_DIS     (1 << 2)
@@ -110,6 +126,7 @@ DECLARE_GLOBAL_DATA_PTR;
 #define AFI_PEX0_CTRL                  0x110
 #define AFI_PEX1_CTRL                  0x118
 #define AFI_PEX2_CTRL                  0x128
+#define AFI_PEX2_CTRL_T186             0x19c
 #define  AFI_PEX_CTRL_RST              (1 << 0)
 #define  AFI_PEX_CTRL_CLKREQ_EN                (1 << 1)
 #define  AFI_PEX_CTRL_REFCLK_EN                (1 << 3)
@@ -173,6 +190,7 @@ enum tegra_pci_id {
        TEGRA30_PCIE,
        TEGRA124_PCIE,
        TEGRA210_PCIE,
+       TEGRA186_PCIE,
 };
 
 struct tegra_pcie_port {
@@ -189,6 +207,7 @@ struct tegra_pcie_soc {
        unsigned int num_ports;
        unsigned long pads_pll_ctl;
        unsigned long tx_ref_sel;
+       unsigned long afi_pex2_ctrl;
        u32 pads_refclk_cfg0;
        u32 pads_refclk_cfg1;
        bool has_pex_clkreq_en;
@@ -209,7 +228,17 @@ struct tegra_pcie {
        unsigned long xbar;
 
        const struct tegra_pcie_soc *soc;
+
+#ifdef CONFIG_TEGRA186
+       struct clk clk_afi;
+       struct clk clk_pex;
+       struct reset_ctl reset_afi;
+       struct reset_ctl reset_pex;
+       struct reset_ctl reset_pcie_x;
+       struct power_domain pwrdom;
+#else
        struct tegra_xusb_phy *phy;
+#endif
 };
 
 static void afi_writel(struct tegra_pcie *pcie, unsigned long value,
@@ -229,10 +258,12 @@ static void pads_writel(struct tegra_pcie *pcie, unsigned long value,
        writel(value, pcie->pads.start + offset);
 }
 
+#ifndef CONFIG_TEGRA186
 static unsigned long pads_readl(struct tegra_pcie *pcie, unsigned long offset)
 {
        return readl(pcie->pads.start + offset);
 }
+#endif
 
 static unsigned long rp_readl(struct tegra_pcie_port *port,
                              unsigned long offset)
@@ -400,6 +431,24 @@ static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes,
                        return 0;
                }
                break;
+       case TEGRA186_PCIE:
+               switch (lanes) {
+               case 0x0010004:
+                       debug("x4 x1 configuration\n");
+                       *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_401;
+                       return 0;
+
+               case 0x0010102:
+                       debug("x2 x1 x1 configuration\n");
+                       *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_211;
+                       return 0;
+
+               case 0x0010101:
+                       debug("x1 x1 x1 configuration\n");
+                       *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_111;
+                       return 0;
+               }
+               break;
        default:
                break;
        }
@@ -471,6 +520,7 @@ static int tegra_pcie_parse_dt(const void *fdt, int node, enum tegra_pci_id id,
                return err;
        }
 
+#ifndef CONFIG_TEGRA186
        pcie->phy = tegra_xusb_phy_get(TEGRA_XUSB_PADCTL_PCIE);
        if (pcie->phy) {
                err = tegra_xusb_phy_prepare(pcie->phy);
@@ -479,6 +529,7 @@ static int tegra_pcie_parse_dt(const void *fdt, int node, enum tegra_pci_id id,
                        return err;
                }
        }
+#endif
 
        fdt_for_each_subnode(fdt, subnode, node) {
                unsigned int index = 0, num_lanes = 0;
@@ -523,6 +574,44 @@ static int tegra_pcie_parse_dt(const void *fdt, int node, enum tegra_pci_id id,
        return 0;
 }
 
+#ifdef CONFIG_TEGRA186
+static int tegra_pcie_power_on(struct tegra_pcie *pcie)
+{
+       int ret;
+
+       ret = power_domain_on(&pcie->pwrdom);
+       if (ret) {
+               error("power_domain_on() failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = clk_enable(&pcie->clk_afi);
+       if (ret) {
+               error("clk_enable(afi) failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = clk_enable(&pcie->clk_pex);
+       if (ret) {
+               error("clk_enable(pex) failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = reset_deassert(&pcie->reset_afi);
+       if (ret) {
+               error("reset_deassert(afi) failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = reset_deassert(&pcie->reset_pex);
+       if (ret) {
+               error("reset_deassert(pex) failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+#else
 static int tegra_pcie_power_on(struct tegra_pcie *pcie)
 {
        const struct tegra_pcie_soc *soc = pcie->soc;
@@ -639,6 +728,7 @@ static int tegra_pcie_phy_enable(struct tegra_pcie *pcie)
 
        return 0;
 }
+#endif
 
 static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
 {
@@ -647,7 +737,11 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
        u32 value;
        int err;
 
+#ifdef CONFIG_TEGRA186
+       {
+#else
        if (pcie->phy) {
+#endif
                value = afi_readl(pcie, AFI_PLLE_CONTROL);
                value &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
                value |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
@@ -675,6 +769,7 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
 
        afi_writel(pcie, value, AFI_FUSE);
 
+#ifndef CONFIG_TEGRA186
        if (pcie->phy)
                err = tegra_xusb_phy_enable(pcie->phy);
        else
@@ -684,9 +779,18 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
                error("failed to power on PHY: %d\n", err);
                return err;
        }
+#endif
 
        /* take the PCIEXCLK logic out of reset */
+#ifdef CONFIG_TEGRA186
+       err = reset_deassert(&pcie->reset_pcie_x);
+       if (err) {
+               error("reset_deassert(pcie_x) failed: %d\n", err);
+               return err;
+       }
+#else
        reset_set_enable(PERIPH_ID_PCIEXCLK, 0);
+#endif
 
        /* finally enable PCIe */
        value = afi_readl(pcie, AFI_CONFIGURATION);
@@ -787,7 +891,7 @@ static unsigned long tegra_pcie_port_get_pex_ctrl(struct tegra_pcie_port *port)
                break;
 
        case 2:
-               ret = AFI_PEX2_CTRL;
+               ret = port->pcie->soc->afi_pex2_ctrl;
                break;
        }
 
@@ -945,6 +1049,7 @@ static const struct tegra_pcie_soc pci_tegra_soc[] = {
                .num_ports = 3,
                .pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
                .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
+               .afi_pex2_ctrl = AFI_PEX2_CTRL,
                .pads_refclk_cfg0 = 0xfa5cfa5c,
                .pads_refclk_cfg1 = 0xfa5cfa5c,
                .has_pex_clkreq_en = true,
@@ -972,7 +1077,16 @@ static const struct tegra_pcie_soc pci_tegra_soc[] = {
                .has_cml_clk = true,
                .has_gen2 = true,
                .force_pca_enable = true,
-       }
+       },
+       [TEGRA186_PCIE] = {
+               .num_ports = 3,
+               .afi_pex2_ctrl = AFI_PEX2_CTRL_T186,
+               .pads_refclk_cfg0 = 0x80b880b8,
+               .pads_refclk_cfg1 = 0x000480b8,
+               .has_pex_clkreq_en = true,
+               .has_pex_bias_ctrl = true,
+               .has_gen2 = true,
+       },
 };
 
 static int pci_tegra_ofdata_to_platdata(struct udevice *dev)
@@ -996,6 +1110,44 @@ static int pci_tegra_probe(struct udevice *dev)
        struct tegra_pcie *pcie = dev_get_priv(dev);
        int err;
 
+#ifdef CONFIG_TEGRA186
+       err = clk_get_by_name(dev, "afi", &pcie->clk_afi);
+       if (err) {
+               debug("clk_get_by_name(afi) failed: %d\n", err);
+               return err;
+       }
+
+       err = clk_get_by_name(dev, "pex", &pcie->clk_pex);
+       if (err) {
+               debug("clk_get_by_name(pex) failed: %d\n", err);
+               return err;
+       }
+
+       err = reset_get_by_name(dev, "afi", &pcie->reset_afi);
+       if (err) {
+               debug("reset_get_by_name(afi) failed: %d\n", err);
+               return err;
+       }
+
+       err = reset_get_by_name(dev, "pex", &pcie->reset_pex);
+       if (err) {
+               debug("reset_get_by_name(pex) failed: %d\n", err);
+               return err;
+       }
+
+       err = reset_get_by_name(dev, "pcie_x", &pcie->reset_pcie_x);
+       if (err) {
+               debug("reset_get_by_name(pcie_x) failed: %d\n", err);
+               return err;
+       }
+
+       err = power_domain_get(dev, &pcie->pwrdom);
+       if (err) {
+               debug("power_domain_get() failed: %d\n", err);
+               return err;
+       }
+#endif
+
        err = tegra_pcie_power_on(pcie);
        if (err < 0) {
                error("failed to power on");
@@ -1033,6 +1185,7 @@ static const struct udevice_id pci_tegra_ids[] = {
        { .compatible = "nvidia,tegra30-pcie", .data = TEGRA30_PCIE },
        { .compatible = "nvidia,tegra124-pcie", .data = TEGRA124_PCIE },
        { .compatible = "nvidia,tegra210-pcie", .data = TEGRA210_PCIE },
+       { .compatible = "nvidia,tegra186-pcie", .data = TEGRA186_PCIE },
        { }
 };
 
index b904097..132e332 100644 (file)
@@ -17,4 +17,11 @@ config SANDBOX_POWER_DOMAIN
          simply accepts requests to power on/off various HW modules without
          actually doing anything beyond a little error checking.
 
+config TEGRA186_POWER_DOMAIN
+       bool "Enable Tegra186 BPMP-based power domain driver"
+       depends on TEGRA186_BPMP
+       help
+         Enable support for manipulating Tegra's on-SoC power domains via IPC
+         requests to the BPMP (Boot and Power Management Processor).
+
 endmenu
index c18292f..2c3d926 100644 (file)
@@ -5,3 +5,4 @@
 obj-$(CONFIG_POWER_DOMAIN) += power-domain-uclass.o
 obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
 obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o
+obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o
diff --git a/drivers/power/domain/tegra186-power-domain.c b/drivers/power/domain/tegra186-power-domain.c
new file mode 100644 (file)
index 0000000..41d84de
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <misc.h>
+#include <power-domain-uclass.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+
+#define UPDATE BIT(0)
+#define ON     BIT(1)
+
+static int tegra186_power_domain_request(struct power_domain *power_domain)
+{
+       debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
+             power_domain, power_domain->dev, power_domain->id);
+
+       return 0;
+}
+
+static int tegra186_power_domain_free(struct power_domain *power_domain)
+{
+       debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
+             power_domain, power_domain->dev, power_domain->id);
+
+       return 0;
+}
+
+static int tegra186_power_domain_common(struct power_domain *power_domain,
+                                       bool on)
+{
+       struct mrq_pg_update_state_request req;
+       int on_state = on ? ON : 0;
+       int ret;
+
+       req.partition_id = power_domain->id;
+       req.logic_state = UPDATE | on_state;
+       req.sram_state = UPDATE | on_state;
+       /*
+        * Drivers manage their own clocks so they don't get out of sync, and
+        * since some power domains have many clocks, only a subset of which
+        * are actually needed depending on use-case.
+        */
+       req.clock_state = UPDATE;
+
+       ret = misc_call(power_domain->dev->parent, MRQ_PG_UPDATE_STATE, &req,
+                       sizeof(req), NULL, 0);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int tegra186_power_domain_on(struct power_domain *power_domain)
+{
+       debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
+             power_domain, power_domain->dev, power_domain->id);
+
+       return tegra186_power_domain_common(power_domain, true);
+}
+
+static int tegra186_power_domain_off(struct power_domain *power_domain)
+{
+       debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
+             power_domain, power_domain->dev, power_domain->id);
+
+       return tegra186_power_domain_common(power_domain, false);
+}
+
+struct power_domain_ops tegra186_power_domain_ops = {
+       .request = tegra186_power_domain_request,
+       .free = tegra186_power_domain_free,
+       .on = tegra186_power_domain_on,
+       .off = tegra186_power_domain_off,
+};
+
+static int tegra186_power_domain_probe(struct udevice *dev)
+{
+       debug("%s(dev=%p)\n", __func__, dev);
+
+       return 0;
+}
+
+U_BOOT_DRIVER(tegra186_power_domain) = {
+       .name = "tegra186_power_domain",
+       .id = UCLASS_POWER_DOMAIN,
+       .probe = tegra186_power_domain_probe,
+       .ops = &tegra186_power_domain_ops,
+};
index 40cccc2..468c92e 100644 (file)
@@ -623,20 +623,20 @@ static int uec_miiphy_find_dev_by_name(const char *devname)
  * Returns:
  *  0 on success
  */
-static int uec_miiphy_read(const char *devname, unsigned char addr,
-                           unsigned char reg, unsigned short *value)
+static int uec_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+       unsigned short value = 0;
        int devindex = 0;
 
-       if (devname == NULL || value == NULL) {
+       if (bus->name == NULL) {
                debug("%s: NULL pointer given\n", __FUNCTION__);
        } else {
-               devindex = uec_miiphy_find_dev_by_name(devname);
+               devindex = uec_miiphy_find_dev_by_name(bus->name);
                if (devindex >= 0) {
-                       *value = uec_read_phy_reg(devlist[devindex], addr, reg);
+                       value = uec_read_phy_reg(devlist[devindex], addr, reg);
                }
        }
-       return 0;
+       return value;
 }
 
 /*
@@ -645,15 +645,15 @@ static int uec_miiphy_read(const char *devname, unsigned char addr,
  * Returns:
  *  0 on success
  */
-static int uec_miiphy_write(const char *devname, unsigned char addr,
-                            unsigned char reg, unsigned short value)
+static int uec_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+                           u16 value)
 {
        int devindex = 0;
 
-       if (devname == NULL) {
+       if (bus->name == NULL) {
                debug("%s: NULL pointer given\n", __FUNCTION__);
        } else {
-               devindex = uec_miiphy_find_dev_by_name(devname);
+               devindex = uec_miiphy_find_dev_by_name(bus->name);
                if (devindex >= 0) {
                        uec_write_phy_reg(devlist[devindex], addr, reg, value);
                }
@@ -1399,7 +1399,17 @@ int uec_initialize(bd_t *bis, uec_info_t *uec_info)
        }
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-       miiphy_register(dev->name, uec_miiphy_read, uec_miiphy_write);
+       int retval;
+       struct mii_dev *mdiodev = mdio_alloc();
+       if (!mdiodev)
+               return -ENOMEM;
+       strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+       mdiodev->read = uec_miiphy_read;
+       mdiodev->write = uec_miiphy_write;
+
+       retval = mdio_register(mdiodev);
+       if (retval < 0)
+               return retval;
 #endif
 
        return 1;
index 0fe8cc3..5b84f21 100644 (file)
@@ -20,4 +20,11 @@ config SANDBOX_RESET
          simply accepts requests to reset various HW modules without actually
          doing anything beyond a little error checking.
 
+config TEGRA186_RESET
+       bool "Enable Tegra186 BPMP-based reset driver"
+       depends on TEGRA186_BPMP
+       help
+         Enable support for manipulating Tegra's on-SoC reset signals via IPC
+         requests to the BPMP (Boot and Power Management Processor).
+
 endmenu
index 71f3b21..ff0e090 100644 (file)
@@ -5,3 +5,4 @@
 obj-$(CONFIG_DM_RESET) += reset-uclass.o
 obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset.o
 obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o
+obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
diff --git a/drivers/reset/tegra186-reset.c b/drivers/reset/tegra186-reset.c
new file mode 100644 (file)
index 0000000..228adda
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <misc.h>
+#include <reset-uclass.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+
+static int tegra186_reset_request(struct reset_ctl *reset_ctl)
+{
+       debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+             reset_ctl->dev, reset_ctl->id);
+
+       return 0;
+}
+
+static int tegra186_reset_free(struct reset_ctl *reset_ctl)
+{
+       debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+             reset_ctl->dev, reset_ctl->id);
+
+       return 0;
+}
+
+static int tegra186_reset_common(struct reset_ctl *reset_ctl,
+                                enum mrq_reset_commands cmd)
+{
+       struct mrq_reset_request req;
+       int ret;
+
+       req.cmd = cmd;
+       req.reset_id = reset_ctl->id;
+
+       ret = misc_call(reset_ctl->dev->parent, MRQ_RESET, &req, sizeof(req),
+                       NULL, 0);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int tegra186_reset_assert(struct reset_ctl *reset_ctl)
+{
+       debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+             reset_ctl->dev, reset_ctl->id);
+
+       return tegra186_reset_common(reset_ctl, CMD_RESET_ASSERT);
+}
+
+static int tegra186_reset_deassert(struct reset_ctl *reset_ctl)
+{
+       debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+             reset_ctl->dev, reset_ctl->id);
+
+       return tegra186_reset_common(reset_ctl, CMD_RESET_DEASSERT);
+}
+
+struct reset_ops tegra186_reset_ops = {
+       .request = tegra186_reset_request,
+       .free = tegra186_reset_free,
+       .rst_assert = tegra186_reset_assert,
+       .rst_deassert = tegra186_reset_deassert,
+};
+
+static int tegra186_reset_probe(struct udevice *dev)
+{
+       debug("%s(dev=%p)\n", __func__, dev);
+
+       return 0;
+}
+
+U_BOOT_DRIVER(tegra186_reset) = {
+       .name           = "tegra186_reset",
+       .id             = UCLASS_RESET,
+       .probe          = tegra186_reset_probe,
+       .ops = &tegra186_reset_ops,
+};
index 08eaed5..7d9abfd 100644 (file)
@@ -391,8 +391,8 @@ static int smsc95xx_write_hwaddr_common(struct usb_device *udev,
                                        struct smsc95xx_private *priv,
                                        unsigned char *enetaddr)
 {
-       u32 addr_lo = __get_unaligned_le32(&enetaddr[0]);
-       u32 addr_hi = __get_unaligned_le16(&enetaddr[4]);
+       u32 addr_lo = get_unaligned_le32(&enetaddr[0]);
+       u32 addr_hi = get_unaligned_le16(&enetaddr[4]);
        int ret;
 
        /* set hardware address */
index e6a811a..28ea15b 100644 (file)
@@ -95,6 +95,7 @@
 
 /* Ethernet */
 #define CONFIG_MACB
+#define CONFIG_PHYLIB
 #define CONFIG_RMII
 #define CONFIG_NET_RETRY_COUNT         20
 #define CONFIG_AT91_WANTS_COMMON_PHY
index 913256a..227c0ca 100644 (file)
@@ -44,7 +44,6 @@
 /*
  * Ethernet
  */
-#define CONFIG_ETHOC
 #define CONFIG_SYS_ETHOC_BASE          0x92000000
 
 #define CONFIG_BOOTFILE                        "boot.img"
index 257283f..1f64405 100644 (file)
@@ -14,6 +14,9 @@
 /* High-level configuration options */
 #define CONFIG_TEGRA_BOARD_STRING      "NVIDIA P2771-0000"
 
+/* I2C */
+#define CONFIG_SYS_I2C_TEGRA
+
 /* SD/MMC */
 #define CONFIG_MMC
 #define CONFIG_GENERIC_MMC
 #define CONFIG_SYS_MMC_ENV_PART                2
 #define CONFIG_ENV_OFFSET              (-CONFIG_ENV_SIZE)
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+
 #include "tegra-common-post.h"
 
 /* Crystal is 38.4MHz. clk_m runs at half that rate */
index 6add391..076a5ce 100644 (file)
  *
  */
 #define CONFIG_MACB
+#define CONFIG_PHYLIB
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 #define CONFIG_USB_ETHER_MCS7830
index fd6c70e..c91ab71 100644 (file)
@@ -56,6 +56,7 @@
 
 /* Ethernet */
 #define CONFIG_MACB
+#define CONFIG_PHYLIB
 #define CONFIG_RMII
 #define CONFIG_NET_RETRY_COUNT         20
 #define CONFIG_RESET_PHY_R
index 882a4e5..2d091db 100644 (file)
@@ -99,6 +99,7 @@
 
 /* Ethernet */
 #define CONFIG_MACB
+#define CONFIG_PHYLIB
 #define CONFIG_RMII
 #define CONFIG_AT91_WANTS_COMMON_PHY
 
index b761640..9d49f63 100644 (file)
@@ -37,7 +37,8 @@
 #define CONFIG_ENV_SPI_MAX_HZ          48000000
 #define CONFIG_ENV_SPI_MODE            SPI_MODE_0
 #define CONFIG_ENV_SECT_SIZE           CONFIG_ENV_SIZE
-#define CONFIG_ENV_OFFSET              (512 * 1024)
+/* 1MiB flash, environment located as high as possible */
+#define CONFIG_ENV_OFFSET              (SZ_1M - CONFIG_ENV_SIZE)
 
 /* USB Host support */
 #define CONFIG_USB_EHCI
diff --git a/include/dm/platform_data/net_ethoc.h b/include/dm/platform_data/net_ethoc.h
new file mode 100644 (file)
index 0000000..3f94bde
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef _ETHOC_H
+#define _ETHOC_H
+
+#include <net.h>
+
+#ifdef CONFIG_DM_ETH
+
+struct ethoc_eth_pdata {
+       struct eth_pdata eth_pdata;
+       phys_addr_t packet_base;
+};
+
+#endif
+
+#endif /* _ETHOC_H */
index af12274..83141b4 100644 (file)
 #include <net.h>
 #include <phy.h>
 
-struct legacy_mii_dev {
-       int (*read)(const char *devname, unsigned char addr,
-                    unsigned char reg, unsigned short *value);
-       int (*write)(const char *devname, unsigned char addr,
-                     unsigned char reg, unsigned short value);
-};
-
 int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
                 unsigned short *value);
 int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
@@ -44,12 +37,6 @@ int miiphy_link(const char *devname, unsigned char addr);
 
 void miiphy_init(void);
 
-void miiphy_register(const char *devname,
-                     int (*read)(const char *devname, unsigned char addr,
-                                  unsigned char reg, unsigned short *value),
-                     int (*write)(const char *devname, unsigned char addr,
-                                   unsigned char reg, unsigned short value));
-
 int miiphy_set_current_dev(const char *devname);
 const char *miiphy_get_current_dev(void);
 struct mii_dev *mdio_get_current_dev(void);
@@ -86,10 +73,9 @@ extern struct bb_miiphy_bus bb_miiphy_buses[];
 extern int bb_miiphy_buses_num;
 
 void bb_miiphy_init(void);
-int bb_miiphy_read(const char *devname, unsigned char addr,
-                   unsigned char reg, unsigned short *value);
-int bb_miiphy_write(const char *devname, unsigned char addr,
-                    unsigned char reg, unsigned short value);
+int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg);
+int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,
+                   u16 value);
 #endif
 
 /* phy seed setup */
diff --git a/scripts/coccinelle/net/mdio_register.cocci b/scripts/coccinelle/net/mdio_register.cocci
new file mode 100644 (file)
index 0000000..100f102
--- /dev/null
@@ -0,0 +1,142 @@
+/// Use mdio_alloc and mdio_register instead of miiphy_register
+///
+//# Stop using the oldest mii interface in drivers
+//
+// Confidence: High
+// Copyright: (C) 2016 Joe Hershberger.  GPLv2.
+// Comments:
+// Options: --include-headers --recursive-includes --local-includes -I include
+
+@ mii_reg @
+expression devname;
+identifier readfunc, writefunc;
+@@
+
++ int retval;
+- miiphy_register(devname, readfunc, writefunc);
++ struct mii_dev *mdiodev = mdio_alloc();
++ if (!mdiodev) return -ENOMEM;
++ strncpy(mdiodev->name, devname, MDIO_NAME_LEN);
++ mdiodev->read = readfunc;
++ mdiodev->write = writefunc;
++ 
++ retval = mdio_register(mdiodev);
++ if (retval < 0) return retval;
+
+@ update_read_sig @
+identifier mii_reg.readfunc;
+identifier name0, addr0, reg0, output;
+type addrT, outputT;
+@@
+
+- readfunc (
+-      const char *name0,
+-      addrT addr0,
+-      addrT reg0,
+-      outputT *output
+- )
++ readfunc (
++      struct mii_dev *bus,
++      int addr0,
++      int devad,
++      int reg0
++ )
+  {
+  ...
+  }
+
+@ update_read_impl @
+identifier mii_reg.readfunc;
+identifier update_read_sig.output;
+type update_read_sig.outputT;
+constant c;
+identifier retvar;
+expression E;
+@@
+
+  readfunc (...)
+  {
++ outputT output = 0;
+  ...
+(
+- return 0;
++ return *output;
+|
+  return c;
+|
+- return retvar;
++ if (retvar < 0)
++      return retvar;
++ return *output;
+|
+- return E;
++ int retval = E;
++ if (retval < 0)
++      return retval;
++ return *output;
+)
+  }
+
+@ update_read_impl2 @
+identifier mii_reg.readfunc;
+identifier update_read_sig.output;
+@@
+
+  readfunc (...)
+  {
+  <...
+(
+- *output
++ output
+|
+- output
++ &output
+)
+  ...>
+  }
+
+@ update_read_name @
+identifier mii_reg.readfunc;
+identifier update_read_sig.name0;
+@@
+  readfunc (...) {
+  <...
+- name0
++ bus->name
+  ...>
+  }
+
+@ update_write_sig @
+identifier mii_reg.writefunc;
+identifier name0, addr0, reg0, value0;
+type addrT, valueT;
+typedef u16;
+@@
+
+- writefunc (
+-      const char *name0,
+-      addrT addr0,
+-      addrT reg0,
+-      valueT value0
+- )
++ writefunc (
++      struct mii_dev *bus,
++      int addr0,
++      int devad,
++      int reg0,
++      u16 value0
++ )
+  {
+  ...
+  }
+
+@ update_write_name @
+identifier mii_reg.writefunc;
+identifier update_write_sig.name0;
+@@
+  writefunc (...) {
+  <...
+- name0
++ bus->name
+  ...>
+  }