1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Shared Transport Line discipline driver Core |
4 | * Init Manager module responsible for GPIO control |
5 | * and firmware download |
6 | * Copyright (C) 2009-2010 Texas Instruments |
7 | * Author: Pavan Savoy <pavan_savoy@ti.com> |
8 | */ |
9 | |
10 | #define pr_fmt(fmt) "(stk) :" fmt |
11 | #include <linux/platform_device.h> |
12 | #include <linux/jiffies.h> |
13 | #include <linux/firmware.h> |
14 | #include <linux/delay.h> |
15 | #include <linux/wait.h> |
16 | #include <linux/gpio.h> |
17 | #include <linux/debugfs.h> |
18 | #include <linux/seq_file.h> |
19 | #include <linux/sched.h> |
20 | #include <linux/sysfs.h> |
21 | #include <linux/tty.h> |
22 | |
23 | #include <linux/skbuff.h> |
24 | #include <linux/ti_wilink_st.h> |
25 | #include <linux/module.h> |
26 | |
27 | #define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */ |
28 | static struct platform_device *st_kim_devices[MAX_ST_DEVICES]; |
29 | |
30 | /**********************************************************************/ |
31 | /* internal functions */ |
32 | |
33 | /* |
34 | * st_get_plat_device - |
35 | * function which returns the reference to the platform device |
36 | * requested by id. As of now only 1 such device exists (id=0) |
37 | * the context requesting for reference can get the id to be |
38 | * requested by a. The protocol driver which is registering or |
39 | * b. the tty device which is opened. |
40 | */ |
41 | static struct platform_device *st_get_plat_device(int id) |
42 | { |
43 | return st_kim_devices[id]; |
44 | } |
45 | |
46 | /* |
47 | * validate_firmware_response - |
48 | * function to return whether the firmware response was proper |
49 | * in case of error don't complete so that waiting for proper |
50 | * response times out |
51 | */ |
52 | static void validate_firmware_response(struct kim_data_s *kim_gdata) |
53 | { |
54 | struct sk_buff *skb = kim_gdata->rx_skb; |
55 | if (!skb) |
56 | return; |
57 | |
58 | /* |
59 | * these magic numbers are the position in the response buffer which |
60 | * allows us to distinguish whether the response is for the read |
61 | * version info. command |
62 | */ |
63 | if (skb->data[2] == 0x01 && skb->data[3] == 0x01 && |
64 | skb->data[4] == 0x10 && skb->data[5] == 0x00) { |
65 | /* fw version response */ |
66 | memcpy(kim_gdata->resp_buffer, |
67 | kim_gdata->rx_skb->data, |
68 | kim_gdata->rx_skb->len); |
69 | kim_gdata->rx_state = ST_W4_PACKET_TYPE; |
70 | kim_gdata->rx_skb = NULL; |
71 | kim_gdata->rx_count = 0; |
72 | } else if (unlikely(skb->data[5] != 0)) { |
73 | pr_err("no proper response during fw download" ); |
74 | pr_err("data6 %x" , skb->data[5]); |
75 | kfree_skb(skb); |
76 | return; /* keep waiting for the proper response */ |
77 | } |
78 | /* becos of all the script being downloaded */ |
79 | complete_all(&kim_gdata->kim_rcvd); |
80 | kfree_skb(skb); |
81 | } |
82 | |
83 | /* |
84 | * check for data len received inside kim_int_recv |
85 | * most often hit the last case to update state to waiting for data |
86 | */ |
87 | static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len) |
88 | { |
89 | register int room = skb_tailroom(skb: kim_gdata->rx_skb); |
90 | |
91 | pr_debug("len %d room %d" , len, room); |
92 | |
93 | if (!len) { |
94 | validate_firmware_response(kim_gdata); |
95 | } else if (len > room) { |
96 | /* |
97 | * Received packet's payload length is larger. |
98 | * We can't accommodate it in created skb. |
99 | */ |
100 | pr_err("Data length is too large len %d room %d" , len, |
101 | room); |
102 | kfree_skb(skb: kim_gdata->rx_skb); |
103 | } else { |
104 | /* |
105 | * Packet header has non-zero payload length and |
106 | * we have enough space in created skb. Lets read |
107 | * payload data */ |
108 | kim_gdata->rx_state = ST_W4_DATA; |
109 | kim_gdata->rx_count = len; |
110 | return len; |
111 | } |
112 | |
113 | /* |
114 | * Change ST LL state to continue to process next |
115 | * packet |
116 | */ |
117 | kim_gdata->rx_state = ST_W4_PACKET_TYPE; |
118 | kim_gdata->rx_skb = NULL; |
119 | kim_gdata->rx_count = 0; |
120 | |
121 | return 0; |
122 | } |
123 | |
124 | /* |
125 | * kim_int_recv - receive function called during firmware download |
126 | * firmware download responses on different UART drivers |
127 | * have been observed to come in bursts of different |
128 | * tty_receive and hence the logic |
129 | */ |
130 | static void kim_int_recv(struct kim_data_s *kim_gdata, const u8 *ptr, |
131 | size_t count) |
132 | { |
133 | int len = 0; |
134 | unsigned char *plen; |
135 | |
136 | pr_debug("%s" , __func__); |
137 | /* Decode received bytes here */ |
138 | while (count) { |
139 | if (kim_gdata->rx_count) { |
140 | len = min_t(unsigned int, kim_gdata->rx_count, count); |
141 | skb_put_data(skb: kim_gdata->rx_skb, data: ptr, len); |
142 | kim_gdata->rx_count -= len; |
143 | count -= len; |
144 | ptr += len; |
145 | |
146 | if (kim_gdata->rx_count) |
147 | continue; |
148 | |
149 | /* Check ST RX state machine , where are we? */ |
150 | switch (kim_gdata->rx_state) { |
151 | /* Waiting for complete packet ? */ |
152 | case ST_W4_DATA: |
153 | pr_debug("Complete pkt received" ); |
154 | validate_firmware_response(kim_gdata); |
155 | kim_gdata->rx_state = ST_W4_PACKET_TYPE; |
156 | kim_gdata->rx_skb = NULL; |
157 | continue; |
158 | /* Waiting for Bluetooth event header ? */ |
159 | case ST_W4_HEADER: |
160 | plen = |
161 | (unsigned char *)&kim_gdata->rx_skb->data[1]; |
162 | pr_debug("event hdr: plen 0x%02x\n" , *plen); |
163 | kim_check_data_len(kim_gdata, len: *plen); |
164 | continue; |
165 | } /* end of switch */ |
166 | } /* end of if rx_state */ |
167 | switch (*ptr) { |
168 | /* Bluetooth event packet? */ |
169 | case 0x04: |
170 | kim_gdata->rx_state = ST_W4_HEADER; |
171 | kim_gdata->rx_count = 2; |
172 | break; |
173 | default: |
174 | pr_info("unknown packet" ); |
175 | ptr++; |
176 | count--; |
177 | continue; |
178 | } |
179 | ptr++; |
180 | count--; |
181 | kim_gdata->rx_skb = |
182 | alloc_skb(size: 1024+8, GFP_ATOMIC); |
183 | if (!kim_gdata->rx_skb) { |
184 | pr_err("can't allocate mem for new packet" ); |
185 | kim_gdata->rx_state = ST_W4_PACKET_TYPE; |
186 | kim_gdata->rx_count = 0; |
187 | return; |
188 | } |
189 | skb_reserve(skb: kim_gdata->rx_skb, len: 8); |
190 | kim_gdata->rx_skb->cb[0] = 4; |
191 | kim_gdata->rx_skb->cb[1] = 0; |
192 | |
193 | } |
194 | return; |
195 | } |
196 | |
197 | static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) |
198 | { |
199 | unsigned short version = 0, chip = 0, min_ver = 0, maj_ver = 0; |
200 | static const char read_ver_cmd[] = { 0x01, 0x01, 0x10, 0x00 }; |
201 | long timeout; |
202 | |
203 | pr_debug("%s" , __func__); |
204 | |
205 | reinit_completion(x: &kim_gdata->kim_rcvd); |
206 | if (4 != st_int_write(kim_gdata->core_data, read_ver_cmd, 4)) { |
207 | pr_err("kim: couldn't write 4 bytes" ); |
208 | return -EIO; |
209 | } |
210 | |
211 | timeout = wait_for_completion_interruptible_timeout( |
212 | x: &kim_gdata->kim_rcvd, timeout: msecs_to_jiffies(CMD_RESP_TIME)); |
213 | if (timeout <= 0) { |
214 | pr_err(" waiting for ver info- timed out or received signal" ); |
215 | return timeout ? -ERESTARTSYS : -ETIMEDOUT; |
216 | } |
217 | reinit_completion(x: &kim_gdata->kim_rcvd); |
218 | /* |
219 | * the positions 12 & 13 in the response buffer provide with the |
220 | * chip, major & minor numbers |
221 | */ |
222 | |
223 | version = |
224 | MAKEWORD(kim_gdata->resp_buffer[12], |
225 | kim_gdata->resp_buffer[13]); |
226 | chip = (version & 0x7C00) >> 10; |
227 | min_ver = (version & 0x007F); |
228 | maj_ver = (version & 0x0380) >> 7; |
229 | |
230 | if (version & 0x8000) |
231 | maj_ver |= 0x0008; |
232 | |
233 | sprintf(buf: bts_scr_name, fmt: "ti-connectivity/TIInit_%d.%d.%d.bts" , |
234 | chip, maj_ver, min_ver); |
235 | |
236 | /* to be accessed later via sysfs entry */ |
237 | kim_gdata->version.full = version; |
238 | kim_gdata->version.chip = chip; |
239 | kim_gdata->version.maj_ver = maj_ver; |
240 | kim_gdata->version.min_ver = min_ver; |
241 | |
242 | pr_info("%s" , bts_scr_name); |
243 | return 0; |
244 | } |
245 | |
246 | static void skip_change_remote_baud(unsigned char **ptr, long *len) |
247 | { |
248 | unsigned char *nxt_action, *cur_action; |
249 | cur_action = *ptr; |
250 | |
251 | nxt_action = cur_action + sizeof(struct bts_action) + |
252 | ((struct bts_action *) cur_action)->size; |
253 | |
254 | if (((struct bts_action *) nxt_action)->type != ACTION_WAIT_EVENT) { |
255 | pr_err("invalid action after change remote baud command" ); |
256 | } else { |
257 | *ptr = *ptr + sizeof(struct bts_action) + |
258 | ((struct bts_action *)cur_action)->size; |
259 | *len = *len - (sizeof(struct bts_action) + |
260 | ((struct bts_action *)cur_action)->size); |
261 | /* warn user on not commenting these in firmware */ |
262 | pr_warn("skipping the wait event of change remote baud" ); |
263 | } |
264 | } |
265 | |
266 | /* |
267 | * download_firmware - |
268 | * internal function which parses through the .bts firmware |
269 | * script file intreprets SEND, DELAY actions only as of now |
270 | */ |
271 | static long download_firmware(struct kim_data_s *kim_gdata) |
272 | { |
273 | long err = 0; |
274 | long len = 0; |
275 | unsigned char *ptr = NULL; |
276 | unsigned char *action_ptr = NULL; |
277 | unsigned char bts_scr_name[40] = { 0 }; /* 40 char long bts scr name? */ |
278 | int wr_room_space; |
279 | int cmd_size; |
280 | unsigned long timeout; |
281 | |
282 | err = read_local_version(kim_gdata, bts_scr_name); |
283 | if (err != 0) { |
284 | pr_err("kim: failed to read local ver" ); |
285 | return err; |
286 | } |
287 | err = |
288 | request_firmware(fw: &kim_gdata->fw_entry, name: bts_scr_name, |
289 | device: &kim_gdata->kim_pdev->dev); |
290 | if (unlikely((err != 0) || (kim_gdata->fw_entry->data == NULL) || |
291 | (kim_gdata->fw_entry->size == 0))) { |
292 | pr_err(" request_firmware failed(errno %ld) for %s" , err, |
293 | bts_scr_name); |
294 | return -EINVAL; |
295 | } |
296 | ptr = (void *)kim_gdata->fw_entry->data; |
297 | len = kim_gdata->fw_entry->size; |
298 | /* |
299 | * bts_header to remove out magic number and |
300 | * version |
301 | */ |
302 | ptr += sizeof(struct bts_header); |
303 | len -= sizeof(struct bts_header); |
304 | |
305 | while (len > 0 && ptr) { |
306 | pr_debug(" action size %d, type %d " , |
307 | ((struct bts_action *)ptr)->size, |
308 | ((struct bts_action *)ptr)->type); |
309 | |
310 | switch (((struct bts_action *)ptr)->type) { |
311 | case ACTION_SEND_COMMAND: /* action send */ |
312 | pr_debug("S" ); |
313 | action_ptr = &(((struct bts_action *)ptr)->data[0]); |
314 | if (unlikely |
315 | (((struct hci_command *)action_ptr)->opcode == |
316 | 0xFF36)) { |
317 | /* |
318 | * ignore remote change |
319 | * baud rate HCI VS command |
320 | */ |
321 | pr_warn("change remote baud" |
322 | " rate command in firmware" ); |
323 | skip_change_remote_baud(ptr: &ptr, len: &len); |
324 | break; |
325 | } |
326 | /* |
327 | * Make sure we have enough free space in uart |
328 | * tx buffer to write current firmware command |
329 | */ |
330 | cmd_size = ((struct bts_action *)ptr)->size; |
331 | timeout = jiffies + msecs_to_jiffies(CMD_WR_TIME); |
332 | do { |
333 | wr_room_space = |
334 | st_get_uart_wr_room(st_gdata: kim_gdata->core_data); |
335 | if (wr_room_space < 0) { |
336 | pr_err("Unable to get free " |
337 | "space info from uart tx buffer" ); |
338 | release_firmware(fw: kim_gdata->fw_entry); |
339 | return wr_room_space; |
340 | } |
341 | mdelay(1); /* wait 1ms before checking room */ |
342 | } while ((wr_room_space < cmd_size) && |
343 | time_before(jiffies, timeout)); |
344 | |
345 | /* Timeout happened ? */ |
346 | if (time_after_eq(jiffies, timeout)) { |
347 | pr_err("Timeout while waiting for free " |
348 | "free space in uart tx buffer" ); |
349 | release_firmware(fw: kim_gdata->fw_entry); |
350 | return -ETIMEDOUT; |
351 | } |
352 | /* |
353 | * reinit completion before sending for the |
354 | * relevant wait |
355 | */ |
356 | reinit_completion(x: &kim_gdata->kim_rcvd); |
357 | |
358 | /* |
359 | * Free space found in uart buffer, call st_int_write |
360 | * to send current firmware command to the uart tx |
361 | * buffer. |
362 | */ |
363 | err = st_int_write(kim_gdata->core_data, |
364 | ((struct bts_action_send *)action_ptr)->data, |
365 | ((struct bts_action *)ptr)->size); |
366 | if (unlikely(err < 0)) { |
367 | release_firmware(fw: kim_gdata->fw_entry); |
368 | return err; |
369 | } |
370 | /* |
371 | * Check number of bytes written to the uart tx buffer |
372 | * and requested command write size |
373 | */ |
374 | if (err != cmd_size) { |
375 | pr_err("Number of bytes written to uart " |
376 | "tx buffer are not matching with " |
377 | "requested cmd write size" ); |
378 | release_firmware(fw: kim_gdata->fw_entry); |
379 | return -EIO; |
380 | } |
381 | break; |
382 | case ACTION_WAIT_EVENT: /* wait */ |
383 | pr_debug("W" ); |
384 | err = wait_for_completion_interruptible_timeout( |
385 | x: &kim_gdata->kim_rcvd, |
386 | timeout: msecs_to_jiffies(CMD_RESP_TIME)); |
387 | if (err <= 0) { |
388 | pr_err("response timeout/signaled during fw download " ); |
389 | /* timed out */ |
390 | release_firmware(fw: kim_gdata->fw_entry); |
391 | return err ? -ERESTARTSYS : -ETIMEDOUT; |
392 | } |
393 | reinit_completion(x: &kim_gdata->kim_rcvd); |
394 | break; |
395 | case ACTION_DELAY: /* sleep */ |
396 | pr_info("sleep command in scr" ); |
397 | action_ptr = &(((struct bts_action *)ptr)->data[0]); |
398 | mdelay(((struct bts_action_delay *)action_ptr)->msec); |
399 | break; |
400 | } |
401 | len = |
402 | len - (sizeof(struct bts_action) + |
403 | ((struct bts_action *)ptr)->size); |
404 | ptr = |
405 | ptr + sizeof(struct bts_action) + |
406 | ((struct bts_action *)ptr)->size; |
407 | } |
408 | /* fw download complete */ |
409 | release_firmware(fw: kim_gdata->fw_entry); |
410 | return 0; |
411 | } |
412 | |
413 | /**********************************************************************/ |
414 | /* functions called from ST core */ |
415 | /* called from ST Core, when REG_IN_PROGRESS (registration in progress) |
416 | * can be because of |
417 | * 1. response to read local version |
418 | * 2. during send/recv's of firmware download |
419 | */ |
420 | void st_kim_recv(void *disc_data, const u8 *data, size_t count) |
421 | { |
422 | struct st_data_s *st_gdata = (struct st_data_s *)disc_data; |
423 | struct kim_data_s *kim_gdata = st_gdata->kim_data; |
424 | |
425 | /* |
426 | * proceed to gather all data and distinguish read fw version response |
427 | * from other fw responses when data gathering is complete |
428 | */ |
429 | kim_int_recv(kim_gdata, ptr: data, count); |
430 | return; |
431 | } |
432 | |
433 | /* |
434 | * to signal completion of line discipline installation |
435 | * called from ST Core, upon tty_open |
436 | */ |
437 | void st_kim_complete(void *kim_data) |
438 | { |
439 | struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; |
440 | complete(&kim_gdata->ldisc_installed); |
441 | } |
442 | |
443 | /* |
444 | * st_kim_start - called from ST Core upon 1st registration |
445 | * This involves toggling the chip enable gpio, reading |
446 | * the firmware version from chip, forming the fw file name |
447 | * based on the chip version, requesting the fw, parsing it |
448 | * and perform download(send/recv). |
449 | */ |
450 | long st_kim_start(void *kim_data) |
451 | { |
452 | long err = 0; |
453 | long retry = POR_RETRY_COUNT; |
454 | struct ti_st_plat_data *pdata; |
455 | struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; |
456 | |
457 | pr_info(" %s" , __func__); |
458 | pdata = kim_gdata->kim_pdev->dev.platform_data; |
459 | |
460 | do { |
461 | /* platform specific enabling code here */ |
462 | if (pdata->chip_enable) |
463 | pdata->chip_enable(kim_gdata); |
464 | |
465 | /* Configure BT nShutdown to HIGH state */ |
466 | gpio_set_value_cansleep(gpio: kim_gdata->nshutdown, GPIO_LOW); |
467 | mdelay(5); /* FIXME: a proper toggle */ |
468 | gpio_set_value_cansleep(gpio: kim_gdata->nshutdown, GPIO_HIGH); |
469 | mdelay(100); |
470 | /* re-initialize the completion */ |
471 | reinit_completion(x: &kim_gdata->ldisc_installed); |
472 | /* send notification to UIM */ |
473 | kim_gdata->ldisc_install = 1; |
474 | pr_info("ldisc_install = 1" ); |
475 | sysfs_notify(kobj: &kim_gdata->kim_pdev->dev.kobj, |
476 | NULL, attr: "install" ); |
477 | /* wait for ldisc to be installed */ |
478 | err = wait_for_completion_interruptible_timeout( |
479 | x: &kim_gdata->ldisc_installed, timeout: msecs_to_jiffies(LDISC_TIME)); |
480 | if (!err) { |
481 | /* |
482 | * ldisc installation timeout, |
483 | * flush uart, power cycle BT_EN |
484 | */ |
485 | pr_err("ldisc installation timeout" ); |
486 | err = st_kim_stop(kim_gdata); |
487 | continue; |
488 | } else { |
489 | /* ldisc installed now */ |
490 | pr_info("line discipline installed" ); |
491 | err = download_firmware(kim_gdata); |
492 | if (err != 0) { |
493 | /* |
494 | * ldisc installed but fw download failed, |
495 | * flush uart & power cycle BT_EN |
496 | */ |
497 | pr_err("download firmware failed" ); |
498 | err = st_kim_stop(kim_gdata); |
499 | continue; |
500 | } else { /* on success don't retry */ |
501 | break; |
502 | } |
503 | } |
504 | } while (retry--); |
505 | return err; |
506 | } |
507 | |
508 | /* |
509 | * st_kim_stop - stop communication with chip. |
510 | * This can be called from ST Core/KIM, on the- |
511 | * (a) last un-register when chip need not be powered there-after, |
512 | * (b) upon failure to either install ldisc or download firmware. |
513 | * The function is responsible to (a) notify UIM about un-installation, |
514 | * (b) flush UART if the ldisc was installed. |
515 | * (c) reset BT_EN - pull down nshutdown at the end. |
516 | * (d) invoke platform's chip disabling routine. |
517 | */ |
518 | long st_kim_stop(void *kim_data) |
519 | { |
520 | long err = 0; |
521 | struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; |
522 | struct ti_st_plat_data *pdata = |
523 | kim_gdata->kim_pdev->dev.platform_data; |
524 | struct tty_struct *tty = kim_gdata->core_data->tty; |
525 | |
526 | reinit_completion(x: &kim_gdata->ldisc_installed); |
527 | |
528 | if (tty) { /* can be called before ldisc is installed */ |
529 | /* Flush any pending characters in the driver and discipline. */ |
530 | tty_ldisc_flush(tty); |
531 | tty_driver_flush_buffer(tty); |
532 | } |
533 | |
534 | /* send uninstall notification to UIM */ |
535 | pr_info("ldisc_install = 0" ); |
536 | kim_gdata->ldisc_install = 0; |
537 | sysfs_notify(kobj: &kim_gdata->kim_pdev->dev.kobj, NULL, attr: "install" ); |
538 | |
539 | /* wait for ldisc to be un-installed */ |
540 | err = wait_for_completion_interruptible_timeout( |
541 | x: &kim_gdata->ldisc_installed, timeout: msecs_to_jiffies(LDISC_TIME)); |
542 | if (!err) { /* timeout */ |
543 | pr_err(" timed out waiting for ldisc to be un-installed" ); |
544 | err = -ETIMEDOUT; |
545 | } |
546 | |
547 | /* By default configure BT nShutdown to LOW state */ |
548 | gpio_set_value_cansleep(gpio: kim_gdata->nshutdown, GPIO_LOW); |
549 | mdelay(1); |
550 | gpio_set_value_cansleep(gpio: kim_gdata->nshutdown, GPIO_HIGH); |
551 | mdelay(1); |
552 | gpio_set_value_cansleep(gpio: kim_gdata->nshutdown, GPIO_LOW); |
553 | |
554 | /* platform specific disable */ |
555 | if (pdata->chip_disable) |
556 | pdata->chip_disable(kim_gdata); |
557 | return err; |
558 | } |
559 | |
560 | /**********************************************************************/ |
561 | /* functions called from subsystems */ |
562 | /* called when debugfs entry is read from */ |
563 | |
564 | static int version_show(struct seq_file *s, void *unused) |
565 | { |
566 | struct kim_data_s *kim_gdata = (struct kim_data_s *)s->private; |
567 | seq_printf(m: s, fmt: "%04X %d.%d.%d\n" , kim_gdata->version.full, |
568 | kim_gdata->version.chip, kim_gdata->version.maj_ver, |
569 | kim_gdata->version.min_ver); |
570 | return 0; |
571 | } |
572 | |
573 | static int list_show(struct seq_file *s, void *unused) |
574 | { |
575 | struct kim_data_s *kim_gdata = (struct kim_data_s *)s->private; |
576 | kim_st_list_protocols(kim_gdata->core_data, s); |
577 | return 0; |
578 | } |
579 | |
580 | static ssize_t show_install(struct device *dev, |
581 | struct device_attribute *attr, char *buf) |
582 | { |
583 | struct kim_data_s *kim_data = dev_get_drvdata(dev); |
584 | return sprintf(buf, fmt: "%d\n" , kim_data->ldisc_install); |
585 | } |
586 | |
587 | #ifdef DEBUG |
588 | static ssize_t store_dev_name(struct device *dev, |
589 | struct device_attribute *attr, const char *buf, size_t count) |
590 | { |
591 | struct kim_data_s *kim_data = dev_get_drvdata(dev); |
592 | pr_debug("storing dev name >%s<" , buf); |
593 | strscpy(kim_data->dev_name, buf, sizeof(kim_data->dev_name)); |
594 | pr_debug("stored dev name >%s<" , kim_data->dev_name); |
595 | return count; |
596 | } |
597 | |
598 | static ssize_t store_baud_rate(struct device *dev, |
599 | struct device_attribute *attr, const char *buf, size_t count) |
600 | { |
601 | struct kim_data_s *kim_data = dev_get_drvdata(dev); |
602 | pr_debug("storing baud rate >%s<" , buf); |
603 | sscanf(buf, "%ld" , &kim_data->baud_rate); |
604 | pr_debug("stored baud rate >%ld<" , kim_data->baud_rate); |
605 | return count; |
606 | } |
607 | #endif /* if DEBUG */ |
608 | |
609 | static ssize_t show_dev_name(struct device *dev, |
610 | struct device_attribute *attr, char *buf) |
611 | { |
612 | struct kim_data_s *kim_data = dev_get_drvdata(dev); |
613 | return sprintf(buf, fmt: "%s\n" , kim_data->dev_name); |
614 | } |
615 | |
616 | static ssize_t show_baud_rate(struct device *dev, |
617 | struct device_attribute *attr, char *buf) |
618 | { |
619 | struct kim_data_s *kim_data = dev_get_drvdata(dev); |
620 | return sprintf(buf, fmt: "%d\n" , kim_data->baud_rate); |
621 | } |
622 | |
623 | static ssize_t show_flow_cntrl(struct device *dev, |
624 | struct device_attribute *attr, char *buf) |
625 | { |
626 | struct kim_data_s *kim_data = dev_get_drvdata(dev); |
627 | return sprintf(buf, fmt: "%d\n" , kim_data->flow_cntrl); |
628 | } |
629 | |
630 | /* structures specific for sysfs entries */ |
631 | static struct kobj_attribute ldisc_install = |
632 | __ATTR(install, 0444, (void *)show_install, NULL); |
633 | |
634 | static struct kobj_attribute uart_dev_name = |
635 | #ifdef DEBUG /* TODO: move this to debug-fs if possible */ |
636 | __ATTR(dev_name, 0644, (void *)show_dev_name, (void *)store_dev_name); |
637 | #else |
638 | __ATTR(dev_name, 0444, (void *)show_dev_name, NULL); |
639 | #endif |
640 | |
641 | static struct kobj_attribute uart_baud_rate = |
642 | #ifdef DEBUG /* TODO: move to debugfs */ |
643 | __ATTR(baud_rate, 0644, (void *)show_baud_rate, (void *)store_baud_rate); |
644 | #else |
645 | __ATTR(baud_rate, 0444, (void *)show_baud_rate, NULL); |
646 | #endif |
647 | |
648 | static struct kobj_attribute uart_flow_cntrl = |
649 | __ATTR(flow_cntrl, 0444, (void *)show_flow_cntrl, NULL); |
650 | |
651 | static struct attribute *uim_attrs[] = { |
652 | &ldisc_install.attr, |
653 | &uart_dev_name.attr, |
654 | &uart_baud_rate.attr, |
655 | &uart_flow_cntrl.attr, |
656 | NULL, |
657 | }; |
658 | |
659 | static const struct attribute_group uim_attr_grp = { |
660 | .attrs = uim_attrs, |
661 | }; |
662 | |
663 | /* |
664 | * st_kim_ref - reference the core's data |
665 | * This references the per-ST platform device in the arch/xx/ |
666 | * board-xx.c file. |
667 | * This would enable multiple such platform devices to exist |
668 | * on a given platform |
669 | */ |
670 | void st_kim_ref(struct st_data_s **core_data, int id) |
671 | { |
672 | struct platform_device *pdev; |
673 | struct kim_data_s *kim_gdata; |
674 | /* get kim_gdata reference from platform device */ |
675 | pdev = st_get_plat_device(id); |
676 | if (!pdev) |
677 | goto err; |
678 | kim_gdata = platform_get_drvdata(pdev); |
679 | if (!kim_gdata) |
680 | goto err; |
681 | |
682 | *core_data = kim_gdata->core_data; |
683 | return; |
684 | err: |
685 | *core_data = NULL; |
686 | } |
687 | |
688 | DEFINE_SHOW_ATTRIBUTE(version); |
689 | DEFINE_SHOW_ATTRIBUTE(list); |
690 | |
691 | /**********************************************************************/ |
692 | /* functions called from platform device driver subsystem |
693 | * need to have a relevant platform device entry in the platform's |
694 | * board-*.c file |
695 | */ |
696 | |
697 | static struct dentry *kim_debugfs_dir; |
698 | static int kim_probe(struct platform_device *pdev) |
699 | { |
700 | struct kim_data_s *kim_gdata; |
701 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; |
702 | int err; |
703 | |
704 | if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) { |
705 | /* multiple devices could exist */ |
706 | st_kim_devices[pdev->id] = pdev; |
707 | } else { |
708 | /* platform's sure about existence of 1 device */ |
709 | st_kim_devices[0] = pdev; |
710 | } |
711 | |
712 | kim_gdata = kzalloc(size: sizeof(struct kim_data_s), GFP_KERNEL); |
713 | if (!kim_gdata) { |
714 | pr_err("no mem to allocate" ); |
715 | return -ENOMEM; |
716 | } |
717 | platform_set_drvdata(pdev, data: kim_gdata); |
718 | |
719 | err = st_core_init(&kim_gdata->core_data); |
720 | if (err != 0) { |
721 | pr_err(" ST core init failed" ); |
722 | err = -EIO; |
723 | goto err_core_init; |
724 | } |
725 | /* refer to itself */ |
726 | kim_gdata->core_data->kim_data = kim_gdata; |
727 | |
728 | /* Claim the chip enable nShutdown gpio from the system */ |
729 | kim_gdata->nshutdown = pdata->nshutdown_gpio; |
730 | err = gpio_request(gpio: kim_gdata->nshutdown, label: "kim" ); |
731 | if (unlikely(err)) { |
732 | pr_err(" gpio %d request failed " , kim_gdata->nshutdown); |
733 | goto err_sysfs_group; |
734 | } |
735 | |
736 | /* Configure nShutdown GPIO as output=0 */ |
737 | err = gpio_direction_output(gpio: kim_gdata->nshutdown, value: 0); |
738 | if (unlikely(err)) { |
739 | pr_err(" unable to configure gpio %d" , kim_gdata->nshutdown); |
740 | goto err_sysfs_group; |
741 | } |
742 | /* get reference of pdev for request_firmware */ |
743 | kim_gdata->kim_pdev = pdev; |
744 | init_completion(x: &kim_gdata->kim_rcvd); |
745 | init_completion(x: &kim_gdata->ldisc_installed); |
746 | |
747 | err = sysfs_create_group(kobj: &pdev->dev.kobj, grp: &uim_attr_grp); |
748 | if (err) { |
749 | pr_err("failed to create sysfs entries" ); |
750 | goto err_sysfs_group; |
751 | } |
752 | |
753 | /* copying platform data */ |
754 | strscpy(kim_gdata->dev_name, pdata->dev_name, |
755 | sizeof(kim_gdata->dev_name)); |
756 | kim_gdata->flow_cntrl = pdata->flow_cntrl; |
757 | kim_gdata->baud_rate = pdata->baud_rate; |
758 | pr_info("sysfs entries created\n" ); |
759 | |
760 | kim_debugfs_dir = debugfs_create_dir(name: "ti-st" , NULL); |
761 | |
762 | debugfs_create_file(name: "version" , S_IRUGO, parent: kim_debugfs_dir, |
763 | data: kim_gdata, fops: &version_fops); |
764 | debugfs_create_file(name: "protocols" , S_IRUGO, parent: kim_debugfs_dir, |
765 | data: kim_gdata, fops: &list_fops); |
766 | return 0; |
767 | |
768 | err_sysfs_group: |
769 | st_core_exit(kim_gdata->core_data); |
770 | |
771 | err_core_init: |
772 | kfree(objp: kim_gdata); |
773 | |
774 | return err; |
775 | } |
776 | |
777 | static void kim_remove(struct platform_device *pdev) |
778 | { |
779 | /* free the GPIOs requested */ |
780 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; |
781 | struct kim_data_s *kim_gdata; |
782 | |
783 | kim_gdata = platform_get_drvdata(pdev); |
784 | |
785 | /* |
786 | * Free the Bluetooth/FM/GPIO |
787 | * nShutdown gpio from the system |
788 | */ |
789 | gpio_free(gpio: pdata->nshutdown_gpio); |
790 | pr_info("nshutdown GPIO Freed" ); |
791 | |
792 | debugfs_remove_recursive(dentry: kim_debugfs_dir); |
793 | sysfs_remove_group(kobj: &pdev->dev.kobj, grp: &uim_attr_grp); |
794 | pr_info("sysfs entries removed" ); |
795 | |
796 | kim_gdata->kim_pdev = NULL; |
797 | st_core_exit(kim_gdata->core_data); |
798 | |
799 | kfree(objp: kim_gdata); |
800 | kim_gdata = NULL; |
801 | } |
802 | |
803 | static int kim_suspend(struct platform_device *pdev, pm_message_t state) |
804 | { |
805 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; |
806 | |
807 | if (pdata->suspend) |
808 | return pdata->suspend(pdev, state); |
809 | |
810 | return 0; |
811 | } |
812 | |
813 | static int kim_resume(struct platform_device *pdev) |
814 | { |
815 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; |
816 | |
817 | if (pdata->resume) |
818 | return pdata->resume(pdev); |
819 | |
820 | return 0; |
821 | } |
822 | |
823 | /**********************************************************************/ |
824 | /* entry point for ST KIM module, called in from ST Core */ |
825 | static struct platform_driver kim_platform_driver = { |
826 | .probe = kim_probe, |
827 | .remove_new = kim_remove, |
828 | .suspend = kim_suspend, |
829 | .resume = kim_resume, |
830 | .driver = { |
831 | .name = "kim" , |
832 | }, |
833 | }; |
834 | |
835 | module_platform_driver(kim_platform_driver); |
836 | |
837 | MODULE_AUTHOR("Pavan Savoy <pavan_savoy@ti.com>" ); |
838 | MODULE_DESCRIPTION("Shared Transport Driver for TI BT/FM/GPS combo chips " ); |
839 | MODULE_LICENSE("GPL" ); |
840 | |