dram_console.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. #include <mt-plat/aee.h>
  2. #include <linux/atomic.h>
  3. #include <linux/console.h>
  4. #include <linux/delay.h>
  5. #include <linux/init.h>
  6. #include <linux/memblock.h>
  7. #include <linux/module.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/proc_fs.h>
  10. #include <linux/string.h>
  11. #include <linux/uaccess.h>
  12. #include <linux/vmalloc.h>
  13. #include <linux/mm.h>
  14. #include <linux/io.h>
  15. struct dram_console_buffer {
  16. uint32_t sig;
  17. uint32_t start;
  18. uint32_t size;
  19. uint8_t data[0];
  20. };
  21. #define RAM_CONSOLE_SIG (0x43474244) /* DBGC */
  22. static char *ram_console_old_log;
  23. static size_t ram_console_old_log_size;
  24. static struct dram_console_buffer *dram_console_buffer;
  25. static size_t dram_console_buffer_size;
  26. static void dram_console_write(struct console *console, const char *msg, unsigned int count)
  27. {
  28. struct dram_console_buffer *buffer = dram_console_buffer;
  29. int rem;
  30. /* count >= buffer_size, full the buffer */
  31. if (count >= dram_console_buffer_size) {
  32. memcpy(buffer->data, msg + (count - dram_console_buffer_size),
  33. dram_console_buffer_size);
  34. buffer->start = 0;
  35. buffer->size = dram_console_buffer_size;
  36. } else if (count > (dram_console_buffer_size - buffer->start)) {
  37. /* count > last buffer, full them and fill the head buffer */
  38. rem = dram_console_buffer_size - buffer->start;
  39. memcpy(buffer->data + buffer->start, msg, rem);
  40. memcpy(buffer->data, msg + rem, count - rem);
  41. buffer->start = count - rem;
  42. buffer->size = dram_console_buffer_size;
  43. } else { /* count <= last buffer, fill in free buffer */
  44. memcpy(buffer->data + buffer->start, msg, count); /* count <= last buffer, fill them */
  45. buffer->start += count;
  46. buffer->size += count;
  47. if (buffer->start >= dram_console_buffer_size)
  48. buffer->start = 0;
  49. if (buffer->size > dram_console_buffer_size)
  50. buffer->size = dram_console_buffer_size;
  51. }
  52. }
  53. static struct console dram_console = {
  54. .name = "dram",
  55. .write = dram_console_write,
  56. .flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME,
  57. .index = -1,
  58. };
  59. static void __init ram_console_save_old(const struct dram_console_buffer *buffer)
  60. {
  61. ram_console_old_log = kmalloc(buffer->size, GFP_KERNEL);
  62. if (ram_console_old_log == NULL) {
  63. LOGE("ram_console: failed to allocate old buffer\n");
  64. return;
  65. }
  66. ram_console_old_log_size = buffer->size;
  67. memcpy(ram_console_old_log, &buffer->data[buffer->start], buffer->size - buffer->start);
  68. memcpy(ram_console_old_log + buffer->size - buffer->start, &buffer->data[0], buffer->start);
  69. }
  70. static int __init ram_console_init(struct dram_console_buffer *buffer, size_t buffer_size)
  71. {
  72. dram_console_buffer = buffer;
  73. dram_console_buffer_size = buffer_size - sizeof(struct dram_console_buffer);
  74. if (buffer->sig == RAM_CONSOLE_SIG) {
  75. if (buffer->size > dram_console_buffer_size || buffer->start > buffer->size)
  76. LOGE("ram_console: found existing invalid buffer, size %d, start %d\n",
  77. buffer->size, buffer->start);
  78. else {
  79. LOGE("ram_console: found existing buffer, size %d, start %d\n",
  80. buffer->size, buffer->start);
  81. ram_console_save_old(buffer);
  82. }
  83. } else {
  84. LOGE("ram_console: no valid data in buffer " "(sig = 0x%08x)\n", buffer->sig);
  85. }
  86. memset(buffer, 0, buffer_size);
  87. buffer->sig = RAM_CONSOLE_SIG;
  88. register_console(&dram_console);
  89. return 0;
  90. }
  91. static void __init *remap_lowmem(phys_addr_t start, phys_addr_t size)
  92. {
  93. struct page **pages;
  94. phys_addr_t page_start;
  95. unsigned int page_count;
  96. pgprot_t prot;
  97. unsigned int i;
  98. void *vaddr;
  99. page_start = start - offset_in_page(start);
  100. page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE);
  101. prot = pgprot_noncached(PAGE_KERNEL);
  102. pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL);
  103. if (!pages)
  104. return NULL;
  105. for (i = 0; i < page_count; i++) {
  106. phys_addr_t addr = page_start + i * PAGE_SIZE;
  107. pages[i] = pfn_to_page(addr >> PAGE_SHIFT);
  108. }
  109. vaddr = vmap(pages, page_count, VM_MAP, prot);
  110. kfree(pages);
  111. if (!vaddr) {
  112. pr_err("%s: Failed to map %u pages\n", __func__, page_count);
  113. return NULL;
  114. }
  115. return vaddr + offset_in_page(start);
  116. }
  117. static int __init dram_console_early_init(void)
  118. {
  119. struct dram_console_buffer *bufp = NULL;
  120. size_t buffer_size = 0;
  121. bufp = (struct dram_console_buffer *)CONFIG_MTK_AEE_DRAM_CONSOLE_ADDR;
  122. buffer_size = CONFIG_MTK_AEE_DRAM_CONSOLE_SIZE;
  123. bufp = remap_lowmem(CONFIG_MTK_AEE_DRAM_CONSOLE_ADDR, CONFIG_MTK_AEE_DRAM_CONSOLE_SIZE);
  124. if (bufp == NULL) {
  125. LOGE("ioremap failed, no ram console available\n");
  126. return 0;
  127. }
  128. buffer_size = CONFIG_MTK_AEE_DRAM_CONSOLE_SIZE;
  129. LOGE("%s: start: 0x%p, size: %d\n", __func__, bufp, buffer_size);
  130. return ram_console_init(bufp, buffer_size);
  131. }
  132. static ssize_t dram_console_read_old(struct file *file, char __user *buf,
  133. size_t len, loff_t *offset)
  134. {
  135. loff_t pos = *offset;
  136. ssize_t count;
  137. if (pos >= ram_console_old_log_size)
  138. return 0;
  139. count = min(len, (size_t) (ram_console_old_log_size - pos));
  140. if (copy_to_user(buf, ram_console_old_log + pos, count))
  141. return -EFAULT;
  142. *offset += count;
  143. return count;
  144. }
  145. static const struct file_operations ram_console_file_ops = {
  146. .owner = THIS_MODULE,
  147. .read = dram_console_read_old,
  148. };
  149. void dram_console_init(struct proc_dir_entry *root_entry)
  150. {
  151. struct proc_dir_entry *entry;
  152. if (ram_console_old_log == NULL) {
  153. LOGE("%s: old log is null!\n", KBUILD_MODNAME);
  154. return;
  155. }
  156. entry = create_proc_entry("last_dram_kmsg", S_IFREG | S_IRUGO, root_entry);
  157. if (!entry) {
  158. LOGE("%s: failed to create proc entry\n", __func__);
  159. kfree(ram_console_old_log);
  160. ram_console_old_log = NULL;
  161. return;
  162. }
  163. entry->proc_fops = &ram_console_file_ops;
  164. entry->size = ram_console_old_log_size;
  165. }
  166. void dram_console_done(struct proc_dir_entry *aed_proc_dir)
  167. {
  168. remove_proc_entry("last_dram_kmsg", aed_proc_dir);
  169. }
  170. void aee_dram_console_reserve_memory(void)
  171. {
  172. memblock_reserve(CONFIG_MTK_AEE_DRAM_CONSOLE_ADDR, CONFIG_MTK_AEE_DRAM_CONSOLE_SIZE);
  173. }
  174. console_initcall(dram_console_early_init);