diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 15:05:40 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 15:05:40 -0700 |
commit | a5e6b135bdff649e4330f98e2e80dbb1984f7e77 (patch) | |
tree | 475bfb1163c59d1370fd77415255afba768f9520 /drivers/misc | |
parent | 971f115a50afbe409825c9f3399d5a3b9aca4381 (diff) | |
parent | 9d90c8d9cde929cbc575098e825d7c29d9f45054 (diff) |
Merge branch 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (50 commits)
printk: do not mangle valid userspace syslog prefixes
efivars: Add Documentation
efivars: Expose efivars functionality to external drivers.
efivars: Parameterize operations.
efivars: Split out variable registration
efivars: parameterize efivars
efivars: Make efivars bin_attributes dynamic
efivars: move efivars globals into struct efivars
drivers:misc: ti-st: fix debugging code
kref: Fix typo in kref documentation
UIO: add PRUSS UIO driver support
Fix spelling mistakes in Documentation/zh_CN/SubmittingPatches
firmware: Fix unaligned memory accesses in dmi-sysfs
firmware: Add documentation for /sys/firmware/dmi
firmware: Expose DMI type 15 System Event Log
firmware: Break out system_event_log in dmi-sysfs
firmware: Basic dmi-sysfs support
firmware: Add DMI entry types to the headers
Driver core: convert platform_{get,set}_drvdata to static inline functions
Translate linux-2.6/Documentation/magic-number.txt into Chinese
...
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/Kconfig | 7 | ||||
-rw-r--r-- | drivers/misc/pch_phub.c | 69 | ||||
-rw-r--r-- | drivers/misc/ti-st/st_core.c | 419 | ||||
-rw-r--r-- | drivers/misc/ti-st/st_kim.c | 491 | ||||
-rw-r--r-- | drivers/misc/ti-st/st_ll.c | 10 |
5 files changed, 448 insertions, 548 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index cc8e49db45f..b7d5ef234ac 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -441,7 +441,7 @@ config BMP085 module will be called bmp085. config PCH_PHUB - tristate "PCH Packet Hub of Intel Topcliff" + tristate "PCH Packet Hub of Intel Topcliff / OKI SEMICONDUCTOR ML7213" depends on PCI help This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of @@ -449,6 +449,11 @@ config PCH_PHUB processor. The Topcliff has MAC address and Option ROM data in SROM. This driver can access MAC address and Option ROM data in SROM. + This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is + for IVI(In-Vehicle Infotainment) use. + ML7213 is companion chip for Intel Atom E6xx series. + ML7213 is completely compatible for Intel EG20T PCH. + To compile this driver as a module, choose M here: the module will be called pch_phub. diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index 744b804aca1..98bffc471b1 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD. + * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,7 +33,12 @@ #define PHUB_TIMEOUT 0x05 /* Time out value for Status Register */ #define PCH_PHUB_ROM_WRITE_ENABLE 0x01 /* Enabling for writing ROM */ #define PCH_PHUB_ROM_WRITE_DISABLE 0x00 /* Disabling for writing ROM */ -#define PCH_PHUB_ROM_START_ADDR 0x14 /* ROM data area start address offset */ +#define PCH_PHUB_MAC_START_ADDR 0x20C /* MAC data area start address offset */ +#define PCH_PHUB_ROM_START_ADDR_EG20T 0x14 /* ROM data area start address offset + (Intel EG20T PCH)*/ +#define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address + offset(OKI SEMICONDUCTOR ML7213) + */ /* MAX number of INT_REDUCE_CONTROL registers */ #define MAX_NUM_INT_REDUCE_CONTROL_REG 128 @@ -42,6 +47,10 @@ #define CLKCFG_CAN_50MHZ 0x12000000 #define CLKCFG_CANCLK_MASK 0xFF000000 +/* Macros for ML7213 */ +#define PCI_VENDOR_ID_ROHM 0x10db +#define PCI_DEVICE_ID_ROHM_ML7213_PHUB 0x801A + /* SROM ACCESS Macro */ #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1)) @@ -298,7 +307,7 @@ static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip, { unsigned int mem_addr; - mem_addr = PCH_PHUB_ROM_START_ADDR + + mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T + pch_phub_mac_offset[offset_address]; pch_phub_read_serial_rom(chip, mem_addr, data); @@ -315,7 +324,7 @@ static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip, int retval; unsigned int mem_addr; - mem_addr = PCH_PHUB_ROM_START_ADDR + + mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T + pch_phub_mac_offset[offset_address]; retval = pch_phub_write_serial_rom(chip, mem_addr, data); @@ -594,23 +603,38 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, "pch_phub_extrom_base_address variable is %p\n", __func__, chip->pch_phub_extrom_base_address); - pci_set_drvdata(pdev, chip); - - retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); - if (retval) - goto err_sysfs_create; - - retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); - if (retval) - goto exit_bin_attr; - - pch_phub_read_modify_write_reg(chip, (unsigned int)CLKCFG_REG_OFFSET, - CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK); + if (id->driver_data == 1) { + retval = sysfs_create_file(&pdev->dev.kobj, + &dev_attr_pch_mac.attr); + if (retval) + goto err_sysfs_create; - /* set the prefech value */ - iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14); - /* set the interrupt delay value */ - iowrite32(0x25, chip->pch_phub_base_address + 0x44); + retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); + if (retval) + goto exit_bin_attr; + + pch_phub_read_modify_write_reg(chip, + (unsigned int)CLKCFG_REG_OFFSET, + CLKCFG_CAN_50MHZ, + CLKCFG_CANCLK_MASK); + + /* set the prefech value */ + iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14); + /* set the interrupt delay value */ + iowrite32(0x25, chip->pch_phub_base_address + 0x44); + } else if (id->driver_data == 2) { + retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); + if (retval) + goto err_sysfs_create; + /* set the prefech value + * Device2(USB OHCI #1/ USB EHCI #1/ USB Device):a + * Device4(SDIO #0,1,2):f + * Device6(SATA 2):f + * Device8(USB OHCI #0/ USB EHCI #0):a + */ + iowrite32(0x000affa0, chip->pch_phub_base_address + 0x14); + } + pci_set_drvdata(pdev, chip); return 0; exit_bin_attr: @@ -687,8 +711,9 @@ static int pch_phub_resume(struct pci_dev *pdev) #endif /* CONFIG_PM */ static struct pci_device_id pch_phub_pcidev_id[] = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)}, - {0,} + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB), 1, }, + { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2, }, + { } }; static struct pci_driver pch_phub_driver = { diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index f9aad06d1ae..486117f72c9 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c @@ -25,10 +25,9 @@ #include <linux/init.h> #include <linux/tty.h> -/* understand BT, FM and GPS for now */ -#include <net/bluetooth/bluetooth.h> -#include <net/bluetooth/hci_core.h> -#include <net/bluetooth/hci.h> +#include <linux/seq_file.h> +#include <linux/skbuff.h> + #include <linux/ti_wilink_st.h> /* function pointer pointing to either, @@ -38,21 +37,38 @@ void (*st_recv) (void*, const unsigned char*, long); /********************************************************************/ -#if 0 -/* internal misc functions */ -bool is_protocol_list_empty(void) +static void add_channel_to_table(struct st_data_s *st_gdata, + struct st_proto_s *new_proto) { - unsigned char i = 0; - pr_debug(" %s ", __func__); - for (i = 0; i < ST_MAX; i++) { - if (st_gdata->list[i] != NULL) - return ST_NOTEMPTY; - /* not empty */ + pr_info("%s: id %d\n", __func__, new_proto->chnl_id); + /* list now has the channel id as index itself */ + st_gdata->list[new_proto->chnl_id] = new_proto; +} + +static void remove_channel_from_table(struct st_data_s *st_gdata, + struct st_proto_s *proto) +{ + pr_info("%s: id %d\n", __func__, proto->chnl_id); + st_gdata->list[proto->chnl_id] = NULL; +} + +/* + * called from KIM during firmware download. + * + * This is a wrapper function to tty->ops->write_room. + * It returns number of free space available in + * uart tx buffer. + */ +int st_get_uart_wr_room(struct st_data_s *st_gdata) +{ + struct tty_struct *tty; + if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) { + pr_err("tty unavailable to perform write"); + return -1; } - /* list empty */ - return ST_EMPTY; + tty = st_gdata->tty; + return tty->ops->write_room(tty); } -#endif /* can be called in from * -- KIM (during fw download) @@ -67,7 +83,7 @@ int st_int_write(struct st_data_s *st_gdata, struct tty_struct *tty; if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) { pr_err("tty unavailable to perform write"); - return -1; + return -EINVAL; } tty = st_gdata->tty; #ifdef VERBOSE @@ -82,15 +98,15 @@ int st_int_write(struct st_data_s *st_gdata, * push the skb received to relevant * protocol stacks */ -void st_send_frame(enum proto_type protoid, struct st_data_s *st_gdata) +void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata) { - pr_info(" %s(prot:%d) ", __func__, protoid); + pr_debug(" %s(prot:%d) ", __func__, chnl_id); if (unlikely (st_gdata == NULL || st_gdata->rx_skb == NULL - || st_gdata->list[protoid] == NULL)) { - pr_err("protocol %d not registered, no data to send?", - protoid); + || st_gdata->list[chnl_id] == NULL)) { + pr_err("chnl_id %d not registered, no data to send?", + chnl_id); kfree_skb(st_gdata->rx_skb); return; } @@ -99,17 +115,17 @@ void st_send_frame(enum proto_type protoid, struct st_data_s *st_gdata) * - should be just skb_queue_tail for the * protocol stack driver */ - if (likely(st_gdata->list[protoid]->recv != NULL)) { + if (likely(st_gdata->list[chnl_id]->recv != NULL)) { if (unlikely - (st_gdata->list[protoid]->recv - (st_gdata->list[protoid]->priv_data, st_gdata->rx_skb) + (st_gdata->list[chnl_id]->recv + (st_gdata->list[chnl_id]->priv_data, st_gdata->rx_skb) != 0)) { - pr_err(" proto stack %d's ->recv failed", protoid); + pr_err(" proto stack %d's ->recv failed", chnl_id); kfree_skb(st_gdata->rx_skb); return; } } else { - pr_err(" proto stack %d's ->recv null", protoid); + pr_err(" proto stack %d's ->recv null", chnl_id); kfree_skb(st_gdata->rx_skb); } return; @@ -124,16 +140,22 @@ void st_reg_complete(struct st_data_s *st_gdata, char err) { unsigned char i = 0; pr_info(" %s ", __func__); - for (i = 0; i < ST_MAX; i++) { + for (i = 0; i < ST_MAX_CHANNELS; i++) { if (likely(st_gdata != NULL && st_gdata->list[i] != NULL && - st_gdata->list[i]->reg_complete_cb != NULL)) + st_gdata->list[i]->reg_complete_cb != NULL)) { st_gdata->list[i]->reg_complete_cb (st_gdata->list[i]->priv_data, err); + pr_info("protocol %d's cb sent %d\n", i, err); + if (err) { /* cleanup registered protocol */ + st_gdata->protos_registered--; + st_gdata->list[i] = NULL; + } + } } } static inline int st_check_data_len(struct st_data_s *st_gdata, - int protoid, int len) + unsigned char chnl_id, int len) { int room = skb_tailroom(st_gdata->rx_skb); @@ -144,7 +166,7 @@ static inline int st_check_data_len(struct st_data_s *st_gdata, * has zero length payload. So, ask ST CORE to * forward the packet to protocol driver (BT/FM/GPS) */ - st_send_frame(protoid, st_gdata); + st_send_frame(chnl_id, st_gdata); } else if (len > room) { /* Received packet's payload length is larger. @@ -157,7 +179,7 @@ static inline int st_check_data_len(struct st_data_s *st_gdata, /* Packet header has non-zero payload length and * we have enough space in created skb. Lets read * payload data */ - st_gdata->rx_state = ST_BT_W4_DATA; + st_gdata->rx_state = ST_W4_DATA; st_gdata->rx_count = len; return len; } @@ -167,6 +189,7 @@ static inline int st_check_data_len(struct st_data_s *st_gdata, st_gdata->rx_state = ST_W4_PACKET_TYPE; st_gdata->rx_skb = NULL; st_gdata->rx_count = 0; + st_gdata->rx_chnl = 0; return 0; } @@ -208,14 +231,12 @@ void st_int_recv(void *disc_data, const unsigned char *data, long count) { char *ptr; - struct hci_event_hdr *eh; - struct hci_acl_hdr *ah; - struct hci_sco_hdr *sh; - struct fm_event_hdr *fm; - struct gps_event_hdr *gps; - int len = 0, type = 0, dlen = 0; - static enum proto_type protoid = ST_MAX; + struct st_proto_s *proto; + unsigned short payload_len = 0; + int len = 0, type = 0; + unsigned char *plen; struct st_data_s *st_gdata = (struct st_data_s *)disc_data; + unsigned long flags; ptr = (char *)data; /* tty_receive sent null ? */ @@ -224,10 +245,11 @@ void st_int_recv(void *disc_data, return; } - pr_info("count %ld rx_state %ld" + pr_debug("count %ld rx_state %ld" "rx_count %ld", count, st_gdata->rx_state, st_gdata->rx_count); + spin_lock_irqsave(&st_gdata->lock, flags); /* Decode received bytes here */ while (count) { if (st_gdata->rx_count) { @@ -242,64 +264,36 @@ void st_int_recv(void *disc_data, /* Check ST RX state machine , where are we? */ switch (st_gdata->rx_state) { - - /* Waiting for complete packet ? */ - case ST_BT_W4_DATA: + /* Waiting for complete packet ? */ + case ST_W4_DATA: pr_debug("Complete pkt received"); - /* Ask ST CORE to forward * the packet to protocol driver */ - st_send_frame(protoid, st_gdata); + st_send_frame(st_gdata->rx_chnl, st_gdata); st_gdata->rx_state = ST_W4_PACKET_TYPE; st_gdata->rx_skb = NULL; - protoid = ST_MAX; /* is this required ? */ continue; - - /* Waiting for Bluetooth event header ? */ - case ST_BT_W4_EVENT_HDR: - eh = (struct hci_event_hdr *)st_gdata->rx_skb-> - data; - - pr_debug("Event header: evt 0x%2.2x" - "plen %d", eh->evt, eh->plen); - - st_check_data_len(st_gdata, protoid, eh->plen); - continue; - - /* Waiting for Bluetooth acl header ? */ - case ST_BT_W4_ACL_HDR: - ah = (struct hci_acl_hdr *)st_gdata->rx_skb-> - data; - dlen = __le16_to_cpu(ah->dlen); - - pr_info("ACL header: dlen %d", dlen); - - st_check_data_len(st_gdata, protoid, dlen); - continue; - - /* Waiting for Bluetooth sco header ? */ - case ST_BT_W4_SCO_HDR: - sh = (struct hci_sco_hdr *)st_gdata->rx_skb-> - data; - - pr_info("SCO header: dlen %d", sh->dlen); - - st_check_data_len(st_gdata, protoid, sh->dlen); - continue; - case ST_FM_W4_EVENT_HDR: - fm = (struct fm_event_hdr *)st_gdata->rx_skb-> - data; - pr_info("FM Header: "); - st_check_data_len(st_gdata, ST_FM, fm->plen); - continue; - /* TODO : Add GPS packet machine logic here */ - case ST_GPS_W4_EVENT_HDR: - /* [0x09 pkt hdr][R/W byte][2 byte len] */ - gps = (struct gps_event_hdr *)st_gdata->rx_skb-> - data; - pr_info("GPS Header: "); - st_check_data_len(st_gdata, ST_GPS, gps->plen); + /* parse the header to know details */ + case ST_W4_HEADER: + proto = st_gdata->list[st_gdata->rx_chnl]; + plen = + &st_gdata->rx_skb->data + [proto->offset_len_in_hdr]; + pr_debug("plen pointing to %x\n", *plen); + if (proto->len_size == 1)/* 1 byte len field */ + payload_len = *(unsigned char *)plen; + else if (proto->len_size == 2) + payload_len = + __le16_to_cpu(*(unsigned short *)plen); + else + pr_info("%s: invalid length " + "for id %d\n", + __func__, proto->chnl_id); + st_check_data_len(st_gdata, proto->chnl_id, + payload_len); + pr_debug("off %d, pay len %d\n", + proto->offset_len_in_hdr, payload_len); continue; } /* end of switch rx_state */ } @@ -308,123 +302,56 @@ void st_int_recv(void *disc_data, /* Check first byte of packet and identify module * owner (BT/FM/GPS) */ switch (*ptr) { - - /* Bluetooth event packet? */ - case HCI_EVENT_PKT: - pr_info("Event packet"); - st_gdata->rx_state = ST_BT_W4_EVENT_HDR; - st_gdata->rx_count = HCI_EVENT_HDR_SIZE; - type = HCI_EVENT_PKT; - protoid = ST_BT; - break; - - /* Bluetooth acl packet? */ - case HCI_ACLDATA_PKT: - pr_info("ACL packet"); - st_gdata->rx_state = ST_BT_W4_ACL_HDR; - st_gdata->rx_count = HCI_ACL_HDR_SIZE; - type = HCI_ACLDATA_PKT; - protoid = ST_BT; - break; - - /* Bluetooth sco packet? */ - case HCI_SCODATA_PKT: - pr_info("SCO packet"); - st_gdata->rx_state = ST_BT_W4_SCO_HDR; - st_gdata->rx_count = HCI_SCO_HDR_SIZE; - type = HCI_SCODATA_PKT; - protoid = ST_BT; - break; - - /* Channel 8(FM) packet? */ - case ST_FM_CH8_PKT: - pr_info("FM CH8 packet"); - type = ST_FM_CH8_PKT; - st_gdata->rx_state = ST_FM_W4_EVENT_HDR; - st_gdata->rx_count = FM_EVENT_HDR_SIZE; - protoid = ST_FM; - break; - - /* Channel 9(GPS) packet? */ - case 0x9: /*ST_LL_GPS_CH9_PKT */ - pr_info("GPS CH9 packet"); - type = 0x9; /* ST_LL_GPS_CH9_PKT; */ - protoid = ST_GPS; - st_gdata->rx_state = ST_GPS_W4_EVENT_HDR; - st_gdata->rx_count = 3; /* GPS_EVENT_HDR_SIZE -1*/ - break; case LL_SLEEP_IND: case LL_SLEEP_ACK: case LL_WAKE_UP_IND: - pr_info("PM packet"); + pr_debug("PM packet"); /* this takes appropriate action based on * sleep state received -- */ st_ll_sleep_state(st_gdata, *ptr); + /* if WAKEUP_IND collides copy from waitq to txq + * and assume chip awake + */ + spin_unlock_irqrestore(&st_gdata->lock, flags); + if (st_ll_getstate(st_gdata) == ST_LL_AWAKE) + st_wakeup_ack(st_gdata, LL_WAKE_UP_ACK); + spin_lock_irqsave(&st_gdata->lock, flags); + ptr++; count--; continue; case LL_WAKE_UP_ACK: - pr_info("PM packet"); + pr_debug("PM packet"); + + spin_unlock_irqrestore(&st_gdata->lock, flags); /* wake up ack received */ st_wakeup_ack(st_gdata, *ptr); + spin_lock_irqsave(&st_gdata->lock, flags); + ptr++; count--; continue; /* Unknow packet? */ default: - pr_err("Unknown packet type %2.2x", (__u8) *ptr); - ptr++; - count--; - continue; + type = *ptr; + st_gdata->rx_skb = alloc_skb( + st_gdata->list[type]->max_frame_size, + GFP_ATOMIC); + skb_reserve(st_gdata->rx_skb, + st_gdata->list[type]->reserve); + /* next 2 required for BT only */ + st_gdata->rx_skb->cb[0] = type; /*pkt_type*/ + st_gdata->rx_skb->cb[1] = 0; /*incoming*/ + st_gdata->rx_chnl = *ptr; + st_gdata->rx_state = ST_W4_HEADER; + st_gdata->rx_count = st_gdata->list[type]->hdr_len; + pr_debug("rx_count %ld\n", st_gdata->rx_count); }; ptr++; count--; - - switch (protoid) { - case ST_BT: - /* Allocate new packet to hold received data */ - st_gdata->rx_skb = - bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); - if (!st_gdata->rx_skb) { - pr_err("Can't allocate mem for new packet"); - st_gdata->rx_state = ST_W4_PACKET_TYPE; - st_gdata->rx_count = 0; - return; - } - bt_cb(st_gdata->rx_skb)->pkt_type = type; - break; - case ST_FM: /* for FM */ - st_gdata->rx_skb = - alloc_skb(FM_MAX_FRAME_SIZE, GFP_ATOMIC); - if (!st_gdata->rx_skb) { - pr_err("Can't allocate mem for new packet"); - st_gdata->rx_state = ST_W4_PACKET_TYPE; - st_gdata->rx_count = 0; - return; - } - /* place holder 0x08 */ - skb_reserve(st_gdata->rx_skb, 1); - st_gdata->rx_skb->cb[0] = ST_FM_CH8_PKT; - break; - case ST_GPS: - /* for GPS */ - st_gdata->rx_skb = - alloc_skb(100 /*GPS_MAX_FRAME_SIZE */ , GFP_ATOMIC); - if (!st_gdata->rx_skb) { - pr_err("Can't allocate mem for new packet"); - st_gdata->rx_state = ST_W4_PACKET_TYPE; - st_gdata->rx_count = 0; - return; - } - /* place holder 0x09 */ - skb_reserve(st_gdata->rx_skb, 1); - st_gdata->rx_skb->cb[0] = 0x09; /*ST_GPS_CH9_PKT; */ - break; - case ST_MAX: - break; - } } + spin_unlock_irqrestore(&st_gdata->lock, flags); pr_debug("done %s", __func__); return; } @@ -466,7 +393,7 @@ void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb) switch (st_ll_getstate(st_gdata)) { case ST_LL_AWAKE: - pr_info("ST LL is AWAKE, sending normally"); + pr_debug("ST LL is AWAKE, sending normally"); skb_queue_tail(&st_gdata->txq, skb); break; case ST_LL_ASLEEP_TO_AWAKE: @@ -506,7 +433,7 @@ void st_tx_wakeup(struct st_data_s *st_data) pr_debug("%s", __func__); /* check for sending & set flag sending here */ if (test_and_set_bit(ST_TX_SENDING, &st_data->tx_state)) { - pr_info("ST already sending"); + pr_debug("ST already sending"); /* keep sending */ set_bit(ST_TX_WAKEUP, &st_data->tx_state); return; @@ -548,9 +475,9 @@ void kim_st_list_protocols(struct st_data_s *st_gdata, void *buf) { seq_printf(buf, "[%d]\nBT=%c\nFM=%c\nGPS=%c\n", st_gdata->protos_registered, - st_gdata->list[ST_BT] != NULL ? 'R' : 'U', - st_gdata->list[ST_FM] != NULL ? 'R' : 'U', - st_gdata->list[ST_GPS] != NULL ? 'R' : 'U'); + st_gdata->list[0x04] != NULL ? 'R' : 'U', + st_gdata->list[0x08] != NULL ? 'R' : 'U', + st_gdata->list[0x09] != NULL ? 'R' : 'U'); } /********************************************************************/ @@ -565,20 +492,20 @@ long st_register(struct st_proto_s *new_proto) unsigned long flags = 0; st_kim_ref(&st_gdata, 0); - pr_info("%s(%d) ", __func__, new_proto->type); + pr_info("%s(%d) ", __func__, new_proto->chnl_id); if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL || new_proto->reg_complete_cb == NULL) { pr_err("gdata/new_proto/recv or reg_complete_cb not ready"); - return -1; + return -EINVAL; } - if (new_proto->type < ST_BT || new_proto->type >= ST_MAX) { - pr_err("protocol %d not supported", new_proto->type); + if (new_proto->chnl_id >= ST_MAX_CHANNELS) { + pr_err("chnl_id %d not supported", new_proto->chnl_id); return -EPROTONOSUPPORT; } - if (st_gdata->list[new_proto->type] != NULL) { - pr_err("protocol %d already registered", new_proto->type); + if (st_gdata->list[new_proto->chnl_id] != NULL) { + pr_err("chnl_id %d already registered", new_proto->chnl_id); return -EALREADY; } @@ -586,11 +513,10 @@ long st_register(struct st_proto_s *new_proto) spin_lock_irqsave(&st_gdata->lock, flags); if (test_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state)) { - pr_info(" ST_REG_IN_PROGRESS:%d ", new_proto->type); + pr_info(" ST_REG_IN_PROGRESS:%d ", new_proto->chnl_id); /* fw download in progress */ - st_kim_chip_toggle(new_proto->type, KIM_GPIO_ACTIVE); - st_gdata->list[new_proto->type] = new_proto; + add_channel_to_table(st_gdata, new_proto); st_gdata->protos_registered++; new_proto->write = st_write; @@ -598,7 +524,7 @@ long st_register(struct st_proto_s *new_proto) spin_unlock_irqrestore(&st_gdata->lock, flags); return -EINPROGRESS; } else if (st_gdata->protos_registered == ST_EMPTY) { - pr_info(" protocol list empty :%d ", new_proto->type); + pr_info(" chnl_id list empty :%d ", new_proto->chnl_id); set_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state); st_recv = st_kim_recv; @@ -616,16 +542,11 @@ long st_register(struct st_proto_s *new_proto) if ((st_gdata->protos_registered != ST_EMPTY) && (test_bit(ST_REG_PENDING, &st_gdata->st_state))) { pr_err(" KIM failure complete callback "); - st_reg_complete(st_gdata, -1); + st_reg_complete(st_gdata, err); } - - return -1; + return -EINVAL; } - /* the protocol might require other gpios to be toggled - */ - st_kim_chip_toggle(new_proto->type, KIM_GPIO_ACTIVE); - clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state); st_recv = st_int_recv; @@ -642,14 +563,14 @@ long st_register(struct st_proto_s *new_proto) /* check for already registered once more, * since the above check is old */ - if (st_gdata->list[new_proto->type] != NULL) { + if (st_gdata->list[new_proto->chnl_id] != NULL) { pr_err(" proto %d already registered ", - new_proto->type); + new_proto->chnl_id); return -EALREADY; } spin_lock_irqsave(&st_gdata->lock, flags); - st_gdata->list[new_proto->type] = new_proto; + add_channel_to_table(st_gdata, new_proto); st_gdata->protos_registered++; new_proto->write = st_write; spin_unlock_irqrestore(&st_gdata->lock, flags); @@ -657,22 +578,7 @@ long st_register(struct st_proto_s *new_proto) } /* if fw is already downloaded & new stack registers protocol */ else { - switch (new_proto->type) { - case ST_BT: - /* do nothing */ - break; - case ST_FM: - case ST_GPS: - st_kim_chip_toggle(new_proto->type, KIM_GPIO_ACTIVE); - break; - case ST_MAX: - default: - pr_err("%d protocol not supported", - new_proto->type); - spin_unlock_irqrestore(&st_gdata->lock, flags); - return -EPROTONOSUPPORT; - } - st_gdata->list[new_proto->type] = new_proto; + add_channel_to_table(st_gdata, new_proto); st_gdata->protos_registered++; new_proto->write = st_write; @@ -680,48 +586,42 @@ long st_register(struct st_proto_s *new_proto) spin_unlock_irqrestore(&st_gdata->lock, flags); return err; } - pr_debug("done %s(%d) ", __func__, new_proto->type); + pr_debug("done %s(%d) ", __func__, new_proto->chnl_id); } EXPORT_SYMBOL_GPL(st_register); /* to unregister a protocol - * to be called from protocol stack driver */ -long st_unregister(enum proto_type type) +long st_unregister(struct st_proto_s *proto) { long err = 0; unsigned long flags = 0; struct st_data_s *st_gdata; - pr_debug("%s: %d ", __func__, type); + pr_debug("%s: %d ", __func__, proto->chnl_id); st_kim_ref(&st_gdata, 0); - if (type < ST_BT || type >= ST_MAX) { - pr_err(" protocol %d not supported", type); + if (proto->chnl_id >= ST_MAX_CHANNELS) { + pr_err(" chnl_id %d not supported", proto->chnl_id); return -EPROTONOSUPPORT; } spin_lock_irqsave(&st_gdata->lock, flags); - if (st_gdata->list[type] == NULL) { - pr_err(" protocol %d not registered", type); + if (st_gdata->list[proto->chnl_id] == NULL) { + pr_err(" chnl_id %d not registered", proto->chnl_id); spin_unlock_irqrestore(&st_gdata->lock, flags); return -EPROTONOSUPPORT; } st_gdata->protos_registered--; - st_gdata->list[type] = NULL; - - /* kim ignores BT in the below function - * and handles the rest, BT is toggled - * only in kim_start and kim_stop - */ - st_kim_chip_toggle(type, KIM_GPIO_INACTIVE); + remove_channel_from_table(st_gdata, proto); spin_unlock_irqrestore(&st_gdata->lock, flags); if ((st_gdata->protos_registered == ST_EMPTY) && (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) { - pr_info(" all protocols unregistered "); + pr_info(" all chnl_ids unregistered "); /* stop traffic on tty */ if (st_gdata->tty) { @@ -729,7 +629,7 @@ long st_unregister(enum proto_type type) stop_tty(st_gdata->tty); } - /* all protocols now unregistered */ + /* all chnl_ids now unregistered */ st_kim_stop(st_gdata->kim_data); /* disable ST LL */ st_ll_disable(st_gdata); @@ -744,37 +644,15 @@ long st_unregister(enum proto_type type) long st_write(struct sk_buff *skb) { struct st_data_s *st_gdata; -#ifdef DEBUG - enum proto_type protoid = ST_MAX; -#endif long len; st_kim_ref(&st_gdata, 0); if (unlikely(skb == NULL || st_gdata == NULL || st_gdata->tty == NULL)) { pr_err("data/tty unavailable to perform write"); - return -1; + return -EINVAL; } -#ifdef DEBUG /* open-up skb to read the 1st byte */ - switch (skb->data[0]) { - case HCI_COMMAND_PKT: - case HCI_ACLDATA_PKT: - case HCI_SCODATA_PKT: - protoid = ST_BT; - break; - case ST_FM_CH8_PKT: - protoid = ST_FM; - break; - case 0x09: - protoid = ST_GPS; - break; - } - if (unlikely(st_gdata->list[protoid] == NULL)) { - pr_err(" protocol %d not registered, and writing? ", - protoid); - return -1; - } -#endif + pr_debug("%d to be written", skb->len); len = skb->len; @@ -824,7 +702,7 @@ static int st_tty_open(struct tty_struct *tty) static void st_tty_close(struct tty_struct *tty) { - unsigned char i = ST_MAX; + unsigned char i = ST_MAX_CHANNELS; unsigned long flags = 0; struct st_data_s *st_gdata = tty->disc_data; @@ -835,7 +713,7 @@ static void st_tty_close(struct tty_struct *tty) * un-installed for some reason - what should be done ? */ spin_lock_irqsave(&st_gdata->lock, flags); - for (i = ST_BT; i < ST_MAX; i++) { + for (i = ST_BT; i < ST_MAX_CHANNELS; i++) { if (st_gdata->list[i] != NULL) pr_err("%d not un-registered", i); st_gdata->list[i] = NULL; @@ -869,7 +747,6 @@ static void st_tty_close(struct tty_struct *tty) static void st_tty_receive(struct tty_struct *tty, const unsigned char *data, char *tty_flags, int count) { - #ifdef VERBOSE print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE, 16, 1, data, count, 0); @@ -960,7 +837,7 @@ int st_core_init(struct st_data_s **core_data) err = tty_unregister_ldisc(N_TI_WL); if (err) pr_err("unable to un-register ldisc"); - return -1; + return err; } *core_data = st_gdata; return 0; diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 73b6c8b0e86..9ee4c788aa6 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -30,50 +30,12 @@ #include <linux/debugfs.h> #include <linux/seq_file.h> #include <linux/sched.h> -#include <linux/rfkill.h> - -/* understand BT events for fw response */ -#include <net/bluetooth/bluetooth.h> -#include <net/bluetooth/hci_core.h> -#include <net/bluetooth/hci.h> +#include <linux/tty.h> +#include <linux/skbuff.h> #include <linux/ti_wilink_st.h> -static int kim_probe(struct platform_device *pdev); -static int kim_remove(struct platform_device *pdev); - -/* KIM platform device driver structure */ -static struct platform_driver kim_platform_driver = { - .probe = kim_probe, - .remove = kim_remove, - /* TODO: ST driver power management during suspend/resume ? - */ -#if 0 - .suspend = kim_suspend, - .resume = kim_resume, -#endif - .driver = { - .name = "kim", - .owner = THIS_MODULE, - }, -}; - -static int kim_toggle_radio(void*, bool); -static const struct rfkill_ops kim_rfkill_ops = { - .set_block = kim_toggle_radio, -}; - -/* strings to be used for rfkill entries and by - * ST Core to be used for sysfs debug entry - */ -#define PROTO_ENTRY(type, name) name -const unsigned char *protocol_names[] = { - PROTO_ENTRY(ST_BT, "Bluetooth"), - PROTO_ENTRY(ST_FM, "FM"), - PROTO_ENTRY(ST_GPS, "GPS"), -}; - #define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */ static struct platform_device *st_kim_devices[MAX_ST_DEVICES]; @@ -134,7 +96,7 @@ static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len) /* Packet header has non-zero payload length and * we have enough space in created skb. Lets read * payload data */ - kim_gdata->rx_state = ST_BT_W4_DATA; + kim_gdata->rx_state = ST_W4_DATA; kim_gdata->rx_count = len; return len; } @@ -158,8 +120,8 @@ void kim_int_recv(struct kim_data_s *kim_gdata, const unsigned char *data, long count) { const unsigned char *ptr; - struct hci_event_hdr *eh; int len = 0, type = 0; + unsigned char *plen; pr_debug("%s", __func__); /* Decode received bytes here */ @@ -183,29 +145,27 @@ void kim_int_recv(struct kim_data_s *kim_gdata, /* Check ST RX state machine , where are we? */ switch (kim_gdata->rx_state) { /* Waiting for complete packet ? */ - case ST_BT_W4_DATA: + case ST_W4_DATA: pr_debug("Complete pkt received"); validate_firmware_response(kim_gdata); kim_gdata->rx_state = ST_W4_PACKET_TYPE; kim_gdata->rx_skb = NULL; continue; /* Waiting for Bluetooth event header ? */ - case ST_BT_W4_EVENT_HDR: - eh = (struct hci_event_hdr *)kim_gdata-> - rx_skb->data; - pr_debug("Event header: evt 0x%2.2x" - "plen %d", eh->evt, eh->plen); - kim_check_data_len(kim_gdata, eh->plen); + case ST_W4_HEADER: + plen = + (unsigned char *)&kim_gdata->rx_skb->data[1]; + pr_debug("event hdr: plen 0x%02x\n", *plen); + kim_check_data_len(kim_gdata, *plen); continue; } /* end of switch */ } /* end of if rx_state */ switch (*ptr) { /* Bluetooth event packet? */ - case HCI_EVENT_PKT: - pr_info("Event packet"); - kim_gdata->rx_state = ST_BT_W4_EVENT_HDR; - kim_gdata->rx_count = HCI_EVENT_HDR_SIZE; - type = HCI_EVENT_PKT; + case 0x04: + kim_gdata->rx_state = ST_W4_HEADER; + kim_gdata->rx_count = 2; + type = *ptr; break; default: pr_info("unknown packet"); @@ -216,16 +176,18 @@ void kim_int_recv(struct kim_data_s *kim_gdata, ptr++; count--; kim_gdata->rx_skb = - bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); + alloc_skb(1024+8, GFP_ATOMIC); if (!kim_gdata->rx_skb) { pr_err("can't allocate mem for new packet"); kim_gdata->rx_state = ST_W4_PACKET_TYPE; kim_gdata->rx_count = 0; return; } - bt_cb(kim_gdata->rx_skb)->pkt_type = type; + skb_reserve(kim_gdata->rx_skb, 8); + kim_gdata->rx_skb->cb[0] = 4; + kim_gdata->rx_skb->cb[1] = 0; + } - pr_info("done %s", __func__); return; } @@ -239,13 +201,13 @@ static long read_local_version(struct kim_dat |