Commit Graph

16 Commits

Author SHA1 Message Date
Qipan Li
7282cec903 serial: sirf: transfer more bytes once to decrease interrupts
the current codes send 1 bytes, then after getting TX done interrupt,
send subsequent bytes. it causes redundant interrupts.
for example, if we have 3 bytes in TX buffer, the TX flow is:
1. send 1 byte
2. get TX down interrupt
3. send the left 2 bytes
4. get TX down interrupt

this patch moves to send more bytes and decrease interrupts, the new
flow is:
1. send 3 bytes
2. get TX down interrupt

Signed-off-by: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-07-09 17:37:00 -07:00
Qipan Li
07d410e064 serial: sirf: fix spinlock deadlock issue
commit fb78b81142 provide a workaround for
kernel panic, but bring potential deadlock risk. that is in
sirfsoc_rx_tmo_process_tl while enter into sirfsoc_uart_pio_rx_chars
cpu hold uart_port->lock, if uart interrupt comes cpu enter into
sirfsoc_uart_isr and deadlock occurs in getting uart_port->lock.

the patch replace spin_lock version to spin_lock_irq* version to avoid
spinlock dead lock issue. let function tty_flip_buffer_push in tasklet
outof spin_lock_irq* protect area to avoid add the pair of spin_lock and
spin_unlock for tty_flip_buffer_push.
BTW drop self defined unused spinlock protect of tx_lock/rx_lock.

56274.220464] BUG: spinlock lockup suspected on CPU#0, swapper/0/0
[56274.223648]  lock: 0xc05d9db0, .magic: dead4ead, .owner: swapper/0/0,
	.owner_cpu: 0
	[56274.231278] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G
	O 3.10.35 #1
	[56274.238241] [<c0015530>] (unwind_backtrace+0x0/0xf4) from
	[<c00120d8>] (show_stack+0x10/0x14)
	[56274.246742] [<c00120d8>] (show_stack+0x10/0x14) from
	[<c01b11b0>] (do_raw_spin_lock+0x110/0x184)
	[56274.255501] [<c01b11b0>] (do_raw_spin_lock+0x110/0x184) from
	[<c02124c8>] (sirfsoc_uart_isr+0x20/0x42c)
	[56274.264874] [<c02124c8>] (sirfsoc_uart_isr+0x20/0x42c) from
	[<c0075790>] (handle_irq_event_percpu+0x54/0x17c)
	[56274.274758] [<c0075790>] (handle_irq_event_percpu+0x54/0x17c)
	from [<c00758f4>] (handle_irq_event+0x3c/0x5c)
	[56274.284561] [<c00758f4>] (handle_irq_event+0x3c/0x5c) from
	[<c0077fa0>] (handle_level_irq+0x98/0xfc)
	[56274.293670] [<c0077fa0>] (handle_level_irq+0x98/0xfc) from
	[<c0074f44>] (generic_handle_irq+0x2c/0x3c)
	[56274.302952] [<c0074f44>] (generic_handle_irq+0x2c/0x3c) from
	[<c000ef80>] (handle_IRQ+0x40/0x90)
	[56274.311706] [<c000ef80>] (handle_IRQ+0x40/0x90) from
	[<c000dc80>] (__irq_svc+0x40/0x70)
	[56274.319697] [<c000dc80>] (__irq_svc+0x40/0x70) from
	[<c038113c>] (_raw_spin_unlock_irqrestore+0x10/0x48)
	[56274.329158] [<c038113c>]
	(_raw_spin_unlock_irqrestore+0x10/0x48) from [<c0200034>]
	(tty_port_tty_get+0x58/0x90)
	[56274.339213] [<c0200034>] (tty_port_tty_get+0x58/0x90) from
	[<c0212008>] (sirfsoc_uart_pio_rx_chars+0x1c/0xc8)
	[56274.349097] [<c0212008>]
	(sirfsoc_uart_pio_rx_chars+0x1c/0xc8) from [<c0212ef8>]
	(sirfsoc_rx_tmo_process_tl+0xe4/0x1fc)
	[56274.359853] [<c0212ef8>]
	(sirfsoc_rx_tmo_process_tl+0xe4/0x1fc) from [<c0027c04>]
	(tasklet_action+0x84/0x114)
	[56274.369739] [<c0027c04>] (tasklet_action+0x84/0x114) from
	[<c0027db4>] (__do_softirq+0x120/0x200)
	[56274.378585] [<c0027db4>] (__do_softirq+0x120/0x200) from
	[<c0027f44>] (do_softirq+0x54/0x5c)
	[56274.386998] [<c0027f44>] (do_softirq+0x54/0x5c) from
	[<c00281ec>] (irq_exit+0x9c/0xd0)
	[56274.394899] [<c00281ec>] (irq_exit+0x9c/0xd0) from
	[<c000ef84>] (handle_IRQ+0x44/0x90)
	[56274.402790] [<c000ef84>] (handle_IRQ+0x44/0x90) from
	[<c000dc80>] (__irq_svc+0x40/0x70)
	[56274.410774] [<c000dc80>] (__irq_svc+0x40/0x70) from
	[<c0288af4>] (cpuidle_enter_state+0x50/0xe0)
	[56274.419532] [<c0288af4>] (cpuidle_enter_state+0x50/0xe0) from
	[<c0288c34>] (cpuidle_idle_call+0xb0/0x148)
	[56274.429080] [<c0288c34>] (cpuidle_idle_call+0xb0/0x148) from
	[<c000f3ac>] (arch_cpu_idle+0x8/0x38)
	[56274.438016] [<c000f3ac>] (arch_cpu_idle+0x8/0x38) from
	[<c0059344>] (cpu_startup_entry+0xfc/0x140)
	[56274.446956] [<c0059344>] (cpu_startup_entry+0xfc/0x140) from
	[<c04a3a54>] (start_kernel+0x2d8/0x2e4)

Signed-off-by: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-05-28 12:22:43 -07:00
Barry Song
205c384f73 serial: sirf: move to writel for TXFIFO instead of writeb
All SiRFSoC UART registers are in 32-bits. If we use writeb for
TXFIFO, actually all of 32-bits are still written, for TXTIFO,
only low 8-bits are valid, so in prima2&atlas6, this causes no
problem.
But in the new atlas7, using writeb to write UART registers will
cause an imprecise data abort as HW does check the "wrong" writeb.
So move to writel and this also makes the code consistent with
sirfsoc_uart_pio_tx_chars() in which we use writel.

Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-05-28 12:22:43 -07:00
Qipan Li
9be16b38cf serial: sirf: move to use generic dma dt-binding to get dma channels
instead of using sirf specific dma channel property like "sirf,uart-dma-rx-channel"
and "sirf,uart-dma-tx-channel", here we move to use generic dma dt-binding to get
the channel like:
- sirf,uart-dma-rx-channel = <21>;
- sirf,uart-dma-tx-channel = <2>;
+ dmas = <&dmac1 5>, <&dmac0 2>;
+ dma-names = "rx", "tx";

and we move dma_request_channel() to dma_request_slave_channel(), we don't need to
call sirfsoc dma filter function sirfsoc_dma_filter_id() again.

Signed-off-by: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-02-13 10:36:25 -08:00
Michael Opdenacker
24b6bb0714 serial: sirf: remove duplicate defines
This patch removes duplicate defines in drivers/tty/serial/sirfsoc_uart.h

Signed-off-by: Michael Opdenacker <michael.opdenacker@free-electrons.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-10-29 16:26:54 -07:00
Qipan Li
b60dfbae41 serial: sirf: fix the amount of serial ports
SiRFprimaII has three uart ports and three USP-based ports, so there
are totally six lines instead of five.

Signed-off-by: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-27 16:25:44 -07:00
Qipan Li
459f15c45e serial: sirf: define macro for some magic numbers of USP
this patch clears some magic numbers for offset and bitshift
of USP registers.

Signed-off-by: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-27 16:25:44 -07:00
Qipan Li
8316d04c42 serial: sirf: add DMA support using dmaengine APIs
if we get the valid dma channels from dts, move to use dmaengine to do
rx/tx. because the dma hardware requires dma address and length to be
4bytes aligned, in this driver, we will still use PIO for non-aligned
bytes, and use dma for aligned bytes.

for rx, to keep the dmaengine always active, we use double-buffer, so
we issue two dma_desc at first, and maintain the status of both
1. dma transfer done: update in rx dma finish callback
2. dma buffer is inserted into tty: update in rx dma finish tasklet and
   rx timeout tasklet
so we re-issue the dma_desc only if both 1&2 are finished.

for tx, as we know the actual length for every transfer, we don't need
the above double buffering.

Signed-off-by: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-19 17:13:22 -07:00
Qipan Li
2eb5618de8 serial: sirf: fix the hardware-flow-ctrl for USP-based UART
for USP-based UART, we use two gpios as RTS and CST pins.

Signed-off-by: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-14 18:33:08 -07:00
Barry Song
a343756e07 serial: sirf: drop redundant pinctrl_get_select_default as pinctrl core does it
pinctrl core will get default pinmux, so drop it in the sirfsoc serial driver.

Cc: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-14 18:33:08 -07:00
Qipan Li
5df831117b serial: sirf: make the driver also support USP-based UART
Universal Serial Ports (USP) can be used as PCM, UART, SPI,
I2S etc. this makes the USP work as UART. the basic work
flow is same with UART controller, the main difference will
be offset of registers and bits.

this patch makes the old sirfsoc uart driver support both
sirf UART and USP-based UART by making their differences
become private data.

Signed-off-by: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-12 11:29:53 -07:00
Barry Song
909102db44 serial: sirf: add support for Marco chip
the marco and coming new CSR multiple SoCs have SET/CLR pair for
INTEN registers to avoid some read-modify-write.

this patch adds support for this and make the driver support current
up and coming mp SoCs.

Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-12 11:29:53 -07:00
Barry Song
ac4ce71889 serial: sirf: only use lookup table to set baudrate when ioclk=150MHz
The fast lookup table to set baudrate is only right when ioclk
is 150MHz. for most platforms, ioclk is 150MHz, but some boards
might set ioclk to other frequency.

so re-calc the clk_div_reg when ioclk is not 150MHz. this patch
also gets clk in probe and puts it in remove.

Signed-off-by: Barry Song <Baohua.Song@csr.com>
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-01-17 17:18:55 -08:00
Barry Song
5425e03f97 serial: sirf: add support for new SiRFmarco SMP SoC
CSR SiRFmarco's UART IP is same with SiRFprimaII except that
it has two more uart ports.
this patch makes the old driver support new SiRFmarco as well:
1. add .compatible = "sirf,marco-uart" to OF match table
2. add two ports in the port table
3. take spin_lock in isr to avoid the conflict of threads opening
uart on CPU1 and isr running on CPU0.
For 3, we did see some problems on SiRFmarco as SiRFmarco is a
SMP SoC but the old SiRFprimaII is UP.

Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-01-15 21:54:40 -08:00
Linus Walleij
5c9bdc3f52 serial/sirf: fixup for changes to pin control
We changed the signature of the pin multiplexing functions to
handle any pin business, so fix up the Sirf driver to call this
new interface and rename some variables to make the semantics
understandable.

Cc: linux-serial@vger.kernel.org
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2012-02-22 17:59:12 +01:00
Rong Wang
161e773cbd UART: add CSR SiRFprimaII SoC on-chip uart drivers
SiRFprimaII is the latest generation application processor from CSR’s
multi-function SoC product family.
The SoC support codes are in arch/arm/mach-prima2 from Linux mainline
3.0.

There are three dedicated UARTs in system. This patch adds basic driver
support for them.

It has used the newest pinmux subsystem from Linus Walleij.

Cc: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Rong Wang <Rong.Wang@csr.com>
Signed-off-by: Bin Shi <Bin.Shi@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2011-11-17 11:46:04 -08:00