blob: e4492e662e927920c8dab08fb944f780b1913168 [file] [log] [blame]
Stefan Bosch51f153c2022-12-18 12:20:49 +00001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2022 Stefan Bosch <stefan_b@posteo.net>
4 */
5
Tom Riniabb9a042024-05-18 20:20:43 -06006#include <common.h>
Stefan Bosch51f153c2022-12-18 12:20:49 +00007#include <dm.h>
8#include <asm/arch/clk.h>
9#include <asm/arch/reset.h>
10#include <linux/delay.h>
11
12#include <dm/platform_data/serial_pl01x.h>
13#include <serial.h>
14#include "serial_pl01x_internal.h"
15
16int s5p4418_pl011_serial_probe(struct udevice *dev)
17{
18 struct pl01x_serial_plat *plat = dev_get_plat(dev);
19 struct clk *nx_clk;
20 ulong rate_act;
21 char uart_clk_name[10];
22 int uart_num = -1;
23 int rst_id, ret;
24
25 if (!plat->skip_init) {
26 uart_num = dev->seq_;
27 rst_id = RESET_ID_UART0 + uart_num;
28
29 if (uart_num < 0 || rst_id > RESET_ID_UART5) {
30 /* invalid UART-number */
31 debug("%s: sequence/uart number %d is invalid!\n", __func__, uart_num);
32 return -ENODEV;
33 }
34
35 sprintf(uart_clk_name, "nx-uart.%d", uart_num);
36 nx_clk = clk_get(uart_clk_name);
37 if (!nx_clk) {
38 debug("%s: clk_get('%s') failed!\n", __func__, uart_clk_name);
39 return -ENODEV;
40 }
41
42 /* wait to make sure all pending characters have been sent */
43 mdelay(100);
44 }
45
46 /*
47 * Note: Unless !plat->skip_init, the UART is disabled here, so printf()
48 * or debug() must not be used until pl01x_serial_setbrg() has been called
49 * (enables the UART). Otherwise u-boot is hanging!
50 */
51 ret = pl01x_serial_probe(dev);
52 if (ret)
53 return ret;
54
55 if (!plat->skip_init) {
56 /* do reset UART */
57 nx_rstcon_setrst(rst_id, RSTCON_ASSERT);
58 udelay(10);
59 nx_rstcon_setrst(rst_id, RSTCON_NEGATE);
60 udelay(10);
61 clk_disable(nx_clk);
62
63 rate_act = clk_set_rate(nx_clk, plat->clock);
64 clk_enable(nx_clk);
65
66 plat->clock = rate_act;
67 }
68
69 return 0;
70}
71
72static const struct dm_serial_ops s5p4418_pl011_serial_ops = {
73 .putc = pl01x_serial_putc,
74 .pending = pl01x_serial_pending,
75 .getc = pl01x_serial_getc,
76 .setbrg = pl01x_serial_setbrg,
77};
78
79static const struct udevice_id s5p4418_pl011_serial_id[] = {
80 {.compatible = "nexell,s5p4418-pl011", .data = TYPE_PL011},
81 {}
82};
83
84U_BOOT_DRIVER(s5p4418_pl011_uart) = {
85 .name = "s5p4418_pl011",
86 .id = UCLASS_SERIAL,
87 .of_match = of_match_ptr(s5p4418_pl011_serial_id),
88 .of_to_plat = of_match_ptr(pl01x_serial_of_to_plat),
89 .plat_auto = sizeof(struct pl01x_serial_plat),
90 .probe = s5p4418_pl011_serial_probe,
91 .ops = &s5p4418_pl011_serial_ops,
92 .flags = DM_FLAG_PRE_RELOC,
93 .priv_auto = sizeof(struct pl01x_priv),
94};