From 700598cef866011b878f389c30414d31fa5bb87b Mon Sep 17 00:00:00 2001 From: GuanXuetao Date: Sat, 15 Jan 2011 18:25:14 +0800 Subject: unicore32 machine related files: pci bus handling This patch implements arch-specific pci bus driver. Signed-off-by: Guan Xuetao --- drivers/pci/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 98e6fdf34d30..77cf813ba264 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o obj-$(CONFIG_X86) += setup-bus.o obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o +obj-$(CONFIG_UNICORE32) += setup-bus.o setup-irq.o obj-$(CONFIG_PARISC) += setup-bus.o obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o obj-$(CONFIG_PPC) += setup-bus.o -- cgit v1.2.3 From 425ad52b86d9710719b3aa811d6cab56b3852981 Mon Sep 17 00:00:00 2001 From: GuanXuetao Date: Sat, 15 Jan 2011 18:28:19 +0800 Subject: unicore32 machine related files: ps2 driver This patch implements arch-specific ps2 driver. By reviewed with Dmitry Torokhov: 1. move i8042-ucio.h to drivers/input/serio/i8042-unicore32io.h 2. move puv3_ps2_init() to arch/unicore32/kernel/puv3-core.c 3. remove unused comments. Signed-off-by: Guan Xuetao Acked-by: Dmitry Torokhov --- drivers/input/serio/i8042-unicore32io.h | 70 +++++++++++++++++++++++++++++++++ drivers/input/serio/i8042.h | 2 + 2 files changed, 72 insertions(+) create mode 100644 drivers/input/serio/i8042-unicore32io.h (limited to 'drivers') diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h new file mode 100644 index 000000000000..6a7e8b3ce61a --- /dev/null +++ b/drivers/input/serio/i8042-unicore32io.h @@ -0,0 +1,70 @@ +/* + * Code specific to PKUnity SoC and UniCore ISA + * + * Maintained by GUAN Xue-tao + * Copyright (C) 2001-2011 Guan Xuetao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _I8042_UNICORE32_H +#define _I8042_UNICORE32_H + +#include + +/* + * Names. + */ +#define I8042_KBD_PHYS_DESC "isa0060/serio0" +#define I8042_AUX_PHYS_DESC "isa0060/serio1" +#define I8042_MUX_PHYS_DESC "isa0060/serio%d" + +/* + * IRQs. + */ +#define I8042_KBD_IRQ IRQ_PS2_KBD +#define I8042_AUX_IRQ IRQ_PS2_AUX + +/* + * Register numbers. + */ +#define I8042_COMMAND_REG ((unsigned long)&PS2_COMMAND) +#define I8042_STATUS_REG ((unsigned long)&PS2_STATUS) +#define I8042_DATA_REG ((unsigned long)&PS2_DATA) + +static inline int i8042_read_data(void) +{ + return inb(I8042_DATA_REG); +} + +static inline int i8042_read_status(void) +{ + return inb(I8042_STATUS_REG); +} + +static inline void i8042_write_data(int val) +{ + outb(val, I8042_DATA_REG); +} + +static inline void i8042_write_command(int val) +{ + outb(val, I8042_COMMAND_REG); +} + +static inline int i8042_platform_init(void) +{ + if (!request_region(I8042_DATA_REG, 16, "i8042")) + return -EBUSY; + + i8042_reset = 1; + return 0; +} + +static inline void i8042_platform_exit(void) +{ + release_region(I8042_DATA_REG, 16); +} + +#endif /* _I8042_UNICORE32_H */ diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h index ac1d759d0f55..3452708fbe3b 100644 --- a/drivers/input/serio/i8042.h +++ b/drivers/input/serio/i8042.h @@ -26,6 +26,8 @@ #include "i8042-sparcio.h" #elif defined(CONFIG_X86) || defined(CONFIG_IA64) #include "i8042-x86ia64io.h" +#elif defined(CONFIG_UNICORE32) +#include "i8042-unicore32io.h" #else #include "i8042-io.h" #endif -- cgit v1.2.3 From 3838b82c0a6806daf820acacf02cd9aefe9df7b8 Mon Sep 17 00:00:00 2001 From: GuanXuetao Date: Fri, 18 Feb 2011 18:38:33 +0800 Subject: unicore32 i8042: adjust io funcs of i8042-unicore32io.h replace inb/outb with readb/writeb in i8042-unicore32io.h and correct typecasting of register and region macros -- by advice with Arnd Bergmann Signed-off-by: Guan Xuetao --- drivers/input/serio/i8042-unicore32io.h | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h index 6a7e8b3ce61a..2cdd8726446f 100644 --- a/drivers/input/serio/i8042-unicore32io.h +++ b/drivers/input/serio/i8042-unicore32io.h @@ -29,33 +29,36 @@ /* * Register numbers. */ -#define I8042_COMMAND_REG ((unsigned long)&PS2_COMMAND) -#define I8042_STATUS_REG ((unsigned long)&PS2_STATUS) -#define I8042_DATA_REG ((unsigned long)&PS2_DATA) +#define I8042_COMMAND_REG ((volatile void __iomem *)&PS2_COMMAND) +#define I8042_STATUS_REG ((volatile void __iomem *)&PS2_STATUS) +#define I8042_DATA_REG ((volatile void __iomem *)&PS2_DATA) + +#define I8042_REGION_START (resource_size_t)(&PS2_DATA) +#define I8042_REGION_SIZE (resource_size_t)(16) static inline int i8042_read_data(void) { - return inb(I8042_DATA_REG); + return readb(I8042_DATA_REG); } static inline int i8042_read_status(void) { - return inb(I8042_STATUS_REG); + return readb(I8042_STATUS_REG); } static inline void i8042_write_data(int val) { - outb(val, I8042_DATA_REG); + writeb(val, I8042_DATA_REG); } static inline void i8042_write_command(int val) { - outb(val, I8042_COMMAND_REG); + writeb(val, I8042_COMMAND_REG); } static inline int i8042_platform_init(void) { - if (!request_region(I8042_DATA_REG, 16, "i8042")) + if (!request_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042")) return -EBUSY; i8042_reset = 1; @@ -64,7 +67,7 @@ static inline int i8042_platform_init(void) static inline void i8042_platform_exit(void) { - release_region(I8042_DATA_REG, 16); + release_region(I8042_REGION_START, I8042_REGION_SIZE); } #endif /* _I8042_UNICORE32_H */ -- cgit v1.2.3 From 4517366d870b89d6fb8c0c90deb6c73d975908af Mon Sep 17 00:00:00 2001 From: GuanXuetao Date: Fri, 25 Feb 2011 17:58:00 +0800 Subject: unicore32 i8042 upgrade and bugfix: adjust resource request region type Signed-off-by: Guan Xuetao --- drivers/input/serio/i8042-unicore32io.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h index 2cdd8726446f..620b040b81b0 100644 --- a/drivers/input/serio/i8042-unicore32io.h +++ b/drivers/input/serio/i8042-unicore32io.h @@ -58,7 +58,7 @@ static inline void i8042_write_command(int val) static inline int i8042_platform_init(void) { - if (!request_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042")) + if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042")) return -EBUSY; i8042_reset = 1; @@ -67,7 +67,7 @@ static inline int i8042_platform_init(void) static inline void i8042_platform_exit(void) { - release_region(I8042_REGION_START, I8042_REGION_SIZE); + release_mem_region(I8042_REGION_START, I8042_REGION_SIZE); } #endif /* _I8042_UNICORE32_H */ -- cgit v1.2.3 From e5abf78b57199a417eb01ff922a5ea6ff9e10b61 Mon Sep 17 00:00:00 2001 From: GuanXuetao Date: Sat, 26 Feb 2011 21:21:18 +0800 Subject: unicore32 io: redefine __REG(x) and re-use readl/writel funcs -- by advice of Arnd Bergmann Signed-off-by: Guan Xuetao Reviewed-by: Arnd Bergmann --- arch/unicore32/include/asm/gpio.h | 9 ++-- arch/unicore32/include/mach/dma.h | 11 ++++- arch/unicore32/include/mach/hardware.h | 8 +--- arch/unicore32/kernel/clock.c | 34 +++++++------- arch/unicore32/kernel/dma.c | 15 ++++--- arch/unicore32/kernel/gpio.c | 12 ++--- arch/unicore32/kernel/irq.c | 80 ++++++++++++++++----------------- arch/unicore32/kernel/pci.c | 58 ++++++++++++------------ arch/unicore32/kernel/process.c | 10 ++--- arch/unicore32/kernel/puv3-core.c | 10 ++--- arch/unicore32/kernel/rtc.c | 34 +++++++------- arch/unicore32/kernel/time.c | 46 +++++++++---------- drivers/input/serio/i8042-unicore32io.h | 8 ++-- 13 files changed, 171 insertions(+), 164 deletions(-) (limited to 'drivers') diff --git a/arch/unicore32/include/asm/gpio.h b/arch/unicore32/include/asm/gpio.h index 3aaa41e9e413..2716f14e3ff6 100644 --- a/arch/unicore32/include/asm/gpio.h +++ b/arch/unicore32/include/asm/gpio.h @@ -13,6 +13,7 @@ #ifndef __UNICORE_GPIO_H__ #define __UNICORE_GPIO_H__ +#include #include #include #include @@ -66,7 +67,7 @@ static inline int gpio_get_value(unsigned gpio) { if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX)) - return GPIO_GPLR & GPIO_GPIO(gpio); + return readl(GPIO_GPLR) & GPIO_GPIO(gpio); else return __gpio_get_value(gpio); } @@ -75,9 +76,9 @@ static inline void gpio_set_value(unsigned gpio, int value) { if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX)) if (value) - GPIO_GPSR = GPIO_GPIO(gpio); + writel(GPIO_GPIO(gpio), GPIO_GPSR); else - GPIO_GPCR = GPIO_GPIO(gpio); + writel(GPIO_GPIO(gpio), GPIO_GPCR); else __gpio_set_value(gpio, value); } @@ -86,7 +87,7 @@ static inline void gpio_set_value(unsigned gpio, int value) static inline unsigned gpio_to_irq(unsigned gpio) { - if ((gpio < IRQ_GPIOHIGH) && (FIELD(1, 1, gpio) & GPIO_GPIR)) + if ((gpio < IRQ_GPIOHIGH) && (FIELD(1, 1, gpio) & readl(GPIO_GPIR))) return IRQ_GPIOLOW0 + gpio; else return IRQ_GPIO0 + gpio; diff --git a/arch/unicore32/include/mach/dma.h b/arch/unicore32/include/mach/dma.h index 3e3224a10525..d655c1b6e083 100644 --- a/arch/unicore32/include/mach/dma.h +++ b/arch/unicore32/include/mach/dma.h @@ -35,7 +35,14 @@ extern int puv3_request_dma(char *name, extern void puv3_free_dma(int dma_ch); -#define puv3_stop_dma(ch) (DMAC_CONFIG(ch) &= ~DMAC_CONFIG_EN) -#define puv3_resume_dma(ch) (DMAC_CONFIG(ch) |= DMAC_CONFIG_EN) +static inline void puv3_stop_dma(int ch) +{ + writel(readl(DMAC_CONFIG(ch)) & ~DMAC_CONFIG_EN, DMAC_CONFIG(ch)); +} + +static inline void puv3_resume_dma(int ch) +{ + writel(readl(DMAC_CONFIG(ch)) | DMAC_CONFIG_EN, DMAC_CONFIG(ch)); +} #endif /* __MACH_PUV3_DMA_H__ */ diff --git a/arch/unicore32/include/mach/hardware.h b/arch/unicore32/include/mach/hardware.h index c7d3dd6b4eff..b71405ab6de6 100644 --- a/arch/unicore32/include/mach/hardware.h +++ b/arch/unicore32/include/mach/hardware.h @@ -22,13 +22,7 @@ #ifndef __ASSEMBLY__ -# define __REG(x) (*((volatile unsigned long *)io_p2v(x))) -# define __PREG(x) (io_v2p((unsigned long)&(x))) - -#else - -# define __REG(x) io_p2v(x) -# define __PREG(x) io_v2p(x) +# define __REG(x) (void __iomem *)io_p2v(x) #endif diff --git a/arch/unicore32/kernel/clock.c b/arch/unicore32/kernel/clock.c index 80323db581fd..18d4563e6fa5 100644 --- a/arch/unicore32/kernel/clock.c +++ b/arch/unicore32/kernel/clock.c @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -152,28 +153,29 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (ret) return ret; - if (PM_PLLVGACFG == pll_vgacfg) + if (readl(PM_PLLVGACFG) == pll_vgacfg) return 0; /* set pll vga cfg reg. */ - PM_PLLVGACFG = pll_vgacfg; + writel(pll_vgacfg, PM_PLLVGACFG); - PM_PMCR = PM_PMCR_CFBVGA; - while ((PM_PLLDFCDONE & PM_PLLDFCDONE_VGADFC) + writel(PM_PMCR_CFBVGA, PM_PMCR); + while ((readl(PM_PLLDFCDONE) & PM_PLLDFCDONE_VGADFC) != PM_PLLDFCDONE_VGADFC) udelay(100); /* about 1ms */ /* set div cfg reg. */ - PM_PCGR |= PM_PCGR_VGACLK; + writel(readl(PM_PCGR) | PM_PCGR_VGACLK, PM_PCGR); - PM_DIVCFG = (PM_DIVCFG & ~PM_DIVCFG_VGACLK_MASK) - | PM_DIVCFG_VGACLK(pll_vgadiv); + writel((readl(PM_DIVCFG) & ~PM_DIVCFG_VGACLK_MASK) + | PM_DIVCFG_VGACLK(pll_vgadiv), PM_DIVCFG); - PM_SWRESET |= PM_SWRESET_VGADIV; - while ((PM_SWRESET & PM_SWRESET_VGADIV) == PM_SWRESET_VGADIV) + writel(readl(PM_SWRESET) | PM_SWRESET_VGADIV, PM_SWRESET); + while ((readl(PM_SWRESET) & PM_SWRESET_VGADIV) + == PM_SWRESET_VGADIV) udelay(100); /* 65536 bclk32, about 320us */ - PM_PCGR &= ~PM_PCGR_VGACLK; + writel(readl(PM_PCGR) & ~PM_PCGR_VGACLK, PM_PCGR); } #ifdef CONFIG_CPU_FREQ if (clk == &clk_mclk_clk) { @@ -323,15 +325,15 @@ struct { static int __init clk_init(void) { #ifdef CONFIG_PUV3_PM - u32 pllrate, divstatus = PM_DIVSTATUS; - u32 pcgr_val = PM_PCGR; + u32 pllrate, divstatus = readl(PM_DIVSTATUS); + u32 pcgr_val = readl(PM_PCGR); int i; pcgr_val |= PM_PCGR_BCLKMME | PM_PCGR_BCLKH264E | PM_PCGR_BCLKH264D | PM_PCGR_HECLK | PM_PCGR_HDCLK; - PM_PCGR = pcgr_val; + writel(pcgr_val, PM_PCGR); - pllrate = PM_PLLSYSSTATUS; + pllrate = readl(PM_PLLSYSSTATUS); /* lookup pmclk_table */ clk_mclk_clk.rate = 0; @@ -346,7 +348,7 @@ static int __init clk_init(void) clk_bclk32_clk.rate = clk_mclk_clk.rate / (((divstatus & 0x0000f000) >> 12) + 1); - pllrate = PM_PLLDDRSTATUS; + pllrate = readl(PM_PLLDDRSTATUS); /* lookup pddr_table */ clk_ddr_clk.rate = 0; @@ -357,7 +359,7 @@ static int __init clk_init(void) } } - pllrate = PM_PLLVGASTATUS; + pllrate = readl(PM_PLLVGASTATUS); /* lookup pvga_table */ clk_vga_clk.rate = 0; diff --git a/arch/unicore32/kernel/dma.c b/arch/unicore32/kernel/dma.c index b8dcc2514e9a..ae441bc3122c 100644 --- a/arch/unicore32/kernel/dma.c +++ b/arch/unicore32/kernel/dma.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -94,15 +95,16 @@ EXPORT_SYMBOL(puv3_free_dma); static irqreturn_t dma_irq_handler(int irq, void *dev_id) { - int i, dint = DMAC_ITCSR; + int i, dint; + dint = readl(DMAC_ITCSR); for (i = 0; i < MAX_DMA_CHANNELS; i++) { if (dint & DMAC_CHANNEL(i)) { struct dma_channel *channel = &dma_channels[i]; /* Clear TC interrupt of channel i */ - DMAC_ITCCR = DMAC_CHANNEL(i); - DMAC_ITCCR = 0; + writel(DMAC_CHANNEL(i), DMAC_ITCCR); + writel(0, DMAC_ITCCR); if (channel->name && channel->irq_handler) { channel->irq_handler(i, channel->data); @@ -121,15 +123,16 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) static irqreturn_t dma_err_handler(int irq, void *dev_id) { - int i, dint = DMAC_IESR; + int i, dint; + dint = readl(DMAC_IESR); for (i = 0; i < MAX_DMA_CHANNELS; i++) { if (dint & DMAC_CHANNEL(i)) { struct dma_channel *channel = &dma_channels[i]; /* Clear Err interrupt of channel i */ - DMAC_IECR = DMAC_CHANNEL(i); - DMAC_IECR = 0; + writel(DMAC_CHANNEL(i), DMAC_IECR); + writel(0, DMAC_IECR); if (channel->name && channel->err_handler) { channel->err_handler(i, channel->data); diff --git a/arch/unicore32/kernel/gpio.c b/arch/unicore32/kernel/gpio.c index 4cb28308bb5f..cb12ec39552c 100644 --- a/arch/unicore32/kernel/gpio.c +++ b/arch/unicore32/kernel/gpio.c @@ -52,15 +52,15 @@ device_initcall(puv3_gpio_leds_init); static int puv3_gpio_get(struct gpio_chip *chip, unsigned offset) { - return GPIO_GPLR & GPIO_GPIO(offset); + return readl(GPIO_GPLR) & GPIO_GPIO(offset); } static void puv3_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { if (value) - GPIO_GPSR = GPIO_GPIO(offset); + writel(GPIO_GPIO(offset), GPIO_GPSR); else - GPIO_GPCR = GPIO_GPIO(offset); + writel(GPIO_GPIO(offset), GPIO_GPCR); } static int puv3_direction_input(struct gpio_chip *chip, unsigned offset) @@ -68,7 +68,7 @@ static int puv3_direction_input(struct gpio_chip *chip, unsigned offset) unsigned long flags; local_irq_save(flags); - GPIO_GPDR &= ~GPIO_GPIO(offset); + writel(readl(GPIO_GPDR) & ~GPIO_GPIO(offset), GPIO_GPDR); local_irq_restore(flags); return 0; } @@ -80,7 +80,7 @@ static int puv3_direction_output(struct gpio_chip *chip, unsigned offset, local_irq_save(flags); puv3_gpio_set(chip, offset, value); - GPIO_GPDR |= GPIO_GPIO(offset); + writel(readl(GPIO_GPDR) | GPIO_GPIO(offset), GPIO_GPDR); local_irq_restore(flags); return 0; } @@ -97,7 +97,7 @@ static struct gpio_chip puv3_gpio_chip = { void __init puv3_init_gpio(void) { - GPIO_GPDR = GPIO_DIR; + writel(GPIO_DIR, GPIO_GPDR); #if defined(CONFIG_PUV3_NB0916) || defined(CONFIG_PUV3_SMW0919) \ || defined(CONFIG_PUV3_DB0913) gpio_set_value(GPO_WIFI_EN, 1); diff --git a/arch/unicore32/kernel/irq.c b/arch/unicore32/kernel/irq.c index 38e30897dea3..e1dbfcb61873 100644 --- a/arch/unicore32/kernel/irq.c +++ b/arch/unicore32/kernel/irq.c @@ -66,8 +66,8 @@ static int puv3_gpio_type(struct irq_data *d, unsigned int type) else GPIO_IRQ_falling_edge &= ~mask; - GPIO_GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; - GPIO_GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; + writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER); + writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER); return 0; } @@ -77,25 +77,25 @@ static int puv3_gpio_type(struct irq_data *d, unsigned int type) */ static void puv3_low_gpio_ack(struct irq_data *d) { - GPIO_GEDR = (1 << d->irq); + writel((1 << d->irq), GPIO_GEDR); } static void puv3_low_gpio_mask(struct irq_data *d) { - INTC_ICMR &= ~(1 << d->irq); + writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR); } static void puv3_low_gpio_unmask(struct irq_data *d) { - INTC_ICMR |= 1 << d->irq; + writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR); } static int puv3_low_gpio_wake(struct irq_data *d, unsigned int on) { if (on) - PM_PWER |= 1 << d->irq; + writel(readl(PM_PWER) | (1 << d->irq), PM_PWER); else - PM_PWER &= ~(1 << d->irq); + writel(readl(PM_PWER) & ~(1 << d->irq), PM_PWER); return 0; } @@ -118,13 +118,13 @@ puv3_gpio_handler(unsigned int irq, struct irq_desc *desc) { unsigned int mask; - mask = GPIO_GEDR; + mask = readl(GPIO_GEDR); do { /* * clear down all currently active IRQ sources. * We will be processing them all. */ - GPIO_GEDR = mask; + writel(mask, GPIO_GEDR); irq = IRQ_GPIO0; do { @@ -133,7 +133,7 @@ puv3_gpio_handler(unsigned int irq, struct irq_desc *desc) mask >>= 1; irq++; } while (mask); - mask = GPIO_GEDR; + mask = readl(GPIO_GEDR); } while (mask); } @@ -146,7 +146,7 @@ static void puv3_high_gpio_ack(struct irq_data *d) { unsigned int mask = GPIO_MASK(d->irq); - GPIO_GEDR = mask; + writel(mask, GPIO_GEDR); } static void puv3_high_gpio_mask(struct irq_data *d) @@ -155,8 +155,8 @@ static void puv3_high_gpio_mask(struct irq_data *d) GPIO_IRQ_mask &= ~mask; - GPIO_GRER &= ~mask; - GPIO_GFER &= ~mask; + writel(readl(GPIO_GRER) & ~mask, GPIO_GRER); + writel(readl(GPIO_GFER) & ~mask, GPIO_GFER); } static void puv3_high_gpio_unmask(struct irq_data *d) @@ -165,16 +165,16 @@ static void puv3_high_gpio_unmask(struct irq_data *d) GPIO_IRQ_mask |= mask; - GPIO_GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; - GPIO_GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; + writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER); + writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER); } static int puv3_high_gpio_wake(struct irq_data *d, unsigned int on) { if (on) - PM_PWER |= PM_PWER_GPIOHIGH; + writel(readl(PM_PWER) | PM_PWER_GPIOHIGH, PM_PWER); else - PM_PWER &= ~PM_PWER_GPIOHIGH; + writel(readl(PM_PWER) & ~PM_PWER_GPIOHIGH, PM_PWER); return 0; } @@ -193,12 +193,12 @@ static struct irq_chip puv3_high_gpio_chip = { */ static void puv3_mask_irq(struct irq_data *d) { - INTC_ICMR &= ~(1 << d->irq); + writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR); } static void puv3_unmask_irq(struct irq_data *d) { - INTC_ICMR |= (1 << d->irq); + writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR); } /* @@ -208,9 +208,9 @@ static int puv3_set_wake(struct irq_data *d, unsigned int on) { if (d->irq == IRQ_RTCAlarm) { if (on) - PM_PWER |= PM_PWER_RTC; + writel(readl(PM_PWER) | PM_PWER_RTC, PM_PWER); else - PM_PWER &= ~PM_PWER_RTC; + writel(readl(PM_PWER) & ~PM_PWER_RTC, PM_PWER); return 0; } return -EINVAL; @@ -242,25 +242,25 @@ static int puv3_irq_suspend(struct sys_device *dev, pm_message_t state) struct puv3_irq_state *st = &puv3_irq_state; st->saved = 1; - st->icmr = INTC_ICMR; - st->iclr = INTC_ICLR; - st->iccr = INTC_ICCR; + st->icmr = readl(INTC_ICMR); + st->iclr = readl(INTC_ICLR); + st->iccr = readl(INTC_ICCR); /* * Disable all GPIO-based interrupts. */ - INTC_ICMR &= ~(0x1ff); + writel(readl(INTC_ICMR) & ~(0x1ff), INTC_ICMR); /* * Set the appropriate edges for wakeup. */ - GPIO_GRER = PM_PWER & GPIO_IRQ_rising_edge; - GPIO_GFER = PM_PWER & GPIO_IRQ_falling_edge; + writel(readl(PM_PWER) & GPIO_IRQ_rising_edge, GPIO_GRER); + writel(readl(PM_PWER) & GPIO_IRQ_falling_edge, GPIO_GFER); /* * Clear any pending GPIO interrupts. */ - GPIO_GEDR = GPIO_GEDR; + writel(readl(GPIO_GEDR), GPIO_GEDR); return 0; } @@ -270,13 +270,13 @@ static int puv3_irq_resume(struct sys_device *dev) struct puv3_irq_state *st = &puv3_irq_state; if (st->saved) { - INTC_ICCR = st->iccr; - INTC_ICLR = st->iclr; + writel(st->iccr, INTC_ICCR); + writel(st->iclr, INTC_ICLR); - GPIO_GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; - GPIO_GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; + writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER); + writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER); - INTC_ICMR = st->icmr; + writel(st->icmr, INTC_ICMR); } return 0; } @@ -307,18 +307,18 @@ void __init init_IRQ(void) request_resource(&iomem_resource, &irq_resource); /* disable all IRQs */ - INTC_ICMR = 0; + writel(0, INTC_ICMR); /* all IRQs are IRQ, not REAL */ - INTC_ICLR = 0; + writel(0, INTC_ICLR); /* clear all GPIO edge detects */ - GPIO_GPIR = FMASK(8, 0) & ~FIELD(1, 1, GPI_SOFF_REQ); - GPIO_GFER = 0; - GPIO_GRER = 0; - GPIO_GEDR = 0x0FFFFFFF; + writel(FMASK(8, 0) & ~FIELD(1, 1, GPI_SOFF_REQ), GPIO_GPIR); + writel(0, GPIO_GFER); + writel(0, GPIO_GRER); + writel(0x0FFFFFFF, GPIO_GEDR); - INTC_ICCR = 1; + writel(1, INTC_ICCR); for (irq = 0; irq < IRQ_GPIOHIGH; irq++) { set_irq_chip(irq, &puv3_low_gpio_chip); diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c index d4e55e2d2d29..65c265ee8e94 100644 --- a/arch/unicore32/kernel/pci.c +++ b/arch/unicore32/kernel/pci.c @@ -30,16 +30,16 @@ static int puv3_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) { - PCICFG_ADDR = CONFIG_CMD(bus, devfn, where); + writel(CONFIG_CMD(bus, devfn, where), PCICFG_ADDR); switch (size) { case 1: - *value = (PCICFG_DATA >> ((where & 3) * 8)) & 0xFF; + *value = (readl(PCICFG_DATA) >> ((where & 3) * 8)) & 0xFF; break; case 2: - *value = (PCICFG_DATA >> ((where & 2) * 8)) & 0xFFFF; + *value = (readl(PCICFG_DATA) >> ((where & 2) * 8)) & 0xFFFF; break; case 4: - *value = PCICFG_DATA; + *value = readl(PCICFG_DATA); break; } return PCIBIOS_SUCCESSFUL; @@ -49,18 +49,18 @@ static int puv3_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { - PCICFG_ADDR = CONFIG_CMD(bus, devfn, where); + writel(CONFIG_CMD(bus, devfn, where), PCICFG_ADDR); switch (size) { case 1: - PCICFG_DATA = (PCICFG_DATA & ~FMASK(8, (where&3)*8)) - | FIELD(value, 8, (where&3)*8); + writel((readl(PCICFG_DATA) & ~FMASK(8, (where&3)*8)) + | FIELD(value, 8, (where&3)*8), PCICFG_DATA); break; case 2: - PCICFG_DATA = (PCICFG_DATA & ~FMASK(16, (where&2)*8)) - | FIELD(value, 16, (where&2)*8); + writel((readl(PCICFG_DATA) & ~FMASK(16, (where&2)*8)) + | FIELD(value, 16, (where&2)*8), PCICFG_DATA); break; case 4: - PCICFG_DATA = value; + writel(value, PCICFG_DATA); break; } return PCIBIOS_SUCCESSFUL; @@ -75,31 +75,31 @@ void pci_puv3_preinit(void) { printk(KERN_DEBUG "PCI: PKUnity PCI Controller Initializing ...\n"); /* config PCI bridge base */ - PCICFG_BRIBASE = PKUNITY_PCIBRI_BASE; + writel(PKUNITY_PCIBRI_BASE, PCICFG_BRIBASE); - PCIBRI_AHBCTL0 = 0; - PCIBRI_AHBBAR0 = PKUNITY_PCIBRI_BASE | PCIBRI_BARx_MEM; - PCIBRI_AHBAMR0 = 0xFFFF0000; - PCIBRI_AHBTAR0 = 0; + writel(0, PCIBRI_AHBCTL0); + writel(PKUNITY_PCIBRI_BASE | PCIBRI_BARx_MEM, PCIBRI_AHBBAR0); + writel(0xFFFF0000, PCIBRI_AHBAMR0); + writel(0, PCIBRI_AHBTAR0); - PCIBRI_AHBCTL1 = PCIBRI_CTLx_AT; - PCIBRI_AHBBAR1 = PKUNITY_PCILIO_BASE | PCIBRI_BARx_IO; - PCIBRI_AHBAMR1 = 0xFFFF0000; - PCIBRI_AHBTAR1 = 0x00000000; + writel(PCIBRI_CTLx_AT, PCIBRI_AHBCTL1); + writel(PKUNITY_PCILIO_BASE | PCIBRI_BARx_IO, PCIBRI_AHBBAR1); + writel(0xFFFF0000, PCIBRI_AHBAMR1); + writel(0x00000000, PCIBRI_AHBTAR1); - PCIBRI_AHBCTL2 = PCIBRI_CTLx_PREF; - PCIBRI_AHBBAR2 = PKUNITY_PCIMEM_BASE | PCIBRI_BARx_MEM; - PCIBRI_AHBAMR2 = 0xF8000000; - PCIBRI_AHBTAR2 = 0; + writel(PCIBRI_CTLx_PREF, PCIBRI_AHBCTL2); + writel(PKUNITY_PCIMEM_BASE | PCIBRI_BARx_MEM, PCIBRI_AHBBAR2); + writel(0xF8000000, PCIBRI_AHBAMR2); + writel(0, PCIBRI_AHBTAR2); - PCIBRI_BAR1 = PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM; + writel(PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM, PCIBRI_BAR1); - PCIBRI_PCICTL0 = PCIBRI_CTLx_AT | PCIBRI_CTLx_PREF; - PCIBRI_PCIBAR0 = PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM; - PCIBRI_PCIAMR0 = 0xF8000000; - PCIBRI_PCITAR0 = PKUNITY_SDRAM_BASE; + writel(PCIBRI_CTLx_AT | PCIBRI_CTLx_PREF, PCIBRI_PCICTL0); + writel(PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM, PCIBRI_PCIBAR0); + writel(0xF8000000, PCIBRI_PCIAMR0); + writel(PKUNITY_SDRAM_BASE, PCIBRI_PCITAR0); - PCIBRI_CMD = PCIBRI_CMD | PCIBRI_CMD_IO | PCIBRI_CMD_MEM; + writel(readl(PCIBRI_CMD) | PCIBRI_CMD_IO | PCIBRI_CMD_MEM, PCIBRI_CMD); } static int __init pci_puv3_map_irq(struct pci_dev *dev, u8 slot, u8 pin) diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c index 8d4a273ae086..ba401df971ed 100644 --- a/arch/unicore32/kernel/process.c +++ b/arch/unicore32/kernel/process.c @@ -125,9 +125,9 @@ void machine_restart(char *cmd) /* Jump into ROM at address 0xffff0000 */ cpu_reset(VECTORS_BASE); } else { - PM_PLLSYSCFG = 0x00002001; /* cpu clk = 250M */ - PM_PLLDDRCFG = 0x00100800; /* ddr clk = 44M */ - PM_PLLVGACFG = 0x00002001; /* vga clk = 250M */ + writel(0x00002001, PM_PLLSYSCFG); /* cpu clk = 250M */ + writel(0x00100800, PM_PLLDDRCFG); /* ddr clk = 44M */ + writel(0x00002001, PM_PLLVGACFG); /* vga clk = 250M */ /* Use on-chip reset capability */ /* following instructions must be in one icache line */ @@ -141,10 +141,10 @@ void machine_restart(char *cmd) " nop; nop; nop\n\t" /* prefetch 3 instructions at most */ : - : "r" ((unsigned long)&PM_PMCR), + : "r" (PM_PMCR), "r" (PM_PMCR_CFBSYS | PM_PMCR_CFBDDR | PM_PMCR_CFBVGA), - "r" ((unsigned long)&RESETC_SWRR), + "r" (RESETC_SWRR), "r" (RESETC_SWRR_SRB) : "r0", "memory"); } diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c index 26cc52b51e7b..6edf928a106c 100644 --- a/arch/unicore32/kernel/puv3-core.c +++ b/arch/unicore32/kernel/puv3-core.c @@ -36,7 +36,7 @@ */ unsigned long long sched_clock(void) { - unsigned long long v = cnt32_to_63(OST_OSCR); + unsigned long long v = cnt32_to_63(readl(OST_OSCR)); /* original conservative method, but overflow frequently * v *= NSEC_PER_SEC >> 12; @@ -187,15 +187,15 @@ static void puv3_cpu_pm_restore(unsigned long *sleep_save) static int puv3_cpu_pm_prepare(void) { /* set resume return address */ - PM_DIVCFG = virt_to_phys(puv3_cpu_resume); + writel(virt_to_phys(puv3_cpu_resume), PM_DIVCFG); return 0; } static void puv3_cpu_pm_enter(suspend_state_t state) { /* Clear reset status */ - RESETC_RSSR = RESETC_RSSR_HWR | RESETC_RSSR_WDR - | RESETC_RSSR_SMR | RESETC_RSSR_SWR; + writel(RESETC_RSSR_HWR | RESETC_RSSR_WDR + | RESETC_RSSR_SMR | RESETC_RSSR_SWR, RESETC_RSSR); switch (state) { /* case PM_SUSPEND_ON: @@ -242,7 +242,7 @@ void puv3_ps2_init(void) struct clk *bclk32; bclk32 = clk_get(NULL, "BUS32_CLK"); - PS2_CNT = clk_get_rate(bclk32) / 200000; /* should > 5us */ + writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */ } void __init puv3_core_init(void) diff --git a/arch/unicore32/kernel/rtc.c b/arch/unicore32/kernel/rtc.c index 5e4db4158589..c5f068295b51 100644 --- a/arch/unicore32/kernel/rtc.c +++ b/arch/unicore32/kernel/rtc.c @@ -41,7 +41,7 @@ static irqreturn_t puv3_rtc_alarmirq(int irq, void *id) { struct rtc_device *rdev = id; - RTC_RTSR |= RTC_RTSR_AL; + writel(readl(RTC_RTSR) | RTC_RTSR_AL, RTC_RTSR); rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); return IRQ_HANDLED; } @@ -50,7 +50,7 @@ static irqreturn_t puv3_rtc_tickirq(int irq, void *id) { struct rtc_device *rdev = id; - RTC_RTSR |= RTC_RTSR_HZ; + writel(readl(RTC_RTSR) | RTC_RTSR_HZ, RTC_RTSR); rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); return IRQ_HANDLED; } @@ -62,12 +62,12 @@ static void puv3_rtc_setaie(int to) pr_debug("%s: aie=%d\n", __func__, to); - tmp = RTC_RTSR & ~RTC_RTSR_ALE; + tmp = readl(RTC_RTSR) & ~RTC_RTSR_ALE; if (to) tmp |= RTC_RTSR_ALE; - RTC_RTSR = tmp; + writel(tmp, RTC_RTSR); } static int puv3_rtc_setpie(struct device *dev, int enabled) @@ -77,12 +77,12 @@ static int puv3_rtc_setpie(struct device *dev, int enabled) pr_debug("%s: pie=%d\n", __func__, enabled); spin_lock_irq(&puv3_rtc_pie_lock); - tmp = RTC_RTSR & ~RTC_RTSR_HZE; + tmp = readl(RTC_RTSR) & ~RTC_RTSR_HZE; if (enabled) tmp |= RTC_RTSR_HZE; - RTC_RTSR = tmp; + writel(tmp, RTC_RTSR); spin_unlock_irq(&puv3_rtc_pie_lock); return 0; @@ -97,7 +97,7 @@ static int puv3_rtc_setfreq(struct device *dev, int freq) static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) { - rtc_time_to_tm(RTC_RCNR, rtc_tm); + rtc_time_to_tm(readl(RTC_RCNR), rtc_tm); pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, @@ -115,7 +115,7 @@ static int puv3_rtc_settime(struct device *dev, struct rtc_time *tm) tm->tm_hour, tm->tm_min, tm->tm_sec); rtc_tm_to_time(tm, &rtc_count); - RTC_RCNR = rtc_count; + writel(rtc_count, RTC_RCNR); return 0; } @@ -124,9 +124,9 @@ static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_time *alm_tm = &alrm->time; - rtc_time_to_tm(RTC_RTAR, alm_tm); + rtc_time_to_tm(readl(RTC_RTAR), alm_tm); - alrm->enabled = RTC_RTSR & RTC_RTSR_ALE; + alrm->enabled = readl(RTC_RTSR) & RTC_RTSR_ALE; pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", alrm->enabled, @@ -147,7 +147,7 @@ static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec); rtc_tm_to_time(tm, &rtcalarm_count); - RTC_RTAR = rtcalarm_count; + writel(rtcalarm_count, RTC_RTAR); puv3_rtc_setaie(alrm->enabled); @@ -162,7 +162,7 @@ static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) static int puv3_rtc_proc(struct device *dev, struct seq_file *seq) { seq_printf(seq, "periodic_IRQ\t: %s\n", - (RTC_RTSR & RTC_RTSR_HZE) ? "yes" : "no"); + (readl(RTC_RTSR) & RTC_RTSR_HZE) ? "yes" : "no"); return 0; } @@ -222,13 +222,13 @@ static const struct rtc_class_ops puv3_rtcops = { static void puv3_rtc_enable(struct platform_device *pdev, int en) { if (!en) { - RTC_RTSR &= ~RTC_RTSR_HZE; + writel(readl(RTC_RTSR) & ~RTC_RTSR_HZE, RTC_RTSR); } else { /* re-enable the device, and check it is ok */ - if ((RTC_RTSR & RTC_RTSR_HZE) == 0) { + if ((readl(RTC_RTSR) & RTC_RTSR_HZE) == 0) { dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); - RTC_RTSR |= RTC_RTSR_HZE; + writel(readl(RTC_RTSR) | RTC_RTSR_HZE, RTC_RTSR); } } } @@ -331,7 +331,7 @@ static int ticnt_save; static int puv3_rtc_suspend(struct platform_device *pdev, pm_message_t state) { /* save RTAR for anyone using periodic interrupts */ - ticnt_save = RTC_RTAR; + ticnt_save = readl(RTC_RTAR); puv3_rtc_enable(pdev, 0); return 0; } @@ -339,7 +339,7 @@ static int puv3_rtc_suspend(struct platform_device *pdev, pm_message_t state) static int puv3_rtc_resume(struct platform_device *pdev) { puv3_rtc_enable(pdev, 1); - RTC_RTAR = ticnt_save; + writel(ticnt_save, RTC_RTAR); return 0; } #else diff --git a/arch/unicore32/kernel/time.c b/arch/unicore32/kernel/time.c index 8bb4b815bce9..080710c09241 100644 --- a/arch/unicore32/kernel/time.c +++ b/arch/unicore32/kernel/time.c @@ -26,8 +26,8 @@ static irqreturn_t puv3_ost0_interrupt(int irq, void *dev_id) struct clock_event_device *c = dev_id; /* Disarm the compare/match, signal the event. */ - OST_OIER &= ~OST_OIER_E0; - OST_OSSR &= ~OST_OSSR_M0; + writel(readl(OST_OIER) & ~OST_OIER_E0, OST_OIER); + writel(readl(OST_OSSR) & ~OST_OSSR_M0, OST_OSSR); c->event_handler(c); return IRQ_HANDLED; @@ -38,10 +38,10 @@ puv3_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c) { unsigned long next, oscr; - OST_OIER |= OST_OIER_E0; - next = OST_OSCR + delta; - OST_OSMR0 = next; - oscr = OST_OSCR; + writel(readl(OST_OIER) | OST_OIER_E0, OST_OIER); + next = readl(OST_OSCR) + delta; + writel(next, OST_OSMR0); + oscr = readl(OST_OSCR); return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; } @@ -53,8 +53,8 @@ puv3_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c) case CLOCK_EVT_MODE_ONESHOT: case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - OST_OIER &= ~OST_OIER_E0; - OST_OSSR &= ~OST_OSSR_M0; + writel(readl(OST_OIER) & ~OST_OIER_E0, OST_OIER); + writel(readl(OST_OSSR) & ~OST_OSSR_M0, OST_OSSR); break; case CLOCK_EVT_MODE_RESUME: @@ -73,7 +73,7 @@ static struct clock_event_device ckevt_puv3_osmr0 = { static cycle_t puv3_read_oscr(struct clocksource *cs) { - return OST_OSCR; + return readl(OST_OSCR); } static struct clocksource cksrc_puv3_oscr = { @@ -93,8 +93,8 @@ static struct irqaction puv3_timer_irq = { void __init time_init(void) { - OST_OIER = 0; /* disable any timer interrupts */ - OST_OSSR = 0; /* clear status on all timers */ + writel(0, OST_OIER); /* disable any timer interrupts */ + writel(0, OST_OSSR); /* clear status on all timers */ clockevents_calc_mult_shift(&ckevt_puv3_osmr0, CLOCK_TICK_RATE, 5); @@ -115,26 +115,26 @@ unsigned long osmr[4], oier; void puv3_timer_suspend(void) { - osmr[0] = OST_OSMR0; - osmr[1] = OST_OSMR1; - osmr[2] = OST_OSMR2; - osmr[3] = OST_OSMR3; - oier = OST_OIER; + osmr[0] = readl(OST_OSMR0); + osmr[1] = readl(OST_OSMR1); + osmr[2] = readl(OST_OSMR2); + osmr[3] = readl(OST_OSMR3); + oier = readl(OST_OIER); } void puv3_timer_resume(void) { - OST_OSSR = 0; - OST_OSMR0 = osmr[0]; - OST_OSMR1 = osmr[1]; - OST_OSMR2 = osmr[2]; - OST_OSMR3 = osmr[3]; - OST_OIER = oier; + writel(0, OST_OSSR); + writel(osmr[0], OST_OSMR0); + writel(osmr[1], OST_OSMR1); + writel(osmr[2], OST_OSMR2); + writel(osmr[3], OST_OSMR3); + writel(oier, OST_OIER); /* * OSMR0 is the system timer: make sure OSCR is sufficiently behind */ - OST_OSCR = OST_OSMR0 - LATCH; + writel(readl(OST_OSMR0) - LATCH, OST_OSCR); } #else void puv3_timer_suspend(void) { }; diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h index 620b040b81b0..73f5cc124a36 100644 --- a/drivers/input/serio/i8042-unicore32io.h +++ b/drivers/input/serio/i8042-unicore32io.h @@ -29,11 +29,11 @@ /* * Register numbers. */ -#define I8042_COMMAND_REG ((volatile void __iomem *)&PS2_COMMAND) -#define I8042_STATUS_REG ((volatile void __iomem *)&PS2_STATUS) -#define I8042_DATA_REG ((volatile void __iomem *)&PS2_DATA) +#define I8042_COMMAND_REG PS2_COMMAND +#define I8042_STATUS_REG PS2_STATUS +#define I8042_DATA_REG PS2_DATA -#define I8042_REGION_START (resource_size_t)(&PS2_DATA) +#define I8042_REGION_START (resource_size_t)(PS2_DATA) #define I8042_REGION_SIZE (resource_size_t)(16) static inline int i8042_read_data(void) -- cgit v1.2.3 From d10e4a660d11212a41ac5d2c116a655e25e2d38a Mon Sep 17 00:00:00 2001 From: GuanXuetao Date: Sat, 26 Feb 2011 21:29:29 +0800 Subject: unicore32 machine related files: add i2c bus drivers for pkunity-v3 soc change from original version -- by advice of Jean Delvare 1. remove global variable i2c_reg, replaced by local variables 2. replace ENXIO with ENODEV when no platform resources 3. add adapter->nr assignment before i2c_add_numbered_adapter() call 4. add judgement for i2c_del_adapter() return value 5. release adapter when driver removed 6. add __devexit for puv3_i2c_remove() function 7. modify several names to more appropriated ones Signed-off-by: Guan Xuetao Acked-by: Arnd Bergmann --- MAINTAINERS | 1 + arch/unicore32/configs/debug_defconfig | 4 + drivers/i2c/busses/Kconfig | 11 ++ drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-puv3.c | 306 +++++++++++++++++++++++++++++++++ 5 files changed, 323 insertions(+) create mode 100644 drivers/i2c/busses/i2c-puv3.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index e8b15bfec6d6..fa842ba63a1b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4901,6 +4901,7 @@ W: http://mprc.pku.edu.cn/~guanxuetao/linux S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.git F: drivers/input/serio/i8042-unicore32io.h +F: drivers/i2c/busses/i2c-puv3.c PMC SIERRA MaxRAID DRIVER M: Anil Ravindranath diff --git a/arch/unicore32/configs/debug_defconfig b/arch/unicore32/configs/debug_defconfig index 3647f68147da..bf42abdd9683 100644 --- a/arch/unicore32/configs/debug_defconfig +++ b/arch/unicore32/configs/debug_defconfig @@ -114,6 +114,10 @@ CONFIG_INPUT_EVDEV=m # Keyboards CONFIG_KEYBOARD_GPIO=m +# I2C support +CONFIG_I2C=y +CONFIG_I2C_PUV3=y + # Hardware Monitoring support #CONFIG_SENSORS_LM75=m # Generic Thermal sysfs driver diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 113505a6434e..cbfcf6fb4a61 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -523,6 +523,17 @@ config I2C_PNX This driver can also be built as a module. If so, the module will be called i2c-pnx. +config I2C_PUV3 + tristate "PKUnity v3 I2C bus support" + depends on UNICORE32 && ARCH_PUV3 + select I2C_ALGOBIT + help + This driver supports the I2C IP inside the PKUnity-v3 SoC. + This I2C bus controller is under AMBA/AXI bus. + + This driver can also be built as a module. If so, the module + will be called i2c-puv3. + config I2C_PXA tristate "Intel PXA2XX I2C adapter" depends on ARCH_PXA || ARCH_MMP diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 9d2d0ec7fb23..a83966acc5ab 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o obj-$(CONFIG_I2C_PNX) += i2c-pnx.o +obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o obj-$(CONFIG_I2C_S6000) += i2c-s6000.o diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c new file mode 100644 index 000000000000..fac673940849 --- /dev/null +++ b/drivers/i2c/busses/i2c-puv3.c @@ -0,0 +1,306 @@ +/* + * I2C driver for PKUnity-v3 SoC + * Code specific to PKUnity SoC and UniCore ISA + * + * Maintained by GUAN Xue-tao + * Copyright (C) 2001-2010 Guan Xuetao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Poll the i2c status register until the specified bit is set. + * Returns 0 if timed out (100 msec). + */ +static short poll_status(unsigned long bit) +{ + int loop_cntr = 1000; + + if (bit & I2C_STATUS_TFNF) { + do { + udelay(10); + } while (!(readl(I2C_STATUS) & bit) && (--loop_cntr > 0)); + } else { + /* RXRDY handler */ + do { + if (readl(I2C_TAR) == I2C_TAR_EEPROM) + msleep(20); + else + udelay(10); + } while (!(readl(I2C_RXFLR) & 0xf) && (--loop_cntr > 0)); + } + + return (loop_cntr > 0); +} + +static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length) +{ + int i2c_reg = *buf; + + /* Read data */ + while (length--) { + if (!poll_status(I2C_STATUS_TFNF)) { + dev_dbg(&adap->dev, "Tx FIFO Not Full timeout\n"); + return -ETIMEDOUT; + } + + /* send addr */ + writel(i2c_reg | I2C_DATACMD_WRITE, I2C_DATACMD); + + /* get ready to next write */ + i2c_reg++; + + /* send read CMD */ + writel(I2C_DATACMD_READ, I2C_DATACMD); + + /* wait until the Rx FIFO have available */ + if (!poll_status(I2C_STATUS_RFNE)) { + dev_dbg(&adap->dev, "RXRDY timeout\n"); + return -ETIMEDOUT; + } + + /* read the data to buf */ + *buf = (readl(I2C_DATACMD) & I2C_DATACMD_DAT_MASK); + buf++; + } + + return 0; +} + +static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length) +{ + int i2c_reg = *buf; + + /* Do nothing but storing the reg_num to a static variable */ + if (i2c_reg == -1) { + printk(KERN_WARNING "Error i2c reg\n"); + return -ETIMEDOUT; + } + + if (length == 1) + return 0; + + buf++; + length--; + while (length--) { + /* send addr */ + writel(i2c_reg | I2C_DATACMD_WRITE, I2C_DATACMD); + + /* send write CMD */ + writel(*buf | I2C_DATACMD_WRITE, I2C_DATACMD); + + /* wait until the Rx FIFO have available */ + msleep(20); + + /* read the data to buf */ + i2c_reg++; + buf++; + } + + return 0; +} + +/* + * Generic i2c master transfer entrypoint. + * + */ +static int puv3_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, + int num) +{ + int i, ret; + unsigned char swap; + + /* Disable i2c */ + writel(I2C_ENABLE_DISABLE, I2C_ENABLE); + + /* Set the work mode and speed*/ + writel(I2C_CON_MASTER | I2C_CON_SPEED_STD | I2C_CON_SLAVEDISABLE, I2C_CON); + + writel(pmsg->addr, I2C_TAR); + + /* Enable i2c */ + writel(I2C_ENABLE_ENABLE, I2C_ENABLE); + + dev_dbg(&adap->dev, "puv3_i2c_xfer: processing %d messages:\n", num); + + for (i = 0; i < num; i++) { + dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i, + pmsg->flags & I2C_M_RD ? "read" : "writ", + pmsg->len, pmsg->len > 1 ? "s" : "", + pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr); + + if (pmsg->len && pmsg->buf) { /* sanity check */ + if (pmsg->flags & I2C_M_RD) + ret = xfer_read(adap, pmsg->buf, pmsg->len); + else + ret = xfer_write(adap, pmsg->buf, pmsg->len); + + if (ret) + return ret; + + } + dev_dbg(&adap->dev, "transfer complete\n"); + pmsg++; /* next message */ + } + + /* XXX: fixup be16_to_cpu in bq27x00_battery.c */ + if (pmsg->addr == I2C_TAR_PWIC) { + swap = pmsg->buf[0]; + pmsg->buf[0] = pmsg->buf[1]; + pmsg->buf[1] = swap; + } + + return i; +} + +/* + * Return list of supported functionality. + */ +static u32 puv3_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm puv3_i2c_algorithm = { + .master_xfer = puv3_i2c_xfer, + .functionality = puv3_i2c_func, +}; + +/* + * Main initialization routine. + */ +static int __devinit puv3_i2c_probe(struct platform_device *pdev) +{ + struct i2c_adapter *adapter; + struct resource *mem; + int rc; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) + return -ENODEV; + + if (!request_mem_region(mem->start, resource_size(mem), "puv3_i2c")) + return -EBUSY; + + adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); + if (adapter == NULL) { + dev_err(&pdev->dev, "can't allocate inteface!\n"); + rc = -ENOMEM; + goto fail_nomem; + } + snprintf(adapter->name, sizeof(adapter->name), "PUV3-I2C at 0x%08x", + mem->start); + adapter->algo = &puv3_i2c_algorithm; + adapter->class = I2C_CLASS_HWMON; + adapter->dev.parent = &pdev->dev; + + platform_set_drvdata(pdev, adapter); + + adapter->nr = pdev->id; + rc = i2c_add_numbered_adapter(adapter); + if (rc) { + dev_err(&pdev->dev, "Adapter '%s' registration failed\n", + adapter->name); + goto fail_add_adapter; + } + + dev_info(&pdev->dev, "PKUnity v3 i2c bus adapter.\n"); + return 0; + +fail_add_adapter: + platform_set_drvdata(pdev, NULL); + kfree(adapter); +fail_nomem: + release_mem_region(mem->start, resource_size(mem)); + + return rc; +} + +static int __devexit puv3_i2c_remove(struct platform_device *pdev) +{ + struct i2c_adapter *adapter = platform_get_drvdata(pdev); + struct resource *mem; + int rc; + + rc = i2c_del_adapter(adapter); + if (rc) { + dev_err(&pdev->dev, "Adapter '%s' delete fail\n", + adapter->name); + return rc; + } + + put_device(&pdev->dev); + platform_set_drvdata(pdev, NULL); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(mem->start, resource_size(mem)); + + return rc; +} + +#ifdef CONFIG_PM +static int puv3_i2c_suspend(struct platform_device *dev, pm_message_t state) +{ + int poll_count; + /* Disable the IIC */ + writel(I2C_ENABLE_DISABLE, I2C_ENABLE); + for (poll_count = 0; poll_count < 50; poll_count++) { + if (readl(I2C_ENSTATUS) & I2C_ENSTATUS_ENABLE) + udelay(25); + } + + return 0; +} + +static int puv3_i2c_resume(struct platform_device *dev) +{ + return 0 ; +} +#else +#define puv3_i2c_suspend NULL +#define puv3_i2c_resume NULL +#endif + +MODULE_ALIAS("platform:puv3_i2c"); + +static struct platform_driver puv3_i2c_driver = { + .probe = puv3_i2c_probe, + .remove = __devexit_p(puv3_i2c_remove), + .suspend = puv3_i2c_suspend, + .resume = puv3_i2c_resume, + .driver = { + .name = "PKUnity-v3-I2C", + .owner = THIS_MODULE, + } +}; + +static int __init puv3_i2c_init(void) +{ + return platform_driver_register(&puv3_i2c_driver); +} + +static void __exit puv3_i2c_exit(void) +{ + platform_driver_unregister(&puv3_i2c_driver); +} + +module_init(puv3_i2c_init); +module_exit(puv3_i2c_exit); + +MODULE_DESCRIPTION("PKUnity v3 I2C driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From ce443ab5fd536941da1d529ba3963324f941fc29 Mon Sep 17 00:00:00 2001 From: GuanXuetao Date: Sat, 26 Feb 2011 21:39:10 +0800 Subject: unicore32 machine related: add frame buffer driver for pkunity-v3 soc change from original version -- by advice of Paul Mundt 1. remove videomemorysize definitions 2. remove unifb_enable and unifb_setup 3. use dev_warn instead of printk in fb driver 4. remove judgement for FB_ACCEL_PUV3_UNIGFX 5. adjust clk_get and clk_set_rate calls 6. add resources definitions 7. remove unifb_option 8. adjust register for platform_device 9. adjust unifb_ops position and unifb_regs assignment position Signed-off-by: Guan Xuetao Acked-by: Arnd Bergmann --- MAINTAINERS | 1 + arch/unicore32/configs/debug_defconfig | 3 +- arch/unicore32/include/mach/memory.h | 2 +- arch/unicore32/kernel/puv3-core.c | 15 + drivers/video/Kconfig | 11 + drivers/video/Makefile | 1 + drivers/video/fb-puv3.c | 846 +++++++++++++++++++++++++++++++++ include/linux/fb.h | 2 + 8 files changed, 879 insertions(+), 2 deletions(-) create mode 100644 drivers/video/fb-puv3.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index fa842ba63a1b..98f942eb7286 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4902,6 +4902,7 @@ S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.git F: drivers/input/serio/i8042-unicore32io.h F: drivers/i2c/busses/i2c-puv3.c +F: drivers/video/fb-puv3.c PMC SIERRA MaxRAID DRIVER M: Anil Ravindranath diff --git a/arch/unicore32/configs/debug_defconfig b/arch/unicore32/configs/debug_defconfig index bf42abdd9683..b5fbde9f1cb2 100644 --- a/arch/unicore32/configs/debug_defconfig +++ b/arch/unicore32/configs/debug_defconfig @@ -66,7 +66,6 @@ CONFIG_LCD_BACKLIGHT=n CONFIG_PUV3_RTC=y CONFIG_PUV3_UMAL=y -CONFIG_PUV3_UNIGFX=y CONFIG_PUV3_MUSB=n CONFIG_PUV3_AC97=n CONFIG_PUV3_NAND=n @@ -130,6 +129,8 @@ CONFIG_VIDEO_DEV=n CONFIG_USB_VIDEO_CLASS=n # Graphics support +CONFIG_FB=y +CONFIG_FB_PUV3_UNIGFX=y # Console display driver support CONFIG_VGA_CONSOLE=n CONFIG_FRAMEBUFFER_CONSOLE=y diff --git a/arch/unicore32/include/mach/memory.h b/arch/unicore32/include/mach/memory.h index 541949dfa5b4..b774eff3ea65 100644 --- a/arch/unicore32/include/mach/memory.h +++ b/arch/unicore32/include/mach/memory.h @@ -50,7 +50,7 @@ void puv3_pci_adjust_zones(unsigned long *size, unsigned long *holes); /* kuser area */ #define KUSER_VECPAGE_BASE (KUSER_BASE + UL(0x3fff0000)) -#define KUSER_UNIGFX_BASE (KUSER_BASE + PKUNITY_UNIGFX_MMAP_BASE) +#define KUSER_UNIGFX_BASE (PAGE_OFFSET + PKUNITY_UNIGFX_MMAP_BASE) /* kuser_vecpage (0xbfff0000) is ro, and vectors page (0xffff0000) is rw */ #define kuser_vecpage_to_vectors(x) ((x) - (KUSER_VECPAGE_BASE) \ + (VECTORS_BASE)) diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c index 6edf928a106c..7d10e7b07c20 100644 --- a/arch/unicore32/kernel/puv3-core.c +++ b/arch/unicore32/kernel/puv3-core.c @@ -93,6 +93,19 @@ static struct resource puv3_mmc_resources[] = { }, }; +static struct resource puv3_unigfx_resources[] = { + [0] = { + .start = PKUNITY_UNIGFX_BASE, + .end = PKUNITY_UNIGFX_BASE + 0xfff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PKUNITY_UNIGFX_MMAP_BASE, + .end = PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE, + .flags = IORESOURCE_MEM, + }, +}; + static struct resource puv3_rtc_resources[] = { [0] = { .start = PKUNITY_RTC_BASE, @@ -256,6 +269,8 @@ void __init puv3_core_init(void) puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources)); platform_device_register_simple("PKUnity-v3-MMC", -1, puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources)); + platform_device_register_simple("PKUnity-v3-UNIGFX", -1, + puv3_unigfx_resources, ARRAY_SIZE(puv3_unigfx_resources)); platform_device_register_simple("PKUnity-v3-PWM", -1, puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources)); platform_device_register_simple("PKUnity-v3-UART", 0, diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 6bafb51bb437..ec55a87899ab 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2365,6 +2365,17 @@ config FB_JZ4740 help Framebuffer support for the JZ4740 SoC. +config FB_PUV3_UNIGFX + tristate "PKUnity v3 Unigfx framebuffer support" + depends on FB && UNICORE32 && ARCH_PUV3 + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + help + Choose this option if you want to use the Unigfx device as a + framebuffer device. Without the support of PCI & AGP. + source "drivers/video/omap/Kconfig" source "drivers/video/omap2/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 8c8fabdff9d0..b0eb3da24670 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -139,6 +139,7 @@ obj-$(CONFIG_FB_MB862XX) += mb862xx/ obj-$(CONFIG_FB_MSM) += msm/ obj-$(CONFIG_FB_NUC900) += nuc900fb.o obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o +obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c new file mode 100644 index 000000000000..dbd2dc4745d1 --- /dev/null +++ b/drivers/video/fb-puv3.c @@ -0,0 +1,846 @@ +/* + * Frame Buffer Driver for PKUnity-v3 Unigfx + * Code specific to PKUnity SoC and UniCore ISA + * + * Maintained by GUAN Xue-tao + * Copyright (C) 2001-2010 Guan Xuetao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Platform_data reserved for unifb registers. */ +#define UNIFB_REGS_NUM 10 +/* RAM reserved for the frame buffer. */ +#define UNIFB_MEMSIZE (SZ_4M) /* 4 MB for 1024*768*32b */ + +/* + * cause UNIGFX don not have EDID + * all the modes are organized as follow + */ +static const struct fb_videomode unifb_modes[] = { + /* 0 640x480-60 VESA */ + { "640x480@60", 60, 640, 480, 25175000, 48, 16, 34, 10, 96, 1, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 1 640x480-75 VESA */ + { "640x480@75", 75, 640, 480, 31500000, 120, 16, 18, 1, 64, 1, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 2 800x600-60 VESA */ + { "800x600@60", 60, 800, 600, 40000000, 88, 40, 26, 1, 128, 1, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 3 800x600-75 VESA */ + { "800x600@75", 75, 800, 600, 49500000, 160, 16, 23, 1, 80, 1, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 4 1024x768-60 VESA */ + { "1024x768@60", 60, 1024, 768, 65000000, 160, 24, 34, 3, 136, 1, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 5 1024x768-75 VESA */ + { "1024x768@75", 75, 1024, 768, 78750000, 176, 16, 30, 1, 96, 1, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 6 1280x960-60 VESA */ + { "1280x960@60", 60, 1280, 960, 108000000, 312, 96, 38, 1, 112, 1, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 7 1440x900-60 VESA */ + { "1440x900@60", 60, 1440, 900, 106500000, 232, 80, 30, 3, 152, 1, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 8 FIXME 9 1024x600-60 VESA UNTESTED */ + { "1024x600@60", 60, 1024, 600, 50650000, 160, 24, 26, 1, 136, 1, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 9 FIXME 10 1024x600-75 VESA UNTESTED */ + { "1024x600@75", 75, 1024, 600, 61500000, 176, 16, 23, 1, 96, 1, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 10 FIXME 11 1366x768-60 VESA UNTESTED */ + { "1366x768@60", 60, 1366, 768, 85500000, 256, 58, 18, 1, 112, 3, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, +}; + +static struct fb_var_screeninfo unifb_default = { + .xres = 640, + .yres = 480, + .xres_virtual = 640, + .yres_virtual = 480, + .bits_per_pixel = 16, + .red = { 11, 5, 0 }, + .green = { 5, 6, 0 }, + .blue = { 0, 5, 0 }, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .pixclock = 25175000, + .left_margin = 48, + .right_margin = 16, + .upper_margin = 33, + .lower_margin = 10, + .hsync_len = 96, + .vsync_len = 2, + .vmode = FB_VMODE_NONINTERLACED, +}; + +static struct fb_fix_screeninfo unifb_fix = { + .id = "UNIGFX FB", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .xpanstep = 1, + .ypanstep = 1, + .ywrapstep = 1, + .accel = FB_ACCEL_NONE, +}; + +static void unifb_sync(struct fb_info *info) +{ + /* TODO: may, this can be replaced by interrupt */ + int cnt; + + for (cnt = 0; cnt < 0x10000000; cnt++) { + if (readl(UGE_COMMAND) & 0x1000000) + return; + } + + if (cnt > 0x8000000) + dev_warn(info->device, "Warning: UniGFX GE time out ...\n"); +} + +static void unifb_prim_fillrect(struct fb_info *info, + const struct fb_fillrect *region) +{ + int awidth = region->width; + int aheight = region->height; + int m_iBpp = info->var.bits_per_pixel; + int screen_width = info->var.xres; + int src_sel = 1; /* from fg_color */ + int pat_sel = 1; + int src_x0 = 0; + int dst_x0 = region->dx; + int src_y0 = 0; + int dst_y0 = region->dy; + int rop_alpha_sel = 0; + int rop_alpha_code = 0xCC; + int x_dir = 1; + int y_dir = 1; + int alpha_r = 0; + int alpha_sel = 0; + int dst_pitch = screen_width * (m_iBpp / 8); + int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8); + int src_pitch = screen_width * (m_iBpp / 8); + int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8); + unsigned int command = 0; + int clip_region = 0; + int clip_en = 0; + int tp_en = 0; + int fg_color = 0; + int bottom = info->var.yres - 1; + int right = info->var.xres - 1; + int top = 0; + + bottom = (bottom << 16) | right; + command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16) + | (x_dir << 20) | (y_dir << 21) | (command << 24) + | (clip_region << 23) | (clip_en << 22) | (tp_en << 27); + src_pitch = (dst_pitch << 16) | src_pitch; + awidth = awidth | (aheight << 16); + alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff) + | (alpha_sel << 16); + src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16); + dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16); + fg_color = region->color; + + unifb_sync(info); + + writel(((u32 *)(info->pseudo_palette))[fg_color], UGE_FCOLOR); + writel(0, UGE_BCOLOR); + writel(src_pitch, UGE_PITCH); + writel(src_offset, UGE_SRCSTART); + writel(dst_offset, UGE_DSTSTART); + writel(awidth, UGE_WIDHEIGHT); + writel(top, UGE_CLIP0); + writel(bottom, UGE_CLIP1); + writel(alpha_r, UGE_ROPALPHA); + writel(src_x0, UGE_SRCXY); + writel(dst_x0, UGE_DSTXY); + writel(command, UGE_COMMAND); +} + +static void unifb_fillrect(struct fb_info *info, + const struct fb_fillrect *region) +{ + struct fb_fillrect modded; + int vxres, vyres; + + if (info->flags & FBINFO_HWACCEL_DISABLED) { + sys_fillrect(info, region); + return; + } + + vxres = info->var.xres_virtual; + vyres = info->var.yres_virtual; + + memcpy(&modded, region, sizeof(struct fb_fillrect)); + + if (!modded.width || !modded.height || + modded.dx >= vxres || modded.dy >= vyres) + return; + + if (modded.dx + modded.width > vxres) + modded.width = vxres - modded.dx; + if (modded.dy + modded.height > vyres) + modded.height = vyres - modded.dy; + + unifb_prim_fillrect(info, &modded); +} + +static void unifb_prim_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ + int awidth = area->width; + int aheight = area->height; + int m_iBpp = info->var.bits_per_pixel; + int screen_width = info->var.xres; + int src_sel = 2; /* from mem */ + int pat_sel = 0; + int src_x0 = area->sx; + int dst_x0 = area->dx; + int src_y0 = area->sy; + int dst_y0 = area->dy; + + int rop_alpha_sel = 0; + int rop_alpha_code = 0xCC; + int x_dir = 1; + int y_dir = 1; + + int alpha_r = 0; + int alpha_sel = 0; + int dst_pitch = screen_width * (m_iBpp / 8); + int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8); + int src_pitch = screen_width * (m_iBpp / 8); + int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8); + unsigned int command = 0; + int clip_region = 0; + int clip_en = 1; + int tp_en = 0; + int top = 0; + int bottom = info->var.yres; + int right = info->var.xres; + int fg_color = 0; + int bg_color = 0; + + if (src_x0 < 0) + src_x0 = 0; + if (src_y0 < 0) + src_y0 = 0; + + if (src_y0 - dst_y0 > 0) { + y_dir = 1; + } else { + y_dir = 0; + src_offset = (src_y0 + aheight) * src_pitch + + src_x0 * (m_iBpp / 8); + dst_offset = (dst_y0 + aheight) * dst_pitch + + dst_x0 * (m_iBpp / 8); + src_y0 += aheight; + dst_y0 += aheight; + } + + command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16) | + (x_dir << 20) | (y_dir << 21) | (command << 24) | + (clip_region << 23) | (clip_en << 22) | (tp_en << 27); + src_pitch = (dst_pitch << 16) | src_pitch; + awidth = awidth | (aheight << 16); + alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff) | + (alpha_sel << 16); + src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16); + dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16); + bottom = (bottom << 16) | right; + + unifb_sync(info); + + writel(src_pitch, UGE_PITCH); + writel(src_offset, UGE_SRCSTART); + writel(dst_offset, UGE_DSTSTART); + writel(awidth, UGE_WIDHEIGHT); + writel(top, UGE_CLIP0); + writel(bottom, UGE_CLIP1); + writel(bg_color, UGE_BCOLOR); + writel(fg_color, UGE_FCOLOR); + writel(alpha_r, UGE_ROPALPHA); + writel(src_x0, UGE_SRCXY); + writel(dst_x0, UGE_DSTXY); + writel(command, UGE_COMMAND); +} + +static void unifb_copyarea(struct fb_info *info, const struct fb_copyarea *area) +{ + struct fb_copyarea modded; + u32 vxres, vyres; + modded.sx = area->sx; + modded.sy = area->sy; + modded.dx = area->dx; + modded.dy = area->dy; + modded.width = area->width; + modded.height = area->height; + + if (info->flags & FBINFO_HWACCEL_DISABLED) { + sys_copyarea(info, area); + return; + } + + vxres = info->var.xres_virtual; + vyres = info->var.yres_virtual; + + if (!modded.width || !modded.height || + modded.sx >= vxres || modded.sy >= vyres || + modded.dx >= vxres || modded.dy >= vyres) + return; + + if (modded.sx + modded.width > vxres) + modded.width = vxres - modded.sx; + if (modded.dx + modded.width > vxres) + modded.width = vxres - modded.dx; + if (modded.sy + modded.height > vyres) + modded.height = vyres - modded.sy; + if (modded.dy + modded.height > vyres) + modded.height = vyres - modded.dy; + + unifb_prim_copyarea(info, &modded); +} + +static void unifb_imageblit(struct fb_info *info, const struct fb_image *image) +{ + sys_imageblit(info, image); +} + +static u_long get_line_length(int xres_virtual, int bpp) +{ + u_long length; + + length = xres_virtual * bpp; + length = (length + 31) & ~31; + length >>= 3; + return length; +} + +/* + * Setting the video mode has been split into two parts. + * First part, xxxfb_check_var, must not write anything + * to hardware, it should only verify and adjust var. + * This means it doesn't alter par but it does use hardware + * data from it to check this var. + */ +static int unifb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + u_long line_length; + + /* + * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal! + * as FB_VMODE_SMOOTH_XPAN is only used internally + */ + + if (var->vmode & FB_VMODE_CONUPDATE) { + var->vmode |= FB_VMODE_YWRAP; + var->xoffset = info->var.xoffset; + var->yoffset = info->var.yoffset; + } + + /* + * Some very basic checks + */ + if (!var->xres) + var->xres = 1; + if (!var->yres) + var->yres = 1; + if (var->xres > var->xres_virtual) + var->xres_virtual = var->xres; + if (var->yres > var->yres_virtual) + var->yres_virtual = var->yres; + if (var->bits_per_pixel <= 1) + var->bits_per_pixel = 1; + else if (var->bits_per_pixel <= 8) + var->bits_per_pixel = 8; + else if (var->bits_per_pixel <= 16) + var->bits_per_pixel = 16; + else if (var->bits_per_pixel <= 24) + var->bits_per_pixel = 24; + else if (var->bits_per_pixel <= 32) + var->bits_per_pixel = 32; + else + return -EINVAL; + + if (var->xres_virtual < var->xoffset + var->xres) + var->xres_virtual = var->xoffset + var->xres; + if (var->yres_virtual < var->yoffset + var->yres) + var->yres_virtual = var->yoffset + var->yres; + + /* + * Memory limit + */ + line_length = + get_line_length(var->xres_virtual, var->bits_per_pixel); + if (line_length * var->yres_virtual > UNIFB_MEMSIZE) + return -ENOMEM; + + /* + * Now that we checked it we alter var. The reason being is that the + * video mode passed in might not work but slight changes to it might + * make it work. This way we let the user know what is acceptable. + */ + switch (var->bits_per_pixel) { + case 1: + case 8: + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 0; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 16: /* RGBA 5551 */ + if (var->transp.length) { + var->red.offset = 0; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 5; + var->blue.offset = 10; + var->blue.length = 5; + var->transp.offset = 15; + var->transp.length = 1; + } else { /* RGB 565 */ + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + } + break; + case 24: /* RGB 888 */ + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 16; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 32: /* RGBA 8888 */ + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 24; + var->transp.length = 8; + break; + } + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + var->transp.msb_right = 0; + + return 0; +} + +/* + * This routine actually sets the video mode. It's in here where we + * the hardware state info->par and fix which can be affected by the + * change in par. For this driver it doesn't do much. + */ +static int unifb_set_par(struct fb_info *info) +{ + int hTotal, vTotal, hSyncStart, hSyncEnd, vSyncStart, vSyncEnd; + int format; + +#ifdef CONFIG_PUV3_PM + struct clk *clk_vga; + u32 pixclk = 0; + int i; + + for (i = 0; i <= 10; i++) { + if (info->var.xres == unifb_modes[i].xres + && info->var.yres == unifb_modes[i].yres + && info->var.upper_margin == unifb_modes[i].upper_margin + && info->var.lower_margin == unifb_modes[i].lower_margin + && info->var.left_margin == unifb_modes[i].left_margin + && info->var.right_margin == unifb_modes[i].right_margin + && info->var.hsync_len == unifb_modes[i].hsync_len + && info->var.vsync_len == unifb_modes[i].vsync_len) { + pixclk = unifb_modes[i].pixclock; + break; + } + } + + /* set clock rate */ + clk_vga = clk_get(info->device, "VGA_CLK"); + if (clk_vga == ERR_PTR(-ENOENT)) + return -ENOENT; + + if (pixclk != 0) { + if (clk_set_rate(clk_vga, pixclk)) { /* set clock failed */ + info->fix = unifb_fix; + info->var = unifb_default; + if (clk_set_rate(clk_vga, unifb_default.pixclock)) + return -EINVAL; + } + } +#endif + + info->fix.line_length = get_line_length(info->var.xres_virtual, + info->var.bits_per_pixel); + + hSyncStart = info->var.xres + info->var.right_margin; + hSyncEnd = hSyncStart + info->var.hsync_len; + hTotal = hSyncEnd + info->var.left_margin; + + vSyncStart = info->var.yres + info->var.lower_margin; + vSyncEnd = vSyncStart + info->var.vsync_len; + vTotal = vSyncEnd + info->var.upper_margin; + + switch (info->var.bits_per_pixel) { + case 8: + format = UDE_CFG_DST8; + break; + case 16: + format = UDE_CFG_DST16; + break; + case 24: + format = UDE_CFG_DST24; + break; + case 32: + format = UDE_CFG_DST32; + break; + default: + return -EINVAL; + } + + writel(PKUNITY_UNIGFX_MMAP_BASE, UDE_FSA); + writel(info->var.yres, UDE_LS); + writel(get_line_length(info->var.xres, + info->var.bits_per_pixel) >> 3, UDE_PS); + /* >> 3 for hardware required. */ + writel((hTotal << 16) | (info->var.xres), UDE_HAT); + writel(((hTotal - 1) << 16) | (info->var.xres - 1), UDE_HBT); + writel(((hSyncEnd - 1) << 16) | (hSyncStart - 1), UDE_HST); + writel((vTotal << 16) | (info->var.yres), UDE_VAT); + writel(((vTotal - 1) << 16) | (info->var.yres - 1), UDE_VBT); + writel(((vSyncEnd - 1) << 16) | (vSyncStart - 1), UDE_VST); + writel(UDE_CFG_GDEN_ENABLE | UDE_CFG_TIMEUP_ENABLE + | format | 0xC0000001, UDE_CFG); + + return 0; +} + +/* + * Set a single color register. The values supplied are already + * rounded down to the hardware's capabilities (according to the + * entries in the var structure). Return != 0 for invalid regno. + */ +static int unifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + if (regno >= 256) /* no. of hw registers */ + return 1; + + /* grayscale works only partially under directcolor */ + if (info->var.grayscale) { + /* grayscale = 0.30*R + 0.59*G + 0.11*B */ + red = green = blue = + (red * 77 + green * 151 + blue * 28) >> 8; + } + +#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16) + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + case FB_VISUAL_PSEUDOCOLOR: + red = CNVT_TOHW(red, info->var.red.length); + green = CNVT_TOHW(green, info->var.green.length); + blue = CNVT_TOHW(blue, info->var.blue.length); + transp = CNVT_TOHW(transp, info->var.transp.length); + break; + case FB_VISUAL_DIRECTCOLOR: + red = CNVT_TOHW(red, 8); /* expect 8 bit DAC */ + green = CNVT_TOHW(green, 8); + blue = CNVT_TOHW(blue, 8); + /* hey, there is bug in transp handling... */ + transp = CNVT_TOHW(transp, 8); + break; + } +#undef CNVT_TOHW + /* Truecolor has hardware independent palette */ + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 v; + + if (regno >= 16) + return 1; + + v = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset) | + (transp << info->var.transp.offset); + switch (info->var.bits_per_pixel) { + case 8: + break; + case 16: + case 24: + case 32: + ((u32 *) (info->pseudo_palette))[regno] = v; + break; + default: + return 1; + } + return 0; + } + return 0; +} + +/* + * Pan or Wrap the Display + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ +static int unifb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + if (var->vmode & FB_VMODE_YWRAP) { + if (var->yoffset < 0 + || var->yoffset >= info->var.yres_virtual + || var->xoffset) + return -EINVAL; + } else { + if (var->xoffset + var->xres > info->var.xres_virtual || + var->yoffset + var->yres > info->var.yres_virtual) + return -EINVAL; + } + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; + if (var->vmode & FB_VMODE_YWRAP) + info->var.vmode |= FB_VMODE_YWRAP; + else + info->var.vmode &= ~FB_VMODE_YWRAP; + return 0; +} + +int unifb_mmap(struct fb_info *info, + struct vm_area_struct *vma) +{ + unsigned long size = vma->vm_end - vma->vm_start; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long pos = info->fix.smem_start + offset; + + if (offset + size > info->fix.smem_len) + return -EINVAL; + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + if (io_remap_pfn_range(vma, vma->vm_start, pos >> PAGE_SHIFT, size, + vma->vm_page_prot)) + return -EAGAIN; + + vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ + return 0; + +} + +static struct fb_ops unifb_ops = { + .fb_read = fb_sys_read, + .fb_write = fb_sys_write, + .fb_check_var = unifb_check_var, + .fb_set_par = unifb_set_par, + .fb_setcolreg = unifb_setcolreg, + .fb_pan_display = unifb_pan_display, + .fb_fillrect = unifb_fillrect, + .fb_copyarea = unifb_copyarea, + .fb_imageblit = unifb_imageblit, + .fb_mmap = unifb_mmap, +}; + +/* + * Initialisation + */ +static int unifb_probe(struct platform_device *dev) +{ + struct fb_info *info; + u32 unifb_regs[UNIFB_REGS_NUM]; + int retval = -ENOMEM; + struct resource *iomem, *mapmem; + + info = framebuffer_alloc(sizeof(u32)*256, &dev->dev); + if (!info) + goto err; + + info->screen_base = (char __iomem *)KUSER_UNIGFX_BASE; + info->fbops = &unifb_ops; + + retval = fb_find_mode(&info->var, info, NULL, + unifb_modes, 10, &unifb_modes[0], 16); + + if (!retval || (retval == 4)) + info->var = unifb_default; + + iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); + unifb_fix.mmio_start = iomem->start; + + mapmem = platform_get_resource(dev, IORESOURCE_MEM, 1); + unifb_fix.smem_start = mapmem->start; + unifb_fix.smem_len = UNIFB_MEMSIZE; + + info->fix = unifb_fix; + info->pseudo_palette = info->par; + info->par = NULL; + info->flags = FBINFO_FLAG_DEFAULT; +#ifdef FB_ACCEL_PUV3_UNIGFX + info->fix.accel = FB_ACCEL_PUV3_UNIGFX; +#endif + + retval = fb_alloc_cmap(&info->cmap, 256, 0); + if (retval < 0) + goto err1; + + retval = register_framebuffer(info); + if (retval < 0) + goto err2; + platform_set_drvdata(dev, info); + platform_device_add_data(dev, unifb_regs, sizeof(u32) * UNIFB_REGS_NUM); + + printk(KERN_INFO + "fb%d: Virtual frame buffer device, using %dM of video memory\n", + info->node, UNIFB_MEMSIZE >> 20); + return 0; +err2: + fb_dealloc_cmap(&info->cmap); +err1: + framebuffer_release(info); +err: + return retval; +} + +static int unifb_remove(struct platform_device *dev) +{ + struct fb_info *info = platform_get_drvdata(dev); + + if (info) { + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + } + return 0; +} + +#ifdef CONFIG_PM +static int unifb_resume(struct platform_device *dev) +{ + int rc = 0; + u32 *unifb_regs = dev->dev.platform_data; + + if (dev->dev.power.power_state.event == PM_EVENT_ON) + return 0; + + console_lock(); + + if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND) { + writel(unifb_regs[0], UDE_FSA); + writel(unifb_regs[1], UDE_LS); + writel(unifb_regs[2], UDE_PS); + writel(unifb_regs[3], UDE_HAT); + writel(unifb_regs[4], UDE_HBT); + writel(unifb_regs[5], UDE_HST); + writel(unifb_regs[6], UDE_VAT); + writel(unifb_regs[7], UDE_VBT); + writel(unifb_regs[8], UDE_VST); + writel(unifb_regs[9], UDE_CFG); + } + dev->dev.power.power_state = PMSG_ON; + + console_unlock(); + + return rc; +} + +static int unifb_suspend(struct platform_device *dev, pm_message_t mesg) +{ + u32 *unifb_regs = dev->dev.platform_data; + + unifb_regs[0] = readl(UDE_FSA); + unifb_regs[1] = readl(UDE_LS); + unifb_regs[2] = readl(UDE_PS); + unifb_regs[3] = readl(UDE_HAT); + unifb_regs[4] = readl(UDE_HBT); + unifb_regs[5] = readl(UDE_HST); + unifb_regs[6] = readl(UDE_VAT); + unifb_regs[7] = readl(UDE_VBT); + unifb_regs[8] = readl(UDE_VST); + unifb_regs[9] = readl(UDE_CFG); + + if (mesg.event == dev->dev.power.power_state.event) + return 0; + + switch (mesg.event) { + case PM_EVENT_FREEZE: /* about to take snapshot */ + case PM_EVENT_PRETHAW: /* before restoring snapshot */ + goto done; + } + + console_lock(); + + /* do nothing... */ + + console_unlock(); + +done: + dev->dev.power.power_state = mesg; + + return 0; +} +#else +#define unifb_resume NULL +#define unifb_suspend NULL +#endif + +static struct platform_driver unifb_driver = { + .probe = unifb_probe, + .remove = unifb_remove, + .resume = unifb_resume, + .suspend = unifb_suspend, + .driver = { + .name = "PKUnity-v3-UNIGFX", + }, +}; + +static int __init unifb_init(void) +{ +#ifndef MODULE + if (fb_get_options("unifb", NULL)) + return -ENODEV; +#endif + + return platform_driver_register(&unifb_driver); +} + +module_init(unifb_init); + +static void __exit unifb_exit(void) +{ + platform_driver_unregister(&unifb_driver); +} + +module_exit(unifb_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/fb.h b/include/linux/fb.h index 68ba85a00c06..b2a36391d2a1 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -152,6 +152,8 @@ #define FB_ACCEL_PROSAVAGE_DDR 0x8d /* S3 ProSavage DDR */ #define FB_ACCEL_PROSAVAGE_DDRK 0x8e /* S3 ProSavage DDR-K */ +#define FB_ACCEL_PUV3_UNIGFX 0xa0 /* PKUnity-v3 Unigfx */ + struct fb_fix_screeninfo { char id[16]; /* identification string eg "TT Builtin" */ unsigned long smem_start; /* Start of frame buffer mem */ -- cgit v1.2.3