2 * This file is part of Nokia H4P bluetooth driver
4 * Copyright (C) 2005, 2006 Nokia Corporation.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 #include <linux/serial_reg.h>
23 #include <linux/delay.h>
24 #include <linux/clk.h>
30 inline void hci_h4p_outb(struct hci_h4p_info *info, unsigned int offset, u8 val)
32 __raw_writeb(val, info->uart_base + (offset << 2));
35 inline u8 hci_h4p_inb(struct hci_h4p_info *info, unsigned int offset)
37 return __raw_readb(info->uart_base + (offset << 2));
40 void hci_h4p_set_rts(struct hci_h4p_info *info, int active)
44 b = hci_h4p_inb(info, UART_MCR);
49 hci_h4p_outb(info, UART_MCR, b);
52 int hci_h4p_wait_for_cts(struct hci_h4p_info *info, int active,
55 unsigned long timeout;
58 timeout = jiffies + msecs_to_jiffies(timeout_ms);
60 state = hci_h4p_inb(info, UART_MSR) & UART_MSR_CTS;
68 if (time_after(jiffies, timeout))
74 void __hci_h4p_set_auto_ctsrts(struct hci_h4p_info *info, int on, u8 which)
78 lcr = hci_h4p_inb(info, UART_LCR);
79 hci_h4p_outb(info, UART_LCR, 0xbf);
80 b = hci_h4p_inb(info, UART_EFR);
85 hci_h4p_outb(info, UART_EFR, b);
86 hci_h4p_outb(info, UART_LCR, lcr);
89 void hci_h4p_set_auto_ctsrts(struct hci_h4p_info *info, int on, u8 which)
93 spin_lock_irqsave(&info->lock, flags);
94 __hci_h4p_set_auto_ctsrts(info, on, which);
95 spin_unlock_irqrestore(&info->lock, flags);
98 void hci_h4p_change_speed(struct hci_h4p_info *info, unsigned long speed)
100 unsigned int divisor;
103 BT_DBG("Setting speed %lu", speed);
105 if (speed >= 460800) {
106 divisor = UART_CLOCK / 13 / speed;
109 divisor = UART_CLOCK / 16 / speed;
113 /* Make sure UART mode is disabled */
114 hci_h4p_outb(info, UART_OMAP_MDR1, 7);
116 lcr = hci_h4p_inb(info, UART_LCR);
117 hci_h4p_outb(info, UART_LCR, UART_LCR_DLAB); /* Set DLAB */
118 hci_h4p_outb(info, UART_DLL, divisor & 0xff); /* Set speed */
119 hci_h4p_outb(info, UART_DLM, divisor >> 8);
120 hci_h4p_outb(info, UART_LCR, lcr);
122 /* Make sure UART mode is enabled */
123 hci_h4p_outb(info, UART_OMAP_MDR1, mdr1);
126 int hci_h4p_reset_uart(struct hci_h4p_info *info)
131 hci_h4p_outb(info, UART_OMAP_SYSC, UART_SYSC_OMAP_RESET);
132 while (!(hci_h4p_inb(info, UART_OMAP_SYSS) & UART_SYSS_RESETDONE)) {
134 dev_err(info->dev, "hci_h4p: UART reset timeout\n");
143 void hci_h4p_store_regs(struct hci_h4p_info *info)
147 lcr = hci_h4p_inb(info, UART_LCR);
148 hci_h4p_outb(info, UART_LCR, 0xBF);
149 info->dll = hci_h4p_inb(info, UART_DLL);
150 info->dlh = hci_h4p_inb(info, UART_DLM);
151 info->efr = hci_h4p_inb(info, UART_EFR);
152 hci_h4p_outb(info, UART_LCR, lcr);
153 info->mdr1 = hci_h4p_inb(info, UART_OMAP_MDR1);
154 info->ier = hci_h4p_inb(info, UART_IER);
157 void hci_h4p_restore_regs(struct hci_h4p_info *info)
161 hci_h4p_init_uart(info);
163 hci_h4p_outb(info, UART_OMAP_MDR1, 7);
164 lcr = hci_h4p_inb(info, UART_LCR);
165 hci_h4p_outb(info, UART_LCR, 0xBF);
166 hci_h4p_outb(info, UART_DLL, info->dll); /* Set speed */
167 hci_h4p_outb(info, UART_DLM, info->dlh);
168 hci_h4p_outb(info, UART_EFR, info->efr);
169 hci_h4p_outb(info, UART_LCR, lcr);
170 hci_h4p_outb(info, UART_OMAP_MDR1, info->mdr1);
171 hci_h4p_outb(info, UART_IER, info->ier);
174 void hci_h4p_init_uart(struct hci_h4p_info *info)
178 /* Enable and setup FIFO */
179 hci_h4p_outb(info, UART_OMAP_MDR1, 0x00);
181 hci_h4p_outb(info, UART_LCR, 0xbf);
182 efr = hci_h4p_inb(info, UART_EFR);
183 hci_h4p_outb(info, UART_EFR, UART_EFR_ECB);
184 hci_h4p_outb(info, UART_LCR, UART_LCR_DLAB);
185 mcr = hci_h4p_inb(info, UART_MCR);
186 hci_h4p_outb(info, UART_MCR, UART_MCR_TCRTLR);
187 hci_h4p_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO |
188 UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT |
189 (3 << 6) | (0 << 4));
190 hci_h4p_outb(info, UART_LCR, 0xbf);
191 hci_h4p_outb(info, UART_TI752_TLR, 0xed);
192 hci_h4p_outb(info, UART_TI752_TCR, 0xef);
193 hci_h4p_outb(info, UART_EFR, efr);
194 hci_h4p_outb(info, UART_LCR, UART_LCR_DLAB);
195 hci_h4p_outb(info, UART_MCR, 0x00);
196 hci_h4p_outb(info, UART_LCR, UART_LCR_WLEN8);
197 hci_h4p_outb(info, UART_IER, UART_IER_RDI);
198 hci_h4p_outb(info, UART_OMAP_SYSC, (1 << 0) | (1 << 2) | (2 << 3));