diff options
Diffstat (limited to 'drivers/misc/ti-st/st_kim.c')
-rw-r--r-- | drivers/misc/ti-st/st_kim.c | 491 |
1 files changed, 242 insertions, 249 deletions
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 73b6c8b0e869..9ee4c788aa69 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c | |||
@@ -30,50 +30,12 @@ | |||
30 | #include <linux/debugfs.h> | 30 | #include <linux/debugfs.h> |
31 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <linux/rfkill.h> | 33 | #include <linux/tty.h> |
34 | |||
35 | /* understand BT events for fw response */ | ||
36 | #include <net/bluetooth/bluetooth.h> | ||
37 | #include <net/bluetooth/hci_core.h> | ||
38 | #include <net/bluetooth/hci.h> | ||
39 | 34 | ||
35 | #include <linux/skbuff.h> | ||
40 | #include <linux/ti_wilink_st.h> | 36 | #include <linux/ti_wilink_st.h> |
41 | 37 | ||
42 | 38 | ||
43 | static int kim_probe(struct platform_device *pdev); | ||
44 | static int kim_remove(struct platform_device *pdev); | ||
45 | |||
46 | /* KIM platform device driver structure */ | ||
47 | static struct platform_driver kim_platform_driver = { | ||
48 | .probe = kim_probe, | ||
49 | .remove = kim_remove, | ||
50 | /* TODO: ST driver power management during suspend/resume ? | ||
51 | */ | ||
52 | #if 0 | ||
53 | .suspend = kim_suspend, | ||
54 | .resume = kim_resume, | ||
55 | #endif | ||
56 | .driver = { | ||
57 | .name = "kim", | ||
58 | .owner = THIS_MODULE, | ||
59 | }, | ||
60 | }; | ||
61 | |||
62 | static int kim_toggle_radio(void*, bool); | ||
63 | static const struct rfkill_ops kim_rfkill_ops = { | ||
64 | .set_block = kim_toggle_radio, | ||
65 | }; | ||
66 | |||
67 | /* strings to be used for rfkill entries and by | ||
68 | * ST Core to be used for sysfs debug entry | ||
69 | */ | ||
70 | #define PROTO_ENTRY(type, name) name | ||
71 | const unsigned char *protocol_names[] = { | ||
72 | PROTO_ENTRY(ST_BT, "Bluetooth"), | ||
73 | PROTO_ENTRY(ST_FM, "FM"), | ||
74 | PROTO_ENTRY(ST_GPS, "GPS"), | ||
75 | }; | ||
76 | |||
77 | #define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */ | 39 | #define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */ |
78 | static struct platform_device *st_kim_devices[MAX_ST_DEVICES]; | 40 | static struct platform_device *st_kim_devices[MAX_ST_DEVICES]; |
79 | 41 | ||
@@ -134,7 +96,7 @@ static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len) | |||
134 | /* Packet header has non-zero payload length and | 96 | /* Packet header has non-zero payload length and |
135 | * we have enough space in created skb. Lets read | 97 | * we have enough space in created skb. Lets read |
136 | * payload data */ | 98 | * payload data */ |
137 | kim_gdata->rx_state = ST_BT_W4_DATA; | 99 | kim_gdata->rx_state = ST_W4_DATA; |
138 | kim_gdata->rx_count = len; | 100 | kim_gdata->rx_count = len; |
139 | return len; | 101 | return len; |
140 | } | 102 | } |
@@ -158,8 +120,8 @@ void kim_int_recv(struct kim_data_s *kim_gdata, | |||
158 | const unsigned char *data, long count) | 120 | const unsigned char *data, long count) |
159 | { | 121 | { |
160 | const unsigned char *ptr; | 122 | const unsigned char *ptr; |
161 | struct hci_event_hdr *eh; | ||
162 | int len = 0, type = 0; | 123 | int len = 0, type = 0; |
124 | unsigned char *plen; | ||
163 | 125 | ||
164 | pr_debug("%s", __func__); | 126 | pr_debug("%s", __func__); |
165 | /* Decode received bytes here */ | 127 | /* Decode received bytes here */ |
@@ -183,29 +145,27 @@ void kim_int_recv(struct kim_data_s *kim_gdata, | |||
183 | /* Check ST RX state machine , where are we? */ | 145 | /* Check ST RX state machine , where are we? */ |
184 | switch (kim_gdata->rx_state) { | 146 | switch (kim_gdata->rx_state) { |
185 | /* Waiting for complete packet ? */ | 147 | /* Waiting for complete packet ? */ |
186 | case ST_BT_W4_DATA: | 148 | case ST_W4_DATA: |
187 | pr_debug("Complete pkt received"); | 149 | pr_debug("Complete pkt received"); |
188 | validate_firmware_response(kim_gdata); | 150 | validate_firmware_response(kim_gdata); |
189 | kim_gdata->rx_state = ST_W4_PACKET_TYPE; | 151 | kim_gdata->rx_state = ST_W4_PACKET_TYPE; |
190 | kim_gdata->rx_skb = NULL; | 152 | kim_gdata->rx_skb = NULL; |
191 | continue; | 153 | continue; |
192 | /* Waiting for Bluetooth event header ? */ | 154 | /* Waiting for Bluetooth event header ? */ |
193 | case ST_BT_W4_EVENT_HDR: | 155 | case ST_W4_HEADER: |
194 | eh = (struct hci_event_hdr *)kim_gdata-> | 156 | plen = |
195 | rx_skb->data; | 157 | (unsigned char *)&kim_gdata->rx_skb->data[1]; |
196 | pr_debug("Event header: evt 0x%2.2x" | 158 | pr_debug("event hdr: plen 0x%02x\n", *plen); |
197 | "plen %d", eh->evt, eh->plen); | 159 | kim_check_data_len(kim_gdata, *plen); |
198 | kim_check_data_len(kim_gdata, eh->plen); | ||
199 | continue; | 160 | continue; |
200 | } /* end of switch */ | 161 | } /* end of switch */ |
201 | } /* end of if rx_state */ | 162 | } /* end of if rx_state */ |
202 | switch (*ptr) { | 163 | switch (*ptr) { |
203 | /* Bluetooth event packet? */ | 164 | /* Bluetooth event packet? */ |
204 | case HCI_EVENT_PKT: | 165 | case 0x04: |
205 | pr_info("Event packet"); | 166 | kim_gdata->rx_state = ST_W4_HEADER; |
206 | kim_gdata->rx_state = ST_BT_W4_EVENT_HDR; | 167 | kim_gdata->rx_count = 2; |
207 | kim_gdata->rx_count = HCI_EVENT_HDR_SIZE; | 168 | type = *ptr; |
208 | type = HCI_EVENT_PKT; | ||
209 | break; | 169 | break; |
210 | default: | 170 | default: |
211 | pr_info("unknown packet"); | 171 | pr_info("unknown packet"); |
@@ -216,16 +176,18 @@ void kim_int_recv(struct kim_data_s *kim_gdata, | |||
216 | ptr++; | 176 | ptr++; |
217 | count--; | 177 | count--; |
218 | kim_gdata->rx_skb = | 178 | kim_gdata->rx_skb = |
219 | bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); | 179 | alloc_skb(1024+8, GFP_ATOMIC); |
220 | if (!kim_gdata->rx_skb) { | 180 | if (!kim_gdata->rx_skb) { |
221 | pr_err("can't allocate mem for new packet"); | 181 | pr_err("can't allocate mem for new packet"); |
222 | kim_gdata->rx_state = ST_W4_PACKET_TYPE; | 182 | kim_gdata->rx_state = ST_W4_PACKET_TYPE; |
223 | kim_gdata->rx_count = 0; | 183 | kim_gdata->rx_count = 0; |
224 | return; | 184 | return; |
225 | } | 185 | } |
226 | bt_cb(kim_gdata->rx_skb)->pkt_type = type; | 186 | skb_reserve(kim_gdata->rx_skb, 8); |
187 | kim_gdata->rx_skb->cb[0] = 4; | ||
188 | kim_gdata->rx_skb->cb[1] = 0; | ||
189 | |||
227 | } | 190 | } |
228 | pr_info("done %s", __func__); | ||
229 | return; | 191 | return; |
230 | } | 192 | } |
231 | 193 | ||
@@ -239,13 +201,13 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) | |||
239 | INIT_COMPLETION(kim_gdata->kim_rcvd); | 201 | INIT_COMPLETION(kim_gdata->kim_rcvd); |
240 | if (4 != st_int_write(kim_gdata->core_data, read_ver_cmd, 4)) { | 202 | if (4 != st_int_write(kim_gdata->core_data, read_ver_cmd, 4)) { |
241 | pr_err("kim: couldn't write 4 bytes"); | 203 | pr_err("kim: couldn't write 4 bytes"); |
242 | return -1; | 204 | return -EIO; |
243 | } | 205 | } |
244 | 206 | ||
245 | if (!wait_for_completion_timeout | 207 | if (!wait_for_completion_timeout |
246 | (&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) { | 208 | (&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) { |
247 | pr_err(" waiting for ver info- timed out "); | 209 | pr_err(" waiting for ver info- timed out "); |
248 | return -1; | 210 | return -ETIMEDOUT; |
249 | } | 211 | } |
250 | 212 | ||
251 | version = | 213 | version = |
@@ -270,6 +232,26 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) | |||
270 | return 0; | 232 | return 0; |
271 | } | 233 | } |
272 | 234 | ||
235 | void skip_change_remote_baud(unsigned char **ptr, long *len) | ||
236 | { | ||
237 | unsigned char *nxt_action, *cur_action; | ||
238 | cur_action = *ptr; | ||
239 | |||
240 | nxt_action = cur_action + sizeof(struct bts_action) + | ||
241 | ((struct bts_action *) cur_action)->size; | ||
242 | |||
243 | if (((struct bts_action *) nxt_action)->type != ACTION_WAIT_EVENT) { | ||
244 | pr_err("invalid action after change remote baud command"); | ||
245 | } else { | ||
246 | *ptr = *ptr + sizeof(struct bts_action) + | ||
247 | ((struct bts_action *)nxt_action)->size; | ||
248 | *len = *len - (sizeof(struct bts_action) + | ||
249 | ((struct bts_action *)nxt_action)->size); | ||
250 | /* warn user on not commenting these in firmware */ | ||
251 | pr_warn("skipping the wait event of change remote baud"); | ||
252 | } | ||
253 | } | ||
254 | |||
273 | /** | 255 | /** |
274 | * download_firmware - | 256 | * download_firmware - |
275 | * internal function which parses through the .bts firmware | 257 | * internal function which parses through the .bts firmware |
@@ -282,6 +264,9 @@ static long download_firmware(struct kim_data_s *kim_gdata) | |||
282 | unsigned char *ptr = NULL; | 264 | unsigned char *ptr = NULL; |
283 | unsigned char *action_ptr = NULL; | 265 | unsigned char *action_ptr = NULL; |
284 | unsigned char bts_scr_name[30] = { 0 }; /* 30 char long bts scr name? */ | 266 | unsigned char bts_scr_name[30] = { 0 }; /* 30 char long bts scr name? */ |
267 | int wr_room_space; | ||
268 | int cmd_size; | ||
269 | unsigned long timeout; | ||
285 | 270 | ||
286 | err = read_local_version(kim_gdata, bts_scr_name); | 271 | err = read_local_version(kim_gdata, bts_scr_name); |
287 | if (err != 0) { | 272 | if (err != 0) { |
@@ -295,7 +280,7 @@ static long download_firmware(struct kim_data_s *kim_gdata) | |||
295 | (kim_gdata->fw_entry->size == 0))) { | 280 | (kim_gdata->fw_entry->size == 0))) { |
296 | pr_err(" request_firmware failed(errno %ld) for %s", err, | 281 | pr_err(" request_firmware failed(errno %ld) for %s", err, |
297 | bts_scr_name); | 282 | bts_scr_name); |
298 | return -1; | 283 | return -EINVAL; |
299 | } | 284 | } |
300 | ptr = (void *)kim_gdata->fw_entry->data; | 285 | ptr = (void *)kim_gdata->fw_entry->data; |
301 | len = kim_gdata->fw_entry->size; | 286 | len = kim_gdata->fw_entry->size; |
@@ -318,29 +303,72 @@ static long download_firmware(struct kim_data_s *kim_gdata) | |||
318 | 0xFF36)) { | 303 | 0xFF36)) { |
319 | /* ignore remote change | 304 | /* ignore remote change |
320 | * baud rate HCI VS command */ | 305 | * baud rate HCI VS command */ |
321 | pr_err | 306 | pr_warn("change remote baud" |
322 | (" change remote baud" | ||
323 | " rate command in firmware"); | 307 | " rate command in firmware"); |
308 | skip_change_remote_baud(&ptr, &len); | ||
324 | break; | 309 | break; |
325 | } | 310 | } |
311 | /* | ||
312 | * Make sure we have enough free space in uart | ||
313 | * tx buffer to write current firmware command | ||
314 | */ | ||
315 | cmd_size = ((struct bts_action *)ptr)->size; | ||
316 | timeout = jiffies + msecs_to_jiffies(CMD_WR_TIME); | ||
317 | do { | ||
318 | wr_room_space = | ||
319 | st_get_uart_wr_room(kim_gdata->core_data); | ||
320 | if (wr_room_space < 0) { | ||
321 | pr_err("Unable to get free " | ||
322 | "space info from uart tx buffer"); | ||
323 | release_firmware(kim_gdata->fw_entry); | ||
324 | return wr_room_space; | ||
325 | } | ||
326 | mdelay(1); /* wait 1ms before checking room */ | ||
327 | } while ((wr_room_space < cmd_size) && | ||
328 | time_before(jiffies, timeout)); | ||
329 | |||
330 | /* Timeout happened ? */ | ||
331 | if (time_after_eq(jiffies, timeout)) { | ||
332 | pr_err("Timeout while waiting for free " | ||
333 | "free space in uart tx buffer"); | ||
334 | release_firmware(kim_gdata->fw_entry); | ||
335 | return -ETIMEDOUT; | ||
336 | } | ||
326 | 337 | ||
327 | INIT_COMPLETION(kim_gdata->kim_rcvd); | 338 | /* |
339 | * Free space found in uart buffer, call st_int_write | ||
340 | * to send current firmware command to the uart tx | ||
341 | * buffer. | ||
342 | */ | ||
328 | err = st_int_write(kim_gdata->core_data, | 343 | err = st_int_write(kim_gdata->core_data, |
329 | ((struct bts_action_send *)action_ptr)->data, | 344 | ((struct bts_action_send *)action_ptr)->data, |
330 | ((struct bts_action *)ptr)->size); | 345 | ((struct bts_action *)ptr)->size); |
331 | if (unlikely(err < 0)) { | 346 | if (unlikely(err < 0)) { |
332 | release_firmware(kim_gdata->fw_entry); | 347 | release_firmware(kim_gdata->fw_entry); |
333 | return -1; | 348 | return err; |
334 | } | 349 | } |
350 | /* | ||
351 | * Check number of bytes written to the uart tx buffer | ||
352 | * and requested command write size | ||
353 | */ | ||
354 | if (err != cmd_size) { | ||
355 | pr_err("Number of bytes written to uart " | ||
356 | "tx buffer are not matching with " | ||
357 | "requested cmd write size"); | ||
358 | release_firmware(kim_gdata->fw_entry); | ||
359 | return -EIO; | ||
360 | } | ||
361 | break; | ||
362 | case ACTION_WAIT_EVENT: /* wait */ | ||
335 | if (!wait_for_completion_timeout | 363 | if (!wait_for_completion_timeout |
336 | (&kim_gdata->kim_rcvd, | 364 | (&kim_gdata->kim_rcvd, |
337 | msecs_to_jiffies(CMD_RESP_TIME))) { | 365 | msecs_to_jiffies(CMD_RESP_TIME))) { |
338 | pr_err | 366 | pr_err("response timeout during fw download "); |
339 | (" response timeout during fw download "); | ||
340 | /* timed out */ | 367 | /* timed out */ |
341 | release_firmware(kim_gdata->fw_entry); | 368 | release_firmware(kim_gdata->fw_entry); |
342 | return -1; | 369 | return -ETIMEDOUT; |
343 | } | 370 | } |
371 | INIT_COMPLETION(kim_gdata->kim_rcvd); | ||
344 | break; | 372 | break; |
345 | case ACTION_DELAY: /* sleep */ | 373 | case ACTION_DELAY: /* sleep */ |
346 | pr_info("sleep command in scr"); | 374 | pr_info("sleep command in scr"); |
@@ -362,50 +390,6 @@ static long download_firmware(struct kim_data_s *kim_gdata) | |||
362 | 390 | ||
363 | /**********************************************************************/ | 391 | /**********************************************************************/ |
364 | /* functions called from ST core */ | 392 | /* functions called from ST core */ |
365 | /* function to toggle the GPIO | ||
366 | * needs to know whether the GPIO is active high or active low | ||
367 | */ | ||
368 | void st_kim_chip_toggle(enum proto_type type, enum kim_gpio_state state) | ||
369 | { | ||
370 | struct platform_device *kim_pdev; | ||
371 | struct kim_data_s *kim_gdata; | ||
372 | pr_info(" %s ", __func__); | ||
373 | |||
374 | kim_pdev = st_get_plat_device(0); | ||
375 | kim_gdata = dev_get_drvdata(&kim_pdev->dev); | ||
376 | |||
377 | if (kim_gdata->gpios[type] == -1) { | ||
378 | pr_info(" gpio not requested for protocol %s", | ||
379 | protocol_names[type]); | ||
380 | return; | ||
381 | } | ||
382 | switch (type) { | ||
383 | case ST_BT: | ||
384 | /*Do Nothing */ | ||
385 | break; | ||
386 | |||
387 | case ST_FM: | ||
388 | if (state == KIM_GPIO_ACTIVE) | ||
389 | gpio_set_value(kim_gdata->gpios[ST_FM], GPIO_LOW); | ||
390 | else | ||
391 | gpio_set_value(kim_gdata->gpios[ST_FM], GPIO_HIGH); | ||
392 | break; | ||
393 | |||
394 | case ST_GPS: | ||
395 | if (state == KIM_GPIO_ACTIVE) | ||
396 | gpio_set_value(kim_gdata->gpios[ST_GPS], GPIO_HIGH); | ||
397 | else | ||
398 | gpio_set_value(kim_gdata->gpios[ST_GPS], GPIO_LOW); | ||
399 | break; | ||
400 | |||
401 | case ST_MAX: | ||
402 | default: | ||
403 | break; | ||
404 | } | ||
405 | |||
406 | return; | ||
407 | } | ||
408 | |||
409 | /* called from ST Core, when REG_IN_PROGRESS (registration in progress) | 393 | /* called from ST Core, when REG_IN_PROGRESS (registration in progress) |
410 | * can be because of | 394 | * can be because of |
411 | * 1. response to read local version | 395 | * 1. response to read local version |
@@ -416,7 +400,6 @@ void st_kim_recv(void *disc_data, const unsigned char *data, long count) | |||
416 | struct st_data_s *st_gdata = (struct st_data_s *)disc_data; | 400 | struct st_data_s *st_gdata = (struct st_data_s *)disc_data; |
417 | struct kim_data_s *kim_gdata = st_gdata->kim_data; | 401 | struct kim_data_s *kim_gdata = st_gdata->kim_data; |
418 | 402 | ||
419 | pr_info(" %s ", __func__); | ||
420 | /* copy to local buffer */ | 403 | /* copy to local buffer */ |
421 | if (unlikely(data[4] == 0x01 && data[5] == 0x10 && data[0] == 0x04)) { | 404 | if (unlikely(data[4] == 0x01 && data[5] == 0x10 && data[0] == 0x04)) { |
422 | /* must be the read_ver_cmd */ | 405 | /* must be the read_ver_cmd */ |
@@ -455,35 +438,28 @@ long st_kim_start(void *kim_data) | |||
455 | pr_info(" %s", __func__); | 438 | pr_info(" %s", __func__); |
456 | 439 | ||
457 | do { | 440 | do { |
458 | /* TODO: this is only because rfkill sub-system | ||
459 | * doesn't send events to user-space if the state | ||
460 | * isn't changed | ||
461 | */ | ||
462 | rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 1); | ||
463 | /* Configure BT nShutdown to HIGH state */ | 441 | /* Configure BT nShutdown to HIGH state */ |
464 | gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_LOW); | 442 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); |
465 | mdelay(5); /* FIXME: a proper toggle */ | 443 | mdelay(5); /* FIXME: a proper toggle */ |
466 | gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_HIGH); | 444 | gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); |
467 | mdelay(100); | 445 | mdelay(100); |
468 | /* re-initialize the completion */ | 446 | /* re-initialize the completion */ |
469 | INIT_COMPLETION(kim_gdata->ldisc_installed); | 447 | INIT_COMPLETION(kim_gdata->ldisc_installed); |
470 | #if 0 /* older way of signalling user-space UIM */ | 448 | /* send notification to UIM */ |
471 | /* send signal to UIM */ | 449 | kim_gdata->ldisc_install = 1; |
472 | err = kill_pid(find_get_pid(kim_gdata->uim_pid), SIGUSR2, 0); | 450 | pr_info("ldisc_install = 1"); |
473 | if (err != 0) { | 451 | sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, |
474 | pr_info(" sending SIGUSR2 to uim failed %ld", err); | 452 | NULL, "install"); |
475 | err = -1; | ||
476 | continue; | ||
477 | } | ||
478 | #endif | ||
479 | /* unblock and send event to UIM via /dev/rfkill */ | ||
480 | rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 0); | ||
481 | /* wait for ldisc to be installed */ | 453 | /* wait for ldisc to be installed */ |
482 | err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, | 454 | err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, |
483 | msecs_to_jiffies(LDISC_TIME)); | 455 | msecs_to_jiffies(LDISC_TIME)); |
484 | if (!err) { /* timeout */ | 456 | if (!err) { /* timeout */ |
485 | pr_err("line disc installation timed out "); | 457 | pr_err("line disc installation timed out "); |
486 | err = -1; | 458 | kim_gdata->ldisc_install = 0; |
459 | pr_info("ldisc_install = 0"); | ||
460 | sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, | ||
461 | NULL, "install"); | ||
462 | err = -ETIMEDOUT; | ||
487 | continue; | 463 | continue; |
488 | } else { | 464 | } else { |
489 | /* ldisc installed now */ | 465 | /* ldisc installed now */ |
@@ -491,6 +467,10 @@ long st_kim_start(void *kim_data) | |||
491 | err = download_firmware(kim_gdata); | 467 | err = download_firmware(kim_gdata); |
492 | if (err != 0) { | 468 | if (err != 0) { |
493 | pr_err("download firmware failed"); | 469 | pr_err("download firmware failed"); |
470 | kim_gdata->ldisc_install = 0; | ||
471 | pr_info("ldisc_install = 0"); | ||
472 | sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, | ||
473 | NULL, "install"); | ||
494 | continue; | 474 | continue; |
495 | } else { /* on success don't retry */ | 475 | } else { /* on success don't retry */ |
496 | break; | 476 | break; |
@@ -510,31 +490,30 @@ long st_kim_stop(void *kim_data) | |||
510 | struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; | 490 | struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; |
511 | 491 | ||
512 | INIT_COMPLETION(kim_gdata->ldisc_installed); | 492 | INIT_COMPLETION(kim_gdata->ldisc_installed); |
513 | #if 0 /* older way of signalling user-space UIM */ | 493 | |
514 | /* send signal to UIM */ | 494 | /* Flush any pending characters in the driver and discipline. */ |
515 | err = kill_pid(find_get_pid(kim_gdata->uim_pid), SIGUSR2, 1); | 495 | tty_ldisc_flush(kim_gdata->core_data->tty); |
516 | if (err != 0) { | 496 | tty_driver_flush_buffer(kim_gdata->core_data->tty); |
517 | pr_err("sending SIGUSR2 to uim failed %ld", err); | 497 | |
518 | return -1; | 498 | /* send uninstall notification to UIM */ |
519 | } | 499 | pr_info("ldisc_install = 0"); |
520 | #endif | 500 | kim_gdata->ldisc_install = 0; |
521 | /* set BT rfkill to be blocked */ | 501 | sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install"); |
522 | err = rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 1); | ||
523 | 502 | ||
524 | /* wait for ldisc to be un-installed */ | 503 | /* wait for ldisc to be un-installed */ |
525 | err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, | 504 | err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, |
526 | msecs_to_jiffies(LDISC_TIME)); | 505 | msecs_to_jiffies(LDISC_TIME)); |
527 | if (!err) { /* timeout */ | 506 | if (!err) { /* timeout */ |
528 | pr_err(" timed out waiting for ldisc to be un-installed"); | 507 | pr_err(" timed out waiting for ldisc to be un-installed"); |
529 | return -1; | 508 | return -ETIMEDOUT; |
530 | } | 509 | } |
531 | 510 | ||
532 | /* By default configure BT nShutdown to LOW state */ | 511 | /* By default configure BT nShutdown to LOW state */ |
533 | gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_LOW); | 512 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); |
534 | mdelay(1); | 513 | mdelay(1); |
535 | gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_HIGH); | 514 | gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); |
536 | mdelay(1); | 515 | mdelay(1); |
537 | gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_LOW); | 516 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); |
538 | return err; | 517 | return err; |
539 | } | 518 | } |
540 | 519 | ||
@@ -558,33 +537,59 @@ static int show_list(struct seq_file *s, void *unused) | |||
558 | return 0; | 537 | return 0; |
559 | } | 538 | } |
560 | 539 | ||
561 | /* function called from rfkill subsystem, when someone from | 540 | static ssize_t show_install(struct device *dev, |
562 | * user space would write 0/1 on the sysfs entry | 541 | struct device_attribute *attr, char *buf) |
563 | * /sys/class/rfkill/rfkill0,1,3/state | ||
564 | */ | ||
565 | static int kim_toggle_radio(void *data, bool blocked) | ||
566 | { | 542 | { |
567 | enum proto_type type = *((enum proto_type *)data); | 543 | struct kim_data_s *kim_data = dev_get_drvdata(dev); |
568 | pr_debug(" %s: %d ", __func__, type); | 544 | return sprintf(buf, "%d\n", kim_data->ldisc_install); |
569 | |||
570 | switch (type) { | ||
571 | case ST_BT: | ||
572 | /* do nothing */ | ||
573 | break; | ||
574 | case ST_FM: | ||
575 | case ST_GPS: | ||
576 | if (blocked) | ||
577 | st_kim_chip_toggle(type, KIM_GPIO_INACTIVE); | ||
578 | else | ||
579 | st_kim_chip_toggle(type, KIM_GPIO_ACTIVE); | ||
580 | break; | ||
581 | case ST_MAX: | ||
582 | pr_err(" wrong proto type "); | ||
583 | break; | ||
584 | } | ||
585 | return 0; | ||
586 | } | 545 | } |
587 | 546 | ||
547 | static ssize_t show_dev_name(struct device *dev, | ||
548 | struct device_attribute *attr, char *buf) | ||
549 | { | ||
550 | struct kim_data_s *kim_data = dev_get_drvdata(dev); | ||
551 | return sprintf(buf, "%s\n", kim_data->dev_name); | ||
552 | } | ||
553 | |||
554 | static ssize_t show_baud_rate(struct device *dev, | ||
555 | struct device_attribute *attr, char *buf) | ||
556 | { | ||
557 | struct kim_data_s *kim_data = dev_get_drvdata(dev); | ||
558 | return sprintf(buf, "%ld\n", kim_data->baud_rate); | ||
559 | } | ||
560 | |||
561 | static ssize_t show_flow_cntrl(struct device *dev, | ||
562 | struct device_attribute *attr, char *buf) | ||
563 | { | ||
564 | struct kim_data_s *kim_data = dev_get_drvdata(dev); | ||
565 | return sprintf(buf, "%d\n", kim_data->flow_cntrl); | ||
566 | } | ||
567 | |||
568 | /* structures specific for sysfs entries */ | ||
569 | static struct kobj_attribute ldisc_install = | ||
570 | __ATTR(install, 0444, (void *)show_install, NULL); | ||
571 | |||
572 | static struct kobj_attribute uart_dev_name = | ||
573 | __ATTR(dev_name, 0444, (void *)show_dev_name, NULL); | ||
574 | |||
575 | static struct kobj_attribute uart_baud_rate = | ||
576 | __ATTR(baud_rate, 0444, (void *)show_baud_rate, NULL); | ||
577 | |||
578 | static struct kobj_attribute uart_flow_cntrl = | ||
579 | __ATTR(flow_cntrl, 0444, (void *)show_flow_cntrl, NULL); | ||
580 | |||
581 | static struct attribute *uim_attrs[] = { | ||
582 | &ldisc_install.attr, | ||
583 | &uart_dev_name.attr, | ||
584 | &uart_baud_rate.attr, | ||
585 | &uart_flow_cntrl.attr, | ||
586 | NULL, | ||
587 | }; | ||
588 | |||
589 | static struct attribute_group uim_attr_grp = { | ||
590 | .attrs = uim_attrs, | ||
591 | }; | ||
592 | |||
588 | /** | 593 | /** |
589 | * st_kim_ref - reference the core's data | 594 | * st_kim_ref - reference the core's data |
590 | * This references the per-ST platform device in the arch/xx/ | 595 | * This references the per-ST platform device in the arch/xx/ |
@@ -637,9 +642,8 @@ struct dentry *kim_debugfs_dir; | |||
637 | static int kim_probe(struct platform_device *pdev) | 642 | static int kim_probe(struct platform_device *pdev) |
638 | { | 643 | { |
639 | long status; | 644 | long status; |
640 | long proto; | ||
641 | long *gpios = pdev->dev.platform_data; | ||
642 | struct kim_data_s *kim_gdata; | 645 | struct kim_data_s *kim_gdata; |
646 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | ||
643 | 647 | ||
644 | if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) { | 648 | if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) { |
645 | /* multiple devices could exist */ | 649 | /* multiple devices could exist */ |
@@ -659,44 +663,24 @@ static int kim_probe(struct platform_device *pdev) | |||
659 | status = st_core_init(&kim_gdata->core_data); | 663 | status = st_core_init(&kim_gdata->core_data); |
660 | if (status != 0) { | 664 | if (status != 0) { |
661 | pr_err(" ST core init failed"); | 665 | pr_err(" ST core init failed"); |
662 | return -1; | 666 | return -EIO; |
663 | } | 667 | } |
664 | /* refer to itself */ | 668 | /* refer to itself */ |
665 | kim_gdata->core_data->kim_data = kim_gdata; | 669 | kim_gdata->core_data->kim_data = kim_gdata; |
666 | 670 | ||
667 | for (proto = 0; proto < ST_MAX; proto++) { | 671 | /* Claim the chip enable nShutdown gpio from the system */ |
668 | kim_gdata->gpios[proto] = gpios[proto]; | 672 | kim_gdata->nshutdown = pdata->nshutdown_gpio; |
669 | pr_info(" %ld gpio to be requested", gpios[proto]); | 673 | status = gpio_request(kim_gdata->nshutdown, "kim"); |
674 | if (unlikely(status)) { | ||
675 | pr_err(" gpio %ld request failed ", kim_gdata->nshutdown); | ||
676 | return status; | ||
670 | } | 677 | } |
671 | 678 | ||
672 | for (proto = 0; (proto < ST_MAX) && (gpios[proto] != -1); proto++) { | 679 | /* Configure nShutdown GPIO as output=0 */ |
673 | /* Claim the Bluetooth/FM/GPIO | 680 | status = gpio_direction_output(kim_gdata->nshutdown, 0); |
674 | * nShutdown gpio from the system | 681 | if (unlikely(status)) { |
675 | */ | 682 | pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown); |
676 | status = gpio_request(gpios[proto], "kim"); | 683 | return status; |
677 | if (unlikely(status)) { | ||
678 | pr_err(" gpio %ld request failed ", gpios[proto]); | ||
679 | proto -= 1; | ||
680 | while (proto >= 0) { | ||
681 | if (gpios[proto] != -1) | ||
682 | gpio_free(gpios[proto]); | ||
683 | } | ||
684 | return status; | ||
685 | } | ||
686 | |||
687 | /* Configure nShutdown GPIO as output=0 */ | ||
688 | status = | ||
689 | gpio_direction_output(gpios[proto], 0); | ||
690 | if (unlikely(status)) { | ||
691 | pr_err(" unable to configure gpio %ld", | ||
692 | gpios[proto]); | ||
693 | proto -= 1; | ||
694 | while (proto >= 0) { | ||
695 | if (gpios[proto] != -1) | ||
696 | gpio_free(gpios[proto]); | ||
697 | } | ||
698 | return status; | ||
699 | } | ||
700 | } | 684 | } |
701 | /* get reference of pdev for request_firmware | 685 | /* get reference of pdev for request_firmware |
702 | */ | 686 | */ |
@@ -704,34 +688,23 @@ static int kim_probe(struct platform_device *pdev) | |||
704 | init_completion(&kim_gdata->kim_rcvd); | 688 | init_completion(&kim_gdata->kim_rcvd); |
705 | init_completion(&kim_gdata->ldisc_installed); | 689 | init_completion(&kim_gdata->ldisc_installed); |
706 | 690 | ||
707 | for (proto = 0; (proto < ST_MAX) && (gpios[proto] != -1); proto++) { | 691 | status = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp); |
708 | /* TODO: should all types be rfkill_type_bt ? */ | 692 | if (status) { |
709 | kim_gdata->rf_protos[proto] = proto; | 693 | pr_err("failed to create sysfs entries"); |
710 | kim_gdata->rfkill[proto] = rfkill_alloc(protocol_names[proto], | 694 | return status; |
711 | &pdev->dev, RFKILL_TYPE_BLUETOOTH, | ||
712 | &kim_rfkill_ops, &kim_gdata->rf_protos[proto]); | ||
713 | if (kim_gdata->rfkill[proto] == NULL) { | ||
714 | pr_err("cannot create rfkill entry for gpio %ld", | ||
715 | gpios[proto]); | ||
716 | continue; | ||
717 | } | ||
718 | /* block upon creation */ | ||
719 | rfkill_init_sw_state(kim_gdata->rfkill[proto], 1); | ||
720 | status = rfkill_register(kim_gdata->rfkill[proto]); | ||
721 | if (unlikely(status)) { | ||
722 | pr_err("rfkill registration failed for gpio %ld", | ||
723 | gpios[proto]); | ||
724 | rfkill_unregister(kim_gdata->rfkill[proto]); | ||
725 | continue; | ||
726 | } | ||
727 | pr_info("rfkill entry created for %ld", gpios[proto]); | ||
728 | } | 695 | } |
729 | 696 | ||
697 | /* copying platform data */ | ||
698 | strncpy(kim_gdata->dev_name, pdata->dev_name, UART_DEV_NAME_LEN); | ||
699 | kim_gdata->flow_cntrl = pdata->flow_cntrl; | ||
700 | kim_gdata->baud_rate = pdata->baud_rate; | ||
701 | pr_info("sysfs entries created\n"); | ||
702 | |||
730 | kim_debugfs_dir = debugfs_create_dir("ti-st", NULL); | 703 | kim_debugfs_dir = debugfs_create_dir("ti-st", NULL); |
731 | if (IS_ERR(kim_debugfs_dir)) { | 704 | if (IS_ERR(kim_debugfs_dir)) { |
732 | pr_err(" debugfs entries creation failed "); | 705 | pr_err(" debugfs entries creation failed "); |
733 | kim_debugfs_dir = NULL; | 706 | kim_debugfs_dir = NULL; |
734 | return -1; | 707 | return -EIO; |
735 | } | 708 | } |
736 | 709 | ||
737 | debugfs_create_file("version", S_IRUGO, kim_debugfs_dir, | 710 | debugfs_create_file("version", S_IRUGO, kim_debugfs_dir, |
@@ -744,25 +717,22 @@ static int kim_probe(struct platform_device *pdev) | |||
744 | 717 | ||
745 | static int kim_remove(struct platform_device *pdev) | 718 | static int kim_remove(struct platform_device *pdev) |
746 | { | 719 | { |
747 | /* free the GPIOs requested | 720 | /* free the GPIOs requested */ |
748 | */ | 721 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; |
749 | long *gpios = pdev->dev.platform_data; | ||
750 | long proto; | ||
751 | struct kim_data_s *kim_gdata; | 722 | struct kim_data_s *kim_gdata; |
752 | 723 | ||
753 | kim_gdata = dev_get_drvdata(&pdev->dev); | 724 | kim_gdata = dev_get_drvdata(&pdev->dev); |
754 | 725 | ||
755 | for (proto = 0; (proto < ST_MAX) && (gpios[proto] != -1); proto++) { | 726 | /* Free the Bluetooth/FM/GPIO |
756 | /* Claim the Bluetooth/FM/GPIO | 727 | * nShutdown gpio from the system |
757 | * nShutdown gpio from the system | 728 | */ |
758 | */ | 729 | gpio_free(pdata->nshutdown_gpio); |
759 | gpio_free(gpios[proto]); | 730 | pr_info("nshutdown GPIO Freed"); |
760 | rfkill_unregister(kim_gdata->rfkill[proto]); | 731 | |
761 | rfkill_destroy(kim_gdata->rfkill[proto]); | ||
762 | kim_gdata->rfkill[proto] = NULL; | ||
763 | } | ||
764 | pr_info("kim: GPIO Freed"); | ||
765 | debugfs_remove_recursive(kim_debugfs_dir); | 732 | debugfs_remove_recursive(kim_debugfs_dir); |
733 | sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); | ||
734 | pr_info("sysfs entries removed"); | ||
735 | |||
766 | kim_gdata->kim_pdev = NULL; | 736 | kim_gdata->kim_pdev = NULL; |
767 | st_core_exit(kim_gdata->core_data); | 737 | st_core_exit(kim_gdata->core_data); |
768 | 738 | ||
@@ -771,23 +741,46 @@ static int kim_remove(struct platform_device *pdev) | |||
771 | return 0; | 741 | return 0; |
772 | } | 742 | } |
773 | 743 | ||
744 | int kim_suspend(struct platform_device *pdev, pm_message_t state) | ||
745 | { | ||
746 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | ||
747 | |||
748 | if (pdata->suspend) | ||
749 | return pdata->suspend(pdev, state); | ||
750 | |||
751 | return -EOPNOTSUPP; | ||
752 | } | ||
753 | |||
754 | int kim_resume(struct platform_device *pdev) | ||
755 | { | ||
756 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | ||
757 | |||
758 | if (pdata->resume) | ||
759 | return pdata->resume(pdev); | ||
760 | |||
761 | return -EOPNOTSUPP; | ||
762 | } | ||
763 | |||
774 | /**********************************************************************/ | 764 | /**********************************************************************/ |
775 | /* entry point for ST KIM module, called in from ST Core */ | 765 | /* entry point for ST KIM module, called in from ST Core */ |
766 | static struct platform_driver kim_platform_driver = { | ||
767 | .probe = kim_probe, | ||
768 | .remove = kim_remove, | ||
769 | .suspend = kim_suspend, | ||
770 | .resume = kim_resume, | ||
771 | .driver = { | ||
772 | .name = "kim", | ||
773 | .owner = THIS_MODULE, | ||
774 | }, | ||
775 | }; | ||
776 | 776 | ||
777 | static int __init st_kim_init(void) | 777 | static int __init st_kim_init(void) |
778 | { | 778 | { |
779 | long ret = 0; | 779 | return platform_driver_register(&kim_platform_driver); |
780 | ret = platform_driver_register(&kim_platform_driver); | ||
781 | if (ret != 0) { | ||
782 | pr_err("platform drv registration failed"); | ||
783 | return -1; | ||
784 | } | ||
785 | return 0; | ||
786 | } | 780 | } |
787 | 781 | ||
788 | static void __exit st_kim_deinit(void) | 782 | static void __exit st_kim_deinit(void) |
789 | { | 783 | { |
790 | /* the following returns void */ | ||
791 | platform_driver_unregister(&kim_platform_driver); | 784 | platform_driver_unregister(&kim_platform_driver); |
792 | } | 785 | } |
793 | 786 | ||