Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/uart/uart_bus_fdt.c
Show First 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | |||||
uart_fdt_get_shift(phandle_t node, pcell_t *cell) | uart_fdt_get_shift(phandle_t node, pcell_t *cell) | ||||
{ | { | ||||
if ((OF_getencprop(node, "reg-shift", cell, sizeof(*cell))) <= 0) | if ((OF_getencprop(node, "reg-shift", cell, sizeof(*cell))) <= 0) | ||||
return (-1); | return (-1); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | |||||
uart_fdt_get_io_width(phandle_t node, pcell_t *cell) | |||||
{ | |||||
if ((OF_getencprop(node, "reg-io-width", cell, sizeof(*cell))) <= 0) | |||||
return (-1); | |||||
return (0); | |||||
} | |||||
static uintptr_t | static uintptr_t | ||||
uart_fdt_find_device(device_t dev) | uart_fdt_find_device(device_t dev) | ||||
{ | { | ||||
struct ofw_compat_data **cd; | struct ofw_compat_data **cd; | ||||
const struct ofw_compat_data *ocd; | const struct ofw_compat_data *ocd; | ||||
SET_FOREACH(cd, uart_fdt_class_and_device_set) { | SET_FOREACH(cd, uart_fdt_class_and_device_set) { | ||||
ocd = ofw_bus_search_compatible(dev, *cd); | ocd = ofw_bus_search_compatible(dev, *cd); | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | if (class_list) { | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
uart_cpu_fdt_probe(struct uart_class **classp, bus_space_tag_t *bst, | uart_cpu_fdt_probe(struct uart_class **classp, bus_space_tag_t *bst, | ||||
bus_space_handle_t *bsh, int *baud, u_int *rclk, u_int *shiftp) | bus_space_handle_t *bsh, int *baud, u_int *rclk, u_int *shiftp, | ||||
u_int *iowidthp) | |||||
{ | { | ||||
const char *propnames[] = {"stdout-path", "linux,stdout-path", "stdout", | const char *propnames[] = {"stdout-path", "linux,stdout-path", "stdout", | ||||
"stdin-path", "stdin", NULL}; | "stdin-path", "stdin", NULL}; | ||||
const char **name; | const char **name; | ||||
struct uart_class *class; | struct uart_class *class; | ||||
phandle_t node, chosen; | phandle_t node, chosen; | ||||
pcell_t br, clk, shift; | pcell_t br, clk, shift, iowidth; | ||||
char *cp; | char *cp; | ||||
int err; | int err; | ||||
/* Has the user forced a specific device node? */ | /* Has the user forced a specific device node? */ | ||||
cp = kern_getenv("hw.fdt.console"); | cp = kern_getenv("hw.fdt.console"); | ||||
if (cp == NULL) { | if (cp == NULL) { | ||||
/* | /* | ||||
* Retrieve /chosen/std{in,out}. | * Retrieve /chosen/std{in,out}. | ||||
Show All 34 Lines | uart_cpu_fdt_probe(struct uart_class **classp, bus_space_tag_t *bst, | ||||
} | } | ||||
/* | /* | ||||
* Retrieve serial attributes. | * Retrieve serial attributes. | ||||
*/ | */ | ||||
if (uart_fdt_get_shift(node, &shift) != 0) | if (uart_fdt_get_shift(node, &shift) != 0) | ||||
shift = uart_getregshift(class); | shift = uart_getregshift(class); | ||||
if (uart_fdt_get_io_width(node, &iowidth) != 0) | |||||
iowidth = uart_getregiowidth(class); | |||||
if (OF_getencprop(node, "current-speed", &br, sizeof(br)) <= 0) | if (OF_getencprop(node, "current-speed", &br, sizeof(br)) <= 0) | ||||
br = 0; | br = 0; | ||||
err = OF_decode_addr(node, 0, bst, bsh, NULL); | err = OF_decode_addr(node, 0, bst, bsh, NULL); | ||||
if (err != 0) | if (err != 0) | ||||
return (err); | return (err); | ||||
*classp = class; | *classp = class; | ||||
*baud = br; | *baud = br; | ||||
*rclk = clk; | *rclk = clk; | ||||
*shiftp = shift; | *shiftp = shift; | ||||
*iowidthp = iowidth; | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
uart_fdt_probe(device_t dev) | uart_fdt_probe(device_t dev) | ||||
{ | { | ||||
struct uart_softc *sc; | struct uart_softc *sc; | ||||
phandle_t node; | phandle_t node; | ||||
pcell_t clock, shift; | pcell_t clock, shift, iowidth; | ||||
int err; | int err; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
if (!ofw_bus_status_okay(dev)) | if (!ofw_bus_status_okay(dev)) | ||||
return (ENXIO); | return (ENXIO); | ||||
sc->sc_class = (struct uart_class *)uart_fdt_find_device(dev); | sc->sc_class = (struct uart_class *)uart_fdt_find_device(dev); | ||||
if (sc->sc_class == NULL) | if (sc->sc_class == NULL) | ||||
return (ENXIO); | return (ENXIO); | ||||
node = ofw_bus_get_node(dev); | node = ofw_bus_get_node(dev); | ||||
if ((err = uart_fdt_get_clock(node, &clock)) != 0) | if ((err = uart_fdt_get_clock(node, &clock)) != 0) | ||||
return (err); | return (err); | ||||
if (uart_fdt_get_shift(node, &shift) != 0) | if (uart_fdt_get_shift(node, &shift) != 0) | ||||
shift = uart_getregshift(sc->sc_class); | shift = uart_getregshift(sc->sc_class); | ||||
if (uart_fdt_get_io_width(node, &iowidth) != 0) | |||||
iowidth = uart_getregiowidth(sc->sc_class); | |||||
return (uart_bus_probe(dev, (int)shift, (int)clock, 0, 0)); | return (uart_bus_probe(dev, (int)shift, (int)iowidth, (int)clock, 0, 0)); | ||||
} | } | ||||
DRIVER_MODULE(uart, simplebus, uart_fdt_driver, uart_devclass, 0, 0); | DRIVER_MODULE(uart, simplebus, uart_fdt_driver, uart_devclass, 0, 0); | ||||
DRIVER_MODULE(uart, ofwbus, uart_fdt_driver, uart_devclass, 0, 0); | DRIVER_MODULE(uart, ofwbus, uart_fdt_driver, uart_devclass, 0, 0); |