summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/dts/tegra114-dalmore.dts4
-rw-r--r--arch/arm/dts/tegra114.dtsi53
-rw-r--r--arch/arm/dts/tegra124-jetson-tk1.dts4
-rw-r--r--arch/arm/dts/tegra124-venice2.dts4
-rw-r--r--arch/arm/dts/tegra124.dtsi66
-rw-r--r--arch/arm/dts/tegra20-colibri_t20_iris.dts4
-rw-r--r--arch/arm/dts/tegra20-harmony.dts4
-rw-r--r--arch/arm/dts/tegra20-medcom-wide.dts4
-rw-r--r--arch/arm/dts/tegra20-paz00.dts4
-rw-r--r--arch/arm/dts/tegra20-plutux.dts4
-rw-r--r--arch/arm/dts/tegra20-seaboard.dts4
-rw-r--r--arch/arm/dts/tegra20-tec.dts4
-rw-r--r--arch/arm/dts/tegra20-trimslice.dts4
-rw-r--r--arch/arm/dts/tegra20-ventana.dts4
-rw-r--r--arch/arm/dts/tegra20-whistler.dts4
-rw-r--r--arch/arm/dts/tegra20.dtsi51
-rw-r--r--arch/arm/dts/tegra30-beaver.dts4
-rw-r--r--arch/arm/dts/tegra30-cardhu.dts4
-rw-r--r--arch/arm/dts/tegra30-tamonten.dtsi4
-rw-r--r--arch/arm/dts/tegra30.dtsi66
-rw-r--r--arch/arm/include/asm/arch-tegra/gpio.h15
-rw-r--r--arch/sandbox/dts/sandbox.dts10
-rw-r--r--board/nvidia/seaboard/seaboard.c2
-rw-r--r--common/board_f.c4
-rw-r--r--common/board_r.c19
-rw-r--r--common/stdio.c18
-rw-r--r--doc/device-tree-bindings/serial/ns16550.txt10
-rw-r--r--doc/device-tree-bindings/serial/sandbox-serial.txt13
-rw-r--r--drivers/core/lists.c10
-rw-r--r--drivers/core/root.c2
-rw-r--r--drivers/gpio/tegra_gpio.c327
-rw-r--r--drivers/serial/Makefile7
-rw-r--r--drivers/serial/ns16550.c203
-rw-r--r--drivers/serial/sandbox.c140
-rw-r--r--drivers/serial/serial-uclass.c213
-rw-r--r--drivers/serial/serial.c1
-rw-r--r--drivers/serial/serial_ns16550.c14
-rw-r--r--drivers/serial/serial_tegra.c38
-rw-r--r--include/configs/sandbox.h3
-rw-r--r--include/configs/tegra-common.h11
-rw-r--r--include/dm/lists.h6
-rw-r--r--include/dm/uclass-id.h1
-rw-r--r--include/dt-bindings/clock/tegra114-car.h342
-rw-r--r--include/dt-bindings/clock/tegra124-car.h342
-rw-r--r--include/dt-bindings/clock/tegra20-car.h158
-rw-r--r--include/dt-bindings/clock/tegra30-car.h273
-rw-r--r--include/fdtdec.h12
-rw-r--r--include/ns16550.h66
-rw-r--r--include/serial.h92
-rw-r--r--include/stdio_dev.h24
-rw-r--r--lib/fdtdec.c15
51 files changed, 2542 insertions, 149 deletions
diff --git a/arch/arm/dts/tegra114-dalmore.dts b/arch/arm/dts/tegra114-dalmore.dts
index 435c01e..81ad212 100644
--- a/arch/arm/dts/tegra114-dalmore.dts
+++ b/arch/arm/dts/tegra114-dalmore.dts
@@ -6,6 +6,10 @@
model = "NVIDIA Dalmore";
compatible = "nvidia,dalmore", "nvidia,tegra114";
+ chosen {
+ stdout-path = &uartd;
+ };
+
aliases {
i2c0 = "/i2c@7000d000";
i2c1 = "/i2c@7000c000";
diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi
index 59434e0..88bdc49 100644
--- a/arch/arm/dts/tegra114.dtsi
+++ b/arch/arm/dts/tegra114.dtsi
@@ -1,3 +1,4 @@
+#include <dt-bindings/clock/tegra114-car.h>
#include <dt-bindings/gpio/tegra-gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -116,6 +117,58 @@
status = "disabled";
};
+ uarta: serial@70006000 {
+ compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+ reg = <0x70006000 0x40>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA114_CLK_UARTA>;
+ resets = <&tegra_car 6>;
+ reset-names = "serial";
+ dmas = <&apbdma 8>, <&apbdma 8>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uartb: serial@70006040 {
+ compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+ reg = <0x70006040 0x40>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA114_CLK_UARTB>;
+ resets = <&tegra_car 7>;
+ reset-names = "serial";
+ dmas = <&apbdma 9>, <&apbdma 9>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uartc: serial@70006200 {
+ compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+ reg = <0x70006200 0x100>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA114_CLK_UARTC>;
+ resets = <&tegra_car 55>;
+ reset-names = "serial";
+ dmas = <&apbdma 10>, <&apbdma 10>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uartd: serial@70006300 {
+ compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+ reg = <0x70006300 0x100>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA114_CLK_UARTD>;
+ resets = <&tegra_car 65>;
+ reset-names = "serial";
+ dmas = <&apbdma 19>, <&apbdma 19>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
spi@7000d400 {
compatible = "nvidia,tegra114-spi";
reg = <0x7000d400 0x200>;
diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts
index 464287e..ffad116 100644
--- a/arch/arm/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/dts/tegra124-jetson-tk1.dts
@@ -6,6 +6,10 @@
model = "NVIDIA Jetson TK1";
compatible = "nvidia,jetson-tk1", "nvidia,tegra124";
+ chosen {
+ stdout-path = &uartd;
+ };
+
aliases {
i2c0 = "/i2c@7000d000";
i2c1 = "/i2c@7000c000";
diff --git a/arch/arm/dts/tegra124-venice2.dts b/arch/arm/dts/tegra124-venice2.dts
index f003413..f7ccfc5 100644
--- a/arch/arm/dts/tegra124-venice2.dts
+++ b/arch/arm/dts/tegra124-venice2.dts
@@ -6,6 +6,10 @@
model = "NVIDIA Venice2";
compatible = "nvidia,venice2", "nvidia,tegra124";
+ chosen {
+ stdout-path = &uarta;
+ };
+
aliases {
i2c0 = "/i2c@7000d000";
i2c1 = "/i2c@7000c000";
diff --git a/arch/arm/dts/tegra124.dtsi b/arch/arm/dts/tegra124.dtsi
index 4561c5f..3288f28 100644
--- a/arch/arm/dts/tegra124.dtsi
+++ b/arch/arm/dts/tegra124.dtsi
@@ -1,3 +1,4 @@
+#include <dt-bindings/clock/tegra124-car.h>
#include <dt-bindings/gpio/tegra-gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -126,6 +127,71 @@
status = "disabled";
};
+ uarta: serial@70006000 {
+ compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
+ reg = <0x70006000 0x40>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA124_CLK_UARTA>;
+ resets = <&tegra_car 6>;
+ reset-names = "serial";
+ dmas = <&apbdma 8>, <&apbdma 8>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uartb: serial@70006040 {
+ compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
+ reg = <0x70006040 0x40>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA124_CLK_UARTB>;
+ resets = <&tegra_car 7>;
+ reset-names = "serial";
+ dmas = <&apbdma 9>, <&apbdma 9>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uartc: serial@70006200 {
+ compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
+ reg = <0x70006200 0x40>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA124_CLK_UARTC>;
+ resets = <&tegra_car 55>;
+ reset-names = "serial";
+ dmas = <&apbdma 10>, <&apbdma 10>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uartd: serial@70006300 {
+ compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
+ reg = <0x70006300 0x40>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA124_CLK_UARTD>;
+ resets = <&tegra_car 65>;
+ reset-names = "serial";
+ dmas = <&apbdma 19>, <&apbdma 19>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uarte: serial@70006400 {
+ compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
+ reg = <0x70006400 0x40>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA124_CLK_UARTE>;
+ resets = <&tegra_car 66>;
+ reset-names = "serial";
+ dmas = <&apbdma 20>, <&apbdma 20>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
spi@7000d400 {
compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
reg = <0x7000d400 0x200>;
diff --git a/arch/arm/dts/tegra20-colibri_t20_iris.dts b/arch/arm/dts/tegra20-colibri_t20_iris.dts
index c0e54af..7cf08f4 100644
--- a/arch/arm/dts/tegra20-colibri_t20_iris.dts
+++ b/arch/arm/dts/tegra20-colibri_t20_iris.dts
@@ -6,6 +6,10 @@
model = "Toradex Colibri T20";
compatible = "toradex,t20", "nvidia,tegra20";
+ chosen {
+ stdout-path = &uarta;
+ };
+
aliases {
usb0 = "/usb@c5008000";
usb1 = "/usb@c5000000";
diff --git a/arch/arm/dts/tegra20-harmony.dts b/arch/arm/dts/tegra20-harmony.dts
index b115f87..982a14c 100644
--- a/arch/arm/dts/tegra20-harmony.dts
+++ b/arch/arm/dts/tegra20-harmony.dts
@@ -6,6 +6,10 @@
model = "NVIDIA Tegra20 Harmony evaluation board";
compatible = "nvidia,harmony", "nvidia,tegra20";
+ chosen {
+ stdout-path = &uartd;
+ };
+
aliases {
usb0 = "/usb@c5008000";
usb1 = "/usb@c5004000";
diff --git a/arch/arm/dts/tegra20-medcom-wide.dts b/arch/arm/dts/tegra20-medcom-wide.dts
index a9a07f9..be2ed42 100644
--- a/arch/arm/dts/tegra20-medcom-wide.dts
+++ b/arch/arm/dts/tegra20-medcom-wide.dts
@@ -6,6 +6,10 @@
model = "Avionic Design Medcom-Wide";
compatible = "ad,medcom-wide", "nvidia,tegra20";
+ chosen {
+ stdout-path = &uartd;
+ };
+
aliases {
usb0 = "/usb@c5008000";
sdhci0 = "/sdhci@c8000600";
diff --git a/arch/arm/dts/tegra20-paz00.dts b/arch/arm/dts/tegra20-paz00.dts
index 780203c..9d735b5 100644
--- a/arch/arm/dts/tegra20-paz00.dts
+++ b/arch/arm/dts/tegra20-paz00.dts
@@ -6,6 +6,10 @@
model = "Toshiba AC100 / Dynabook AZ";
compatible = "compal,paz00", "nvidia,tegra20";
+ chosen {
+ stdout-path = &uarta;
+ };
+
aliases {
usb0 = "/usb@c5008000";
sdhci0 = "/sdhci@c8000600";
diff --git a/arch/arm/dts/tegra20-plutux.dts b/arch/arm/dts/tegra20-plutux.dts
index 20016f2..e5562a9 100644
--- a/arch/arm/dts/tegra20-plutux.dts
+++ b/arch/arm/dts/tegra20-plutux.dts
@@ -6,6 +6,10 @@
model = "Avionic Design Plutux";
compatible = "ad,plutux", "nvidia,tegra20";
+ chosen {
+ stdout-path = &uartd;
+ };
+
aliases {
usb0 = "/usb@c5008000";
sdhci0 = "/sdhci@c8000600";
diff --git a/arch/arm/dts/tegra20-seaboard.dts b/arch/arm/dts/tegra20-seaboard.dts
index c0e2e1e..43b9911 100644
--- a/arch/arm/dts/tegra20-seaboard.dts
+++ b/arch/arm/dts/tegra20-seaboard.dts
@@ -10,6 +10,10 @@
bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk1p3 rw rootwait";
};
+ chosen {
+ stdout-path = &uartd;
+ };
+
aliases {
/* This defines the order of our ports */
usb0 = "/usb@c5008000";
diff --git a/arch/arm/dts/tegra20-tec.dts b/arch/arm/dts/tegra20-tec.dts
index 4c1b08d..e99bd44 100644
--- a/arch/arm/dts/tegra20-tec.dts
+++ b/arch/arm/dts/tegra20-tec.dts
@@ -6,6 +6,10 @@
model = "Avionic Design Tamonten Evaluation Carrier";
compatible = "ad,tec", "nvidia,tegra20";
+ chosen {
+ stdout-path = &uartd;
+ };
+
aliases {
usb0 = "/usb@c5008000";
sdhci0 = "/sdhci@c8000600";
diff --git a/arch/arm/dts/tegra20-trimslice.dts b/arch/arm/dts/tegra20-trimslice.dts
index ee31476..cee5cfe 100644
--- a/arch/arm/dts/tegra20-trimslice.dts
+++ b/arch/arm/dts/tegra20-trimslice.dts
@@ -6,6 +6,10 @@
model = "Compulab TrimSlice board";
compatible = "compulab,trimslice", "nvidia,tegra20";
+ chosen {
+ stdout-path = &uarta;
+ };
+
aliases {
usb0 = "/usb@c5008000";
usb1 = "/usb@c5000000";
diff --git a/arch/arm/dts/tegra20-ventana.dts b/arch/arm/dts/tegra20-ventana.dts
index 1a526ba..6812203 100644
--- a/arch/arm/dts/tegra20-ventana.dts
+++ b/arch/arm/dts/tegra20-ventana.dts
@@ -6,6 +6,10 @@
model = "NVIDIA Tegra20 Ventana evaluation board";
compatible = "nvidia,ventana", "nvidia,tegra20";
+ chosen {
+ stdout-path = &uartd;
+ };
+
aliases {
usb0 = "/usb@c5008000";
sdhci0 = "/sdhci@c8000600";
diff --git a/arch/arm/dts/tegra20-whistler.dts b/arch/arm/dts/tegra20-whistler.dts
index eb92264..4fd2496 100644
--- a/arch/arm/dts/tegra20-whistler.dts
+++ b/arch/arm/dts/tegra20-whistler.dts
@@ -6,6 +6,10 @@
model = "NVIDIA Tegra20 Whistler evaluation board";
compatible = "nvidia,whistler", "nvidia,tegra20";
+ chosen {
+ stdout-path = &uarta;
+ };
+
aliases {
i2c0 = "/i2c@7000d000";
usb0 = "/usb@c5008000";
diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi
index a524f6e..5f927f7 100644
--- a/arch/arm/dts/tegra20.dtsi
+++ b/arch/arm/dts/tegra20.dtsi
@@ -1,3 +1,4 @@
+#include <dt-bindings/clock/tegra20-car.h>
#include <dt-bindings/gpio/tegra-gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -189,39 +190,69 @@
dma-channel = < 1 >;
};
- serial@70006000 {
+ uarta: serial@70006000 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006000 0x40>;
reg-shift = <2>;
- interrupts = < 68 >;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA20_CLK_UARTA>;
+ resets = <&tegra_car 6>;
+ reset-names = "serial";
+ dmas = <&apbdma 8>, <&apbdma 8>;
+ dma-names = "rx", "tx";
+ status = "disabled";
};
- serial@70006040 {
+ uartb: serial@70006040 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006040 0x40>;
reg-shift = <2>;
- interrupts = < 69 >;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA20_CLK_UARTB>;
+ resets = <&tegra_car 7>;
+ reset-names = "serial";
+ dmas = <&apbdma 9>, <&apbdma 9>;
+ dma-names = "rx", "tx";
+ status = "disabled";
};
- serial@70006200 {
+ uartc: serial@70006200 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006200 0x100>;
reg-shift = <2>;
- interrupts = < 78 >;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA20_CLK_UARTC>;
+ resets = <&tegra_car 55>;
+ reset-names = "serial";
+ dmas = <&apbdma 10>, <&apbdma 10>;
+ dma-names = "rx", "tx";
+ status = "disabled";
};
- serial@70006300 {
+ uartd: serial@70006300 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006300 0x100>;
reg-shift = <2>;
- interrupts = < 122 >;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA20_CLK_UARTD>;
+ resets = <&tegra_car 65>;
+ reset-names = "serial";
+ dmas = <&apbdma 19>, <&apbdma 19>;
+ dma-names = "rx", "tx";
+ status = "disabled";
};
- serial@70006400 {
+ uarte: serial@70006400 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006400 0x100>;
reg-shift = <2>;
- interrupts = < 123 >;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA20_CLK_UARTE>;
+ resets = <&tegra_car 66>;
+ reset-names = "serial";
+ dmas = <&apbdma 20>, <&apbdma 20>;
+ dma-names = "rx", "tx";
+ status = "disabled";
};
nand: nand-controller@70008000 {
diff --git a/arch/arm/dts/tegra30-beaver.dts b/arch/arm/dts/tegra30-beaver.dts
index 85e62e9..ad140de 100644
--- a/arch/arm/dts/tegra30-beaver.dts
+++ b/arch/arm/dts/tegra30-beaver.dts
@@ -6,6 +6,10 @@
model = "NVIDIA Beaver";
compatible = "nvidia,beaver", "nvidia,tegra30";
+ chosen {
+ stdout-path = &uarta;
+ };
+
aliases {
i2c0 = "/i2c@7000d000";
i2c1 = "/i2c@7000c000";
diff --git a/arch/arm/dts/tegra30-cardhu.dts b/arch/arm/dts/tegra30-cardhu.dts
index ea2cf76..b4fbe71 100644
--- a/arch/arm/dts/tegra30-cardhu.dts
+++ b/arch/arm/dts/tegra30-cardhu.dts
@@ -6,6 +6,10 @@
model = "NVIDIA Cardhu";
compatible = "nvidia,cardhu", "nvidia,tegra30";
+ chosen {
+ stdout-path = &uarta;
+ };
+
aliases {
i2c0 = "/i2c@7000d000";
i2c1 = "/i2c@7000c000";
diff --git a/arch/arm/dts/tegra30-tamonten.dtsi b/arch/arm/dts/tegra30-tamonten.dtsi
index 50d5762..c73afef 100644
--- a/arch/arm/dts/tegra30-tamonten.dtsi
+++ b/arch/arm/dts/tegra30-tamonten.dtsi
@@ -8,6 +8,10 @@
reg = <0x80000000 0x40000000>;
};
+ chosen {
+ stdout-path = &uartd;
+ };
+
aliases {
i2c0 = "/i2c@7000c000";
i2c1 = "/i2c@7000c700";
diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi
index 7be3791..fb92a0f 100644
--- a/arch/arm/dts/tegra30.dtsi
+++ b/arch/arm/dts/tegra30.dtsi
@@ -1,3 +1,4 @@
+#include <dt-bindings/clock/tegra30-car.h>
#include <dt-bindings/gpio/tegra-gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -122,6 +123,71 @@
status = "disabled";
};
+ uarta: serial@70006000 {
+ compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
+ reg = <0x70006000 0x40>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA30_CLK_UARTA>;
+ resets = <&tegra_car 6>;
+ reset-names = "serial";
+ dmas = <&apbdma 8>, <&apbdma 8>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uartb: serial@70006040 {
+ compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
+ reg = <0x70006040 0x40>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA30_CLK_UARTB>;
+ resets = <&tegra_car 7>;
+ reset-names = "serial";
+ dmas = <&apbdma 9>, <&apbdma 9>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uartc: serial@70006200 {
+ compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
+ reg = <0x70006200 0x100>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA30_CLK_UARTC>;
+ resets = <&tegra_car 55>;
+ reset-names = "serial";
+ dmas = <&apbdma 10>, <&apbdma 10>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uartd: serial@70006300 {
+ compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
+ reg = <0x70006300 0x100>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA30_CLK_UARTD>;
+ resets = <&tegra_car 65>;
+ reset-names = "serial";
+ dmas = <&apbdma 19>, <&apbdma 19>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uarte: serial@70006400 {
+ compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
+ reg = <0x70006400 0x100>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA30_CLK_UARTE>;
+ resets = <&tegra_car 66>;
+ reset-names = "serial";
+ dmas = <&apbdma 20>, <&apbdma 20>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
spi@7000d400 {
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
reg = <0x7000d400 0x200>;
diff --git a/arch/arm/include/asm/arch-tegra/gpio.h b/arch/arm/include/asm/arch-tegra/gpio.h
index 44cd455..7334e0c 100644
--- a/arch/arm/include/asm/arch-tegra/gpio.h
+++ b/arch/arm/include/asm/arch-tegra/gpio.h
@@ -6,6 +6,8 @@
#ifndef _TEGRA_GPIO_H_
#define _TEGRA_GPIO_H_
+#define TEGRA_GPIOS_PER_PORT 8
+#define TEGRA_PORTS_PER_BANK 4
#define MAX_NUM_GPIOS (TEGRA_GPIO_PORTS * TEGRA_GPIO_BANKS * 8)
#define GPIO_NAME_SIZE 20 /* gpio_request max label len */
@@ -25,9 +27,14 @@ struct tegra_gpio_config {
u32 init:2;
};
-/*
- * Tegra-specific GPIO API
+/**
+ * tegra_spl_gpio_direction_output() - set the output value of a GPIO
+ *
+ * This function is only used from SPL on seaboard, which needs to enable a
+ * GPIO to get the UART running. It could be done in U-Boot rather than SPL,
+ * but for now, this gets it working
*/
+int tegra_spl_gpio_direction_output(int gpio, int value);
/**
* Configure a list of GPIOs
@@ -37,8 +44,4 @@ struct tegra_gpio_config {
*/
void gpio_config_table(const struct tegra_gpio_config *config, int len);
-void gpio_info(void);
-
-#define gpio_status() gpio_info()
-
#endif /* TEGRA_GPIO_H_ */
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index efffacb..797478a 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -1,6 +1,16 @@
/dts-v1/;
/ {
+ chosen {
+ stdout-path = "/serial";
+ };
+
+ /* Needs to be available prior to relocation */
+ uart0: serial {
+ compatible = "sandbox,serial";
+ sandbox,text-colour = "cyan";
+ };
+
triangle {
compatible = "demo-shape";
colour = "cyan";
diff --git a/board/nvidia/seaboard/seaboard.c b/board/nvidia/seaboard/seaboard.c
index ce2db40..6a243f0 100644
--- a/board/nvidia/seaboard/seaboard.c
+++ b/board/nvidia/seaboard/seaboard.c
@@ -22,7 +22,7 @@ void gpio_early_init_uart(void)
#ifndef CONFIG_SPL_BUILD
gpio_request(GPIO_PI3, NULL);
#endif
- gpio_direction_output(GPIO_PI3, 0);
+ tegra_spl_gpio_direction_output(GPIO_PI3, 0);
}
#endif
diff --git a/common/board_f.c b/common/board_f.c
index 4ece2b6..ea33ead 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -831,6 +831,8 @@ static init_fnc_t init_sequence_f[] = {
#ifdef CONFIG_OF_CONTROL
fdtdec_check_fdt,
#endif
+ initf_malloc,
+ initf_dm,
#if defined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f,
#endif
@@ -866,8 +868,6 @@ static init_fnc_t init_sequence_f[] = {
sdram_adjust_866,
init_timebase,
#endif
- initf_malloc,
- initf_dm,
init_baud_rate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
diff --git a/common/board_r.c b/common/board_r.c
index 551429c..231c6d6 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -715,6 +715,15 @@ init_fnc_t init_sequence_r[] = {
/* TODO: could x86/PPC have this also perhaps? */
#ifdef CONFIG_ARM
initr_caches,
+#endif
+ initr_reloc_global_data,
+ initr_barrier,
+ initr_malloc,
+ bootstage_relocate,
+#ifdef CONFIG_DM
+ initr_dm,
+#endif
+#ifdef CONFIG_ARM
board_init, /* Setup chipselects */
#endif
/*
@@ -726,7 +735,7 @@ init_fnc_t init_sequence_r[] = {
#ifdef CONFIG_CLOCKS
set_cpu_clk_info, /* Setup clock information */
#endif
- initr_reloc_global_data,
+ stdio_init_tables,
initr_serial,
initr_announce,
INIT_FUNC_WATCHDOG_RESET
@@ -763,12 +772,6 @@ init_fnc_t init_sequence_r[] = {
#ifdef CONFIG_WINBOND_83C553
initr_w83c553f,
#endif
- initr_barrier,
- initr_malloc,
- bootstage_relocate,
-#ifdef CONFIG_DM
- initr_dm,
-#endif
#ifdef CONFIG_ARCH_EARLY_INIT_R
arch_early_init_r,
#endif
@@ -818,7 +821,7 @@ init_fnc_t init_sequence_r[] = {
*/
initr_pci,
#endif
- stdio_init,
+ stdio_add_devices,
initr_jumptable,
#ifdef CONFIG_API
initr_api,
diff --git a/common/stdio.c b/common/stdio.c
index 692ca7f..c878103 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -215,7 +215,7 @@ int stdio_deregister(const char *devname)
}
#endif /* CONFIG_SYS_STDIO_DEREGISTER */
-int stdio_init (void)
+int stdio_init_tables(void)
{
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
/* already relocated for current ARM implementation */
@@ -232,6 +232,11 @@ int stdio_init (void)
/* Initialize the list */
INIT_LIST_HEAD(&(devs.list));
+ return 0;
+}
+
+int stdio_add_devices(void)
+{
#ifdef CONFIG_SYS_I2C
i2c_init_all();
#else
@@ -265,5 +270,14 @@ int stdio_init (void)
#ifdef CONFIG_CBMEM_CONSOLE
cbmemc_init();
#endif
- return (0);
+
+ return 0;
+}
+
+int stdio_init(void)
+{
+ stdio_init_tables();
+ stdio_add_devices();
+
+ return 0;
}
diff --git a/doc/device-tree-bindings/serial/ns16550.txt b/doc/device-tree-bindings/serial/ns16550.txt
new file mode 100644
index 0000000..ef0b9ae
--- /dev/null
+++ b/doc/device-tree-bindings/serial/ns16550.txt
@@ -0,0 +1,10 @@
+NS16550 UART
+
+This UART driver supports many chip variants and is used in mamy SoCs.
+
+Required properties:
+- compatible: "ns16550" or "nvidia,tegra20-uart"
+- reg: start address and size of registers
+- reg-shift: shift value indicating register size: 0=byte, 1=16bit,2=32bit etc.
+- clock-frequency: input clock frequency for the UART (used to calculate the
+ baud rate divisor)
diff --git a/doc/device-tree-bindings/serial/sandbox-serial.txt b/doc/device-tree-bindings/serial/sandbox-serial.txt
new file mode 100644
index 0000000..f429c90
--- /dev/null
+++ b/doc/device-tree-bindings/serial/sandbox-serial.txt
@@ -0,0 +1,13 @@
+Sandbox serial
+
+The sandbox serial device is an emulated device which displays its output
+on the host machine's console, and accepts input from its keyboard.
+
+Required properties:
+ compatible: "sandbox,serial"
+
+Optional properties:
+ sandbox,text-colour: If present, this is the colour of the console text.
+ Supported values are:
+ "black", "red", "green", "yellow", "blue", "megenta", "cyan",
+ "white"
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index 0f08bfd..699f94b 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -118,7 +118,8 @@ static int driver_check_compatible(const void *blob, int offset,
return -ENOENT;
}
-int lists_bind_fdt(struct udevice *parent, const void *blob, int offset)
+int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
+ struct udevice **devp)
{
struct driver *driver = ll_entry_start(struct driver, driver);
const int n_ents = ll_entry_count(struct driver, driver);
@@ -130,6 +131,8 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset)
int ret = 0;
dm_dbg("bind node %s\n", fdt_get_name(blob, offset, NULL));
+ if (devp)
+ *devp = NULL;
for (entry = driver; entry != driver + n_ents; entry++) {
ret = driver_check_compatible(blob, offset, entry->of_match);
name = fdt_get_name(blob, offset, NULL);
@@ -149,10 +152,11 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset)
ret = device_bind(parent, entry, name, NULL, offset, &dev);
if (ret) {
dm_warn("Error binding driver '%s'\n", entry->name);
- if (!result || ret != -ENOENT)
- result = ret;
+ return ret;
} else {
found = true;
+ if (devp)
+ *devp = dev;
}
break;
}
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 393dd98..a328a48 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -91,7 +91,7 @@ int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
if (pre_reloc_only &&
!fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
continue;
- err = lists_bind_fdt(parent, blob, offset);
+ err = lists_bind_fdt(parent, blob, offset, NULL);
if (err && !ret)
ret = err;
}
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c
index fea9d17..1cc4abb 100644
--- a/drivers/gpio/tegra_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -12,10 +12,17 @@
*/
#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <errno.h>
+#include <fdtdec.h>
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/arch/tegra.h>
#include <asm/gpio.h>
+#include <dm/device-internal.h>
+
+DECLARE_GLOBAL_DATA_PTR;
enum {
TEGRA_CMD_INFO,
@@ -24,14 +31,18 @@ enum {
TEGRA_CMD_INPUT,
};
-static struct gpio_names {
- char name[GPIO_NAME_SIZE];
-} gpio_names[MAX_NUM_GPIOS];
+struct tegra_gpio_platdata {
+ struct gpio_ctlr_bank *bank;
+ const char *port_name; /* Name of port, e.g. "B" */
+ int base_gpio; /* Port number for this port (0, 1,.., n-1) */
+};
-static char *get_name(int i)
-{
- return *gpio_names[i].name ? gpio_names[i].name : "UNKNOWN";
-}
+/* Information about each port at run-time */
+struct tegra_port_info {
+ char label[TEGRA_GPIOS_PER_PORT][GPIO_NAME_SIZE];
+ struct gpio_ctlr_bank *bank;
+ int base_gpio; /* Port number for this port (0, 1,.., n-1) */
+};
/* Return config of pin 'gpio' as GPIO (1) or SFPIO (0) */
static int get_config(unsigned gpio)
@@ -121,38 +132,72 @@ static void set_level(unsigned gpio, int high)
writel(u, &bank->gpio_out[GPIO_PORT(gpio)]);
}
+static int check_reserved(struct udevice *dev, unsigned offset,
+ const char *func)
+{
+ struct tegra_port_info *state = dev_get_priv(dev);
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+ if (!*state->label[offset]) {
+ printf("tegra_gpio: %s: error: gpio %s%d not reserved\n",
+ func, uc_priv->bank_name, offset);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+/* set GPIO pin 'gpio' as an output, with polarity 'value' */
+int tegra_spl_gpio_direction_output(int gpio, int value)
+{
+ /* Configure as a GPIO */
+ set_config(gpio, 1);
+
+ /* Configure GPIO output value. */
+ set_level(gpio, value);
+
+ /* Configure GPIO direction as output. */
+ set_direction(gpio, 1);
+
+ return 0;
+}
+
/*
* Generic_GPIO primitives.
*/
-int gpio_request(unsigned gpio, const char *label)
+static int tegra_gpio_request(struct udevice *dev, unsigned offset,
+ const char *label)
{
- if (gpio >= MAX_NUM_GPIOS)
- return -1;
+ struct tegra_port_info *state = dev_get_priv(dev);
- if (label != NULL) {
- strncpy(gpio_names[gpio].name, label, GPIO_NAME_SIZE);
- gpio_names[gpio].name[GPIO_NAME_SIZE - 1] = '\0';
- }
+ if (*state->label[offset])
+ return -EBUSY;
+
+ strncpy(state->label[offset], label, GPIO_NAME_SIZE);
+ state->label[offset][GPIO_NAME_SIZE - 1] = '\0';
/* Configure as a GPIO */
- set_config(gpio, 1);
+ set_config(state->base_gpio + offset, 1);
return 0;
}
-int gpio_free(unsigned gpio)
+static int tegra_gpio_free(struct udevice *dev, unsigned offset)
{
- if (gpio >= MAX_NUM_GPIOS)
- return -1;
+ struct tegra_port_info *state = dev_get_priv(dev);
+ int ret;
+
+ ret = check_reserved(dev, offset, __func__);
+ if (ret)
+ return ret;
+ state->label[offset][0] = '\0';
- gpio_names[gpio].name[0] = '\0';
- /* Do not configure as input or change pin mux here */
return 0;
}
/* read GPIO OUT value of pin 'gpio' */
-static int gpio_get_output_value(unsigned gpio)
+static int tegra_gpio_get_output_value(unsigned gpio)
{
struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
@@ -166,24 +211,34 @@ static int gpio_get_output_value(unsigned gpio)
return (val >> GPIO_BIT(gpio)) & 1;
}
+
/* set GPIO pin 'gpio' as an input */
-int gpio_direction_input(unsigned gpio)
+static int tegra_gpio_direction_input(struct udevice *dev, unsigned offset)
{
- debug("gpio_direction_input: pin = %d (port %d:bit %d)\n",
- gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
+ struct tegra_port_info *state = dev_get_priv(dev);
+ int ret;
+
+ ret = check_reserved(dev, offset, __func__);
+ if (ret)
+ return ret;
/* Configure GPIO direction as input. */
- set_direction(gpio, 0);
+ set_direction(state->base_gpio + offset, 0);
return 0;
}
/* set GPIO pin 'gpio' as an output, with polarity 'value' */
-int gpio_direction_output(unsigned gpio, int value)
+static int tegra_gpio_direction_output(struct udevice *dev, unsigned offset,
+ int value)
{
- debug("gpio_direction_output: pin = %d (port %d:bit %d) = %s\n",
- gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio),
- value ? "HIGH" : "LOW");
+ struct tegra_port_info *state = dev_get_priv(dev);
+ int gpio = state->base_gpio + offset;
+ int ret;
+
+ ret = check_reserved(dev, offset, __func__);
+ if (ret)
+ return ret;
/* Configure GPIO output value. */
set_level(gpio, value);
@@ -195,25 +250,38 @@ int gpio_direction_output(unsigned gpio, int value)
}
/* read GPIO IN value of pin 'gpio' */
-int gpio_get_value(unsigned gpio)
+static int tegra_gpio_get_value(struct udevice *dev, unsigned offset)
{
- struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
- struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
+ struct tegra_port_info *state = dev_get_priv(dev);
+ int gpio = state->base_gpio + offset;
+ int ret;
int val;
- debug("gpio_get_value: pin = %d (port %d:bit %d)\n",
- gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
+ ret = check_reserved(dev, offset, __func__);
+ if (ret)
+ return ret;
+
+ debug("%s: pin = %d (port %d:bit %d)\n", __func__,
+ gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
- val = readl(&bank->gpio_in[GPIO_PORT(gpio)]);
+ val = readl(&state->bank->gpio_in[GPIO_PORT(gpio)]);
return (val >> GPIO_BIT(gpio)) & 1;
}
/* write GPIO OUT value to pin 'gpio' */
-int gpio_set_value(unsigned gpio, int value)
+static int tegra_gpio_set_value(struct udevice *dev, unsigned offset, int value)
{
+ struct tegra_port_info *state = dev_get_priv(dev);
+ int gpio = state->base_gpio + offset;
+ int ret;
+
+ ret = check_reserved(dev, offset, __func__);
+ if (ret)
+ return ret;
+
debug("gpio_set_value: pin = %d (port %d:bit %d), value = %d\n",
- gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio), value);
+ gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio), value);
/* Configure GPIO output value. */
set_level(gpio, value);
@@ -241,26 +309,175 @@ void gpio_config_table(const struct tegra_gpio_config *config, int len)
}
}
-/*
- * Display Tegra GPIO information
+static int tegra_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+ struct tegra_port_info *state = dev_get_priv(dev);
+ int gpio = state->base_gpio + offset;
+
+ if (!*state->label[offset])
+ return GPIOF_UNUSED;
+ if (!get_config(gpio))
+ return GPIOF_FUNC;
+ else if (get_direction(gpio))
+ return GPIOF_OUTPUT;
+ else
+ return GPIOF_INPUT;
+}
+
+static int tegra_gpio_get_state(struct udevice *dev, unsigned int offset,
+ char *buf, int bufsize)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ struct tegra_port_info *state = dev_get_priv(dev);
+ int gpio = state->base_gpio + offset;
+ const char *label;
+ int is_output;
+ int is_gpio;
+ int size;
+
+ label = state->label[offset];
+ is_gpio = get_config(gpio); /* GPIO, not SFPIO */
+ size = snprintf(buf, bufsize, "%s%d: ",
+ uc_priv->bank_name ? uc_priv->bank_name : "", offset);
+ buf += size;
+ bufsize -= size;
+ if (is_gpio) {
+ is_output = get_direction(gpio);
+
+ snprintf(buf, bufsize, "%s: %d [%c]%s%s",
+ is_output ? "out" : " in",
+ is_output ?
+ tegra_gpio_get_output_value(gpio) :
+ tegra_gpio_get_value(dev, offset),
+ *label ? 'x' : ' ',
+ *label ? " " : "",
+ label);
+ } else {
+ snprintf(buf, bufsize, "sfpio");
+ }
+
+ return 0;
+}
+
+static const struct dm_gpio_ops gpio_tegra_ops = {
+ .request = tegra_gpio_request,
+ .free = tegra_gpio_free,
+ .direction_input = tegra_gpio_direction_input,
+ .direction_output = tegra_gpio_direction_output,
+ .get_value = tegra_gpio_get_value,
+ .set_value = tegra_gpio_set_value,
+ .get_function = tegra_gpio_get_function,
+ .get_state = tegra_gpio_get_state,
+};
+
+/**
+ * Returns the name of a GPIO port
+ *
+ * GPIOs are named A, B, C, ..., Z, AA, BB, CC, ...
+ *
+ * @base_port: Base port number (0, 1..n-1)
+ * @return allocated string containing the name
*/
-void gpio_info(void)
+static char *gpio_port_name(int base_port)
{
- unsigned c;
- int type;
+ char *name, *s;
+
+ name = malloc(3);
+ if (name) {
+ s = name;
+ *s++ = 'A' + (base_port % 26);
+ if (base_port >= 26)
+ *s++ = *name;
+ *s = '\0';
+ }
- 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;
+ return name;
+}
+
+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->uclass_priv;
+ 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;
+ int len;
+
+ /* If this is a child device, there is nothing to do here */
+ if (plat)
+ return 0;
+
+ /*
+ * 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 *)fdtdec_get_addr(gd->fdt_blob,
+ parent->of_offset, "reg");
+ 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;
+ }
}
+
+ return 0;
}
+
+U_BOOT_DRIVER(gpio_tegra) = {
+ .name = "gpio_tegra",
+ .id = UCLASS_GPIO,
+ .of_match = tegra_gpio_ids,
+ .bind = gpio_tegra_bind,
+ .probe = gpio_tegra_probe,
+ .priv_auto_alloc_size = sizeof(struct tegra_port_info),
+ .ops = &gpio_tegra_ops,
+};
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 571c18f..853a8c6 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -5,7 +5,12 @@
# SPDX-License-Identifier: GPL-2.0+
#
+ifdef CONFIG_DM_SERIAL
+obj-y += serial-uclass.o
+else
obj-y += serial.o
+obj-$(CONFIG_SYS_NS16550_SERIAL) += serial_ns16550.o
+endif
obj-$(CONFIG_ALTERA_UART) += altera_uart.o
obj-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o
@@ -16,7 +21,6 @@ obj-$(CONFIG_MCFUART) += mcfuart.o
obj-$(CONFIG_OPENCORES_YANU) += opencores_yanu.o
obj-$(CONFIG_SYS_NS16550) += ns16550.o
obj-$(CONFIG_S5P) += serial_s5p.o
-obj-$(CONFIG_SYS_NS16550_SERIAL) += serial_ns16550.o
obj-$(CONFIG_IMX_SERIAL) += serial_imx.o
obj-$(CONFIG_KS8695_SERIAL) += serial_ks8695.o
obj-$(CONFIG_MAX3100_SERIAL) += serial_max3100.o
@@ -34,6 +38,7 @@ obj-$(CONFIG_BFIN_SERIAL) += serial_bfin.o
obj-$(CONFIG_FSL_LPUART) += serial_lpuart.o
obj-$(CONFIG_MXS_AUART) += mxs_auart.o
obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
+obj-$(CONFIG_TEGRA_SERIAL) += serial_tegra.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_USB_TTY) += usbtty.o
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 079f67d..63a9ef6 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -4,18 +4,26 @@
* modified to use CONFIG_SYS_ISA_MEM and new defines
*/
-#include <config.h>
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
#include <ns16550.h>
+#include <serial.h>
#include <watchdog.h>
#include <linux/types.h>
#include <asm/io.h>
+DECLARE_GLOBAL_DATA_PTR;
+
#define UART_LCRVAL UART_LCR_8N1 /* 8 data, 1 stop, no parity */
#define UART_MCRVAL (UART_MCR_DTR | \
UART_MCR_RTS) /* RTS/DTR */
#define UART_FCRVAL (UART_FCR_FIFO_EN | \
UART_FCR_RXSR | \
UART_FCR_TXSR) /* Clear & enable FIFOs */
+
+#ifndef CONFIG_DM_SERIAL
#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
#define serial_out(x, y) outb(x, (ulong)y)
#define serial_in(y) inb((ulong)y)
@@ -29,6 +37,7 @@
#define serial_out(x, y) writeb(x, y)
#define serial_in(y) readb(y)
#endif
+#endif /* !CONFIG_DM_SERIAL */
#if defined(CONFIG_SOC_KEYSTONE)
#define UART_REG_VAL_PWREMU_MGMT_UART_DISABLE 0
@@ -45,6 +54,82 @@
#define CONFIG_SYS_NS16550_IER 0x00
#endif /* CONFIG_SYS_NS16550_IER */
+#ifdef CONFIG_DM_SERIAL
+static void ns16550_writeb(NS16550_t port, int offset, int value)
+{
+ struct ns16550_platdata *plat = port->plat;
+ unsigned char *addr;
+
+ offset *= 1 << plat->reg_shift;
+ addr = plat->base + offset;
+ /*
+ * As far as we know it doesn't make sense to support selection of
+ * these options at run-time, so use the existing CONFIG options.
+ */
+#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+ outb(value, addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
+ out_le32(addr, value);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
+ out_be32(addr, value);
+#elif defined(CONFIG_SYS_BIG_ENDIAN)
+ writeb(value, addr + (1 << plat->reg_shift) - 1);
+#else
+ writeb(value, addr);
+#endif
+}
+
+static int ns16550_readb(NS16550_t port, int offset)
+{
+ struct ns16550_platdata *plat = port->plat;
+ unsigned char *addr;
+
+ offset *= 1 << plat->reg_shift;
+ addr = plat->base + offset;
+#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+ return inb(addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
+ return in_le32(addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
+ return in_be32(addr);
+#elif defined(CONFIG_SYS_BIG_ENDIAN)
+ return readb(addr + (1 << plat->reg_shift) - 1);
+#else
+ return readb(addr);
+#endif
+}
+
+/* We can clean these up once everything is moved to driver model */
+#define serial_out(value, addr) \
+ ns16550_writeb(com_port, addr - (unsigned char *)com_port, value)
+#define serial_in(addr) \
+ ns16550_readb(com_port, addr - (unsigned char *)com_port)
+#endif
+
+int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate)
+{
+ const unsigned int mode_x_div = 16;
+
+#ifdef CONFIG_OMAP1510
+ /* If can't cleanly clock 115200 set div to 1 */
+ if ((clock == 12000000) && (baudrate == 115200)) {
+ port->osc_12m_sel = OSC_12M_SEL; /* enable 6.5 * divisor */
+ return 1; /* return 1 for base divisor */
+ }
+ port->osc_12m_sel = 0; /* clear if previsouly set */
+#endif
+
+ return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate);
+}
+
+static void NS16550_setbrg(NS16550_t com_port, int baud_divisor)
+{
+ serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr);
+ serial_out(baud_divisor & 0xff, &com_port->dll);
+ serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm);
+ serial_out(UART_LCRVAL, &com_port->lcr);
+}
+
void NS16550_init(NS16550_t com_port, int baud_divisor)
{
#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_OMAP34XX))
@@ -55,10 +140,8 @@ void NS16550_init(NS16550_t com_port, int baud_divisor)
*/
if ((serial_in(&com_port->lsr) & (UART_LSR_TEMT | UART_LSR_THRE))
== UART_LSR_THRE) {
- serial_out(UART_LCR_DLAB, &com_port->lcr);
- serial_out(baud_divisor & 0xff, &com_port->dll);
- serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm);
- serial_out(UART_LCRVAL, &com_port->lcr);
+ if (baud_divisor != -1)
+ NS16550_setbrg(com_port, baud_divisor);
serial_out(0, &com_port->mdr1);
}
#endif
@@ -71,16 +154,11 @@ void NS16550_init(NS16550_t com_port, int baud_divisor)
defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX)
serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/
#endif
- serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr);
- serial_out(0, &com_port->dll);
- serial_out(0, &com_port->dlm);
- serial_out(UART_LCRVAL, &com_port->lcr);
+ NS16550_setbrg(com_port, 0);
serial_out(UART_MCRVAL, &com_port->mcr);
serial_out(UART_FCRVAL, &com_port->fcr);
- serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr);
- serial_out(baud_divisor & 0xff, &com_port->dll);
- serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm);
- serial_out(UART_LCRVAL, &com_port->lcr);
+ if (baud_divisor != -1)
+ NS16550_setbrg(com_port, baud_divisor);
#if defined(CONFIG_OMAP) || \
defined(CONFIG_AM33XX) || defined(CONFIG_SOC_DA8XX) || \
defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX)
@@ -97,16 +175,10 @@ void NS16550_init(NS16550_t com_port, int baud_divisor)
void NS16550_reinit(NS16550_t com_port, int baud_divisor)
{
serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier);
- serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr);
- serial_out(0, &com_port->dll);
- serial_out(0, &com_port->dlm);
- serial_out(UART_LCRVAL, &com_port->lcr);
+ NS16550_setbrg(com_port, 0);
serial_out(UART_MCRVAL, &com_port->mcr);
serial_out(UART_FCRVAL, &com_port->fcr);
- serial_out(UART_LCR_BKSE, &com_port->lcr);
- serial_out(baud_divisor & 0xff, &com_port->dll);
- serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm);
- serial_out(UART_LCRVAL, &com_port->lcr);
+ NS16550_setbrg(com_port, baud_divisor);
}
#endif /* CONFIG_NS16550_MIN_FUNCTIONS */
@@ -145,3 +217,92 @@ int NS16550_tstc(NS16550_t com_port)
}
#endif /* CONFIG_NS16550_MIN_FUNCTIONS */
+
+#ifdef CONFIG_DM_SERIAL
+static int ns16550_serial_putc(struct udevice *dev, const char ch)
+{
+ struct NS16550 *const com_port = dev_get_priv(dev);
+
+ if (!(serial_in(&com_port->lsr) & UART_LSR_THRE))
+ return -EAGAIN;
+ serial_out(ch, &com_port->thr);
+
+ /*
+ * Call watchdog_reset() upon newline. This is done here in putc
+ * since the environment code uses a single puts() to print the complete
+ * environment upon "printenv". So we can't put this watchdog call
+ * in puts().
+ */
+ if (ch == '\n')
+ WATCHDOG_RESET();
+
+ return 0;
+}
+
+static int ns16550_serial_pending(struct udevice *dev, bool input)
+{
+ struct NS16550 *const com_port = dev_get_priv(dev);
+
+ if (input)
+ return serial_in(&com_port->lsr) & UART_LSR_DR ? 1 : 0;
+ else
+ return serial_in(&com_port->lsr) & UART_LSR_THRE ? 0 : 1;
+}
+
+static int ns16550_serial_getc(struct udevice *dev)
+{
+ struct NS16550 *const com_port = dev_get_priv(dev);
+
+ if (!serial_in(&com_port->lsr) & UART_LSR_DR)
+ return -EAGAIN;
+
+ return serial_in(&com_port->rbr);
+}
+
+static int ns16550_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct NS16550 *const com_port = dev_get_priv(dev);
+ struct ns16550_platdata *plat = com_port->plat;
+ int clock_divisor;
+
+ clock_divisor = ns16550_calc_divisor(com_port, plat->clock, baudrate);
+
+ NS16550_setbrg(com_port, clock_divisor);
+
+ return 0;
+}
+
+int ns16550_serial_probe(struct udevice *dev)
+{
+ struct NS16550 *const com_port = dev_get_priv(dev);
+
+ NS16550_init(com_port, -1);
+
+ return 0;
+}
+
+int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
+{
+ struct NS16550 *const com_port = dev_get_priv(dev);
+ struct ns16550_platdata *plat = dev->platdata;
+ fdt_addr_t addr;
+
+ addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->base = (unsigned char *)addr;
+ plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ "reg-shift", 1);
+ com_port->plat = plat;
+
+ return 0;
+}
+
+const struct dm_serial_ops ns16550_serial_ops = {
+ .putc = ns16550_serial_putc,
+ .pending = ns16550_serial_pending,
+ .getc = ns16550_serial_getc,
+ .setbrg = ns16550_serial_setbrg,
+};
+#endif /* CONFIG_DM_SERIAL */
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index 51fd871..cd2f91e 100644
--- a/drivers/serial/sandbox.c
+++ b/drivers/serial/sandbox.c
@@ -11,12 +11,16 @@
*/
#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
#include <lcd.h>
#include <os.h>
#include <serial.h>
#include <linux/compiler.h>
#include <asm/state.h>
+DECLARE_GLOBAL_DATA_PTR;
+
/*
*
* serial_buf: A buffer that holds keyboard characters for the
@@ -30,27 +34,69 @@ static char serial_buf[16];
static unsigned int serial_buf_write;
static unsigned int serial_buf_read;
-static int sandbox_serial_init(void)
+struct sandbox_serial_platdata {
+ int colour; /* Text colour to use for output, -1 for none */
+};
+
+struct sandbox_serial_priv {
+ bool start_of_line;
+};
+
+/**
+ * output_ansi_colour() - Output an ANSI colour code
+ *
+ * @colour: Colour to output (0-7)
+ */
+static void output_ansi_colour(int colour)
+{
+ char ansi_code[] = "\x1b[1;3Xm";
+
+ ansi_code[5] = '0' + colour;
+ os_write(1, ansi_code, sizeof(ansi_code) - 1);
+}
+
+static void output_ansi_reset(void)
+{
+ os_write(1, "\x1b[0m", 4);
+}
+
+static int sandbox_serial_probe(struct udevice *dev)
{
struct sandbox_state *state = state_get_current();
+ struct sandbox_serial_priv *priv = dev_get_priv(dev);
if (state->term_raw != STATE_TERM_COOKED)
os_tty_raw(0, state->term_raw == STATE_TERM_RAW_WITH_SIGS);
+ priv->start_of_line = 0;
+
return 0;
}
-static void sandbox_serial_setbrg(void)
+static int sandbox_serial_remove(struct udevice *dev)
{
+ struct sandbox_serial_platdata *plat = dev->platdata;
+
+ if (plat->colour != -1)
+ output_ansi_reset();
+
+ return 0;
}
-static void sandbox_serial_putc(const char ch)
+static int sandbox_serial_putc(struct udevice *dev, const char ch)
{
+ struct sandbox_serial_priv *priv = dev_get_priv(dev);
+ struct sandbox_serial_platdata *plat = dev->platdata;
+
+ if (priv->start_of_line && plat->colour != -1) {
+ priv->start_of_line = false;
+ output_ansi_colour(plat->colour);
+ }
+
os_write(1, &ch, 1);
-}
+ if (ch == '\n')
+ priv->start_of_line = true;
-static void sandbox_serial_puts(const char *str)
-{
- os_write(1, str, strlen(str));
+ return 0;
}
static unsigned int increment_buffer_index(unsigned int index)
@@ -58,12 +104,15 @@ static unsigned int increment_buffer_index(unsigned int index)
return (index + 1) % ARRAY_SIZE(serial_buf);
}
-static int sandbox_serial_tstc(void)
+static int sandbox_serial_pending(struct udevice *dev, bool input)
{
const unsigned int next_index =
increment_buffer_index(serial_buf_write);
ssize_t count;
+ if (!input)
+ return 0;
+
os_usleep(100);
#ifdef CONFIG_LCD
lcd_sync();
@@ -74,38 +123,77 @@ static int sandbox_serial_tstc(void)
count = os_read_no_block(0, &serial_buf[serial_buf_write], 1);
if (count == 1)
serial_buf_write = next_index;
+
return serial_buf_write != serial_buf_read;
}
-static int sandbox_serial_getc(void)
+static int sandbox_serial_getc(struct udevice *dev)
{
int result;
- while (!sandbox_serial_tstc())
- ; /* buffer empty */
+ if (!sandbox_serial_pending(dev, true))
+ return -EAGAIN; /* buffer empty */
result = serial_buf[serial_buf_read];
serial_buf_read = increment_buffer_index(serial_buf_read);
return result;
}
-static struct serial_device sandbox_serial_drv = {
- .name = "sandbox_serial",
- .start = sandbox_serial_init,
- .stop = NULL,
- .setbrg = sandbox_serial_setbrg,
- .putc = sandbox_serial_putc,
- .puts = sandbox_serial_puts,
- .getc = sandbox_serial_getc,
- .tstc = sandbox_serial_tstc,
+static const char * const ansi_colour[] = {
+ "black", "red", "green", "yellow", "blue", "megenta", "cyan",
+ "white",
};
-void sandbox_serial_initialize(void)
+static int sandbox_serial_ofdata_to_platdata(struct udevice *dev)
{
- serial_register(&sandbox_serial_drv);
-}
+ struct sandbox_serial_platdata *plat = dev->platdata;
+ const char *colour;
+ int i;
+
+ plat->colour = -1;
+ colour = fdt_getprop(gd->fdt_blob, dev->of_offset,
+ "sandbox,text-colour", NULL);
+ if (colour) {
+ for (i = 0; i < ARRAY_SIZE(ansi_colour); i++) {
+ if (!strcmp(colour, ansi_colour[i])) {
+ plat->colour = i;
+ break;
+ }
+ }
+ }
-__weak struct serial_device *default_serial_console(void)
-{
- return &sandbox_serial_drv;
+ return 0;
}
+
+static const struct dm_serial_ops sandbox_serial_ops = {
+ .putc = sandbox_serial_putc,
+ .pending = sandbox_serial_pending,
+ .getc = sandbox_serial_getc,
+};
+
+static const struct udevice_id sandbox_serial_ids[] = {
+ { .compatible = "sandbox,serial" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_sandbox) = {
+ .name = "serial_sandbox",
+ .id = UCLASS_SERIAL,
+ .of_match = sandbox_serial_ids,
+ .ofdata_to_platdata = sandbox_serial_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct sandbox_serial_platdata),
+ .priv_auto_alloc_size = sizeof(struct sandbox_serial_priv),
+ .probe = sandbox_serial_probe,
+ .remove = sandbox_serial_remove,
+ .ops = &sandbox_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+static const struct sandbox_serial_platdata platdata_non_fdt = {
+ .colour = -1,
+};
+
+U_BOOT_DEVICE(serial_sandbox_non_fdt) = {
+ .name = "serial_sandbox",
+ .platdata = &platdata_non_fdt,
+};
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
new file mode 100644
index 0000000..d04104e
--- /dev/null
+++ b/drivers/serial/serial-uclass.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2014 The Chromium OS Authors.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <os.h>
+#include <serial.h>
+#include <stdio_dev.h>
+#include <dm/lists.h>
+#include <dm/device-internal.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* The currently-selected console serial device */
+struct udevice *cur_dev __attribute__ ((section(".data")));
+
+#ifndef CONFIG_SYS_MALLOC_F_LEN
+#error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work"
+#endif
+
+static void serial_find_console_or_panic(void)
+{
+ int node;
+
+ /* Check for a chosen console */
+ node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path");
+ if (node < 0)
+ node = fdtdec_get_alias_node(gd->fdt_blob, "console");
+ if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &cur_dev))
+ return;
+
+ /*
+ * If the console is not marked to be bound before relocation, bind
+ * it anyway.
+ */
+ if (node > 0 &&
+ !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &cur_dev)) {
+ if (!device_probe(cur_dev))
+ return;
+ cur_dev = NULL;
+ }
+
+ /*
+ * Failing that, get the device with sequence number 0, or in extremis
+ * just the first serial device we can find. But we insist on having
+ * a console (even if it is silent).
+ */
+ if (uclass_get_device_by_seq(UCLASS_SERIAL, 0, &cur_dev) &&
+ (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev))
+ panic("No serial driver found");
+}
+
+/* Called prior to relocation */
+int serial_init(void)
+{
+ serial_find_console_or_panic();
+ gd->flags |= GD_FLG_SERIAL_READY;
+
+ return 0;
+}
+
+/* Called after relocation */
+void serial_initialize(void)
+{
+ serial_find_console_or_panic();
+}
+
+void serial_putc(char ch)
+{
+ struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+ int err;
+
+ do {
+ err = ops->putc(cur_dev, ch);
+ } while (err == -EAGAIN);
+ if (ch == '\n')
+ serial_putc('\r');
+}
+
+void serial_setbrg(void)
+{
+ struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+
+ if (ops->setbrg)
+ ops->setbrg(cur_dev, gd->baudrate);
+}
+
+void serial_puts(const char *str)
+{
+ while (*str)
+ serial_putc(*str++);
+}
+
+int serial_tstc(void)
+{
+ struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+
+ if (ops->pending)
+ return ops->pending(cur_dev, true);
+
+ return 1;
+}
+
+int serial_getc(void)
+{
+ struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+ int err;
+
+ do {
+ err = ops->getc(cur_dev);
+ } while (err == -EAGAIN);
+
+ return err >= 0 ? err : 0;
+}
+
+void serial_stdio_init(void)
+{
+}
+
+void serial_stub_putc(struct stdio_dev *sdev, const char ch)
+{
+ struct udevice *dev = sdev->priv;
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+
+ ops->putc(dev, ch);
+}
+
+void serial_stub_puts(struct stdio_dev *sdev, const char *str)
+{
+ while (*str)
+ serial_stub_putc(sdev, *str++);
+}
+
+int serial_stub_getc(struct stdio_dev *sdev)
+{
+ struct udevice *dev = sdev->priv;
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+
+ int err;
+
+ do {
+ err = ops->getc(dev);
+ } while (err == -EAGAIN);
+
+ return err >= 0 ? err : 0;
+}
+
+int serial_stub_tstc(struct stdio_dev *sdev)
+{
+ struct udevice *dev = sdev->priv;
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+
+ if (ops->pending)
+ return ops->pending(dev, true);
+
+ return 1;
+}
+
+static int serial_post_probe(struct udevice *dev)
+{
+ struct stdio_dev sdev;
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+ struct serial_dev_priv *upriv = dev->uclass_priv;
+ int ret;
+
+ /* Set the baud rate */
+ if (ops->setbrg) {
+ ret = ops->setbrg(dev, gd->baudrate);
+ if (ret)
+ return ret;
+ }
+
+ if (!(gd->flags & GD_FLG_RELOC))
+ return 0;
+
+ memset(&sdev, '\0', sizeof(sdev));
+
+ strncpy(sdev.name, dev->name, sizeof(sdev.name));
+ sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
+ sdev.priv = dev;
+ sdev.putc = serial_stub_putc;
+ sdev.puts = serial_stub_puts;
+ sdev.getc = serial_stub_getc;
+ sdev.tstc = serial_stub_tstc;
+ stdio_register_dev(&sdev, &upriv->sdev);
+
+ return 0;
+}
+
+static int serial_pre_remove(struct udevice *dev)
+{
+#ifdef CONFIG_SYS_STDIO_DEREGISTER
+ struct serial_dev_priv *upriv = dev->uclass_priv;
+
+ if (stdio_deregister_dev(upriv->sdev))
+ return -EPERM;
+#endif
+
+ return 0;
+}
+
+UCLASS_DRIVER(serial) = {
+ .id = UCLASS_SERIAL,
+ .name = "serial",
+ .post_probe = serial_post_probe,
+ .pre_remove = serial_pre_remove,
+ .per_device_auto_alloc_size = sizeof(struct serial_dev_priv),
+};
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index d2eb752..bbe60af 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -320,6 +320,7 @@ void serial_stdio_init(void)
dev.puts = serial_stub_puts;
dev.getc = serial_stub_getc;
dev.tstc = serial_stub_tstc;
+ dev.priv = s;
stdio_register(&dev);
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index dafeed7..632da4c 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -81,7 +81,8 @@ static NS16550_t serial_ports[6] = {
static int eserial##port##_init(void) \
{ \
int clock_divisor; \
- clock_divisor = calc_divisor(serial_ports[port-1]); \
+ clock_divisor = ns16550_calc_divisor(serial_ports[port-1], \
+ CONFIG_SYS_NS16550_CLK, gd->baudrate); \
NS16550_init(serial_ports[port-1], clock_divisor); \
return 0 ; \
} \
@@ -118,14 +119,6 @@ static NS16550_t serial_ports[6] = {
.puts = eserial##port##_puts, \
}
-static int calc_divisor (NS16550_t port)
-{
- const unsigned int mode_x_div = 16;
-
- return DIV_ROUND_CLOSEST(CONFIG_SYS_NS16550_CLK,
- mode_x_div * gd->baudrate);
-}
-
void
_serial_putc(const char c,const int port)
{
@@ -167,7 +160,8 @@ _serial_setbrg (const int port)
{
int clock_divisor;
- clock_divisor = calc_divisor(PORT);
+ clock_divisor = ns16550_calc_divisor(PORT, CONFIG_SYS_NS16550_CLK,
+ gd->baudrate);
NS16550_reinit(PORT, clock_divisor);
}
diff --git a/drivers/serial/serial_tegra.c b/drivers/serial/serial_tegra.c
new file mode 100644
index 0000000..7eb70e1
--- /dev/null
+++ b/drivers/serial/serial_tegra.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ns16550.h>
+#include <serial.h>
+
+static const struct udevice_id tegra_serial_ids[] = {
+ { .compatible = "nvidia,tegra20-uart" },
+ { }
+};
+
+static int tegra_serial_ofdata_to_platdata(struct udevice *dev)
+{
+ struct ns16550_platdata *plat = dev_get_platdata(dev);
+ int ret;
+
+ ret = ns16550_serial_ofdata_to_platdata(dev);
+ if (ret)
+ return ret;
+ plat->clock = V_NS16550_CLK;
+
+ return 0;
+}
+U_BOOT_DRIVER(serial_ns16550) = {
+ .name = "serial_tegra20",
+ .id = UCLASS_SERIAL,
+ .of_match = tegra_serial_ids,
+ .ofdata_to_platdata = tegra_serial_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+ .priv_auto_alloc_size = sizeof(struct NS16550),
+ .probe = ns16550_serial_probe,
+ .ops = &ns16550_serial_ops,
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index bf2d25c..f5fa4b3 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -31,6 +31,9 @@
#define CONFIG_DM_DEMO_SHAPE
#define CONFIG_DM_GPIO
#define CONFIG_DM_TEST
+#define CONFIG_DM_SERIAL
+
+#define CONFIG_SYS_STDIO_DEREGISTER
/* Number of bits in a C 'long' on this architecture */
#define CONFIG_SANDBOX_BITS_PER_LONG 64
diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h
index d27fceb..834b3d5 100644
--- a/include/configs/tegra-common.h
+++ b/include/configs/tegra-common.h
@@ -20,6 +20,10 @@
#define CONFIG_DM
#define CONFIG_CMD_DM
+#define CONFIG_DM_GPIO
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_DM_SERIAL
+#endif
#define CONFIG_SYS_TIMER_RATE 1000000
#define CONFIG_SYS_TIMER_COUNTER NV_PA_TMRUS_BASE
@@ -40,14 +44,19 @@
* Size of malloc() pool
*/
#define CONFIG_SYS_MALLOC_LEN (4 << 20) /* 4MB */
+#define CONFIG_SYS_MALLOC_F_LEN (1 << 10)
/*
* NS16550 Configuration
*/
-#define CONFIG_SYS_NS16550
+#ifdef CONFIG_SPL_BUILD
#define CONFIG_SYS_NS16550_SERIAL
#define CONFIG_SYS_NS16550_REG_SIZE (-4)
#define CONFIG_SYS_NS16550_CLK V_NS16550_CLK
+#else
+#define CONFIG_TEGRA_SERIAL
+#endif
+#define CONFIG_SYS_NS16550
/*
* Common HW configuration.
diff --git a/include/dm/lists.h b/include/dm/lists.h
index 87a3af5..2356895 100644
--- a/include/dm/lists.h
+++ b/include/dm/lists.h
@@ -53,7 +53,11 @@ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only);
* @parent: parent driver (root)
* @blob: device tree blob
* @offset: offset of this device tree node
+ * @devp: if non-NULL, returns a pointer to the bound device
+ * @return 0 if device was bound, -EINVAL if the device tree is invalid,
+ * other -ve value on error
*/
-int lists_bind_fdt(struct udevice *parent, const void *blob, int offset);
+int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
+ struct udevice **devp);
#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index dd95fca..7f0e37b 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -21,6 +21,7 @@ enum uclass_id {
/* U-Boot uclasses start here */
UCLASS_GPIO, /* Bank of general-purpose I/O pins */
+ UCLASS_SERIAL, /* Serial UART */
UCLASS_COUNT,
UCLASS_INVALID = -1,
diff --git a/include/dt-bindings/clock/tegra114-car.h b/include/dt-bindings/clock/tegra114-car.h
new file mode 100644
index 0000000..6d0d8d8
--- /dev/null
+++ b/include/dt-bindings/clock/tegra114-car.h
@@ -0,0 +1,342 @@
+/*
+ * This header provides constants for binding nvidia,tegra114-car.
+ *
+ * The first 160 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+ * registers. These IDs often match those in the CAR's RST_DEVICES registers,
+ * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+ * this case, those clocks are assigned IDs above 160 in order to highlight
+ * this issue. Implementations that interpret these clock IDs as bit values
+ * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+ * explicitly handle these special cases.
+ *
+ * The balance of the clocks controlled by the CAR are assigned IDs of 160 and
+ * above.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_TEGRA114_CAR_H
+#define _DT_BINDINGS_CLOCK_TEGRA114_CAR_H
+
+/* 0 */
+/* 1 */
+/* 2 */
+/* 3 */
+#define TEGRA114_CLK_RTC 4
+#define TEGRA114_CLK_TIMER 5
+#define TEGRA114_CLK_UARTA 6
+/* 7 (register bit affects uartb and vfir) */
+/* 8 */
+#define TEGRA114_CLK_SDMMC2 9
+/* 10 (register bit affects spdif_in and spdif_out) */
+#define TEGRA114_CLK_I2S1 11
+#define TEGRA114_CLK_I2C1 12
+#define TEGRA114_CLK_NDFLASH 13
+#define TEGRA114_CLK_SDMMC1 14
+#define TEGRA114_CLK_SDMMC4 15
+/* 16 */
+#define TEGRA114_CLK_PWM 17
+#define TEGRA114_CLK_I2S2 18
+#define TEGRA114_CLK_EPP 19
+/* 20 (register bit affects vi and vi_sensor) */
+#define TEGRA114_CLK_GR2D 21
+#define TEGRA114_CLK_USBD 22
+#define TEGRA114_CLK_ISP 23
+#define TEGRA114_CLK_GR3D 24
+/* 25 */
+#define TEGRA114_CLK_DISP2 26
+#define TEGRA114_CLK_DISP1 27
+#define TEGRA114_CLK_HOST1X 28
+#define TEGRA114_CLK_VCP 29
+#define TEGRA114_CLK_I2S0 30
+/* 31 */
+
+/* 32 */
+/* 33 */
+#define TEGRA114_CLK_APBDMA 34
+/* 35 */
+#define TEGRA114_CLK_KBC 36
+/* 37 */
+/* 38 */
+/* 39 (register bit affects fuse and fuse_burn) */
+#define TEGRA114_CLK_KFUSE 40
+#define TEGRA114_CLK_SBC1 41
+#define TEGRA114_CLK_NOR 42
+/* 43 */
+#define TEGRA114_CLK_SBC2 44
+/* 45 */
+#define TEGRA114_CLK_SBC3 46
+#define TEGRA114_CLK_I2C5 47
+#define TEGRA114_CLK_DSIA 48
+/* 49 */
+#define TEGRA114_CLK_MIPI 50
+#define TEGRA114_CLK_HDMI 51
+#define TEGRA114_CLK_CSI 52
+/* 53 */
+#define TEGRA114_CLK_I2C2 54
+#define TEGRA114_CLK_UARTC 55
+#define TEGRA114_CLK_MIPI_CAL 56
+#define TEGRA114_CLK_EMC 57
+#define TEGRA114_CLK_USB2 58
+#define TEGRA114_CLK_USB3 59
+/* 60 */
+#define TEGRA114_CLK_VDE 61
+#define TEGRA114_CLK_BSEA 62
+#define TEGRA114_CLK_BSEV 63
+
+/* 64 */
+#define TEGRA114_CLK_UARTD 65
+/* 66 */
+#define TEGRA114_CLK_I2C3 67
+#define TEGRA114_CLK_SBC4 68
+#define TEGRA114_CLK_SDMMC3 69
+/* 70 */
+#define TEGRA114_CLK_OWR 71
+/* 72 */
+#define TEGRA114_CLK_CSITE 73
+/* 74 */
+/* 75 */
+#define TEGRA114_CLK_LA 76
+#define TEGRA114_CLK_TRACE 77
+#define TEGRA114_CLK_SOC_THERM 78
+#define TEGRA114_CLK_DTV 79
+#define TEGRA114_CLK_NDSPEED 80
+#define TEGRA114_CLK_I2CSLOW 81
+#define TEGRA114_CLK_DSIB 82
+#define TEGRA114_CLK_TSEC 83
+/* 84 */
+/* 85 */
+/* 86 */
+/* 87 */
+/* 88 */
+#define TEGRA114_CLK_XUSB_HOST 89
+/* 90 */
+#define TEGRA114_CLK_MSENC 91
+#define TEGRA114_CLK_CSUS 92
+/* 93 */
+/* 94 */
+/* 95 (bit affects xusb_dev and xusb_dev_src) */
+
+/* 96 */
+/* 97 */
+/* 98 */
+#define TEGRA114_CLK_MSELECT 99
+#define TEGRA114_CLK_TSENSOR 100
+#define TEGRA114_CLK_I2S3 101
+#define TEGRA114_CLK_I2S4 102
+#define TEGRA114_CLK_I2C4 103
+#define TEGRA114_CLK_SBC5 104
+#define TEGRA114_CLK_SBC6 105
+#define TEGRA114_CLK_D_AUDIO 106
+#define TEGRA114_CLK_APBIF 107
+#define TEGRA114_CLK_DAM0 108
+#define TEGRA114_CLK_DAM1 109
+#define TEGRA114_CLK_DAM2 110
+#define TEGRA114_CLK_HDA2CODEC_2X 111
+/* 112 */
+#define TEGRA114_CLK_AUDIO0_2X 113
+#define TEGRA114_CLK_AUDIO1_2X 114
+#define TEGRA114_CLK_AUDIO2_2X 115
+#define TEGRA114_CLK_AUDIO3_2X 116
+#define TEGRA114_CLK_AUDIO4_2X 117
+#define TEGRA114_CLK_SPDIF_2X 118
+#define TEGRA114_CLK_ACTMON 119
+#define TEGRA114_CLK_EXTERN1 120
+#define TEGRA114_CLK_EXTERN2 121
+#define TEGRA114_CLK_EXTERN3 122
+/* 123 */
+/* 124 */
+#define TEGRA114_CLK_HDA 125
+/* 126 */
+#define TEGRA114_CLK_SE 127
+
+#define TEGRA114_CLK_HDA2HDMI 128
+/* 129 */
+/* 130 */
+/* 131 */
+/* 132 */
+/* 133 */
+/* 134 */
+/* 135 */
+/* 136 */
+/* 137 */
+/* 138 */
+/* 139 */
+/* 140 */
+/* 141 */
+/* 142 */
+/* 143 (bit affects xusb_falcon_src, xusb_fs_src, */
+/* xusb_host_src and xusb_ss_src) */
+#define TEGRA114_CLK_CILAB 144
+#define TEGRA114_CLK_CILCD 145
+#define TEGRA114_CLK_CILE 146
+#define TEGRA114_CLK_DSIALP 147
+#define TEGRA114_CLK_DSIBLP 148
+/* 149 */
+#define TEGRA114_CLK_DDS 150
+/* 151 */
+#define TEGRA114_CLK_DP2 152
+#define TEGRA114_CLK_AMX 153
+#define TEGRA114_CLK_ADX 154
+/* 155 (bit affects dfll_ref and dfll_soc) */
+#define TEGRA114_CLK_XUSB_SS 156
+/* 157 */
+/* 158 */
+/* 159 */
+
+/* 160 */
+/* 161 */
+/* 162 */
+/* 163 */
+/* 164 */
+/* 165 */
+/* 166 */
+/* 167 */
+/* 168 */
+/* 169 */
+/* 170 */
+/* 171 */
+/* 172 */
+/* 173 */
+/* 174 */
+/* 175 */
+/* 176 */
+/* 177 */
+/* 178 */
+/* 179 */
+/* 180 */
+/* 181 */
+/* 182 */
+/* 183 */
+/* 184 */
+/* 185 */
+/* 186 */
+/* 187 */
+/* 188 */
+/* 189 */
+/* 190 */
+/* 191 */
+
+#define TEGRA114_CLK_UARTB 192
+#define TEGRA114_CLK_VFIR 193
+#define TEGRA114_CLK_SPDIF_IN 194
+#define TEGRA114_CLK_SPDIF_OUT 195
+#define TEGRA114_CLK_VI 196
+#define TEGRA114_CLK_VI_SENSOR 197
+#define TEGRA114_CLK_FUSE 198
+#define TEGRA114_CLK_FUSE_BURN 199
+#define TEGRA114_CLK_CLK_32K 200
+#define TEGRA114_CLK_CLK_M 201
+#define TEGRA114_CLK_CLK_M_DIV2 202
+#define TEGRA114_CLK_CLK_M_DIV4 203
+#define TEGRA114_CLK_PLL_REF 204
+#define TEGRA114_CLK_PLL_C 205
+#define TEGRA114_CLK_PLL_C_OUT1 206
+#define TEGRA114_CLK_PLL_C2 207
+#define TEGRA114_CLK_PLL_C3 208
+#define TEGRA114_CLK_PLL_M 209
+#define TEGRA114_CLK_PLL_M_OUT1 210
+#define TEGRA114_CLK_PLL_P 211
+#define TEGRA114_CLK_PLL_P_OUT1 212
+#define TEGRA114_CLK_PLL_P_OUT2 213
+#define TEGRA114_CLK_PLL_P_OUT3 214
+#define TEGRA114_CLK_PLL_P_OUT4 215
+#define TEGRA114_CLK_PLL_A 216
+#define TEGRA114_CLK_PLL_A_OUT0 217
+#define TEGRA114_CLK_PLL_D 218
+#define TEGRA114_CLK_PLL_D_OUT0 219
+#define TEGRA114_CLK_PLL_D2 220
+#define TEGRA114_CLK_PLL_D2_OUT0 221
+#define TEGRA114_CLK_PLL_U 222
+#define TEGRA114_CLK_PLL_U_480M 223
+
+#define TEGRA114_CLK_PLL_U_60M 224
+#define TEGRA114_CLK_PLL_U_48M 225
+#define TEGRA114_CLK_PLL_U_12M 226
+#define TEGRA114_CLK_PLL_X 227
+#define TEGRA114_CLK_PLL_X_OUT0 228
+#define TEGRA114_CLK_PLL_RE_VCO 229
+#define TEGRA114_CLK_PLL_RE_OUT 230
+#define TEGRA114_CLK_PLL_E_OUT0 231
+#define TEGRA114_CLK_SPDIF_IN_SYNC 232
+#define TEGRA114_CLK_I2S0_SYNC 233
+#define TEGRA114_CLK_I2S1_SYNC 234
+#define TEGRA114_CLK_I2S2_SYNC 235
+#define TEGRA114_CLK_I2S3_SYNC 236
+#define TEGRA114_CLK_I2S4_SYNC 237
+#define TEGRA114_CLK_VIMCLK_SYNC 238
+#define TEGRA114_CLK_AUDIO0 239
+#define TEGRA114_CLK_AUDIO1 240
+#define TEGRA114_CLK_AUDIO2 241
+#define TEGRA114_CLK_AUDIO3 242
+#define TEGRA114_CLK_AUDIO4 243
+#define TEGRA114_CLK_SPDIF 244
+#define TEGRA114_CLK_CLK_OUT_1 245
+#define TEGRA114_CLK_CLK_OUT_2 246
+#define TEGRA114_CLK_CLK_OUT_3 247
+#define TEGRA114_CLK_BLINK 248
+/* 249 */
+/* 250 */
+/* 251 */
+#define TEGRA114_CLK_XUSB_HOST_SRC 252
+#define TEGRA114_CLK_XUSB_FALCON_SRC 253
+#define TEGRA114_CLK_XUSB_FS_SRC 254
+#define TEGRA114_CLK_XUSB_SS_SRC 255
+
+#define TEGRA114_CLK_XUSB_DEV_SRC 256
+#define TEGRA114_CLK_XUSB_DEV 257
+#define TEGRA114_CLK_XUSB_HS_SRC 258
+#define TEGRA114_CLK_SCLK 259
+#define TEGRA114_CLK_HCLK 260
+#define TEGRA114_CLK_PCLK 261
+#define TEGRA114_CLK_CCLK_G 262
+#define TEGRA114_CLK_CCLK_LP 263
+#define TEGRA114_CLK_DFLL_REF 264
+#define TEGRA114_CLK_DFLL_SOC 265
+/* 266 */
+/* 267 */
+/* 268 */
+/* 269 */
+/* 270 */
+/* 271 */
+/* 272 */
+/* 273 */
+/* 274 */
+/* 275 */
+/* 276 */
+/* 277 */
+/* 278 */
+/* 279 */
+/* 280 */
+/* 281 */
+/* 282 */
+/* 283 */
+/* 284 */
+/* 285 */
+/* 286 */
+/* 287 */
+
+/* 288 */
+/* 289 */
+/* 290 */
+/* 291 */
+/* 292 */
+/* 293 */
+/* 294 */
+/* 295 */
+/* 296 */
+/* 297 */
+/* 298 */
+/* 299 */
+#define TEGRA114_CLK_AUDIO0_MUX 300
+#define TEGRA114_CLK_AUDIO1_MUX 301
+#define TEGRA114_CLK_AUDIO2_MUX 302
+#define TEGRA114_CLK_AUDIO3_MUX 303
+#define TEGRA114_CLK_AUDIO4_MUX 304
+#define TEGRA114_CLK_SPDIF_MUX 305
+#define TEGRA114_CLK_CLK_OUT_1_MUX 306
+#define TEGRA114_CLK_CLK_OUT_2_MUX 307
+#define TEGRA114_CLK_CLK_OUT_3_MUX 308
+#define TEGRA114_CLK_DSIA_MUX 309
+#define TEGRA114_CLK_DSIB_MUX 310
+#define TEGRA114_CLK_CLK_MAX 311
+
+#endif /* _DT_BINDINGS_CLOCK_TEGRA114_CAR_H */
diff --git a/include/dt-bindings/clock/tegra124-car.h b/include/dt-bindings/clock/tegra124-car.h
new file mode 100644
index 0000000..fd8d62a
--- /dev/null
+++ b/include/dt-bindings/clock/tegra124-car.h
@@ -0,0 +1,342 @@
+/*
+ * This header provides constants for binding nvidia,tegra124-car.
+ *
+ * The first 192 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+ * registers. These IDs often match those in the CAR's RST_DEVICES registers,
+ * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+ * this case, those clocks are assigned IDs above 185 in order to highlight
+ * this issue. Implementations that interpret these clock IDs as bit values
+ * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+ * explicitly handle these special cases.
+ *
+ * The balance of the clocks controlled by the CAR are assigned IDs of 185 and
+ * above.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_TEGRA124_CAR_H
+#define _DT_BINDINGS_CLOCK_TEGRA124_CAR_H
+
+/* 0 */
+/* 1 */
+/* 2 */
+#define TEGRA124_CLK_ISPB 3
+#define TEGRA124_CLK_RTC 4
+#define TEGRA124_CLK_TIMER 5
+#define TEGRA124_CLK_UARTA 6
+/* 7 (register bit affects uartb and vfir) */
+/* 8 */
+#define TEGRA124_CLK_SDMMC2 9
+/* 10 (register bit affects spdif_in and spdif_out) */
+#define TEGRA124_CLK_I2S1 11
+#define TEGRA124_CLK_I2C1 12
+#define TEGRA124_CLK_NDFLASH 13
+#define TEGRA124_CLK_SDMMC1 14
+#define TEGRA124_CLK_SDMMC4 15
+/* 16 */
+#define TEGRA124_CLK_PWM 17
+#define TEGRA124_CLK_I2S2 18
+/* 20 (register bit affects vi and vi_sensor) */
+/* 21 */
+#define TEGRA124_CLK_USBD 22
+#define TEGRA124_CLK_ISP 23
+/* 26 */
+/* 25 */
+#define TEGRA124_CLK_DISP2 26
+#define TEGRA124_CLK_DISP1 27
+#define TEGRA124_CLK_HOST1X 28
+#define TEGRA124_CLK_VCP 29
+#define TEGRA124_CLK_I2S0 30
+/* 31 */
+
+/* 32 */
+/* 33 */
+#define TEGRA124_CLK_APBDMA 34
+/* 35 */
+#define TEGRA124_CLK_KBC 36
+/* 37 */
+/* 38 */
+/* 39 (register bit affects fuse and fuse_burn) */
+#define TEGRA124_CLK_KFUSE 40
+#define TEGRA124_CLK_SBC1 41
+#define TEGRA124_CLK_NOR 42
+/* 43 */
+#define TEGRA124_CLK_SBC2 44
+/* 45 */
+#define TEGRA124_CLK_SBC3 46
+#define TEGRA124_CLK_I2C5 47
+#define TEGRA124_CLK_DSIA 48
+/* 49 */
+#define TEGRA124_CLK_MIPI 50
+#define TEGRA124_CLK_HDMI 51
+#define TEGRA124_CLK_CSI 52
+/* 53 */
+#define TEGRA124_CLK_I2C2 54
+#define TEGRA124_CLK_UARTC 55
+#define TEGRA124_CLK_MIPI_CAL 56
+#define TEGRA124_CLK_EMC 57
+#define TEGRA124_CLK_USB2 58
+#define TEGRA124_CLK_USB3 59
+/* 60 */
+#define TEGRA124_CLK_VDE 61
+#define TEGRA124_CLK_BSEA 62
+#define TEGRA124_CLK_BSEV 63
+
+/* 64 */
+#define TEGRA124_CLK_UARTD 65
+#define TEGRA124_CLK_UARTE 66
+#define TEGRA124_CLK_I2C3 67
+#define TEGRA124_CLK_SBC4 68
+#define TEGRA124_CLK_SDMMC3 69
+#define TEGRA124_CLK_PCIE 70
+#define TEGRA124_CLK_OWR 71
+#define TEGRA124_CLK_AFI 72
+#define TEGRA124_CLK_CSITE 73
+/* 74 */
+/* 75 */
+#define TEGRA124_CLK_LA 76
+#define TEGRA124_CLK_TRACE 77
+#define TEGRA124_CLK_SOC_THERM 78
+#define TEGRA124_CLK_DTV 79
+#define TEGRA124_CLK_NDSPEED 80
+#define TEGRA124_CLK_I2CSLOW 81
+#define TEGRA124_CLK_DSIB 82
+#define TEGRA124_CLK_TSEC 83
+/* 84 */
+/* 85 */
+/* 86 */
+/* 87 */
+/* 88 */
+#define TEGRA124_CLK_XUSB_HOST 89
+/* 90 */
+#define TEGRA124_CLK_MSENC 91
+#define TEGRA124_CLK_CSUS 92
+/* 93 */
+/* 94 */
+/* 95 (bit affects xusb_dev and xusb_dev_src) */
+
+/* 96 */
+/* 97 */
+/* 98 */
+#define TEGRA124_CLK_MSELECT 99
+#define TEGRA124_CLK_TSENSOR 100
+#define TEGRA124_CLK_I2S3 101
+#define TEGRA124_CLK_I2S4 102
+#define TEGRA124_CLK_I2C4 103
+#define TEGRA124_CLK_SBC5 104
+#define TEGRA124_CLK_SBC6 105
+#define TEGRA124_CLK_D_AUDIO 106
+#define TEGRA124_CLK_APBIF 107
+#define TEGRA124_CLK_DAM0 108
+#define TEGRA124_CLK_DAM1 109
+#define TEGRA124_CLK_DAM2 110
+#define TEGRA124_CLK_HDA2CODEC_2X 111
+/* 112 */
+#define TEGRA124_CLK_AUDIO0_2X 113
+#define TEGRA124_CLK_AUDIO1_2X 114
+#define TEGRA124_CLK_AUDIO2_2X 115
+#define TEGRA124_CLK_AUDIO3_2X 116
+#define TEGRA124_CLK_AUDIO4_2X 117
+#define TEGRA124_CLK_SPDIF_2X 118
+#define TEGRA124_CLK_ACTMON 119
+#define TEGRA124_CLK_EXTERN1 120
+#define TEGRA124_CLK_EXTERN2 121
+#define TEGRA124_CLK_EXTERN3 122
+#define TEGRA124_CLK_SATA_OOB 123
+#define TEGRA124_CLK_SATA 124
+#define TEGRA124_CLK_HDA 125
+/* 126 */
+#define TEGRA124_CLK_SE 127
+
+#define TEGRA124_CLK_HDA2HDMI 128
+#define TEGRA124_CLK_SATA_COLD 129
+/* 130 */
+/* 131 */
+/* 132 */
+/* 133 */
+/* 134 */
+/* 135 */
+/* 136 */
+/* 137 */
+/* 138 */
+/* 139 */
+/* 140 */
+/* 141 */
+/* 142 */
+/* 143 (bit affects xusb_falcon_src, xusb_fs_src, */
+/* xusb_host_src and xusb_ss_src) */
+#define TEGRA124_CLK_CILAB 144
+#define TEGRA124_CLK_CILCD 145
+#define TEGRA124_CLK_CILE 146
+#define TEGRA124_CLK_DSIALP 147
+#define TEGRA124_CLK_DSIBLP 148
+#define TEGRA124_CLK_ENTROPY 149
+#define TEGRA124_CLK_DDS 150
+/* 151 */
+#define TEGRA124_CLK_DP2 152
+#define TEGRA124_CLK_AMX 153
+#define TEGRA124_CLK_ADX 154
+/* 155 (bit affects dfll_ref and dfll_soc) */
+#define TEGRA124_CLK_XUSB_SS 156
+/* 157 */
+/* 158 */
+/* 159 */
+
+/* 160 */
+/* 161 */
+/* 162 */
+/* 163 */
+/* 164 */
+/* 165 */
+#define TEGRA124_CLK_I2C6 166
+/* 167 */
+/* 168 */
+/* 169 */
+/* 170 */
+#define TEGRA124_CLK_VIM2_CLK 171
+/* 172 */
+/* 173 */
+/* 174 */
+/* 175 */
+#define TEGRA124_CLK_HDMI_AUDIO 176
+#define TEGRA124_CLK_CLK72MHZ 177
+#define TEGRA124_CLK_VIC03 178
+/* 179 */
+#define TEGRA124_CLK_ADX1 180
+#define TEGRA124_CLK_DPAUX 181
+#define TEGRA124_CLK_SOR0 182
+/* 183 */
+#define TEGRA124_CLK_GPU 184
+#define TEGRA124_CLK_AMX1 185
+#define TEGRA124_CLK_AFC0 186
+#define TEGRA124_CLK_AFC1 187
+#define TEGRA124_CLK_AFC2 188
+#define TEGRA124_CLK_AFC3 189
+#define TEGRA124_CLK_AFC4 190
+#define TEGRA124_CLK_AFC5 191
+#define TEGRA124_CLK_UARTB 192
+#define TEGRA124_CLK_VFIR 193
+#define TEGRA124_CLK_SPDIF_IN 194
+#define TEGRA124_CLK_SPDIF_OUT 195
+#define TEGRA124_CLK_VI 196
+#define TEGRA124_CLK_VI_SENSOR 197
+#define TEGRA124_CLK_FUSE 198
+#define TEGRA124_CLK_FUSE_BURN 199
+#define TEGRA124_CLK_CLK_32K 200
+#define TEGRA124_CLK_CLK_M 201
+#define TEGRA124_CLK_CLK_M_DIV2 202
+#define TEGRA124_CLK_CLK_M_DIV4 203
+#define TEGRA124_CLK_PLL_REF 204
+#define TEGRA124_CLK_PLL_C 205
+#define TEGRA124_CLK_PLL_C_OUT1 206
+#define TEGRA124_CLK_PLL_C2 207
+#define TEGRA124_CLK_PLL_C3 208
+#define TEGRA124_CLK_PLL_M 209
+#define TEGRA124_CLK_PLL_M_OUT1 210
+#define TEGRA124_CLK_PLL_P 211
+#define TEGRA124_CLK_PLL_P_OUT1 212
+#define TEGRA124_CLK_PLL_P_OUT2 213
+#define TEGRA124_CLK_PLL_P_OUT3 214
+#define TEGRA124_CLK_PLL_P_OUT4 215
+#define TEGRA124_CLK_PLL_A 216
+#define TEGRA124_CLK_PLL_A_OUT0 217
+#define TEGRA124_CLK_PLL_D 218
+#define TEGRA124_CLK_PLL_D_OUT0 219
+#define TEGRA124_CLK_PLL_D2 220
+#define TEGRA124_CLK_PLL_D2_OUT0 221
+#define TEGRA124_CLK_PLL_U 222
+#define TEGRA124_CLK_PLL_U_480M 223
+
+#define TEGRA124_CLK_PLL_U_60M 224
+#define TEGRA124_CLK_PLL_U_48M 225
+#define TEGRA124_CLK_PLL_U_12M 226
+#define TEGRA124_CLK_PLL_X 227
+#define TEGRA124_CLK_PLL_X_OUT0 228
+#define TEGRA124_CLK_PLL_RE_VCO 229
+#define TEGRA124_CLK_PLL_RE_OUT 230
+#define TEGRA124_CLK_PLL_E 231
+#define TEGRA124_CLK_SPDIF_IN_SYNC 232
+#define TEGRA124_CLK_I2S0_SYNC 233
+#define TEGRA124_CLK_I2S1_SYNC 234
+#define TEGRA124_CLK_I2S2_SYNC 235
+#define TEGRA124_CLK_I2S3_SYNC 236
+#define TEGRA124_CLK_I2S4_SYNC 237
+#define TEGRA124_CLK_VIMCLK_SYNC 238
+#define TEGRA124_CLK_AUDIO0 239
+#define TEGRA124_CLK_AUDIO1 240
+#define TEGRA124_CLK_AUDIO2 241
+#define TEGRA124_CLK_AUDIO3 242
+#define TEGRA124_CLK_AUDIO4 243
+#define TEGRA124_CLK_SPDIF 244
+#define TEGRA124_CLK_CLK_OUT_1 245
+#define TEGRA124_CLK_CLK_OUT_2 246
+#define TEGRA124_CLK_CLK_OUT_3 247
+#define TEGRA124_CLK_BLINK 248
+/* 249 */
+/* 250 */
+/* 251 */
+#define TEGRA124_CLK_XUSB_HOST_SRC 252
+#define TEGRA124_CLK_XUSB_FALCON_SRC 253
+#define TEGRA124_CLK_XUSB_FS_SRC 254
+#define TEGRA124_CLK_XUSB_SS_SRC 255
+
+#define TEGRA124_CLK_XUSB_DEV_SRC 256
+#define TEGRA124_CLK_XUSB_DEV 257
+#define TEGRA124_CLK_XUSB_HS_SRC 258
+#define TEGRA124_CLK_SCLK 259
+#define TEGRA124_CLK_HCLK 260
+#define TEGRA124_CLK_PCLK 261
+#define TEGRA124_CLK_CCLK_G 262
+#define TEGRA124_CLK_CCLK_LP 263
+#define TEGRA124_CLK_DFLL_REF 264
+#define TEGRA124_CLK_DFLL_SOC 265
+#define TEGRA124_CLK_VI_SENSOR2 266
+#define TEGRA124_CLK_PLL_P_OUT5 267
+#define TEGRA124_CLK_CML0 268
+#define TEGRA124_CLK_CML1 269
+#define TEGRA124_CLK_PLL_C4 270
+#define TEGRA124_CLK_PLL_DP 271
+#define TEGRA124_CLK_PLL_E_MUX 272
+/* 273 */
+/* 274 */
+/* 275 */
+/* 276 */
+/* 277 */
+/* 278 */
+/* 279 */
+/* 280 */
+/* 281 */
+/* 282 */
+/* 283 */
+/* 284 */
+/* 285 */
+/* 286 */
+/* 287 */
+
+/* 288 */
+/* 289 */
+/* 290 */
+/* 291 */
+/* 292 */
+/* 293 */
+/* 294 */
+/* 295 */
+/* 296 */
+/* 297 */
+/* 298 */
+/* 299 */
+#define TEGRA124_CLK_AUDIO0_MUX 300
+#define TEGRA124_CLK_AUDIO1_MUX 301
+#define TEGRA124_CLK_AUDIO2_MUX 302
+#define TEGRA124_CLK_AUDIO3_MUX 303
+#define TEGRA124_CLK_AUDIO4_MUX 304
+#define TEGRA124_CLK_SPDIF_MUX 305
+#define TEGRA124_CLK_CLK_OUT_1_MUX 306
+#define TEGRA124_CLK_CLK_OUT_2_MUX 307
+#define TEGRA124_CLK_CLK_OUT_3_MUX 308
+#define TEGRA124_CLK_DSIA_MUX 309
+#define TEGRA124_CLK_DSIB_MUX 310
+#define TEGRA124_CLK_SOR0_LVDS 311
+#define TEGRA124_CLK_PLL_M_UD 311
+#define TEGRA124_CLK_CLK_MAX 312
+
+#endif /* _DT_BINDINGS_CLOCK_TEGRA124_CAR_H */
diff --git a/include/dt-bindings/clock/tegra20-car.h b/include/dt-bindings/clock/tegra20-car.h
new file mode 100644
index 0000000..9406207
--- /dev/null
+++ b/include/dt-bindings/clock/tegra20-car.h
@@ -0,0 +1,158 @@
+/*
+ * This header provides constants for binding nvidia,tegra20-car.
+ *
+ * The first 96 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+ * registers. These IDs often match those in the CAR's RST_DEVICES registers,
+ * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+ * this case, those clocks are assigned IDs above 95 in order to highlight
+ * this issue. Implementations that interpret these clock IDs as bit values
+ * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+ * explicitly handle these special cases.
+ *
+ * The balance of the clocks controlled by the CAR are assigned IDs of 96 and
+ * above.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_TEGRA20_CAR_H
+#define _DT_BINDINGS_CLOCK_TEGRA20_CAR_H
+
+#define TEGRA20_CLK_CPU 0
+/* 1 */
+/* 2 */
+#define TEGRA20_CLK_AC97 3
+#define TEGRA20_CLK_RTC 4
+#define TEGRA20_CLK_TIMER 5
+#define TEGRA20_CLK_UARTA 6
+/* 7 (register bit affects uart2 and vfir) */
+#define TEGRA20_CLK_GPIO 8
+#define TEGRA20_CLK_SDMMC2 9
+/* 10 (register bit affects spdif_in and spdif_out) */
+#define TEGRA20_CLK_I2S1 11
+#define TEGRA20_CLK_I2C1 12
+#define TEGRA20_CLK_NDFLASH 13
+#define TEGRA20_CLK_SDMMC1 14
+#define TEGRA20_CLK_SDMMC4 15
+#define TEGRA20_CLK_TWC 16
+#define TEGRA20_CLK_PWM 17
+#define TEGRA20_CLK_I2S2 18
+#define TEGRA20_CLK_EPP 19
+/* 20 (register bit affects vi and vi_sensor) */
+#define TEGRA20_CLK_GR2D 21
+#define TEGRA20_CLK_USBD 22
+#define TEGRA20_CLK_ISP 23
+#define TEGRA20_CLK_GR3D 24
+#define TEGRA20_CLK_IDE 25
+#define TEGRA20_CLK_DISP2 26
+#define TEGRA20_CLK_DISP1 27
+#define TEGRA20_CLK_HOST1X 28
+#define TEGRA20_CLK_VCP 29
+/* 30 */
+#define TEGRA20_CLK_CACHE2 31
+
+#define TEGRA20_CLK_MEM 32
+#define TEGRA20_CLK_AHBDMA 33
+#define TEGRA20_CLK_APBDMA 34
+/* 35 */
+#define TEGRA20_CLK_KBC 36
+#define TEGRA20_CLK_STAT_MON 37
+#define TEGRA20_CLK_PMC 38
+#define TEGRA20_CLK_FUSE 39
+#define TEGRA20_CLK_KFUSE 40
+#define TEGRA20_CLK_SBC1 41
+#define TEGRA20_CLK_NOR 42
+#define TEGRA20_CLK_SPI 43
+#define TEGRA20_CLK_SBC2 44
+#define TEGRA20_CLK_XIO 45
+#define TEGRA20_CLK_SBC3 46
+#define TEGRA20_CLK_DVC 47
+#define TEGRA20_CLK_DSI 48
+/* 49 (register bit affects tvo and cve) */
+#define TEGRA20_CLK_MIPI 50
+#define TEGRA20_CLK_HDMI 51
+#define TEGRA20_CLK_CSI 52
+#define TEGRA20_CLK_TVDAC 53
+#define TEGRA20_CLK_I2C2 54
+#define TEGRA20_CLK_UARTC 55
+/* 56 */
+#define TEGRA20_CLK_EMC 57
+#define TEGRA20_CLK_USB2 58
+#define TEGRA20_CLK_USB3 59
+#define TEGRA20_CLK_MPE 60
+#define TEGRA20_CLK_VDE 61
+#define TEGRA20_CLK_BSEA 62
+#define TEGRA20_CLK_BSEV 63
+
+#define TEGRA20_CLK_SPEEDO 64
+#define TEGRA20_CLK_UARTD 65
+#define TEGRA20_CLK_UARTE 66
+#define TEGRA20_CLK_I2C3 67
+#define TEGRA20_CLK_SBC4 68
+#define TEGRA20_CLK_SDMMC3 69
+#define TEGRA20_CLK_PEX 70
+#define TEGRA20_CLK_OWR 71
+#define TEGRA20_CLK_AFI 72
+#define TEGRA20_CLK_CSITE 73
+/* 74 */
+#define TEGRA20_CLK_AVPUCQ 75
+#define TEGRA20_CLK_LA 76
+/* 77 */
+/* 78 */
+/* 79 */
+/* 80 */
+/* 81 */
+/* 82 */
+/* 83 */
+#define TEGRA20_CLK_IRAMA 84
+#define TEGRA20_CLK_IRAMB 85
+#define TEGRA20_CLK_IRAMC 86
+#define TEGRA20_CLK_IRAMD 87
+#define TEGRA20_CLK_CRAM2 88
+#define TEGRA20_CLK_AUDIO_2X 89 /* a/k/a audio_2x_sync_clk */
+#define TEGRA20_CLK_CLK_D 90
+/* 91 */
+#define TEGRA20_CLK_CSUS 92
+#define TEGRA20_CLK_CDEV2 93
+#define TEGRA20_CLK_CDEV1 94
+/* 95 */
+
+#define TEGRA20_CLK_UARTB 96
+#define TEGRA20_CLK_VFIR 97
+#define TEGRA20_CLK_SPDIF_IN 98
+#define TEGRA20_CLK_SPDIF_OUT 99
+#define TEGRA20_CLK_VI 100
+#define TEGRA20_CLK_VI_SENSOR 101
+#define TEGRA20_CLK_TVO 102
+#define TEGRA20_CLK_CVE 103
+#define TEGRA20_CLK_OSC 104
+#define TEGRA20_CLK_CLK_32K 105 /* a/k/a clk_s */
+#define TEGRA20_CLK_CLK_M 106
+#define TEGRA20_CLK_SCLK 107
+#define TEGRA20_CLK_CCLK 108
+#define TEGRA20_CLK_HCLK 109
+#define TEGRA20_CLK_PCLK 110
+#define TEGRA20_CLK_BLINK 111
+#define TEGRA20_CLK_PLL_A 112
+#define TEGRA20_CLK_PLL_A_OUT0 113
+#define TEGRA20_CLK_PLL_C 114
+#define TEGRA20_CLK_PLL_C_OUT1 115
+#define TEGRA20_CLK_PLL_D 116
+#define TEGRA20_CLK_PLL_D_OUT0 117
+#define TEGRA20_CLK_PLL_E 118
+#define TEGRA20_CLK_PLL_M 119
+#define TEGRA20_CLK_PLL_M_OUT1 120
+#define TEGRA20_CLK_PLL_P 121
+#define TEGRA20_CLK_PLL_P_OUT1 122
+#define TEGRA20_CLK_PLL_P_OUT2 123
+#define TEGRA20_CLK_PLL_P_OUT3 124
+#define TEGRA20_CLK_PLL_P_OUT4 125
+#define TEGRA20_CLK_PLL_S 126
+#define TEGRA20_CLK_PLL_U 127
+
+#define TEGRA20_CLK_PLL_X 128
+#define TEGRA20_CLK_COP 129 /* a/k/a avp */
+#define TEGRA20_CLK_AUDIO 130 /* a/k/a audio_sync_clk */
+#define TEGRA20_CLK_PLL_REF 131
+#define TEGRA20_CLK_TWD 132
+#define TEGRA20_CLK_CLK_MAX 133
+
+#endif /* _DT_BINDINGS_CLOCK_TEGRA20_CAR_H */
diff --git a/include/dt-bindings/clock/tegra30-car.h b/include/dt-bindings/clock/tegra30-car.h
new file mode 100644
index 0000000..889e49b
--- /dev/null
+++ b/include/dt-bindings/clock/tegra30-car.h
@@ -0,0 +1,273 @@
+/*
+ * This header provides constants for binding nvidia,tegra30-car.
+ *
+ * The first 130 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+ * registers. These IDs often match those in the CAR's RST_DEVICES registers,
+ * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+ * this case, those clocks are assigned IDs above 160 in order to highlight
+ * this issue. Implementations that interpret these clock IDs as bit values
+ * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+ * explicitly handle these special cases.
+ *
+ * The balance of the clocks controlled by the CAR are assigned IDs of 160 and
+ * above.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_TEGRA30_CAR_H
+#define _DT_BINDINGS_CLOCK_TEGRA30_CAR_H
+
+#define TEGRA30_CLK_CPU 0
+/* 1 */
+/* 2 */
+/* 3 */
+#define TEGRA30_CLK_RTC 4
+#define TEGRA30_CLK_TIMER 5
+#define TEGRA30_CLK_UARTA 6
+/* 7 (register bit affects uartb and vfir) */
+#define TEGRA30_CLK_GPIO 8
+#define TEGRA30_CLK_SDMMC2 9
+/* 10 (register bit affects spdif_in and spdif_out) */
+#define TEGRA30_CLK_I2S1 11
+#define TEGRA30_CLK_I2C1 12
+#define TEGRA30_CLK_NDFLASH 13
+#define TEGRA30_CLK_SDMMC1 14
+#define TEGRA30_CLK_SDMMC4 15
+/* 16 */
+#define TEGRA30_CLK_PWM 17
+#define TEGRA30_CLK_I2S2 18
+#define TEGRA30_CLK_EPP 19
+/* 20 (register bit affects vi and vi_sensor) */
+#define TEGRA30_CLK_GR2D 21
+#define TEGRA30_CLK_USBD 22
+#define TEGRA30_CLK_ISP 23
+#define TEGRA30_CLK_GR3D 24
+/* 25 */
+#define TEGRA30_CLK_DISP2 26
+#define TEGRA30_CLK_DISP1 27
+#define TEGRA30_CLK_HOST1X 28
+#define TEGRA30_CLK_VCP 29
+#define TEGRA30_CLK_I2S0 30
+#define TEGRA30_CLK_COP_CACHE 31
+
+#define TEGRA30_CLK_MC 32
+#define TEGRA30_CLK_AHBDMA 33
+#define TEGRA30_CLK_APBDMA 34
+/* 35 */
+#define TEGRA30_CLK_KBC 36
+#define TEGRA30_CLK_STATMON 37
+#define TEGRA30_CLK_PMC 38
+/* 39 (register bit affects fuse and fuse_burn) */
+#define TEGRA30_CLK_KFUSE 40
+#define TEGRA30_CLK_SBC1 41
+#define TEGRA30_CLK_NOR 42
+/* 43 */
+#define TEGRA30_CLK_SBC2 44
+/* 45 */
+#define TEGRA30_CLK_SBC3 46
+#define TEGRA30_CLK_I2C5 47
+#define TEGRA30_CLK_DSIA 48
+/* 49 (register bit affects cve and tvo) */
+#define TEGRA30_CLK_MIPI 50
+#define TEGRA30_CLK_HDMI 51
+#define TEGRA30_CLK_CSI 52
+#define TEGRA30_CLK_TVDAC 53
+#define TEGRA30_CLK_I2C2 54
+#define TEGRA30_CLK_UARTC 55
+/* 56 */
+#define TEGRA30_CLK_EMC 57
+#define TEGRA30_CLK_USB2 58
+#define TEGRA30_CLK_USB3 59
+#define TEGRA30_CLK_MPE 60
+#define TEGRA30_CLK_VDE 61
+#define TEGRA30_CLK_BSEA 62
+#define TEGRA30_CLK_BSEV 63
+
+#define TEGRA30_CLK_SPEEDO 64
+#define TEGRA30_CLK_UARTD 65
+#define TEGRA30_CLK_UARTE 66
+#define TEGRA30_CLK_I2C3 67
+#define TEGRA30_CLK_SBC4 68
+#define TEGRA30_CLK_SDMMC3 69
+#define TEGRA30_CLK_PCIE 70
+#define TEGRA30_CLK_OWR 71
+#define TEGRA30_CLK_AFI 72
+#define TEGRA30_CLK_CSITE 73
+/* 74 */
+#define TEGRA30_CLK_AVPUCQ 75
+#define TEGRA30_CLK_LA 76
+/* 77 */
+/* 78 */
+#define TEGRA30_CLK_DTV 79
+#define TEGRA30_CLK_NDSPEED 80
+#define TEGRA30_CLK_I2CSLOW 81
+#define TEGRA30_CLK_DSIB 82
+/* 83 */
+#define TEGRA30_CLK_IRAMA 84
+#define TEGRA30_CLK_IRAMB 85
+#define TEGRA30_CLK_IRAMC 86
+#define TEGRA30_CLK_IRAMD 87
+#define TEGRA30_CLK_CRAM2 88
+/* 89 */
+#define TEGRA30_CLK_AUDIO_2X 90 /* a/k/a audio_2x_sync_clk */
+/* 91 */
+#define TEGRA30_CLK_CSUS 92
+#define TEGRA30_CLK_CDEV2 93
+#define TEGRA30_CLK_CDEV1 94
+/* 95 */
+
+#define TEGRA30_CLK_CPU_G 96
+#define TEGRA30_CLK_CPU_LP 97
+#define TEGRA30_CLK_GR3D2 98
+#define TEGRA30_CLK_MSELECT 99
+#define TEGRA30_CLK_TSENSOR 100
+#define TEGRA30_CLK_I2S3 101
+#define TEGRA30_CLK_I2S4 102
+#define TEGRA30_CLK_I2C4 103
+#define TEGRA30_CLK_SBC5 104
+#define TEGRA30_CLK_SBC6 105
+#define TEGRA30_CLK_D_AUDIO 106
+#define TEGRA30_CLK_APBIF 107
+#define TEGRA30_CLK_DAM0 108
+#define TEGRA30_CLK_DAM1 109
+#define TEGRA30_CLK_DAM2 110
+#define TEGRA30_CLK_HDA2CODEC_2X 111
+#define TEGRA30_CLK_ATOMICS 112
+#define TEGRA30_CLK_AUDIO0_2X 113
+#define TEGRA30_CLK_AUDIO1_2X 114
+#define TEGRA30_CLK_AUDIO2_2X 115
+#define TEGRA30_CLK_AUDIO3_2X 116
+#define TEGRA30_CLK_AUDIO4_2X 117
+#define TEGRA30_CLK_SPDIF_2X 118
+#define TEGRA30_CLK_ACTMON 119
+#define TEGRA30_CLK_EXTERN1 120
+#define TEGRA30_CLK_EXTERN2 121
+#define TEGRA30_CLK_EXTERN3 122
+#define TEGRA30_CLK_SATA_OOB 123
+#define TEGRA30_CLK_SATA 124
+#define TEGRA30_CLK_HDA 125
+/* 126 */
+#define TEGRA30_CLK_SE 127
+
+#define TEGRA30_CLK_HDA2HDMI 128
+#define TEGRA30_CLK_SATA_COLD 129
+/* 130 */
+/* 131 */
+/* 132 */
+/* 133 */
+/* 134 */
+/* 135 */
+/* 136 */
+/* 137 */
+/* 138 */
+/* 139 */
+/* 140 */
+/* 141 */
+/* 142 */
+/* 143 */
+/* 144 */
+/* 145 */
+/* 146 */
+/* 147 */
+/* 148 */
+/* 149 */
+/* 150 */
+/* 151 */
+/* 152 */
+/* 153 */
+/* 154 */
+/* 155 */
+/* 156 */
+/* 157 */
+/* 158 */
+/* 159 */
+
+#define TEGRA30_CLK_UARTB 160
+#define TEGRA30_CLK_VFIR 161
+#define TEGRA30_CLK_SPDIF_IN 162
+#define TEGRA30_CLK_SPDIF_OUT 163
+#define TEGRA30_CLK_VI 164
+#define TEGRA30_CLK_VI_SENSOR 165
+#define TEGRA30_CLK_FUSE 166
+#define TEGRA30_CLK_FUSE_BURN 167
+#define TEGRA30_CLK_CVE 168
+#define TEGRA30_CLK_TVO 169
+#define TEGRA30_CLK_CLK_32K 170
+#define TEGRA30_CLK_CLK_M 171
+#define TEGRA30_CLK_CLK_M_DIV2 172
+#define TEGRA30_CLK_CLK_M_DIV4 173
+#define TEGRA30_CLK_PLL_REF 174
+#define TEGRA30_CLK_PLL_C 175
+#define TEGRA30_CLK_PLL_C_OUT1 176
+#define TEGRA30_CLK_PLL_M 177
+#define TEGRA30_CLK_PLL_M_OUT1 178
+#define TEGRA30_CLK_PLL_P 179
+#define TEGRA30_CLK_PLL_P_OUT1 180
+#define TEGRA30_CLK_PLL_P_OUT2 181
+#define TEGRA30_CLK_PLL_P_OUT3 182
+#define TEGRA30_CLK_PLL_P_OUT4 183
+#define TEGRA30_CLK_PLL_A 184
+#define TEGRA30_CLK_PLL_A_OUT0 185
+#define TEGRA30_CLK_PLL_D 186
+#define TEGRA30_CLK_PLL_D_OUT0 187
+#define TEGRA30_CLK_PLL_D2 188
+#define TEGRA30_CLK_PLL_D2_OUT0 189
+#define TEGRA30_CLK_PLL_U 190
+#define TEGRA30_CLK_PLL_X 191
+
+#define TEGRA30_CLK_PLL_X_OUT0 192
+#define TEGRA30_CLK_PLL_E 193
+#define TEGRA30_CLK_SPDIF_IN_SYNC 194
+#define TEGRA30_CLK_I2S0_SYNC 195
+#define TEGRA30_CLK_I2S1_SYNC 196
+#define TEGRA30_CLK_I2S2_SYNC 197
+#define TEGRA30_CLK_I2S3_SYNC 198
+#define TEGRA30_CLK_I2S4_SYNC 199
+#define TEGRA30_CLK_VIMCLK_SYNC 200
+#define TEGRA30_CLK_AUDIO0 201
+#define TEGRA30_CLK_AUDIO1 202
+#define TEGRA30_CLK_AUDIO2 203
+#define TEGRA30_CLK_AUDIO3 204
+#define TEGRA30_CLK_AUDIO4 205
+#define TEGRA30_CLK_SPDIF 206
+#define TEGRA30_CLK_CLK_OUT_1 207 /* (extern1) */
+#define TEGRA30_CLK_CLK_OUT_2 208 /* (extern2) */
+#define TEGRA30_CLK_CLK_OUT_3 209 /* (extern3) */
+#define TEGRA30_CLK_SCLK 210
+#define TEGRA30_CLK_BLINK 211
+#define TEGRA30_CLK_CCLK_G 212
+#define TEGRA30_CLK_CCLK_LP 213
+#define TEGRA30_CLK_TWD 214
+#define TEGRA30_CLK_CML0 215
+#define TEGRA30_CLK_CML1 216
+#define TEGRA30_CLK_HCLK 217
+#define TEGRA30_CLK_PCLK 218
+/* 219 */
+/* 220 */
+/* 221 */
+/* 222 */
+/* 223 */
+
+/* 288 */
+/* 289 */
+/* 290 */
+/* 291 */
+/* 292 */
+/* 293 */
+/* 294 */
+/* 295 */
+/* 296 */
+/* 297 */
+/* 298 */
+/* 299 */
+#define TEGRA30_CLK_CLK_OUT_1_MUX 300
+#define TEGRA30_CLK_CLK_OUT_2_MUX 301
+#define TEGRA30_CLK_CLK_OUT_3_MUX 302
+#define TEGRA30_CLK_AUDIO0_MUX 303
+#define TEGRA30_CLK_AUDIO1_MUX 304
+#define TEGRA30_CLK_AUDIO2_MUX 305
+#define TEGRA30_CLK_AUDIO3_MUX 306
+#define TEGRA30_CLK_AUDIO4_MUX 307
+#define TEGRA30_CLK_SPDIF_MUX 308
+#define TEGRA30_CLK_CLK_MAX 309
+
+#endif /* _DT_BINDINGS_CLOCK_TEGRA30_CAR_H */
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 5f88938..2590d30 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -376,6 +376,18 @@ int fdtdec_get_alias_seq(const void *blob, const char *base, int node,
*/
int fdtdec_get_alias_node(const void *blob, const char *name);
+/**
+ * Get the offset of the given chosen node
+ *
+ * This looks up a property in /chosen containing the path to another node,
+ * then finds the offset of that node.
+ *
+ * @param blob Device tree blob (if NULL, then error is returned)
+ * @param name Property name, e.g. "stdout-path"
+ * @return Node offset referred to by that chosen node, or -ve FDT_ERR_...
+ */
+int fdtdec_get_chosen_node(const void *blob, const char *name);
+
/*
* Get the name for a compatible ID
*
diff --git a/include/ns16550.h b/include/ns16550.h
index d1f3a90..5784cfd 100644
--- a/include/ns16550.h
+++ b/include/ns16550.h
@@ -23,6 +23,14 @@
#include <linux/types.h>
+#ifdef CONFIG_DM_SERIAL
+/*
+ * For driver model we always use one byte per register, and sort out the
+ * differences in the driver
+ */
+#define CONFIG_SYS_NS16550_REG_SIZE (-1)
+#endif
+
#if !defined(CONFIG_SYS_NS16550_REG_SIZE) || (CONFIG_SYS_NS16550_REG_SIZE == 0)
#error "Please define NS16550 registers size."
#elif defined(CONFIG_SYS_NS16550_MEM32)
@@ -37,6 +45,21 @@
unsigned char postpad_##x[-CONFIG_SYS_NS16550_REG_SIZE - 1];
#endif
+/**
+ * struct ns16550_platdata - information about a NS16550 port
+ *
+ * @base: Base register address
+ * @reg_shift: Shift size of registers (0=byte, 1=16bit, 2=32bit...)
+ * @clock: UART base clock speed in Hz
+ */
+struct ns16550_platdata {
+ unsigned char *base;
+ int reg_shift;
+ int clock;
+};
+
+struct udevice;
+
struct NS16550 {
UART_REG(rbr); /* 0 */
UART_REG(ier); /* 1 */
@@ -65,6 +88,9 @@ struct NS16550 {
UART_REG(scr); /* 10*/
UART_REG(ssr); /* 11*/
#endif
+#ifdef CONFIG_DM_SERIAL
+ struct ns16550_platdata *plat;
+#endif
};
#define thr rbr
@@ -170,3 +196,43 @@ void NS16550_putc(NS16550_t com_port, char c);
char NS16550_getc(NS16550_t com_port);
int NS16550_tstc(NS16550_t com_port);
void NS16550_reinit(NS16550_t com_port, int baud_divisor);
+
+/**
+ * ns16550_calc_divisor() - calculate the divisor given clock and baud rate
+ *
+ * Given the UART input clock and required baudrate, calculate the divisor
+ * that should be used.
+ *
+ * @port: UART port
+ * @clock: UART input clock speed in Hz
+ * @baudrate: Required baud rate
+ * @return baud rate divisor that should be used
+ */
+int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate);
+
+/**
+ * ns16550_serial_ofdata_to_platdata() - convert DT to platform data
+ *
+ * Decode a device tree node for an ns16550 device. This includes the
+ * register base address and register shift properties. The caller must set
+ * up the clock frequency.
+ *
+ * @dev: dev to decode platform data for
+ * @return: 0 if OK, -EINVAL on error
+ */
+int ns16550_serial_ofdata_to_platdata(struct udevice *dev);
+
+/**
+ * ns16550_serial_probe() - probe a serial port
+ *
+ * This sets up the serial port ready for use, except for the baud rate
+ * @return 0, or -ve on error
+ */
+int ns16550_serial_probe(struct udevice *dev);
+
+/**
+ * struct ns16550_serial_ops - ns16550 serial operations
+ *
+ * These should be used by the client driver for the driver's 'ops' member
+ */
+extern const struct dm_serial_ops ns16550_serial_ops;
diff --git a/include/serial.h b/include/serial.h
index d232d47..8f574e4 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -72,4 +72,96 @@ extern int write_port(struct stdio_dev *port, char *buf);
extern int read_port(struct stdio_dev *port, char *buf, int size);
#endif
+struct udevice;
+
+/**
+ * struct struct dm_serial_ops - Driver model serial operations
+ *
+ * The uclass interface is implemented by all serial devices which use
+ * driver model.
+ */
+struct dm_serial_ops {
+ /**
+ * setbrg() - Set up the baud rate generator
+ *
+ * Adjust baud rate divisors to set up a new baud rate for this
+ * device. Not all devices will support all rates. If the rate
+ * cannot be supported, the driver is free to select the nearest
+ * available rate. or return -EINVAL if this is not possible.
+ *
+ * @dev: Device pointer
+ * @baudrate: New baud rate to use
+ * @return 0 if OK, -ve on error
+ */
+ int (*setbrg)(struct udevice *dev, int baudrate);
+ /**
+ * getc() - Read a character and return it
+ *
+ * If no character is available, this should return -EAGAIN without
+ * waiting.
+ *
+ * @dev: Device pointer
+ * @return character (0..255), -ve on error
+ */
+ int (*getc)(struct udevice *dev);
+ /**
+ * putc() - Write a character
+ *
+ * @dev: Device pointer
+ * @ch: character to write
+ * @return 0 if OK, -ve on error
+ */
+ int (*putc)(struct udevice *dev, const char ch);
+ /**
+ * pending() - Check if input/output characters are waiting
+ *
+ * This can be used to return an indication of the number of waiting
+ * characters if the driver knows this (e.g. by looking at the FIFO
+ * level). It is acceptable to return 1 if an indeterminant number
+ * of characters is waiting.
+ *
+ * This method is optional.
+ *
+ * @dev: Device pointer
+ * @input: true to check input characters, false for output
+ * @return number of waiting characters, 0 for none, -ve on error
+ */
+ int (*pending)(struct udevice *dev, bool input);
+ /**
+ * clear() - Clear the serial FIFOs/holding registers
+ *
+ * This method is optional.
+ *
+ * This quickly clears any input/output characters from the UART.
+ * If this is not possible, but characters still exist, then it
+ * is acceptable to return -EAGAIN (try again) or -EINVAL (not
+ * supported).
+ *
+ * @dev: Device pointer
+ * @return 0 if OK, -ve on error
+ */
+ int (*clear)(struct udevice *dev);
+#if CONFIG_POST & CONFIG_SYS_POST_UART
+ /**
+ * loop() - Control serial device loopback mode
+ *
+ * @dev: Device pointer
+ * @on: 1 to turn loopback on, 0 to turn if off
+ */
+ int (*loop)(struct udevice *dev, int on);
+#endif
+};
+
+/**
+ * struct serial_dev_priv - information about a device used by the uclass
+ *
+ * @sdev: stdio device attached to this uart
+ */
+struct serial_dev_priv {
+ struct stdio_dev *sdev;
+};
+
+/* Access the serial operations for a device */
+#define serial_get_ops(dev) ((struct dm_serial_ops *)(dev)->driver->ops)
+
#endif
diff --git a/include/stdio_dev.h b/include/stdio_dev.h
index a7d0825..268de8e 100644
--- a/include/stdio_dev.h
+++ b/include/stdio_dev.h
@@ -78,7 +78,29 @@ extern char *stdio_names[MAX_FILES];
*/
int stdio_register (struct stdio_dev * dev);
int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp);
-int stdio_init (void);
+
+/**
+ * stdio_init_tables() - set up stdio tables ready for devices
+ *
+ * This does not add any devices, but just prepares stdio for use.
+ */
+int stdio_init_tables(void);
+
+/**
+ * stdio_add_devices() - Add stdio devices to the table
+ *
+ * This makes calls to all the various subsystems that use stdio, to make
+ * them register with stdio.
+ */
+int stdio_add_devices(void);
+
+/**
+ * stdio_init() - Sets up stdio ready for use
+ *
+ * This calls stdio_init_tables() and stdio_add_devices()
+ */
+int stdio_init(void);
+
void stdio_print_current_devices(void);
#ifdef CONFIG_SYS_STDIO_DEREGISTER
int stdio_deregister(const char *devname);
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index c2f3645..06d4542 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -382,6 +382,21 @@ int fdtdec_get_alias_node(const void *blob, const char *name)
return fdt_path_offset(blob, prop);
}
+int fdtdec_get_chosen_node(const void *blob, const char *name)
+{
+ const char *prop;
+ int chosen_node;
+ int len;
+
+ if (!blob)
+ return -FDT_ERR_NOTFOUND;
+ chosen_node = fdt_path_offset(blob, "/chosen");
+ prop = fdt_getprop(blob, chosen_node, name, &len);
+ if (!prop)
+ return -FDT_ERR_NOTFOUND;
+ return fdt_path_offset(blob, prop);
+}
+
int fdtdec_check_fdt(void)
{
/*