- for (c = 0; c < MAX_NUM_GPIOS; c++) {
- type = get_config(c); /* GPIO, not SFPIO */
- if (type) {
- printf("GPIO_%d:\t%s is an %s, ", c,
- get_name(c),
- get_direction(c) ? "OUTPUT" : "INPUT");
- if (get_direction(c))
- printf("value = %d", gpio_get_output_value(c));
- else
- printf("value = %d", gpio_get_value(c));
- printf("\n");
- } else
- continue;
+static const struct udevice_id tegra_gpio_ids[] = {
+ { .compatible = "nvidia,tegra30-gpio" },
+ { .compatible = "nvidia,tegra20-gpio" },
+ { }
+};
+
+static int gpio_tegra_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct tegra_port_info *priv = dev->priv;
+ struct tegra_gpio_platdata *plat = dev->platdata;
+
+ /* Only child devices have ports */
+ if (!plat)
+ return 0;
+
+ priv->bank = plat->bank;
+ priv->base_gpio = plat->base_gpio;
+
+ uc_priv->gpio_count = TEGRA_GPIOS_PER_PORT;
+ uc_priv->bank_name = plat->port_name;
+
+ return 0;
+}
+
+/**
+ * We have a top-level GPIO device with no actual GPIOs. It has a child
+ * device for each Tegra port.
+ */
+static int gpio_tegra_bind(struct udevice *parent)
+{
+ struct tegra_gpio_platdata *plat = parent->platdata;
+ struct gpio_ctlr *ctlr;
+ int bank_count;
+ int bank;
+ int ret;
+
+ /* If this is a child device, there is nothing to do here */
+ if (plat)
+ return 0;
+
+ /* TODO(sjg@chromium.org): Remove once SPL supports device tree */
+#ifdef CONFIG_SPL_BUILD
+ ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
+ bank_count = TEGRA_GPIO_BANKS;
+#else
+ {
+ int len;
+
+ /*
+ * This driver does not make use of interrupts, other than to figure
+ * out the number of GPIO banks
+ */
+ if (!fdt_getprop(gd->fdt_blob, parent->of_offset, "interrupts", &len))
+ return -EINVAL;
+ bank_count = len / 3 / sizeof(u32);
+ ctlr = (struct gpio_ctlr *)dev_get_addr(parent);
+ }
+#endif
+ for (bank = 0; bank < bank_count; bank++) {
+ int port;
+
+ for (port = 0; port < TEGRA_PORTS_PER_BANK; port++) {
+ struct tegra_gpio_platdata *plat;
+ struct udevice *dev;
+ int base_port;
+
+ plat = calloc(1, sizeof(*plat));
+ if (!plat)
+ return -ENOMEM;
+ plat->bank = &ctlr->gpio_bank[bank];
+ base_port = bank * TEGRA_PORTS_PER_BANK + port;
+ plat->base_gpio = TEGRA_GPIOS_PER_PORT * base_port;
+ plat->port_name = gpio_port_name(base_port);
+
+ ret = device_bind(parent, parent->driver,
+ plat->port_name, plat, -1, &dev);
+ if (ret)
+ return ret;
+ dev->of_offset = parent->of_offset;
+ }