Skip to content

Commit

Permalink
Merge tag 'devicetree-for-4.1' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/robh/linux

Pull second batch of devicetree updates from Rob Herring:
 "As Grant mentioned in the first devicetree pull request, here is the
  2nd batch of DT changes for 4.1.  The main remaining item here is the
  endianness bindings and related 8250 driver support.

   - DT endianness specification bindings

   - big-endian 8250 serial support

   - DT overlay unittest updates

   - various DT doc updates

   - compile fixes for OF_IRQ=n"

* tag 'devicetree-for-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux:
  frv: add io{read,write}{16,32}be functions
  mn10300: add io{read,write}{16,32}be functions
  Documentation: DT bindings: add doc for Altera's SoCFPGA platform
  of: base: improve of_get_next_child() kernel-doc
  Doc: dt: arch_timer: discourage clock-frequency use
  of: unittest: overlay: Keep track of created overlays
  of/fdt: fix allocation size for device node path
  serial: of_serial: Support big-endian register accesses
  serial: 8250: Add support for big-endian MMIO accesses
  of: Document {little,big,native}-endian bindings
  of/fdt: Add endianness helper function for early init code
  of: Add helper function to check MMIO register endianness
  of/fdt: Remove "reg" data prints from early_init_dt_scan_memory
  of: add vendor prefix for Artesyn
  of: Add dummy of_irq_to_resource_table() for IRQ_OF=n
  of: OF_IRQ should depend on IRQ_DOMAIN
  • Loading branch information
torvalds committed Apr 24, 2015
2 parents 836ee48 + 04fca0e commit d56a669
Show file tree
Hide file tree
Showing 16 changed files with 243 additions and 11 deletions.
14 changes: 14 additions & 0 deletions Documentation/devicetree/bindings/arm/altera.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Altera's SoCFPGA platform device tree bindings
---------------------------------------------

Boards with Cyclone 5 SoC:
Required root node properties:
compatible = "altr,socfpga-cyclone5", "altr,socfpga";

Boards with Arria 5 SoC:
Required root node properties:
compatible = "altr,socfpga-arria5", "altr,socfpga";

Boards with Arria 10 SoC:
Required root node properties:
compatible = "altr,socfpga-arria10", "altr,socfpga";
8 changes: 6 additions & 2 deletions Documentation/devicetree/bindings/arm/arch_timer.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ to deliver its interrupts via SPIs.
- interrupts : Interrupt list for secure, non-secure, virtual and
hypervisor timers, in that order.

- clock-frequency : The frequency of the main counter, in Hz. Optional.
- clock-frequency : The frequency of the main counter, in Hz. Should be present
only where necessary to work around broken firmware which does not configure
CNTFRQ on all CPUs to a uniform correct value. Use of this property is
strongly discouraged; fix your firmware unless absolutely impossible.

- always-on : a boolean property. If present, the timer is powered through an
always-on power domain, therefore it never loses context.
Expand Down Expand Up @@ -46,7 +49,8 @@ Example:

- compatible : Should at least contain "arm,armv7-timer-mem".

- clock-frequency : The frequency of the main counter, in Hz. Optional.
- clock-frequency : The frequency of the main counter, in Hz. Should be present
only when firmware has not configured the MMIO CNTFRQ registers.

- reg : The control frame base address.

Expand Down
60 changes: 60 additions & 0 deletions Documentation/devicetree/bindings/common-properties.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
Common properties

The ePAPR specification does not define any properties related to hardware
byteswapping, but endianness issues show up frequently in porting Linux to
different machine types. This document attempts to provide a consistent
way of handling byteswapping across drivers.

Optional properties:
- big-endian: Boolean; force big endian register accesses
unconditionally (e.g. ioread32be/iowrite32be). Use this if you
know the peripheral always needs to be accessed in BE mode.
- little-endian: Boolean; force little endian register accesses
unconditionally (e.g. readl/writel). Use this if you know the
peripheral always needs to be accessed in LE mode.
- native-endian: Boolean; always use register accesses matched to the
endianness of the kernel binary (e.g. LE vmlinux -> readl/writel,
BE vmlinux -> ioread32be/iowrite32be). In this case no byteswaps
will ever be performed. Use this if the hardware "self-adjusts"
register endianness based on the CPU's configured endianness.

If a binding supports these properties, then the binding should also
specify the default behavior if none of these properties are present.
In such cases, little-endian is the preferred default, but it is not
a requirement. The of_device_is_big_endian() and of_fdt_is_big_endian()
helper functions do assume that little-endian is the default, because
most existing (PCI-based) drivers implicitly default to LE by using
readl/writel for MMIO accesses.

Examples:
Scenario 1 : CPU in LE mode & device in LE mode.
dev: dev@40031000 {
compatible = "name";
reg = <0x40031000 0x1000>;
...
native-endian;
};

Scenario 2 : CPU in LE mode & device in BE mode.
dev: dev@40031000 {
compatible = "name";
reg = <0x40031000 0x1000>;
...
big-endian;
};

Scenario 3 : CPU in BE mode & device in BE mode.
dev: dev@40031000 {
compatible = "name";
reg = <0x40031000 0x1000>;
...
native-endian;
};

Scenario 4 : CPU in BE mode & device in LE mode.
dev: dev@40031000 {
compatible = "name";
reg = <0x40031000 0x1000>;
...
little-endian;
};
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/vendor-prefixes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ aptina Aptina Imaging
arasan Arasan Chip Systems
arm ARM Ltd.
armadeus ARMadeus Systems SARL
artesyn Artesyn Embedded Technologies Inc.
asahi-kasei Asahi Kasei Corp.
atmel Atmel Corporation
auo AU Optronics Corporation
Expand Down
5 changes: 5 additions & 0 deletions arch/frv/include/asm/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,11 @@ static inline void iowrite32(u32 val, void __iomem *p)
__flush_PCI_writes();
}

#define ioread16be(addr) be16_to_cpu(ioread16(addr))
#define ioread32be(addr) be32_to_cpu(ioread32(addr))
#define iowrite16be(v, addr) iowrite16(cpu_to_be16(v), (addr))
#define iowrite32be(v, addr) iowrite32(cpu_to_be32(v), (addr))

static inline void ioread8_rep(void __iomem *p, void *dst, unsigned long count)
{
io_insb((unsigned long) p, dst, count);
Expand Down
5 changes: 5 additions & 0 deletions arch/mn10300/include/asm/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ static inline void outsl(unsigned long addr, const void *buffer, int count)
#define iowrite16(v, addr) writew((v), (addr))
#define iowrite32(v, addr) writel((v), (addr))

#define ioread16be(addr) be16_to_cpu(readw(addr))
#define ioread32be(addr) be32_to_cpu(readl(addr))
#define iowrite16be(v, addr) writew(cpu_to_be16(v), (addr))
#define iowrite32be(v, addr) writel(cpu_to_be32(v), (addr))

#define ioread8_rep(p, dst, count) \
insb((unsigned long) (p), (dst), (count))
#define ioread16_rep(p, dst, count) \
Expand Down
2 changes: 1 addition & 1 deletion drivers/of/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ config OF_ADDRESS_PCI

config OF_IRQ
def_bool y
depends on !SPARC
depends on !SPARC && IRQ_DOMAIN

config OF_NET
depends on NETDEVICES
Expand Down
28 changes: 26 additions & 2 deletions drivers/of/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,29 @@ bool of_device_is_available(const struct device_node *device)
}
EXPORT_SYMBOL(of_device_is_available);

/**
* of_device_is_big_endian - check if a device has BE registers
*
* @device: Node to check for endianness
*
* Returns true if the device has a "big-endian" property, or if the kernel
* was compiled for BE *and* the device has a "native-endian" property.
* Returns false otherwise.
*
* Callers would nominally use ioread32be/iowrite32be if
* of_device_is_big_endian() == true, or readl/writel otherwise.
*/
bool of_device_is_big_endian(const struct device_node *device)
{
if (of_property_read_bool(device, "big-endian"))
return true;
if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
of_property_read_bool(device, "native-endian"))
return true;
return false;
}
EXPORT_SYMBOL(of_device_is_big_endian);

/**
* of_get_parent - Get a node's parent if any
* @node: Node to get parent
Expand Down Expand Up @@ -640,8 +663,9 @@ static struct device_node *__of_get_next_child(const struct device_node *node,
* @node: parent node
* @prev: previous child of the parent node, or NULL to get first
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
* Returns a node pointer with refcount incremented, use of_node_put() on
* it when done. Returns NULL when prev is the last child. Decrements the
* refcount of prev.
*/
struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev)
Expand Down
24 changes: 21 additions & 3 deletions drivers/of/fdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,25 @@ int of_fdt_is_compatible(const void *blob,
return 0;
}

/**
* of_fdt_is_big_endian - Return true if given node needs BE MMIO accesses
* @blob: A device tree blob
* @node: node to test
*
* Returns true if the node has a "big-endian" property, or if the kernel
* was compiled for BE *and* the node has a "native-endian" property.
* Returns false otherwise.
*/
bool of_fdt_is_big_endian(const void *blob, unsigned long node)
{
if (fdt_getprop(blob, node, "big-endian", NULL))
return true;
if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
fdt_getprop(blob, node, "native-endian", NULL))
return true;
return false;
}

/**
* of_fdt_match - Return true if node matches a list of compatible values
*/
Expand Down Expand Up @@ -172,7 +191,7 @@ static void * unflatten_dt_node(void *blob,
if (!pathp)
return mem;

allocl = l++;
allocl = ++l;

/* version 0x10 has a more compact unit name here instead of the full
* path. we accumulate the full path size using "fpsize", we'll rebuild
Expand Down Expand Up @@ -879,8 +898,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,

endp = reg + (l / sizeof(__be32));

pr_debug("memory scan node %s, reg size %d, data: %x %x %x %x,\n",
uname, l, reg[0], reg[1], reg[2], reg[3]);
pr_debug("memory scan node %s, reg size %d,\n", uname, l);

while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
u64 base, size;
Expand Down
62 changes: 62 additions & 0 deletions drivers/of/unittest.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include <linux/i2c.h>
#include <linux/i2c-mux.h>

#include <linux/bitops.h>

#include "of_private.h"

static struct unittest_results {
Expand Down Expand Up @@ -1109,6 +1111,59 @@ static const char *overlay_path(int nr)

static const char *bus_path = "/testcase-data/overlay-node/test-bus";

/* it is guaranteed that overlay ids are assigned in sequence */
#define MAX_UNITTEST_OVERLAYS 256
static unsigned long overlay_id_bits[BITS_TO_LONGS(MAX_UNITTEST_OVERLAYS)];
static int overlay_first_id = -1;

static void of_unittest_track_overlay(int id)
{
if (overlay_first_id < 0)
overlay_first_id = id;
id -= overlay_first_id;

/* we shouldn't need that many */
BUG_ON(id >= MAX_UNITTEST_OVERLAYS);
overlay_id_bits[BIT_WORD(id)] |= BIT_MASK(id);
}

static void of_unittest_untrack_overlay(int id)
{
if (overlay_first_id < 0)
return;
id -= overlay_first_id;
BUG_ON(id >= MAX_UNITTEST_OVERLAYS);
overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);
}

static void of_unittest_destroy_tracked_overlays(void)
{
int id, ret, defers;

if (overlay_first_id < 0)
return;

/* try until no defers */
do {
defers = 0;
/* remove in reverse order */
for (id = MAX_UNITTEST_OVERLAYS - 1; id >= 0; id--) {
if (!(overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id)))
continue;

ret = of_overlay_destroy(id + overlay_first_id);
if (ret != 0) {
defers++;
pr_warn("%s: overlay destroy failed for #%d\n",
__func__, id + overlay_first_id);
continue;
}

overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);
}
} while (defers > 0);
}

static int of_unittest_apply_overlay(int unittest_nr, int overlay_nr,
int *overlay_id)
{
Expand All @@ -1130,6 +1185,7 @@ static int of_unittest_apply_overlay(int unittest_nr, int overlay_nr,
goto out;
}
id = ret;
of_unittest_track_overlay(id);

ret = 0;

Expand Down Expand Up @@ -1343,6 +1399,7 @@ static void of_unittest_overlay_6(void)
return;
}
ov_id[i] = ret;
of_unittest_track_overlay(ov_id[i]);
}

for (i = 0; i < 2; i++) {
Expand All @@ -1367,6 +1424,7 @@ static void of_unittest_overlay_6(void)
PDEV_OVERLAY));
return;
}
of_unittest_untrack_overlay(ov_id[i]);
}

for (i = 0; i < 2; i++) {
Expand Down Expand Up @@ -1411,6 +1469,7 @@ static void of_unittest_overlay_8(void)
return;
}
ov_id[i] = ret;
of_unittest_track_overlay(ov_id[i]);
}

/* now try to remove first overlay (it should fail) */
Expand All @@ -1433,6 +1492,7 @@ static void of_unittest_overlay_8(void)
PDEV_OVERLAY));
return;
}
of_unittest_untrack_overlay(ov_id[i]);
}

unittest(1, "overlay test %d passed\n", 8);
Expand Down Expand Up @@ -1855,6 +1915,8 @@ static void __init of_unittest_overlay(void)
of_unittest_overlay_i2c_cleanup();
#endif

of_unittest_destroy_tracked_overlays();

out:
of_node_put(bus_np);
}
Expand Down
20 changes: 20 additions & 0 deletions drivers/tty/serial/8250/8250_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,18 @@ static unsigned int mem32_serial_in(struct uart_port *p, int offset)
return readl(p->membase + offset);
}

static void mem32be_serial_out(struct uart_port *p, int offset, int value)
{
offset = offset << p->regshift;
iowrite32be(value, p->membase + offset);
}

static unsigned int mem32be_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
return ioread32be(p->membase + offset);
}

static unsigned int io_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
Expand Down Expand Up @@ -488,6 +500,11 @@ static void set_io_from_upio(struct uart_port *p)
p->serial_out = mem32_serial_out;
break;

case UPIO_MEM32BE:
p->serial_in = mem32be_serial_in;
p->serial_out = mem32be_serial_out;
break;

#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
case UPIO_AU:
p->serial_in = au_serial_in;
Expand All @@ -513,6 +530,7 @@ serial_port_out_sync(struct uart_port *p, int offset, int value)
switch (p->iotype) {
case UPIO_MEM:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_AU:
p->serial_out(p, offset, value);
p->serial_in(p, UART_LCR); /* safe, no side-effects */
Expand Down Expand Up @@ -2748,6 +2766,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
case UPIO_AU:
case UPIO_TSI:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_MEM:
if (!port->mapbase)
break;
Expand Down Expand Up @@ -2784,6 +2803,7 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
case UPIO_AU:
case UPIO_TSI:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_MEM:
if (!port->mapbase)
break;
Expand Down
Loading

0 comments on commit d56a669

Please sign in to comment.