^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Freescale DPAA2 Platforms Console Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2015-2016 Freescale Semiconductor Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2018 NXP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define pr_fmt(fmt) "dpaa2-console: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/miscdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* MC firmware base low/high registers indexes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define MCFBALR_OFFSET 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define MCFBAHR_OFFSET 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* Bit masks used to get the most/least significant part of the MC base addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define MC_FW_ADDR_MASK_HIGH 0x1FFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define MC_FW_ADDR_MASK_LOW 0xE0000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define MC_BUFFER_OFFSET 0x01000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MC_BUFFER_SIZE (1024 * 1024 * 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define MC_OFFSET_DELTA MC_BUFFER_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define AIOP_BUFFER_OFFSET 0x06000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define AIOP_BUFFER_SIZE (1024 * 1024 * 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define AIOP_OFFSET_DELTA 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define LOG_HEADER_FLAG_BUFFER_WRAPAROUND 0x80000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define LAST_BYTE(a) ((a) & ~(LOG_HEADER_FLAG_BUFFER_WRAPAROUND))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* MC and AIOP Magic words */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define MAGIC_MC 0x4d430100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define MAGIC_AIOP 0x41494F50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct log_header {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) __le32 magic_word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) char reserved[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) __le32 buf_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) __le32 buf_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) __le32 last_byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct console_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) void __iomem *map_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct log_header __iomem *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) void __iomem *start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) void __iomem *end_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) void __iomem *end_of_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) void __iomem *cur_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static struct resource mc_base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static inline void adjust_end(struct console_data *cd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u32 last_byte = readl(&cd->hdr->last_byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) cd->end_of_data = cd->start_addr + LAST_BYTE(last_byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static u64 get_mc_fw_base_address(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) u64 mcfwbase = 0ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) u32 __iomem *mcfbaregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) mcfbaregs = ioremap(mc_base_addr.start, resource_size(&mc_base_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (!mcfbaregs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) pr_err("could not map MC Firmware Base registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) mcfwbase = readl(mcfbaregs + MCFBAHR_OFFSET) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) MC_FW_ADDR_MASK_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) mcfwbase <<= 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) mcfwbase |= readl(mcfbaregs + MCFBALR_OFFSET) & MC_FW_ADDR_MASK_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) iounmap(mcfbaregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) pr_debug("MC base address at 0x%016llx\n", mcfwbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return mcfwbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static ssize_t dpaa2_console_size(struct console_data *cd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ssize_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (cd->cur_ptr <= cd->end_of_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) size = cd->end_of_data - cd->cur_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) size = (cd->end_addr - cd->cur_ptr) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) (cd->end_of_data - cd->start_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static int dpaa2_generic_console_open(struct inode *node, struct file *fp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u64 offset, u64 size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 expected_magic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u32 offset_delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u32 read_magic, wrapped, last_byte, buf_start, buf_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct console_data *cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u64 base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) cd = kmalloc(sizeof(*cd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (!cd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) base_addr = get_mc_fw_base_address();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (!base_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) goto err_fwba;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) cd->map_addr = ioremap(base_addr + offset, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (!cd->map_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) pr_err("cannot map console log memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) goto err_ioremap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) cd->hdr = (struct log_header __iomem *)cd->map_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) read_magic = readl(&cd->hdr->magic_word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) last_byte = readl(&cd->hdr->last_byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) buf_start = readl(&cd->hdr->buf_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) buf_length = readl(&cd->hdr->buf_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (read_magic != expected_magic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) pr_warn("expected = %08x, read = %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) expected_magic, read_magic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) goto err_magic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) cd->start_addr = cd->map_addr + buf_start - offset_delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) cd->end_addr = cd->start_addr + buf_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) wrapped = last_byte & LOG_HEADER_FLAG_BUFFER_WRAPAROUND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) adjust_end(cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (wrapped && cd->end_of_data != cd->end_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) cd->cur_ptr = cd->end_of_data + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) cd->cur_ptr = cd->start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) fp->private_data = cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) err_magic:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) iounmap(cd->map_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) err_ioremap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) err_fwba:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) kfree(cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static int dpaa2_mc_console_open(struct inode *node, struct file *fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return dpaa2_generic_console_open(node, fp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) MC_BUFFER_OFFSET, MC_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) MAGIC_MC, MC_OFFSET_DELTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static int dpaa2_aiop_console_open(struct inode *node, struct file *fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return dpaa2_generic_console_open(node, fp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) AIOP_BUFFER_OFFSET, AIOP_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) MAGIC_AIOP, AIOP_OFFSET_DELTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static int dpaa2_console_close(struct inode *node, struct file *fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct console_data *cd = fp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) iounmap(cd->map_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) kfree(cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static ssize_t dpaa2_console_read(struct file *fp, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) size_t count, loff_t *f_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct console_data *cd = fp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) size_t bytes = dpaa2_console_size(cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) size_t bytes_end = cd->end_addr - cd->cur_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) size_t written = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) void *kbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /* Check if we need to adjust the end of data addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) adjust_end(cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (cd->end_of_data == cd->cur_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (count < bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) bytes = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) kbuf = kmalloc(bytes, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (!kbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (bytes > bytes_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) memcpy_fromio(kbuf, cd->cur_ptr, bytes_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (copy_to_user(buf, kbuf, bytes_end)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) goto err_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) buf += bytes_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) cd->cur_ptr = cd->start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) bytes -= bytes_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) written += bytes_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) memcpy_fromio(kbuf, cd->cur_ptr, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (copy_to_user(buf, kbuf, bytes)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) goto err_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) cd->cur_ptr += bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) written += bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) kfree(kbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) err_free_buf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) kfree(kbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static const struct file_operations dpaa2_mc_console_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .open = dpaa2_mc_console_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .release = dpaa2_console_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .read = dpaa2_console_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static struct miscdevice dpaa2_mc_console_dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .minor = MISC_DYNAMIC_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .name = "dpaa2_mc_console",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .fops = &dpaa2_mc_console_fops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static const struct file_operations dpaa2_aiop_console_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .open = dpaa2_aiop_console_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .release = dpaa2_console_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .read = dpaa2_console_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static struct miscdevice dpaa2_aiop_console_dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .minor = MISC_DYNAMIC_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .name = "dpaa2_aiop_console",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .fops = &dpaa2_aiop_console_fops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static int dpaa2_console_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) error = of_address_to_resource(pdev->dev.of_node, 0, &mc_base_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (error < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) pr_err("of_address_to_resource() failed for %pOF with %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) pdev->dev.of_node, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) error = misc_register(&dpaa2_mc_console_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) pr_err("cannot register device %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) dpaa2_mc_console_dev.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) goto err_register_mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) error = misc_register(&dpaa2_aiop_console_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) pr_err("cannot register device %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) dpaa2_aiop_console_dev.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) goto err_register_aiop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) err_register_aiop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) misc_deregister(&dpaa2_mc_console_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) err_register_mc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static int dpaa2_console_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) misc_deregister(&dpaa2_mc_console_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) misc_deregister(&dpaa2_aiop_console_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static const struct of_device_id dpaa2_console_match_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) { .compatible = "fsl,dpaa2-console",},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) MODULE_DEVICE_TABLE(of, dpaa2_console_match_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static struct platform_driver dpaa2_console_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) .name = "dpaa2-console",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) .pm = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) .of_match_table = dpaa2_console_match_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) .probe = dpaa2_console_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) .remove = dpaa2_console_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) module_platform_driver(dpaa2_console_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) MODULE_LICENSE("Dual BSD/GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) MODULE_AUTHOR("Roy Pledge <roy.pledge@nxp.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) MODULE_DESCRIPTION("DPAA2 console driver");