Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 374173
b: refs/heads/master
c: 787b0c1
h: refs/heads/master
i:
  374171: 686a2e3
v: v3
  • Loading branch information
Arnd Bergmann committed Mar 12, 2013
1 parent aa51f24 commit ef5aeee
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: dc715452e9145156840b09df765ea2ede4851eda
refs/heads/master: 787b0c1f8e1975157fe73104e67cac18f955281b
19 changes: 18 additions & 1 deletion trunk/Documentation/devicetree/bindings/arm/primecell.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,31 @@ Optional properties:
- clocks : From common clock binding. First clock is phandle to clock for apb
pclk. Additional clocks are optional and specific to those peripherals.
- clock-names : From common clock binding. Shall be "apb_pclk" for first clock.
- dmas : From common DMA binding. If present, refers to one or more dma channels.
- dma-names : From common DMA binding, needs to match the 'dmas' property.
Devices with exactly one receive and transmit channel shall name
these "rx" and "tx", respectively.
- pinctrl-<n> : Pinctrl states as described in bindings/pinctrl/pinctrl-bindings.txt
- pinctrl-names : Names corresponding to the numbered pinctrl states
- interrupts : one or more interrupt specifiers
- interrupt-names : names corresponding to the interrupts properties

Example:

serial@fff36000 {
compatible = "arm,pl011", "arm,primecell";
arm,primecell-periphid = <0x00341011>;

clocks = <&pclk>;
clock-names = "apb_pclk";


dmas = <&dma-controller 4>, <&dma-controller 5>;
dma-names = "rx", "tx";

pinctrl-0 = <&uart0_default_mux>, <&uart0_default_mode>;
pinctrl-1 = <&uart0_sleep_mode>;
pinctrl-names = "default","sleep";

interrupts = <0 11 0x4>;
};

17 changes: 17 additions & 0 deletions trunk/Documentation/devicetree/bindings/serial/pl011.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
* ARM AMBA Primecell PL011 serial UART

Required properties:
- compatible: must be "arm,primecell", "arm,pl011"
- reg: exactly one register range with length 0x1000
- interrupts: exactly one interrupt specifier

Optional properties:
- pinctrl: When present, must have one state named "sleep"
and one state named "default"
- clocks: When present, must refer to exactly one clock named
"apb_pclk"
- dmas: When present, may have one or two dma channels.
The first one must be named "rx", the second one
must be named "tx".

See also bindings/arm/primecell.txt
62 changes: 37 additions & 25 deletions trunk/drivers/tty/serial/amba-pl011.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
}
}

static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap)
{
/* DMA is the sole user of the platform data right now */
struct amba_pl011_data *plat = uap->port.dev->platform_data;
Expand All @@ -259,20 +259,25 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
struct dma_chan *chan;
dma_cap_mask_t mask;

/* We need platform data */
if (!plat || !plat->dma_filter) {
dev_info(uap->port.dev, "no DMA platform data\n");
return;
}
chan = dma_request_slave_channel(dev, "tx");

/* Try to acquire a generic DMA engine slave TX channel */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);

chan = dma_request_channel(mask, plat->dma_filter, plat->dma_tx_param);
if (!chan) {
dev_err(uap->port.dev, "no TX DMA channel!\n");
return;
/* We need platform data */
if (!plat || !plat->dma_filter) {
dev_info(uap->port.dev, "no DMA platform data\n");
return;
}

/* Try to acquire a generic DMA engine slave TX channel */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);

chan = dma_request_channel(mask, plat->dma_filter,
plat->dma_tx_param);
if (!chan) {
dev_err(uap->port.dev, "no TX DMA channel!\n");
return;
}
}

dmaengine_slave_config(chan, &tx_conf);
Expand All @@ -282,7 +287,18 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
dma_chan_name(uap->dmatx.chan));

/* Optionally make use of an RX channel as well */
if (plat->dma_rx_param) {
chan = dma_request_slave_channel(dev, "rx");

if (!chan && plat->dma_rx_param) {
chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);

if (!chan) {
dev_err(uap->port.dev, "no RX DMA channel!\n");
return;
}
}

if (chan) {
struct dma_slave_config rx_conf = {
.src_addr = uap->port.mapbase + UART01x_DR,
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
Expand All @@ -291,12 +307,6 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
.device_fc = false,
};

chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
if (!chan) {
dev_err(uap->port.dev, "no RX DMA channel!\n");
return;
}

dmaengine_slave_config(chan, &rx_conf);
uap->dmarx.chan = chan;

Expand All @@ -315,6 +325,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
struct dma_uap {
struct list_head node;
struct uart_amba_port *uap;
struct device *dev;
};

static LIST_HEAD(pl011_dma_uarts);
Expand All @@ -325,7 +336,7 @@ static int __init pl011_dma_initcall(void)

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->uap);
pl011_dma_probe_initcall(dmau->dev, dmau->uap);
list_del(node);
kfree(dmau);
}
Expand All @@ -334,18 +345,19 @@ static int __init pl011_dma_initcall(void)

device_initcall(pl011_dma_initcall);

static void pl011_dma_probe(struct uart_amba_port *uap)
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 uart_amba_port *uap)
static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
{
pl011_dma_probe_initcall(uap);
pl011_dma_probe_initcall(dev, uap);
}
#endif

Expand Down Expand Up @@ -2020,7 +2032,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
uap->port.ops = &amba_pl011_pops;
uap->port.flags = UPF_BOOT_AUTOCONF;
uap->port.line = i;
pl011_dma_probe(uap);
pl011_dma_probe(&dev->dev, uap);

/* Ensure interrupts from this UART are masked and cleared */
writew(0, uap->port.membase + UART011_IMSC);
Expand Down

0 comments on commit ef5aeee

Please sign in to comment.