From 6c3a158316598bfb165b8c83b168fa413d5ae2d8 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 17 Aug 2007 16:55:22 +0100 Subject: [ARM] 4550/1: sched_clock on PXA should cope with run time clock rate selection The previous implementation was relying on compile time optimizations based on a constant clock rate. However, support for different PXA flavors in the same kernel binary requires that the clock be selected at run time, so here it is. Let's move this code to a more appropriate location while at it. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mach-pxa/generic.c | 62 --------------------------------------------- arch/arm/mach-pxa/time.c | 39 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 62 deletions(-) diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 5510f6fdce5..9d6a2c00d76 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -25,10 +25,6 @@ #include #include -#include -#include -#include - #include #include #include @@ -46,64 +42,6 @@ #include "devices.h" #include "generic.h" -/* - * This is the PXA2xx sched_clock implementation. This has a resolution - * of at least 308ns and a maximum value that depends on the value of - * CLOCK_TICK_RATE. - * - * The return value is guaranteed to be monotonic in that range as - * long as there is always less than 582 seconds between successive - * calls to this function. - */ -unsigned long long sched_clock(void) -{ - unsigned long long v = cnt32_to_63(OSCR); - /* Note: top bit ov v needs cleared unless multiplier is even. */ - -#if CLOCK_TICK_RATE == 3686400 - /* 1E9 / 3686400 => 78125 / 288, max value = 32025597s (370 days). */ - /* The <<1 is used to get rid of tick.hi top bit */ - v *= 78125<<1; - do_div(v, 288<<1); -#elif CLOCK_TICK_RATE == 3250000 - /* 1E9 / 3250000 => 4000 / 13, max value = 709490156s (8211 days) */ - v *= 4000; - do_div(v, 13); -#elif CLOCK_TICK_RATE == 3249600 - /* 1E9 / 3249600 => 625000 / 2031, max value = 4541295s (52 days) */ - v *= 625000; - do_div(v, 2031); -#else -#warning "consider fixing sched_clock for your value of CLOCK_TICK_RATE" - /* - * 96-bit math to perform tick * NSEC_PER_SEC / CLOCK_TICK_RATE for - * any value of CLOCK_TICK_RATE. Max value is in the 80 thousand - * years range and truncation to unsigned long long limits it to - * sched_clock's max range of ~584 years. This is nice but with - * higher computation cost. - */ - { - union { - unsigned long long val; - struct { unsigned long lo, hi; }; - } x; - unsigned long long y; - - x.val = v; - x.hi &= 0x7fffffff; - y = (unsigned long long)x.lo * NSEC_PER_SEC; - x.lo = y; - y = (y >> 32) + (unsigned long long)x.hi * NSEC_PER_SEC; - x.hi = do_div(y, CLOCK_TICK_RATE); - do_div(x.val, CLOCK_TICK_RATE); - x.hi += y; - v = x.val; - } -#endif - - return v; -} - /* * Handy function to set GPIO alternate functions */ diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 98d27e646b0..7916311547c 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -16,11 +16,48 @@ #include #include #include +#include +#include +#include #include #include #include +/* + * This is PXA's sched_clock implementation. This has a resolution + * of at least 308 ns and a maximum value of 208 days. + * + * The return value is guaranteed to be monotonic in that range as + * long as there is always less than 582 seconds between successive + * calls to sched_clock() which should always be the case in practice. + */ + +#define OSCR2NS_SCALE_FACTOR 10 + +static unsigned long oscr2ns_scale; + +static void __init set_oscr2ns_scale(unsigned long oscr_rate) +{ + unsigned long long v = 1000000000ULL << OSCR2NS_SCALE_FACTOR; + do_div(v, oscr_rate); + oscr2ns_scale = v; + /* + * We want an even value to automatically clear the top bit + * returned by cnt32_to_63() without an additional run time + * instruction. So if the LSB is 1 then round it up. + */ + if (oscr2ns_scale & 1) + oscr2ns_scale++; +} + +unsigned long long sched_clock(void) +{ + unsigned long long v = cnt32_to_63(OSCR); + return (v * oscr2ns_scale) >> OSCR2NS_SCALE_FACTOR; +} + + static irqreturn_t pxa_ost0_interrupt(int irq, void *dev_id) { @@ -152,6 +189,8 @@ static void __init pxa_timer_init(void) OIER = 0; OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; + set_oscr2ns_scale(CLOCK_TICK_RATE); + ckevt_pxa_osmr0.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); ckevt_pxa_osmr0.max_delta_ns = -- cgit v1.2.3-18-g5258 From 08197f6e3b262f4fb8b164c818d5e54b46c14711 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 1 Sep 2007 21:12:50 +0100 Subject: [ARM] pxa: make pxa timer initialisation select clock rate at runtime Rather than using the compile-time constant CLOCK_TICK_RATE, select the clock tick rate at run time. We organise the selection so that PXA3 automatically falls out with the right tick rate. Signed-off-by: Russell King --- arch/arm/mach-pxa/time.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 7916311547c..ec4286c7931 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -23,6 +23,7 @@ #include #include #include +#include /* * This is PXA's sched_clock implementation. This has a resolution @@ -186,20 +187,29 @@ static struct irqaction pxa_ost0_irq = { static void __init pxa_timer_init(void) { + unsigned long clock_tick_rate; + OIER = 0; OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; - set_oscr2ns_scale(CLOCK_TICK_RATE); + if (cpu_is_pxa21x() || cpu_is_pxa25x()) + clock_tick_rate = 3686400; + else if (machine_is_mainstone()) + clock_tick_rate = 3249600; + else + clock_tick_rate = 3250000; + + set_oscr2ns_scale(clock_tick_rate); ckevt_pxa_osmr0.mult = - div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); + div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); ckevt_pxa_osmr0.max_delta_ns = clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0); ckevt_pxa_osmr0.min_delta_ns = clockevent_delta2ns(MIN_OSCR_DELTA, &ckevt_pxa_osmr0) + 1; cksrc_pxa_oscr0.mult = - clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_pxa_oscr0.shift); + clocksource_hz2mult(clock_tick_rate, cksrc_pxa_oscr0.shift); setup_irq(IRQ_OST0, &pxa_ost0_irq); -- cgit v1.2.3-18-g5258 From e259a3aecbfb61981175ddc7fc02dd180da7d73e Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Aug 2007 09:47:41 +0100 Subject: [ARM] pxa: convert PXA serial drivers to use platform resources Signed-off-by: Russell King --- arch/arm/mach-pxa/generic.c | 59 +++++++++++++++++++ drivers/serial/pxa.c | 139 +++++++++++++++++++------------------------- 2 files changed, 120 insertions(+), 78 deletions(-) diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 9d6a2c00d76..98df63898d1 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -267,21 +267,80 @@ void __init set_pxa_fb_parent(struct device *parent_dev) pxa_device_fb.dev.parent = parent_dev; } +static struct resource pxa_resource_ffuart[] = { + { + .start = __PREG(FFUART), + .end = __PREG(FFUART) + 35, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_FFUART, + .end = IRQ_FFUART, + .flags = IORESOURCE_IRQ, + } +}; + struct platform_device pxa_device_ffuart= { .name = "pxa2xx-uart", .id = 0, + .resource = pxa_resource_ffuart, + .num_resources = ARRAY_SIZE(pxa_resource_ffuart), +}; + +static struct resource pxa_resource_btuart[] = { + { + .start = __PREG(BTUART), + .end = __PREG(BTUART) + 35, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_BTUART, + .end = IRQ_BTUART, + .flags = IORESOURCE_IRQ, + } }; + struct platform_device pxa_device_btuart = { .name = "pxa2xx-uart", .id = 1, + .resource = pxa_resource_btuart, + .num_resources = ARRAY_SIZE(pxa_resource_btuart), }; + +static struct resource pxa_resource_stuart[] = { + { + .start = __PREG(STUART), + .end = __PREG(STUART) + 35, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_STUART, + .end = IRQ_STUART, + .flags = IORESOURCE_IRQ, + } +}; + struct platform_device pxa_device_stuart = { .name = "pxa2xx-uart", .id = 2, + .resource = pxa_resource_stuart, + .num_resources = ARRAY_SIZE(pxa_resource_stuart), }; + +static struct resource pxa_resource_hwuart[] = { + { + .start = __PREG(HWUART), + .end = __PREG(HWUART) + 47, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_HWUART, + .end = IRQ_HWUART, + .flags = IORESOURCE_IRQ, + } +}; + struct platform_device pxa_device_hwuart = { .name = "pxa2xx-uart", .id = 3, + .resource = pxa_resource_hwuart, + .num_resources = ARRAY_SIZE(pxa_resource_hwuart), }; static struct resource pxai2c_resources[] = { diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index e9c6cb391a2..59889f6a86b 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -582,7 +582,7 @@ serial_pxa_type(struct uart_port *port) #ifdef CONFIG_SERIAL_PXA_CONSOLE -static struct uart_pxa_port serial_pxa_ports[]; +static struct uart_pxa_port *serial_pxa_ports[4]; static struct uart_driver serial_pxa_reg; #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) @@ -632,7 +632,7 @@ static void serial_pxa_console_putchar(struct uart_port *port, int ch) static void serial_pxa_console_write(struct console *co, const char *s, unsigned int count) { - struct uart_pxa_port *up = &serial_pxa_ports[co->index]; + struct uart_pxa_port *up = serial_pxa_ports[co->index]; unsigned int ier; /* @@ -662,7 +662,9 @@ serial_pxa_console_setup(struct console *co, char *options) if (co->index == -1 || co->index >= serial_pxa_reg.nr) co->index = 0; - up = &serial_pxa_ports[co->index]; + up = serial_pxa_ports[co->index]; + if (!up) + return -ENODEV; if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -680,15 +682,6 @@ static struct console serial_pxa_console = { .data = &serial_pxa_reg, }; -static int __init -serial_pxa_console_init(void) -{ - register_console(&serial_pxa_console); - return 0; -} - -console_initcall(serial_pxa_console_init); - #define PXA_CONSOLE &serial_pxa_console #else #define PXA_CONSOLE NULL @@ -714,73 +707,13 @@ struct uart_ops serial_pxa_pops = { .verify_port = serial_pxa_verify_port, }; -static struct uart_pxa_port serial_pxa_ports[] = { - { /* FFUART */ - .name = "FFUART", - .cken = CKEN_FFUART, - .port = { - .type = PORT_PXA, - .iotype = UPIO_MEM, - .membase = (void *)&FFUART, - .mapbase = __PREG(FFUART), - .irq = IRQ_FFUART, - .uartclk = 921600 * 16, - .fifosize = 64, - .ops = &serial_pxa_pops, - .line = 0, - }, - }, { /* BTUART */ - .name = "BTUART", - .cken = CKEN_BTUART, - .port = { - .type = PORT_PXA, - .iotype = UPIO_MEM, - .membase = (void *)&BTUART, - .mapbase = __PREG(BTUART), - .irq = IRQ_BTUART, - .uartclk = 921600 * 16, - .fifosize = 64, - .ops = &serial_pxa_pops, - .line = 1, - }, - }, { /* STUART */ - .name = "STUART", - .cken = CKEN_STUART, - .port = { - .type = PORT_PXA, - .iotype = UPIO_MEM, - .membase = (void *)&STUART, - .mapbase = __PREG(STUART), - .irq = IRQ_STUART, - .uartclk = 921600 * 16, - .fifosize = 64, - .ops = &serial_pxa_pops, - .line = 2, - }, - }, { /* HWUART */ - .name = "HWUART", - .cken = CKEN_HWUART, - .port = { - .type = PORT_PXA, - .iotype = UPIO_MEM, - .membase = (void *)&HWUART, - .mapbase = __PREG(HWUART), - .irq = IRQ_HWUART, - .uartclk = 921600 * 16, - .fifosize = 64, - .ops = &serial_pxa_pops, - .line = 3, - }, - } -}; - static struct uart_driver serial_pxa_reg = { .owner = THIS_MODULE, .driver_name = "PXA serial", .dev_name = "ttyS", .major = TTY_MAJOR, .minor = 64, - .nr = ARRAY_SIZE(serial_pxa_ports), + .nr = 4, .cons = PXA_CONSOLE, }; @@ -806,10 +739,60 @@ static int serial_pxa_resume(struct platform_device *dev) static int serial_pxa_probe(struct platform_device *dev) { - serial_pxa_ports[dev->id].port.dev = &dev->dev; - uart_add_one_port(&serial_pxa_reg, &serial_pxa_ports[dev->id].port); - platform_set_drvdata(dev, &serial_pxa_ports[dev->id]); + struct uart_pxa_port *sport; + struct resource *mmres, *irqres; + int ret; + + mmres = platform_get_resource(dev, IORESOURCE_MEM, 0); + irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0); + if (!mmres || !irqres) + return -ENODEV; + + sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL); + if (!sport) + return -ENOMEM; + + sport->port.type = PORT_PXA; + sport->port.iotype = UPIO_MEM; + sport->port.mapbase = mmres->start; + sport->port.irq = irqres->start; + sport->port.fifosize = 64; + sport->port.ops = &serial_pxa_pops; + sport->port.line = dev->id; + sport->port.dev = &dev->dev; + sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; + sport->port.uartclk = 921600 * 16; + + /* + * Is it worth keeping this? + */ + if (mmres->start == __PREG(FFUART)) + sport->name = "FFUART"; + else if (mmres->start == __PREG(BTUART)) + sport->name = "BTUART"; + else if (mmres->start == __PREG(STUART)) + sport->name = "STUART"; + else if (mmres->start == __PREG(HWUART)) + sport->name = "HWUART"; + else + sport->name = "???"; + + sport->port.membase = ioremap(mmres->start, mmres->end - mmres->start + 1); + if (!sport->port.membase) { + ret = -ENOMEM; + goto err_free; + } + + serial_pxa_ports[dev->id] = sport; + + uart_add_one_port(&serial_pxa_reg, &sport->port); + platform_set_drvdata(dev, sport); + return 0; + + err_free: + kfree(sport); + return ret; } static int serial_pxa_remove(struct platform_device *dev) @@ -818,8 +801,8 @@ static int serial_pxa_remove(struct platform_device *dev) platform_set_drvdata(dev, NULL); - if (sport) - uart_remove_one_port(&serial_pxa_reg, &sport->port); + uart_remove_one_port(&serial_pxa_reg, &sport->port); + kfree(sport); return 0; } -- cgit v1.2.3-18-g5258 From 15a4033354c68eb75e417ab60771f36212610820 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Aug 2007 10:07:44 +0100 Subject: [ARM] pxa: fix naming of memory/lcd/core clock functions Rename pxa25x and pxa27x memory/lcd/core clock functions, and select the correct version at run time. Signed-off-by: Russell King --- arch/arm/mach-pxa/generic.c | 38 ++++++++++++++++++++++++++++++++++++++ arch/arm/mach-pxa/generic.h | 18 ++++++++++++++++++ arch/arm/mach-pxa/pxa25x.c | 18 ++---------------- arch/arm/mach-pxa/pxa27x.c | 10 +++------- 4 files changed, 61 insertions(+), 23 deletions(-) diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 98df63898d1..ac2b1fc5bda 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -42,6 +42,44 @@ #include "devices.h" #include "generic.h" +/* + * Get the clock frequency as reflected by CCCR and the turbo flag. + * We assume these values have been applied via a fcs. + * If info is not 0 we also display the current settings. + */ +unsigned int get_clk_frequency_khz(int info) +{ + if (cpu_is_pxa21x() || cpu_is_pxa25x()) + return pxa25x_get_clk_frequency_khz(info); + else + return pxa27x_get_clk_frequency_khz(info); +} +EXPORT_SYMBOL(get_clk_frequency_khz); + +/* + * Return the current memory clock frequency in units of 10kHz + */ +unsigned int get_memclk_frequency_10khz(void) +{ + if (cpu_is_pxa21x() || cpu_is_pxa25x()) + return pxa25x_get_memclk_frequency_10khz(); + else + return pxa27x_get_memclk_frequency_10khz(); +} +EXPORT_SYMBOL(get_memclk_frequency_10khz); + +/* + * Return the current LCD clock frequency in units of 10kHz + */ +unsigned int get_lcdclk_frequency_10khz(void) +{ + if (cpu_is_pxa21x() || cpu_is_pxa25x()) + return pxa25x_get_memclk_frequency_10khz(); + else + return pxa27x_get_lcdclk_frequency_10khz(); +} +EXPORT_SYMBOL(get_lcdclk_frequency_10khz); + /* * Handy function to set GPIO alternate functions */ diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index 91ab2ad8b34..0a8a6f8a4f9 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -26,3 +26,21 @@ extern unsigned int get_clk_frequency_khz(int info); mi->bank[__nr].size = (__size), \ mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27) +#ifdef CONFIG_PXA25x +extern unsigned pxa25x_get_clk_frequency_khz(int); +extern unsigned pxa25x_get_memclk_frequency_10khz(void); +#else +#define pxa25x_get_clk_frequency_khz(x) (0) +#define pxa25x_get_memclk_frequency_10khz() (0) +#endif + +#ifdef CONFIG_PXA27x +extern unsigned pxa27x_get_clk_frequency_khz(int); +extern unsigned pxa27x_get_memclk_frequency_10khz(void); +extern unsigned pxa27x_get_lcdclk_frequency_10khz(void); +#else +#define pxa27x_get_clk_frequency_khz(x) (0) +#define pxa27x_get_memclk_frequency_10khz() (0) +#define pxa27x_get_lcdclk_frequency_10khz() (0) +#endif + diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 6dfcca72e90..bcf3f0a7846 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -53,7 +53,7 @@ static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 }; * We assume these values have been applied via a fcs. * If info is not 0 we also display the current settings. */ -unsigned int get_clk_frequency_khz(int info) +unsigned int pxa25x_get_clk_frequency_khz(int info) { unsigned long cccr, turbo; unsigned int l, L, m, M, n2, N; @@ -86,28 +86,14 @@ unsigned int get_clk_frequency_khz(int info) return (turbo & 1) ? (N/1000) : (M/1000); } -EXPORT_SYMBOL(get_clk_frequency_khz); - /* * Return the current memory clock frequency in units of 10kHz */ -unsigned int get_memclk_frequency_10khz(void) +unsigned int pxa25x_get_memclk_frequency_10khz(void) { return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000; } -EXPORT_SYMBOL(get_memclk_frequency_10khz); - -/* - * Return the current LCD clock frequency in units of 10kHz - */ -unsigned int get_lcdclk_frequency_10khz(void) -{ - return get_memclk_frequency_10khz(); -} - -EXPORT_SYMBOL(get_lcdclk_frequency_10khz); - #ifdef CONFIG_PM #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 203371ab19d..b3bbf3feef7 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -36,7 +36,7 @@ * We assume these values have been applied via a fcs. * If info is not 0 we also display the current settings. */ -unsigned int get_clk_frequency_khz( int info) +unsigned int pxa27x_get_clk_frequency_khz(int info) { unsigned long ccsr, clkcfg; unsigned int l, L, m, M, n2, N, S; @@ -79,7 +79,7 @@ unsigned int get_clk_frequency_khz( int info) * Return the current mem clock frequency in units of 10kHz as * reflected by CCCR[A], B, and L */ -unsigned int get_memclk_frequency_10khz(void) +unsigned int pxa27x_get_memclk_frequency_10khz(void) { unsigned long ccsr, clkcfg; unsigned int l, L, m, M; @@ -104,7 +104,7 @@ unsigned int get_memclk_frequency_10khz(void) /* * Return the current LCD clock frequency in units of 10kHz as */ -unsigned int get_lcdclk_frequency_10khz(void) +unsigned int pxa27x_get_lcdclk_frequency_10khz(void) { unsigned long ccsr; unsigned int l, L, k, K; @@ -120,10 +120,6 @@ unsigned int get_lcdclk_frequency_10khz(void) return (K / 10000); } -EXPORT_SYMBOL(get_clk_frequency_khz); -EXPORT_SYMBOL(get_memclk_frequency_10khz); -EXPORT_SYMBOL(get_lcdclk_frequency_10khz); - #ifdef CONFIG_PM #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x -- cgit v1.2.3-18-g5258 From 00dc4f949e7423769de1a160c590840534ea3a70 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Aug 2007 10:09:18 +0100 Subject: [ARM] pxa: make pxa27x devices globally visible Signed-off-by: Russell King --- arch/arm/mach-pxa/devices.h | 3 +++ arch/arm/mach-pxa/pxa27x.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h index 636fdb1c049..94c8d5cdd60 100644 --- a/arch/arm/mach-pxa/devices.h +++ b/arch/arm/mach-pxa/devices.h @@ -9,3 +9,6 @@ extern struct platform_device pxa_device_i2c; extern struct platform_device pxa_device_i2s; extern struct platform_device pxa_device_ficp; extern struct platform_device pxa_device_rtc; + +extern struct platform_device pxa27x_device_i2c_power; +extern struct platform_device pxa27x_device_ohci; diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index b3bbf3feef7..3710981b72d 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -282,7 +282,7 @@ static struct resource pxa27x_ohci_resources[] = { }, }; -static struct platform_device pxa27x_device_ohci = { +struct platform_device pxa27x_device_ohci = { .name = "pxa27x-ohci", .id = -1, .dev = { @@ -310,7 +310,7 @@ static struct resource i2c_power_resources[] = { }, }; -static struct platform_device pxa27x_device_i2c_power = { +struct platform_device pxa27x_device_i2c_power = { .name = "pxa2xx-i2c", .id = 1, .resource = i2c_power_resources, -- cgit v1.2.3-18-g5258 From a6dba20c5c7b3a18d69bcbd60a1d2ebc0536f0ce Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Aug 2007 10:18:02 +0100 Subject: [ARM] pxa: introduce clk support for PXA SoC clocks Signed-off-by: Russell King --- arch/arm/mach-pxa/clock.c | 79 +++++++++++++++++++++++++++++----------------- arch/arm/mach-pxa/clock.h | 43 +++++++++++++++++++++++++ arch/arm/mach-pxa/pxa25x.c | 38 ++++++++++++++++++++++ arch/arm/mach-pxa/pxa27x.c | 45 ++++++++++++++++++++++++++ 4 files changed, 176 insertions(+), 29 deletions(-) create mode 100644 arch/arm/mach-pxa/clock.h diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c index 34a31caa6f9..83ef5ecaf43 100644 --- a/arch/arm/mach-pxa/clock.c +++ b/arch/arm/mach-pxa/clock.c @@ -9,19 +9,15 @@ #include #include #include +#include +#include #include #include -struct clk { - struct list_head node; - unsigned long rate; - struct module *owner; - const char *name; - unsigned int enabled; - void (*enable)(void); - void (*disable)(void); -}; +#include "devices.h" +#include "generic.h" +#include "clock.h" static LIST_HEAD(clocks); static DEFINE_MUTEX(clocks_mutex); @@ -33,7 +29,8 @@ struct clk *clk_get(struct device *dev, const char *id) mutex_lock(&clocks_mutex); list_for_each_entry(p, &clocks, node) { - if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + if (strcmp(id, p->name) == 0 && + (p->dev == NULL || p->dev == dev)) { clk = p; break; } @@ -46,7 +43,6 @@ EXPORT_SYMBOL(clk_get); void clk_put(struct clk *clk) { - module_put(clk->owner); } EXPORT_SYMBOL(clk_put); @@ -56,8 +52,12 @@ int clk_enable(struct clk *clk) spin_lock_irqsave(&clocks_lock, flags); if (clk->enabled++ == 0) - clk->enable(); + clk->ops->enable(clk); spin_unlock_irqrestore(&clocks_lock, flags); + + if (clk->delay) + udelay(clk->delay); + return 0; } EXPORT_SYMBOL(clk_enable); @@ -70,54 +70,75 @@ void clk_disable(struct clk *clk) spin_lock_irqsave(&clocks_lock, flags); if (--clk->enabled == 0) - clk->disable(); + clk->ops->disable(clk); spin_unlock_irqrestore(&clocks_lock, flags); } EXPORT_SYMBOL(clk_disable); unsigned long clk_get_rate(struct clk *clk) { - return clk->rate; + unsigned long rate; + + rate = clk->rate; + if (clk->ops->getrate) + rate = clk->ops->getrate(clk); + + return rate; } EXPORT_SYMBOL(clk_get_rate); -static void clk_gpio27_enable(void) +static void clk_gpio27_enable(struct clk *clk) { pxa_gpio_mode(GPIO11_3_6MHz_MD); } -static void clk_gpio27_disable(void) +static void clk_gpio27_disable(struct clk *clk) { } -static struct clk clk_gpio27 = { - .name = "GPIO27_CLK", - .rate = 3686400, +static const struct clkops clk_gpio27_ops = { .enable = clk_gpio27_enable, .disable = clk_gpio27_disable, }; -int clk_register(struct clk *clk) + +void clk_cken_enable(struct clk *clk) { - mutex_lock(&clocks_mutex); - list_add(&clk->node, &clocks); - mutex_unlock(&clocks_mutex); - return 0; + CKEN |= 1 << clk->cken; } -EXPORT_SYMBOL(clk_register); -void clk_unregister(struct clk *clk) +void clk_cken_disable(struct clk *clk) { + CKEN &= ~(1 << clk->cken); +} + +const struct clkops clk_cken_ops = { + .enable = clk_cken_enable, + .disable = clk_cken_disable, +}; + +static struct clk common_clks[] = { + { + .name = "GPIO27_CLK", + .ops = &clk_gpio27_ops, + .rate = 3686400, + }, +}; + +void clks_register(struct clk *clks, size_t num) +{ + int i; + mutex_lock(&clocks_mutex); - list_del(&clk->node); + for (i = 0; i < num; i++) + list_add(&clks[i].node, &clocks); mutex_unlock(&clocks_mutex); } -EXPORT_SYMBOL(clk_unregister); static int __init clk_init(void) { - clk_register(&clk_gpio27); + clks_register(common_clks, ARRAY_SIZE(common_clks)); return 0; } arch_initcall(clk_init); diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h new file mode 100644 index 00000000000..bc6b77e1592 --- /dev/null +++ b/arch/arm/mach-pxa/clock.h @@ -0,0 +1,43 @@ +struct clk; + +struct clkops { + void (*enable)(struct clk *); + void (*disable)(struct clk *); + unsigned long (*getrate)(struct clk *); +}; + +struct clk { + struct list_head node; + const char *name; + struct device *dev; + const struct clkops *ops; + unsigned long rate; + unsigned int cken; + unsigned int delay; + unsigned int enabled; +}; + +#define INIT_CKEN(_name, _cken, _rate, _delay, _dev) \ + { \ + .name = _name, \ + .dev = _dev, \ + .ops = &clk_cken_ops, \ + .rate = _rate, \ + .cken = CKEN_##_cken, \ + .delay = _delay, \ + } + +#define INIT_CK(_name, _cken, _ops, _dev) \ + { \ + .name = _name, \ + .dev = _dev, \ + .ops = _ops, \ + .cken = CKEN_##_cken, \ + } + +extern const struct clkops clk_cken_ops; + +void clk_cken_enable(struct clk *clk); +void clk_cken_disable(struct clk *clk); + +void clks_register(struct clk *clks, size_t num); diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index bcf3f0a7846..62a770121bf 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -30,6 +30,7 @@ #include "generic.h" #include "devices.h" +#include "clock.h" /* * Various clock factors driven by the CCCR register. @@ -94,6 +95,41 @@ unsigned int pxa25x_get_memclk_frequency_10khz(void) return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000; } +static unsigned long clk_pxa25x_lcd_getrate(struct clk *clk) +{ + return pxa25x_get_memclk_frequency_10khz() * 10000; +} + +static const struct clkops clk_pxa25x_lcd_ops = { + .enable = clk_cken_enable, + .disable = clk_cken_disable, + .getrate = clk_pxa25x_lcd_getrate, +}; + +/* + * 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz) + * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz + * 147.456MHz -> UART 14.7456MHz, AC97 12.288MHz, I2S 5.672MHz (allegedly) + */ +static struct clk pxa25x_clks[] = { + INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev), + INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev), + INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev), + INIT_CKEN("UARTCLK", STUART, 14745600, 1, &pxa_device_stuart.dev), + INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev), + INIT_CKEN("UDCCLK", USB, 47923000, 5, &pxa_device_udc.dev), + INIT_CKEN("MMCCLK", MMC, 19169000, 0, &pxa_device_mci.dev), + INIT_CKEN("I2CCLK", I2C, 31949000, 0, &pxa_device_i2c.dev), + /* + INIT_CKEN("PWMCLK", PWM0, 3686400, 0, NULL), + INIT_CKEN("PWMCLK", PWM0, 3686400, 0, NULL), + INIT_CKEN("SSPCLK", SSP, 3686400, 0, NULL), + INIT_CKEN("I2SCLK", I2S, 14745600, 0, NULL), + INIT_CKEN("NSSPCLK", NSSP, 3686400, 0, NULL), + INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL), + */ +}; + #ifdef CONFIG_PM #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x @@ -215,6 +251,8 @@ static int __init pxa25x_init(void) int ret = 0; if (cpu_is_pxa21x() || cpu_is_pxa25x()) { + clks_register(pxa25x_clks, ARRAY_SIZE(pxa25x_clks)); + if ((ret = pxa_init_dma(16))) return ret; #ifdef CONFIG_PM diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 3710981b72d..433644edf79 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -27,6 +27,7 @@ #include "generic.h" #include "devices.h" +#include "clock.h" /* Crystal clock: 13MHz */ #define BASE_CLK 13000000 @@ -120,6 +121,48 @@ unsigned int pxa27x_get_lcdclk_frequency_10khz(void) return (K / 10000); } +static unsigned long clk_pxa27x_lcd_getrate(struct clk *clk) +{ + return pxa27x_get_lcdclk_frequency_10khz() * 10000; +} + +static const struct clkops clk_pxa27x_lcd_ops = { + .enable = clk_cken_enable, + .disable = clk_cken_disable, + .getrate = clk_pxa27x_lcd_getrate, +}; + +static struct clk pxa27x_clks[] = { + INIT_CK("LCDCLK", LCD, &clk_pxa27x_lcd_ops, &pxa_device_fb.dev), + INIT_CK("CAMCLK", CAMERA, &clk_pxa27x_lcd_ops, NULL), + + INIT_CKEN("UARTCLK", STUART, 14857000, 1, &pxa_device_stuart.dev), + INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev), + INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev), + + INIT_CKEN("I2SCLK", I2S, 14682000, 0, &pxa_device_i2s.dev), + INIT_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev), + INIT_CKEN("UDCCLK", USB, 48000000, 5, &pxa_device_udc.dev), + INIT_CKEN("MMCCLK", MMC, 19500000, 0, &pxa_device_mci.dev), + INIT_CKEN("FICPCLK", FICP, 48000000, 0, &pxa_device_ficp.dev), + + INIT_CKEN("USBCLK", USB, 48000000, 0, &pxa27x_device_ohci.dev), + INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev), + INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, NULL), + + /* + INIT_CKEN("PWMCLK", PWM0, 13000000, 0, NULL), + INIT_CKEN("SSPCLK", SSP1, 13000000, 0, NULL), + INIT_CKEN("SSPCLK", SSP2, 13000000, 0, NULL), + INIT_CKEN("SSPCLK", SSP3, 13000000, 0, NULL), + INIT_CKEN("MSLCLK", MSL, 48000000, 0, NULL), + INIT_CKEN("USIMCLK", USIM, 48000000, 0, NULL), + INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0, NULL), + INIT_CKEN("IMCLK", IM, 0, 0, NULL), + INIT_CKEN("MEMCLK", MEMC, 0, 0, NULL), + */ +}; + #ifdef CONFIG_PM #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x @@ -343,6 +386,8 @@ static int __init pxa27x_init(void) { int ret = 0; if (cpu_is_pxa27x()) { + clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks)); + if ((ret = pxa_init_dma(32))) return ret; #ifdef CONFIG_PM -- cgit v1.2.3-18-g5258 From 72e3524c0b591c30c3a2e2058dd78327ec99efed Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Aug 2007 10:18:42 +0100 Subject: [ARM] pxa: update pxafb to use clk support Signed-off-by: Russell King --- drivers/video/pxafb.c | 36 +++++++++++++++++++++++------------- drivers/video/pxafb.h | 1 + 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index a280a52f8ef..f9b12ab5964 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include @@ -506,15 +508,15 @@ static struct fb_ops pxafb_ops = { * * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below. */ -static inline unsigned int get_pcd(unsigned int pixclock) +static inline unsigned int get_pcd(struct pxafb_info *fbi, unsigned int pixclock) { unsigned long long pcd; /* FIXME: Need to take into account Double Pixel Clock mode - * (DPC) bit? or perhaps set it based on the various clock - * speeds */ - - pcd = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock; + * (DPC) bit? or perhaps set it based on the various clock + * speeds */ + pcd = (unsigned long long)(clk_get_rate(fbi->clk) / 10000); + pcd *= pixclock; do_div(pcd, 100000000 * 2); /* no need for this, since we should subtract 1 anyway. they cancel */ /* pcd += 1; */ /* make up for integer math truncations */ @@ -523,19 +525,21 @@ static inline unsigned int get_pcd(unsigned int pixclock) /* * Some touchscreens need hsync information from the video driver to - * function correctly. We export it here. + * function correctly. We export it here. Note that 'hsync_time' and + * the value returned from pxafb_get_hsync_time() is the *reciprocal* + * of the hsync period in seconds. */ static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd) { - unsigned long long htime; + unsigned long htime; if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) { fbi->hsync_time=0; return; } - htime = (unsigned long long)get_lcdclk_frequency_10khz() * 10000; - do_div(htime, pcd * fbi->fb.var.hsync_len); + htime = clk_get_rate(fbi->clk) / (pcd * fbi->fb.var.hsync_len); + fbi->hsync_time = htime; } @@ -560,7 +564,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info * { struct pxafb_lcd_reg new_regs; u_long flags; - u_int lines_per_panel, pcd = get_pcd(var->pixclock); + u_int lines_per_panel, pcd = get_pcd(fbi, var->pixclock); pr_debug("pxafb: Configuring PXA LCD\n"); @@ -803,7 +807,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi) pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); /* enable LCD controller clock */ - pxa_set_cken(CKEN_LCD, 1); + clk_enable(fbi->clk); /* Sequence from 11.7.10 */ LCCR3 = fbi->reg_lccr3; @@ -840,7 +844,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) remove_wait_queue(&fbi->ctrlr_wait, &wait); /* disable LCD controller clock */ - pxa_set_cken(CKEN_LCD, 0); + clk_disable(fbi->clk); } /* @@ -994,7 +998,7 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data) break; case CPUFREQ_POSTCHANGE: - pcd = get_pcd(fbi->fb.var.pixclock); + pcd = get_pcd(fbi, fbi->fb.var.pixclock); set_hsync_time(fbi, pcd); fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE); @@ -1119,6 +1123,12 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev) memset(fbi, 0, sizeof(struct pxafb_info)); fbi->dev = dev; + fbi->clk = clk_get(dev, "LCDCLK"); + if (IS_ERR(fbi->clk)) { + kfree(fbi); + return NULL; + } + strcpy(fbi->fb.fix.id, PXA_NAME); fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS; diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h index 7499a1c4bf7..f8605b807b0 100644 --- a/drivers/video/pxafb.h +++ b/drivers/video/pxafb.h @@ -40,6 +40,7 @@ struct pxafb_dma_descriptor { struct pxafb_info { struct fb_info fb; struct device *dev; + struct clk *clk; /* * These are the addresses we mapped -- cgit v1.2.3-18-g5258 From c3cef3f3c07bb98e023e4d5441e60538516a4741 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Aug 2007 10:19:10 +0100 Subject: [ARM] pxa: update pxa i2c driver to use clk support Signed-off-by: Russell King --- drivers/i2c/busses/i2c-pxa.c | 45 ++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index bb5466b27b5..00fad11733a 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -48,6 +50,7 @@ struct pxa_i2c { unsigned int slave_addr; struct i2c_adapter adap; + struct clk *clk; #ifdef CONFIG_I2C_PXA_SLAVE struct i2c_slave_client *slave; #endif @@ -869,6 +872,12 @@ static int i2c_pxa_probe(struct platform_device *dev) sprintf(i2c->adap.name, "pxa_i2c-i2c.%u", dev->id); + i2c->clk = clk_get(&dev->dev, "I2CCLK"); + if (IS_ERR(i2c->clk)) { + ret = PTR_ERR(i2c->clk); + goto eclk; + } + i2c->reg_base = ioremap(res->start, res_len(res)); if (!i2c->reg_base) { ret = -EIO; @@ -889,22 +898,19 @@ static int i2c_pxa_probe(struct platform_device *dev) } #endif + clk_enable(i2c->clk); +#ifdef CONFIG_PXA27x switch (dev->id) { case 0: -#ifdef CONFIG_PXA27x pxa_gpio_mode(GPIO117_I2CSCL_MD); pxa_gpio_mode(GPIO118_I2CSDA_MD); -#endif - pxa_set_cken(CKEN_I2C, 1); break; -#ifdef CONFIG_PXA27x case 1: local_irq_disable(); PCFR |= PCFR_PI2CEN; local_irq_enable(); - pxa_set_cken(CKEN_PWRI2C, 1); -#endif } +#endif ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED, i2c->adap.name, i2c); @@ -948,19 +954,18 @@ static int i2c_pxa_probe(struct platform_device *dev) eadapt: free_irq(irq, i2c); ereqirq: - switch (dev->id) { - case 0: - pxa_set_cken(CKEN_I2C, 0); - break; + clk_disable(i2c->clk); + #ifdef CONFIG_PXA27x - case 1: - pxa_set_cken(CKEN_PWRI2C, 0); + if (dev->id == 1) { local_irq_disable(); PCFR &= ~PCFR_PI2CEN; local_irq_enable(); -#endif } +#endif eremap: + clk_put(i2c->clk); +eclk: kfree(i2c); emalloc: release_mem_region(res->start, res_len(res)); @@ -975,18 +980,18 @@ static int i2c_pxa_remove(struct platform_device *dev) i2c_del_adapter(&i2c->adap); free_irq(i2c->irq, i2c); - switch (dev->id) { - case 0: - pxa_set_cken(CKEN_I2C, 0); - break; + + clk_disable(i2c->clk); + clk_put(i2c->clk); + #ifdef CONFIG_PXA27x - case 1: - pxa_set_cken(CKEN_PWRI2C, 0); + if (dev->id == 1) { local_irq_disable(); PCFR &= ~PCFR_PI2CEN; local_irq_enable(); -#endif } +#endif + release_mem_region(i2c->iobase, i2c->iosize); kfree(i2c); -- cgit v1.2.3-18-g5258 From 22d8a73a8b39ef236c80ea73704884f7a7862193 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Aug 2007 10:19:39 +0100 Subject: [ARM] pxa: update pxa27x keypad driver to use clk support Signed-off-by: Russell King --- drivers/input/keyboard/pxa27x_keyboard.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c index ebe5eacf299..b7061aa3881 100644 --- a/drivers/input/keyboard/pxa27x_keyboard.c +++ b/drivers/input/keyboard/pxa27x_keyboard.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -40,6 +42,8 @@ col/2 == 2 ? KPASMKP2 : KPASMKP3) #define KPASMKPx_MKC(row, col) (1 << (row + 16 * (col % 2))) +static struct clk *pxakbd_clk; + static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id) { struct platform_device *pdev = dev_id; @@ -104,7 +108,7 @@ static int pxakbd_open(struct input_dev *dev) KPREC = 0x7F; /* Enable unit clock */ - pxa_set_cken(CKEN_KEYPAD, 1); + clk_enable(pxakbd_clk); return 0; } @@ -112,7 +116,7 @@ static int pxakbd_open(struct input_dev *dev) static void pxakbd_close(struct input_dev *dev) { /* Disable clock unit */ - pxa_set_cken(CKEN_KEYPAD, 0); + clk_disable(pxakbd_clk); } #ifdef CONFIG_PM @@ -140,7 +144,8 @@ static int pxakbd_resume(struct platform_device *pdev) KPREC = pdata->reg_kprec; /* Enable unit clock */ - pxa_set_cken(CKEN_KEYPAD, 1); + clk_disable(pxakbd_clk); + clk_enable(pxakbd_clk); } mutex_unlock(&input_dev->mutex); @@ -158,11 +163,18 @@ static int __devinit pxakbd_probe(struct platform_device *pdev) struct input_dev *input_dev; int i, row, col, error; + pxakbd_clk = clk_get(&pdev->dev, "KBDCLK"); + if (IS_ERR(pxakbd_clk)) { + error = PTR_ERR(pxakbd_clk); + goto err_clk; + } + /* Create and register the input driver. */ input_dev = input_allocate_device(); if (!input_dev) { printk(KERN_ERR "Cannot request keypad device\n"); - return -ENOMEM; + error = -ENOMEM; + goto err_alloc; } input_dev->name = DRIVER_NAME; @@ -185,7 +197,6 @@ static int __devinit pxakbd_probe(struct platform_device *pdev) DRIVER_NAME, pdev); if (error) { printk(KERN_ERR "Cannot request keypad IRQ\n"); - pxa_set_cken(CKEN_KEYPAD, 0); goto err_free_dev; } @@ -217,6 +228,9 @@ static int __devinit pxakbd_probe(struct platform_device *pdev) free_irq(IRQ_KEYPAD, pdev); err_free_dev: input_free_device(input_dev); + err_alloc: + clk_put(pxakbd_clk); + err_clk: return error; } @@ -226,6 +240,7 @@ static int __devexit pxakbd_remove(struct platform_device *pdev) input_unregister_device(input_dev); free_irq(IRQ_KEYPAD, pdev); + clk_put(pxakbd_clk); platform_set_drvdata(pdev, NULL); return 0; -- cgit v1.2.3-18-g5258 From ebebd9b0a1463d5de89017ad59a6b9cd4044687f Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Aug 2007 10:20:03 +0100 Subject: [ARM] pxa: update PXA MMC interface driver to use clk support Signed-off-by: Russell King --- drivers/mmc/host/pxamci.c | 43 ++++++++++++++++++++++++++++++++++++------- drivers/mmc/host/pxamci.h | 14 -------------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 657901eecfc..0601e01aa2c 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -44,6 +46,8 @@ struct pxamci_host { spinlock_t lock; struct resource *res; void __iomem *base; + struct clk *clk; + unsigned long clkrate; int irq; int dma; unsigned int clkrt; @@ -119,7 +123,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) writel(nob, host->base + MMC_NOB); writel(data->blksz, host->base + MMC_BLKLEN); - clks = (unsigned long long)data->timeout_ns * CLOCKRATE; + clks = (unsigned long long)data->timeout_ns * host->clkrate; do_div(clks, 1000000000UL); timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt); writel((timeout + 255) / 256, host->base + MMC_RDTO); @@ -365,18 +369,25 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) struct pxamci_host *host = mmc_priv(mmc); if (ios->clock) { - unsigned int clk = CLOCKRATE / ios->clock; - if (CLOCKRATE / clk > ios->clock) + unsigned long rate = host->clkrate; + unsigned int clk = rate / ios->clock; + + /* + * clk might result in a lower divisor than we + * desire. check for that condition and adjust + * as appropriate. + */ + if (rate / clk > ios->clock) clk <<= 1; host->clkrt = fls(clk) - 1; - pxa_set_cken(CKEN_MMC, 1); + clk_enable(host->clk); /* * we write clkrt on the next command */ } else { pxamci_stop_clock(host); - pxa_set_cken(CKEN_MMC, 0); + clk_disable(host->clk); } if (host->power_mode != ios->power_mode) { @@ -462,8 +473,6 @@ static int pxamci_probe(struct platform_device *pdev) } mmc->ops = &pxamci_ops; - mmc->f_min = CLOCKRATE_MIN; - mmc->f_max = CLOCKRATE_MAX; /* * We can do SG-DMA, but we don't because we never know how much @@ -490,6 +499,22 @@ static int pxamci_probe(struct platform_device *pdev) host->mmc = mmc; host->dma = -1; host->pdata = pdev->dev.platform_data; + + host->clk = clk_get(&pdev->dev, "MMCCLK"); + if (IS_ERR(host->clk)) { + ret = PTR_ERR(host->clk); + host->clk = NULL; + goto out; + } + + host->clkrate = clk_get_rate(host->clk); + + /* + * Calculate minimum clock rate, rounding up. + */ + mmc->f_min = (host->clkrate + 63) / 64; + mmc->f_max = host->clkrate; + mmc->ocr_avail = host->pdata ? host->pdata->ocr_mask : MMC_VDD_32_33|MMC_VDD_33_34; @@ -554,6 +579,8 @@ static int pxamci_probe(struct platform_device *pdev) iounmap(host->base); if (host->sg_cpu) dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); + if (host->clk) + clk_put(host->clk); } if (mmc) mmc_free_host(mmc); @@ -588,6 +615,8 @@ static int pxamci_remove(struct platform_device *pdev) iounmap(host->base); dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); + clk_put(host->clk); + release_resource(host->res); mmc_free_host(mmc); diff --git a/drivers/mmc/host/pxamci.h b/drivers/mmc/host/pxamci.h index 3153e779d46..748c7706f23 100644 --- a/drivers/mmc/host/pxamci.h +++ b/drivers/mmc/host/pxamci.h @@ -88,17 +88,3 @@ #define MMC_RXFIFO 0x0040 /* 8 bit */ #define MMC_TXFIFO 0x0044 /* 8 bit */ - -/* - * The base MMC clock rate - */ -#ifdef CONFIG_PXA27x -#define CLOCKRATE_MIN 304688 -#define CLOCKRATE_MAX 19500000 -#else -#define CLOCKRATE_MIN 312500 -#define CLOCKRATE_MAX 20000000 -#endif - -#define CLOCKRATE CLOCKRATE_MAX - -- cgit v1.2.3-18-g5258 From b049bd9de4959dd9e4b586d14b6de450a52c6f1f Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Aug 2007 10:28:15 +0100 Subject: [ARM] pxa: update pxa serial driver to use clk support Signed-off-by: Russell King --- drivers/serial/pxa.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 59889f6a86b..af3a011b2b2 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -55,7 +56,7 @@ struct uart_pxa_port { unsigned char lcr; unsigned char mcr; unsigned int lsr_break_flag; - unsigned int cken; + struct clk *clk; char *name; }; @@ -351,6 +352,8 @@ static int serial_pxa_startup(struct uart_port *port) else up->mcr = 0; + up->port.uartclk = clk_get_rate(up->clk); + /* * Allocate the IRQ */ @@ -546,9 +549,11 @@ serial_pxa_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; - pxa_set_cken(up->cken, !state); + if (!state) - udelay(1); + clk_enable(up->clk); + else + clk_disable(up->clk); } static void serial_pxa_release_port(struct uart_port *port) @@ -635,6 +640,8 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) struct uart_pxa_port *up = serial_pxa_ports[co->index]; unsigned int ier; + clk_enable(up->clk); + /* * First save the IER then disable the interrupts */ @@ -649,6 +656,8 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) */ wait_for_xmitr(up); serial_out(up, UART_IER, ier); + + clk_disable(up->clk); } static int __init @@ -752,6 +761,12 @@ static int serial_pxa_probe(struct platform_device *dev) if (!sport) return -ENOMEM; + sport->clk = clk_get(&dev->dev, "UARTCLK"); + if (IS_ERR(sport->clk)) { + ret = PTR_ERR(sport->clk); + goto err_free; + } + sport->port.type = PORT_PXA; sport->port.iotype = UPIO_MEM; sport->port.mapbase = mmres->start; @@ -761,7 +776,7 @@ static int serial_pxa_probe(struct platform_device *dev) sport->port.line = dev->id; sport->port.dev = &dev->dev; sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; - sport->port.uartclk = 921600 * 16; + sport->port.uartclk = clk_get_rate(sport->clk); /* * Is it worth keeping this? @@ -780,7 +795,7 @@ static int serial_pxa_probe(struct platform_device *dev) sport->port.membase = ioremap(mmres->start, mmres->end - mmres->start + 1); if (!sport->port.membase) { ret = -ENOMEM; - goto err_free; + goto err_clk; } serial_pxa_ports[dev->id] = sport; @@ -790,6 +805,8 @@ static int serial_pxa_probe(struct platform_device *dev) return 0; + err_clk: + clk_put(sport->clk); err_free: kfree(sport); return ret; @@ -802,6 +819,7 @@ static int serial_pxa_remove(struct platform_device *dev) platform_set_drvdata(dev, NULL); uart_remove_one_port(&serial_pxa_reg, &sport->port); + clk_put(sport->clk); kfree(sport); return 0; -- cgit v1.2.3-18-g5258 From 6549e6c9575c897514b183071a2b5d839cef9469 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Aug 2007 10:33:35 +0100 Subject: [ARM] pxa: update PXA UDC driver to use clk support Note: this produces a WARN() dump. Signed-off-by: Russell King --- drivers/usb/gadget/pxa2xx_udc.c | 68 +++++++++++++++++++++++++---------------- drivers/usb/gadget/pxa2xx_udc.h | 1 + 2 files changed, 43 insertions(+), 26 deletions(-) diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 1407ad1c812..90d0d086b9b 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include @@ -1157,7 +1159,7 @@ static void udc_disable(struct pxa2xx_udc *dev) #ifdef CONFIG_ARCH_PXA /* Disable clock for USB device */ - pxa_set_cken(CKEN_USB, 0); + clk_disable(dev->clk); #endif ep0_idle (dev); @@ -1202,8 +1204,7 @@ static void udc_enable (struct pxa2xx_udc *dev) #ifdef CONFIG_ARCH_PXA /* Enable clock for USB device */ - pxa_set_cken(CKEN_USB, 1); - udelay(5); + clk_enable(dev->clk); #endif /* try to clear these bits before we enable the udc */ @@ -2137,6 +2138,14 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) if (irq < 0) return -ENODEV; +#ifdef CONFIG_ARCH_PXA + dev->clk = clk_get(&pdev->dev, "UDCCLK"); + if (IS_ERR(dev->clk)) { + retval = PTR_ERR(dev->clk); + goto err_clk; + } +#endif + pr_debug("%s: IRQ %d%s%s\n", driver_name, irq, dev->has_cfr ? "" : " (!cfr)", SIZE_STR "(pio)" @@ -2152,11 +2161,10 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "can't get vbus gpio %d, err: %d\n", dev->mach->gpio_vbus, retval); - return -EBUSY; + goto err_gpio_vbus; } gpio_direction_input(dev->mach->gpio_vbus); vbus_irq = gpio_to_irq(dev->mach->gpio_vbus); - set_irq_type(vbus_irq, IRQT_BOTHEDGE); } else vbus_irq = 0; @@ -2166,9 +2174,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "can't get pullup gpio %d, err: %d\n", dev->mach->gpio_pullup, retval); - if (dev->mach->gpio_vbus) - gpio_free(dev->mach->gpio_vbus); - return -EBUSY; + goto err_gpio_pullup; } gpio_direction_output(dev->mach->gpio_pullup, 0); } @@ -2195,11 +2201,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) if (retval != 0) { printk(KERN_ERR "%s: can't get irq %d, err %d\n", driver_name, irq, retval); - if (dev->mach->gpio_pullup) - gpio_free(dev->mach->gpio_pullup); - if (dev->mach->gpio_vbus) - gpio_free(dev->mach->gpio_vbus); - return -EBUSY; + goto err_irq1; } dev->got_irq = 1; @@ -2213,12 +2215,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) printk(KERN_ERR "%s: can't get irq %i, err %d\n", driver_name, LUBBOCK_USB_DISC_IRQ, retval); lubbock_fail0: - free_irq(irq, dev); - if (dev->mach->gpio_pullup) - gpio_free(dev->mach->gpio_pullup); - if (dev->mach->gpio_vbus) - gpio_free(dev->mach->gpio_vbus); - return -EBUSY; + goto err_irq_lub; } retval = request_irq(LUBBOCK_USB_IRQ, lubbock_vbus_irq, @@ -2234,22 +2231,37 @@ lubbock_fail0: #endif if (vbus_irq) { retval = request_irq(vbus_irq, udc_vbus_irq, - IRQF_DISABLED | IRQF_SAMPLE_RANDOM, + IRQF_DISABLED | IRQF_SAMPLE_RANDOM | + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, driver_name, dev); if (retval != 0) { printk(KERN_ERR "%s: can't get irq %i, err %d\n", driver_name, vbus_irq, retval); - free_irq(irq, dev); - if (dev->mach->gpio_pullup) - gpio_free(dev->mach->gpio_pullup); - if (dev->mach->gpio_vbus) - gpio_free(dev->mach->gpio_vbus); - return -EBUSY; + goto err_vbus_irq; } } create_proc_files(); return 0; + + err_vbus_irq: +#ifdef CONFIG_ARCH_LUBBOCK + free_irq(LUBBOCK_USB_DISC_IRQ, dev); + err_irq_lub: +#endif + free_irq(irq, dev); + err_irq1: + if (dev->mach->gpio_pullup) + gpio_free(dev->mach->gpio_pullup); + err_gpio_pullup: + if (dev->mach->gpio_vbus) + gpio_free(dev->mach->gpio_vbus); + err_gpio_vbus: +#ifdef CONFIG_ARCH_PXA + clk_put(dev->clk); + err_clk: +#endif + return retval; } static void pxa2xx_udc_shutdown(struct platform_device *_dev) @@ -2284,6 +2296,10 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) if (dev->mach->gpio_pullup) gpio_free(dev->mach->gpio_pullup); +#ifdef CONFIG_ARCH_PXA + clk_put(dev->clk); +#endif + platform_set_drvdata(pdev, NULL); the_controller = NULL; return 0; diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h index 0e5d0e6fb0e..1db46d70577 100644 --- a/drivers/usb/gadget/pxa2xx_udc.h +++ b/drivers/usb/gadget/pxa2xx_udc.h @@ -125,6 +125,7 @@ struct pxa2xx_udc { struct timer_list timer; struct device *dev; + struct clk *clk; struct pxa2xx_udc_mach_info *mach; u64 dma_mask; struct pxa2xx_ep ep [PXA_UDC_NUM_ENDPOINTS]; -- cgit v1.2.3-18-g5258 From 435b6e94b88af96c3f5b5798c087978c3793400c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 2 Sep 2007 17:08:42 +0100 Subject: [ARM] pxa: Make STUART and FICP clocks available Signed-off-by: Russell King --- arch/arm/mach-pxa/pxa25x.c | 4 ++-- arch/arm/mach-pxa/pxa27x.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 62a770121bf..ef40c049d9e 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -115,8 +115,8 @@ static struct clk pxa25x_clks[] = { INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev), INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev), INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev), - INIT_CKEN("UARTCLK", STUART, 14745600, 1, &pxa_device_stuart.dev), INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev), + INIT_CKEN("UARTCLK", STUART, 14745600, 1, NULL), INIT_CKEN("UDCCLK", USB, 47923000, 5, &pxa_device_udc.dev), INIT_CKEN("MMCCLK", MMC, 19169000, 0, &pxa_device_mci.dev), INIT_CKEN("I2CCLK", I2C, 31949000, 0, &pxa_device_i2c.dev), @@ -126,8 +126,8 @@ static struct clk pxa25x_clks[] = { INIT_CKEN("SSPCLK", SSP, 3686400, 0, NULL), INIT_CKEN("I2SCLK", I2S, 14745600, 0, NULL), INIT_CKEN("NSSPCLK", NSSP, 3686400, 0, NULL), - INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL), */ + INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL), }; #ifdef CONFIG_PM diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 433644edf79..f7762bf1862 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -136,9 +136,9 @@ static struct clk pxa27x_clks[] = { INIT_CK("LCDCLK", LCD, &clk_pxa27x_lcd_ops, &pxa_device_fb.dev), INIT_CK("CAMCLK", CAMERA, &clk_pxa27x_lcd_ops, NULL), - INIT_CKEN("UARTCLK", STUART, 14857000, 1, &pxa_device_stuart.dev), INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev), INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev), + INIT_CKEN("UARTCLK", STUART, 14857000, 1, NULL), INIT_CKEN("I2SCLK", I2S, 14682000, 0, &pxa_device_i2s.dev), INIT_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev), -- cgit v1.2.3-18-g5258 From 82d553c67deef92c6c84ecb70afc56e99863060c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 2 Sep 2007 17:09:23 +0100 Subject: [ARM] pxa: update pxa irda driver to use clk support Signed-off-by: Russell King --- drivers/net/irda/pxaficp_ir.c | 51 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index 55ff0fbe525..8c09344f58d 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -87,8 +88,30 @@ struct pxa_irda { struct device *dev; struct pxaficp_platform_data *pdata; + struct clk *fir_clk; + struct clk *sir_clk; + struct clk *cur_clk; }; +static inline void pxa_irda_disable_clk(struct pxa_irda *si) +{ + if (si->cur_clk) + clk_disable(si->cur_clk); + si->cur_clk = NULL; +} + +static inline void pxa_irda_enable_firclk(struct pxa_irda *si) +{ + si->cur_clk = si->fir_clk; + clk_enable(si->fir_clk); +} + +static inline void pxa_irda_enable_sirclk(struct pxa_irda *si) +{ + si->cur_clk = si->sir_clk; + clk_enable(si->sir_clk); +} + #define IS_FIR(si) ((si)->speed >= 4000000) #define IRDA_FRAME_SIZE_LIMIT 2047 @@ -134,7 +157,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) DCSR(si->rxdma) &= ~DCSR_RUN; /* disable FICP */ ICCR0 = 0; - pxa_set_cken(CKEN_FICP, 0); + pxa_irda_disable_clk(si); /* set board transceiver to SIR mode */ si->pdata->transceiver_mode(si->dev, IR_SIRMODE); @@ -144,7 +167,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) pxa_gpio_mode(GPIO47_STTXD_MD); /* enable the STUART clock */ - pxa_set_cken(CKEN_STUART, 1); + pxa_irda_enable_sirclk(si); } /* disable STUART first */ @@ -169,7 +192,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) /* disable STUART */ STIER = 0; STISR = 0; - pxa_set_cken(CKEN_STUART, 0); + pxa_irda_disable_clk(si); /* disable FICP first */ ICCR0 = 0; @@ -182,7 +205,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) pxa_gpio_mode(GPIO47_ICPTXD_MD); /* enable the FICP clock */ - pxa_set_cken(CKEN_FICP, 1); + pxa_irda_enable_firclk(si); si->speed = speed; pxa_irda_fir_dma_rx_start(si); @@ -592,16 +615,15 @@ static void pxa_irda_shutdown(struct pxa_irda *si) STIER = 0; /* disable STUART SIR mode */ STISR = 0; - /* disable the STUART clock */ - pxa_set_cken(CKEN_STUART, 0); /* disable DMA */ DCSR(si->txdma) &= ~DCSR_RUN; DCSR(si->rxdma) &= ~DCSR_RUN; /* disable FICP */ ICCR0 = 0; - /* disable the FICP clock */ - pxa_set_cken(CKEN_FICP, 0); + + /* disable the STUART or FICP clocks */ + pxa_irda_disable_clk(si); DRCMR17 = 0; DRCMR18 = 0; @@ -792,6 +814,13 @@ static int pxa_irda_probe(struct platform_device *pdev) si->dev = &pdev->dev; si->pdata = pdev->dev.platform_data; + si->sir_clk = clk_get(&pdev->dev, "UARTCLK"); + si->fir_clk = clk_get(&pdev->dev, "FICPCLK"); + if (IS_ERR(si->sir_clk) || IS_ERR(si->fir_clk)) { + err = PTR_ERR(IS_ERR(si->sir_clk) ? si->sir_clk : si->fir_clk); + goto err_mem_4; + } + /* * Initialise the SIR buffers */ @@ -831,6 +860,10 @@ static int pxa_irda_probe(struct platform_device *pdev) err_mem_5: kfree(si->rx_buff.head); err_mem_4: + if (si->sir_clk && !IS_ERR(si->sir_clk)) + clk_put(si->sir_clk); + if (si->fir_clk && !IS_ERR(si->fir_clk)) + clk_put(si->fir_clk); free_netdev(dev); err_mem_3: release_mem_region(__PREG(FICP), 0x1c); @@ -850,6 +883,8 @@ static int pxa_irda_remove(struct platform_device *_dev) unregister_netdev(dev); kfree(si->tx_buff.head); kfree(si->rx_buff.head); + clk_put(si->fir_clk); + clk_put(si->sir_clk); free_netdev(dev); } -- cgit v1.2.3-18-g5258 From a88a447d44648f1dfba4c40b3f4b6f75597150ed Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Aug 2007 10:34:37 +0100 Subject: [ARM] pxa: remove get_lcdclk_frequency_10khz() get_lcdclk_frequency_10khz() is now redundant, remove it. Hide pxa27x_get_lcdclk_frequency_10khz() from public view. Signed-off-by: Russell King --- arch/arm/mach-pxa/generic.c | 12 ------------ arch/arm/mach-pxa/generic.h | 2 -- arch/arm/mach-pxa/pxa27x.c | 2 +- include/asm-arm/arch-pxa/hardware.h | 1 - 4 files changed, 1 insertion(+), 16 deletions(-) diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index ac2b1fc5bda..2f0cc1c4995 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -68,18 +68,6 @@ unsigned int get_memclk_frequency_10khz(void) } EXPORT_SYMBOL(get_memclk_frequency_10khz); -/* - * Return the current LCD clock frequency in units of 10kHz - */ -unsigned int get_lcdclk_frequency_10khz(void) -{ - if (cpu_is_pxa21x() || cpu_is_pxa25x()) - return pxa25x_get_memclk_frequency_10khz(); - else - return pxa27x_get_lcdclk_frequency_10khz(); -} -EXPORT_SYMBOL(get_lcdclk_frequency_10khz); - /* * Handy function to set GPIO alternate functions */ diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index 0a8a6f8a4f9..5b11741cccf 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -37,10 +37,8 @@ extern unsigned pxa25x_get_memclk_frequency_10khz(void); #ifdef CONFIG_PXA27x extern unsigned pxa27x_get_clk_frequency_khz(int); extern unsigned pxa27x_get_memclk_frequency_10khz(void); -extern unsigned pxa27x_get_lcdclk_frequency_10khz(void); #else #define pxa27x_get_clk_frequency_khz(x) (0) #define pxa27x_get_memclk_frequency_10khz() (0) -#define pxa27x_get_lcdclk_frequency_10khz() (0) #endif diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index f7762bf1862..d193755afb2 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -105,7 +105,7 @@ unsigned int pxa27x_get_memclk_frequency_10khz(void) /* * Return the current LCD clock frequency in units of 10kHz as */ -unsigned int pxa27x_get_lcdclk_frequency_10khz(void) +static unsigned int pxa27x_get_lcdclk_frequency_10khz(void) { unsigned long ccsr; unsigned int l, L, k, K; diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h index 38612174641..68e7b430ac8 100644 --- a/include/asm-arm/arch-pxa/hardware.h +++ b/include/asm-arm/arch-pxa/hardware.h @@ -122,7 +122,6 @@ extern void pxa_set_cken(int clock, int enable); * return current memory and LCD clock frequency in units of 10kHz */ extern unsigned int get_memclk_frequency_10khz(void); -extern unsigned int get_lcdclk_frequency_10khz(void); #endif -- cgit v1.2.3-18-g5258 From a7073b8b47651ce2ed27564ed8395eff81120c58 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Sep 2007 09:33:55 +0100 Subject: [ARM] pxa: mark pxa_set_cken deprecated Allow the generic clock support code to fiddle with the CKEN register and mark pxa_set_cken() deprecated. Signed-off-by: Russell King --- arch/arm/mach-pxa/generic.c | 4 ++-- include/asm-arm/arch-pxa/hardware.h | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 2f0cc1c4995..1c5413fc6e7 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -123,7 +123,7 @@ EXPORT_SYMBOL(pxa_gpio_set_value); /* * Routine to safely enable or disable a clock in the CKEN */ -void pxa_set_cken(int clock, int enable) +void __pxa_set_cken(int clock, int enable) { unsigned long flags; local_irq_save(flags); @@ -136,7 +136,7 @@ void pxa_set_cken(int clock, int enable) local_irq_restore(flags); } -EXPORT_SYMBOL(pxa_set_cken); +EXPORT_SYMBOL(__pxa_set_cken); /* * Intel PXA2xx internal register mapping. diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h index 68e7b430ac8..538a34e39e9 100644 --- a/include/asm-arm/arch-pxa/hardware.h +++ b/include/asm-arm/arch-pxa/hardware.h @@ -116,7 +116,11 @@ extern void pxa_gpio_set_value(unsigned gpio, int value); /* * Routine to enable or disable CKEN */ -extern void pxa_set_cken(int cl