+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
* Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
+#include <clk.h>
#include <common.h>
#include <debug_uart.h>
#include <dm.h>
#include <fdtdec.h>
#include <watchdog.h>
#include <asm/io.h>
+#include <dm/device_compat.h>
#include <linux/compiler.h>
#include <serial.h>
-#include <asm/arch/clk.h>
-#include <asm/arch/hardware.h>
+#include <linux/err.h>
DECLARE_GLOBAL_DATA_PTR;
-#define ZYNQ_UART_SR_TXFULL 0x00000010 /* TX FIFO full */
-#define ZYNQ_UART_SR_TXACTIVE (1 << 11) /* TX active */
-#define ZYNQ_UART_SR_RXEMPTY 0x00000002 /* RX FIFO empty */
+#define ZYNQ_UART_SR_TXACTIVE BIT(11) /* TX active */
+#define ZYNQ_UART_SR_TXFULL BIT(4) /* TX FIFO full */
+#define ZYNQ_UART_SR_RXEMPTY BIT(1) /* RX FIFO empty */
-#define ZYNQ_UART_CR_TX_EN 0x00000010 /* TX enabled */
-#define ZYNQ_UART_CR_RX_EN 0x00000004 /* RX enabled */
-#define ZYNQ_UART_CR_TXRST 0x00000002 /* TX logic reset */
-#define ZYNQ_UART_CR_RXRST 0x00000001 /* RX logic reset */
+#define ZYNQ_UART_CR_TX_EN BIT(4) /* TX enabled */
+#define ZYNQ_UART_CR_RX_EN BIT(2) /* RX enabled */
+#define ZYNQ_UART_CR_TXRST BIT(1) /* TX logic reset */
+#define ZYNQ_UART_CR_RXRST BIT(0) /* RX logic reset */
#define ZYNQ_UART_MR_PARITY_NONE 0x00000020 /* No parity mode */
u32 baud_rate_divider; /* 0x34 - Baud Rate Divider [7:0] */
};
-struct zynq_uart_priv {
+struct zynq_uart_platdata {
struct uart_zynq *regs;
};
return 0;
}
-int zynq_serial_setbrg(struct udevice *dev, int baudrate)
+static int zynq_serial_setbrg(struct udevice *dev, int baudrate)
{
- struct zynq_uart_priv *priv = dev_get_priv(dev);
- unsigned long clock = get_uart_clk(0);
+ struct zynq_uart_platdata *platdata = dev_get_platdata(dev);
+ unsigned long clock;
- _uart_zynq_serial_setbrg(priv->regs, clock, baudrate);
+ int ret;
+ struct clk clk;
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret < 0) {
+ dev_err(dev, "failed to get clock\n");
+ return ret;
+ }
+
+ clock = clk_get_rate(&clk);
+ if (IS_ERR_VALUE(clock)) {
+ dev_err(dev, "failed to get rate\n");
+ return clock;
+ }
+ debug("%s: CLK %ld\n", __func__, clock);
+
+ ret = clk_enable(&clk);
+ if (ret && ret != -ENOSYS) {
+ dev_err(dev, "failed to enable clock\n");
+ return ret;
+ }
+
+ _uart_zynq_serial_setbrg(platdata->regs, clock, baudrate);
return 0;
}
static int zynq_serial_probe(struct udevice *dev)
{
- struct zynq_uart_priv *priv = dev_get_priv(dev);
+ struct zynq_uart_platdata *platdata = dev_get_platdata(dev);
- _uart_zynq_serial_init(priv->regs);
+ /* No need to reinitialize the UART after relocation */
+ if (gd->flags & GD_FLG_RELOC)
+ return 0;
+
+ _uart_zynq_serial_init(platdata->regs);
return 0;
}
static int zynq_serial_getc(struct udevice *dev)
{
- struct zynq_uart_priv *priv = dev_get_priv(dev);
- struct uart_zynq *regs = priv->regs;
+ struct zynq_uart_platdata *platdata = dev_get_platdata(dev);
+ struct uart_zynq *regs = platdata->regs;
if (readl(®s->channel_sts) & ZYNQ_UART_SR_RXEMPTY)
return -EAGAIN;
static int zynq_serial_putc(struct udevice *dev, const char ch)
{
- struct zynq_uart_priv *priv = dev_get_priv(dev);
+ struct zynq_uart_platdata *platdata = dev_get_platdata(dev);
- return _uart_zynq_serial_putc(priv->regs, ch);
+ return _uart_zynq_serial_putc(platdata->regs, ch);
}
static int zynq_serial_pending(struct udevice *dev, bool input)
{
- struct zynq_uart_priv *priv = dev_get_priv(dev);
- struct uart_zynq *regs = priv->regs;
+ struct zynq_uart_platdata *platdata = dev_get_platdata(dev);
+ struct uart_zynq *regs = platdata->regs;
if (input)
return !(readl(®s->channel_sts) & ZYNQ_UART_SR_RXEMPTY);
static int zynq_serial_ofdata_to_platdata(struct udevice *dev)
{
- struct zynq_uart_priv *priv = dev_get_priv(dev);
- fdt_addr_t addr;
-
- addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
- if (addr == FDT_ADDR_T_NONE)
- return -EINVAL;
+ struct zynq_uart_platdata *platdata = dev_get_platdata(dev);
- priv->regs = (struct uart_zynq *)addr;
+ platdata->regs = (struct uart_zynq *)dev_read_addr(dev);
+ if (IS_ERR(platdata->regs))
+ return PTR_ERR(platdata->regs);
return 0;
}
static const struct udevice_id zynq_serial_ids[] = {
{ .compatible = "xlnx,xuartps" },
{ .compatible = "cdns,uart-r1p8" },
+ { .compatible = "cdns,uart-r1p12" },
{ }
};
.id = UCLASS_SERIAL,
.of_match = zynq_serial_ids,
.ofdata_to_platdata = zynq_serial_ofdata_to_platdata,
- .priv_auto_alloc_size = sizeof(struct zynq_uart_priv),
+ .platdata_auto_alloc_size = sizeof(struct zynq_uart_platdata),
.probe = zynq_serial_probe,
.ops = &zynq_serial_ops,
- .flags = DM_FLAG_PRE_RELOC,
};
#ifdef CONFIG_DEBUG_UART_ZYNQ
-void _debug_uart_init(void)
+static inline void _debug_uart_init(void)
{
struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE;