Merge tag 'dropmachtimexh-v2' of git://git.pengutronix.de/git/ukl/linux
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Mon, 24 Feb 2014 09:06:56 +0000 (10:06 +0100)
committerUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Mon, 24 Feb 2014 09:06:56 +0000 (10:06 +0100)
This cleanup series gets rid of <mach/timex.h> for platforms not using
ARCH_MULTIPLATFORM. (For multi-platform code it's already unused since
387798b (ARM: initial multiplatform support).)

To make this work some code out of arch/arm needed to be adapted. The
respective changes got acks by their maintainers to be taken via armsoc
(with Andrew Morton substituting for Alessandro Zummo as rtc maintainer).

Compared to the previous pull request there was another patch added that
fixes a (non-critical) regression on ixp4xx. Olof Johansson asked to not
squash this fix into the original commit to save him from the need to
reverify the series.

Conflicts:
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-mmp/time.c
arch/arm/mach-sa1100/time.c

15 files changed:
1  2 
Documentation/devicetree/bindings/serial/atmel-usart.txt
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam926x_time.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/pm.c
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-mmp/time.c
arch/arm/mach-sa1100/time.c
drivers/tty/serial/atmel_serial.c

@@@ -6,13 -6,12 +6,15 @@@ Required properties
    additional mode or an USART new feature.
  - reg: Should contain registers location and length
  - interrupts: Should contain interrupt
 +- clock-names: tuple listing input clock names.
 +      Required elements: "usart"
 +- clocks: phandles to input clocks.
  
  Optional properties:
  - atmel,use-dma-rx: use of PDC or DMA for receiving data
  - atmel,use-dma-tx: use of PDC or DMA for transmitting data
+ - rts-gpios: specify a GPIO for RTS line. It will use specified PIO instead of the peripheral
+   function pin for the USART RTS feature. If unsure, don't specify this property.
  - add dma bindings for dma transfer:
        - dmas: DMA specifier, consisting of a phandle to DMA controller node,
                memory peripheral interface and USART DMA channel ID, FIFO configuration.
@@@ -29,10 -28,9 +31,11 @@@ Example
                compatible = "atmel,at91sam9260-usart";
                reg = <0xfff8c000 0x4000>;
                interrupts = <7>;
 +              clocks = <&usart0_clk>;
 +              clock-names = "usart";
                atmel,use-dma-rx;
                atmel,use-dma-tx;
+               rts-gpios = <&pioD 15 0>;
        };
  
  - use DMA:
@@@ -40,8 -38,6 +43,8 @@@
                compatible = "atmel,at91sam9260-usart";
                reg = <0xf001c000 0x100>;
                interrupts = <12 4 5>;
 +              clocks = <&usart0_clk>;
 +              clock-names = "usart";
                atmel,use-dma-rx;
                atmel,use-dma-tx;
                dmas = <&dma0 2 0x3>,
  
  #include <linux/module.h>
  #include <linux/reboot.h>
 +#include <linux/clk/at91_pmc.h>
  
  #include <asm/irq.h>
  #include <asm/mach/arch.h>
  #include <asm/mach/map.h>
  #include <asm/system_misc.h>
  #include <mach/at91rm9200.h>
 -#include <mach/at91_pmc.h>
  #include <mach/at91_st.h>
  #include <mach/cpu.h>
+ #include <mach/hardware.h>
  
  #include "at91_aic.h"
  #include "soc.h"
@@@ -31,6 -31,7 +31,7 @@@
  #include <asm/mach/time.h>
  
  #include <mach/at91_st.h>
+ #include <mach/hardware.h>
  
  static unsigned long last_crtr;
  static u32 irqmask;
@@@ -174,6 -175,7 +175,6 @@@ clkevt32k_next_event(unsigned long delt
  static struct clock_event_device clkevt = {
        .name           = "at91_tick",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 -      .shift          = 32,
        .rating         = 150,
        .set_next_event = clkevt32k_next_event,
        .set_mode       = clkevt32k_mode,
@@@ -264,9 -266,11 +265,9 @@@ void __init at91rm9200_timer_init(void
        at91_st_write(AT91_ST_RTMR, 1);
  
        /* Setup timer clockevent, with minimum of two ticks (important!!) */
 -      clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift);
 -      clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt);
 -      clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1;
        clkevt.cpumask = cpumask_of(0);
 -      clockevents_register_device(&clkevt);
 +      clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK,
 +                                      2, AT91_ST_ALMV);
  
        /* register clocksource */
        clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
@@@ -11,7 -11,6 +11,7 @@@
   */
  
  #include <linux/module.h>
 +#include <linux/clk/at91_pmc.h>
  
  #include <asm/proc-fns.h>
  #include <asm/irq.h>
@@@ -21,6 -20,8 +21,7 @@@
  #include <mach/cpu.h>
  #include <mach/at91_dbgu.h>
  #include <mach/at91sam9260.h>
 -#include <mach/at91_pmc.h>
+ #include <mach/hardware.h>
  
  #include "at91_aic.h"
  #include "at91_rstc.h"
@@@ -11,7 -11,6 +11,7 @@@
   */
  
  #include <linux/module.h>
 +#include <linux/clk/at91_pmc.h>
  
  #include <asm/proc-fns.h>
  #include <asm/irq.h>
@@@ -20,6 -19,8 +20,7 @@@
  #include <asm/system_misc.h>
  #include <mach/cpu.h>
  #include <mach/at91sam9261.h>
 -#include <mach/at91_pmc.h>
+ #include <mach/hardware.h>
  
  #include "at91_aic.h"
  #include "at91_rstc.h"
@@@ -11,7 -11,6 +11,7 @@@
   */
  
  #include <linux/module.h>
 +#include <linux/clk/at91_pmc.h>
  
  #include <asm/proc-fns.h>
  #include <asm/irq.h>
@@@ -19,6 -18,8 +19,7 @@@
  #include <asm/mach/map.h>
  #include <asm/system_misc.h>
  #include <mach/at91sam9263.h>
 -#include <mach/at91_pmc.h>
+ #include <mach/hardware.h>
  
  #include "at91_aic.h"
  #include "at91_rstc.h"
@@@ -19,6 -19,7 +19,7 @@@
  #include <linux/of_irq.h>
  
  #include <asm/mach/time.h>
+ #include <mach/hardware.h>
  
  #define AT91_PIT_MR           0x00                    /* Mode Register */
  #define               AT91_PIT_PITIEN         (1 << 25)               /* Timer Interrupt Enable */
@@@ -39,7 -40,6 +40,7 @@@
  static u32 pit_cycle;         /* write-once */
  static u32 pit_cnt;           /* access only w/system irq blocked */
  static void __iomem *pit_base_addr __read_mostly;
 +static struct clk *mck;
  
  static inline unsigned int pit_read(unsigned int reg_offset)
  {
@@@ -196,14 -196,10 +197,14 @@@ static int __init of_at91sam926x_pit_in
        if (!pit_base_addr)
                goto node_err;
  
 +      mck = of_clk_get(np, 0);
 +
        /* Get the interrupts property */
        ret = irq_of_parse_and_map(np, 0);
        if (!ret) {
                pr_crit("AT91: PIT: Unable to get IRQ from DT\n");
 +              if (!IS_ERR(mck))
 +                      clk_put(mck);
                goto ioremap_err;
        }
        at91sam926x_pit_irq.irq = ret;
@@@ -235,8 -231,6 +236,8 @@@ void __init at91sam926x_pit_init(void
        unsigned        bits;
        int             ret;
  
 +      mck = ERR_PTR(-ENOENT);
 +
        /* For device tree enabled device: initialize here */
        of_at91sam926x_pit_init();
  
         * Use our actual MCK to figure out how many MCK/16 ticks per
         * 1/HZ period (instead of a compile-time constant LATCH).
         */
 -      pit_rate = clk_get_rate(clk_get(NULL, "mck")) / 16;
 +      if (IS_ERR(mck))
 +              mck = clk_get(NULL, "mck");
 +
 +      if (IS_ERR(mck))
 +              panic("AT91: PIT: Unable to get mck clk\n");
 +      pit_rate = clk_get_rate(mck) / 16;
        pit_cycle = (pit_rate + HZ/2) / HZ;
        WARN_ON(((pit_cycle - 1) & ~AT91_PIT_PIV) != 0);
  
  
  #include <linux/module.h>
  #include <linux/dma-mapping.h>
 +#include <linux/clk/at91_pmc.h>
  
  #include <asm/irq.h>
  #include <asm/mach/arch.h>
  #include <asm/mach/map.h>
  #include <asm/system_misc.h>
  #include <mach/at91sam9g45.h>
 -#include <mach/at91_pmc.h>
  #include <mach/cpu.h>
+ #include <mach/hardware.h>
  
  #include "at91_aic.h"
  #include "soc.h"
@@@ -10,7 -10,6 +10,7 @@@
   */
  
  #include <linux/module.h>
 +#include <linux/clk/at91_pmc.h>
  
  #include <asm/proc-fns.h>
  #include <asm/irq.h>
@@@ -20,6 -19,8 +20,7 @@@
  #include <mach/cpu.h>
  #include <mach/at91_dbgu.h>
  #include <mach/at91sam9rl.h>
 -#include <mach/at91_pmc.h>
+ #include <mach/hardware.h>
  
  #include "at91_aic.h"
  #include "at91_rstc.h"
diff --combined arch/arm/mach-at91/pm.c
  #include <linux/module.h>
  #include <linux/platform_device.h>
  #include <linux/io.h>
 +#include <linux/clk/at91_pmc.h>
  
  #include <asm/irq.h>
  #include <linux/atomic.h>
  #include <asm/mach/time.h>
  #include <asm/mach/irq.h>
  
 -#include <mach/at91_pmc.h>
  #include <mach/cpu.h>
+ #include <mach/hardware.h>
  
  #include "at91_aic.h"
  #include "generic.h"
@@@ -155,6 -156,9 +156,6 @@@ static int at91_pm_verify_clocks(void
                }
        }
  
 -      if (!IS_ENABLED(CONFIG_AT91_PROGRAMMABLE_CLOCKS))
 -              return 1;
 -
        /* PCK0..PCK3 must be disabled, or configured to use clk32k */
        for (i = 0; i < 4; i++) {
                u32 css;
@@@ -21,7 -21,6 +21,7 @@@
  #include <linux/platform_device.h>
  #include <linux/interrupt.h>
  #include <linux/dma-mapping.h>
 +#include <linux/sys_soc.h>
  #include <linux/timex.h>
  #include <linux/irq.h>
  #include <linux/io.h>
@@@ -45,7 -44,6 +45,7 @@@
  #include <linux/platform_data/spi-ep93xx.h>
  #include <mach/gpio-ep93xx.h>
  
 +#include <asm/mach/arch.h>
  #include <asm/mach/map.h>
  #include <asm/mach/time.h>
  
@@@ -117,7 -115,7 +117,7 @@@ void __init ep93xx_map_io(void
  #define EP93XX_TIMER4_CLOCK           983040
  
  #define TIMER1_RELOAD                 ((EP93XX_TIMER123_CLOCK / HZ) - 1)
- #define TIMER4_TICKS_PER_JIFFY                DIV_ROUND_CLOSEST(CLOCK_TICK_RATE, HZ)
+ #define TIMER4_TICKS_PER_JIFFY                DIV_ROUND_CLOSEST(EP93XX_TIMER4_CLOCK, HZ)
  
  static unsigned int last_jiffy_time;
  
@@@ -139,7 -137,7 +139,7 @@@ static irqreturn_t ep93xx_timer_interru
  
  static struct irqaction ep93xx_timer_irq = {
        .name           = "ep93xx timer",
 -      .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 +      .flags          = IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = ep93xx_timer_interrupt,
  };
  
@@@ -927,108 -925,8 +927,108 @@@ void ep93xx_ide_release_gpio(struct pla
  }
  EXPORT_SYMBOL(ep93xx_ide_release_gpio);
  
 -void __init ep93xx_init_devices(void)
 +/*************************************************************************
 + * EP93xx Security peripheral
 + *************************************************************************/
 +
 +/*
 + * The Maverick Key is 256 bits of micro fuses blown at the factory during
 + * manufacturing to uniquely identify a part.
 + *
 + * See: http://arm.cirrus.com/forum/viewtopic.php?t=486&highlight=maverick+key
 + */
 +#define EP93XX_SECURITY_REG(x)                (EP93XX_SECURITY_BASE + (x))
 +#define EP93XX_SECURITY_SECFLG                EP93XX_SECURITY_REG(0x2400)
 +#define EP93XX_SECURITY_FUSEFLG               EP93XX_SECURITY_REG(0x2410)
 +#define EP93XX_SECURITY_UNIQID                EP93XX_SECURITY_REG(0x2440)
 +#define EP93XX_SECURITY_UNIQCHK               EP93XX_SECURITY_REG(0x2450)
 +#define EP93XX_SECURITY_UNIQVAL               EP93XX_SECURITY_REG(0x2460)
 +#define EP93XX_SECURITY_SECID1                EP93XX_SECURITY_REG(0x2500)
 +#define EP93XX_SECURITY_SECID2                EP93XX_SECURITY_REG(0x2504)
 +#define EP93XX_SECURITY_SECCHK1               EP93XX_SECURITY_REG(0x2520)
 +#define EP93XX_SECURITY_SECCHK2               EP93XX_SECURITY_REG(0x2524)
 +#define EP93XX_SECURITY_UNIQID2               EP93XX_SECURITY_REG(0x2700)
 +#define EP93XX_SECURITY_UNIQID3               EP93XX_SECURITY_REG(0x2704)
 +#define EP93XX_SECURITY_UNIQID4               EP93XX_SECURITY_REG(0x2708)
 +#define EP93XX_SECURITY_UNIQID5               EP93XX_SECURITY_REG(0x270c)
 +
 +static char ep93xx_soc_id[33];
 +
 +static const char __init *ep93xx_get_soc_id(void)
  {
 +      unsigned int id, id2, id3, id4, id5;
 +
 +      if (__raw_readl(EP93XX_SECURITY_UNIQVAL) != 1)
 +              return "bad Hamming code";
 +
 +      id = __raw_readl(EP93XX_SECURITY_UNIQID);
 +      id2 = __raw_readl(EP93XX_SECURITY_UNIQID2);
 +      id3 = __raw_readl(EP93XX_SECURITY_UNIQID3);
 +      id4 = __raw_readl(EP93XX_SECURITY_UNIQID4);
 +      id5 = __raw_readl(EP93XX_SECURITY_UNIQID5);
 +
 +      if (id != id2)
 +              return "invalid";
 +
 +      snprintf(ep93xx_soc_id, sizeof(ep93xx_soc_id),
 +               "%08x%08x%08x%08x", id2, id3, id4, id5);
 +
 +      return ep93xx_soc_id;
 +}
 +
 +static const char __init *ep93xx_get_soc_rev(void)
 +{
 +      int rev = ep93xx_chip_revision();
 +
 +      switch (rev) {
 +      case EP93XX_CHIP_REV_D0:
 +              return "D0";
 +      case EP93XX_CHIP_REV_D1:
 +              return "D1";
 +      case EP93XX_CHIP_REV_E0:
 +              return "E0";
 +      case EP93XX_CHIP_REV_E1:
 +              return "E1";
 +      case EP93XX_CHIP_REV_E2:
 +              return "E2";
 +      default:
 +              return "unknown";
 +      }
 +}
 +
 +static const char __init *ep93xx_get_machine_name(void)
 +{
 +      return kasprintf(GFP_KERNEL,"%s", machine_desc->name);
 +}
 +
 +static struct device __init *ep93xx_init_soc(void)
 +{
 +      struct soc_device_attribute *soc_dev_attr;
 +      struct soc_device *soc_dev;
 +
 +      soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
 +      if (!soc_dev_attr)
 +              return NULL;
 +
 +      soc_dev_attr->machine = ep93xx_get_machine_name();
 +      soc_dev_attr->family = "Cirrus Logic EP93xx";
 +      soc_dev_attr->revision = ep93xx_get_soc_rev();
 +      soc_dev_attr->soc_id = ep93xx_get_soc_id();
 +
 +      soc_dev = soc_device_register(soc_dev_attr);
 +      if (IS_ERR(soc_dev)) {
 +              kfree(soc_dev_attr->machine);
 +              kfree(soc_dev_attr);
 +              return NULL;
 +      }
 +
 +      return soc_device_to_device(soc_dev);
 +}
 +
 +struct device __init *ep93xx_init_devices(void)
 +{
 +      struct device *parent;
 +
        /* Disallow access to MaverickCrunch initially */
        ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA);
  
                               EP93XX_SYSCON_DEVCFG_GONIDE |
                               EP93XX_SYSCON_DEVCFG_HONIDE);
  
 +      parent = ep93xx_init_soc();
 +
        /* Get the GPIO working early, other devices need it */
        platform_device_register(&ep93xx_gpio_device);
  
        platform_device_register(&ep93xx_wdt_device);
  
        gpio_led_register_device(-1, &ep93xx_led_data);
 +
 +      return parent;
  }
  
  void ep93xx_restart(enum reboot_mode mode, const char *cmd)
@@@ -23,7 -23,6 +23,6 @@@
  #include <linux/interrupt.h>
  #include <linux/bitops.h>
  #include <linux/time.h>
- #include <linux/timex.h>
  #include <linux/clocksource.h>
  #include <linux/clockchips.h>
  #include <linux/io.h>
  #include <asm/mach/irq.h>
  #include <asm/mach/time.h>
  
+ #define IXP4XX_TIMER_FREQ 66666000
+ /*
+  * The timer register doesn't allow to specify the two least significant bits of
+  * the timeout value and assumes them being zero. So make sure IXP4XX_LATCH is
+  * the best value with the two least significant bits unset.
+  */
+ #define IXP4XX_LATCH DIV_ROUND_CLOSEST(IXP4XX_TIMER_FREQ, \
+                                      (IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \
+                       (IXP4XX_OST_RELOAD_MASK + 1)
  static void __init ixp4xx_clocksource_init(void);
  static void __init ixp4xx_clockevent_init(void);
  static struct clock_event_device clockevent_ixp4xx;
@@@ -475,7 -485,7 +485,7 @@@ void __init ixp4xx_sys_init(void
  /*
   * sched_clock()
   */
 -static u32 notrace ixp4xx_read_sched_clock(void)
 +static u64 notrace ixp4xx_read_sched_clock(void)
  {
        return *IXP4XX_OSTS;
  }
@@@ -493,7 -503,7 +503,7 @@@ unsigned long ixp4xx_timer_freq = IXP4X
  EXPORT_SYMBOL(ixp4xx_timer_freq);
  static void __init ixp4xx_clocksource_init(void)
  {
 -      setup_sched_clock(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq);
 +      sched_clock_register(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq);
  
        clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32,
                        ixp4xx_clocksource_read);
@@@ -520,7 -530,7 +530,7 @@@ static void ixp4xx_set_mode(enum clock_
  
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
-               osrt = LATCH & ~IXP4XX_OST_RELOAD_MASK;
+               osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK;
                opts = IXP4XX_OST_ENABLE;
                break;
        case CLOCK_EVT_MODE_ONESHOT:
@@@ -560,7 -570,7 +570,7 @@@ static void __init ixp4xx_clockevent_in
  
  void ixp4xx_restart(enum reboot_mode mode, const char *cmd)
  {
 -      if ( 1 && mode == REBOOT_SOFT) {
 +      if (mode == REBOOT_SOFT) {
                /* Jump into ROM at address 0 */
                soft_restart(0);
        } else {
diff --combined arch/arm/mach-mmp/time.c
  
  #include "clock.h"
  
+ #ifdef CONFIG_CPU_MMP2
+ #define MMP_CLOCK_FREQ                6500000
+ #else
+ #define MMP_CLOCK_FREQ                3250000
+ #endif
  #define TIMERS_VIRT_BASE      TIMERS1_VIRT_BASE
  
  #define MAX_DELTA             (0xfffffffe)
@@@ -61,7 -67,7 +67,7 @@@ static inline uint32_t timer_read(void
        return __raw_readl(mmp_timer_base + TMR_CVWR(1));
  }
  
 -static u32 notrace mmp_read_sched_clock(void)
 +static u64 notrace mmp_read_sched_clock(void)
  {
        return timer_read();
  }
@@@ -195,14 -201,14 +201,14 @@@ void __init timer_init(int irq
  {
        timer_config();
  
-       sched_clock_register(mmp_read_sched_clock, 32, CLOCK_TICK_RATE);
 -      setup_sched_clock(mmp_read_sched_clock, 32, MMP_CLOCK_FREQ);
++      sched_clock_register(mmp_read_sched_clock, 32, MMP_CLOCK_FREQ);
  
        ckevt.cpumask = cpumask_of(0);
  
        setup_irq(irq, &timer_irq);
  
-       clocksource_register_hz(&cksrc, CLOCK_TICK_RATE);
-       clockevents_config_and_register(&ckevt, CLOCK_TICK_RATE,
+       clocksource_register_hz(&cksrc, MMP_CLOCK_FREQ);
+       clockevents_config_and_register(&ckevt, MMP_CLOCK_FREQ,
                                        MIN_DELTA, MAX_DELTA);
  }
  
@@@ -9,6 -9,7 +9,7 @@@
   *
   */
  #include <linux/init.h>
+ #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/interrupt.h>
  #include <linux/irq.h>
  #include <mach/hardware.h>
  #include <mach/irqs.h>
  
 -static u32 notrace sa1100_read_sched_clock(void)
+ #define SA1100_CLOCK_FREQ 3686400
+ #define SA1100_LATCH DIV_ROUND_CLOSEST(SA1100_CLOCK_FREQ, HZ)
 +static u64 notrace sa1100_read_sched_clock(void)
  {
        return readl_relaxed(OSCR);
  }
@@@ -93,7 -97,7 +97,7 @@@ static void sa1100_timer_resume(struct 
        /*
         * OSMR0 is the system timer: make sure OSCR is sufficiently behind
         */
-       writel_relaxed(OSMR0 - LATCH, OSCR);
+       writel_relaxed(OSMR0 - SA1100_LATCH, OSCR);
  }
  #else
  #define sa1100_timer_suspend NULL
@@@ -122,13 -126,13 +126,13 @@@ void __init sa1100_timer_init(void
        writel_relaxed(0, OIER);
        writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
  
 -      setup_sched_clock(sa1100_read_sched_clock, 32, 3686400);
 +      sched_clock_register(sa1100_read_sched_clock, 32, 3686400);
  
        ckevt_sa1100_osmr0.cpumask = cpumask_of(0);
  
        setup_irq(IRQ_OST0, &sa1100_timer_irq);
  
-       clocksource_mmio_init(OSCR, "oscr", CLOCK_TICK_RATE, 200, 32,
+       clocksource_mmio_init(OSCR, "oscr", SA1100_CLOCK_FREQ, 200, 32,
                clocksource_mmio_readl_up);
        clockevents_config_and_register(&ckevt_sa1100_osmr0, 3686400,
                                        MIN_OSCR_DELTA * 2, 0x7fffffff);
  #include <linux/platform_device.h>
  #include <linux/of.h>
  #include <linux/of_device.h>
+ #include <linux/of_gpio.h>
  #include <linux/dma-mapping.h>
  #include <linux/atmel_pdc.h>
  #include <linux/atmel_serial.h>
  #include <linux/uaccess.h>
  #include <linux/platform_data/atmel.h>
  #include <linux/timer.h>
+ #include <linux/gpio.h>
  
  #include <asm/io.h>
  #include <asm/ioctls.h>
  
- #ifdef CONFIG_ARM
- #include <mach/cpu.h>
- #include <asm/gpio.h>
- #endif
  #define PDC_BUFFER_SIZE               512
  /* Revisit: We should calculate this based on the actual port settings */
  #define PDC_RX_TIMEOUT                (3 * 10)                /* 3 bytes */
@@@ -168,6 -165,7 +165,7 @@@ struct atmel_uart_port 
        struct circ_buf         rx_ring;
  
        struct serial_rs485     rs485;          /* rs485 settings */
+       int                     rts_gpio;       /* optional RTS GPIO */
        unsigned int            tx_done_mask;
        bool                    is_usart;       /* usart or uart */
        struct timer_list       uart_timer;     /* uart timer */
@@@ -301,20 -299,16 +299,16 @@@ static void atmel_set_mctrl(struct uart
        unsigned int mode;
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
  
- #ifdef CONFIG_ARCH_AT91RM9200
-       if (cpu_is_at91rm9200()) {
-               /*
-                * AT91RM9200 Errata #39: RTS0 is not internally connected
-                * to PA21. We need to drive the pin manually.
-                */
-               if (port->mapbase == AT91RM9200_BASE_US0) {
-                       if (mctrl & TIOCM_RTS)
-                               at91_set_gpio_value(AT91_PIN_PA21, 0);
-                       else
-                               at91_set_gpio_value(AT91_PIN_PA21, 1);
-               }
+       /*
+        * AT91RM9200 Errata #39: RTS0 is not internally connected
+        * to PA21. We need to drive the pin as a GPIO.
+        */
+       if (gpio_is_valid(atmel_port->rts_gpio)) {
+               if (mctrl & TIOCM_RTS)
+                       gpio_set_value(atmel_port->rts_gpio, 0);
+               else
+                       gpio_set_value(atmel_port->rts_gpio, 1);
        }
- #endif
  
        if (mctrl & TIOCM_RTS)
                control |= ATMEL_US_RTSEN;
@@@ -825,6 -819,9 +819,6 @@@ static void atmel_release_rx_dma(struc
        atmel_port->desc_rx = NULL;
        atmel_port->chan_rx = NULL;
        atmel_port->cookie_rx = -EINVAL;
 -
 -      if (!atmel_port->is_usart)
 -              del_timer_sync(&atmel_port->uart_timer);
  }
  
  static void atmel_rx_from_dma(struct uart_port *port)
@@@ -1226,6 -1223,9 +1220,6 @@@ static void atmel_release_rx_pdc(struc
                                 DMA_FROM_DEVICE);
                kfree(pdc->buf);
        }
 -
 -      if (!atmel_port->is_usart)
 -              del_timer_sync(&atmel_port->uart_timer);
  }
  
  static void atmel_rx_from_pdc(struct uart_port *port)
@@@ -1598,13 -1598,12 +1592,13 @@@ static int atmel_startup(struct uart_po
        /* enable xmit & rcvr */
        UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
  
 +      setup_timer(&atmel_port->uart_timer,
 +                      atmel_uart_timer_callback,
 +                      (unsigned long)port);
 +
        if (atmel_use_pdc_rx(port)) {
                /* set UART timeout */
                if (!atmel_port->is_usart) {
 -                      setup_timer(&atmel_port->uart_timer,
 -                                      atmel_uart_timer_callback,
 -                                      (unsigned long)port);
                        mod_timer(&atmel_port->uart_timer,
                                        jiffies + uart_poll_timeout(port));
                /* set USART timeout */
        } else if (atmel_use_dma_rx(port)) {
                /* set UART timeout */
                if (!atmel_port->is_usart) {
 -                      setup_timer(&atmel_port->uart_timer,
 -                                      atmel_uart_timer_callback,
 -                                      (unsigned long)port);
                        mod_timer(&atmel_port->uart_timer,
                                        jiffies + uart_poll_timeout(port));
                /* set USART timeout */
  static void atmel_shutdown(struct uart_port *port)
  {
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 +
        /*
 -       * Ensure everything is stopped.
 +       * Prevent any tasklets being scheduled during
 +       * cleanup
 +       */
 +      del_timer_sync(&atmel_port->uart_timer);
 +
 +      /*
 +       * Clear out any scheduled tasklets before
 +       * we destroy the buffers
 +       */
 +      tasklet_kill(&atmel_port->tasklet);
 +
 +      /*
 +       * Ensure everything is stopped and
 +       * disable all interrupts, port and break condition.
         */
        atmel_stop_rx(port);
        atmel_stop_tx(port);
  
 +      UART_PUT_CR(port, ATMEL_US_RSTSTA);
 +      UART_PUT_IDR(port, -1);
 +
 +
        /*
         * Shut-down the DMA.
         */
                atmel_port->release_tx(port);
  
        /*
 -       * Disable all interrupts, port and break condition.
 +       * Reset ring buffer pointers
         */
 -      UART_PUT_CR(port, ATMEL_US_RSTSTA);
 -      UART_PUT_IDR(port, -1);
 +      atmel_port->rx_ring.head = 0;
 +      atmel_port->rx_ring.tail = 0;
  
        /*
         * Free the interrupt
@@@ -2389,6 -2373,25 +2383,25 @@@ static int atmel_serial_probe(struct pl
        port = &atmel_ports[ret];
        port->backup_imr = 0;
        port->uart.line = ret;
+       port->rts_gpio = -EINVAL; /* Invalid, zero could be valid */
+       if (pdata)
+               port->rts_gpio = pdata->rts_gpio;
+       else if (np)
+               port->rts_gpio = of_get_named_gpio(np, "rts-gpios", 0);
+       if (gpio_is_valid(port->rts_gpio)) {
+               ret = devm_gpio_request(&pdev->dev, port->rts_gpio, "RTS");
+               if (ret) {
+                       dev_err(&pdev->dev, "error requesting RTS GPIO\n");
+                       goto err;
+               }
+               /* Default to 1 as RTS is active low */
+               ret = gpio_direction_output(port->rts_gpio, 1);
+               if (ret) {
+                       dev_err(&pdev->dev, "error setting up RTS GPIO\n");
+                       goto err;
+               }
+       }
  
        ret = atmel_init_port(port, pdev);
        if (ret)
@@@ -2451,12 -2454,11 +2464,12 @@@ static int atmel_serial_remove(struct p
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
        int ret = 0;
  
 +      tasklet_kill(&atmel_port->tasklet);
 +
        device_init_wakeup(&pdev->dev, 0);
  
        ret = uart_remove_one_port(&atmel_uart, port);
  
 -      tasklet_kill(&atmel_port->tasklet);
        kfree(atmel_port->rx_ring.buf);
  
        /* "port" is allocated statically, so we shouldn't free it */