forked from luck/tmp_suning_uos_patched
arm: lpc32xx: switch to common clock framework
The change switches NXP LPC32xx platforms to LPC32xx clock driver powered by common clock framework, this obsoletes mach-lpc32xx/clock.o legacy clock driver and thus it is removed. Legacy timer driver mach-lpc32xx/timer.o strictly depends on legacy clock support, but fortunately an existing LPC32xx clock source and clock event driver completely replaces it, and thus it can be removed as well. Noticeably platform UART driver directly operates on LPC32xx source control block registers, remove this dependency to avoid overlapping with common clock framework driver, also this guarantees that UART is working expectedly. Tested-by: Sylvain Lemieux <slemieux@tycoint.com> Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
This commit is contained in:
parent
92e963f50f
commit
c227f127e3
|
@ -527,7 +527,8 @@ config ARCH_LPC32XX
|
|||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_AMBA
|
||||
select CLKDEV_LOOKUP
|
||||
select CLKSRC_MMIO
|
||||
select CLKSRC_LPC32XX
|
||||
select COMMON_CLK
|
||||
select CPU_ARM926T
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select HAVE_IDE
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
obj-y := timer.o irq.o common.o serial.o clock.o
|
||||
obj-y := irq.o common.o serial.o
|
||||
obj-y += pm.o suspend.o
|
||||
obj-y += phy3250.o
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -260,7 +260,6 @@ DT_MACHINE_START(LPC32XX_DT, "LPC32XX SoC (Flattened Device Tree)")
|
|||
.atag_offset = 0x100,
|
||||
.map_io = lpc32xx_map_io,
|
||||
.init_irq = lpc32xx_init_irq,
|
||||
.init_time = lpc32xx_timer_init,
|
||||
.init_machine = lpc3250_machine_init,
|
||||
.dt_compat = lpc32xx_dt_compat,
|
||||
.restart = lpc23xx_restart,
|
||||
|
|
|
@ -76,9 +76,6 @@ void __init lpc32xx_serial_init(void)
|
|||
unsigned int puart;
|
||||
int i, j;
|
||||
|
||||
/* UART clocks are off, let clock driver manage them */
|
||||
__raw_writel(0, LPC32XX_CLKPWR_UART_CLK_CTRL);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(uartinit_data); i++) {
|
||||
clk = clk_get(NULL, uartinit_data[i].uart_ck_name);
|
||||
if (!IS_ERR(clk)) {
|
||||
|
|
|
@ -1,144 +0,0 @@
|
|||
/*
|
||||
* arch/arm/mach-lpc32xx/timer.c
|
||||
*
|
||||
* Author: Kevin Wells <kevin.wells@nxp.com>
|
||||
*
|
||||
* Copyright (C) 2009 - 2010 NXP Semiconductors
|
||||
* Copyright (C) 2009 Fontys University of Applied Sciences, Eindhoven
|
||||
* Ed Schouten <e.schouten@fontys.nl>
|
||||
* Laurens Timmermans <l.timmermans@fontys.nl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/platform.h>
|
||||
#include "common.h"
|
||||
|
||||
static int lpc32xx_clkevt_next_event(unsigned long delta,
|
||||
struct clock_event_device *dev)
|
||||
{
|
||||
__raw_writel(LPC32XX_TIMER_CNTR_TCR_RESET,
|
||||
LPC32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
|
||||
__raw_writel(delta, LPC32XX_TIMER_PR(LPC32XX_TIMER0_BASE));
|
||||
__raw_writel(LPC32XX_TIMER_CNTR_TCR_EN,
|
||||
LPC32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpc32xx_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
/*
|
||||
* Disable the timer. When using oneshot, we must also
|
||||
* disable the timer to wait for the first call to
|
||||
* set_next_event().
|
||||
*/
|
||||
__raw_writel(0, LPC32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device lpc32xx_clkevt = {
|
||||
.name = "lpc32xx_clkevt",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 300,
|
||||
.set_next_event = lpc32xx_clkevt_next_event,
|
||||
.set_state_shutdown = lpc32xx_shutdown,
|
||||
.set_state_oneshot = lpc32xx_shutdown,
|
||||
};
|
||||
|
||||
static irqreturn_t lpc32xx_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *evt = &lpc32xx_clkevt;
|
||||
|
||||
/* Clear match */
|
||||
__raw_writel(LPC32XX_TIMER_CNTR_MTCH_BIT(0),
|
||||
LPC32XX_TIMER_IR(LPC32XX_TIMER0_BASE));
|
||||
|
||||
evt->event_handler(evt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction lpc32xx_timer_irq = {
|
||||
.name = "LPC32XX Timer Tick",
|
||||
.flags = IRQF_TIMER | IRQF_IRQPOLL,
|
||||
.handler = lpc32xx_timer_interrupt,
|
||||
};
|
||||
|
||||
/*
|
||||
* The clock management driver isn't initialized at this point, so the
|
||||
* clocks need to be enabled here manually and then tagged as used in
|
||||
* the clock driver initialization
|
||||
*/
|
||||
void __init lpc32xx_timer_init(void)
|
||||
{
|
||||
u32 clkrate, pllreg;
|
||||
|
||||
/* Enable timer clock */
|
||||
__raw_writel(LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN |
|
||||
LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN,
|
||||
LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1);
|
||||
|
||||
/*
|
||||
* The clock driver isn't initialized at this point. So determine if
|
||||
* the SYSCLK is driven from the PLL397 or main oscillator and then use
|
||||
* it to compute the PLL frequency and the PCLK divider to get the base
|
||||
* timer rates. This rate is needed to compute the tick rate.
|
||||
*/
|
||||
if (clk_is_sysclk_mainosc() != 0)
|
||||
clkrate = LPC32XX_MAIN_OSC_FREQ;
|
||||
else
|
||||
clkrate = 397 * LPC32XX_CLOCK_OSC_FREQ;
|
||||
|
||||
/* Get ARM HCLKPLL register and convert it into a frequency */
|
||||
pllreg = __raw_readl(LPC32XX_CLKPWR_HCLKPLL_CTRL) & 0x1FFFF;
|
||||
clkrate = clk_get_pllrate_from_reg(clkrate, pllreg);
|
||||
|
||||
/* Get PCLK divider and divide ARM PLL clock by it to get timer rate */
|
||||
clkrate = clkrate / clk_get_pclk_div();
|
||||
|
||||
/* Initial timer setup */
|
||||
__raw_writel(0, LPC32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
|
||||
__raw_writel(LPC32XX_TIMER_CNTR_MTCH_BIT(0),
|
||||
LPC32XX_TIMER_IR(LPC32XX_TIMER0_BASE));
|
||||
__raw_writel(1, LPC32XX_TIMER_MR0(LPC32XX_TIMER0_BASE));
|
||||
__raw_writel(LPC32XX_TIMER_CNTR_MCR_MTCH(0) |
|
||||
LPC32XX_TIMER_CNTR_MCR_STOP(0) |
|
||||
LPC32XX_TIMER_CNTR_MCR_RESET(0),
|
||||
LPC32XX_TIMER_MCR(LPC32XX_TIMER0_BASE));
|
||||
|
||||
/* Setup tick interrupt */
|
||||
setup_irq(IRQ_LPC32XX_TIMER0, &lpc32xx_timer_irq);
|
||||
|
||||
/* Setup the clockevent structure. */
|
||||
lpc32xx_clkevt.cpumask = cpumask_of(0);
|
||||
clockevents_config_and_register(&lpc32xx_clkevt, clkrate, 1, -1);
|
||||
|
||||
/* Use timer1 as clock source. */
|
||||
__raw_writel(LPC32XX_TIMER_CNTR_TCR_RESET,
|
||||
LPC32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
|
||||
__raw_writel(0, LPC32XX_TIMER_PR(LPC32XX_TIMER1_BASE));
|
||||
__raw_writel(0, LPC32XX_TIMER_MCR(LPC32XX_TIMER1_BASE));
|
||||
__raw_writel(LPC32XX_TIMER_CNTR_TCR_EN,
|
||||
LPC32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
|
||||
|
||||
clocksource_mmio_init(LPC32XX_TIMER_TC(LPC32XX_TIMER1_BASE),
|
||||
"lpc32xx_clksrc", clkrate, 300, 32, clocksource_mmio_readl_up);
|
||||
}
|
Loading…
Reference in New Issue
Block a user