CG2900 Driver Henrik Possung
henrik.possung@stericsson.com
Par-Gunnar Hjalmdahl
par-gunnar.p.hjalmdahl@stericsson.com
2010 ST-Ericsson SA Connectivity This documentation is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA For more details see the file COPYING in the source distribution of Linux.
Introduction This documentation describes the functions provided by the ST-Ericsson CG2900 Driver for enabling ST-Ericsson CG2900 Combo Controller Hardware. Getting Started There are no special compilation flags needed to build the CG2900 driver. There must be patch and settings files that match the used chip version inside the firmware folder. The files: CG2900_XXXX_YYYY_patch.fw CG2900_XXXX_YYYY_settings.fw where XXXX is chip revision and YYYY is chip sub-version returned from the HCI Read Local Version command.
Basic Tutorial To enable the ST-Ericsson CG2900 driver using KConfig go to Device Drivers -> Staging Drivers and enable the CG2900 Driver. If BlueZ shall be used as Bluetooth stack also enable the CG2900 Bluetooth driver. Depending on choice the driver will either be included as LKM or built into the Kernel. If building as LKM, several files will be generated: cg2900.ko which contains the main driver cg2900_char_devices.ko which contains the character devices cg2900_uart.ko which contains the UART driver cg2900_chip.ko which contains the CG2900 chip specific driver stlc2690_chip.ko which contains the STLC2690 chip specific driver cg2900_audio.ko which contains the CG2900 audio driver btcg2900.ko which contains the registration and mapping towards the BlueZ Bluetooth stack
Concepts The ST-Ericsson CG2900 driver works as a multiplexer between different users, such as a Bluetooth stack and a FM driver, and the connectivity chip. The driver supports multiple physical transports, although currently only UART is implemented. Apart from just transporting data between stacks and the chip, the ST-Ericsson CG2900 driver also deals with power handling, powering up and down the chip and also downloading necessary patches and settings for the chip to start up properly. Tasks Platform device handling Each H:4 channel is created as a multifunction device. The driver for each channel must register as a platform driver for this channel, supplying probe and remove functions. When a transport is opened to the chip, the CG2900 chip driver will allocate and instantiate a platform device for each channel. This means that at this point the device framework in the Kernel will call the probe function for the platform driver. It is then the responsibility for the platform driver to register its callback functions and save its device to the platform data structure inside the probed device. When the transport is removed the CG2900 chip driver will free each platform device and the the platform driver's remove function will then be called. For user space, the user space character device will not exist until the character device driver has been probed. The character devices will be removed when the character device driver is removed, i.e. when the transport is removed. Opening a channel In order to be able to send and receive data on an H:4 channel, the user (i.e. respective stack) must open the channel. Opening a channel will make it possible to send data to and receive data from the connectivity controller. If the controller were earlier powered down, opening a channel will also cause the controller to be powered up. When chip is powered up, patches and settings for the ARM subsystem will be downloaded as well. Other IPs within the controller must however download each respective patches and settings. If chip was already powered up when opening the channel no patch will be automatically downloaded. Opening a channel from Kernel space When a stack is placed in Kernel space, it shall open a channel by calling the API function open inside the platform data of the device. Opening a channel from User space When a stack is placed in User space, it shall open a channel by calling the syscall function open on the corresponding file. The files are located in folder /dev/ and are named cg2900_gnss and similar. Each file corresponds to one H:4 channel. Closing a channel When a user, i.e. a stack has no need for a functionality, it should close the corresponding H:4 channel. This is usually done when a user disables a certain feature, for example Bluetooth. The reason why the channels need to be closed is that the ST-E CG2900 driver will free the resources and also shutdown the controller if there are no more active users of the chip. This will lower the power consumption thereby increasing battery life. Closing a channel from Kernel space When a stack is placed in Kernel space, it shall close a channel by calling the API function close inside the platform data of the device. Closing a channel from User space When a stack is placed in User space, it shall close a channel by calling the syscall function close on the corresponding file. Writing to a channel When a stack (Bluetooth, FM, GNSS or NFC) wants to send a packet it shall perform a write operation. The packet shall not contain the H:4 header since this is added by the CG2900 driver. All other data in the packet shall however exist in the packet in the format correct for that HCI channel. The CG2900 users need to perform flow control over channels so any ticket handling or similar must be handled by respective stack. Writing to a channel from Kernel space When a stack is placed in Kernel space, it shall start with allocating a packet of the correct size using alloc_skb inside the platform data of the device. This function will return an sk_buff (Socket buffer) structure that has necessary space reserved for CG2900 driver operation. The stack shall then copy the data, preferrably using skb_put, and then call write inside the platform data of the device to perform the write operation. When the function returns, the buffer has been transferred and there is no need for the calling function to free the buffer. If the operation fails, i.e. an error code is returned, the caller must however free the buffer. Writing to a channel from User space When a stack is placed in User space, it shall call the write function on the corresponding file to perform a transmit operation. After function returns the data has been copied and is considered sent. The caller does not need to preserve the data. Writing to FM_Radio and FM_Audio channel CG2900 driver only supports FM legacy commands. The reason is that the FM_Radio and FM_Audio uses the same H4 channel aginst the chip, in order to multiplex the FM user commands the data pakets are parsed by the CG2900 driver. Reading from a channel When a stack (Bluetooth, FM, GNSS or NFC) wants to receive a packet it shall perform a receive operation. The packet returned does not contain the H:4 header since this is removed by the CG2900 driver. All other data in the packet in the packet is in the format correct for that HCI channel. The CG2900 driver does not perform any flow control over the H:4 channel so any ticket handling or similar must be handled by respective stack. Reading from a channel from Kernel space When a stack is placed in Kernel space, it has to supply a callback function for the receive functionality when being probed. This callback function will be called when the ST-E CG2900 driver has received a packet. The packet received will always be a complete HCI packet, i.e. no fragmention on HCI layer. When the packet has been received it is the responsability of the receiver to see to that the packet is freed using kfree_skb when it is no more needed. Reading from a channel from User space When a stack is placed in User space, it shall call the read function on the corresponding file to perform a receive operation. This function will read as many bytes as there are present up to the size of the supplied buffer. If no data is available the function will hang until data becomes available, reset occurs, or the channel is closed. For smooth operation it is recommended to use the poll functionality on the file, preferrably from a dedicated thread. This way one thread can monitor both read and reset operations in one common thread while transmit operations may continue unblocked in a separate thread. Reset handling The stacks shall always try to avoid performing Reset operations. The Reset will result in a hardware reset of the controller and will therefore cause all existing links and settings to be lost. All stacks using the controller must also be informed about the reset and handle it in a proper way. The reset operation should only be used when there is no other option to get the controller into a working state, for example if the controller has stopped answering to commands. After the hardware reset, the ST-E CG2900 driver will automatically perform deregister the channel so it has to be reopened again. Reset handling from Kernel space When a stack is placed in Kernel space, it initiates a Reset operation by calling reset inside the platform data of the device. This will trigger a hardware reset of the controller. When the hardware reset is finished all registered users will be called through respective reset callback. When the callback function is finished the registered device will be closed and when all opened users have been informed and closed, the chip is shutdown. This is similar to a closure of all opened channels. The stack will then have to open the channel in order to use the channel once again. Reset handling from User space When a stack is placed in User space, it shall call the ioctl function on the corresponding file to perform a reset operation. The command parameter CG2900_CHAR_DEV_IOCTL_RESET shall be used when calling ioctl. When the ioctl returns, the stack shall close the channel and then re-open it again. This must be done so the channel is registered correctly in Kernel space. For smooth operation it is recommended to use the poll functionality on the file, preferrably from a dedicated thread. This way one thread can monitor both read and reset operations in one common thread while transmit operations may continue unblocked in a separate thread. Example code Kernel space This example will open the FM channel, write a packet, read a packet and then close the channel. bool event_received; void read_cb(struct cg2900_user_data *dev, struct sk_buff *skb) { event_received = true; kfree_skb(skb); } void reset_cb(struct cg2900_user_data *dev) { /* Handle reset. Device will be automatically closed by the CG2900 driver */ } void example_open(struct my_info *info) { struct cg2900_user_data *user = dev_get_platdata(info->dev); int err; if (user->opened) { dev_err(info->dev, "Error! Channel already opened!\n"); return; } err = user->open(user); if (err) { dev_err(info->dev, "Error (%d)! Couldn't register!\n", err); } } void example_close(struct my_info *info) { struct cg2900_user_data *user = dev_get_platdata(info->dev); if (user->opened) user->close(user); } void example_write_and_read(struct my_info *info, uint8_t *data, int len) { int err; struct cg2900_user_data *user = dev_get_platdata(info->dev); struct sk_buff *skb = user->alloc_skb(len, GFP_KERNEL); if (skb) { memcpy(skb_put(skb, len), data, len); err = user->write(user, skb); if (!err) { event_received = false; while (!event_received) { /* Wait for ack event. Received in read_cb() above */ schedule_timeout_interruptible(jiffies + 50); } } else { dev_err(info->dev, "Couldn't write to controller (%d)\n", err); kfree_skb(skb); } } } static int __devinit my_probe(struct platform_device *pdev) { struct my_info *info; struct cg2900_user_data *pf_data; info = kzalloc(sizeof(*info)); if (!info) return -ENOMEM; dev_set_drvdata(&pdev->dev, info); info->dev = &pdev->dev; pf_data = dev_get_platdata(&pdev->dev); pf_data->dev = &pdev->dev; pf_data->read_cb = read_cb; pf_data->reset_cb = reset_cb; /* * Alert my user that we are ready to start and give * it my info pointer. */ return my_user_start(info); } static int __devexit my_remove(struct platform_device *pdev) { struct my_info *info; info = dev_get_drvdata(&pdev->dev); my_user_stop(info); kfree(info); return 0; } static struct platform_driver my_driver = { .driver = { .name = "cg2900-fm", .owner = THIS_MODULE, }, .probe = my_probe, .remove = __devexit_p(my_remove), }; static int __init my_init(void) { return platform_driver_register(&my_driver); } static void __exit my_exit(void) { platform_driver_unregister(&my_driver); } module_init(my_init); module_exit(my_exit); Example code User space This example will open the GNSS channel, write a packet, read a packet and then close the channel. The same example is applicable for all other user space access for eg. NFC driver. In this example all functions are performed in the same thread. It is however adviced to perform read and ioctl read through a separate thread, preferrably using poll. struct my_info_t { int fd; }; static struct my_info_t my_info; /* This is a fake command and has nothing to do with real GNSS commands. * Note that the command does NOT contain the H:4 header. * The header is added by the ST-E CG2900 driver. */ static const uint8_t tx_cmd[] = {0x12, 0x34, 0x56}; int main(int argc, char **argv) { uint8_t rx_buffer[100]; int rx_bytes = 0; int err; my_info.fd = open("/dev/cg2900_gnss", O_RDWR); if (my_info.fd < 0) { printf("Error on open file: %d (%s)\n", errno, strerror(errno)); return errno; } if (0 > write(my_info.fd, tx_cmd, sizeof(tx_cmd))) { printf("Error on write file: %d (%s)\n", errno, strerror(errno)); return errno; } /* Read will sleep until there is data available */ rx_bytes = read(my_info.fd, rx_buffer, 100); if (rx_bytes >= 0) { printf("Received %d bytes\n", rx_bytes); } else { printf("Error on read file: %d (%s)\n", errno, strerror(errno)); return errno; } err = close(my_info.fd); if (err) { printf("Error on close file: %d (%s)\n", errno, strerror(errno)); return errno; } return 0; } Driver Configuration and Interaction N/A
Implemented operations in driver Supported device driver operations when using character device open Opening a character device will register the caller to that HCI channel. release Releasing a character device will deregister the caller from that HCI channel poll Polling a character device will check if there is data to read on that HCI channel read Reading from a character device reads from that HCI channel write Writing to a character device writes to that HCI channel unlocked_ioctl Performing IO control on a character device will perform special operations such as reset on that HCI channel
Driver loading parameters uart_default_baud Parameter type int Default value 115200 Runtime readable/modifiable Readable Description The parameter uart_default_baud in cg2900_uart.c defines the baud rate used after a chip has just been powered up. It shall be set to the default baud rate of the controller. For ST-Ericsson controllers STLC2690 and CG2900 this value shall be 115200. uart_high_baud Parameter type int Default value 3000000 Runtime readable/modifiable Modifiable Description The parameter uart_high_baud in cg2900_uart.c defines the baud rate to use for normal data transfer. This should normally be the highest allowed by the system with regards to flow control, clocks, etc. For ST-Ericsson controllers STLC2690 and CG2900 the following values are supported: 57600 115200 230400 460800 921600 2000000 3000000 4000000 uart_debug Parameter type int Default value 0 Runtime readable/modifiable Modifiable Description The parameter uart_debug in cg2900_uart.c enables or disables dumping of all data transmitted and received through the UART. 0 means disabled and non-zero value means enabled. bd_address Parameter type array (Entered as comma separated value) Default value 0x00 0x80 0xDE 0xAD 0xBE 0x00 Runtime readable/modifiable Modifiable Description The parameter bd_address in cg2900_core.c defines the Bluetooth device address to use for the current device. The value is an array of 6 bytes and shall be entered as a comma separated value. sleep_timeout_ms Parameter type int Default value 10000 Runtime readable/modifiable Modifiable Description The parameter sleep_timeout_ms in cg2900_core.c defines the sleep timeout for data transmission in milliseconds.
Driver IO Control CG2900_CHAR_DEV_IOCTL_RESET Direction Set Parameter int Description The CG2900_CHAR_DEV_IOCTL_RESET IOCTL starts a reset of the connectivity chip. This will affect the current open channel and all other open channels as well. IOCTL value created using _IOW('U', 210, int). Returned values are: If reset is performed without errors the IOCTL function will return 0. A negative value will indicate error. CG2900_CHAR_DEV_IOCTL_CHECK4RESET Direction Query Parameter int Description The CG2900_CHAR_DEV_IOCTL_CHECK4RESET IOCTL checks if a reset has been performed on a device. IOCTL value created using _IOR('U', 212, int). Returned values are: If device is still open the IOCTL function will return 0. If reset has occurred the IOCTL function will return 1. If device has been closed the IOCTL function will return 2. A negative value will indicate error. CG2900_CHAR_DEV_IOCTL_GET_REVISION Direction Query Parameter struct cg2900_rev_data Description The CG2900_CHAR_DEV_IOCTL_GET_REVISION IOCTL returns the revision value and the sub-version value of the local connectivity controller if such information is available. IOCTL value created using _IOR('U', 213, struct cg2900_rev_data). Returned values are according to information that may be retrieved from chip manufacturer. One example is ST-Ericsson CG2900 PG2.0 which have revision 0x0200 and sub-version 0x0000.
Driver Interaction with Sysfs Not Applicable
Driver Interaction using /proc filesystem Not Applicable
Other means for Driver Interaction Not Applicable
Driver Node File CG2900 main device File /dev/cg2900_driver0 Description The cg2900_driver represents the main parent node for all other character devices supplied in the ST-Ericsson CG2900 driver except for the Test device. It does not support any operations such as read or write. BT Command File /dev/cg2900_bt_cmd Description The cg2900_bt_cmd is the device for the HCI Bluetooth command channel. BT ACL File /dev/cg2900_bt_acl Description The cg2900_bt_acl is the device for the HCI Bluetooth ACL channel. BT Event File /dev/cg2900_bt_evt Description The cg2900_bt_evt is the device for the HCI Bluetooth event channel. FM Radio File /dev/cg2900_fm_radio Description The cg2900_fm_radio is the device for the HCI FM Radio channel. GNSS File /dev/cg2900_gnss Description The cg2900_gnss is the device for the HCI GNSS channel. Debug File /dev/cg2900_debug Description The cg2900_debug is the device for the HCI Debug channel. ST-Ericsson Tools File /dev/cg2900_ste_tools Description The cg2900_ste_tools is the device for the HCI ST-Ericsson tools channel. HCI Logger File /dev/cg2900_hci_logger Description The cg2900_hci_logger is the device for the HCI logger channel. Test stub File /dev/cg2900_test Description The cg2900_test is the device for performing module tests of the ST-Ericsson CG2900 driver. It acts as a stub replacing the transport towards the chip. It is of the type Misc devices. BT Audio File /dev/cg2900_bt_audio Description The cg2900_bt_audio is the device for sending HCI BT Audio controll commands to the chip. FM Audio File /dev/cg2900_fm_audio Description The cg2900_fm_audio is the device for sending HCI BT Audio controll commands to the chip. Core File /dev/cg2900_core Description The cg2900_core is a device for turn on/off the chip. NOTE other devices will also turn on/off the chip if needed. CG2900 Audio File /dev/cg2900_audio Description The cg2900_audio is a device for testing the CG2900 Audio driver from User space. It replicates the normal CG2900 Audio interface through write/read operations. The write command is used as following: 4 byte op code (see below) Data field according to respective CG2900 Audio function (no session ID needed) If the operation fails the write command operation will return the error. Op codes are (4 bytes size): 0x00000001 = CHAR_DEV_OP_CODE_SET_DAI_CONF 0x00000002 = CHAR_DEV_OP_CODE_GET_DAI_CONF 0x00000003 = CHAR_DEV_OP_CODE_CONFIGURE_ENDPOINT 0x00000004 = CHAR_DEV_OP_CODE_CONNECT_AND_START_STREAM 0x00000005 = CHAR_DEV_OP_CODE_STOP_STREAM The read command is used for the commands CHAR_DEV_OP_CODE_GET_DAI_CONF and CHAR_DEV_OP_CODE_CONNECT_AND_START_STREAM if the corresponding commands are successful. The returned data will be formatted accordingly: 4 byte op code (see below) Data field according to normal CG2900 Audio functions, e.g. stream handle or configuration The CHAR_DEV_OP_CODE_GET_DAI_CONF is a bit special since it require an endpoint in-parameter (when calling write) to return the corresponding DAI configuration when calling read. HCI Raw File /dev/cg2900_hci_raw Description The cg2900_hci_raw is the device for raw access to HCI interface. NFC File /dev/cg2900_nfc Description The cg2900_nfc is the device for the HCI NFC channel.
Known Bugs And Assumptions Driver supports only one user per HCI channel. To simplify design and limitation as well as keeping the API simple and reliable, the driver only supports one user per HCI channel. HCI Raw channel requires exclusive access to chip. cg2900_hci_raw channel cannot be opened if there are any other channels already opened except hci_logger channel. Also any other channels cannot be opened except hci_logger channel when cg2900_hci_raw is already opened. This is to guarantee that different users won't interfere with each other and prevent flow control issues. Public Functions Provided List of public functions.
cg2900.h !Edrivers/staging/cg2900/mfd/cg2900_core.c !Idrivers/staging/cg2900/include/cg2900.h
cg2900_audio.h !Edrivers/staging/cg2900/mfd/cg2900_audio.c
Internal Functions Provided List of internal functions.
cg2900_lib.h !Edrivers/staging/cg2900/mfd/cg2900_lib.c