[BACK]Return to dw_apb_uart.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / fdt

Annotation of src/sys/dev/fdt/dw_apb_uart.c, Revision 1.10

1.10    ! thorpej     1: /* $NetBSD: dw_apb_uart.c,v 1.9 2021/01/15 20:50:49 ryo Exp $ */
1.1       jmcneill    2:
                      3: /*-
                      4:  * Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     17:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     18:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     19:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     20:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     21:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     22:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     23:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     24:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     25:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29: #include <sys/cdefs.h>
                     30:
1.10    ! thorpej    31: __KERNEL_RCSID(1, "$NetBSD: dw_apb_uart.c,v 1.9 2021/01/15 20:50:49 ryo Exp $");
1.1       jmcneill   32:
                     33: #include <sys/param.h>
                     34: #include <sys/bus.h>
                     35: #include <sys/device.h>
                     36: #include <sys/intr.h>
                     37: #include <sys/systm.h>
                     38: #include <sys/time.h>
                     39: #include <sys/termios.h>
                     40:
                     41: #include <dev/ic/comvar.h>
                     42:
                     43: #include <dev/fdt/fdtvar.h>
                     44:
                     45: static int dw_apb_uart_match(device_t, cfdata_t, void *);
                     46: static void dw_apb_uart_attach(device_t, device_t, void *);
                     47:
1.10    ! thorpej    48: static const struct device_compatible_entry compat_data[] = {
        !            49:        { .compat = "snps,dw-apb-uart" },
        !            50:        DEVICE_COMPAT_EOL
1.1       jmcneill   51: };
                     52:
                     53: struct dw_apb_uart_softc {
                     54:        struct com_softc ssc_sc;
                     55:        void *ssc_ih;
                     56:
                     57:        struct clk *ssc_clk;
1.2       jmcneill   58:        struct clk *ssc_pclk;
1.1       jmcneill   59:        struct fdtbus_reset *ssc_rst;
                     60: };
                     61:
                     62: CFATTACH_DECL_NEW(dw_apb_uart, sizeof(struct dw_apb_uart_softc),
                     63:        dw_apb_uart_match, dw_apb_uart_attach, NULL, NULL);
                     64:
                     65: static int
                     66: dw_apb_uart_match(device_t parent, cfdata_t cf, void *aux)
                     67: {
                     68:        struct fdt_attach_args * const faa = aux;
                     69:
1.10    ! thorpej    70:        return of_compatible_match(faa->faa_phandle, compat_data);
1.1       jmcneill   71: }
                     72:
                     73: static void
                     74: dw_apb_uart_attach(device_t parent, device_t self, void *aux)
                     75: {
                     76:        struct dw_apb_uart_softc * const ssc = device_private(self);
                     77:        struct com_softc * const sc = &ssc->ssc_sc;
                     78:        struct fdt_attach_args * const faa = aux;
1.6       jmcneill   79:        bus_space_tag_t bst = faa->faa_bst;
1.1       jmcneill   80:        bus_space_handle_t bsh;
                     81:        char intrstr[128];
                     82:        bus_addr_t addr;
                     83:        bus_size_t size;
                     84:        u_int reg_shift;
                     85:        int error;
                     86:
                     87:        if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
                     88:                aprint_error(": couldn't get registers\n");
                     89:                return;
                     90:        }
                     91:
                     92:        if (of_getprop_uint32(faa->faa_phandle, "reg-shift", &reg_shift)) {
                     93:                /* missing or bad reg-shift property, assume 2 */
1.6       jmcneill   94:                reg_shift = 2;
1.1       jmcneill   95:        }
                     96:
                     97:        sc->sc_dev = self;
                     98:
                     99:        ssc->ssc_clk = fdtbus_clock_get_index(faa->faa_phandle, 0);
                    100:        if (ssc->ssc_clk == NULL) {
                    101:                aprint_error(": couldn't get clock\n");
                    102:                return;
                    103:        }
                    104:        if (clk_enable(ssc->ssc_clk) != 0) {
                    105:                aprint_error(": couldn't enable clock\n");
                    106:                return;
                    107:        }
                    108:
1.2       jmcneill  109:        ssc->ssc_pclk = fdtbus_clock_get(faa->faa_phandle, "apb_pclk");
                    110:        if (ssc->ssc_pclk != NULL && clk_enable(ssc->ssc_pclk) != 0) {
                    111:                aprint_error(": couldn't enable peripheral clock\n");
                    112:                return;
                    113:        }
                    114:
1.1       jmcneill  115:        ssc->ssc_rst = fdtbus_reset_get_index(faa->faa_phandle, 0);
                    116:        if (ssc->ssc_rst && fdtbus_reset_deassert(ssc->ssc_rst) != 0) {
                    117:                aprint_error(": couldn't de-assert reset\n");
                    118:                return;
                    119:        }
                    120:
                    121:        sc->sc_frequency = clk_get_rate(ssc->ssc_clk);
                    122:        sc->sc_type = COM_TYPE_DW_APB;
                    123:
                    124:        error = bus_space_map(bst, addr, size, 0, &bsh);
                    125:        if (error) {
1.3       christos  126:                aprint_error(": couldn't map %#" PRIx64 ": %d", (uint64_t)addr, error);
1.1       jmcneill  127:                return;
                    128:        }
                    129:
1.6       jmcneill  130:        com_init_regs_stride(&sc->sc_regs, bst, bsh, addr, reg_shift);
1.1       jmcneill  131:
                    132:        com_attach_subr(sc);
                    133:
                    134:        if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) {
                    135:                aprint_error_dev(self, "failed to decode interrupt\n");
                    136:                return;
                    137:        }
                    138:
1.9       ryo       139:        ssc->ssc_ih = fdtbus_intr_establish_xname(faa->faa_phandle, 0,
                    140:            IPL_SERIAL, FDT_INTR_MPSAFE, comintr, sc, device_xname(self));
1.1       jmcneill  141:        if (ssc->ssc_ih == NULL) {
                    142:                aprint_error_dev(self, "failed to establish interrupt on %s\n",
                    143:                    intrstr);
                    144:        }
                    145:        aprint_normal_dev(self, "interrupting on %s\n", intrstr);
                    146: }
                    147:
                    148: /*
                    149:  * Console support
                    150:  */
                    151:
                    152: static int
                    153: dw_apb_uart_console_match(int phandle)
                    154: {
1.10    ! thorpej   155:        return of_compatible_match(phandle, compat_data);
1.1       jmcneill  156: }
                    157:
                    158: static void
                    159: dw_apb_uart_console_consinit(struct fdt_attach_args *faa, u_int uart_freq)
                    160: {
                    161:        const int phandle = faa->faa_phandle;
1.6       jmcneill  162:        bus_space_tag_t bst = faa->faa_bst;
                    163:        bus_space_handle_t dummy_bsh;
                    164:        struct com_regs regs;
1.1       jmcneill  165:        bus_addr_t addr;
                    166:        tcflag_t flags;
1.6       jmcneill  167:        u_int reg_shift;
1.1       jmcneill  168:        int speed;
                    169:
                    170:        fdtbus_get_reg(phandle, 0, &addr, NULL);
                    171:        speed = fdtbus_get_stdout_speed();
                    172:        if (speed < 0)
                    173:                speed = 115200; /* default */
                    174:        flags = fdtbus_get_stdout_flags();
                    175:
1.6       jmcneill  176:        if (of_getprop_uint32(phandle, "reg-shift", &reg_shift)) {
1.7       jmcneill  177:                /* missing or bad reg-shift property, assume 2 */
                    178:                reg_shift = 2;
1.6       jmcneill  179:        }
                    180:
                    181:        memset(&dummy_bsh, 0, sizeof(dummy_bsh));
                    182:        com_init_regs_stride(&regs, bst, dummy_bsh, addr, reg_shift);
                    183:
                    184:        if (comcnattach1(&regs, speed, uart_freq, COM_TYPE_DW_APB, flags))
1.1       jmcneill  185:                panic("Cannot initialize dw-apb-uart console");
                    186: }
                    187:
                    188: static const struct fdt_console dw_apb_uart_console = {
                    189:        .match = dw_apb_uart_console_match,
                    190:        .consinit = dw_apb_uart_console_consinit,
                    191: };
                    192:
                    193: FDT_CONSOLE(dw_apb_uart, &dw_apb_uart_console);

CVSweb <webmaster@jp.NetBSD.org>