Merge tag 'devicetree-for-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/robh...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Apr 2015 15:46:18 +0000 (08:46 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Apr 2015 15:46:18 +0000 (08:46 -0700)
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

1  2 
Documentation/devicetree/bindings/vendor-prefixes.txt
drivers/of/Kconfig
drivers/of/base.c
drivers/of/unittest.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_early.c
drivers/tty/serial/of_serial.c
include/linux/of.h

@@@ -11,21 -11,19 +11,22 @@@ adapteva   Adapteva, Inc
  adh   AD Holdings Plc.
  adi   Analog Devices, Inc.
  aeroflexgaisler       Aeroflex Gaisler AB
 +al    Annapurna Labs
  allwinner     Allwinner Technology Co., Ltd.
  alphascale    AlphaScale Integrated Circuits Systems, Inc.
  altr  Altera Corp.
  amcc  Applied Micro Circuits Corporation (APM, formally AMCC)
  amd   Advanced Micro Devices (AMD), Inc.
  amlogic       Amlogic, Inc.
 +ampire        Ampire Co., Ltd.
  ams   AMS AG
  amstaos       AMS-Taos Inc.
  apm   Applied Micro Circuits Corporation (APM)
 +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
@@@ -40,7 -38,6 +41,7 @@@ capella       Capella Microsystems, In
  cavium        Cavium, Inc.
  cdns  Cadence Design Systems Inc.
  chipidea      Chipidea, Inc
 +chipone               ChipOne
  chipspark     ChipSPARK
  chrp  Common Hardware Reference Platform
  chunghwa      Chunghwa Picture Tubes Ltd.
@@@ -82,9 -79,7 +83,9 @@@ geniatech     Geniatech, Inc
  giantplus     Giantplus Technology Co., Ltd.
  globalscale   Globalscale Technologies, Inc.
  gmt   Global Mixed-mode Technology, Inc.
 +goodix        Shenzhen Huiding Technology Co., Ltd.
  google        Google, Inc.
 +grinn Grinn
  gumstix       Gumstix, Inc.
  gw    Gateworks Corporation
  hannstar      HannStar Display Corporation
@@@ -120,7 -115,6 +121,7 @@@ merrii     Merrii Technology Co., Ltd
  micrel        Micrel Inc.
  microchip     Microchip Technology Inc.
  micron        Micron Technology Inc.
 +minix MINIX Technology Ltd.
  mitsubishi    Mitsubishi Electric Corporation
  mosaixtech    Mosaix Technologies, Inc.
  moxa  Moxa
@@@ -132,7 -126,6 +133,7 @@@ mxicy      Macronix International Co., Ltd
  national      National Semiconductor
  neonode               Neonode Inc.
  netgear       NETGEAR
 +netlogic      Broadcom Corporation (formerly NetLogic Microsystems)
  newhaven      Newhaven Display International
  nintendo      Nintendo
  nokia Nokia
@@@ -140,7 -133,6 +141,7 @@@ nvidia     NVIDI
  nxp   NXP Semiconductors
  onnn  ON Semiconductor Corp.
  opencores     OpenCores.org
 +ortustech     Ortus Technology Co., Ltd.
  ovti  OmniVision Technologies
  panasonic     Panasonic Corporation
  parade        Parade Technologies Inc.
@@@ -176,7 -168,6 +177,7 @@@ sii        Seiko Instruments, Inc
  silergy       Silergy Corp.
  sirf  SiRF Technology, Inc.
  sitronix      Sitronix Technology Corporation
 +skyworks      Skyworks Solutions, Inc.
  smsc  Standard Microsystems Corporation
  snps  Synopsys, Inc.
  solidrun      SolidRun
@@@ -204,7 -195,6 +205,7 @@@ voipac     Voipac Technologies s.r.o
  winbond Winbond Electronics corp.
  wlf   Wolfson Microelectronics
  wm    Wondermedia Technologies, Inc.
 +x-powers      X-Powers
  xes   Extreme Engineering Solutions (X-ES)
  xillybus      Xillybus Ltd.
  xlnx  Xilinx
diff --combined drivers/of/Kconfig
@@@ -34,11 -34,7 +34,11 @@@ config OF_PROMTRE
  # Hardly any platforms need this.  It is safe to select, but only do so if you
  # need it.
  config OF_DYNAMIC
 -      bool
 +      bool "Support for dynamic device trees" if OF_UNITTEST
 +      help
 +        On some platforms, the device tree can be manipulated at runtime.
 +        While this option is selected automatically on such platforms, you
 +        can enable it manually to improve device tree unit test coverage.
  
  config OF_ADDRESS
        def_bool y
@@@ -50,7 -46,7 +50,7 @@@ config OF_ADDRESS_PC
  
  config OF_IRQ
        def_bool y
-       depends on !SPARC
+       depends on !SPARC && IRQ_DOMAIN
  
  config OF_NET
        depends on NETDEVICES
@@@ -91,10 -87,5 +91,10 @@@ config OF_OVERLA
        bool "Device Tree overlays"
        select OF_DYNAMIC
        select OF_RESOLVE
 +      help
 +        Overlays are a method to dynamically modify part of the kernel's
 +        device tree with dynamically loaded data.
 +        While this option is selected automatically when needed, you can
 +        enable it manually to improve device tree unit test coverage.
  
  endmenu # OF
diff --combined drivers/of/base.c
@@@ -567,6 -567,29 +567,29 @@@ bool of_device_is_available(const struc
  }
  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
@@@ -640,8 -663,9 +663,9 @@@ static struct device_node *__of_get_nex
   *    @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)
@@@ -1960,32 -1984,6 +1984,32 @@@ int of_alias_get_id(struct device_node 
  }
  EXPORT_SYMBOL_GPL(of_alias_get_id);
  
 +/**
 + * of_alias_get_highest_id - Get highest alias id for the given stem
 + * @stem:     Alias stem to be examined
 + *
 + * The function travels the lookup table to get the highest alias id for the
 + * given alias stem.  It returns the alias id if found.
 + */
 +int of_alias_get_highest_id(const char *stem)
 +{
 +      struct alias_prop *app;
 +      int id = -ENODEV;
 +
 +      mutex_lock(&of_mutex);
 +      list_for_each_entry(app, &aliases_lookup, link) {
 +              if (strcmp(app->stem, stem) != 0)
 +                      continue;
 +
 +              if (app->id > id)
 +                      id = app->id;
 +      }
 +      mutex_unlock(&of_mutex);
 +
 +      return id;
 +}
 +EXPORT_SYMBOL_GPL(of_alias_get_highest_id);
 +
  const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
                               u32 *pu)
  {
diff --combined drivers/of/unittest.c
@@@ -23,6 -23,8 +23,8 @@@
  #include <linux/i2c.h>
  #include <linux/i2c-mux.h>
  
+ #include <linux/bitops.h>
  #include "of_private.h"
  
  static struct unittest_results {
@@@ -228,9 -230,8 +230,9 @@@ static void __init of_unittest_check_tr
        child_count = of_unittest_check_node_linkage(of_root);
  
        unittest(child_count > 0, "Device node data structure is corrupted\n");
 -      unittest(child_count == allnode_count, "allnodes list size (%i) doesn't match"
 -               "sibling lists size (%i)\n", allnode_count, child_count);
 +      unittest(child_count == allnode_count,
 +               "allnodes list size (%i) doesn't match sibling lists size (%i)\n",
 +               allnode_count, child_count);
        pr_debug("allnodes list size (%i); sibling lists size (%i)\n", allnode_count, child_count);
  }
  
@@@ -295,7 -296,6 +297,7 @@@ static void __init of_unittest_parse_ph
  
        for (i = 0; i < 8; i++) {
                bool passed = true;
 +
                rc = of_parse_phandle_with_args(np, "phandle-list",
                                                "#phandle-cells", i, &args);
  
@@@ -555,7 -555,6 +557,7 @@@ static void __init of_unittest_parse_in
  
        for (i = 0; i < 4; i++) {
                bool passed = true;
 +
                args.args_count = 0;
                rc = of_irq_parse_one(np, i, &args);
  
  
        for (i = 0; i < 4; i++) {
                bool passed = true;
 +
                args.args_count = 0;
                rc = of_irq_parse_one(np, i, &args);
  
@@@ -629,7 -627,6 +631,7 @@@ static void __init of_unittest_parse_in
  
        for (i = 0; i < 7; i++) {
                bool passed = true;
 +
                rc = of_irq_parse_one(np, i, &args);
  
                /* Test the values from tests-phandle.dtsi */
        of_node_put(np);
  }
  
 -static struct of_device_id match_node_table[] = {
 +static const struct of_device_id match_node_table[] = {
        { .data = "A", .name = "name0", }, /* Name alone is lowest priority */
        { .data = "B", .type = "type1", }, /* followed by type alone */
  
@@@ -751,15 -748,15 +753,15 @@@ static void __init of_unittest_match_no
        }
  }
  
 -struct device test_bus = {
 -      .init_name = "unittest-bus",
 +static const struct platform_device_info test_bus_info = {
 +      .name = "unittest-bus",
  };
  static void __init of_unittest_platform_populate(void)
  {
        int irq, rc;
        struct device_node *np, *child, *grandchild;
 -      struct platform_device *pdev;
 -      struct of_device_id match[] = {
 +      struct platform_device *pdev, *test_bus;
 +      const struct of_device_id match[] = {
                { .compatible = "test-device", },
                {}
        };
        irq = platform_get_irq(pdev, 0);
        unittest(irq < 0 && irq != -EPROBE_DEFER, "device parsing error failed - %d\n", irq);
  
 -      if (unittest(np = of_find_node_by_path("/testcase-data/platform-tests"),
 -                   "No testcase data in device tree\n"));
 +      np = of_find_node_by_path("/testcase-data/platform-tests");
 +      unittest(np, "No testcase data in device tree\n");
 +      if (!np)
                return;
  
 -      if (unittest(!(rc = device_register(&test_bus)),
 -                   "testbus registration failed; rc=%i\n", rc));
 +      test_bus = platform_device_register_full(&test_bus_info);
 +      rc = PTR_ERR_OR_ZERO(test_bus);
 +      unittest(!rc, "testbus registration failed; rc=%i\n", rc);
 +      if (rc)
                return;
 +      test_bus->dev.of_node = np;
  
 +      of_platform_populate(np, match, NULL, &test_bus->dev);
        for_each_child_of_node(np, child) {
 -              of_platform_populate(child, match, NULL, &test_bus);
                for_each_child_of_node(child, grandchild)
                        unittest(of_find_device_by_node(grandchild),
                                 "Could not create device for node '%s'\n",
                                 grandchild->name);
        }
  
 -      of_platform_depopulate(&test_bus);
 +      of_platform_depopulate(&test_bus->dev);
        for_each_child_of_node(np, child) {
                for_each_child_of_node(child, grandchild)
                        unittest(!of_find_device_by_node(grandchild),
                                 grandchild->name);
        }
  
 -      device_unregister(&test_bus);
 +      platform_device_unregister(test_bus);
        of_node_put(np);
  }
  
@@@ -882,10 -875,6 +884,10 @@@ static int __init unittest_data_add(voi
  {
        void *unittest_data;
        struct device_node *unittest_data_node, *np;
 +      /*
 +       * __dtb_testcases_begin[] and __dtb_testcases_end[] are magically
 +       * created by cmd_dt_S_dtb in scripts/Makefile.lib
 +       */
        extern uint8_t __dtb_testcases_begin[];
        extern uint8_t __dtb_testcases_end[];
        const int size = __dtb_testcases_end - __dtb_testcases_begin;
        np = unittest_data_node->child;
        while (np) {
                struct device_node *next = np->sibling;
 +
                np->parent = of_root;
                attach_node_and_children(np);
                np = next;
@@@ -967,7 -955,7 +969,7 @@@ static int unittest_remove(struct platf
        return 0;
  }
  
 -static struct of_device_id unittest_match[] = {
 +static const struct of_device_id unittest_match[] = {
        { .compatible = "unittest", },
        {},
  };
@@@ -1109,6 -1097,59 +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)
  {
                goto out;
        }
        id = ret;
+       of_unittest_track_overlay(id);
  
        ret = 0;
  
@@@ -1343,6 -1385,7 +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++) {
                                                PDEV_OVERLAY));
                        return;
                }
+               of_unittest_untrack_overlay(ov_id[i]);
        }
  
        for (i = 0; i < 2; i++) {
@@@ -1411,6 -1455,7 +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) */
                                                PDEV_OVERLAY));
                        return;
                }
+               of_unittest_untrack_overlay(ov_id[i]);
        }
  
        unittest(1, "overlay test %d passed\n", 8);
@@@ -1559,7 -1605,7 +1619,7 @@@ static int unittest_i2c_bus_remove(stru
        return 0;
  }
  
 -static struct of_device_id unittest_i2c_bus_match[] = {
 +static const struct of_device_id unittest_i2c_bus_match[] = {
        { .compatible = "unittest-i2c-bus", },
        {},
  };
@@@ -1855,6 -1901,8 +1915,8 @@@ static void __init of_unittest_overlay(
        of_unittest_overlay_i2c_cleanup();
  #endif
  
+       of_unittest_destroy_tracked_overlays();
  out:
        of_node_put(bus_np);
  }
@@@ -31,6 -31,7 +31,6 @@@
  #include <linux/tty.h>
  #include <linux/ratelimit.h>
  #include <linux/tty_flip.h>
 -#include <linux/serial_core.h>
  #include <linux/serial.h>
  #include <linux/serial_8250.h>
  #include <linux/nmi.h>
@@@ -60,7 -61,7 +60,7 @@@ static struct uart_driver serial8250_re
  
  static int serial_index(struct uart_port *port)
  {
 -      return (serial8250_reg.minor - 64) + port->line;
 +      return port->minor - 64;
  }
  
  static unsigned int skip_txen_test; /* force skip of txen test at init time */
@@@ -357,46 -358,34 +357,46 @@@ static void default_serial_dl_write(str
  #if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
  
  /* Au1x00/RT288x UART hardware has a weird register layout */
 -static const u8 au_io_in_map[] = {
 -      [UART_RX]  = 0,
 -      [UART_IER] = 2,
 -      [UART_IIR] = 3,
 -      [UART_LCR] = 5,
 -      [UART_MCR] = 6,
 -      [UART_LSR] = 7,
 -      [UART_MSR] = 8,
 +static const s8 au_io_in_map[8] = {
 +       0,     /* UART_RX  */
 +       2,     /* UART_IER */
 +       3,     /* UART_IIR */
 +       5,     /* UART_LCR */
 +       6,     /* UART_MCR */
 +       7,     /* UART_LSR */
 +       8,     /* UART_MSR */
 +      -1,     /* UART_SCR (unmapped) */
  };
  
 -static const u8 au_io_out_map[] = {
 -      [UART_TX]  = 1,
 -      [UART_IER] = 2,
 -      [UART_FCR] = 4,
 -      [UART_LCR] = 5,
 -      [UART_MCR] = 6,
 +static const s8 au_io_out_map[8] = {
 +       1,     /* UART_TX  */
 +       2,     /* UART_IER */
 +       4,     /* UART_FCR */
 +       5,     /* UART_LCR */
 +       6,     /* UART_MCR */
 +      -1,     /* UART_LSR (unmapped) */
 +      -1,     /* UART_MSR (unmapped) */
 +      -1,     /* UART_SCR (unmapped) */
  };
  
  static unsigned int au_serial_in(struct uart_port *p, int offset)
  {
 -      offset = au_io_in_map[offset] << p->regshift;
 -      return __raw_readl(p->membase + offset);
 +      if (offset >= ARRAY_SIZE(au_io_in_map))
 +              return UINT_MAX;
 +      offset = au_io_in_map[offset];
 +      if (offset < 0)
 +              return UINT_MAX;
 +      return __raw_readl(p->membase + (offset << p->regshift));
  }
  
  static void au_serial_out(struct uart_port *p, int offset, int value)
  {
 -      offset = au_io_out_map[offset] << p->regshift;
 -      __raw_writel(value, p->membase + offset);
 +      if (offset >= ARRAY_SIZE(au_io_out_map))
 +              return;
 +      offset = au_io_out_map[offset];
 +      if (offset < 0)
 +              return;
 +      __raw_writel(value, p->membase + (offset << p->regshift));
  }
  
  /* Au1x00 haven't got a standard divisor latch */
@@@ -450,6 -439,18 +450,18 @@@ static unsigned int mem32_serial_in(str
        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;
@@@ -488,6 -489,11 +500,11 @@@ static void set_io_from_upio(struct uar
                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;
@@@ -513,6 -519,7 +530,7 @@@ serial_port_out_sync(struct uart_port *
        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 */
@@@ -906,7 -913,7 +924,7 @@@ static int broken_efr(struct uart_8250_
        /*
         * Exar ST16C2550 "A2" devices incorrectly detect as
         * having an EFR, and report an ID of 0x0201.  See
 -       * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html 
 +       * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
         */
        if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
                return 1;
        return 0;
  }
  
 -static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
 -{
 -      unsigned char status;
 -
 -      status = serial_in(up, 0x04); /* EXCR2 */
 -#define PRESL(x) ((x) & 0x30)
 -      if (PRESL(status) == 0x10) {
 -              /* already in high speed mode */
 -              return 0;
 -      } else {
 -              status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
 -              status |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
 -              serial_out(up, 0x04, status);
 -      }
 -      return 1;
 -}
 -
  /*
   * We know that the chip has FIFOs.  Does it have an EFR?  The
   * EFR is located in the same register position as the IIR and
@@@ -1116,7 -1140,7 +1134,7 @@@ static void autoconfig_16550a(struct ua
   * whether or not this UART is a 16550A or not, since this will
   * determine whether or not we can use its FIFO features or not.
   */
 -static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
 +static void autoconfig(struct uart_8250_port *up)
  {
        unsigned char status1, scratch, scratch2, scratch3;
        unsigned char save_lcr, save_mcr;
        /*
         * Only probe for RSA ports if we got the region.
         */
 -      if (port->type == PORT_16550A && probeflags & PROBE_RSA) {
 -              int i;
 -
 -              for (i = 0 ; i < probe_rsa_count; ++i) {
 -                      if (probe_rsa[i] == port->iobase && __enable_rsa(up)) {
 -                              port->type = PORT_RSA;
 -                              break;
 -                      }
 -              }
 -      }
 +      if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA &&
 +          __enable_rsa(up))
 +              port->type = PORT_RSA;
  #endif
  
        serial_out(up, UART_LCR, save_lcr);
  
        port->fifosize = uart_config[up->port.type].fifo_size;
 -      old_capabilities = up->capabilities; 
 +      old_capabilities = up->capabilities;
        up->capabilities = uart_config[port->type].flags;
        up->tx_loadsz = uart_config[port->type].tx_loadsz;
  
@@@ -1894,48 -1925,6 +1912,48 @@@ static void serial8250_backup_timeout(u
                jiffies + uart_poll_timeout(&up->port) + HZ / 5);
  }
  
 +static int univ8250_setup_irq(struct uart_8250_port *up)
 +{
 +      struct uart_port *port = &up->port;
 +      int retval = 0;
 +
 +      /*
 +       * The above check will only give an accurate result the first time
 +       * the port is opened so this value needs to be preserved.
 +       */
 +      if (up->bugs & UART_BUG_THRE) {
 +              pr_debug("ttyS%d - using backup timer\n", serial_index(port));
 +
 +              up->timer.function = serial8250_backup_timeout;
 +              up->timer.data = (unsigned long)up;
 +              mod_timer(&up->timer, jiffies +
 +                        uart_poll_timeout(port) + HZ / 5);
 +      }
 +
 +      /*
 +       * If the "interrupt" for this port doesn't correspond with any
 +       * hardware interrupt, we use a timer-based system.  The original
 +       * driver used to do this with IRQ0.
 +       */
 +      if (!port->irq) {
 +              up->timer.data = (unsigned long)up;
 +              mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
 +      } else
 +              retval = serial_link_irq_chain(up);
 +
 +      return retval;
 +}
 +
 +static void univ8250_release_irq(struct uart_8250_port *up)
 +{
 +      struct uart_port *port = &up->port;
 +
 +      del_timer_sync(&up->timer);
 +      up->timer.function = serial8250_timeout;
 +      if (port->irq)
 +              serial_unlink_irq_chain(up);
 +}
 +
  static unsigned int serial8250_tx_empty(struct uart_port *port)
  {
        struct uart_8250_port *up = up_to_u8250p(port);
@@@ -2240,12 -2229,35 +2258,12 @@@ int serial8250_do_startup(struct uart_p
                if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
                    up->port.flags & UPF_BUG_THRE) {
                        up->bugs |= UART_BUG_THRE;
 -                      pr_debug("ttyS%d - using backup timer\n",
 -                               serial_index(port));
                }
        }
  
 -      /*
 -       * The above check will only give an accurate result the first time
 -       * the port is opened so this value needs to be preserved.
 -       */
 -      if (up->bugs & UART_BUG_THRE) {
 -              up->timer.function = serial8250_backup_timeout;
 -              up->timer.data = (unsigned long)up;
 -              mod_timer(&up->timer, jiffies +
 -                      uart_poll_timeout(port) + HZ / 5);
 -      }
 -
 -      /*
 -       * If the "interrupt" for this port doesn't correspond with any
 -       * hardware interrupt, we use a timer-based system.  The original
 -       * driver used to do this with IRQ0.
 -       */
 -      if (!port->irq) {
 -              up->timer.data = (unsigned long)up;
 -              mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
 -      } else {
 -              retval = serial_link_irq_chain(up);
 -              if (retval)
 -                      goto out;
 -      }
 +      retval = up->ops->setup_irq(up);
 +      if (retval)
 +              goto out;
  
        /*
         * Now, initialize the UART
           is variable. So, let's just don't test if we receive
           TX irq. This way, we'll never enable UART_BUG_TXEN.
         */
 -      if (skip_txen_test || up->port.flags & UPF_NO_TXEN_TEST)
 +      if (up->port.flags & UPF_NO_TXEN_TEST)
                goto dont_test_tx_en;
  
        /*
@@@ -2403,7 -2415,10 +2421,7 @@@ void serial8250_do_shutdown(struct uart
        serial_port_in(port, UART_RX);
        serial8250_rpm_put(up);
  
 -      del_timer_sync(&up->timer);
 -      up->timer.function = serial8250_timeout;
 -      if (port->irq)
 -              serial_unlink_irq_chain(up);
 +      up->ops->release_irq(up);
  }
  EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
  
@@@ -2722,8 -2737,6 +2740,8 @@@ serial8250_pm(struct uart_port *port, u
  
  static unsigned int serial8250_port_size(struct uart_8250_port *pt)
  {
 +      if (pt->port.mapsize)
 +              return pt->port.mapsize;
        if (pt->port.iotype == UPIO_AU) {
                if (pt->port.type == PORT_RT2880)
                        return 0x100;
@@@ -2748,6 -2761,7 +2766,7 @@@ static int serial8250_request_std_resou
        case UPIO_AU:
        case UPIO_TSI:
        case UPIO_MEM32:
+       case UPIO_MEM32BE:
        case UPIO_MEM:
                if (!port->mapbase)
                        break;
@@@ -2784,6 -2798,7 +2803,7 @@@ static void serial8250_release_std_reso
        case UPIO_AU:
        case UPIO_TSI:
        case UPIO_MEM32:
+       case UPIO_MEM32BE:
        case UPIO_MEM:
                if (!port->mapbase)
                        break;
        }
  }
  
 +#ifdef CONFIG_SERIAL_8250_RSA
  static int serial8250_request_rsa_resource(struct uart_8250_port *up)
  {
        unsigned long start = UART_RSA_BASE << up->port.regshift;
@@@ -2838,13 -2852,14 +2858,13 @@@ static void serial8250_release_rsa_reso
                break;
        }
  }
 +#endif
  
  static void serial8250_release_port(struct uart_port *port)
  {
        struct uart_8250_port *up = up_to_u8250p(port);
  
        serial8250_release_std_resource(up);
 -      if (port->type == PORT_RSA)
 -              serial8250_release_rsa_resource(up);
  }
  
  static int serial8250_request_port(struct uart_port *port)
                return -ENODEV;
  
        ret = serial8250_request_std_resource(up);
 -      if (ret == 0 && port->type == PORT_RSA) {
 -              ret = serial8250_request_rsa_resource(up);
 -              if (ret < 0)
 -                      serial8250_release_std_resource(up);
 -      }
  
        return ret;
  }
@@@ -3003,6 -3023,7 +3023,6 @@@ static void register_dev_spec_attr_grp(
  static void serial8250_config_port(struct uart_port *port, int flags)
  {
        struct uart_8250_port *up = up_to_u8250p(port);
 -      int probeflags = PROBE_ANY;
        int ret;
  
        if (port->type == PORT_8250_CIR)
        if (ret < 0)
                return;
  
 -      ret = serial8250_request_rsa_resource(up);
 -      if (ret < 0)
 -              probeflags &= ~PROBE_RSA;
 -
        if (port->iotype != up->cur_iotype)
                set_io_from_upio(port);
  
        if (flags & UART_CONFIG_TYPE)
 -              autoconfig(up, probeflags);
 +              autoconfig(up);
  
        /* if access method is AU, it is a 16550 with a quirk */
        if (port->type == PORT_16550A && port->iotype == UPIO_AU)
        if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
                autoconfig_irq(up);
  
 -      if (port->type != PORT_RSA && probeflags & PROBE_RSA)
 -              serial8250_release_rsa_resource(up);
        if (port->type == PORT_UNKNOWN)
                serial8250_release_std_resource(up);
  
@@@ -3066,7 -3093,7 +3086,7 @@@ serial8250_type(struct uart_port *port
        return uart_config[type].name;
  }
  
 -static struct uart_ops serial8250_pops = {
 +static const struct uart_ops serial8250_pops = {
        .tx_empty       = serial8250_tx_empty,
        .set_mctrl      = serial8250_set_mctrl,
        .get_mctrl      = serial8250_get_mctrl,
  #endif
  };
  
 +static const struct uart_ops *base_ops;
 +static struct uart_ops univ8250_port_ops;
 +
 +static const struct uart_8250_ops univ8250_driver_ops = {
 +      .setup_irq      = univ8250_setup_irq,
 +      .release_irq    = univ8250_release_irq,
 +};
 +
  static struct uart_8250_port serial8250_ports[UART_NR];
  
  /**
@@@ -3131,105 -3150,6 +3151,105 @@@ void serial8250_set_isa_configurator
  }
  EXPORT_SYMBOL(serial8250_set_isa_configurator);
  
 +static void serial8250_init_port(struct uart_8250_port *up)
 +{
 +      struct uart_port *port = &up->port;
 +
 +      spin_lock_init(&port->lock);
 +      port->ops = &serial8250_pops;
 +
 +      up->cur_iotype = 0xFF;
 +}
 +
 +static void serial8250_set_defaults(struct uart_8250_port *up)
 +{
 +      struct uart_port *port = &up->port;
 +
 +      if (up->port.flags & UPF_FIXED_TYPE) {
 +              unsigned int type = up->port.type;
 +
 +              if (!up->port.fifosize)
 +                      up->port.fifosize = uart_config[type].fifo_size;
 +              if (!up->tx_loadsz)
 +                      up->tx_loadsz = uart_config[type].tx_loadsz;
 +              if (!up->capabilities)
 +                      up->capabilities = uart_config[type].flags;
 +      }
 +
 +      set_io_from_upio(port);
 +
 +      /* default dma handlers */
 +      if (up->dma) {
 +              if (!up->dma->tx_dma)
 +                      up->dma->tx_dma = serial8250_tx_dma;
 +              if (!up->dma->rx_dma)
 +                      up->dma->rx_dma = serial8250_rx_dma;
 +      }
 +}
 +
 +#ifdef CONFIG_SERIAL_8250_RSA
 +
 +static void univ8250_config_port(struct uart_port *port, int flags)
 +{
 +      struct uart_8250_port *up = up_to_u8250p(port);
 +
 +      up->probe &= ~UART_PROBE_RSA;
 +      if (port->type == PORT_RSA) {
 +              if (serial8250_request_rsa_resource(up) == 0)
 +                      up->probe |= UART_PROBE_RSA;
 +      } else if (flags & UART_CONFIG_TYPE) {
 +              int i;
 +
 +              for (i = 0; i < probe_rsa_count; i++) {
 +                      if (probe_rsa[i] == up->port.iobase) {
 +                              if (serial8250_request_rsa_resource(up) == 0)
 +                                      up->probe |= UART_PROBE_RSA;
 +                              break;
 +                      }
 +              }
 +      }
 +
 +      base_ops->config_port(port, flags);
 +
 +      if (port->type != PORT_RSA && up->probe & UART_PROBE_RSA)
 +              serial8250_release_rsa_resource(up);
 +}
 +
 +static int univ8250_request_port(struct uart_port *port)
 +{
 +      struct uart_8250_port *up = up_to_u8250p(port);
 +      int ret;
 +
 +      ret = base_ops->request_port(port);
 +      if (ret == 0 && port->type == PORT_RSA) {
 +              ret = serial8250_request_rsa_resource(up);
 +              if (ret < 0)
 +                      base_ops->release_port(port);
 +      }
 +
 +      return ret;
 +}
 +
 +static void univ8250_release_port(struct uart_port *port)
 +{
 +      struct uart_8250_port *up = up_to_u8250p(port);
 +
 +      if (port->type == PORT_RSA)
 +              serial8250_release_rsa_resource(up);
 +      base_ops->release_port(port);
 +}
 +
 +static void univ8250_rsa_support(struct uart_ops *ops)
 +{
 +      ops->config_port  = univ8250_config_port;
 +      ops->request_port = univ8250_request_port;
 +      ops->release_port = univ8250_release_port;
 +}
 +
 +#else
 +#define univ8250_rsa_support(x)               do { } while (0)
 +#endif /* CONFIG_SERIAL_8250_RSA */
 +
  static void __init serial8250_isa_init_ports(void)
  {
        struct uart_8250_port *up;
                struct uart_port *port = &up->port;
  
                port->line = i;
 -              spin_lock_init(&port->lock);
 +              serial8250_init_port(up);
 +              if (!base_ops)
 +                      base_ops = port->ops;
 +              port->ops = &univ8250_port_ops;
  
                init_timer(&up->timer);
                up->timer.function = serial8250_timeout;
 -              up->cur_iotype = 0xFF;
 +
 +              up->ops = &univ8250_driver_ops;
  
                /*
                 * ALPHA_KLUDGE_MCR needs to be killed.
                 */
                up->mcr_mask = ~ALPHA_KLUDGE_MCR;
                up->mcr_force = ALPHA_KLUDGE_MCR;
 -
 -              port->ops = &serial8250_pops;
        }
  
 +      /* chain base port ops to support Remote Supervisor Adapter */
 +      univ8250_port_ops = *base_ops;
 +      univ8250_rsa_support(&univ8250_port_ops);
 +
        if (share_irqs)
                irqflag = IRQF_SHARED;
  
                port->membase  = old_serial_port[i].iomem_base;
                port->iotype   = old_serial_port[i].io_type;
                port->regshift = old_serial_port[i].iomem_reg_shift;
 -              set_io_from_upio(port);
 +              serial8250_set_defaults(up);
 +
                port->irqflags |= irqflag;
                if (serial8250_isa_config != NULL)
                        serial8250_isa_config(i, &up->port, &up->capabilities);
 -
        }
  }
  
 -static void
 -serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
 -{
 -      up->port.type = type;
 -      if (!up->port.fifosize)
 -              up->port.fifosize = uart_config[type].fifo_size;
 -      if (!up->tx_loadsz)
 -              up->tx_loadsz = uart_config[type].tx_loadsz;
 -      if (!up->capabilities)
 -              up->capabilities = uart_config[type].flags;
 -}
 -
  static void __init
  serial8250_register_ports(struct uart_driver *drv, struct device *dev)
  {
  
                up->port.dev = dev;
  
 -              if (up->port.flags & UPF_FIXED_TYPE)
 -                      serial8250_init_fixed_type_port(up, up->port.type);
 +              if (skip_txen_test)
 +                      up->port.flags |= UPF_NO_TXEN_TEST;
  
                uart_add_one_port(drv, &up->port);
        }
@@@ -3330,9 -3256,10 +3350,9 @@@ static void serial8250_console_putchar(
   *
   *    The console_lock must be held when we get here.
   */
 -static void
 -serial8250_console_write(struct console *co, const char *s, unsigned int count)
 +static void serial8250_console_write(struct uart_8250_port *up, const char *s,
 +                                   unsigned int count)
  {
 -      struct uart_8250_port *up = &serial8250_ports[co->index];
        struct uart_port *port = &up->port;
        unsigned long flags;
        unsigned int ier;
        serial8250_rpm_put(up);
  }
  
 -static int serial8250_console_setup(struct console *co, char *options)
 +static void univ8250_console_write(struct console *co, const char *s,
 +                                 unsigned int count)
 +{
 +      struct uart_8250_port *up = &serial8250_ports[co->index];
 +
 +      serial8250_console_write(up, s, count);
 +}
 +
 +static unsigned int probe_baud(struct uart_port *port)
 +{
 +      unsigned char lcr, dll, dlm;
 +      unsigned int quot;
 +
 +      lcr = serial_port_in(port, UART_LCR);
 +      serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB);
 +      dll = serial_port_in(port, UART_DLL);
 +      dlm = serial_port_in(port, UART_DLM);
 +      serial_port_out(port, UART_LCR, lcr);
 +
 +      quot = (dlm << 8) | dll;
 +      return (port->uartclk / 16) / quot;
 +}
 +
 +static int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
  {
 -      struct uart_port *port;
        int baud = 9600;
        int bits = 8;
        int parity = 'n';
        int flow = 'n';
  
 +      if (!port->iobase && !port->membase)
 +              return -ENODEV;
 +
 +      if (options)
 +              uart_parse_options(options, &baud, &parity, &bits, &flow);
 +      else if (probe)
 +              baud = probe_baud(port);
 +
 +      return uart_set_options(port, port->cons, baud, parity, bits, flow);
 +}
 +
 +static int univ8250_console_setup(struct console *co, char *options)
 +{
 +      struct uart_port *port;
 +
        /*
         * Check whether an invalid uart number has been specified, and
         * if so, search for the first available port that does have
        if (co->index >= nr_uarts)
                co->index = 0;
        port = &serial8250_ports[co->index].port;
 -      if (!port->iobase && !port->membase)
 -              return -ENODEV;
 +      /* link port to console */
 +      port->cons = co;
  
 -      if (options)
 -              uart_parse_options(options, &baud, &parity, &bits, &flow);
 -
 -      return uart_set_options(port, co, baud, parity, bits, flow);
 +      return serial8250_console_setup(port, options, false);
  }
  
 -static int serial8250_console_early_setup(void)
 +/**
 + *    univ8250_console_match - non-standard console matching
 + *    @co:      registering console
 + *    @name:    name from console command line
 + *    @idx:     index from console command line
 + *    @options: ptr to option string from console command line
 + *
 + *    Only attempts to match console command lines of the form:
 + *        console=uart[8250],io|mmio|mmio32,<addr>[,<options>]
 + *        console=uart[8250],0x<addr>[,<options>]
 + *    This form is used to register an initial earlycon boot console and
 + *    replace it with the serial8250_console at 8250 driver init.
 + *
 + *    Performs console setup for a match (as required by interface)
 + *    If no <options> are specified, then assume the h/w is already setup.
 + *
 + *    Returns 0 if console matches; otherwise non-zero to use default matching
 + */
 +static int univ8250_console_match(struct console *co, char *name, int idx,
 +                                char *options)
  {
 -      return serial8250_find_port_for_earlycon();
 +      char match[] = "uart";  /* 8250-specific earlycon name */
 +      unsigned char iotype;
 +      unsigned long addr;
 +      int i;
 +
 +      if (strncmp(name, match, 4) != 0)
 +              return -ENODEV;
 +
 +      if (uart_parse_earlycon(options, &iotype, &addr, &options))
 +              return -ENODEV;
 +
 +      /* try to match the port specified on the command line */
 +      for (i = 0; i < nr_uarts; i++) {
 +              struct uart_port *port = &serial8250_ports[i].port;
 +
 +              if (port->iotype != iotype)
 +                      continue;
 +              if ((iotype == UPIO_MEM || iotype == UPIO_MEM32) &&
 +                  (port->mapbase != addr))
 +                      continue;
 +              if (iotype == UPIO_PORT && port->iobase != addr)
 +                      continue;
 +
 +              co->index = i;
 +              port->cons = co;
 +              return serial8250_console_setup(port, options, true);
 +      }
 +
 +      return -ENODEV;
  }
  
 -static struct console serial8250_console = {
 +static struct console univ8250_console = {
        .name           = "ttyS",
 -      .write          = serial8250_console_write,
 +      .write          = univ8250_console_write,
        .device         = uart_console_device,
 -      .setup          = serial8250_console_setup,
 -      .early_setup    = serial8250_console_early_setup,
 +      .setup          = univ8250_console_setup,
 +      .match          = univ8250_console_match,
        .flags          = CON_PRINTBUFFER | CON_ANYTIME,
        .index          = -1,
        .data           = &serial8250_reg,
  };
  
 -static int __init serial8250_console_init(void)
 +static int __init univ8250_console_init(void)
  {
        serial8250_isa_init_ports();
 -      register_console(&serial8250_console);
 +      register_console(&univ8250_console);
        return 0;
  }
 -console_initcall(serial8250_console_init);
 -
 -int serial8250_find_port(struct uart_port *p)
 -{
 -      int line;
 -      struct uart_port *port;
 -
 -      for (line = 0; line < nr_uarts; line++) {
 -              port = &serial8250_ports[line].port;
 -              if (uart_match_port(p, port))
 -                      return line;
 -      }
 -      return -ENODEV;
 -}
 +console_initcall(univ8250_console_init);
  
 -#define SERIAL8250_CONSOLE    &serial8250_console
 +#define SERIAL8250_CONSOLE    &univ8250_console
  #else
  #define SERIAL8250_CONSOLE    NULL
  #endif
@@@ -3573,19 -3432,19 +3593,19 @@@ int __init early_serial_setup(struct ua
        p->iotype       = port->iotype;
        p->flags        = port->flags;
        p->mapbase      = port->mapbase;
 +      p->mapsize      = port->mapsize;
        p->private_data = port->private_data;
        p->type         = port->type;
        p->line         = port->line;
  
 -      set_io_from_upio(p);
 +      serial8250_set_defaults(up_to_u8250p(p));
 +
        if (port->serial_in)
                p->serial_in = port->serial_in;
        if (port->serial_out)
                p->serial_out = port->serial_out;
        if (port->handle_irq)
                p->handle_irq = port->handle_irq;
 -      else
 -              p->handle_irq = serial8250_default_handle_irq;
  
        return 0;
  }
@@@ -3605,8 -3464,7 +3625,8 @@@ void serial8250_suspend_port(int line
            port->type != PORT_8250) {
                unsigned char canary = 0xa5;
                serial_out(up, UART_SCR, canary);
 -              up->canary = canary;
 +              if (serial_in(up, UART_SCR) == canary)
 +                      up->canary = canary;
        }
  
        uart_suspend_port(&serial8250_reg, port);
@@@ -3828,7 -3686,6 +3848,7 @@@ int serial8250_register_8250_port(struc
                uart->port.flags        = up->port.flags | UPF_BOOT_AUTOCONF;
                uart->bugs              = up->bugs;
                uart->port.mapbase      = up->port.mapbase;
 +              uart->port.mapsize      = up->port.mapsize;
                uart->port.private_data = up->port.private_data;
                uart->port.fifosize     = up->port.fifosize;
                uart->tx_loadsz         = up->tx_loadsz;
                uart->port.unthrottle   = up->port.unthrottle;
                uart->port.rs485_config = up->port.rs485_config;
                uart->port.rs485        = up->port.rs485;
 +              uart->dma               = up->dma;
  
                /* Take tx_loadsz from fifosize if it wasn't set separately */
                if (uart->port.fifosize && !uart->tx_loadsz)
                if (up->port.dev)
                        uart->port.dev = up->port.dev;
  
 +              if (skip_txen_test)
 +                      uart->port.flags |= UPF_NO_TXEN_TEST;
 +
                if (up->port.flags & UPF_FIXED_TYPE)
 -                      serial8250_init_fixed_type_port(uart, up->port.type);
 +                      uart->port.type = up->port.type;
 +
 +              serial8250_set_defaults(uart);
  
 -              set_io_from_upio(&uart->port);
                /* Possibly override default I/O functions.  */
                if (up->port.serial_in)
                        uart->port.serial_in = up->port.serial_in;
                        uart->dl_read = up->dl_read;
                if (up->dl_write)
                        uart->dl_write = up->dl_write;
 -              if (up->dma) {
 -                      uart->dma = up->dma;
 -                      if (!uart->dma->tx_dma)
 -                              uart->dma->tx_dma = serial8250_tx_dma;
 -                      if (!uart->dma->rx_dma)
 -                              uart->dma->rx_dma = serial8250_rx_dma;
 -              }
  
                if (serial8250_isa_config != NULL)
                        serial8250_isa_config(0, &uart->port,
@@@ -3908,11 -3767,9 +3928,11 @@@ void serial8250_unregister_port(int lin
        uart_remove_one_port(&serial8250_reg, &uart->port);
        if (serial8250_isa_devs) {
                uart->port.flags &= ~UPF_BOOT_AUTOCONF;
 +              if (skip_txen_test)
 +                      uart->port.flags |= UPF_NO_TXEN_TEST;
                uart->port.type = PORT_UNKNOWN;
                uart->port.dev = &serial8250_isa_devs->dev;
 -              uart->capabilities = uart_config[uart->port.type].flags;
 +              uart->capabilities = 0;
                uart_add_one_port(&serial8250_reg, &uart->port);
        } else {
                uart->port.dev = NULL;
  #include <linux/tty.h>
  #include <linux/init.h>
  #include <linux/console.h>
 -#include <linux/serial_core.h>
  #include <linux/serial_reg.h>
  #include <linux/serial.h>
  #include <linux/serial_8250.h>
  #include <asm/io.h>
  #include <asm/serial.h>
  
 -static struct earlycon_device *early_device;
 -
  unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset)
  {
        switch (port->iotype) {
@@@ -42,6 -45,8 +42,8 @@@
                return readb(port->membase + offset);
        case UPIO_MEM32:
                return readl(port->membase + (offset << 2));
+       case UPIO_MEM32BE:
+               return ioread32be(port->membase + (offset << 2));
        case UPIO_PORT:
                return inb(port->iobase + offset);
        default:
@@@ -58,6 -63,9 +60,9 @@@ void __weak __init serial8250_early_out
        case UPIO_MEM32:
                writel(value, port->membase + (offset << 2));
                break;
+       case UPIO_MEM32BE:
+               iowrite32be(value, port->membase + (offset << 2));
+               break;
        case UPIO_PORT:
                outb(value, port->iobase + offset);
                break;
@@@ -87,8 -95,7 +92,8 @@@ static void __init serial_putc(struct u
  static void __init early_serial8250_write(struct console *console,
                                        const char *s, unsigned int count)
  {
 -      struct uart_port *port = &early_device->port;
 +      struct earlycon_device *device = console->data;
 +      struct uart_port *port = &device->port;
        unsigned int ier;
  
        /* Save the IER and disable interrupts preserving the UUE bit */
                serial8250_early_out(port, UART_IER, ier);
  }
  
 -static unsigned int __init probe_baud(struct uart_port *port)
 -{
 -      unsigned char lcr, dll, dlm;
 -      unsigned int quot;
 -
 -      lcr = serial8250_early_in(port, UART_LCR);
 -      serial8250_early_out(port, UART_LCR, lcr | UART_LCR_DLAB);
 -      dll = serial8250_early_in(port, UART_DLL);
 -      dlm = serial8250_early_in(port, UART_DLM);
 -      serial8250_early_out(port, UART_LCR, lcr);
 -
 -      quot = (dlm << 8) | dll;
 -      return (port->uartclk / 16) / quot;
 -}
 -
  static void __init init_port(struct earlycon_device *device)
  {
        struct uart_port *port = &device->port;
@@@ -130,20 -152,52 +135,20 @@@ static int __init early_serial8250_setu
                                         const char *options)
  {
        if (!(device->port.membase || device->port.iobase))
 -              return 0;
 +              return -ENODEV;
  
        if (!device->baud) {
 -              device->baud = probe_baud(&device->port);
 -              snprintf(device->options, sizeof(device->options), "%u",
 -                       device->baud);
 -      }
 +              struct uart_port *port = &device->port;
 +              unsigned int ier;
  
 -      init_port(device);
 +              /* assume the device was initialized, only mask interrupts */
 +              ier = serial8250_early_in(port, UART_IER);
 +              serial8250_early_out(port, UART_IER, ier & UART_IER_UUE);
 +      } else
 +              init_port(device);
  
 -      early_device = device;
        device->con->write = early_serial8250_write;
        return 0;
  }
  EARLYCON_DECLARE(uart8250, early_serial8250_setup);
  EARLYCON_DECLARE(uart, early_serial8250_setup);
 -
 -int __init setup_early_serial8250_console(char *cmdline)
 -{
 -      char match[] = "uart8250";
 -
 -      if (cmdline && cmdline[4] == ',')
 -              match[4] = '\0';
 -
 -      return setup_earlycon(cmdline, match, early_serial8250_setup);
 -}
 -
 -int serial8250_find_port_for_earlycon(void)
 -{
 -      struct earlycon_device *device = early_device;
 -      struct uart_port *port = device ? &device->port : NULL;
 -      int line;
 -      int ret;
 -
 -      if (!port || (!port->membase && !port->iobase))
 -              return -ENODEV;
 -
 -      line = serial8250_find_port(port);
 -      if (line < 0)
 -              return -ENODEV;
 -
 -      ret = update_console_cmdline("uart", 8250,
 -                           "ttyS", line, device->options);
 -      if (ret < 0)
 -              ret = update_console_cmdline("uart", 0,
 -                                   "ttyS", line, device->options);
 -
 -      return ret;
 -}
@@@ -89,7 -89,6 +89,7 @@@ static int of_platform_serial_setup(str
  
        spin_lock_init(&port->lock);
        port->mapbase = resource.start;
 +      port->mapsize = resource_size(&resource);
  
        /* Check for shifted address mapping */
        if (of_property_read_u32(np, "reg-offset", &prop) == 0)
                        port->iotype = UPIO_MEM;
                        break;
                case 4:
-                       port->iotype = UPIO_MEM32;
+                       port->iotype = of_device_is_big_endian(np) ?
+                                      UPIO_MEM32BE : UPIO_MEM32;
                        break;
                default:
                        dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
@@@ -156,7 -156,7 +157,7 @@@ out
  /*
   * Try to register a serial port
   */
 -static struct of_device_id of_platform_serial_table[];
 +static const struct of_device_id of_platform_serial_table[];
  static int of_platform_serial_probe(struct platform_device *ofdev)
  {
        const struct of_device_id *match;
@@@ -321,7 -321,7 +322,7 @@@ static SIMPLE_DEV_PM_OPS(of_serial_pm_o
  /*
   * A few common types, add more as needed.
   */
 -static struct of_device_id of_platform_serial_table[] = {
 +static const struct of_device_id of_platform_serial_table[] = {
        { .compatible = "ns8250",   .data = (void *)PORT_8250, },
        { .compatible = "ns16450",  .data = (void *)PORT_16450, },
        { .compatible = "ns16550a", .data = (void *)PORT_16550A, },
diff --combined include/linux/of.h
@@@ -305,6 -305,7 +305,7 @@@ extern int of_property_read_string_help
  extern int of_device_is_compatible(const struct device_node *device,
                                   const char *);
  extern bool of_device_is_available(const struct device_node *device);
+ extern bool of_device_is_big_endian(const struct device_node *device);
  extern const void *of_get_property(const struct device_node *node,
                                const char *name,
                                int *lenp);
@@@ -332,7 -333,6 +333,7 @@@ extern int of_count_phandle_with_args(c
  
  extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
  extern int of_alias_get_id(struct device_node *np, const char *stem);
 +extern int of_alias_get_highest_id(const char *stem);
  
  extern int of_machine_is_compatible(const char *compat);
  
@@@ -467,6 -467,11 +468,11 @@@ static inline bool of_device_is_availab
        return false;
  }
  
+ static inline bool of_device_is_big_endian(const struct device_node *device)
+ {
+       return false;
+ }
  static inline struct property *of_find_property(const struct device_node *np,
                                                const char *name,
                                                int *lenp)
@@@ -595,11 -600,6 +601,11 @@@ static inline int of_alias_get_id(struc
        return -ENOSYS;
  }
  
 +static inline int of_alias_get_highest_id(const char *stem)
 +{
 +      return -ENOSYS;
 +}
 +
  static inline int of_machine_is_compatible(const char *compat)
  {
        return 0;
@@@ -622,38 -622,6 +628,38 @@@ static inline const char *of_prop_next_
        return NULL;
  }
  
 +static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
 +{
 +      return 0;
 +}
 +
 +static inline int of_node_test_and_set_flag(struct device_node *n,
 +                                          unsigned long flag)
 +{
 +      return 0;
 +}
 +
 +static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
 +{
 +}
 +
 +static inline void of_node_clear_flag(struct device_node *n, unsigned long flag)
 +{
 +}
 +
 +static inline int of_property_check_flag(struct property *p, unsigned long flag)
 +{
 +      return 0;
 +}
 +
 +static inline void of_property_set_flag(struct property *p, unsigned long flag)
 +{
 +}
 +
 +static inline void of_property_clear_flag(struct property *p, unsigned long flag)
 +{
 +}
 +
  #define of_match_ptr(_ptr)    NULL
  #define of_match_node(_matches, _node)        NULL
  #endif /* CONFIG_OF */