aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-msm
diff options
context:
space:
mode:
authorBrian Swetland <swetland@google.com>2009-07-01 20:58:37 -0400
committerDaniel Walker <dwalker@codeaurora.org>2010-05-12 12:15:09 -0400
commit03e00cd350c6636b5f2a9854609fea93a5c7b677 (patch)
tree82c9fa41f1b21c1450500cb92577b17ed4ae8b45 /arch/arm/mach-msm
parentec9d3d14ffa9454e6d51e5dd1889d6e9e0be5198 (diff)
[ARM] msm: cleanup smd, separate debugfs support
- pull debug code into smd_debug.c - move necessary structures and defines into smd_private.h - fix some comment formatting, etc Signed-off-by: Brian Swetland <swetland@google.com> Signed-off-by: Daniel Walker <dwalker@codeaurora.org>
Diffstat (limited to 'arch/arm/mach-msm')
-rw-r--r--arch/arm/mach-msm/Makefile2
-rw-r--r--arch/arm/mach-msm/smd.c425
-rw-r--r--arch/arm/mach-msm/smd_debug.c310
-rw-r--r--arch/arm/mach-msm/smd_private.h101
4 files changed, 433 insertions, 405 deletions
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index d23fd0bf9fcc..9c3c4019da8a 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -5,7 +5,7 @@ obj-y += vreg.o
5obj-y += acpuclock-arm11.o 5obj-y += acpuclock-arm11.o
6obj-y += clock.o clock-7x01a.o 6obj-y += clock.o clock-7x01a.o
7 7
8obj-$(CONFIG_MSM_SMD) += smd.o 8obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
9 9
10obj-$(CONFIG_MACH_TROUT) += board-trout.o 10obj-$(CONFIG_MACH_TROUT) += board-trout.o
11obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o 11obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index b5f8957725de..1aaee4d70863 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -46,8 +46,7 @@ enum {
46 46
47static int msm_smd_debug_mask; 47static int msm_smd_debug_mask;
48 48
49struct shared_info 49struct shared_info {
50{
51 int ready; 50 int ready;
52 unsigned state; 51 unsigned state;
53}; 52};
@@ -61,8 +60,7 @@ static struct shared_info smd_info = {
61module_param_named(debug_mask, msm_smd_debug_mask, 60module_param_named(debug_mask, msm_smd_debug_mask,
62 int, S_IRUGO | S_IWUSR | S_IWGRP); 61 int, S_IRUGO | S_IWUSR | S_IWGRP);
63 62
64void *smem_find(unsigned id, unsigned size); 63void *smem_item(unsigned id, unsigned *size);
65static void *smem_item(unsigned id, unsigned *size);
66static void smd_diag(void); 64static void smd_diag(void);
67 65
68static unsigned last_heap_free = 0xffffffff; 66static unsigned last_heap_free = 0xffffffff;
@@ -126,114 +124,27 @@ static int check_for_modem_crash(void)
126 return 0; 124 return 0;
127} 125}
128 126
129#define SMD_SS_CLOSED 0x00000000
130#define SMD_SS_OPENING 0x00000001
131#define SMD_SS_OPENED 0x00000002
132#define SMD_SS_FLUSHING 0x00000003
133#define SMD_SS_CLOSING 0x00000004
134#define SMD_SS_RESET 0x00000005
135#define SMD_SS_RESET_OPENING 0x00000006
136
137#define SMD_BUF_SIZE 8192
138#define SMD_CHANNELS 64
139
140#define SMD_HEADER_SIZE 20
141
142
143/* the spinlock is used to synchronize between the 127/* the spinlock is used to synchronize between the
144** irq handler and code that mutates the channel 128 * irq handler and code that mutates the channel
145** list or fiddles with channel state 129 * list or fiddles with channel state
146*/ 130 */
147static DEFINE_SPINLOCK(smd_lock); 131DEFINE_SPINLOCK(smd_lock);
148static DEFINE_SPINLOCK(smem_lock); 132DEFINE_SPINLOCK(smem_lock);
149 133
150/* the mutex is used during open() and close() 134/* the mutex is used during open() and close()
151** operations to avoid races while creating or 135 * operations to avoid races while creating or
152** destroying smd_channel structures 136 * destroying smd_channel structures
153*/ 137 */
154static DEFINE_MUTEX(smd_creation_mutex); 138static DEFINE_MUTEX(smd_creation_mutex);
155 139
156static int smd_initialized; 140static int smd_initialized;
157 141
158struct smd_alloc_elm { 142LIST_HEAD(smd_ch_closed_list);
159 char name[20]; 143LIST_HEAD(smd_ch_list); /* todo: per-target lists */
160 uint32_t cid;
161 uint32_t ctype;
162 uint32_t ref_count;
163};
164
165struct smd_half_channel {
166 unsigned state;
167 unsigned char fDSR;
168 unsigned char fCTS;
169 unsigned char fCD;
170 unsigned char fRI;
171 unsigned char fHEAD;
172 unsigned char fTAIL;
173 unsigned char fSTATE;
174 unsigned char fUNUSED;
175 unsigned tail;
176 unsigned head;
177} __attribute__((packed));
178
179struct smd_shared_v1 {
180 struct smd_half_channel ch0;
181 unsigned char data0[SMD_BUF_SIZE];
182 struct smd_half_channel ch1;
183 unsigned char data1[SMD_BUF_SIZE];
184};
185
186struct smd_shared_v2 {
187 struct smd_half_channel ch0;
188 struct smd_half_channel ch1;
189};
190
191struct smd_channel {
192 volatile struct smd_half_channel *send;
193 volatile struct smd_half_channel *recv;
194 unsigned char *send_data;
195 unsigned char *recv_data;
196
197 unsigned fifo_mask;
198 unsigned fifo_size;
199 unsigned current_packet;
200 unsigned n;
201
202 struct list_head ch_list;
203
204 void *priv;
205 void (*notify)(void *priv, unsigned flags);
206
207 int (*read)(smd_channel_t *ch, void *data, int len);
208 int (*write)(smd_channel_t *ch, const void *data, int len);
209 int (*read_avail)(smd_channel_t *ch);
210 int (*write_avail)(smd_channel_t *ch);
211
212 void (*update_state)(smd_channel_t *ch);
213 unsigned last_state;
214 void (*notify_other_cpu)(void);
215 unsigned type;
216
217 char name[32];
218 struct platform_device pdev;
219};
220
221static LIST_HEAD(smd_ch_closed_list);
222static LIST_HEAD(smd_ch_list); /* todo: per-target lists */
223 144
224static unsigned char smd_ch_allocated[64]; 145static unsigned char smd_ch_allocated[64];
225static struct work_struct probe_work; 146static struct work_struct probe_work;
226 147
227#define SMD_TYPE_MASK 0x0FF
228#define SMD_TYPE_APPS_MODEM 0x000
229#define SMD_TYPE_APPS_DSP 0x001
230#define SMD_TYPE_MODEM_DSP 0x002
231
232#define SMD_KIND_MASK 0xF00
233#define SMD_KIND_UNKNOWN 0x000
234#define SMD_KIND_STREAM 0x100
235#define SMD_KIND_PACKET 0x200
236
237static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type); 148static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type);
238 149
239static void smd_channel_probe_worker(struct work_struct *work) 150static void smd_channel_probe_worker(struct work_struct *work)
@@ -264,28 +175,6 @@ static void smd_channel_probe_worker(struct work_struct *work)
264 } 175 }
265} 176}
266 177
267static char *chstate(unsigned n)
268{
269 switch (n) {
270 case SMD_SS_CLOSED:
271 return "CLOSED";
272 case SMD_SS_OPENING:
273 return "OPENING";
274 case SMD_SS_OPENED:
275 return "OPENED";
276 case SMD_SS_FLUSHING:
277 return "FLUSHING";
278 case SMD_SS_CLOSING:
279 return "CLOSING";
280 case SMD_SS_RESET:
281 return "RESET";
282 case SMD_SS_RESET_OPENING:
283 return "ROPENING";
284 default:
285 return "UNKNOWN";
286 }
287}
288
289/* how many bytes are available for reading */ 178/* how many bytes are available for reading */
290static int smd_stream_read_avail(struct smd_channel *ch) 179static int smd_stream_read_avail(struct smd_channel *ch)
291{ 180{
@@ -345,9 +234,9 @@ static void ch_read_done(struct smd_channel *ch, unsigned count)
345} 234}
346 235
347/* basic read interface to ch_read_{buffer,done} used 236/* basic read interface to ch_read_{buffer,done} used
348** by smd_*_read() and update_packet_state() 237 * by smd_*_read() and update_packet_state()
349** will read-and-discard if the _data pointer is null 238 * will read-and-discard if the _data pointer is null
350*/ 239 */
351static int ch_read(struct smd_channel *ch, void *_data, int len) 240static int ch_read(struct smd_channel *ch, void *_data, int len)
352{ 241{
353 void *ptr; 242 void *ptr;
@@ -454,8 +343,7 @@ static void smd_state_change(struct smd_channel *ch,
454{ 343{
455 ch->last_state = next; 344 ch->last_state = next;
456 345
457 pr_info("SMD: ch %d %s -> %s\n", ch->n, 346 pr_info("SMD: ch %d %d -> %d\n", ch->n, last, next);
458 chstate(last), chstate(next));
459 347
460 switch (next) { 348 switch (next) {
461 case SMD_SS_OPENING: 349 case SMD_SS_OPENING:
@@ -936,7 +824,7 @@ void *smem_alloc(unsigned id, unsigned size)
936 return smem_find(id, size); 824 return smem_find(id, size);
937} 825}
938 826
939static void *smem_item(unsigned id, unsigned *size) 827void *smem_item(unsigned id, unsigned *size)
940{ 828{
941 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE; 829 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
942 struct smem_heap_entry *toc = shared->heap_toc; 830 struct smem_heap_entry *toc = shared->heap_toc;
@@ -1042,8 +930,9 @@ uint32_t smsm_get_state(enum smsm_state_item item)
1042 930
1043int smsm_set_sleep_duration(uint32_t delay) 931int smsm_set_sleep_duration(uint32_t delay)
1044{ 932{
1045 struct msm_dem_slave_data *ptr = smem_alloc(SMEM_APPS_DEM_SLAVE_DATA, 933 struct msm_dem_slave_data *ptr;
1046 sizeof(*ptr)); 934
935 ptr = smem_find(SMEM_APPS_DEM_SLAVE_DATA, sizeof(*ptr));
1047 if (ptr == NULL) { 936 if (ptr == NULL) {
1048 pr_err("smsm_set_sleep_duration <SM NO APPS_DEM_SLAVE_DATA>\n"); 937 pr_err("smsm_set_sleep_duration <SM NO APPS_DEM_SLAVE_DATA>\n");
1049 return -EIO; 938 return -EIO;
@@ -1061,7 +950,7 @@ int smsm_set_sleep_duration(uint32_t delay)
1061{ 950{
1062 uint32_t *ptr; 951 uint32_t *ptr;
1063 952
1064 ptr = smem_alloc(SMEM_SMSM_SLEEP_DELAY, sizeof(*ptr)); 953 ptr = smem_find(SMEM_SMSM_SLEEP_DELAY, sizeof(*ptr));
1065 if (ptr == NULL) { 954 if (ptr == NULL) {
1066 pr_err("smsm_set_sleep_duration <SM NO SLEEP_DELAY>\n"); 955 pr_err("smsm_set_sleep_duration <SM NO SLEEP_DELAY>\n");
1067 return -EIO; 956 return -EIO;
@@ -1075,76 +964,6 @@ int smsm_set_sleep_duration(uint32_t delay)
1075 964
1076#endif 965#endif
1077 966
1078#define MAX_NUM_SLEEP_CLIENTS 64
1079#define MAX_SLEEP_NAME_LEN 8
1080
1081#define NUM_GPIO_INT_REGISTERS 6
1082#define GPIO_SMEM_NUM_GROUPS 2
1083#define GPIO_SMEM_MAX_PC_INTERRUPTS 8
1084
1085struct tramp_gpio_save {
1086 unsigned int enable;
1087 unsigned int detect;
1088 unsigned int polarity;
1089};
1090
1091struct tramp_gpio_smem {
1092 uint16_t num_fired[GPIO_SMEM_NUM_GROUPS];
1093 uint16_t fired[GPIO_SMEM_NUM_GROUPS][GPIO_SMEM_MAX_PC_INTERRUPTS];
1094 uint32_t enabled[NUM_GPIO_INT_REGISTERS];
1095 uint32_t detection[NUM_GPIO_INT_REGISTERS];
1096 uint32_t polarity[NUM_GPIO_INT_REGISTERS];
1097};
1098
1099
1100void smsm_print_sleep_info(void)
1101{
1102 unsigned long flags;
1103 uint32_t *ptr;
1104 struct tramp_gpio_smem *gpio;
1105 struct smsm_interrupt_info *int_info;
1106
1107
1108 spin_lock_irqsave(&smem_lock, flags);
1109
1110 ptr = smem_alloc(SMEM_SMSM_SLEEP_DELAY, sizeof(*ptr));
1111 if (ptr)
1112 pr_info("SMEM_SMSM_SLEEP_DELAY: %x\n", *ptr);
1113
1114 ptr = smem_alloc(SMEM_SMSM_LIMIT_SLEEP, sizeof(*ptr));
1115 if (ptr)
1116 pr_info("SMEM_SMSM_LIMIT_SLEEP: %x\n", *ptr);
1117
1118 ptr = smem_alloc(SMEM_SLEEP_POWER_COLLAPSE_DISABLED, sizeof(*ptr));
1119 if (ptr)
1120 pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: %x\n", *ptr);
1121
1122#ifndef CONFIG_ARCH_MSM_SCORPION
1123 int_info = smem_alloc(SMEM_SMSM_INT_INFO, sizeof(*int_info));
1124 if (int_info)
1125 pr_info("SMEM_SMSM_INT_INFO %x %x %x\n",
1126 int_info->interrupt_mask,
1127 int_info->pending_interrupts,
1128 int_info->wakeup_reason);
1129
1130 gpio = smem_alloc(SMEM_GPIO_INT, sizeof(*gpio));
1131 if (gpio) {
1132 int i;
1133 for (i = 0; i < NUM_GPIO_INT_REGISTERS; i++)
1134 pr_info("SMEM_GPIO_INT: %d: e %x d %x p %x\n",
1135 i, gpio->enabled[i], gpio->detection[i],
1136 gpio->polarity[i]);
1137
1138 for (i = 0; i < GPIO_SMEM_NUM_GROUPS; i++)
1139 pr_info("SMEM_GPIO_INT: %d: f %d: %d %d...\n",
1140 i, gpio->num_fired[i], gpio->fired[i][0],
1141 gpio->fired[i][1]);
1142 }
1143#else
1144#endif
1145 spin_unlock_irqrestore(&smem_lock, flags);
1146}
1147
1148int smd_core_init(void) 967int smd_core_init(void)
1149{ 968{
1150 int r; 969 int r;
@@ -1196,207 +1015,6 @@ int smd_core_init(void)
1196 return 0; 1015 return 0;
1197} 1016}
1198 1017
1199#if defined(CONFIG_DEBUG_FS)
1200
1201static int dump_ch(char *buf, int max, struct smd_channel *ch)
1202{
1203 volatile struct smd_half_channel *s = ch->send;
1204 volatile struct smd_half_channel *r = ch->recv;
1205
1206 return scnprintf(
1207 buf, max,
1208 "ch%02d:"
1209 " %8s(%05d/%05d) %c%c%c%c%c%c%c <->"
1210 " %8s(%05d/%05d) %c%c%c%c%c%c%c\n", ch->n,
1211 chstate(s->state), s->tail, s->head,
1212 s->fDSR ? 'D' : 'd',
1213 s->fCTS ? 'C' : 'c',
1214 s->fCD ? 'C' : 'c',
1215 s->fRI ? 'I' : 'i',
1216 s->fHEAD ? 'W' : 'w',
1217 s->fTAIL ? 'R' : 'r',
1218 s->fSTATE ? 'S' : 's',
1219 chstate(r->state), r->tail, r->head,
1220 r->fDSR ? 'D' : 'd',
1221 r->fCTS ? 'R' : 'r',
1222 r->fCD ? 'C' : 'c',
1223 r->fRI ? 'I' : 'i',
1224 r->fHEAD ? 'W' : 'w',
1225 r->fTAIL ? 'R' : 'r',
1226 r->fSTATE ? 'S' : 's'
1227 );
1228}
1229
1230static int debug_read_stat(char *buf, int max)
1231{
1232 char *msg;
1233 int i = 0;
1234
1235 msg = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
1236
1237 if (raw_smsm_get_state(SMSM_STATE_MODEM) & SMSM_RESET)
1238 i += scnprintf(buf + i, max - i,
1239 "smsm: ARM9 HAS CRASHED\n");
1240
1241 i += scnprintf(buf + i, max - i, "smsm: a9: %08x a11: %08x\n",
1242 raw_smsm_get_state(SMSM_STATE_MODEM),
1243 raw_smsm_get_state(SMSM_STATE_APPS));
1244#ifdef CONFIG_ARCH_MSM_SCORPION
1245 i += scnprintf(buf + i, max - i, "smsm dem: apps: %08x modem: %08x "
1246 "qdsp6: %08x power: %08x time: %08x\n",
1247 raw_smsm_get_state(SMSM_STATE_APPS_DEM),
1248 raw_smsm_get_state(SMSM_STATE_MODEM_DEM),
1249 raw_smsm_get_state(SMSM_STATE_QDSP6_DEM),
1250 raw_smsm_get_state(SMSM_STATE_POWER_MASTER_DEM),
1251 raw_smsm_get_state(SMSM_STATE_TIME_MASTER_DEM));
1252#endif
1253 if (msg) {
1254 msg[SZ_DIAG_ERR_MSG - 1] = 0;
1255 i += scnprintf(buf + i, max - i, "diag: '%s'\n", msg);
1256 }
1257 return i;
1258}
1259
1260static int debug_read_mem(char *buf, int max)
1261{
1262 unsigned n;
1263 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
1264 struct smem_heap_entry *toc = shared->heap_toc;
1265 int i = 0;
1266
1267 i += scnprintf(buf + i, max - i,
1268 "heap: init=%d free=%d remain=%d\n",
1269 shared->heap_info.initialized,
1270 shared->heap_info.free_offset,
1271 shared->heap_info.heap_remaining);
1272
1273 for (n = 0; n < SMEM_NUM_ITEMS; n++) {
1274 if (toc[n].allocated == 0)
1275 continue;
1276 i += scnprintf(buf + i, max - i,
1277 "%04d: offset %08x size %08x\n",
1278 n, toc[n].offset, toc[n].size);
1279 }
1280 return i;
1281}
1282
1283static int debug_read_ch(char *buf, int max)
1284{
1285 struct smd_channel *ch;
1286 unsigned long flags;
1287 int i = 0;
1288
1289 spin_lock_irqsave(&smd_lock, flags);
1290 list_for_each_entry(ch, &smd_ch_list, ch_list)
1291 i += dump_ch(buf + i, max - i, ch);
1292 list_for_each_entry(ch, &smd_ch_closed_list, ch_list)
1293 i += dump_ch(buf + i, max - i, ch);
1294 spin_unlock_irqrestore(&smd_lock, flags);
1295
1296 return i;
1297}
1298
1299static int debug_read_version(char *buf, int max)
1300{
1301 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
1302 unsigned version = shared->version[VERSION_MODEM];
1303 return sprintf(buf, "%d.%d\n", version >> 16, version & 0xffff);
1304}
1305
1306static int debug_read_build_id(char *buf, int max)
1307{
1308 unsigned size;
1309 void *data;
1310
1311 data = smem_item(SMEM_HW_SW_BUILD_ID, &size);
1312 if (!data)
1313 return 0;
1314
1315 if (size >= max)
1316 size = max;
1317 memcpy(buf, data, size);
1318
1319 return size;
1320}
1321
1322static int debug_read_alloc_tbl(char *buf, int max)
1323{
1324 struct smd_alloc_elm *shared;
1325 int n, i = 0;
1326
1327 shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64);
1328
1329 for (n = 0; n < 64; n++) {
1330 if (shared[n].ref_count == 0)
1331 continue;
1332 i += scnprintf(buf + i, max - i,
1333 "%03d: %-20s cid=%02d type=%03d "
1334 "kind=%02d ref_count=%d\n",
1335 n, shared[n].name, shared[n].cid,
1336 shared[n].ctype & 0xff,
1337 (shared[n].ctype >> 8) & 0xf,
1338 shared[n].ref_count);
1339 }
1340
1341 return i;
1342}
1343
1344static int debug_boom(char *buf, int max)
1345{
1346 unsigned ms = 5000;
1347 msm_proc_comm(PCOM_RESET_MODEM, &ms, 0);
1348 return 0;
1349}
1350
1351#define DEBUG_BUFMAX 4096
1352static char debug_buffer[DEBUG_BUFMAX];
1353
1354static ssize_t debug_read(struct file *file, char __user *buf,
1355 size_t count, loff_t *ppos)
1356{
1357 int (*fill)(char *buf, int max) = file->private_data;
1358 int bsize = fill(debug_buffer, DEBUG_BUFMAX);
1359 return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
1360}
1361
1362static int debug_open(struct inode *inode, struct file *file)
1363{
1364 file->private_data = inode->i_private;
1365 return 0;
1366}
1367
1368static const struct file_operations debug_ops = {
1369 .read = debug_read,
1370 .open = debug_open,
1371};
1372
1373static void debug_create(const char *name, mode_t mode,
1374 struct dentry *dent,
1375 int (*fill)(char *buf, int max))
1376{
1377 debugfs_create_file(name, mode, dent, fill, &debug_ops);
1378}
1379
1380static void smd_debugfs_init(void)
1381{
1382 struct dentry *dent;
1383
1384 dent = debugfs_create_dir("smd", 0);
1385 if (IS_ERR(dent))
1386 return;
1387
1388 debug_create("ch", 0444, dent, debug_read_ch);
1389 debug_create("stat", 0444, dent, debug_read_stat);
1390 debug_create("mem", 0444, dent, debug_read_mem);
1391 debug_create("version", 0444, dent, debug_read_version);
1392 debug_create("tbl", 0444, dent, debug_read_alloc_tbl);
1393 debug_create("build", 0444, dent, debug_read_build_id);
1394 debug_create("boom", 0444, dent, debug_boom);
1395}
1396#else
1397static void smd_debugfs_init(void) {}
1398#endif
1399
1400static int __init msm_smd_probe(struct platform_device *pdev) 1018static int __init msm_smd_probe(struct platform_device *pdev)
1401{ 1019{
1402 pr_info("smd_init()\n"); 1020 pr_info("smd_init()\n");
@@ -1412,7 +1030,6 @@ static int __init msm_smd_probe(struct platform_device *pdev)
1412 1030
1413 msm_check_for_modem_crash = check_for_modem_crash; 1031 msm_check_for_modem_crash = check_for_modem_crash;
1414 1032
1415 smd_debugfs_init();
1416 smd_initialized = 1; 1033 smd_initialized = 1;
1417 1034
1418 return 0; 1035 return 0;
diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c
new file mode 100644
index 000000000000..3bb40a7fa283
--- /dev/null
+++ b/arch/arm/mach-msm/smd_debug.c
@@ -0,0 +1,310 @@
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\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 );
76}
77
78static int debug_read_stat(char *buf, int max)
79{
80 char *msg;
81 int i = 0;
82
83 msg = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
84
85 if (raw_smsm_get_state(SMSM_STATE_MODEM) & SMSM_RESET)
86 i += scnprintf(buf + i, max - i,
87 "smsm: ARM9 HAS CRASHED\n");
88
89 i += scnprintf(buf + i, max - i, "smsm: a9: %08x a11: %08x\n",
90 raw_smsm_get_state(SMSM_STATE_MODEM),
91 raw_smsm_get_state(SMSM_STATE_APPS));
92#ifdef CONFIG_ARCH_MSM_SCORPION
93 i += scnprintf(buf + i, max - i, "smsm dem: apps: %08x modem: %08x "
94 "qdsp6: %08x power: %08x time: %08x\n",
95 raw_smsm_get_state(SMSM_STATE_APPS_DEM),
96 raw_smsm_get_state(SMSM_STATE_MODEM_DEM),
97 raw_smsm_get_state(SMSM_STATE_QDSP6_DEM),
98 raw_smsm_get_state(SMSM_STATE_POWER_MASTER_DEM),
99 raw_smsm_get_state(SMSM_STATE_TIME_MASTER_DEM));
100#endif
101 if (msg) {
102 msg[SZ_DIAG_ERR_MSG - 1] = 0;
103 i += scnprintf(buf + i, max - i, "diag: '%s'\n", msg);
104 }
105 return i;
106}
107
108static int debug_read_mem(char *buf, int max)
109{
110 unsigned n;
111 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
112 struct smem_heap_entry *toc = shared->heap_toc;
113 int i = 0;
114
115 i += scnprintf(buf + i, max - i,
116 "heap: init=%d free=%d remain=%d\n",
117 shared->heap_info.initialized,
118 shared->heap_info.free_offset,
119 shared->heap_info.heap_remaining);
120
121 for (n = 0; n < SMEM_NUM_ITEMS; n++) {
122 if (toc[n].allocated == 0)
123 continue;
124 i += scnprintf(buf + i, max - i,
125 "%04d: offset %08x size %08x\n",
126 n, toc[n].offset, toc[n].size);
127 }
128 return i;
129}
130
131static int debug_read_ch(char *buf, int max)
132{
133 struct smd_channel *ch;
134 unsigned long flags;
135 int i = 0;
136
137 spin_lock_irqsave(&smd_lock, flags);
138 list_for_each_entry(ch, &smd_ch_list, ch_list)
139 i += dump_ch(buf + i, max - i, ch);
140 list_for_each_entry(ch, &smd_ch_closed_list, ch_list)
141 i += dump_ch(buf + i, max - i, ch);
142 spin_unlock_irqrestore(&smd_lock, flags);
143
144 return i;
145}
146
147static int debug_read_version(char *buf, int max)
148{
149 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
150 unsigned version = shared->version[VERSION_MODEM];
151 return sprintf(buf, "%d.%d\n", version >> 16, version & 0xffff);
152}
153
154static int debug_read_build_id(char *buf, int max)
155{
156 unsigned size;
157 void *data;
158
159 data = smem_item(SMEM_HW_SW_BUILD_ID, &size);
160 if (!data)
161 return 0;
162
163 if (size >= max)
164 size = max;
165 memcpy(buf, data, size);
166
167 return size;
168}
169
170static int debug_read_alloc_tbl(char *buf, int max)
171{
172 struct smd_alloc_elm *shared;
173 int n, i = 0;
174
175 shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64);
176
177 for (n = 0; n < 64; n++) {
178 if (shared[n].ref_count == 0)
179 continue;
180 i += scnprintf(buf + i, max - i,
181 "%03d: %-20s cid=%02d type=%03d "
182 "kind=%02d ref_count=%d\n",
183 n, shared[n].name, shared[n].cid,
184 shared[n].ctype & 0xff,
185 (shared[n].ctype >> 8) & 0xf,
186 shared[n].ref_count);
187 }
188
189 return i;
190}
191
192#define DEBUG_BUFMAX 4096
193static char debug_buffer[DEBUG_BUFMAX];
194
195static ssize_t debug_read(struct file *file, char __user *buf,
196 size_t count, loff_t *ppos)
197{
198 int (*fill)(char *buf, int max) = file->private_data;
199 int bsize = fill(debug_buffer, DEBUG_BUFMAX);
200 return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
201}
202
203static int debug_open(struct inode *inode, struct file *file)
204{
205 file->private_data = inode->i_private;
206 return 0;
207}
208
209static const struct file_operations debug_ops = {
210 .read = debug_read,
211 .open = debug_open,
212};
213
214static void debug_create(const char *name, mode_t mode,
215 struct dentry *dent,
216 int (*fill)(char *buf, int max))
217{
218 debugfs_create_file(name, mode, dent, fill, &debug_ops);
219}
220
221static void smd_debugfs_init(void)
222{
223 struct dentry *dent;
224
225 dent = debugfs_create_dir("smd", 0);
226 if (IS_ERR(dent))
227 return;
228
229 debug_create("ch", 0444, dent, debug_read_ch);
230 debug_create("stat", 0444, dent, debug_read_stat);
231 debug_create("mem", 0444, dent, debug_read_mem);
232 debug_create("version", 0444, dent, debug_read_version);
233 debug_create("tbl", 0444, dent, debug_read_alloc_tbl);
234 debug_create("build", 0444, dent, debug_read_build_id);
235}
236
237late_initcall(smd_debugfs_init);
238#endif
239
240
241#define MAX_NUM_SLEEP_CLIENTS 64
242#define MAX_SLEEP_NAME_LEN 8
243
244#define NUM_GPIO_INT_REGISTERS 6
245#define GPIO_SMEM_NUM_GROUPS 2
246#define GPIO_SMEM_MAX_PC_INTERRUPTS 8
247
248struct tramp_gpio_save {
249 unsigned int enable;
250 unsigned int detect;
251 unsigned int polarity;
252};
253
254struct tramp_gpio_smem {
255 uint16_t num_fired[GPIO_SMEM_NUM_GROUPS];
256 uint16_t fired[GPIO_SMEM_NUM_GROUPS][GPIO_SMEM_MAX_PC_INTERRUPTS];
257 uint32_t enabled[NUM_GPIO_INT_REGISTERS];
258 uint32_t detection[NUM_GPIO_INT_REGISTERS];
259 uint32_t polarity[NUM_GPIO_INT_REGISTERS];
260};
261
262
263void smsm_print_sleep_info(void)
264{
265 unsigned long flags;
266 uint32_t *ptr;
267 struct tramp_gpio_smem *gpio;
268 struct smsm_interrupt_info *int_info;
269
270
271 spin_lock_irqsave(&smem_lock, flags);
272
273 ptr = smem_alloc(SMEM_SMSM_SLEEP_DELAY, sizeof(*ptr));
274 if (ptr)
275 pr_info("SMEM_SMSM_SLEEP_DELAY: %x\n", *ptr);
276
277 ptr = smem_alloc(SMEM_SMSM_LIMIT_SLEEP, sizeof(*ptr));
278 if (ptr)
279 pr_info("SMEM_SMSM_LIMIT_SLEEP: %x\n", *ptr);
280
281 ptr = smem_alloc(SMEM_SLEEP_POWER_COLLAPSE_DISABLED, sizeof(*ptr));
282 if (ptr)
283 pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: %x\n", *ptr);
284
285#ifndef CONFIG_ARCH_MSM_SCORPION
286 int_info = smem_alloc(SMEM_SMSM_INT_INFO, sizeof(*int_info));
287 if (int_info)
288 pr_info("SMEM_SMSM_INT_INFO %x %x %x\n",
289 int_info->interrupt_mask,
290 int_info->pending_interrupts,
291 int_info->wakeup_reason);
292
293 gpio = smem_alloc(SMEM_GPIO_INT, sizeof(*gpio));
294 if (gpio) {
295 int i;
296 for (i = 0; i < NUM_GPIO_INT_REGISTERS; i++)
297 pr_info("SMEM_GPIO_INT: %d: e %x d %x p %x\n",
298 i, gpio->enabled[i], gpio->detection[i],
299 gpio->polarity[i]);
300
301 for (i = 0; i < GPIO_SMEM_NUM_GROUPS; i++)
302 pr_info("SMEM_GPIO_INT: %d: f %d: %d %d...\n",
303 i, gpio->num_fired[i], gpio->fired[i][0],
304 gpio->fired[i][1]);
305 }
306#else
307#endif
308 spin_unlock_irqrestore(&smem_lock, flags);
309}
310
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
index 71f9612d5f50..13d7c9d31a9a 100644
--- a/arch/arm/mach-msm/smd_private.h
+++ b/arch/arm/mach-msm/smd_private.h
@@ -16,6 +16,10 @@
16#ifndef _ARCH_ARM_MACH_MSM_MSM_SMD_PRIVATE_H_ 16#ifndef _ARCH_ARM_MACH_MSM_MSM_SMD_PRIVATE_H_
17#define _ARCH_ARM_MACH_MSM_MSM_SMD_PRIVATE_H_ 17#define _ARCH_ARM_MACH_MSM_MSM_SMD_PRIVATE_H_
18 18
19#include <linux/platform_device.h>
20#include <linux/spinlock.h>
21#include <linux/list.h>
22
19struct smem_heap_info 23struct smem_heap_info
20{ 24{
21 unsigned initialized; 25 unsigned initialized;
@@ -232,4 +236,101 @@ typedef enum
232 SMEM_NUM_ITEMS, 236 SMEM_NUM_ITEMS,
233} smem_mem_type; 237} smem_mem_type;
234 238
239
240#define SMD_SS_CLOSED 0x00000000
241#define SMD_SS_OPENING 0x00000001
242#define SMD_SS_OPENED 0x00000002
243#define SMD_SS_FLUSHING 0x00000003
244#define SMD_SS_CLOSING 0x00000004
245#define SMD_SS_RESET 0x00000005
246#define SMD_SS_RESET_OPENING 0x00000006
247
248#define SMD_BUF_SIZE 8192
249#define SMD_CHANNELS 64
250
251#define SMD_HEADER_SIZE 20
252
253struct smd_alloc_elm {
254 char name[20];
255 uint32_t cid;
256 uint32_t ctype;
257 uint32_t ref_count;
258};
259
260struct smd_half_channel {
261 unsigned state;
262 unsigned char fDSR;
263 unsigned char fCTS;
264 unsigned char fCD;
265 unsigned char fRI;
266 unsigned char fHEAD;
267 unsigned char fTAIL;
268 unsigned char fSTATE;
269 unsigned char fUNUSED;
270 unsigned tail;
271 unsigned head;
272} __attribute__((packed));
273
274struct smd_shared_v1 {
275 struct smd_half_channel ch0;
276 unsigned char data0[SMD_BUF_SIZE];
277 struct smd_half_channel ch1;
278 unsigned char data1[SMD_BUF_SIZE];
279};
280
281struct smd_shared_v2 {
282 struct smd_half_channel ch0;
283 struct smd_half_channel ch1;
284};
285
286struct smd_channel {
287 volatile struct smd_half_channel *send;
288 volatile struct smd_half_channel *recv;
289 unsigned char *send_data;
290 unsigned char *recv_data;
291
292 unsigned fifo_mask;
293 unsigned fifo_size;
294 unsigned current_packet;
295 unsigned n;
296
297 struct list_head ch_list;
298
299 void *priv;
300 void (*notify)(void *priv, unsigned flags);
301
302 int (*read)(struct smd_channel *ch, void *data, int len);
303 int (*write)(struct smd_channel *ch, const void *data, int len);
304 int (*read_avail)(struct smd_channel *ch);
305 int (*write_avail)(struct smd_channel *ch);
306
307 void (*update_state)(struct smd_channel *ch);
308 unsigned last_state;
309 void (*notify_other_cpu)(void);
310 unsigned type;
311
312 char name[32];
313 struct platform_device pdev;
314};
315
316#define SMD_TYPE_MASK 0x0FF
317#define SMD_TYPE_APPS_MODEM 0x000
318#define SMD_TYPE_APPS_DSP 0x001
319#define SMD_TYPE_MODEM_DSP 0x002
320
321#define SMD_KIND_MASK 0xF00
322#define SMD_KIND_UNKNOWN 0x000
323#define SMD_KIND_STREAM 0x100
324#define SMD_KIND_PACKET 0x200
325
326extern struct list_head smd_ch_closed_list;
327extern struct list_head smd_ch_list;
328
329extern spinlock_t smd_lock;
330extern spinlock_t smem_lock;
331
332void *smem_find(unsigned id, unsigned size);
333void *smem_item(unsigned id, unsigned *size);
334uint32_t raw_smsm_get_state(enum smsm_state_item item);
335
235#endif 336#endif