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, or GNSS) 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, or GNSS) 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.
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.
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