From owner-svn-src-head@FreeBSD.ORG Sat Mar 7 15:18:59 2015 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 09C08F78; Sat, 7 Mar 2015 15:18:59 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id DE665C50; Sat, 7 Mar 2015 15:18:58 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t27FIwoE097300; Sat, 7 Mar 2015 15:18:58 GMT (envelope-from ian@FreeBSD.org) Received: (from ian@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t27FIvUf097296; Sat, 7 Mar 2015 15:18:57 GMT (envelope-from ian@FreeBSD.org) Message-Id: <201503071518.t27FIvUf097296@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: ian set sender to ian@FreeBSD.org using -f From: Ian Lepore Date: Sat, 7 Mar 2015 15:18:57 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r279723 - head/sys/dev/uart X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 07 Mar 2015 15:18:59 -0000 Author: ian Date: Sat Mar 7 15:18:57 2015 New Revision: 279723 URL: https://svnweb.freebsd.org/changeset/base/279723 Log: Define new linker set, UART_FDT_CLASS_AND_DEVICE, for registering full (class and device) FDT UART. Define second one, UART_FDT_CLASS, for UART class only. This paves the way for declaring uart_class data and ofw/fdt compat data with a uart implementation, rather than needing a big global table of compat data and weak-symbol declarations of every existing implementation. Differential Revision: https://reviews.freebsd.org/D1992 Submitted by: Michal Meloun Added: head/sys/dev/uart/uart_cpu_fdt.h (contents, props changed) Modified: head/sys/dev/uart/uart.h head/sys/dev/uart/uart_bus_fdt.c head/sys/dev/uart/uart_cpu_fdt.c Modified: head/sys/dev/uart/uart.h ============================================================================== --- head/sys/dev/uart/uart.h Sat Mar 7 13:54:44 2015 (r279722) +++ head/sys/dev/uart/uart.h Sat Mar 7 15:18:57 2015 (r279723) @@ -80,10 +80,6 @@ extern struct uart_class uart_vybrid_cla extern struct uart_class at91_usart_class __attribute__((weak)); extern struct uart_class uart_exynos4210_class __attribute__((weak)); -#ifdef FDT -struct ofw_compat_data; -extern const struct ofw_compat_data *uart_fdt_compat_data; -#endif #ifdef PC98 struct uart_class *uart_pc98_getdev(u_long port); Modified: head/sys/dev/uart/uart_bus_fdt.c ============================================================================== --- head/sys/dev/uart/uart_bus_fdt.c Sat Mar 7 13:54:44 2015 (r279722) +++ head/sys/dev/uart/uart_bus_fdt.c Sat Mar 7 15:18:57 2015 (r279723) @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include static int uart_fdt_probe(device_t); @@ -91,7 +92,7 @@ static struct ofw_compat_data compat_dat }; /* Export the compat_data table for use by the uart_cpu_fdt.c probe routine. */ -const struct ofw_compat_data *uart_fdt_compat_data = compat_data; +UART_FDT_CLASS_AND_DEVICE(compat_data); static int uart_fdt_get_clock(phandle_t node, pcell_t *cell) @@ -127,6 +128,20 @@ uart_fdt_get_shift(phandle_t node, pcell return (0); } +static uintptr_t +uart_fdt_find_device(device_t dev) +{ + struct ofw_compat_data **cd; + const struct ofw_compat_data *ocd; + + SET_FOREACH(cd, uart_fdt_class_and_device_set) { + ocd = ofw_bus_search_compatible(dev, *cd); + if (ocd->ocd_data != 0) + return (ocd->ocd_data); + } + return (0); +} + static int uart_fdt_probe(device_t dev) { @@ -134,19 +149,16 @@ uart_fdt_probe(device_t dev) phandle_t node; pcell_t clock, shift; int err; - const struct ofw_compat_data * cd; sc = device_get_softc(dev); if (!ofw_bus_status_okay(dev)) return (ENXIO); - cd = ofw_bus_search_compatible(dev, compat_data); - if (cd->ocd_data == (uintptr_t)NULL) + sc->sc_class = (struct uart_class *)uart_fdt_find_device(dev); + if (sc->sc_class == NULL) return (ENXIO); - sc->sc_class = (struct uart_class *)cd->ocd_data; - node = ofw_bus_get_node(dev); if ((err = uart_fdt_get_clock(node, &clock)) != 0) Modified: head/sys/dev/uart/uart_cpu_fdt.c ============================================================================== --- head/sys/dev/uart/uart_cpu_fdt.c Sat Mar 7 13:54:44 2015 (r279722) +++ head/sys/dev/uart/uart_cpu_fdt.c Sat Mar 7 15:18:57 2015 (r279723) @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include /* * UART console routines. @@ -115,13 +116,46 @@ phandle_chosen_propdev(phandle_t chosen, return (0); } +static const struct ofw_compat_data * +uart_fdt_find_compatible(phandle_t node, const struct ofw_compat_data *cd) +{ + const struct ofw_compat_data *ocd; + + for (ocd = cd; ocd->ocd_str != NULL; ocd++) { + if (fdt_is_compatible(node, ocd->ocd_str)) + return (ocd); + } + return (NULL); +} + +static uintptr_t +uart_fdt_find_by_node(phandle_t node, int class_list) +{ + struct ofw_compat_data **cd; + const struct ofw_compat_data *ocd; + + if (class_list) { + SET_FOREACH(cd, uart_fdt_class_set) { + ocd = uart_fdt_find_compatible(node, *cd); + if ((ocd != NULL) && (ocd->ocd_data != 0)) + return (ocd->ocd_data); + } + } else { + SET_FOREACH(cd, uart_fdt_class_and_device_set) { + ocd = uart_fdt_find_compatible(node, *cd); + if ((ocd != NULL) && (ocd->ocd_data != 0)) + return (ocd->ocd_data); + } + } + return (0); +} + int uart_cpu_getdev(int devtype, struct uart_devinfo *di) { const char *propnames[] = {"stdout-path", "linux,stdout-path", "stdout", "stdin-path", "stdin", NULL}; const char **name; - const struct ofw_compat_data *cd; struct uart_class *class; phandle_t node, chosen; pcell_t shift, br, rclk; @@ -160,24 +194,32 @@ uart_cpu_getdev(int devtype, struct uart * Retrieve serial attributes. */ uart_fdt_get_shift(node, &shift); - if (OF_getprop(node, "current-speed", &br, sizeof(br)) <= 0) br = 0; - br = fdt32_to_cpu(br); + else + br = fdt32_to_cpu(br); - if ((err = uart_fdt_get_clock(node, &rclk)) != 0) - return (err); /* - * Finalize configuration. + * Check old style of UART definition first. Unfortunately, the common + * FDT processing is not possible if we have clock, power domains and + * pinmux stuff. */ - for (cd = uart_fdt_compat_data; cd->ocd_str != NULL; ++cd) { - if (fdt_is_compatible(node, cd->ocd_str)) - break; + class = (struct uart_class *)uart_fdt_find_by_node(node, 0); + if (class != NULL) { + if ((err = uart_fdt_get_clock(node, &rclk)) != 0) + return (err); + } else { + /* Check class only linker set */ + class = + (struct uart_class *)uart_fdt_find_by_node(node, 1); + if (class == NULL) + return (ENXIO); + rclk = 0; } - if (cd->ocd_str == NULL) - return (ENXIO); - class = (struct uart_class *)cd->ocd_data; + /* + * Finalize configuration. + */ di->bas.chan = 0; di->bas.regshft = (u_int)shift; di->baudrate = br; Added: head/sys/dev/uart/uart_cpu_fdt.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/uart/uart_cpu_fdt.h Sat Mar 7 15:18:57 2015 (r279723) @@ -0,0 +1,54 @@ +/*- + * Copyright 2015 Michal Meloun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _DEV_UART_CPU_FDT_H_ +#define _DEV_UART_CPU_FDT_H_ + +#include + +#include + +/* + * If your UART driver implements only uart_class and uses uart_cpu_fdt.c + * for device instantiation, then use UART_FDT_CLASS_AND_DEVICE for its + * declaration + */ +SET_DECLARE(uart_fdt_class_and_device_set, struct ofw_compat_data ); +#define UART_FDT_CLASS_AND_DEVICE(data) \ + DATA_SET(uart_fdt_class_and_device_set, data) + +/* + * If your UART driver implements uart_class and custom device layer, + * then use UART_FDT_CLASS for its declaration + */ +SET_DECLARE(uart_fdt_class_set, struct ofw_compat_data ); +#define UART_FDT_CLASS(data) \ + DATA_SET(uart_fdt_class_set, data) + + +#endif /* _DEV_UART_CPU_FDT_H_ */