diff options
author | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-03-14 15:52:42 +0000 |
---|---|---|
committer | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-03-14 15:52:42 +0000 |
commit | 26e3776a22bf894ced5af4c28968dc1dc99968eb (patch) | |
tree | 2d38a3789e27a423439c37a45a09cae31990a615 /target/linux/s3c24xx/patches-2.6.24/1033-smedia-glamo.patch.patch | |
parent | 4bd70fc26256cf485f19e0c8b881e078dc36134f (diff) |
nuke obsolete kernel stuff
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@14875 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.24/1033-smedia-glamo.patch.patch')
-rw-r--r-- | target/linux/s3c24xx/patches-2.6.24/1033-smedia-glamo.patch.patch | 3498 |
1 files changed, 0 insertions, 3498 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.24/1033-smedia-glamo.patch.patch b/target/linux/s3c24xx/patches-2.6.24/1033-smedia-glamo.patch.patch deleted file mode 100644 index 0e15f3ed1..000000000 --- a/target/linux/s3c24xx/patches-2.6.24/1033-smedia-glamo.patch.patch +++ /dev/null @@ -1,3498 +0,0 @@ -From f9fc3f480aeb1fdfcdefdd3c560d06c8297c758b Mon Sep 17 00:00:00 2001 -From: mokopatches <mokopatches@openmoko.org> -Date: Fri, 4 Apr 2008 11:34:54 +0100 -Subject: [PATCH] smedia-glamo.patch - [ FIXME: - include/asm-arm/arch-s3c2410/irqs.h shouldn't contain device-specific - changes. ] - -This is a Linux kernel driver for the Smedia Glamo336x / Glamo337x -multi-function peripheral device. - -Signed-off-by: Harald Welte <laforge@openmoko.org> ---- - drivers/mfd/Kconfig | 2 + - drivers/mfd/Makefile | 1 + - drivers/mfd/glamo/Kconfig | 35 ++ - drivers/mfd/glamo/Makefile | 11 + - drivers/mfd/glamo/glamo-core.c | 1151 +++++++++++++++++++++++++++++++++++ - drivers/mfd/glamo/glamo-core.h | 91 +++ - drivers/mfd/glamo/glamo-fb.c | 822 +++++++++++++++++++++++++ - drivers/mfd/glamo/glamo-gpio.c | 62 ++ - drivers/mfd/glamo/glamo-lcm-spi.c | 241 ++++++++ - drivers/mfd/glamo/glamo-regs.h | 477 +++++++++++++++ - drivers/mfd/glamo/glamo-spi-gpio.c | 256 ++++++++ - include/asm-arm/arch-s3c2410/irqs.h | 32 +- - include/linux/glamo-gpio.h | 99 +++ - include/linux/glamofb.h | 39 ++ - include/linux/spi/glamo.h | 28 + - 15 files changed, 3345 insertions(+), 2 deletions(-) - create mode 100644 drivers/mfd/glamo/Kconfig - create mode 100644 drivers/mfd/glamo/Makefile - create mode 100644 drivers/mfd/glamo/glamo-core.c - create mode 100644 drivers/mfd/glamo/glamo-core.h - create mode 100644 drivers/mfd/glamo/glamo-fb.c - create mode 100644 drivers/mfd/glamo/glamo-gpio.c - create mode 100644 drivers/mfd/glamo/glamo-lcm-spi.c - create mode 100644 drivers/mfd/glamo/glamo-regs.h - create mode 100644 drivers/mfd/glamo/glamo-spi-gpio.c - create mode 100644 include/linux/glamo-gpio.h - create mode 100644 include/linux/glamofb.h - create mode 100644 include/linux/spi/glamo.h - -diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index 2571619..fe06f8e 100644 ---- a/drivers/mfd/Kconfig -+++ b/drivers/mfd/Kconfig -@@ -15,6 +15,8 @@ config MFD_SM501 - interface. The device may be connected by PCI or local bus with - varying functions enabled. - -+source "drivers/mfd/glamo/Kconfig" -+ - endmenu - - menu "Multimedia Capabilities Port drivers" -diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index 5143209..a2da091 100644 ---- a/drivers/mfd/Makefile -+++ b/drivers/mfd/Makefile -@@ -3,6 +3,7 @@ - # - - obj-$(CONFIG_MFD_SM501) += sm501.o -+obj-$(CONFIG_MFD_GLAMO) += glamo/ - - obj-$(CONFIG_MCP) += mcp-core.o - obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o -diff --git a/drivers/mfd/glamo/Kconfig b/drivers/mfd/glamo/Kconfig -new file mode 100644 -index 0000000..b99f2b2 ---- /dev/null -+++ b/drivers/mfd/glamo/Kconfig -@@ -0,0 +1,35 @@ -+config MFD_GLAMO -+ bool "Smedia Glamo 336x/337x support" -+ help -+ This enables the core driver for the Smedia Glamo 336x/337x -+ multi-function device. It includes irq_chip demultiplex as -+ well as clock / power management and GPIO support. -+ -+config MFD_GLAMO_FB -+ tristate "Smedia Glamo 336x/337x framebuffer support" -+ depends on FB && MFD_GLAMO -+ help -+ Frame buffer driver for the LCD controller in the Smedia Glamo -+ 336x/337x. -+ -+ This driver is also available as a module ( = code which can be -+ inserted and removed from the running kernel whenever you want). The -+ module will be called glamofb. If you want to compile it as a module, -+ say M here and read <file:Documentation/modules.txt>. -+ -+ If unsure, say N. -+ -+config MFD_GLAMO_SPI_GPIO -+ tristate "Glamo GPIO SPI bitbang support" -+ depends on MFD_GLAMO -+ help -+ Enable a bitbanging SPI adapter driver for the Smedia Glamo. -+ -+config MFD_GLAMO_SPI_FB -+ tristate "Glamo LCM control channel SPI support" -+ depends on MFD_GLAMO_FB -+ help -+ Enable a bitbanging SPI adapter driver for the Smedia Glamo LCM -+ control channel. This SPI interface is frequently used to -+ interconnect the LCM control interface. -+ -diff --git a/drivers/mfd/glamo/Makefile b/drivers/mfd/glamo/Makefile -new file mode 100644 -index 0000000..fb53982 ---- /dev/null -+++ b/drivers/mfd/glamo/Makefile -@@ -0,0 +1,11 @@ -+# -+# Makefile for the Smedia Glamo framebuffer driver -+# -+ -+obj-$(CONFIG_MFD_GLAMO) += glamo-core.o glamo-gpio.o -+obj-$(CONFIG_MFD_GLAMO_SPI) += glamo-spi.o -+obj-$(CONFIG_MFD_GLAMO_SPI_GPIO) += glamo-spi-gpio.o -+ -+obj-$(CONFIG_MFD_GLAMO_FB) += glamo-fb.o -+obj-$(CONFIG_MFD_GLAMO_SPI_FB) += glamo-lcm-spi.o -+ -diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c -new file mode 100644 -index 0000000..acf545f ---- /dev/null -+++ b/drivers/mfd/glamo/glamo-core.c -@@ -0,0 +1,1151 @@ -+/* Smedia Glamo 336x/337x driver -+ * -+ * (C) 2007 by OpenMoko, Inc. -+ * Author: Harald Welte <laforge@openmoko.org> -+ * All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ */ -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/errno.h> -+#include <linux/string.h> -+#include <linux/mm.h> -+#include <linux/tty.h> -+#include <linux/slab.h> -+#include <linux/delay.h> -+#include <linux/fb.h> -+#include <linux/init.h> -+#include <linux/irq.h> -+#include <linux/interrupt.h> -+#include <linux/workqueue.h> -+#include <linux/wait.h> -+#include <linux/platform_device.h> -+#include <linux/kernel_stat.h> -+#include <linux/spinlock.h> -+#include <linux/glamofb.h> -+#include <linux/mmc/mmc.h> -+#include <linux/mmc/host.h> -+ -+#include <asm/io.h> -+#include <asm/uaccess.h> -+#include <asm/div64.h> -+ -+#ifdef CONFIG_PM -+#include <linux/pm.h> -+#endif -+ -+#include "glamo-regs.h" -+#include "glamo-core.h" -+ -+#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1) -+ -+static struct glamo_core *glamo_handle; -+ -+static inline void __reg_write(struct glamo_core *glamo, -+ u_int16_t reg, u_int16_t val) -+{ -+ writew(val, glamo->base + reg); -+} -+ -+static inline u_int16_t __reg_read(struct glamo_core *glamo, -+ u_int16_t reg) -+{ -+ return readw(glamo->base + reg); -+} -+ -+static void __reg_set_bit_mask(struct glamo_core *glamo, -+ u_int16_t reg, u_int16_t mask, -+ u_int16_t val) -+{ -+ u_int16_t tmp; -+ -+ val &= mask; -+ -+ tmp = __reg_read(glamo, reg); -+ tmp &= ~mask; -+ tmp |= val; -+ __reg_write(glamo, reg, tmp); -+} -+ -+static void reg_set_bit_mask(struct glamo_core *glamo, -+ u_int16_t reg, u_int16_t mask, -+ u_int16_t val) -+{ -+ spin_lock(&glamo->lock); -+ __reg_set_bit_mask(glamo, reg, mask, val); -+ spin_unlock(&glamo->lock); -+} -+ -+static inline void __reg_set_bit(struct glamo_core *glamo, -+ u_int16_t reg, u_int16_t bit) -+{ -+ __reg_set_bit_mask(glamo, reg, bit, 0xffff); -+} -+ -+static inline void __reg_clear_bit(struct glamo_core *glamo, -+ u_int16_t reg, u_int16_t bit) -+{ -+ __reg_set_bit_mask(glamo, reg, bit, 0); -+} -+ -+static inline void glamo_vmem_write(struct glamo_core *glamo, u_int32_t addr, -+ u_int16_t *src, int len) -+{ -+ if (addr & 0x0001 || (unsigned long)src & 0x0001 || len & 0x0001) { -+ dev_err(&glamo->pdev->dev, "unaligned write(0x%08x, 0x%p, " -+ "0x%x)!!\n", addr, src, len); -+ } -+ -+} -+ -+static inline void glamo_vmem_read(struct glamo_core *glamo, u_int16_t *buf, -+ u_int32_t addr, int len) -+{ -+ if (addr & 0x0001 || (unsigned long) buf & 0x0001 || len & 0x0001) { -+ dev_err(&glamo->pdev->dev, "unaligned read(0x%p, 0x08%x, " -+ "0x%x)!!\n", buf, addr, len); -+ } -+ -+ -+} -+ -+/*********************************************************************** -+ * resources of sibling devices -+ ***********************************************************************/ -+ -+#if 0 -+static struct resource glamo_core_resources[] = { -+ { -+ .start = GLAMO_REGOFS_GENERIC, -+ .end = GLAMO_REGOFS_GENERIC + 0x400, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = 0, -+ .end = 0, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device glamo_core_dev = { -+ .name = "glamo-core", -+ .resource = &glamo_core_resources, -+ .num_resources = ARRAY_SIZE(glamo_core_resources), -+}; -+#endif -+ -+static struct resource glamo_jpeg_resources[] = { -+ { -+ .start = GLAMO_REGOFS_JPEG, -+ .end = GLAMO_REGOFS_MPEG - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_GLAMO_JPEG, -+ .end = IRQ_GLAMO_JPEG, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device glamo_jpeg_dev = { -+ .name = "glamo-jpeg", -+ .resource = glamo_jpeg_resources, -+ .num_resources = ARRAY_SIZE(glamo_jpeg_resources), -+}; -+ -+static struct resource glamo_mpeg_resources[] = { -+ { -+ .start = GLAMO_REGOFS_MPEG, -+ .end = GLAMO_REGOFS_LCD - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_GLAMO_MPEG, -+ .end = IRQ_GLAMO_MPEG, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device glamo_mpeg_dev = { -+ .name = "glamo-mpeg", -+ .resource = glamo_mpeg_resources, -+ .num_resources = ARRAY_SIZE(glamo_mpeg_resources), -+}; -+ -+static struct resource glamo_2d_resources[] = { -+ { -+ .start = GLAMO_REGOFS_2D, -+ .end = GLAMO_REGOFS_3D - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_GLAMO_2D, -+ .end = IRQ_GLAMO_2D, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device glamo_2d_dev = { -+ .name = "glamo-2d", -+ .resource = glamo_2d_resources, -+ .num_resources = ARRAY_SIZE(glamo_2d_resources), -+}; -+ -+static struct resource glamo_3d_resources[] = { -+ { -+ .start = GLAMO_REGOFS_3D, -+ .end = GLAMO_REGOFS_END - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+}; -+ -+static struct platform_device glamo_3d_dev = { -+ .name = "glamo-3d", -+ .resource = glamo_3d_resources, -+ .num_resources = ARRAY_SIZE(glamo_3d_resources), -+}; -+ -+static struct platform_device glamo_spigpio_dev = { -+ .name = "glamo-spi-gpio", -+}; -+ -+static struct resource glamo_fb_resources[] = { -+ /* FIXME: those need to be incremented by parent base */ -+ { -+ .name = "glamo-fb-regs", -+ .start = GLAMO_REGOFS_LCD, -+ .end = GLAMO_REGOFS_MMC - 1, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .name = "glamo-fb-mem", -+ .start = GLAMO_OFFSET_FB, -+ .end = GLAMO_OFFSET_FB + GLAMO_FB_SIZE - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+}; -+ -+static struct platform_device glamo_fb_dev = { -+ .name = "glamo-fb", -+ .resource = glamo_fb_resources, -+ .num_resources = ARRAY_SIZE(glamo_fb_resources), -+}; -+ -+static struct resource glamo_mmc_resources[] = { -+ { -+ /* FIXME: those need to be incremented by parent base */ -+ .start = GLAMO_REGOFS_MMC, -+ .end = GLAMO_REGOFS_MPROC0 - 1, -+ .flags = IORESOURCE_MEM -+ }, { -+ .start = IRQ_GLAMO_MMC, -+ .end = IRQ_GLAMO_MMC, -+ .flags = IORESOURCE_IRQ, -+ }, { /* our data buffer for MMC transfers */ -+ .start = GLAMO_OFFSET_FB + GLAMO_FB_SIZE, -+ .end = GLAMO_OFFSET_FB + GLAMO_FB_SIZE + -+ GLAMO_MMC_BUFFER_SIZE - 1, -+ .flags = IORESOURCE_MEM -+ }, -+}; -+ -+static struct platform_device glamo_mmc_dev = { -+ .name = "glamo-mci", -+ .resource = glamo_mmc_resources, -+ .num_resources = ARRAY_SIZE(glamo_mmc_resources), -+}; -+ -+struct glamo_mci_pdata glamo_mci_def_pdata = { -+ .gpio_detect = 0, -+ .glamo_set_mci_power = NULL, /* filled in from MFD platform data */ -+ .ocr_avail = MMC_VDD_32_33, -+ .glamo_irq_is_wired = NULL, /* filled in from MFD platform data */ -+}; -+EXPORT_SYMBOL_GPL(glamo_mci_def_pdata); -+ -+ -+ -+static void mangle_mem_resources(struct resource *res, int num_res, -+ struct resource *parent) -+{ -+ int i; -+ -+ for (i = 0; i < num_res; i++) { -+ if (res[i].flags != IORESOURCE_MEM) -+ continue; -+ res[i].start += parent->start; -+ res[i].end += parent->start; -+ res[i].parent = parent; -+ } -+} -+ -+/*********************************************************************** -+ * IRQ demultiplexer -+ ***********************************************************************/ -+#define irq2glamo(x) (x - IRQ_GLAMO(0)) -+ -+static void glamo_ack_irq(unsigned int irq) -+{ -+ /* clear interrupt source */ -+ __reg_write(glamo_handle, GLAMO_REG_IRQ_CLEAR, -+ 1 << irq2glamo(irq)); -+} -+ -+static void glamo_mask_irq(unsigned int irq) -+{ -+ u_int16_t tmp; -+ -+ /* clear bit in enable register */ -+ tmp = __reg_read(glamo_handle, GLAMO_REG_IRQ_ENABLE); -+ tmp &= ~(1 << irq2glamo(irq)); -+ __reg_write(glamo_handle, GLAMO_REG_IRQ_ENABLE, tmp); -+} -+ -+static void glamo_unmask_irq(unsigned int irq) -+{ -+ u_int16_t tmp; -+ -+ /* set bit in enable register */ -+ tmp = __reg_read(glamo_handle, GLAMO_REG_IRQ_ENABLE); -+ tmp |= (1 << irq2glamo(irq)); -+ __reg_write(glamo_handle, GLAMO_REG_IRQ_ENABLE, tmp); -+} -+ -+static struct irq_chip glamo_irq_chip = { -+ .ack = glamo_ack_irq, -+ .mask = glamo_mask_irq, -+ .unmask = glamo_unmask_irq, -+}; -+ -+static void glamo_irq_demux_handler(unsigned int irq, struct irq_desc *desc) -+{ -+ const unsigned int cpu = smp_processor_id(); -+ -+ spin_lock(&desc->lock); -+ -+ desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); -+ -+ if (unlikely(desc->status & IRQ_INPROGRESS)) { -+ desc->status |= (IRQ_PENDING | IRQ_MASKED); -+ desc->chip->mask(irq); -+ desc->chip->ack(irq); -+ goto out_unlock; -+ } -+ -+ kstat_cpu(cpu).irqs[irq]++; -+ desc->chip->ack(irq); -+ desc->status |= IRQ_INPROGRESS; -+ -+ do { -+ u_int16_t irqstatus; -+ int i; -+ -+ if (unlikely((desc->status & -+ (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) == -+ (IRQ_PENDING | IRQ_MASKED))) { -+ /* dealing with pending IRQ, unmasking */ -+ desc->chip->unmask(irq); -+ desc->status &= ~IRQ_MASKED; -+ } -+ -+ desc->status &= ~IRQ_PENDING; -+ -+ /* read IRQ status register */ -+ irqstatus = __reg_read(glamo_handle, GLAMO_REG_IRQ_STATUS); -+ for (i = 0; i < 9; i++) -+ if (irqstatus & (1 << i)) -+ desc_handle_irq(IRQ_GLAMO(i), -+ irq_desc+IRQ_GLAMO(i)); -+ -+ } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); -+ -+ desc->status &= ~IRQ_INPROGRESS; -+ -+out_unlock: -+ spin_unlock(&desc->lock); -+} -+ -+/*********************************************************************** -+ * 'engine' support -+ ***********************************************************************/ -+ -+int glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine) -+{ -+ spin_lock(&glamo->lock); -+ switch (engine) { -+ case GLAMO_ENGINE_LCD: -+ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_LCD, -+ GLAMO_CLOCK_LCD_EN_M5CLK | -+ GLAMO_CLOCK_LCD_EN_DHCLK | -+ GLAMO_CLOCK_LCD_EN_DMCLK | -+ GLAMO_CLOCK_LCD_EN_DCLK | -+ GLAMO_CLOCK_LCD_DG_M5CLK | -+ GLAMO_CLOCK_LCD_DG_DMCLK, 0xffff); -+ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1, -+ GLAMO_CLOCK_GEN51_EN_DIV_DHCLK | -+ GLAMO_CLOCK_GEN51_EN_DIV_DMCLK | -+ GLAMO_CLOCK_GEN51_EN_DIV_DCLK, 0xffff); -+ __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2), -+ GLAMO_HOSTBUS2_MMIO_EN_LCD, -+ 0xffff); -+ break; -+ case GLAMO_ENGINE_MMC: -+ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MMC, -+ GLAMO_CLOCK_MMC_EN_M9CLK | -+ GLAMO_CLOCK_MMC_EN_TCLK | -+ GLAMO_CLOCK_MMC_DG_M9CLK | -+ GLAMO_CLOCK_MMC_DG_TCLK, 0xffff); -+ __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2), -+ GLAMO_HOSTBUS2_MMIO_EN_MMC, -+ GLAMO_HOSTBUS2_MMIO_EN_MMC); -+ break; -+ case GLAMO_ENGINE_2D: -+ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_2D, -+ GLAMO_CLOCK_2D_EN_M7CLK | -+ GLAMO_CLOCK_2D_EN_GCLK | -+ GLAMO_CLOCK_2D_DG_M7CLK | -+ GLAMO_CLOCK_2D_DG_GCLK, 0xffff); -+ __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2), -+ GLAMO_HOSTBUS2_MMIO_EN_2D, -+ GLAMO_HOSTBUS2_MMIO_EN_2D); -+ break; -+ case GLAMO_ENGINE_CMDQ: -+ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_2D, -+ GLAMO_CLOCK_2D_EN_M6CLK, 0xffff); -+ __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2), -+ GLAMO_HOSTBUS2_MMIO_EN_CQ, -+ GLAMO_HOSTBUS2_MMIO_EN_CQ); -+ break; -+ /* FIXME: Implementation */ -+ default: -+ break; -+ } -+ spin_unlock(&glamo->lock); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(glamo_engine_enable); -+ -+int glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine) -+{ -+ spin_lock(&glamo->lock); -+ switch (engine) { -+ /* FIXME: Implementation */ -+ default: -+ break; -+ } -+ spin_unlock(&glamo->lock); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(glamo_engine_disable); -+ -+struct glamo_script reset_regs[] = { -+ [GLAMO_ENGINE_LCD] = { -+ GLAMO_REG_CLOCK_LCD, GLAMO_CLOCK_LCD_RESET -+ }, -+#if 0 -+ [GLAMO_ENGINE_HOST] = { -+ GLAMO_REG_CLOCK_HOST, GLAMO_CLOCK_HOST_RESET -+ }, -+ [GLAMO_ENGINE_MEM] = { -+ GLAMO_REG_CLOCK_MEM, GLAMO_CLOCK_MEM_RESET -+ }, -+#endif -+ [GLAMO_ENGINE_MMC] = { -+ GLAMO_REG_CLOCK_MMC, GLAMO_CLOCK_MMC_RESET -+ }, -+ [GLAMO_ENGINE_2D] = { -+ GLAMO_REG_CLOCK_2D, GLAMO_CLOCK_2D_RESET -+ }, -+ [GLAMO_ENGINE_JPEG] = { -+ GLAMO_REG_CLOCK_JPEG, GLAMO_CLOCK_JPEG_RESET -+ }, -+}; -+ -+void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine) -+{ -+ struct glamo_script *rst; -+ -+ if (engine >= ARRAY_SIZE(reset_regs)) { -+ dev_warn(&glamo->pdev->dev, "unknown engine %u ", engine); -+ return; -+ } -+ -+ rst = &reset_regs[engine]; -+ -+ spin_lock(&glamo->lock); -+ __reg_set_bit(glamo, rst->reg, rst->val); -+ spin_unlock(&glamo->lock); -+ -+ msleep(1); -+ -+ spin_lock(&glamo->lock); -+ __reg_clear_bit(glamo, rst->reg, rst->val); -+ spin_unlock(&glamo->lock); -+ -+ msleep(1); -+} -+EXPORT_SYMBOL_GPL(glamo_engine_reset); -+ -+enum glamo_pll { -+ GLAMO_PLL1, -+ GLAMO_PLL2, -+}; -+ -+static int glamo_pll_rate(struct glamo_core *glamo, -+ enum glamo_pll pll) -+{ -+ u_int16_t reg; -+ unsigned int div = 512; -+ /* FIXME: move osci into platform_data */ -+ unsigned int osci = 32768; -+ -+ if (osci == 32768) -+ div = 1; -+ -+ switch (pll) { -+ case GLAMO_PLL1: -+ reg = __reg_read(glamo, GLAMO_REG_PLL_GEN1); -+ break; -+ case GLAMO_PLL2: -+ reg = __reg_read(glamo, GLAMO_REG_PLL_GEN3); -+ break; -+ default: -+ return -EINVAL; -+ } -+ return (osci/div)*reg; -+} -+ -+int glamo_engine_reclock(struct glamo_core *glamo, -+ enum glamo_engine engine, -+ int ps) -+{ -+ int pll, khz; -+ u_int16_t reg, mask, val = 0; -+ -+ if (!ps) -+ return 0; -+ -+ switch (engine) { -+ case GLAMO_ENGINE_LCD: -+ pll = GLAMO_PLL1; -+ reg = GLAMO_REG_CLOCK_GEN7; -+ mask = 0xff; -+ break; -+ default: -+ dev_warn(&glamo->pdev->dev, -+ "reclock of engine 0x%x not supported\n", engine); -+ return -EINVAL; -+ break; -+ } -+ -+ pll = glamo_pll_rate(glamo, pll); -+ khz = 1000000000UL / ps; -+ -+ if (khz) -+ val = (pll / khz) / 1000; -+ -+ dev_dbg(&glamo->pdev->dev, -+ "PLL %d, kHZ %d, div %d\n", pll, khz, val); -+ -+ if (val) { -+ val--; -+ reg_set_bit_mask(glamo, reg, mask, val); -+ msleep(5); /* wait some time to stabilize */ -+ -+ return 0; -+ } else { -+ return -EINVAL; -+ } -+} -+EXPORT_SYMBOL_GPL(glamo_engine_reclock); -+ -+/*********************************************************************** -+ * script support -+ ***********************************************************************/ -+ -+int glamo_run_script(struct glamo_core *glamo, struct glamo_script *script, -+ int len, int may_sleep) -+{ -+ int i; -+ -+ for (i = 0; i < len; i++) { -+ struct glamo_script *line = &script[i]; -+ -+ switch (line->reg) { -+ case 0xffff: -+ return 0; -+ case 0xfffe: -+ if (may_sleep) -+ msleep(line->val); -+ else -+ mdelay(line->val); -+ break; -+ case 0xfffd: -+ /* spin until PLLs lock */ -+ while ((__reg_read(glamo, GLAMO_REG_PLL_GEN5) & 3) != 3) -+ ; -+ break; -+ default: -+ __reg_write(glamo, script[i].reg, script[i].val); -+ break; -+ } -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(glamo_run_script); -+ -+static struct glamo_script glamo_init_script[] = { -+ { GLAMO_REG_CLOCK_HOST, 0x1000 }, -+ { 0xfffe, 2 }, -+ { GLAMO_REG_CLOCK_MEMORY, 0x1000 }, -+ { GLAMO_REG_CLOCK_MEMORY, 0x2000 }, -+ { GLAMO_REG_CLOCK_LCD, 0x1000 }, -+ { GLAMO_REG_CLOCK_MMC, 0x1000 }, -+ { GLAMO_REG_CLOCK_ISP, 0x1000 }, -+ { GLAMO_REG_CLOCK_ISP, 0x3000 }, -+ { GLAMO_REG_CLOCK_JPEG, 0x1000 }, -+ { GLAMO_REG_CLOCK_3D, 0x1000 }, -+ { GLAMO_REG_CLOCK_3D, 0x3000 }, -+ { GLAMO_REG_CLOCK_2D, 0x1000 }, -+ { GLAMO_REG_CLOCK_2D, 0x3000 }, -+ { GLAMO_REG_CLOCK_RISC1, 0x1000 }, -+ { GLAMO_REG_CLOCK_MPEG, 0x3000 }, -+ { GLAMO_REG_CLOCK_MPEG, 0x3000 }, -+ { GLAMO_REG_CLOCK_MPROC, 0x1000 /*0x100f*/ }, -+ { 0xfffe, 2 }, -+ { GLAMO_REG_CLOCK_HOST, 0x0000 }, -+ { GLAMO_REG_CLOCK_MEMORY, 0x0000 }, -+ { GLAMO_REG_CLOCK_LCD, 0x0000 }, -+ { GLAMO_REG_CLOCK_MMC, 0x0000 }, -+#if 0 -+/* unused engines must be left in reset to stop MMC block read "blackouts" */ -+ { GLAMO_REG_CLOCK_ISP, 0x0000 }, -+ { GLAMO_REG_CLOCK_ISP, 0x0000 }, -+ { GLAMO_REG_CLOCK_JPEG, 0x0000 }, -+ { GLAMO_REG_CLOCK_3D, 0x0000 }, -+ { GLAMO_REG_CLOCK_3D, 0x0000 }, -+ { GLAMO_REG_CLOCK_2D, 0x0000 }, -+ { GLAMO_REG_CLOCK_2D, 0x0000 }, -+ { GLAMO_REG_CLOCK_RISC1, 0x0000 }, -+ { GLAMO_REG_CLOCK_MPEG, 0x0000 }, -+ { GLAMO_REG_CLOCK_MPEG, 0x0000 }, -+#endif -+ { GLAMO_REG_PLL_GEN1, 0x05db }, /* 48MHz */ -+ { GLAMO_REG_PLL_GEN3, 0x09c3 }, /* 80MHz */ -+ { 0xfffd, 0 }, -+ /* -+ * b9 of this register MUST be zero to get any interrupts on INT# -+ * the other set bits enable all the engine interrupt sources -+ */ -+ { GLAMO_REG_IRQ_ENABLE, 0x01ff }, -+ { GLAMO_REG_CLOCK_GEN6, 0x2000 }, -+ { GLAMO_REG_CLOCK_GEN7, 0x0101 }, -+ { GLAMO_REG_CLOCK_GEN8, 0x0100 }, -+ { GLAMO_REG_CLOCK_HOST, 0x000d }, -+ { 0x200, 0x0ef0 }, -+ { 0x202, 0x07ff }, -+ { 0x212, 0x0000 }, -+ { 0x214, 0x4000 }, -+ { 0x216, 0xf00e }, -+ { GLAMO_REG_MEM_TYPE, 0x0874 }, /* 8MB, 16 word pg wr+rd */ -+ { GLAMO_REG_MEM_GEN, 0xafaf }, /* 63 grants min + max */ -+ /* -+ * the register below originally 0x0108 makes unreliable Glamo MMC -+ * write operations. Cranked to 0x05ad to add a wait state, the -+ * unreliability is not seen after 4GB of write / read testing -+ */ -+ { GLAMO_REG_MEM_TIMING1, 0x0108 }, -+ { GLAMO_REG_MEM_TIMING2, 0x0010 }, /* Taa = 3 MCLK */ -+ { GLAMO_REG_MEM_TIMING3, 0x0000 }, -+ { GLAMO_REG_MEM_TIMING4, 0x0000 }, /* CE1# delay fall/rise */ -+ { GLAMO_REG_MEM_TIMING5, 0x0000 }, /* UB# LB# */ -+ { GLAMO_REG_MEM_TIMING6, 0x0000 }, /* OE# */ -+ { GLAMO_REG_MEM_TIMING7, 0x0000 }, /* WE# */ -+ { GLAMO_REG_MEM_TIMING8, 0x1002 }, /* MCLK delay, was 0x1000 */ -+ { GLAMO_REG_MEM_TIMING9, 0x6006 }, -+ { GLAMO_REG_MEM_TIMING10, 0x00ff }, -+ { GLAMO_REG_MEM_TIMING11, 0x0001 }, -+ { GLAMO_REG_MEM_POWER1, 0x0020 }, -+ { GLAMO_REG_MEM_POWER2, 0x0000 }, -+ { GLAMO_REG_MEM_DRAM1, 0x0000 }, -+ { 0xfffe, 1 }, -+ { GLAMO_REG_MEM_DRAM1, 0xc100 }, -+ { 0xfffe, 1 }, -+ { GLAMO_REG_MEM_DRAM1, 0xe100 }, -+ { GLAMO_REG_MEM_DRAM2, 0x01d6 }, -+ { GLAMO_REG_CLOCK_MEMORY, 0x000b }, -+}; -+ -+static struct glamo_script glamo_resume_script[] = { -+ { GLAMO_REG_IRQ_ENABLE, 0x01ff }, -+ { GLAMO_REG_CLOCK_GEN6, 0x2000 }, -+ { GLAMO_REG_CLOCK_GEN7, 0x0001 }, /* 0101 */ -+ { GLAMO_REG_CLOCK_GEN8, 0x0100 }, -+ { GLAMO_REG_CLOCK_HOST, 0x000d }, -+ { 0x200, 0x0ef0 }, -+ { 0x202, 0x07ff }, -+ { 0x212, 0x0000 }, -+ { 0x214, 0x4000 }, -+ { 0x216, 0xf00e }, -+ { GLAMO_REG_MEM_TYPE, 0x0874 }, /* 8MB, 16 word pg wr+rd */ -+ { GLAMO_REG_MEM_GEN, 0xafaf }, /* 63 grants min + max */ -+ -+ { GLAMO_REG_MEM_TIMING1, 0x0108 }, -+ { GLAMO_REG_MEM_TIMING2, 0x0010 }, /* Taa = 3 MCLK */ -+ { GLAMO_REG_MEM_TIMING3, 0x0000 }, -+ { GLAMO_REG_MEM_TIMING4, 0x0000 }, /* CE1# delay fall/rise */ -+ { GLAMO_REG_MEM_TIMING5, 0x0000 }, /* UB# LB# */ -+ { GLAMO_REG_MEM_TIMING6, 0x0000 }, /* OE# */ -+ { GLAMO_REG_MEM_TIMING7, 0x0000 }, /* WE# */ -+ { GLAMO_REG_MEM_TIMING8, 0x1002 }, /* MCLK delay, was 0x1000 */ -+ { GLAMO_REG_MEM_TIMING9, 0x6006 }, -+ { GLAMO_REG_MEM_TIMING10, 0x00ff }, -+ { GLAMO_REG_MEM_TIMING11, 0x0001 }, -+ { GLAMO_REG_MEM_POWER1, 0x0020 }, -+ { GLAMO_REG_MEM_POWER2, 0x0000 }, -+ { GLAMO_REG_MEM_DRAM1, 0x0000 }, -+ { 0xfffe, 1 }, -+ { GLAMO_REG_MEM_DRAM1, 0xc100 }, -+ { 0xfffe, 1 }, -+ { GLAMO_REG_MEM_DRAM1, 0xe100 }, -+ { GLAMO_REG_MEM_DRAM2, 0x01d6 }, -+ { GLAMO_REG_CLOCK_MEMORY, 0x000b }, -+}; -+ -+#if 0 /* MM370 */ -+static const struct glamo_script regs_vram_2mb = { -+ { GLAMO_REG_CLOCK_MEMORY, 0x3aaa }, -+ { 0xfffe, 50 }, -+ { GLAMO_REG_CLOCK_MEMORY, 0x0aaa }, -+ { 0xfffe, 3 }, -+ { GLAMO_REG_MEM_POWER1, 0x0020 }, -+ { 0x033a, 0x0000 }, -+ { 0x033c, 0x0000 }, -+ { 0x033e, 0x0000 }, -+ { 0x0340, 0x0000 }, -+ { 0x0342, 0x0000 }, -+ { 0x0344, 0x0000 }, -+ { 0x0346, 0x0240 }, -+ { GLAMO_REG_MEM_TIMING8, 0x1016 }, -+ { GLAMO_REG_MEM_TIMING9, 0x6067 }, -+ { GLAMO_REG_MEM_TIMING10, 0x00ff }, -+ { GLAMO_REG_MEM_TIMING11, 0x0030 }, -+ { GLAMO_REG_MEM_GEN, 0x3fff }, -+ { GLAMO_REG_MEM_GEN, 0xafaf }, -+ { GLAMO_REG_MEM_TIMING1, 0x0108 }, -+ { GLAMO_REG_MEM_TIMING2, 0x0010 }, -+ { GLAMO_REG_MEM_DRAM1, 0x0a00 }, -+ { 0xfffe, 3 }, -+ { GLAMO_REG_MEM_DRAM1, 0xe200 }, -+ { 0xfffe, 1 }, -+}; -+ -+static const struct glamo_script regs_vram_8mb = { -+ { GLAMO_REG_CLOCK_MEMORY, 0x3aaa }, -+ { 0xfffe, 50 }, -+ { GLAMO_REG_CLOCK_MEMORY, 0x0aaa }, -+ { 0xfffe, 3 }, -+ { GLAMO_REG_MEM_POWER1, 0x0020 }, -+ { 0x033a, 0x45cf }, -+ { 0x033c, 0x4240 }, -+ { 0x033e, 0x53e0 }, -+ { 0x0340, 0x1401 }, -+ { 0x0342, 0x0c44 }, -+ { 0x0344, 0x1d0b }, -+ { 0x0346, 0x25ac }, -+ { 0x0348, 0x1953 }, -+ { 0xfffe, 1 }, -+ { GLAMO_REG_MEM_TYPE, 0x087a }, -+ { GLAMO_REG_MEM_DRAM2, 0x01d6 }, -+ { GLAMO_REG_MEM_TIMING8, 0x1060 }, -+ { GLAMO_REG_MEM_TIMING9, 0x6067 }, -+ { GLAMO_REG_MEM_TIMING10, 0x00ff }, -+ { GLAMO_REG_MEM_TIMING11, 0x0030 }, -+ { GLAMO_REG_MEM_GEN, 0x3fff }, -+ { GLAMO_REG_MEM_GEN, 0xafaf }, -+ { GLAMO_REG_MEM_TIMING1, 0x3108 }, -+ { GLAMO_REG_MEM_TIMING2, 0x0010 }, -+ { GLAMO_REG_MEM_DRAM1, 0x0a00 }, -+ { 0xfffe, 3 }, -+ { GLAMO_REG_MEM_DRAM1, 0xe200 }, -+ { 0xfffe, 1 }, -+}; -+#endif -+ -+enum glamo_power { -+ GLAMO_POWER_ON, -+ GLAMO_POWER_STANDBY, -+ GLAMO_POWER_SUSPEND, -+}; -+ -+static void glamo_power(struct glamo_core *glamo, -+ enum glamo_power new_state) -+{ -+ spin_lock(&glamo->lock); -+ -+ switch (new_state) { -+ case GLAMO_POWER_ON: -+ /* power up PLL1 and PLL2 */ -+ __reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN6, 0x0001, 0xffff); -+ __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 0x2000, 0x0000); -+ -+ /* spin until PLL1 and PLL2 lock */ -+ while ((__reg_read(glamo, GLAMO_REG_PLL_GEN5) & 3) != 3) -+ ; -+ -+ /* enable memory clock and get it out of deep pwrdown */ -+ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MEMORY, -+ GLAMO_CLOCK_MEM_EN_MOCACLK, 0xffff); -+ __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM2, -+ GLAMO_MEM_DRAM2_DEEP_PWRDOWN, 0x0000); -+ __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM1, -+ GLAMO_MEM_DRAM1_SELF_REFRESH, 0x0000); -+ -+ glamo_run_script(glamo, glamo_resume_script, -+ ARRAY_SIZE(glamo_resume_script), 0); -+ -+ break; -+ case GLAMO_POWER_STANDBY: -+ /* enable memory self-refresh */ -+ __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM1, -+ GLAMO_MEM_DRAM1_SELF_REFRESH, 0xffff); -+ /* stop memory clock */ -+ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MEMORY, -+ GLAMO_CLOCK_MEM_EN_MOCACLK, 0x0000); -+ /* power down PLL2 and then PLL1 */ -+ __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 0x2000, 0xffff); -+ __reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN5, 0x0001, 0xffff); -+ break; -+ case GLAMO_POWER_SUSPEND: -+ __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM2, -+ GLAMO_MEM_DRAM2_DEEP_PWRDOWN, 0xffff); -+ /* stop memory clock */ -+ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MEMORY, -+ GLAMO_CLOCK_MEM_EN_MOCACLK, 0x0000); -+ /* power down PLL2 and then PLL1 */ -+ __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 0x2000, 0xffff); -+ __reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN5, 0x0001, 0xffff); -+ break; -+ } -+ -+ spin_unlock(&glamo->lock); -+} -+ -+#if 0 -+#define MEMDETECT_RETRY 6 -+static unsigned int detect_memsize(struct glamo_core *glamo) -+{ -+ int i; -+ -+ /*static const u_int16_t pattern[] = { -+ 0x1111, 0x8a8a, 0x2222, 0x7a7a, -+ 0x3333, 0x6a6a, 0x4444, 0x5a5a, -+ 0x5555, 0x4a4a, 0x6666, 0x3a3a, -+ 0x7777, 0x2a2a, 0x8888, 0x1a1a -+ }; */ -+ -+ for (i = 0; i < MEMDETECT_RETRY; i++) { -+ switch (glamo->type) { -+ case 3600: -+ __reg_write(glamo, GLAMO_REG_MEM_TYPE, 0x0072); -+ __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0xc100); -+ break; -+ case 3650: -+ switch (glamo->revision) { -+ case GLAMO_CORE_REV_A0: -+ if (i & 1) -+ __reg_write(glamo, GLAMO_REG_MEM_TYPE, -+ 0x097a); -+ else -+ __reg_write(glamo, GLAMO_REG_MEM_TYPE, -+ 0x0173); -+ -+ __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0x0000); -+ msleep(1); -+ __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0xc100); -+ break; -+ default: -+ if (i & 1) -+ __reg_write(glamo, GLAMO_REG_MEM_TYPE, -+ 0x0972); -+ else -+ __reg_write(glamo, GLAMO_REG_MEM_TYPE, -+ 0x0872); -+ -+ __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0x0000); -+ msleep(1); -+ __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0xe100); -+ break; -+ } -+ break; -+ case 3700: -+ /* FIXME */ -+ default: -+ break; -+ } -+ -+#if 0 -+ /* FIXME: finish implementation */ -+ for (j = 0; j < 8; j++) { -+ __ -+#endif -+ } -+ -+ return 0; -+} -+#endif -+ -+/* Find out if we can support this version of the Glamo chip */ -+static int glamo_supported(struct glamo_core *glamo) -+{ -+ u_int16_t dev_id, rev_id; /*, memsize; */ -+ -+ dev_id = __reg_read(glamo, GLAMO_REG_DEVICE_ID); -+ rev_id = __reg_read(glamo, GLAMO_REG_REVISION_ID); -+ -+ switch (dev_id) { -+ case 0x3650: -+ switch (rev_id) { -+ case GLAMO_CORE_REV_A2: -+ break; -+ case GLAMO_CORE_REV_A0: -+ case GLAMO_CORE_REV_A1: -+ case GLAMO_CORE_REV_A3: -+ dev_warn(&glamo->pdev->dev, "untested core revision " -+ "%04x, your mileage may vary\n", rev_id); -+ break; -+ default: -+ dev_warn(&glamo->pdev->dev, "unknown glamo revision " -+ "%04x, your mileage may vary\n", rev_id); -+ /* maybe should abort ? */ -+ } -+ break; -+ case 0x3600: -+ case 0x3700: -+ default: -+ dev_err(&glamo->pdev->dev, "unsupported Glamo device %04x\n", -+ dev_id); -+ return 0; -+ } -+ -+ dev_info(&glamo->pdev->dev, "Detected Glamo core %04x Revision %04x " -+ "(%uHz CPU / %uHz Memory)\n", dev_id, rev_id, -+ glamo_pll_rate(glamo, GLAMO_PLL1), -+ glamo_pll_rate(glamo, GLAMO_PLL2)); -+ -+ return 1; -+} -+ -+ -+static int __init glamo_probe(struct platform_device *pdev) -+{ -+ int rc, irq; -+ struct glamo_core *glamo; -+ -+ if (glamo_handle) { -+ dev_err(&pdev->dev, -+ "This driver supports only one instance\n"); -+ return -EBUSY; -+ } -+ -+ glamo = kmalloc(GFP_KERNEL, sizeof(*glamo)); -+ if (!glamo) -+ return -ENOMEM; -+ -+ spin_lock_init(&glamo->lock); -+ glamo_handle = glamo; -+ glamo->pdev = pdev; -+ glamo->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ glamo->irq = platform_get_irq(pdev, 0); -+ glamo->pdata = pdev->dev.platform_data; -+ if (!glamo->mem || !glamo->pdata) { -+ dev_err(&pdev->dev, "platform device with no MEM/PDATA ?\n"); -+ rc = -ENOENT; -+ goto out_free; -+ } -+ -+ /* register a number of sibling devices whoise IOMEM resources -+ * are siblings of pdev's IOMEM resource */ -+#if 0 -+ glamo_core_dev.dev.parent = &pdev.dev; -+ mangle_mem_resources(glamo_core_dev.resources, -+ glamo_core_dev.num_resources, glamo->mem); -+ glamo_core_dev.resources[1].start = glamo->irq; -+ glamo_core_dev.resources[1].end = glamo->irq; -+ platform_device_register(&glamo_core_dev); -+#endif -+ /* only remap the generic, hostbus and memory controller registers */ -+ glamo->base = ioremap(glamo->mem->start, GLAMO_REGOFS_VIDCAP); -+ if (!glamo->base) { -+ dev_err(&pdev->dev, "failed to ioremap() memory region\n"); -+ goto out_free; -+ } -+ -+ /* bring MCI specific stuff over from our MFD platform data */ -+ glamo_mci_def_pdata.glamo_set_mci_power = -+ glamo->pdata->glamo_set_mci_power; -+ glamo_mci_def_pdata.glamo_irq_is_wired = -+ glamo->pdata->glamo_irq_is_wired; -+ -+ glamo_mmc_dev.dev.parent = &pdev->dev; -+ /* we need it later to give to the engine enable and disable */ -+ glamo_mci_def_pdata.pglamo = glamo; -+ mangle_mem_resources(glamo_mmc_dev.resource, -+ glamo_mmc_dev.num_resources, glamo->mem); -+ platform_device_register(&glamo_mmc_dev); -+ -+ glamo_2d_dev.dev.parent = &pdev->dev; -+ mangle_mem_resources(glamo_2d_dev.resource, -+ glamo_2d_dev.num_resources, glamo->mem); -+ platform_device_register(&glamo_2d_dev); -+ -+ glamo_3d_dev.dev.parent = &pdev->dev; -+ mangle_mem_resources(glamo_3d_dev.resource, -+ glamo_3d_dev.num_resources, glamo->mem); -+ platform_device_register(&glamo_3d_dev); -+ -+ glamo_jpeg_dev.dev.parent = &pdev->dev; -+ mangle_mem_resources(glamo_jpeg_dev.resource, -+ glamo_jpeg_dev.num_resources, glamo->mem); -+ platform_device_register(&glamo_jpeg_dev); -+ -+ glamo_mpeg_dev.dev.parent = &pdev->dev; -+ mangle_mem_resources(glamo_mpeg_dev.resource, -+ glamo_mpeg_dev.num_resources, glamo->mem); -+ platform_device_register(&glamo_mpeg_dev); -+ -+ glamo->pdata->glamo = glamo; -+ glamo_fb_dev.dev.parent = &pdev->dev; -+ glamo_fb_dev.dev.platform_data = glamo->pdata; -+ mangle_mem_resources(glamo_fb_dev.resource, -+ glamo_fb_dev.num_resources, glamo->mem); -+ platform_device_register(&glamo_fb_dev); -+ -+ glamo->pdata->spigpio_info->glamo = glamo; -+ glamo_spigpio_dev.dev.parent = &pdev->dev; -+ glamo_spigpio_dev.dev.platform_data = glamo->pdata->spigpio_info; -+ platform_device_register(&glamo_spigpio_dev); -+ -+ /* only request the generic, hostbus and memory controller MMIO */ -+ glamo->mem = request_mem_region(glamo->mem->start, -+ GLAMO_REGOFS_VIDCAP, "glamo-core"); -+ if (!glamo->mem) { -+ dev_err(&pdev->dev, "failed to request memory region\n"); -+ goto out_free; -+ } -+ -+ if (!glamo_supported(glamo)) { -+ dev_err(&pdev->dev, "This Glamo is not supported\n"); -+ goto out_free; -+ } -+ -+ platform_set_drvdata(pdev, glamo); -+ -+ dev_dbg(&glamo->pdev->dev, "running init script\n"); -+ glamo_run_script(glamo, glamo_init_script, -+ ARRAY_SIZE(glamo_init_script), 1); -+ -+ dev_info(&glamo->pdev->dev, "Glamo core now %uHz CPU / %uHz Memory)\n", -+ glamo_pll_rate(glamo, GLAMO_PLL1), -+ glamo_pll_rate(glamo, GLAMO_PLL2)); -+ -+ for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) { -+ set_irq_chip(irq, &glamo_irq_chip); -+ set_irq_handler(irq, handle_level_irq); -+ set_irq_flags(irq, IRQF_VALID); -+ } -+ -+ if (glamo->pdata->glamo_irq_is_wired && -+ !glamo->pdata->glamo_irq_is_wired()) { -+ set_irq_chained_handler(glamo->irq, glamo_irq_demux_handler); -+ set_irq_type(glamo->irq, IRQT_FALLING); -+ glamo->irq_works = 1; -+ } else -+ glamo->irq_works = 0; -+ return 0; -+ -+out_free: -+ glamo_handle = NULL; -+ kfree(glamo); -+ return rc; -+} -+ -+static int glamo_remove(struct platform_device *pdev) -+{ -+ struct glamo_core *glamo = platform_get_drvdata(pdev); -+ int irq; -+ -+ disable_irq(glamo->irq); -+ set_irq_chained_handler(glamo->irq, NULL); -+ -+ for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) { -+ set_irq_flags(irq, 0); -+ set_irq_chip(irq, NULL); -+ } -+ -+ platform_set_drvdata(pdev, NULL); -+ platform_device_unregister(&glamo_fb_dev); -+ platform_device_unregister(&glamo_mmc_dev); -+ iounmap(glamo->base); -+ release_mem_region(glamo->mem->start, GLAMO_REGOFS_VIDCAP); -+ glamo_handle = NULL; -+ kfree(glamo); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int glamo_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ return 0; -+} -+ -+static int glamo_resume(struct platform_device *pdev) -+{ -+ return 0; -+} -+#else -+#define glamo_suspend NULL -+#define glamo_resume NULL -+#endif -+ -+static struct platform_driver glamo_driver = { -+ .probe = glamo_probe, -+ .remove = glamo_remove, -+ .suspend = glamo_suspend, -+ .resume = glamo_resume, -+ .driver = { -+ .name = "glamo3362", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __devinit glamo_init(void) -+{ -+ return platform_driver_register(&glamo_driver); -+} -+ -+static void __exit glamo_cleanup(void) -+{ -+ platform_driver_unregister(&glamo_driver); -+} -+ -+module_init(glamo_init); -+module_exit(glamo_cleanup); -+ -+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>"); -+MODULE_DESCRIPTION("Smedia Glamo 336x/337x core/resource driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/mfd/glamo/glamo-core.h b/drivers/mfd/glamo/glamo-core.h -new file mode 100644 -index 0000000..cf89f03 ---- /dev/null -+++ b/drivers/mfd/glamo/glamo-core.h -@@ -0,0 +1,91 @@ -+#ifndef __GLAMO_CORE_H -+#define __GLAMO_CORE_H -+ -+#include <asm/system.h> -+ -+ -+/* for the time being, we put the on-screen framebuffer into the lowest -+ * VRAM space. This should make the code easily compatible with the various -+ * 2MB/4MB/8MB variants of the Smedia chips */ -+#define GLAMO_OFFSET_VRAM 0x800000 -+#define GLAMO_OFFSET_FB (GLAMO_OFFSET_VRAM) -+ -+/* we only allocate the minimum possible size for the framebuffer to make -+ * sure we have sufficient memory for other functions of the chip */ -+//#define GLAMO_FB_SIZE (640*480*4) /* == 0x12c000 */ -+#define GLAMO_INTERNAL_RAM_SIZE 0x800000 -+#define GLAMO_MMC_BUFFER_SIZE (64 * 1024) -+#define GLAMO_FB_SIZE (GLAMO_INTERNAL_RAM_SIZE - GLAMO_MMC_BUFFER_SIZE) -+ -+ -+struct glamo_core { -+ int irq; -+ int irq_works; /* 0 means PCB does not support Glamo IRQ */ -+ struct resource *mem; -+ struct resource *mem_core; -+ void __iomem *base; -+ struct platform_device *pdev; -+ struct glamofb_platform_data *pdata; -+ u_int16_t type; -+ u_int16_t revision; -+ spinlock_t lock; -+}; -+ -+struct glamo_script { -+ u_int16_t reg; -+ u_int16_t val; -+}; -+ -+int glamo_run_script(struct glamo_core *glamo, -+ struct glamo_script *script, int len, int may_sleep); -+ -+enum glamo_engine { -+ GLAMO_ENGINE_CAPTURE, -+ GLAMO_ENGINE_ISP, -+ GLAMO_ENGINE_JPEG, -+ GLAMO_ENGINE_MPEG_ENC, -+ GLAMO_ENGINE_MPEG_DEC, -+ GLAMO_ENGINE_LCD, -+ GLAMO_ENGINE_CMDQ, -+ GLAMO_ENGINE_2D, -+ GLAMO_ENGINE_3D, -+ GLAMO_ENGINE_MMC, -+ GLAMO_ENGINE_MICROP0, -+ GLAMO_ENGINE_RISC, -+ GLAMO_ENGINE_MICROP1_MPEG_ENC, -+ GLAMO_ENGINE_MICROP1_MPEG_DEC, -+#if 0 -+ GLAMO_ENGINE_H264_DEC, -+ GLAMO_ENGINE_RISC1, -+ GLAMO_ENGINE_SPI, -+#endif -+ __NUM_GLAMO_ENGINES -+}; -+ -+struct glamo_mci_pdata { -+ struct glamo_core * pglamo; -+ unsigned int gpio_detect; -+ unsigned int gpio_wprotect; -+ unsigned long ocr_avail; -+ void (*glamo_set_mci_power)(unsigned char power_mode, -+ unsigned short vdd); -+ int (*glamo_irq_is_wired)(void); -+}; -+ -+ -+static inline void glamo_reg_access_delay(void) -+{ -+ int n; -+ -+ for (n = 0; n != 2; n++) -+ nop(); -+} -+ -+ -+int glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine); -+int glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine); -+void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine); -+int glamo_engine_reclock(struct glamo_core *glamo, -+ enum glamo_engine engine, int ps); -+ -+#endif /* __GLAMO_CORE_H */ -diff --git a/drivers/mfd/glamo/glamo-fb.c b/drivers/mfd/glamo/glamo-fb.c -new file mode 100644 -index 0000000..394a0ad ---- /dev/null -+++ b/drivers/mfd/glamo/glamo-fb.c -@@ -0,0 +1,822 @@ -+/* Smedia Glamo 336x/337x driver -+ * -+ * (C) 2007 by OpenMoko, Inc. -+ * Author: Harald Welte <laforge@openmoko.org> -+ * All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ */ -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/errno.h> -+#include <linux/string.h> -+#include <linux/mm.h> -+#include <linux/slab.h> -+#include <linux/delay.h> -+#include <linux/fb.h> -+#include <linux/init.h> -+#include <linux/vmalloc.h> -+#include <linux/dma-mapping.h> -+#include <linux/interrupt.h> -+#include <linux/workqueue.h> -+#include <linux/wait.h> -+#include <linux/platform_device.h> -+#include <linux/clk.h> -+ -+#include <asm/io.h> -+#include <asm/uaccess.h> -+#include <asm/div64.h> -+ -+#ifdef CONFIG_PM -+#include <linux/pm.h> -+#endif -+ -+#include <linux/glamofb.h> -+ -+#include "glamo-regs.h" -+#include "glamo-core.h" -+ -+#ifdef DEBUG -+#define GLAMO_LOG(...) -+#else -+#define GLAMO_LOG(...) \ -+do { \ -+ printk(KERN_DEBUG "in %s:%s:%d", __FILE__, __func__, __LINE__); \ -+ printk(KERN_DEBUG __VA_ARGS__); \ -+} while (0); -+#endif -+ -+ -+#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1) -+ -+struct glamofb_handle { -+ struct fb_info *fb; -+ struct device *dev; -+ struct resource *reg; -+ struct resource *fb_res; -+ char __iomem *base; -+ struct glamofb_platform_data *mach_info; -+ char __iomem *cursor_addr; -+ u_int32_t pseudo_pal[16]; -+}; -+ -+/* 'sibling' spi device for lcm init */ -+static struct platform_device glamo_spi_dev = { -+ .name = "glamo-lcm-spi", -+}; -+ -+ -+static int reg_read(struct glamofb_handle *glamo, -+ u_int16_t reg) -+{ -+ glamo_reg_access_delay(); -+ return readw(glamo->base + reg); -+} -+ -+static void reg_write(struct glamofb_handle *glamo, -+ u_int16_t reg, u_int16_t val) -+{ -+ glamo_reg_access_delay(); -+ writew(val, glamo->base + reg); -+} -+ -+static struct glamo_script glamo_regs[] = { -+ { GLAMO_REG_LCD_MODE1, 0x0020 }, -+ /* no display rotation, no hardware cursor, no dither, no gamma, -+ * no retrace flip, vsync low-active, hsync low active, -+ * no TVCLK, no partial display, hw dest color from fb, -+ * no partial display mode, LCD1, software flip, */ -+ { GLAMO_REG_LCD_MODE2, 0x1020 }, -+ /* no video flip, no ptr, no ptr, dhclk, -+ * normal mode, no cpuif, -+ * res, serial msb first, single fb, no fr ctrl, -+ * cpu if bits all zero, no crc -+ * 0000 0000 0010 0000 */ -+ { GLAMO_REG_LCD_MODE3, 0x0b40 }, -+ /* src data rgb565, res, 18bit rgb666 -+ * 000 01 011 0100 0000 */ -+ { GLAMO_REG_LCD_POLARITY, 0x440c }, -+ /* DE high active, no cpu/lcd if, cs0 force low, a0 low active, -+ * np cpu if, 9bit serial data, sclk rising edge latch data -+ * 01 00 0 100 0 000 01 0 0 */ -+ { GLAMO_REG_LCD_A_BASE1, 0x0000 }, /* display A base address 15:0 */ -+ { GLAMO_REG_LCD_A_BASE2, 0x0000 }, /* display A base address 22:16 */ -+}; -+ -+static int glamofb_run_script(struct glamofb_handle *glamo, -+ struct glamo_script *script, int len) -+{ -+ int i; -+ -+ for (i = 0; i < len; i++) { -+ struct glamo_script *line = &script[i]; -+ -+ if (line->reg == 0xffff) -+ return 0; -+ else if (line->reg == 0xfffe) -+ msleep(line->val); -+ else -+ reg_write(glamo, script[i].reg, script[i].val); -+ } -+ -+ return 0; -+} -+ -+static int glamofb_check_var(struct fb_var_screeninfo *var, -+ struct fb_info *info) -+{ -+ struct glamofb_handle *glamo = info->par; -+ -+ if (var->yres > glamo->mach_info->yres.max) -+ var->yres = glamo->mach_info->yres.max; -+ else if (var->yres < glamo->mach_info->yres.min) -+ var->yres = glamo->mach_info->yres.min; -+ -+ if (var->xres > glamo->mach_info->xres.max) -+ var->xres = glamo->mach_info->xres.max; -+ else if (var->xres < glamo->mach_info->xres.min) -+ var->xres = glamo->mach_info->xres.min; -+ -+ if (var->bits_per_pixel > glamo->mach_info->bpp.max) -+ var->bits_per_pixel = glamo->mach_info->bpp.max; -+ else if (var->bits_per_pixel < glamo->mach_info->bpp.min) -+ var->bits_per_pixel = glamo->mach_info->bpp.min; -+ -+ /* FIXME: set rgb positions */ -+ switch (var->bits_per_pixel) { -+ case 16: -+ switch (reg_read(glamo, GLAMO_REG_LCD_MODE3) & 0xc000) { -+ case GLAMO_LCD_SRC_RGB565: -+ var->red.offset = 11; -+ var->green.offset = 5; -+ var->blue.offset = 0; -+ var->red.length = 5; -+ var->green.length = 6; -+ var->blue.length = 5; -+ var->transp.length = 0; -+ break; -+ case GLAMO_LCD_SRC_ARGB1555: -+ var->transp.offset = 15; -+ var->red.offset = 10; -+ var->green.offset = 5; -+ var->blue.offset = 0; -+ var->transp.length = 1; -+ var->red.length = 5; -+ var->green.length = 5; -+ var->blue.length = 5; -+ break; -+ case GLAMO_LCD_SRC_ARGB4444: -+ var->transp.offset = 12; -+ var->red.offset = 8; -+ var->green.offset = 4; -+ var->blue.offset = 0; -+ var->transp.length = 4; -+ var->red.length = 4; -+ var->green.length = 4; -+ var->blue.length = 4; -+ break; -+ } -+ break; -+ case 24: -+ case 32: -+ default: -+ /* The Smedia Glamo doesn't support anything but 16bit color */ -+ printk(KERN_ERR -+ "Smedia driver does not [yet?] support 24/32bpp\n"); -+ return -EINVAL; -+ break; -+ } -+ -+ return 0; -+} -+ -+static void reg_set_bit_mask(struct glamofb_handle *glamo, -+ u_int16_t reg, u_int16_t mask, -+ u_int16_t val) -+{ -+ u_int16_t tmp; -+ -+ val &= mask; -+ -+ tmp = reg_read(glamo, reg); -+ tmp &= ~mask; -+ tmp |= val; -+ reg_write(glamo, reg, tmp); -+} -+ -+#define GLAMO_LCD_WIDTH_MASK 0x03FF -+#define GLAMO_LCD_HEIGHT_MASK 0x03FF -+#define GLAMO_LCD_PITCH_MASK 0x07FE -+#define GLAMO_LCD_HV_TOTAL_MASK 0x03FF -+#define GLAMO_LCD_HV_RETR_START_MASK 0x03FF -+#define GLAMO_LCD_HV_RETR_END_MASK 0x03FF -+#define GLAMO_LCD_HV_RETR_DISP_START_MASK 0x03FF -+#define GLAMO_LCD_HV_RETR_DISP_END_MASK 0x03FF -+ -+enum orientation { -+ ORIENTATION_PORTRAIT, -+ ORIENTATION_LANDSCAPE -+}; -+ -+ -+static void rotate_lcd(struct glamofb_handle *glamo, -+ __u32 rotation) -+{ -+ int glamo_rot; -+ -+ switch (rotation) { -+ case FB_ROTATE_UR: -+ glamo_rot = GLAMO_LCD_ROT_MODE_0; -+ break; -+ case FB_ROTATE_CW: -+ glamo_rot = GLAMO_LCD_ROT_MODE_90; -+ break; -+ case FB_ROTATE_UD: -+ glamo_rot = GLAMO_LCD_ROT_MODE_180; -+ break; -+ case FB_ROTATE_CCW: -+ glamo_rot = GLAMO_LCD_ROT_MODE_270; -+ break; -+ default: -+ glamo_rot = GLAMO_LCD_ROT_MODE_0; -+ break; -+ } -+ glamofb_cmd_mode(glamo, 1); -+ reg_set_bit_mask(glamo, -+ GLAMO_REG_LCD_WIDTH, -+ GLAMO_LCD_ROT_MODE_MASK, -+ glamo_rot); -+ reg_set_bit_mask(glamo, -+ GLAMO_REG_LCD_MODE1, -+ GLAMO_LCD_MODE1_ROTATE_EN, -+ (glamo_rot != GLAMO_LCD_ROT_MODE_0)? -+ GLAMO_LCD_MODE1_ROTATE_EN : 0); -+ glamofb_cmd_mode(glamo, 0); -+} -+ -+static enum orientation get_orientation(struct fb_var_screeninfo *var) -+{ -+ GLAMO_LOG("mark\n") -+ if (var->xres <= var->yres) { -+ GLAMO_LOG("portrait\n") -+ return ORIENTATION_PORTRAIT; -+ } -+ GLAMO_LOG("landscape\n") -+ return ORIENTATION_LANDSCAPE; -+} -+ -+static int will_orientation_change(struct fb_var_screeninfo *var) -+{ -+ enum orientation orient = get_orientation(var); -+ switch (orient) { -+ case ORIENTATION_LANDSCAPE: -+ if (var->rotate == FB_ROTATE_UR || var->rotate == FB_ROTATE_UD) -+ return 1; -+ break; -+ case ORIENTATION_PORTRAIT: -+ if (var->rotate == FB_ROTATE_CW || var->rotate == FB_ROTATE_CCW) -+ return 1; -+ break; -+ } -+ return 0; -+} -+ -+static void glamofb_update_lcd_controller(struct glamofb_handle *glamo, -+ struct fb_var_screeninfo *var) -+{ -+ int sync, bp, disp, fp, total, xres, yres, pitch, orientation_changing; -+ -+ GLAMO_LOG("enter: glamo:%#x, var:%#x\n", (unsigned)glamo, (unsigned)var); -+ if (!glamo || !var) -+ return; -+ -+ glamofb_cmd_mode(glamo, 1); -+ -+ if (var->pixclock) -+ glamo_engine_reclock(glamo->mach_info->glamo, -+ GLAMO_ENGINE_LCD, -+ var->pixclock); -+ -+ xres = var->xres; -+ yres = var->yres; -+ GLAMO_LOG("xres:%d, yres:%d, rotate:%d\n", xres, yres, var->rotate); -+ -+ /* -+ * figure out if orientation is going to change -+ */ -+ orientation_changing = will_orientation_change(var); -+ GLAMO_LOG("orientation_changing:%d\n", orientation_changing); -+ -+ /* -+ * adjust the pitch according to new orientation to come -+ */ -+ if (orientation_changing) { -+ pitch = var->yres * var->bits_per_pixel / 8; -+ } else { -+ pitch = var->xres * var->bits_per_pixel / 8; -+ } -+ GLAMO_LOG("pitch:%d\n", pitch); -+ -+ /* -+ * set the awaiten LCD geometry -+ */ -+ reg_set_bit_mask(glamo, -+ GLAMO_REG_LCD_WIDTH, -+ GLAMO_LCD_WIDTH_MASK, -+ xres); -+ reg_set_bit_mask(glamo, -+ GLAMO_REG_LCD_HEIGHT, -+ GLAMO_LCD_HEIGHT_MASK, -+ yres); -+ reg_set_bit_mask(glamo, -+ GLAMO_REG_LCD_PITCH, -+ GLAMO_LCD_PITCH_MASK, -+ pitch); -+ -+ GLAMO_LOG("mark:\n"); -+ /* -+ * honour the rotation request -+ */ -+ rotate_lcd(glamo, var->rotate); -+ -+ /* -+ * update the reported geometry -+ * of the framebuffer. -+ */ -+ if (orientation_changing) { -+ var->xres_virtual = var->xres = yres; -+ var->yres_virtual = var->yres = xres; -+ } else { -+ var->xres_virtual = var->xres = xres; -+ var->yres_virtual = var->yres = yres; -+ } -+ -+ GLAMO_LOG("reported res:(%d,%d)\n", var->xres, var->yres); -+ /* -+ * update scannout timings -+ */ -+ sync = 0; -+ bp = sync + var->hsync_len; -+ disp = bp + var->left_margin; -+ fp = disp + xres; -+ total = fp + var->right_margin; -+ -+ reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_TOTAL, -+ GLAMO_LCD_HV_TOTAL_MASK, total); -+ reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_RETR_START, -+ GLAMO_LCD_HV_RETR_START_MASK, sync); -+ reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_RETR_END, -+ GLAMO_LCD_HV_RETR_END_MASK, bp); -+ reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_START, -+ GLAMO_LCD_HV_RETR_DISP_START_MASK, disp); -+ reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_END, -+ GLAMO_LCD_HV_RETR_DISP_END_MASK, fp); -+ -+ GLAMO_LOG("mark:\n"); -+ -+ sync = 0; -+ bp = sync + var->vsync_len; -+ disp = bp + var->upper_margin; -+ fp = disp + yres; -+ total = fp + var->lower_margin; -+ -+ reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_TOTAL, -+ GLAMO_LCD_HV_TOTAL_MASK, total); -+ reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_RETR_START, -+ GLAMO_LCD_HV_RETR_START_MASK, sync); -+ reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_RETR_END, -+ GLAMO_LCD_HV_RETR_END_MASK, bp); -+ reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_START, -+ GLAMO_LCD_HV_RETR_DISP_START_MASK, disp); -+ reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_END, -+ GLAMO_LCD_HV_RETR_DISP_END_MASK, fp); -+ -+ GLAMO_LOG("mark:\n"); -+ glamofb_cmd_mode(glamo, 0); -+ -+ GLAMO_LOG("leave:\n"); -+} -+ -+static int glamofb_set_par(struct fb_info *info) -+{ -+ struct glamofb_handle *glamo = info->par; -+ struct fb_var_screeninfo *var = &info->var; -+ -+ switch (var->bits_per_pixel) { -+ case 16: -+ info->fix.visual = FB_VISUAL_TRUECOLOR; -+ break; -+ default: -+ printk("Smedia driver doesn't support != 16bpp\n"); -+ return -EINVAL; -+ } -+ -+ info->fix.line_length = (var->xres * var->bits_per_pixel) / 8; -+ -+ glamofb_update_lcd_controller(glamo, var); -+ -+ return 0; -+} -+ -+static int glamofb_blank(int blank_mode, struct fb_info *info) -+{ -+ /* FIXME */ -+ return 0; -+} -+ -+static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf) -+{ -+ chan &= 0xffff; -+ chan >>= 16 - bf->length; -+ return chan << bf->offset; -+} -+ -+static int glamofb_setcolreg(unsigned regno, -+ unsigned red, unsigned green, unsigned blue, -+ unsigned transp, struct fb_info *info) -+{ -+ struct glamofb_handle *glamo = info->par; -+ unsigned int val; -+ -+ switch (glamo->fb->fix.visual) { -+ case FB_VISUAL_TRUECOLOR: -+ case FB_VISUAL_DIRECTCOLOR: -+ /* true-colour, use pseuo-palette */ -+ -+ if (regno < 16) { -+ u32 *pal = glamo->fb->pseudo_palette; -+ -+ val = chan_to_field(red, &glamo->fb->var.red); -+ val |= chan_to_field(green, &glamo->fb->var.green); -+ val |= chan_to_field(blue, &glamo->fb->var.blue); -+ -+ pal[regno] = val; -+ }; -+ break; -+ default: -+ return 1; /* unknown type */ -+ } -+ -+ return 0; -+} -+ -+static int glamofb_cursor(struct fb_info *info, struct fb_cursor *cursor) -+{ -+ struct glamofb_handle *glamo = info->par; -+ u_int16_t reg; -+ -+ if (cursor->image.depth > 2) -+ return -EINVAL; -+ -+ reg = reg_read(glamo, GLAMO_REG_LCD_MODE1); -+ -+ if (cursor->enable) -+ reg_write(glamo, GLAMO_REG_LCD_MODE1, -+ reg | GLAMO_LCD_MODE1_CURSOR_EN); -+ else -+ reg_write(glamo, GLAMO_REG_LCD_MODE1, -+ reg & ~GLAMO_LCD_MODE1_CURSOR_EN); -+ -+ if (cursor->set & FB_CUR_SETPOS) { -+ reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_POS, -+ cursor->image.dx); -+ reg_write(glamo, GLAMO_REG_LCD_CURSOR_Y_POS, -+ cursor->image.dy); -+ } -+ -+ if (cursor->set & FB_CUR_SETCMAP) { -+ /* FIXME */ -+ } -+ -+ if (cursor->set & FB_CUR_SETSIZE || -+ cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) { -+ int x, y, op; -+ const unsigned char *pcol = cursor->image.data; -+ const unsigned char *pmsk = cursor->mask; -+ void __iomem *dst = glamo->cursor_addr; -+ unsigned char dcol = 0; -+ unsigned char dmsk = 0; -+ -+ reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE, -+ cursor->image.width); -+ reg_write(glamo, GLAMO_REG_LCD_CURSOR_PITCH, -+ cursor->image.width * 2); -+ reg_write(glamo, GLAMO_REG_LCD_CURSOR_Y_SIZE, -+ cursor->image.height); -+ -+ for (op = 0; op < (cursor->image.width * -+ cursor->image.height * 2)/8; op += 4) -+ writel(0x0, dst + op); -+ -+ for (y = 0; y < cursor->image.height; y++) { -+ for (x = 0; x < cursor->image.width; x++) { -+ if ((x % 8) == 0) { -+ dcol = *pcol++; -+ dmsk = *pmsk++; -+ } else { -+ dcol >>= 1; -+ dmsk >>= 1; -+ } -+ -+ if (dmsk & 1) { -+ unsigned int op; -+ -+ op = (dcol & 1) ? 1 : 3; -+ op <<= ((x % 4) * 2); -+ -+ op |= readb(dst + (x / 4)); -+ writeb(op, dst + (x / 4)); -+ } -+ } -+ } -+ } -+} -+ -+static inline int glamofb_cmdq_empty(struct glamofb_handle *gfb) -+{ -+ return reg_read(gfb, GLAMO_REG_LCD_STATUS1) & (1 << 15); -+} -+ -+void glamofb_cmd_mode(struct glamofb_handle *gfb, int on) -+{ -+ dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on); -+ if (on) { -+ dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ", -+ __FUNCTION__); -+ while (!glamofb_cmdq_empty(gfb)) -+ yield(); -+ dev_dbg(gfb->dev, "empty!\n"); -+ -+ /* display the entire frame then switch to command */ -+ reg_write(gfb, GLAMO_REG_LCD_COMMAND1, -+ GLAMO_LCD_CMD_TYPE_DISP | -+ GLAMO_LCD_CMD_DATA_FIRE_VSYNC); -+ -+ /* wait until LCD is idle */ -+ dev_dbg(gfb->dev, "waiting for LCD idle: "); -+ while (!reg_read(gfb, GLAMO_REG_LCD_STATUS2) & (1 << 12)) -+ yield(); -+ dev_dbg(gfb->dev, "idle!\n"); -+ -+ msleep(90); -+ } else { -+ /* RGB interface needs vsync/hsync */ -+ if (reg_read(gfb, GLAMO_REG_LCD_MODE3) & GLAMO_LCD_MODE3_RGB) -+ reg_write(gfb, GLAMO_REG_LCD_COMMAND1, -+ GLAMO_LCD_CMD_TYPE_DISP | -+ GLAMO_LCD_CMD_DATA_DISP_SYNC); -+ -+ reg_write(gfb, GLAMO_REG_LCD_COMMAND1, -+ GLAMO_LCD_CMD_TYPE_DISP | -+ GLAMO_LCD_CMD_DATA_DISP_FIRE); -+ } -+} -+EXPORT_SYMBOL_GPL(glamofb_cmd_mode); -+ -+int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val) -+{ -+ dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n", -+ __FUNCTION__); -+ while (!glamofb_cmdq_empty(gfb)) -+ yield(); -+ dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val); -+ -+ reg_write(gfb, GLAMO_REG_LCD_COMMAND1, val); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(glamofb_cmd_write); -+ -+static struct fb_ops glamofb_ops = { -+ .owner = THIS_MODULE, -+ .fb_check_var = glamofb_check_var, -+ .fb_set_par = glamofb_set_par, -+ .fb_blank = glamofb_blank, -+ .fb_setcolreg = glamofb_setcolreg, -+ //.fb_cursor = glamofb_cursor, -+ .fb_fillrect = cfb_fillrect, -+ .fb_copyarea = cfb_copyarea, -+ .fb_imageblit = cfb_imageblit, -+}; -+ -+static int glamofb_init_regs(struct glamofb_handle *glamo) -+{ -+ struct fb_info *info = glamo->fb; -+ -+ glamofb_check_var(&info->var, info); -+ glamofb_run_script(glamo, glamo_regs, ARRAY_SIZE(glamo_regs)); -+ glamofb_set_par(info); -+ -+ return 0; -+} -+ -+static int __init glamofb_probe(struct platform_device *pdev) -+{ -+ int rc = -EIO; -+ struct fb_info *fbinfo; -+ struct glamofb_handle *glamofb; -+ struct glamofb_platform_data *mach_info = pdev->dev.platform_data; -+ -+ printk(KERN_INFO "SMEDIA Glamo frame buffer driver (C) 2007 " -+ "OpenMoko, Inc.\n"); -+ -+ fbinfo = framebuffer_alloc(sizeof(struct glamofb_handle), &pdev->dev); -+ if (!fbinfo) -+ return -ENOMEM; -+ -+ glamofb = fbinfo->par; -+ glamofb->fb = fbinfo; -+ glamofb->dev = &pdev->dev; -+ -+ strcpy(fbinfo->fix.id, "SMedia Glamo"); -+ -+ glamofb->reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, -+ "glamo-fb-regs"); -+ if (!glamofb->reg) { -+ dev_err(&pdev->dev, "platform device with no registers?\n"); -+ rc = -ENOENT; -+ goto out_free; -+ } -+ -+ glamofb->fb_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, -+ "glamo-fb-mem"); -+ if (!glamofb->fb_res) { -+ dev_err(&pdev->dev, "platform device with no memory ?\n"); -+ rc = -ENOENT; -+ goto out_free; -+ } -+ -+ glamofb->reg = request_mem_region(glamofb->reg->start, -+ RESSIZE(glamofb->reg), pdev->name); -+ if (!glamofb->reg) { -+ dev_err(&pdev->dev, "failed to request mmio region\n"); -+ goto out_free; -+ } -+ -+ glamofb->fb_res = request_mem_region(glamofb->fb_res->start, -+ mach_info->fb_mem_size, -+ pdev->name); -+ if (!glamofb->fb_res) { -+ dev_err(&pdev->dev, "failed to request vram region\n"); -+ goto out_release_reg; -+ } -+ -+ /* we want to remap only the registers required for this core -+ * driver. */ -+ glamofb->base = ioremap(glamofb->reg->start, RESSIZE(glamofb->reg)); -+ if (!glamofb->base) { -+ dev_err(&pdev->dev, "failed to ioremap() mmio memory\n"); -+ goto out_release_fb; -+ } -+ fbinfo->fix.smem_start = (unsigned long) glamofb->fb_res->start; -+ fbinfo->fix.smem_len = mach_info->fb_mem_size; -+ -+ fbinfo->screen_base = ioremap(glamofb->fb_res->start, -+ RESSIZE(glamofb->fb_res)); -+ if (!fbinfo->screen_base) { -+ dev_err(&pdev->dev, "failed to ioremap() vram memory\n"); -+ goto out_release_fb; -+ } -+ -+ platform_set_drvdata(pdev, fbinfo); -+ -+ glamofb->mach_info = pdev->dev.platform_data; -+ -+ fbinfo->fix.visual = FB_VISUAL_TRUECOLOR; -+ fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; -+ fbinfo->fix.type_aux = 0; -+ fbinfo->fix.xpanstep = 0; -+ fbinfo->fix.ypanstep = 0; -+ fbinfo->fix.ywrapstep = 0; -+ fbinfo->fix.accel = FB_ACCEL_NONE; /* FIXME */ -+ -+ fbinfo->var.nonstd = 0; -+ fbinfo->var.activate = FB_ACTIVATE_NOW; -+ fbinfo->var.height = mach_info->height; -+ fbinfo->var.width = mach_info->width; -+ fbinfo->var.accel_flags = 0; -+ fbinfo->var.vmode = FB_VMODE_NONINTERLACED; -+ -+ fbinfo->fbops = &glamofb_ops; -+ fbinfo->flags = FBINFO_FLAG_DEFAULT; -+ fbinfo->pseudo_palette = &glamofb->pseudo_pal; -+ -+ fbinfo->var.xres = mach_info->xres.defval; -+ fbinfo->var.xres_virtual = mach_info->xres.defval; -+ fbinfo->var.yres = mach_info->yres.defval; -+ fbinfo->var.yres_virtual = mach_info->yres.defval; -+ fbinfo->var.bits_per_pixel = mach_info->bpp.defval; -+ -+ fbinfo->var.pixclock = mach_info->pixclock; -+ fbinfo->var.left_margin = mach_info->left_margin; -+ fbinfo->var.right_margin = mach_info->right_margin; -+ fbinfo->var.upper_margin = mach_info->upper_margin; -+ fbinfo->var.lower_margin = mach_info->lower_margin; -+ fbinfo->var.hsync_len = mach_info->hsync_len; -+ fbinfo->var.vsync_len = mach_info->vsync_len; -+ -+ memset(fbinfo->screen_base, 0, fbinfo->fix.smem_len); -+ -+ glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD); -+ glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD); -+ glamofb_init_regs(glamofb); -+ -+ rc = register_framebuffer(fbinfo); -+ if (rc < 0) { -+ dev_err(&pdev->dev, "failed to register framebuffer\n"); -+ goto out_unmap_fb; -+ } -+ -+ if (mach_info->spi_info) { -+ /* register the sibling spi device */ -+ mach_info->spi_info->glamofb_handle = glamofb; -+ glamo_spi_dev.dev.parent = &pdev->dev; -+ glamo_spi_dev.dev.platform_data = mach_info->spi_info; -+ platform_device_register(&glamo_spi_dev); -+ } -+ -+ printk(KERN_INFO "fb%d: %s frame buffer device\n", -+ fbinfo->node, fbinfo->fix.id); -+ -+ return 0; -+ -+out_unmap_fb: -+ iounmap(fbinfo->screen_base); -+ iounmap(glamofb->base); -+out_release_fb: -+ release_mem_region(glamofb->fb_res->start, RESSIZE(glamofb->fb_res)); -+out_release_reg: -+ release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg)); -+out_free: -+ framebuffer_release(fbinfo); -+ return rc; -+} -+ -+static int glamofb_remove(struct platform_device *pdev) -+{ -+ struct glamofb_handle *glamofb = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ iounmap(glamofb->base); -+ release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg)); -+ kfree(glamofb); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int glamofb_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ return 0; -+} -+ -+static int glamofb_resume(struct platform_device *pdev) -+{ -+ return 0; -+} -+#else -+#define glamofb_suspend NULL -+#define glamofb_resume NULL -+#endif -+ -+static struct platform_driver glamofb_driver = { -+ .probe = glamofb_probe, -+ .remove = glamofb_remove, -+ .suspend = glamofb_suspend, -+ .resume = glamofb_resume, -+ .driver = { -+ .name = "glamo-fb", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __devinit glamofb_init(void) -+{ -+ return platform_driver_register(&glamofb_driver); -+} -+ -+static void __exit glamofb_cleanup(void) -+{ -+ platform_driver_unregister(&glamofb_driver); -+} -+ -+module_init(glamofb_init); -+module_exit(glamofb_cleanup); -+ -+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>"); -+MODULE_DESCRIPTION("Smedia Glamo 336x/337x framebuffer driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/mfd/glamo/glamo-gpio.c b/drivers/mfd/glamo/glamo-gpio.c -new file mode 100644 -index 0000000..45d0bf9 ---- /dev/null -+++ b/drivers/mfd/glamo/glamo-gpio.c -@@ -0,0 +1,62 @@ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/spinlock.h> -+#include <linux/io.h> -+ -+#include <linux/glamo-gpio.h> -+ -+#include "glamo-core.h" -+#include "glamo-regs.h" -+ -+void glamo_gpio_setpin(struct glamo_core *glamo, unsigned int pin, -+ unsigned int value) -+{ -+ unsigned int reg = REG_OF_GPIO(pin); -+ u_int16_t tmp; -+ -+ spin_lock(&glamo->lock); -+ tmp = readw(glamo->base + reg); -+ if (value) -+ tmp |= OUTPUT_BIT(pin); -+ else -+ tmp &= ~OUTPUT_BIT(pin); -+ writew(tmp, glamo->base + reg); -+ spin_unlock(&glamo->lock); -+} -+EXPORT_SYMBOL(glamo_gpio_setpin); -+ -+int glamo_gpio_getpin(struct glamo_core *glamo, unsigned int pin) -+{ -+ return readw(REG_OF_GPIO(pin)) & INPUT_BIT(pin) ? 1 : 0; -+} -+EXPORT_SYMBOL(glamo_gpio_getpin); -+ -+void glamo_gpio_cfgpin(struct glamo_core *glamo, unsigned int pinfunc) -+{ -+ unsigned int reg = REG_OF_GPIO(pinfunc); -+ u_int16_t tmp; -+ -+ spin_lock(&glamo->lock); -+ tmp = readw(glamo->base + reg); -+ -+ if ((pinfunc & 0x00f0) == GLAMO_GPIO_F_FUNC) { -+ /* pin is a function pin: clear gpio bit */ -+ tmp &= ~FUNC_BIT(pinfunc); -+ } else { -+ /* pin is gpio: set gpio bit */ -+ tmp |= FUNC_BIT(pinfunc); -+ -+ if (pinfunc & GLAMO_GPIO_F_IN) { -+ /* gpio input: set bit to disable output mode */ -+ tmp |= GPIO_OUT_BIT(pinfunc); -+ } else if (pinfunc & GLAMO_GPIO_F_OUT) { -+ /* gpio output: clear bit to enable output mode */ -+ tmp &= ~GPIO_OUT_BIT(pinfunc); -+ } -+ } -+ writew(tmp, glamo->base + reg); -+ spin_unlock(&glamo->lock); -+} -+EXPORT_SYMBOL(glamo_gpio_cfgpin); -+ -diff --git a/drivers/mfd/glamo/glamo-lcm-spi.c b/drivers/mfd/glamo/glamo-lcm-spi.c -new file mode 100644 -index 0000000..92cabe4 ---- /dev/null -+++ b/drivers/mfd/glamo/glamo-lcm-spi.c -@@ -0,0 +1,241 @@ -+/* -+ * Copyright (C) 2007 OpenMoko, Inc. -+ * Author: Harald Welte <laforge@openmoko.org> -+ * -+ * Smedia Glamo GPIO based SPI driver -+ * -+ * 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. -+ * -+ * This driver currently only implements a minimum subset of the hardware -+ * features, esp. those features that are required to drive the jbt6k74 -+ * LCM controller asic in the TD028TTEC1 LCM. -+ * -+*/ -+ -+#define DEBUG -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <linux/spinlock.h> -+#include <linux/workqueue.h> -+#include <linux/platform_device.h> -+ -+#include <linux/spi/spi.h> -+#include <linux/spi/spi_bitbang.h> -+#include <linux/spi/glamo.h> -+ -+#include <linux/glamofb.h> -+ -+#include <asm/hardware.h> -+ -+#include "glamo-core.h" -+#include "glamo-regs.h" -+ -+struct glamo_spi { -+ struct spi_bitbang bitbang; -+ struct spi_master *master; -+ struct glamo_spi_info *info; -+ struct device *dev; -+}; -+ -+static inline struct glamo_spi *to_gs(struct spi_device *spi) -+{ -+ return spi->controller_data; -+} -+ -+static int glamo_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) -+{ -+ struct glamo_spi *gs = to_gs(spi); -+ unsigned int bpw; -+ -+ bpw = t ? t->bits_per_word : spi->bits_per_word; -+ -+ if (bpw != 9 && bpw != 8) { -+ dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static void glamo_spi_chipsel(struct spi_device *spi, int value) -+{ -+#if 0 -+ struct glamo_spi *gs = to_gs(spi); -+ -+ dev_dbg(&spi->dev, "chipsel %d: spi=%p, gs=%p, info=%p, handle=%p\n", -+ value, spi, gs, gs->info, gs->info->glamofb_handle); -+ -+ glamofb_cmd_mode(gs->info->glamofb_handle, value); -+#endif -+} -+ -+static int glamo_spi_txrx(struct spi_device *spi, struct spi_transfer *t) -+{ -+ struct glamo_spi *gs = to_gs(spi); -+ const u_int16_t *ui16 = (const u_int16_t *) t->tx_buf; -+ u_int16_t nine_bits; -+ int i; -+ -+ dev_dbg(&spi->dev, "txrx: tx %p, rx %p, bpw %d, len %d\n", -+ t->tx_buf, t->rx_buf, t->bits_per_word, t->len); -+ -+ if (spi->bits_per_word == 9) -+ nine_bits = (1 << 9); -+ else -+ nine_bits = 0; -+ -+ if (t->len > 3 * sizeof(u_int16_t)) { -+ dev_err(&spi->dev, "this driver doesn't support " -+ "%u sized xfers\n", t->len); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < t->len/sizeof(u_int16_t); i++) { -+ /* actually transfer the data */ -+#if 1 -+ glamofb_cmd_write(gs->info->glamofb_handle, -+ GLAMO_LCD_CMD_TYPE_SERIAL | nine_bits | -+ (1 << 10) | (1 << 11) | (ui16[i] & 0x1ff)); -+#endif -+ /* FIXME: fire ?!? */ -+ if (i == 0 && (ui16[i] & 0x1ff) == 0x29) { -+ dev_dbg(&spi->dev, "leaving command mode\n"); -+ glamofb_cmd_mode(gs->info->glamofb_handle, 0); -+ } -+ } -+ -+ return t->len; -+} -+ -+static int glamo_spi_setup(struct spi_device *spi) -+{ -+ int ret; -+ -+ if (!spi->bits_per_word) -+ spi->bits_per_word = 9; -+ -+ /* FIXME: hardware can do this */ -+ if (spi->mode & SPI_LSB_FIRST) -+ return -EINVAL; -+ -+ ret = glamo_spi_setupxfer(spi, NULL); -+ if (ret < 0) { -+ dev_err(&spi->dev, "setupxfer returned %d\n", ret); -+ return ret; -+ } -+ -+ dev_dbg(&spi->dev, "%s: mode %d, %u bpw\n", -+ __FUNCTION__, spi->mode, spi->bits_per_word); -+ -+ return 0; -+} -+ -+static int glamo_spi_probe(struct platform_device *pdev) -+{ -+ struct spi_master *master; -+ struct glamo_spi *sp; -+ int ret; -+ int i; -+ -+ master = spi_alloc_master(&pdev->dev, sizeof(struct glamo_spi)); -+ if (master == NULL) { -+ dev_err(&pdev->dev, "failed to allocate spi master\n"); -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ sp = spi_master_get_devdata(master); -+ memset(sp, 0, sizeof(struct glamo_spi)); -+ -+ sp->master = spi_master_get(master); -+ sp->info = pdev->dev.platform_data; -+ if (!sp->info) { -+ dev_err(&pdev->dev, "can't operate without platform data\n"); -+ ret = -EIO; -+ goto err_no_pdev; -+ } -+ dev_dbg(&pdev->dev, "sp->info(pdata) = %p\n", sp->info); -+ -+ sp->dev = &pdev->dev; -+ -+ platform_set_drvdata(pdev, sp); -+ -+ sp->bitbang.master = sp->master; -+ sp->bitbang.setup_transfer = glamo_spi_setupxfer; -+ sp->bitbang.chipselect = glamo_spi_chipsel; -+ sp->bitbang.txrx_bufs = glamo_spi_txrx; -+ sp->bitbang.master->setup = glamo_spi_setup; -+ -+ ret = spi_bitbang_start(&sp->bitbang); -+ if (ret) -+ goto err_no_bitbang; -+ -+ /* register the chips to go with the board */ -+ -+ glamofb_cmd_mode(sp->info->glamofb_handle, 1); -+ -+ for (i = 0; i < sp->info->board_size; i++) { -+ dev_info(&pdev->dev, "registering %p: %s\n", -+ &sp->info->board_info[i], -+ sp->info->board_info[i].modalias); -+ -+ sp->info->board_info[i].controller_data = sp; -+ spi_new_device(master, sp->info->board_info + i); -+ } -+ -+ return 0; -+ -+err_no_bitbang: -+ platform_set_drvdata(pdev, NULL); -+err_no_pdev: -+ spi_master_put(sp->bitbang.master); -+err: -+ return ret; -+ -+} -+ -+static int glamo_spi_remove(struct platform_device *pdev) -+{ -+ struct glamo_spi *sp = platform_get_drvdata(pdev); -+ -+ spi_bitbang_stop(&sp->bitbang); -+ spi_master_put(sp->bitbang.master); -+ -+ return 0; -+} -+ -+#define glamo_spi_suspend NULL -+#define glamo_spi_resume NULL -+ -+static struct platform_driver glamo_spi_drv = { -+ .probe = glamo_spi_probe, -+ .remove = glamo_spi_remove, -+ .suspend = glamo_spi_suspend, -+ .resume = glamo_spi_resume, -+ .driver = { -+ .name = "glamo-lcm-spi", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init glamo_spi_init(void) -+{ -+ return platform_driver_register(&glamo_spi_drv); -+} -+ -+static void __exit glamo_spi_exit(void) -+{ -+ platform_driver_unregister(&glamo_spi_drv); -+} -+ -+module_init(glamo_spi_init); -+module_exit(glamo_spi_exit); -+ -+MODULE_DESCRIPTION("Smedia Glamo 336x/337x LCM serial command SPI Driver"); -+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>") -+MODULE_LICENSE("GPL"); -diff --git a/drivers/mfd/glamo/glamo-regs.h b/drivers/mfd/glamo/glamo-regs.h -new file mode 100644 -index 0000000..151cd66 ---- /dev/null -+++ b/drivers/mfd/glamo/glamo-regs.h -@@ -0,0 +1,477 @@ -+#ifndef _GLAMO_REGS_H -+#define _GLAMO_REGS_H -+ -+/* Smedia Glamo 336x/337x driver -+ * -+ * (C) 2007 by OpenMoko, Inc. -+ * Author: Harald Welte <laforge@openmoko.org> -+ * All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ */ -+ -+enum glamo_regster_offsets { -+ GLAMO_REGOFS_GENERIC = 0x0000, -+ GLAMO_REGOFS_HOSTBUS = 0x0200, -+ GLAMO_REGOFS_MEMORY = 0x0300, -+ GLAMO_REGOFS_VIDCAP = 0x0400, -+ GLAMO_REGOFS_ISP = 0x0500, -+ GLAMO_REGOFS_JPEG = 0x0800, -+ GLAMO_REGOFS_MPEG = 0x0c00, -+ GLAMO_REGOFS_LCD = 0x1100, -+ GLAMO_REGOFS_MMC = 0x1400, -+ GLAMO_REGOFS_MPROC0 = 0x1500, -+ GLAMO_REGOFS_MPROC1 = 0x1580, -+ GLAMO_REGOFS_CMDQUEUE = 0x1600, -+ GLAMO_REGOFS_RISC = 0x1680, -+ GLAMO_REGOFS_2D = 0x1700, -+ GLAMO_REGOFS_3D = 0x1b00, -+ GLAMO_REGOFS_END = 0x2400, -+}; -+ -+ -+enum glamo_register_generic { -+ GLAMO_REG_GCONF1 = 0x0000, -+ GLAMO_REG_GCONF2 = 0x0002, -+#define GLAMO_REG_DEVICE_ID GLAMO_REG_GCONF2 -+ GLAMO_REG_GCONF3 = 0x0004, -+#define GLAMO_REG_REVISION_ID GLAMO_REG_GCONF3 -+ GLAMO_REG_IRQ_GEN1 = 0x0006, -+#define GLAMO_REG_IRQ_ENABLE GLAMO_REG_IRQ_GEN1 -+ GLAMO_REG_IRQ_GEN2 = 0x0008, -+#define GLAMO_REG_IRQ_SET GLAMO_REG_IRQ_GEN2 -+ GLAMO_REG_IRQ_GEN3 = 0x000a, -+#define GLAMO_REG_IRQ_CLEAR GLAMO_REG_IRQ_GEN3 -+ GLAMO_REG_IRQ_GEN4 = 0x000c, -+#define GLAMO_REG_IRQ_STATUS GLAMO_REG_IRQ_GEN4 -+ GLAMO_REG_CLOCK_HOST = 0x0010, -+ GLAMO_REG_CLOCK_MEMORY = 0x0012, -+ GLAMO_REG_CLOCK_LCD = 0x0014, -+ GLAMO_REG_CLOCK_MMC = 0x0016, -+ GLAMO_REG_CLOCK_ISP = 0x0018, -+ GLAMO_REG_CLOCK_JPEG = 0x001a, -+ GLAMO_REG_CLOCK_3D = 0x001c, -+ GLAMO_REG_CLOCK_2D = 0x001e, -+ GLAMO_REG_CLOCK_RISC1 = 0x0020, /* 3365 only? */ -+ GLAMO_REG_CLOCK_RISC2 = 0x0022, /* 3365 only? */ -+ GLAMO_REG_CLOCK_MPEG = 0x0024, -+ GLAMO_REG_CLOCK_MPROC = 0x0026, -+ -+ GLAMO_REG_CLOCK_GEN5_1 = 0x0030, -+ GLAMO_REG_CLOCK_GEN5_2 = 0x0032, -+ GLAMO_REG_CLOCK_GEN6 = 0x0034, -+ GLAMO_REG_CLOCK_GEN7 = 0x0036, -+ GLAMO_REG_CLOCK_GEN8 = 0x0038, -+ GLAMO_REG_CLOCK_GEN9 = 0x003a, -+ GLAMO_REG_CLOCK_GEN10 = 0x003c, -+ GLAMO_REG_CLOCK_GEN11 = 0x003e, -+ GLAMO_REG_PLL_GEN1 = 0x0040, -+ GLAMO_REG_PLL_GEN2 = 0x0042, -+ GLAMO_REG_PLL_GEN3 = 0x0044, -+ GLAMO_REG_PLL_GEN4 = 0x0046, -+ GLAMO_REG_PLL_GEN5 = 0x0048, -+ GLAMO_REG_GPIO_GEN1 = 0x0050, -+ GLAMO_REG_GPIO_GEN2 = 0x0052, -+ GLAMO_REG_GPIO_GEN3 = 0x0054, -+ GLAMO_REG_GPIO_GEN4 = 0x0056, -+ GLAMO_REG_GPIO_GEN5 = 0x0058, -+ GLAMO_REG_GPIO_GEN6 = 0x005a, -+ GLAMO_REG_GPIO_GEN7 = 0x005c, -+ GLAMO_REG_GPIO_GEN8 = 0x005e, -+ GLAMO_REG_GPIO_GEN9 = 0x0060, -+ GLAMO_REG_GPIO_GEN10 = 0x0062, -+ GLAMO_REG_DFT_GEN1 = 0x0070, -+ GLAMO_REG_DFT_GEN2 = 0x0072, -+ GLAMO_REG_DFT_GEN3 = 0x0074, -+ GLAMO_REG_DFT_GEN4 = 0x0076, -+ -+ GLAMO_REG_DFT_GEN5 = 0x01e0, -+ GLAMO_REG_DFT_GEN6 = 0x01f0, -+}; -+ -+#define GLAMO_REG_HOSTBUS(x) (GLAMO_REGOFS_HOSTBUS-2+(x*2)) -+ -+#define REG_MEM(x) (GLAMO_REGOFS_MEMORY+(x)) -+#define GLAMO_REG_MEM_TIMING(x) (GLAMO_REG_MEM_TIMING1-2+(x*2)) -+ -+enum glamo_register_mem { -+ GLAMO_REG_MEM_TYPE = REG_MEM(0x00), -+ GLAMO_REG_MEM_GEN = REG_MEM(0x02), -+ GLAMO_REG_MEM_TIMING1 = REG_MEM(0x04), -+ GLAMO_REG_MEM_TIMING2 = REG_MEM(0x06), -+ GLAMO_REG_MEM_TIMING3 = REG_MEM(0x08), -+ GLAMO_REG_MEM_TIMING4 = REG_MEM(0x0a), -+ GLAMO_REG_MEM_TIMING5 = REG_MEM(0x0c), -+ GLAMO_REG_MEM_TIMING6 = REG_MEM(0x0e), -+ GLAMO_REG_MEM_TIMING7 = REG_MEM(0x10), -+ GLAMO_REG_MEM_TIMING8 = REG_MEM(0x12), -+ GLAMO_REG_MEM_TIMING9 = REG_MEM(0x14), -+ GLAMO_REG_MEM_TIMING10 = REG_MEM(0x16), -+ GLAMO_REG_MEM_TIMING11 = REG_MEM(0x18), -+ GLAMO_REG_MEM_POWER1 = REG_MEM(0x1a), -+ GLAMO_REG_MEM_POWER2 = REG_MEM(0x1c), -+ GLAMO_REG_MEM_LCD_BUF1 = REG_MEM(0x1e), -+ GLAMO_REG_MEM_LCD_BUF2 = REG_MEM(0x20), -+ GLAMO_REG_MEM_LCD_BUF3 = REG_MEM(0x22), -+ GLAMO_REG_MEM_LCD_BUF4 = REG_MEM(0x24), -+ GLAMO_REG_MEM_BIST1 = REG_MEM(0x26), -+ GLAMO_REG_MEM_BIST2 = REG_MEM(0x28), -+ GLAMO_REG_MEM_BIST3 = REG_MEM(0x2a), -+ GLAMO_REG_MEM_BIST4 = REG_MEM(0x2c), -+ GLAMO_REG_MEM_BIST5 = REG_MEM(0x2e), -+ GLAMO_REG_MEM_MAH1 = REG_MEM(0x30), -+ GLAMO_REG_MEM_MAH2 = REG_MEM(0x32), -+ GLAMO_REG_MEM_DRAM1 = REG_MEM(0x34), -+ GLAMO_REG_MEM_DRAM2 = REG_MEM(0x36), -+ GLAMO_REG_MEM_CRC = REG_MEM(0x38), -+}; -+ -+#define GLAMO_MEM_TYPE_MASK 0x03 -+ -+enum glamo_reg_mem_dram1 { -+ GLAMO_MEM_DRAM1_EN_SDRAM_CLK = (1 << 11), -+ GLAMO_MEM_DRAM1_SELF_REFRESH = (1 << 12), -+}; -+ -+enum glamo_reg_mem_dram2 { -+ GLAMO_MEM_DRAM2_DEEP_PWRDOWN = (1 << 12), -+}; -+ -+enum glamo_irq { -+ GLAMO_IRQ_HOSTBUS = 0x0001, -+ GLAMO_IRQ_JPEG = 0x0002, -+ GLAMO_IRQ_MPEG = 0x0004, -+ GLAMO_IRQ_MPROC1 = 0x0008, -+ GLAMO_IRQ_MPROC0 = 0x0010, -+ GLAMO_IRQ_CMDQUEUE = 0x0020, -+ GLAMO_IRQ_2D = 0x0040, -+ GLAMO_IRQ_MMC = 0x0080, -+ GLAMO_IRQ_RISC = 0x0100, -+}; -+ -+enum glamo_reg_clock_host { -+ GLAMO_CLOCK_HOST_DG_BCLK = 0x0001, -+ GLAMO_CLOCK_HOST_DG_M0CLK = 0x0004, -+ GLAMO_CLOCK_HOST_RESET = 0x1000, -+}; -+ -+enum glamo_reg_clock_mem { -+ GLAMO_CLOCK_MEM_DG_M1CLK = 0x0001, -+ GLAMO_CLOCK_MEM_EN_M1CLK = 0x0002, -+ GLAMO_CLOCK_MEM_DG_MOCACLK = 0x0004, -+ GLAMO_CLOCK_MEM_EN_MOCACLK = 0x0008, -+ GLAMO_CLOCK_MEM_RESET = 0x1000, -+ GLAMO_CLOCK_MOCA_RESET = 0x2000, -+}; -+ -+enum glamo_reg_clock_lcd { -+ GLAMO_CLOCK_LCD_DG_DCLK = 0x0001, -+ GLAMO_CLOCK_LCD_EN_DCLK = 0x0002, -+ GLAMO_CLOCK_LCD_DG_DMCLK = 0x0004, -+ GLAMO_CLOCK_LCD_EN_DMCLK = 0x0008, -+ // -+ GLAMO_CLOCK_LCD_EN_DHCLK = 0x0020, -+ GLAMO_CLOCK_LCD_DG_M5CLK = 0x0040, -+ GLAMO_CLOCK_LCD_EN_M5CLK = 0x0080, -+ GLAMO_CLOCK_LCD_RESET = 0x1000, -+}; -+ -+enum glamo_reg_clock_mmc { -+ GLAMO_CLOCK_MMC_DG_TCLK = 0x0001, -+ GLAMO_CLOCK_MMC_EN_TCLK = 0x0002, -+ GLAMO_CLOCK_MMC_DG_M9CLK = 0x0004, -+ GLAMO_CLOCK_MMC_EN_M9CLK = 0x0008, -+ GLAMO_CLOCK_MMC_RESET = 0x1000, -+}; -+ -+enum glamo_reg_clock_isp { -+ GLAMO_CLOCK_ISP_DG_I1CLK = 0x0001, -+ GLAMO_CLOCK_ISP_EN_I1CLK = 0x0002, -+ GLAMO_CLOCK_ISP_DG_CCLK = 0x0004, -+ GLAMO_CLOCK_ISP_EN_CCLK = 0x0008, -+ // -+ GLAMO_CLOCK_ISP_EN_SCLK = 0x0020, -+ GLAMO_CLOCK_ISP_DG_M2CLK = 0x0040, -+ GLAMO_CLOCK_ISP_EN_M2CLK = 0x0080, -+ GLAMO_CLOCK_ISP_DG_M15CLK = 0x0100, -+ GLAMO_CLOCK_ISP_EN_M15CLK = 0x0200, -+ GLAMO_CLOCK_ISP1_RESET = 0x1000, -+ GLAMO_CLOCK_ISP2_RESET = 0x2000, -+}; -+ -+enum glamo_reg_clock_jpeg { -+ GLAMO_CLOCK_JPEG_DG_JCLK = 0x0001, -+ GLAMO_CLOCK_JPEG_EN_JCLK = 0x0002, -+ GLAMO_CLOCK_JPEG_DG_M3CLK = 0x0004, -+ GLAMO_CLOCK_JPEG_EN_M3CLK = 0x0008, -+ GLAMO_CLOCK_JPEG_RESET = 0x1000, -+}; -+ -+enum glamo_reg_clock_2d { -+ GLAMO_CLOCK_2D_DG_GCLK = 0x0001, -+ GLAMO_CLOCK_2D_EN_GCLK = 0x0002, -+ GLAMO_CLOCK_2D_DG_M7CLK = 0x0004, -+ GLAMO_CLOCK_2D_EN_M7CLK = 0x0008, -+ GLAMO_CLOCK_2D_DG_M6CLK = 0x0010, -+ GLAMO_CLOCK_2D_EN_M6CLK = 0x0020, -+ GLAMO_CLOCK_2D_RESET = 0x1000, -+ GLAMO_CLOCK_2D_CQ_RESET = 0x2000, -+}; -+ -+enum glamo_reg_clock_3d { -+ GLAMO_CLOCK_3D_DG_ECLK = 0x0001, -+ GLAMO_CLOCK_3D_EN_ECLK = 0x0002, -+ GLAMO_CLOCK_3D_DG_RCLK = 0x0004, -+ GLAMO_CLOCK_3D_EN_RCLK = 0x0008, -+ GLAMO_CLOCK_3D_DG_M8CLK = 0x0010, -+ GLAMO_CLOCK_3D_EN_M8CLK = 0x0020, -+ GLAMO_CLOCK_3D_BACK_RESET = 0x1000, -+ GLAMO_CLOCK_3D_FRONT_RESET = 0x2000, -+}; -+ -+enum glamo_reg_clock_mpeg { -+ GLAMO_CLOCK_MPEG_DG_X0CLK = 0x0001, -+ GLAMO_CLOCK_MPEG_EN_X0CLK = 0x0002, -+ GLAMO_CLOCK_MPEG_DG_X1CLK = 0x0004, -+ GLAMO_CLOCK_MPEG_EN_X1CLK = 0x0008, -+ GLAMO_CLOCK_MPEG_DG_X2CLK = 0x0010, -+ GLAMO_CLOCK_MPEG_EN_X2CLK = 0x0020, -+ GLAMO_CLOCK_MPEG_DG_X3CLK = 0x0040, -+ GLAMO_CLOCK_MPEG_EN_X3CLK = 0x0080, -+ GLAMO_CLOCK_MPEG_DG_X4CLK = 0x0100, -+ GLAMO_CLOCK_MPEG_EN_X4CLK = 0x0200, -+ GLAMO_CLOCK_MPEG_DG_X6CLK = 0x0400, -+ GLAMO_CLOCK_MPEG_EN_X6CLK = 0x0800, -+ GLAMO_CLOCK_MPEG_ENC_RESET = 0x1000, -+ GLAMO_CLOCK_MPEG_DEC_RESET = 0x2000, -+}; -+ -+enum glamo_reg_clock51 { -+ GLAMO_CLOCK_GEN51_EN_DIV_MCLK = 0x0001, -+ GLAMO_CLOCK_GEN51_EN_DIV_SCLK = 0x0002, -+ GLAMO_CLOCK_GEN51_EN_DIV_JCLK = 0x0004, -+ GLAMO_CLOCK_GEN51_EN_DIV_DCLK = 0x0008, -+ GLAMO_CLOCK_GEN51_EN_DIV_DMCLK = 0x0010, -+ GLAMO_CLOCK_GEN51_EN_DIV_DHCLK = 0x0020, -+ GLAMO_CLOCK_GEN51_EN_DIV_GCLK = 0x0040, -+ GLAMO_CLOCK_GEN51_EN_DIV_TCLK = 0x0080, -+ /* FIXME: higher bits */ -+}; -+ -+enum glamo_reg_hostbus2 { -+ GLAMO_HOSTBUS2_MMIO_EN_ISP = 0x0001, -+ GLAMO_HOSTBUS2_MMIO_EN_JPEG = 0x0002, -+ GLAMO_HOSTBUS2_MMIO_EN_MPEG = 0x0004, -+ GLAMO_HOSTBUS2_MMIO_EN_LCD = 0x0008, -+ GLAMO_HOSTBUS2_MMIO_EN_MMC = 0x0010, -+ GLAMO_HOSTBUS2_MMIO_EN_MICROP0 = 0x0020, -+ GLAMO_HOSTBUS2_MMIO_EN_MICROP1 = 0x0040, -+ GLAMO_HOSTBUS2_MMIO_EN_CQ = 0x0080, -+ GLAMO_HOSTBUS2_MMIO_EN_RISC = 0x0100, -+ GLAMO_HOSTBUS2_MMIO_EN_2D = 0x0200, -+ GLAMO_HOSTBUS2_MMIO_EN_3D = 0x0400, -+}; -+ -+/* LCD Controller */ -+ -+#define REG_LCD(x) (x) -+enum glamo_reg_lcd { -+ GLAMO_REG_LCD_MODE1 = REG_LCD(0x00), -+ GLAMO_REG_LCD_MODE2 = REG_LCD(0x02), -+ GLAMO_REG_LCD_MODE3 = REG_LCD(0x04), -+ GLAMO_REG_LCD_WIDTH = REG_LCD(0x06), -+ GLAMO_REG_LCD_HEIGHT = REG_LCD(0x08), -+ GLAMO_REG_LCD_POLARITY = REG_LCD(0x0a), -+ GLAMO_REG_LCD_A_BASE1 = REG_LCD(0x0c), -+ GLAMO_REG_LCD_A_BASE2 = REG_LCD(0x0e), -+ GLAMO_REG_LCD_B_BASE1 = REG_LCD(0x10), -+ GLAMO_REG_LCD_B_BASE2 = REG_LCD(0x12), -+ GLAMO_REG_LCD_C_BASE1 = REG_LCD(0x14), -+ GLAMO_REG_LCD_C_BASE2 = REG_LCD(0x16), -+ GLAMO_REG_LCD_PITCH = REG_LCD(0x18), -+ /* RES */ -+ GLAMO_REG_LCD_HORIZ_TOTAL = REG_LCD(0x1c), -+ /* RES */ -+ GLAMO_REG_LCD_HORIZ_RETR_START = REG_LCD(0x20), -+ /* RES */ -+ GLAMO_REG_LCD_HORIZ_RETR_END = REG_LCD(0x24), -+ /* RES */ -+ GLAMO_REG_LCD_HORIZ_DISP_START = REG_LCD(0x28), -+ /* RES */ -+ GLAMO_REG_LCD_HORIZ_DISP_END = REG_LCD(0x2c), -+ /* RES */ -+ GLAMO_REG_LCD_VERT_TOTAL = REG_LCD(0x30), -+ /* RES */ -+ GLAMO_REG_LCD_VERT_RETR_START = REG_LCD(0x34), -+ /* RES */ -+ GLAMO_REG_LCD_VERT_RETR_END = REG_LCD(0x38), -+ /* RES */ -+ GLAMO_REG_LCD_VERT_DISP_START = REG_LCD(0x3c), -+ /* RES */ -+ GLAMO_REG_LCD_VERT_DISP_END = REG_LCD(0x40), -+ /* RES */ -+ GLAMO_REG_LCD_POL = REG_LCD(0x44), -+ GLAMO_REG_LCD_DATA_START = REG_LCD(0x46), -+ GLAMO_REG_LCD_FRATE_CONTRO = REG_LCD(0x48), -+ GLAMO_REG_LCD_DATA_CMD_HDR = REG_LCD(0x4a), -+ GLAMO_REG_LCD_SP_START = REG_LCD(0x4c), -+ GLAMO_REG_LCD_SP_END = REG_LCD(0x4e), -+ GLAMO_REG_LCD_CURSOR_BASE1 = REG_LCD(0x50), -+ GLAMO_REG_LCD_CURSOR_BASE2 = REG_LCD(0x52), -+ GLAMO_REG_LCD_CURSOR_PITCH = REG_LCD(0x54), -+ GLAMO_REG_LCD_CURSOR_X_SIZE = REG_LCD(0x56), -+ GLAMO_REG_LCD_CURSOR_Y_SIZE = REG_LCD(0x58), -+ GLAMO_REG_LCD_CURSOR_X_POS = REG_LCD(0x5a), -+ GLAMO_REG_LCD_CURSOR_Y_POS = REG_LCD(0x5c), -+ GLAMO_REG_LCD_CURSOR_PRESET = REG_LCD(0x5e), -+ GLAMO_REG_LCD_CURSOR_FG_COLOR = REG_LCD(0x60), -+ /* RES */ -+ GLAMO_REG_LCD_CURSOR_BG_COLOR = REG_LCD(0x64), -+ /* RES */ -+ GLAMO_REG_LCD_CURSOR_DST_COLOR = REG_LCD(0x68), -+ /* RES */ -+ GLAMO_REG_LCD_STATUS1 = REG_LCD(0x80), -+ GLAMO_REG_LCD_STATUS2 = REG_LCD(0x82), -+ GLAMO_REG_LCD_STATUS3 = REG_LCD(0x84), -+ GLAMO_REG_LCD_STATUS4 = REG_LCD(0x86), -+ /* RES */ -+ GLAMO_REG_LCD_COMMAND1 = REG_LCD(0xa0), -+ GLAMO_REG_LCD_COMMAND2 = REG_LCD(0xa2), -+ /* RES */ -+ GLAMO_REG_LCD_WFORM_DELAY1 = REG_LCD(0xb0), -+ GLAMO_REG_LCD_WFORM_DELAY2 = REG_LCD(0xb2), -+ /* RES */ -+ GLAMO_REG_LCD_GAMMA_CORR = REG_LCD(0x100), -+ /* RES */ -+ GLAMO_REG_LCD_GAMMA_R_ENTRY01 = REG_LCD(0x110), -+ GLAMO_REG_LCD_GAMMA_R_ENTRY23 = REG_LCD(0x112), -+ GLAMO_REG_LCD_GAMMA_R_ENTRY45 = REG_LCD(0x114), -+ GLAMO_REG_LCD_GAMMA_R_ENTRY67 = REG_LCD(0x116), -+ GLAMO_REG_LCD_GAMMA_R_ENTRY8 = REG_LCD(0x118), -+ /* RES */ -+ GLAMO_REG_LCD_GAMMA_G_ENTRY01 = REG_LCD(0x130), -+ GLAMO_REG_LCD_GAMMA_G_ENTRY23 = REG_LCD(0x132), -+ GLAMO_REG_LCD_GAMMA_G_ENTRY45 = REG_LCD(0x134), -+ GLAMO_REG_LCD_GAMMA_G_ENTRY67 = REG_LCD(0x136), -+ GLAMO_REG_LCD_GAMMA_G_ENTRY8 = REG_LCD(0x138), -+ /* RES */ -+ GLAMO_REG_LCD_GAMMA_B_ENTRY01 = REG_LCD(0x150), -+ GLAMO_REG_LCD_GAMMA_B_ENTRY23 = REG_LCD(0x152), -+ GLAMO_REG_LCD_GAMMA_B_ENTRY45 = REG_LCD(0x154), -+ GLAMO_REG_LCD_GAMMA_B_ENTRY67 = REG_LCD(0x156), -+ GLAMO_REG_LCD_GAMMA_B_ENTRY8 = REG_LCD(0x158), -+ /* RES */ -+ GLAMO_REG_LCD_SRAM_DRIVING1 = REG_LCD(0x160), -+ GLAMO_REG_LCD_SRAM_DRIVING2 = REG_LCD(0x162), -+ GLAMO_REG_LCD_SRAM_DRIVING3 = REG_LCD(0x164), -+}; -+ -+enum glamo_reg_lcd_mode1 { -+ GLAMO_LCD_MODE1_PWRSAVE = 0x0001, -+ GLAMO_LCD_MODE1_PARTIAL_PRT = 0x0002, -+ GLAMO_LCD_MODE1_HWFLIP = 0x0004, -+ GLAMO_LCD_MODE1_LCD2 = 0x0008, -+ /* RES */ -+ GLAMO_LCD_MODE1_PARTIAL_MODE = 0x0020, -+ GLAMO_LCD_MODE1_CURSOR_DSTCOLOR = 0x0040, -+ GLAMO_LCD_MODE1_PARTIAL_ENABLE = 0x0080, -+ GLAMO_LCD_MODE1_TVCLK_IN_ENABLE = 0x0100, -+ GLAMO_LCD_MODE1_HSYNC_HIGH_ACT = 0x0200, -+ GLAMO_LCD_MODE1_VSYNC_HIGH_ACT = 0x0400, -+ GLAMO_LCD_MODE1_HSYNC_FLIP = 0x0800, -+ GLAMO_LCD_MODE1_GAMMA_COR_EN = 0x1000, -+ GLAMO_LCD_MODE1_DITHER_EN = 0x2000, -+ GLAMO_LCD_MODE1_CURSOR_EN = 0x4000, -+ GLAMO_LCD_MODE1_ROTATE_EN = 0x8000, -+}; -+ -+enum glamo_reg_lcd_mode2 { -+ GLAMO_LCD_MODE2_CRC_CHECK_EN = 0x0001, -+ GLAMO_LCD_MODE2_DCMD_PER_LINE = 0x0002, -+ GLAMO_LCD_MODE2_NOUSE_BDEF = 0x0004, -+ GLAMO_LCD_MODE2_OUT_POS_MODE = 0x0008, -+ GLAMO_LCD_MODE2_FRATE_CTRL_EN = 0x0010, -+ GLAMO_LCD_MODE2_SINGLE_BUFFER = 0x0020, -+ GLAMO_LCD_MODE2_SER_LSB_TO_MSB = 0x0040, -+ /* FIXME */ -+}; -+ -+enum glamo_reg_lcd_mode3 { -+ /* LCD color source data format */ -+ GLAMO_LCD_SRC_RGB565 = 0x0000, -+ GLAMO_LCD_SRC_ARGB1555 = 0x4000, -+ GLAMO_LCD_SRC_ARGB4444 = 0x8000, -+ /* interface type */ -+ GLAMO_LCD_MODE3_LCD = 0x1000, -+ GLAMO_LCD_MODE3_RGB = 0x0800, -+ GLAMO_LCD_MODE3_CPU = 0x0000, -+ /* mode */ -+ GLAMO_LCD_MODE3_RGB332 = 0x0000, -+ GLAMO_LCD_MODE3_RGB444 = 0x0100, -+ GLAMO_LCD_MODE3_RGB565 = 0x0200, -+ GLAMO_LCD_MODE3_RGB666 = 0x0300, -+ /* depth */ -+ GLAMO_LCD_MODE3_6BITS = 0x0000, -+ GLAMO_LCD_MODE3_8BITS = 0x0010, -+ GLAMO_LCD_MODE3_9BITS = 0x0020, -+ GLAMO_LCD_MODE3_16BITS = 0x0030, -+ GLAMO_LCD_MODE3_18BITS = 0x0040, -+}; -+ -+enum glamo_lcd_rot_mode { -+ GLAMO_LCD_ROT_MODE_0 = 0x0000, -+ GLAMO_LCD_ROT_MODE_180 = 0x2000, -+ GLAMO_LCD_ROT_MODE_MIRROR = 0x4000, -+ GLAMO_LCD_ROT_MODE_FLIP = 0x6000, -+ GLAMO_LCD_ROT_MODE_90 = 0x8000, -+ GLAMO_LCD_ROT_MODE_270 = 0xa000, -+}; -+#define GLAMO_LCD_ROT_MODE_MASK 0xe000 -+ -+enum glamo_lcd_cmd_type { -+ GLAMO_LCD_CMD_TYPE_DISP = 0x0000, -+ GLAMO_LCD_CMD_TYPE_PARALLEL = 0x4000, -+ GLAMO_LCD_CMD_TYPE_SERIAL = 0x8000, -+ GLAMO_LCD_CMD_TYPE_SERIAL_DIRECT= 0xc000, -+}; -+#define GLAMO_LCD_CMD_TYPE_MASK 0xc000 -+ -+enum glamo_lcd_cmds { -+ GLAMO_LCD_CMD_DATA_DISP_FIRE = 0x00, -+ GLAMO_LCD_CMD_DATA_DISP_SYNC = 0x01, /* RGB only */ -+ /* switch to command mode, no display */ -+ GLAMO_LCD_CMD_DATA_FIRE_NO_DISP = 0x02, -+ /* display until VSYNC, switch to command */ -+ GLAMO_LCD_CMD_DATA_FIRE_VSYNC = 0x11, -+ /* display until HSYNC, switch to command */ -+ GLAMO_LCD_CMD_DATA_FIRE_HSYNC = 0x12, -+ /* display until VSYNC, 1 black frame, VSYNC, switch to command */ -+ GLAMO_LCD_CMD_DATA_FIRE_VSYNC_B = 0x13, -+ /* don't care about display and switch to command */ -+ GLAMO_LCD_CMD_DATA_FIRE_FREE = 0x14, /* RGB only */ -+ /* don't care about display, keep data display but disable data, -+ * and switch to command */ -+ GLAMO_LCD_CMD_DATA_FIRE_FREE_D = 0x15, /* RGB only */ -+}; -+ -+enum glamo_core_revisions { -+ GLAMO_CORE_REV_A0 = 0x0000, -+ GLAMO_CORE_REV_A1 = 0x0001, -+ GLAMO_CORE_REV_A2 = 0x0002, -+ GLAMO_CORE_REV_A3 = 0x0003, -+}; -+ -+#endif /* _GLAMO_REGS_H */ -diff --git a/drivers/mfd/glamo/glamo-spi-gpio.c b/drivers/mfd/glamo/glamo-spi-gpio.c -new file mode 100644 -index 0000000..73926bd ---- /dev/null -+++ b/drivers/mfd/glamo/glamo-spi-gpio.c -@@ -0,0 +1,256 @@ -+/* -+ * Copyright (C) 2007 OpenMoko, Inc. -+ * Author: Harald Welte <laforge@openmoko.org> -+ * -+ * Smedia Glamo GPIO based SPI driver -+ * -+ * 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. -+ * -+ * This driver currently only implements a minimum subset of the hardware -+ * features, esp. those features that are required to drive the jbt6k74 -+ * LCM controller asic in the TD028TTEC1 LCM. -+ * -+*/ -+ -+#define DEBUG -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <linux/spinlock.h> -+#include <linux/workqueue.h> -+#include <linux/platform_device.h> -+ -+#include <linux/spi/spi.h> -+#include <linux/spi/spi_bitbang.h> -+#include <linux/spi/glamo.h> -+ -+#include <linux/glamofb.h> -+ -+#include <asm/hardware.h> -+ -+#include "glamo-core.h" -+#include "glamo-regs.h" -+ -+struct glamo_spigpio { -+ struct spi_bitbang bitbang; -+ struct spi_master *master; -+ struct glamo_spigpio_info *info; -+ struct glamo_core *glamo; -+}; -+ -+static inline struct glamo_spigpio *to_sg(struct spi_device *spi) -+{ -+ return spi->controller_data; -+} -+ -+static inline void setsck(struct spi_device *dev, int on) -+{ -+ struct glamo_spigpio *sg = to_sg(dev); -+ glamo_gpio_setpin(sg->glamo, sg->info->pin_clk, on ? 1 : 0); -+} -+ -+static inline void setmosi(struct spi_device *dev, int on) -+{ -+ struct glamo_spigpio *sg = to_sg(dev); -+ glamo_gpio_setpin(sg->glamo, sg->info->pin_mosi, on ? 1 : 0); -+} -+ -+static inline u32 getmiso(struct spi_device *dev) -+{ -+ struct glamo_spigpio *sg = to_sg(dev); -+ if (sg->info->pin_miso) -+ return glamo_gpio_getpin(sg->glamo, sg->info->pin_miso) ? 1 : 0; -+ else -+ return 0; -+} -+ -+#define spidelay(x) ndelay(x) -+ -+#define EXPAND_BITBANG_TXRX -+#include <linux/spi/spi_bitbang.h> -+ -+static u32 glamo_spigpio_txrx_mode0(struct spi_device *spi, -+ unsigned nsecs, u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); -+} -+ -+static u32 glamo_spigpio_txrx_mode1(struct spi_device *spi, -+ unsigned nsecs, u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); -+} -+ -+static u32 glamo_spigpio_txrx_mode2(struct spi_device *spi, -+ unsigned nsecs, u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); -+} -+ -+static u32 glamo_spigpio_txrx_mode3(struct spi_device *spi, -+ unsigned nsecs, u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); -+} -+ -+ -+#if 0 -+static int glamo_spigpio_setupxfer(struct spi_device *spi, -+ struct spi_transfer *t) -+{ -+ struct glamo_spi *gs = to_sg(spi); -+ unsigned int bpw; -+ -+ bpw = t ? t->bits_per_word : spi->bits_per_word; -+ -+ if (bpw != 9 && bpw != 8) { -+ dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+#endif -+ -+static void glamo_spigpio_chipsel(struct spi_device *spi, int value) -+{ -+ struct glamo_spigpio *gs = to_sg(spi); -+#if 0 -+ dev_dbg(&spi->dev, "chipsel %d: spi=%p, gs=%p, info=%p, handle=%p\n", -+ value, spi, gs, gs->info, gs->info->glamo); -+#endif -+ glamo_gpio_setpin(gs->glamo, gs->info->pin_cs, value ? 0 : 1); -+} -+ -+ -+static int glamo_spigpio_probe(struct platform_device *pdev) -+{ -+ struct spi_master *master; -+ struct glamo_spigpio *sp; -+ int ret; -+ int i; -+ -+ master = spi_alloc_master(&pdev->dev, sizeof(struct glamo_spigpio)); -+ if (master == NULL) { -+ dev_err(&pdev->dev, "failed to allocate spi master\n"); -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ sp = spi_master_get_devdata(master); -+ platform_set_drvdata(pdev, sp); -+ sp->info = pdev->dev.platform_data; -+ if (!sp->info) { -+ dev_err(&pdev->dev, "can't operate without platform data\n"); -+ ret = -EIO; -+ goto err_no_pdev; -+ } -+ -+ master->num_chipselect = 1; -+ master->bus_num = 2; /* FIXME: use dynamic number */ -+ -+ sp->master = spi_master_get(master); -+ sp->glamo = sp->info->glamo; -+ -+ sp->bitbang.master = sp->master; -+ sp->bitbang.chipselect = glamo_spigpio_chipsel; -+ sp->bitbang.txrx_word[SPI_MODE_0] = glamo_spigpio_txrx_mode0; -+ sp->bitbang.txrx_word[SPI_MODE_1] = glamo_spigpio_txrx_mode1; -+ sp->bitbang.txrx_word[SPI_MODE_2] = glamo_spigpio_txrx_mode2; -+ sp->bitbang.txrx_word[SPI_MODE_3] = glamo_spigpio_txrx_mode3; -+ -+ /* set state of spi pins */ -+ glamo_gpio_setpin(sp->glamo, sp->info->pin_clk, 0); -+ glamo_gpio_setpin(sp->glamo, sp->info->pin_mosi, 0); -+ glamo_gpio_setpin(sp->glamo, sp->info->pin_cs, 1); -+ -+ glamo_gpio_cfgpin(sp->glamo, sp->info->pin_clk); -+ glamo_gpio_cfgpin(sp->glamo, sp->info->pin_mosi); -+ glamo_gpio_cfgpin(sp->glamo, sp->info->pin_cs); -+ if (sp->info->pin_miso) -+ glamo_gpio_cfgpin(sp->glamo, sp->info->pin_miso); -+ -+ /* bring the LCM panel out of reset if it isn't already */ -+ -+ glamo_gpio_setpin(sp->glamo, GLAMO_GPIO4, 1); -+ glamo_gpio_cfgpin(sp->glamo, GLAMO_GPIO4_OUTPUT); -+ msleep(90); -+ -+#if 0 -+ sp->dev = &pdev->dev; -+ -+ sp->bitbang.setup_transfer = glamo_spi_setupxfer; -+ sp->bitbang.txrx_bufs = glamo_spi_txrx; -+ sp->bitbang.master->setup = glamo_spi_setup; -+#endif -+ -+ ret = spi_bitbang_start(&sp->bitbang); -+ if (ret) -+ goto err_no_bitbang; -+ -+ /* register the chips to go with the board */ -+ -+ for (i = 0; i < sp->info->board_size; i++) { -+ dev_info(&pdev->dev, "registering %p: %s\n", -+ &sp->info->board_info[i], -+ sp->info->board_info[i].modalias); -+ -+ sp->info->board_info[i].controller_data = sp; -+ spi_new_device(master, sp->info->board_info + i); -+ } -+ -+ return 0; -+ -+err_no_bitbang: -+ platform_set_drvdata(pdev, NULL); -+err_no_pdev: -+ spi_master_put(sp->bitbang.master); -+err: -+ return ret; -+ -+} -+ -+static int glamo_spigpio_remove(struct platform_device *pdev) -+{ -+ struct glamo_spigpio *sp = platform_get_drvdata(pdev); -+ -+ spi_bitbang_stop(&sp->bitbang); -+ spi_master_put(sp->bitbang.master); -+ -+ return 0; -+} -+ -+#define glamo_spigpio_suspend NULL -+#define glamo_spigpio_resume NULL -+ -+static struct platform_driver glamo_spi_drv = { -+ .probe = glamo_spigpio_probe, -+ .remove = glamo_spigpio_remove, -+ .suspend = glamo_spigpio_suspend, -+ .resume = glamo_spigpio_resume, -+ .driver = { -+ .name = "glamo-spi-gpio", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init glamo_spi_init(void) -+{ -+ return platform_driver_register(&glamo_spi_drv); -+} -+ -+static void __exit glamo_spi_exit(void) -+{ -+ platform_driver_unregister(&glamo_spi_drv); -+} -+ -+module_init(glamo_spi_init); -+module_exit(glamo_spi_exit); -+ -+MODULE_DESCRIPTION("Smedia Glamo 336x/337x LCM serial command SPI Driver"); -+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>") -+MODULE_LICENSE("GPL"); -diff --git a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h -index 996f654..9522cd1 100644 ---- a/include/asm-arm/arch-s3c2410/irqs.h -+++ b/include/asm-arm/arch-s3c2410/irqs.h -@@ -155,9 +155,37 @@ - #define IRQ_S3C2443_AC97 S3C2410_IRQSUB(28) - - #ifdef CONFIG_CPU_S3C2443 --#define NR_IRQS (IRQ_S3C2443_AC97+1) -+#define _NR_IRQS (IRQ_S3C2443_AC97+1) - #else --#define NR_IRQS (IRQ_S3C2440_AC97+1) -+#define _NR_IRQS (IRQ_S3C2440_AC97+1) - #endif - -+/* -+ * The next 16 interrupts are for board specific purposes. Since -+ * the kernel can only run on one machine at a time, we can re-use -+ * these. If you need more, increase IRQ_BOARD_END, but keep it -+ * within sensible limits. -+ */ -+#define IRQ_BOARD_START _NR_IRQS -+#define IRQ_BOARD_END (_NR_IRQS + 10) -+ -+#if defined(CONFIG_MACH_NEO1973_GTA02) -+#define NR_IRQS (IRQ_BOARD_END) -+#else -+#define NR_IRQS (IRQ_BOARD_START) -+#endif -+ -+/* Neo1973 GTA02 interrupts */ -+#define NEO1973_GTA02_IRQ(x) (IRQ_BOARD_START + (x)) -+#define IRQ_GLAMO(x) NEO1973_GTA02_IRQ(x) -+#define IRQ_GLAMO_HOSTBUS IRQ_GLAMO(0) -+#define IRQ_GLAMO_JPEG IRQ_GLAMO(1) -+#define IRQ_GLAMO_MPEG IRQ_GLAMO(2) -+#define IRQ_GLAMO_MPROC1 IRQ_GLAMO(3) -+#define IRQ_GLAMO_MPROC0 IRQ_GLAMO(4) -+#define IRQ_GLAMO_CMDQUEUE IRQ_GLAMO(5) -+#define IRQ_GLAMO_2D IRQ_GLAMO(6) -+#define IRQ_GLAMO_MMC IRQ_GLAMO(7) -+#define IRQ_GLAMO_RISC IRQ_GLAMO(8) -+ - #endif /* __ASM_ARCH_IRQ_H */ -diff --git a/include/linux/glamo-gpio.h b/include/linux/glamo-gpio.h -new file mode 100644 -index 0000000..d00f7e9 ---- /dev/null -+++ b/include/linux/glamo-gpio.h -@@ -0,0 +1,99 @@ -+#ifndef __GLAMO_GPIO_H -+#define __GLAMO_GPIO_H -+ -+struct glamo_core; -+ -+#define GLAMO_GPIO_BANKA 0x0000 -+#define GLAMO_GPIO_BANKB 0x1000 -+#define GLAMO_GPIO_BANKC 0x2000 -+#define GLAMO_GPIO_BANKD 0x3000 -+ -+#define GLAMO_GPIONO(bank, pin) ((bank & 0xf000) | ((pin & 0xf) << 8)) -+ -+#define GLAMO_GPIO_F_IN 0x0010 -+#define GLAMO_GPIO_F_OUT 0x0020 -+#define GLAMO_GPIO_F_FUNC 0x0030 -+ -+#define GLAMO_GPIO0 GLAMO_GPIONO(GLAMO_GPIO_BANKA, 0) -+#define GLAMO_GPIO0_INPUT (GLAMO_GPIO0 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO0_OUTPUT (GLAMO_GPIO0 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO0_HA20 (GLAMO_GPIO0 | GLAMO_GPIO_F_FUNC) -+ -+#define GLAMO_GPIO1 GLAMO_GPIONO(GLAMO_GPIO_BANKA, 1) -+#define GLAMO_GPIO1_INPUT (GLAMO_GPIO1 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO1_OUTPUT (GLAMO_GPIO1 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO1_HA21 (GLAMO_GPIO1 | GLAMO_GPIO_F_FUNC) -+ -+#define GLAMO_GPIO2 GLAMO_GPIONO(GLAMO_GPIO_BANKA, 2) -+#define GLAMO_GPIO2_INPUT (GLAMO_GPIO2 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO2_OUTPUT (GLAMO_GPIO2 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO2_HA22 (GLAMO_GPIO2 | GLAMO_GPIO_F_FUNC) -+ -+#define GLAMO_GPIO3 GLAMO_GPIONO(GLAMO_GPIO_BANKA, 3) -+#define GLAMO_GPIO3_INPUT (GLAMO_GPIO3 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO3_OUTPUT (GLAMO_GPIO3 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO3_HA23 (GLAMO_GPIO3 | GLAMO_GPIO_F_FUNC) -+ -+#define GLAMO_GPIO4 GLAMO_GPIONO(GLAMO_GPIO_BANKB, 0) -+#define GLAMO_GPIO4_INPUT (GLAMO_GPIO4 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO4_OUTPUT (GLAMO_GPIO4 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO4_nLCS0 (GLAMO_GPIO4 | GLAMO_GPIO_F_FUNC) -+ -+#define GLAMO_GPIO5 GLAMO_GPIONO(GLAMO_GPIO_BANKB, 1) -+#define GLAMO_GPIO5_INPUT (GLAMO_GPIO5 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO5_OUTPUT (GLAMO_GPIO5 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO5_nLCS1 (GLAMO_GPIO5 | GLAMO_GPIO_F_FUNC) -+ -+#define GLAMO_GPIO6 GLAMO_GPIONO(GLAMO_GPIO_BANKB, 2) -+#define GLAMO_GPIO6_INPUT (GLAMO_GPIO6 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO6_OUTPUT (GLAMO_GPIO6 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO6_LDCLK (GLAMO_GPIO6 | GLAMO_GPIO_F_FUNC) -+ -+#define GLAMO_GPIO7 GLAMO_GPIONO(GLAMO_GPIO_BANKB, 3) -+#define GLAMO_GPIO7_INPUT (GLAMO_GPIO7 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO7_OUTPUT (GLAMO_GPIO7 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO7_nLDE (GLAMO_GPIO7 | GLAMO_GPIO_F_FUNC) -+ -+#define GLAMO_GPIO8 GLAMO_GPIONO(GLAMO_GPIO_BANKC, 0) -+#define GLAMO_GPIO8_INPUT (GLAMO_GPIO8 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO8_OUTPUT (GLAMO_GPIO8 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO8_LD16 (GLAMO_GPIO8 | GLAMO_GPIO_F_FUNC) -+ -+#define GLAMO_GPIO9 GLAMO_GPIONO(GLAMO_GPIO_BANKC, 1) -+#define GLAMO_GPIO9_INPUT (GLAMO_GPIO9 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO9_OUTPUT (GLAMO_GPIO9 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO9_LD17 (GLAMO_GPIO9 | GLAMO_GPIO_F_FUNC) -+ -+#define GLAMO_GPIO10 GLAMO_GPIONO(GLAMO_GPIO_BANKC, 2) -+#define GLAMO_GPIO10_INPUT (GLAMO_GPIO10 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO10_OUTPUT (GLAMO_GPIO10 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO10_LSCK (GLAMO_GPIO10 | GLAMO_GPIO_F_FUNC) -+ -+#define GLAMO_GPIO11 GLAMO_GPIONO(GLAMO_GPIO_BANKC, 3) -+#define GLAMO_GPIO11_INPUT (GLAMO_GPIO11 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO11_OUTPUT (GLAMO_GPIO11 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO11_LSDA (GLAMO_GPIO11 | GLAMO_GPIO_F_FUNC) -+ -+#define GLAMO_GPIO12 GLAMO_GPIONO(GLAMO_GPIO_BANKD, 0) -+#define GLAMO_GPIO12_INPUT (GLAMO_GPIO12 | GLAMO_GPIO_F_IN) -+#define GLAMO_GPIO12_OUTPUT (GLAMO_GPIO12 | GLAMO_GPIO_F_OUT) -+#define GLAMO_GPIO12_LSA0 (GLAMO_GPIO12 | GLAMO_GPIO_F_FUNC) -+ -+ -+#define REG_OF_GPIO(gpio) (((gpio & 0xf000) >> 12)*2 \ -+ + GLAMO_REG_GPIO_GEN1) -+#define NUM_OF_GPIO(gpio) ((gpio & 0x0f00) >> 8) -+#define GPIO_OUT_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 0)) -+#define OUTPUT_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 4)) -+#define INPUT_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 8)) -+#define FUNC_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 12)) -+ -+void glamo_gpio_setpin(struct glamo_core *glamo, unsigned int pin, -+ unsigned int value); -+ -+int glamo_gpio_getpin(struct glamo_core *glamo, unsigned int pin); -+ -+void glamo_gpio_cfgpin(struct glamo_core *glamo, unsigned int pinfunc); -+ -+ -+#endif /* _GLAMO_GPIO */ -diff --git a/include/linux/glamofb.h b/include/linux/glamofb.h -new file mode 100644 -index 0000000..24742a2 ---- /dev/null -+++ b/include/linux/glamofb.h -@@ -0,0 +1,39 @@ -+#ifndef _LINUX_GLAMOFB_H -+#define _LINUX_GLAMOFB_H -+ -+#include <linux/spi/glamo.h> -+ -+struct glamofb_val { -+ unsigned int defval; -+ unsigned int min; -+ unsigned int max; -+}; -+ -+struct glamo_core; -+ -+struct glamofb_platform_data { -+ int width, height; -+ int pixclock; -+ int left_margin, right_margin; -+ int upper_margin, lower_margin; -+ int hsync_len, vsync_len; -+ int fb_mem_size; -+ -+ struct glamofb_val xres; -+ struct glamofb_val yres; -+ struct glamofb_val bpp; -+ -+ struct glamo_spi_info *spi_info; -+ struct glamo_spigpio_info *spigpio_info; -+ struct glamo_core *glamo; -+ -+ /* glamo mmc platform specific info */ -+ void (*glamo_set_mci_power)(unsigned char power_mode, -+ unsigned short vdd); -+ int (*glamo_irq_is_wired)(void); -+}; -+ -+void glamofb_cmd_mode(struct glamofb_handle *gfb, int on); -+int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val); -+ -+#endif -diff --git a/include/linux/spi/glamo.h b/include/linux/spi/glamo.h -new file mode 100644 -index 0000000..86419ea ---- /dev/null -+++ b/include/linux/spi/glamo.h -@@ -0,0 +1,28 @@ -+#ifndef __GLAMO_SPI_H -+#define __GLAMO_SPI_H -+ -+#include <linux/glamo-gpio.h> -+ -+struct spi_board_info; -+struct glamofb_handle; -+struct glamo_core; -+ -+struct glamo_spi_info { -+ unsigned long board_size; -+ struct spi_board_info *board_info; -+ struct glamofb_handle *glamofb_handle; -+}; -+ -+struct glamo_spigpio_info { -+ unsigned int pin_clk; -+ unsigned int pin_mosi; -+ unsigned int pin_miso; -+ unsigned int pin_cs; -+ -+ unsigned int board_size; -+ struct spi_board_info *board_info; -+ struct glamo_core *glamo; -+}; -+ -+ -+#endif --- -1.5.6.5 - |