1*72ef722bSBjoern A. Zeeb /*- 2*72ef722bSBjoern A. Zeeb * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause 3*72ef722bSBjoern A. Zeeb */ 4*72ef722bSBjoern A. Zeeb /* 5*72ef722bSBjoern A. Zeeb * // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 6*72ef722bSBjoern A. Zeeb * 7*72ef722bSBjoern A. Zeeb * Freescale DPAA2 Platforms Console Driver 8*72ef722bSBjoern A. Zeeb * 9*72ef722bSBjoern A. Zeeb * Copyright 2015-2016 Freescale Semiconductor Inc. 10*72ef722bSBjoern A. Zeeb * Copyright 2018 NXP 11*72ef722bSBjoern A. Zeeb * 12*72ef722bSBjoern A. Zeeb * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/drivers/soc/fsl/dpaa2-console.c#8120bd469f5525da229953c1197f2b826c0109f4 13*72ef722bSBjoern A. Zeeb */ 14*72ef722bSBjoern A. Zeeb /* 15*72ef722bSBjoern A. Zeeb * Copyright (c) 2022-2023 Bjoern A. Zeeb 16*72ef722bSBjoern A. Zeeb * 17*72ef722bSBjoern A. Zeeb * Redistribution and use in source and binary forms, with or without 18*72ef722bSBjoern A. Zeeb * modification, are permitted provided that the following conditions 19*72ef722bSBjoern A. Zeeb * are met: 20*72ef722bSBjoern A. Zeeb * 1. Redistributions of source code must retain the above copyright 21*72ef722bSBjoern A. Zeeb * notice, this list of conditions and the following disclaimer. 22*72ef722bSBjoern A. Zeeb * 2. Redistributions in binary form must reproduce the above copyright 23*72ef722bSBjoern A. Zeeb * notice, this list of conditions and the following disclaimer in the 24*72ef722bSBjoern A. Zeeb * documentation and/or other materials provided with the distribution. 25*72ef722bSBjoern A. Zeeb * 26*72ef722bSBjoern A. Zeeb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 27*72ef722bSBjoern A. Zeeb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28*72ef722bSBjoern A. Zeeb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29*72ef722bSBjoern A. Zeeb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 30*72ef722bSBjoern A. Zeeb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31*72ef722bSBjoern A. Zeeb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32*72ef722bSBjoern A. Zeeb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33*72ef722bSBjoern A. Zeeb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34*72ef722bSBjoern A. Zeeb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35*72ef722bSBjoern A. Zeeb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36*72ef722bSBjoern A. Zeeb * SUCH DAMAGE. 37*72ef722bSBjoern A. Zeeb */ 38*72ef722bSBjoern A. Zeeb 39*72ef722bSBjoern A. Zeeb /* 40*72ef722bSBjoern A. Zeeb * Some docs are in: 41*72ef722bSBjoern A. Zeeb * - https://www.nxp.com.cn/docs/en/application-note/AN13329.pdf 42*72ef722bSBjoern A. Zeeb * - DPAA2UM 43*72ef722bSBjoern A. Zeeb * - git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/drivers/soc/fsl/dpaa2-console.c 44*72ef722bSBjoern A. Zeeb */ 45*72ef722bSBjoern A. Zeeb 46*72ef722bSBjoern A. Zeeb #include "opt_platform.h" 47*72ef722bSBjoern A. Zeeb #ifdef __notyet__ 48*72ef722bSBjoern A. Zeeb #include "opt_acpi.h" 49*72ef722bSBjoern A. Zeeb #endif 50*72ef722bSBjoern A. Zeeb 51*72ef722bSBjoern A. Zeeb #include <sys/cdefs.h> 52*72ef722bSBjoern A. Zeeb #include <sys/param.h> 53*72ef722bSBjoern A. Zeeb #include <sys/bus.h> 54*72ef722bSBjoern A. Zeeb #include <sys/conf.h> 55*72ef722bSBjoern A. Zeeb #include <sys/fcntl.h> 56*72ef722bSBjoern A. Zeeb #include <sys/kernel.h> 57*72ef722bSBjoern A. Zeeb #include <sys/malloc.h> 58*72ef722bSBjoern A. Zeeb #include <sys/module.h> 59*72ef722bSBjoern A. Zeeb #include <sys/mutex.h> 60*72ef722bSBjoern A. Zeeb #include <sys/rman.h> 61*72ef722bSBjoern A. Zeeb #include <sys/stat.h> 62*72ef722bSBjoern A. Zeeb #include <sys/uio.h> 63*72ef722bSBjoern A. Zeeb 64*72ef722bSBjoern A. Zeeb #include <machine/bus.h> 65*72ef722bSBjoern A. Zeeb #include <machine/resource.h> 66*72ef722bSBjoern A. Zeeb 67*72ef722bSBjoern A. Zeeb #ifdef FDT 68*72ef722bSBjoern A. Zeeb #include <dev/ofw/ofw_bus.h> 69*72ef722bSBjoern A. Zeeb #include <dev/ofw/ofw_bus_subr.h> 70*72ef722bSBjoern A. Zeeb #endif 71*72ef722bSBjoern A. Zeeb 72*72ef722bSBjoern A. Zeeb /* Table 6-1. MC Memory Map */ 73*72ef722bSBjoern A. Zeeb #define MC_REG_MCFBA 0x20 74*72ef722bSBjoern A. Zeeb #define MC_REG_MCFBALR_OFF 0x00 75*72ef722bSBjoern A. Zeeb #define MC_REG_MCFBALR_MASK 0xe0000000 76*72ef722bSBjoern A. Zeeb #define MC_REG_MCFBAHR_OFF 0x04 77*72ef722bSBjoern A. Zeeb #define MC_REG_MCFBAHR_MASK 0x0001ffff 78*72ef722bSBjoern A. Zeeb 79*72ef722bSBjoern A. Zeeb /* Firmware Consoles. */ 80*72ef722bSBjoern A. Zeeb #define MC_BUFFER_OFFSET 0x01000000 81*72ef722bSBjoern A. Zeeb #define MC_BUFFER_SIZE (1024 * 1024 * 16) 82*72ef722bSBjoern A. Zeeb #define MC_OFFSET_DELTA MC_BUFFER_OFFSET 83*72ef722bSBjoern A. Zeeb 84*72ef722bSBjoern A. Zeeb #define AIOP_BUFFER_OFFSET 0x06000000 85*72ef722bSBjoern A. Zeeb #define AIOP_BUFFER_SIZE (1024 * 1024 * 16) 86*72ef722bSBjoern A. Zeeb #define AIOP_OFFSET_DELTA 0 87*72ef722bSBjoern A. Zeeb 88*72ef722bSBjoern A. Zeeb /* MC and AIOP Magic words */ 89*72ef722bSBjoern A. Zeeb #define MAGIC_MC 0x4d430100 90*72ef722bSBjoern A. Zeeb #define MAGIC_AIOP 0X41494f50 91*72ef722bSBjoern A. Zeeb 92*72ef722bSBjoern A. Zeeb #define LOG_HEADER_FLAG_BUFFER_WRAPAROUND \ 93*72ef722bSBjoern A. Zeeb 0x80000000 94*72ef722bSBjoern A. Zeeb #define LAST_BYTE(a) \ 95*72ef722bSBjoern A. Zeeb ((a) & ~(LOG_HEADER_FLAG_BUFFER_WRAPAROUND)) 96*72ef722bSBjoern A. Zeeb 97*72ef722bSBjoern A. Zeeb struct dpaa2_cons_dev { 98*72ef722bSBjoern A. Zeeb struct cdev *cdev; 99*72ef722bSBjoern A. Zeeb struct mtx mtx; 100*72ef722bSBjoern A. Zeeb size_t offset; 101*72ef722bSBjoern A. Zeeb uint32_t magic; 102*72ef722bSBjoern A. Zeeb 103*72ef722bSBjoern A. Zeeb uint32_t hdr_magic; 104*72ef722bSBjoern A. Zeeb uint32_t hdr_eobyte; 105*72ef722bSBjoern A. Zeeb uint32_t hdr_start; 106*72ef722bSBjoern A. Zeeb uint32_t hdr_len; 107*72ef722bSBjoern A. Zeeb 108*72ef722bSBjoern A. Zeeb uoff_t start; 109*72ef722bSBjoern A. Zeeb uoff_t end; 110*72ef722bSBjoern A. Zeeb uoff_t eod; 111*72ef722bSBjoern A. Zeeb uoff_t cur; 112*72ef722bSBjoern A. Zeeb 113*72ef722bSBjoern A. Zeeb bus_space_tag_t bst; 114*72ef722bSBjoern A. Zeeb bus_space_handle_t bsh; 115*72ef722bSBjoern A. Zeeb vm_size_t size; 116*72ef722bSBjoern A. Zeeb }; 117*72ef722bSBjoern A. Zeeb 118*72ef722bSBjoern A. Zeeb struct dpaa2_cons_softc { 119*72ef722bSBjoern A. Zeeb struct resource *res; 120*72ef722bSBjoern A. Zeeb bus_space_tag_t bst; 121*72ef722bSBjoern A. Zeeb uint64_t mcfba; 122*72ef722bSBjoern A. Zeeb struct dpaa2_cons_dev mc_cd; 123*72ef722bSBjoern A. Zeeb struct dpaa2_cons_dev aiop_cd; 124*72ef722bSBjoern A. Zeeb }; 125*72ef722bSBjoern A. Zeeb 126*72ef722bSBjoern A. Zeeb struct dpaa2_cons_hdr { 127*72ef722bSBjoern A. Zeeb uint32_t magic; 128*72ef722bSBjoern A. Zeeb uint32_t _reserved; 129*72ef722bSBjoern A. Zeeb uint32_t start; 130*72ef722bSBjoern A. Zeeb uint32_t len; 131*72ef722bSBjoern A. Zeeb uint32_t eobyte; 132*72ef722bSBjoern A. Zeeb }; 133*72ef722bSBjoern A. Zeeb 134*72ef722bSBjoern A. Zeeb #define DPAA2_MC_READ_4(_sc, _r) bus_read_4((_sc)->res, (_r)) 135*72ef722bSBjoern A. Zeeb 136*72ef722bSBjoern A. Zeeb /* Management interface */ 137*72ef722bSBjoern A. Zeeb static d_open_t dpaa2_cons_open; 138*72ef722bSBjoern A. Zeeb static d_close_t dpaa2_cons_close; 139*72ef722bSBjoern A. Zeeb static d_read_t dpaa2_cons_read; 140*72ef722bSBjoern A. Zeeb 141*72ef722bSBjoern A. Zeeb static struct cdevsw dpaa2_mc_cons_cdevsw = { 142*72ef722bSBjoern A. Zeeb .d_version = D_VERSION, 143*72ef722bSBjoern A. Zeeb .d_flags = 0, 144*72ef722bSBjoern A. Zeeb .d_open = dpaa2_cons_open, 145*72ef722bSBjoern A. Zeeb .d_close = dpaa2_cons_close, 146*72ef722bSBjoern A. Zeeb .d_read = dpaa2_cons_read, 147*72ef722bSBjoern A. Zeeb .d_name = "fsl_mc_console", 148*72ef722bSBjoern A. Zeeb }; 149*72ef722bSBjoern A. Zeeb 150*72ef722bSBjoern A. Zeeb static struct cdevsw dpaa2_aiop_cons_cdevsw = { 151*72ef722bSBjoern A. Zeeb .d_version = D_VERSION, 152*72ef722bSBjoern A. Zeeb .d_flags = 0, 153*72ef722bSBjoern A. Zeeb .d_open = dpaa2_cons_open, 154*72ef722bSBjoern A. Zeeb .d_close = dpaa2_cons_close, 155*72ef722bSBjoern A. Zeeb .d_read = dpaa2_cons_read, 156*72ef722bSBjoern A. Zeeb .d_name = "fsl_aiop_console", 157*72ef722bSBjoern A. Zeeb }; 158*72ef722bSBjoern A. Zeeb 159*72ef722bSBjoern A. Zeeb static size_t 160*72ef722bSBjoern A. Zeeb dpaa2_cons_read_bs(struct dpaa2_cons_dev *cd, size_t offset, void *dst, size_t len) 161*72ef722bSBjoern A. Zeeb { 162*72ef722bSBjoern A. Zeeb size_t count, l; 163*72ef722bSBjoern A. Zeeb uint8_t *p; 164*72ef722bSBjoern A. Zeeb 165*72ef722bSBjoern A. Zeeb count = 0; 166*72ef722bSBjoern A. Zeeb p = dst; 167*72ef722bSBjoern A. Zeeb l = offset % 8; 168*72ef722bSBjoern A. Zeeb if (l != 0) { 169*72ef722bSBjoern A. Zeeb bus_space_read_region_1(cd->bst, cd->bsh, offset + count, p + count, l); 170*72ef722bSBjoern A. Zeeb count += l; 171*72ef722bSBjoern A. Zeeb len -= l; 172*72ef722bSBjoern A. Zeeb } 173*72ef722bSBjoern A. Zeeb 174*72ef722bSBjoern A. Zeeb l = len / 8; 175*72ef722bSBjoern A. Zeeb if (l != 0) { 176*72ef722bSBjoern A. Zeeb bus_space_read_region_8(cd->bst, cd->bsh, offset + count, (uint64_t *)(p + count), l); 177*72ef722bSBjoern A. Zeeb l *= 8; 178*72ef722bSBjoern A. Zeeb count += l; 179*72ef722bSBjoern A. Zeeb len -= l; 180*72ef722bSBjoern A. Zeeb } 181*72ef722bSBjoern A. Zeeb l = len / 4; 182*72ef722bSBjoern A. Zeeb if (l != 0) { 183*72ef722bSBjoern A. Zeeb bus_space_read_region_4(cd->bst, cd->bsh, offset + count, (uint32_t *)(p + count), l); 184*72ef722bSBjoern A. Zeeb l *= 4; 185*72ef722bSBjoern A. Zeeb count += l; 186*72ef722bSBjoern A. Zeeb len -= l; 187*72ef722bSBjoern A. Zeeb } 188*72ef722bSBjoern A. Zeeb l = len / 2; 189*72ef722bSBjoern A. Zeeb if (l != 0) { 190*72ef722bSBjoern A. Zeeb bus_space_read_region_2(cd->bst, cd->bsh, offset + count, (uint16_t *)(p + count), l); 191*72ef722bSBjoern A. Zeeb l *= 2; 192*72ef722bSBjoern A. Zeeb count += l; 193*72ef722bSBjoern A. Zeeb len -= l; 194*72ef722bSBjoern A. Zeeb } 195*72ef722bSBjoern A. Zeeb if (len != 0) { 196*72ef722bSBjoern A. Zeeb bus_space_read_region_1(cd->bst, cd->bsh, offset + count, p + count, len); 197*72ef722bSBjoern A. Zeeb count += len; 198*72ef722bSBjoern A. Zeeb } 199*72ef722bSBjoern A. Zeeb 200*72ef722bSBjoern A. Zeeb return (count); 201*72ef722bSBjoern A. Zeeb } 202*72ef722bSBjoern A. Zeeb 203*72ef722bSBjoern A. Zeeb static int 204*72ef722bSBjoern A. Zeeb dpaa2_cons_open(struct cdev *cdev, int flags, int fmt, struct thread *td) 205*72ef722bSBjoern A. Zeeb { 206*72ef722bSBjoern A. Zeeb struct dpaa2_cons_dev *cd; 207*72ef722bSBjoern A. Zeeb struct dpaa2_cons_hdr hdr; 208*72ef722bSBjoern A. Zeeb size_t rlen __diagused; 209*72ef722bSBjoern A. Zeeb uint32_t wrapped; 210*72ef722bSBjoern A. Zeeb 211*72ef722bSBjoern A. Zeeb if (flags & FWRITE) 212*72ef722bSBjoern A. Zeeb return (EACCES); 213*72ef722bSBjoern A. Zeeb 214*72ef722bSBjoern A. Zeeb cd = cdev->si_drv1; 215*72ef722bSBjoern A. Zeeb if (cd->size == 0) 216*72ef722bSBjoern A. Zeeb return (ENODEV); 217*72ef722bSBjoern A. Zeeb 218*72ef722bSBjoern A. Zeeb mtx_lock(&cd->mtx); 219*72ef722bSBjoern A. Zeeb rlen = dpaa2_cons_read_bs(cd, 0, &hdr, sizeof(hdr)); 220*72ef722bSBjoern A. Zeeb KASSERT(rlen == sizeof(hdr), ("%s:%d: rlen %zu != count %zu, cdev %p " 221*72ef722bSBjoern A. Zeeb "cd %p\n", __func__, __LINE__, rlen, sizeof(hdr), cdev, cd)); 222*72ef722bSBjoern A. Zeeb 223*72ef722bSBjoern A. Zeeb cd->hdr_magic = hdr.magic; 224*72ef722bSBjoern A. Zeeb if (cd->hdr_magic != cd->magic) { 225*72ef722bSBjoern A. Zeeb mtx_unlock(&cd->mtx); 226*72ef722bSBjoern A. Zeeb return (ENODEV); 227*72ef722bSBjoern A. Zeeb } 228*72ef722bSBjoern A. Zeeb 229*72ef722bSBjoern A. Zeeb cd->hdr_eobyte = hdr.eobyte; 230*72ef722bSBjoern A. Zeeb cd->hdr_start = hdr.start; 231*72ef722bSBjoern A. Zeeb cd->hdr_len = hdr.len; 232*72ef722bSBjoern A. Zeeb 233*72ef722bSBjoern A. Zeeb cd->start = cd->hdr_start - cd->offset; 234*72ef722bSBjoern A. Zeeb cd->end = cd->start + cd->hdr_len; 235*72ef722bSBjoern A. Zeeb 236*72ef722bSBjoern A. Zeeb wrapped = cd->hdr_eobyte & LOG_HEADER_FLAG_BUFFER_WRAPAROUND; 237*72ef722bSBjoern A. Zeeb cd->eod = cd->start + LAST_BYTE(cd->hdr_eobyte); 238*72ef722bSBjoern A. Zeeb 239*72ef722bSBjoern A. Zeeb if (wrapped && cd->eod != cd->end) 240*72ef722bSBjoern A. Zeeb cd->cur = cd->eod + 1; 241*72ef722bSBjoern A. Zeeb else 242*72ef722bSBjoern A. Zeeb cd->cur = cd->start; 243*72ef722bSBjoern A. Zeeb mtx_unlock(&cd->mtx); 244*72ef722bSBjoern A. Zeeb 245*72ef722bSBjoern A. Zeeb return (0); 246*72ef722bSBjoern A. Zeeb } 247*72ef722bSBjoern A. Zeeb 248*72ef722bSBjoern A. Zeeb static int 249*72ef722bSBjoern A. Zeeb dpaa2_cons_close(struct cdev *cdev, int flags, int fmt, struct thread *td) 250*72ef722bSBjoern A. Zeeb { 251*72ef722bSBjoern A. Zeeb struct dpaa2_cons_dev *cd; 252*72ef722bSBjoern A. Zeeb 253*72ef722bSBjoern A. Zeeb cd = cdev->si_drv1; 254*72ef722bSBjoern A. Zeeb mtx_lock(&cd->mtx); 255*72ef722bSBjoern A. Zeeb cd->hdr_magic = cd->hdr_eobyte = cd->hdr_start = cd->hdr_len = 0; 256*72ef722bSBjoern A. Zeeb cd->start = cd->end = 0; 257*72ef722bSBjoern A. Zeeb mtx_unlock(&cd->mtx); 258*72ef722bSBjoern A. Zeeb 259*72ef722bSBjoern A. Zeeb return (0); 260*72ef722bSBjoern A. Zeeb } 261*72ef722bSBjoern A. Zeeb 262*72ef722bSBjoern A. Zeeb static int 263*72ef722bSBjoern A. Zeeb dpaa2_cons_read(struct cdev *cdev, struct uio *uio, int flag) 264*72ef722bSBjoern A. Zeeb { 265*72ef722bSBjoern A. Zeeb char buf[128]; 266*72ef722bSBjoern A. Zeeb struct dpaa2_cons_dev *cd; 267*72ef722bSBjoern A. Zeeb size_t len, size, count; 268*72ef722bSBjoern A. Zeeb size_t rlen __diagused; 269*72ef722bSBjoern A. Zeeb int error; 270*72ef722bSBjoern A. Zeeb 271*72ef722bSBjoern A. Zeeb cd = cdev->si_drv1; 272*72ef722bSBjoern A. Zeeb mtx_lock(&cd->mtx); 273*72ef722bSBjoern A. Zeeb if (cd->cur == cd->eod) { 274*72ef722bSBjoern A. Zeeb mtx_unlock(&cd->mtx); 275*72ef722bSBjoern A. Zeeb return (0); 276*72ef722bSBjoern A. Zeeb } else if (cd->cur > cd->eod) { 277*72ef722bSBjoern A. Zeeb len = (cd->end - cd->cur) + (cd->eod - cd->start); 278*72ef722bSBjoern A. Zeeb } else { 279*72ef722bSBjoern A. Zeeb len = cd->eod - cd->cur; 280*72ef722bSBjoern A. Zeeb } 281*72ef722bSBjoern A. Zeeb size = cd->end - cd->cur; 282*72ef722bSBjoern A. Zeeb 283*72ef722bSBjoern A. Zeeb if (len > size) { 284*72ef722bSBjoern A. Zeeb /* dump cur [size] */ 285*72ef722bSBjoern A. Zeeb while (uio->uio_resid > 0) { 286*72ef722bSBjoern A. Zeeb count = imin(sizeof(buf), uio->uio_resid); 287*72ef722bSBjoern A. Zeeb if (count > size) 288*72ef722bSBjoern A. Zeeb count = size; 289*72ef722bSBjoern A. Zeeb 290*72ef722bSBjoern A. Zeeb rlen = dpaa2_cons_read_bs(cd, cd->cur, buf, count); 291*72ef722bSBjoern A. Zeeb KASSERT(rlen == count, ("%s:%d: rlen %zu != count %zu, " 292*72ef722bSBjoern A. Zeeb "cdev %p cd %p\n", __func__, __LINE__, rlen, count, 293*72ef722bSBjoern A. Zeeb cdev, cd)); 294*72ef722bSBjoern A. Zeeb 295*72ef722bSBjoern A. Zeeb cd->cur += count; 296*72ef722bSBjoern A. Zeeb len -= count; 297*72ef722bSBjoern A. Zeeb size -= count; 298*72ef722bSBjoern A. Zeeb mtx_unlock(&cd->mtx); 299*72ef722bSBjoern A. Zeeb error = uiomove(buf, count, uio); 300*72ef722bSBjoern A. Zeeb if (error != 0 || uio->uio_resid == 0) 301*72ef722bSBjoern A. Zeeb return (error); 302*72ef722bSBjoern A. Zeeb mtx_lock(&cd->mtx); 303*72ef722bSBjoern A. Zeeb } 304*72ef722bSBjoern A. Zeeb cd->cur = cd->start; 305*72ef722bSBjoern A. Zeeb } 306*72ef722bSBjoern A. Zeeb 307*72ef722bSBjoern A. Zeeb /* dump cur [len] */ 308*72ef722bSBjoern A. Zeeb while (len > 0 && uio->uio_resid > 0) { 309*72ef722bSBjoern A. Zeeb count = imin(sizeof(buf), uio->uio_resid); 310*72ef722bSBjoern A. Zeeb if (count > len) 311*72ef722bSBjoern A. Zeeb count = len; 312*72ef722bSBjoern A. Zeeb 313*72ef722bSBjoern A. Zeeb rlen = dpaa2_cons_read_bs(cd, cd->cur, buf, count); 314*72ef722bSBjoern A. Zeeb KASSERT(rlen == count, ("%s:%d: rlen %zu != count %zu, cdev %p " 315*72ef722bSBjoern A. Zeeb "cd %p\n", __func__, __LINE__, rlen, count, cdev, cd)); 316*72ef722bSBjoern A. Zeeb 317*72ef722bSBjoern A. Zeeb cd->cur += count; 318*72ef722bSBjoern A. Zeeb len -= count; 319*72ef722bSBjoern A. Zeeb mtx_unlock(&cd->mtx); 320*72ef722bSBjoern A. Zeeb error = uiomove(buf, count, uio); 321*72ef722bSBjoern A. Zeeb if (error != 0 || uio->uio_resid == 0) 322*72ef722bSBjoern A. Zeeb return (error); 323*72ef722bSBjoern A. Zeeb mtx_lock(&cd->mtx); 324*72ef722bSBjoern A. Zeeb } 325*72ef722bSBjoern A. Zeeb mtx_unlock(&cd->mtx); 326*72ef722bSBjoern A. Zeeb return (0); 327*72ef722bSBjoern A. Zeeb } 328*72ef722bSBjoern A. Zeeb 329*72ef722bSBjoern A. Zeeb static int 330*72ef722bSBjoern A. Zeeb dpaa2_cons_create_dev(device_t dev, bus_addr_t pa, size_t size, 331*72ef722bSBjoern A. Zeeb size_t offset, uint32_t magic, struct cdevsw *devsw, 332*72ef722bSBjoern A. Zeeb struct dpaa2_cons_dev *cd) 333*72ef722bSBjoern A. Zeeb { 334*72ef722bSBjoern A. Zeeb struct dpaa2_cons_softc *sc; 335*72ef722bSBjoern A. Zeeb struct dpaa2_cons_hdr hdr; 336*72ef722bSBjoern A. Zeeb struct make_dev_args md_args; 337*72ef722bSBjoern A. Zeeb size_t len; 338*72ef722bSBjoern A. Zeeb int error; 339*72ef722bSBjoern A. Zeeb 340*72ef722bSBjoern A. Zeeb sc = device_get_softc(dev); 341*72ef722bSBjoern A. Zeeb 342*72ef722bSBjoern A. Zeeb error = bus_space_map(sc->bst, pa, size, 0, &cd->bsh); 343*72ef722bSBjoern A. Zeeb if (error != 0) { 344*72ef722bSBjoern A. Zeeb device_printf(dev, "%s: failed to map bus space %#jx/%zu: %d\n", 345*72ef722bSBjoern A. Zeeb __func__, (uintmax_t)pa, size, error); 346*72ef722bSBjoern A. Zeeb return (error); 347*72ef722bSBjoern A. Zeeb } 348*72ef722bSBjoern A. Zeeb 349*72ef722bSBjoern A. Zeeb cd->bst = sc->bst; 350*72ef722bSBjoern A. Zeeb cd->size = size; 351*72ef722bSBjoern A. Zeeb 352*72ef722bSBjoern A. Zeeb len = dpaa2_cons_read_bs(cd, 0, &hdr, sizeof(hdr)); 353*72ef722bSBjoern A. Zeeb if (len != sizeof(hdr)) { 354*72ef722bSBjoern A. Zeeb device_printf(dev, "%s: failed to read hdr for %#jx/%zu: %d\n", 355*72ef722bSBjoern A. Zeeb __func__, (uintmax_t)pa, size, error); 356*72ef722bSBjoern A. Zeeb bus_space_unmap(cd->bst, cd->bsh, cd->size); 357*72ef722bSBjoern A. Zeeb cd->size = 0; 358*72ef722bSBjoern A. Zeeb return (EIO); 359*72ef722bSBjoern A. Zeeb } 360*72ef722bSBjoern A. Zeeb 361*72ef722bSBjoern A. Zeeb /* This checks probably needs to be removed one day? */ 362*72ef722bSBjoern A. Zeeb if (hdr.magic != magic) { 363*72ef722bSBjoern A. Zeeb if (bootverbose) 364*72ef722bSBjoern A. Zeeb device_printf(dev, "%s: magic wrong for %#jx/%zu: " 365*72ef722bSBjoern A. Zeeb "%#010x != %#010x, no console?\n", __func__, 366*72ef722bSBjoern A. Zeeb (uintmax_t)pa, size, hdr.magic, magic); 367*72ef722bSBjoern A. Zeeb bus_space_unmap(cd->bst, cd->bsh, cd->size); 368*72ef722bSBjoern A. Zeeb cd->size = 0; 369*72ef722bSBjoern A. Zeeb return (ENOENT); 370*72ef722bSBjoern A. Zeeb } 371*72ef722bSBjoern A. Zeeb 372*72ef722bSBjoern A. Zeeb if (hdr.start - offset > size) { 373*72ef722bSBjoern A. Zeeb device_printf(dev, "%s: range wrong for %#jx/%zu: %u - %zu > %zu\n", 374*72ef722bSBjoern A. Zeeb __func__, (uintmax_t)pa, size, hdr.start, offset, size); 375*72ef722bSBjoern A. Zeeb bus_space_unmap(cd->bst, cd->bsh, cd->size); 376*72ef722bSBjoern A. Zeeb cd->size = 0; 377*72ef722bSBjoern A. Zeeb return (ERANGE); 378*72ef722bSBjoern A. Zeeb } 379*72ef722bSBjoern A. Zeeb 380*72ef722bSBjoern A. Zeeb cd->offset = offset; 381*72ef722bSBjoern A. Zeeb cd->magic = magic; 382*72ef722bSBjoern A. Zeeb mtx_init(&cd->mtx, "dpaa2 cons", NULL, MTX_DEF); 383*72ef722bSBjoern A. Zeeb 384*72ef722bSBjoern A. Zeeb make_dev_args_init(&md_args); 385*72ef722bSBjoern A. Zeeb md_args.mda_devsw = devsw; 386*72ef722bSBjoern A. Zeeb md_args.mda_uid = 0; 387*72ef722bSBjoern A. Zeeb md_args.mda_gid = 69; 388*72ef722bSBjoern A. Zeeb md_args.mda_mode = S_IRUSR | S_IRGRP; 389*72ef722bSBjoern A. Zeeb md_args.mda_unit = 0; 390*72ef722bSBjoern A. Zeeb md_args.mda_si_drv1 = cd; 391*72ef722bSBjoern A. Zeeb error = make_dev_s(&md_args, &cd->cdev, "%s", devsw->d_name); 392*72ef722bSBjoern A. Zeeb if (error != 0) { 393*72ef722bSBjoern A. Zeeb device_printf(dev, "%s: make_dev_s failed for %#jx/%zu: %d\n", 394*72ef722bSBjoern A. Zeeb __func__, (uintmax_t)pa, size, error); 395*72ef722bSBjoern A. Zeeb mtx_destroy(&cd->mtx); 396*72ef722bSBjoern A. Zeeb bus_space_unmap(cd->bst, cd->bsh, cd->size); 397*72ef722bSBjoern A. Zeeb cd->size = 0; 398*72ef722bSBjoern A. Zeeb return (error); 399*72ef722bSBjoern A. Zeeb } 400*72ef722bSBjoern A. Zeeb 401*72ef722bSBjoern A. Zeeb if (bootverbose) 402*72ef722bSBjoern A. Zeeb device_printf(dev, "dpaa2 console %s at pa %#jx size %#010zx " 403*72ef722bSBjoern A. Zeeb "(%zu) offset %zu, hdr: magic %#010x start %#010x len " 404*72ef722bSBjoern A. Zeeb "%#010x eobyte %#010x\n", devsw->d_name, (uintmax_t)pa, 405*72ef722bSBjoern A. Zeeb size, size, offset, hdr.magic, hdr.start, hdr.len, hdr.eobyte); 406*72ef722bSBjoern A. Zeeb 407*72ef722bSBjoern A. Zeeb return (0); 408*72ef722bSBjoern A. Zeeb } 409*72ef722bSBjoern A. Zeeb 410*72ef722bSBjoern A. Zeeb static int 411*72ef722bSBjoern A. Zeeb dpaa2_cons_attach_common(device_t dev) 412*72ef722bSBjoern A. Zeeb { 413*72ef722bSBjoern A. Zeeb struct dpaa2_cons_softc *sc; 414*72ef722bSBjoern A. Zeeb 415*72ef722bSBjoern A. Zeeb sc = device_get_softc(dev); 416*72ef722bSBjoern A. Zeeb 417*72ef722bSBjoern A. Zeeb dpaa2_cons_create_dev(dev, (bus_addr_t)(sc->mcfba + MC_BUFFER_OFFSET), 418*72ef722bSBjoern A. Zeeb MC_BUFFER_SIZE, MC_OFFSET_DELTA, MAGIC_MC, 419*72ef722bSBjoern A. Zeeb &dpaa2_mc_cons_cdevsw, &sc->mc_cd); 420*72ef722bSBjoern A. Zeeb 421*72ef722bSBjoern A. Zeeb dpaa2_cons_create_dev(dev, (bus_addr_t)(sc->mcfba + AIOP_BUFFER_OFFSET), 422*72ef722bSBjoern A. Zeeb AIOP_BUFFER_SIZE, AIOP_OFFSET_DELTA, MAGIC_AIOP, 423*72ef722bSBjoern A. Zeeb &dpaa2_aiop_cons_cdevsw, &sc->aiop_cd); 424*72ef722bSBjoern A. Zeeb 425*72ef722bSBjoern A. Zeeb return (0); 426*72ef722bSBjoern A. Zeeb } 427*72ef722bSBjoern A. Zeeb 428*72ef722bSBjoern A. Zeeb static void 429*72ef722bSBjoern A. Zeeb dpaa2_cons_detach_common(struct dpaa2_cons_dev *cd) 430*72ef722bSBjoern A. Zeeb { 431*72ef722bSBjoern A. Zeeb 432*72ef722bSBjoern A. Zeeb bus_space_unmap(cd->bst, cd->bsh, cd->size); 433*72ef722bSBjoern A. Zeeb mtx_destroy(&cd->mtx); 434*72ef722bSBjoern A. Zeeb } 435*72ef722bSBjoern A. Zeeb 436*72ef722bSBjoern A. Zeeb static int 437*72ef722bSBjoern A. Zeeb dpaa2_cons_detach(device_t dev) 438*72ef722bSBjoern A. Zeeb { 439*72ef722bSBjoern A. Zeeb struct dpaa2_cons_softc *sc; 440*72ef722bSBjoern A. Zeeb 441*72ef722bSBjoern A. Zeeb sc = device_get_softc(dev); 442*72ef722bSBjoern A. Zeeb 443*72ef722bSBjoern A. Zeeb if (sc->aiop_cd.cdev != NULL) 444*72ef722bSBjoern A. Zeeb destroy_dev(sc->aiop_cd.cdev); 445*72ef722bSBjoern A. Zeeb if (sc->mc_cd.cdev != NULL) 446*72ef722bSBjoern A. Zeeb destroy_dev(sc->mc_cd.cdev); 447*72ef722bSBjoern A. Zeeb 448*72ef722bSBjoern A. Zeeb if (sc->aiop_cd.size != 0) 449*72ef722bSBjoern A. Zeeb dpaa2_cons_detach_common(&sc->aiop_cd); 450*72ef722bSBjoern A. Zeeb if (sc->mc_cd.size != 0) 451*72ef722bSBjoern A. Zeeb dpaa2_cons_detach_common(&sc->mc_cd); 452*72ef722bSBjoern A. Zeeb 453*72ef722bSBjoern A. Zeeb if (sc->res != NULL) 454*72ef722bSBjoern A. Zeeb bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->res), 455*72ef722bSBjoern A. Zeeb sc->res); 456*72ef722bSBjoern A. Zeeb 457*72ef722bSBjoern A. Zeeb return (0); 458*72ef722bSBjoern A. Zeeb } 459*72ef722bSBjoern A. Zeeb 460*72ef722bSBjoern A. Zeeb #ifdef __notyet__ 461*72ef722bSBjoern A. Zeeb #ifdef ACPI 462*72ef722bSBjoern A. Zeeb static int 463*72ef722bSBjoern A. Zeeb dpaa2_cons_acpi_probe(device_t dev) 464*72ef722bSBjoern A. Zeeb { 465*72ef722bSBjoern A. Zeeb 466*72ef722bSBjoern A. Zeeb if (!ofw_bus_status_okay(dev)) 467*72ef722bSBjoern A. Zeeb return (ENXIO); 468*72ef722bSBjoern A. Zeeb 469*72ef722bSBjoern A. Zeeb device_set_desc(dev, "DPAA2 Console Driver"); 470*72ef722bSBjoern A. Zeeb return (BUS_PROBE_DEFAULT); 471*72ef722bSBjoern A. Zeeb } 472*72ef722bSBjoern A. Zeeb 473*72ef722bSBjoern A. Zeeb static int 474*72ef722bSBjoern A. Zeeb dpaa2_cons_acpi_attach(device_t dev) 475*72ef722bSBjoern A. Zeeb { 476*72ef722bSBjoern A. Zeeb struct dpaa2_cons_softc *sc; 477*72ef722bSBjoern A. Zeeb uint32_t val; 478*72ef722bSBjoern A. Zeeb int error, rid; 479*72ef722bSBjoern A. Zeeb 480*72ef722bSBjoern A. Zeeb sc = device_get_softc(dev); 481*72ef722bSBjoern A. Zeeb 482*72ef722bSBjoern A. Zeeb rid = 0; 483*72ef722bSBjoern A. Zeeb sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 484*72ef722bSBjoern A. Zeeb if (sc->res == NULL) { 485*72ef722bSBjoern A. Zeeb device_printf(dev, "Could not allocate memory\n"); 486*72ef722bSBjoern A. Zeeb return (ENXIO); 487*72ef722bSBjoern A. Zeeb } 488*72ef722bSBjoern A. Zeeb sc->bst = rman_get_bustag(sc->res); 489*72ef722bSBjoern A. Zeeb 490*72ef722bSBjoern A. Zeeb val = DPAA2_MC_READ_4(sc, MC_REG_MCFBALR_OFF); 491*72ef722bSBjoern A. Zeeb val &= MC_REG_MCFBALR_MASK; 492*72ef722bSBjoern A. Zeeb sc->mcfba |= val; 493*72ef722bSBjoern A. Zeeb val = DPAA2_MC_READ_4(sc, MC_REG_MCFBAHR_OFF); 494*72ef722bSBjoern A. Zeeb val &= MC_REG_MCFBAHR_MASK; 495*72ef722bSBjoern A. Zeeb sc->mcfba |= ((uint64_t)val << 32); 496*72ef722bSBjoern A. Zeeb 497*72ef722bSBjoern A. Zeeb error = dpaa2_cons_attach_common(dev); 498*72ef722bSBjoern A. Zeeb 499*72ef722bSBjoern A. Zeeb return (error); 500*72ef722bSBjoern A. Zeeb } 501*72ef722bSBjoern A. Zeeb 502*72ef722bSBjoern A. Zeeb static device_method_t dpaa2_cons_acpi_methods[] = { 503*72ef722bSBjoern A. Zeeb /* Device interface */ 504*72ef722bSBjoern A. Zeeb DEVMETHOD(device_probe, dpaa2_cons_acpi_probe), 505*72ef722bSBjoern A. Zeeb DEVMETHOD(device_attach, dpaa2_cons_acpi_attach), 506*72ef722bSBjoern A. Zeeb DEVMETHOD(device_detach, dpaa2_cons_detach), 507*72ef722bSBjoern A. Zeeb 508*72ef722bSBjoern A. Zeeb DEVMETHOD_END 509*72ef722bSBjoern A. Zeeb }; 510*72ef722bSBjoern A. Zeeb 511*72ef722bSBjoern A. Zeeb DEFINE_CLASS_0(dpaa2_cons_acpi, dpaa2_cons_acpi_driver, dpaa2_cons_acpi_methods, 512*72ef722bSBjoern A. Zeeb sizeof(struct dpaa2_cons_softc)); 513*72ef722bSBjoern A. Zeeb 514*72ef722bSBjoern A. Zeeb DRIVER_MODULE(dpaa2_cons_acpi, simplebus, dpaa2_cons_acpi_driver, 0, 0); 515*72ef722bSBjoern A. Zeeb MODULE_DEPEND(dpaa2_cons_acpi, dpaa2_mc, 1, 1, 1); 516*72ef722bSBjoern A. Zeeb #endif 517*72ef722bSBjoern A. Zeeb #endif /* 0 */ 518*72ef722bSBjoern A. Zeeb 519*72ef722bSBjoern A. Zeeb #ifdef FDT 520*72ef722bSBjoern A. Zeeb static struct ofw_compat_data compat_data[] = { 521*72ef722bSBjoern A. Zeeb { "fsl,dpaa2-console", 1 }, 522*72ef722bSBjoern A. Zeeb { NULL, 0 } 523*72ef722bSBjoern A. Zeeb }; 524*72ef722bSBjoern A. Zeeb 525*72ef722bSBjoern A. Zeeb static int 526*72ef722bSBjoern A. Zeeb dpaa2_cons_fdt_probe(device_t dev) 527*72ef722bSBjoern A. Zeeb { 528*72ef722bSBjoern A. Zeeb 529*72ef722bSBjoern A. Zeeb if (!ofw_bus_status_okay(dev)) 530*72ef722bSBjoern A. Zeeb return (ENXIO); 531*72ef722bSBjoern A. Zeeb 532*72ef722bSBjoern A. Zeeb if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 533*72ef722bSBjoern A. Zeeb return (ENXIO); 534*72ef722bSBjoern A. Zeeb 535*72ef722bSBjoern A. Zeeb device_set_desc(dev, "DPAA2 Console Driver"); 536*72ef722bSBjoern A. Zeeb return (BUS_PROBE_DEFAULT); 537*72ef722bSBjoern A. Zeeb } 538*72ef722bSBjoern A. Zeeb 539*72ef722bSBjoern A. Zeeb static int 540*72ef722bSBjoern A. Zeeb dpaa2_cons_fdt_attach(device_t dev) 541*72ef722bSBjoern A. Zeeb { 542*72ef722bSBjoern A. Zeeb struct dpaa2_cons_softc *sc; 543*72ef722bSBjoern A. Zeeb uint32_t val; 544*72ef722bSBjoern A. Zeeb int error, rid; 545*72ef722bSBjoern A. Zeeb 546*72ef722bSBjoern A. Zeeb sc = device_get_softc(dev); 547*72ef722bSBjoern A. Zeeb 548*72ef722bSBjoern A. Zeeb rid = 0; 549*72ef722bSBjoern A. Zeeb sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 550*72ef722bSBjoern A. Zeeb if (sc->res == NULL) { 551*72ef722bSBjoern A. Zeeb device_printf(dev, "Could not allocate memory\n"); 552*72ef722bSBjoern A. Zeeb return (ENXIO); 553*72ef722bSBjoern A. Zeeb } 554*72ef722bSBjoern A. Zeeb sc->bst = rman_get_bustag(sc->res); 555*72ef722bSBjoern A. Zeeb 556*72ef722bSBjoern A. Zeeb val = DPAA2_MC_READ_4(sc, MC_REG_MCFBALR_OFF); 557*72ef722bSBjoern A. Zeeb val &= MC_REG_MCFBALR_MASK; 558*72ef722bSBjoern A. Zeeb sc->mcfba |= val; 559*72ef722bSBjoern A. Zeeb val = DPAA2_MC_READ_4(sc, MC_REG_MCFBAHR_OFF); 560*72ef722bSBjoern A. Zeeb val &= MC_REG_MCFBAHR_MASK; 561*72ef722bSBjoern A. Zeeb sc->mcfba |= ((uint64_t)val << 32); 562*72ef722bSBjoern A. Zeeb 563*72ef722bSBjoern A. Zeeb error = dpaa2_cons_attach_common(dev); 564*72ef722bSBjoern A. Zeeb 565*72ef722bSBjoern A. Zeeb return (error); 566*72ef722bSBjoern A. Zeeb } 567*72ef722bSBjoern A. Zeeb 568*72ef722bSBjoern A. Zeeb static device_method_t dpaa2_cons_fdt_methods[] = { 569*72ef722bSBjoern A. Zeeb /* Device interface */ 570*72ef722bSBjoern A. Zeeb DEVMETHOD(device_probe, dpaa2_cons_fdt_probe), 571*72ef722bSBjoern A. Zeeb DEVMETHOD(device_attach, dpaa2_cons_fdt_attach), 572*72ef722bSBjoern A. Zeeb DEVMETHOD(device_detach, dpaa2_cons_detach), 573*72ef722bSBjoern A. Zeeb 574*72ef722bSBjoern A. Zeeb DEVMETHOD_END 575*72ef722bSBjoern A. Zeeb }; 576*72ef722bSBjoern A. Zeeb 577*72ef722bSBjoern A. Zeeb DEFINE_CLASS_0(dpaa2_cons_fdt, dpaa2_cons_fdt_driver, dpaa2_cons_fdt_methods, 578*72ef722bSBjoern A. Zeeb sizeof(struct dpaa2_cons_softc)); 579*72ef722bSBjoern A. Zeeb 580*72ef722bSBjoern A. Zeeb DRIVER_MODULE(dpaa2_cons_fdt, simplebus, dpaa2_cons_fdt_driver, 0, 0); 581*72ef722bSBjoern A. Zeeb #endif 582