iPXE
dwuart.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2025 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26/** @file
27 *
28 * DesignWare UART
29 *
30 */
31
32#include <errno.h>
33#include <ipxe/uart.h>
34#include <ipxe/ns16550.h>
35#include <ipxe/devtree.h>
36#include <ipxe/fdt.h>
37
38/**
39 * Probe devicetree device
40 *
41 * @v dt Devicetree device
42 * @v offset Starting node offset
43 * @ret rc Return status code
44 */
45static int dwuart_probe ( struct dt_device *dt, unsigned int offset ) {
46 struct ns16550_uart *ns16550;
47 struct uart *uart;
48 uint32_t shift;
49 uint32_t clock;
50 int rc;
51
52 /* Allocate and initialise UART */
53 uart = alloc_uart ( sizeof ( *ns16550 ) );
54 if ( ! uart ) {
55 rc = -ENOMEM;
56 goto err_alloc;
57 }
58 uart->name = dt->name;
60 ns16550 = uart->priv;
61 dt_set_drvdata ( dt, uart );
62
63 /* Map registers */
64 ns16550->base = dt_ioremap ( dt, offset, 0, 0 );
65 if ( ! ns16550->base ) {
66 rc = -ENODEV;
67 goto err_ioremap;
68 }
69
70 /* Get register shift */
71 if ( ( rc = fdt_u32 ( &sysfdt, offset, "reg-shift", &shift ) ) != 0 )
72 shift = 0;
73 ns16550->shift = shift;
74
75 /* Get clock rate */
76 if ( ( rc = fdt_u32 ( &sysfdt, offset, "clock-frequency",
77 &clock ) ) != 0 ) {
78 clock = NS16550_CLK_DEFAULT;
79 }
80 ns16550->clock = clock;
81
82 /* Register UART */
83 if ( ( rc = uart_register ( uart ) ) != 0 )
84 goto err_register;
85
86 return 0;
87
89 err_register:
90 iounmap ( ns16550->base );
91 err_ioremap:
92 uart_nullify ( uart );
93 uart_put ( uart );
94 err_alloc:
95 return rc;
96}
97
98/**
99 * Remove devicetree device
100 *
101 * @v dt Devicetree device
102 */
103static void dwuart_remove ( struct dt_device *dt ) {
104 struct uart *uart = dt_get_drvdata ( dt );
105 struct ns16550_uart *ns16550 = uart->priv;
106
107 /* Unregister UART */
109
110 /* Free UART */
111 iounmap ( ns16550->base );
112 uart_nullify ( uart );
113 uart_put ( uart );
114}
115
116/** DesignWare UART compatible model identifiers */
117static const char * dwuart_ids[] = {
118 DT_ID ( "snps,dw-apb-uart", "DesignWare UART" ),
119 DT_ID ( "ns16550a", "NS16550-compatible" ),
120};
121
122/** DesignWare UART devicetree driver */
123struct dt_driver dwuart_driver __dt_driver = {
124 .name = "dwuart",
125 .ids = dwuart_ids,
126 .id_count = ( sizeof ( dwuart_ids ) / sizeof ( dwuart_ids[0] ) ),
129};
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned int uint32_t
Definition stdint.h:12
uint16_t offset
Offset to command line.
Definition bzimage.h:3
void * dt_ioremap(struct dt_device *dt, unsigned int offset, unsigned int index, size_t len)
Map devicetree range.
Definition devtree.c:52
Devicetree bus.
static void * dt_get_drvdata(struct dt_device *dt)
Get devicetree driver-private data.
Definition devtree.h:82
#define DT_ID(_name, _desc)
Definition devtree.h:31
static void dt_set_drvdata(struct dt_device *dt, void *priv)
Set devicetree driver-private data.
Definition devtree.h:72
#define __dt_driver
Declare a devicetree driver.
Definition devtree.h:64
static void dwuart_remove(struct dt_device *dt)
Remove devicetree device.
Definition dwuart.c:103
static const char * dwuart_ids[]
DesignWare UART compatible model identifiers.
Definition dwuart.c:117
static int dwuart_probe(struct dt_device *dt, unsigned int offset)
Probe devicetree device.
Definition dwuart.c:45
Error codes.
int fdt_u32(struct fdt *fdt, unsigned int offset, const char *name, uint32_t *value)
Get 32-bit integer property.
Definition fdt.c:664
struct fdt sysfdt
The system flattened device tree (if present)
Definition fdt.c:45
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENODEV
No such device.
Definition errno.h:510
Flattened Device Tree.
void iounmap(volatile const void *io_addr)
Unmap I/O address.
16550-compatible UART
#define NS16550_CLK_DEFAULT
Default input clock rate (1.8432 MHz)
Definition ns16550.h:95
struct uart_operations ns16550_operations
16550 UART operations
Definition ns16550.c:171
A devicetree device.
Definition devtree.h:17
const char * name
Device name.
Definition devtree.h:19
A devicetree driver.
Definition devtree.h:37
int(* probe)(struct dt_device *dt, unsigned int offset)
Probe device.
Definition devtree.h:51
A 16550-compatible UART.
Definition ns16550.h:80
unsigned int clock
Input clock frequency.
Definition ns16550.h:86
unsigned int shift
Register shift.
Definition ns16550.h:84
void * base
Register base address.
Definition ns16550.h:82
A generic UART.
Definition uart.h:17
const char * name
Name.
Definition uart.h:21
struct uart_operations * op
UART operations.
Definition uart.h:29
void * priv
Driver-private data.
Definition uart.h:31
void uart_unregister(struct uart *uart)
Unregister UART.
Definition uart.c:117
struct uart * alloc_uart(size_t priv_len)
Allocate UART.
Definition uart.c:74
int uart_register(struct uart *uart)
Register UART.
Definition uart.c:102
Generic UART.
static struct xen_remove_from_physmap * remove
Definition xenmem.h:40