[U-Boot] [PATCH 1/7] dt-bindings: allow child nodes inside the Tegra BPMP

From: Stephen Warren swarren@nvidia.com
The BPMP implements some services which must be represented by separate nodes. For example, it can provide access to certain I2C controllers, and the I2C bindings represent each I2C controller as a device tree node. Update the binding to describe how the BPMP supports this.
Signed-off-by: Stephen Warren swarren@nvidia.com --- This series naturally depends on all the other Tegra186 patches I've sent.
.../firmware/nvidia,tegra186-bpmp.txt | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+)
diff --git a/doc/device-tree-bindings/firmware/nvidia,tegra186-bpmp.txt b/doc/device-tree-bindings/firmware/nvidia,tegra186-bpmp.txt index 9a3864f56955..447252e882b1 100644 --- a/doc/device-tree-bindings/firmware/nvidia,tegra186-bpmp.txt +++ b/doc/device-tree-bindings/firmware/nvidia,tegra186-bpmp.txt @@ -38,6 +38,24 @@ implemented by this node: - .../reset/reset.txt - <dt-bindings/reset/tegra186-reset.h>
+The BPMP implements some services which must be represented by separate nodes. +For example, it can provide access to certain I2C controllers, and the I2C +bindings represent each I2C controller as a device tree node. Such nodes should +be nested directly inside the main BPMP node. + +Software can determine whether a child node of the BPMP node represents a device +by checking for a compatible property. Any node with a compatible property +represents a device that can be instantiated. Nodes without a compatible +property may be used to provide configuration information regarding the BPMP +itself, although no such configuration nodes are currently defined by this +binding. + +The BPMP firmware defines no single global name-/numbering-space for such +services. Put another way, the numbering scheme for I2C buses is distinct from +the numbering scheme for any other service the BPMP may provide (e.g. a future +hypothetical SPI bus service). As such, child device nodes will have no reg +property, and the BPMP node will have no #address-cells or #size-cells property. + The shared memory bindings for BPMP -----------------------------------
@@ -78,4 +96,9 @@ bpmp { #clock-cells = <1>; #power-domain-cells = <1>; #reset-cells = <1>; + + i2c { + compatible = "..."; + ... + }; };

From: Stephen Warren swarren@nvidia.com
The BPMP bindings allow devices to be represented as child nodes of the BPMP node. This requires the driver to trigger scanning of its node for those child nodes.
Signed-off-by: Stephen Warren swarren@nvidia.com --- drivers/misc/tegra186_bpmp.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/misc/tegra186_bpmp.c b/drivers/misc/tegra186_bpmp.c index 147528da9269..526d812ecd39 100644 --- a/drivers/misc/tegra186_bpmp.c +++ b/drivers/misc/tegra186_bpmp.c @@ -129,6 +129,10 @@ static int tegra186_bpmp_bind(struct udevice *dev) if (ret) return ret;
+ ret = dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); + if (ret) + return ret; + return 0; }

Hi Stephen,
On 29 July 2016 at 13:15, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
The BPMP bindings allow devices to be represented as child nodes of the BPMP node. This requires the driver to trigger scanning of its node for those child nodes.
Signed-off-by: Stephen Warren swarren@nvidia.com
drivers/misc/tegra186_bpmp.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/misc/tegra186_bpmp.c b/drivers/misc/tegra186_bpmp.c index 147528da9269..526d812ecd39 100644 --- a/drivers/misc/tegra186_bpmp.c +++ b/drivers/misc/tegra186_bpmp.c @@ -129,6 +129,10 @@ static int tegra186_bpmp_bind(struct udevice *dev) if (ret) return ret;
ret = dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
if (ret)
return ret;
Can you use dm_scan_fdt_dev() here? Hot off the press.
return 0;
}
-- 2.9.2
Regards, Simon

On 07/31/2016 07:03 PM, Simon Glass wrote:
On 29 July 2016 at 13:15, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
The BPMP bindings allow devices to be represented as child nodes of the BPMP node. This requires the driver to trigger scanning of its node for
diff --git a/drivers/misc/tegra186_bpmp.c b/drivers/misc/tegra186_bpmp.c index 147528da9269..526d812ecd39 100644 --- a/drivers/misc/tegra186_bpmp.c +++ b/drivers/misc/tegra186_bpmp.c @@ -129,6 +129,10 @@ static int tegra186_bpmp_bind(struct udevice *dev) if (ret) return ret;
ret = dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
if (ret)
return ret;
Can you use dm_scan_fdt_dev() here? Hot off the press.
It looks like it, yes.

From: Stephen Warren swarren@nvidia.com
In Tegra186, the BPMP (Boot and Power Management Processor) owns certain HW devices, such as the I2C controller for the power management I2C bus. Software running on other CPUs must perform IPC to the BPMP in order to execute transactions on that I2C bus. This binding describes an I2C bus that is accessed in such a fashion.
Signed-off-by: Stephen Warren swarren@nvidia.com --- .../i2c/nvidia,tegra186-bpmp-i2c.txt | 42 ++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 doc/device-tree-bindings/i2c/nvidia,tegra186-bpmp-i2c.txt
diff --git a/doc/device-tree-bindings/i2c/nvidia,tegra186-bpmp-i2c.txt b/doc/device-tree-bindings/i2c/nvidia,tegra186-bpmp-i2c.txt new file mode 100644 index 000000000000..ab240e10debc --- /dev/null +++ b/doc/device-tree-bindings/i2c/nvidia,tegra186-bpmp-i2c.txt @@ -0,0 +1,42 @@ +NVIDIA Tegra186 BPMP I2C controller + +In Tegra186, the BPMP (Boot and Power Management Processor) owns certain HW +devices, such as the I2C controller for the power management I2C bus. Software +running on other CPUs must perform IPC to the BPMP in order to execute +transactions on that I2C bus. This binding describes an I2C bus that is +accessed in such a fashion. + +The BPMP I2C node must be located directly inside the main BPMP node. See +../firmware/nvidia,tegra186-bpmp.txt for details of the BPMP binding. + +This node represents an I2C controller. See ../i2c/i2c.txt for details of the +core I2C binding. + +Required properties: +- compatible: + Array of strings. + One of: + - "nvidia,tegra186-bpmp-i2c". +- #address-cells: Address cells for I2C device address. + Single-cell integer. + Must be <1>. +- #size-cells: + Single-cell integer. + Must be <0>. +- nvidia,bpmp-bus-id: + Single-cell integer. + Indicates the I2C bus number this DT node represent, as defined by the + BPMP firmware. + +Example: + +bpmp { + ... + + i2c { + compatible = "nvidia,tegra186-bpmp-i2c"; + #address-cells = <1>; + #size-cells = <0>; + nvidia,bpmp-bus-id = <5>; + }; +};

On 29 July 2016 at 13:15, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
In Tegra186, the BPMP (Boot and Power Management Processor) owns certain HW devices, such as the I2C controller for the power management I2C bus. Software running on other CPUs must perform IPC to the BPMP in order to execute transactions on that I2C bus. This binding describes an I2C bus that is accessed in such a fashion.
Signed-off-by: Stephen Warren swarren@nvidia.com
.../i2c/nvidia,tegra186-bpmp-i2c.txt | 42 ++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 doc/device-tree-bindings/i2c/nvidia,tegra186-bpmp-i2c.txt
Reviewed-by: Simon Glass sjg@chromium.org

Hello Stephen,
Am 29.07.2016 um 21:15 schrieb Stephen Warren:
From: Stephen Warren swarren@nvidia.com
In Tegra186, the BPMP (Boot and Power Management Processor) owns certain HW devices, such as the I2C controller for the power management I2C bus. Software running on other CPUs must perform IPC to the BPMP in order to execute transactions on that I2C bus. This binding describes an I2C bus that is accessed in such a fashion.
Signed-off-by: Stephen Warren swarren@nvidia.com
.../i2c/nvidia,tegra186-bpmp-i2c.txt | 42 ++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 doc/device-tree-bindings/i2c/nvidia,tegra186-bpmp-i2c.txt
Reviewed-by: Heiko Schocher hs@denx.de
bye, Heiko
diff --git a/doc/device-tree-bindings/i2c/nvidia,tegra186-bpmp-i2c.txt b/doc/device-tree-bindings/i2c/nvidia,tegra186-bpmp-i2c.txt new file mode 100644 index 000000000000..ab240e10debc --- /dev/null +++ b/doc/device-tree-bindings/i2c/nvidia,tegra186-bpmp-i2c.txt @@ -0,0 +1,42 @@ +NVIDIA Tegra186 BPMP I2C controller
+In Tegra186, the BPMP (Boot and Power Management Processor) owns certain HW +devices, such as the I2C controller for the power management I2C bus. Software +running on other CPUs must perform IPC to the BPMP in order to execute +transactions on that I2C bus. This binding describes an I2C bus that is +accessed in such a fashion.
+The BPMP I2C node must be located directly inside the main BPMP node. See +../firmware/nvidia,tegra186-bpmp.txt for details of the BPMP binding.
+This node represents an I2C controller. See ../i2c/i2c.txt for details of the +core I2C binding.
+Required properties: +- compatible:
- Array of strings.
- One of:
- "nvidia,tegra186-bpmp-i2c".
+- #address-cells: Address cells for I2C device address.
- Single-cell integer.
- Must be <1>.
+- #size-cells:
- Single-cell integer.
- Must be <0>.
+- nvidia,bpmp-bus-id:
- Single-cell integer.
- Indicates the I2C bus number this DT node represent, as defined by the
- BPMP firmware.
+Example:
+bpmp {
- ...
- i2c {
compatible = "nvidia,tegra186-bpmp-i2c";
#address-cells = <1>;
#size-cells = <0>;
nvidia,bpmp-bus-id = <5>;
- };
+};

From: Stephen Warren swarren@nvidia.com
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.
Signed-off-by: Stephen Warren swarren@nvidia.com --- drivers/i2c/Kconfig | 10 ++++ drivers/i2c/Makefile | 1 + drivers/i2c/tegra186_bpmp_i2c.c | 129 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 drivers/i2c/tegra186_bpmp_i2c.c
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 6e22bbadff2d..68d3956e473c 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -154,6 +154,16 @@ config SYS_I2C_UNIPHIER_F Support for UniPhier FIFO-builtin I2C controller driver. This I2C controller is used on PH1-Pro4 or newer UniPhier SoCs.
+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 diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 167424db9820..97b6bedde822 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -41,5 +41,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 index 000000000000..d3b3edffb53f --- /dev/null +++ b/drivers/i2c/tegra186_bpmp_i2c.c @@ -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 <asm/arch-tegra/bpmp_abi.h> +#include <asm/arch-tegra/tegra186_bpmp.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 = tegra186_bpmp_call(dev->parent, MRQ_I2C, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret) + 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, +};

On 29 July 2016 at 13:15, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
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.
Signed-off-by: Stephen Warren swarren@nvidia.com
drivers/i2c/Kconfig | 10 ++++ drivers/i2c/Makefile | 1 + drivers/i2c/tegra186_bpmp_i2c.c | 129 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 drivers/i2c/tegra186_bpmp_i2c.c
Reviewed-by: Simon Glass sjg@chromium.org
As before, hopefully the bpmp thing can move to calling via DM.

Hello Stephen,
Am 29.07.2016 um 21:15 schrieb Stephen Warren:
From: Stephen Warren swarren@nvidia.com
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.
Signed-off-by: Stephen Warren swarren@nvidia.com
drivers/i2c/Kconfig | 10 ++++ drivers/i2c/Makefile | 1 + drivers/i2c/tegra186_bpmp_i2c.c | 129 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 drivers/i2c/tegra186_bpmp_i2c.c
Reviewed-by: Heiko Schocher hs@denx.de
bye, Heiko
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 6e22bbadff2d..68d3956e473c 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -154,6 +154,16 @@ config SYS_I2C_UNIPHIER_F Support for UniPhier FIFO-builtin I2C controller driver. This I2C controller is used on PH1-Pro4 or newer UniPhier SoCs.
+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
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 167424db9820..97b6bedde822 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -41,5 +41,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 index 000000000000..d3b3edffb53f --- /dev/null +++ b/drivers/i2c/tegra186_bpmp_i2c.c @@ -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 <asm/arch-tegra/bpmp_abi.h> +#include <asm/arch-tegra/tegra186_bpmp.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 = tegra186_bpmp_call(dev->parent, MRQ_I2C,
&req, sizeof(req), &resp, sizeof(resp));
- if (ret)
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,
+};

From: Stephen Warren swarren@nvidia.com
This allows the BPMP I2C device to be instantiated, which makes it available to other drivers and the user.
Signed-off-by: Stephen Warren swarren@nvidia.com --- arch/arm/dts/tegra186.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/arch/arm/dts/tegra186.dtsi b/arch/arm/dts/tegra186.dtsi index 0778d2117658..d9e7f0351f57 100644 --- a/arch/arm/dts/tegra186.dtsi +++ b/arch/arm/dts/tegra186.dtsi @@ -308,5 +308,14 @@ #clock-cells = <1>; #power-domain-cells = <1>; #reset-cells = <1>; + + bpmp_i2c: i2c { + compatible = "nvidia,tegra186-bpmp-i2c"; + nvidia,bpmp = <&bpmp>; + nvidia,bpmp-bus-id = <5>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; };

On 29 July 2016 at 13:15, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
This allows the BPMP I2C device to be instantiated, which makes it available to other drivers and the user.
Signed-off-by: Stephen Warren swarren@nvidia.com
arch/arm/dts/tegra186.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

From: Stephen Warren swarren@nvidia.com
Now that clock and reset drivers exist for Tegra186, we can enable the SD card controller. Now that a BPMP I2C driver exists for Tegra186, we can communicate with the PMIC to enable power to the SD card. Hook up the DT content and board code required to make the SD card work.
Signed-off-by: Stephen Warren swarren@nvidia.com --- arch/arm/dts/tegra186-p2771-0000-a02.dts | 5 +++++ arch/arm/dts/tegra186-p2771-0000-b00.dts | 5 +++++ arch/arm/dts/tegra186-p2771-0000.dtsi | 14 ++++++++++++++ board/nvidia/p2771-0000/p2771-0000.c | 26 ++++++++++++++++++++++++++ configs/p2771-0000-a02_defconfig | 1 + configs/p2771-0000-b00_defconfig | 1 + 6 files changed, 52 insertions(+)
diff --git a/arch/arm/dts/tegra186-p2771-0000-a02.dts b/arch/arm/dts/tegra186-p2771-0000-a02.dts index 70f4326c0913..5ed3817a41c6 100644 --- a/arch/arm/dts/tegra186-p2771-0000-a02.dts +++ b/arch/arm/dts/tegra186-p2771-0000-a02.dts @@ -5,4 +5,9 @@ / { 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>; + }; }; diff --git a/arch/arm/dts/tegra186-p2771-0000-b00.dts b/arch/arm/dts/tegra186-p2771-0000-b00.dts index 2384a65e870a..90c99c33ccc6 100644 --- a/arch/arm/dts/tegra186-p2771-0000-b00.dts +++ b/arch/arm/dts/tegra186-p2771-0000-b00.dts @@ -5,4 +5,9 @@ / { 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>; + }; }; diff --git a/arch/arm/dts/tegra186-p2771-0000.dtsi b/arch/arm/dts/tegra186-p2771-0000.dtsi index 4e2b6fbf97f8..d867674fd04e 100644 --- a/arch/arm/dts/tegra186-p2771-0000.dtsi +++ b/arch/arm/dts/tegra186-p2771-0000.dtsi @@ -10,6 +10,8 @@
aliases { sdhci0 = "/sdhci@3460000"; + sdhci1 = "/sdhci@3400000"; + i2c0 = "/bpmp/i2c"; i2c1 = "/i2c@3160000"; i2c2 = "/i2c@c240000"; i2c3 = "/i2c@3180000"; @@ -39,6 +41,12 @@ 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>; @@ -55,4 +63,10 @@ i2c@31e0000 { status = "okay"; }; + + bpmp { + i2c { + status = "okay"; + }; + }; }; diff --git a/board/nvidia/p2771-0000/p2771-0000.c b/board/nvidia/p2771-0000/p2771-0000.c index 4ba8ebc0dce8..0c828a200542 100644 --- a/board/nvidia/p2771-0000/p2771-0000.c +++ b/board/nvidia/p2771-0000/p2771-0000.c @@ -5,3 +5,29 @@ */
#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; +} diff --git a/configs/p2771-0000-a02_defconfig b/configs/p2771-0000-a02_defconfig index 1fe25f58f199..404f7acf7ef5 100644 --- a/configs/p2771-0000-a02_defconfig +++ b/configs/p2771-0000-a02_defconfig @@ -26,6 +26,7 @@ CONFIG_CMD_EXT4=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y +CONFIG_TEGRA186_BPMP_I2C=y CONFIG_SYS_NS16550=y CONFIG_USB=y CONFIG_DM_USB=y diff --git a/configs/p2771-0000-b00_defconfig b/configs/p2771-0000-b00_defconfig index 552fb6cec78b..ad35c99bbbcc 100644 --- a/configs/p2771-0000-b00_defconfig +++ b/configs/p2771-0000-b00_defconfig @@ -26,6 +26,7 @@ CONFIG_CMD_EXT4=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y +CONFIG_TEGRA186_BPMP_I2C=y CONFIG_SYS_NS16550=y CONFIG_USB=y CONFIG_DM_USB=y

Hi Stephen,
On 29 July 2016 at 13:15, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
Now that clock and reset drivers exist for Tegra186, we can enable the SD card controller. Now that a BPMP I2C driver exists for Tegra186, we can communicate with the PMIC to enable power to the SD card. Hook up the DT content and board code required to make the SD card work.
Signed-off-by: Stephen Warren swarren@nvidia.com
arch/arm/dts/tegra186-p2771-0000-a02.dts | 5 +++++ arch/arm/dts/tegra186-p2771-0000-b00.dts | 5 +++++ arch/arm/dts/tegra186-p2771-0000.dtsi | 14 ++++++++++++++ board/nvidia/p2771-0000/p2771-0000.c | 26 ++++++++++++++++++++++++++ configs/p2771-0000-a02_defconfig | 1 + configs/p2771-0000-b00_defconfig | 1 + 6 files changed, 52 insertions(+)
diff --git a/arch/arm/dts/tegra186-p2771-0000-a02.dts b/arch/arm/dts/tegra186-p2771-0000-a02.dts index 70f4326c0913..5ed3817a41c6 100644 --- a/arch/arm/dts/tegra186-p2771-0000-a02.dts +++ b/arch/arm/dts/tegra186-p2771-0000-a02.dts @@ -5,4 +5,9 @@ / { 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>;
};
}; diff --git a/arch/arm/dts/tegra186-p2771-0000-b00.dts b/arch/arm/dts/tegra186-p2771-0000-b00.dts index 2384a65e870a..90c99c33ccc6 100644 --- a/arch/arm/dts/tegra186-p2771-0000-b00.dts +++ b/arch/arm/dts/tegra186-p2771-0000-b00.dts @@ -5,4 +5,9 @@ / { 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>;
};
}; diff --git a/arch/arm/dts/tegra186-p2771-0000.dtsi b/arch/arm/dts/tegra186-p2771-0000.dtsi index 4e2b6fbf97f8..d867674fd04e 100644 --- a/arch/arm/dts/tegra186-p2771-0000.dtsi +++ b/arch/arm/dts/tegra186-p2771-0000.dtsi @@ -10,6 +10,8 @@
aliases { sdhci0 = "/sdhci@3460000";
sdhci1 = "/sdhci@3400000";
i2c0 = "/bpmp/i2c"; i2c1 = "/i2c@3160000"; i2c2 = "/i2c@c240000"; i2c3 = "/i2c@3180000";
@@ -39,6 +41,12 @@ 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>;
@@ -55,4 +63,10 @@ i2c@31e0000 { status = "okay"; };
bpmp {
i2c {
status = "okay";
};
};
}; diff --git a/board/nvidia/p2771-0000/p2771-0000.c b/board/nvidia/p2771-0000/p2771-0000.c index 4ba8ebc0dce8..0c828a200542 100644 --- a/board/nvidia/p2771-0000/p2771-0000.c +++ b/board/nvidia/p2771-0000/p2771-0000.c @@ -5,3 +5,29 @@ */
#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;
}
Can you add a simple pmic driver for this? It's really easy and avoids the horrible busnum stuff. The i2c_get_chip_for_busnum() should ideally not be used.
return 0;
+} diff --git a/configs/p2771-0000-a02_defconfig b/configs/p2771-0000-a02_defconfig index 1fe25f58f199..404f7acf7ef5 100644 --- a/configs/p2771-0000-a02_defconfig +++ b/configs/p2771-0000-a02_defconfig @@ -26,6 +26,7 @@ CONFIG_CMD_EXT4=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y +CONFIG_TEGRA186_BPMP_I2C=y CONFIG_SYS_NS16550=y CONFIG_USB=y CONFIG_DM_USB=y diff --git a/configs/p2771-0000-b00_defconfig b/configs/p2771-0000-b00_defconfig index 552fb6cec78b..ad35c99bbbcc 100644 --- a/configs/p2771-0000-b00_defconfig +++ b/configs/p2771-0000-b00_defconfig @@ -26,6 +26,7 @@ CONFIG_CMD_EXT4=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y +CONFIG_TEGRA186_BPMP_I2C=y CONFIG_SYS_NS16550=y CONFIG_USB=y CONFIG_DM_USB=y -- 2.9.2
Regards, Simon

On 07/31/2016 07:04 PM, Simon Glass wrote:
Hi Stephen,
On 29 July 2016 at 13:15, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
Now that clock and reset drivers exist for Tegra186, we can enable the SD card controller. Now that a BPMP I2C driver exists for Tegra186, we can communicate with the PMIC to enable power to the SD card. Hook up the DT content and board code required to make the SD card work.
diff --git a/board/nvidia/p2771-0000/p2771-0000.c b/board/nvidia/p2771-0000/p2771-0000.c
+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;
}
Can you add a simple pmic driver for this? It's really easy and avoids the horrible busnum stuff. The i2c_get_chip_for_busnum() should ideally not be used.
Perhaps we can defer that until later?
FWIW, this current approach is used by all/most Tegra boards and works great for now. If converting this kind of code to use the PMIC infra-structure, I'd rather take a pass and do all Tegra boards at once, but equally I'd rather not hold up the Tegra186 patches behind yet another common API conversion; there are already 3 new common APIs introduced for Tegra in the Tegra186 support...

Hi Stephen,
On 1 August 2016 at 10:02, Stephen Warren swarren@wwwdotorg.org wrote:
On 07/31/2016 07:04 PM, Simon Glass wrote:
Hi Stephen,
On 29 July 2016 at 13:15, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
Now that clock and reset drivers exist for Tegra186, we can enable the SD card controller. Now that a BPMP I2C driver exists for Tegra186, we can communicate with the PMIC to enable power to the SD card. Hook up the DT content and board code required to make the SD card work.
diff --git a/board/nvidia/p2771-0000/p2771-0000.c b/board/nvidia/p2771-0000/p2771-0000.c
+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;
}
Can you add a simple pmic driver for this? It's really easy and avoids the horrible busnum stuff. The i2c_get_chip_for_busnum() should ideally not be used.
Perhaps we can defer that until later?
FWIW, this current approach is used by all/most Tegra boards and works great for now. If converting this kind of code to use the PMIC infra-structure, I'd rather take a pass and do all Tegra boards at once, but equally I'd rather not hold up the Tegra186 patches behind yet another common API conversion; there are already 3 new common APIs introduced for Tegra in the Tegra186 support...
OK, will I remember this coming up previously, so I look forward to it getting sorted out. It really isn't that much work to write a PMIC driver.
Regards, Simon

From: Stephen Warren swarren@nvidia.com
p2771-0000 has a couple of PCIe ports; one physically x4 desktop PCI connector (which may run at x2 electrically, depending on the board version and configuration) and a x1 connection to the M.2 slot (which may not be active, depending on the board version and configuration). This change enables those.
Signed-off-by: Stephen Warren swarren@nvidia.com --- arch/arm/dts/tegra186-p2771-0000-a02.dts | 19 +++++++++++++++++++ arch/arm/dts/tegra186-p2771-0000-b00.dts | 19 +++++++++++++++++++ board/nvidia/p2771-0000/p2771-0000.c | 22 ++++++++++++++++++++++ configs/p2771-0000-a02_defconfig | 5 +++++ configs/p2771-0000-b00_defconfig | 5 +++++ include/configs/p2771-0000.h | 5 +++++ 6 files changed, 75 insertions(+)
diff --git a/arch/arm/dts/tegra186-p2771-0000-a02.dts b/arch/arm/dts/tegra186-p2771-0000-a02.dts index 5ed3817a41c6..36a3c21a55de 100644 --- a/arch/arm/dts/tegra186-p2771-0000-a02.dts +++ b/arch/arm/dts/tegra186-p2771-0000-a02.dts @@ -10,4 +10,23 @@ 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>; + }; + }; }; diff --git a/arch/arm/dts/tegra186-p2771-0000-b00.dts b/arch/arm/dts/tegra186-p2771-0000-b00.dts index 90c99c33ccc6..0f1d0e83e80d 100644 --- a/arch/arm/dts/tegra186-p2771-0000-b00.dts +++ b/arch/arm/dts/tegra186-p2771-0000-b00.dts @@ -10,4 +10,23 @@ 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>; + }; + }; }; diff --git a/board/nvidia/p2771-0000/p2771-0000.c b/board/nvidia/p2771-0000/p2771-0000.c index 0c828a200542..529ed9d4547a 100644 --- a/board/nvidia/p2771-0000/p2771-0000.c +++ b/board/nvidia/p2771-0000/p2771-0000.c @@ -31,3 +31,25 @@ int tegra_board_init(void)
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; +} diff --git a/configs/p2771-0000-a02_defconfig b/configs/p2771-0000-a02_defconfig index 404f7acf7ef5..5ce369c6d330 100644 --- a/configs/p2771-0000-a02_defconfig +++ b/configs/p2771-0000-a02_defconfig @@ -26,7 +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 diff --git a/configs/p2771-0000-b00_defconfig b/configs/p2771-0000-b00_defconfig index ad35c99bbbcc..27393f3a5d46 100644 --- a/configs/p2771-0000-b00_defconfig +++ b/configs/p2771-0000-b00_defconfig @@ -26,7 +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 diff --git a/include/configs/p2771-0000.h b/include/configs/p2771-0000.h index 3ce72086ce9c..1f64405f119a 100644 --- a/include/configs/p2771-0000.h +++ b/include/configs/p2771-0000.h @@ -28,6 +28,11 @@ #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 */

Hi Stephen,
On 29 July 2016 at 13:15, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
p2771-0000 has a couple of PCIe ports; one physically x4 desktop PCI connector (which may run at x2 electrically, depending on the board version and configuration) and a x1 connection to the M.2 slot (which may not be active, depending on the board version and configuration). This change enables those.
Signed-off-by: Stephen Warren swarren@nvidia.com
arch/arm/dts/tegra186-p2771-0000-a02.dts | 19 +++++++++++++++++++ arch/arm/dts/tegra186-p2771-0000-b00.dts | 19 +++++++++++++++++++ board/nvidia/p2771-0000/p2771-0000.c | 22 ++++++++++++++++++++++ configs/p2771-0000-a02_defconfig | 5 +++++ configs/p2771-0000-b00_defconfig | 5 +++++ include/configs/p2771-0000.h | 5 +++++ 6 files changed, 75 insertions(+)
diff --git a/arch/arm/dts/tegra186-p2771-0000-a02.dts b/arch/arm/dts/tegra186-p2771-0000-a02.dts index 5ed3817a41c6..36a3c21a55de 100644 --- a/arch/arm/dts/tegra186-p2771-0000-a02.dts +++ b/arch/arm/dts/tegra186-p2771-0000-a02.dts @@ -10,4 +10,23 @@ 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>;
};
};
}; diff --git a/arch/arm/dts/tegra186-p2771-0000-b00.dts b/arch/arm/dts/tegra186-p2771-0000-b00.dts index 90c99c33ccc6..0f1d0e83e80d 100644 --- a/arch/arm/dts/tegra186-p2771-0000-b00.dts +++ b/arch/arm/dts/tegra186-p2771-0000-b00.dts @@ -10,4 +10,23 @@ 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>;
};
};
}; diff --git a/board/nvidia/p2771-0000/p2771-0000.c b/board/nvidia/p2771-0000/p2771-0000.c index 0c828a200542..529ed9d4547a 100644 --- a/board/nvidia/p2771-0000/p2771-0000.c +++ b/board/nvidia/p2771-0000/p2771-0000.c @@ -31,3 +31,25 @@ int tegra_board_init(void)
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);
This looks like it should be a pmic regulator driver.
return 0;
+} diff --git a/configs/p2771-0000-a02_defconfig b/configs/p2771-0000-a02_defconfig index 404f7acf7ef5..5ce369c6d330 100644 --- a/configs/p2771-0000-a02_defconfig +++ b/configs/p2771-0000-a02_defconfig @@ -26,7 +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 diff --git a/configs/p2771-0000-b00_defconfig b/configs/p2771-0000-b00_defconfig index ad35c99bbbcc..27393f3a5d46 100644 --- a/configs/p2771-0000-b00_defconfig +++ b/configs/p2771-0000-b00_defconfig @@ -26,7 +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 diff --git a/include/configs/p2771-0000.h b/include/configs/p2771-0000.h index 3ce72086ce9c..1f64405f119a 100644 --- a/include/configs/p2771-0000.h +++ b/include/configs/p2771-0000.h @@ -28,6 +28,11 @@ #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 */
2.9.2
Regards, Simon
participants (3)
-
Heiko Schocher
-
Simon Glass
-
Stephen Warren