linux/arch/arm/mach-msm/smd_debug.c
<<
>>
Prefs
   1/* arch/arm/mach-msm/smd_debug.c
   2 *
   3 * Copyright (C) 2007 Google, Inc.
   4 * Author: Brian Swetland <swetland@google.com>
   5 *
   6 * This software is licensed under the terms of the GNU General Public
   7 * License version 2, as published by the Free Software Foundation, and
   8 * may be copied, distributed, and modified under those terms.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 */
  16
  17#include <linux/debugfs.h>
  18#include <linux/list.h>
  19
  20#include <mach/msm_iomap.h>
  21
  22#include "smd_private.h"
  23
  24#if defined(CONFIG_DEBUG_FS)
  25
  26static char *chstate(unsigned n)
  27{
  28        switch (n) {
  29        case SMD_SS_CLOSED:
  30                return "CLOSED";
  31        case SMD_SS_OPENING:
  32                return "OPENING";
  33        case SMD_SS_OPENED:
  34                return "OPENED";
  35        case SMD_SS_FLUSHING:
  36                return "FLUSHING";
  37        case SMD_SS_CLOSING:
  38                return "CLOSING";
  39        case SMD_SS_RESET:
  40                return "RESET";
  41        case SMD_SS_RESET_OPENING:
  42                return "ROPENING";
  43        default:
  44                return "UNKNOWN";
  45        }
  46}
  47
  48
  49static int dump_ch(char *buf, int max, struct smd_channel *ch)
  50{
  51        volatile struct smd_half_channel *s = ch->send;
  52        volatile struct smd_half_channel *r = ch->recv;
  53
  54        return scnprintf(
  55                buf, max,
  56                "ch%02d:"
  57                " %8s(%05d/%05d) %c%c%c%c%c%c%c <->"
  58                " %8s(%05d/%05d) %c%c%c%c%c%c%c '%s'\n", ch->n,
  59                chstate(s->state), s->tail, s->head,
  60                s->fDSR ? 'D' : 'd',
  61                s->fCTS ? 'C' : 'c',
  62                s->fCD ? 'C' : 'c',
  63                s->fRI ? 'I' : 'i',
  64                s->fHEAD ? 'W' : 'w',
  65                s->fTAIL ? 'R' : 'r',
  66                s->fSTATE ? 'S' : 's',
  67                chstate(r->state), r->tail, r->head,
  68                r->fDSR ? 'D' : 'd',
  69                r->fCTS ? 'R' : 'r',
  70                r->fCD ? 'C' : 'c',
  71                r->fRI ? 'I' : 'i',
  72                r->fHEAD ? 'W' : 'w',
  73                r->fTAIL ? 'R' : 'r',
  74                r->fSTATE ? 'S' : 's',
  75                ch->name
  76                );
  77}
  78
  79static int debug_read_stat(char *buf, int max)
  80{
  81        char *msg;
  82        int i = 0;
  83
  84        msg = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
  85
  86        if (raw_smsm_get_state(SMSM_STATE_MODEM) & SMSM_RESET)
  87                i += scnprintf(buf + i, max - i,
  88                               "smsm: ARM9 HAS CRASHED\n");
  89
  90        i += scnprintf(buf + i, max - i, "smsm: a9: %08x a11: %08x\n",
  91                       raw_smsm_get_state(SMSM_STATE_MODEM),
  92                       raw_smsm_get_state(SMSM_STATE_APPS));
  93#ifdef CONFIG_ARCH_MSM_SCORPION
  94        i += scnprintf(buf + i, max - i, "smsm dem: apps: %08x modem: %08x "
  95                       "qdsp6: %08x power: %08x time: %08x\n",
  96                       raw_smsm_get_state(SMSM_STATE_APPS_DEM),
  97                       raw_smsm_get_state(SMSM_STATE_MODEM_DEM),
  98                       raw_smsm_get_state(SMSM_STATE_QDSP6_DEM),
  99                       raw_smsm_get_state(SMSM_STATE_POWER_MASTER_DEM),
 100                       raw_smsm_get_state(SMSM_STATE_TIME_MASTER_DEM));
 101#endif
 102        if (msg) {
 103                msg[SZ_DIAG_ERR_MSG - 1] = 0;
 104                i += scnprintf(buf + i, max - i, "diag: '%s'\n", msg);
 105        }
 106        return i;
 107}
 108
 109static int debug_read_mem(char *buf, int max)
 110{
 111        unsigned n;
 112        struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
 113        struct smem_heap_entry *toc = shared->heap_toc;
 114        int i = 0;
 115
 116        i += scnprintf(buf + i, max - i,
 117                       "heap: init=%d free=%d remain=%d\n",
 118                       shared->heap_info.initialized,
 119                       shared->heap_info.free_offset,
 120                       shared->heap_info.heap_remaining);
 121
 122        for (n = 0; n < SMEM_NUM_ITEMS; n++) {
 123                if (toc[n].allocated == 0)
 124                        continue;
 125                i += scnprintf(buf + i, max - i,
 126                               "%04d: offset %08x size %08x\n",
 127                               n, toc[n].offset, toc[n].size);
 128        }
 129        return i;
 130}
 131
 132static int debug_read_ch(char *buf, int max)
 133{
 134        struct smd_channel *ch;
 135        unsigned long flags;
 136        int i = 0;
 137
 138        spin_lock_irqsave(&smd_lock, flags);
 139        list_for_each_entry(ch, &smd_ch_list_dsp, ch_list)
 140                i += dump_ch(buf + i, max - i, ch);
 141        list_for_each_entry(ch, &smd_ch_list_modem, ch_list)
 142                i += dump_ch(buf + i, max - i, ch);
 143        list_for_each_entry(ch, &smd_ch_closed_list, ch_list)
 144                i += dump_ch(buf + i, max - i, ch);
 145        spin_unlock_irqrestore(&smd_lock, flags);
 146
 147        return i;
 148}
 149
 150static int debug_read_version(char *buf, int max)
 151{
 152        struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
 153        unsigned version = shared->version[VERSION_MODEM];
 154        return sprintf(buf, "%d.%d\n", version >> 16, version & 0xffff);
 155}
 156
 157static int debug_read_build_id(char *buf, int max)
 158{
 159        unsigned size;
 160        void *data;
 161
 162        data = smem_item(SMEM_HW_SW_BUILD_ID, &size);
 163        if (!data)
 164                return 0;
 165
 166        if (size >= max)
 167                size = max;
 168        memcpy(buf, data, size);
 169
 170        return size;
 171}
 172
 173static int debug_read_alloc_tbl(char *buf, int max)
 174{
 175        struct smd_alloc_elm *shared;
 176        int n, i = 0;
 177
 178        shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64);
 179
 180        for (n = 0; n < 64; n++) {
 181                if (shared[n].ref_count == 0)
 182                        continue;
 183                i += scnprintf(buf + i, max - i,
 184                               "%03d: %-20s cid=%02d type=%03d "
 185                               "kind=%02d ref_count=%d\n",
 186                               n, shared[n].name, shared[n].cid,
 187                               shared[n].ctype & 0xff,
 188                               (shared[n].ctype >> 8) & 0xf,
 189                               shared[n].ref_count);
 190        }
 191
 192        return i;
 193}
 194
 195#define DEBUG_BUFMAX 4096
 196static char debug_buffer[DEBUG_BUFMAX];
 197
 198static ssize_t debug_read(struct file *file, char __user *buf,
 199                          size_t count, loff_t *ppos)
 200{
 201        int (*fill)(char *buf, int max) = file->private_data;
 202        int bsize = fill(debug_buffer, DEBUG_BUFMAX);
 203        return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
 204}
 205
 206static const struct file_operations debug_ops = {
 207        .read = debug_read,
 208        .open = simple_open,
 209        .llseek = default_llseek,
 210};
 211
 212static void debug_create(const char *name, umode_t mode,
 213                         struct dentry *dent,
 214                         int (*fill)(char *buf, int max))
 215{
 216        debugfs_create_file(name, mode, dent, fill, &debug_ops);
 217}
 218
 219int __init smd_debugfs_init(void)
 220{
 221        struct dentry *dent;
 222
 223        dent = debugfs_create_dir("smd", 0);
 224        if (IS_ERR(dent))
 225                return 1;
 226
 227        debug_create("ch", 0444, dent, debug_read_ch);
 228        debug_create("stat", 0444, dent, debug_read_stat);
 229        debug_create("mem", 0444, dent, debug_read_mem);
 230        debug_create("version", 0444, dent, debug_read_version);
 231        debug_create("tbl", 0444, dent, debug_read_alloc_tbl);
 232        debug_create("build", 0444, dent, debug_read_build_id);
 233
 234        return 0;
 235}
 236
 237#endif
 238
 239
 240#define MAX_NUM_SLEEP_CLIENTS           64
 241#define MAX_SLEEP_NAME_LEN              8
 242
 243#define NUM_GPIO_INT_REGISTERS          6
 244#define GPIO_SMEM_NUM_GROUPS            2
 245#define GPIO_SMEM_MAX_PC_INTERRUPTS     8
 246
 247struct tramp_gpio_save {
 248        unsigned int enable;
 249        unsigned int detect;
 250        unsigned int polarity;
 251};
 252
 253struct tramp_gpio_smem {
 254        uint16_t num_fired[GPIO_SMEM_NUM_GROUPS];
 255        uint16_t fired[GPIO_SMEM_NUM_GROUPS][GPIO_SMEM_MAX_PC_INTERRUPTS];
 256        uint32_t enabled[NUM_GPIO_INT_REGISTERS];
 257        uint32_t detection[NUM_GPIO_INT_REGISTERS];
 258        uint32_t polarity[NUM_GPIO_INT_REGISTERS];
 259};
 260
 261
 262void smsm_print_sleep_info(void)
 263{
 264        unsigned long flags;
 265        uint32_t *ptr;
 266#ifndef CONFIG_ARCH_MSM_SCORPION
 267        struct tramp_gpio_smem *gpio;
 268        struct smsm_interrupt_info *int_info;
 269#endif
 270
 271
 272        spin_lock_irqsave(&smem_lock, flags);
 273
 274        ptr = smem_alloc(SMEM_SMSM_SLEEP_DELAY, sizeof(*ptr));
 275        if (ptr)
 276                pr_info("SMEM_SMSM_SLEEP_DELAY: %x\n", *ptr);
 277
 278        ptr = smem_alloc(SMEM_SMSM_LIMIT_SLEEP, sizeof(*ptr));
 279        if (ptr)
 280                pr_info("SMEM_SMSM_LIMIT_SLEEP: %x\n", *ptr);
 281
 282        ptr = smem_alloc(SMEM_SLEEP_POWER_COLLAPSE_DISABLED, sizeof(*ptr));
 283        if (ptr)
 284                pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: %x\n", *ptr);
 285
 286#ifndef CONFIG_ARCH_MSM_SCORPION
 287        int_info = smem_alloc(SMEM_SMSM_INT_INFO, sizeof(*int_info));
 288        if (int_info)
 289                pr_info("SMEM_SMSM_INT_INFO %x %x %x\n",
 290                        int_info->interrupt_mask,
 291                        int_info->pending_interrupts,
 292                        int_info->wakeup_reason);
 293
 294        gpio = smem_alloc(SMEM_GPIO_INT, sizeof(*gpio));
 295        if (gpio) {
 296                int i;
 297                for (i = 0; i < NUM_GPIO_INT_REGISTERS; i++)
 298                        pr_info("SMEM_GPIO_INT: %d: e %x d %x p %x\n",
 299                                i, gpio->enabled[i], gpio->detection[i],
 300                                gpio->polarity[i]);
 301
 302                for (i = 0; i < GPIO_SMEM_NUM_GROUPS; i++)
 303                        pr_info("SMEM_GPIO_INT: %d: f %d: %d %d...\n",
 304                                i, gpio->num_fired[i], gpio->fired[i][0],
 305                                gpio->fired[i][1]);
 306        }
 307#else
 308#endif
 309        spin_unlock_irqrestore(&smem_lock, flags);
 310}
 311
 312