[dev][aml-ethernet-s912] Convert to a composite device driver.
This driver now uses composite protocol to access I2C and GPIOs.
TEST: pave vim2 over ethernet.
Change-Id: I6db6552be21b80e3aa79947c21feb4cc5044cbd7
diff --git a/zircon/system/dev/board/vim/vim-eth.cpp b/zircon/system/dev/board/vim/vim-eth.cpp
index 6f051da..f964e95 100644
--- a/zircon/system/dev/board/vim/vim-eth.cpp
+++ b/zircon/system/dev/board/vim/vim-eth.cpp
@@ -15,17 +15,9 @@
#include <limits.h>
#include "vim.h"
+#include "vim-gpios.h"
+
namespace vim {
-static const pbus_gpio_t eth_board_gpios[] = {
- {
- // MAC_RST
- .gpio = S912_GPIOZ(14),
- },
- {
- // MAC_INTR (need to wire up interrupt?)
- .gpio = S912_GPIOZ(15),
- },
-};
static const pbus_irq_t eth_mac_irqs[] = {
{
@@ -96,13 +88,6 @@
},
};
-static const pbus_i2c_channel_t vim2_mcu_i2c[] = {
- {
- .bus_id = 1,
- .address = 0x18,
- },
-};
-
static pbus_dev_t eth_board_dev = [](){
pbus_dev_t dev;
dev.name = "ethernet_mac";
@@ -111,10 +96,6 @@
dev.did = PDEV_DID_AMLOGIC_ETH;
dev.mmio_list = eth_board_mmios;
dev.mmio_count = countof(eth_board_mmios);
- dev.gpio_list = eth_board_gpios;
- dev.gpio_count = countof(eth_board_gpios);
- dev.i2c_channel_list = vim2_mcu_i2c;
- dev.i2c_channel_count = countof(vim2_mcu_i2c);
dev.metadata_list = eth_board_metadata;
dev.metadata_count = countof(eth_board_metadata);
return dev;
@@ -138,10 +119,43 @@
return dev;
}();
-// Composite binding rules for ethernet driver.
static const zx_bind_inst_t root_match[] = {
BI_MATCH(),
};
+
+// Composite binding rules for ethernet board driver.
+const zx_bind_inst_t i2c_match[] = {
+ BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_I2C),
+ BI_ABORT_IF(NE, BIND_I2C_BUS_ID, 1),
+ BI_MATCH_IF(EQ, BIND_I2C_ADDRESS, 0x18),
+};
+static const zx_bind_inst_t gpio_reset_match[] = {
+ BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+ BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_ETH_MAC_RST),
+};
+static const zx_bind_inst_t gpio_int_match[] = {
+ BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+ BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_ETH_MAC_INTR),
+};
+static const device_component_part_t i2c_component[] = {
+ { countof(root_match), root_match },
+ { countof(i2c_match), i2c_match },
+};
+static const device_component_part_t gpio_reset_component[] = {
+ { countof(root_match), root_match },
+ { countof(gpio_reset_match), gpio_reset_match },
+};
+static const device_component_part_t gpio_int_component[] = {
+ { countof(root_match), root_match },
+ { countof(gpio_int_match), gpio_int_match },
+};
+static const device_component_t eth_components[] = {
+ { countof(i2c_component), i2c_component },
+ { countof(gpio_reset_component), gpio_reset_component },
+ { countof(gpio_int_component), gpio_int_component },
+};
+
+// Composite binding rules for dwmac.
static const zx_bind_inst_t eth_board_match[] = {
BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_ETH_BOARD),
BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_DESIGNWARE),
@@ -151,7 +165,7 @@
{ fbl::count_of(root_match), root_match },
{ fbl::count_of(eth_board_match), eth_board_match },
};
-static const device_component_t components[] = {
+static const device_component_t dwmac_components[] = {
{ fbl::count_of(eth_board_component), eth_board_component },
};
@@ -175,14 +189,17 @@
gpio_impl_.SetAltFunction(S912_ETH_TXD2, S912_ETH_TXD2_FN);
gpio_impl_.SetAltFunction(S912_ETH_TXD3, S912_ETH_TXD3_FN);
- auto status = pbus_.DeviceAdd(ð_board_dev);
+ // Add a composite device for ethernet board in a new devhost.
+ auto status = pbus_.CompositeDeviceAdd(ð_board_dev, eth_components,
+ fbl::count_of(eth_components), UINT32_MAX);
if (status != ZX_OK) {
- zxlogf(ERROR, "%s: pbus_device_add failed: %d\n", __func__, status);
+ zxlogf(ERROR, "%s: CompositeDeviceAdd failed: %d\n", __func__, status);
return status;
}
- // Add a composite device for dwmac driver.
- status = pbus_.CompositeDeviceAdd(&dwmac_dev, components, fbl::count_of(components), 1);
+ // Add a composite device for dwmac driver in the ethernet board driver's devhost.
+ status = pbus_.CompositeDeviceAdd(&dwmac_dev, dwmac_components, fbl::count_of(dwmac_components),
+ 1);
if (status != ZX_OK) {
zxlogf(ERROR, "%s: CompositeDeviceAdd failed: %d\n", __func__, status);
return status;
diff --git a/zircon/system/dev/board/vim/vim-gpio.cpp b/zircon/system/dev/board/vim/vim-gpio.cpp
index e78c8fc..0ed445d 100644
--- a/zircon/system/dev/board/vim/vim-gpio.cpp
+++ b/zircon/system/dev/board/vim/vim-gpio.cpp
@@ -87,7 +87,10 @@
{ GPIO_WIFI_DEBUG },
// For thermal.
{ GPIO_THERMAL_FAN_O },
- { GPIO_THERMAL_FAN_1 },
+ { GPIO_THERMAL_FAN_1 },
+ // For ethernet.
+ { GPIO_ETH_MAC_RST },
+ { GPIO_ETH_MAC_INTR },
};
static const pbus_metadata_t gpio_metadata[] = {
diff --git a/zircon/system/dev/board/vim/vim-gpios.h b/zircon/system/dev/board/vim/vim-gpios.h
index 0a515a5..79ba905 100644
--- a/zircon/system/dev/board/vim/vim-gpios.h
+++ b/zircon/system/dev/board/vim/vim-gpios.h
@@ -9,3 +9,5 @@
#define GPIO_WIFI_DEBUG S912_GPIODV(13)
#define GPIO_THERMAL_FAN_O S912_GPIODV(14)
#define GPIO_THERMAL_FAN_1 S912_GPIODV(15)
+#define GPIO_ETH_MAC_RST S912_GPIOZ(14)
+#define GPIO_ETH_MAC_INTR S912_GPIOZ(15)
diff --git a/zircon/system/dev/board/vim/vim-i2c.cpp b/zircon/system/dev/board/vim/vim-i2c.cpp
index 570d6d7..7f0dcbc5 100644
--- a/zircon/system/dev/board/vim/vim-i2c.cpp
+++ b/zircon/system/dev/board/vim/vim-i2c.cpp
@@ -75,6 +75,15 @@
.pid = PDEV_PID_GENERIC,
.did = PDEV_DID_LED2472G,
},
+ // Ethernet
+ {
+ .bus_id = 1,
+ .address = 0x18,
+ // Binds to a composite device.
+ .vid = 0,
+ .pid = 0,
+ .did = 0,
+ },
};
static const pbus_metadata_t i2c_metadata[] = {
diff --git a/zircon/system/dev/ethernet/aml-ethernet-s912/BUILD.gn b/zircon/system/dev/ethernet/aml-ethernet-s912/BUILD.gn
index f1109e6..3446420 100644
--- a/zircon/system/dev/ethernet/aml-ethernet-s912/BUILD.gn
+++ b/zircon/system/dev/ethernet/aml-ethernet-s912/BUILD.gn
@@ -5,10 +5,10 @@
driver("aml-ethernet-s912") {
sources = [
"aml-ethernet.cpp",
- "binding.c",
]
deps = [
"$zx/system/banjo/ddk-protocol-clock",
+ "$zx/system/banjo/ddk-protocol-composite",
"$zx/system/banjo/ddk-protocol-ethernet",
"$zx/system/banjo/ddk-protocol-ethernet-board",
"$zx/system/banjo/ddk-protocol-gpio",
diff --git a/zircon/system/dev/ethernet/aml-ethernet-s912/aml-ethernet.cpp b/zircon/system/dev/ethernet/aml-ethernet-s912/aml-ethernet.cpp
index 95f7312..8f2402c 100644
--- a/zircon/system/dev/ethernet/aml-ethernet-s912/aml-ethernet.cpp
+++ b/zircon/system/dev/ethernet/aml-ethernet-s912/aml-ethernet.cpp
@@ -10,6 +10,7 @@
#include <ddk/metadata.h>
#include <ddk/platform-defs.h>
#include <ddk/protocol/i2c-lib.h>
+#include <ddk/protocol/composite.h>
#include <ddk/protocol/ethernet.h>
#include <ddk/protocol/platform/device.h>
#include <ddk/protocol/platform-device-lib.h>
@@ -37,23 +38,52 @@
}
zx_status_t AmlEthernet::InitPdev() {
- if (!pdev_.is_valid()) {
- return ZX_ERR_NO_RESOURCES;
+ composite_protocol_t composite;
+
+ auto status = device_get_protocol(parent(), ZX_PROTOCOL_COMPOSITE, &composite);
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "Could not get composite protocol\n");
+ return status;
}
- zx_status_t status;
- for (uint32_t i = 0; i < countof(gpios_); i++) {
- gpios_[i] = pdev_.GetGpio(i);
- if (!gpios_[i].is_valid()) {
- return ZX_ERR_NO_RESOURCES;
- }
+ zx_device_t* components[COMPONENT_COUNT];
+ size_t actual;
+ composite_get_components(&composite, components, fbl::count_of(components), &actual);
+ if (actual != fbl::count_of(components)) {
+ zxlogf(ERROR, "could not get components\n");
+ return ZX_ERR_NOT_SUPPORTED;
}
- // I2c for MCU messages.
- i2c_ = pdev_.GetI2c(0);
- if (!i2c_.is_valid()) {
- return ZX_ERR_NO_RESOURCES;
+ pdev_protocol_t pdev;
+ status = device_get_protocol(components[COMPONENT_PDEV], ZX_PROTOCOL_PDEV, &pdev);
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "Could not get PDEV protocol\n");
+ return status;
}
+ pdev_ = &pdev;
+
+ i2c_protocol_t i2c;
+ status = device_get_protocol(components[COMPONENT_I2C], ZX_PROTOCOL_I2C, &i2c);
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "Could not get I2C protocol\n");
+ return status;
+ }
+ i2c_ = &i2c;
+
+ gpio_protocol_t gpio;
+ status = device_get_protocol(components[COMPONENT_RESET_GPIO], ZX_PROTOCOL_GPIO, &gpio);
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "Could not get GPIO protocol\n");
+ return status;
+ }
+ gpios_[PHY_RESET] = &gpio;
+
+ status = device_get_protocol(components[COMPONENT_INTR_GPIO], ZX_PROTOCOL_GPIO, &gpio);
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "Could not get GPIO protocol\n");
+ return status;
+ }
+ gpios_[PHY_INTR] = &gpio;
// Map amlogic peripheral control registers.
status = pdev_.MapMmio(MMIO_PERIPH, &periph_mmio_);
@@ -126,7 +156,7 @@
delete this;
}
-zx_status_t AmlEthernet::Create(zx_device_t* parent) {
+zx_status_t AmlEthernet::Create(void* ctx, zx_device_t* parent) {
fbl::AllocChecker ac;
auto eth_device = fbl::make_unique_checked<AmlEthernet>(&ac, parent);
if (!ac.check()) {
@@ -152,8 +182,19 @@
return ZX_OK;
}
+static zx_driver_ops_t driver_ops = [](){
+ zx_driver_ops_t ops = {};
+ ops.version = DRIVER_OPS_VERSION;
+ ops.bind = AmlEthernet::Create;
+ return ops;
+}();
+
} // namespace eth
-extern "C" zx_status_t aml_eth_bind(void* ctx, zx_device_t* parent) {
- return eth::AmlEthernet::Create(parent);
-}
+// clang-format off
+ZIRCON_DRIVER_BEGIN(aml_eth, eth::driver_ops, "aml-ethernet", "0.1", 4)
+ BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_COMPOSITE),
+ BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_AMLOGIC),
+ BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_AMLOGIC_S912),
+ BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_ETH),
+ZIRCON_DRIVER_END(aml_eth)
diff --git a/zircon/system/dev/ethernet/aml-ethernet-s912/aml-ethernet.h b/zircon/system/dev/ethernet/aml-ethernet-s912/aml-ethernet.h
index d401fcd..88d7478 100644
--- a/zircon/system/dev/ethernet/aml-ethernet-s912/aml-ethernet.h
+++ b/zircon/system/dev/ethernet/aml-ethernet-s912/aml-ethernet.h
@@ -24,9 +24,9 @@
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(AmlEthernet);
explicit AmlEthernet(zx_device_t* parent)
- : DeviceType(parent), pdev_(parent) {}
+ : DeviceType(parent) {}
- static zx_status_t Create(zx_device_t* parent);
+ static zx_status_t Create(void* ctx, zx_device_t* parent);
// DDK Hooks.
void DdkRelease();
@@ -36,6 +36,15 @@
zx_status_t EthBoardResetPhy();
private:
+ // Component Indexes.
+ enum {
+ COMPONENT_PDEV,
+ COMPONENT_I2C,
+ COMPONENT_RESET_GPIO,
+ COMPONENT_INTR_GPIO,
+ COMPONENT_COUNT,
+ };
+
// GPIO Indexes.
enum {
PHY_RESET,
diff --git a/zircon/system/dev/ethernet/aml-ethernet-s912/binding.c b/zircon/system/dev/ethernet/aml-ethernet-s912/binding.c
deleted file mode 100644
index 604b76a..0000000
--- a/zircon/system/dev/ethernet/aml-ethernet-s912/binding.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2018 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#include <ddk/binding.h>
-#include <ddk/device.h>
-#include <ddk/driver.h>
-#include <ddk/platform-defs.h>
-#include <stdlib.h>
-#include <string.h>
-
-extern zx_status_t aml_eth_bind(void* ctx, zx_device_t* parent);
-
-static zx_driver_ops_t aml_eth_driver_ops = {
- .version = DRIVER_OPS_VERSION,
- .bind = aml_eth_bind,
-};
-
-// clang-format off
-ZIRCON_DRIVER_BEGIN(aml_eth, aml_eth_driver_ops, "aml-ethernet", "0.1", 3)
- BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_AMLOGIC),
- BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_AMLOGIC_S912),
- BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_ETH),
-ZIRCON_DRIVER_END(aml_eth)