diff options
Diffstat (limited to 'arch/arm/mach-pnx4008')
-rw-r--r-- | arch/arm/mach-pnx4008/clock.c | 173 | ||||
-rw-r--r-- | arch/arm/mach-pnx4008/clock.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-pnx4008/i2c.c | 108 | ||||
-rw-r--r-- | arch/arm/mach-pnx4008/include/mach/clkdev.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-pnx4008/include/mach/timex.h | 54 | ||||
-rw-r--r-- | arch/arm/mach-pnx4008/pm.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-pnx4008/time.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-pnx4008/time.h | 70 |
8 files changed, 181 insertions, 241 deletions
diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c index 898c0e88acbc..9d1975fa4d9f 100644 --- a/arch/arm/mach-pnx4008/clock.c +++ b/arch/arm/mach-pnx4008/clock.c @@ -22,8 +22,9 @@ #include <linux/delay.h> #include <linux/io.h> -#include <mach/hardware.h> +#include <asm/clkdev.h> +#include <mach/hardware.h> #include <mach/clock.h> #include "clock.h" @@ -56,18 +57,19 @@ static void propagate_rate(struct clk *clk) } } -static inline void clk_reg_disable(struct clk *clk) +static void clk_reg_disable(struct clk *clk) { if (clk->enable_reg) __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_shift), clk->enable_reg); } -static inline void clk_reg_enable(struct clk *clk) +static int clk_reg_enable(struct clk *clk) { if (clk->enable_reg) __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_shift), clk->enable_reg); + return 0; } static inline void clk_reg_disable1(struct clk *clk) @@ -636,31 +638,34 @@ static struct clk flash_ck = { static struct clk i2c0_ck = { .name = "i2c0_ck", .parent = &per_ck, - .flags = NEEDS_INITIALIZATION, - .round_rate = &on_off_round_rate, - .set_rate = &on_off_set_rate, + .flags = NEEDS_INITIALIZATION | FIXED_RATE, .enable_shift = 0, .enable_reg = I2CCLKCTRL_REG, + .rate = 13000000, + .enable = clk_reg_enable, + .disable = clk_reg_disable, }; static struct clk i2c1_ck = { .name = "i2c1_ck", .parent = &per_ck, - .flags = NEEDS_INITIALIZATION, - .round_rate = &on_off_round_rate, - .set_rate = &on_off_set_rate, + .flags = NEEDS_INITIALIZATION | FIXED_RATE, .enable_shift = 1, .enable_reg = I2CCLKCTRL_REG, + .rate = 13000000, + .enable = clk_reg_enable, + .disable = clk_reg_disable, }; static struct clk i2c2_ck = { .name = "i2c2_ck", .parent = &per_ck, - .flags = NEEDS_INITIALIZATION, - .round_rate = &on_off_round_rate, - .set_rate = &on_off_set_rate, + .flags = NEEDS_INITIALIZATION | FIXED_RATE, .enable_shift = 2, .enable_reg = USB_OTG_CLKCTRL_REG, + .rate = 13000000, + .enable = clk_reg_enable, + .disable = clk_reg_disable, }; static struct clk spi0_ck = { @@ -738,16 +743,16 @@ static struct clk wdt_ck = { .name = "wdt_ck", .parent = &per_ck, .flags = NEEDS_INITIALIZATION, - .round_rate = &on_off_round_rate, - .set_rate = &on_off_set_rate, .enable_shift = 0, .enable_reg = TIMCLKCTRL_REG, + .enable = clk_reg_enable, + .disable = clk_reg_disable, }; /* These clocks are visible outside this module * and can be initialized */ -static struct clk *onchip_clks[] = { +static struct clk *onchip_clks[] __initdata = { &ck_13MHz, &ck_pll1, &ck_pll4, @@ -777,49 +782,74 @@ static struct clk *onchip_clks[] = { &wdt_ck, }; -static int local_clk_enable(struct clk *clk) -{ - int ret = 0; - - if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate - && clk->user_rate) - ret = clk->set_rate(clk, clk->user_rate); - return ret; -} +static struct clk_lookup onchip_clkreg[] = { + { .clk = &ck_13MHz, .con_id = "ck_13MHz" }, + { .clk = &ck_pll1, .con_id = "ck_pll1" }, + { .clk = &ck_pll4, .con_id = "ck_pll4" }, + { .clk = &ck_pll5, .con_id = "ck_pll5" }, + { .clk = &ck_pll3, .con_id = "ck_pll3" }, + { .clk = &vfp9_ck, .con_id = "vfp9_ck" }, + { .clk = &m2hclk_ck, .con_id = "m2hclk_ck" }, + { .clk = &hclk_ck, .con_id = "hclk_ck" }, + { .clk = &dma_ck, .con_id = "dma_ck" }, + { .clk = &flash_ck, .con_id = "flash_ck" }, + { .clk = &dum_ck, .con_id = "dum_ck" }, + { .clk = &keyscan_ck, .con_id = "keyscan_ck" }, + { .clk = &pwm1_ck, .con_id = "pwm1_ck" }, + { .clk = &pwm2_ck, .con_id = "pwm2_ck" }, + { .clk = &jpeg_ck, .con_id = "jpeg_ck" }, + { .clk = &ms_ck, .con_id = "ms_ck" }, + { .clk = &touch_ck, .con_id = "touch_ck" }, + { .clk = &i2c0_ck, .dev_id = "pnx-i2c.0" }, + { .clk = &i2c1_ck, .dev_id = "pnx-i2c.1" }, + { .clk = &i2c2_ck, .dev_id = "pnx-i2c.2" }, + { .clk = &spi0_ck, .con_id = "spi0_ck" }, + { .clk = &spi1_ck, .con_id = "spi1_ck" }, + { .clk = &uart3_ck, .con_id = "uart3_ck" }, + { .clk = &uart4_ck, .con_id = "uart4_ck" }, + { .clk = &uart5_ck, .con_id = "uart5_ck" }, + { .clk = &uart6_ck, .con_id = "uart6_ck" }, + { .clk = &wdt_ck, .dev_id = "pnx4008-watchdog" }, +}; static void local_clk_disable(struct clk *clk) { - if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate) - clk->set_rate(clk, 0); -} + if (WARN_ON(clk->usecount == 0)) + return; -static void local_clk_unuse(struct clk *clk) -{ - if (clk->usecount > 0 && !(--clk->usecount)) { - local_clk_disable(clk); + if (!(--clk->usecount)) { + if (clk->disable) + clk->disable(clk); + else if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate) + clk->set_rate(clk, 0); if (clk->parent) - local_clk_unuse(clk->parent); + local_clk_disable(clk->parent); } } -static int local_clk_use(struct clk *clk) +static int local_clk_enable(struct clk *clk) { int ret = 0; - if (clk->usecount++ == 0) { - if (clk->parent) - ret = local_clk_use(clk->parent); - if (ret != 0) { - clk->usecount--; - goto out; + if (clk->usecount == 0) { + if (clk->parent) { + ret = local_clk_enable(clk->parent); + if (ret != 0) + goto out; } - ret = local_clk_enable(clk); + if (clk->enable) + ret = clk->enable(clk); + else if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate + && clk->user_rate) + ret = clk->set_rate(clk, clk->user_rate); if (ret != 0 && clk->parent) { - local_clk_unuse(clk->parent); - clk->usecount--; + local_clk_disable(clk->parent); + goto out; } + + clk->usecount++; } out: return ret; @@ -866,35 +896,6 @@ out: EXPORT_SYMBOL(clk_set_rate); -struct clk *clk_get(struct device *dev, const char *id) -{ - struct clk *clk = ERR_PTR(-ENOENT); - struct clk **clkp; - - clock_lock(); - for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks); - clkp++) { - if (strcmp(id, (*clkp)->name) == 0 - && try_module_get((*clkp)->owner)) { - clk = (*clkp); - break; - } - } - clock_unlock(); - - return clk; -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ - clock_lock(); - if (clk && !IS_ERR(clk)) - module_put(clk->owner); - clock_unlock(); -} -EXPORT_SYMBOL(clk_put); - unsigned long clk_get_rate(struct clk *clk) { unsigned long ret; @@ -907,10 +908,10 @@ EXPORT_SYMBOL(clk_get_rate); int clk_enable(struct clk *clk) { - int ret = 0; + int ret; clock_lock(); - ret = local_clk_use(clk); + ret = local_clk_enable(clk); clock_unlock(); return ret; } @@ -920,7 +921,7 @@ EXPORT_SYMBOL(clk_enable); void clk_disable(struct clk *clk) { clock_lock(); - local_clk_unuse(clk); + local_clk_disable(clk); clock_unlock(); } @@ -967,18 +968,24 @@ static int __init clk_init(void) for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks); clkp++) { - if (((*clkp)->flags & NEEDS_INITIALIZATION) - && ((*clkp)->set_rate)) { - (*clkp)->user_rate = (*clkp)->rate; - local_set_rate((*clkp), (*clkp)->user_rate); - if ((*clkp)->set_parent) - (*clkp)->set_parent((*clkp), (*clkp)->parent); + struct clk *clk = *clkp; + if (clk->flags & NEEDS_INITIALIZATION) { + if (clk->set_rate) { + clk->user_rate = clk->rate; + local_set_rate(clk, clk->user_rate); + if (clk->set_parent) + clk->set_parent(clk, clk->parent); + } + if (clk->enable && clk->usecount) + clk->enable(clk); + if (clk->disable && !clk->usecount) + clk->disable(clk); } pr_debug("%s: clock %s, rate %ld\n", - __func__, (*clkp)->name, (*clkp)->rate); + __func__, clk->name, clk->rate); } - local_clk_use(&ck_pll4); + local_clk_enable(&ck_pll4); /* if ck_13MHz is not used, disable it. */ if (ck_13MHz.usecount == 0) @@ -987,6 +994,8 @@ static int __init clk_init(void) /* Disable autoclocking */ __raw_writeb(0xff, AUTOCLK_CTRL); + clkdev_add_table(onchip_clkreg, ARRAY_SIZE(onchip_clkreg)); + return 0; } diff --git a/arch/arm/mach-pnx4008/clock.h b/arch/arm/mach-pnx4008/clock.h index cd58f372cfd0..39720d6c0d01 100644 --- a/arch/arm/mach-pnx4008/clock.h +++ b/arch/arm/mach-pnx4008/clock.h @@ -14,8 +14,6 @@ #define __ARCH_ARM_PNX4008_CLOCK_H__ struct clk { - struct list_head node; - struct module *owner; const char *name; struct clk *parent; struct clk *propagate_next; @@ -29,9 +27,11 @@ struct clk { u8 enable_shift1; u32 enable_reg1; u32 parent_switch_reg; - u32(*round_rate) (struct clk *, u32); + u32(*round_rate) (struct clk *, u32); int (*set_rate) (struct clk *, u32); int (*set_parent) (struct clk * clk, struct clk * parent); + int (*enable)(struct clk *); + void (*disable)(struct clk *); }; /* Flags */ diff --git a/arch/arm/mach-pnx4008/i2c.c b/arch/arm/mach-pnx4008/i2c.c index f3fea29c00d3..8103f9644e2d 100644 --- a/arch/arm/mach-pnx4008/i2c.c +++ b/arch/arm/mach-pnx4008/i2c.c @@ -18,120 +18,24 @@ #include <mach/irqs.h> #include <mach/i2c.h> -static int set_clock_run(struct platform_device *pdev) -{ - struct clk *clk; - char name[10]; - int retval = 0; - - snprintf(name, 10, "i2c%d_ck", pdev->id); - clk = clk_get(&pdev->dev, name); - if (!IS_ERR(clk)) { - clk_set_rate(clk, 1); - clk_put(clk); - } else - retval = -ENOENT; - - return retval; -} - -static int set_clock_stop(struct platform_device *pdev) -{ - struct clk *clk; - char name[10]; - int retval = 0; - - snprintf(name, 10, "i2c%d_ck", pdev->id); - clk = clk_get(&pdev->dev, name); - if (!IS_ERR(clk)) { - clk_set_rate(clk, 0); - clk_put(clk); - } else - retval = -ENOENT; - - return retval; -} - -static int i2c_pnx_suspend(struct platform_device *pdev, pm_message_t state) -{ - int retval = 0; -#ifdef CONFIG_PM - retval = set_clock_run(pdev); -#endif - return retval; -} - -static int i2c_pnx_resume(struct platform_device *pdev) -{ - int retval = 0; -#ifdef CONFIG_PM - retval = set_clock_run(pdev); -#endif - return retval; -} - -static u32 calculate_input_freq(struct platform_device *pdev) -{ - return HCLK_MHZ; -} - - -static struct i2c_pnx_algo_data pnx_algo_data0 = { +static struct i2c_pnx_data i2c0_data = { + .name = I2C_CHIP_NAME "0", .base = PNX4008_I2C1_BASE, .irq = I2C_1_INT, }; -static struct i2c_pnx_algo_data pnx_algo_data1 = { +static struct i2c_pnx_data i2c1_data = { + .name = I2C_CHIP_NAME "1", .base = PNX4008_I2C2_BASE, .irq = I2C_2_INT, }; -static struct i2c_pnx_algo_data pnx_algo_data2 = { +static struct i2c_pnx_data i2c2_data = { + .name = "USB-I2C", .base = (PNX4008_USB_CONFIG_BASE + 0x300), .irq = USB_I2C_INT, }; -static struct i2c_adapter pnx_adapter0 = { - .name = I2C_CHIP_NAME "0", - .algo_data = &pnx_algo_data0, -}; -static struct i2c_adapter pnx_adapter1 = { - .name = I2C_CHIP_NAME "1", - .algo_data = &pnx_algo_data1, -}; - -static struct i2c_adapter pnx_adapter2 = { - .name = "USB-I2C", - .algo_data = &pnx_algo_data2, -}; - -static struct i2c_pnx_data i2c0_data = { - .suspend = i2c_pnx_suspend, - .resume = i2c_pnx_resume, - .calculate_input_freq = calculate_input_freq, - .set_clock_run = set_clock_run, - .set_clock_stop = set_clock_stop, - .adapter = &pnx_adapter0, -}; - -static struct i2c_pnx_data i2c1_data = { - .suspend = i2c_pnx_suspend, - .resume = i2c_pnx_resume, - .calculate_input_freq = calculate_input_freq, - .set_clock_run = set_clock_run, - .set_clock_stop = set_clock_stop, - .adapter = &pnx_adapter1, -}; - -static struct i2c_pnx_data i2c2_data = { - .suspend = i2c_pnx_suspend, - .resume = i2c_pnx_resume, - .calculate_input_freq = calculate_input_freq, - .set_clock_run = set_clock_run, - .set_clock_stop = set_clock_stop, - .adapter = &pnx_adapter2, -}; - static struct platform_device i2c0_device = { .name = "pnx-i2c", .id = 0, diff --git a/arch/arm/mach-pnx4008/include/mach/clkdev.h b/arch/arm/mach-pnx4008/include/mach/clkdev.h new file mode 100644 index 000000000000..04b37a89801c --- /dev/null +++ b/arch/arm/mach-pnx4008/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/mach-pnx4008/include/mach/timex.h b/arch/arm/mach-pnx4008/include/mach/timex.h index 5ff0196c0f16..b383c7de7ab4 100644 --- a/arch/arm/mach-pnx4008/include/mach/timex.h +++ b/arch/arm/mach-pnx4008/include/mach/timex.h @@ -14,60 +14,6 @@ #ifndef __PNX4008_TIMEX_H #define __PNX4008_TIMEX_H -#include <linux/io.h> -#include <mach/hardware.h> - #define CLOCK_TICK_RATE 1000000 -#define TICKS2USECS(x) (x) - -/* MilliSecond Timer - Chapter 21 Page 202 */ - -#define MSTIM_INT IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x0)) -#define MSTIM_CTRL IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x4)) -#define MSTIM_COUNTER IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x8)) -#define MSTIM_MCTRL IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x14)) -#define MSTIM_MATCH0 IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x18)) -#define MSTIM_MATCH1 IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x1c)) - -/* High Speed Timer - Chpater 22, Page 205 */ - -#define HSTIM_INT IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x0)) -#define HSTIM_CTRL IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x4)) -#define HSTIM_COUNTER IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x8)) -#define HSTIM_PMATCH IO_ADDRESS((PNX4008_HSTIMER_BASE + 0xC)) -#define HSTIM_PCOUNT IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x10)) -#define HSTIM_MCTRL IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x14)) -#define HSTIM_MATCH0 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x18)) -#define HSTIM_MATCH1 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x1c)) -#define HSTIM_MATCH2 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x20)) -#define HSTIM_CCR IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x28)) -#define HSTIM_CR0 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x2C)) -#define HSTIM_CR1 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x30)) - -/* IMPORTANT: both timers are UPCOUNTING */ - -/* xSTIM_MCTRL bit definitions */ -#define MR0_INT 1 -#define RESET_COUNT0 (1<<1) -#define STOP_COUNT0 (1<<2) -#define MR1_INT (1<<3) -#define RESET_COUNT1 (1<<4) -#define STOP_COUNT1 (1<<5) -#define MR2_INT (1<<6) -#define RESET_COUNT2 (1<<7) -#define STOP_COUNT2 (1<<8) - -/* xSTIM_CTRL bit definitions */ -#define COUNT_ENAB 1 -#define RESET_COUNT (1<<1) -#define DEBUG_EN (1<<2) - -/* xSTIM_INT bit definitions */ -#define MATCH0_INT 1 -#define MATCH1_INT (1<<1) -#define MATCH2_INT (1<<2) -#define RTC_TICK0 (1<<4) -#define RTC_TICK1 (1<<5) - #endif diff --git a/arch/arm/mach-pnx4008/pm.c b/arch/arm/mach-pnx4008/pm.c index b3d8d53e32ef..1f0585329be4 100644 --- a/arch/arm/mach-pnx4008/pm.c +++ b/arch/arm/mach-pnx4008/pm.c @@ -21,6 +21,8 @@ #include <linux/io.h> #include <asm/cacheflush.h> + +#include <mach/hardware.h> #include <mach/pm.h> #include <mach/clock.h> diff --git a/arch/arm/mach-pnx4008/time.c b/arch/arm/mach-pnx4008/time.c index fc0ba183fe12..0c8aad4bb0dc 100644 --- a/arch/arm/mach-pnx4008/time.c +++ b/arch/arm/mach-pnx4008/time.c @@ -30,6 +30,8 @@ #include <asm/mach/time.h> #include <asm/errno.h> +#include "time.h" + /*! Note: all timers are UPCOUNTING */ /*! diff --git a/arch/arm/mach-pnx4008/time.h b/arch/arm/mach-pnx4008/time.h new file mode 100644 index 000000000000..75e88c570aa7 --- /dev/null +++ b/arch/arm/mach-pnx4008/time.h @@ -0,0 +1,70 @@ +/* + * arch/arm/mach-pnx4008/include/mach/timex.h + * + * PNX4008 timers header file + * + * Author: Dmitry Chigirev <source@mvista.com> + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef PNX_TIME_H +#define PNX_TIME_H + +#include <linux/io.h> +#include <mach/hardware.h> + +#define TICKS2USECS(x) (x) + +/* MilliSecond Timer - Chapter 21 Page 202 */ + +#define MSTIM_INT IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x0)) +#define MSTIM_CTRL IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x4)) +#define MSTIM_COUNTER IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x8)) +#define MSTIM_MCTRL IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x14)) +#define MSTIM_MATCH0 IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x18)) +#define MSTIM_MATCH1 IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x1c)) + +/* High Speed Timer - Chpater 22, Page 205 */ + +#define HSTIM_INT IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x0)) +#define HSTIM_CTRL IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x4)) +#define HSTIM_COUNTER IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x8)) +#define HSTIM_PMATCH IO_ADDRESS((PNX4008_HSTIMER_BASE + 0xC)) +#define HSTIM_PCOUNT IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x10)) +#define HSTIM_MCTRL IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x14)) +#define HSTIM_MATCH0 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x18)) +#define HSTIM_MATCH1 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x1c)) +#define HSTIM_MATCH2 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x20)) +#define HSTIM_CCR IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x28)) +#define HSTIM_CR0 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x2C)) +#define HSTIM_CR1 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x30)) + +/* IMPORTANT: both timers are UPCOUNTING */ + +/* xSTIM_MCTRL bit definitions */ +#define MR0_INT 1 +#define RESET_COUNT0 (1<<1) +#define STOP_COUNT0 (1<<2) +#define MR1_INT (1<<3) +#define RESET_COUNT1 (1<<4) +#define STOP_COUNT1 (1<<5) +#define MR2_INT (1<<6) +#define RESET_COUNT2 (1<<7) +#define STOP_COUNT2 (1<<8) + +/* xSTIM_CTRL bit definitions */ +#define COUNT_ENAB 1 +#define RESET_COUNT (1<<1) +#define DEBUG_EN (1<<2) + +/* xSTIM_INT bit definitions */ +#define MATCH0_INT 1 +#define MATCH1_INT (1<<1) +#define MATCH2_INT (1<<2) +#define RTC_TICK0 (1<<4) +#define RTC_TICK1 (1<<5) + +#endif |