Clock control of a Bluetooth UART via hci_ll.c

From: Nick Pelly
Date: Fri Dec 12 2008 - 13:11:42 EST


Hi,

On embedded architectures we need to perform clk_enable() and
clk_disable() on the bluetooth uart when the bluetooth chip enters and
exists low power mode. This needs to be independent of traditional
linux cpu suspend/resume modes that correspond to the linux CPU power
state, because many Bluetooth chips (eg TI BRF6300) have low power
modes that are independent of the linux cpu..

drivers/bluetooth/hci_ll.c knows when the bt chip has entered low
power mode, as it
contains the HCILL state machine. But the clk_enable() and
clk_disable() should be done from the uart driver since that driver
owns the uart clock.

The question is - what interface should hci_ll.c use to tell the uart
driver when to enter and exit low power modes?

Right now we call new functions in our uart driver directly from
hci_ll.c. We know this not going to get accepted upstream, because we
have bypassed the tty and serial_core layers. We are looking for a
better designed solution, which I expect would have to pass through
these layers and use an existing uart_ops (serial_core.h).

A requirements for this interface are that it cannot sleep (hci_ll.c
needs to make these clock requests while holding a spinlock). This
eliminates many uart_ops including .ioctl (uart_ioctl() grabs a
mutex).

.pm is no good because it gets called during suspend() and resume().

>From our investigation, the only really promising option amongst the
existing set of uart_ops seems to be to use .set_termios with a baud
rate of zero. It seems API compliant for the uart driver to then
clk_disable().

clk_enable() could be triggered by hci_ll.c by restoring the old baud
rate. Unfortunately this means hci_ll would need to track the old baud
rate. Also, wakeup can occur via RX traffic on the bluetooth chip in
which case the uart driver needs to trigger the clk_enable(). It would
have to restore the baud rate itself, which may not be API friendly.
It also leaves the question of what happens if userspace changes the
baud rate while the uart is clocked off.

So this approach has its issues, but is the only workable solution we
have right now that uses an existing uart operation.

Any thoughts on this approach? Any other ideas?

Thanks,
Nick
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/