From 0fc8e6dfe05b25df6750e741f83f88d3cac05f3e Mon Sep 17 00:00:00 2001 From: Nitin Dhingra Date: Tue, 27 Dec 2011 14:39:29 +0530 Subject: cg2900: firmware download at 115kbps CG2910/05 There is a bug in CG2910/05 PG1, due to which ARMSS firmware patch has to be downloaded at 115kbps. CQ Ticket for this hardware bug is CM0033243 ST-Ericsson Linux next: Not Tested, ER 373024 ST-Ericsson ID: 373024 ST-Ericsson FOSS-OUT ID: STETL-FOSS-OUT-10019 Change-Id: I4965618f5a1b0ab40f683a5f720a99790d80c3da Depends-On: 09e279e3710a122eccd1ebd4929f79c244c78c9e Signed-off-by: Nitin Dhingra Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/43862 Reviewed-by: QATOOLS --- drivers/staging/cg2900/bluetooth/cg2900_uart.c | 60 ++++++++++++++++++++++++-- drivers/staging/cg2900/include/cg2900.h | 1 + drivers/staging/cg2900/mfd/cg2900_chip.c | 14 ++++++ 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 @@ -1288,6 +1288,44 @@ static int set_baud_rate(struct hci_uart *hu, int baud) return err; } +/** + * 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. @@ -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); -- cgit v1.2.3