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 
24 FILE_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  */
45 static 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  */
103 static 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 */
108  uart_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 */
117 static const char * dwuart_ids[] = {
118  "snps,dw-apb-uart",
119  "ns16550a",
120 };
121 
122 /** DesignWare UART devicetree driver */
123 struct dt_driver dwuart_driver __dt_driver = {
124  .name = "dwuart",
125  .ids = dwuart_ids,
126  .id_count = ( sizeof ( dwuart_ids ) / sizeof ( dwuart_ids[0] ) ),
127  .probe = dwuart_probe,
129 };
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
Generic UART.
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
static void dwuart_remove(struct dt_device *dt)
Remove devicetree device.
Definition: dwuart.c:103
Error codes.
A generic UART.
Definition: uart.h:17
void * base
Register base address.
Definition: ns16550.h:82
A devicetree driver.
Definition: devtree.h:31
unsigned int shift
Register shift.
Definition: ns16550.h:84
int uart_register(struct uart *uart)
Register UART.
Definition: uart.c:102
16550-compatible UART
const char * name
Name.
Definition: uart.h:21
#define NS16550_CLK_DEFAULT
Default input clock rate (1.8432 MHz)
Definition: ns16550.h:95
int(* probe)(struct dt_device *dt, unsigned int offset)
Probe device.
Definition: devtree.h:45
#define ENOMEM
Not enough space.
Definition: errno.h:534
int fdt_u32(struct fdt *fdt, unsigned int offset, const char *name, uint32_t *value)
Get 32-bit integer property.
Definition: fdt.c:663
Devicetree bus.
A devicetree device.
Definition: devtree.h:17
unsigned int clock
Input clock frequency.
Definition: ns16550.h:86
static void dt_set_drvdata(struct dt_device *dt, void *priv)
Set devicetree driver-private data.
Definition: devtree.h:66
void * priv
Driver-private data.
Definition: uart.h:31
A 16550-compatible UART.
Definition: ns16550.h:80
#define ENODEV
No such device.
Definition: errno.h:509
struct uart_operations ns16550_operations
16550 UART operations
Definition: ns16550.c:171
unsigned int uint32_t
Definition: stdint.h:12
static struct xen_remove_from_physmap * remove
Definition: xenmem.h:39
const char * name
Device name.
Definition: devtree.h:19
static const char * dwuart_ids[]
DesignWare UART compatible model identifiers.
Definition: dwuart.c:117
const char * name
Driver name.
Definition: devtree.h:33
struct dt_driver dwuart_driver __dt_driver
DesignWare UART devicetree driver.
Definition: dwuart.c:123
static int dwuart_probe(struct dt_device *dt, unsigned int offset)
Probe devicetree device.
Definition: dwuart.c:45
Flattened Device Tree.
void * dt_ioremap(struct dt_device *dt, unsigned int offset, unsigned int index, size_t len)
Map devicetree range.
Definition: devtree.c:52
struct uart_operations * op
UART operations.
Definition: uart.h:29
void iounmap(volatile const void *io_addr)
Unmap I/O address.
struct uart * alloc_uart(size_t priv_len)
Allocate UART.
Definition: uart.c:74
void uart_unregister(struct uart *uart)
Unregister UART.
Definition: uart.c:117
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
static void * dt_get_drvdata(struct dt_device *dt)
Get devicetree driver-private data.
Definition: devtree.h:76
struct fdt sysfdt
The system flattened device tree (if present)
Definition: fdt.c:44