summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/cg2900/bluetooth/cg2900_uart.c60
-rw-r--r--drivers/staging/cg2900/include/cg2900.h1
-rw-r--r--drivers/staging/cg2900/mfd/cg2900_chip.c14
3 files changed, 71 insertions, 4 deletions
diff --git a/drivers/staging/cg2900/bluetooth/cg2900_uart.c b/drivers/staging/cg2900/bluetooth/cg2900_uart.c
index 6b577514ae6..adfc1b26e83 100644
--- a/drivers/staging/cg2900/bluetooth/cg2900_uart.c
+++ b/drivers/staging/cg2900/bluetooth/cg2900_uart.c
@@ -1289,6 +1289,44 @@ static int set_baud_rate(struct hci_uart *hu, int baud)
}
/**
+ * uart_set_baud_rate() - External Interface for setting baud rate
+ * @dev: Transport device information.
+ * @low_baud: whether switch to low_baud or high.
+ *
+ * Returns:
+ * none
+ */
+static void uart_set_baud_rate(struct cg2900_chip_dev *dev, bool low_baud)
+{
+ struct uart_info *uart_info = dev_get_drvdata(dev->dev);
+
+ if (!uart_info->hu) {
+ dev_err(MAIN_DEV, "uart_set_baud_rate: UART not open\n");
+ return;
+ }
+
+ if (low_baud) {
+ if (uart_info->baud_rate != uart_default_baud) {
+ dev_dbg(MAIN_DEV, "Changing BAUD now to : %d",
+ uart_default_baud);
+ set_baud_rate(uart_info->hu, uart_default_baud);
+ } else {
+ dev_dbg(MAIN_DEV, "BAUD is already set to :%d",
+ uart_default_baud);
+ }
+ } else {
+ if (uart_info->baud_rate != uart_high_baud) {
+ dev_dbg(MAIN_DEV, "Changing BAUD now to : %d",
+ uart_high_baud);
+ set_baud_rate(uart_info->hu, uart_high_baud);
+ } else {
+ dev_dbg(MAIN_DEV, "BAUD is already set to :%d",
+ uart_high_baud);
+ }
+ }
+}
+
+/**
* uart_write() - Transmit data to CG2900 over UART.
* @dev: Transport device information.
* @skb: SK buffer to transmit.
@@ -1341,6 +1379,7 @@ static int uart_open(struct cg2900_chip_dev *dev)
return -EACCES;
}
+ uart_info->baud_rate = uart_default_baud;
/*
* Chip has just been started up. It has a system to autodetect
* exact baud rate and transport to use. There are only a few commands
@@ -1390,10 +1429,21 @@ static int uart_open(struct cg2900_chip_dev *dev)
}
/* Just return if there will be no change of baud rate */
- if (uart_default_baud != uart_high_baud)
- return set_baud_rate(uart_info->hu, uart_high_baud);
- else
- return 0;
+ if (uart_default_baud != uart_high_baud) {
+
+ /*
+ * Don't change to high baud yet
+ * as there is bug CG2905/10 PG1 that firmware d/l
+ * has to take place at lower baud
+ * after firmware d/l UART will be switched
+ * to higher baud.
+ */
+ if (CG2905_PG1_1_REV != dev->chip.hci_revision &&
+ CG2910_PG1_REV != dev->chip.hci_revision)
+ return set_baud_rate(uart_info->hu, uart_high_baud);
+ }
+
+ return 0;
}
/**
@@ -2078,6 +2128,8 @@ static int __devinit cg2900_uart_probe(struct platform_device *pdev)
uart_info->chip_dev.t_cb.set_chip_power = uart_set_chip_power;
uart_info->chip_dev.t_cb.chip_startup_finished =
uart_chip_startup_finished;
+ uart_info->chip_dev.t_cb.set_baud_rate =
+ uart_set_baud_rate;
uart_info->chip_dev.pdev = pdev;
uart_info->chip_dev.dev = &pdev->dev;
uart_info->chip_dev.t_data = uart_info;
diff --git a/drivers/staging/cg2900/include/cg2900.h b/drivers/staging/cg2900/include/cg2900.h
index 85b5e03eb3c..e1c1860765a 100644
--- a/drivers/staging/cg2900/include/cg2900.h
+++ b/drivers/staging/cg2900/include/cg2900.h
@@ -124,6 +124,7 @@ struct cg2900_trans_callbacks {
int (*write)(struct cg2900_chip_dev *dev, struct sk_buff *skb);
void (*set_chip_power)(struct cg2900_chip_dev *dev, bool chip_on);
void (*chip_startup_finished)(struct cg2900_chip_dev *dev);
+ void (*set_baud_rate)(struct cg2900_chip_dev *dev, bool low_baud);
};
/**
diff --git a/drivers/staging/cg2900/mfd/cg2900_chip.c b/drivers/staging/cg2900/mfd/cg2900_chip.c
index 5e1a337ed03..2ae418c9f03 100644
--- a/drivers/staging/cg2900/mfd/cg2900_chip.c
+++ b/drivers/staging/cg2900/mfd/cg2900_chip.c
@@ -2570,6 +2570,20 @@ static int cg2900_open(struct cg2900_user_data *user)
err = -EIO;
goto err_free_list_item;
}
+
+ if (CG2905_PG1_1_REV == dev->chip.hci_revision ||
+ CG2910_PG1_REV == dev->chip.hci_revision) {
+ /*
+ * Switch to higher baud rate
+ * Because of bug in CG2905/CG2910 PG1 H/W,
+ * We have to download the ptc/ssf files
+ * at lower baud and then switch to Higher Baud
+ */
+ if (info->chip_dev->t_cb.set_baud_rate)
+ info->chip_dev->t_cb.set_baud_rate(
+ info->chip_dev, false);
+ }
+
}
list_add_tail(&tmp->list, &info->open_channels);