Merge 4.0-rc3 into tty-testing

This resolves a merge issue in drivers/tty/serial/8250/8250_pci.c

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Greg Kroah-Hartman 2015-03-09 07:08:37 +01:00
commit becba85f0e
40 changed files with 1422 additions and 2132 deletions

View File

@ -43,10 +43,6 @@ config EARLY_PRINTK
with klogd/syslogd or the X server. You should normally N here,
unless you want to debug such a crash.
config EARLY_PRINTK_INTEL_MID
bool "Early printk for Intel MID platform support"
depends on EARLY_PRINTK && X86_INTEL_MID
config EARLY_PRINTK_DBGP
bool "Early printk via EHCI debug port"
depends on EARLY_PRINTK && PCI

View File

@ -136,9 +136,6 @@ extern enum intel_mid_timer_options intel_mid_timer_options;
#define SFI_MTMR_MAX_NUM 8
#define SFI_MRTC_MAX 8
extern struct console early_hsu_console;
extern void hsu_early_console_init(const char *);
extern void intel_scu_devices_create(void);
extern void intel_scu_devices_destroy(void);

View File

@ -375,12 +375,6 @@ static int __init setup_early_printk(char *buf)
if (!strncmp(buf, "xen", 3))
early_console_register(&xenboot_console, keep);
#endif
#ifdef CONFIG_EARLY_PRINTK_INTEL_MID
if (!strncmp(buf, "hsu", 3)) {
hsu_early_console_init(buf + 3);
early_console_register(&early_hsu_console, keep);
}
#endif
#ifdef CONFIG_EARLY_PRINTK_EFI
if (!strncmp(buf, "efi", 3))
early_console_register(&early_efi_console, keep);

View File

@ -1,5 +1,4 @@
obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o intel_mid_vrtc.o mfld.o mrfl.o
obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_intel_mid.o
# SFI specific code
ifdef CONFIG_X86_INTEL_MID

View File

@ -1,112 +0,0 @@
/*
* early_printk_intel_mid.c - early consoles for Intel MID platforms
*
* Copyright (c) 2008-2010, Intel Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*/
/*
* This file implements early console named hsu.
* hsu is based on a High Speed UART device which only exists in the Medfield
* platform
*/
#include <linux/serial_reg.h>
#include <linux/serial_mfd.h>
#include <linux/console.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <asm/fixmap.h>
#include <asm/pgtable.h>
#include <asm/intel-mid.h>
/*
* Following is the early console based on Medfield HSU (High
* Speed UART) device.
*/
#define HSU_PORT_BASE 0xffa28080
static void __iomem *phsu;
void hsu_early_console_init(const char *s)
{
unsigned long paddr, port = 0;
u8 lcr;
/*
* Select the early HSU console port if specified by user in the
* kernel command line.
*/
if (*s && !kstrtoul(s, 10, &port))
port = clamp_val(port, 0, 2);
paddr = HSU_PORT_BASE + port * 0x80;
phsu = (void __iomem *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, paddr);
/* Disable FIFO */
writeb(0x0, phsu + UART_FCR);
/* Set to default 115200 bps, 8n1 */
lcr = readb(phsu + UART_LCR);
writeb((0x80 | lcr), phsu + UART_LCR);
writeb(0x18, phsu + UART_DLL);
writeb(lcr, phsu + UART_LCR);
writel(0x3600, phsu + UART_MUL*4);
writeb(0x8, phsu + UART_MCR);
writeb(0x7, phsu + UART_FCR);
writeb(0x3, phsu + UART_LCR);
/* Clear IRQ status */
readb(phsu + UART_LSR);
readb(phsu + UART_RX);
readb(phsu + UART_IIR);
readb(phsu + UART_MSR);
/* Enable FIFO */
writeb(0x7, phsu + UART_FCR);
}
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
static void early_hsu_putc(char ch)
{
unsigned int timeout = 10000; /* 10ms */
u8 status;
while (--timeout) {
status = readb(phsu + UART_LSR);
if (status & BOTH_EMPTY)
break;
udelay(1);
}
/* Only write the char when there was no timeout */
if (timeout)
writeb(ch, phsu + UART_TX);
}
static void early_hsu_write(struct console *con, const char *str, unsigned n)
{
int i;
for (i = 0; i < n && *str; i++) {
if (*str == '\n')
early_hsu_putc('\r');
early_hsu_putc(*str);
str++;
}
}
struct console early_hsu_console = {
.name = "earlyhsu",
.write = early_hsu_write,
.flags = CON_PRINTBUFFER,
.index = -1,
};

View File

@ -125,6 +125,8 @@ config FSL_DMA
EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on
some Txxx and Bxxx parts.
source "drivers/dma/hsu/Kconfig"
config MPC512X_DMA
tristate "Freescale MPC512x built-in DMA engine support"
depends on PPC_MPC512x || PPC_MPC831x

View File

@ -11,6 +11,7 @@ obj-$(CONFIG_DMATEST) += dmatest.o
obj-$(CONFIG_INTEL_IOATDMA) += ioat/
obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
obj-$(CONFIG_FSL_DMA) += fsldma.o
obj-$(CONFIG_HSU_DMA) += hsu/
obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
obj-$(CONFIG_MV_XOR) += mv_xor.o

14
drivers/dma/hsu/Kconfig Normal file
View File

@ -0,0 +1,14 @@
# DMA engine configuration for hsu
config HSU_DMA
tristate "High Speed UART DMA support"
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
config HSU_DMA_PCI
tristate "High Speed UART DMA PCI driver"
depends on PCI
select HSU_DMA
help
Support the High Speed UART DMA on the platfroms that
enumerate it as a PCI device. For example, Intel Medfield
has integrated this HSU DMA controller.

5
drivers/dma/hsu/Makefile Normal file
View File

@ -0,0 +1,5 @@
obj-$(CONFIG_HSU_DMA) += hsu_dma.o
hsu_dma-objs := hsu.o
obj-$(CONFIG_HSU_DMA_PCI) += hsu_dma_pci.o
hsu_dma_pci-objs := pci.o

504
drivers/dma/hsu/hsu.c Normal file
View File

@ -0,0 +1,504 @@
/*
* Core driver for the High Speed UART DMA
*
* Copyright (C) 2015 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*
* Partially based on the bits found in drivers/tty/serial/mfd.c.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* DMA channel allocation:
* 1. Even number chans are used for DMA Read (UART TX), odd chans for DMA
* Write (UART RX).
* 2. 0/1 channel are assigned to port 0, 2/3 chan to port 1, 4/5 chan to
* port 3, and so on.
*/
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include "hsu.h"
#define HSU_DMA_BUSWIDTHS \
BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) | \
BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_16_BYTES)
static inline void hsu_chan_disable(struct hsu_dma_chan *hsuc)
{
hsu_chan_writel(hsuc, HSU_CH_CR, 0);
}
static inline void hsu_chan_enable(struct hsu_dma_chan *hsuc)
{
u32 cr = HSU_CH_CR_CHA;
if (hsuc->direction == DMA_MEM_TO_DEV)
cr &= ~HSU_CH_CR_CHD;
else if (hsuc->direction == DMA_DEV_TO_MEM)
cr |= HSU_CH_CR_CHD;
hsu_chan_writel(hsuc, HSU_CH_CR, cr);
}
static void hsu_dma_chan_start(struct hsu_dma_chan *hsuc)
{
struct dma_slave_config *config = &hsuc->config;
struct hsu_dma_desc *desc = hsuc->desc;
u32 bsr, mtsr;
u32 dcr = HSU_CH_DCR_CHSOE | HSU_CH_DCR_CHEI;
unsigned int i, count;
if (hsuc->direction == DMA_MEM_TO_DEV) {
bsr = config->dst_maxburst;
mtsr = config->dst_addr_width;
} else if (hsuc->direction == DMA_DEV_TO_MEM) {
bsr = config->src_maxburst;
mtsr = config->src_addr_width;
} else {
/* Not supported direction */
return;
}
hsu_chan_disable(hsuc);
hsu_chan_writel(hsuc, HSU_CH_DCR, 0);
hsu_chan_writel(hsuc, HSU_CH_BSR, bsr);
hsu_chan_writel(hsuc, HSU_CH_MTSR, mtsr);
/* Set descriptors */
count = (desc->nents - desc->active) % HSU_DMA_CHAN_NR_DESC;
for (i = 0; i < count; i++) {
hsu_chan_writel(hsuc, HSU_CH_DxSAR(i), desc->sg[i].addr);
hsu_chan_writel(hsuc, HSU_CH_DxTSR(i), desc->sg[i].len);
/* Prepare value for DCR */
dcr |= HSU_CH_DCR_DESCA(i);
dcr |= HSU_CH_DCR_CHTOI(i); /* timeout bit, see HSU Errata 1 */
desc->active++;
}
/* Only for the last descriptor in the chain */
dcr |= HSU_CH_DCR_CHSOD(count - 1);
dcr |= HSU_CH_DCR_CHDI(count - 1);
hsu_chan_writel(hsuc, HSU_CH_DCR, dcr);
hsu_chan_enable(hsuc);
}
static void hsu_dma_stop_channel(struct hsu_dma_chan *hsuc)
{
unsigned long flags;
spin_lock_irqsave(&hsuc->lock, flags);
hsu_chan_disable(hsuc);
hsu_chan_writel(hsuc, HSU_CH_DCR, 0);
spin_unlock_irqrestore(&hsuc->lock, flags);
}
static void hsu_dma_start_channel(struct hsu_dma_chan *hsuc)
{
unsigned long flags;
spin_lock_irqsave(&hsuc->lock, flags);
hsu_dma_chan_start(hsuc);
spin_unlock_irqrestore(&hsuc->lock, flags);
}
static void hsu_dma_start_transfer(struct hsu_dma_chan *hsuc)
{
struct virt_dma_desc *vdesc;
/* Get the next descriptor */
vdesc = vchan_next_desc(&hsuc->vchan);
if (!vdesc) {
hsuc->desc = NULL;
return;
}
list_del(&vdesc->node);
hsuc->desc = to_hsu_dma_desc(vdesc);
/* Start the channel with a new descriptor */
hsu_dma_start_channel(hsuc);
}
static u32 hsu_dma_chan_get_sr(struct hsu_dma_chan *hsuc)
{
unsigned long flags;
u32 sr;
spin_lock_irqsave(&hsuc->lock, flags);
sr = hsu_chan_readl(hsuc, HSU_CH_SR);
spin_unlock_irqrestore(&hsuc->lock, flags);
return sr;
}
irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr)
{
struct hsu_dma_chan *hsuc;
struct hsu_dma_desc *desc;
unsigned long flags;
u32 sr;
/* Sanity check */
if (nr >= chip->pdata->nr_channels)
return IRQ_NONE;
hsuc = &chip->hsu->chan[nr];
/*
* No matter what situation, need read clear the IRQ status
* There is a bug, see Errata 5, HSD 2900918
*/
sr = hsu_dma_chan_get_sr(hsuc);
if (!sr)
return IRQ_NONE;
/* Timeout IRQ, need wait some time, see Errata 2 */
if (hsuc->direction == DMA_DEV_TO_MEM && (sr & HSU_CH_SR_DESCTO_ANY))
udelay(2);
sr &= ~HSU_CH_SR_DESCTO_ANY;
if (!sr)
return IRQ_HANDLED;
spin_lock_irqsave(&hsuc->vchan.lock, flags);
desc = hsuc->desc;
if (desc) {
if (sr & HSU_CH_SR_CHE) {
desc->status = DMA_ERROR;
} else if (desc->active < desc->nents) {
hsu_dma_start_channel(hsuc);
} else {
vchan_cookie_complete(&desc->vdesc);
desc->status = DMA_COMPLETE;
hsu_dma_start_transfer(hsuc);
}
}
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
return IRQ_HANDLED;
}
EXPORT_SYMBOL_GPL(hsu_dma_irq);
static struct hsu_dma_desc *hsu_dma_alloc_desc(unsigned int nents)
{
struct hsu_dma_desc *desc;
desc = kzalloc(sizeof(*desc), GFP_ATOMIC);
if (!desc)
return NULL;
desc->sg = kcalloc(nents, sizeof(*desc->sg), GFP_ATOMIC);
if (!desc->sg) {
kfree(desc);
return NULL;
}
return desc;
}
static void hsu_dma_desc_free(struct virt_dma_desc *vdesc)
{
struct hsu_dma_desc *desc = to_hsu_dma_desc(vdesc);
kfree(desc->sg);
kfree(desc);
}
static struct dma_async_tx_descriptor *hsu_dma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags, void *context)
{
struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
struct hsu_dma_desc *desc;
struct scatterlist *sg;
unsigned int i;
desc = hsu_dma_alloc_desc(sg_len);
if (!desc)
return NULL;
for_each_sg(sgl, sg, sg_len, i) {
desc->sg[i].addr = sg_dma_address(sg);
desc->sg[i].len = sg_dma_len(sg);
}
desc->nents = sg_len;
desc->direction = direction;
desc->active = 0;
desc->status = DMA_IN_PROGRESS;
return vchan_tx_prep(&hsuc->vchan, &desc->vdesc, flags);
}
static void hsu_dma_issue_pending(struct dma_chan *chan)
{
struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
unsigned long flags;
spin_lock_irqsave(&hsuc->vchan.lock, flags);
if (vchan_issue_pending(&hsuc->vchan) && !hsuc->desc)
hsu_dma_start_transfer(hsuc);
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
}
static size_t hsu_dma_desc_size(struct hsu_dma_desc *desc)
{
size_t bytes = 0;
unsigned int i;
for (i = desc->active; i < desc->nents; i++)
bytes += desc->sg[i].len;
return bytes;
}
static size_t hsu_dma_active_desc_size(struct hsu_dma_chan *hsuc)
{
struct hsu_dma_desc *desc = hsuc->desc;
size_t bytes = hsu_dma_desc_size(desc);
int i;
unsigned long flags;
spin_lock_irqsave(&hsuc->lock, flags);
i = desc->active % HSU_DMA_CHAN_NR_DESC;
do {
bytes += hsu_chan_readl(hsuc, HSU_CH_DxTSR(i));
} while (--i >= 0);
spin_unlock_irqrestore(&hsuc->lock, flags);
return bytes;
}
static enum dma_status hsu_dma_tx_status(struct dma_chan *chan,
dma_cookie_t cookie, struct dma_tx_state *state)
{
struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
struct virt_dma_desc *vdesc;
enum dma_status status;
size_t bytes;
unsigned long flags;
status = dma_cookie_status(chan, cookie, state);
if (status == DMA_COMPLETE)
return status;
spin_lock_irqsave(&hsuc->vchan.lock, flags);
vdesc = vchan_find_desc(&hsuc->vchan, cookie);
if (hsuc->desc && cookie == hsuc->desc->vdesc.tx.cookie) {
bytes = hsu_dma_active_desc_size(hsuc);
dma_set_residue(state, bytes);
status = hsuc->desc->status;
} else if (vdesc) {
bytes = hsu_dma_desc_size(to_hsu_dma_desc(vdesc));
dma_set_residue(state, bytes);
}
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
return status;
}
static int hsu_dma_slave_config(struct dma_chan *chan,
struct dma_slave_config *config)
{
struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
/* Check if chan will be configured for slave transfers */
if (!is_slave_direction(config->direction))
return -EINVAL;
memcpy(&hsuc->config, config, sizeof(hsuc->config));
return 0;
}
static void hsu_dma_chan_deactivate(struct hsu_dma_chan *hsuc)
{
unsigned long flags;
spin_lock_irqsave(&hsuc->lock, flags);
hsu_chan_disable(hsuc);
spin_unlock_irqrestore(&hsuc->lock, flags);
}
static void hsu_dma_chan_activate(struct hsu_dma_chan *hsuc)
{
unsigned long flags;
spin_lock_irqsave(&hsuc->lock, flags);
hsu_chan_enable(hsuc);
spin_unlock_irqrestore(&hsuc->lock, flags);
}
static int hsu_dma_pause(struct dma_chan *chan)
{
struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
unsigned long flags;
spin_lock_irqsave(&hsuc->vchan.lock, flags);
if (hsuc->desc && hsuc->desc->status == DMA_IN_PROGRESS) {
hsu_dma_chan_deactivate(hsuc);
hsuc->desc->status = DMA_PAUSED;
}
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
return 0;
}
static int hsu_dma_resume(struct dma_chan *chan)
{
struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
unsigned long flags;
spin_lock_irqsave(&hsuc->vchan.lock, flags);
if (hsuc->desc && hsuc->desc->status == DMA_PAUSED) {
hsuc->desc->status = DMA_IN_PROGRESS;
hsu_dma_chan_activate(hsuc);
}
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
return 0;
}
static int hsu_dma_terminate_all(struct dma_chan *chan)
{
struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
unsigned long flags;
LIST_HEAD(head);
spin_lock_irqsave(&hsuc->vchan.lock, flags);
hsu_dma_stop_channel(hsuc);
hsuc->desc = NULL;
vchan_get_all_descriptors(&hsuc->vchan, &head);
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
vchan_dma_desc_free_list(&hsuc->vchan, &head);
return 0;
}
static int hsu_dma_alloc_chan_resources(struct dma_chan *chan)
{
return 0;
}
static void hsu_dma_free_chan_resources(struct dma_chan *chan)
{
vchan_free_chan_resources(to_virt_chan(chan));
}
int hsu_dma_probe(struct hsu_dma_chip *chip)
{
struct hsu_dma *hsu;
struct hsu_dma_platform_data *pdata = chip->pdata;
void __iomem *addr = chip->regs + chip->offset;
unsigned short i;
int ret;
hsu = devm_kzalloc(chip->dev, sizeof(*hsu), GFP_KERNEL);
if (!hsu)
return -ENOMEM;
chip->hsu = hsu;
if (!pdata) {
pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
chip->pdata = pdata;
/* Guess nr_channels from the IO space length */
pdata->nr_channels = (chip->length - chip->offset) /
HSU_DMA_CHAN_LENGTH;
}
hsu->chan = devm_kcalloc(chip->dev, pdata->nr_channels,
sizeof(*hsu->chan), GFP_KERNEL);
if (!hsu->chan)
return -ENOMEM;
INIT_LIST_HEAD(&hsu->dma.channels);
for (i = 0; i < pdata->nr_channels; i++) {
struct hsu_dma_chan *hsuc = &hsu->chan[i];
hsuc->vchan.desc_free = hsu_dma_desc_free;
vchan_init(&hsuc->vchan, &hsu->dma);
hsuc->direction = (i & 0x1) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
hsuc->reg = addr + i * HSU_DMA_CHAN_LENGTH;
spin_lock_init(&hsuc->lock);
}
dma_cap_set(DMA_SLAVE, hsu->dma.cap_mask);
dma_cap_set(DMA_PRIVATE, hsu->dma.cap_mask);
hsu->dma.device_alloc_chan_resources = hsu_dma_alloc_chan_resources;
hsu->dma.device_free_chan_resources = hsu_dma_free_chan_resources;
hsu->dma.device_prep_slave_sg = hsu_dma_prep_slave_sg;
hsu->dma.device_issue_pending = hsu_dma_issue_pending;
hsu->dma.device_tx_status = hsu_dma_tx_status;
hsu->dma.device_config = hsu_dma_slave_config;
hsu->dma.device_pause = hsu_dma_pause;
hsu->dma.device_resume = hsu_dma_resume;
hsu->dma.device_terminate_all = hsu_dma_terminate_all;
hsu->dma.src_addr_widths = HSU_DMA_BUSWIDTHS;
hsu->dma.dst_addr_widths = HSU_DMA_BUSWIDTHS;
hsu->dma.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
hsu->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
hsu->dma.dev = chip->dev;
ret = dma_async_device_register(&hsu->dma);
if (ret)
return ret;
dev_info(chip->dev, "Found HSU DMA, %d channels\n", pdata->nr_channels);
return 0;
}
EXPORT_SYMBOL_GPL(hsu_dma_probe);
int hsu_dma_remove(struct hsu_dma_chip *chip)
{
struct hsu_dma *hsu = chip->hsu;
unsigned short i;
dma_async_device_unregister(&hsu->dma);
for (i = 0; i < chip->pdata->nr_channels; i++) {
struct hsu_dma_chan *hsuc = &hsu->chan[i];
tasklet_kill(&hsuc->vchan.task);
}
return 0;
}
EXPORT_SYMBOL_GPL(hsu_dma_remove);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("High Speed UART DMA core driver");
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");

118
drivers/dma/hsu/hsu.h Normal file
View File

@ -0,0 +1,118 @@
/*
* Driver for the High Speed UART DMA
*
* Copyright (C) 2015 Intel Corporation
*
* Partially based on the bits found in drivers/tty/serial/mfd.c.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __DMA_HSU_H__
#define __DMA_HSU_H__
#include <linux/spinlock.h>
#include <linux/dma/hsu.h>
#include "../virt-dma.h"
#define HSU_CH_SR 0x00 /* channel status */
#define HSU_CH_CR 0x04 /* channel control */
#define HSU_CH_DCR 0x08 /* descriptor control */
#define HSU_CH_BSR 0x10 /* FIFO buffer size */
#define HSU_CH_MTSR 0x14 /* minimum transfer size */
#define HSU_CH_DxSAR(x) (0x20 + 8 * (x)) /* desc start addr */
#define HSU_CH_DxTSR(x) (0x24 + 8 * (x)) /* desc transfer size */
#define HSU_CH_D0SAR 0x20 /* desc 0 start addr */
#define HSU_CH_D0TSR 0x24 /* desc 0 transfer size */
#define HSU_CH_D1SAR 0x28
#define HSU_CH_D1TSR 0x2c
#define HSU_CH_D2SAR 0x30
#define HSU_CH_D2TSR 0x34
#define HSU_CH_D3SAR 0x38
#define HSU_CH_D3TSR 0x3c
#define HSU_DMA_CHAN_NR_DESC 4
#define HSU_DMA_CHAN_LENGTH 0x40
/* Bits in HSU_CH_SR */
#define HSU_CH_SR_DESCTO(x) BIT(8 + (x))
#define HSU_CH_SR_DESCTO_ANY (BIT(11) | BIT(10) | BIT(9) | BIT(8))
#define HSU_CH_SR_CHE BIT(15)
/* Bits in HSU_CH_CR */
#define HSU_CH_CR_CHA BIT(0)
#define HSU_CH_CR_CHD BIT(1)
/* Bits in HSU_CH_DCR */
#define HSU_CH_DCR_DESCA(x) BIT(0 + (x))
#define HSU_CH_DCR_CHSOD(x) BIT(8 + (x))
#define HSU_CH_DCR_CHSOTO BIT(14)
#define HSU_CH_DCR_CHSOE BIT(15)
#define HSU_CH_DCR_CHDI(x) BIT(16 + (x))
#define HSU_CH_DCR_CHEI BIT(23)
#define HSU_CH_DCR_CHTOI(x) BIT(24 + (x))
struct hsu_dma_sg {
dma_addr_t addr;
unsigned int len;
};
struct hsu_dma_desc {
struct virt_dma_desc vdesc;
enum dma_transfer_direction direction;
struct hsu_dma_sg *sg;
unsigned int nents;
unsigned int active;
enum dma_status status;
};
static inline struct hsu_dma_desc *to_hsu_dma_desc(struct virt_dma_desc *vdesc)
{
return container_of(vdesc, struct hsu_dma_desc, vdesc);
}
struct hsu_dma_chan {
struct virt_dma_chan vchan;
void __iomem *reg;
spinlock_t lock;
/* hardware configuration */
enum dma_transfer_direction direction;
struct dma_slave_config config;
struct hsu_dma_desc *desc;
};
static inline struct hsu_dma_chan *to_hsu_dma_chan(struct dma_chan *chan)
{
return container_of(chan, struct hsu_dma_chan, vchan.chan);
}
static inline u32 hsu_chan_readl(struct hsu_dma_chan *hsuc, int offset)
{
return readl(hsuc->reg + offset);
}
static inline void hsu_chan_writel(struct hsu_dma_chan *hsuc, int offset,
u32 value)
{
writel(value, hsuc->reg + offset);
}
struct hsu_dma {
struct dma_device dma;
/* channels */
struct hsu_dma_chan *chan;
};
static inline struct hsu_dma *to_hsu_dma(struct dma_device *ddev)
{
return container_of(ddev, struct hsu_dma, dma);
}
#endif /* __DMA_HSU_H__ */

123
drivers/dma/hsu/pci.c Normal file
View File

@ -0,0 +1,123 @@
/*
* PCI driver for the High Speed UART DMA
*
* Copyright (C) 2015 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*
* Partially based on the bits found in drivers/tty/serial/mfd.c.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "hsu.h"
#define HSU_PCI_DMASR 0x00
#define HSU_PCI_DMAISR 0x04
#define HSU_PCI_CHAN_OFFSET 0x100
static irqreturn_t hsu_pci_irq(int irq, void *dev)
{
struct hsu_dma_chip *chip = dev;
u32 dmaisr;
unsigned short i;
irqreturn_t ret = IRQ_NONE;
dmaisr = readl(chip->regs + HSU_PCI_DMAISR);
for (i = 0; i < chip->pdata->nr_channels; i++) {
if (dmaisr & 0x1)
ret |= hsu_dma_irq(chip, i);
dmaisr >>= 1;
}
return ret;
}
static int hsu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct hsu_dma_chip *chip;
int ret;
ret = pcim_enable_device(pdev);
if (ret)
return ret;
ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
if (ret) {
dev_err(&pdev->dev, "I/O memory remapping failed\n");
return ret;
}
pci_set_master(pdev);
pci_try_set_mwi(pdev);
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (ret)
return ret;
ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (ret)
return ret;
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
chip->dev = &pdev->dev;
chip->regs = pcim_iomap_table(pdev)[0];
chip->length = pci_resource_len(pdev, 0);
chip->offset = HSU_PCI_CHAN_OFFSET;
chip->irq = pdev->irq;
pci_enable_msi(pdev);
ret = hsu_dma_probe(chip);
if (ret)
return ret;
ret = request_irq(chip->irq, hsu_pci_irq, 0, "hsu_dma_pci", chip);
if (ret)
goto err_register_irq;
pci_set_drvdata(pdev, chip);
return 0;
err_register_irq:
hsu_dma_remove(chip);
return ret;
}
static void hsu_pci_remove(struct pci_dev *pdev)
{
struct hsu_dma_chip *chip = pci_get_drvdata(pdev);
free_irq(chip->irq, chip);
hsu_dma_remove(chip);
}
static const struct pci_device_id hsu_pci_id_table[] = {
{ PCI_VDEVICE(INTEL, 0x081e), 0 },
{ }
};
MODULE_DEVICE_TABLE(pci, hsu_pci_id_table);
static struct pci_driver hsu_pci_driver = {
.name = "hsu_dma_pci",
.id_table = hsu_pci_id_table,
.probe = hsu_pci_probe,
.remove = hsu_pci_remove,
};
module_pci_driver(hsu_pci_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("High Speed UART DMA PCI driver");
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");

View File

@ -416,18 +416,24 @@ static int dw8250_probe(struct platform_device *pdev)
{
struct uart_8250_port uart = {};
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
int irq = platform_get_irq(pdev, 0);
struct dw8250_data *data;
int err;
if (!regs || !irq) {
dev_err(&pdev->dev, "no registers/irq defined\n");
if (!regs) {
dev_err(&pdev->dev, "no registers defined\n");
return -EINVAL;
}
if (irq < 0) {
if (irq != -EPROBE_DEFER)
dev_err(&pdev->dev, "cannot get irq\n");
return irq;
}
spin_lock_init(&uart.port.lock);
uart.port.mapbase = regs->start;
uart.port.irq = irq->start;
uart.port.irq = irq;
uart.port.handle_irq = dw8250_handle_irq;
uart.port.pm = dw8250_do_pm;
uart.port.type = PORT_8250;
@ -640,3 +646,4 @@ module_platform_driver(dw8250_platform_driver);
MODULE_AUTHOR("Jamie Iles");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
MODULE_ALIAS("platform:dw-apb-uart");

View File

@ -27,6 +27,7 @@
#include <linux/dmaengine.h>
#include <linux/platform_data/dma-dw.h>
#include <linux/platform_data/dma-hsu.h>
#include "8250.h"
@ -1525,6 +1526,148 @@ byt_serial_setup(struct serial_private *priv,
return ret;
}
#define INTEL_MID_UART_PS 0x30
#define INTEL_MID_UART_MUL 0x34
static void intel_mid_set_termios_50M(struct uart_port *p,
struct ktermios *termios,
struct ktermios *old)
{
unsigned int baud = tty_termios_baud_rate(termios);
u32 ps, mul;
/*
* The uart clk is 50Mhz, and the baud rate come from:
* baud = 50M * MUL / (DIV * PS * DLAB)
*
* For those basic low baud rate we can get the direct
* scalar from 2746800, like 115200 = 2746800/24. For those
* higher baud rate, we handle them case by case, mainly by
* adjusting the MUL/PS registers, and DIV register is kept
* as default value 0x3d09 to make things simple.
*/
ps = 0x10;
switch (baud) {
case 500000:
case 1000000:
case 1500000:
case 3000000:
mul = 0x3a98;
p->uartclk = 48000000;
break;
case 2000000:
case 4000000:
mul = 0x2710;
ps = 0x08;
p->uartclk = 64000000;
break;
case 2500000:
mul = 0x30d4;
p->uartclk = 40000000;
break;
case 3500000:
mul = 0x3345;
ps = 0x0c;
p->uartclk = 56000000;
break;
default:
mul = 0x2400;
p->uartclk = 29491200;
}
writel(ps, p->membase + INTEL_MID_UART_PS); /* set PS */
writel(mul, p->membase + INTEL_MID_UART_MUL); /* set MUL */
serial8250_do_set_termios(p, termios, old);
}
static bool intel_mid_dma_filter(struct dma_chan *chan, void *param)
{
struct hsu_dma_slave *s = param;
if (s->dma_dev != chan->device->dev || s->chan_id != chan->chan_id)
return false;
chan->private = s;
return true;
}
static int intel_mid_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx,
int index, struct pci_dev *dma_dev)
{
struct device *dev = port->port.dev;
struct uart_8250_dma *dma;
struct hsu_dma_slave *tx_param, *rx_param;
dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
if (!dma)
return -ENOMEM;
tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
if (!tx_param)
return -ENOMEM;
rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
if (!rx_param)
return -ENOMEM;
rx_param->chan_id = index * 2 + 1;
tx_param->chan_id = index * 2;
dma->rxconf.src_maxburst = 64;
dma->txconf.dst_maxburst = 64;
rx_param->dma_dev = &dma_dev->dev;
tx_param->dma_dev = &dma_dev->dev;
dma->fn = intel_mid_dma_filter;
dma->rx_param = rx_param;
dma->tx_param = tx_param;
port->port.type = PORT_16750;
port->port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE;
port->dma = dma;
return pci_default_setup(priv, board, port, idx);
}
#define PCI_DEVICE_ID_INTEL_PNW_UART1 0x081b
#define PCI_DEVICE_ID_INTEL_PNW_UART2 0x081c
#define PCI_DEVICE_ID_INTEL_PNW_UART3 0x081d
static int pnw_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
struct pci_dev *pdev = priv->dev;
struct pci_dev *dma_dev;
int index;
switch (pdev->device) {
case PCI_DEVICE_ID_INTEL_PNW_UART1:
index = 0;
break;
case PCI_DEVICE_ID_INTEL_PNW_UART2:
index = 1;
break;
case PCI_DEVICE_ID_INTEL_PNW_UART3:
index = 2;
break;
default:
return -EINVAL;
}
dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 3));
port->port.set_termios = intel_mid_set_termios_50M;
return intel_mid_serial_setup(priv, board, port, idx, index, dma_dev);
}
static int
pci_omegapci_setup(struct serial_private *priv,
const struct pciserial_board *board,
@ -1987,6 +2130,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.setup = byt_serial_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_PNW_UART1,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pnw_serial_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_PNW_UART2,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pnw_serial_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_PNW_UART3,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pnw_serial_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_BSW_UART1,
@ -2864,6 +3028,7 @@ enum pci_board_num_t {
pbn_ADDIDATA_PCIe_8_3906250,
pbn_ce4100_1_115200,
pbn_byt,
pbn_pnw,
pbn_qrk,
pbn_omegapci,
pbn_NETMOS9900_2s_115200,
@ -3630,6 +3795,11 @@ static struct pciserial_board pci_boards[] = {
.uart_offset = 0x80,
.reg_shift = 2,
},
[pbn_pnw] = {
.flags = FL_BASE0,
.num_ports = 1,
.base_baud = 115200,
},
[pbn_qrk] = {
.flags = FL_BASE0,
.num_ports = 1,
@ -4006,41 +4176,41 @@ static void pciserial_remove_one(struct pci_dev *dev)
pci_disable_device(dev);
}
#ifdef CONFIG_PM
static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
#ifdef CONFIG_PM_SLEEP
static int pciserial_suspend_one(struct device *dev)
{
struct serial_private *priv = pci_get_drvdata(dev);
struct pci_dev *pdev = to_pci_dev(dev);
struct serial_private *priv = pci_get_drvdata(pdev);
if (priv)
pciserial_suspend_ports(priv);
pci_save_state(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
}
static int pciserial_resume_one(struct pci_dev *dev)
static int pciserial_resume_one(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct serial_private *priv = pci_get_drvdata(pdev);
int err;
struct serial_private *priv = pci_get_drvdata(dev);
pci_set_power_state(dev, PCI_D0);
pci_restore_state(dev);
if (priv) {
/*
* The device may have been disabled. Re-enable it.
*/
err = pci_enable_device(dev);
err = pci_enable_device(pdev);
/* FIXME: We cannot simply error out here */
if (err)
dev_err(&dev->dev, "Unable to re-enable ports, trying to continue.\n");
dev_err(dev, "Unable to re-enable ports, trying to continue.\n");
pciserial_resume_ports(priv);
}
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(pciserial_pm_ops, pciserial_suspend_one,
pciserial_resume_one);
static struct pci_device_id serial_pci_tbl[] = {
/* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
{ PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
@ -5362,6 +5532,19 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
pbn_byt },
/*
* Intel Penwell
*/
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART1,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_pnw},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_pnw},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART3,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_pnw},
/*
* Intel Quark x1000
*/
@ -5510,10 +5693,9 @@ static struct pci_driver serial_pci_driver = {
.name = "serial",
.probe = pciserial_init_one,
.remove = pciserial_remove_one,
#ifdef CONFIG_PM
.suspend = pciserial_suspend_one,
.resume = pciserial_resume_one,
#endif
.driver = {
.pm = &pciserial_pm_ops,
},
.id_table = serial_pci_tbl,
.err_handler = &serial8250_err_handler,
};

View File

@ -20,7 +20,7 @@ comment "Non-8250 serial port support"
config SERIAL_AMBA_PL010
tristate "ARM AMBA PL010 serial port support"
depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE)
depends on ARM_AMBA
select SERIAL_CORE
help
This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have
@ -483,16 +483,6 @@ config SERIAL_SA1100_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
config SERIAL_MFD_HSU
tristate "Medfield High Speed UART support"
depends on PCI
select SERIAL_CORE
config SERIAL_MFD_HSU_CONSOLE
bool "Medfile HSU serial console support"
depends on SERIAL_MFD_HSU=y
select SERIAL_CORE_CONSOLE
config SERIAL_BFIN
tristate "Blackfin serial port support"
depends on BLACKFIN
@ -835,7 +825,7 @@ config SERIAL_MCF_CONSOLE
config SERIAL_PMACZILOG
tristate "Mac or PowerMac z85c30 ESCC support"
depends on (M68K && MAC) || (PPC_OF && PPC_PMAC)
depends on (M68K && MAC) || PPC_PMAC
select SERIAL_CORE
help
This driver supports the Zilog z85C30 serial ports found on
@ -1153,7 +1143,7 @@ config SERIAL_OMAP_CONSOLE
config SERIAL_OF_PLATFORM_NWPSERIAL
tristate "NWP serial port driver"
depends on PPC_OF && PPC_DCR
depends on PPC_DCR
select SERIAL_OF_PLATFORM
select SERIAL_CORE_CONSOLE
select SERIAL_CORE

View File

@ -78,7 +78,6 @@ obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o
obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o
obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o
obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o

View File

@ -58,6 +58,7 @@
#include <linux/pinctrl/consumer.h>
#include <linux/sizes.h>
#include <linux/io.h>
#include <linux/workqueue.h>
#define UART_NR 14
@ -156,7 +157,9 @@ struct uart_amba_port {
unsigned int lcrh_tx; /* vendor-specific */
unsigned int lcrh_rx; /* vendor-specific */
unsigned int old_cr; /* state during shutdown */
struct delayed_work tx_softirq_work;
bool autorts;
unsigned int tx_irq_seen; /* 0=none, 1=1, 2=2 or more */
char type[12];
#ifdef CONFIG_DMA_ENGINE
/* DMA stuff */
@ -164,6 +167,7 @@ struct uart_amba_port {
bool using_rx_dma;
struct pl011_dmarx_data dmarx;
struct pl011_dmatx_data dmatx;
bool dma_probed;
#endif
};
@ -261,10 +265,11 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
}
}
static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap)
static void pl011_dma_probe(struct uart_amba_port *uap)
{
/* DMA is the sole user of the platform data right now */
struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
struct device *dev = uap->port.dev;
struct dma_slave_config tx_conf = {
.dst_addr = uap->port.mapbase + UART01x_DR,
.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
@ -275,9 +280,15 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
struct dma_chan *chan;
dma_cap_mask_t mask;
chan = dma_request_slave_channel(dev, "tx");
uap->dma_probed = true;
chan = dma_request_slave_channel_reason(dev, "tx");
if (IS_ERR(chan)) {
if (PTR_ERR(chan) == -EPROBE_DEFER) {
dev_info(uap->port.dev, "DMA driver not ready\n");
uap->dma_probed = false;
return;
}
if (!chan) {
/* We need platform data */
if (!plat || !plat->dma_filter) {
dev_info(uap->port.dev, "no DMA platform data\n");
@ -385,63 +396,17 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
}
}
#ifndef MODULE
/*
* Stack up the UARTs and let the above initcall be done at device
* initcall time, because the serial driver is called as an arch
* initcall, and at this time the DMA subsystem is not yet registered.
* At this point the driver will switch over to using DMA where desired.
*/
struct dma_uap {
struct list_head node;
struct uart_amba_port *uap;
struct device *dev;
};
static LIST_HEAD(pl011_dma_uarts);
static int __init pl011_dma_initcall(void)
{
struct list_head *node, *tmp;
list_for_each_safe(node, tmp, &pl011_dma_uarts) {
struct dma_uap *dmau = list_entry(node, struct dma_uap, node);
pl011_dma_probe_initcall(dmau->dev, dmau->uap);
list_del(node);
kfree(dmau);
}
return 0;
}
device_initcall(pl011_dma_initcall);
static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
{
struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL);
if (dmau) {
dmau->uap = uap;
dmau->dev = dev;
list_add_tail(&dmau->node, &pl011_dma_uarts);
}
}
#else
static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
{
pl011_dma_probe_initcall(dev, uap);
}
#endif
static void pl011_dma_remove(struct uart_amba_port *uap)
{
/* TODO: remove the initcall if it has not yet executed */
if (uap->dmatx.chan)
dma_release_channel(uap->dmatx.chan);
if (uap->dmarx.chan)
dma_release_channel(uap->dmarx.chan);
}
/* Forward declare this for the refill routine */
/* Forward declare these for the refill routine */
static int pl011_dma_tx_refill(struct uart_amba_port *uap);
static void pl011_start_tx_pio(struct uart_amba_port *uap);
/*
* The current DMA TX buffer has been sent.
@ -479,14 +444,13 @@ static void pl011_dma_tx_callback(void *data)
return;
}
if (pl011_dma_tx_refill(uap) <= 0) {
if (pl011_dma_tx_refill(uap) <= 0)
/*
* We didn't queue a DMA buffer for some reason, but we
* have data pending to be sent. Re-enable the TX IRQ.
*/
uap->im |= UART011_TXIM;
writew(uap->im, uap->port.membase + UART011_IMSC);
}
pl011_start_tx_pio(uap);
spin_unlock_irqrestore(&uap->port.lock, flags);
}
@ -664,12 +628,10 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
if (!uap->dmatx.queued) {
if (pl011_dma_tx_refill(uap) > 0) {
uap->im &= ~UART011_TXIM;
ret = true;
} else {
uap->im |= UART011_TXIM;
writew(uap->im, uap->port.membase +
UART011_IMSC);
} else
ret = false;
}
writew(uap->im, uap->port.membase + UART011_IMSC);
} else if (!(uap->dmacr & UART011_TXDMAE)) {
uap->dmacr |= UART011_TXDMAE;
writew(uap->dmacr,
@ -1021,6 +983,9 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
{
int ret;
if (!uap->dma_probed)
pl011_dma_probe(uap);
if (!uap->dmatx.chan)
return;
@ -1142,7 +1107,7 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
#else
/* Blank functions if the DMA engine is not available */
static inline void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
static inline void pl011_dma_probe(struct uart_amba_port *uap)
{
}
@ -1208,15 +1173,24 @@ static void pl011_stop_tx(struct uart_port *port)
pl011_dma_tx_stop(uap);
}
static bool pl011_tx_chars(struct uart_amba_port *uap);
/* Start TX with programmed I/O only (no DMA) */
static void pl011_start_tx_pio(struct uart_amba_port *uap)
{
uap->im |= UART011_TXIM;
writew(uap->im, uap->port.membase + UART011_IMSC);
if (!uap->tx_irq_seen)
pl011_tx_chars(uap);
}
static void pl011_start_tx(struct uart_port *port)
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
if (!pl011_dma_tx_start(uap)) {
uap->im |= UART011_TXIM;
writew(uap->im, uap->port.membase + UART011_IMSC);
}
if (!pl011_dma_tx_start(uap))
pl011_start_tx_pio(uap);
}
static void pl011_stop_rx(struct uart_port *port)
@ -1274,40 +1248,87 @@ __acquires(&uap->port.lock)
spin_lock(&uap->port.lock);
}
static void pl011_tx_chars(struct uart_amba_port *uap)
/*
* Transmit a character
* There must be at least one free entry in the TX FIFO to accept the char.
*
* Returns true if the FIFO might have space in it afterwards;
* returns false if the FIFO definitely became full.
*/
static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c)
{
writew(c, uap->port.membase + UART01x_DR);
uap->port.icount.tx++;
if (likely(uap->tx_irq_seen > 1))
return true;
return !(readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF);
}
static bool pl011_tx_chars(struct uart_amba_port *uap)
{
struct circ_buf *xmit = &uap->port.state->xmit;
int count;
if (unlikely(uap->tx_irq_seen < 2))
/*
* Initial FIFO fill level unknown: we must check TXFF
* after each write, so just try to fill up the FIFO.
*/
count = uap->fifosize;
else /* tx_irq_seen >= 2 */
/*
* FIFO initially at least half-empty, so we can simply
* write half the FIFO without polling TXFF.
* Note: the *first* TX IRQ can still race with
* pl011_start_tx_pio(), which can result in the FIFO
* being fuller than expected in that case.
*/
count = uap->fifosize >> 1;
/*
* If the FIFO is full we're guaranteed a TX IRQ at some later point,
* and can't transmit immediately in any case:
*/
if (unlikely(uap->tx_irq_seen < 2 &&
readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF))
return false;
if (uap->port.x_char) {
writew(uap->port.x_char, uap->port.membase + UART01x_DR);
uap->port.icount.tx++;
pl011_tx_char(uap, uap->port.x_char);
uap->port.x_char = 0;
return;
--count;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
pl011_stop_tx(&uap->port);
return;
goto done;
}
/* If we are using DMA mode, try to send some characters. */
if (pl011_dma_tx_irq(uap))
return;
goto done;
count = uap->fifosize >> 1;
do {
writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
while (count-- > 0 && pl011_tx_char(uap, xmit->buf[xmit->tail])) {
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
uap->port.icount.tx++;
if (uart_circ_empty(xmit))
break;
} while (--count > 0);
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&uap->port);
if (uart_circ_empty(xmit))
if (uart_circ_empty(xmit)) {
pl011_stop_tx(&uap->port);
goto done;
}
if (unlikely(!uap->tx_irq_seen))
schedule_delayed_work(&uap->tx_softirq_work, uap->port.timeout);
done:
return false;
}
static void pl011_modem_status(struct uart_amba_port *uap)
@ -1334,6 +1355,28 @@ static void pl011_modem_status(struct uart_amba_port *uap)
wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
}
static void pl011_tx_softirq(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
struct uart_amba_port *uap =
container_of(dwork, struct uart_amba_port, tx_softirq_work);
spin_lock(&uap->port.lock);
while (pl011_tx_chars(uap)) ;
spin_unlock(&uap->port.lock);
}
static void pl011_tx_irq_seen(struct uart_amba_port *uap)
{
if (likely(uap->tx_irq_seen > 1))
return;
uap->tx_irq_seen++;
if (uap->tx_irq_seen < 2)
/* first TX IRQ */
cancel_delayed_work(&uap->tx_softirq_work);
}
static irqreturn_t pl011_int(int irq, void *dev_id)
{
struct uart_amba_port *uap = dev_id;
@ -1372,8 +1415,10 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
if (status & (UART011_DSRMIS|UART011_DCDMIS|
UART011_CTSMIS|UART011_RIMIS))
pl011_modem_status(uap);
if (status & UART011_TXIS)
if (status & UART011_TXIS) {
pl011_tx_irq_seen(uap);
pl011_tx_chars(uap);
}
if (pass_counter-- == 0)
break;
@ -1577,7 +1622,7 @@ static int pl011_startup(struct uart_port *port)
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
unsigned int cr, lcr_h, fbrd, ibrd;
unsigned int cr;
int retval;
retval = pl011_hwinit(port);
@ -1595,30 +1640,8 @@ static int pl011_startup(struct uart_port *port)
writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
/*
* Provoke TX FIFO interrupt into asserting. Taking care to preserve
* baud rate and data format specified by FBRD, IBRD and LCRH as the
* UART may already be in use as a console.
*/
spin_lock_irq(&uap->port.lock);
fbrd = readw(uap->port.membase + UART011_FBRD);
ibrd = readw(uap->port.membase + UART011_IBRD);
lcr_h = readw(uap->port.membase + uap->lcrh_rx);
cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE;
writew(cr, uap->port.membase + UART011_CR);
writew(0, uap->port.membase + UART011_FBRD);
writew(1, uap->port.membase + UART011_IBRD);
pl011_write_lcr_h(uap, 0);
writew(0, uap->port.membase + UART01x_DR);
while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
barrier();
writew(fbrd, uap->port.membase + UART011_FBRD);
writew(ibrd, uap->port.membase + UART011_IBRD);
pl011_write_lcr_h(uap, lcr_h);
/* restore RTS and DTR */
cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
@ -1672,13 +1695,15 @@ static void pl011_shutdown(struct uart_port *port)
container_of(port, struct uart_amba_port, port);
unsigned int cr;
cancel_delayed_work_sync(&uap->tx_softirq_work);
/*
* disable all interrupts
*/
spin_lock_irq(&uap->port.lock);
uap->im = 0;
writew(uap->im, uap->port.membase + UART011_IMSC);
writew(0xffff, uap->port.membase + UART011_ICR);
writew(0xffff & ~UART011_TXIS, uap->port.membase + UART011_ICR);
spin_unlock_irq(&uap->port.lock);
pl011_dma_shutdown(uap);
@ -2218,7 +2243,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
uap->port.ops = &amba_pl011_pops;
uap->port.flags = UPF_BOOT_AUTOCONF;
uap->port.line = i;
pl011_dma_probe(&dev->dev, uap);
INIT_DELAYED_WORK(&uap->tx_softirq_work, pl011_tx_softirq);
/* Ensure interrupts from this UART are masked and cleared */
writew(0, uap->port.membase + UART011_IMSC);
@ -2233,7 +2258,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
if (!amba_reg.state) {
ret = uart_register_driver(&amba_reg);
if (ret < 0) {
pr_err("Failed to register AMBA-PL011 driver\n");
dev_err(&dev->dev,
"Failed to register AMBA-PL011 driver\n");
return ret;
}
}
@ -2242,7 +2268,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
if (ret) {
amba_ports[i] = NULL;
uart_unregister_driver(&amba_reg);
pl011_dma_remove(uap);
}
return ret;

View File

@ -649,7 +649,7 @@ static int ar933x_uart_probe(struct platform_device *pdev)
id = 0;
}
if (id > CONFIG_SERIAL_AR933X_NR_UARTS)
if (id >= CONFIG_SERIAL_AR933X_NR_UARTS)
return -EINVAL;
irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);

View File

@ -855,7 +855,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
spin_lock_init(&atmel_port->lock_tx);
sg_init_table(&atmel_port->sg_tx, 1);
/* UART circular tx buffer is an aligned page. */
BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
BUG_ON(!PAGE_ALIGNED(port->state->xmit.buf));
sg_set_page(&atmel_port->sg_tx,
virt_to_page(port->state->xmit.buf),
UART_XMIT_SIZE,
@ -1034,10 +1034,10 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
spin_lock_init(&atmel_port->lock_rx);
sg_init_table(&atmel_port->sg_rx, 1);
/* UART circular rx buffer is an aligned page. */
BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
BUG_ON(!PAGE_ALIGNED(ring->buf));
sg_set_page(&atmel_port->sg_rx,
virt_to_page(ring->buf),
ATMEL_SERIAL_RINGSIZE,
sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE,
(int)ring->buf & ~PAGE_MASK);
nent = dma_map_sg(port->dev,
&atmel_port->sg_rx,
@ -1554,7 +1554,7 @@ static void atmel_tasklet_func(unsigned long data)
spin_unlock(&port->lock);
}
static int atmel_init_property(struct atmel_uart_port *atmel_port,
static void atmel_init_property(struct atmel_uart_port *atmel_port,
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@ -1595,7 +1595,6 @@ static int atmel_init_property(struct atmel_uart_port *atmel_port,
atmel_port->use_dma_tx = false;
}
return 0;
}
static void atmel_init_rs485(struct uart_port *port,
@ -1777,10 +1776,13 @@ static int atmel_startup(struct uart_port *port)
if (retval)
goto free_irq;
tasklet_enable(&atmel_port->tasklet);
/*
* Initialize DMA (if necessary)
*/
atmel_init_property(atmel_port, pdev);
atmel_set_ops(port);
if (atmel_port->prepare_rx) {
retval = atmel_port->prepare_rx(port);
@ -1879,6 +1881,7 @@ static void atmel_shutdown(struct uart_port *port)
* Clear out any scheduled tasklets before
* we destroy the buffers
*/
tasklet_disable(&atmel_port->tasklet);
tasklet_kill(&atmel_port->tasklet);
/*
@ -2256,7 +2259,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
struct uart_port *port = &atmel_port->uart;
struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
if (!atmel_init_property(atmel_port, pdev))
atmel_init_property(atmel_port, pdev);
atmel_set_ops(port);
atmel_init_rs485(port, pdev);
@ -2272,6 +2275,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
tasklet_init(&atmel_port->tasklet, atmel_tasklet_func,
(unsigned long)port);
tasklet_disable(&atmel_port->tasklet);
memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
@ -2581,8 +2585,8 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
struct gpio_desc *gpiod;
p->gpios = mctrl_gpio_init(dev, 0);
if (IS_ERR_OR_NULL(p->gpios))
return -1;
if (IS_ERR(p->gpios))
return PTR_ERR(p->gpios);
for (i = 0; i < UART_GPIO_MAX; i++) {
gpiod = mctrl_gpio_to_gpiod(p->gpios, i);
@ -2635,9 +2639,10 @@ static int atmel_serial_probe(struct platform_device *pdev)
spin_lock_init(&port->lock_suspended);
ret = atmel_init_gpios(port, &pdev->dev);
if (ret < 0)
dev_err(&pdev->dev, "%s",
"Failed to initialize GPIOs. The serial port may not work as expected");
if (ret < 0) {
dev_err(&pdev->dev, "Failed to initialize GPIOs.");
goto err;
}
ret = atmel_init_port(port, pdev);
if (ret)

View File

@ -854,7 +854,7 @@ static int bcm_uart_probe(struct platform_device *pdev)
ret = uart_add_one_port(&bcm_uart_driver, port);
if (ret) {
ports[pdev->id].membase = 0;
ports[pdev->id].membase = NULL;
return ret;
}
platform_set_drvdata(pdev, port);
@ -868,7 +868,7 @@ static int bcm_uart_remove(struct platform_device *pdev)
port = platform_get_drvdata(pdev);
uart_remove_one_port(&bcm_uart_driver, port);
/* mark port as free */
ports[pdev->id].membase = 0;
ports[pdev->id].membase = NULL;
return 0;
}

View File

@ -501,6 +501,8 @@ static int uart_clps711x_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, s);
s->gpios = mctrl_gpio_init(&pdev->dev, 0);
if (IS_ERR(s->gpios))
return PTR_ERR(s->gpios);
ret = uart_add_one_port(&clps711x_uart, &s->port);
if (ret)

View File

@ -54,44 +54,31 @@ static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
return base;
}
static int __init parse_options(struct earlycon_device *device,
char *options)
static int __init parse_options(struct earlycon_device *device, char *options)
{
struct uart_port *port = &device->port;
int mmio, mmio32, length;
int length;
unsigned long addr;
if (!options)
return -ENODEV;
if (uart_parse_earlycon(options, &port->iotype, &addr, &options))
return -EINVAL;
mmio = !strncmp(options, "mmio,", 5);
mmio32 = !strncmp(options, "mmio32,", 7);
if (mmio || mmio32) {
port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
options += mmio ? 5 : 7;
addr = simple_strtoul(options, NULL, 0);
switch (port->iotype) {
case UPIO_MEM32:
port->regshift = 2; /* fall-through */
case UPIO_MEM:
port->mapbase = addr;
if (mmio32)
port->regshift = 2;
} else if (!strncmp(options, "io,", 3)) {
port->iotype = UPIO_PORT;
options += 3;
addr = simple_strtoul(options, NULL, 0);
break;
case UPIO_PORT:
port->iobase = addr;
mmio = 0;
} else if (!strncmp(options, "0x", 2)) {
port->iotype = UPIO_MEM;
addr = simple_strtoul(options, NULL, 0);
port->mapbase = addr;
} else {
break;
default:
return -EINVAL;
}
port->uartclk = BASE_BAUD * 16;
options = strchr(options, ',');
if (options) {
options++;
device->baud = simple_strtoul(options, NULL, 0);
length = min(strcspn(options, " ") + 1,
(size_t)(sizeof(device->options)));
@ -100,7 +87,7 @@ static int __init parse_options(struct earlycon_device *device,
if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32)
pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
mmio32 ? "32" : "",
(port->iotype == UPIO_MEM32) ? "32" : "",
(unsigned long long)port->mapbase,
device->options);
else

View File

@ -1,14 +1,11 @@
/*
* Driver for Motorola IMX serial ports
* Driver for Motorola/Freescale IMX serial ports
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
*
* Author: Sascha Hauer <sascha@saschahauer.de>
* Copyright (C) 2004 Pengutronix
*
* Copyright (C) 2009 emlix GmbH
* Author: Fabian Godehardt (added IrDA support for iMX)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@ -18,13 +15,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* [29-Mar-2005] Mike Lee
* Added hardware handshake
*/
#if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
@ -189,7 +179,7 @@
#define UART_NR 8
/* i.mx21 type uart runs on all i.mx except i.mx1 */
/* i.MX21 type uart runs on all i.mx except i.MX1 and i.MX6q */
enum imx_uart_type {
IMX1_UART,
IMX21_UART,
@ -206,10 +196,8 @@ struct imx_port {
struct uart_port port;
struct timer_list timer;
unsigned int old_status;
int txirq, rxirq, rtsirq;
unsigned int have_rtscts:1;
unsigned int dte_mode:1;
unsigned int use_irda:1;
unsigned int irda_inv_rx:1;
unsigned int irda_inv_tx:1;
unsigned short trcv_delay; /* transceiver delay */
@ -236,12 +224,6 @@ struct imx_port_ucrs {
unsigned int ucr3;
};
#ifdef CONFIG_IRDA
#define USE_IRDA(sport) ((sport)->use_irda)
#else
#define USE_IRDA(sport) (0)
#endif
static struct imx_uart_data imx_uart_devdata[] = {
[IMX1_UART] = {
.uts_reg = IMX1_UTS,
@ -273,7 +255,7 @@ static struct platform_device_id imx_uart_devtype[] = {
};
MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
static struct of_device_id imx_uart_dt_ids[] = {
static const struct of_device_id imx_uart_dt_ids[] = {
{ .compatible = "fsl,imx6q-uart", .data = &imx_uart_devdata[IMX6Q_UART], },
{ .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
{ .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_UART], },
@ -376,48 +358,6 @@ static void imx_stop_tx(struct uart_port *port)
struct imx_port *sport = (struct imx_port *)port;
unsigned long temp;
if (USE_IRDA(sport)) {
/* half duplex - wait for end of transmission */
int n = 256;
while ((--n > 0) &&
!(readl(sport->port.membase + USR2) & USR2_TXDC)) {
udelay(5);
barrier();
}
/*
* irda transceiver - wait a bit more to avoid
* cutoff, hardware dependent
*/
udelay(sport->trcv_delay);
/*
* half duplex - reactivate receive mode,
* flush receive pipe echo crap
*/
if (readl(sport->port.membase + USR2) & USR2_TXDC) {
temp = readl(sport->port.membase + UCR1);
temp &= ~(UCR1_TXMPTYEN | UCR1_TRDYEN);
writel(temp, sport->port.membase + UCR1);
temp = readl(sport->port.membase + UCR4);
temp &= ~(UCR4_TCEN);
writel(temp, sport->port.membase + UCR4);
while (readl(sport->port.membase + URXD0) &
URXD_CHARRDY)
barrier();
temp = readl(sport->port.membase + UCR1);
temp |= UCR1_RRDYEN;
writel(temp, sport->port.membase + UCR1);
temp = readl(sport->port.membase + UCR4);
temp |= UCR4_DREN;
writel(temp, sport->port.membase + UCR4);
}
return;
}
/*
* We are maybe in the SMP context, so if the DMA TX thread is running
* on other cpu, we have to wait for it to finish.
@ -425,8 +365,23 @@ static void imx_stop_tx(struct uart_port *port)
if (sport->dma_is_enabled && sport->dma_is_txing)
return;
temp = readl(sport->port.membase + UCR1);
writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1);
temp = readl(port->membase + UCR1);
writel(temp & ~UCR1_TXMPTYEN, port->membase + UCR1);
/* in rs485 mode disable transmitter if shifter is empty */
if (port->rs485.flags & SER_RS485_ENABLED &&
readl(port->membase + USR2) & USR2_TXDC) {
temp = readl(port->membase + UCR2);
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
temp &= ~UCR2_CTS;
else
temp |= UCR2_CTS;
writel(temp, port->membase + UCR2);
temp = readl(port->membase + UCR4);
temp &= ~UCR4_TCEN;
writel(temp, port->membase + UCR4);
}
}
/*
@ -620,15 +575,18 @@ static void imx_start_tx(struct uart_port *port)
struct imx_port *sport = (struct imx_port *)port;
unsigned long temp;
if (USE_IRDA(sport)) {
/* half duplex in IrDA mode; have to disable receive mode */
temp = readl(sport->port.membase + UCR4);
temp &= ~(UCR4_DREN);
writel(temp, sport->port.membase + UCR4);
if (port->rs485.flags & SER_RS485_ENABLED) {
/* enable transmitter and shifter empty irq */
temp = readl(port->membase + UCR2);
if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
temp &= ~UCR2_CTS;
else
temp |= UCR2_CTS;
writel(temp, port->membase + UCR2);
temp = readl(sport->port.membase + UCR1);
temp &= ~(UCR1_RRDYEN);
writel(temp, sport->port.membase + UCR1);
temp = readl(port->membase + UCR4);
temp |= UCR4_TCEN;
writel(temp, port->membase + UCR4);
}
if (!sport->dma_is_enabled) {
@ -636,16 +594,6 @@ static void imx_start_tx(struct uart_port *port)
writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
}
if (USE_IRDA(sport)) {
temp = readl(sport->port.membase + UCR1);
temp |= UCR1_TRDYEN;
writel(temp, sport->port.membase + UCR1);
temp = readl(sport->port.membase + UCR4);
temp |= UCR4_TCEN;
writel(temp, sport->port.membase + UCR4);
}
if (sport->dma_is_enabled) {
if (sport->port.x_char) {
/* We have X-char to send, so enable TX IRQ and
@ -796,6 +744,7 @@ static irqreturn_t imx_int(int irq, void *dev_id)
unsigned int sts2;
sts = readl(sport->port.membase + USR1);
sts2 = readl(sport->port.membase + USR2);
if (sts & USR1_RRDY) {
if (sport->dma_is_enabled)
@ -804,8 +753,10 @@ static irqreturn_t imx_int(int irq, void *dev_id)
imx_rxint(irq, dev_id);
}
if (sts & USR1_TRDY &&
readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN)
if ((sts & USR1_TRDY &&
readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) ||
(sts2 & USR2_TXDC &&
readl(sport->port.membase + UCR4) & UCR4_TCEN))
imx_txint(irq, dev_id);
if (sts & USR1_RTSD)
@ -814,11 +765,10 @@ static irqreturn_t imx_int(int irq, void *dev_id)
if (sts & USR1_AWAKE)
writel(USR1_AWAKE, sport->port.membase + USR1);
sts2 = readl(sport->port.membase + USR2);
if (sts2 & USR2_ORE) {
dev_err(sport->port.dev, "Rx FIFO overrun\n");
sport->port.icount.overrun++;
writel(sts2 | USR2_ORE, sport->port.membase + USR2);
writel(USR2_ORE, sport->port.membase + USR2);
}
return IRQ_HANDLED;
@ -866,11 +816,13 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
struct imx_port *sport = (struct imx_port *)port;
unsigned long temp;
temp = readl(sport->port.membase + UCR2) & ~(UCR2_CTS | UCR2_CTSC);
if (!(port->rs485.flags & SER_RS485_ENABLED)) {
temp = readl(sport->port.membase + UCR2);
temp &= ~(UCR2_CTS | UCR2_CTSC);
if (mctrl & TIOCM_RTS)
temp |= UCR2_CTS | UCR2_CTSC;
writel(temp, sport->port.membase + UCR2);
}
temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP;
if (mctrl & TIOCM_LOOP)
@ -1156,9 +1108,6 @@ static int imx_startup(struct uart_port *port)
*/
temp = readl(sport->port.membase + UCR4);
if (USE_IRDA(sport))
temp |= UCR4_IRSC;
/* set the trigger level for CTS */
temp &= ~(UCR4_CTSTL_MASK << UCR4_CTSTL_SHF);
temp |= CTSTL << UCR4_CTSTL_SHF;
@ -1181,10 +1130,12 @@ static int imx_startup(struct uart_port *port)
imx_uart_dma_init(sport);
spin_lock_irqsave(&sport->port.lock, flags);
/*
* Finally, clear and enable interrupts
*/
writel(USR1_RTSD, sport->port.membase + USR1);
writel(USR2_ORE, sport->port.membase + USR2);
if (sport->dma_is_inited && !sport->dma_is_enabled)
imx_enable_dma(sport);
@ -1192,17 +1143,8 @@ static int imx_startup(struct uart_port *port)
temp = readl(sport->port.membase + UCR1);
temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
if (USE_IRDA(sport)) {
temp |= UCR1_IREN;
temp &= ~(UCR1_RTSDEN);
}
writel(temp, sport->port.membase + UCR1);
/* Clear any pending ORE flag before enabling interrupt */
temp = readl(sport->port.membase + USR2);
writel(temp | USR2_ORE, sport->port.membase + USR2);
temp = readl(sport->port.membase + UCR4);
temp |= UCR4_OREN;
writel(temp, sport->port.membase + UCR4);
@ -1219,38 +1161,12 @@ static int imx_startup(struct uart_port *port)
writel(temp, sport->port.membase + UCR3);
}
if (USE_IRDA(sport)) {
temp = readl(sport->port.membase + UCR4);
if (sport->irda_inv_rx)
temp |= UCR4_INVR;
else
temp &= ~(UCR4_INVR);
writel(temp | UCR4_DREN, sport->port.membase + UCR4);
temp = readl(sport->port.membase + UCR3);
if (sport->irda_inv_tx)
temp |= UCR3_INVT;
else
temp &= ~(UCR3_INVT);
writel(temp, sport->port.membase + UCR3);
}
/*
* Enable modem status interrupts
*/
imx_enable_ms(&sport->port);
spin_unlock_irqrestore(&sport->port.lock, flags);
if (USE_IRDA(sport)) {
struct imxuart_platform_data *pdata;
pdata = dev_get_platdata(sport->port.dev);
sport->irda_inv_rx = pdata->irda_inv_rx;
sport->irda_inv_tx = pdata->irda_inv_tx;
sport->trcv_delay = pdata->transceiver_delay;
if (pdata->irda_enable)
pdata->irda_enable(1);
}
return 0;
}
@ -1286,13 +1202,6 @@ static void imx_shutdown(struct uart_port *port)
writel(temp, sport->port.membase + UCR2);
spin_unlock_irqrestore(&sport->port.lock, flags);
if (USE_IRDA(sport)) {
struct imxuart_platform_data *pdata;
pdata = dev_get_platdata(sport->port.dev);
if (pdata->irda_enable)
pdata->irda_enable(0);
}
/*
* Stop our timer.
*/
@ -1305,8 +1214,6 @@ static void imx_shutdown(struct uart_port *port)
spin_lock_irqsave(&sport->port.lock, flags);
temp = readl(sport->port.membase + UCR1);
temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
if (USE_IRDA(sport))
temp &= ~(UCR1_IREN);
writel(temp, sport->port.membase + UCR1);
spin_unlock_irqrestore(&sport->port.lock, flags);
@ -1320,7 +1227,7 @@ static void imx_flush_buffer(struct uart_port *port)
struct imx_port *sport = (struct imx_port *)port;
struct scatterlist *sgl = &sport->tx_sgl[0];
unsigned long temp;
int i = 100, ubir, ubmr, ubrc, uts;
int i = 100, ubir, ubmr, uts;
if (!sport->dma_chan_tx)
return;
@ -1345,7 +1252,6 @@ static void imx_flush_buffer(struct uart_port *port)
*/
ubir = readl(sport->port.membase + UBIR);
ubmr = readl(sport->port.membase + UBMR);
ubrc = readl(sport->port.membase + UBRC);
uts = readl(sport->port.membase + IMX21_UTS);
temp = readl(sport->port.membase + UCR2);
@ -1358,7 +1264,6 @@ static void imx_flush_buffer(struct uart_port *port)
/* Restore the registers */
writel(ubir, sport->port.membase + UBIR);
writel(ubmr, sport->port.membase + UBMR);
writel(ubrc, sport->port.membase + UBRC);
writel(uts, sport->port.membase + IMX21_UTS);
}
@ -1374,15 +1279,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned long num, denom;
uint64_t tdiv64;
/*
* If we don't support modem control lines, don't allow
* these to be set.
*/
if (0) {
termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
termios->c_cflag |= CLOCAL;
}
/*
* We only support CS7 and CS8.
*/
@ -1401,11 +1297,26 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
if (termios->c_cflag & CRTSCTS) {
if (sport->have_rtscts) {
ucr2 &= ~UCR2_IRTS;
if (port->rs485.flags & SER_RS485_ENABLED)
/*
* RTS is mandatory for rs485 operation, so keep
* it under manual control and keep transmitter
* disabled.
*/
if (!(port->rs485.flags &
SER_RS485_RTS_AFTER_SEND))
ucr2 |= UCR2_CTS;
else
ucr2 |= UCR2_CTSC;
} else {
termios->c_cflag &= ~CRTSCTS;
}
}
} else if (port->rs485.flags & SER_RS485_ENABLED)
/* disable transmitter */
if (!(port->rs485.flags & SER_RS485_RTS_AFTER_SEND))
ucr2 |= UCR2_CTS;
if (termios->c_cflag & CSTOPB)
ucr2 |= UCR2_STPB;
@ -1471,13 +1382,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
sport->port.membase + UCR2);
old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
if (USE_IRDA(sport)) {
/*
* use maximum available submodule frequency to
* avoid missing short pulses due to low sampling rate
*/
div = 1;
} else {
/* custom-baudrate handling */
div = sport->port.uartclk / (baud * 16);
if (baud == 38400 && quot != div)
@ -1488,7 +1392,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
div = 7;
if (!div)
div = 1;
}
rational_best_approximation(16 * div * baud, sport->port.uartclk,
1 << 16, 1 << 16, &num, &denom);
@ -1635,6 +1538,38 @@ static void imx_poll_put_char(struct uart_port *port, unsigned char c)
}
#endif
static int imx_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485conf)
{
struct imx_port *sport = (struct imx_port *)port;
/* unimplemented */
rs485conf->delay_rts_before_send = 0;
rs485conf->delay_rts_after_send = 0;
rs485conf->flags |= SER_RS485_RX_DURING_TX;
/* RTS is required to control the transmitter */
if (!sport->have_rtscts)
rs485conf->flags &= ~SER_RS485_ENABLED;
if (rs485conf->flags & SER_RS485_ENABLED) {
unsigned long temp;
/* disable transmitter */
temp = readl(sport->port.membase + UCR2);
temp &= ~UCR2_CTSC;
if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
temp &= ~UCR2_CTS;
else
temp |= UCR2_CTS;
writel(temp, sport->port.membase + UCR2);
}
port->rs485 = *rs485conf;
return 0;
}
static struct uart_ops imx_pops = {
.tx_empty = imx_tx_empty,
.set_mctrl = imx_set_mctrl,
@ -1927,9 +1862,6 @@ static int serial_imx_probe_dt(struct imx_port *sport,
if (of_get_property(np, "fsl,uart-has-rtscts", NULL))
sport->have_rtscts = 1;
if (of_get_property(np, "fsl,irda-mode", NULL))
sport->use_irda = 1;
if (of_get_property(np, "fsl,dte-mode", NULL))
sport->dte_mode = 1;
@ -1958,9 +1890,6 @@ static void serial_imx_probe_pdata(struct imx_port *sport,
if (pdata->flags & IMXUART_HAVE_RTSCTS)
sport->have_rtscts = 1;
if (pdata->flags & IMXUART_IRDA)
sport->use_irda = 1;
}
static int serial_imx_probe(struct platform_device *pdev)
@ -1969,6 +1898,7 @@ static int serial_imx_probe(struct platform_device *pdev)
void __iomem *base;
int ret = 0;
struct resource *res;
int txirq, rxirq, rtsirq;
sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
if (!sport)
@ -1985,17 +1915,21 @@ static int serial_imx_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
rxirq = platform_get_irq(pdev, 0);
txirq = platform_get_irq(pdev, 1);
rtsirq = platform_get_irq(pdev, 2);
sport->port.dev = &pdev->dev;
sport->port.mapbase = res->start;
sport->port.membase = base;
sport->port.type = PORT_IMX,
sport->port.iotype = UPIO_MEM;
sport->port.irq = platform_get_irq(pdev, 0);
sport->rxirq = platform_get_irq(pdev, 0);
sport->txirq = platform_get_irq(pdev, 1);
sport->rtsirq = platform_get_irq(pdev, 2);
sport->port.irq = rxirq;
sport->port.fifosize = 32;
sport->port.ops = &imx_pops;
sport->port.rs485_config = imx_rs485_config;
sport->port.rs485.flags =
SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX;
sport->port.flags = UPF_BOOT_AUTOCONF;
init_timer(&sport->timer);
sport->timer.function = imx_timeout;
@ -2021,27 +1955,18 @@ static int serial_imx_probe(struct platform_device *pdev)
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later
* chips only have one interrupt.
*/
if (sport->txirq > 0) {
ret = devm_request_irq(&pdev->dev, sport->rxirq, imx_rxint, 0,
if (txirq > 0) {
ret = devm_request_irq(&pdev->dev, rxirq, imx_rxint, 0,
dev_name(&pdev->dev), sport);
if (ret)
return ret;
ret = devm_request_irq(&pdev->dev, sport->txirq, imx_txint, 0,
ret = devm_request_irq(&pdev->dev, txirq, imx_txint, 0,
dev_name(&pdev->dev), sport);
if (ret)
return ret;
/* do not use RTS IRQ on IrDA */
if (!USE_IRDA(sport)) {
ret = devm_request_irq(&pdev->dev, sport->rtsirq,
imx_rtsint, 0,
dev_name(&pdev->dev), sport);
if (ret)
return ret;
}
} else {
ret = devm_request_irq(&pdev->dev, sport->port.irq, imx_int, 0,
ret = devm_request_irq(&pdev->dev, rxirq, imx_int, 0,
dev_name(&pdev->dev), sport);
if (ret)
return ret;

View File

@ -782,7 +782,7 @@ static int max3100_probe(struct spi_device *spi)
pdata = dev_get_platdata(&spi->dev);
max3100s[i]->crystal = pdata->crystal;
max3100s[i]->loopback = pdata->loopback;
max3100s[i]->poll_time = pdata->poll_time * HZ / 1000;
max3100s[i]->poll_time = msecs_to_jiffies(pdata->poll_time);
if (pdata->poll_time > 0 && max3100s[i]->poll_time == 0)
max3100s[i]->poll_time = 1;
max3100s[i]->max3100_hw_suspend = pdata->max3100_hw_suspend;

File diff suppressed because it is too large Load Diff

View File

@ -1155,14 +1155,14 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
return 0;
}
static bool mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
{
enum mctrl_gpio_idx i;
struct gpio_desc *gpiod;
s->gpios = mctrl_gpio_init(dev, 0);
if (IS_ERR_OR_NULL(s->gpios))
return false;
if (IS_ERR(s->gpios))
return PTR_ERR(s->gpios);
/* Block (enabled before) DMA option if RTS or CTS is GPIO line */
if (!RTS_AT_AUART() || !CTS_AT_AUART()) {
@ -1180,7 +1180,7 @@ static bool mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
s->gpio_irq[i] = -EINVAL;
}
return true;
return 0;
}
static void mxs_auart_free_gpio_irq(struct mxs_auart_port *s)
@ -1276,9 +1276,11 @@ static int mxs_auart_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, s);
if (!mxs_auart_init_gpios(s, &pdev->dev))
dev_err(&pdev->dev,
"Failed to initialize GPIOs. The serial port may not work as expected\n");
ret = mxs_auart_init_gpios(s, &pdev->dev);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize GPIOs.\n");
got out_free_irq;
}
/*
* Get the GPIO lines IRQ

View File

@ -1118,8 +1118,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
cprev = cnow;
}
current->state = TASK_RUNNING;
__set_current_state(TASK_RUNNING);
remove_wait_queue(&port->delta_msr_wait, &wait);
return ret;
@ -1809,6 +1808,52 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
return ports + idx;
}
/**
* uart_parse_earlycon - Parse earlycon options
* @p: ptr to 2nd field (ie., just beyond '<name>,')
* @iotype: ptr for decoded iotype (out)
* @addr: ptr for decoded mapbase/iobase (out)
* @options: ptr for <options> field; NULL if not present (out)
*
* Decodes earlycon kernel command line parameters of the form
* earlycon=<name>,io|mmio|mmio32,<addr>,<options>
* console=<name>,io|mmio|mmio32,<addr>,<options>
*
* The optional form
* earlycon=<name>,0x<addr>,<options>
* console=<name>,0x<addr>,<options>
* is also accepted; the returned @iotype will be UPIO_MEM.
*
* Returns 0 on success or -EINVAL on failure
*/
int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
char **options)
{
if (strncmp(p, "mmio,", 5) == 0) {
*iotype = UPIO_MEM;
p += 5;
} else if (strncmp(p, "mmio32,", 7) == 0) {
*iotype = UPIO_MEM32;
p += 7;
} else if (strncmp(p, "io,", 3) == 0) {
*iotype = UPIO_PORT;
p += 3;
} else if (strncmp(p, "0x", 2) == 0) {
*iotype = UPIO_MEM;
} else {
return -EINVAL;
}
*addr = simple_strtoul(p, NULL, 0);
p = strchr(p, ',');
if (p)
p++;
*options = p;
return 0;
}
EXPORT_SYMBOL_GPL(uart_parse_earlycon);
/**
* uart_parse_options - Parse serial port baud/parity/bits/flow control.
* @options: pointer to option string

View File

@ -48,9 +48,6 @@ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
int value_array[UART_GPIO_MAX];
unsigned int count = 0;
if (IS_ERR_OR_NULL(gpios))
return;
for (i = 0; i < UART_GPIO_MAX; i++)
if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
mctrl_gpios_desc[i].dir_out) {
@ -65,10 +62,7 @@ EXPORT_SYMBOL_GPL(mctrl_gpio_set);
struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
enum mctrl_gpio_idx gidx)
{
if (!IS_ERR_OR_NULL(gpios) && !IS_ERR_OR_NULL(gpios->gpio[gidx]))
return gpios->gpio[gidx];
else
return NULL;
}
EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod);
@ -76,15 +70,8 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
{
enum mctrl_gpio_idx i;
/*
* return it unchanged if the structure is not allocated
*/
if (IS_ERR_OR_NULL(gpios))
return *mctrl;
for (i = 0; i < UART_GPIO_MAX; i++) {
if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
!mctrl_gpios_desc[i].dir_out) {
if (gpios->gpio[i] && !mctrl_gpios_desc[i].dir_out) {
if (gpiod_get_value(gpios->gpio[i]))
*mctrl |= mctrl_gpios_desc[i].mctrl;
else
@ -107,27 +94,20 @@ struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
return ERR_PTR(-ENOMEM);
for (i = 0; i < UART_GPIO_MAX; i++) {
gpios->gpio[i] = devm_gpiod_get_index(dev,
mctrl_gpios_desc[i].name,
idx);
/*
* The GPIOs are maybe not all filled,
* this is not an error.
*/
if (IS_ERR_OR_NULL(gpios->gpio[i]))
continue;
enum gpiod_flags flags;
if (mctrl_gpios_desc[i].dir_out)
err = gpiod_direction_output(gpios->gpio[i], 0);
flags = GPIOD_OUT_LOW;
else
err = gpiod_direction_input(gpios->gpio[i]);
if (err) {
dev_dbg(dev, "Unable to set direction for %s GPIO",
mctrl_gpios_desc[i].name);
devm_gpiod_put(dev, gpios->gpio[i]);
gpios->gpio[i] = NULL;
}
flags = GPIOD_IN;
gpios->gpio[i] =
devm_gpiod_get_index_optional(dev,
mctrl_gpios_desc[i].name,
idx, flags);
if (IS_ERR(gpios->gpio[i]))
return PTR_ERR(gpios->gpio[i]);
}
return gpios;
@ -138,9 +118,6 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
{
enum mctrl_gpio_idx i;
if (IS_ERR_OR_NULL(gpios))
return;
for (i = 0; i < UART_GPIO_MAX; i++)
if (!IS_ERR_OR_NULL(gpios->gpio[i]))
devm_gpiod_put(dev, gpios->gpio[i]);

View File

@ -493,6 +493,8 @@ static int sprd_verify_port(struct uart_port *port,
return -EINVAL;
if (port->irq != ser->irq)
return -EINVAL;
if (port->iotype != ser->io_type)
return -EINVAL;
return 0;
}
@ -707,7 +709,7 @@ static int sprd_probe(struct platform_device *pdev)
up->dev = &pdev->dev;
up->line = index;
up->type = PORT_SPRD;
up->iotype = SERIAL_IO_PORT;
up->iotype = UPIO_MEM;
up->uartclk = SPRD_DEF_RATE;
up->fifosize = SPRD_FIFO_SIZE;
up->ops = &serial_sprd_ops;
@ -754,6 +756,7 @@ static int sprd_probe(struct platform_device *pdev)
return ret;
}
#ifdef CONFIG_PM_SLEEP
static int sprd_suspend(struct device *dev)
{
struct sprd_uart_port *sup = dev_get_drvdata(dev);
@ -771,6 +774,7 @@ static int sprd_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(sprd_pm_ops, sprd_suspend, sprd_resume);

View File

@ -1154,7 +1154,8 @@ static int __init cdns_uart_console_setup(struct console *co, char *options)
return -EINVAL;
if (!port->mapbase) {
pr_debug("console on ttyPS%i not present\n", co->index);
pr_debug("console on " CDNS_UART_TTY_NAME "%i not present\n",
co->index);
return -ENODEV;
}

View File

@ -1237,7 +1237,7 @@ static void default_attr(struct vc_data *vc)
struct rgb { u8 r; u8 g; u8 b; };
struct rgb rgb_from_256(int i)
static struct rgb rgb_from_256(int i)
{
struct rgb c;
if (i < 8) { /* Standard colours. */
@ -1573,7 +1573,7 @@ static void setterm_command(struct vc_data *vc)
case 11: /* set bell duration in msec */
if (vc->vc_npar >= 1)
vc->vc_bell_duration = (vc->vc_par[1] < 2000) ?
vc->vc_par[1] * HZ / 1000 : 0;
msecs_to_jiffies(vc->vc_par[1]) : 0;
else
vc->vc_bell_duration = DEFAULT_BELL_DURATION;
break;

View File

@ -388,7 +388,7 @@ int vt_ioctl(struct tty_struct *tty,
* Generate the tone for the appropriate number of ticks.
* If the time is zero, turn off sound ourselves.
*/
ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
ticks = msecs_to_jiffies((arg >> 16) & 0xffff);
count = ticks ? (arg & 0xffff) : 0;
if (count)
count = PIT_TICK_RATE / count;

48
include/linux/dma/hsu.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Driver for the High Speed UART DMA
*
* Copyright (C) 2015 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _DMA_HSU_H
#define _DMA_HSU_H
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/platform_data/dma-hsu.h>
struct hsu_dma;
/**
* struct hsu_dma_chip - representation of HSU DMA hardware
* @dev: struct device of the DMA controller
* @irq: irq line
* @regs: memory mapped I/O space
* @length: I/O space length
* @offset: offset of the I/O space where registers are located
* @hsu: struct hsu_dma that is filed by ->probe()
* @pdata: platform data for the DMA controller if provided
*/
struct hsu_dma_chip {
struct device *dev;
int irq;
void __iomem *regs;
unsigned int length;
unsigned int offset;
struct hsu_dma *hsu;
struct hsu_dma_platform_data *pdata;
};
/* Export to the internal users */
irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr);
/* Export to the platform drivers */
int hsu_dma_probe(struct hsu_dma_chip *chip);
int hsu_dma_remove(struct hsu_dma_chip *chip);
#endif /* _DMA_HSU_H */

View File

@ -0,0 +1,25 @@
/*
* Driver for the High Speed UART DMA
*
* Copyright (C) 2015 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _PLATFORM_DATA_DMA_HSU_H
#define _PLATFORM_DATA_DMA_HSU_H
#include <linux/device.h>
struct hsu_dma_slave {
struct device *dma_dev;
int chan_id;
};
struct hsu_dma_platform_data {
unsigned short nr_channels;
};
#endif /* _PLATFORM_DATA_DMA_HSU_H */

View File

@ -20,14 +20,9 @@
#define ASMARM_ARCH_UART_H
#define IMXUART_HAVE_RTSCTS (1<<0)
#define IMXUART_IRDA (1<<1)
struct imxuart_platform_data {
unsigned int flags;
void (*irda_enable)(int enable);
unsigned int irda_inv_rx:1;
unsigned int irda_inv_tx:1;
unsigned short transceiver_delay;
};
#endif

View File

@ -354,6 +354,8 @@ early_param("earlycon", name ## _setup_earlycon);
struct uart_port *uart_get_console(struct uart_port *ports, int nr,
struct console *c);
int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
char **options);
void uart_parse_options(char *options, int *baud, int *parity, int *bits,
int *flow);
int uart_set_options(struct uart_port *port, struct console *co, int baud,

View File

@ -1,47 +0,0 @@
#ifndef _SERIAL_MFD_H_
#define _SERIAL_MFD_H_
/* HW register offset definition */
#define UART_FOR 0x08
#define UART_PS 0x0C
#define UART_MUL 0x0D
#define UART_DIV 0x0E
#define HSU_GBL_IEN 0x0
#define HSU_GBL_IST 0x4
#define HSU_GBL_INT_BIT_PORT0 0x0
#define HSU_GBL_INT_BIT_PORT1 0x1
#define HSU_GBL_INT_BIT_PORT2 0x2
#define HSU_GBL_INT_BIT_IRI 0x3
#define HSU_GBL_INT_BIT_HDLC 0x4
#define HSU_GBL_INT_BIT_DMA 0x5
#define HSU_GBL_ISR 0x8
#define HSU_GBL_DMASR 0x400
#define HSU_GBL_DMAISR 0x404
#define HSU_PORT_REG_OFFSET 0x80
#define HSU_PORT0_REG_OFFSET 0x80
#define HSU_PORT1_REG_OFFSET 0x100
#define HSU_PORT2_REG_OFFSET 0x180
#define HSU_PORT_REG_LENGTH 0x80
#define HSU_DMA_CHANS_REG_OFFSET 0x500
#define HSU_DMA_CHANS_REG_LENGTH 0x40
#define HSU_CH_SR 0x0 /* channel status reg */
#define HSU_CH_CR 0x4 /* control reg */
#define HSU_CH_DCR 0x8 /* descriptor control reg */
#define HSU_CH_BSR 0x10 /* max fifo buffer size reg */
#define HSU_CH_MOTSR 0x14 /* minimum ocp transfer size */
#define HSU_CH_D0SAR 0x20 /* desc 0 start addr */
#define HSU_CH_D0TSR 0x24 /* desc 0 transfer size */
#define HSU_CH_D1SAR 0x28
#define HSU_CH_D1TSR 0x2C
#define HSU_CH_D2SAR 0x30
#define HSU_CH_D2TSR 0x34
#define HSU_CH_D3SAR 0x38
#define HSU_CH_D3TSR 0x3C
#endif

View File

@ -241,25 +241,6 @@
#define UART_FCR_PXAR16 0x80 /* receive FIFO threshold = 16 */
#define UART_FCR_PXAR32 0xc0 /* receive FIFO threshold = 32 */
/*
* Intel MID on-chip HSU (High Speed UART) defined bits
*/
#define UART_FCR_HSU_64_1B 0x00 /* receive FIFO treshold = 1 */
#define UART_FCR_HSU_64_16B 0x40 /* receive FIFO treshold = 16 */
#define UART_FCR_HSU_64_32B 0x80 /* receive FIFO treshold = 32 */
#define UART_FCR_HSU_64_56B 0xc0 /* receive FIFO treshold = 56 */
#define UART_FCR_HSU_16_1B 0x00 /* receive FIFO treshold = 1 */
#define UART_FCR_HSU_16_4B 0x40 /* receive FIFO treshold = 4 */
#define UART_FCR_HSU_16_8B 0x80 /* receive FIFO treshold = 8 */
#define UART_FCR_HSU_16_14B 0xc0 /* receive FIFO treshold = 14 */
#define UART_FCR_HSU_64B_FIFO 0x20 /* chose 64 bytes FIFO */
#define UART_FCR_HSU_16B_FIFO 0x00 /* chose 16 bytes FIFO */
#define UART_FCR_HALF_EMPT_TXI 0x00 /* trigger TX_EMPT IRQ for half empty */
#define UART_FCR_FULL_EMPT_TXI 0x08 /* trigger TX_EMPT IRQ for full empty */
/*
* These register definitions are for the 16C950
*/

View File

@ -2480,7 +2480,6 @@ void register_console(struct console *newcon)
newcon->setup(newcon, console_cmdline[i].options) != 0)
break;
newcon->flags |= CON_ENABLED;
newcon->index = c->index;
if (i == selected_console) {
newcon->flags |= CON_CONSDEV;
preferred_console = selected_console;