summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/mvsata_ide.c2
-rw-r--r--drivers/clk/Kconfig2
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/uniphier/Kconfig13
-rw-r--r--drivers/clk/uniphier/Makefile3
-rw-r--r--drivers/clk/uniphier/clk-uniphier-core.c159
-rw-r--r--drivers/clk/uniphier/clk-uniphier-mio.c178
-rw-r--r--drivers/clk/uniphier/clk-uniphier.h57
-rw-r--r--drivers/ddr/marvell/axp/ddr3_hw_training.c2
-rw-r--r--drivers/fpga/socfpga.c2
-rw-r--r--drivers/gpio/db8500_gpio.c4
-rw-r--r--drivers/gpio/intel_ich6_gpio.c125
-rw-r--r--drivers/gpio/tegra_gpio.c5
-rw-r--r--drivers/input/tegra-kbc.c2
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/smsc_sio1007.c126
-rw-r--r--drivers/mmc/sh_sdhi.c2
-rw-r--r--drivers/mmc/tegra_mmc.c4
-rw-r--r--drivers/mtd/nand/Kconfig7
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/arasan_nfc.c1154
-rw-r--r--drivers/mtd/nand/fsl_ifc_spl.c2
-rw-r--r--drivers/mtd/nand/lpc32xx_nand_slc.c2
-rw-r--r--drivers/mtd/nand/mxc_nand_spl.c2
-rw-r--r--drivers/mtd/nand/mxs_nand.c24
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c17
-rw-r--r--drivers/net/at91_emac.c10
-rw-r--r--drivers/net/davinci_emac.c8
-rw-r--r--drivers/net/designware.c4
-rw-r--r--drivers/net/e1000.c77
-rw-r--r--drivers/net/e1000.h4
-rw-r--r--drivers/net/fsl-mc/mc.c2
-rw-r--r--drivers/net/keystone_net.c473
-rw-r--r--drivers/net/lan91c96.c2
-rw-r--r--drivers/net/ne2000_base.c2
-rw-r--r--drivers/net/pch_gbe.c27
-rw-r--r--drivers/net/pch_gbe.h2
-rw-r--r--drivers/net/phy/marvell.c26
-rw-r--r--drivers/net/phy/micrel.c6
-rw-r--r--drivers/pch/pch-uclass.c30
-rw-r--r--drivers/pch/pch7.c43
-rw-r--r--drivers/pch/pch9.c54
-rw-r--r--drivers/pwm/Kconfig9
-rw-r--r--drivers/pwm/Makefile3
-rw-r--r--drivers/pwm/tegra_pwm.c85
-rw-r--r--drivers/serial/Makefile5
-rw-r--r--drivers/serial/mxs_auart.c151
-rw-r--r--drivers/serial/opencores_yanu.c242
-rw-r--r--drivers/serial/sandbox.c2
-rw-r--r--drivers/serial/serial_bfin.c2
-rw-r--r--drivers/serial/serial_imx.c223
-rw-r--r--drivers/serial/serial_max3100.c294
-rw-r--r--drivers/serial/serial_s3c24x0.c59
-rw-r--r--drivers/serial/serial_sa1100.c162
-rw-r--r--drivers/serial/serial_stm32.c40
-rw-r--r--drivers/soc/Makefile2
-rw-r--r--drivers/spi/ich.c76
-rw-r--r--drivers/spi/ich.h61
-rw-r--r--drivers/usb/gadget/composite.c2
-rw-r--r--drivers/usb/gadget/config.c2
-rw-r--r--drivers/usb/gadget/dwc2_udc_otg.c4
-rw-r--r--drivers/usb/gadget/epautoconf.c2
-rw-r--r--drivers/usb/gadget/ether.c2
-rw-r--r--drivers/usb/gadget/gadget_chips.h2
-rw-r--r--drivers/usb/gadget/usbstring.c2
-rw-r--r--drivers/usb/host/Kconfig7
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/ehci-atmel.c46
-rw-r--r--drivers/usb/host/ehci-uniphier.c75
-rw-r--r--drivers/usb/host/ohci-at91.c64
-rw-r--r--drivers/video/Kconfig20
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/bcm2835.c4
-rw-r--r--drivers/video/simple_panel.c1
-rw-r--r--drivers/video/tegra.c658
-rw-r--r--drivers/video/tegra124/Makefile1
-rw-r--r--drivers/video/tegra124/display.c184
-rw-r--r--drivers/video/tegra124/dp.c53
-rw-r--r--drivers/video/tegra124/sor.c162
-rw-r--r--drivers/video/tegra124/sor.h45
-rw-r--r--drivers/video/tegra124/tegra124-lcd.c95
-rw-r--r--drivers/video/vidconsole-uclass.c1
-rw-r--r--drivers/video/video_bmp.c2
83 files changed, 3442 insertions, 2078 deletions
diff --git a/drivers/block/mvsata_ide.c b/drivers/block/mvsata_ide.c
index 2c6d42410cb..7b6a1558d27 100644
--- a/drivers/block/mvsata_ide.c
+++ b/drivers/block/mvsata_ide.c
@@ -83,7 +83,7 @@ struct mvsata_port_registers {
* Status codes to return to client callers. Currently, callers ignore
* exact value and only care for zero or nonzero, so no need to make this
* public, it is only #define'd for clarity.
- * If/when standard negative codes are implemented in U-boot, then these
+ * If/when standard negative codes are implemented in U-Boot, then these
* #defines should be moved to, or replaced by ones from, the common list
* of status codes.
*/
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 9fcde39b71f..a98b74bbc0c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -20,4 +20,6 @@ config SPL_CLK
setting up clocks within SPL, and allows the same drivers to be
used as U-Boot proper.
+source "drivers/clk/uniphier/Kconfig"
+
endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index c9144e3e1d4..c51db1562b6 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
obj-$(CONFIG_SANDBOX) += clk_sandbox.o
obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
+obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
new file mode 100644
index 00000000000..0e90c01a9a9
--- /dev/null
+++ b/drivers/clk/uniphier/Kconfig
@@ -0,0 +1,13 @@
+config CLK_UNIPHIER
+ bool
+ select CLK
+ select SPL_CLK
+
+menu "Clock drivers for UniPhier SoCs"
+ depends on CLK_UNIPHIER
+
+config CLK_UNIPHIER_MIO
+ bool "Clock driver for UniPhier Media I/O block"
+ default y
+
+endmenu
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
new file mode 100644
index 00000000000..a3168f9bc1b
--- /dev/null
+++ b/drivers/clk/uniphier/Makefile
@@ -0,0 +1,3 @@
+obj-y += clk-uniphier-core.o
+
+obj-$(CONFIG_CLK_UNIPHIER_MIO) += clk-uniphier-mio.o
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
new file mode 100644
index 00000000000..e79e0ff689f
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-core.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <mapmem.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <clk.h>
+#include <dm/device.h>
+
+#include "clk-uniphier.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int uniphier_clk_enable(struct udevice *dev, int index)
+{
+ struct uniphier_clk_priv *priv = dev_get_priv(dev);
+ struct uniphier_clk_gate_data *gate = priv->socdata->gate;
+ unsigned int nr_gate = priv->socdata->nr_gate;
+ void __iomem *reg;
+ u32 mask, data, tmp;
+ int i;
+
+ for (i = 0; i < nr_gate; i++) {
+ if (gate[i].index != index)
+ continue;
+
+ reg = priv->base + gate[i].reg;
+ mask = gate[i].mask;
+ data = gate[i].data & mask;
+
+ tmp = readl(reg);
+ tmp &= ~mask;
+ tmp |= data & mask;
+ debug("%s: %p: %08x\n", __func__, reg, tmp);
+ writel(tmp, reg);
+ }
+
+ return 0;
+}
+
+static ulong uniphier_clk_get_rate(struct udevice *dev, int index)
+{
+ struct uniphier_clk_priv *priv = dev_get_priv(dev);
+ struct uniphier_clk_rate_data *rdata = priv->socdata->rate;
+ unsigned int nr_rdata = priv->socdata->nr_rate;
+ void __iomem *reg;
+ u32 mask, data;
+ ulong matched_rate = 0;
+ int i;
+
+ for (i = 0; i < nr_rdata; i++) {
+ if (rdata[i].index != index)
+ continue;
+
+ if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED)
+ return rdata[i].rate;
+
+ reg = priv->base + rdata[i].reg;
+ mask = rdata[i].mask;
+ data = rdata[i].data & mask;
+ if ((readl(reg) & mask) == data) {
+ if (matched_rate && rdata[i].rate != matched_rate) {
+ printf("failed to get clk rate for insane register values\n");
+ return -EINVAL;
+ }
+ matched_rate = rdata[i].rate;
+ }
+ }
+
+ debug("%s: rate = %lu\n", __func__, matched_rate);
+
+ return matched_rate;
+}
+
+static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate)
+{
+ struct uniphier_clk_priv *priv = dev_get_priv(dev);
+ struct uniphier_clk_rate_data *rdata = priv->socdata->rate;
+ unsigned int nr_rdata = priv->socdata->nr_rate;
+ void __iomem *reg;
+ u32 mask, data, tmp;
+ ulong best_rate = 0;
+ int i;
+
+ /* first, decide the best match rate */
+ for (i = 0; i < nr_rdata; i++) {
+ if (rdata[i].index != index)
+ continue;
+
+ if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED)
+ return 0;
+
+ if (rdata[i].rate > best_rate && rdata[i].rate <= rate)
+ best_rate = rdata[i].rate;
+ }
+
+ if (!best_rate)
+ return -ENODEV;
+
+ debug("%s: requested rate = %lu, set rate = %lu\n", __func__,
+ rate, best_rate);
+
+ /* second, really set registers */
+ for (i = 0; i < nr_rdata; i++) {
+ if (rdata[i].index != index || rdata[i].rate != best_rate)
+ continue;
+
+ reg = priv->base + rdata[i].reg;
+ mask = rdata[i].mask;
+ data = rdata[i].data & mask;
+
+ tmp = readl(reg);
+ tmp &= ~mask;
+ tmp |= data;
+ debug("%s: %p: %08x\n", __func__, reg, tmp);
+ writel(tmp, reg);
+ }
+
+ return best_rate;
+}
+
+const struct clk_ops uniphier_clk_ops = {
+ .enable = uniphier_clk_enable,
+ .get_periph_rate = uniphier_clk_get_rate,
+ .set_periph_rate = uniphier_clk_set_rate,
+};
+
+int uniphier_clk_probe(struct udevice *dev)
+{
+ struct uniphier_clk_priv *priv = dev_get_priv(dev);
+ fdt_addr_t addr;
+ fdt_size_t size;
+
+ addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg",
+ &size);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->base = map_sysmem(addr, size);
+ if (!priv->base)
+ return -ENOMEM;
+
+ priv->socdata = (void *)dev_get_driver_data(dev);
+
+ return 0;
+}
+
+int uniphier_clk_remove(struct udevice *dev)
+{
+ struct uniphier_clk_priv *priv = dev_get_priv(dev);
+
+ unmap_sysmem(priv->base);
+
+ return 0;
+}
diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c
new file mode 100644
index 00000000000..d91ae34da1c
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-mio.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <clk.h>
+#include <dm/device.h>
+
+#include "clk-uniphier.h"
+
+#define UNIPHIER_MIO_CLK_GATE_SD(ch, idx) \
+ { \
+ .index = (idx), \
+ .reg = 0x20 + 0x200 * (ch), \
+ .mask = 0x00000100, \
+ .data = 0x00000100, \
+ }, \
+ { \
+ .index = (idx), \
+ .reg = 0x110 + 0x200 * (ch), \
+ .mask = 0x00000001, \
+ .data = 0x00000001, \
+ }
+
+#define UNIPHIER_MIO_CLK_RATE_SD(ch, idx) \
+ { \
+ .index = (idx), \
+ .reg = 0x30 + 0x200 * (ch), \
+ .mask = 0x00031300, \
+ .data = 0x00000000, \
+ .rate = 44444444, \
+ }, \
+ { \
+ .index = (idx), \
+ .reg = 0x30 + 0x200 * (ch), \
+ .mask = 0x00031300, \
+ .data = 0x00010000, \
+ .rate = 33333333, \
+ }, \
+ { \
+ .index = (idx), \
+ .reg = 0x30 + 0x200 * (ch), \
+ .mask = 0x00031300, \
+ .data = 0x00020000, \
+ .rate = 50000000, \
+ }, \
+ { \
+ .index = (idx), \
+ .reg = 0x30 + 0x200 * (ch), \
+ .mask = 0x00031300, \
+ .data = 0x00020000, \
+ .rate = 66666666, \
+ }, \
+ { \
+ .index = (idx), \
+ .reg = 0x30 + 0x200 * (ch), \
+ .mask = 0x00031300, \
+ .data = 0x00001000, \
+ .rate = 100000000, \
+ }, \
+ { \
+ .index = (idx), \
+ .reg = 0x30 + 0x200 * (ch), \
+ .mask = 0x00031300, \
+ .data = 0x00001100, \
+ .rate = 40000000, \
+ }, \
+ { \
+ .index = (idx), \
+ .reg = 0x30 + 0x200 * (ch), \
+ .mask = 0x00031300, \
+ .data = 0x00001200, \
+ .rate = 25000000, \
+ }, \
+ { \
+ .index = (idx), \
+ .reg = 0x30 + 0x200 * (ch), \
+ .mask = 0x00031300, \
+ .data = 0x00001300, \
+ .rate = 22222222, \
+ }
+
+#define UNIPHIER_MIO_CLK_GATE_USB(ch, idx) \
+ { \
+ .index = (idx), \
+ .reg = 0x20 + 0x200 * (ch), \
+ .mask = 0x30000000, \
+ .data = 0x30000000, \
+ }, \
+ { \
+ .index = (idx), \
+ .reg = 0x110 + 0x200 * (ch), \
+ .mask = 0x01000000, \
+ .data = 0x01000000, \
+ }, \
+ { \
+ .index = (idx), \
+ .reg = 0x114 + 0x200 * (ch), \
+ .mask = 0x00000001, \
+ .data = 0x00000001, \
+ }
+
+#define UNIPHIER_MIO_CLK_GATE_DMAC(idx) \
+ { \
+ .index = (idx), \
+ .reg = 0x20, \
+ .mask = 0x02000000, \
+ .data = 0x02000000, \
+ }, \
+ { \
+ .index = (idx), \
+ .reg = 0x110, \
+ .mask = 0x00020000, \
+ .data = 0x00020000, \
+ }
+
+static struct uniphier_clk_gate_data uniphier_mio_clk_gate[] = {
+ UNIPHIER_MIO_CLK_GATE_SD(0, 0),
+ UNIPHIER_MIO_CLK_GATE_SD(1, 1),
+ UNIPHIER_MIO_CLK_GATE_SD(2, 2), /* for PH1-Pro4 only */
+ UNIPHIER_MIO_CLK_GATE_USB(0, 3),
+ UNIPHIER_MIO_CLK_GATE_USB(1, 4),
+ UNIPHIER_MIO_CLK_GATE_USB(2, 5),
+ UNIPHIER_MIO_CLK_GATE_DMAC(6),
+ UNIPHIER_MIO_CLK_GATE_USB(3, 7), /* for PH1-sLD3 only */
+};
+
+static struct uniphier_clk_rate_data uniphier_mio_clk_rate[] = {
+ UNIPHIER_MIO_CLK_RATE_SD(0, 0),
+ UNIPHIER_MIO_CLK_RATE_SD(1, 1),
+ UNIPHIER_MIO_CLK_RATE_SD(2, 2), /* for PH1-Pro4 only */
+};
+
+static struct uniphier_clk_soc_data uniphier_mio_clk_data = {
+ .gate = uniphier_mio_clk_gate,
+ .nr_gate = ARRAY_SIZE(uniphier_mio_clk_gate),
+ .rate = uniphier_mio_clk_rate,
+ .nr_rate = ARRAY_SIZE(uniphier_mio_clk_rate),
+};
+
+static const struct udevice_id uniphier_mio_clk_match[] = {
+ {
+ .compatible = "socionext,ph1-sld3-mioctrl",
+ .data = (ulong)&uniphier_mio_clk_data,
+ },
+ {
+ .compatible = "socionext,ph1-ld4-mioctrl",
+ .data = (ulong)&uniphier_mio_clk_data,
+ },
+ {
+ .compatible = "socionext,ph1-pro4-mioctrl",
+ .data = (ulong)&uniphier_mio_clk_data,
+ },
+ {
+ .compatible = "socionext,ph1-sld8-mioctrl",
+ .data = (ulong)&uniphier_mio_clk_data,
+ },
+ {
+ .compatible = "socionext,ph1-pro5-mioctrl",
+ .data = (ulong)&uniphier_mio_clk_data,
+ },
+ {
+ .compatible = "socionext,proxstream2-mioctrl",
+ .data = (ulong)&uniphier_mio_clk_data,
+ },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(uniphier_mio_clk) = {
+ .name = "uniphier-mio-clk",
+ .id = UCLASS_CLK,
+ .of_match = uniphier_mio_clk_match,
+ .probe = uniphier_clk_probe,
+ .remove = uniphier_clk_remove,
+ .priv_auto_alloc_size = sizeof(struct uniphier_clk_priv),
+ .ops = &uniphier_clk_ops,
+};
diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h
new file mode 100644
index 00000000000..560b3f81129
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __CLK_UNIPHIER_H__
+#define __CLK_UNIPHIER_H__
+
+#include <linux/kernel.h>
+
+struct uniphier_clk_gate_data {
+ int index;
+ unsigned int reg;
+ u32 mask;
+ u32 data;
+};
+
+struct uniphier_clk_rate_data {
+ int index;
+ unsigned int reg;
+#define UNIPHIER_CLK_RATE_IS_FIXED UINT_MAX
+ u32 mask;
+ u32 data;
+ unsigned long rate;
+};
+
+struct uniphier_clk_soc_data {
+ struct uniphier_clk_gate_data *gate;
+ unsigned int nr_gate;
+ struct uniphier_clk_rate_data *rate;
+ unsigned int nr_rate;
+};
+
+#define UNIPHIER_CLK_FIXED_RATE(i, f) \
+ { \
+ .index = i, \
+ .reg = UNIPHIER_CLK_RATE_IS_FIXED, \
+ .rate = f, \
+ }
+
+/**
+ * struct uniphier_clk_priv - private data for UniPhier clock driver
+ *
+ * @base: base address of the clock provider
+ * @socdata: SoC specific data
+ */
+struct uniphier_clk_priv {
+ void __iomem *base;
+ struct uniphier_clk_soc_data *socdata;
+};
+
+extern const struct clk_ops uniphier_clk_ops;
+int uniphier_clk_probe(struct udevice *dev);
+int uniphier_clk_remove(struct udevice *dev);
+
+#endif /* __CLK_UNIPHIER_H__ */
diff --git a/drivers/ddr/marvell/axp/ddr3_hw_training.c b/drivers/ddr/marvell/axp/ddr3_hw_training.c
index a8c5e6a5347..c8d70411178 100644
--- a/drivers/ddr/marvell/axp/ddr3_hw_training.c
+++ b/drivers/ddr/marvell/axp/ddr3_hw_training.c
@@ -450,7 +450,7 @@ int ddr3_hw_training(u32 target_freq, u32 ddr_width, int xor_bypass,
ddr3_set_performance_params(&dram_info);
if (dram_info.ecc_ena) {
- /* Need to SCRUB the DRAM memory area to load U-boot */
+ /* Need to SCRUB the DRAM memory area to load U-Boot */
mv_sys_xor_finish();
dram_info.num_cs = 1;
dram_info.cs_ena = 1;
diff --git a/drivers/fpga/socfpga.c b/drivers/fpga/socfpga.c
index 431e159e48c..4448250f5c6 100644
--- a/drivers/fpga/socfpga.c
+++ b/drivers/fpga/socfpga.c
@@ -269,7 +269,7 @@ int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
/* Prior programming the FPGA, all bridges need to be shut off */
/* Disable all signals from hps peripheral controller to fpga */
- writel(0, &sysmgr_regs->fpgaintfgrp_gbl);
+ writel(0, &sysmgr_regs->fpgaintfgrp_module);
/* Disable all signals from FPGA to HPS SDRAM */
#define SDR_CTRLGRP_FPGAPORTRST_ADDRESS 0x5080
diff --git a/drivers/gpio/db8500_gpio.c b/drivers/gpio/db8500_gpio.c
index d5cb383e85e..db32db68451 100644
--- a/drivers/gpio/db8500_gpio.c
+++ b/drivers/gpio/db8500_gpio.c
@@ -1,14 +1,14 @@
/*
* Code ported from Nomadik GPIO driver in ST-Ericsson Linux kernel code.
* The purpose is that GPIO config found in kernel should work by simply
- * copy-paste it to U-boot.
+ * copy-paste it to U-Boot.
*
* Original Linux authors:
* Copyright (C) 2008,2009 STMicroelectronics
* Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
* Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
*
- * Ported to U-boot by:
+ * Ported to U-Boot by:
* Copyright (C) 2010 Joakim Axelsson <joakim.axelsson AT stericsson.com>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 67bf0a2dd31..527ed6d0fab 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -30,6 +30,7 @@
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
+#include <pch.h>
#include <pci.h>
#include <asm/gpio.h>
#include <asm/io.h>
@@ -62,91 +63,6 @@ void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
gd->arch.gpio_map = map;
}
-static int gpio_ich6_get_base(unsigned long base)
-{
- pci_dev_t pci_dev; /* handle for 0:1f:0 */
- u8 tmpbyte;
- u16 tmpword;
- u32 tmplong;
-
- /* Where should it be? */
- pci_dev = PCI_BDF(0, 0x1f, 0);
-
- /* Is the device present? */
- tmpword = x86_pci_read_config16(pci_dev, PCI_VENDOR_ID);
- if (tmpword != PCI_VENDOR_ID_INTEL) {
- debug("%s: wrong VendorID %x\n", __func__, tmpword);
- return -ENODEV;
- }
-
- tmpword = x86_pci_read_config16(pci_dev, PCI_DEVICE_ID);
- debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword);
- /*
- * We'd like to validate the Device ID too, but pretty much any
- * value is either a) correct with slight differences, or b)
- * correct but undocumented. We'll have to check a bunch of other
- * things instead...
- */
-
- /* I/O should already be enabled (it's a RO bit). */
- tmpword = x86_pci_read_config16(pci_dev, PCI_COMMAND);
- if (!(tmpword & PCI_COMMAND_IO)) {
- debug("%s: device IO not enabled\n", __func__);
- return -ENODEV;
- }
-
- /* Header Type must be normal (bits 6-0 only; see spec.) */
- tmpbyte = x86_pci_read_config8(pci_dev, PCI_HEADER_TYPE);
- if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
- debug("%s: invalid Header type\n", __func__);
- return -ENODEV;
- }
-
- /* Base Class must be a bridge device */
- tmpbyte = x86_pci_read_config8(pci_dev, PCI_CLASS_CODE);
- if (tmpbyte != PCI_CLASS_CODE_BRIDGE) {
- debug("%s: invalid class\n", __func__);
- return -ENODEV;
- }
- /* Sub Class must be ISA */
- tmpbyte = x86_pci_read_config8(pci_dev, PCI_CLASS_SUB_CODE);
- if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) {
- debug("%s: invalid subclass\n", __func__);
- return -ENODEV;
- }
-
- /* Programming Interface must be 0x00 (no others exist) */
- tmpbyte = x86_pci_read_config8(pci_dev, PCI_CLASS_PROG);
- if (tmpbyte != 0x00) {
- debug("%s: invalid interface type\n", __func__);
- return -ENODEV;
- }
-
- /*
- * GPIOBASE moved to its current offset with ICH6, but prior to
- * that it was unused (or undocumented). Check that it looks
- * okay: not all ones or zeros.
- *
- * Note we don't need check bit0 here, because the Tunnel Creek
- * GPIO base address register bit0 is reserved (read returns 0),
- * while on the Ivybridge the bit0 is used to indicate it is an
- * I/O space.
- */
- tmplong = x86_pci_read_config32(pci_dev, base);
- if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
- debug("%s: unexpected BASE value\n", __func__);
- return -ENODEV;
- }
-
- /*
- * Okay, I guess we're looking at the right device. The actual
- * GPIO registers are in the PCI device's I/O space, starting
- * at the offset that we just read. Bit 0 indicates that it's
- * an I/O address, not a memory address, so mask that off.
- */
- return tmplong & 1 ? tmplong & ~3 : tmplong & ~15;
-}
-
static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
{
u32 val;
@@ -288,20 +204,26 @@ static int _gpio_ich6_pinctrl_cfg_pin(s32 gpiobase, s32 iobase, int pin_node)
int gpio_ich6_pinctrl_init(void)
{
+ struct udevice *pch;
int pin_node;
int node;
int ret;
- int gpiobase;
- int iobase_offset;
- int iobase = -1;
+ u32 gpiobase;
+ u32 iobase = -1;
+
+ ret = uclass_first_device(UCLASS_PCH, &pch);
+ if (ret)
+ return ret;
+ if (!pch)
+ return -ENODEV;
/*
* Get the memory/io base address to configure every pins.
* IOBASE is used to configure the mode/pads
* GPIOBASE is used to configure the direction and default value
*/
- gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
- if (gpiobase < 0) {
+ ret = pch_get_gpio_base(pch, &gpiobase);
+ if (ret) {
debug("%s: invalid GPIOBASE address (%08x)\n", __func__,
gpiobase);
return -EINVAL;
@@ -319,16 +241,11 @@ int gpio_ich6_pinctrl_init(void)
* Get the IOBASE, this is not mandatory as this is not
* supported by all the CPU
*/
- iobase_offset = fdtdec_get_int(gd->fdt_blob, node, "io-base", -1);
- if (iobase_offset == -1) {
- debug("%s: io-base offset not present\n", __func__);
- } else {
- iobase = gpio_ich6_get_base(iobase_offset);
- if (IS_ERR_VALUE(iobase)) {
- debug("%s: invalid IOBASE address (%08x)\n", __func__,
- iobase);
- return -EINVAL;
- }
+ ret = pch_get_io_base(pch, &iobase);
+ if (ret && ret != -ENOSYS) {
+ debug("%s: invalid IOBASE address (%08x)\n", __func__,
+ iobase);
+ return -EINVAL;
}
for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
@@ -349,10 +266,14 @@ int gpio_ich6_pinctrl_init(void)
static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
{
struct ich6_bank_platdata *plat = dev_get_platdata(dev);
- u16 gpiobase;
+ u32 gpiobase;
int offset;
+ int ret;
+
+ ret = pch_get_gpio_base(dev->parent, &gpiobase);
+ if (ret)
+ return ret;
- gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
if (offset == -1) {
debug("%s: Invalid register offset %d\n", __func__, offset);
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c
index 8e880e276f0..5a031159ca3 100644
--- a/drivers/gpio/tegra_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -177,7 +177,10 @@ static int tegra_gpio_get_value(struct udevice *dev, unsigned offset)
debug("%s: pin = %d (port %d:bit %d)\n", __func__,
gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
- val = readl(&state->bank->gpio_in[GPIO_PORT(gpio)]);
+ if (get_direction(gpio) == DIRECTION_INPUT)
+ val = readl(&state->bank->gpio_in[GPIO_PORT(gpio)]);
+ else
+ val = readl(&state->bank->gpio_out[GPIO_PORT(gpio)]);
return (val >> GPIO_BIT(gpio)) & 1;
}
diff --git a/drivers/input/tegra-kbc.c b/drivers/input/tegra-kbc.c
index 951cbb4481b..c77f6107696 100644
--- a/drivers/input/tegra-kbc.c
+++ b/drivers/input/tegra-kbc.c
@@ -312,6 +312,7 @@ static int tegra_kbd_probe(struct udevice *dev)
__func__, ret);
return ret;
}
+ input_add_tables(input, false);
if (priv->matrix.fn_keycode) {
ret = input_add_table(input, KEY_FN, -1,
priv->matrix.fn_keycode,
@@ -326,7 +327,6 @@ static int tegra_kbd_probe(struct udevice *dev)
priv->input = input;
input->dev = dev;
input->read_keys = tegra_kbc_check;
- input_add_tables(input, false);
strcpy(sdev->name, "tegra-kbc");
ret = input_stdio_register(sdev);
if (ret) {
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e1e3c6b70fc..f2b08abf11d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -32,6 +32,7 @@ ifdef CONFIG_DM_I2C
obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o
endif
obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
+obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
obj-$(CONFIG_STATUS_LED) += status_led.o
obj-$(CONFIG_SANDBOX) += swap_case.o
obj-$(CONFIG_SANDBOX) += syscon_sandbox.o
diff --git a/drivers/misc/smsc_sio1007.c b/drivers/misc/smsc_sio1007.c
new file mode 100644
index 00000000000..ec53533bde6
--- /dev/null
+++ b/drivers/misc/smsc_sio1007.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <smsc_sio1007.h>
+
+static inline u8 sio1007_read(int port, int reg)
+{
+ outb(reg, port);
+
+ return inb(port + 1);
+}
+
+static inline void sio1007_write(int port, int reg, int val)
+{
+ outb(reg, port);
+ outb(val, port + 1);
+}
+
+static inline void sio1007_clrsetbits(int port, int reg, u8 clr, u8 set)
+{
+ sio1007_write(port, reg, (sio1007_read(port, reg) & ~clr) | set);
+}
+
+void sio1007_enable_serial(int port, int num, int iobase, int irq)
+{
+ if (num < 0 || num > SIO1007_UART_NUM)
+ return;
+
+ /* enter configuration state */
+ outb(0x55, port);
+
+ /* power on serial port and set up its i/o base & irq */
+ if (!num) {
+ sio1007_clrsetbits(port, DEV_POWER_CTRL, 0, UART1_POWER_ON);
+ sio1007_clrsetbits(port, UART1_IOBASE, 0xfe, iobase >> 2);
+ sio1007_clrsetbits(port, UART_IRQ, 0xf0, irq << 4);
+ } else {
+ sio1007_clrsetbits(port, DEV_POWER_CTRL, 0, UART2_POWER_ON);
+ sio1007_clrsetbits(port, UART2_IOBASE, 0xfe, iobase >> 2);
+ sio1007_clrsetbits(port, UART_IRQ, 0x0f, irq);
+ }
+
+ /* exit configuration state */
+ outb(0xaa, port);
+}
+
+void sio1007_enable_runtime(int port, int iobase)
+{
+ /* enter configuration state */
+ outb(0x55, port);
+
+ /* set i/o base for the runtime register block */
+ sio1007_clrsetbits(port, RTR_IOBASE_LOW, 0, iobase >> 4);
+ sio1007_clrsetbits(port, RTR_IOBASE_HIGH, 0, iobase >> 12);
+ /* turn on address decoding for this block */
+ sio1007_clrsetbits(port, DEV_ACTIVATE, 0, RTR_EN);
+
+ /* exit configuration state */
+ outb(0xaa, port);
+}
+
+void sio1007_gpio_config(int port, int gpio, int dir, int pol, int type)
+{
+ int reg = GPIO0_DIR;
+
+ if (gpio < 0 || gpio > SIO1007_GPIO_NUM)
+ return;
+ if (gpio >= GPIO_NUM_PER_GROUP) {
+ reg = GPIO1_DIR;
+ gpio -= GPIO_NUM_PER_GROUP;
+ }
+
+ /* enter configuration state */
+ outb(0x55, port);
+
+ /* set gpio pin direction, polority and type */
+ sio1007_clrsetbits(port, reg, 1 << gpio, dir << gpio);
+ sio1007_clrsetbits(port, reg + 1, 1 << gpio, pol << gpio);
+ sio1007_clrsetbits(port, reg + 2, 1 << gpio, type << gpio);
+
+ /* exit configuration state */
+ outb(0xaa, port);
+}
+
+int sio1007_gpio_get_value(int port, int gpio)
+{
+ int reg = GPIO0_DATA;
+ int val;
+
+ if (gpio < 0 || gpio > SIO1007_GPIO_NUM)
+ return -EINVAL;
+ if (gpio >= GPIO_NUM_PER_GROUP) {
+ reg = GPIO1_DATA;
+ gpio -= GPIO_NUM_PER_GROUP;
+ }
+
+ val = inb(port + reg);
+ if (val & (1 << gpio))
+ return 1;
+ else
+ return 0;
+}
+
+void sio1007_gpio_set_value(int port, int gpio, int val)
+{
+ int reg = GPIO0_DATA;
+ u8 data;
+
+ if (gpio < 0 || gpio > SIO1007_GPIO_NUM)
+ return;
+ if (gpio >= GPIO_NUM_PER_GROUP) {
+ reg = GPIO1_DATA;
+ gpio -= GPIO_NUM_PER_GROUP;
+ }
+
+ data = inb(port + reg);
+ data &= ~(1 << gpio);
+ data |= (val << gpio);
+ outb(data, port + reg);
+}
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c
index cc62c89a259..30e538cc161 100644
--- a/drivers/mmc/sh_sdhi.c
+++ b/drivers/mmc/sh_sdhi.c
@@ -526,7 +526,7 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
opc = sh_sdhi_set_cmd(host, data, opc);
/*
- * U-boot cannot use interrupt.
+ * U-Boot cannot use interrupt.
* So this flag may not be clear by timing
*/
sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_RESP_END);
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 15848658e11..573819a01e2 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -674,7 +674,7 @@ void tegra_mmc_init(void)
CONFIG_SYS_MMC_MAX_DEVICE);
debug("%s: count of Tegra210 sdhci nodes is %d\n", __func__, count);
if (process_nodes(blob, node_list, count)) {
- printf("%s: Error processing T30 mmc node(s)!\n", __func__);
+ printf("%s: Error processing T210 mmc node(s)!\n", __func__);
return;
}
@@ -684,7 +684,7 @@ void tegra_mmc_init(void)
CONFIG_SYS_MMC_MAX_DEVICE);
debug("%s: count of Tegra124 sdhci nodes is %d\n", __func__, count);
if (process_nodes(blob, node_list, count)) {
- printf("%s: Error processing T30 mmc node(s)!\n", __func__);
+ printf("%s: Error processing T124 mmc node(s)!\n", __func__);
return;
}
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 9a74064c98b..2fc73ef4e59 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -71,6 +71,13 @@ config NAND_SUNXI
Enable support for NAND. This option allows SPL to read from
sunxi NAND using DMA transfers.
+config NAND_ARASAN
+ bool "Configure Arasan Nand"
+ help
+ This enables Nand driver support for Arasan nand flash
+ controller. This uses the hardware ECC for read and
+ write operations.
+
comment "Generic NAND options"
# Enhance depends when converting drivers to Kconfig which use this config
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index b4e53761766..6fb37182d59 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -42,6 +42,7 @@ ifdef NORMAL_DRIVERS
obj-$(CONFIG_NAND_ECC_BCH) += nand_bch.o
obj-$(CONFIG_NAND_ATMEL) += atmel_nand.o
+obj-$(CONFIG_NAND_ARASAN) += arasan_nfc.o
obj-$(CONFIG_DRIVER_NAND_BFIN) += bfin_nand.o
obj-$(CONFIG_NAND_DAVINCI) += davinci_nand.o
obj-$(CONFIG_NAND_DENALI) += denali.o
diff --git a/drivers/mtd/nand/arasan_nfc.c b/drivers/mtd/nand/arasan_nfc.c
new file mode 100644
index 00000000000..2d73a05e75d
--- /dev/null
+++ b/drivers/mtd/nand/arasan_nfc.c
@@ -0,0 +1,1154 @@
+/*
+ * Arasan NAND Flash Controller Driver
+ *
+ * Copyright (C) 2014 - 2015 Xilinx, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand_ecc.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+#include <nand.h>
+
+struct arasan_nand_info {
+ void __iomem *nand_base;
+ u32 page;
+};
+
+struct nand_regs {
+ u32 pkt_reg;
+ u32 memadr_reg1;
+ u32 memadr_reg2;
+ u32 cmd_reg;
+ u32 pgm_reg;
+ u32 intsts_enr;
+ u32 intsig_enr;
+ u32 intsts_reg;
+ u32 rdy_busy;
+ u32 cms_sysadr_reg;
+ u32 flash_sts_reg;
+ u32 tmg_reg;
+ u32 buf_dataport;
+ u32 ecc_reg;
+ u32 ecc_errcnt_reg;
+ u32 ecc_sprcmd_reg;
+ u32 errcnt_1bitreg;
+ u32 errcnt_2bitreg;
+ u32 errcnt_3bitreg;
+ u32 errcnt_4bitreg;
+ u32 dma_sysadr0_reg;
+ u32 dma_bufbdry_reg;
+ u32 cpu_rls_reg;
+ u32 errcnt_5bitreg;
+ u32 errcnt_6bitreg;
+ u32 errcnt_7bitreg;
+ u32 errcnt_8bitreg;
+ u32 data_if_reg;
+};
+
+#define arasan_nand_base ((struct nand_regs __iomem *)ARASAN_NAND_BASEADDR)
+
+struct arasan_nand_command_format {
+ u8 cmd1;
+ u8 cmd2;
+ u8 addr_cycles;
+ u32 pgm;
+};
+
+#define ONDIE_ECC_FEATURE_ADDR 0x90
+
+#define ARASAN_PROG_RD_MASK 0x00000001
+#define ARASAN_PROG_BLK_ERS_MASK 0x00000004
+#define ARASAN_PROG_RD_ID_MASK 0x00000040
+#define ARASAN_PROG_RD_STS_MASK 0x00000008
+#define ARASAN_PROG_PG_PROG_MASK 0x00000010
+#define ARASAN_PROG_RD_PARAM_PG_MASK 0x00000080
+#define ARASAN_PROG_RST_MASK 0x00000100
+#define ARASAN_PROG_GET_FTRS_MASK 0x00000200
+#define ARASAN_PROG_SET_FTRS_MASK 0x00000400
+#define ARASAN_PROG_CHNG_ROWADR_END_MASK 0x00400000
+
+#define ARASAN_NAND_CMD_ECC_ON_MASK 0x80000000
+#define ARASAN_NAND_CMD_CMD12_MASK 0xFFFF
+#define ARASAN_NAND_CMD_PG_SIZE_MASK 0x3800000
+#define ARASAN_NAND_CMD_PG_SIZE_SHIFT 23
+#define ARASAN_NAND_CMD_CMD2_SHIFT 8
+#define ARASAN_NAND_CMD_ADDR_CYCL_MASK 0x70000000
+#define ARASAN_NAND_CMD_ADDR_CYCL_SHIFT 28
+
+#define ARASAN_NAND_MEM_ADDR1_PAGE_MASK 0xFFFF0000
+#define ARASAN_NAND_MEM_ADDR1_COL_MASK 0xFFFF
+#define ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT 16
+#define ARASAN_NAND_MEM_ADDR2_PAGE_MASK 0xFF
+#define ARASAN_NAND_MEM_ADDR2_CS_MASK 0xC0000000
+#define ARASAN_NAND_MEM_ADDR2_BCH_MASK 0xE000000
+#define ARASAN_NAND_MEM_ADDR2_BCH_SHIFT 25
+
+#define ARASAN_NAND_INT_STS_ERR_EN_MASK 0x10
+#define ARASAN_NAND_INT_STS_MUL_BIT_ERR_MASK 0x08
+#define ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK 0x02
+#define ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK 0x01
+#define ARASAN_NAND_INT_STS_XFR_CMPLT_MASK 0x04
+
+#define ARASAN_NAND_PKT_REG_PKT_CNT_MASK 0xFFF000
+#define ARASAN_NAND_PKT_REG_PKT_SIZE_MASK 0x7FF
+#define ARASAN_NAND_PKT_REG_PKT_CNT_SHFT 12
+
+#define ARASAN_NAND_ROW_ADDR_CYCL_MASK 0x0F
+#define ARASAN_NAND_COL_ADDR_CYCL_MASK 0xF0
+#define ARASAN_NAND_COL_ADDR_CYCL_SHIFT 4
+
+#define ARASAN_NAND_ECC_SIZE_SHIFT 16
+#define ARASAN_NAND_ECC_BCH_SHIFT 27
+
+#define ARASAN_NAND_PKTSIZE_1K 1024
+#define ARASAN_NAND_PKTSIZE_512 512
+
+#define ARASAN_NAND_POLL_TIMEOUT 1000000
+#define ARASAN_NAND_INVALID_ADDR_CYCL 0xFF
+
+#define ERR_ADDR_CYCLE -1
+#define READ_BUFF_SIZE 0x4000
+
+static struct arasan_nand_command_format *curr_cmd;
+
+enum addr_cycles {
+ NAND_ADDR_CYCL_NONE,
+ NAND_ADDR_CYCL_ONE,
+ NAND_ADDR_CYCL_ROW,
+ NAND_ADDR_CYCL_COL,
+ NAND_ADDR_CYCL_BOTH,
+};
+
+static struct arasan_nand_command_format arasan_nand_commands[] = {
+ {NAND_CMD_READ0, NAND_CMD_READSTART, NAND_ADDR_CYCL_BOTH,
+ ARASAN_PROG_RD_MASK},
+ {NAND_CMD_RNDOUT, NAND_CMD_RNDOUTSTART, NAND_ADDR_CYCL_COL,
+ ARASAN_PROG_RD_MASK},
+ {NAND_CMD_READID, NAND_CMD_NONE, NAND_ADDR_CYCL_ONE,
+ ARASAN_PROG_RD_ID_MASK},
+ {NAND_CMD_STATUS, NAND_CMD_NONE, NAND_ADDR_CYCL_NONE,
+ ARASAN_PROG_RD_STS_MASK},
+ {NAND_CMD_SEQIN, NAND_CMD_PAGEPROG, NAND_ADDR_CYCL_BOTH,
+ ARASAN_PROG_PG_PROG_MASK},
+ {NAND_CMD_RNDIN, NAND_CMD_NONE, NAND_ADDR_CYCL_COL,
+ ARASAN_PROG_CHNG_ROWADR_END_MASK},
+ {NAND_CMD_ERASE1, NAND_CMD_ERASE2, NAND_ADDR_CYCL_ROW,
+ ARASAN_PROG_BLK_ERS_MASK},
+ {NAND_CMD_RESET, NAND_CMD_NONE, NAND_ADDR_CYCL_NONE,
+ ARASAN_PROG_RST_MASK},
+ {NAND_CMD_PARAM, NAND_CMD_NONE, NAND_ADDR_CYCL_ONE,
+ ARASAN_PROG_RD_PARAM_PG_MASK},
+ {NAND_CMD_GET_FEATURES, NAND_CMD_NONE, NAND_ADDR_CYCL_ONE,
+ ARASAN_PROG_GET_FTRS_MASK},
+ {NAND_CMD_SET_FEATURES, NAND_CMD_NONE, NAND_ADDR_CYCL_ONE,
+ ARASAN_PROG_SET_FTRS_MASK},
+ {NAND_CMD_NONE, NAND_CMD_NONE, NAND_ADDR_CYCL_NONE, 0},
+};
+
+struct arasan_ecc_matrix {
+ u32 pagesize;
+ u32 ecc_codeword_size;
+ u8 eccbits;
+ u8 bch;
+ u8 bchval;
+ u16 eccaddr;
+ u16 eccsize;
+};
+
+static const struct arasan_ecc_matrix ecc_matrix[] = {
+ {512, 512, 1, 0, 0, 0x20D, 0x3},
+ {512, 512, 4, 1, 3, 0x209, 0x7},
+ {512, 512, 8, 1, 2, 0x203, 0xD},
+ /*
+ * 2K byte page
+ */
+ {2048, 512, 1, 0, 0, 0x834, 0xC},
+ {2048, 512, 4, 1, 3, 0x826, 0x1A},
+ {2048, 512, 8, 1, 2, 0x80c, 0x34},
+ {2048, 512, 12, 1, 1, 0x822, 0x4E},
+ {2048, 512, 16, 1, 0, 0x808, 0x68},
+ {2048, 1024, 24, 1, 4, 0x81c, 0x54},
+ /*
+ * 4K byte page
+ */
+ {4096, 512, 1, 0, 0, 0x1068, 0x18},
+ {4096, 512, 4, 1, 3, 0x104c, 0x34},
+ {4096, 512, 8, 1, 2, 0x1018, 0x68},
+ {4096, 512, 12, 1, 1, 0x1044, 0x9C},
+ {4096, 512, 16, 1, 0, 0x1010, 0xD0},
+ {4096, 1024, 24, 1, 4, 0x1038, 0xA8},
+ /*
+ * 8K byte page
+ */
+ {8192, 512, 1, 0, 0, 0x20d0, 0x30},
+ {8192, 512, 4, 1, 3, 0x2098, 0x68},
+ {8192, 512, 8, 1, 2, 0x2030, 0xD0},
+ {8192, 512, 12, 1, 1, 0x2088, 0x138},
+ {8192, 512, 16, 1, 0, 0x2020, 0x1A0},
+ {8192, 1024, 24, 1, 4, 0x2070, 0x150},
+ /*
+ * 16K byte page
+ */
+ {16384, 512, 1, 0, 0, 0x4460, 0x60},
+ {16384, 512, 4, 1, 3, 0x43f0, 0xD0},
+ {16384, 512, 8, 1, 2, 0x4320, 0x1A0},
+ {16384, 512, 12, 1, 1, 0x4250, 0x270},
+ {16384, 512, 16, 1, 0, 0x4180, 0x340},
+ {16384, 1024, 24, 1, 4, 0x4220, 0x2A0}
+};
+
+static u8 buf_data[READ_BUFF_SIZE];
+static u32 buf_index;
+
+static struct nand_ecclayout nand_oob;
+
+static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
+
+static void arasan_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+}
+
+static void arasan_nand_enable_ecc(void)
+{
+ u32 reg_val;
+
+ reg_val = readl(&arasan_nand_base->cmd_reg);
+ reg_val |= ARASAN_NAND_CMD_ECC_ON_MASK;
+
+ writel(reg_val, &arasan_nand_base->cmd_reg);
+}
+
+static u8 arasan_nand_get_addrcycle(struct mtd_info *mtd)
+{
+ u8 addrcycles;
+ struct nand_chip *chip = mtd->priv;
+
+ switch (curr_cmd->addr_cycles) {
+ case NAND_ADDR_CYCL_NONE:
+ addrcycles = 0;
+ break;
+ case NAND_ADDR_CYCL_ONE:
+ addrcycles = 1;
+ break;
+ case NAND_ADDR_CYCL_ROW:
+ addrcycles = chip->onfi_params.addr_cycles &
+ ARASAN_NAND_ROW_ADDR_CYCL_MASK;
+ break;
+ case NAND_ADDR_CYCL_COL:
+ addrcycles = (chip->onfi_params.addr_cycles &
+ ARASAN_NAND_COL_ADDR_CYCL_MASK) >>
+ ARASAN_NAND_COL_ADDR_CYCL_SHIFT;
+ break;
+ case NAND_ADDR_CYCL_BOTH:
+ addrcycles = chip->onfi_params.addr_cycles &
+ ARASAN_NAND_ROW_ADDR_CYCL_MASK;
+ addrcycles += (chip->onfi_params.addr_cycles &
+ ARASAN_NAND_COL_ADDR_CYCL_MASK) >>
+ ARASAN_NAND_COL_ADDR_CYCL_SHIFT;
+ break;
+ default:
+ addrcycles = ARASAN_NAND_INVALID_ADDR_CYCL;
+ break;
+ }
+ return addrcycles;
+}
+
+static int arasan_nand_read_page(struct mtd_info *mtd, u8 *buf, u32 size)
+{
+ struct nand_chip *chip = mtd->priv;
+ u32 reg_val, i, pktsize, pktnum;
+ u32 *bufptr = (u32 *)buf;
+ u32 timeout;
+ u32 rdcount = 0;
+ u8 addr_cycles;
+
+ if (chip->ecc_step_ds >= ARASAN_NAND_PKTSIZE_1K)
+ pktsize = ARASAN_NAND_PKTSIZE_1K;
+ else
+ pktsize = ARASAN_NAND_PKTSIZE_512;
+
+ if (size % pktsize)
+ pktnum = size/pktsize + 1;
+ else
+ pktnum = size/pktsize;
+
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ reg_val |= ARASAN_NAND_INT_STS_ERR_EN_MASK |
+ ARASAN_NAND_INT_STS_MUL_BIT_ERR_MASK;
+ writel(reg_val, &arasan_nand_base->intsts_enr);
+
+ reg_val = readl(&arasan_nand_base->pkt_reg);
+ reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK |
+ ARASAN_NAND_PKT_REG_PKT_SIZE_MASK);
+ reg_val |= (pktnum << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) |
+ pktsize;
+ writel(reg_val, &arasan_nand_base->pkt_reg);
+
+ arasan_nand_enable_ecc();
+ addr_cycles = arasan_nand_get_addrcycle(mtd);
+ if (addr_cycles == ARASAN_NAND_INVALID_ADDR_CYCL)
+ return ERR_ADDR_CYCLE;
+
+ writel((NAND_CMD_RNDOUTSTART << ARASAN_NAND_CMD_CMD2_SHIFT) |
+ NAND_CMD_RNDOUT | (addr_cycles <<
+ ARASAN_NAND_CMD_ADDR_CYCL_SHIFT),
+ &arasan_nand_base->ecc_sprcmd_reg);
+ writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
+
+ while (rdcount < pktnum) {
+ timeout = ARASAN_NAND_POLL_TIMEOUT;
+ while (!(readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK) && timeout) {
+ udelay(1);
+ timeout--;
+ }
+ if (!timeout) {
+ puts("arasan_read_page: timedout:Buff RDY\n");
+ return -ETIMEDOUT;
+ }
+
+ rdcount++;
+
+ if (pktnum == rdcount) {
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ reg_val |= ARASAN_NAND_INT_STS_XFR_CMPLT_MASK;
+ writel(reg_val, &arasan_nand_base->intsts_enr);
+ } else {
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK,
+ &arasan_nand_base->intsts_enr);
+ }
+ reg_val = readl(&arasan_nand_base->intsts_reg);
+ writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK,
+ &arasan_nand_base->intsts_reg);
+
+ for (i = 0; i < pktsize/4; i++)
+ bufptr[i] = readl(&arasan_nand_base->buf_dataport);
+
+
+ bufptr += pktsize/4;
+
+ if (rdcount >= pktnum)
+ break;
+
+ writel(ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK,
+ &arasan_nand_base->intsts_enr);
+ }
+
+ timeout = ARASAN_NAND_POLL_TIMEOUT;
+
+ while (!(readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
+ udelay(1);
+ timeout--;
+ }
+ if (!timeout) {
+ puts("arasan rd_page timedout:Xfer CMPLT\n");
+ return -ETIMEDOUT;
+ }
+
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_enr);
+ reg_val = readl(&arasan_nand_base->intsts_reg);
+ writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_reg);
+
+ if (readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_MUL_BIT_ERR_MASK) {
+ printf("arasan rd_page:sbiterror\n");
+ return -1;
+ }
+
+ if (readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_ERR_EN_MASK) {
+ mtd->ecc_stats.failed++;
+ printf("arasan rd_page:multibiterror\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int arasan_nand_read_page_hwecc(struct mtd_info *mtd,
+ struct nand_chip *chip, u8 *buf, int oob_required, int page)
+{
+ int status;
+
+ status = arasan_nand_read_page(mtd, buf, (mtd->writesize));
+
+ if (oob_required)
+ chip->ecc.read_oob(mtd, chip, page);
+
+ return status;
+}
+
+static void arasan_nand_fill_tx(const u8 *buf, int len)
+{
+ u32 __iomem *nand = &arasan_nand_base->buf_dataport;
+
+ if (((unsigned long)buf & 0x3) != 0) {
+ if (((unsigned long)buf & 0x1) != 0) {
+ if (len) {
+ writeb(*buf, nand);
+ buf += 1;
+ len--;
+ }
+ }
+
+ if (((unsigned long)buf & 0x3) != 0) {
+ if (len >= 2) {
+ writew(*(u16 *)buf, nand);
+ buf += 2;
+ len -= 2;
+ }
+ }
+ }
+
+ while (len >= 4) {
+ writel(*(u32 *)buf, nand);
+ buf += 4;
+ len -= 4;
+ }
+
+ if (len) {
+ if (len >= 2) {
+ writew(*(u16 *)buf, nand);
+ buf += 2;
+ len -= 2;
+ }
+
+ if (len)
+ writeb(*buf, nand);
+ }
+}
+
+static int arasan_nand_write_page_hwecc(struct mtd_info *mtd,
+ struct nand_chip *chip, const u8 *buf, int oob_required)
+{
+ u32 reg_val, i, pktsize, pktnum;
+ const u32 *bufptr = (const u32 *)buf;
+ u32 timeout = ARASAN_NAND_POLL_TIMEOUT;
+ u32 size = mtd->writesize;
+ u32 rdcount = 0;
+ u8 column_addr_cycles;
+ struct arasan_nand_info *nand = chip->priv;
+
+ if (chip->ecc_step_ds >= ARASAN_NAND_PKTSIZE_1K)
+ pktsize = ARASAN_NAND_PKTSIZE_1K;
+ else
+ pktsize = ARASAN_NAND_PKTSIZE_512;
+
+ if (size % pktsize)
+ pktnum = size/pktsize + 1;
+ else
+ pktnum = size/pktsize;
+
+ reg_val = readl(&arasan_nand_base->pkt_reg);
+ reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK |
+ ARASAN_NAND_PKT_REG_PKT_SIZE_MASK);
+ reg_val |= (pktnum << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | pktsize;
+ writel(reg_val, &arasan_nand_base->pkt_reg);
+
+ arasan_nand_enable_ecc();
+ column_addr_cycles = (chip->onfi_params.addr_cycles &
+ ARASAN_NAND_COL_ADDR_CYCL_MASK) >>
+ ARASAN_NAND_COL_ADDR_CYCL_SHIFT;
+ writel((NAND_CMD_RNDIN | (column_addr_cycles << 28)),
+ &arasan_nand_base->ecc_sprcmd_reg);
+ writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
+
+ while (rdcount < pktnum) {
+ timeout = ARASAN_NAND_POLL_TIMEOUT;
+ while (!(readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK) && timeout) {
+ udelay(1);
+ timeout--;
+ }
+
+ if (!timeout) {
+ puts("arasan_write_page: timedout:Buff RDY\n");
+ return -ETIMEDOUT;
+ }
+
+ rdcount++;
+
+ if (pktnum == rdcount) {
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ reg_val |= ARASAN_NAND_INT_STS_XFR_CMPLT_MASK;
+ writel(reg_val, &arasan_nand_base->intsts_enr);
+ } else {
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ writel(reg_val | ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK,
+ &arasan_nand_base->intsts_enr);
+ }
+
+ reg_val = readl(&arasan_nand_base->intsts_reg);
+ writel(reg_val | ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK,
+ &arasan_nand_base->intsts_reg);
+
+ for (i = 0; i < pktsize/4; i++)
+ writel(bufptr[i], &arasan_nand_base->buf_dataport);
+
+ bufptr += pktsize/4;
+
+ if (rdcount >= pktnum)
+ break;
+
+ writel(ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK,
+ &arasan_nand_base->intsts_enr);
+ }
+
+ timeout = ARASAN_NAND_POLL_TIMEOUT;
+
+ while (!(readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
+ udelay(1);
+ timeout--;
+ }
+ if (!timeout) {
+ puts("arasan write_page timedout:Xfer CMPLT\n");
+ return -ETIMEDOUT;
+ }
+
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_enr);
+ reg_val = readl(&arasan_nand_base->intsts_reg);
+ writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_reg);
+
+ if (oob_required)
+ chip->ecc.write_oob(mtd, chip, nand->page);
+
+ return 0;
+}
+
+static int arasan_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+ int page)
+{
+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+ chip->read_buf(mtd, chip->oob_poi, (mtd->oobsize));
+
+ return 0;
+}
+
+static int arasan_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+ int page)
+{
+ int status = 0;
+ const u8 *buf = chip->oob_poi;
+
+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+ chip->write_buf(mtd, buf, mtd->oobsize);
+
+ return status;
+}
+
+static int arasan_nand_reset(struct arasan_nand_command_format *curr_cmd)
+{
+ u32 timeout = ARASAN_NAND_POLL_TIMEOUT;
+ u32 cmd_reg = 0;
+
+ writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_enr);
+ cmd_reg = readl(&arasan_nand_base->cmd_reg);
+ cmd_reg &= ~ARASAN_NAND_CMD_CMD12_MASK;
+
+ cmd_reg |= curr_cmd->cmd1 |
+ (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT);
+ writel(cmd_reg, &arasan_nand_base->cmd_reg);
+ writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
+
+ while (!(readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
+ udelay(1);
+ timeout--;
+ }
+ if (!timeout) {
+ printf("ERROR:%s timedout\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_enr);
+
+ writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_reg);
+
+ return 0;
+}
+
+static u8 arasan_nand_page(struct mtd_info *mtd)
+{
+ u8 page_val = 0;
+
+ switch (mtd->writesize) {
+ case 512:
+ page_val = 0;
+ break;
+ case 2048:
+ page_val = 1;
+ break;
+ case 4096:
+ page_val = 2;
+ break;
+ case 8192:
+ page_val = 3;
+ break;
+ case 16384:
+ page_val = 4;
+ break;
+ case 1024:
+ page_val = 5;
+ break;
+ default:
+ printf("%s:Pagesize>16K\n", __func__);
+ break;
+ }
+
+ return page_val;
+}
+
+static int arasan_nand_send_wrcmd(struct arasan_nand_command_format *curr_cmd,
+ int column, int page_addr, struct mtd_info *mtd)
+{
+ u32 reg_val, page;
+ u8 page_val, addr_cycles;
+
+ writel(ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK,
+ &arasan_nand_base->intsts_enr);
+ reg_val = readl(&arasan_nand_base->cmd_reg);
+ reg_val &= ~ARASAN_NAND_CMD_CMD12_MASK;
+ reg_val |= curr_cmd->cmd1 |
+ (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT);
+ if (curr_cmd->cmd1 == NAND_CMD_SEQIN) {
+ reg_val &= ~ARASAN_NAND_CMD_PG_SIZE_MASK;
+ page_val = arasan_nand_page(mtd);
+ reg_val |= (page_val << ARASAN_NAND_CMD_PG_SIZE_SHIFT);
+ }
+
+ reg_val &= ~ARASAN_NAND_CMD_ADDR_CYCL_MASK;
+ addr_cycles = arasan_nand_get_addrcycle(mtd);
+
+ if (addr_cycles == ARASAN_NAND_INVALID_ADDR_CYCL)
+ return ERR_ADDR_CYCLE;
+
+ reg_val |= (addr_cycles <<
+ ARASAN_NAND_CMD_ADDR_CYCL_SHIFT);
+ writel(reg_val, &arasan_nand_base->cmd_reg);
+
+ if (page_addr == -1)
+ page_addr = 0;
+
+ page = (page_addr << ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT) &
+ ARASAN_NAND_MEM_ADDR1_PAGE_MASK;
+ column &= ARASAN_NAND_MEM_ADDR1_COL_MASK;
+ writel(page|column, &arasan_nand_base->memadr_reg1);
+
+ reg_val = readl(&arasan_nand_base->memadr_reg2);
+ reg_val &= ~ARASAN_NAND_MEM_ADDR2_PAGE_MASK;
+ reg_val |= (page_addr >> ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT);
+ writel(reg_val, &arasan_nand_base->memadr_reg2);
+ reg_val = readl(&arasan_nand_base->memadr_reg2);
+ reg_val &= ~ARASAN_NAND_MEM_ADDR2_CS_MASK;
+ writel(reg_val, &arasan_nand_base->memadr_reg2);
+
+ return 0;
+}
+
+static void arasan_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+ u32 reg_val;
+ u32 timeout = ARASAN_NAND_POLL_TIMEOUT;
+
+ reg_val = readl(&arasan_nand_base->pkt_reg);
+ reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK |
+ ARASAN_NAND_PKT_REG_PKT_SIZE_MASK);
+
+ reg_val |= (1 << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | len;
+ writel(reg_val, &arasan_nand_base->pkt_reg);
+ writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
+
+ while (!(readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK) && timeout) {
+ udelay(1);
+ timeout--;
+ }
+
+ if (!timeout)
+ puts("ERROR:arasan_nand_write_buf timedout:Buff RDY\n");
+
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ reg_val |= ARASAN_NAND_INT_STS_XFR_CMPLT_MASK;
+ writel(reg_val, &arasan_nand_base->intsts_enr);
+ writel(reg_val | ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK,
+ &arasan_nand_base->intsts_enr);
+ reg_val = readl(&arasan_nand_base->intsts_reg);
+ writel(reg_val | ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK,
+ &arasan_nand_base->intsts_reg);
+
+ arasan_nand_fill_tx(buf, len);
+
+ timeout = ARASAN_NAND_POLL_TIMEOUT;
+ while (!(readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
+ udelay(1);
+ timeout--;
+ }
+ if (!timeout)
+ puts("ERROR:arasan_nand_write_buf timedout:Xfer CMPLT\n");
+
+ writel(readl(&arasan_nand_base->intsts_enr) |
+ ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_enr);
+ writel(readl(&arasan_nand_base->intsts_reg) |
+ ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_reg);
+}
+
+static int arasan_nand_erase(struct arasan_nand_command_format *curr_cmd,
+ int column, int page_addr, struct mtd_info *mtd)
+{
+ u32 reg_val, page;
+ u32 timeout = ARASAN_NAND_POLL_TIMEOUT;
+ u8 row_addr_cycles;
+
+ writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_enr);
+ reg_val = readl(&arasan_nand_base->cmd_reg);
+ reg_val &= ~ARASAN_NAND_CMD_CMD12_MASK;
+ reg_val |= curr_cmd->cmd1 |
+ (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT);
+ row_addr_cycles = arasan_nand_get_addrcycle(mtd);
+
+ if (row_addr_cycles == ARASAN_NAND_INVALID_ADDR_CYCL)
+ return ERR_ADDR_CYCLE;
+
+ reg_val &= ~ARASAN_NAND_CMD_ADDR_CYCL_MASK;
+ reg_val |= (row_addr_cycles <<
+ ARASAN_NAND_CMD_ADDR_CYCL_SHIFT);
+
+ writel(reg_val, &arasan_nand_base->cmd_reg);
+
+ page = (page_addr << ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT) &
+ ARASAN_NAND_MEM_ADDR1_PAGE_MASK;
+ column = page_addr & ARASAN_NAND_MEM_ADDR1_COL_MASK;
+ writel(page | column, &arasan_nand_base->memadr_reg1);
+
+ reg_val = readl(&arasan_nand_base->memadr_reg2);
+ reg_val &= ~ARASAN_NAND_MEM_ADDR2_PAGE_MASK;
+ reg_val |= (page_addr >> ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT);
+ writel(reg_val, &arasan_nand_base->memadr_reg2);
+ reg_val = readl(&arasan_nand_base->memadr_reg2);
+ reg_val &= ~ARASAN_NAND_MEM_ADDR2_CS_MASK;
+ writel(reg_val, &arasan_nand_base->memadr_reg2);
+ writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
+
+ while (!(readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
+ udelay(1);
+ timeout--;
+ }
+ if (!timeout) {
+ printf("ERROR:%s timedout:Xfer CMPLT\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_enr);
+ reg_val = readl(&arasan_nand_base->intsts_reg);
+ writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_reg);
+
+ return 0;
+}
+
+static int arasan_nand_read_status(struct arasan_nand_command_format *curr_cmd,
+ int column, int page_addr, struct mtd_info *mtd)
+{
+ u32 reg_val;
+ u32 timeout = ARASAN_NAND_POLL_TIMEOUT;
+ u8 addr_cycles;
+
+ writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_enr);
+ reg_val = readl(&arasan_nand_base->cmd_reg);
+ reg_val &= ~ARASAN_NAND_CMD_CMD12_MASK;
+ reg_val |= curr_cmd->cmd1 |
+ (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT);
+ addr_cycles = arasan_nand_get_addrcycle(mtd);
+
+ if (addr_cycles == ARASAN_NAND_INVALID_ADDR_CYCL)
+ return ERR_ADDR_CYCLE;
+
+ reg_val &= ~ARASAN_NAND_CMD_ADDR_CYCL_MASK;
+ reg_val |= (addr_cycles <<
+ ARASAN_NAND_CMD_ADDR_CYCL_SHIFT);
+
+ writel(reg_val, &arasan_nand_base->cmd_reg);
+
+ reg_val = readl(&arasan_nand_base->pkt_reg);
+ reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK |
+ ARASAN_NAND_PKT_REG_PKT_SIZE_MASK);
+ reg_val |= (1 << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | 1;
+ writel(reg_val, &arasan_nand_base->pkt_reg);
+
+ reg_val = readl(&arasan_nand_base->memadr_reg2);
+ reg_val &= ~ARASAN_NAND_MEM_ADDR2_CS_MASK;
+ writel(reg_val, &arasan_nand_base->memadr_reg2);
+
+ writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
+ while (!(readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
+ udelay(1);
+ timeout--;
+ }
+
+ if (!timeout) {
+ printf("ERROR:%s: timedout:Xfer CMPLT\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_enr);
+ reg_val = readl(&arasan_nand_base->intsts_reg);
+ writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_reg);
+
+ return 0;
+}
+
+static int arasan_nand_send_rdcmd(struct arasan_nand_command_format *curr_cmd,
+ int column, int page_addr, struct mtd_info *mtd)
+{
+ u32 reg_val, addr_cycles, page;
+ u8 page_val;
+
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK,
+ &arasan_nand_base->intsts_enr);
+
+ reg_val = readl(&arasan_nand_base->cmd_reg);
+ reg_val &= ~ARASAN_NAND_CMD_CMD12_MASK;
+ reg_val |= curr_cmd->cmd1 |
+ (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT);
+
+ if (curr_cmd->cmd1 == NAND_CMD_RNDOUT ||
+ curr_cmd->cmd1 == NAND_CMD_READ0) {
+ reg_val &= ~ARASAN_NAND_CMD_PG_SIZE_MASK;
+ page_val = arasan_nand_page(mtd);
+ reg_val |= (page_val << ARASAN_NAND_CMD_PG_SIZE_SHIFT);
+ }
+
+ reg_val &= ~ARASAN_NAND_CMD_ADDR_CYCL_MASK;
+
+ addr_cycles = arasan_nand_get_addrcycle(mtd);
+
+ if (addr_cycles == ARASAN_NAND_INVALID_ADDR_CYCL)
+ return ERR_ADDR_CYCLE;
+
+ reg_val |= (addr_cycles << 28);
+ writel(reg_val, &arasan_nand_base->cmd_reg);
+
+ if (page_addr == -1)
+ page_addr = 0;
+
+ page = (page_addr << ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT) &
+ ARASAN_NAND_MEM_ADDR1_PAGE_MASK;
+ column &= ARASAN_NAND_MEM_ADDR1_COL_MASK;
+ writel(page | column, &arasan_nand_base->memadr_reg1);
+
+ reg_val = readl(&arasan_nand_base->memadr_reg2);
+ reg_val &= ~ARASAN_NAND_MEM_ADDR2_PAGE_MASK;
+ reg_val |= (page_addr >> ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT);
+ writel(reg_val, &arasan_nand_base->memadr_reg2);
+
+ reg_val = readl(&arasan_nand_base->memadr_reg2);
+ reg_val &= ~ARASAN_NAND_MEM_ADDR2_CS_MASK;
+ writel(reg_val, &arasan_nand_base->memadr_reg2);
+ buf_index = 0;
+
+ return 0;
+}
+
+static void arasan_nand_read_buf(struct mtd_info *mtd, u8 *buf, int size)
+{
+ u32 reg_val, i;
+ u32 *bufptr = (u32 *)buf;
+ u32 timeout = ARASAN_NAND_POLL_TIMEOUT;
+
+ reg_val = readl(&arasan_nand_base->pkt_reg);
+ reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK |
+ ARASAN_NAND_PKT_REG_PKT_SIZE_MASK);
+ reg_val |= (1 << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | size;
+ writel(reg_val, &arasan_nand_base->pkt_reg);
+
+ writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg);
+
+ while (!(readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK) && timeout) {
+ udelay(1);
+ timeout--;
+ }
+
+ if (!timeout)
+ puts("ERROR:arasan_nand_read_buf timedout:Buff RDY\n");
+
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ reg_val |= ARASAN_NAND_INT_STS_XFR_CMPLT_MASK;
+ writel(reg_val, &arasan_nand_base->intsts_enr);
+
+ writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK,
+ &arasan_nand_base->intsts_enr);
+ reg_val = readl(&arasan_nand_base->intsts_reg);
+ writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK,
+ &arasan_nand_base->intsts_reg);
+
+ buf_index = 0;
+ for (i = 0; i < size / 4; i++)
+ bufptr[i] = readl(&arasan_nand_base->buf_dataport);
+
+ if (size & 0x03)
+ bufptr[i] = readl(&arasan_nand_base->buf_dataport);
+
+ timeout = ARASAN_NAND_POLL_TIMEOUT;
+
+ while (!(readl(&arasan_nand_base->intsts_reg) &
+ ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) {
+ udelay(1);
+ timeout--;
+ }
+
+ if (!timeout)
+ puts("ERROR:arasan_nand_read_buf timedout:Xfer CMPLT\n");
+
+ reg_val = readl(&arasan_nand_base->intsts_enr);
+ writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_enr);
+ reg_val = readl(&arasan_nand_base->intsts_reg);
+ writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_reg);
+}
+
+static u8 arasan_nand_read_byte(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd->priv;
+ u32 size;
+ u8 val;
+ struct nand_onfi_params *p;
+
+ if (buf_index == 0) {
+ p = &chip->onfi_params;
+ if (curr_cmd->cmd1 == NAND_CMD_READID)
+ size = 4;
+ else if (curr_cmd->cmd1 == NAND_CMD_PARAM)
+ size = sizeof(struct nand_onfi_params);
+ else if (curr_cmd->cmd1 == NAND_CMD_RNDOUT)
+ size = le16_to_cpu(p->ext_param_page_length) * 16;
+ else if (curr_cmd->cmd1 == NAND_CMD_GET_FEATURES)
+ size = 4;
+ else if (curr_cmd->cmd1 == NAND_CMD_STATUS)
+ return readb(&arasan_nand_base->flash_sts_reg);
+ else
+ size = 8;
+ chip->read_buf(mtd, &buf_data[0], size);
+ }
+
+ val = *(&buf_data[0] + buf_index);
+ buf_index++;
+
+ return val;
+}
+
+static void arasan_nand_cmd_function(struct mtd_info *mtd, unsigned int command,
+ int column, int page_addr)
+{
+ u32 i, ret = 0;
+ struct nand_chip *chip = mtd->priv;
+ struct arasan_nand_info *nand = chip->priv;
+
+ curr_cmd = NULL;
+ writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
+ &arasan_nand_base->intsts_enr);
+
+ if ((command == NAND_CMD_READOOB) &&
+ (mtd->writesize > 512)) {
+ column += mtd->writesize;
+ command = NAND_CMD_READ0;
+ }
+
+ /* Get the command format */
+ for (i = 0; (arasan_nand_commands[i].cmd1 != NAND_CMD_NONE ||
+ arasan_nand_commands[i].cmd2 != NAND_CMD_NONE); i++) {
+ if (command == arasan_nand_commands[i].cmd1) {
+ curr_cmd = &arasan_nand_commands[i];
+ break;
+ }
+ }
+
+ if (curr_cmd == NULL) {
+ printf("Unsupported Command; 0x%x\n", command);
+ return;
+ }
+
+ if (curr_cmd->cmd1 == NAND_CMD_RESET)
+ ret = arasan_nand_reset(curr_cmd);
+
+ if ((curr_cmd->cmd1 == NAND_CMD_READID) ||
+ (curr_cmd->cmd1 == NAND_CMD_PARAM) ||
+ (curr_cmd->cmd1 == NAND_CMD_RNDOUT) ||
+ (curr_cmd->cmd1 == NAND_CMD_GET_FEATURES) ||
+ (curr_cmd->cmd1 == NAND_CMD_READ0))
+ ret = arasan_nand_send_rdcmd(curr_cmd, column, page_addr, mtd);
+
+ if ((curr_cmd->cmd1 == NAND_CMD_SET_FEATURES) ||
+ (curr_cmd->cmd1 == NAND_CMD_SEQIN)) {
+ nand->page = page_addr;
+ ret = arasan_nand_send_wrcmd(curr_cmd, column, page_addr, mtd);
+ }
+
+ if (curr_cmd->cmd1 == NAND_CMD_ERASE1)
+ ret = arasan_nand_erase(curr_cmd, column, page_addr, mtd);
+
+ if (curr_cmd->cmd1 == NAND_CMD_STATUS)
+ ret = arasan_nand_read_status(curr_cmd, column, page_addr, mtd);
+
+ if (ret != 0)
+ printf("ERROR:%s:command:0x%x\n", __func__, curr_cmd->cmd1);
+}
+
+static int arasan_nand_ecc_init(struct mtd_info *mtd)
+{
+ int found = -1;
+ u32 regval, eccpos_start, i;
+ struct nand_chip *nand_chip = mtd->priv;
+
+ nand_chip->ecc.mode = NAND_ECC_HW;
+ nand_chip->ecc.hwctl = NULL;
+ nand_chip->ecc.read_page = arasan_nand_read_page_hwecc;
+ nand_chip->ecc.write_page = arasan_nand_write_page_hwecc;
+ nand_chip->ecc.read_oob = arasan_nand_read_oob;
+ nand_chip->ecc.write_oob = arasan_nand_write_oob;
+
+ for (i = 0; i < ARRAY_SIZE(ecc_matrix); i++) {
+ if ((ecc_matrix[i].pagesize == mtd->writesize) &&
+ (ecc_matrix[i].ecc_codeword_size >=
+ nand_chip->ecc_step_ds)) {
+ if (ecc_matrix[i].eccbits >=
+ nand_chip->ecc_strength_ds) {
+ found = i;
+ break;
+ }
+ found = i;
+ }
+ }
+
+ if (found < 0)
+ return 1;
+
+ regval = ecc_matrix[i].eccaddr |
+ (ecc_matrix[i].eccsize << ARASAN_NAND_ECC_SIZE_SHIFT) |
+ (ecc_matrix[i].bch << ARASAN_NAND_ECC_BCH_SHIFT);
+ writel(regval, &arasan_nand_base->ecc_reg);
+
+ if (ecc_matrix[i].bch) {
+ regval = readl(&arasan_nand_base->memadr_reg2);
+ regval &= ~ARASAN_NAND_MEM_ADDR2_BCH_MASK;
+ regval |= (ecc_matrix[i].bchval <<
+ ARASAN_NAND_MEM_ADDR2_BCH_SHIFT);
+ writel(regval, &arasan_nand_base->memadr_reg2);
+ }
+
+ nand_oob.eccbytes = ecc_matrix[i].eccsize;
+ eccpos_start = mtd->oobsize - nand_oob.eccbytes;
+
+ for (i = 0; i < nand_oob.eccbytes; i++)
+ nand_oob.eccpos[i] = eccpos_start + i;
+
+ nand_oob.oobfree[0].offset = 2;
+ nand_oob.oobfree[0].length = eccpos_start - 2;
+
+ nand_chip->ecc.size = ecc_matrix[i].ecc_codeword_size;
+ nand_chip->ecc.strength = ecc_matrix[i].eccbits;
+ nand_chip->ecc.bytes = ecc_matrix[i].eccsize;
+ nand_chip->ecc.layout = &nand_oob;
+
+ return 0;
+}
+
+static int arasan_nand_init(struct nand_chip *nand_chip, int devnum)
+{
+ struct arasan_nand_info *nand;
+ struct mtd_info *mtd;
+ int err = -1;
+
+ nand = calloc(1, sizeof(struct arasan_nand_info));
+ if (!nand) {
+ printf("%s: failed to allocate\n", __func__);
+ return err;
+ }
+
+ nand->nand_base = arasan_nand_base;
+ mtd = &nand_info[0];
+ nand_chip->priv = nand;
+ mtd->priv = nand_chip;
+
+ /* Set the driver entry points for MTD */
+ nand_chip->cmdfunc = arasan_nand_cmd_function;
+ nand_chip->select_chip = arasan_nand_select_chip;
+ nand_chip->read_byte = arasan_nand_read_byte;
+
+ /* Buffer read/write routines */
+ nand_chip->read_buf = arasan_nand_read_buf;
+ nand_chip->write_buf = arasan_nand_write_buf;
+ nand_chip->bbt_options = NAND_BBT_USE_FLASH;
+
+ writel(0x0, &arasan_nand_base->cmd_reg);
+ writel(0x0, &arasan_nand_base->pgm_reg);
+
+ /* first scan to find the device and get the page size */
+ if (nand_scan_ident(mtd, 1, NULL)) {
+ printf("%s: nand_scan_ident failed\n", __func__);
+ goto fail;
+ }
+
+ if (arasan_nand_ecc_init(mtd)) {
+ printf("%s: nand_ecc_init failed\n", __func__);
+ goto fail;
+ }
+
+ if (nand_scan_tail(mtd)) {
+ printf("%s: nand_scan_tail failed\n", __func__);
+ goto fail;
+ }
+
+ if (nand_register(devnum)) {
+ printf("Nand Register Fail\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ free(nand);
+ return err;
+}
+
+void board_nand_init(void)
+{
+ struct nand_chip *nand = &nand_chip[0];
+
+ if (arasan_nand_init(nand, 0))
+ puts("NAND init failed\n");
+}
diff --git a/drivers/mtd/nand/fsl_ifc_spl.c b/drivers/mtd/nand/fsl_ifc_spl.c
index fccbfb5129d..cbeb74a5bb8 100644
--- a/drivers/mtd/nand/fsl_ifc_spl.c
+++ b/drivers/mtd/nand/fsl_ifc_spl.c
@@ -236,7 +236,7 @@ int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
/*
* Main entrypoint for NAND Boot. It's necessary that SDRAM is already
- * configured and available since this code loads the main U-boot image
+ * configured and available since this code loads the main U-Boot image
* from NAND into SDRAM and starts from there.
*/
void nand_boot(void)
diff --git a/drivers/mtd/nand/lpc32xx_nand_slc.c b/drivers/mtd/nand/lpc32xx_nand_slc.c
index 2e5f1396061..4e1be36654c 100644
--- a/drivers/mtd/nand/lpc32xx_nand_slc.c
+++ b/drivers/mtd/nand/lpc32xx_nand_slc.c
@@ -516,7 +516,7 @@ static int lpc32xx_write_page_hwecc(struct mtd_info *mtd,
/*
* LPC32xx has only one SLC NAND controller, don't utilize
* CONFIG_SYS_NAND_SELF_INIT to be able to reuse this function
- * both in SPL NAND and U-boot images.
+ * both in SPL NAND and U-Boot images.
*/
int board_nand_init(struct nand_chip *lpc32xx_chip)
{
diff --git a/drivers/mtd/nand/mxc_nand_spl.c b/drivers/mtd/nand/mxc_nand_spl.c
index 69b736a848d..6ac2c96eeb6 100644
--- a/drivers/mtd/nand/mxc_nand_spl.c
+++ b/drivers/mtd/nand/mxc_nand_spl.c
@@ -337,7 +337,7 @@ void nand_boot(void)
if (!nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
CONFIG_SYS_NAND_U_BOOT_SIZE,
(uchar *)CONFIG_SYS_NAND_U_BOOT_DST)) {
- /* Copy from NAND successful, start U-boot */
+ /* Copy from NAND successful, start U-Boot */
uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
uboot();
} else {
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
index ba019a07638..b5bbd889ffc 100644
--- a/drivers/mtd/nand/mxs_nand.c
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -1090,24 +1090,29 @@ int mxs_nand_init(struct mxs_nand_info *info)
(struct mxs_gpmi_regs *)MXS_GPMI_BASE;
struct mxs_bch_regs *bch_regs =
(struct mxs_bch_regs *)MXS_BCH_BASE;
- int i = 0, j;
+ int i = 0, j, ret = 0;
info->desc = malloc(sizeof(struct mxs_dma_desc *) *
MXS_NAND_DMA_DESCRIPTOR_COUNT);
- if (!info->desc)
+ if (!info->desc) {
+ ret = -ENOMEM;
goto err1;
+ }
/* Allocate the DMA descriptors. */
for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) {
info->desc[i] = mxs_dma_desc_alloc();
- if (!info->desc[i])
+ if (!info->desc[i]) {
+ ret = -ENOMEM;
goto err2;
+ }
}
/* Init the DMA controller. */
for (j = MXS_DMA_CHANNEL_AHB_APBH_GPMI0;
j <= MXS_DMA_CHANNEL_AHB_APBH_GPMI7; j++) {
- if (mxs_dma_init_channel(j))
+ ret = mxs_dma_init_channel(j);
+ if (ret)
goto err3;
}
@@ -1127,15 +1132,16 @@ int mxs_nand_init(struct mxs_nand_info *info)
return 0;
err3:
- for (--j; j >= 0; j--)
+ for (--j; j >= MXS_DMA_CHANNEL_AHB_APBH_GPMI0; j--)
mxs_dma_release(j);
err2:
- free(info->desc);
-err1:
for (--i; i >= 0; i--)
mxs_dma_desc_free(info->desc[i]);
- printf("MXS NAND: Unable to allocate DMA descriptors\n");
- return -ENOMEM;
+ free(info->desc);
+err1:
+ if (ret == -ENOMEM)
+ printf("MXS NAND: Unable to allocate DMA descriptors\n");
+ return ret;
}
/*!
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index f65b499beb3..939274204e1 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1486,8 +1486,8 @@ static int alloc_nand_resource(struct pxa3xx_nand_info *info)
info->variant = pxa3xx_nand_get_variant();
for (cs = 0; cs < pdata->num_cs; cs++) {
mtd = &nand_info[cs];
- chip = (struct nand_chip *)info +
- sizeof(struct pxa3xx_nand_host);
+ chip = (struct nand_chip *)
+ ((u8 *)&info[1] + sizeof(*host) * cs);
host = (struct pxa3xx_nand_host *)chip;
info->host[cs] = host;
host->mtd = mtd;
@@ -1600,19 +1600,12 @@ void board_nand_init(void)
struct pxa3xx_nand_host *host;
int ret;
- info = kzalloc(sizeof(*info) + (sizeof(struct mtd_info) +
- sizeof(*host)) *
- CONFIG_SYS_MAX_NAND_DEVICE, GFP_KERNEL);
+ info = kzalloc(sizeof(*info) +
+ sizeof(*host) * CONFIG_SYS_MAX_NAND_DEVICE,
+ GFP_KERNEL);
if (!info)
return;
- /*
- * If CONFIG_SYS_NAND_SELF_INIT is defined, each driver is responsible
- * for instantiating struct nand_chip, while drivers/mtd/nand/nand.c
- * still provides a "struct mtd_info nand_info" instance.
- */
- info->host[0]->mtd = &nand_info[0];
-
ret = pxa3xx_nand_probe(info);
if (ret)
return;
diff --git a/drivers/net/at91_emac.c b/drivers/net/at91_emac.c
index 26595929c51..91516001909 100644
--- a/drivers/net/at91_emac.c
+++ b/drivers/net/at91_emac.c
@@ -12,7 +12,7 @@
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/at91_emac.h>
-#include <asm/arch/at91_pmc.h>
+#include <asm/arch/clk.h>
#include <asm/arch/at91_pio.h>
#include <net.h>
#include <netdev.h>
@@ -321,7 +321,6 @@ static int at91emac_init(struct eth_device *netdev, bd_t *bd)
emac_device *dev;
at91_emac_t *emac;
at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIO;
- at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
emac = (at91_emac_t *) netdev->iobase;
dev = (emac_device *) netdev->priv;
@@ -347,7 +346,8 @@ static int at91emac_init(struct eth_device *netdev, bd_t *bd)
writel(value, &pio->piob.pdr);
writel(value, &pio->piob.bsr);
- writel(1 << ATMEL_ID_EMAC, &pmc->pcer);
+ at91_periph_clk_enable(ATMEL_ID_EMAC);
+
writel(readl(&emac->ctl) | AT91_EMAC_CTL_CSR, &emac->ctl);
/* Init Ethernet buffers */
@@ -452,10 +452,10 @@ static int at91emac_recv(struct eth_device *netdev)
static int at91emac_write_hwaddr(struct eth_device *netdev)
{
at91_emac_t *emac;
- at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
emac = (at91_emac_t *) netdev->iobase;
- writel(1 << ATMEL_ID_EMAC, &pmc->pcer);
+ at91_periph_clk_enable(ATMEL_ID_EMAC);
+
debug_cond(DEBUG_AT91EMAC,
"init MAC-ADDR %02x:%02x:%02x:%02x:%02x:%02x\n",
netdev->enetaddr[5], netdev->enetaddr[4], netdev->enetaddr[3],
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 92c3dcae3c9..b0304984028 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -459,11 +459,11 @@ static int davinci_eth_open(struct eth_device *dev, bd_t *bis)
/* Set DMA 8 TX / 8 RX Head pointers to 0 */
addr = &adap_emac->TX0HDP;
- for(cnt = 0; cnt < 16; cnt++)
+ for (cnt = 0; cnt < 8; cnt++)
writel(0, addr++);
addr = &adap_emac->RX0HDP;
- for(cnt = 0; cnt < 16; cnt++)
+ for (cnt = 0; cnt < 8; cnt++)
writel(0, addr++);
/* Clear Statistics (do this before setting MacControl register) */
@@ -692,8 +692,10 @@ static int davinci_eth_rcv_packet (struct eth_device *dev)
davinci_invalidate_rx_descs();
rx_curr_desc = emac_rx_active_head;
+ if (!rx_curr_desc)
+ return 0;
status = rx_curr_desc->pkt_flag_len;
- if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) {
+ if ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0) {
if (status & EMAC_CPPI_RX_ERROR_FRAME) {
/* Error in packet - discard it and requeue desc */
printf ("WARN: emac_rcv_pkt: Error in packet\n");
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 77b98c94c04..ca58f34f13b 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -591,11 +591,9 @@ static int designware_eth_probe(struct udevice *dev)
* or via a PCI bridge, fill in platdata before we probe the hardware.
*/
if (device_is_on_pci_bus(dev)) {
- pci_dev_t bdf = dm_pci_get_bdf(dev);
-
dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase);
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
- iobase = pci_mem_to_phys(bdf, iobase);
+ iobase = dm_pci_mem_to_phys(dev, iobase);
pdata->iobase = iobase;
pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index 70fc02ee5ca..196989b3864 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -38,8 +38,13 @@ tested on both gig copper and gig fiber boards
#define TOUT_LOOP 100000
+#ifdef CONFIG_DM_ETH
+#define virt_to_bus(devno, v) dm_pci_virt_to_mem(devno, (void *) (v))
+#define bus_to_phys(devno, a) dm_pci_mem_to_phys(devno, a)
+#else
#define virt_to_bus(devno, v) pci_virt_to_mem(devno, (void *) (v))
#define bus_to_phys(devno, a) pci_mem_to_phys(devno, a)
+#endif
#define E1000_DEFAULT_PCI_PBA 0x00000030
#define E1000_DEFAULT_PCIE_PBA 0x000a0026
@@ -1395,8 +1400,13 @@ e1000_reset_hw(struct e1000_hw *hw)
/* For 82542 (rev 2.0), disable MWI before issuing a device reset */
if (hw->mac_type == e1000_82542_rev2_0) {
DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
+#ifdef CONFIG_DM_ETH
+ dm_pci_write_config16(hw->pdev, PCI_COMMAND,
+ hw->pci_cmd_word & ~PCI_COMMAND_INVALIDATE);
+#else
pci_write_config_word(hw->pdev, PCI_COMMAND,
hw->pci_cmd_word & ~PCI_COMMAND_INVALIDATE);
+#endif
}
/* Clear interrupt mask to stop board from generating interrupts */
@@ -1469,7 +1479,11 @@ e1000_reset_hw(struct e1000_hw *hw)
/* If MWI was previously enabled, reenable it. */
if (hw->mac_type == e1000_82542_rev2_0) {
+#ifdef CONFIG_DM_ETH
+ dm_pci_write_config16(hw->pdev, PCI_COMMAND, hw->pci_cmd_word);
+#else
pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word);
+#endif
}
if (hw->mac_type != e1000_igb)
E1000_WRITE_REG(hw, PBA, pba);
@@ -1655,9 +1669,15 @@ e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6])
/* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
if (hw->mac_type == e1000_82542_rev2_0) {
DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
+#ifdef CONFIG_DM_ETH
+ dm_pci_write_config16(hw->pdev, PCI_COMMAND,
+ hw->
+ pci_cmd_word & ~PCI_COMMAND_INVALIDATE);
+#else
pci_write_config_word(hw->pdev, PCI_COMMAND,
hw->
pci_cmd_word & ~PCI_COMMAND_INVALIDATE);
+#endif
E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST);
E1000_WRITE_FLUSH(hw);
mdelay(5);
@@ -1673,7 +1693,11 @@ e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6])
E1000_WRITE_REG(hw, RCTL, 0);
E1000_WRITE_FLUSH(hw);
mdelay(1);
+#ifdef CONFIG_DM_ETH
+ dm_pci_write_config16(hw->pdev, PCI_COMMAND, hw->pci_cmd_word);
+#else
pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word);
+#endif
}
/* Zero out the Multicast HASH table */
@@ -1696,10 +1720,17 @@ e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6])
default:
/* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */
if (hw->bus_type == e1000_bus_type_pcix) {
+#ifdef CONFIG_DM_ETH
+ dm_pci_read_config16(hw->pdev, PCIX_COMMAND_REGISTER,
+ &pcix_cmd_word);
+ dm_pci_read_config16(hw->pdev, PCIX_STATUS_REGISTER_HI,
+ &pcix_stat_hi_word);
+#else
pci_read_config_word(hw->pdev, PCIX_COMMAND_REGISTER,
&pcix_cmd_word);
pci_read_config_word(hw->pdev, PCIX_STATUS_REGISTER_HI,
&pcix_stat_hi_word);
+#endif
cmd_mmrbc =
(pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >>
PCIX_COMMAND_MMRBC_SHIFT;
@@ -1711,8 +1742,13 @@ e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6])
if (cmd_mmrbc > stat_mmrbc) {
pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK;
pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT;
+#ifdef CONFIG_DM_ETH
+ dm_pci_write_config16(hw->pdev, PCIX_COMMAND_REGISTER,
+ pcix_cmd_word);
+#else
pci_write_config_word(hw->pdev, PCIX_COMMAND_REGISTER,
pcix_cmd_word);
+#endif
}
}
break;
@@ -4809,6 +4845,16 @@ e1000_sw_init(struct e1000_hw *hw)
int result;
/* PCI config space info */
+#ifdef CONFIG_DM_ETH
+ dm_pci_read_config16(hw->pdev, PCI_VENDOR_ID, &hw->vendor_id);
+ dm_pci_read_config16(hw->pdev, PCI_DEVICE_ID, &hw->device_id);
+ dm_pci_read_config16(hw->pdev, PCI_SUBSYSTEM_VENDOR_ID,
+ &hw->subsystem_vendor_id);
+ dm_pci_read_config16(hw->pdev, PCI_SUBSYSTEM_ID, &hw->subsystem_id);
+
+ dm_pci_read_config8(hw->pdev, PCI_REVISION_ID, &hw->revision_id);
+ dm_pci_read_config16(hw->pdev, PCI_COMMAND, &hw->pci_cmd_word);
+#else
pci_read_config_word(hw->pdev, PCI_VENDOR_ID, &hw->vendor_id);
pci_read_config_word(hw->pdev, PCI_DEVICE_ID, &hw->device_id);
pci_read_config_word(hw->pdev, PCI_SUBSYSTEM_VENDOR_ID,
@@ -4817,6 +4863,7 @@ e1000_sw_init(struct e1000_hw *hw)
pci_read_config_byte(hw->pdev, PCI_REVISION_ID, &hw->revision_id);
pci_read_config_word(hw->pdev, PCI_COMMAND, &hw->pci_cmd_word);
+#endif
/* identify the MAC */
result = e1000_set_mac_type(hw);
@@ -5232,25 +5279,46 @@ void e1000_get_bus_type(struct e1000_hw *hw)
static LIST_HEAD(e1000_hw_list);
#endif
+#ifdef CONFIG_DM_ETH
+static int e1000_init_one(struct e1000_hw *hw, int cardnum,
+ struct udevice *devno, unsigned char enetaddr[6])
+#else
static int e1000_init_one(struct e1000_hw *hw, int cardnum, pci_dev_t devno,
unsigned char enetaddr[6])
+#endif
{
u32 val;
/* Assign the passed-in values */
+#ifdef CONFIG_DM_ETH
hw->pdev = devno;
+#else
+ hw->pdev = devno;
+#endif
hw->cardnum = cardnum;
/* Print a debug message with the IO base address */
+#ifdef CONFIG_DM_ETH
+ dm_pci_read_config32(devno, PCI_BASE_ADDRESS_0, &val);
+#else
pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &val);
+#endif
E1000_DBG(hw, "iobase 0x%08x\n", val & 0xfffffff0);
/* Try to enable I/O accesses and bus-mastering */
val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+#ifdef CONFIG_DM_ETH
+ dm_pci_write_config32(devno, PCI_COMMAND, val);
+#else
pci_write_config_dword(devno, PCI_COMMAND, val);
+#endif
/* Make sure it worked */
+#ifdef CONFIG_DM_ETH
+ dm_pci_read_config32(devno, PCI_COMMAND, &val);
+#else
pci_read_config_dword(devno, PCI_COMMAND, &val);
+#endif
if (!(val & PCI_COMMAND_MEMORY)) {
E1000_ERR(hw, "Can't enable I/O memory\n");
return -ENOSPC;
@@ -5269,8 +5337,13 @@ static int e1000_init_one(struct e1000_hw *hw, int cardnum, pci_dev_t devno,
#ifndef CONFIG_E1000_NO_NVM
hw->eeprom_semaphore_present = true;
#endif
+#ifdef CONFIG_DM_ETH
+ hw->hw_addr = dm_pci_map_bar(devno, PCI_BASE_ADDRESS_0,
+ PCI_REGION_MEM);
+#else
hw->hw_addr = pci_map_bar(devno, PCI_BASE_ADDRESS_0,
PCI_REGION_MEM);
+#endif
hw->mac_type = e1000_undefined;
/* MAC and Phy settings */
@@ -5380,7 +5453,7 @@ e1000_initialize(bd_t * bis)
for (i = 0; (devno = pci_find_devices(e1000_supported, i)) >= 0; i++) {
/*
* These will never get freed due to errors, this allows us to
- * perform SPI EEPROM programming from U-boot, for example.
+ * perform SPI EEPROM programming from U-Boot, for example.
*/
struct eth_device *nic = malloc(sizeof(*nic));
struct e1000_hw *hw = malloc(sizeof(*hw));
@@ -5554,7 +5627,7 @@ static int e1000_eth_probe(struct udevice *dev)
hw->name = dev->name;
ret = e1000_init_one(hw, trailing_strtol(dev->name),
- dm_pci_get_bdf(dev), plat->enetaddr);
+ dev, plat->enetaddr);
if (ret < 0) {
printf(pr_fmt("failed to initialize card: %d\n"), ret);
return ret;
diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h
index e46edcd4e1d..fcb7df0d83f 100644
--- a/drivers/net/e1000.h
+++ b/drivers/net/e1000.h
@@ -1084,7 +1084,11 @@ struct e1000_hw {
#endif
unsigned int cardnum;
+#ifdef CONFIG_DM_ETH
+ struct udevice *pdev;
+#else
pci_dev_t pdev;
+#endif
uint8_t *hw_addr;
e1000_mac_type mac_type;
e1000_phy_type phy_type;
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c
index fdbd5841868..53c4966c330 100644
--- a/drivers/net/fsl-mc/mc.c
+++ b/drivers/net/fsl-mc/mc.c
@@ -455,7 +455,7 @@ int mc_init(u64 mc_fw_addr, u64 mc_dpc_addr)
/*
* Management Complex cores should be held at reset out of POR.
- * U-boot should be the first software to touch MC. To be safe,
+ * U-Boot should be the first software to touch MC. To be safe,
* we reset all cores again by setting GCR1 to 0. It doesn't do
* anything if they are held at reset. After we setup the firmware
* we kick off MC by deasserting the reset bit for core 0, and
diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c
index 209fae94a77..6b28df0f969 100644
--- a/drivers/net/keystone_net.c
+++ b/drivers/net/keystone_net.c
@@ -10,6 +10,8 @@
#include <command.h>
#include <console.h>
+#include <dm.h>
+
#include <net.h>
#include <phy.h>
#include <errno.h>
@@ -18,10 +20,15 @@
#include <asm/ti-common/keystone_nav.h>
#include <asm/ti-common/keystone_net.h>
#include <asm/ti-common/keystone_serdes.h>
+#include <asm/arch/psc_defs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+#ifndef CONFIG_DM_ETH
unsigned int emac_open;
static struct mii_dev *mdio_bus;
static unsigned int sys_has_mdio = 1;
+#endif
#ifdef KEYSTONE2_EMAC_GIG_ENABLE
#define emac_gigabit_enable(x) keystone2_eth_gigabit_enable(x)
@@ -36,40 +43,74 @@ static unsigned int sys_has_mdio = 1;
static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16);
+#ifndef CONFIG_DM_ETH
struct rx_buff_desc net_rx_buffs = {
.buff_ptr = rx_buffs,
.num_buffs = RX_BUFF_NUMS,
.buff_len = RX_BUFF_LEN,
.rx_flow = 22,
};
-
-#ifndef CONFIG_SOC_K2G
-static void keystone2_net_serdes_setup(void);
#endif
-int keystone2_eth_read_mac_addr(struct eth_device *dev)
-{
- struct eth_priv_t *eth_priv;
- u32 maca = 0;
- u32 macb = 0;
+#ifdef CONFIG_DM_ETH
- eth_priv = (struct eth_priv_t *)dev->priv;
+enum link_type {
+ LINK_TYPE_MAC_TO_MAC_AUTO = 0,
+ LINK_TYPE_MAC_TO_PHY_MODE = 1,
+ LINK_TYPE_MAC_TO_MAC_FORCED_MODE = 2,
+ LINK_TYPE_MAC_TO_FIBRE_MODE = 3,
+ LINK_TYPE_MAC_TO_PHY_NO_MDIO_MODE = 4,
+ LINK_TYPE_10G_MAC_TO_PHY_MODE = 10,
+ LINK_TYPE_10G_MAC_TO_MAC_FORCED_MODE = 11,
+};
- /* Read the e-fuse mac address */
- if (eth_priv->slave_port == 1) {
- maca = __raw_readl(MAC_ID_BASE_ADDR);
- macb = __raw_readl(MAC_ID_BASE_ADDR + 4);
- }
+#define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \
+ ((mac)[2] << 16) | ((mac)[3] << 24))
+#define mac_lo(mac) (((mac)[4] << 0) | ((mac)[5] << 8))
- dev->enetaddr[0] = (macb >> 8) & 0xff;
- dev->enetaddr[1] = (macb >> 0) & 0xff;
- dev->enetaddr[2] = (maca >> 24) & 0xff;
- dev->enetaddr[3] = (maca >> 16) & 0xff;
- dev->enetaddr[4] = (maca >> 8) & 0xff;
- dev->enetaddr[5] = (maca >> 0) & 0xff;
+#ifdef CONFIG_KSNET_NETCP_V1_0
- return 0;
-}
+#define EMAC_EMACSW_BASE_OFS 0x90800
+#define EMAC_EMACSW_PORT_BASE_OFS (EMAC_EMACSW_BASE_OFS + 0x60)
+
+/* CPSW Switch slave registers */
+#define CPGMACSL_REG_SA_LO 0x10
+#define CPGMACSL_REG_SA_HI 0x14
+
+#define DEVICE_EMACSW_BASE(base, x) ((base) + EMAC_EMACSW_PORT_BASE_OFS + \
+ (x) * 0x30)
+
+#elif defined CONFIG_KSNET_NETCP_V1_5
+
+#define EMAC_EMACSW_PORT_BASE_OFS 0x222000
+
+/* CPSW Switch slave registers */
+#define CPGMACSL_REG_SA_LO 0x308
+#define CPGMACSL_REG_SA_HI 0x30c
+
+#define DEVICE_EMACSW_BASE(base, x) ((base) + EMAC_EMACSW_PORT_BASE_OFS + \
+ (x) * 0x1000)
+
+#endif
+
+
+struct ks2_eth_priv {
+ struct udevice *dev;
+ struct phy_device *phydev;
+ struct mii_dev *mdio_bus;
+ int phy_addr;
+ phy_interface_t phy_if;
+ int sgmii_link_type;
+ void *mdio_base;
+ struct rx_buff_desc net_rx_buffs;
+ struct pktdma_cfg *netcp_pktdma;
+ void *hd;
+ int slave_port;
+ enum link_type link_type;
+ bool emac_open;
+ bool has_mdio;
+};
+#endif
/* MDIO */
@@ -140,6 +181,7 @@ static int keystone2_mdio_write(struct mii_dev *bus,
return 0;
}
+#ifndef CONFIG_DM_ETH
static void __attribute__((unused))
keystone2_eth_gigabit_enable(struct eth_device *dev)
{
@@ -163,6 +205,31 @@ static void __attribute__((unused))
EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE,
DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL);
}
+#else
+static void __attribute__((unused))
+ keystone2_eth_gigabit_enable(struct udevice *dev)
+{
+ struct ks2_eth_priv *priv = dev_get_priv(dev);
+ u_int16_t data;
+
+ if (priv->has_mdio) {
+ data = keystone2_mdio_read(priv->mdio_bus, priv->phy_addr,
+ MDIO_DEVAD_NONE, 0);
+ /* speed selection MSB */
+ if (!(data & (1 << 6)))
+ return;
+ }
+
+ /*
+ * Check if link detected is giga-bit
+ * If Gigabit mode detected, enable gigbit in MAC
+ */
+ writel(readl(DEVICE_EMACSL_BASE(priv->slave_port - 1) +
+ CPGMACSL_REG_CTL) |
+ EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE,
+ DEVICE_EMACSL_BASE(priv->slave_port - 1) + CPGMACSL_REG_CTL);
+}
+#endif
#ifdef CONFIG_SOC_K2G
int keystone_rgmii_config(struct phy_device *phy_dev)
@@ -401,6 +468,58 @@ int ethss_stop(void)
return 0;
}
+struct ks2_serdes ks2_serdes_sgmii_156p25mhz = {
+ .clk = SERDES_CLOCK_156P25M,
+ .rate = SERDES_RATE_5G,
+ .rate_mode = SERDES_QUARTER_RATE,
+ .intf = SERDES_PHY_SGMII,
+ .loopback = 0,
+};
+
+#ifndef CONFIG_SOC_K2G
+static void keystone2_net_serdes_setup(void)
+{
+ ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII_BASE,
+ &ks2_serdes_sgmii_156p25mhz,
+ CONFIG_KSNET_SERDES_LANES_PER_SGMII);
+
+#if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L)
+ ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE,
+ &ks2_serdes_sgmii_156p25mhz,
+ CONFIG_KSNET_SERDES_LANES_PER_SGMII);
+#endif
+
+ /* wait till setup */
+ udelay(5000);
+}
+#endif
+
+#ifndef CONFIG_DM_ETH
+
+int keystone2_eth_read_mac_addr(struct eth_device *dev)
+{
+ struct eth_priv_t *eth_priv;
+ u32 maca = 0;
+ u32 macb = 0;
+
+ eth_priv = (struct eth_priv_t *)dev->priv;
+
+ /* Read the e-fuse mac address */
+ if (eth_priv->slave_port == 1) {
+ maca = __raw_readl(MAC_ID_BASE_ADDR);
+ macb = __raw_readl(MAC_ID_BASE_ADDR + 4);
+ }
+
+ dev->enetaddr[0] = (macb >> 8) & 0xff;
+ dev->enetaddr[1] = (macb >> 0) & 0xff;
+ dev->enetaddr[2] = (maca >> 24) & 0xff;
+ dev->enetaddr[3] = (maca >> 16) & 0xff;
+ dev->enetaddr[4] = (maca >> 8) & 0xff;
+ dev->enetaddr[5] = (maca >> 0) & 0xff;
+
+ return 0;
+}
+
int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num)
{
if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE)
@@ -556,6 +675,7 @@ int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
int res;
struct eth_device *dev;
struct phy_device *phy_dev;
+ struct mdio_regs *adap_mdio = (struct mdio_regs *)EMAC_MDIO_BASE_ADDR;
dev = malloc(sizeof(struct eth_device));
if (dev == NULL)
@@ -612,28 +732,301 @@ int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
return 0;
}
-struct ks2_serdes ks2_serdes_sgmii_156p25mhz = {
- .clk = SERDES_CLOCK_156P25M,
- .rate = SERDES_RATE_5G,
- .rate_mode = SERDES_QUARTER_RATE,
- .intf = SERDES_PHY_SGMII,
- .loopback = 0,
-};
+#else
-#ifndef CONFIG_SOC_K2G
-static void keystone2_net_serdes_setup(void)
+static int ks2_eth_start(struct udevice *dev)
{
- ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII_BASE,
- &ks2_serdes_sgmii_156p25mhz,
- CONFIG_KSNET_SERDES_LANES_PER_SGMII);
+ struct ks2_eth_priv *priv = dev_get_priv(dev);
-#if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L)
- ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE,
- &ks2_serdes_sgmii_156p25mhz,
- CONFIG_KSNET_SERDES_LANES_PER_SGMII);
+#ifdef CONFIG_SOC_K2G
+ keystone_rgmii_config(priv->phydev);
+#else
+ keystone_sgmii_config(priv->phydev, priv->slave_port - 1,
+ priv->sgmii_link_type);
#endif
- /* wait till setup */
- udelay(5000);
+ udelay(10000);
+
+ /* On chip switch configuration */
+ ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE);
+
+ qm_init();
+
+ if (ksnav_init(priv->netcp_pktdma, &priv->net_rx_buffs)) {
+ error("ksnav_init failed\n");
+ goto err_knav_init;
+ }
+
+ /*
+ * Streaming switch configuration. If not present this
+ * statement is defined to void in target.h.
+ * If present this is usually defined to a series of register writes
+ */
+ hw_config_streaming_switch();
+
+ if (priv->has_mdio) {
+ phy_startup(priv->phydev);
+ if (priv->phydev->link == 0) {
+ error("phy startup failed\n");
+ goto err_phy_start;
+ }
+ }
+
+ emac_gigabit_enable(dev);
+
+ ethss_start();
+
+ priv->emac_open = true;
+
+ return 0;
+
+err_phy_start:
+ ksnav_close(priv->netcp_pktdma);
+err_knav_init:
+ qm_close();
+
+ return -EFAULT;
+}
+
+static int ks2_eth_send(struct udevice *dev, void *packet, int length)
+{
+ struct ks2_eth_priv *priv = dev_get_priv(dev);
+
+ genphy_update_link(priv->phydev);
+ if (priv->phydev->link == 0)
+ return -1;
+
+ if (length < EMAC_MIN_ETHERNET_PKT_SIZE)
+ length = EMAC_MIN_ETHERNET_PKT_SIZE;
+
+ return ksnav_send(priv->netcp_pktdma, (u32 *)packet,
+ length, (priv->slave_port) << 16);
+}
+
+static int ks2_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+ struct ks2_eth_priv *priv = dev_get_priv(dev);
+ int pkt_size;
+ u32 *pkt = NULL;
+
+ priv->hd = ksnav_recv(priv->netcp_pktdma, &pkt, &pkt_size);
+ if (priv->hd == NULL)
+ return -EAGAIN;
+
+ *packetp = (uchar *)pkt;
+
+ return pkt_size;
+}
+
+static int ks2_eth_free_pkt(struct udevice *dev, uchar *packet,
+ int length)
+{
+ struct ks2_eth_priv *priv = dev_get_priv(dev);
+
+ ksnav_release_rxhd(priv->netcp_pktdma, priv->hd);
+
+ return 0;
+}
+
+static void ks2_eth_stop(struct udevice *dev)
+{
+ struct ks2_eth_priv *priv = dev_get_priv(dev);
+
+ if (!priv->emac_open)
+ return;
+ ethss_stop();
+
+ ksnav_close(priv->netcp_pktdma);
+ qm_close();
+ phy_shutdown(priv->phydev);
+ priv->emac_open = false;
+}
+
+int ks2_eth_read_rom_hwaddr(struct udevice *dev)
+{
+ struct ks2_eth_priv *priv = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ u32 maca = 0;
+ u32 macb = 0;
+
+ /* Read the e-fuse mac address */
+ if (priv->slave_port == 1) {
+ maca = __raw_readl(MAC_ID_BASE_ADDR);
+ macb = __raw_readl(MAC_ID_BASE_ADDR + 4);
+ }
+
+ pdata->enetaddr[0] = (macb >> 8) & 0xff;
+ pdata->enetaddr[1] = (macb >> 0) & 0xff;
+ pdata->enetaddr[2] = (maca >> 24) & 0xff;
+ pdata->enetaddr[3] = (maca >> 16) & 0xff;
+ pdata->enetaddr[4] = (maca >> 8) & 0xff;
+ pdata->enetaddr[5] = (maca >> 0) & 0xff;
+
+ return 0;
+}
+
+int ks2_eth_write_hwaddr(struct udevice *dev)
+{
+ struct ks2_eth_priv *priv = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+
+ writel(mac_hi(pdata->enetaddr),
+ DEVICE_EMACSW_BASE(pdata->iobase, priv->slave_port - 1) +
+ CPGMACSL_REG_SA_HI);
+ writel(mac_lo(pdata->enetaddr),
+ DEVICE_EMACSW_BASE(pdata->iobase, priv->slave_port - 1) +
+ CPGMACSL_REG_SA_LO);
+
+ return 0;
+}
+
+static int ks2_eth_probe(struct udevice *dev)
+{
+ struct ks2_eth_priv *priv = dev_get_priv(dev);
+ struct mii_dev *mdio_bus;
+ int ret;
+
+ priv->dev = dev;
+
+ /* These clock enables has to be moved to common location */
+ if (cpu_is_k2g())
+ writel(KS2_ETHERNET_RGMII, KS2_ETHERNET_CFG);
+
+ /* By default, select PA PLL clock as PA clock source */
+#ifndef CONFIG_SOC_K2G
+ if (psc_enable_module(KS2_LPSC_PA))
+ return -EACCES;
+#endif
+ if (psc_enable_module(KS2_LPSC_CPGMAC))
+ return -EACCES;
+ if (psc_enable_module(KS2_LPSC_CRYPTO))
+ return -EACCES;
+
+ if (cpu_is_k2e() || cpu_is_k2l())
+ pll_pa_clk_sel();
+
+
+ priv->net_rx_buffs.buff_ptr = rx_buffs,
+ priv->net_rx_buffs.num_buffs = RX_BUFF_NUMS,
+ priv->net_rx_buffs.buff_len = RX_BUFF_LEN,
+
+ /* Register MDIO bus */
+ mdio_bus = mdio_alloc();
+ if (!mdio_bus) {
+ error("MDIO alloc failed\n");
+ return -ENOMEM;
+ }
+ priv->mdio_bus = mdio_bus;
+ mdio_bus->read = keystone2_mdio_read;
+ mdio_bus->write = keystone2_mdio_write;
+ mdio_bus->reset = keystone2_mdio_reset;
+ mdio_bus->priv = priv->mdio_base;
+ sprintf(mdio_bus->name, "ethernet-mdio");
+
+ ret = mdio_register(mdio_bus);
+ if (ret) {
+ error("MDIO bus register failed\n");
+ return ret;
+ }
+
+#ifndef CONFIG_SOC_K2G
+ keystone2_net_serdes_setup();
+#endif
+
+ priv->netcp_pktdma = &netcp_pktdma;
+
+ priv->phydev = phy_connect(mdio_bus, priv->phy_addr, dev, priv->phy_if);
+ phy_config(priv->phydev);
+
+ return 0;
}
+
+int ks2_eth_remove(struct udevice *dev)
+{
+ struct ks2_eth_priv *priv = dev_get_priv(dev);
+
+ free(priv->phydev);
+ mdio_unregister(priv->mdio_bus);
+ mdio_free(priv->mdio_bus);
+
+ return 0;
+}
+
+static const struct eth_ops ks2_eth_ops = {
+ .start = ks2_eth_start,
+ .send = ks2_eth_send,
+ .recv = ks2_eth_recv,
+ .free_pkt = ks2_eth_free_pkt,
+ .stop = ks2_eth_stop,
+ .read_rom_hwaddr = ks2_eth_read_rom_hwaddr,
+ .write_hwaddr = ks2_eth_write_hwaddr,
+};
+
+
+static int ks2_eth_ofdata_to_platdata(struct udevice *dev)
+{
+ struct ks2_eth_priv *priv = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ const void *fdt = gd->fdt_blob;
+ int interfaces;
+ int interface_0;
+ int netcp_gbe_0;
+ int phy;
+ int mdio;
+ u32 dma_channel[6];
+
+ interfaces = fdt_subnode_offset(fdt, dev->of_offset,
+ "netcp-interfaces");
+ interface_0 = fdt_subnode_offset(fdt, interfaces, "interface-0");
+
+ netcp_gbe_0 = fdtdec_lookup_phandle(fdt, interface_0, "netcp-gbe");
+ priv->link_type = fdtdec_get_int(fdt, netcp_gbe_0,
+ "link-interface", -1);
+ priv->slave_port = fdtdec_get_int(fdt, netcp_gbe_0, "slave-port", -1);
+ /* U-Boot slave port number starts with 1 instead of 0 */
+ priv->slave_port += 1;
+
+ phy = fdtdec_lookup_phandle(fdt, netcp_gbe_0, "phy-handle");
+ priv->phy_addr = fdtdec_get_int(fdt, phy, "reg", -1);
+
+ mdio = fdt_parent_offset(fdt, phy);
+ if (mdio < 0) {
+ error("mdio dt not found\n");
+ return -ENODEV;
+ }
+ priv->mdio_base = (void *)fdtdec_get_addr(fdt, mdio, "reg");
+
+ if (priv->link_type == LINK_TYPE_MAC_TO_PHY_MODE) {
+ priv->phy_if = PHY_INTERFACE_MODE_SGMII;
+ pdata->phy_interface = priv->phy_if;
+ priv->sgmii_link_type = SGMII_LINK_MAC_PHY;
+ priv->has_mdio = true;
+ }
+ pdata->iobase = dev_get_addr(dev);
+
+ fdtdec_get_int_array(fdt, dev->of_offset, "ti,navigator-dmas",
+ dma_channel, 6);
+ priv->net_rx_buffs.rx_flow = dma_channel[1];
+
+ return 0;
+}
+
+static const struct udevice_id ks2_eth_ids[] = {
+ { .compatible = "ti,netcp-1.0" },
+ { }
+};
+
+
+U_BOOT_DRIVER(eth_ks2) = {
+ .name = "eth_ks2",
+ .id = UCLASS_ETH,
+ .of_match = ks2_eth_ids,
+ .ofdata_to_platdata = ks2_eth_ofdata_to_platdata,
+ .probe = ks2_eth_probe,
+ .remove = ks2_eth_remove,
+ .ops = &ks2_eth_ops,
+ .priv_auto_alloc_size = sizeof(struct ks2_eth_priv),
+ .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
#endif
diff --git a/drivers/net/lan91c96.c b/drivers/net/lan91c96.c
index c4dd01ec2aa..3526876d141 100644
--- a/drivers/net/lan91c96.c
+++ b/drivers/net/lan91c96.c
@@ -1,7 +1,7 @@
/*------------------------------------------------------------------------
* lan91c96.c
* This is a driver for SMSC's LAN91C96 single-chip Ethernet device, based
- * on the SMC91111 driver from U-boot.
+ * on the SMC91111 driver from U-Boot.
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
diff --git a/drivers/net/ne2000_base.c b/drivers/net/ne2000_base.c
index 887cfd957b3..71d133cc8f1 100644
--- a/drivers/net/ne2000_base.c
+++ b/drivers/net/ne2000_base.c
@@ -650,7 +650,7 @@ dp83902a_poll(void)
}
-/* U-boot specific routines */
+/* U-Boot specific routines */
static u8 *pbuf = NULL;
static int pkey = -1;
diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c
index 56d29d47af7..137818b3907 100644
--- a/drivers/net/pch_gbe.c
+++ b/drivers/net/pch_gbe.c
@@ -117,15 +117,15 @@ static void pch_gbe_rx_descs_init(struct udevice *dev)
memset(rx_desc, 0, sizeof(struct pch_gbe_rx_desc) * PCH_GBE_DESC_NUM);
for (i = 0; i < PCH_GBE_DESC_NUM; i++)
- rx_desc->buffer_addr = pci_phys_to_mem(priv->bdf,
+ rx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev,
(u32)(priv->rx_buff[i]));
- writel(pci_phys_to_mem(priv->bdf, (u32)rx_desc),
+ writel(dm_pci_phys_to_mem(priv->dev, (u32)rx_desc),
&mac_regs->rx_dsc_base);
writel(sizeof(struct pch_gbe_rx_desc) * (PCH_GBE_DESC_NUM - 1),
&mac_regs->rx_dsc_size);
- writel(pci_phys_to_mem(priv->bdf, (u32)(rx_desc + 1)),
+ writel(dm_pci_phys_to_mem(priv->dev, (u32)(rx_desc + 1)),
&mac_regs->rx_dsc_sw_p);
}
@@ -137,11 +137,11 @@ static void pch_gbe_tx_descs_init(struct udevice *dev)
memset(tx_desc, 0, sizeof(struct pch_gbe_tx_desc) * PCH_GBE_DESC_NUM);
- writel(pci_phys_to_mem(priv->bdf, (u32)tx_desc),
+ writel(dm_pci_phys_to_mem(priv->dev, (u32)tx_desc),
&mac_regs->tx_dsc_base);
writel(sizeof(struct pch_gbe_tx_desc) * (PCH_GBE_DESC_NUM - 1),
&mac_regs->tx_dsc_size);
- writel(pci_phys_to_mem(priv->bdf, (u32)(tx_desc + 1)),
+ writel(dm_pci_phys_to_mem(priv->dev, (u32)(tx_desc + 1)),
&mac_regs->tx_dsc_sw_p);
}
@@ -251,7 +251,7 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length)
if (length < 64)
frame_ctrl |= PCH_GBE_TXD_CTRL_APAD;
- tx_desc->buffer_addr = pci_phys_to_mem(priv->bdf, (u32)packet);
+ tx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev, (u32)packet);
tx_desc->length = length;
tx_desc->tx_words_eob = length + 3;
tx_desc->tx_frame_ctrl = frame_ctrl;
@@ -262,7 +262,7 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length)
if (++priv->tx_idx >= PCH_GBE_DESC_NUM)
priv->tx_idx = 0;
- writel(pci_phys_to_mem(priv->bdf, (u32)(tx_head + priv->tx_idx)),
+ writel(dm_pci_phys_to_mem(priv->dev, (u32)(tx_head + priv->tx_idx)),
&mac_regs->tx_dsc_sw_p);
start = get_timer(0);
@@ -294,7 +294,7 @@ static int pch_gbe_recv(struct udevice *dev, int flags, uchar **packetp)
if ((u32)rx_desc == hw_desc)
return -EAGAIN;
- buffer_addr = pci_mem_to_phys(priv->bdf, rx_desc->buffer_addr);
+ buffer_addr = dm_pci_mem_to_phys(priv->dev, rx_desc->buffer_addr);
*packetp = (uchar *)buffer_addr;
length = rx_desc->rx_words_eob - 3 - ETH_FCS_LEN;
@@ -315,7 +315,7 @@ static int pch_gbe_free_pkt(struct udevice *dev, uchar *packet, int length)
if (++rx_swp >= PCH_GBE_DESC_NUM)
rx_swp = 0;
- writel(pci_phys_to_mem(priv->bdf, (u32)(rx_head + rx_swp)),
+ writel(dm_pci_phys_to_mem(priv->dev, (u32)(rx_head + rx_swp)),
&mac_regs->rx_dsc_sw_p);
return 0;
@@ -421,11 +421,8 @@ int pch_gbe_probe(struct udevice *dev)
{
struct pch_gbe_priv *priv;
struct eth_pdata *plat = dev_get_platdata(dev);
- pci_dev_t devno;
u32 iobase;
- devno = dm_pci_get_bdf(dev);
-
/*
* The priv structure contains the descriptors and frame buffers which
* need a strict buswidth alignment (64 bytes). This is guaranteed by
@@ -433,11 +430,11 @@ int pch_gbe_probe(struct udevice *dev)
*/
priv = dev_get_priv(dev);
- priv->bdf = devno;
+ priv->dev = dev;
- pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase);
+ dm_pci_read_config32(dev, PCI_BASE_ADDRESS_1, &iobase);
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
- iobase = pci_mem_to_phys(devno, iobase);
+ iobase = dm_pci_mem_to_phys(dev, iobase);
plat->iobase = iobase;
priv->mac_regs = (struct pch_gbe_regs *)iobase;
diff --git a/drivers/net/pch_gbe.h b/drivers/net/pch_gbe.h
index afcb03dd36a..0ea0c73a4fb 100644
--- a/drivers/net/pch_gbe.h
+++ b/drivers/net/pch_gbe.h
@@ -290,7 +290,7 @@ struct pch_gbe_priv {
struct phy_device *phydev;
struct mii_dev *bus;
struct pch_gbe_regs *mac_regs;
- pci_dev_t bdf;
+ struct udevice *dev;
int rx_idx;
int tx_idx;
};
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index eab15585c31..b8b1157a0a4 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -172,7 +172,6 @@ static int m88e1011s_startup(struct phy_device *phydev)
static int m88e1111s_config(struct phy_device *phydev)
{
int reg;
- int timeout;
if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
(phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
@@ -236,16 +235,7 @@ static int m88e1111s_config(struct phy_device *phydev)
MIIM_88E1111_PHY_EXT_SR, reg);
/* soft reset */
- timeout = 1000;
- phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
- udelay(1000);
- reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
- while ((reg & BMCR_RESET) && --timeout) {
- udelay(1000);
- reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
- }
- if (!timeout)
- printf("%s: phy soft reset timeout\n", __func__);
+ phy_reset(phydev);
reg = phy_read(phydev, MDIO_DEVAD_NONE,
MIIM_88E1111_PHY_EXT_SR);
@@ -258,20 +248,10 @@ static int m88e1111s_config(struct phy_device *phydev)
}
/* soft reset */
- timeout = 1000;
- phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
- udelay(1000);
- reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
- while ((reg & BMCR_RESET) && --timeout) {
- udelay(1000);
- reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
- }
- if (!timeout)
- printf("%s: phy soft reset timeout\n", __func__);
+ phy_reset(phydev);
genphy_config_aneg(phydev);
-
- phy_reset(phydev);
+ genphy_restart_aneg(phydev);
return 0;
}
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index c3da1606dc5..8fcf737cb8f 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -279,7 +279,8 @@ static int ksz90x1_of_config_group(struct phy_device *phydev,
#define CTRL1000_CONFIG_MASTER (1 << 11)
#define CTRL1000_MANUAL_CONFIG (1 << 12)
-#ifdef CONFIG_DM_ETH
+#if defined(CONFIG_DM_ETH) && (defined(CONFIG_PHY_MICREL_KSZ9021) || \
+ defined(CONFIG_PHY_MICREL_KSZ9031))
static const struct ksz90x1_reg_field ksz9021_clk_grp[] = {
{ "txen-skew-ps", 4, 0, 0x7 }, { "txc-skew-ps", 4, 4, 0x7 },
{ "rxdv-skew-ps", 4, 8, 0x7 }, { "rxc-skew-ps", 4, 12, 0x7 },
@@ -385,7 +386,8 @@ static struct phy_driver ksz9021_driver = {
#define MII_KSZ9031_MMD_ACCES_CTRL 0x0d
#define MII_KSZ9031_MMD_REG_DATA 0x0e
-#ifdef CONFIG_DM_ETH
+#if defined(CONFIG_DM_ETH) && (defined(CONFIG_PHY_MICREL_KSZ9021) || \
+ defined(CONFIG_PHY_MICREL_KSZ9031))
static const struct ksz90x1_reg_field ksz9031_ctl_grp[] =
{ { "txen-skew-ps", 4, 0, 0x7 }, { "rxdv-skew-ps", 4, 4, 0x7 } };
static const struct ksz90x1_reg_field ksz9031_clk_grp[] =
diff --git a/drivers/pch/pch-uclass.c b/drivers/pch/pch-uclass.c
index 4579ed12f65..7216660a24c 100644
--- a/drivers/pch/pch-uclass.c
+++ b/drivers/pch/pch-uclass.c
@@ -12,35 +12,47 @@
DECLARE_GLOBAL_DATA_PTR;
-int pch_get_sbase(struct udevice *dev, ulong *sbasep)
+int pch_get_spi_base(struct udevice *dev, ulong *sbasep)
{
struct pch_ops *ops = pch_get_ops(dev);
*sbasep = 0;
- if (!ops->get_sbase)
+ if (!ops->get_spi_base)
return -ENOSYS;
- return ops->get_sbase(dev, sbasep);
+ return ops->get_spi_base(dev, sbasep);
}
-enum pch_version pch_get_version(struct udevice *dev)
+int pch_set_spi_protect(struct udevice *dev, bool protect)
{
struct pch_ops *ops = pch_get_ops(dev);
- if (!ops->get_version)
+ if (!ops->set_spi_protect)
return -ENOSYS;
- return ops->get_version(dev);
+ return ops->set_spi_protect(dev, protect);
}
-int pch_set_spi_protect(struct udevice *dev, bool protect)
+int pch_get_gpio_base(struct udevice *dev, u32 *gbasep)
{
struct pch_ops *ops = pch_get_ops(dev);
- if (!ops->set_spi_protect)
+ *gbasep = 0;
+ if (!ops->get_gpio_base)
return -ENOSYS;
- return ops->set_spi_protect(dev, protect);
+ return ops->get_gpio_base(dev, gbasep);
+}
+
+int pch_get_io_base(struct udevice *dev, u32 *iobasep)
+{
+ struct pch_ops *ops = pch_get_ops(dev);
+
+ *iobasep = 0;
+ if (!ops->get_io_base)
+ return -ENOSYS;
+
+ return ops->get_io_base(dev, iobasep);
}
static int pch_uclass_post_bind(struct udevice *bus)
diff --git a/drivers/pch/pch7.c b/drivers/pch/pch7.c
index ef724221c2e..302c9299ee0 100644
--- a/drivers/pch/pch7.c
+++ b/drivers/pch/pch7.c
@@ -8,9 +8,10 @@
#include <dm.h>
#include <pch.h>
+#define GPIO_BASE 0x44
#define BIOS_CTRL 0xd8
-static int pch7_get_sbase(struct udevice *dev, ulong *sbasep)
+static int pch7_get_spi_base(struct udevice *dev, ulong *sbasep)
{
u32 rcba;
@@ -22,11 +23,6 @@ static int pch7_get_sbase(struct udevice *dev, ulong *sbasep)
return 0;
}
-static enum pch_version pch7_get_version(struct udevice *dev)
-{
- return PCHV_7;
-}
-
static int pch7_set_spi_protect(struct udevice *dev, bool protect)
{
uint8_t bios_cntl;
@@ -42,10 +38,41 @@ static int pch7_set_spi_protect(struct udevice *dev, bool protect)
return 0;
}
+static int pch7_get_gpio_base(struct udevice *dev, u32 *gbasep)
+{
+ u32 base;
+
+ /*
+ * GPIO_BASE moved to its current offset with ICH6, but prior to
+ * that it was unused (or undocumented). Check that it looks
+ * okay: not all ones or zeros.
+ *
+ * Note we don't need check bit0 here, because the Tunnel Creek
+ * GPIO base address register bit0 is reserved (read returns 0),
+ * while on the Ivybridge the bit0 is used to indicate it is an
+ * I/O space.
+ */
+ dm_pci_read_config32(dev, GPIO_BASE, &base);
+ if (base == 0x00000000 || base == 0xffffffff) {
+ debug("%s: unexpected BASE value\n", __func__);
+ return -ENODEV;
+ }
+
+ /*
+ * Okay, I guess we're looking at the right device. The actual
+ * GPIO registers are in the PCI device's I/O space, starting
+ * at the offset that we just read. Bit 0 indicates that it's
+ * an I/O address, not a memory address, so mask that off.
+ */
+ *gbasep = base & 1 ? base & ~3 : base & ~15;
+
+ return 0;
+}
+
static const struct pch_ops pch7_ops = {
- .get_sbase = pch7_get_sbase,
- .get_version = pch7_get_version,
+ .get_spi_base = pch7_get_spi_base,
.set_spi_protect = pch7_set_spi_protect,
+ .get_gpio_base = pch7_get_gpio_base,
};
static const struct udevice_id pch7_ids[] = {
diff --git a/drivers/pch/pch9.c b/drivers/pch/pch9.c
index 529cb023e2b..910eb61f482 100644
--- a/drivers/pch/pch9.c
+++ b/drivers/pch/pch9.c
@@ -8,9 +8,11 @@
#include <dm.h>
#include <pch.h>
+#define GPIO_BASE 0x48
+#define IO_BASE 0x4c
#define SBASE_ADDR 0x54
-static int pch9_get_sbase(struct udevice *dev, ulong *sbasep)
+static int pch9_get_spi_base(struct udevice *dev, ulong *sbasep)
{
uint32_t sbase_addr;
@@ -20,14 +22,56 @@ static int pch9_get_sbase(struct udevice *dev, ulong *sbasep)
return 0;
}
-static enum pch_version pch9_get_version(struct udevice *dev)
+static int pch9_get_gpio_base(struct udevice *dev, u32 *gbasep)
{
- return PCHV_9;
+ u32 base;
+
+ /*
+ * GPIO_BASE moved to its current offset with ICH6, but prior to
+ * that it was unused (or undocumented). Check that it looks
+ * okay: not all ones or zeros.
+ *
+ * Note we don't need check bit0 here, because the Tunnel Creek
+ * GPIO base address register bit0 is reserved (read returns 0),
+ * while on the Ivybridge the bit0 is used to indicate it is an
+ * I/O space.
+ */
+ dm_pci_read_config32(dev, GPIO_BASE, &base);
+ if (base == 0x00000000 || base == 0xffffffff) {
+ debug("%s: unexpected BASE value\n", __func__);
+ return -ENODEV;
+ }
+
+ /*
+ * Okay, I guess we're looking at the right device. The actual
+ * GPIO registers are in the PCI device's I/O space, starting
+ * at the offset that we just read. Bit 0 indicates that it's
+ * an I/O address, not a memory address, so mask that off.
+ */
+ *gbasep = base & 1 ? base & ~3 : base & ~15;
+
+ return 0;
+}
+
+static int pch9_get_io_base(struct udevice *dev, u32 *iobasep)
+{
+ u32 base;
+
+ dm_pci_read_config32(dev, IO_BASE, &base);
+ if (base == 0x00000000 || base == 0xffffffff) {
+ debug("%s: unexpected BASE value\n", __func__);
+ return -ENODEV;
+ }
+
+ *iobasep = base & 1 ? base & ~3 : base & ~15;
+
+ return 0;
}
static const struct pch_ops pch9_ops = {
- .get_sbase = pch9_get_sbase,
- .get_version = pch9_get_version,
+ .get_spi_base = pch9_get_spi_base,
+ .get_gpio_base = pch9_get_gpio_base,
+ .get_io_base = pch9_get_io_base,
};
static const struct udevice_id pch9_ids[] = {
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index cd8f3570f06..6f0d61e7ab2 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -17,3 +17,12 @@ config PWM_ROCKCHIP
programmable period and duty cycle. A 32-bit counter is used.
Various options provided in the hardware (such as capture mode and
continuous/single-shot) are not supported by the driver.
+
+config PWM_TEGRA
+ bool "Enable support for the Tegra PWM"
+ depends on DM_PWM
+ help
+ This PWM is found on Tegra 20 and other Nvidia SoCs. It supports
+ four channels with a programmable period and duty cycle. Only a
+ 32KHz clock is supported by the driver but the duty cycle is
+ configurable.
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index b6d8c166048..fd414b1893e 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -13,3 +13,6 @@
obj-$(CONFIG_DM_PWM) += pwm-uclass.o
obj-$(CONFIG_PWM_ROCKCHIP) += rk_pwm.o
obj-$(CONFIG_PWM_IMX) += pwm-imx.o pwm-imx-util.o
+ifdef CONFIG_DM_PWM
+obj-$(CONFIG_PWM_TEGRA) += tegra_pwm.o
+endif
diff --git a/drivers/pwm/tegra_pwm.c b/drivers/pwm/tegra_pwm.c
new file mode 100644
index 00000000000..10e1fdc9b56
--- /dev/null
+++ b/drivers/pwm/tegra_pwm.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pwm.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pwm.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct tegra_pwm_priv {
+ struct pwm_ctlr *regs;
+};
+
+static int tegra_pwm_set_config(struct udevice *dev, uint channel,
+ uint period_ns, uint duty_ns)
+{
+ struct tegra_pwm_priv *priv = dev_get_priv(dev);
+ struct pwm_ctlr *regs = priv->regs;
+ uint pulse_width;
+ u32 reg;
+
+ if (channel >= 4)
+ return -EINVAL;
+ debug("%s: Configure '%s' channel %u\n", __func__, dev->name, channel);
+ /* We ignore the period here and just use 32KHz */
+ clock_start_periph_pll(PERIPH_ID_PWM, CLOCK_ID_SFROM32KHZ, 32768);
+
+ pulse_width = duty_ns * 255 / period_ns;
+
+ reg = pulse_width << PWM_WIDTH_SHIFT;
+ reg |= 1 << PWM_DIVIDER_SHIFT;
+ writel(reg, &regs[channel].control);
+ debug("%s: pulse_width=%u\n", __func__, pulse_width);
+
+ return 0;
+}
+
+static int tegra_pwm_set_enable(struct udevice *dev, uint channel, bool enable)
+{
+ struct tegra_pwm_priv *priv = dev_get_priv(dev);
+ struct pwm_ctlr *regs = priv->regs;
+
+ if (channel >= 4)
+ return -EINVAL;
+ debug("%s: Enable '%s' channel %u\n", __func__, dev->name, channel);
+ clrsetbits_le32(&regs[channel].control, PWM_ENABLE_MASK,
+ enable ? PWM_ENABLE_MASK : 0);
+
+ return 0;
+}
+
+static int tegra_pwm_ofdata_to_platdata(struct udevice *dev)
+{
+ struct tegra_pwm_priv *priv = dev_get_priv(dev);
+
+ priv->regs = (struct pwm_ctlr *)dev_get_addr(dev);
+
+ return 0;
+}
+
+static const struct pwm_ops tegra_pwm_ops = {
+ .set_config = tegra_pwm_set_config,
+ .set_enable = tegra_pwm_set_enable,
+};
+
+static const struct udevice_id tegra_pwm_ids[] = {
+ { .compatible = "nvidia,tegra124-pwm" },
+ { .compatible = "nvidia,tegra20-pwm" },
+ { }
+};
+
+U_BOOT_DRIVER(tegra_pwm) = {
+ .name = "tegra_pwm",
+ .id = UCLASS_PWM,
+ .of_match = tegra_pwm_ids,
+ .ops = &tegra_pwm_ops,
+ .ofdata_to_platdata = tegra_pwm_ofdata_to_platdata,
+ .priv_auto_alloc_size = sizeof(struct tegra_pwm_priv),
+};
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 57cd38bf6e4..c63999ac417 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -22,14 +22,10 @@ obj-$(CONFIG_ATMEL_USART) += atmel_usart.o
obj-$(CONFIG_EFI_APP) += serial_efi.o
obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o
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_IMX_SERIAL) += serial_imx.o
-obj-$(CONFIG_MAX3100_SERIAL) += serial_max3100.o
obj-$(CONFIG_MXC_UART) += serial_mxc.o
obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o
-obj-$(CONFIG_SA1100_SERIAL) += serial_sa1100.o
obj-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o
obj-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
obj-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
@@ -37,7 +33,6 @@ obj-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
obj-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
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_UNIPHIER_SERIAL) += serial_uniphier.o
obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
diff --git a/drivers/serial/mxs_auart.c b/drivers/serial/mxs_auart.c
deleted file mode 100644
index fc0fa96a0e2..00000000000
--- a/drivers/serial/mxs_auart.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Freescale i.MX23/i.MX28 AUART driver
- *
- * Copyright (C) 2013 Andreas Wass <andreas.wass@dalelven.com>
- *
- * Based on the MXC serial driver:
- *
- * (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>
- *
- * Further based on the Linux mxs-auart.c driver:
- *
- * Freescale STMP37XX/STMP38X Application UART drkiver
- * Copyright 2008-2010 Freescale Semiconductor, Inc.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-#include <common.h>
-#include <asm/io.h>
-#include <serial.h>
-#include <linux/compiler.h>
-#include <asm/arch/regs-base.h>
-#include <asm/arch/regs-uartapp.h>
-#include <asm/arch/sys_proto.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#ifndef CONFIG_MXS_AUART_BASE
-#error "CONFIG_MXS_AUART_BASE must be set to the base UART to use"
-#endif
-
-/* AUART clock always supplied by XTAL and always 24MHz */
-#define MXS_AUART_CLK 24000000
-
-static struct mxs_uartapp_regs *get_uartapp_registers(void)
-{
- return (struct mxs_uartapp_regs *)CONFIG_MXS_AUART_BASE;
-}
-
-/**
- * Sets the baud rate and settings.
- * The settings are: 8 data bits, no parit and 1 stop bit.
- */
-static void mxs_auart_setbrg(void)
-{
- u32 div;
- u32 linectrl = 0;
- struct mxs_uartapp_regs *regs = get_uartapp_registers();
-
- if (!gd->baudrate)
- gd->baudrate = CONFIG_BAUDRATE;
-
- /*
- * From i.MX28 datasheet:
- * div is calculated by calculating UARTCLK*32/baudrate, rounded to int
- * div must be between 0xEC and 0x003FFFC0 inclusive
- * Lowest 6 bits of div goes in BAUD_DIVFRAC part of LINECTRL register
- * Next 16 bits goes in BAUD_DIVINT part of LINECTRL register
- */
- div = (MXS_AUART_CLK * 32) / gd->baudrate;
- if (div < 0xEC || div > 0x003FFFC0)
- return;
-
- linectrl |= ((div & UARTAPP_LINECTRL_EXTRACT_BAUD_DIVFRAC_MASK) <<
- UARTAPP_LINECTRL_BAUD_DIVFRAC_OFFSET) &
- UARTAPP_LINECTRL_BAUD_DIVFRAC_MASK;
- linectrl |= ((div >> UARTAPP_LINECTRL_EXTRACT_BAUD_DIVINT_OFFSET) <<
- UARTAPP_LINECTRL_BAUD_DIVINT_OFFSET) &
- UARTAPP_LINECTRL_BAUD_DIVINT_MASK;
-
- /* Word length: 8 bits */
- linectrl |= UARTAPP_LINECTRL_WLEN_8BITS;
-
- /* Enable FIFOs. */
- linectrl |= UARTAPP_LINECTRL_FEN_MASK;
-
- /* Write above settings, no parity, 1 stop bit */
- writel(linectrl, &regs->hw_uartapp_linectrl);
-}
-
-static int mxs_auart_init(void)
-{
- struct mxs_uartapp_regs *regs = get_uartapp_registers();
- /* Reset everything */
- mxs_reset_block(&regs->hw_uartapp_ctrl0_reg);
- /* Disable interrupts */
- writel(0, &regs->hw_uartapp_intr);
- /* Set baud rate and settings */
- serial_setbrg();
- /* Disable RTS and CTS, ignore LINECTRL2 register */
- writel(UARTAPP_CTRL2_RTSEN_MASK |
- UARTAPP_CTRL2_CTSEN_MASK |
- UARTAPP_CTRL2_USE_LCR2_MASK,
- &regs->hw_uartapp_ctrl2_clr);
- /* Enable receiver, transmitter and UART */
- writel(UARTAPP_CTRL2_RXE_MASK |
- UARTAPP_CTRL2_TXE_MASK |
- UARTAPP_CTRL2_UARTEN_MASK,
- &regs->hw_uartapp_ctrl2_set);
- return 0;
-}
-
-static void mxs_auart_putc(const char c)
-{
- struct mxs_uartapp_regs *regs = get_uartapp_registers();
- /* Wait in loop while the transmit FIFO is full */
- while (readl(&regs->hw_uartapp_stat) & UARTAPP_STAT_TXFF_MASK)
- ;
-
- writel(c, &regs->hw_uartapp_data);
-
- if (c == '\n')
- mxs_auart_putc('\r');
-}
-
-static int mxs_auart_tstc(void)
-{
- struct mxs_uartapp_regs *regs = get_uartapp_registers();
- /* Checks if receive FIFO is empty */
- return !(readl(&regs->hw_uartapp_stat) & UARTAPP_STAT_RXFE_MASK);
-}
-
-static int mxs_auart_getc(void)
-{
- struct mxs_uartapp_regs *regs = get_uartapp_registers();
- /* Wait until a character is available to read */
- while (!mxs_auart_tstc())
- ;
- /* Read the character from the data register */
- return readl(&regs->hw_uartapp_data) & 0xFF;
-}
-
-static struct serial_device mxs_auart_drv = {
- .name = "mxs_auart_serial",
- .start = mxs_auart_init,
- .stop = NULL,
- .setbrg = mxs_auart_setbrg,
- .putc = mxs_auart_putc,
- .puts = default_serial_puts,
- .getc = mxs_auart_getc,
- .tstc = mxs_auart_tstc,
-};
-
-void mxs_auart_initialize(void)
-{
- serial_register(&mxs_auart_drv);
-}
-
-__weak struct serial_device *default_serial_console(void)
-{
- return &mxs_auart_drv;
-}
diff --git a/drivers/serial/opencores_yanu.c b/drivers/serial/opencores_yanu.c
deleted file mode 100644
index f68c8d0f043..00000000000
--- a/drivers/serial/opencores_yanu.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Altera NiosII YANU serial interface by Imagos
- * please see http://www.opencores.org/project,yanu for
- * information/downloads
- *
- * Copyright 2010, Renato Andreola <renato.andreola@imagos.it>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <watchdog.h>
-#include <asm/io.h>
-#include <serial.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/*-----------------------------------------------------------------*/
-/* YANU Imagos serial port */
-/*-----------------------------------------------------------------*/
-
-#define YANU_MAX_PRESCALER_N ((1 << 4) - 1) /* 15 */
-#define YANU_MAX_PRESCALER_M ((1 << 11) -1) /* 2047 */
-#define YANU_FIFO_SIZE (16)
-#define YANU_RXFIFO_SIZE (YANU_FIFO_SIZE)
-#define YANU_TXFIFO_SIZE (YANU_FIFO_SIZE)
-
-#define YANU_RXFIFO_DLY (10*11)
-#define YANU_TXFIFO_THR (10)
-#define YANU_DATA_CHAR_MASK (0xFF)
-
-/* data register */
-#define YANU_DATA_OFFSET (0) /* data register offset */
-
-#define YANU_CONTROL_OFFSET (4) /* control register offset */
-/* interrupt enable */
-#define YANU_CONTROL_IE_RRDY (1<<0) /* ie on received character ready */
-#define YANU_CONTROL_IE_OE (1<<1) /* ie on rx overrun */
-#define YANU_CONTROL_IE_BRK (1<<2) /* ie on break detect */
-#define YANU_CONTROL_IE_FE (1<<3) /* ie on framing error */
-#define YANU_CONTROL_IE_PE (1<<4) /* ie on parity error */
-#define YANU_CONTROL_IE_TRDY (1<<5) /* ie interrupt on tranmitter ready */
-/* control bits */
-#define YANU_CONTROL_BITS_POS (6) /* bits number pos */
-#define YANU_CONTROL_BITS (1<<YANU_CONTROL_BITS_POS) /* number of rx/tx bits per word. 3 bit unsigned integer */
-#define YANU_CONTROL_BITS_N (3) /* ... its bit filed length */
-#define YANU_CONTROL_PARENA (1<<9) /* enable parity bit transmission/reception */
-#define YANU_CONTROL_PAREVEN (1<<10) /* parity even */
-#define YANU_CONTROL_STOPS (1<<11) /* number of stop bits */
-#define YANU_CONTROL_HHENA (1<<12) /* Harware Handshake enable... */
-#define YANU_CONTROL_FORCEBRK (1<<13) /* if set than txd = active (0) */
-/* tuning part */
-#define YANU_CONTROL_RDYDLY (1<<14) /* delay from "first" before setting rrdy (in bit) */
-#define YANU_CONTROL_RDYDLY_N (8) /* ... its bit filed length */
-#define YANU_CONTROL_TXTHR (1<<22) /* tx interrupt threshold: the trdy set if txfifo_chars<= txthr (chars) */
-#define YANU_CONTROL_TXTHR_N (4) /* ... its bit field length */
-
-#define YANU_BAUD_OFFSET (8) /* baud register offset */
-#define YANU_BAUDM (1<<0) /* baud mantissa lsb */
-#define YANU_BAUDM_N (12) /* ...its bit filed length */
-#define YANU_BAUDE (1<<12) /* baud exponent lsb */
-#define YANU_BAUDE_N (4) /* ...its bit field length */
-
-#define YANU_ACTION_OFFSET (12) /* action register... write only */
-#define YANU_ACTION_RRRDY (1<<0) /* reset rrdy */
-#define YANU_ACTION_ROE (1<<1) /* reset oe */
-#define YANU_ACTION_RBRK (1<<2) /* reset brk */
-#define YANU_ACTION_RFE (1<<3) /* reset fe */
-#define YANU_ACTION_RPE (1<<4) /* reset pe */
-#define YANU_ACTION_SRRDY (1<<5) /* set rrdy */
-#define YANU_ACTION_SOE (1<<6) /* set oe */
-#define YANU_ACTION_SBRK (1<<7) /* set brk */
-#define YANU_ACTION_SFE (1<<8) /* set fe */
-#define YANU_ACTION_SPE (1<<9) /* set pe */
-#define YANU_ACTION_RFIFO_PULL (1<<10) /* pull a char from rx fifo we MUST do it before taking a char */
-#define YANU_ACTION_RFIFO_CLEAR (1<<11) /* clear rx fifo */
-#define YANU_ACTION_TFIFO_CLEAR (1<<12) /* clear tx fifo */
-#define YANU_ACTION_RTRDY (1<<13) /* clear trdy */
-#define YANU_ACTION_STRDY (1<<14) /* set trdy */
-
-#define YANU_STATUS_OFFSET (16)
-#define YANU_STATUS_RRDY (1<<0) /* rxrdy flag */
-#define YANU_STATUS_TRDY (1<<1) /* txrdy flag */
-#define YANU_STATUS_OE (1<<2) /* rx overrun error */
-#define YANU_STATUS_BRK (1<<3) /* rx break detect flag */
-#define YANU_STATUS_FE (1<<4) /* rx framing error flag */
-#define YANU_STATUS_PE (1<<5) /* rx parity erro flag */
-#define YANU_RFIFO_CHARS_POS (6)
-#define YANU_RFIFO_CHARS (1<<RFIFO_CHAR_POS) /* number of chars into rx fifo */
-#define YANU_RFIFO_CHARS_N (5) /* ...its bit field length: 32 chars */
-#define YANU_TFIFO_CHARS_POS (11)
-#define YANU_TFIFO_CHARS (1<<TFIFO_CHAR_POS) /* number of chars into tx fifo */
-#define YANU_TFIFO_CHARS_N (5) /* ...its bit field length: 32 chars */
-
-typedef volatile struct {
- volatile unsigned data;
- volatile unsigned control; /* control register (RW) 32-bit */
- volatile unsigned baud; /* baud/prescaler register (RW) 32-bit */
- volatile unsigned action; /* action register (W) 32-bit */
- volatile unsigned status; /* status register (R) 32-bit */
- volatile unsigned magic; /* magic register (R) 32-bit */
-} yanu_uart_t;
-
-static yanu_uart_t *uart = (yanu_uart_t *)CONFIG_SYS_NIOS_CONSOLE;
-
-static void oc_serial_setbrg(void)
-{
- int n, k;
- const unsigned max_uns = 0xFFFFFFFF;
- unsigned best_n, best_m, baud;
- unsigned baudrate;
-
-#if defined(CONFIG_SYS_NIOS_FIXEDBAUD)
- /* Everything's already setup for fixed-baud PTF assignment */
- baudrate = CONFIG_BAUDRATE;
-#else
- baudrate = gd->baudrate;
-#endif
- /* compute best N and M couple */
- best_n = YANU_MAX_PRESCALER_N;
- for (n = YANU_MAX_PRESCALER_N; n >= 0; n--) {
- if ((unsigned)CONFIG_SYS_CLK_FREQ / (1 << (n + 4)) >=
- baudrate) {
- best_n = n;
- break;
- }
- }
- for (k = 0;; k++) {
- if (baudrate <= (max_uns >> (15+n-k)))
- break;
- }
- best_m =
- (baudrate * (1 << (15 + n - k))) /
- ((unsigned)CONFIG_SYS_CLK_FREQ >> k);
-
- baud = best_m + best_n * YANU_BAUDE;
- writel(baud, &uart->baud);
-
- return;
-}
-
-static int oc_serial_init(void)
-{
- unsigned action,control;
-
- /* status register cleanup */
- action = YANU_ACTION_RRRDY |
- YANU_ACTION_RTRDY |
- YANU_ACTION_ROE |
- YANU_ACTION_RBRK |
- YANU_ACTION_RFE |
- YANU_ACTION_RPE |
- YANU_ACTION_RFE | YANU_ACTION_RFIFO_CLEAR | YANU_ACTION_TFIFO_CLEAR;
-
- writel(action, &uart->action);
-
- /*
- * control register cleanup
- * no interrupts enabled
- * one stop bit
- * hardware flow control disabled
- * 8 bits
- */
- control = (0x7 << YANU_CONTROL_BITS_POS);
- /* enven parity just to be clean */
- control |= YANU_CONTROL_PAREVEN;
- /* we set threshold for fifo */
- control |= YANU_CONTROL_RDYDLY * YANU_RXFIFO_DLY;
- control |= YANU_CONTROL_TXTHR * YANU_TXFIFO_THR;
-
- writel(control, &uart->control);
-
- /* to set baud rate */
- serial_setbrg();
-
- return (0);
-}
-
-
-/*-----------------------------------------------------------------------
- * YANU CONSOLE
- *---------------------------------------------------------------------*/
-static void oc_serial_putc(char c)
-{
- int tx_chars;
- unsigned status;
-
- if (c == '\n')
- serial_putc ('\r');
-
- while (1) {
- status = readl(&uart->status);
- tx_chars = (status>>YANU_TFIFO_CHARS_POS)
- & ((1<<YANU_TFIFO_CHARS_N)-1);
- if (tx_chars < YANU_TXFIFO_SIZE-1)
- break;
- WATCHDOG_RESET ();
- }
-
- writel((unsigned char)c, &uart->data);
-}
-
-static int oc_serial_tstc(void)
-{
- unsigned status ;
-
- status = readl(&uart->status);
- return (((status >> YANU_RFIFO_CHARS_POS) &
- ((1 << YANU_RFIFO_CHARS_N) - 1)) > 0);
-}
-
-static int oc_serial_getc(void)
-{
- while (serial_tstc() == 0)
- WATCHDOG_RESET ();
-
- /* first we pull the char */
- writel(YANU_ACTION_RFIFO_PULL, &uart->action);
-
- return(readl(&uart->data) & YANU_DATA_CHAR_MASK);
-}
-
-static struct serial_device oc_serial_drv = {
- .name = "oc_serial",
- .start = oc_serial_init,
- .stop = NULL,
- .setbrg = oc_serial_setbrg,
- .putc = oc_serial_putc,
- .puts = default_serial_puts,
- .getc = oc_serial_getc,
- .tstc = oc_serial_tstc,
-};
-
-void oc_serial_initialize(void)
-{
- serial_register(&oc_serial_drv);
-}
-
-__weak struct serial_device *default_serial_console(void)
-{
- return &oc_serial_drv;
-}
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index 45dff98d9d1..58f882b22a6 100644
--- a/drivers/serial/sandbox.c
+++ b/drivers/serial/sandbox.c
@@ -25,7 +25,7 @@ DECLARE_GLOBAL_DATA_PTR;
/*
*
* serial_buf: A buffer that holds keyboard characters for the
- * Sandbox U-boot.
+ * Sandbox U-Boot.
*
* invariants:
* serial_buf_write == serial_buf_read -> empty buffer
diff --git a/drivers/serial/serial_bfin.c b/drivers/serial/serial_bfin.c
index 0443b8427a9..1d5be2a7a26 100644
--- a/drivers/serial/serial_bfin.c
+++ b/drivers/serial/serial_bfin.c
@@ -1,5 +1,5 @@
/*
- * U-boot - serial.c Blackfin Serial Driver
+ * U-Boot - serial.c Blackfin Serial Driver
*
* Copyright (c) 2005-2008 Analog Devices Inc.
*
diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c
deleted file mode 100644
index d43a5fedcc8..00000000000
--- a/drivers/serial/serial_imx.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * (c) 2004 Sascha Hauer <sascha@saschahauer.de>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/arch/imx-regs.h>
-#include <serial.h>
-#include <linux/compiler.h>
-
-#if defined CONFIG_IMX_SERIAL1
-#define UART_BASE IMX_UART1_BASE
-#elif defined CONFIG_IMX_SERIAL2
-#define UART_BASE IMX_UART2_BASE
-#else
-#error "define CONFIG_IMX_SERIAL1, CONFIG_IMX_SERIAL2 or CONFIG_IMX_SERIAL_NONE"
-#endif
-
-struct imx_serial {
- volatile uint32_t urxd[16];
- volatile uint32_t utxd[16];
- volatile uint32_t ucr1;
- volatile uint32_t ucr2;
- volatile uint32_t ucr3;
- volatile uint32_t ucr4;
- volatile uint32_t ufcr;
- volatile uint32_t usr1;
- volatile uint32_t usr2;
- volatile uint32_t uesc;
- volatile uint32_t utim;
- volatile uint32_t ubir;
- volatile uint32_t ubmr;
- volatile uint32_t ubrc;
- volatile uint32_t bipr[4];
- volatile uint32_t bmpr[4];
- volatile uint32_t uts;
-};
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static void imx_serial_setbrg(void)
-{
- serial_init();
-}
-
-extern void imx_gpio_mode(int gpio_mode);
-
-/*
- * Initialise the serial port with the given baudrate. The settings
- * are always 8 data bits, no parity, 1 stop bit, no start bits.
- *
- */
-static int imx_serial_init(void)
-{
- volatile struct imx_serial* base = (struct imx_serial *)UART_BASE;
- unsigned int ufcr_rfdiv;
- unsigned int refclk;
-
-#ifdef CONFIG_IMX_SERIAL1
- imx_gpio_mode(PC11_PF_UART1_TXD);
- imx_gpio_mode(PC12_PF_UART1_RXD);
-#else
- imx_gpio_mode(PB30_PF_UART2_TXD);
- imx_gpio_mode(PB31_PF_UART2_RXD);
-#endif
-
- /* Disable UART */
- base->ucr1 &= ~UCR1_UARTEN;
-
- /* Set to default POR state */
-
- base->ucr1 = 0x00000004;
- base->ucr2 = 0x00000000;
- base->ucr3 = 0x00000000;
- base->ucr4 = 0x00008040;
- base->uesc = 0x0000002B;
- base->utim = 0x00000000;
- base->ubir = 0x00000000;
- base->ubmr = 0x00000000;
- base->uts = 0x00000000;
- /* Set clocks */
- base->ucr4 |= UCR4_REF16;
-
- /* Configure FIFOs */
- base->ufcr = 0xa81;
-
- /* set the baud rate.
- *
- * baud * 16 x
- * --------- = -
- * refclk y
- *
- * x - 1 = UBIR
- * y - 1 = UBMR
- *
- * each register is 16 bits wide. refclk max is 96 MHz
- *
- */
-
- ufcr_rfdiv = ((base->ufcr) & UFCR_RFDIV) >> 7;
- if (ufcr_rfdiv == 6)
- ufcr_rfdiv = 7;
- else
- ufcr_rfdiv = 6 - ufcr_rfdiv;
-
- refclk = get_PERCLK1();
- refclk /= ufcr_rfdiv;
-
- /* Set the numerator value minus one of the BRM ratio */
- base->ubir = (gd->baudrate / 100) - 1;
-
- /* Set the denominator value minus one of the BRM ratio */
- base->ubmr = (refclk/(16 * 100)) - 1;
-
- /* Set to 8N1 */
- base->ucr2 &= ~UCR2_PREN;
- base->ucr2 |= UCR2_WS;
- base->ucr2 &= ~UCR2_STPB;
-
- /* Ignore RTS */
- base->ucr2 |= UCR2_IRTS;
-
- /* Enable UART */
- base->ucr1 |= UCR1_UARTEN | UCR1_UARTCLKEN;
-
- /* Enable FIFOs */
- base->ucr2 |= UCR2_SRST | UCR2_RXEN | UCR2_TXEN;
-
- /* Clear status flags */
- base->usr2 |= USR2_ADET |
- USR2_DTRF |
- USR2_IDLE |
- USR2_IRINT |
- USR2_WAKE |
- USR2_RTSF |
- USR2_BRCD |
- USR2_ORE;
-
- /* Clear status flags */
- base->usr1 |= USR1_PARITYERR |
- USR1_RTSD |
- USR1_ESCF |
- USR1_FRAMERR |
- USR1_AIRINT |
- USR1_AWAKE;
- return (0);
-}
-
-/*
- * Read a single byte from the serial port. Returns 1 on success, 0
- * otherwise. When the function is successful, the character read is
- * written into its argument c.
- */
-static int imx_serial_getc(void)
-{
- volatile struct imx_serial* base = (struct imx_serial *)UART_BASE;
- unsigned char ch;
-
- while(base->uts & UTS_RXEMPTY);
-
- ch = (char)base->urxd[0];
-
- return ch;
-}
-
-#ifdef CONFIG_HWFLOW
-static int hwflow = 0; /* turned off by default */
-int hwflow_onoff(int on)
-{
-}
-#endif
-
-/*
- * Output a single byte to the serial port.
- */
-static void imx_serial_putc(const char c)
-{
- volatile struct imx_serial* base = (struct imx_serial *)UART_BASE;
-
- /* Wait for Tx FIFO not full */
- while (base->uts & UTS_TXFULL);
-
- base->utxd[0] = c;
-
- /* If \n, also do \r */
- if (c == '\n')
- serial_putc ('\r');
-}
-
-/*
- * Test whether a character is in the RX buffer
- */
-static int imx_serial_tstc(void)
-{
- volatile struct imx_serial* base = (struct imx_serial *)UART_BASE;
-
- /* If receive fifo is empty, return false */
- if (base->uts & UTS_RXEMPTY)
- return 0;
- return 1;
-}
-
-static struct serial_device imx_serial_drv = {
- .name = "imx_serial",
- .start = imx_serial_init,
- .stop = NULL,
- .setbrg = imx_serial_setbrg,
- .putc = imx_serial_putc,
- .puts = default_serial_puts,
- .getc = imx_serial_getc,
- .tstc = imx_serial_tstc,
-};
-
-void imx_serial_initialize(void)
-{
- serial_register(&imx_serial_drv);
-}
-
-__weak struct serial_device *default_serial_console(void)
-{
- return &imx_serial_drv;
-}
diff --git a/drivers/serial/serial_max3100.c b/drivers/serial/serial_max3100.c
deleted file mode 100644
index 027d9194a74..00000000000
--- a/drivers/serial/serial_max3100.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * (C) Copyright 2003
- *
- * Pantelis Antoniou <panto@intracom.gr>
- * Intracom S.A.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <watchdog.h>
-#include <serial.h>
-#include <linux/compiler.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/**************************************************************/
-
-/* convienient macros */
-#define MAX3100_SPI_RXD() (MAX3100_SPI_RXD_PORT & MAX3100_SPI_RXD_BIT)
-
-#define MAX3100_SPI_TXD(x) \
- do { \
- if (x) \
- MAX3100_SPI_TXD_PORT |= MAX3100_SPI_TXD_BIT; \
- else \
- MAX3100_SPI_TXD_PORT &= ~MAX3100_SPI_TXD_BIT; \
- } while(0)
-
-#define MAX3100_SPI_CLK(x) \
- do { \
- if (x) \
- MAX3100_SPI_CLK_PORT |= MAX3100_SPI_CLK_BIT; \
- else \
- MAX3100_SPI_CLK_PORT &= ~MAX3100_SPI_CLK_BIT; \
- } while(0)
-
-#define MAX3100_SPI_CLK_TOGGLE() (MAX3100_SPI_CLK_PORT ^= MAX3100_SPI_CLK_BIT)
-
-#define MAX3100_CS(x) \
- do { \
- if (x) \
- MAX3100_CS_PORT |= MAX3100_CS_BIT; \
- else \
- MAX3100_CS_PORT &= ~MAX3100_CS_BIT; \
- } while(0)
-
-/**************************************************************/
-
-/* MAX3100 definitions */
-
-#define MAX3100_WC (3 << 14) /* write configuration */
-#define MAX3100_RC (1 << 14) /* read configuration */
-#define MAX3100_WD (2 << 14) /* write data */
-#define MAX3100_RD (0 << 14) /* read data */
-
-/* configuration register bits */
-#define MAX3100_FEN (1 << 13) /* FIFO enable */
-#define MAX3100_SHDN (1 << 12) /* shutdown bit */
-#define MAX3100_TM (1 << 11) /* T bit irq mask */
-#define MAX3100_RM (1 << 10) /* R bit irq mask */
-#define MAX3100_PM (1 << 9) /* P bit irq mask */
-#define MAX3100_RAM (1 << 8) /* mask for RA/FE bit */
-#define MAX3100_IR (1 << 7) /* IRDA timing mode */
-#define MAX3100_ST (1 << 6) /* transmit stop bit */
-#define MAX3100_PE (1 << 5) /* parity enable bit */
-#define MAX3100_L (1 << 4) /* Length bit */
-#define MAX3100_B_MASK (0x000F) /* baud rate bits mask */
-#define MAX3100_B(x) ((x) & 0x000F) /* baud rate select bits */
-
-/* data register bits (write) */
-#define MAX3100_TE (1 << 10) /* transmit enable bit (active low) */
-#define MAX3100_RTS (1 << 9) /* request-to-send bit (inverted ~RTS pin) */
-
-/* data register bits (read) */
-#define MAX3100_RA (1 << 10) /* receiver activity when in shutdown mode */
-#define MAX3100_FE (1 << 10) /* framing error when in normal mode */
-#define MAX3100_CTS (1 << 9) /* clear-to-send bit (inverted ~CTS pin) */
-
-/* data register bits (both directions) */
-#define MAX3100_R (1 << 15) /* receive bit */
-#define MAX3100_T (1 << 14) /* transmit bit */
-#define MAX3100_P (1 << 8) /* parity bit */
-#define MAX3100_D_MASK 0x00FF /* data bits mask */
-#define MAX3100_D(x) ((x) & 0x00FF) /* data bits */
-
-/* these definitions are valid only for fOSC = 3.6864MHz */
-#define MAX3100_B_230400 MAX3100_B(0)
-#define MAX3100_B_115200 MAX3100_B(1)
-#define MAX3100_B_57600 MAX3100_B(2)
-#define MAX3100_B_38400 MAX3100_B(9)
-#define MAX3100_B_19200 MAX3100_B(10)
-#define MAX3100_B_9600 MAX3100_B(11)
-#define MAX3100_B_4800 MAX3100_B(12)
-#define MAX3100_B_2400 MAX3100_B(13)
-#define MAX3100_B_1200 MAX3100_B(14)
-#define MAX3100_B_600 MAX3100_B(15)
-
-/**************************************************************/
-
-static inline unsigned int max3100_transfer(unsigned int val)
-{
- unsigned int rx;
- int b;
-
- MAX3100_SPI_CLK(0);
- MAX3100_CS(0);
-
- rx = 0; b = 16;
- while (--b >= 0) {
- MAX3100_SPI_TXD(val & 0x8000);
- val <<= 1;
- MAX3100_SPI_CLK_TOGGLE();
- udelay(1);
- rx <<= 1;
- if (MAX3100_SPI_RXD())
- rx |= 1;
- MAX3100_SPI_CLK_TOGGLE();
- udelay(1);
- }
-
- MAX3100_SPI_CLK(1);
- MAX3100_CS(1);
-
- return rx;
-}
-
-/**************************************************************/
-
-/* must be power of 2 */
-#define RXFIFO_SZ 16
-
-static int rxfifo_cnt;
-static int rxfifo_in;
-static int rxfifo_out;
-static unsigned char rxfifo_buf[16];
-
-static void max3100_serial_putc_raw(int c)
-{
- unsigned int rx;
-
- while (((rx = max3100_transfer(MAX3100_RC)) & MAX3100_T) == 0)
- WATCHDOG_RESET();
-
- rx = max3100_transfer(MAX3100_WD | (c & 0xff));
- if ((rx & MAX3100_RD) != 0 && rxfifo_cnt < RXFIFO_SZ) {
- rxfifo_cnt++;
- rxfifo_buf[rxfifo_in++] = rx & 0xff;
- rxfifo_in &= RXFIFO_SZ - 1;
- }
-}
-
-static int max3100_serial_getc(void)
-{
- int c;
- unsigned int rx;
-
- while (rxfifo_cnt == 0) {
- rx = max3100_transfer(MAX3100_RD);
- if ((rx & MAX3100_R) != 0) {
- do {
- rxfifo_cnt++;
- rxfifo_buf[rxfifo_in++] = rx & 0xff;
- rxfifo_in &= RXFIFO_SZ - 1;
-
- if (rxfifo_cnt >= RXFIFO_SZ)
- break;
- } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
- }
- WATCHDOG_RESET();
- }
-
- rxfifo_cnt--;
- c = rxfifo_buf[rxfifo_out++];
- rxfifo_out &= RXFIFO_SZ - 1;
- return c;
-}
-
-static int max3100_serial_tstc(void)
-{
- unsigned int rx;
-
- if (rxfifo_cnt > 0)
- return 1;
-
- rx = max3100_transfer(MAX3100_RD);
- if ((rx & MAX3100_R) == 0)
- return 0;
-
- do {
- rxfifo_cnt++;
- rxfifo_buf[rxfifo_in++] = rx & 0xff;
- rxfifo_in &= RXFIFO_SZ - 1;
-
- if (rxfifo_cnt >= RXFIFO_SZ)
- break;
- } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
-
- return 1;
-}
-
-static int max3100_serial_init(void)
-{
- unsigned int wconf, rconf;
- int i;
-
- wconf = 0;
-
- /* Set baud rate */
- switch (gd->baudrate) {
- case 1200:
- wconf = MAX3100_B_1200;
- break;
- case 2400:
- wconf = MAX3100_B_2400;
- break;
- case 4800:
- wconf = MAX3100_B_4800;
- break;
- case 9600:
- wconf = MAX3100_B_9600;
- break;
- case 19200:
- wconf = MAX3100_B_19200;
- break;
- case 38400:
- wconf = MAX3100_B_38400;
- break;
- case 57600:
- wconf = MAX3100_B_57600;
- break;
- default:
- case 115200:
- wconf = MAX3100_B_115200;
- break;
- case 230400:
- wconf = MAX3100_B_230400;
- break;
- }
-
- /* try for 10ms, with a 100us gap */
- for (i = 0; i < 10000; i += 100) {
-
- max3100_transfer(MAX3100_WC | wconf);
- rconf = max3100_transfer(MAX3100_RC) & 0x3fff;
-
- if (rconf == wconf)
- break;
- udelay(100);
- }
-
- rxfifo_in = rxfifo_out = rxfifo_cnt = 0;
-
- return (0);
-}
-
-static void max3100_serial_putc(const char c)
-{
- if (c == '\n')
- max3100_serial_putc_raw('\r');
-
- max3100_serial_putc_raw(c);
-}
-
-static void max3100_serial_puts(const char *s)
-{
- while (*s)
- max3100_serial_putc_raw(*s++);
-}
-
-static void max3100_serial_setbrg(void)
-{
-}
-
-static struct serial_device max3100_serial_drv = {
- .name = "max3100_serial",
- .start = max3100_serial_init,
- .stop = NULL,
- .setbrg = max3100_serial_setbrg,
- .putc = max3100_serial_putc,
- .puts = max3100_serial_puts,
- .getc = max3100_serial_getc,
- .tstc = max3100_serial_tstc,
-};
-
-void max3100_serial_initialize(void)
-{
- serial_register(&max3100_serial_drv);
-}
-
-__weak struct serial_device *default_serial_console(void)
-{
- return &max3100_serial_drv;
-}
diff --git a/drivers/serial/serial_s3c24x0.c b/drivers/serial/serial_s3c24x0.c
index 7afc5044a8c..d4e7df27be1 100644
--- a/drivers/serial/serial_s3c24x0.c
+++ b/drivers/serial/serial_s3c24x0.c
@@ -65,10 +65,6 @@ DECLARE_GLOBAL_DATA_PTR;
.puts = s3serial##port##_puts, \
}
-#ifdef CONFIG_HWFLOW
-static int hwflow;
-#endif
-
static void _serial_setbrg(const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
@@ -95,10 +91,6 @@ static int serial_init_dev(const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
-#ifdef CONFIG_HWFLOW
- hwflow = 0; /* turned off by default */
-#endif
-
/* FIFO enable, Tx/Rx FIFO clear */
writel(0x07, &uart->ufcon);
writel(0x0, &uart->umcon);
@@ -111,16 +103,6 @@ static int serial_init_dev(const int dev_index)
*/
writel(0x245, &uart->ucon);
-#ifdef CONFIG_HWFLOW
- writel(0x1, &uart->umcon); /* rts up */
-#endif
-
- /* FIXME: This is sooooooooooooooooooo ugly */
-#if defined(CONFIG_ARCH_GTA02_v1) || defined(CONFIG_ARCH_GTA02_v2)
- /* we need auto hw flow control on the gsm and gps port */
- if (dev_index == 0 || dev_index == 1)
- writel(0x10, &uart->umcon);
-#endif
_serial_setbrg(dev_index);
return (0);
@@ -146,57 +128,16 @@ static inline int serial_getc_dev(unsigned int dev_index)
return _serial_getc(dev_index);
}
-#ifdef CONFIG_HWFLOW
-int hwflow_onoff(int on)
-{
- switch (on) {
- case 0:
- default:
- break; /* return current */
- case 1:
- hwflow = 1; /* turn on */
- break;
- case -1:
- hwflow = 0; /* turn off */
- break;
- }
- return hwflow;
-}
-#endif
-
-#ifdef CONFIG_MODEM_SUPPORT
-static int be_quiet = 0;
-void disable_putc(void)
-{
- be_quiet = 1;
-}
-
-void enable_putc(void)
-{
- be_quiet = 0;
-}
-#endif
-
-
/*
* Output a single byte to the serial port.
*/
static void _serial_putc(const char c, const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
-#ifdef CONFIG_MODEM_SUPPORT
- if (be_quiet)
- return;
-#endif
while (!(readl(&uart->utrstat) & 0x2))
/* wait for room in the tx FIFO */ ;
-#ifdef CONFIG_HWFLOW
- while (hwflow && !(readl(&uart->umstat) & 0x1))
- /* Wait for CTS up */ ;
-#endif
-
writeb(c, &uart->utxh);
/* If \n, also do \r */
diff --git a/drivers/serial/serial_sa1100.c b/drivers/serial/serial_sa1100.c
deleted file mode 100644
index 78f241d8508..00000000000
--- a/drivers/serial/serial_sa1100.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * (C) Copyright 2002
- * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
- *
- * (C) Copyright 2002
- * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- * Marius Groeger <mgroeger@sysgo.de>
- *
- * (C) Copyright 2002
- * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- * Alex Zuepke <azu@sysgo.de>
- *
- * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <SA-1100.h>
-#include <serial.h>
-#include <linux/compiler.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static void sa1100_serial_setbrg(void)
-{
- unsigned int reg = 0;
-
- if (gd->baudrate == 1200)
- reg = 191;
- else if (gd->baudrate == 9600)
- reg = 23;
- else if (gd->baudrate == 19200)
- reg = 11;
- else if (gd->baudrate == 38400)
- reg = 5;
- else if (gd->baudrate == 57600)
- reg = 3;
- else if (gd->baudrate == 115200)
- reg = 1;
- else
- hang ();
-
-#ifdef CONFIG_SERIAL1
- /* SA1110 uart function */
- Ser1SDCR0 |= SDCR0_SUS;
-
- /* Wait until port is ready ... */
- while(Ser1UTSR1 & UTSR1_TBY) {}
-
- /* init serial serial 1 */
- Ser1UTCR3 = 0x00;
- Ser1UTSR0 = 0xff;
- Ser1UTCR0 = ( UTCR0_1StpBit | UTCR0_8BitData );
- Ser1UTCR1 = 0;
- Ser1UTCR2 = (u32)reg;
- Ser1UTCR3 = ( UTCR3_RXE | UTCR3_TXE );
-#elif defined(CONFIG_SERIAL3)
- /* Wait until port is ready ... */
- while (Ser3UTSR1 & UTSR1_TBY) {
- }
-
- /* init serial serial 3 */
- Ser3UTCR3 = 0x00;
- Ser3UTSR0 = 0xff;
- Ser3UTCR0 = (UTCR0_1StpBit | UTCR0_8BitData);
- Ser3UTCR1 = 0;
- Ser3UTCR2 = (u32) reg;
- Ser3UTCR3 = (UTCR3_RXE | UTCR3_TXE);
-#else
-#error "Bad: you didn't configured serial ..."
-#endif
-}
-
-
-/*
- * Initialise the serial port with the given baudrate. The settings
- * are always 8 data bits, no parity, 1 stop bit, no start bits.
- *
- */
-static int sa1100_serial_init(void)
-{
- serial_setbrg ();
-
- return (0);
-}
-
-
-/*
- * Output a single byte to the serial port.
- */
-static void sa1100_serial_putc(const char c)
-{
-#ifdef CONFIG_SERIAL1
- /* wait for room in the tx FIFO on SERIAL1 */
- while ((Ser1UTSR0 & UTSR0_TFS) == 0);
-
- Ser1UTDR = c;
-#elif defined(CONFIG_SERIAL3)
- /* wait for room in the tx FIFO on SERIAL3 */
- while ((Ser3UTSR0 & UTSR0_TFS) == 0);
-
- Ser3UTDR = c;
-#endif
-
- /* If \n, also do \r */
- if (c == '\n')
- serial_putc ('\r');
-}
-
-/*
- * Read a single byte from the serial port. Returns 1 on success, 0
- * otherwise. When the function is succesfull, the character read is
- * written into its argument c.
- */
-static int sa1100_serial_tstc(void)
-{
-#ifdef CONFIG_SERIAL1
- return Ser1UTSR1 & UTSR1_RNE;
-#elif defined(CONFIG_SERIAL3)
- return Ser3UTSR1 & UTSR1_RNE;
-#endif
-}
-
-/*
- * Read a single byte from the serial port. Returns 1 on success, 0
- * otherwise. When the function is succesfull, the character read is
- * written into its argument c.
- */
-static int sa1100_serial_getc(void)
-{
-#ifdef CONFIG_SERIAL1
- while (!(Ser1UTSR1 & UTSR1_RNE));
-
- return (char) Ser1UTDR & 0xff;
-#elif defined(CONFIG_SERIAL3)
- while (!(Ser3UTSR1 & UTSR1_RNE));
-
- return (char) Ser3UTDR & 0xff;
-#endif
-}
-
-static struct serial_device sa1100_serial_drv = {
- .name = "sa1100_serial",
- .start = sa1100_serial_init,
- .stop = NULL,
- .setbrg = sa1100_serial_setbrg,
- .putc = sa1100_serial_putc,
- .puts = default_serial_puts,
- .getc = sa1100_serial_getc,
- .tstc = sa1100_serial_tstc,
-};
-
-void sa1100_serial_initialize(void)
-{
- serial_register(&sa1100_serial_drv);
-}
-
-__weak struct serial_device *default_serial_console(void)
-{
- return &sa1100_serial_drv;
-}
diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c
index 91a5dde5776..c793ba6e900 100644
--- a/drivers/serial/serial_stm32.c
+++ b/drivers/serial/serial_stm32.c
@@ -35,24 +35,6 @@ struct stm32_usart {
DECLARE_GLOBAL_DATA_PTR;
-#define MAX_SERIAL_PORTS 4
-
-/*
- * RCC USART specific definitions
- */
-#define RCC_ENR_USART1EN (1 << 4)
-#define RCC_ENR_USART2EN (1 << 17)
-#define RCC_ENR_USART3EN (1 << 18)
-#define RCC_ENR_USART6EN (1 << 5)
-
-/* Array used to figure out which RCC bit needs to be set */
-static const unsigned long usart_port_rcc_pairs[MAX_SERIAL_PORTS][2] = {
- { STM32_USART1_BASE, RCC_ENR_USART1EN },
- { STM32_USART2_BASE, RCC_ENR_USART2EN },
- { STM32_USART3_BASE, RCC_ENR_USART3EN },
- { STM32_USART6_BASE, RCC_ENR_USART6EN }
-};
-
static int stm32_serial_setbrg(struct udevice *dev, int baudrate)
{
struct stm32_serial_platdata *plat = dev->platdata;
@@ -114,28 +96,6 @@ static int stm32_serial_probe(struct udevice *dev)
{
struct stm32_serial_platdata *plat = dev->platdata;
struct stm32_usart *const usart = plat->base;
- int usart_port = -1;
- int i;
-
- for (i = 0; i < MAX_SERIAL_PORTS; i++) {
- if ((u32)usart == usart_port_rcc_pairs[i][0]) {
- usart_port = i;
- break;
- }
- }
-
- if (usart_port == -1)
- return -EINVAL;
-
- if (((u32)usart & STM32_BUS_MASK) == STM32_APB1PERIPH_BASE)
- setbits_le32(&STM32_RCC->apb1enr,
- usart_port_rcc_pairs[usart_port][1]);
- else if (((u32)usart & STM32_BUS_MASK) == STM32_APB2PERIPH_BASE)
- setbits_le32(&STM32_RCC->apb2enr,
- usart_port_rcc_pairs[usart_port][1]);
- else
- return -EINVAL;
-
setbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE);
return 0;
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 99345eb9a02..69f680cc116 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -1,5 +1,5 @@
#
-# Makefile for the U-boot SOC specific device drivers.
+# Makefile for the U-Boot SOC specific device drivers.
#
# SPDX-License-Identifier: GPL-2.0+
#
diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index e543b8f0cf4..00b2fed7b74 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -5,6 +5,7 @@
*
* This file is derived from the flashrom project.
*/
+
#include <common.h>
#include <dm.h>
#include <errno.h>
@@ -17,8 +18,7 @@
#include "ich.h"
-#define SPI_OPCODE_WREN 0x06
-#define SPI_OPCODE_FAST_READ 0x0b
+DECLARE_GLOBAL_DATA_PTR;
#ifdef DEBUG_TRACE
#define debug_trace(fmt, args...) debug(fmt, ##args)
@@ -26,32 +26,6 @@
#define debug_trace(x, args...)
#endif
-struct ich_spi_platdata {
- enum pch_version ich_version; /* Controller version, 7 or 9 */
-};
-
-struct ich_spi_priv {
- int ichspi_lock;
- int locked;
- int opmenu;
- int menubytes;
- void *base; /* Base of register set */
- int preop;
- int optype;
- int addr;
- int data;
- unsigned databytes;
- int status;
- int control;
- int bbar;
- int bcr;
- uint32_t *pr; /* only for ich9 */
- int speed; /* pointer to speed control */
- ulong max_speed; /* Maximum bus speed in MHz */
- ulong cur_speed; /* Current bus speed */
- struct spi_trans trans; /* current transaction in progress */
-};
-
static u8 ich_readb(struct ich_spi_priv *priv, int reg)
{
u8 value = readb(priv->base + reg);
@@ -145,11 +119,11 @@ static int ich_init_controller(struct udevice *dev,
void *sbase;
/* SBASE is similar */
- pch_get_sbase(dev->parent, &sbase_addr);
+ pch_get_spi_base(dev->parent, &sbase_addr);
sbase = (void *)sbase_addr;
debug("%s: sbase=%p\n", __func__, sbase);
- if (plat->ich_version == PCHV_7) {
+ if (plat->ich_version == ICHV_7) {
struct ich7_spi_regs *ich7_spi = sbase;
ich7_spi = (struct ich7_spi_regs *)sbase;
@@ -165,7 +139,7 @@ static int ich_init_controller(struct udevice *dev,
ctlr->bbar = offsetof(struct ich7_spi_regs, bbar);
ctlr->preop = offsetof(struct ich7_spi_regs, preop);
ctlr->base = ich7_spi;
- } else if (plat->ich_version == PCHV_9) {
+ } else if (plat->ich_version == ICHV_9) {
struct ich9_spi_regs *ich9_spi = sbase;
ctlr->ichspi_lock = readw(&ich9_spi->hsfs) & HSFS_FLOCKDN;
@@ -191,7 +165,7 @@ static int ich_init_controller(struct udevice *dev,
/* Work out the maximum speed we can support */
ctlr->max_speed = 20000000;
- if (plat->ich_version == PCHV_9 && ich9_can_do_33mhz(dev))
+ if (plat->ich_version == ICHV_9 && ich9_can_do_33mhz(dev))
ctlr->max_speed = 33000000;
debug("ICH SPI: Version ID %d detected at %p, speed %ld\n",
plat->ich_version, ctlr->base, ctlr->max_speed);
@@ -217,7 +191,7 @@ static void spi_setup_type(struct spi_trans *trans, int data_bytes)
{
trans->type = 0xFF;
- /* Try to guess spi type from read/write sizes. */
+ /* Try to guess spi type from read/write sizes */
if (trans->bytesin == 0) {
if (trans->bytesout + data_bytes > 4)
/*
@@ -301,7 +275,7 @@ static int spi_setup_opcode(struct ich_spi_priv *ctlr, struct spi_trans *trans)
static int spi_setup_offset(struct spi_trans *trans)
{
- /* Separate the SPI address and data. */
+ /* Separate the SPI address and data */
switch (trans->type) {
case SPI_OPCODE_TYPE_READ_NO_ADDRESS:
case SPI_OPCODE_TYPE_WRITE_NO_ADDRESS:
@@ -410,7 +384,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
trans->in = din;
trans->bytesin = din ? bytes : 0;
- /* There has to always at least be an opcode. */
+ /* There has to always at least be an opcode */
if (!trans->bytesout) {
debug("ICH SPI: No opcode for transfer\n");
return -EPROTO;
@@ -420,7 +394,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
if (ret < 0)
return ret;
- if (plat->ich_version == PCHV_7)
+ if (plat->ich_version == ICHV_7)
ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
else
ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
@@ -541,7 +515,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
/* write it */
ich_writew(ctlr, control, ctlr->control);
- /* Wait for Cycle Done Status or Flash Cycle Error. */
+ /* Wait for Cycle Done Status or Flash Cycle Error */
status = ich_status_poll(ctlr, SPIS_CDS | SPIS_FCERR, 1);
if (status < 0)
return status;
@@ -622,9 +596,6 @@ static int ich_spi_probe(struct udevice *dev)
uint8_t bios_cntl;
int ret;
- /* Check the ICH version */
- plat->ich_version = pch_get_version(dev->parent);
-
ret = ich_init_controller(dev, plat, priv);
if (ret)
return ret;
@@ -678,7 +649,7 @@ static int ich_spi_child_pre_probe(struct udevice *dev)
* ICH 7 SPI controller only supports array read command
* and byte program command for SST flash
*/
- if (plat->ich_version == PCHV_7) {
+ if (plat->ich_version == ICHV_7) {
slave->mode_rx = SPI_RX_SLOW;
slave->mode = SPI_TX_BYTE;
}
@@ -686,6 +657,25 @@ static int ich_spi_child_pre_probe(struct udevice *dev)
return 0;
}
+static int ich_spi_ofdata_to_platdata(struct udevice *dev)
+{
+ struct ich_spi_platdata *plat = dev_get_platdata(dev);
+ int ret;
+
+ ret = fdt_node_check_compatible(gd->fdt_blob, dev->of_offset,
+ "intel,ich7-spi");
+ if (ret == 0) {
+ plat->ich_version = ICHV_7;
+ } else {
+ ret = fdt_node_check_compatible(gd->fdt_blob, dev->of_offset,
+ "intel,ich9-spi");
+ if (ret == 0)
+ plat->ich_version = ICHV_9;
+ }
+
+ return ret;
+}
+
static const struct dm_spi_ops ich_spi_ops = {
.xfer = ich_spi_xfer,
.set_speed = ich_spi_set_speed,
@@ -697,7 +687,8 @@ static const struct dm_spi_ops ich_spi_ops = {
};
static const struct udevice_id ich_spi_ids[] = {
- { .compatible = "intel,ich-spi" },
+ { .compatible = "intel,ich7-spi" },
+ { .compatible = "intel,ich9-spi" },
{ }
};
@@ -706,6 +697,7 @@ U_BOOT_DRIVER(ich_spi) = {
.id = UCLASS_SPI,
.of_match = ich_spi_ids,
.ops = &ich_spi_ops,
+ .ofdata_to_platdata = ich_spi_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct ich_spi_platdata),
.priv_auto_alloc_size = sizeof(struct ich_spi_priv),
.child_pre_probe = ich_spi_child_pre_probe,
diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
index 1419b23e119..bd0a8208096 100644
--- a/drivers/spi/ich.h
+++ b/drivers/spi/ich.h
@@ -6,6 +6,9 @@
* This file is derived from the flashrom project.
*/
+#ifndef _ICH_H_
+#define _ICH_H_
+
struct ich7_spi_regs {
uint16_t spis;
uint16_t spic;
@@ -19,34 +22,34 @@ struct ich7_spi_regs {
} __packed;
struct ich9_spi_regs {
- uint32_t bfpr; /* 0x00 */
+ uint32_t bfpr; /* 0x00 */
uint16_t hsfs;
uint16_t hsfc;
uint32_t faddr;
uint32_t _reserved0;
- uint32_t fdata[16]; /* 0x10 */
- uint32_t frap; /* 0x50 */
+ uint32_t fdata[16]; /* 0x10 */
+ uint32_t frap; /* 0x50 */
uint32_t freg[5];
uint32_t _reserved1[3];
- uint32_t pr[5]; /* 0x74 */
+ uint32_t pr[5]; /* 0x74 */
uint32_t _reserved2[2];
- uint8_t ssfs; /* 0x90 */
+ uint8_t ssfs; /* 0x90 */
uint8_t ssfc[3];
- uint16_t preop; /* 0x94 */
+ uint16_t preop; /* 0x94 */
uint16_t optype;
- uint8_t opmenu[8]; /* 0x98 */
+ uint8_t opmenu[8]; /* 0x98 */
uint32_t bbar;
uint8_t _reserved3[12];
- uint32_t fdoc; /* 0xb0 */
+ uint32_t fdoc; /* 0xb0 */
uint32_t fdod;
uint8_t _reserved4[8];
- uint32_t afc; /* 0xc0 */
+ uint32_t afc; /* 0xc0 */
uint32_t lvscc;
uint32_t uvscc;
uint8_t _reserved5[4];
- uint32_t fpb; /* 0xd0 */
+ uint32_t fpb; /* 0xd0 */
uint8_t _reserved6[28];
- uint32_t srdl; /* 0xf0 */
+ uint32_t srdl; /* 0xf0 */
uint32_t srdc;
uint32_t scs;
uint32_t bcr;
@@ -121,8 +124,38 @@ struct spi_trans {
uint32_t offset;
};
-struct ich_spi_slave {
- struct spi_slave slave;
+#define SPI_OPCODE_WREN 0x06
+#define SPI_OPCODE_FAST_READ 0x0b
+
+enum ich_version {
+ ICHV_7,
+ ICHV_9,
+};
+
+struct ich_spi_platdata {
+ enum ich_version ich_version; /* Controller version, 7 or 9 */
+};
+
+struct ich_spi_priv {
+ int ichspi_lock;
+ int locked;
+ int opmenu;
+ int menubytes;
+ void *base; /* Base of register set */
+ int preop;
+ int optype;
+ int addr;
+ int data;
+ unsigned databytes;
+ int status;
+ int control;
+ int bbar;
+ int bcr;
+ uint32_t *pr; /* only for ich9 */
+ int speed; /* pointer to speed control */
+ ulong max_speed; /* Maximum bus speed in MHz */
+ ulong cur_speed; /* Current bus speed */
struct spi_trans trans; /* current transaction in progress */
- int speed; /* SPI speed in Hz */
};
+
+#endif /* _ICH_H_ */
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index a13b21d0a0f..60f9272ae6d 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -2,7 +2,7 @@
* composite.c - infrastructure for Composite USB Gadgets
*
* Copyright (C) 2006-2008 David Brownell
- * U-boot porting: Lukasz Majewski <l.majewski@samsung.com>
+ * U-Boot porting: Lukasz Majewski <l.majewski@samsung.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index 014a6791c17..64284b06f83 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -5,7 +5,7 @@
*
* SPDX-License-Identifier: GPL-2.0+
*
- * Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and
+ * Ported to U-Boot by: Thomas Smits <ts.smits@gmail.com> and
* Remy Bohmer <linux@bohmer.net>
*/
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index ffe2952f56b..cb20b00a56b 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -557,8 +557,8 @@ static int dwc2_ep_enable(struct usb_ep *_ep,
}
/* hardware _could_ do smaller, but driver doesn't */
- if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
- && le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)) !=
+ if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK &&
+ le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)) >
ep_maxpacket(ep)) || !get_unaligned(&desc->wMaxPacketSize)) {
debug("%s: bad %s maxpacket\n", __func__, _ep->name);
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 6ddbe83deba..a53a6dcda33 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -7,7 +7,7 @@
*
* SPDX-License-Identifier: GPL-2.0+
*
- * Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and
+ * Ported to U-Boot by: Thomas Smits <ts.smits@gmail.com> and
* Remy Bohmer <linux@bohmer.net>
*/
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index cfe9a24e24f..9b06f028d60 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -256,7 +256,7 @@ static inline int BITRATE(struct usb_gadget *g)
#if defined(CONFIG_USBNET_MANUFACTURER)
static char *iManufacturer = CONFIG_USBNET_MANUFACTURER;
#else
-static char *iManufacturer = "U-boot";
+static char *iManufacturer = "U-Boot";
#endif
/* These probably need to be configurable. */
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index e9811c3864e..973cd971ad1 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -11,7 +11,7 @@
* Some are available on 2.4 kernels; several are available, but not
* yet pushed in the 2.6 mainline tree.
*
- * Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and
+ * Ported to U-Boot by: Thomas Smits <ts.smits@gmail.com> and
* Remy Bohmer <linux@bohmer.net>
*/
#ifdef CONFIG_USB_GADGET_NET2280
diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
index 8c3ff64fe35..3e24fbf80ea 100644
--- a/drivers/usb/gadget/usbstring.c
+++ b/drivers/usb/gadget/usbstring.c
@@ -3,7 +3,7 @@
*
* SPDX-License-Identifier: LGPL-2.1+
*
- * Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and
+ * Ported to U-Boot by: Thomas Smits <ts.smits@gmail.com> and
* Remy Bohmer <linux@bohmer.net>
*/
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 39f7185e860..93323741938 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -74,13 +74,6 @@ config USB_EHCI_MX6
---help---
Enables support for the on-chip EHCI controller on i.MX6 SoCs.
-config USB_EHCI_UNIPHIER
- bool "Support for UniPhier on-chip EHCI USB controller"
- depends on ARCH_UNIPHIER && OF_CONTROL
- default y
- ---help---
- Enables support for the on-chip EHCI controller on UniPhier SoCs.
-
config USB_EHCI_GENERIC
bool "Support for generic EHCI USB controller"
depends on OF_CONTROL
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 6183b80c75b..9a87d2bf62d 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -47,7 +47,6 @@ obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
obj-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o
obj-$(CONFIG_USB_EHCI_SUNXI) += ehci-sunxi.o
obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o
-obj-$(CONFIG_USB_EHCI_UNIPHIER) += ehci-uniphier.o
obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o
obj-$(CONFIG_USB_EHCI_VF) += ehci-vf.o
obj-$(CONFIG_USB_EHCI_RMOBILE) += ehci-rmobile.o
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 9a8f004eceb..1d7d28048bc 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -7,44 +7,21 @@
*/
#include <common.h>
-#include <watchdog.h>
#include <usb.h>
#include <asm/io.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/at91_pmc.h>
#include <asm/arch/clk.h>
#include "ehci.h"
-/* Enable UTMI PLL time out 500us
- * 10 times as datasheet specified
- */
-#define EN_UPLL_TIMEOUT 500UL
-
int ehci_hcd_init(int index, enum usb_init_type init,
struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
- at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
- ulong start_time, tmp_time;
-
- start_time = get_timer(0);
/* Enable UTMI PLL */
- writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr);
- while ((readl(&pmc->sr) & AT91_PMC_LOCKU) != AT91_PMC_LOCKU) {
- WATCHDOG_RESET();
- tmp_time = get_timer(0);
- if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) {
- printf("ERROR: failed to enable UPLL\n");
- return -1;
- }
- }
+ if (at91_upll_clk_enable())
+ return -1;
/* Enable USB Host clock */
-#ifdef CPU_HAS_PCR
at91_periph_clk_enable(ATMEL_ID_UHPHS);
-#else
- writel(1 << ATMEL_ID_UHPHS, &pmc->pcer);
-#endif
*hccr = (struct ehci_hccr *)ATMEL_BASE_EHCI;
*hcor = (struct ehci_hcor *)((uint32_t)*hccr +
@@ -55,27 +32,12 @@ int ehci_hcd_init(int index, enum usb_init_type init,
int ehci_hcd_stop(int index)
{
- at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
- ulong start_time, tmp_time;
-
/* Disable USB Host Clock */
-#ifdef CPU_HAS_PCR
at91_periph_clk_disable(ATMEL_ID_UHPHS);
-#else
- writel(1 << ATMEL_ID_UHPHS, &pmc->pcdr);
-#endif
- start_time = get_timer(0);
/* Disable UTMI PLL */
- writel(readl(&pmc->uckr) & ~AT91_PMC_UPLLEN, &pmc->uckr);
- while ((readl(&pmc->sr) & AT91_PMC_LOCKU) == AT91_PMC_LOCKU) {
- WATCHDOG_RESET();
- tmp_time = get_timer(0);
- if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) {
- printf("ERROR: failed to stop UPLL\n");
- return -1;
- }
- }
+ if (at91_upll_clk_disable())
+ return -1;
return 0;
}
diff --git a/drivers/usb/host/ehci-uniphier.c b/drivers/usb/host/ehci-uniphier.c
deleted file mode 100644
index c3f827ca0ae..00000000000
--- a/drivers/usb/host/ehci-uniphier.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <usb.h>
-#include <mach/mio-regs.h>
-#include <fdtdec.h>
-#include "ehci.h"
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define FDT gd->fdt_blob
-#define COMPAT "socionext,uniphier-ehci"
-
-static int get_uniphier_ehci_base(int index, struct ehci_hccr **base)
-{
- int offset;
-
- for (offset = fdt_node_offset_by_compatible(FDT, 0, COMPAT);
- offset >= 0;
- offset = fdt_node_offset_by_compatible(FDT, offset, COMPAT)) {
- if (index == 0) {
- *base = (struct ehci_hccr *)
- fdtdec_get_addr(FDT, offset, "reg");
- return 0;
- }
- index--;
- }
-
- return -ENODEV; /* not found */
-}
-
-static void uniphier_ehci_reset(int index, int on)
-{
- u32 tmp;
-
- tmp = readl(MIO_USB_RSTCTRL(index));
- if (on)
- tmp &= ~MIO_USB_RSTCTRL_XRST;
- else
- tmp |= MIO_USB_RSTCTRL_XRST;
- writel(tmp, MIO_USB_RSTCTRL(index));
-}
-
-int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr,
- struct ehci_hcor **hcor)
-{
- int ret;
- struct ehci_hccr *cr;
- struct ehci_hcor *or;
-
- uniphier_ehci_reset(index, 0);
-
- ret = get_uniphier_ehci_base(index, &cr);
- if (ret < 0)
- return ret;
- or = (void *)cr + HC_LENGTH(ehci_readl(&cr->cr_capbase));
-
- *hccr = cr;
- *hcor = or;
-
- return 0;
-}
-
-int ehci_hcd_stop(int index)
-{
- uniphier_ehci_reset(index, 1);
-
- return 0;
-}
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 820e2e56ef4..e030a0ab147 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -9,45 +9,29 @@
#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT)
-#include <asm/io.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/at91_pmc.h>
#include <asm/arch/clk.h>
int usb_cpu_init(void)
{
- at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
-
#ifdef CONFIG_USB_ATMEL_CLK_SEL_PLLB
- /* Enable PLLB */
- writel(get_pllb_init(), &pmc->pllbr);
- while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB)
- ;
+ if (at91_pllb_clk_enable(get_pllb_init()))
+ return -1;
+
#ifdef CONFIG_AT91SAM9N12
- writel(AT91_PMC_USBS_USB_PLLB | AT91_PMC_USB_DIV_2, &pmc->usb);
+ at91_usb_clk_init(AT91_PMC_USBS_USB_PLLB | AT91_PMC_USB_DIV_2);
#endif
#elif defined(CONFIG_USB_ATMEL_CLK_SEL_UPLL)
- /* Enable UPLL */
- writel(readl(&pmc->uckr) | AT91_PMC_UPLLEN | AT91_PMC_BIASEN,
- &pmc->uckr);
- while ((readl(&pmc->sr) & AT91_PMC_LOCKU) != AT91_PMC_LOCKU)
- ;
-
- /* Select PLLA as input clock of OHCI */
- writel(AT91_PMC_USBS_USB_UPLL | AT91_PMC_USBDIV_10, &pmc->usb);
+ if (at91_upll_clk_enable())
+ return -1;
+
+ at91_usb_clk_init(AT91_PMC_USBS_USB_UPLL | AT91_PMC_USBDIV_10);
#endif
- /* Enable USB host clock. */
-#ifdef CPU_HAS_PCR
at91_periph_clk_enable(ATMEL_ID_UHP);
-#else
- writel(1 << ATMEL_ID_UHP, &pmc->pcer);
-#endif
+ at91_system_clk_enable(ATMEL_PMC_UHP);
#if defined(CONFIG_AT91SAM9261) || defined(CONFIG_AT91SAM9G10)
- writel(ATMEL_PMC_UHP | AT91_PMC_HCK0, &pmc->scer);
-#else
- writel(ATMEL_PMC_UHP, &pmc->scer);
+ at91_system_clk_enable(AT91_PMC_HCK0);
#endif
return 0;
@@ -55,34 +39,24 @@ int usb_cpu_init(void)
int usb_cpu_stop(void)
{
- at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
-
- /* Disable USB host clock. */
-#ifdef CPU_HAS_PCR
at91_periph_clk_disable(ATMEL_ID_UHP);
-#else
- writel(1 << ATMEL_ID_UHP, &pmc->pcdr);
-#endif
+ at91_system_clk_disable(ATMEL_PMC_UHP);
#if defined(CONFIG_AT91SAM9261) || defined(CONFIG_AT91SAM9G10)
- writel(ATMEL_PMC_UHP | AT91_PMC_HCK0, &pmc->scdr);
-#else
- writel(ATMEL_PMC_UHP, &pmc->scdr);
+ at91_system_clk_disable(AT91_PMC_HCK0);
#endif
#ifdef CONFIG_USB_ATMEL_CLK_SEL_PLLB
#ifdef CONFIG_AT91SAM9N12
- writel(0, &pmc->usb);
+ at91_usb_clk_init(0);
#endif
- /* Disable PLLB */
- writel(0, &pmc->pllbr);
- while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != 0)
- ;
+
+ if (at91_pllb_clk_disable())
+ return -1;
+
#elif defined(CONFIG_USB_ATMEL_CLK_SEL_UPLL)
- /* Disable UPLL */
- writel(readl(&pmc->uckr) & (~AT91_PMC_UPLLEN), &pmc->uckr);
- while ((readl(&pmc->sr) & AT91_PMC_LOCKU) == AT91_PMC_LOCKU)
- ;
+ if (at91_upll_clk_disable())
+ return -1;
#endif
return 0;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index fbc5d7cfe7e..ff4179fcd89 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -91,6 +91,16 @@ config CONSOLE_TRUETYPE_SIZE
source "drivers/video/fonts/Kconfig"
+config VIDCONSOLE_AS_LCD
+ bool "Use 'vidconsole' when 'lcd' is seen in stdout"
+ depends on DM_VIDEO
+ help
+ This is a work-around for boards which have 'lcd' in their stdout
+ environment variable, but have moved to use driver model for video.
+ In this case the console will no-longer work. While it is possible
+ to update the environment, the breakage may be confusing for users.
+ This option will be removed around the end of 2016.
+
config VIDEO_VESA
bool "Enable VESA video driver support"
default n
@@ -371,8 +381,18 @@ config VIDEO_SANDBOX_SDL
console device and can display stdout output. Within U-Boot is is
a normal bitmap display and can display images as well as text.
+config VIDEO_TEGRA20
+ bool "Enable LCD support on Tegra20"
+ depends on OF_CONTROL
+ help
+ Tegra20 supports video output to an attached LCD panel as well as
+ other options such as HDMI. Only the LCD is supported in U-Boot.
+ This option enables this support which can be used on devices which
+ have an LCD display connected.
+
config VIDEO_TEGRA124
bool "Enable video support on Tegra124"
+ depends on DM_VIDEO
help
Tegra124 supports many video output options including eDP and
HDMI. At present only eDP is supported by U-Boot. This option
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index c55e6eda3b9..d19a1d9042b 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -57,7 +57,7 @@ obj-$(CONFIG_VIDEO_SED13806) += sed13806.o
obj-$(CONFIG_VIDEO_SM501) += sm501.o
obj-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o
obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o videomodes.o
-obj-$(CONFIG_VIDEO_TEGRA) += tegra.o
+obj-$(CONFIG_VIDEO_TEGRA20) += tegra.o
obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
obj-$(CONFIG_VIDEO_VESA) += vesa_fb.o
obj-$(CONFIG_FORMIKE) += formike.o
diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c
index 7867fe3895d..bff1fcb9eaf 100644
--- a/drivers/video/bcm2835.c
+++ b/drivers/video/bcm2835.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <lcd.h>
#include <memalign.h>
+#include <phys2bus.h>
#include <asm/arch/mbox.h>
#include <asm/global_data.h>
@@ -103,7 +104,8 @@ void lcd_ctrl_init(void *lcdbase)
panel_info.vl_row = h;
panel_info.vl_bpix = LCD_COLOR16;
- gd->fb_base = msg_setup->allocate_buffer.body.resp.fb_address;
+ gd->fb_base = bus_to_phys(
+ msg_setup->allocate_buffer.body.resp.fb_address);
}
void lcd_enable(void)
diff --git a/drivers/video/simple_panel.c b/drivers/video/simple_panel.c
index b1615176748..c73f24295a4 100644
--- a/drivers/video/simple_panel.c
+++ b/drivers/video/simple_panel.c
@@ -85,6 +85,7 @@ static const struct panel_ops simple_panel_ops = {
static const struct udevice_id simple_panel_ids[] = {
{ .compatible = "simple-panel" },
+ { .compatible = "auo,b133xtn01" },
{ }
};
diff --git a/drivers/video/tegra.c b/drivers/video/tegra.c
index 8e8134614e3..7fd10e6af35 100644
--- a/drivers/video/tegra.c
+++ b/drivers/video/tegra.c
@@ -4,11 +4,13 @@
*/
#include <common.h>
+#include <dm.h>
#include <fdtdec.h>
-#include <lcd.h>
-
+#include <pwm.h>
+#include <video.h>
#include <asm/system.h>
#include <asm/gpio.h>
+#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/funcmux.h>
@@ -30,165 +32,347 @@ enum stage_t {
STAGE_DONE,
};
-static enum stage_t stage; /* Current stage we are at */
-static unsigned long timer_next; /* Time we can move onto next stage */
+#define FDT_LCD_TIMINGS 4
+
+enum {
+ FDT_LCD_TIMING_REF_TO_SYNC,
+ FDT_LCD_TIMING_SYNC_WIDTH,
+ FDT_LCD_TIMING_BACK_PORCH,
+ FDT_LCD_TIMING_FRONT_PORCH,
+
+ FDT_LCD_TIMING_COUNT,
+};
+
+enum lcd_cache_t {
+ FDT_LCD_CACHE_OFF = 0,
+ FDT_LCD_CACHE_WRITE_THROUGH = 1 << 0,
+ FDT_LCD_CACHE_WRITE_BACK = 1 << 1,
+ FDT_LCD_CACHE_FLUSH = 1 << 2,
+ FDT_LCD_CACHE_WRITE_BACK_FLUSH = FDT_LCD_CACHE_WRITE_BACK |
+ FDT_LCD_CACHE_FLUSH,
+};
+
+/* Information about the display controller */
+struct tegra_lcd_priv {
+ enum stage_t stage; /* Current stage we are at */
+ unsigned long timer_next; /* Time we can move onto next stage */
+ int width; /* width in pixels */
+ int height; /* height in pixels */
-/* Our LCD config, set up in handle_stage() */
-static struct fdt_panel_config config;
-struct fdt_disp_config *disp_config; /* Display controller config */
+ /*
+ * log2 of number of bpp, in general, unless it bpp is 24 in which
+ * case this field holds 24 also! This is a U-Boot thing.
+ */
+ int log2_bpp;
+ struct disp_ctlr *disp; /* Display controller to use */
+ fdt_addr_t frame_buffer; /* Address of frame buffer */
+ unsigned pixel_clock; /* Pixel clock in Hz */
+ uint horiz_timing[FDT_LCD_TIMING_COUNT]; /* Horizontal timing */
+ uint vert_timing[FDT_LCD_TIMING_COUNT]; /* Vertical timing */
+ struct udevice *pwm;
+ int pwm_channel; /* PWM channel to use for backlight */
+ enum lcd_cache_t cache_type;
+
+ struct gpio_desc backlight_en; /* GPIO for backlight enable */
+ struct gpio_desc lvds_shutdown; /* GPIO for lvds shutdown */
+ struct gpio_desc backlight_vdd; /* GPIO for backlight vdd */
+ struct gpio_desc panel_vdd; /* GPIO for panel vdd */
+ /*
+ * Panel required timings
+ * Timing 1: delay between panel_vdd-rise and data-rise
+ * Timing 2: delay between data-rise and backlight_vdd-rise
+ * Timing 3: delay between backlight_vdd and pwm-rise
+ * Timing 4: delay between pwm-rise and backlight_en-rise
+ */
+ uint panel_timings[FDT_LCD_TIMINGS];
+};
enum {
/* Maximum LCD size we support */
LCD_MAX_WIDTH = 1366,
LCD_MAX_HEIGHT = 768,
- LCD_MAX_LOG2_BPP = 4, /* 2^4 = 16 bpp */
+ LCD_MAX_LOG2_BPP = VIDEO_BPP16,
};
-vidinfo_t panel_info = {
- /* Insert a value here so that we don't end up in the BSS */
- .vl_col = -1,
-};
+static void update_window(struct dc_ctlr *dc, struct disp_ctl_win *win)
+{
+ unsigned h_dda, v_dda;
+ unsigned long val;
-#if !CONFIG_IS_ENABLED(OF_CONTROL)
-#error "You must enable CONFIG_OF_CONTROL to get Tegra LCD support"
-#endif
+ val = readl(&dc->cmd.disp_win_header);
+ val |= WINDOW_A_SELECT;
+ writel(val, &dc->cmd.disp_win_header);
-static void update_panel_size(struct fdt_disp_config *config)
-{
- panel_info.vl_col = config->width;
- panel_info.vl_row = config->height;
- panel_info.vl_bpix = config->log2_bpp;
+ writel(win->fmt, &dc->win.color_depth);
+
+ clrsetbits_le32(&dc->win.byte_swap, BYTE_SWAP_MASK,
+ BYTE_SWAP_NOSWAP << BYTE_SWAP_SHIFT);
+
+ val = win->out_x << H_POSITION_SHIFT;
+ val |= win->out_y << V_POSITION_SHIFT;
+ writel(val, &dc->win.pos);
+
+ val = win->out_w << H_SIZE_SHIFT;
+ val |= win->out_h << V_SIZE_SHIFT;
+ writel(val, &dc->win.size);
+
+ val = (win->w * win->bpp / 8) << H_PRESCALED_SIZE_SHIFT;
+ val |= win->h << V_PRESCALED_SIZE_SHIFT;
+ writel(val, &dc->win.prescaled_size);
+
+ writel(0, &dc->win.h_initial_dda);
+ writel(0, &dc->win.v_initial_dda);
+
+ h_dda = (win->w * 0x1000) / max(win->out_w - 1, 1U);
+ v_dda = (win->h * 0x1000) / max(win->out_h - 1, 1U);
+
+ val = h_dda << H_DDA_INC_SHIFT;
+ val |= v_dda << V_DDA_INC_SHIFT;
+ writel(val, &dc->win.dda_increment);
+
+ writel(win->stride, &dc->win.line_stride);
+ writel(0, &dc->win.buf_stride);
+
+ val = WIN_ENABLE;
+ if (win->bpp < 24)
+ val |= COLOR_EXPAND;
+ writel(val, &dc->win.win_opt);
+
+ writel((unsigned long)win->phys_addr, &dc->winbuf.start_addr);
+ writel(win->x, &dc->winbuf.addr_h_offset);
+ writel(win->y, &dc->winbuf.addr_v_offset);
+
+ writel(0xff00, &dc->win.blend_nokey);
+ writel(0xff00, &dc->win.blend_1win);
+
+ val = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
+ val |= GENERAL_UPDATE | WIN_A_UPDATE;
+ writel(val, &dc->cmd.state_ctrl);
}
-/*
- * Main init function called by lcd driver.
- * Inits and then prints test pattern if required.
- */
+static void write_pair(struct tegra_lcd_priv *priv, int item, u32 *reg)
+{
+ writel(priv->horiz_timing[item] |
+ (priv->vert_timing[item] << 16), reg);
+}
-void lcd_ctrl_init(void *lcdbase)
+static int update_display_mode(struct dc_disp_reg *disp,
+ struct tegra_lcd_priv *priv)
{
- int type = DCACHE_OFF;
- int size;
+ unsigned long val;
+ unsigned long rate;
+ unsigned long div;
- assert(disp_config);
+ writel(0x0, &disp->disp_timing_opt);
+ write_pair(priv, FDT_LCD_TIMING_REF_TO_SYNC, &disp->ref_to_sync);
+ write_pair(priv, FDT_LCD_TIMING_SYNC_WIDTH, &disp->sync_width);
+ write_pair(priv, FDT_LCD_TIMING_BACK_PORCH, &disp->back_porch);
+ write_pair(priv, FDT_LCD_TIMING_FRONT_PORCH, &disp->front_porch);
- /* Make sure that we can acommodate the selected LCD */
- assert(disp_config->width <= LCD_MAX_WIDTH);
- assert(disp_config->height <= LCD_MAX_HEIGHT);
- assert(disp_config->log2_bpp <= LCD_MAX_LOG2_BPP);
- if (disp_config->width <= LCD_MAX_WIDTH
- && disp_config->height <= LCD_MAX_HEIGHT
- && disp_config->log2_bpp <= LCD_MAX_LOG2_BPP)
- update_panel_size(disp_config);
- size = lcd_get_size(&lcd_line_length);
+ writel(priv->width | (priv->height << 16), &disp->disp_active);
- /* Set up the LCD caching as requested */
- if (config.cache_type & FDT_LCD_CACHE_WRITE_THROUGH)
- type = DCACHE_WRITETHROUGH;
- else if (config.cache_type & FDT_LCD_CACHE_WRITE_BACK)
- type = DCACHE_WRITEBACK;
- mmu_set_region_dcache_behaviour(disp_config->frame_buffer, size, type);
+ val = DE_SELECT_ACTIVE << DE_SELECT_SHIFT;
+ val |= DE_CONTROL_NORMAL << DE_CONTROL_SHIFT;
+ writel(val, &disp->data_enable_opt);
- /* Enable flushing after LCD writes if requested */
- lcd_set_flush_dcache(config.cache_type & FDT_LCD_CACHE_FLUSH);
+ val = DATA_FORMAT_DF1P1C << DATA_FORMAT_SHIFT;
+ val |= DATA_ALIGNMENT_MSB << DATA_ALIGNMENT_SHIFT;
+ val |= DATA_ORDER_RED_BLUE << DATA_ORDER_SHIFT;
+ writel(val, &disp->disp_interface_ctrl);
+
+ /*
+ * The pixel clock divider is in 7.1 format (where the bottom bit
+ * represents 0.5). Here we calculate the divider needed to get from
+ * the display clock (typically 600MHz) to the pixel clock. We round
+ * up or down as requried.
+ */
+ rate = clock_get_periph_rate(PERIPH_ID_DISP1, CLOCK_ID_CGENERAL);
+ div = ((rate * 2 + priv->pixel_clock / 2) / priv->pixel_clock) - 2;
+ debug("Display clock %lu, divider %lu\n", rate, div);
+
+ writel(0x00010001, &disp->shift_clk_opt);
- debug("LCD frame buffer at %pa\n", &disp_config->frame_buffer);
+ val = PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT;
+ val |= div << SHIFT_CLK_DIVIDER_SHIFT;
+ writel(val, &disp->disp_clk_ctrl);
+
+ return 0;
}
-ulong calc_fbsize(void)
+/* Start up the display and turn on power to PWMs */
+static void basic_init(struct dc_cmd_reg *cmd)
{
- return (panel_info.vl_col * panel_info.vl_row *
- NBITS(panel_info.vl_bpix)) / 8;
+ u32 val;
+
+ writel(0x00000100, &cmd->gen_incr_syncpt_ctrl);
+ writel(0x0000011a, &cmd->cont_syncpt_vsync);
+ writel(0x00000000, &cmd->int_type);
+ writel(0x00000000, &cmd->int_polarity);
+ writel(0x00000000, &cmd->int_mask);
+ writel(0x00000000, &cmd->int_enb);
+
+ val = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE;
+ val |= PW3_ENABLE | PW4_ENABLE | PM0_ENABLE;
+ val |= PM1_ENABLE;
+ writel(val, &cmd->disp_pow_ctrl);
+
+ val = readl(&cmd->disp_cmd);
+ val |= CTRL_MODE_C_DISPLAY << CTRL_MODE_SHIFT;
+ writel(val, &cmd->disp_cmd);
}
-void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
+static void basic_init_timer(struct dc_disp_reg *disp)
{
+ writel(0x00000020, &disp->mem_high_pri);
+ writel(0x00000001, &disp->mem_high_pri_timer);
}
-void tegra_lcd_early_init(const void *blob)
+static const u32 rgb_enb_tab[PIN_REG_COUNT] = {
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const u32 rgb_polarity_tab[PIN_REG_COUNT] = {
+ 0x00000000,
+ 0x01000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const u32 rgb_data_tab[PIN_REG_COUNT] = {
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+};
+
+static const u32 rgb_sel_tab[PIN_OUTPUT_SEL_COUNT] = {
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00210222,
+ 0x00002200,
+ 0x00020000,
+};
+
+static void rgb_enable(struct dc_com_reg *com)
{
- /*
- * Go with the maximum size for now. We will fix this up after
- * relocation. These values are only used for memory alocation.
- */
- panel_info.vl_col = LCD_MAX_WIDTH;
- panel_info.vl_row = LCD_MAX_HEIGHT;
- panel_info.vl_bpix = LCD_MAX_LOG2_BPP;
+ int i;
+
+ for (i = 0; i < PIN_REG_COUNT; i++) {
+ writel(rgb_enb_tab[i], &com->pin_output_enb[i]);
+ writel(rgb_polarity_tab[i], &com->pin_output_polarity[i]);
+ writel(rgb_data_tab[i], &com->pin_output_data[i]);
+ }
+
+ for (i = 0; i < PIN_OUTPUT_SEL_COUNT; i++)
+ writel(rgb_sel_tab[i], &com->pin_output_sel[i]);
+}
+
+static int setup_window(struct disp_ctl_win *win,
+ struct tegra_lcd_priv *priv)
+{
+ win->x = 0;
+ win->y = 0;
+ win->w = priv->width;
+ win->h = priv->height;
+ win->out_x = 0;
+ win->out_y = 0;
+ win->out_w = priv->width;
+ win->out_h = priv->height;
+ win->phys_addr = priv->frame_buffer;
+ win->stride = priv->width * (1 << priv->log2_bpp) / 8;
+ debug("%s: depth = %d\n", __func__, priv->log2_bpp);
+ switch (priv->log2_bpp) {
+ case 5:
+ case 24:
+ win->fmt = COLOR_DEPTH_R8G8B8A8;
+ win->bpp = 32;
+ break;
+ case 4:
+ win->fmt = COLOR_DEPTH_B5G6R5;
+ win->bpp = 16;
+ break;
+
+ default:
+ debug("Unsupported LCD bit depth");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void debug_timing(const char *name, unsigned int timing[])
+{
+#ifdef DEBUG
+ int i;
+
+ debug("%s timing: ", name);
+ for (i = 0; i < FDT_LCD_TIMING_COUNT; i++)
+ debug("%d ", timing[i]);
+ debug("\n");
+#endif
}
/**
- * Decode the panel information from the fdt.
+ * Register a new display based on device tree configuration.
*
- * @param blob fdt blob
- * @param config structure to store fdt config into
- * @return 0 if ok, -ve on error
+ * The frame buffer can be positioned by U-Boot or overriden by the fdt.
+ * You should pass in the U-Boot address here, and check the contents of
+ * struct tegra_lcd_priv to see what was actually chosen.
+ *
+ * @param blob Device tree blob
+ * @param priv Driver's private data
+ * @param default_lcd_base Default address of LCD frame buffer
+ * @return 0 if ok, -1 on error (unsupported bits per pixel)
*/
-static int fdt_decode_lcd(const void *blob, struct fdt_panel_config *config)
+static int tegra_display_probe(const void *blob, struct tegra_lcd_priv *priv,
+ void *default_lcd_base)
{
- int display_node;
+ struct disp_ctl_win window;
+ struct dc_ctlr *dc;
- disp_config = tegra_display_get_config();
- if (!disp_config) {
- debug("%s: Display controller is not configured\n", __func__);
- return -1;
- }
- display_node = disp_config->panel_node;
- if (display_node < 0) {
- debug("%s: No panel configuration available\n", __func__);
- return -1;
- }
+ priv->frame_buffer = (u32)default_lcd_base;
- config->pwm_channel = pwm_request(blob, display_node, "nvidia,pwm");
- if (config->pwm_channel < 0) {
- debug("%s: Unable to request PWM channel\n", __func__);
- return -1;
- }
+ dc = (struct dc_ctlr *)priv->disp;
- config->cache_type = fdtdec_get_int(blob, display_node,
- "nvidia,cache-type",
- FDT_LCD_CACHE_WRITE_BACK_FLUSH);
+ /*
+ * A header file for clock constants was NAKed upstream.
+ * TODO: Put this into the FDT and fdt_lcd struct when we have clock
+ * support there
+ */
+ clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_PERIPH,
+ 144 * 1000000);
+ clock_start_periph_pll(PERIPH_ID_DISP1, CLOCK_ID_CGENERAL,
+ 600 * 1000000);
+ basic_init(&dc->cmd);
+ basic_init_timer(&dc->disp);
+ rgb_enable(&dc->com);
+
+ if (priv->pixel_clock)
+ update_display_mode(&dc->disp, priv);
+
+ if (setup_window(&window, priv))
+ return -1;
- /* These GPIOs are all optional */
- gpio_request_by_name_nodev(blob, display_node,
- "nvidia,backlight-enable-gpios", 0,
- &config->backlight_en, GPIOD_IS_OUT);
- gpio_request_by_name_nodev(blob, display_node,
- "nvidia,lvds-shutdown-gpios", 0,
- &config->lvds_shutdown, GPIOD_IS_OUT);
- gpio_request_by_name_nodev(blob, display_node,
- "nvidia,backlight-vdd-gpios", 0,
- &config->backlight_vdd, GPIOD_IS_OUT);
- gpio_request_by_name_nodev(blob, display_node,
- "nvidia,panel-vdd-gpios", 0,
- &config->panel_vdd, GPIOD_IS_OUT);
+ update_window(dc, &window);
- return fdtdec_get_int_array(blob, display_node, "nvidia,panel-timings",
- config->panel_timings, FDT_LCD_TIMINGS);
+ return 0;
}
/**
* Handle the next stage of device init
*/
-static int handle_stage(const void *blob)
+static int handle_stage(const void *blob, struct tegra_lcd_priv *priv)
{
- debug("%s: stage %d\n", __func__, stage);
+ debug("%s: stage %d\n", __func__, priv->stage);
/* do the things for this stage */
- switch (stage) {
+ switch (priv->stage) {
case STAGE_START:
- /* Initialize the Tegra display controller */
- if (tegra_display_probe(gd->fdt_blob, (void *)gd->fb_base)) {
- printf("%s: Failed to probe display driver\n",
- __func__);
- return -1;
- }
-
- /* get panel details */
- if (fdt_decode_lcd(blob, &config)) {
- printf("No valid LCD information in device tree\n");
- return -1;
- }
-
/*
* It is possible that the FDT has requested that the LCD be
* disabled. We currently don't support this. It would require
@@ -202,52 +386,71 @@ static int handle_stage(const void *blob)
funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT);
break;
case STAGE_PANEL_VDD:
- if (dm_gpio_is_valid(&config.panel_vdd))
- dm_gpio_set_value(&config.panel_vdd, 1);
+ if (dm_gpio_is_valid(&priv->panel_vdd))
+ dm_gpio_set_value(&priv->panel_vdd, 1);
break;
case STAGE_LVDS:
- if (dm_gpio_is_valid(&config.lvds_shutdown))
- dm_gpio_set_value(&config.lvds_shutdown, 1);
+ if (dm_gpio_is_valid(&priv->lvds_shutdown))
+ dm_gpio_set_value(&priv->lvds_shutdown, 1);
break;
case STAGE_BACKLIGHT_VDD:
- if (dm_gpio_is_valid(&config.backlight_vdd))
- dm_gpio_set_value(&config.backlight_vdd, 1);
+ if (dm_gpio_is_valid(&priv->backlight_vdd))
+ dm_gpio_set_value(&priv->backlight_vdd, 1);
break;
case STAGE_PWM:
/* Enable PWM at 15/16 high, 32768 Hz with divider 1 */
pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_PWM);
pinmux_tristate_disable(PMUX_PINGRP_GPU);
- pwm_enable(config.pwm_channel, 32768, 0xdf, 1);
+ pwm_set_config(priv->pwm, priv->pwm_channel, 0xdf, 0xff);
+ pwm_set_enable(priv->pwm, priv->pwm_channel, true);
break;
case STAGE_BACKLIGHT_EN:
- if (dm_gpio_is_valid(&config.backlight_en))
- dm_gpio_set_value(&config.backlight_en, 1);
+ if (dm_gpio_is_valid(&priv->backlight_en))
+ dm_gpio_set_value(&priv->backlight_en, 1);
break;
case STAGE_DONE:
break;
}
/* set up timer for next stage */
- timer_next = timer_get_us();
- if (stage < FDT_LCD_TIMINGS)
- timer_next += config.panel_timings[stage] * 1000;
+ priv->timer_next = timer_get_us();
+ if (priv->stage < FDT_LCD_TIMINGS)
+ priv->timer_next += priv->panel_timings[priv->stage] * 1000;
/* move to next stage */
- stage++;
+ priv->stage++;
return 0;
}
-int tegra_lcd_check_next_stage(const void *blob, int wait)
+/**
+ * Perform the next stage of the LCD init if it is time to do so.
+ *
+ * LCD init can be time-consuming because of the number of delays we need
+ * while waiting for the backlight power supply, etc. This function can
+ * be called at various times during U-Boot operation to advance the
+ * initialization of the LCD to the next stage if sufficient time has
+ * passed since the last stage. It keeps track of what stage it is up to
+ * and the time that it is permitted to move to the next stage.
+ *
+ * The final call should have wait=1 to complete the init.
+ *
+ * @param blob fdt blob containing LCD information
+ * @param wait 1 to wait until all init is complete, and then return
+ * 0 to return immediately, potentially doing nothing if it is
+ * not yet time for the next init.
+ */
+static int tegra_lcd_check_next_stage(const void *blob,
+ struct tegra_lcd_priv *priv, int wait)
{
- if (stage == STAGE_DONE)
+ if (priv->stage == STAGE_DONE)
return 0;
do {
/* wait if we need to */
- debug("%s: stage %d\n", __func__, stage);
- if (stage != STAGE_START) {
- int delay = timer_next - timer_get_us();
+ debug("%s: stage %d\n", __func__, priv->stage);
+ if (priv->stage != STAGE_START) {
+ int delay = priv->timer_next - timer_get_us();
if (delay > 0) {
if (wait)
@@ -257,29 +460,188 @@ int tegra_lcd_check_next_stage(const void *blob, int wait)
}
}
- if (handle_stage(blob))
+ if (handle_stage(blob, priv))
return -1;
- } while (wait && stage != STAGE_DONE);
- if (stage == STAGE_DONE)
+ } while (wait && priv->stage != STAGE_DONE);
+ if (priv->stage == STAGE_DONE)
debug("%s: LCD init complete\n", __func__);
return 0;
}
-void lcd_enable(void)
+static int tegra_lcd_probe(struct udevice *dev)
{
- /*
- * Backlight and power init will be done separately in
- * tegra_lcd_check_next_stage(), which should be called in
- * board_late_init().
- *
- * U-Boot code supports only colour depth, selected at compile time.
- * The device tree setting should match this. Otherwise the display
- * will not look right, and U-Boot may crash.
- */
- if (disp_config->log2_bpp != LCD_BPP) {
- printf("%s: Error: LCD depth configured in FDT (%d = %dbpp)"
- " must match setting of LCD_BPP (%d)\n", __func__,
- disp_config->log2_bpp, disp_config->bpp, LCD_BPP);
+ struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+ struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct tegra_lcd_priv *priv = dev_get_priv(dev);
+ const void *blob = gd->fdt_blob;
+ int type = DCACHE_OFF;
+
+ /* Initialize the Tegra display controller */
+ if (tegra_display_probe(blob, priv, (void *)plat->base)) {
+ printf("%s: Failed to probe display driver\n", __func__);
+ return -1;
}
+
+ tegra_lcd_check_next_stage(blob, priv, 1);
+
+ /* Set up the LCD caching as requested */
+ if (priv->cache_type & FDT_LCD_CACHE_WRITE_THROUGH)
+ type = DCACHE_WRITETHROUGH;
+ else if (priv->cache_type & FDT_LCD_CACHE_WRITE_BACK)
+ type = DCACHE_WRITEBACK;
+ mmu_set_region_dcache_behaviour(priv->frame_buffer, plat->size, type);
+
+ /* Enable flushing after LCD writes if requested */
+ video_set_flush_dcache(dev, priv->cache_type & FDT_LCD_CACHE_FLUSH);
+
+ uc_priv->xsize = priv->width;
+ uc_priv->ysize = priv->height;
+ uc_priv->bpix = priv->log2_bpp;
+ debug("LCD frame buffer at %pa, size %x\n", &priv->frame_buffer,
+ plat->size);
+
+ return 0;
}
+
+static int tegra_lcd_ofdata_to_platdata(struct udevice *dev)
+{
+ struct tegra_lcd_priv *priv = dev_get_priv(dev);
+ struct fdtdec_phandle_args args;
+ const void *blob = gd->fdt_blob;
+ int node = dev->of_offset;
+ int front, back, ref;
+ int panel_node;
+ int rgb;
+ int bpp, bit;
+ int ret;
+
+ priv->disp = (struct disp_ctlr *)dev_get_addr(dev);
+ if (!priv->disp) {
+ debug("%s: No display controller address\n", __func__);
+ return -EINVAL;
+ }
+
+ rgb = fdt_subnode_offset(blob, node, "rgb");
+
+ panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel");
+ if (panel_node < 0) {
+ debug("%s: Cannot find panel information\n", __func__);
+ return -EINVAL;
+ }
+
+ priv->width = fdtdec_get_int(blob, panel_node, "xres", -1);
+ priv->height = fdtdec_get_int(blob, panel_node, "yres", -1);
+ priv->pixel_clock = fdtdec_get_int(blob, panel_node, "clock", 0);
+ if (!priv->pixel_clock || priv->width == -1 || priv->height == -1) {
+ debug("%s: Pixel parameters missing\n", __func__);
+ return -EINVAL;
+ }
+
+ back = fdtdec_get_int(blob, panel_node, "left-margin", -1);
+ front = fdtdec_get_int(blob, panel_node, "right-margin", -1);
+ ref = fdtdec_get_int(blob, panel_node, "hsync-len", -1);
+ if ((back | front | ref) == -1) {
+ debug("%s: Horizontal parameters missing\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Use a ref-to-sync of 1 always, and take this from the front porch */
+ priv->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1;
+ priv->horiz_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref;
+ priv->horiz_timing[FDT_LCD_TIMING_BACK_PORCH] = back;
+ priv->horiz_timing[FDT_LCD_TIMING_FRONT_PORCH] = front -
+ priv->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC];
+ debug_timing("horiz", priv->horiz_timing);
+
+ back = fdtdec_get_int(blob, panel_node, "upper-margin", -1);
+ front = fdtdec_get_int(blob, panel_node, "lower-margin", -1);
+ ref = fdtdec_get_int(blob, panel_node, "vsync-len", -1);
+ if ((back | front | ref) == -1) {
+ debug("%s: Vertical parameters missing\n", __func__);
+ return -EINVAL;
+ }
+
+ priv->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1;
+ priv->vert_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref;
+ priv->vert_timing[FDT_LCD_TIMING_BACK_PORCH] = back;
+ priv->vert_timing[FDT_LCD_TIMING_FRONT_PORCH] = front -
+ priv->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC];
+ debug_timing("vert", priv->vert_timing);
+
+ bpp = fdtdec_get_int(blob, panel_node, "nvidia,bits-per-pixel", -1);
+ bit = ffs(bpp) - 1;
+ if (bpp == (1 << bit))
+ priv->log2_bpp = bit;
+ else
+ priv->log2_bpp = bpp;
+ if (bpp == -1) {
+ debug("%s: Pixel bpp parameters missing\n", __func__);
+ return -EINVAL;
+ }
+
+ if (fdtdec_parse_phandle_with_args(blob, panel_node, "nvidia,pwm",
+ "#pwm-cells", 0, 0, &args)) {
+ debug("%s: Unable to decode PWM\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = uclass_get_device_by_of_offset(UCLASS_PWM, args.node, &priv->pwm);
+ if (ret) {
+ debug("%s: Unable to find PWM\n", __func__);
+ return -EINVAL;
+ }
+ priv->pwm_channel = args.args[0];
+
+ priv->cache_type = fdtdec_get_int(blob, panel_node, "nvidia,cache-type",
+ FDT_LCD_CACHE_WRITE_BACK_FLUSH);
+
+ /* These GPIOs are all optional */
+ gpio_request_by_name_nodev(blob, panel_node,
+ "nvidia,backlight-enable-gpios", 0,
+ &priv->backlight_en, GPIOD_IS_OUT);
+ gpio_request_by_name_nodev(blob, panel_node,
+ "nvidia,lvds-shutdown-gpios", 0,
+ &priv->lvds_shutdown, GPIOD_IS_OUT);
+ gpio_request_by_name_nodev(blob, panel_node,
+ "nvidia,backlight-vdd-gpios", 0,
+ &priv->backlight_vdd, GPIOD_IS_OUT);
+ gpio_request_by_name_nodev(blob, panel_node,
+ "nvidia,panel-vdd-gpios", 0,
+ &priv->panel_vdd, GPIOD_IS_OUT);
+
+ if (fdtdec_get_int_array(blob, panel_node, "nvidia,panel-timings",
+ priv->panel_timings, FDT_LCD_TIMINGS))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int tegra_lcd_bind(struct udevice *dev)
+{
+ struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+
+ plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
+ (1 << LCD_MAX_LOG2_BPP) / 8;
+
+ return 0;
+}
+
+static const struct video_ops tegra_lcd_ops = {
+};
+
+static const struct udevice_id tegra_lcd_ids[] = {
+ { .compatible = "nvidia,tegra20-dc" },
+ { }
+};
+
+U_BOOT_DRIVER(tegra_lcd) = {
+ .name = "tegra_lcd",
+ .id = UCLASS_VIDEO,
+ .of_match = tegra_lcd_ids,
+ .ops = &tegra_lcd_ops,
+ .bind = tegra_lcd_bind,
+ .probe = tegra_lcd_probe,
+ .ofdata_to_platdata = tegra_lcd_ofdata_to_platdata,
+ .priv_auto_alloc_size = sizeof(struct tegra_lcd_priv),
+};
diff --git a/drivers/video/tegra124/Makefile b/drivers/video/tegra124/Makefile
index 52eedb0f08c..4287b9a25fd 100644
--- a/drivers/video/tegra124/Makefile
+++ b/drivers/video/tegra124/Makefile
@@ -7,4 +7,3 @@
obj-y += display.o
obj-y += dp.o
obj-y += sor.o
-obj-y += tegra124-lcd.o
diff --git a/drivers/video/tegra124/display.c b/drivers/video/tegra124/display.c
index 610ffa9684b..2f1f0df20eb 100644
--- a/drivers/video/tegra124/display.c
+++ b/drivers/video/tegra124/display.c
@@ -14,11 +14,13 @@
#include <edid.h>
#include <fdtdec.h>
#include <lcd.h>
+#include <video.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/pwm.h>
#include <asm/arch-tegra/dc.h>
+#include <dm/uclass-internal.h>
#include "displayport.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -333,73 +335,46 @@ static int display_update_config_from_edid(struct udevice *dp_dev,
return 0;
}
-/* Somewhat torturous method */
-static int get_backlight_info(const void *blob, struct gpio_desc *vdd,
- struct gpio_desc *enable, int *pwmp)
-{
- int sor, panel, backlight, power;
- const u32 *prop;
- int len;
- int ret;
-
- *pwmp = 0;
- sor = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_SOR);
- if (sor < 0)
- return -ENOENT;
- panel = fdtdec_lookup_phandle(blob, sor, "nvidia,panel");
- if (panel < 0)
- return -ENOENT;
- backlight = fdtdec_lookup_phandle(blob, panel, "backlight");
- if (backlight < 0)
- return -ENOENT;
- ret = gpio_request_by_name_nodev(blob, backlight, "enable-gpios", 0,
- enable, GPIOD_IS_OUT);
- if (ret)
- return ret;
- prop = fdt_getprop(blob, backlight, "pwms", &len);
- if (!prop || len != 3 * sizeof(u32))
- return -EINVAL;
- *pwmp = fdt32_to_cpu(prop[1]);
-
- power = fdtdec_lookup_phandle(blob, backlight, "power-supply");
- if (power < 0)
- return -ENOENT;
- ret = gpio_request_by_name_nodev(blob, power, "gpio", 0, vdd,
- GPIOD_IS_OUT);
- if (ret)
- goto err;
-
- return 0;
-
-err:
- dm_gpio_free(NULL, enable);
- return ret;
-}
-
-int display_init(void *lcdbase, int fb_bits_per_pixel,
- struct display_timing *timing)
+static int display_init(struct udevice *dev, void *lcdbase,
+ int fb_bits_per_pixel, struct display_timing *timing)
{
+ struct display_plat *disp_uc_plat;
struct dc_ctlr *dc_ctlr;
const void *blob = gd->fdt_blob;
struct udevice *dp_dev;
const int href_to_sync = 1, vref_to_sync = 1;
int panel_bpp = 18; /* default 18 bits per pixel */
u32 plld_rate;
- struct gpio_desc vdd_gpio, enable_gpio;
- int pwm;
- int node;
int ret;
+ /*
+ * Before we probe the display device (eDP), tell it that this device
+ * is are the source of the display data.
+ */
+ ret = uclass_find_first_device(UCLASS_DISPLAY, &dp_dev);
+ if (ret) {
+ debug("%s: device '%s' display not found (ret=%d)\n", __func__,
+ dev->name, ret);
+ return ret;
+ }
+
+ disp_uc_plat = dev_get_uclass_platdata(dp_dev);
+ debug("Found device '%s', disp_uc_priv=%p\n", dp_dev->name,
+ disp_uc_plat);
+ disp_uc_plat->src_dev = dev;
+
ret = uclass_get_device(UCLASS_DISPLAY, 0, &dp_dev);
- if (ret)
+ if (ret) {
+ debug("%s: Failed to probe eDP, ret=%d\n", __func__, ret);
return ret;
+ }
- node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_DC);
- if (node < 0)
- return -ENOENT;
- dc_ctlr = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg");
- if (fdtdec_decode_display_timing(blob, node, 0, timing))
+ dc_ctlr = (struct dc_ctlr *)fdtdec_get_addr(blob, dev->of_offset,
+ "reg");
+ if (fdtdec_decode_display_timing(blob, dev->of_offset, 0, timing)) {
+ debug("%s: Failed to decode display timing\n", __func__);
return -EINVAL;
+ }
ret = display_update_config_from_edid(dp_dev, &panel_bpp, timing);
if (ret) {
@@ -407,12 +382,6 @@ int display_init(void *lcdbase, int fb_bits_per_pixel,
dump_config(panel_bpp, timing);
}
- if (!get_backlight_info(blob, &vdd_gpio, &enable_gpio, &pwm)) {
- dm_gpio_set_value(&vdd_gpio, 1);
- debug("%s: backlight vdd setting gpio %08x to %d\n",
- __func__, gpio_get_number(&vdd_gpio), 1);
- }
-
/*
* The plld is programmed with the assumption of the SHIFT_CLK_DIVIDER
* and PIXEL_CLK_DIVIDER are zero (divide by 1). See the
@@ -443,22 +412,99 @@ int display_init(void *lcdbase, int fb_bits_per_pixel,
/* Enable dp */
ret = display_enable(dp_dev, panel_bpp, timing);
- if (ret)
+ if (ret) {
+ debug("dc: failed to enable display: ret=%d\n", ret);
return ret;
+ }
ret = update_window(dc_ctlr, (ulong)lcdbase, fb_bits_per_pixel, timing);
+ if (ret) {
+ debug("dc: failed to update window\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+enum {
+ /* Maximum LCD size we support */
+ LCD_MAX_WIDTH = 1920,
+ LCD_MAX_HEIGHT = 1200,
+ LCD_MAX_LOG2_BPP = 4, /* 2^4 = 16 bpp */
+};
+
+static int tegra124_lcd_init(struct udevice *dev, void *lcdbase,
+ enum video_log2_bpp l2bpp)
+{
+ struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct display_timing timing;
+ int ret;
+
+ clock_set_up_plldp();
+ clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_PERIPH, 408000000);
+
+ clock_enable(PERIPH_ID_HOST1X);
+ clock_enable(PERIPH_ID_DISP1);
+ clock_enable(PERIPH_ID_PWM);
+ clock_enable(PERIPH_ID_DPAUX);
+ clock_enable(PERIPH_ID_SOR0);
+ udelay(2);
+
+ reset_set_enable(PERIPH_ID_HOST1X, 0);
+ reset_set_enable(PERIPH_ID_DISP1, 0);
+ reset_set_enable(PERIPH_ID_PWM, 0);
+ reset_set_enable(PERIPH_ID_DPAUX, 0);
+ reset_set_enable(PERIPH_ID_SOR0, 0);
+
+ ret = display_init(dev, lcdbase, 1 << l2bpp, &timing);
if (ret)
return ret;
- /* Set up Tegra PWM to drive the panel backlight */
- pwm_enable(pwm, 0, 220, 0x2e);
- udelay(10 * 1000);
+ uc_priv->xsize = roundup(timing.hactive.typ, 16);
+ uc_priv->ysize = timing.vactive.typ;
+ uc_priv->bpix = l2bpp;
- if (dm_gpio_is_valid(&enable_gpio)) {
- dm_gpio_set_value(&enable_gpio, 1);
- debug("%s: backlight enable setting gpio %08x to %d\n",
- __func__, gpio_get_number(&enable_gpio), 1);
- }
+ video_set_flush_dcache(dev, 1);
+ debug("%s: done\n", __func__);
return 0;
}
+
+static int tegra124_lcd_probe(struct udevice *dev)
+{
+ struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+ ulong start;
+ int ret;
+
+ start = get_timer(0);
+ ret = tegra124_lcd_init(dev, (void *)plat->base, VIDEO_BPP16);
+ debug("LCD init took %lu ms\n", get_timer(start));
+ if (ret)
+ printf("%s: Error %d\n", __func__, ret);
+
+ return 0;
+}
+
+static int tegra124_lcd_bind(struct udevice *dev)
+{
+ struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
+
+ uc_plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
+ (1 << VIDEO_BPP16) / 8;
+ debug("%s: Frame buffer size %x\n", __func__, uc_plat->size);
+
+ return 0;
+}
+
+static const struct udevice_id tegra124_lcd_ids[] = {
+ { .compatible = "nvidia,tegra124-dc" },
+ { }
+};
+
+U_BOOT_DRIVER(tegra124_dc) = {
+ .name = "tegra124-dc",
+ .id = UCLASS_VIDEO,
+ .of_match = tegra124_lcd_ids,
+ .bind = tegra124_lcd_bind,
+ .probe = tegra124_lcd_probe,
+};
diff --git a/drivers/video/tegra124/dp.c b/drivers/video/tegra124/dp.c
index bb1805a2482..5bf8524a5e8 100644
--- a/drivers/video/tegra124/dp.c
+++ b/drivers/video/tegra124/dp.c
@@ -11,6 +11,7 @@
#include <div64.h>
#include <errno.h>
#include <fdtdec.h>
+#include <video_bridge.h>
#include <asm/io.h>
#include <asm/arch-tegra/dc.h>
#include "display.h"
@@ -26,9 +27,15 @@ struct tegra_dp_plat {
ulong base;
};
+/**
+ * struct tegra_dp_priv - private displayport driver info
+ *
+ * @dc_dev: Display controller device that is sending the video feed
+ */
struct tegra_dp_priv {
+ struct udevice *sor;
+ struct udevice *dc_dev;
struct dpaux_ctlr *regs;
- struct tegra_dc_sor_data *sor;
u8 revision;
int enabled;
};
@@ -710,8 +717,8 @@ static int tegra_dc_dp_init_max_link_cfg(
return 0;
}
-static int tegra_dc_dp_set_assr(struct tegra_dp_priv *dp,
- struct tegra_dc_sor_data *sor, int ena)
+static int tegra_dc_dp_set_assr(struct tegra_dp_priv *priv,
+ struct udevice *sor, int ena)
{
int ret;
@@ -719,7 +726,7 @@ static int tegra_dc_dp_set_assr(struct tegra_dp_priv *dp,
DP_MAIN_LINK_CHANNEL_CODING_SET_ASC_RESET_ENABLE :
DP_MAIN_LINK_CHANNEL_CODING_SET_ASC_RESET_DISABLE;
- ret = tegra_dc_dp_dpcd_write(dp, DP_EDP_CONFIGURATION_SET,
+ ret = tegra_dc_dp_dpcd_write(priv, DP_EDP_CONFIGURATION_SET,
dpcd_data);
if (ret)
return ret;
@@ -730,7 +737,7 @@ static int tegra_dc_dp_set_assr(struct tegra_dp_priv *dp,
}
static int tegra_dp_set_link_bandwidth(struct tegra_dp_priv *dp,
- struct tegra_dc_sor_data *sor,
+ struct udevice *sor,
u8 link_bw)
{
tegra_dc_sor_set_link_bandwidth(sor, link_bw);
@@ -741,7 +748,7 @@ static int tegra_dp_set_link_bandwidth(struct tegra_dp_priv *dp,
static int tegra_dp_set_lane_count(struct tegra_dp_priv *dp,
const struct tegra_dp_link_config *link_cfg,
- struct tegra_dc_sor_data *sor)
+ struct udevice *sor)
{
u8 dpcd_data;
int ret;
@@ -1002,7 +1009,7 @@ fail:
static int tegra_dp_lt_config(struct tegra_dp_priv *dp, u32 pe[4], u32 vs[4],
u32 pc[4], const struct tegra_dp_link_config *cfg)
{
- struct tegra_dc_sor_data *sor = dp->sor;
+ struct udevice *sor = dp->sor;
u32 n_lanes = cfg->lane_count;
u8 pc_supported = cfg->tps3_supported;
u32 cnt;
@@ -1186,7 +1193,7 @@ static int tegra_dc_dp_full_link_training(struct tegra_dp_priv *dp,
const struct display_timing *timing,
struct tegra_dp_link_config *cfg)
{
- struct tegra_dc_sor_data *sor = dp->sor;
+ struct udevice *sor = dp->sor;
int err;
u32 pe[4], vs[4], pc[4];
@@ -1229,7 +1236,7 @@ fail:
*/
static int tegra_dc_dp_fast_link_training(struct tegra_dp_priv *dp,
const struct tegra_dp_link_config *link_cfg,
- struct tegra_dc_sor_data *sor)
+ struct udevice *sor)
{
u8 link_bw;
u8 lane_count;
@@ -1301,7 +1308,7 @@ static int tegra_dc_dp_fast_link_training(struct tegra_dp_priv *dp,
static int tegra_dp_do_link_training(struct tegra_dp_priv *dp,
struct tegra_dp_link_config *link_cfg,
const struct display_timing *timing,
- struct tegra_dc_sor_data *sor)
+ struct udevice *sor)
{
u8 link_bw;
u8 lane_count;
@@ -1344,7 +1351,7 @@ static int tegra_dp_do_link_training(struct tegra_dp_priv *dp,
static int tegra_dc_dp_explore_link_cfg(struct tegra_dp_priv *dp,
struct tegra_dp_link_config *link_cfg,
- struct tegra_dc_sor_data *sor,
+ struct udevice *sor,
const struct display_timing *timing)
{
struct tegra_dp_link_config temp_cfg;
@@ -1444,7 +1451,7 @@ static int tegra_dc_dp_check_sink(struct tegra_dp_priv *dp,
printf("DP: Out of sync after %d retries\n", max_retry);
return -EIO;
}
- ret = tegra_dc_sor_detach(dp->sor);
+ ret = tegra_dc_sor_detach(dp->dc_dev, dp->sor);
if (ret)
return ret;
if (tegra_dc_dp_explore_link_cfg(dp, link_cfg, dp->sor,
@@ -1454,7 +1461,7 @@ static int tegra_dc_dp_check_sink(struct tegra_dp_priv *dp,
}
tegra_dc_sor_set_power_state(dp->sor, 1);
- tegra_dc_sor_attach(dp->sor, link_cfg, timing);
+ tegra_dc_sor_attach(dp->dc_dev, dp->sor, link_cfg, timing);
/* Increase delay_frame for next try in case the sink is
skipping more frames */
@@ -1467,7 +1474,7 @@ int tegra_dp_enable(struct udevice *dev, int panel_bpp,
{
struct tegra_dp_priv *priv = dev_get_priv(dev);
struct tegra_dp_link_config slink_cfg, *link_cfg = &slink_cfg;
- struct tegra_dc_sor_data *sor;
+ struct udevice *sor;
int data;
int retry;
int ret;
@@ -1489,9 +1496,11 @@ int tegra_dp_enable(struct udevice *dev, int panel_bpp,
return -ENOLINK;
}
- ret = tegra_dc_sor_init(&sor);
- if (ret)
+ ret = uclass_first_device(UCLASS_VIDEO_BRIDGE, &sor);
+ if (ret || !sor) {
+ debug("dp: failed to find SOR device: ret=%d\n", ret);
return ret;
+ }
priv->sor = sor;
ret = tegra_dc_sor_enable_dp(sor, link_cfg);
if (ret)
@@ -1531,7 +1540,7 @@ int tegra_dp_enable(struct udevice *dev, int panel_bpp,
}
tegra_dc_sor_set_power_state(sor, 1);
- ret = tegra_dc_sor_attach(sor, link_cfg, timing);
+ ret = tegra_dc_sor_attach(priv->dc_dev, sor, link_cfg, timing);
if (ret && ret != -EEXIST)
return ret;
@@ -1548,6 +1557,12 @@ int tegra_dp_enable(struct udevice *dev, int panel_bpp,
/* Power down the unused lanes to save power - a few hundred mW */
tegra_dc_sor_power_down_unused_lanes(sor, link_cfg);
+ ret = video_bridge_set_backlight(sor, 80);
+ if (ret) {
+ debug("dp: failed to set backlight\n");
+ return ret;
+ }
+
priv->enabled = true;
error_enable:
return 0;
@@ -1583,10 +1598,14 @@ static int dp_tegra_probe(struct udevice *dev)
{
struct tegra_dp_plat *plat = dev_get_platdata(dev);
struct tegra_dp_priv *priv = dev_get_priv(dev);
+ struct display_plat *disp_uc_plat = dev_get_uclass_platdata(dev);
priv->regs = (struct dpaux_ctlr *)plat->base;
priv->enabled = false;
+ /* Remember the display controller that is sending us video */
+ priv->dc_dev = disp_uc_plat->src_dev;
+
return 0;
}
diff --git a/drivers/video/tegra124/sor.c b/drivers/video/tegra124/sor.c
index aa3d80c4c0f..e5cea51d48c 100644
--- a/drivers/video/tegra124/sor.c
+++ b/drivers/video/tegra124/sor.c
@@ -5,9 +5,12 @@
*/
#include <common.h>
+#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <malloc.h>
+#include <panel.h>
+#include <video_bridge.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch-tegra/dc.h>
@@ -37,6 +40,14 @@ DECLARE_GLOBAL_DATA_PTR;
#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_OFF (0 << 25)
#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON (1 << 25)
+struct tegra_dc_sor_data {
+ void *base;
+ void *pmc_base;
+ u8 portnum; /* 0 or 1 */
+ int power_is_up;
+ struct udevice *panel;
+};
+
static inline u32 tegra_sor_readl(struct tegra_dc_sor_data *sor, u32 reg)
{
return readl((u32 *)sor->base + reg);
@@ -57,15 +68,19 @@ static inline void tegra_sor_write_field(struct tegra_dc_sor_data *sor,
tegra_sor_writel(sor, reg, reg_val);
}
-void tegra_dp_disable_tx_pu(struct tegra_dc_sor_data *sor)
+void tegra_dp_disable_tx_pu(struct udevice *dev)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
+
tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
DP_PADCTL_TX_PU_MASK, DP_PADCTL_TX_PU_DISABLE);
}
-void tegra_dp_set_pe_vs_pc(struct tegra_dc_sor_data *sor, u32 mask, u32 pe_reg,
+void tegra_dp_set_pe_vs_pc(struct udevice *dev, u32 mask, u32 pe_reg,
u32 vs_reg, u32 pc_reg, u8 pc_supported)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
+
tegra_sor_write_field(sor, PR(sor->portnum), mask, pe_reg);
tegra_sor_write_field(sor, DC(sor->portnum), mask, vs_reg);
if (pc_supported) {
@@ -95,8 +110,9 @@ static int tegra_dc_sor_poll_register(struct tegra_dc_sor_data *sor, u32 reg,
return -ETIMEDOUT;
}
-int tegra_dc_sor_set_power_state(struct tegra_dc_sor_data *sor, int pu_pd)
+int tegra_dc_sor_set_power_state(struct udevice *dev, int pu_pd)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
u32 reg_val;
u32 orig_val;
@@ -123,10 +139,11 @@ int tegra_dc_sor_set_power_state(struct tegra_dc_sor_data *sor, int pu_pd)
return 0;
}
-void tegra_dc_sor_set_dp_linkctl(struct tegra_dc_sor_data *sor, int ena,
+void tegra_dc_sor_set_dp_linkctl(struct udevice *dev, int ena,
u8 training_pattern,
const struct tegra_dp_link_config *link_cfg)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
u32 reg_val;
reg_val = tegra_sor_readl(sor, DP_LINKCTL(sor->portnum));
@@ -194,9 +211,10 @@ static int tegra_dc_sor_enable_lane_sequencer(struct tegra_dc_sor_data *sor,
return 0;
}
-static int tegra_dc_sor_power_dplanes(struct tegra_dc_sor_data *sor,
+static int tegra_dc_sor_power_dplanes(struct udevice *dev,
u32 lane_count, int pu)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
u32 reg_val;
reg_val = tegra_sor_readl(sor, DP_PADCTL(sor->portnum));
@@ -218,15 +236,15 @@ static int tegra_dc_sor_power_dplanes(struct tegra_dc_sor_data *sor,
}
tegra_sor_writel(sor, DP_PADCTL(sor->portnum), reg_val);
- tegra_dc_sor_set_lane_count(sor, lane_count);
+ tegra_dc_sor_set_lane_count(dev, lane_count);
}
return tegra_dc_sor_enable_lane_sequencer(sor, pu, 0);
}
-void tegra_dc_sor_set_panel_power(struct tegra_dc_sor_data *sor,
- int power_up)
+void tegra_dc_sor_set_panel_power(struct udevice *dev, int power_up)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
u32 reg_val;
reg_val = tegra_sor_readl(sor, DP_PADCTL(sor->portnum));
@@ -255,14 +273,15 @@ static void tegra_dc_sor_config_pwm(struct tegra_dc_sor_data *sor, u32 pwm_div,
}
}
-static void tegra_dc_sor_set_dp_mode(struct tegra_dc_sor_data *sor,
+static void tegra_dc_sor_set_dp_mode(struct udevice *dev,
const struct tegra_dp_link_config *link_cfg)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
u32 reg_val;
- tegra_dc_sor_set_link_bandwidth(sor, link_cfg->link_bw);
+ tegra_dc_sor_set_link_bandwidth(dev, link_cfg->link_bw);
- tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_none, link_cfg);
+ tegra_dc_sor_set_dp_linkctl(dev, 1, training_pattern_none, link_cfg);
reg_val = tegra_sor_readl(sor, DP_CONFIG(sor->portnum));
reg_val &= ~DP_CONFIG_WATERMARK_MASK;
reg_val |= link_cfg->watermark;
@@ -351,8 +370,9 @@ static int tegra_dc_sor_io_set_dpd(struct tegra_dc_sor_data *sor, int up)
return 0;
}
-void tegra_dc_sor_set_internal_panel(struct tegra_dc_sor_data *sor, int is_int)
+void tegra_dc_sor_set_internal_panel(struct udevice *dev, int is_int)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
u32 reg_val;
reg_val = tegra_sor_readl(sor, DP_SPARE(sor->portnum));
@@ -366,9 +386,10 @@ void tegra_dc_sor_set_internal_panel(struct tegra_dc_sor_data *sor, int is_int)
tegra_sor_writel(sor, DP_SPARE(sor->portnum), reg_val);
}
-void tegra_dc_sor_read_link_config(struct tegra_dc_sor_data *sor, u8 *link_bw,
+void tegra_dc_sor_read_link_config(struct udevice *dev, u8 *link_bw,
u8 *lane_count)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
u32 reg_val;
reg_val = tegra_sor_readl(sor, CLK_CNTRL);
@@ -395,15 +416,18 @@ void tegra_dc_sor_read_link_config(struct tegra_dc_sor_data *sor, u8 *link_bw,
}
}
-void tegra_dc_sor_set_link_bandwidth(struct tegra_dc_sor_data *sor, u8 link_bw)
+void tegra_dc_sor_set_link_bandwidth(struct udevice *dev, u8 link_bw)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
+
tegra_sor_write_field(sor, CLK_CNTRL,
CLK_CNTRL_DP_LINK_SPEED_MASK,
link_bw << CLK_CNTRL_DP_LINK_SPEED_SHIFT);
}
-void tegra_dc_sor_set_lane_count(struct tegra_dc_sor_data *sor, u8 lane_count)
+void tegra_dc_sor_set_lane_count(struct udevice *dev, u8 lane_count)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
u32 reg_val;
reg_val = tegra_sor_readl(sor, DP_LINKCTL(sor->portnum));
@@ -439,15 +463,16 @@ void tegra_dc_sor_set_lane_count(struct tegra_dc_sor_data *sor, u8 lane_count)
* 4 1 0 0 0 0 0 1
* 5 0 0 0 0 0 0 1
*/
-static int tegra_dc_sor_power_up(struct tegra_dc_sor_data *sor, int is_lvds)
+static int tegra_dc_sor_power_up(struct udevice *dev, int is_lvds)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
int ret;
if (sor->power_is_up)
return 0;
/* Set link bw */
- tegra_dc_sor_set_link_bandwidth(sor, is_lvds ?
+ tegra_dc_sor_set_link_bandwidth(dev, is_lvds ?
CLK_CNTRL_DP_LINK_SPEED_LVDS :
CLK_CNTRL_DP_LINK_SPEED_G1_62);
@@ -655,9 +680,10 @@ static void tegra_dc_sor_enable_dc(struct dc_ctlr *disp_ctrl)
writel(reg_val, &disp_ctrl->cmd.state_access);
}
-int tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor,
+int tegra_dc_sor_enable_dp(struct udevice *dev,
const struct tegra_dp_link_config *link_cfg)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
int ret;
tegra_sor_write_field(sor, CLK_CNTRL,
@@ -701,7 +727,7 @@ int tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor,
PLL2_AUX2_OVERRIDE_POWERDOWN |
PLL2_AUX7_PORT_POWERDOWN_DISABLE);
- ret = tegra_dc_sor_power_up(sor, 0);
+ ret = tegra_dc_sor_power_up(dev, 0);
if (ret) {
debug("DP failed to power up\n");
return ret;
@@ -711,18 +737,19 @@ int tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor,
clock_sor_enable_edp_clock();
/* Power up lanes */
- tegra_dc_sor_power_dplanes(sor, link_cfg->lane_count, 1);
+ tegra_dc_sor_power_dplanes(dev, link_cfg->lane_count, 1);
- tegra_dc_sor_set_dp_mode(sor, link_cfg);
+ tegra_dc_sor_set_dp_mode(dev, link_cfg);
debug("%s ret\n", __func__);
return 0;
}
-int tegra_dc_sor_attach(struct tegra_dc_sor_data *sor,
+int tegra_dc_sor_attach(struct udevice *dc_dev, struct udevice *dev,
const struct tegra_dp_link_config *link_cfg,
const struct display_timing *timing)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
const void *blob = gd->fdt_blob;
struct dc_ctlr *disp_ctrl;
u32 reg_val;
@@ -730,9 +757,7 @@ int tegra_dc_sor_attach(struct tegra_dc_sor_data *sor,
/* Use the first display controller */
debug("%s\n", __func__);
- node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_DC);
- if (node < 0)
- return -ENOENT;
+ node = dc_dev->of_offset;
disp_ctrl = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg");
tegra_dc_sor_enable_dc(disp_ctrl);
@@ -798,9 +823,11 @@ int tegra_dc_sor_attach(struct tegra_dc_sor_data *sor,
return 0;
}
-void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor,
+void tegra_dc_sor_set_lane_parm(struct udevice *dev,
const struct tegra_dp_link_config *link_cfg)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
+
tegra_sor_writel(sor, LANE_DRIVE_CURRENT(sor->portnum),
link_cfg->drive_current);
tegra_sor_writel(sor, PR(sor->portnum),
@@ -809,8 +836,8 @@ void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor,
link_cfg->postcursor);
tegra_sor_writel(sor, LVDS, 0);
- tegra_dc_sor_set_link_bandwidth(sor, link_cfg->link_bw);
- tegra_dc_sor_set_lane_count(sor, link_cfg->lane_count);
+ tegra_dc_sor_set_link_bandwidth(dev, link_cfg->link_bw);
+ tegra_dc_sor_set_lane_count(dev, link_cfg->lane_count);
tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
DP_PADCTL_TX_PU_ENABLE |
@@ -825,9 +852,10 @@ void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor,
tegra_sor_write_field(sor, DP_PADCTL(sor->portnum), 0xf0, 0x0);
}
-int tegra_dc_sor_set_voltage_swing(struct tegra_dc_sor_data *sor,
+int tegra_dc_sor_set_voltage_swing(struct udevice *dev,
const struct tegra_dp_link_config *link_cfg)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
u32 drive_current = 0;
u32 pre_emphasis = 0;
@@ -851,9 +879,10 @@ int tegra_dc_sor_set_voltage_swing(struct tegra_dc_sor_data *sor,
return 0;
}
-void tegra_dc_sor_power_down_unused_lanes(struct tegra_dc_sor_data *sor,
+void tegra_dc_sor_power_down_unused_lanes(struct udevice *dev,
const struct tegra_dp_link_config *link_cfg)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
u32 pad_ctrl = 0;
int err = 0;
@@ -891,9 +920,10 @@ void tegra_dc_sor_power_down_unused_lanes(struct tegra_dc_sor_data *sor,
}
}
-int tegra_sor_precharge_lanes(struct tegra_dc_sor_data *sor,
+int tegra_sor_precharge_lanes(struct udevice *dev,
const struct tegra_dp_link_config *cfg)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
u32 val = 0;
switch (cfg->lane_count) {
@@ -931,8 +961,9 @@ static void tegra_dc_sor_enable_sor(struct dc_ctlr *disp_ctrl, bool enable)
writel(reg_val, &disp_ctrl->disp.disp_win_opt);
}
-int tegra_dc_sor_detach(struct tegra_dc_sor_data *sor)
+int tegra_dc_sor_detach(struct udevice *dc_dev, struct udevice *dev)
{
+ struct tegra_dc_sor_data *sor = dev_get_priv(dev);
int dc_reg_ctx[DC_REG_SAVE_SPACE];
const void *blob = gd->fdt_blob;
struct dc_ctlr *disp_ctrl;
@@ -942,11 +973,7 @@ int tegra_dc_sor_detach(struct tegra_dc_sor_data *sor)
debug("%s\n", __func__);
/* Use the first display controller */
- node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_DC);
- if (node < 0) {
- ret = -ENOENT;
- goto err;
- }
+ node = dc_dev->of_offset;
disp_ctrl = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg");
/* Sleep mode */
@@ -997,28 +1024,61 @@ err:
return ret;
}
-int tegra_dc_sor_init(struct tegra_dc_sor_data **sorp)
+static int tegra_sor_set_backlight(struct udevice *dev, int percent)
{
+ struct tegra_dc_sor_data *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = panel_enable_backlight(priv->panel);
+ if (ret) {
+ debug("sor: Cannot enable panel backlight\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tegra_sor_ofdata_to_platdata(struct udevice *dev)
+{
+ struct tegra_dc_sor_data *priv = dev_get_priv(dev);
const void *blob = gd->fdt_blob;
- struct tegra_dc_sor_data *sor;
int node;
+ int ret;
- node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_SOR);
- if (node < 0)
- return -ENOENT;
- sor = calloc(1, sizeof(*sor));
- if (!sor)
- return -ENOMEM;
- sor->base = (void *)fdtdec_get_addr(blob, node, "reg");
+ priv->base = (void *)fdtdec_get_addr(blob, dev->of_offset, "reg");
node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_PMC);
- if (node < 0)
+ if (node < 0) {
+ debug("%s: Cannot find PMC\n", __func__);
return -ENOENT;
- sor->pmc_base = (void *)fdtdec_get_addr(blob, node, "reg");
+ }
+ priv->pmc_base = (void *)fdtdec_get_addr(blob, node, "reg");
- sor->power_is_up = 0;
- sor->portnum = 0;
- *sorp = sor;
+ ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, "nvidia,panel",
+ &priv->panel);
+ if (ret) {
+ debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__,
+ dev->name, ret);
+ return ret;
+ }
return 0;
}
+
+static const struct video_bridge_ops tegra_sor_ops = {
+ .set_backlight = tegra_sor_set_backlight,
+};
+
+static const struct udevice_id tegra_sor_ids[] = {
+ { .compatible = "nvidia,tegra124-sor" },
+ { }
+};
+
+U_BOOT_DRIVER(sor_tegra) = {
+ .name = "sor_tegra",
+ .id = UCLASS_VIDEO_BRIDGE,
+ .of_match = tegra_sor_ids,
+ .ofdata_to_platdata = tegra_sor_ofdata_to_platdata,
+ .ops = &tegra_sor_ops,
+ .priv_auto_alloc_size = sizeof(struct tegra_dc_sor_data),
+};
diff --git a/drivers/video/tegra124/sor.h b/drivers/video/tegra124/sor.h
index dc8fd03d808..e854bef17d1 100644
--- a/drivers/video/tegra124/sor.h
+++ b/drivers/video/tegra124/sor.h
@@ -873,44 +873,37 @@ struct tegra_dp_link_config {
u8 tps3_supported;
};
-struct tegra_dc_sor_data {
- void *base;
- void *pmc_base;
- u8 portnum; /* 0 or 1 */
- int power_is_up;
-};
-
#define TEGRA_SOR_TIMEOUT_MS 1000
#define TEGRA_SOR_ATTACH_TIMEOUT_MS 1000
-int tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor,
+int tegra_dc_sor_enable_dp(struct udevice *sor,
const struct tegra_dp_link_config *link_cfg);
-int tegra_dc_sor_set_power_state(struct tegra_dc_sor_data *sor, int pu_pd);
-void tegra_dc_sor_set_dp_linkctl(struct tegra_dc_sor_data *sor, int ena,
+int tegra_dc_sor_set_power_state(struct udevice *sor, int pu_pd);
+void tegra_dc_sor_set_dp_linkctl(struct udevice *dev, int ena,
u8 training_pattern, const struct tegra_dp_link_config *link_cfg);
-void tegra_dc_sor_set_link_bandwidth(struct tegra_dc_sor_data *sor, u8 link_bw);
-void tegra_dc_sor_set_lane_count(struct tegra_dc_sor_data *sor, u8 lane_count);
-void tegra_dc_sor_set_panel_power(struct tegra_dc_sor_data *sor,
+void tegra_dc_sor_set_link_bandwidth(struct udevice *dev, u8 link_bw);
+void tegra_dc_sor_set_lane_count(struct udevice *dev, u8 lane_count);
+void tegra_dc_sor_set_panel_power(struct udevice *sor,
int power_up);
-void tegra_dc_sor_set_internal_panel(struct tegra_dc_sor_data *sor, int is_int);
-void tegra_dc_sor_read_link_config(struct tegra_dc_sor_data *sor, u8 *link_bw,
+void tegra_dc_sor_set_internal_panel(struct udevice *dev, int is_int);
+void tegra_dc_sor_read_link_config(struct udevice *dev, u8 *link_bw,
u8 *lane_count);
-void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor,
- const struct tegra_dp_link_config *link_cfg);
-void tegra_dc_sor_power_down_unused_lanes(struct tegra_dc_sor_data *sor,
+void tegra_dc_sor_set_lane_parm(struct udevice *dev,
+ const struct tegra_dp_link_config *link_cfg);
+void tegra_dc_sor_power_down_unused_lanes(struct udevice *sor,
const struct tegra_dp_link_config *link_cfg);
-int tegra_dc_sor_set_voltage_swing(struct tegra_dc_sor_data *sor,
+int tegra_dc_sor_set_voltage_swing(struct udevice *sor,
const struct tegra_dp_link_config *link_cfg);
-int tegra_sor_precharge_lanes(struct tegra_dc_sor_data *sor,
+int tegra_sor_precharge_lanes(struct udevice *dev,
const struct tegra_dp_link_config *cfg);
-void tegra_dp_disable_tx_pu(struct tegra_dc_sor_data *sor);
-void tegra_dp_set_pe_vs_pc(struct tegra_dc_sor_data *sor, u32 mask,
- u32 pe_reg, u32 vs_reg, u32 pc_reg, u8 pc_supported);
+void tegra_dp_disable_tx_pu(struct udevice *sor);
+void tegra_dp_set_pe_vs_pc(struct udevice *dev, u32 mask, u32 pe_reg,
+ u32 vs_reg, u32 pc_reg, u8 pc_supported);
-int tegra_dc_sor_attach(struct tegra_dc_sor_data *sor,
+int tegra_dc_sor_attach(struct udevice *dc_dev, struct udevice *sor,
const struct tegra_dp_link_config *link_cfg,
const struct display_timing *timing);
-int tegra_dc_sor_detach(struct tegra_dc_sor_data *sor);
+int tegra_dc_sor_detach(struct udevice *dc_dev, struct udevice *sor);
void tegra_dc_sor_disable_win_short_raster(struct dc_ctlr *disp_ctrl,
int *dc_reg_ctx);
@@ -918,5 +911,5 @@ int tegra_dc_sor_general_act(struct dc_ctlr *disp_ctrl);
void tegra_dc_sor_restore_win_and_raster(struct dc_ctlr *disp_ctrl,
int *dc_reg_ctx);
-int tegra_dc_sor_init(struct tegra_dc_sor_data **sorp);
+int tegra_dc_sor_init(struct udevice **sorp);
#endif
diff --git a/drivers/video/tegra124/tegra124-lcd.c b/drivers/video/tegra124/tegra124-lcd.c
deleted file mode 100644
index cfdc77ffe37..00000000000
--- a/drivers/video/tegra124/tegra124-lcd.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * SPDX-License-Identifier: GPL-2.0+
- *
- */
-
-#include <common.h>
-#include <errno.h>
-#include <fdtdec.h>
-#include <lcd.h>
-#include <asm/gpio.h>
-#include <asm/arch-tegra/clk_rst.h>
-#include <asm/arch/clock.h>
-#include <asm/arch-tegra/dc.h>
-#include <asm/io.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-enum {
- /* Maximum LCD size we support */
- LCD_MAX_WIDTH = 1920,
- LCD_MAX_HEIGHT = 1200,
- LCD_MAX_LOG2_BPP = 4, /* 2^4 = 16 bpp */
-};
-
-vidinfo_t panel_info = {
- /* Insert a value here so that we don't end up in the BSS */
- .vl_col = -1,
-};
-
-int tegra_lcd_check_next_stage(const void *blob, int wait)
-{
- return 0;
-}
-
-void tegra_lcd_early_init(const void *blob)
-{
- /*
- * Go with the maximum size for now. We will fix this up after
- * relocation. These values are only used for memory alocation.
- */
- panel_info.vl_col = LCD_MAX_WIDTH;
- panel_info.vl_row = LCD_MAX_HEIGHT;
- panel_info.vl_bpix = LCD_MAX_LOG2_BPP;
-}
-
-static int tegra124_lcd_init(void *lcdbase)
-{
- struct display_timing timing;
- int ret;
-
- clock_set_up_plldp();
- clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_PERIPH, 408000000);
-
- clock_enable(PERIPH_ID_HOST1X);
- clock_enable(PERIPH_ID_DISP1);
- clock_enable(PERIPH_ID_PWM);
- clock_enable(PERIPH_ID_DPAUX);
- clock_enable(PERIPH_ID_SOR0);
- udelay(2);
-
- reset_set_enable(PERIPH_ID_HOST1X, 0);
- reset_set_enable(PERIPH_ID_DISP1, 0);
- reset_set_enable(PERIPH_ID_PWM, 0);
- reset_set_enable(PERIPH_ID_DPAUX, 0);
- reset_set_enable(PERIPH_ID_SOR0, 0);
-
- ret = display_init(lcdbase, 1 << LCD_BPP, &timing);
- if (ret)
- return ret;
-
- panel_info.vl_col = roundup(timing.hactive.typ, 16);
- panel_info.vl_row = timing.vactive.typ;
-
- lcd_set_flush_dcache(1);
-
- return 0;
-}
-
-void lcd_ctrl_init(void *lcdbase)
-{
- ulong start;
- int ret;
-
- start = get_timer(0);
- ret = tegra124_lcd_init(lcdbase);
- debug("LCD init took %lu ms\n", get_timer(start));
- if (ret)
- printf("%s: Error %d\n", __func__, ret);
-}
-
-void lcd_enable(void)
-{
-}
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index f6326b6e072..832e90aea2b 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -170,6 +170,7 @@ static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
while (*s)
vidconsole_put_char(dev, *s++);
+ video_sync(dev->parent);
}
/* Set up the number of rows and colours (rotated drivers override this) */
diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c
index c9075d62dd7..fb7943e06d9 100644
--- a/drivers/video/video_bmp.c
+++ b/drivers/video/video_bmp.c
@@ -194,7 +194,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
{
struct video_priv *priv = dev_get_uclass_priv(dev);
ushort *cmap_base = NULL;
- ushort i, j;
+ int i, j;
uchar *fb;
struct bmp_image *bmp = map_sysmem(bmp_image, 0);
uchar *bmap;