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, with klogd/syslogd or the X server. You should normally N here,
unless you want to debug such a crash. 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 config EARLY_PRINTK_DBGP
bool "Early printk via EHCI debug port" bool "Early printk via EHCI debug port"
depends on EARLY_PRINTK && PCI 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_MTMR_MAX_NUM 8
#define SFI_MRTC_MAX 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_create(void);
extern void intel_scu_devices_destroy(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)) if (!strncmp(buf, "xen", 3))
early_console_register(&xenboot_console, keep); early_console_register(&xenboot_console, keep);
#endif #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 #ifdef CONFIG_EARLY_PRINTK_EFI
if (!strncmp(buf, "efi", 3)) if (!strncmp(buf, "efi", 3))
early_console_register(&early_efi_console, keep); 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_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 # SFI specific code
ifdef CONFIG_X86_INTEL_MID 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 EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on
some Txxx and Bxxx parts. some Txxx and Bxxx parts.
source "drivers/dma/hsu/Kconfig"
config MPC512X_DMA config MPC512X_DMA
tristate "Freescale MPC512x built-in DMA engine support" tristate "Freescale MPC512x built-in DMA engine support"
depends on PPC_MPC512x || PPC_MPC831x 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_IOATDMA) += ioat/
obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
obj-$(CONFIG_FSL_DMA) += fsldma.o obj-$(CONFIG_FSL_DMA) += fsldma.o
obj-$(CONFIG_HSU_DMA) += hsu/
obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/ obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
obj-$(CONFIG_MV_XOR) += mv_xor.o 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 uart_8250_port uart = {};
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 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; struct dw8250_data *data;
int err; int err;
if (!regs || !irq) { if (!regs) {
dev_err(&pdev->dev, "no registers/irq defined\n"); dev_err(&pdev->dev, "no registers defined\n");
return -EINVAL; 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); spin_lock_init(&uart.port.lock);
uart.port.mapbase = regs->start; uart.port.mapbase = regs->start;
uart.port.irq = irq->start; uart.port.irq = irq;
uart.port.handle_irq = dw8250_handle_irq; uart.port.handle_irq = dw8250_handle_irq;
uart.port.pm = dw8250_do_pm; uart.port.pm = dw8250_do_pm;
uart.port.type = PORT_8250; uart.port.type = PORT_8250;
@ -640,3 +646,4 @@ module_platform_driver(dw8250_platform_driver);
MODULE_AUTHOR("Jamie Iles"); MODULE_AUTHOR("Jamie Iles");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver"); 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/dmaengine.h>
#include <linux/platform_data/dma-dw.h> #include <linux/platform_data/dma-dw.h>
#include <linux/platform_data/dma-hsu.h>
#include "8250.h" #include "8250.h"
@ -1525,6 +1526,148 @@ byt_serial_setup(struct serial_private *priv,
return ret; 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 static int
pci_omegapci_setup(struct serial_private *priv, pci_omegapci_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
@ -1987,6 +2130,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.setup = byt_serial_setup, .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, .vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_BSW_UART1, .device = PCI_DEVICE_ID_INTEL_BSW_UART1,
@ -2864,6 +3028,7 @@ enum pci_board_num_t {
pbn_ADDIDATA_PCIe_8_3906250, pbn_ADDIDATA_PCIe_8_3906250,
pbn_ce4100_1_115200, pbn_ce4100_1_115200,
pbn_byt, pbn_byt,
pbn_pnw,
pbn_qrk, pbn_qrk,
pbn_omegapci, pbn_omegapci,
pbn_NETMOS9900_2s_115200, pbn_NETMOS9900_2s_115200,
@ -3630,6 +3795,11 @@ static struct pciserial_board pci_boards[] = {
.uart_offset = 0x80, .uart_offset = 0x80,
.reg_shift = 2, .reg_shift = 2,
}, },
[pbn_pnw] = {
.flags = FL_BASE0,
.num_ports = 1,
.base_baud = 115200,
},
[pbn_qrk] = { [pbn_qrk] = {
.flags = FL_BASE0, .flags = FL_BASE0,
.num_ports = 1, .num_ports = 1,
@ -4006,41 +4176,41 @@ static void pciserial_remove_one(struct pci_dev *dev)
pci_disable_device(dev); pci_disable_device(dev);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state) 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) if (priv)
pciserial_suspend_ports(priv); pciserial_suspend_ports(priv);
pci_save_state(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
return 0; 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; int err;
struct serial_private *priv = pci_get_drvdata(dev);
pci_set_power_state(dev, PCI_D0);
pci_restore_state(dev);
if (priv) { if (priv) {
/* /*
* The device may have been disabled. Re-enable it. * 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 */ /* FIXME: We cannot simply error out here */
if (err) 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); pciserial_resume_ports(priv);
} }
return 0; return 0;
} }
#endif #endif
static SIMPLE_DEV_PM_OPS(pciserial_pm_ops, pciserial_suspend_one,
pciserial_resume_one);
static struct pci_device_id serial_pci_tbl[] = { static struct pci_device_id serial_pci_tbl[] = {
/* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */ /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
{ PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620, { 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, PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
pbn_byt }, 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 * Intel Quark x1000
*/ */
@ -5510,10 +5693,9 @@ static struct pci_driver serial_pci_driver = {
.name = "serial", .name = "serial",
.probe = pciserial_init_one, .probe = pciserial_init_one,
.remove = pciserial_remove_one, .remove = pciserial_remove_one,
#ifdef CONFIG_PM .driver = {
.suspend = pciserial_suspend_one, .pm = &pciserial_pm_ops,
.resume = pciserial_resume_one, },
#endif
.id_table = serial_pci_tbl, .id_table = serial_pci_tbl,
.err_handler = &serial8250_err_handler, .err_handler = &serial8250_err_handler,
}; };

View File

@ -20,7 +20,7 @@ comment "Non-8250 serial port support"
config SERIAL_AMBA_PL010 config SERIAL_AMBA_PL010
tristate "ARM AMBA PL010 serial port support" tristate "ARM AMBA PL010 serial port support"
depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE) depends on ARM_AMBA
select SERIAL_CORE select SERIAL_CORE
help help
This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have 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 your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.) 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 config SERIAL_BFIN
tristate "Blackfin serial port support" tristate "Blackfin serial port support"
depends on BLACKFIN depends on BLACKFIN
@ -835,7 +825,7 @@ config SERIAL_MCF_CONSOLE
config SERIAL_PMACZILOG config SERIAL_PMACZILOG
tristate "Mac or PowerMac z85c30 ESCC support" tristate "Mac or PowerMac z85c30 ESCC support"
depends on (M68K && MAC) || (PPC_OF && PPC_PMAC) depends on (M68K && MAC) || PPC_PMAC
select SERIAL_CORE select SERIAL_CORE
help help
This driver supports the Zilog z85C30 serial ports found on This driver supports the Zilog z85C30 serial ports found on
@ -1153,7 +1143,7 @@ config SERIAL_OMAP_CONSOLE
config SERIAL_OF_PLATFORM_NWPSERIAL config SERIAL_OF_PLATFORM_NWPSERIAL
tristate "NWP serial port driver" tristate "NWP serial port driver"
depends on PPC_OF && PPC_DCR depends on PPC_DCR
select SERIAL_OF_PLATFORM select SERIAL_OF_PLATFORM
select SERIAL_CORE_CONSOLE select SERIAL_CORE_CONSOLE
select SERIAL_CORE 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_GRLIB_GAISLER_APBUART) += apbuart.o
obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o
obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o
obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o
obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o

View File

@ -58,6 +58,7 @@
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/workqueue.h>
#define UART_NR 14 #define UART_NR 14
@ -156,7 +157,9 @@ struct uart_amba_port {
unsigned int lcrh_tx; /* vendor-specific */ unsigned int lcrh_tx; /* vendor-specific */
unsigned int lcrh_rx; /* vendor-specific */ unsigned int lcrh_rx; /* vendor-specific */
unsigned int old_cr; /* state during shutdown */ unsigned int old_cr; /* state during shutdown */
struct delayed_work tx_softirq_work;
bool autorts; bool autorts;
unsigned int tx_irq_seen; /* 0=none, 1=1, 2=2 or more */
char type[12]; char type[12];
#ifdef CONFIG_DMA_ENGINE #ifdef CONFIG_DMA_ENGINE
/* DMA stuff */ /* DMA stuff */
@ -164,6 +167,7 @@ struct uart_amba_port {
bool using_rx_dma; bool using_rx_dma;
struct pl011_dmarx_data dmarx; struct pl011_dmarx_data dmarx;
struct pl011_dmatx_data dmatx; struct pl011_dmatx_data dmatx;
bool dma_probed;
#endif #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 */ /* DMA is the sole user of the platform data right now */
struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev); struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
struct device *dev = uap->port.dev;
struct dma_slave_config tx_conf = { struct dma_slave_config tx_conf = {
.dst_addr = uap->port.mapbase + UART01x_DR, .dst_addr = uap->port.mapbase + UART01x_DR,
.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, .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; struct dma_chan *chan;
dma_cap_mask_t mask; 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 */ /* We need platform data */
if (!plat || !plat->dma_filter) { if (!plat || !plat->dma_filter) {
dev_info(uap->port.dev, "no DMA platform data\n"); 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) static void pl011_dma_remove(struct uart_amba_port *uap)
{ {
/* TODO: remove the initcall if it has not yet executed */
if (uap->dmatx.chan) if (uap->dmatx.chan)
dma_release_channel(uap->dmatx.chan); dma_release_channel(uap->dmatx.chan);
if (uap->dmarx.chan) if (uap->dmarx.chan)
dma_release_channel(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 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. * The current DMA TX buffer has been sent.
@ -479,14 +444,13 @@ static void pl011_dma_tx_callback(void *data)
return; 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 * We didn't queue a DMA buffer for some reason, but we
* have data pending to be sent. Re-enable the TX IRQ. * have data pending to be sent. Re-enable the TX IRQ.
*/ */
uap->im |= UART011_TXIM; pl011_start_tx_pio(uap);
writew(uap->im, uap->port.membase + UART011_IMSC);
}
spin_unlock_irqrestore(&uap->port.lock, flags); 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 (!uap->dmatx.queued) {
if (pl011_dma_tx_refill(uap) > 0) { if (pl011_dma_tx_refill(uap) > 0) {
uap->im &= ~UART011_TXIM; uap->im &= ~UART011_TXIM;
ret = true; writew(uap->im, uap->port.membase +
} else { UART011_IMSC);
uap->im |= UART011_TXIM; } else
ret = false; ret = false;
}
writew(uap->im, uap->port.membase + UART011_IMSC);
} else if (!(uap->dmacr & UART011_TXDMAE)) { } else if (!(uap->dmacr & UART011_TXDMAE)) {
uap->dmacr |= UART011_TXDMAE; uap->dmacr |= UART011_TXDMAE;
writew(uap->dmacr, writew(uap->dmacr,
@ -1021,6 +983,9 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
{ {
int ret; int ret;
if (!uap->dma_probed)
pl011_dma_probe(uap);
if (!uap->dmatx.chan) if (!uap->dmatx.chan)
return; return;
@ -1142,7 +1107,7 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
#else #else
/* Blank functions if the DMA engine is not available */ /* 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); 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) static void pl011_start_tx(struct uart_port *port)
{ {
struct uart_amba_port *uap = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); container_of(port, struct uart_amba_port, port);
if (!pl011_dma_tx_start(uap)) { if (!pl011_dma_tx_start(uap))
uap->im |= UART011_TXIM; pl011_start_tx_pio(uap);
writew(uap->im, uap->port.membase + UART011_IMSC);
}
} }
static void pl011_stop_rx(struct uart_port *port) static void pl011_stop_rx(struct uart_port *port)
@ -1274,40 +1248,87 @@ __acquires(&uap->port.lock)
spin_lock(&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; struct circ_buf *xmit = &uap->port.state->xmit;
int count; 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) { if (uap->port.x_char) {
writew(uap->port.x_char, uap->port.membase + UART01x_DR); pl011_tx_char(uap, uap->port.x_char);
uap->port.icount.tx++;
uap->port.x_char = 0; uap->port.x_char = 0;
return; --count;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) { if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
pl011_stop_tx(&uap->port); pl011_stop_tx(&uap->port);
return; goto done;
} }
/* If we are using DMA mode, try to send some characters. */ /* If we are using DMA mode, try to send some characters. */
if (pl011_dma_tx_irq(uap)) if (pl011_dma_tx_irq(uap))
return; goto done;
count = uap->fifosize >> 1; while (count-- > 0 && pl011_tx_char(uap, xmit->buf[xmit->tail])) {
do {
writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
uap->port.icount.tx++;
if (uart_circ_empty(xmit)) if (uart_circ_empty(xmit))
break; break;
} while (--count > 0); }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&uap->port); uart_write_wakeup(&uap->port);
if (uart_circ_empty(xmit)) if (uart_circ_empty(xmit)) {
pl011_stop_tx(&uap->port); 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) 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); 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) static irqreturn_t pl011_int(int irq, void *dev_id)
{ {
struct uart_amba_port *uap = 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| if (status & (UART011_DSRMIS|UART011_DCDMIS|
UART011_CTSMIS|UART011_RIMIS)) UART011_CTSMIS|UART011_RIMIS))
pl011_modem_status(uap); pl011_modem_status(uap);
if (status & UART011_TXIS) if (status & UART011_TXIS) {
pl011_tx_irq_seen(uap);
pl011_tx_chars(uap); pl011_tx_chars(uap);
}
if (pass_counter-- == 0) if (pass_counter-- == 0)
break; break;
@ -1577,7 +1622,7 @@ static int pl011_startup(struct uart_port *port)
{ {
struct uart_amba_port *uap = struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port); container_of(port, struct uart_amba_port, port);
unsigned int cr, lcr_h, fbrd, ibrd; unsigned int cr;
int retval; int retval;
retval = pl011_hwinit(port); 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); 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); 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 */ /* restore RTS and DTR */
cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; 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); container_of(port, struct uart_amba_port, port);
unsigned int cr; unsigned int cr;
cancel_delayed_work_sync(&uap->tx_softirq_work);
/* /*
* disable all interrupts * disable all interrupts
*/ */
spin_lock_irq(&uap->port.lock); spin_lock_irq(&uap->port.lock);
uap->im = 0; uap->im = 0;
writew(uap->im, uap->port.membase + UART011_IMSC); 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); spin_unlock_irq(&uap->port.lock);
pl011_dma_shutdown(uap); 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.ops = &amba_pl011_pops;
uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.flags = UPF_BOOT_AUTOCONF;
uap->port.line = i; 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 */ /* Ensure interrupts from this UART are masked and cleared */
writew(0, uap->port.membase + UART011_IMSC); 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) { if (!amba_reg.state) {
ret = uart_register_driver(&amba_reg); ret = uart_register_driver(&amba_reg);
if (ret < 0) { 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; return ret;
} }
} }
@ -2242,7 +2268,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
if (ret) { if (ret) {
amba_ports[i] = NULL; amba_ports[i] = NULL;
uart_unregister_driver(&amba_reg); uart_unregister_driver(&amba_reg);
pl011_dma_remove(uap);
} }
return ret; return ret;

View File

@ -649,7 +649,7 @@ static int ar933x_uart_probe(struct platform_device *pdev)
id = 0; id = 0;
} }
if (id > CONFIG_SERIAL_AR933X_NR_UARTS) if (id >= CONFIG_SERIAL_AR933X_NR_UARTS)
return -EINVAL; return -EINVAL;
irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 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); spin_lock_init(&atmel_port->lock_tx);
sg_init_table(&atmel_port->sg_tx, 1); sg_init_table(&atmel_port->sg_tx, 1);
/* UART circular tx buffer is an aligned page. */ /* 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, sg_set_page(&atmel_port->sg_tx,
virt_to_page(port->state->xmit.buf), virt_to_page(port->state->xmit.buf),
UART_XMIT_SIZE, UART_XMIT_SIZE,
@ -1034,10 +1034,10 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
spin_lock_init(&atmel_port->lock_rx); spin_lock_init(&atmel_port->lock_rx);
sg_init_table(&atmel_port->sg_rx, 1); sg_init_table(&atmel_port->sg_rx, 1);
/* UART circular rx buffer is an aligned page. */ /* 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, sg_set_page(&atmel_port->sg_rx,
virt_to_page(ring->buf), virt_to_page(ring->buf),
ATMEL_SERIAL_RINGSIZE, sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE,
(int)ring->buf & ~PAGE_MASK); (int)ring->buf & ~PAGE_MASK);
nent = dma_map_sg(port->dev, nent = dma_map_sg(port->dev,
&atmel_port->sg_rx, &atmel_port->sg_rx,
@ -1554,7 +1554,7 @@ static void atmel_tasklet_func(unsigned long data)
spin_unlock(&port->lock); 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 platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; 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; atmel_port->use_dma_tx = false;
} }
return 0;
} }
static void atmel_init_rs485(struct uart_port *port, static void atmel_init_rs485(struct uart_port *port,
@ -1777,10 +1776,13 @@ static int atmel_startup(struct uart_port *port)
if (retval) if (retval)
goto free_irq; goto free_irq;
tasklet_enable(&atmel_port->tasklet);
/* /*
* Initialize DMA (if necessary) * Initialize DMA (if necessary)
*/ */
atmel_init_property(atmel_port, pdev); atmel_init_property(atmel_port, pdev);
atmel_set_ops(port);
if (atmel_port->prepare_rx) { if (atmel_port->prepare_rx) {
retval = atmel_port->prepare_rx(port); retval = atmel_port->prepare_rx(port);
@ -1879,6 +1881,7 @@ static void atmel_shutdown(struct uart_port *port)
* Clear out any scheduled tasklets before * Clear out any scheduled tasklets before
* we destroy the buffers * we destroy the buffers
*/ */
tasklet_disable(&atmel_port->tasklet);
tasklet_kill(&atmel_port->tasklet); tasklet_kill(&atmel_port->tasklet);
/* /*
@ -2256,8 +2259,8 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
struct uart_port *port = &atmel_port->uart; struct uart_port *port = &atmel_port->uart;
struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev); 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_set_ops(port);
atmel_init_rs485(port, pdev); 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, tasklet_init(&atmel_port->tasklet, atmel_tasklet_func,
(unsigned long)port); (unsigned long)port);
tasklet_disable(&atmel_port->tasklet);
memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); 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; struct gpio_desc *gpiod;
p->gpios = mctrl_gpio_init(dev, 0); p->gpios = mctrl_gpio_init(dev, 0);
if (IS_ERR_OR_NULL(p->gpios)) if (IS_ERR(p->gpios))
return -1; return PTR_ERR(p->gpios);
for (i = 0; i < UART_GPIO_MAX; i++) { for (i = 0; i < UART_GPIO_MAX; i++) {
gpiod = mctrl_gpio_to_gpiod(p->gpios, 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); spin_lock_init(&port->lock_suspended);
ret = atmel_init_gpios(port, &pdev->dev); ret = atmel_init_gpios(port, &pdev->dev);
if (ret < 0) if (ret < 0) {
dev_err(&pdev->dev, "%s", dev_err(&pdev->dev, "Failed to initialize GPIOs.");
"Failed to initialize GPIOs. The serial port may not work as expected"); goto err;
}
ret = atmel_init_port(port, pdev); ret = atmel_init_port(port, pdev);
if (ret) 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); ret = uart_add_one_port(&bcm_uart_driver, port);
if (ret) { if (ret) {
ports[pdev->id].membase = 0; ports[pdev->id].membase = NULL;
return ret; return ret;
} }
platform_set_drvdata(pdev, port); platform_set_drvdata(pdev, port);
@ -868,7 +868,7 @@ static int bcm_uart_remove(struct platform_device *pdev)
port = platform_get_drvdata(pdev); port = platform_get_drvdata(pdev);
uart_remove_one_port(&bcm_uart_driver, port); uart_remove_one_port(&bcm_uart_driver, port);
/* mark port as free */ /* mark port as free */
ports[pdev->id].membase = 0; ports[pdev->id].membase = NULL;
return 0; return 0;
} }

View File

@ -501,6 +501,8 @@ static int uart_clps711x_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, s); platform_set_drvdata(pdev, s);
s->gpios = mctrl_gpio_init(&pdev->dev, 0); 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); ret = uart_add_one_port(&clps711x_uart, &s->port);
if (ret) if (ret)

View File

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

View File

@ -1,13 +1,10 @@
/* /*
* 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. * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
* *
* Author: Sascha Hauer <sascha@saschahauer.de> * Author: Sascha Hauer <sascha@saschahauer.de>
* Copyright (C) 2004 Pengutronix * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -18,13 +15,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * 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) #if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
@ -189,7 +179,7 @@
#define UART_NR 8 #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 { enum imx_uart_type {
IMX1_UART, IMX1_UART,
IMX21_UART, IMX21_UART,
@ -206,10 +196,8 @@ struct imx_port {
struct uart_port port; struct uart_port port;
struct timer_list timer; struct timer_list timer;
unsigned int old_status; unsigned int old_status;
int txirq, rxirq, rtsirq;
unsigned int have_rtscts:1; unsigned int have_rtscts:1;
unsigned int dte_mode:1; unsigned int dte_mode:1;
unsigned int use_irda:1;
unsigned int irda_inv_rx:1; unsigned int irda_inv_rx:1;
unsigned int irda_inv_tx:1; unsigned int irda_inv_tx:1;
unsigned short trcv_delay; /* transceiver delay */ unsigned short trcv_delay; /* transceiver delay */
@ -236,12 +224,6 @@ struct imx_port_ucrs {
unsigned int ucr3; 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[] = { static struct imx_uart_data imx_uart_devdata[] = {
[IMX1_UART] = { [IMX1_UART] = {
.uts_reg = IMX1_UTS, .uts_reg = IMX1_UTS,
@ -273,7 +255,7 @@ static struct platform_device_id imx_uart_devtype[] = {
}; };
MODULE_DEVICE_TABLE(platform, 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,imx6q-uart", .data = &imx_uart_devdata[IMX6Q_UART], },
{ .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], }, { .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
{ .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_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; struct imx_port *sport = (struct imx_port *)port;
unsigned long temp; 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 * 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. * 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) if (sport->dma_is_enabled && sport->dma_is_txing)
return; return;
temp = readl(sport->port.membase + UCR1); temp = readl(port->membase + UCR1);
writel(temp & ~UCR1_TXMPTYEN, sport->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; struct imx_port *sport = (struct imx_port *)port;
unsigned long temp; unsigned long temp;
if (USE_IRDA(sport)) { if (port->rs485.flags & SER_RS485_ENABLED) {
/* half duplex in IrDA mode; have to disable receive mode */ /* enable transmitter and shifter empty irq */
temp = readl(sport->port.membase + UCR4); temp = readl(port->membase + UCR2);
temp &= ~(UCR4_DREN); if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
writel(temp, sport->port.membase + UCR4); temp &= ~UCR2_CTS;
else
temp |= UCR2_CTS;
writel(temp, port->membase + UCR2);
temp = readl(sport->port.membase + UCR1); temp = readl(port->membase + UCR4);
temp &= ~(UCR1_RRDYEN); temp |= UCR4_TCEN;
writel(temp, sport->port.membase + UCR1); writel(temp, port->membase + UCR4);
} }
if (!sport->dma_is_enabled) { 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); 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->dma_is_enabled) {
if (sport->port.x_char) { if (sport->port.x_char) {
/* We have X-char to send, so enable TX IRQ and /* 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; unsigned int sts2;
sts = readl(sport->port.membase + USR1); sts = readl(sport->port.membase + USR1);
sts2 = readl(sport->port.membase + USR2);
if (sts & USR1_RRDY) { if (sts & USR1_RRDY) {
if (sport->dma_is_enabled) if (sport->dma_is_enabled)
@ -804,8 +753,10 @@ static irqreturn_t imx_int(int irq, void *dev_id)
imx_rxint(irq, dev_id); imx_rxint(irq, dev_id);
} }
if (sts & USR1_TRDY && if ((sts & USR1_TRDY &&
readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) ||
(sts2 & USR2_TXDC &&
readl(sport->port.membase + UCR4) & UCR4_TCEN))
imx_txint(irq, dev_id); imx_txint(irq, dev_id);
if (sts & USR1_RTSD) if (sts & USR1_RTSD)
@ -814,11 +765,10 @@ static irqreturn_t imx_int(int irq, void *dev_id)
if (sts & USR1_AWAKE) if (sts & USR1_AWAKE)
writel(USR1_AWAKE, sport->port.membase + USR1); writel(USR1_AWAKE, sport->port.membase + USR1);
sts2 = readl(sport->port.membase + USR2);
if (sts2 & USR2_ORE) { if (sts2 & USR2_ORE) {
dev_err(sport->port.dev, "Rx FIFO overrun\n"); dev_err(sport->port.dev, "Rx FIFO overrun\n");
sport->port.icount.overrun++; sport->port.icount.overrun++;
writel(sts2 | USR2_ORE, sport->port.membase + USR2); writel(USR2_ORE, sport->port.membase + USR2);
} }
return IRQ_HANDLED; 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; struct imx_port *sport = (struct imx_port *)port;
unsigned long temp; unsigned long temp;
temp = readl(sport->port.membase + UCR2) & ~(UCR2_CTS | UCR2_CTSC); if (!(port->rs485.flags & SER_RS485_ENABLED)) {
if (mctrl & TIOCM_RTS) temp = readl(sport->port.membase + UCR2);
temp |= UCR2_CTS | UCR2_CTSC; temp &= ~(UCR2_CTS | UCR2_CTSC);
if (mctrl & TIOCM_RTS)
writel(temp, sport->port.membase + UCR2); temp |= UCR2_CTS | UCR2_CTSC;
writel(temp, sport->port.membase + UCR2);
}
temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP; temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP;
if (mctrl & TIOCM_LOOP) if (mctrl & TIOCM_LOOP)
@ -1156,9 +1108,6 @@ static int imx_startup(struct uart_port *port)
*/ */
temp = readl(sport->port.membase + UCR4); temp = readl(sport->port.membase + UCR4);
if (USE_IRDA(sport))
temp |= UCR4_IRSC;
/* set the trigger level for CTS */ /* set the trigger level for CTS */
temp &= ~(UCR4_CTSTL_MASK << UCR4_CTSTL_SHF); temp &= ~(UCR4_CTSTL_MASK << UCR4_CTSTL_SHF);
temp |= CTSTL << 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); imx_uart_dma_init(sport);
spin_lock_irqsave(&sport->port.lock, flags); spin_lock_irqsave(&sport->port.lock, flags);
/* /*
* Finally, clear and enable interrupts * Finally, clear and enable interrupts
*/ */
writel(USR1_RTSD, sport->port.membase + USR1); writel(USR1_RTSD, sport->port.membase + USR1);
writel(USR2_ORE, sport->port.membase + USR2);
if (sport->dma_is_inited && !sport->dma_is_enabled) if (sport->dma_is_inited && !sport->dma_is_enabled)
imx_enable_dma(sport); imx_enable_dma(sport);
@ -1192,17 +1143,8 @@ static int imx_startup(struct uart_port *port)
temp = readl(sport->port.membase + UCR1); temp = readl(sport->port.membase + UCR1);
temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN; temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
if (USE_IRDA(sport)) {
temp |= UCR1_IREN;
temp &= ~(UCR1_RTSDEN);
}
writel(temp, sport->port.membase + UCR1); 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 = readl(sport->port.membase + UCR4);
temp |= UCR4_OREN; temp |= UCR4_OREN;
writel(temp, sport->port.membase + UCR4); writel(temp, sport->port.membase + UCR4);
@ -1219,38 +1161,12 @@ static int imx_startup(struct uart_port *port)
writel(temp, sport->port.membase + UCR3); 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 * Enable modem status interrupts
*/ */
imx_enable_ms(&sport->port); imx_enable_ms(&sport->port);
spin_unlock_irqrestore(&sport->port.lock, flags); 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; return 0;
} }
@ -1286,13 +1202,6 @@ static void imx_shutdown(struct uart_port *port)
writel(temp, sport->port.membase + UCR2); writel(temp, sport->port.membase + UCR2);
spin_unlock_irqrestore(&sport->port.lock, flags); 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. * Stop our timer.
*/ */
@ -1305,8 +1214,6 @@ static void imx_shutdown(struct uart_port *port)
spin_lock_irqsave(&sport->port.lock, flags); spin_lock_irqsave(&sport->port.lock, flags);
temp = readl(sport->port.membase + UCR1); temp = readl(sport->port.membase + UCR1);
temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
if (USE_IRDA(sport))
temp &= ~(UCR1_IREN);
writel(temp, sport->port.membase + UCR1); writel(temp, sport->port.membase + UCR1);
spin_unlock_irqrestore(&sport->port.lock, flags); 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 imx_port *sport = (struct imx_port *)port;
struct scatterlist *sgl = &sport->tx_sgl[0]; struct scatterlist *sgl = &sport->tx_sgl[0];
unsigned long temp; unsigned long temp;
int i = 100, ubir, ubmr, ubrc, uts; int i = 100, ubir, ubmr, uts;
if (!sport->dma_chan_tx) if (!sport->dma_chan_tx)
return; return;
@ -1345,7 +1252,6 @@ static void imx_flush_buffer(struct uart_port *port)
*/ */
ubir = readl(sport->port.membase + UBIR); ubir = readl(sport->port.membase + UBIR);
ubmr = readl(sport->port.membase + UBMR); ubmr = readl(sport->port.membase + UBMR);
ubrc = readl(sport->port.membase + UBRC);
uts = readl(sport->port.membase + IMX21_UTS); uts = readl(sport->port.membase + IMX21_UTS);
temp = readl(sport->port.membase + UCR2); temp = readl(sport->port.membase + UCR2);
@ -1358,7 +1264,6 @@ static void imx_flush_buffer(struct uart_port *port)
/* Restore the registers */ /* Restore the registers */
writel(ubir, sport->port.membase + UBIR); writel(ubir, sport->port.membase + UBIR);
writel(ubmr, sport->port.membase + UBMR); writel(ubmr, sport->port.membase + UBMR);
writel(ubrc, sport->port.membase + UBRC);
writel(uts, sport->port.membase + IMX21_UTS); 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; unsigned long num, denom;
uint64_t tdiv64; 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. * 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 (termios->c_cflag & CRTSCTS) {
if (sport->have_rtscts) { if (sport->have_rtscts) {
ucr2 &= ~UCR2_IRTS; ucr2 &= ~UCR2_IRTS;
ucr2 |= UCR2_CTSC;
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 { } else {
termios->c_cflag &= ~CRTSCTS; 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) if (termios->c_cflag & CSTOPB)
ucr2 |= UCR2_STPB; ucr2 |= UCR2_STPB;
@ -1471,24 +1382,16 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
sport->port.membase + UCR2); sport->port.membase + UCR2);
old_txrxen &= (UCR2_TXEN | UCR2_RXEN); old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
if (USE_IRDA(sport)) { /* custom-baudrate handling */
/* div = sport->port.uartclk / (baud * 16);
* use maximum available submodule frequency to if (baud == 38400 && quot != div)
* avoid missing short pulses due to low sampling rate baud = sport->port.uartclk / (quot * 16);
*/
div = 1;
} else {
/* custom-baudrate handling */
div = sport->port.uartclk / (baud * 16);
if (baud == 38400 && quot != div)
baud = sport->port.uartclk / (quot * 16);
div = sport->port.uartclk / (baud * 16); div = sport->port.uartclk / (baud * 16);
if (div > 7) if (div > 7)
div = 7; div = 7;
if (!div) if (!div)
div = 1; div = 1;
}
rational_best_approximation(16 * div * baud, sport->port.uartclk, rational_best_approximation(16 * div * baud, sport->port.uartclk,
1 << 16, 1 << 16, &num, &denom); 1 << 16, 1 << 16, &num, &denom);
@ -1635,6 +1538,38 @@ static void imx_poll_put_char(struct uart_port *port, unsigned char c)
} }
#endif #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 = { static struct uart_ops imx_pops = {
.tx_empty = imx_tx_empty, .tx_empty = imx_tx_empty,
.set_mctrl = imx_set_mctrl, .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)) if (of_get_property(np, "fsl,uart-has-rtscts", NULL))
sport->have_rtscts = 1; 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)) if (of_get_property(np, "fsl,dte-mode", NULL))
sport->dte_mode = 1; sport->dte_mode = 1;
@ -1958,9 +1890,6 @@ static void serial_imx_probe_pdata(struct imx_port *sport,
if (pdata->flags & IMXUART_HAVE_RTSCTS) if (pdata->flags & IMXUART_HAVE_RTSCTS)
sport->have_rtscts = 1; sport->have_rtscts = 1;
if (pdata->flags & IMXUART_IRDA)
sport->use_irda = 1;
} }
static int serial_imx_probe(struct platform_device *pdev) 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; void __iomem *base;
int ret = 0; int ret = 0;
struct resource *res; struct resource *res;
int txirq, rxirq, rtsirq;
sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL); sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
if (!sport) if (!sport)
@ -1985,17 +1915,21 @@ static int serial_imx_probe(struct platform_device *pdev)
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_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.dev = &pdev->dev;
sport->port.mapbase = res->start; sport->port.mapbase = res->start;
sport->port.membase = base; sport->port.membase = base;
sport->port.type = PORT_IMX, sport->port.type = PORT_IMX,
sport->port.iotype = UPIO_MEM; sport->port.iotype = UPIO_MEM;
sport->port.irq = platform_get_irq(pdev, 0); sport->port.irq = rxirq;
sport->rxirq = platform_get_irq(pdev, 0);
sport->txirq = platform_get_irq(pdev, 1);
sport->rtsirq = platform_get_irq(pdev, 2);
sport->port.fifosize = 32; sport->port.fifosize = 32;
sport->port.ops = &imx_pops; 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; sport->port.flags = UPF_BOOT_AUTOCONF;
init_timer(&sport->timer); init_timer(&sport->timer);
sport->timer.function = imx_timeout; 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 * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
* chips only have one interrupt. * chips only have one interrupt.
*/ */
if (sport->txirq > 0) { if (txirq > 0) {
ret = devm_request_irq(&pdev->dev, sport->rxirq, imx_rxint, 0, ret = devm_request_irq(&pdev->dev, rxirq, imx_rxint, 0,
dev_name(&pdev->dev), sport); dev_name(&pdev->dev), sport);
if (ret) if (ret)
return 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); dev_name(&pdev->dev), sport);
if (ret) if (ret)
return 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 { } 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); dev_name(&pdev->dev), sport);
if (ret) if (ret)
return ret; return ret;

View File

@ -782,7 +782,7 @@ static int max3100_probe(struct spi_device *spi)
pdata = dev_get_platdata(&spi->dev); pdata = dev_get_platdata(&spi->dev);
max3100s[i]->crystal = pdata->crystal; max3100s[i]->crystal = pdata->crystal;
max3100s[i]->loopback = pdata->loopback; 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) if (pdata->poll_time > 0 && max3100s[i]->poll_time == 0)
max3100s[i]->poll_time = 1; max3100s[i]->poll_time = 1;
max3100s[i]->max3100_hw_suspend = pdata->max3100_hw_suspend; 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; 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; enum mctrl_gpio_idx i;
struct gpio_desc *gpiod; struct gpio_desc *gpiod;
s->gpios = mctrl_gpio_init(dev, 0); s->gpios = mctrl_gpio_init(dev, 0);
if (IS_ERR_OR_NULL(s->gpios)) if (IS_ERR(s->gpios))
return false; return PTR_ERR(s->gpios);
/* Block (enabled before) DMA option if RTS or CTS is GPIO line */ /* Block (enabled before) DMA option if RTS or CTS is GPIO line */
if (!RTS_AT_AUART() || !CTS_AT_AUART()) { 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; s->gpio_irq[i] = -EINVAL;
} }
return true; return 0;
} }
static void mxs_auart_free_gpio_irq(struct mxs_auart_port *s) 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); platform_set_drvdata(pdev, s);
if (!mxs_auart_init_gpios(s, &pdev->dev)) ret = mxs_auart_init_gpios(s, &pdev->dev);
dev_err(&pdev->dev, if (ret) {
"Failed to initialize GPIOs. The serial port may not work as expected\n"); dev_err(&pdev->dev, "Failed to initialize GPIOs.\n");
got out_free_irq;
}
/* /*
* Get the GPIO lines 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; cprev = cnow;
} }
__set_current_state(TASK_RUNNING);
current->state = TASK_RUNNING;
remove_wait_queue(&port->delta_msr_wait, &wait); remove_wait_queue(&port->delta_msr_wait, &wait);
return ret; return ret;
@ -1809,6 +1808,52 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
return ports + idx; 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. * uart_parse_options - Parse serial port baud/parity/bits/flow control.
* @options: pointer to option string * @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]; int value_array[UART_GPIO_MAX];
unsigned int count = 0; unsigned int count = 0;
if (IS_ERR_OR_NULL(gpios))
return;
for (i = 0; i < UART_GPIO_MAX; i++) for (i = 0; i < UART_GPIO_MAX; i++)
if (!IS_ERR_OR_NULL(gpios->gpio[i]) && if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
mctrl_gpios_desc[i].dir_out) { 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, struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
enum mctrl_gpio_idx gidx) enum mctrl_gpio_idx gidx)
{ {
if (!IS_ERR_OR_NULL(gpios) && !IS_ERR_OR_NULL(gpios->gpio[gidx])) return gpios->gpio[gidx];
return gpios->gpio[gidx];
else
return NULL;
} }
EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod); 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; 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++) { for (i = 0; i < UART_GPIO_MAX; i++) {
if (!IS_ERR_OR_NULL(gpios->gpio[i]) && if (gpios->gpio[i] && !mctrl_gpios_desc[i].dir_out) {
!mctrl_gpios_desc[i].dir_out) {
if (gpiod_get_value(gpios->gpio[i])) if (gpiod_get_value(gpios->gpio[i]))
*mctrl |= mctrl_gpios_desc[i].mctrl; *mctrl |= mctrl_gpios_desc[i].mctrl;
else else
@ -107,27 +94,20 @@ struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
for (i = 0; i < UART_GPIO_MAX; i++) { for (i = 0; i < UART_GPIO_MAX; i++) {
gpios->gpio[i] = devm_gpiod_get_index(dev, enum gpiod_flags flags;
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;
if (mctrl_gpios_desc[i].dir_out) if (mctrl_gpios_desc[i].dir_out)
err = gpiod_direction_output(gpios->gpio[i], 0); flags = GPIOD_OUT_LOW;
else else
err = gpiod_direction_input(gpios->gpio[i]); flags = GPIOD_IN;
if (err) {
dev_dbg(dev, "Unable to set direction for %s GPIO", gpios->gpio[i] =
mctrl_gpios_desc[i].name); devm_gpiod_get_index_optional(dev,
devm_gpiod_put(dev, gpios->gpio[i]); mctrl_gpios_desc[i].name,
gpios->gpio[i] = NULL; idx, flags);
}
if (IS_ERR(gpios->gpio[i]))
return PTR_ERR(gpios->gpio[i]);
} }
return gpios; return gpios;
@ -138,9 +118,6 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
{ {
enum mctrl_gpio_idx i; enum mctrl_gpio_idx i;
if (IS_ERR_OR_NULL(gpios))
return;
for (i = 0; i < UART_GPIO_MAX; i++) for (i = 0; i < UART_GPIO_MAX; i++)
if (!IS_ERR_OR_NULL(gpios->gpio[i])) if (!IS_ERR_OR_NULL(gpios->gpio[i]))
devm_gpiod_put(dev, 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; return -EINVAL;
if (port->irq != ser->irq) if (port->irq != ser->irq)
return -EINVAL; return -EINVAL;
if (port->iotype != ser->io_type)
return -EINVAL;
return 0; return 0;
} }
@ -707,7 +709,7 @@ static int sprd_probe(struct platform_device *pdev)
up->dev = &pdev->dev; up->dev = &pdev->dev;
up->line = index; up->line = index;
up->type = PORT_SPRD; up->type = PORT_SPRD;
up->iotype = SERIAL_IO_PORT; up->iotype = UPIO_MEM;
up->uartclk = SPRD_DEF_RATE; up->uartclk = SPRD_DEF_RATE;
up->fifosize = SPRD_FIFO_SIZE; up->fifosize = SPRD_FIFO_SIZE;
up->ops = &serial_sprd_ops; up->ops = &serial_sprd_ops;
@ -754,6 +756,7 @@ static int sprd_probe(struct platform_device *pdev)
return ret; return ret;
} }
#ifdef CONFIG_PM_SLEEP
static int sprd_suspend(struct device *dev) static int sprd_suspend(struct device *dev)
{ {
struct sprd_uart_port *sup = dev_get_drvdata(dev); struct sprd_uart_port *sup = dev_get_drvdata(dev);
@ -771,6 +774,7 @@ static int sprd_resume(struct device *dev)
return 0; return 0;
} }
#endif
static SIMPLE_DEV_PM_OPS(sprd_pm_ops, sprd_suspend, sprd_resume); 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; return -EINVAL;
if (!port->mapbase) { 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; 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 { u8 r; u8 g; u8 b; };
struct rgb rgb_from_256(int i) static struct rgb rgb_from_256(int i)
{ {
struct rgb c; struct rgb c;
if (i < 8) { /* Standard colours. */ if (i < 8) { /* Standard colours. */
@ -1573,7 +1573,7 @@ static void setterm_command(struct vc_data *vc)
case 11: /* set bell duration in msec */ case 11: /* set bell duration in msec */
if (vc->vc_npar >= 1) if (vc->vc_npar >= 1)
vc->vc_bell_duration = (vc->vc_par[1] < 2000) ? 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 else
vc->vc_bell_duration = DEFAULT_BELL_DURATION; vc->vc_bell_duration = DEFAULT_BELL_DURATION;
break; break;

View File

@ -388,7 +388,7 @@ int vt_ioctl(struct tty_struct *tty,
* Generate the tone for the appropriate number of ticks. * Generate the tone for the appropriate number of ticks.
* If the time is zero, turn off sound ourselves. * 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; count = ticks ? (arg & 0xffff) : 0;
if (count) if (count)
count = PIT_TICK_RATE / 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 ASMARM_ARCH_UART_H
#define IMXUART_HAVE_RTSCTS (1<<0) #define IMXUART_HAVE_RTSCTS (1<<0)
#define IMXUART_IRDA (1<<1)
struct imxuart_platform_data { struct imxuart_platform_data {
unsigned int flags; 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 #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 uart_port *uart_get_console(struct uart_port *ports, int nr,
struct console *c); 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, void uart_parse_options(char *options, int *baud, int *parity, int *bits,
int *flow); int *flow);
int uart_set_options(struct uart_port *port, struct console *co, int baud, 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_PXAR16 0x80 /* receive FIFO threshold = 16 */
#define UART_FCR_PXAR32 0xc0 /* receive FIFO threshold = 32 */ #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 * 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) newcon->setup(newcon, console_cmdline[i].options) != 0)
break; break;
newcon->flags |= CON_ENABLED; newcon->flags |= CON_ENABLED;
newcon->index = c->index;
if (i == selected_console) { if (i == selected_console) {
newcon->flags |= CON_CONSDEV; newcon->flags |= CON_CONSDEV;
preferred_console = selected_console; preferred_console = selected_console;