Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");