1 From f9fc3f480aeb1fdfcdefdd3c560d06c8297c758b Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Fri, 4 Apr 2008 11:34:54 +0100
4 Subject: [PATCH] smedia-glamo.patch
6 include/asm-arm/arch-s3c2410/irqs.h shouldn't contain device-specific
9 This is a Linux kernel driver for the Smedia Glamo336x / Glamo337x
10 multi-function peripheral device.
12 Signed-off-by: Harald Welte <laforge@openmoko.org>
14 drivers/mfd/Kconfig | 2 +
15 drivers/mfd/Makefile | 1 +
16 drivers/mfd/glamo/Kconfig | 35 ++
17 drivers/mfd/glamo/Makefile | 11 +
18 drivers/mfd/glamo/glamo-core.c | 1151 +++++++++++++++++++++++++++++++++++
19 drivers/mfd/glamo/glamo-core.h | 91 +++
20 drivers/mfd/glamo/glamo-fb.c | 822 +++++++++++++++++++++++++
21 drivers/mfd/glamo/glamo-gpio.c | 62 ++
22 drivers/mfd/glamo/glamo-lcm-spi.c | 241 ++++++++
23 drivers/mfd/glamo/glamo-regs.h | 477 +++++++++++++++
24 drivers/mfd/glamo/glamo-spi-gpio.c | 256 ++++++++
25 include/asm-arm/arch-s3c2410/irqs.h | 32 +-
26 include/linux/glamo-gpio.h | 99 +++
27 include/linux/glamofb.h | 39 ++
28 include/linux/spi/glamo.h | 28 +
29 15 files changed, 3345 insertions(+), 2 deletions(-)
30 create mode 100644 drivers/mfd/glamo/Kconfig
31 create mode 100644 drivers/mfd/glamo/Makefile
32 create mode 100644 drivers/mfd/glamo/glamo-core.c
33 create mode 100644 drivers/mfd/glamo/glamo-core.h
34 create mode 100644 drivers/mfd/glamo/glamo-fb.c
35 create mode 100644 drivers/mfd/glamo/glamo-gpio.c
36 create mode 100644 drivers/mfd/glamo/glamo-lcm-spi.c
37 create mode 100644 drivers/mfd/glamo/glamo-regs.h
38 create mode 100644 drivers/mfd/glamo/glamo-spi-gpio.c
39 create mode 100644 include/linux/glamo-gpio.h
40 create mode 100644 include/linux/glamofb.h
41 create mode 100644 include/linux/spi/glamo.h
43 diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
44 index 2571619..fe06f8e 100644
45 --- a/drivers/mfd/Kconfig
46 +++ b/drivers/mfd/Kconfig
47 @@ -15,6 +15,8 @@ config MFD_SM501
48 interface. The device may be connected by PCI or local bus with
49 varying functions enabled.
51 +source "drivers/mfd/glamo/Kconfig"
55 menu "Multimedia Capabilities Port drivers"
56 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
57 index 5143209..a2da091 100644
58 --- a/drivers/mfd/Makefile
59 +++ b/drivers/mfd/Makefile
63 obj-$(CONFIG_MFD_SM501) += sm501.o
64 +obj-$(CONFIG_MFD_GLAMO) += glamo/
66 obj-$(CONFIG_MCP) += mcp-core.o
67 obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
68 diff --git a/drivers/mfd/glamo/Kconfig b/drivers/mfd/glamo/Kconfig
70 index 0000000..b99f2b2
72 +++ b/drivers/mfd/glamo/Kconfig
75 + bool "Smedia Glamo 336x/337x support"
77 + This enables the core driver for the Smedia Glamo 336x/337x
78 + multi-function device. It includes irq_chip demultiplex as
79 + well as clock / power management and GPIO support.
82 + tristate "Smedia Glamo 336x/337x framebuffer support"
83 + depends on FB && MFD_GLAMO
85 + Frame buffer driver for the LCD controller in the Smedia Glamo
88 + This driver is also available as a module ( = code which can be
89 + inserted and removed from the running kernel whenever you want). The
90 + module will be called glamofb. If you want to compile it as a module,
91 + say M here and read <file:Documentation/modules.txt>.
95 +config MFD_GLAMO_SPI_GPIO
96 + tristate "Glamo GPIO SPI bitbang support"
97 + depends on MFD_GLAMO
99 + Enable a bitbanging SPI adapter driver for the Smedia Glamo.
101 +config MFD_GLAMO_SPI_FB
102 + tristate "Glamo LCM control channel SPI support"
103 + depends on MFD_GLAMO_FB
105 + Enable a bitbanging SPI adapter driver for the Smedia Glamo LCM
106 + control channel. This SPI interface is frequently used to
107 + interconnect the LCM control interface.
109 diff --git a/drivers/mfd/glamo/Makefile b/drivers/mfd/glamo/Makefile
111 index 0000000..fb53982
113 +++ b/drivers/mfd/glamo/Makefile
116 +# Makefile for the Smedia Glamo framebuffer driver
119 +obj-$(CONFIG_MFD_GLAMO) += glamo-core.o glamo-gpio.o
120 +obj-$(CONFIG_MFD_GLAMO_SPI) += glamo-spi.o
121 +obj-$(CONFIG_MFD_GLAMO_SPI_GPIO) += glamo-spi-gpio.o
123 +obj-$(CONFIG_MFD_GLAMO_FB) += glamo-fb.o
124 +obj-$(CONFIG_MFD_GLAMO_SPI_FB) += glamo-lcm-spi.o
126 diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c
128 index 0000000..acf545f
130 +++ b/drivers/mfd/glamo/glamo-core.c
132 +/* Smedia Glamo 336x/337x driver
134 + * (C) 2007 by OpenMoko, Inc.
135 + * Author: Harald Welte <laforge@openmoko.org>
136 + * All rights reserved.
138 + * This program is free software; you can redistribute it and/or
139 + * modify it under the terms of the GNU General Public License as
140 + * published by the Free Software Foundation; either version 2 of
141 + * the License, or (at your option) any later version.
143 + * This program is distributed in the hope that it will be useful,
144 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
145 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
146 + * GNU General Public License for more details.
148 + * You should have received a copy of the GNU General Public License
149 + * along with this program; if not, write to the Free Software
150 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
151 + * MA 02111-1307 USA
154 +#include <linux/module.h>
155 +#include <linux/kernel.h>
156 +#include <linux/errno.h>
157 +#include <linux/string.h>
158 +#include <linux/mm.h>
159 +#include <linux/tty.h>
160 +#include <linux/slab.h>
161 +#include <linux/delay.h>
162 +#include <linux/fb.h>
163 +#include <linux/init.h>
164 +#include <linux/irq.h>
165 +#include <linux/interrupt.h>
166 +#include <linux/workqueue.h>
167 +#include <linux/wait.h>
168 +#include <linux/platform_device.h>
169 +#include <linux/kernel_stat.h>
170 +#include <linux/spinlock.h>
171 +#include <linux/glamofb.h>
172 +#include <linux/mmc/mmc.h>
173 +#include <linux/mmc/host.h>
176 +#include <asm/uaccess.h>
177 +#include <asm/div64.h>
180 +#include <linux/pm.h>
183 +#include "glamo-regs.h"
184 +#include "glamo-core.h"
186 +#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
188 +static struct glamo_core *glamo_handle;
190 +static inline void __reg_write(struct glamo_core *glamo,
191 + u_int16_t reg, u_int16_t val)
193 + writew(val, glamo->base + reg);
196 +static inline u_int16_t __reg_read(struct glamo_core *glamo,
199 + return readw(glamo->base + reg);
202 +static void __reg_set_bit_mask(struct glamo_core *glamo,
203 + u_int16_t reg, u_int16_t mask,
210 + tmp = __reg_read(glamo, reg);
213 + __reg_write(glamo, reg, tmp);
216 +static void reg_set_bit_mask(struct glamo_core *glamo,
217 + u_int16_t reg, u_int16_t mask,
220 + spin_lock(&glamo->lock);
221 + __reg_set_bit_mask(glamo, reg, mask, val);
222 + spin_unlock(&glamo->lock);
225 +static inline void __reg_set_bit(struct glamo_core *glamo,
226 + u_int16_t reg, u_int16_t bit)
228 + __reg_set_bit_mask(glamo, reg, bit, 0xffff);
231 +static inline void __reg_clear_bit(struct glamo_core *glamo,
232 + u_int16_t reg, u_int16_t bit)
234 + __reg_set_bit_mask(glamo, reg, bit, 0);
237 +static inline void glamo_vmem_write(struct glamo_core *glamo, u_int32_t addr,
238 + u_int16_t *src, int len)
240 + if (addr & 0x0001 || (unsigned long)src & 0x0001 || len & 0x0001) {
241 + dev_err(&glamo->pdev->dev, "unaligned write(0x%08x, 0x%p, "
242 + "0x%x)!!\n", addr, src, len);
247 +static inline void glamo_vmem_read(struct glamo_core *glamo, u_int16_t *buf,
248 + u_int32_t addr, int len)
250 + if (addr & 0x0001 || (unsigned long) buf & 0x0001 || len & 0x0001) {
251 + dev_err(&glamo->pdev->dev, "unaligned read(0x%p, 0x08%x, "
252 + "0x%x)!!\n", buf, addr, len);
258 +/***********************************************************************
259 + * resources of sibling devices
260 + ***********************************************************************/
263 +static struct resource glamo_core_resources[] = {
265 + .start = GLAMO_REGOFS_GENERIC,
266 + .end = GLAMO_REGOFS_GENERIC + 0x400,
267 + .flags = IORESOURCE_MEM,
271 + .flags = IORESOURCE_IRQ,
275 +static struct platform_device glamo_core_dev = {
276 + .name = "glamo-core",
277 + .resource = &glamo_core_resources,
278 + .num_resources = ARRAY_SIZE(glamo_core_resources),
282 +static struct resource glamo_jpeg_resources[] = {
284 + .start = GLAMO_REGOFS_JPEG,
285 + .end = GLAMO_REGOFS_MPEG - 1,
286 + .flags = IORESOURCE_MEM,
288 + .start = IRQ_GLAMO_JPEG,
289 + .end = IRQ_GLAMO_JPEG,
290 + .flags = IORESOURCE_IRQ,
294 +static struct platform_device glamo_jpeg_dev = {
295 + .name = "glamo-jpeg",
296 + .resource = glamo_jpeg_resources,
297 + .num_resources = ARRAY_SIZE(glamo_jpeg_resources),
300 +static struct resource glamo_mpeg_resources[] = {
302 + .start = GLAMO_REGOFS_MPEG,
303 + .end = GLAMO_REGOFS_LCD - 1,
304 + .flags = IORESOURCE_MEM,
306 + .start = IRQ_GLAMO_MPEG,
307 + .end = IRQ_GLAMO_MPEG,
308 + .flags = IORESOURCE_IRQ,
312 +static struct platform_device glamo_mpeg_dev = {
313 + .name = "glamo-mpeg",
314 + .resource = glamo_mpeg_resources,
315 + .num_resources = ARRAY_SIZE(glamo_mpeg_resources),
318 +static struct resource glamo_2d_resources[] = {
320 + .start = GLAMO_REGOFS_2D,
321 + .end = GLAMO_REGOFS_3D - 1,
322 + .flags = IORESOURCE_MEM,
324 + .start = IRQ_GLAMO_2D,
325 + .end = IRQ_GLAMO_2D,
326 + .flags = IORESOURCE_IRQ,
330 +static struct platform_device glamo_2d_dev = {
331 + .name = "glamo-2d",
332 + .resource = glamo_2d_resources,
333 + .num_resources = ARRAY_SIZE(glamo_2d_resources),
336 +static struct resource glamo_3d_resources[] = {
338 + .start = GLAMO_REGOFS_3D,
339 + .end = GLAMO_REGOFS_END - 1,
340 + .flags = IORESOURCE_MEM,
344 +static struct platform_device glamo_3d_dev = {
345 + .name = "glamo-3d",
346 + .resource = glamo_3d_resources,
347 + .num_resources = ARRAY_SIZE(glamo_3d_resources),
350 +static struct platform_device glamo_spigpio_dev = {
351 + .name = "glamo-spi-gpio",
354 +static struct resource glamo_fb_resources[] = {
355 + /* FIXME: those need to be incremented by parent base */
357 + .name = "glamo-fb-regs",
358 + .start = GLAMO_REGOFS_LCD,
359 + .end = GLAMO_REGOFS_MMC - 1,
360 + .flags = IORESOURCE_MEM,
362 + .name = "glamo-fb-mem",
363 + .start = GLAMO_OFFSET_FB,
364 + .end = GLAMO_OFFSET_FB + GLAMO_FB_SIZE - 1,
365 + .flags = IORESOURCE_MEM,
369 +static struct platform_device glamo_fb_dev = {
370 + .name = "glamo-fb",
371 + .resource = glamo_fb_resources,
372 + .num_resources = ARRAY_SIZE(glamo_fb_resources),
375 +static struct resource glamo_mmc_resources[] = {
377 + /* FIXME: those need to be incremented by parent base */
378 + .start = GLAMO_REGOFS_MMC,
379 + .end = GLAMO_REGOFS_MPROC0 - 1,
380 + .flags = IORESOURCE_MEM
382 + .start = IRQ_GLAMO_MMC,
383 + .end = IRQ_GLAMO_MMC,
384 + .flags = IORESOURCE_IRQ,
385 + }, { /* our data buffer for MMC transfers */
386 + .start = GLAMO_OFFSET_FB + GLAMO_FB_SIZE,
387 + .end = GLAMO_OFFSET_FB + GLAMO_FB_SIZE +
388 + GLAMO_MMC_BUFFER_SIZE - 1,
389 + .flags = IORESOURCE_MEM
393 +static struct platform_device glamo_mmc_dev = {
394 + .name = "glamo-mci",
395 + .resource = glamo_mmc_resources,
396 + .num_resources = ARRAY_SIZE(glamo_mmc_resources),
399 +struct glamo_mci_pdata glamo_mci_def_pdata = {
401 + .glamo_set_mci_power = NULL, /* filled in from MFD platform data */
402 + .ocr_avail = MMC_VDD_32_33,
403 + .glamo_irq_is_wired = NULL, /* filled in from MFD platform data */
405 +EXPORT_SYMBOL_GPL(glamo_mci_def_pdata);
409 +static void mangle_mem_resources(struct resource *res, int num_res,
410 + struct resource *parent)
414 + for (i = 0; i < num_res; i++) {
415 + if (res[i].flags != IORESOURCE_MEM)
417 + res[i].start += parent->start;
418 + res[i].end += parent->start;
419 + res[i].parent = parent;
423 +/***********************************************************************
424 + * IRQ demultiplexer
425 + ***********************************************************************/
426 +#define irq2glamo(x) (x - IRQ_GLAMO(0))
428 +static void glamo_ack_irq(unsigned int irq)
430 + /* clear interrupt source */
431 + __reg_write(glamo_handle, GLAMO_REG_IRQ_CLEAR,
432 + 1 << irq2glamo(irq));
435 +static void glamo_mask_irq(unsigned int irq)
439 + /* clear bit in enable register */
440 + tmp = __reg_read(glamo_handle, GLAMO_REG_IRQ_ENABLE);
441 + tmp &= ~(1 << irq2glamo(irq));
442 + __reg_write(glamo_handle, GLAMO_REG_IRQ_ENABLE, tmp);
445 +static void glamo_unmask_irq(unsigned int irq)
449 + /* set bit in enable register */
450 + tmp = __reg_read(glamo_handle, GLAMO_REG_IRQ_ENABLE);
451 + tmp |= (1 << irq2glamo(irq));
452 + __reg_write(glamo_handle, GLAMO_REG_IRQ_ENABLE, tmp);
455 +static struct irq_chip glamo_irq_chip = {
456 + .ack = glamo_ack_irq,
457 + .mask = glamo_mask_irq,
458 + .unmask = glamo_unmask_irq,
461 +static void glamo_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
463 + const unsigned int cpu = smp_processor_id();
465 + spin_lock(&desc->lock);
467 + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
469 + if (unlikely(desc->status & IRQ_INPROGRESS)) {
470 + desc->status |= (IRQ_PENDING | IRQ_MASKED);
471 + desc->chip->mask(irq);
472 + desc->chip->ack(irq);
476 + kstat_cpu(cpu).irqs[irq]++;
477 + desc->chip->ack(irq);
478 + desc->status |= IRQ_INPROGRESS;
481 + u_int16_t irqstatus;
484 + if (unlikely((desc->status &
485 + (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==
486 + (IRQ_PENDING | IRQ_MASKED))) {
487 + /* dealing with pending IRQ, unmasking */
488 + desc->chip->unmask(irq);
489 + desc->status &= ~IRQ_MASKED;
492 + desc->status &= ~IRQ_PENDING;
494 + /* read IRQ status register */
495 + irqstatus = __reg_read(glamo_handle, GLAMO_REG_IRQ_STATUS);
496 + for (i = 0; i < 9; i++)
497 + if (irqstatus & (1 << i))
498 + desc_handle_irq(IRQ_GLAMO(i),
499 + irq_desc+IRQ_GLAMO(i));
501 + } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
503 + desc->status &= ~IRQ_INPROGRESS;
506 + spin_unlock(&desc->lock);
509 +/***********************************************************************
511 + ***********************************************************************/
513 +int glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine)
515 + spin_lock(&glamo->lock);
517 + case GLAMO_ENGINE_LCD:
518 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_LCD,
519 + GLAMO_CLOCK_LCD_EN_M5CLK |
520 + GLAMO_CLOCK_LCD_EN_DHCLK |
521 + GLAMO_CLOCK_LCD_EN_DMCLK |
522 + GLAMO_CLOCK_LCD_EN_DCLK |
523 + GLAMO_CLOCK_LCD_DG_M5CLK |
524 + GLAMO_CLOCK_LCD_DG_DMCLK, 0xffff);
525 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1,
526 + GLAMO_CLOCK_GEN51_EN_DIV_DHCLK |
527 + GLAMO_CLOCK_GEN51_EN_DIV_DMCLK |
528 + GLAMO_CLOCK_GEN51_EN_DIV_DCLK, 0xffff);
529 + __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2),
530 + GLAMO_HOSTBUS2_MMIO_EN_LCD,
533 + case GLAMO_ENGINE_MMC:
534 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MMC,
535 + GLAMO_CLOCK_MMC_EN_M9CLK |
536 + GLAMO_CLOCK_MMC_EN_TCLK |
537 + GLAMO_CLOCK_MMC_DG_M9CLK |
538 + GLAMO_CLOCK_MMC_DG_TCLK, 0xffff);
539 + __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2),
540 + GLAMO_HOSTBUS2_MMIO_EN_MMC,
541 + GLAMO_HOSTBUS2_MMIO_EN_MMC);
543 + case GLAMO_ENGINE_2D:
544 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_2D,
545 + GLAMO_CLOCK_2D_EN_M7CLK |
546 + GLAMO_CLOCK_2D_EN_GCLK |
547 + GLAMO_CLOCK_2D_DG_M7CLK |
548 + GLAMO_CLOCK_2D_DG_GCLK, 0xffff);
549 + __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2),
550 + GLAMO_HOSTBUS2_MMIO_EN_2D,
551 + GLAMO_HOSTBUS2_MMIO_EN_2D);
553 + case GLAMO_ENGINE_CMDQ:
554 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_2D,
555 + GLAMO_CLOCK_2D_EN_M6CLK, 0xffff);
556 + __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2),
557 + GLAMO_HOSTBUS2_MMIO_EN_CQ,
558 + GLAMO_HOSTBUS2_MMIO_EN_CQ);
560 + /* FIXME: Implementation */
564 + spin_unlock(&glamo->lock);
568 +EXPORT_SYMBOL_GPL(glamo_engine_enable);
570 +int glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine)
572 + spin_lock(&glamo->lock);
574 + /* FIXME: Implementation */
578 + spin_unlock(&glamo->lock);
582 +EXPORT_SYMBOL_GPL(glamo_engine_disable);
584 +struct glamo_script reset_regs[] = {
585 + [GLAMO_ENGINE_LCD] = {
586 + GLAMO_REG_CLOCK_LCD, GLAMO_CLOCK_LCD_RESET
589 + [GLAMO_ENGINE_HOST] = {
590 + GLAMO_REG_CLOCK_HOST, GLAMO_CLOCK_HOST_RESET
592 + [GLAMO_ENGINE_MEM] = {
593 + GLAMO_REG_CLOCK_MEM, GLAMO_CLOCK_MEM_RESET
596 + [GLAMO_ENGINE_MMC] = {
597 + GLAMO_REG_CLOCK_MMC, GLAMO_CLOCK_MMC_RESET
599 + [GLAMO_ENGINE_2D] = {
600 + GLAMO_REG_CLOCK_2D, GLAMO_CLOCK_2D_RESET
602 + [GLAMO_ENGINE_JPEG] = {
603 + GLAMO_REG_CLOCK_JPEG, GLAMO_CLOCK_JPEG_RESET
607 +void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine)
609 + struct glamo_script *rst;
611 + if (engine >= ARRAY_SIZE(reset_regs)) {
612 + dev_warn(&glamo->pdev->dev, "unknown engine %u ", engine);
616 + rst = &reset_regs[engine];
618 + spin_lock(&glamo->lock);
619 + __reg_set_bit(glamo, rst->reg, rst->val);
620 + spin_unlock(&glamo->lock);
624 + spin_lock(&glamo->lock);
625 + __reg_clear_bit(glamo, rst->reg, rst->val);
626 + spin_unlock(&glamo->lock);
630 +EXPORT_SYMBOL_GPL(glamo_engine_reset);
637 +static int glamo_pll_rate(struct glamo_core *glamo,
638 + enum glamo_pll pll)
641 + unsigned int div = 512;
642 + /* FIXME: move osci into platform_data */
643 + unsigned int osci = 32768;
650 + reg = __reg_read(glamo, GLAMO_REG_PLL_GEN1);
653 + reg = __reg_read(glamo, GLAMO_REG_PLL_GEN3);
658 + return (osci/div)*reg;
661 +int glamo_engine_reclock(struct glamo_core *glamo,
662 + enum glamo_engine engine,
666 + u_int16_t reg, mask, val = 0;
672 + case GLAMO_ENGINE_LCD:
674 + reg = GLAMO_REG_CLOCK_GEN7;
678 + dev_warn(&glamo->pdev->dev,
679 + "reclock of engine 0x%x not supported\n", engine);
684 + pll = glamo_pll_rate(glamo, pll);
685 + khz = 1000000000UL / ps;
688 + val = (pll / khz) / 1000;
690 + dev_dbg(&glamo->pdev->dev,
691 + "PLL %d, kHZ %d, div %d\n", pll, khz, val);
695 + reg_set_bit_mask(glamo, reg, mask, val);
696 + msleep(5); /* wait some time to stabilize */
703 +EXPORT_SYMBOL_GPL(glamo_engine_reclock);
705 +/***********************************************************************
707 + ***********************************************************************/
709 +int glamo_run_script(struct glamo_core *glamo, struct glamo_script *script,
710 + int len, int may_sleep)
714 + for (i = 0; i < len; i++) {
715 + struct glamo_script *line = &script[i];
717 + switch (line->reg) {
727 + /* spin until PLLs lock */
728 + while ((__reg_read(glamo, GLAMO_REG_PLL_GEN5) & 3) != 3)
732 + __reg_write(glamo, script[i].reg, script[i].val);
739 +EXPORT_SYMBOL(glamo_run_script);
741 +static struct glamo_script glamo_init_script[] = {
742 + { GLAMO_REG_CLOCK_HOST, 0x1000 },
744 + { GLAMO_REG_CLOCK_MEMORY, 0x1000 },
745 + { GLAMO_REG_CLOCK_MEMORY, 0x2000 },
746 + { GLAMO_REG_CLOCK_LCD, 0x1000 },
747 + { GLAMO_REG_CLOCK_MMC, 0x1000 },
748 + { GLAMO_REG_CLOCK_ISP, 0x1000 },
749 + { GLAMO_REG_CLOCK_ISP, 0x3000 },
750 + { GLAMO_REG_CLOCK_JPEG, 0x1000 },
751 + { GLAMO_REG_CLOCK_3D, 0x1000 },
752 + { GLAMO_REG_CLOCK_3D, 0x3000 },
753 + { GLAMO_REG_CLOCK_2D, 0x1000 },
754 + { GLAMO_REG_CLOCK_2D, 0x3000 },
755 + { GLAMO_REG_CLOCK_RISC1, 0x1000 },
756 + { GLAMO_REG_CLOCK_MPEG, 0x3000 },
757 + { GLAMO_REG_CLOCK_MPEG, 0x3000 },
758 + { GLAMO_REG_CLOCK_MPROC, 0x1000 /*0x100f*/ },
760 + { GLAMO_REG_CLOCK_HOST, 0x0000 },
761 + { GLAMO_REG_CLOCK_MEMORY, 0x0000 },
762 + { GLAMO_REG_CLOCK_LCD, 0x0000 },
763 + { GLAMO_REG_CLOCK_MMC, 0x0000 },
765 +/* unused engines must be left in reset to stop MMC block read "blackouts" */
766 + { GLAMO_REG_CLOCK_ISP, 0x0000 },
767 + { GLAMO_REG_CLOCK_ISP, 0x0000 },
768 + { GLAMO_REG_CLOCK_JPEG, 0x0000 },
769 + { GLAMO_REG_CLOCK_3D, 0x0000 },
770 + { GLAMO_REG_CLOCK_3D, 0x0000 },
771 + { GLAMO_REG_CLOCK_2D, 0x0000 },
772 + { GLAMO_REG_CLOCK_2D, 0x0000 },
773 + { GLAMO_REG_CLOCK_RISC1, 0x0000 },
774 + { GLAMO_REG_CLOCK_MPEG, 0x0000 },
775 + { GLAMO_REG_CLOCK_MPEG, 0x0000 },
777 + { GLAMO_REG_PLL_GEN1, 0x05db }, /* 48MHz */
778 + { GLAMO_REG_PLL_GEN3, 0x09c3 }, /* 80MHz */
781 + * b9 of this register MUST be zero to get any interrupts on INT#
782 + * the other set bits enable all the engine interrupt sources
784 + { GLAMO_REG_IRQ_ENABLE, 0x01ff },
785 + { GLAMO_REG_CLOCK_GEN6, 0x2000 },
786 + { GLAMO_REG_CLOCK_GEN7, 0x0101 },
787 + { GLAMO_REG_CLOCK_GEN8, 0x0100 },
788 + { GLAMO_REG_CLOCK_HOST, 0x000d },
794 + { GLAMO_REG_MEM_TYPE, 0x0874 }, /* 8MB, 16 word pg wr+rd */
795 + { GLAMO_REG_MEM_GEN, 0xafaf }, /* 63 grants min + max */
797 + * the register below originally 0x0108 makes unreliable Glamo MMC
798 + * write operations. Cranked to 0x05ad to add a wait state, the
799 + * unreliability is not seen after 4GB of write / read testing
801 + { GLAMO_REG_MEM_TIMING1, 0x0108 },
802 + { GLAMO_REG_MEM_TIMING2, 0x0010 }, /* Taa = 3 MCLK */
803 + { GLAMO_REG_MEM_TIMING3, 0x0000 },
804 + { GLAMO_REG_MEM_TIMING4, 0x0000 }, /* CE1# delay fall/rise */
805 + { GLAMO_REG_MEM_TIMING5, 0x0000 }, /* UB# LB# */
806 + { GLAMO_REG_MEM_TIMING6, 0x0000 }, /* OE# */
807 + { GLAMO_REG_MEM_TIMING7, 0x0000 }, /* WE# */
808 + { GLAMO_REG_MEM_TIMING8, 0x1002 }, /* MCLK delay, was 0x1000 */
809 + { GLAMO_REG_MEM_TIMING9, 0x6006 },
810 + { GLAMO_REG_MEM_TIMING10, 0x00ff },
811 + { GLAMO_REG_MEM_TIMING11, 0x0001 },
812 + { GLAMO_REG_MEM_POWER1, 0x0020 },
813 + { GLAMO_REG_MEM_POWER2, 0x0000 },
814 + { GLAMO_REG_MEM_DRAM1, 0x0000 },
816 + { GLAMO_REG_MEM_DRAM1, 0xc100 },
818 + { GLAMO_REG_MEM_DRAM1, 0xe100 },
819 + { GLAMO_REG_MEM_DRAM2, 0x01d6 },
820 + { GLAMO_REG_CLOCK_MEMORY, 0x000b },
823 +static struct glamo_script glamo_resume_script[] = {
824 + { GLAMO_REG_IRQ_ENABLE, 0x01ff },
825 + { GLAMO_REG_CLOCK_GEN6, 0x2000 },
826 + { GLAMO_REG_CLOCK_GEN7, 0x0001 }, /* 0101 */
827 + { GLAMO_REG_CLOCK_GEN8, 0x0100 },
828 + { GLAMO_REG_CLOCK_HOST, 0x000d },
834 + { GLAMO_REG_MEM_TYPE, 0x0874 }, /* 8MB, 16 word pg wr+rd */
835 + { GLAMO_REG_MEM_GEN, 0xafaf }, /* 63 grants min + max */
837 + { GLAMO_REG_MEM_TIMING1, 0x0108 },
838 + { GLAMO_REG_MEM_TIMING2, 0x0010 }, /* Taa = 3 MCLK */
839 + { GLAMO_REG_MEM_TIMING3, 0x0000 },
840 + { GLAMO_REG_MEM_TIMING4, 0x0000 }, /* CE1# delay fall/rise */
841 + { GLAMO_REG_MEM_TIMING5, 0x0000 }, /* UB# LB# */
842 + { GLAMO_REG_MEM_TIMING6, 0x0000 }, /* OE# */
843 + { GLAMO_REG_MEM_TIMING7, 0x0000 }, /* WE# */
844 + { GLAMO_REG_MEM_TIMING8, 0x1002 }, /* MCLK delay, was 0x1000 */
845 + { GLAMO_REG_MEM_TIMING9, 0x6006 },
846 + { GLAMO_REG_MEM_TIMING10, 0x00ff },
847 + { GLAMO_REG_MEM_TIMING11, 0x0001 },
848 + { GLAMO_REG_MEM_POWER1, 0x0020 },
849 + { GLAMO_REG_MEM_POWER2, 0x0000 },
850 + { GLAMO_REG_MEM_DRAM1, 0x0000 },
852 + { GLAMO_REG_MEM_DRAM1, 0xc100 },
854 + { GLAMO_REG_MEM_DRAM1, 0xe100 },
855 + { GLAMO_REG_MEM_DRAM2, 0x01d6 },
856 + { GLAMO_REG_CLOCK_MEMORY, 0x000b },
860 +static const struct glamo_script regs_vram_2mb = {
861 + { GLAMO_REG_CLOCK_MEMORY, 0x3aaa },
863 + { GLAMO_REG_CLOCK_MEMORY, 0x0aaa },
865 + { GLAMO_REG_MEM_POWER1, 0x0020 },
866 + { 0x033a, 0x0000 },
867 + { 0x033c, 0x0000 },
868 + { 0x033e, 0x0000 },
869 + { 0x0340, 0x0000 },
870 + { 0x0342, 0x0000 },
871 + { 0x0344, 0x0000 },
872 + { 0x0346, 0x0240 },
873 + { GLAMO_REG_MEM_TIMING8, 0x1016 },
874 + { GLAMO_REG_MEM_TIMING9, 0x6067 },
875 + { GLAMO_REG_MEM_TIMING10, 0x00ff },
876 + { GLAMO_REG_MEM_TIMING11, 0x0030 },
877 + { GLAMO_REG_MEM_GEN, 0x3fff },
878 + { GLAMO_REG_MEM_GEN, 0xafaf },
879 + { GLAMO_REG_MEM_TIMING1, 0x0108 },
880 + { GLAMO_REG_MEM_TIMING2, 0x0010 },
881 + { GLAMO_REG_MEM_DRAM1, 0x0a00 },
883 + { GLAMO_REG_MEM_DRAM1, 0xe200 },
887 +static const struct glamo_script regs_vram_8mb = {
888 + { GLAMO_REG_CLOCK_MEMORY, 0x3aaa },
890 + { GLAMO_REG_CLOCK_MEMORY, 0x0aaa },
892 + { GLAMO_REG_MEM_POWER1, 0x0020 },
893 + { 0x033a, 0x45cf },
894 + { 0x033c, 0x4240 },
895 + { 0x033e, 0x53e0 },
896 + { 0x0340, 0x1401 },
897 + { 0x0342, 0x0c44 },
898 + { 0x0344, 0x1d0b },
899 + { 0x0346, 0x25ac },
900 + { 0x0348, 0x1953 },
902 + { GLAMO_REG_MEM_TYPE, 0x087a },
903 + { GLAMO_REG_MEM_DRAM2, 0x01d6 },
904 + { GLAMO_REG_MEM_TIMING8, 0x1060 },
905 + { GLAMO_REG_MEM_TIMING9, 0x6067 },
906 + { GLAMO_REG_MEM_TIMING10, 0x00ff },
907 + { GLAMO_REG_MEM_TIMING11, 0x0030 },
908 + { GLAMO_REG_MEM_GEN, 0x3fff },
909 + { GLAMO_REG_MEM_GEN, 0xafaf },
910 + { GLAMO_REG_MEM_TIMING1, 0x3108 },
911 + { GLAMO_REG_MEM_TIMING2, 0x0010 },
912 + { GLAMO_REG_MEM_DRAM1, 0x0a00 },
914 + { GLAMO_REG_MEM_DRAM1, 0xe200 },
921 + GLAMO_POWER_STANDBY,
922 + GLAMO_POWER_SUSPEND,
925 +static void glamo_power(struct glamo_core *glamo,
926 + enum glamo_power new_state)
928 + spin_lock(&glamo->lock);
930 + switch (new_state) {
931 + case GLAMO_POWER_ON:
932 + /* power up PLL1 and PLL2 */
933 + __reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN6, 0x0001, 0xffff);
934 + __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 0x2000, 0x0000);
936 + /* spin until PLL1 and PLL2 lock */
937 + while ((__reg_read(glamo, GLAMO_REG_PLL_GEN5) & 3) != 3)
940 + /* enable memory clock and get it out of deep pwrdown */
941 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MEMORY,
942 + GLAMO_CLOCK_MEM_EN_MOCACLK, 0xffff);
943 + __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM2,
944 + GLAMO_MEM_DRAM2_DEEP_PWRDOWN, 0x0000);
945 + __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM1,
946 + GLAMO_MEM_DRAM1_SELF_REFRESH, 0x0000);
948 + glamo_run_script(glamo, glamo_resume_script,
949 + ARRAY_SIZE(glamo_resume_script), 0);
952 + case GLAMO_POWER_STANDBY:
953 + /* enable memory self-refresh */
954 + __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM1,
955 + GLAMO_MEM_DRAM1_SELF_REFRESH, 0xffff);
956 + /* stop memory clock */
957 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MEMORY,
958 + GLAMO_CLOCK_MEM_EN_MOCACLK, 0x0000);
959 + /* power down PLL2 and then PLL1 */
960 + __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 0x2000, 0xffff);
961 + __reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN5, 0x0001, 0xffff);
963 + case GLAMO_POWER_SUSPEND:
964 + __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM2,
965 + GLAMO_MEM_DRAM2_DEEP_PWRDOWN, 0xffff);
966 + /* stop memory clock */
967 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MEMORY,
968 + GLAMO_CLOCK_MEM_EN_MOCACLK, 0x0000);
969 + /* power down PLL2 and then PLL1 */
970 + __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 0x2000, 0xffff);
971 + __reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN5, 0x0001, 0xffff);
975 + spin_unlock(&glamo->lock);
979 +#define MEMDETECT_RETRY 6
980 +static unsigned int detect_memsize(struct glamo_core *glamo)
984 + /*static const u_int16_t pattern[] = {
985 + 0x1111, 0x8a8a, 0x2222, 0x7a7a,
986 + 0x3333, 0x6a6a, 0x4444, 0x5a5a,
987 + 0x5555, 0x4a4a, 0x6666, 0x3a3a,
988 + 0x7777, 0x2a2a, 0x8888, 0x1a1a
991 + for (i = 0; i < MEMDETECT_RETRY; i++) {
992 + switch (glamo->type) {
994 + __reg_write(glamo, GLAMO_REG_MEM_TYPE, 0x0072);
995 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0xc100);
998 + switch (glamo->revision) {
999 + case GLAMO_CORE_REV_A0:
1001 + __reg_write(glamo, GLAMO_REG_MEM_TYPE,
1004 + __reg_write(glamo, GLAMO_REG_MEM_TYPE,
1007 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0x0000);
1009 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0xc100);
1013 + __reg_write(glamo, GLAMO_REG_MEM_TYPE,
1016 + __reg_write(glamo, GLAMO_REG_MEM_TYPE,
1019 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0x0000);
1021 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0xe100);
1032 + /* FIXME: finish implementation */
1033 + for (j = 0; j < 8; j++) {
1042 +/* Find out if we can support this version of the Glamo chip */
1043 +static int glamo_supported(struct glamo_core *glamo)
1045 + u_int16_t dev_id, rev_id; /*, memsize; */
1047 + dev_id = __reg_read(glamo, GLAMO_REG_DEVICE_ID);
1048 + rev_id = __reg_read(glamo, GLAMO_REG_REVISION_ID);
1053 + case GLAMO_CORE_REV_A2:
1055 + case GLAMO_CORE_REV_A0:
1056 + case GLAMO_CORE_REV_A1:
1057 + case GLAMO_CORE_REV_A3:
1058 + dev_warn(&glamo->pdev->dev, "untested core revision "
1059 + "%04x, your mileage may vary\n", rev_id);
1062 + dev_warn(&glamo->pdev->dev, "unknown glamo revision "
1063 + "%04x, your mileage may vary\n", rev_id);
1064 + /* maybe should abort ? */
1070 + dev_err(&glamo->pdev->dev, "unsupported Glamo device %04x\n",
1075 + dev_info(&glamo->pdev->dev, "Detected Glamo core %04x Revision %04x "
1076 + "(%uHz CPU / %uHz Memory)\n", dev_id, rev_id,
1077 + glamo_pll_rate(glamo, GLAMO_PLL1),
1078 + glamo_pll_rate(glamo, GLAMO_PLL2));
1084 +static int __init glamo_probe(struct platform_device *pdev)
1087 + struct glamo_core *glamo;
1089 + if (glamo_handle) {
1090 + dev_err(&pdev->dev,
1091 + "This driver supports only one instance\n");
1095 + glamo = kmalloc(GFP_KERNEL, sizeof(*glamo));
1099 + spin_lock_init(&glamo->lock);
1100 + glamo_handle = glamo;
1101 + glamo->pdev = pdev;
1102 + glamo->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1103 + glamo->irq = platform_get_irq(pdev, 0);
1104 + glamo->pdata = pdev->dev.platform_data;
1105 + if (!glamo->mem || !glamo->pdata) {
1106 + dev_err(&pdev->dev, "platform device with no MEM/PDATA ?\n");
1111 + /* register a number of sibling devices whoise IOMEM resources
1112 + * are siblings of pdev's IOMEM resource */
1114 + glamo_core_dev.dev.parent = &pdev.dev;
1115 + mangle_mem_resources(glamo_core_dev.resources,
1116 + glamo_core_dev.num_resources, glamo->mem);
1117 + glamo_core_dev.resources[1].start = glamo->irq;
1118 + glamo_core_dev.resources[1].end = glamo->irq;
1119 + platform_device_register(&glamo_core_dev);
1121 + /* only remap the generic, hostbus and memory controller registers */
1122 + glamo->base = ioremap(glamo->mem->start, GLAMO_REGOFS_VIDCAP);
1123 + if (!glamo->base) {
1124 + dev_err(&pdev->dev, "failed to ioremap() memory region\n");
1128 + /* bring MCI specific stuff over from our MFD platform data */
1129 + glamo_mci_def_pdata.glamo_set_mci_power =
1130 + glamo->pdata->glamo_set_mci_power;
1131 + glamo_mci_def_pdata.glamo_irq_is_wired =
1132 + glamo->pdata->glamo_irq_is_wired;
1134 + glamo_mmc_dev.dev.parent = &pdev->dev;
1135 + /* we need it later to give to the engine enable and disable */
1136 + glamo_mci_def_pdata.pglamo = glamo;
1137 + mangle_mem_resources(glamo_mmc_dev.resource,
1138 + glamo_mmc_dev.num_resources, glamo->mem);
1139 + platform_device_register(&glamo_mmc_dev);
1141 + glamo_2d_dev.dev.parent = &pdev->dev;
1142 + mangle_mem_resources(glamo_2d_dev.resource,
1143 + glamo_2d_dev.num_resources, glamo->mem);
1144 + platform_device_register(&glamo_2d_dev);
1146 + glamo_3d_dev.dev.parent = &pdev->dev;
1147 + mangle_mem_resources(glamo_3d_dev.resource,
1148 + glamo_3d_dev.num_resources, glamo->mem);
1149 + platform_device_register(&glamo_3d_dev);
1151 + glamo_jpeg_dev.dev.parent = &pdev->dev;
1152 + mangle_mem_resources(glamo_jpeg_dev.resource,
1153 + glamo_jpeg_dev.num_resources, glamo->mem);
1154 + platform_device_register(&glamo_jpeg_dev);
1156 + glamo_mpeg_dev.dev.parent = &pdev->dev;
1157 + mangle_mem_resources(glamo_mpeg_dev.resource,
1158 + glamo_mpeg_dev.num_resources, glamo->mem);
1159 + platform_device_register(&glamo_mpeg_dev);
1161 + glamo->pdata->glamo = glamo;
1162 + glamo_fb_dev.dev.parent = &pdev->dev;
1163 + glamo_fb_dev.dev.platform_data = glamo->pdata;
1164 + mangle_mem_resources(glamo_fb_dev.resource,
1165 + glamo_fb_dev.num_resources, glamo->mem);
1166 + platform_device_register(&glamo_fb_dev);
1168 + glamo->pdata->spigpio_info->glamo = glamo;
1169 + glamo_spigpio_dev.dev.parent = &pdev->dev;
1170 + glamo_spigpio_dev.dev.platform_data = glamo->pdata->spigpio_info;
1171 + platform_device_register(&glamo_spigpio_dev);
1173 + /* only request the generic, hostbus and memory controller MMIO */
1174 + glamo->mem = request_mem_region(glamo->mem->start,
1175 + GLAMO_REGOFS_VIDCAP, "glamo-core");
1176 + if (!glamo->mem) {
1177 + dev_err(&pdev->dev, "failed to request memory region\n");
1181 + if (!glamo_supported(glamo)) {
1182 + dev_err(&pdev->dev, "This Glamo is not supported\n");
1186 + platform_set_drvdata(pdev, glamo);
1188 + dev_dbg(&glamo->pdev->dev, "running init script\n");
1189 + glamo_run_script(glamo, glamo_init_script,
1190 + ARRAY_SIZE(glamo_init_script), 1);
1192 + dev_info(&glamo->pdev->dev, "Glamo core now %uHz CPU / %uHz Memory)\n",
1193 + glamo_pll_rate(glamo, GLAMO_PLL1),
1194 + glamo_pll_rate(glamo, GLAMO_PLL2));
1196 + for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) {
1197 + set_irq_chip(irq, &glamo_irq_chip);
1198 + set_irq_handler(irq, handle_level_irq);
1199 + set_irq_flags(irq, IRQF_VALID);
1202 + if (glamo->pdata->glamo_irq_is_wired &&
1203 + !glamo->pdata->glamo_irq_is_wired()) {
1204 + set_irq_chained_handler(glamo->irq, glamo_irq_demux_handler);
1205 + set_irq_type(glamo->irq, IRQT_FALLING);
1206 + glamo->irq_works = 1;
1208 + glamo->irq_works = 0;
1212 + glamo_handle = NULL;
1217 +static int glamo_remove(struct platform_device *pdev)
1219 + struct glamo_core *glamo = platform_get_drvdata(pdev);
1222 + disable_irq(glamo->irq);
1223 + set_irq_chained_handler(glamo->irq, NULL);
1225 + for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) {
1226 + set_irq_flags(irq, 0);
1227 + set_irq_chip(irq, NULL);
1230 + platform_set_drvdata(pdev, NULL);
1231 + platform_device_unregister(&glamo_fb_dev);
1232 + platform_device_unregister(&glamo_mmc_dev);
1233 + iounmap(glamo->base);
1234 + release_mem_region(glamo->mem->start, GLAMO_REGOFS_VIDCAP);
1235 + glamo_handle = NULL;
1242 +static int glamo_suspend(struct platform_device *pdev, pm_message_t state)
1247 +static int glamo_resume(struct platform_device *pdev)
1252 +#define glamo_suspend NULL
1253 +#define glamo_resume NULL
1256 +static struct platform_driver glamo_driver = {
1257 + .probe = glamo_probe,
1258 + .remove = glamo_remove,
1259 + .suspend = glamo_suspend,
1260 + .resume = glamo_resume,
1262 + .name = "glamo3362",
1263 + .owner = THIS_MODULE,
1267 +static int __devinit glamo_init(void)
1269 + return platform_driver_register(&glamo_driver);
1272 +static void __exit glamo_cleanup(void)
1274 + platform_driver_unregister(&glamo_driver);
1277 +module_init(glamo_init);
1278 +module_exit(glamo_cleanup);
1280 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
1281 +MODULE_DESCRIPTION("Smedia Glamo 336x/337x core/resource driver");
1282 +MODULE_LICENSE("GPL");
1283 diff --git a/drivers/mfd/glamo/glamo-core.h b/drivers/mfd/glamo/glamo-core.h
1284 new file mode 100644
1285 index 0000000..cf89f03
1287 +++ b/drivers/mfd/glamo/glamo-core.h
1289 +#ifndef __GLAMO_CORE_H
1290 +#define __GLAMO_CORE_H
1292 +#include <asm/system.h>
1295 +/* for the time being, we put the on-screen framebuffer into the lowest
1296 + * VRAM space. This should make the code easily compatible with the various
1297 + * 2MB/4MB/8MB variants of the Smedia chips */
1298 +#define GLAMO_OFFSET_VRAM 0x800000
1299 +#define GLAMO_OFFSET_FB (GLAMO_OFFSET_VRAM)
1301 +/* we only allocate the minimum possible size for the framebuffer to make
1302 + * sure we have sufficient memory for other functions of the chip */
1303 +//#define GLAMO_FB_SIZE (640*480*4) /* == 0x12c000 */
1304 +#define GLAMO_INTERNAL_RAM_SIZE 0x800000
1305 +#define GLAMO_MMC_BUFFER_SIZE (64 * 1024)
1306 +#define GLAMO_FB_SIZE (GLAMO_INTERNAL_RAM_SIZE - GLAMO_MMC_BUFFER_SIZE)
1309 +struct glamo_core {
1311 + int irq_works; /* 0 means PCB does not support Glamo IRQ */
1312 + struct resource *mem;
1313 + struct resource *mem_core;
1314 + void __iomem *base;
1315 + struct platform_device *pdev;
1316 + struct glamofb_platform_data *pdata;
1318 + u_int16_t revision;
1322 +struct glamo_script {
1327 +int glamo_run_script(struct glamo_core *glamo,
1328 + struct glamo_script *script, int len, int may_sleep);
1330 +enum glamo_engine {
1331 + GLAMO_ENGINE_CAPTURE,
1333 + GLAMO_ENGINE_JPEG,
1334 + GLAMO_ENGINE_MPEG_ENC,
1335 + GLAMO_ENGINE_MPEG_DEC,
1337 + GLAMO_ENGINE_CMDQ,
1341 + GLAMO_ENGINE_MICROP0,
1342 + GLAMO_ENGINE_RISC,
1343 + GLAMO_ENGINE_MICROP1_MPEG_ENC,
1344 + GLAMO_ENGINE_MICROP1_MPEG_DEC,
1346 + GLAMO_ENGINE_H264_DEC,
1347 + GLAMO_ENGINE_RISC1,
1350 + __NUM_GLAMO_ENGINES
1353 +struct glamo_mci_pdata {
1354 + struct glamo_core * pglamo;
1355 + unsigned int gpio_detect;
1356 + unsigned int gpio_wprotect;
1357 + unsigned long ocr_avail;
1358 + void (*glamo_set_mci_power)(unsigned char power_mode,
1359 + unsigned short vdd);
1360 + int (*glamo_irq_is_wired)(void);
1364 +static inline void glamo_reg_access_delay(void)
1368 + for (n = 0; n != 2; n++)
1373 +int glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine);
1374 +int glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine);
1375 +void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine);
1376 +int glamo_engine_reclock(struct glamo_core *glamo,
1377 + enum glamo_engine engine, int ps);
1379 +#endif /* __GLAMO_CORE_H */
1380 diff --git a/drivers/mfd/glamo/glamo-fb.c b/drivers/mfd/glamo/glamo-fb.c
1381 new file mode 100644
1382 index 0000000..394a0ad
1384 +++ b/drivers/mfd/glamo/glamo-fb.c
1386 +/* Smedia Glamo 336x/337x driver
1388 + * (C) 2007 by OpenMoko, Inc.
1389 + * Author: Harald Welte <laforge@openmoko.org>
1390 + * All rights reserved.
1392 + * This program is free software; you can redistribute it and/or
1393 + * modify it under the terms of the GNU General Public License as
1394 + * published by the Free Software Foundation; either version 2 of
1395 + * the License, or (at your option) any later version.
1397 + * This program is distributed in the hope that it will be useful,
1398 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1399 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1400 + * GNU General Public License for more details.
1402 + * You should have received a copy of the GNU General Public License
1403 + * along with this program; if not, write to the Free Software
1404 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
1405 + * MA 02111-1307 USA
1408 +#include <linux/module.h>
1409 +#include <linux/kernel.h>
1410 +#include <linux/errno.h>
1411 +#include <linux/string.h>
1412 +#include <linux/mm.h>
1413 +#include <linux/slab.h>
1414 +#include <linux/delay.h>
1415 +#include <linux/fb.h>
1416 +#include <linux/init.h>
1417 +#include <linux/vmalloc.h>
1418 +#include <linux/dma-mapping.h>
1419 +#include <linux/interrupt.h>
1420 +#include <linux/workqueue.h>
1421 +#include <linux/wait.h>
1422 +#include <linux/platform_device.h>
1423 +#include <linux/clk.h>
1425 +#include <asm/io.h>
1426 +#include <asm/uaccess.h>
1427 +#include <asm/div64.h>
1430 +#include <linux/pm.h>
1433 +#include <linux/glamofb.h>
1435 +#include "glamo-regs.h"
1436 +#include "glamo-core.h"
1439 +#define GLAMO_LOG(...)
1441 +#define GLAMO_LOG(...) \
1443 + printk(KERN_DEBUG "in %s:%s:%d", __FILE__, __func__, __LINE__); \
1444 + printk(KERN_DEBUG __VA_ARGS__); \
1449 +#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
1451 +struct glamofb_handle {
1452 + struct fb_info *fb;
1453 + struct device *dev;
1454 + struct resource *reg;
1455 + struct resource *fb_res;
1456 + char __iomem *base;
1457 + struct glamofb_platform_data *mach_info;
1458 + char __iomem *cursor_addr;
1459 + u_int32_t pseudo_pal[16];
1462 +/* 'sibling' spi device for lcm init */
1463 +static struct platform_device glamo_spi_dev = {
1464 + .name = "glamo-lcm-spi",
1468 +static int reg_read(struct glamofb_handle *glamo,
1471 + glamo_reg_access_delay();
1472 + return readw(glamo->base + reg);
1475 +static void reg_write(struct glamofb_handle *glamo,
1476 + u_int16_t reg, u_int16_t val)
1478 + glamo_reg_access_delay();
1479 + writew(val, glamo->base + reg);
1482 +static struct glamo_script glamo_regs[] = {
1483 + { GLAMO_REG_LCD_MODE1, 0x0020 },
1484 + /* no display rotation, no hardware cursor, no dither, no gamma,
1485 + * no retrace flip, vsync low-active, hsync low active,
1486 + * no TVCLK, no partial display, hw dest color from fb,
1487 + * no partial display mode, LCD1, software flip, */
1488 + { GLAMO_REG_LCD_MODE2, 0x1020 },
1489 + /* no video flip, no ptr, no ptr, dhclk,
1490 + * normal mode, no cpuif,
1491 + * res, serial msb first, single fb, no fr ctrl,
1492 + * cpu if bits all zero, no crc
1493 + * 0000 0000 0010 0000 */
1494 + { GLAMO_REG_LCD_MODE3, 0x0b40 },
1495 + /* src data rgb565, res, 18bit rgb666
1496 + * 000 01 011 0100 0000 */
1497 + { GLAMO_REG_LCD_POLARITY, 0x440c },
1498 + /* DE high active, no cpu/lcd if, cs0 force low, a0 low active,
1499 + * np cpu if, 9bit serial data, sclk rising edge latch data
1500 + * 01 00 0 100 0 000 01 0 0 */
1501 + { GLAMO_REG_LCD_A_BASE1, 0x0000 }, /* display A base address 15:0 */
1502 + { GLAMO_REG_LCD_A_BASE2, 0x0000 }, /* display A base address 22:16 */
1505 +static int glamofb_run_script(struct glamofb_handle *glamo,
1506 + struct glamo_script *script, int len)
1510 + for (i = 0; i < len; i++) {
1511 + struct glamo_script *line = &script[i];
1513 + if (line->reg == 0xffff)
1515 + else if (line->reg == 0xfffe)
1516 + msleep(line->val);
1518 + reg_write(glamo, script[i].reg, script[i].val);
1524 +static int glamofb_check_var(struct fb_var_screeninfo *var,
1525 + struct fb_info *info)
1527 + struct glamofb_handle *glamo = info->par;
1529 + if (var->yres > glamo->mach_info->yres.max)
1530 + var->yres = glamo->mach_info->yres.max;
1531 + else if (var->yres < glamo->mach_info->yres.min)
1532 + var->yres = glamo->mach_info->yres.min;
1534 + if (var->xres > glamo->mach_info->xres.max)
1535 + var->xres = glamo->mach_info->xres.max;
1536 + else if (var->xres < glamo->mach_info->xres.min)
1537 + var->xres = glamo->mach_info->xres.min;
1539 + if (var->bits_per_pixel > glamo->mach_info->bpp.max)
1540 + var->bits_per_pixel = glamo->mach_info->bpp.max;
1541 + else if (var->bits_per_pixel < glamo->mach_info->bpp.min)
1542 + var->bits_per_pixel = glamo->mach_info->bpp.min;
1544 + /* FIXME: set rgb positions */
1545 + switch (var->bits_per_pixel) {
1547 + switch (reg_read(glamo, GLAMO_REG_LCD_MODE3) & 0xc000) {
1548 + case GLAMO_LCD_SRC_RGB565:
1549 + var->red.offset = 11;
1550 + var->green.offset = 5;
1551 + var->blue.offset = 0;
1552 + var->red.length = 5;
1553 + var->green.length = 6;
1554 + var->blue.length = 5;
1555 + var->transp.length = 0;
1557 + case GLAMO_LCD_SRC_ARGB1555:
1558 + var->transp.offset = 15;
1559 + var->red.offset = 10;
1560 + var->green.offset = 5;
1561 + var->blue.offset = 0;
1562 + var->transp.length = 1;
1563 + var->red.length = 5;
1564 + var->green.length = 5;
1565 + var->blue.length = 5;
1567 + case GLAMO_LCD_SRC_ARGB4444:
1568 + var->transp.offset = 12;
1569 + var->red.offset = 8;
1570 + var->green.offset = 4;
1571 + var->blue.offset = 0;
1572 + var->transp.length = 4;
1573 + var->red.length = 4;
1574 + var->green.length = 4;
1575 + var->blue.length = 4;
1582 + /* The Smedia Glamo doesn't support anything but 16bit color */
1584 + "Smedia driver does not [yet?] support 24/32bpp\n");
1592 +static void reg_set_bit_mask(struct glamofb_handle *glamo,
1593 + u_int16_t reg, u_int16_t mask,
1600 + tmp = reg_read(glamo, reg);
1603 + reg_write(glamo, reg, tmp);
1606 +#define GLAMO_LCD_WIDTH_MASK 0x03FF
1607 +#define GLAMO_LCD_HEIGHT_MASK 0x03FF
1608 +#define GLAMO_LCD_PITCH_MASK 0x07FE
1609 +#define GLAMO_LCD_HV_TOTAL_MASK 0x03FF
1610 +#define GLAMO_LCD_HV_RETR_START_MASK 0x03FF
1611 +#define GLAMO_LCD_HV_RETR_END_MASK 0x03FF
1612 +#define GLAMO_LCD_HV_RETR_DISP_START_MASK 0x03FF
1613 +#define GLAMO_LCD_HV_RETR_DISP_END_MASK 0x03FF
1616 + ORIENTATION_PORTRAIT,
1617 + ORIENTATION_LANDSCAPE
1621 +static void rotate_lcd(struct glamofb_handle *glamo,
1626 + switch (rotation) {
1627 + case FB_ROTATE_UR:
1628 + glamo_rot = GLAMO_LCD_ROT_MODE_0;
1630 + case FB_ROTATE_CW:
1631 + glamo_rot = GLAMO_LCD_ROT_MODE_90;
1633 + case FB_ROTATE_UD:
1634 + glamo_rot = GLAMO_LCD_ROT_MODE_180;
1636 + case FB_ROTATE_CCW:
1637 + glamo_rot = GLAMO_LCD_ROT_MODE_270;
1640 + glamo_rot = GLAMO_LCD_ROT_MODE_0;
1643 + glamofb_cmd_mode(glamo, 1);
1644 + reg_set_bit_mask(glamo,
1645 + GLAMO_REG_LCD_WIDTH,
1646 + GLAMO_LCD_ROT_MODE_MASK,
1648 + reg_set_bit_mask(glamo,
1649 + GLAMO_REG_LCD_MODE1,
1650 + GLAMO_LCD_MODE1_ROTATE_EN,
1651 + (glamo_rot != GLAMO_LCD_ROT_MODE_0)?
1652 + GLAMO_LCD_MODE1_ROTATE_EN : 0);
1653 + glamofb_cmd_mode(glamo, 0);
1656 +static enum orientation get_orientation(struct fb_var_screeninfo *var)
1658 + GLAMO_LOG("mark\n")
1659 + if (var->xres <= var->yres) {
1660 + GLAMO_LOG("portrait\n")
1661 + return ORIENTATION_PORTRAIT;
1663 + GLAMO_LOG("landscape\n")
1664 + return ORIENTATION_LANDSCAPE;
1667 +static int will_orientation_change(struct fb_var_screeninfo *var)
1669 + enum orientation orient = get_orientation(var);
1671 + case ORIENTATION_LANDSCAPE:
1672 + if (var->rotate == FB_ROTATE_UR || var->rotate == FB_ROTATE_UD)
1675 + case ORIENTATION_PORTRAIT:
1676 + if (var->rotate == FB_ROTATE_CW || var->rotate == FB_ROTATE_CCW)
1683 +static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
1684 + struct fb_var_screeninfo *var)
1686 + int sync, bp, disp, fp, total, xres, yres, pitch, orientation_changing;
1688 + GLAMO_LOG("enter: glamo:%#x, var:%#x\n", (unsigned)glamo, (unsigned)var);
1689 + if (!glamo || !var)
1692 + glamofb_cmd_mode(glamo, 1);
1694 + if (var->pixclock)
1695 + glamo_engine_reclock(glamo->mach_info->glamo,
1701 + GLAMO_LOG("xres:%d, yres:%d, rotate:%d\n", xres, yres, var->rotate);
1704 + * figure out if orientation is going to change
1706 + orientation_changing = will_orientation_change(var);
1707 + GLAMO_LOG("orientation_changing:%d\n", orientation_changing);
1710 + * adjust the pitch according to new orientation to come
1712 + if (orientation_changing) {
1713 + pitch = var->yres * var->bits_per_pixel / 8;
1715 + pitch = var->xres * var->bits_per_pixel / 8;
1717 + GLAMO_LOG("pitch:%d\n", pitch);
1720 + * set the awaiten LCD geometry
1722 + reg_set_bit_mask(glamo,
1723 + GLAMO_REG_LCD_WIDTH,
1724 + GLAMO_LCD_WIDTH_MASK,
1726 + reg_set_bit_mask(glamo,
1727 + GLAMO_REG_LCD_HEIGHT,
1728 + GLAMO_LCD_HEIGHT_MASK,
1730 + reg_set_bit_mask(glamo,
1731 + GLAMO_REG_LCD_PITCH,
1732 + GLAMO_LCD_PITCH_MASK,
1735 + GLAMO_LOG("mark:\n");
1737 + * honour the rotation request
1739 + rotate_lcd(glamo, var->rotate);
1742 + * update the reported geometry
1743 + * of the framebuffer.
1745 + if (orientation_changing) {
1746 + var->xres_virtual = var->xres = yres;
1747 + var->yres_virtual = var->yres = xres;
1749 + var->xres_virtual = var->xres = xres;
1750 + var->yres_virtual = var->yres = yres;
1753 + GLAMO_LOG("reported res:(%d,%d)\n", var->xres, var->yres);
1755 + * update scannout timings
1758 + bp = sync + var->hsync_len;
1759 + disp = bp + var->left_margin;
1761 + total = fp + var->right_margin;
1763 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_TOTAL,
1764 + GLAMO_LCD_HV_TOTAL_MASK, total);
1765 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_RETR_START,
1766 + GLAMO_LCD_HV_RETR_START_MASK, sync);
1767 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_RETR_END,
1768 + GLAMO_LCD_HV_RETR_END_MASK, bp);
1769 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_START,
1770 + GLAMO_LCD_HV_RETR_DISP_START_MASK, disp);
1771 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_END,
1772 + GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
1774 + GLAMO_LOG("mark:\n");
1777 + bp = sync + var->vsync_len;
1778 + disp = bp + var->upper_margin;
1780 + total = fp + var->lower_margin;
1782 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_TOTAL,
1783 + GLAMO_LCD_HV_TOTAL_MASK, total);
1784 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_RETR_START,
1785 + GLAMO_LCD_HV_RETR_START_MASK, sync);
1786 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_RETR_END,
1787 + GLAMO_LCD_HV_RETR_END_MASK, bp);
1788 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_START,
1789 + GLAMO_LCD_HV_RETR_DISP_START_MASK, disp);
1790 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_END,
1791 + GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
1793 + GLAMO_LOG("mark:\n");
1794 + glamofb_cmd_mode(glamo, 0);
1796 + GLAMO_LOG("leave:\n");
1799 +static int glamofb_set_par(struct fb_info *info)
1801 + struct glamofb_handle *glamo = info->par;
1802 + struct fb_var_screeninfo *var = &info->var;
1804 + switch (var->bits_per_pixel) {
1806 + info->fix.visual = FB_VISUAL_TRUECOLOR;
1809 + printk("Smedia driver doesn't support != 16bpp\n");
1813 + info->fix.line_length = (var->xres * var->bits_per_pixel) / 8;
1815 + glamofb_update_lcd_controller(glamo, var);
1820 +static int glamofb_blank(int blank_mode, struct fb_info *info)
1826 +static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
1829 + chan >>= 16 - bf->length;
1830 + return chan << bf->offset;
1833 +static int glamofb_setcolreg(unsigned regno,
1834 + unsigned red, unsigned green, unsigned blue,
1835 + unsigned transp, struct fb_info *info)
1837 + struct glamofb_handle *glamo = info->par;
1840 + switch (glamo->fb->fix.visual) {
1841 + case FB_VISUAL_TRUECOLOR:
1842 + case FB_VISUAL_DIRECTCOLOR:
1843 + /* true-colour, use pseuo-palette */
1846 + u32 *pal = glamo->fb->pseudo_palette;
1848 + val = chan_to_field(red, &glamo->fb->var.red);
1849 + val |= chan_to_field(green, &glamo->fb->var.green);
1850 + val |= chan_to_field(blue, &glamo->fb->var.blue);
1856 + return 1; /* unknown type */
1862 +static int glamofb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1864 + struct glamofb_handle *glamo = info->par;
1867 + if (cursor->image.depth > 2)
1870 + reg = reg_read(glamo, GLAMO_REG_LCD_MODE1);
1872 + if (cursor->enable)
1873 + reg_write(glamo, GLAMO_REG_LCD_MODE1,
1874 + reg | GLAMO_LCD_MODE1_CURSOR_EN);
1876 + reg_write(glamo, GLAMO_REG_LCD_MODE1,
1877 + reg & ~GLAMO_LCD_MODE1_CURSOR_EN);
1879 + if (cursor->set & FB_CUR_SETPOS) {
1880 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_POS,
1881 + cursor->image.dx);
1882 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_Y_POS,
1883 + cursor->image.dy);
1886 + if (cursor->set & FB_CUR_SETCMAP) {
1890 + if (cursor->set & FB_CUR_SETSIZE ||
1891 + cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) {
1893 + const unsigned char *pcol = cursor->image.data;
1894 + const unsigned char *pmsk = cursor->mask;
1895 + void __iomem *dst = glamo->cursor_addr;
1896 + unsigned char dcol = 0;
1897 + unsigned char dmsk = 0;
1899 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE,
1900 + cursor->image.width);
1901 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_PITCH,
1902 + cursor->image.width * 2);
1903 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_Y_SIZE,
1904 + cursor->image.height);
1906 + for (op = 0; op < (cursor->image.width *
1907 + cursor->image.height * 2)/8; op += 4)
1908 + writel(0x0, dst + op);
1910 + for (y = 0; y < cursor->image.height; y++) {
1911 + for (x = 0; x < cursor->image.width; x++) {
1912 + if ((x % 8) == 0) {
1923 + op = (dcol & 1) ? 1 : 3;
1924 + op <<= ((x % 4) * 2);
1926 + op |= readb(dst + (x / 4));
1927 + writeb(op, dst + (x / 4));
1934 +static inline int glamofb_cmdq_empty(struct glamofb_handle *gfb)
1936 + return reg_read(gfb, GLAMO_REG_LCD_STATUS1) & (1 << 15);
1939 +void glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
1941 + dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on);
1943 + dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ",
1945 + while (!glamofb_cmdq_empty(gfb))
1947 + dev_dbg(gfb->dev, "empty!\n");
1949 + /* display the entire frame then switch to command */
1950 + reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
1951 + GLAMO_LCD_CMD_TYPE_DISP |
1952 + GLAMO_LCD_CMD_DATA_FIRE_VSYNC);
1954 + /* wait until LCD is idle */
1955 + dev_dbg(gfb->dev, "waiting for LCD idle: ");
1956 + while (!reg_read(gfb, GLAMO_REG_LCD_STATUS2) & (1 << 12))
1958 + dev_dbg(gfb->dev, "idle!\n");
1962 + /* RGB interface needs vsync/hsync */
1963 + if (reg_read(gfb, GLAMO_REG_LCD_MODE3) & GLAMO_LCD_MODE3_RGB)
1964 + reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
1965 + GLAMO_LCD_CMD_TYPE_DISP |
1966 + GLAMO_LCD_CMD_DATA_DISP_SYNC);
1968 + reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
1969 + GLAMO_LCD_CMD_TYPE_DISP |
1970 + GLAMO_LCD_CMD_DATA_DISP_FIRE);
1973 +EXPORT_SYMBOL_GPL(glamofb_cmd_mode);
1975 +int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val)
1977 + dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n",
1979 + while (!glamofb_cmdq_empty(gfb))
1981 + dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val);
1983 + reg_write(gfb, GLAMO_REG_LCD_COMMAND1, val);
1987 +EXPORT_SYMBOL_GPL(glamofb_cmd_write);
1989 +static struct fb_ops glamofb_ops = {
1990 + .owner = THIS_MODULE,
1991 + .fb_check_var = glamofb_check_var,
1992 + .fb_set_par = glamofb_set_par,
1993 + .fb_blank = glamofb_blank,
1994 + .fb_setcolreg = glamofb_setcolreg,
1995 + //.fb_cursor = glamofb_cursor,
1996 + .fb_fillrect = cfb_fillrect,
1997 + .fb_copyarea = cfb_copyarea,
1998 + .fb_imageblit = cfb_imageblit,
2001 +static int glamofb_init_regs(struct glamofb_handle *glamo)
2003 + struct fb_info *info = glamo->fb;
2005 + glamofb_check_var(&info->var, info);
2006 + glamofb_run_script(glamo, glamo_regs, ARRAY_SIZE(glamo_regs));
2007 + glamofb_set_par(info);
2012 +static int __init glamofb_probe(struct platform_device *pdev)
2015 + struct fb_info *fbinfo;
2016 + struct glamofb_handle *glamofb;
2017 + struct glamofb_platform_data *mach_info = pdev->dev.platform_data;
2019 + printk(KERN_INFO "SMEDIA Glamo frame buffer driver (C) 2007 "
2020 + "OpenMoko, Inc.\n");
2022 + fbinfo = framebuffer_alloc(sizeof(struct glamofb_handle), &pdev->dev);
2026 + glamofb = fbinfo->par;
2027 + glamofb->fb = fbinfo;
2028 + glamofb->dev = &pdev->dev;
2030 + strcpy(fbinfo->fix.id, "SMedia Glamo");
2032 + glamofb->reg = platform_get_resource_byname(pdev, IORESOURCE_MEM,
2034 + if (!glamofb->reg) {
2035 + dev_err(&pdev->dev, "platform device with no registers?\n");
2040 + glamofb->fb_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
2042 + if (!glamofb->fb_res) {
2043 + dev_err(&pdev->dev, "platform device with no memory ?\n");
2048 + glamofb->reg = request_mem_region(glamofb->reg->start,
2049 + RESSIZE(glamofb->reg), pdev->name);
2050 + if (!glamofb->reg) {
2051 + dev_err(&pdev->dev, "failed to request mmio region\n");
2055 + glamofb->fb_res = request_mem_region(glamofb->fb_res->start,
2056 + mach_info->fb_mem_size,
2058 + if (!glamofb->fb_res) {
2059 + dev_err(&pdev->dev, "failed to request vram region\n");
2060 + goto out_release_reg;
2063 + /* we want to remap only the registers required for this core
2065 + glamofb->base = ioremap(glamofb->reg->start, RESSIZE(glamofb->reg));
2066 + if (!glamofb->base) {
2067 + dev_err(&pdev->dev, "failed to ioremap() mmio memory\n");
2068 + goto out_release_fb;
2070 + fbinfo->fix.smem_start = (unsigned long) glamofb->fb_res->start;
2071 + fbinfo->fix.smem_len = mach_info->fb_mem_size;
2073 + fbinfo->screen_base = ioremap(glamofb->fb_res->start,
2074 + RESSIZE(glamofb->fb_res));
2075 + if (!fbinfo->screen_base) {
2076 + dev_err(&pdev->dev, "failed to ioremap() vram memory\n");
2077 + goto out_release_fb;
2080 + platform_set_drvdata(pdev, fbinfo);
2082 + glamofb->mach_info = pdev->dev.platform_data;
2084 + fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
2085 + fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
2086 + fbinfo->fix.type_aux = 0;
2087 + fbinfo->fix.xpanstep = 0;
2088 + fbinfo->fix.ypanstep = 0;
2089 + fbinfo->fix.ywrapstep = 0;
2090 + fbinfo->fix.accel = FB_ACCEL_NONE; /* FIXME */
2092 + fbinfo->var.nonstd = 0;
2093 + fbinfo->var.activate = FB_ACTIVATE_NOW;
2094 + fbinfo->var.height = mach_info->height;
2095 + fbinfo->var.width = mach_info->width;
2096 + fbinfo->var.accel_flags = 0;
2097 + fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
2099 + fbinfo->fbops = &glamofb_ops;
2100 + fbinfo->flags = FBINFO_FLAG_DEFAULT;
2101 + fbinfo->pseudo_palette = &glamofb->pseudo_pal;
2103 + fbinfo->var.xres = mach_info->xres.defval;
2104 + fbinfo->var.xres_virtual = mach_info->xres.defval;
2105 + fbinfo->var.yres = mach_info->yres.defval;
2106 + fbinfo->var.yres_virtual = mach_info->yres.defval;
2107 + fbinfo->var.bits_per_pixel = mach_info->bpp.defval;
2109 + fbinfo->var.pixclock = mach_info->pixclock;
2110 + fbinfo->var.left_margin = mach_info->left_margin;
2111 + fbinfo->var.right_margin = mach_info->right_margin;
2112 + fbinfo->var.upper_margin = mach_info->upper_margin;
2113 + fbinfo->var.lower_margin = mach_info->lower_margin;
2114 + fbinfo->var.hsync_len = mach_info->hsync_len;
2115 + fbinfo->var.vsync_len = mach_info->vsync_len;
2117 + memset(fbinfo->screen_base, 0, fbinfo->fix.smem_len);
2119 + glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
2120 + glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
2121 + glamofb_init_regs(glamofb);
2123 + rc = register_framebuffer(fbinfo);
2125 + dev_err(&pdev->dev, "failed to register framebuffer\n");
2126 + goto out_unmap_fb;
2129 + if (mach_info->spi_info) {
2130 + /* register the sibling spi device */
2131 + mach_info->spi_info->glamofb_handle = glamofb;
2132 + glamo_spi_dev.dev.parent = &pdev->dev;
2133 + glamo_spi_dev.dev.platform_data = mach_info->spi_info;
2134 + platform_device_register(&glamo_spi_dev);
2137 + printk(KERN_INFO "fb%d: %s frame buffer device\n",
2138 + fbinfo->node, fbinfo->fix.id);
2143 + iounmap(fbinfo->screen_base);
2144 + iounmap(glamofb->base);
2146 + release_mem_region(glamofb->fb_res->start, RESSIZE(glamofb->fb_res));
2148 + release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg));
2150 + framebuffer_release(fbinfo);
2154 +static int glamofb_remove(struct platform_device *pdev)
2156 + struct glamofb_handle *glamofb = platform_get_drvdata(pdev);
2158 + platform_set_drvdata(pdev, NULL);
2159 + iounmap(glamofb->base);
2160 + release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg));
2167 +static int glamofb_suspend(struct platform_device *pdev, pm_message_t state)
2172 +static int glamofb_resume(struct platform_device *pdev)
2177 +#define glamofb_suspend NULL
2178 +#define glamofb_resume NULL
2181 +static struct platform_driver glamofb_driver = {
2182 + .probe = glamofb_probe,
2183 + .remove = glamofb_remove,
2184 + .suspend = glamofb_suspend,
2185 + .resume = glamofb_resume,
2187 + .name = "glamo-fb",
2188 + .owner = THIS_MODULE,
2192 +static int __devinit glamofb_init(void)
2194 + return platform_driver_register(&glamofb_driver);
2197 +static void __exit glamofb_cleanup(void)
2199 + platform_driver_unregister(&glamofb_driver);
2202 +module_init(glamofb_init);
2203 +module_exit(glamofb_cleanup);
2205 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
2206 +MODULE_DESCRIPTION("Smedia Glamo 336x/337x framebuffer driver");
2207 +MODULE_LICENSE("GPL");
2208 diff --git a/drivers/mfd/glamo/glamo-gpio.c b/drivers/mfd/glamo/glamo-gpio.c
2209 new file mode 100644
2210 index 0000000..45d0bf9
2212 +++ b/drivers/mfd/glamo/glamo-gpio.c
2215 +#include <linux/kernel.h>
2216 +#include <linux/module.h>
2217 +#include <linux/spinlock.h>
2218 +#include <linux/io.h>
2220 +#include <linux/glamo-gpio.h>
2222 +#include "glamo-core.h"
2223 +#include "glamo-regs.h"
2225 +void glamo_gpio_setpin(struct glamo_core *glamo, unsigned int pin,
2226 + unsigned int value)
2228 + unsigned int reg = REG_OF_GPIO(pin);
2231 + spin_lock(&glamo->lock);
2232 + tmp = readw(glamo->base + reg);
2234 + tmp |= OUTPUT_BIT(pin);
2236 + tmp &= ~OUTPUT_BIT(pin);
2237 + writew(tmp, glamo->base + reg);
2238 + spin_unlock(&glamo->lock);
2240 +EXPORT_SYMBOL(glamo_gpio_setpin);
2242 +int glamo_gpio_getpin(struct glamo_core *glamo, unsigned int pin)
2244 + return readw(REG_OF_GPIO(pin)) & INPUT_BIT(pin) ? 1 : 0;
2246 +EXPORT_SYMBOL(glamo_gpio_getpin);
2248 +void glamo_gpio_cfgpin(struct glamo_core *glamo, unsigned int pinfunc)
2250 + unsigned int reg = REG_OF_GPIO(pinfunc);
2253 + spin_lock(&glamo->lock);
2254 + tmp = readw(glamo->base + reg);
2256 + if ((pinfunc & 0x00f0) == GLAMO_GPIO_F_FUNC) {
2257 + /* pin is a function pin: clear gpio bit */
2258 + tmp &= ~FUNC_BIT(pinfunc);
2260 + /* pin is gpio: set gpio bit */
2261 + tmp |= FUNC_BIT(pinfunc);
2263 + if (pinfunc & GLAMO_GPIO_F_IN) {
2264 + /* gpio input: set bit to disable output mode */
2265 + tmp |= GPIO_OUT_BIT(pinfunc);
2266 + } else if (pinfunc & GLAMO_GPIO_F_OUT) {
2267 + /* gpio output: clear bit to enable output mode */
2268 + tmp &= ~GPIO_OUT_BIT(pinfunc);
2271 + writew(tmp, glamo->base + reg);
2272 + spin_unlock(&glamo->lock);
2274 +EXPORT_SYMBOL(glamo_gpio_cfgpin);
2276 diff --git a/drivers/mfd/glamo/glamo-lcm-spi.c b/drivers/mfd/glamo/glamo-lcm-spi.c
2277 new file mode 100644
2278 index 0000000..92cabe4
2280 +++ b/drivers/mfd/glamo/glamo-lcm-spi.c
2283 + * Copyright (C) 2007 OpenMoko, Inc.
2284 + * Author: Harald Welte <laforge@openmoko.org>
2286 + * Smedia Glamo GPIO based SPI driver
2288 + * This program is free software; you can redistribute it and/or modify
2289 + * it under the terms of the GNU General Public License version 2 as
2290 + * published by the Free Software Foundation.
2292 + * This driver currently only implements a minimum subset of the hardware
2293 + * features, esp. those features that are required to drive the jbt6k74
2294 + * LCM controller asic in the TD028TTEC1 LCM.
2300 +#include <linux/kernel.h>
2301 +#include <linux/init.h>
2302 +#include <linux/delay.h>
2303 +#include <linux/device.h>
2304 +#include <linux/spinlock.h>
2305 +#include <linux/workqueue.h>
2306 +#include <linux/platform_device.h>
2308 +#include <linux/spi/spi.h>
2309 +#include <linux/spi/spi_bitbang.h>
2310 +#include <linux/spi/glamo.h>
2312 +#include <linux/glamofb.h>
2314 +#include <asm/hardware.h>
2316 +#include "glamo-core.h"
2317 +#include "glamo-regs.h"
2320 + struct spi_bitbang bitbang;
2321 + struct spi_master *master;
2322 + struct glamo_spi_info *info;
2323 + struct device *dev;
2326 +static inline struct glamo_spi *to_gs(struct spi_device *spi)
2328 + return spi->controller_data;
2331 +static int glamo_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
2333 + struct glamo_spi *gs = to_gs(spi);
2336 + bpw = t ? t->bits_per_word : spi->bits_per_word;
2338 + if (bpw != 9 && bpw != 8) {
2339 + dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
2346 +static void glamo_spi_chipsel(struct spi_device *spi, int value)
2349 + struct glamo_spi *gs = to_gs(spi);
2351 + dev_dbg(&spi->dev, "chipsel %d: spi=%p, gs=%p, info=%p, handle=%p\n",
2352 + value, spi, gs, gs->info, gs->info->glamofb_handle);
2354 + glamofb_cmd_mode(gs->info->glamofb_handle, value);
2358 +static int glamo_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
2360 + struct glamo_spi *gs = to_gs(spi);
2361 + const u_int16_t *ui16 = (const u_int16_t *) t->tx_buf;
2362 + u_int16_t nine_bits;
2365 + dev_dbg(&spi->dev, "txrx: tx %p, rx %p, bpw %d, len %d\n",
2366 + t->tx_buf, t->rx_buf, t->bits_per_word, t->len);
2368 + if (spi->bits_per_word == 9)
2369 + nine_bits = (1 << 9);
2373 + if (t->len > 3 * sizeof(u_int16_t)) {
2374 + dev_err(&spi->dev, "this driver doesn't support "
2375 + "%u sized xfers\n", t->len);
2379 + for (i = 0; i < t->len/sizeof(u_int16_t); i++) {
2380 + /* actually transfer the data */
2382 + glamofb_cmd_write(gs->info->glamofb_handle,
2383 + GLAMO_LCD_CMD_TYPE_SERIAL | nine_bits |
2384 + (1 << 10) | (1 << 11) | (ui16[i] & 0x1ff));
2386 + /* FIXME: fire ?!? */
2387 + if (i == 0 && (ui16[i] & 0x1ff) == 0x29) {
2388 + dev_dbg(&spi->dev, "leaving command mode\n");
2389 + glamofb_cmd_mode(gs->info->glamofb_handle, 0);
2396 +static int glamo_spi_setup(struct spi_device *spi)
2400 + if (!spi->bits_per_word)
2401 + spi->bits_per_word = 9;
2403 + /* FIXME: hardware can do this */
2404 + if (spi->mode & SPI_LSB_FIRST)
2407 + ret = glamo_spi_setupxfer(spi, NULL);
2409 + dev_err(&spi->dev, "setupxfer returned %d\n", ret);
2413 + dev_dbg(&spi->dev, "%s: mode %d, %u bpw\n",
2414 + __FUNCTION__, spi->mode, spi->bits_per_word);
2419 +static int glamo_spi_probe(struct platform_device *pdev)
2421 + struct spi_master *master;
2422 + struct glamo_spi *sp;
2426 + master = spi_alloc_master(&pdev->dev, sizeof(struct glamo_spi));
2427 + if (master == NULL) {
2428 + dev_err(&pdev->dev, "failed to allocate spi master\n");
2433 + sp = spi_master_get_devdata(master);
2434 + memset(sp, 0, sizeof(struct glamo_spi));
2436 + sp->master = spi_master_get(master);
2437 + sp->info = pdev->dev.platform_data;
2439 + dev_err(&pdev->dev, "can't operate without platform data\n");
2443 + dev_dbg(&pdev->dev, "sp->info(pdata) = %p\n", sp->info);
2445 + sp->dev = &pdev->dev;
2447 + platform_set_drvdata(pdev, sp);
2449 + sp->bitbang.master = sp->master;
2450 + sp->bitbang.setup_transfer = glamo_spi_setupxfer;
2451 + sp->bitbang.chipselect = glamo_spi_chipsel;
2452 + sp->bitbang.txrx_bufs = glamo_spi_txrx;
2453 + sp->bitbang.master->setup = glamo_spi_setup;
2455 + ret = spi_bitbang_start(&sp->bitbang);
2457 + goto err_no_bitbang;
2459 + /* register the chips to go with the board */
2461 + glamofb_cmd_mode(sp->info->glamofb_handle, 1);
2463 + for (i = 0; i < sp->info->board_size; i++) {
2464 + dev_info(&pdev->dev, "registering %p: %s\n",
2465 + &sp->info->board_info[i],
2466 + sp->info->board_info[i].modalias);
2468 + sp->info->board_info[i].controller_data = sp;
2469 + spi_new_device(master, sp->info->board_info + i);
2475 + platform_set_drvdata(pdev, NULL);
2477 + spi_master_put(sp->bitbang.master);
2483 +static int glamo_spi_remove(struct platform_device *pdev)
2485 + struct glamo_spi *sp = platform_get_drvdata(pdev);
2487 + spi_bitbang_stop(&sp->bitbang);
2488 + spi_master_put(sp->bitbang.master);
2493 +#define glamo_spi_suspend NULL
2494 +#define glamo_spi_resume NULL
2496 +static struct platform_driver glamo_spi_drv = {
2497 + .probe = glamo_spi_probe,
2498 + .remove = glamo_spi_remove,
2499 + .suspend = glamo_spi_suspend,
2500 + .resume = glamo_spi_resume,
2502 + .name = "glamo-lcm-spi",
2503 + .owner = THIS_MODULE,
2507 +static int __init glamo_spi_init(void)
2509 + return platform_driver_register(&glamo_spi_drv);
2512 +static void __exit glamo_spi_exit(void)
2514 + platform_driver_unregister(&glamo_spi_drv);
2517 +module_init(glamo_spi_init);
2518 +module_exit(glamo_spi_exit);
2520 +MODULE_DESCRIPTION("Smedia Glamo 336x/337x LCM serial command SPI Driver");
2521 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>")
2522 +MODULE_LICENSE("GPL");
2523 diff --git a/drivers/mfd/glamo/glamo-regs.h b/drivers/mfd/glamo/glamo-regs.h
2524 new file mode 100644
2525 index 0000000..151cd66
2527 +++ b/drivers/mfd/glamo/glamo-regs.h
2529 +#ifndef _GLAMO_REGS_H
2530 +#define _GLAMO_REGS_H
2532 +/* Smedia Glamo 336x/337x driver
2534 + * (C) 2007 by OpenMoko, Inc.
2535 + * Author: Harald Welte <laforge@openmoko.org>
2536 + * All rights reserved.
2538 + * This program is free software; you can redistribute it and/or
2539 + * modify it under the terms of the GNU General Public License as
2540 + * published by the Free Software Foundation; either version 2 of
2541 + * the License, or (at your option) any later version.
2543 + * This program is distributed in the hope that it will be useful,
2544 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2545 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2546 + * GNU General Public License for more details.
2548 + * You should have received a copy of the GNU General Public License
2549 + * along with this program; if not, write to the Free Software
2550 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
2551 + * MA 02111-1307 USA
2554 +enum glamo_regster_offsets {
2555 + GLAMO_REGOFS_GENERIC = 0x0000,
2556 + GLAMO_REGOFS_HOSTBUS = 0x0200,
2557 + GLAMO_REGOFS_MEMORY = 0x0300,
2558 + GLAMO_REGOFS_VIDCAP = 0x0400,
2559 + GLAMO_REGOFS_ISP = 0x0500,
2560 + GLAMO_REGOFS_JPEG = 0x0800,
2561 + GLAMO_REGOFS_MPEG = 0x0c00,
2562 + GLAMO_REGOFS_LCD = 0x1100,
2563 + GLAMO_REGOFS_MMC = 0x1400,
2564 + GLAMO_REGOFS_MPROC0 = 0x1500,
2565 + GLAMO_REGOFS_MPROC1 = 0x1580,
2566 + GLAMO_REGOFS_CMDQUEUE = 0x1600,
2567 + GLAMO_REGOFS_RISC = 0x1680,
2568 + GLAMO_REGOFS_2D = 0x1700,
2569 + GLAMO_REGOFS_3D = 0x1b00,
2570 + GLAMO_REGOFS_END = 0x2400,
2574 +enum glamo_register_generic {
2575 + GLAMO_REG_GCONF1 = 0x0000,
2576 + GLAMO_REG_GCONF2 = 0x0002,
2577 +#define GLAMO_REG_DEVICE_ID GLAMO_REG_GCONF2
2578 + GLAMO_REG_GCONF3 = 0x0004,
2579 +#define GLAMO_REG_REVISION_ID GLAMO_REG_GCONF3
2580 + GLAMO_REG_IRQ_GEN1 = 0x0006,
2581 +#define GLAMO_REG_IRQ_ENABLE GLAMO_REG_IRQ_GEN1
2582 + GLAMO_REG_IRQ_GEN2 = 0x0008,
2583 +#define GLAMO_REG_IRQ_SET GLAMO_REG_IRQ_GEN2
2584 + GLAMO_REG_IRQ_GEN3 = 0x000a,
2585 +#define GLAMO_REG_IRQ_CLEAR GLAMO_REG_IRQ_GEN3
2586 + GLAMO_REG_IRQ_GEN4 = 0x000c,
2587 +#define GLAMO_REG_IRQ_STATUS GLAMO_REG_IRQ_GEN4
2588 + GLAMO_REG_CLOCK_HOST = 0x0010,
2589 + GLAMO_REG_CLOCK_MEMORY = 0x0012,
2590 + GLAMO_REG_CLOCK_LCD = 0x0014,
2591 + GLAMO_REG_CLOCK_MMC = 0x0016,
2592 + GLAMO_REG_CLOCK_ISP = 0x0018,
2593 + GLAMO_REG_CLOCK_JPEG = 0x001a,
2594 + GLAMO_REG_CLOCK_3D = 0x001c,
2595 + GLAMO_REG_CLOCK_2D = 0x001e,
2596 + GLAMO_REG_CLOCK_RISC1 = 0x0020, /* 3365 only? */
2597 + GLAMO_REG_CLOCK_RISC2 = 0x0022, /* 3365 only? */
2598 + GLAMO_REG_CLOCK_MPEG = 0x0024,
2599 + GLAMO_REG_CLOCK_MPROC = 0x0026,
2601 + GLAMO_REG_CLOCK_GEN5_1 = 0x0030,
2602 + GLAMO_REG_CLOCK_GEN5_2 = 0x0032,
2603 + GLAMO_REG_CLOCK_GEN6 = 0x0034,
2604 + GLAMO_REG_CLOCK_GEN7 = 0x0036,
2605 + GLAMO_REG_CLOCK_GEN8 = 0x0038,
2606 + GLAMO_REG_CLOCK_GEN9 = 0x003a,
2607 + GLAMO_REG_CLOCK_GEN10 = 0x003c,
2608 + GLAMO_REG_CLOCK_GEN11 = 0x003e,
2609 + GLAMO_REG_PLL_GEN1 = 0x0040,
2610 + GLAMO_REG_PLL_GEN2 = 0x0042,
2611 + GLAMO_REG_PLL_GEN3 = 0x0044,
2612 + GLAMO_REG_PLL_GEN4 = 0x0046,
2613 + GLAMO_REG_PLL_GEN5 = 0x0048,
2614 + GLAMO_REG_GPIO_GEN1 = 0x0050,
2615 + GLAMO_REG_GPIO_GEN2 = 0x0052,
2616 + GLAMO_REG_GPIO_GEN3 = 0x0054,
2617 + GLAMO_REG_GPIO_GEN4 = 0x0056,
2618 + GLAMO_REG_GPIO_GEN5 = 0x0058,
2619 + GLAMO_REG_GPIO_GEN6 = 0x005a,
2620 + GLAMO_REG_GPIO_GEN7 = 0x005c,
2621 + GLAMO_REG_GPIO_GEN8 = 0x005e,
2622 + GLAMO_REG_GPIO_GEN9 = 0x0060,
2623 + GLAMO_REG_GPIO_GEN10 = 0x0062,
2624 + GLAMO_REG_DFT_GEN1 = 0x0070,
2625 + GLAMO_REG_DFT_GEN2 = 0x0072,
2626 + GLAMO_REG_DFT_GEN3 = 0x0074,
2627 + GLAMO_REG_DFT_GEN4 = 0x0076,
2629 + GLAMO_REG_DFT_GEN5 = 0x01e0,
2630 + GLAMO_REG_DFT_GEN6 = 0x01f0,
2633 +#define GLAMO_REG_HOSTBUS(x) (GLAMO_REGOFS_HOSTBUS-2+(x*2))
2635 +#define REG_MEM(x) (GLAMO_REGOFS_MEMORY+(x))
2636 +#define GLAMO_REG_MEM_TIMING(x) (GLAMO_REG_MEM_TIMING1-2+(x*2))
2638 +enum glamo_register_mem {
2639 + GLAMO_REG_MEM_TYPE = REG_MEM(0x00),
2640 + GLAMO_REG_MEM_GEN = REG_MEM(0x02),
2641 + GLAMO_REG_MEM_TIMING1 = REG_MEM(0x04),
2642 + GLAMO_REG_MEM_TIMING2 = REG_MEM(0x06),
2643 + GLAMO_REG_MEM_TIMING3 = REG_MEM(0x08),
2644 + GLAMO_REG_MEM_TIMING4 = REG_MEM(0x0a),
2645 + GLAMO_REG_MEM_TIMING5 = REG_MEM(0x0c),
2646 + GLAMO_REG_MEM_TIMING6 = REG_MEM(0x0e),
2647 + GLAMO_REG_MEM_TIMING7 = REG_MEM(0x10),
2648 + GLAMO_REG_MEM_TIMING8 = REG_MEM(0x12),
2649 + GLAMO_REG_MEM_TIMING9 = REG_MEM(0x14),
2650 + GLAMO_REG_MEM_TIMING10 = REG_MEM(0x16),
2651 + GLAMO_REG_MEM_TIMING11 = REG_MEM(0x18),
2652 + GLAMO_REG_MEM_POWER1 = REG_MEM(0x1a),
2653 + GLAMO_REG_MEM_POWER2 = REG_MEM(0x1c),
2654 + GLAMO_REG_MEM_LCD_BUF1 = REG_MEM(0x1e),
2655 + GLAMO_REG_MEM_LCD_BUF2 = REG_MEM(0x20),
2656 + GLAMO_REG_MEM_LCD_BUF3 = REG_MEM(0x22),
2657 + GLAMO_REG_MEM_LCD_BUF4 = REG_MEM(0x24),
2658 + GLAMO_REG_MEM_BIST1 = REG_MEM(0x26),
2659 + GLAMO_REG_MEM_BIST2 = REG_MEM(0x28),
2660 + GLAMO_REG_MEM_BIST3 = REG_MEM(0x2a),
2661 + GLAMO_REG_MEM_BIST4 = REG_MEM(0x2c),
2662 + GLAMO_REG_MEM_BIST5 = REG_MEM(0x2e),
2663 + GLAMO_REG_MEM_MAH1 = REG_MEM(0x30),
2664 + GLAMO_REG_MEM_MAH2 = REG_MEM(0x32),
2665 + GLAMO_REG_MEM_DRAM1 = REG_MEM(0x34),
2666 + GLAMO_REG_MEM_DRAM2 = REG_MEM(0x36),
2667 + GLAMO_REG_MEM_CRC = REG_MEM(0x38),
2670 +#define GLAMO_MEM_TYPE_MASK 0x03
2672 +enum glamo_reg_mem_dram1 {
2673 + GLAMO_MEM_DRAM1_EN_SDRAM_CLK = (1 << 11),
2674 + GLAMO_MEM_DRAM1_SELF_REFRESH = (1 << 12),
2677 +enum glamo_reg_mem_dram2 {
2678 + GLAMO_MEM_DRAM2_DEEP_PWRDOWN = (1 << 12),
2682 + GLAMO_IRQ_HOSTBUS = 0x0001,
2683 + GLAMO_IRQ_JPEG = 0x0002,
2684 + GLAMO_IRQ_MPEG = 0x0004,
2685 + GLAMO_IRQ_MPROC1 = 0x0008,
2686 + GLAMO_IRQ_MPROC0 = 0x0010,
2687 + GLAMO_IRQ_CMDQUEUE = 0x0020,
2688 + GLAMO_IRQ_2D = 0x0040,
2689 + GLAMO_IRQ_MMC = 0x0080,
2690 + GLAMO_IRQ_RISC = 0x0100,
2693 +enum glamo_reg_clock_host {
2694 + GLAMO_CLOCK_HOST_DG_BCLK = 0x0001,
2695 + GLAMO_CLOCK_HOST_DG_M0CLK = 0x0004,
2696 + GLAMO_CLOCK_HOST_RESET = 0x1000,
2699 +enum glamo_reg_clock_mem {
2700 + GLAMO_CLOCK_MEM_DG_M1CLK = 0x0001,
2701 + GLAMO_CLOCK_MEM_EN_M1CLK = 0x0002,
2702 + GLAMO_CLOCK_MEM_DG_MOCACLK = 0x0004,
2703 + GLAMO_CLOCK_MEM_EN_MOCACLK = 0x0008,
2704 + GLAMO_CLOCK_MEM_RESET = 0x1000,
2705 + GLAMO_CLOCK_MOCA_RESET = 0x2000,
2708 +enum glamo_reg_clock_lcd {
2709 + GLAMO_CLOCK_LCD_DG_DCLK = 0x0001,
2710 + GLAMO_CLOCK_LCD_EN_DCLK = 0x0002,
2711 + GLAMO_CLOCK_LCD_DG_DMCLK = 0x0004,
2712 + GLAMO_CLOCK_LCD_EN_DMCLK = 0x0008,
2714 + GLAMO_CLOCK_LCD_EN_DHCLK = 0x0020,
2715 + GLAMO_CLOCK_LCD_DG_M5CLK = 0x0040,
2716 + GLAMO_CLOCK_LCD_EN_M5CLK = 0x0080,
2717 + GLAMO_CLOCK_LCD_RESET = 0x1000,
2720 +enum glamo_reg_clock_mmc {
2721 + GLAMO_CLOCK_MMC_DG_TCLK = 0x0001,
2722 + GLAMO_CLOCK_MMC_EN_TCLK = 0x0002,
2723 + GLAMO_CLOCK_MMC_DG_M9CLK = 0x0004,
2724 + GLAMO_CLOCK_MMC_EN_M9CLK = 0x0008,
2725 + GLAMO_CLOCK_MMC_RESET = 0x1000,
2728 +enum glamo_reg_clock_isp {
2729 + GLAMO_CLOCK_ISP_DG_I1CLK = 0x0001,
2730 + GLAMO_CLOCK_ISP_EN_I1CLK = 0x0002,
2731 + GLAMO_CLOCK_ISP_DG_CCLK = 0x0004,
2732 + GLAMO_CLOCK_ISP_EN_CCLK = 0x0008,
2734 + GLAMO_CLOCK_ISP_EN_SCLK = 0x0020,
2735 + GLAMO_CLOCK_ISP_DG_M2CLK = 0x0040,
2736 + GLAMO_CLOCK_ISP_EN_M2CLK = 0x0080,
2737 + GLAMO_CLOCK_ISP_DG_M15CLK = 0x0100,
2738 + GLAMO_CLOCK_ISP_EN_M15CLK = 0x0200,
2739 + GLAMO_CLOCK_ISP1_RESET = 0x1000,
2740 + GLAMO_CLOCK_ISP2_RESET = 0x2000,
2743 +enum glamo_reg_clock_jpeg {
2744 + GLAMO_CLOCK_JPEG_DG_JCLK = 0x0001,
2745 + GLAMO_CLOCK_JPEG_EN_JCLK = 0x0002,
2746 + GLAMO_CLOCK_JPEG_DG_M3CLK = 0x0004,
2747 + GLAMO_CLOCK_JPEG_EN_M3CLK = 0x0008,
2748 + GLAMO_CLOCK_JPEG_RESET = 0x1000,
2751 +enum glamo_reg_clock_2d {
2752 + GLAMO_CLOCK_2D_DG_GCLK = 0x0001,
2753 + GLAMO_CLOCK_2D_EN_GCLK = 0x0002,
2754 + GLAMO_CLOCK_2D_DG_M7CLK = 0x0004,
2755 + GLAMO_CLOCK_2D_EN_M7CLK = 0x0008,
2756 + GLAMO_CLOCK_2D_DG_M6CLK = 0x0010,
2757 + GLAMO_CLOCK_2D_EN_M6CLK = 0x0020,
2758 + GLAMO_CLOCK_2D_RESET = 0x1000,
2759 + GLAMO_CLOCK_2D_CQ_RESET = 0x2000,
2762 +enum glamo_reg_clock_3d {
2763 + GLAMO_CLOCK_3D_DG_ECLK = 0x0001,
2764 + GLAMO_CLOCK_3D_EN_ECLK = 0x0002,
2765 + GLAMO_CLOCK_3D_DG_RCLK = 0x0004,
2766 + GLAMO_CLOCK_3D_EN_RCLK = 0x0008,
2767 + GLAMO_CLOCK_3D_DG_M8CLK = 0x0010,
2768 + GLAMO_CLOCK_3D_EN_M8CLK = 0x0020,
2769 + GLAMO_CLOCK_3D_BACK_RESET = 0x1000,
2770 + GLAMO_CLOCK_3D_FRONT_RESET = 0x2000,
2773 +enum glamo_reg_clock_mpeg {
2774 + GLAMO_CLOCK_MPEG_DG_X0CLK = 0x0001,
2775 + GLAMO_CLOCK_MPEG_EN_X0CLK = 0x0002,
2776 + GLAMO_CLOCK_MPEG_DG_X1CLK = 0x0004,
2777 + GLAMO_CLOCK_MPEG_EN_X1CLK = 0x0008,
2778 + GLAMO_CLOCK_MPEG_DG_X2CLK = 0x0010,
2779 + GLAMO_CLOCK_MPEG_EN_X2CLK = 0x0020,
2780 + GLAMO_CLOCK_MPEG_DG_X3CLK = 0x0040,
2781 + GLAMO_CLOCK_MPEG_EN_X3CLK = 0x0080,
2782 + GLAMO_CLOCK_MPEG_DG_X4CLK = 0x0100,
2783 + GLAMO_CLOCK_MPEG_EN_X4CLK = 0x0200,
2784 + GLAMO_CLOCK_MPEG_DG_X6CLK = 0x0400,
2785 + GLAMO_CLOCK_MPEG_EN_X6CLK = 0x0800,
2786 + GLAMO_CLOCK_MPEG_ENC_RESET = 0x1000,
2787 + GLAMO_CLOCK_MPEG_DEC_RESET = 0x2000,
2790 +enum glamo_reg_clock51 {
2791 + GLAMO_CLOCK_GEN51_EN_DIV_MCLK = 0x0001,
2792 + GLAMO_CLOCK_GEN51_EN_DIV_SCLK = 0x0002,
2793 + GLAMO_CLOCK_GEN51_EN_DIV_JCLK = 0x0004,
2794 + GLAMO_CLOCK_GEN51_EN_DIV_DCLK = 0x0008,
2795 + GLAMO_CLOCK_GEN51_EN_DIV_DMCLK = 0x0010,
2796 + GLAMO_CLOCK_GEN51_EN_DIV_DHCLK = 0x0020,
2797 + GLAMO_CLOCK_GEN51_EN_DIV_GCLK = 0x0040,
2798 + GLAMO_CLOCK_GEN51_EN_DIV_TCLK = 0x0080,
2799 + /* FIXME: higher bits */
2802 +enum glamo_reg_hostbus2 {
2803 + GLAMO_HOSTBUS2_MMIO_EN_ISP = 0x0001,
2804 + GLAMO_HOSTBUS2_MMIO_EN_JPEG = 0x0002,
2805 + GLAMO_HOSTBUS2_MMIO_EN_MPEG = 0x0004,
2806 + GLAMO_HOSTBUS2_MMIO_EN_LCD = 0x0008,
2807 + GLAMO_HOSTBUS2_MMIO_EN_MMC = 0x0010,
2808 + GLAMO_HOSTBUS2_MMIO_EN_MICROP0 = 0x0020,
2809 + GLAMO_HOSTBUS2_MMIO_EN_MICROP1 = 0x0040,
2810 + GLAMO_HOSTBUS2_MMIO_EN_CQ = 0x0080,
2811 + GLAMO_HOSTBUS2_MMIO_EN_RISC = 0x0100,
2812 + GLAMO_HOSTBUS2_MMIO_EN_2D = 0x0200,
2813 + GLAMO_HOSTBUS2_MMIO_EN_3D = 0x0400,
2816 +/* LCD Controller */
2818 +#define REG_LCD(x) (x)
2819 +enum glamo_reg_lcd {
2820 + GLAMO_REG_LCD_MODE1 = REG_LCD(0x00),
2821 + GLAMO_REG_LCD_MODE2 = REG_LCD(0x02),
2822 + GLAMO_REG_LCD_MODE3 = REG_LCD(0x04),
2823 + GLAMO_REG_LCD_WIDTH = REG_LCD(0x06),
2824 + GLAMO_REG_LCD_HEIGHT = REG_LCD(0x08),
2825 + GLAMO_REG_LCD_POLARITY = REG_LCD(0x0a),
2826 + GLAMO_REG_LCD_A_BASE1 = REG_LCD(0x0c),
2827 + GLAMO_REG_LCD_A_BASE2 = REG_LCD(0x0e),
2828 + GLAMO_REG_LCD_B_BASE1 = REG_LCD(0x10),
2829 + GLAMO_REG_LCD_B_BASE2 = REG_LCD(0x12),
2830 + GLAMO_REG_LCD_C_BASE1 = REG_LCD(0x14),
2831 + GLAMO_REG_LCD_C_BASE2 = REG_LCD(0x16),
2832 + GLAMO_REG_LCD_PITCH = REG_LCD(0x18),
2834 + GLAMO_REG_LCD_HORIZ_TOTAL = REG_LCD(0x1c),
2836 + GLAMO_REG_LCD_HORIZ_RETR_START = REG_LCD(0x20),
2838 + GLAMO_REG_LCD_HORIZ_RETR_END = REG_LCD(0x24),
2840 + GLAMO_REG_LCD_HORIZ_DISP_START = REG_LCD(0x28),
2842 + GLAMO_REG_LCD_HORIZ_DISP_END = REG_LCD(0x2c),
2844 + GLAMO_REG_LCD_VERT_TOTAL = REG_LCD(0x30),
2846 + GLAMO_REG_LCD_VERT_RETR_START = REG_LCD(0x34),
2848 + GLAMO_REG_LCD_VERT_RETR_END = REG_LCD(0x38),
2850 + GLAMO_REG_LCD_VERT_DISP_START = REG_LCD(0x3c),
2852 + GLAMO_REG_LCD_VERT_DISP_END = REG_LCD(0x40),
2854 + GLAMO_REG_LCD_POL = REG_LCD(0x44),
2855 + GLAMO_REG_LCD_DATA_START = REG_LCD(0x46),
2856 + GLAMO_REG_LCD_FRATE_CONTRO = REG_LCD(0x48),
2857 + GLAMO_REG_LCD_DATA_CMD_HDR = REG_LCD(0x4a),
2858 + GLAMO_REG_LCD_SP_START = REG_LCD(0x4c),
2859 + GLAMO_REG_LCD_SP_END = REG_LCD(0x4e),
2860 + GLAMO_REG_LCD_CURSOR_BASE1 = REG_LCD(0x50),
2861 + GLAMO_REG_LCD_CURSOR_BASE2 = REG_LCD(0x52),
2862 + GLAMO_REG_LCD_CURSOR_PITCH = REG_LCD(0x54),
2863 + GLAMO_REG_LCD_CURSOR_X_SIZE = REG_LCD(0x56),
2864 + GLAMO_REG_LCD_CURSOR_Y_SIZE = REG_LCD(0x58),
2865 + GLAMO_REG_LCD_CURSOR_X_POS = REG_LCD(0x5a),
2866 + GLAMO_REG_LCD_CURSOR_Y_POS = REG_LCD(0x5c),
2867 + GLAMO_REG_LCD_CURSOR_PRESET = REG_LCD(0x5e),
2868 + GLAMO_REG_LCD_CURSOR_FG_COLOR = REG_LCD(0x60),
2870 + GLAMO_REG_LCD_CURSOR_BG_COLOR = REG_LCD(0x64),
2872 + GLAMO_REG_LCD_CURSOR_DST_COLOR = REG_LCD(0x68),
2874 + GLAMO_REG_LCD_STATUS1 = REG_LCD(0x80),
2875 + GLAMO_REG_LCD_STATUS2 = REG_LCD(0x82),
2876 + GLAMO_REG_LCD_STATUS3 = REG_LCD(0x84),
2877 + GLAMO_REG_LCD_STATUS4 = REG_LCD(0x86),
2879 + GLAMO_REG_LCD_COMMAND1 = REG_LCD(0xa0),
2880 + GLAMO_REG_LCD_COMMAND2 = REG_LCD(0xa2),
2882 + GLAMO_REG_LCD_WFORM_DELAY1 = REG_LCD(0xb0),
2883 + GLAMO_REG_LCD_WFORM_DELAY2 = REG_LCD(0xb2),
2885 + GLAMO_REG_LCD_GAMMA_CORR = REG_LCD(0x100),
2887 + GLAMO_REG_LCD_GAMMA_R_ENTRY01 = REG_LCD(0x110),
2888 + GLAMO_REG_LCD_GAMMA_R_ENTRY23 = REG_LCD(0x112),
2889 + GLAMO_REG_LCD_GAMMA_R_ENTRY45 = REG_LCD(0x114),
2890 + GLAMO_REG_LCD_GAMMA_R_ENTRY67 = REG_LCD(0x116),
2891 + GLAMO_REG_LCD_GAMMA_R_ENTRY8 = REG_LCD(0x118),
2893 + GLAMO_REG_LCD_GAMMA_G_ENTRY01 = REG_LCD(0x130),
2894 + GLAMO_REG_LCD_GAMMA_G_ENTRY23 = REG_LCD(0x132),
2895 + GLAMO_REG_LCD_GAMMA_G_ENTRY45 = REG_LCD(0x134),
2896 + GLAMO_REG_LCD_GAMMA_G_ENTRY67 = REG_LCD(0x136),
2897 + GLAMO_REG_LCD_GAMMA_G_ENTRY8 = REG_LCD(0x138),
2899 + GLAMO_REG_LCD_GAMMA_B_ENTRY01 = REG_LCD(0x150),
2900 + GLAMO_REG_LCD_GAMMA_B_ENTRY23 = REG_LCD(0x152),
2901 + GLAMO_REG_LCD_GAMMA_B_ENTRY45 = REG_LCD(0x154),
2902 + GLAMO_REG_LCD_GAMMA_B_ENTRY67 = REG_LCD(0x156),
2903 + GLAMO_REG_LCD_GAMMA_B_ENTRY8 = REG_LCD(0x158),
2905 + GLAMO_REG_LCD_SRAM_DRIVING1 = REG_LCD(0x160),
2906 + GLAMO_REG_LCD_SRAM_DRIVING2 = REG_LCD(0x162),
2907 + GLAMO_REG_LCD_SRAM_DRIVING3 = REG_LCD(0x164),
2910 +enum glamo_reg_lcd_mode1 {
2911 + GLAMO_LCD_MODE1_PWRSAVE = 0x0001,
2912 + GLAMO_LCD_MODE1_PARTIAL_PRT = 0x0002,
2913 + GLAMO_LCD_MODE1_HWFLIP = 0x0004,
2914 + GLAMO_LCD_MODE1_LCD2 = 0x0008,
2916 + GLAMO_LCD_MODE1_PARTIAL_MODE = 0x0020,
2917 + GLAMO_LCD_MODE1_CURSOR_DSTCOLOR = 0x0040,
2918 + GLAMO_LCD_MODE1_PARTIAL_ENABLE = 0x0080,
2919 + GLAMO_LCD_MODE1_TVCLK_IN_ENABLE = 0x0100,
2920 + GLAMO_LCD_MODE1_HSYNC_HIGH_ACT = 0x0200,
2921 + GLAMO_LCD_MODE1_VSYNC_HIGH_ACT = 0x0400,
2922 + GLAMO_LCD_MODE1_HSYNC_FLIP = 0x0800,
2923 + GLAMO_LCD_MODE1_GAMMA_COR_EN = 0x1000,
2924 + GLAMO_LCD_MODE1_DITHER_EN = 0x2000,
2925 + GLAMO_LCD_MODE1_CURSOR_EN = 0x4000,
2926 + GLAMO_LCD_MODE1_ROTATE_EN = 0x8000,
2929 +enum glamo_reg_lcd_mode2 {
2930 + GLAMO_LCD_MODE2_CRC_CHECK_EN = 0x0001,
2931 + GLAMO_LCD_MODE2_DCMD_PER_LINE = 0x0002,
2932 + GLAMO_LCD_MODE2_NOUSE_BDEF = 0x0004,
2933 + GLAMO_LCD_MODE2_OUT_POS_MODE = 0x0008,
2934 + GLAMO_LCD_MODE2_FRATE_CTRL_EN = 0x0010,
2935 + GLAMO_LCD_MODE2_SINGLE_BUFFER = 0x0020,
2936 + GLAMO_LCD_MODE2_SER_LSB_TO_MSB = 0x0040,
2940 +enum glamo_reg_lcd_mode3 {
2941 + /* LCD color source data format */
2942 + GLAMO_LCD_SRC_RGB565 = 0x0000,
2943 + GLAMO_LCD_SRC_ARGB1555 = 0x4000,
2944 + GLAMO_LCD_SRC_ARGB4444 = 0x8000,
2945 + /* interface type */
2946 + GLAMO_LCD_MODE3_LCD = 0x1000,
2947 + GLAMO_LCD_MODE3_RGB = 0x0800,
2948 + GLAMO_LCD_MODE3_CPU = 0x0000,
2950 + GLAMO_LCD_MODE3_RGB332 = 0x0000,
2951 + GLAMO_LCD_MODE3_RGB444 = 0x0100,
2952 + GLAMO_LCD_MODE3_RGB565 = 0x0200,
2953 + GLAMO_LCD_MODE3_RGB666 = 0x0300,
2955 + GLAMO_LCD_MODE3_6BITS = 0x0000,
2956 + GLAMO_LCD_MODE3_8BITS = 0x0010,
2957 + GLAMO_LCD_MODE3_9BITS = 0x0020,
2958 + GLAMO_LCD_MODE3_16BITS = 0x0030,
2959 + GLAMO_LCD_MODE3_18BITS = 0x0040,
2962 +enum glamo_lcd_rot_mode {
2963 + GLAMO_LCD_ROT_MODE_0 = 0x0000,
2964 + GLAMO_LCD_ROT_MODE_180 = 0x2000,
2965 + GLAMO_LCD_ROT_MODE_MIRROR = 0x4000,
2966 + GLAMO_LCD_ROT_MODE_FLIP = 0x6000,
2967 + GLAMO_LCD_ROT_MODE_90 = 0x8000,
2968 + GLAMO_LCD_ROT_MODE_270 = 0xa000,
2970 +#define GLAMO_LCD_ROT_MODE_MASK 0xe000
2972 +enum glamo_lcd_cmd_type {
2973 + GLAMO_LCD_CMD_TYPE_DISP = 0x0000,
2974 + GLAMO_LCD_CMD_TYPE_PARALLEL = 0x4000,
2975 + GLAMO_LCD_CMD_TYPE_SERIAL = 0x8000,
2976 + GLAMO_LCD_CMD_TYPE_SERIAL_DIRECT= 0xc000,
2978 +#define GLAMO_LCD_CMD_TYPE_MASK 0xc000
2980 +enum glamo_lcd_cmds {
2981 + GLAMO_LCD_CMD_DATA_DISP_FIRE = 0x00,
2982 + GLAMO_LCD_CMD_DATA_DISP_SYNC = 0x01, /* RGB only */
2983 + /* switch to command mode, no display */
2984 + GLAMO_LCD_CMD_DATA_FIRE_NO_DISP = 0x02,
2985 + /* display until VSYNC, switch to command */
2986 + GLAMO_LCD_CMD_DATA_FIRE_VSYNC = 0x11,
2987 + /* display until HSYNC, switch to command */
2988 + GLAMO_LCD_CMD_DATA_FIRE_HSYNC = 0x12,
2989 + /* display until VSYNC, 1 black frame, VSYNC, switch to command */
2990 + GLAMO_LCD_CMD_DATA_FIRE_VSYNC_B = 0x13,
2991 + /* don't care about display and switch to command */
2992 + GLAMO_LCD_CMD_DATA_FIRE_FREE = 0x14, /* RGB only */
2993 + /* don't care about display, keep data display but disable data,
2994 + * and switch to command */
2995 + GLAMO_LCD_CMD_DATA_FIRE_FREE_D = 0x15, /* RGB only */
2998 +enum glamo_core_revisions {
2999 + GLAMO_CORE_REV_A0 = 0x0000,
3000 + GLAMO_CORE_REV_A1 = 0x0001,
3001 + GLAMO_CORE_REV_A2 = 0x0002,
3002 + GLAMO_CORE_REV_A3 = 0x0003,
3005 +#endif /* _GLAMO_REGS_H */
3006 diff --git a/drivers/mfd/glamo/glamo-spi-gpio.c b/drivers/mfd/glamo/glamo-spi-gpio.c
3007 new file mode 100644
3008 index 0000000..73926bd
3010 +++ b/drivers/mfd/glamo/glamo-spi-gpio.c
3013 + * Copyright (C) 2007 OpenMoko, Inc.
3014 + * Author: Harald Welte <laforge@openmoko.org>
3016 + * Smedia Glamo GPIO based SPI driver
3018 + * This program is free software; you can redistribute it and/or modify
3019 + * it under the terms of the GNU General Public License version 2 as
3020 + * published by the Free Software Foundation.
3022 + * This driver currently only implements a minimum subset of the hardware
3023 + * features, esp. those features that are required to drive the jbt6k74
3024 + * LCM controller asic in the TD028TTEC1 LCM.
3030 +#include <linux/kernel.h>
3031 +#include <linux/init.h>
3032 +#include <linux/delay.h>
3033 +#include <linux/device.h>
3034 +#include <linux/spinlock.h>
3035 +#include <linux/workqueue.h>
3036 +#include <linux/platform_device.h>
3038 +#include <linux/spi/spi.h>
3039 +#include <linux/spi/spi_bitbang.h>
3040 +#include <linux/spi/glamo.h>
3042 +#include <linux/glamofb.h>
3044 +#include <asm/hardware.h>
3046 +#include "glamo-core.h"
3047 +#include "glamo-regs.h"
3049 +struct glamo_spigpio {
3050 + struct spi_bitbang bitbang;
3051 + struct spi_master *master;
3052 + struct glamo_spigpio_info *info;
3053 + struct glamo_core *glamo;
3056 +static inline struct glamo_spigpio *to_sg(struct spi_device *spi)
3058 + return spi->controller_data;
3061 +static inline void setsck(struct spi_device *dev, int on)
3063 + struct glamo_spigpio *sg = to_sg(dev);
3064 + glamo_gpio_setpin(sg->glamo, sg->info->pin_clk, on ? 1 : 0);
3067 +static inline void setmosi(struct spi_device *dev, int on)
3069 + struct glamo_spigpio *sg = to_sg(dev);
3070 + glamo_gpio_setpin(sg->glamo, sg->info->pin_mosi, on ? 1 : 0);
3073 +static inline u32 getmiso(struct spi_device *dev)
3075 + struct glamo_spigpio *sg = to_sg(dev);
3076 + if (sg->info->pin_miso)
3077 + return glamo_gpio_getpin(sg->glamo, sg->info->pin_miso) ? 1 : 0;
3082 +#define spidelay(x) ndelay(x)
3084 +#define EXPAND_BITBANG_TXRX
3085 +#include <linux/spi/spi_bitbang.h>
3087 +static u32 glamo_spigpio_txrx_mode0(struct spi_device *spi,
3088 + unsigned nsecs, u32 word, u8 bits)
3090 + return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
3093 +static u32 glamo_spigpio_txrx_mode1(struct spi_device *spi,
3094 + unsigned nsecs, u32 word, u8 bits)
3096 + return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
3099 +static u32 glamo_spigpio_txrx_mode2(struct spi_device *spi,
3100 + unsigned nsecs, u32 word, u8 bits)
3102 + return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
3105 +static u32 glamo_spigpio_txrx_mode3(struct spi_device *spi,
3106 + unsigned nsecs, u32 word, u8 bits)
3108 + return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
3113 +static int glamo_spigpio_setupxfer(struct spi_device *spi,
3114 + struct spi_transfer *t)
3116 + struct glamo_spi *gs = to_sg(spi);
3119 + bpw = t ? t->bits_per_word : spi->bits_per_word;
3121 + if (bpw != 9 && bpw != 8) {
3122 + dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
3130 +static void glamo_spigpio_chipsel(struct spi_device *spi, int value)
3132 + struct glamo_spigpio *gs = to_sg(spi);
3134 + dev_dbg(&spi->dev, "chipsel %d: spi=%p, gs=%p, info=%p, handle=%p\n",
3135 + value, spi, gs, gs->info, gs->info->glamo);
3137 + glamo_gpio_setpin(gs->glamo, gs->info->pin_cs, value ? 0 : 1);
3141 +static int glamo_spigpio_probe(struct platform_device *pdev)
3143 + struct spi_master *master;
3144 + struct glamo_spigpio *sp;
3148 + master = spi_alloc_master(&pdev->dev, sizeof(struct glamo_spigpio));
3149 + if (master == NULL) {
3150 + dev_err(&pdev->dev, "failed to allocate spi master\n");
3155 + sp = spi_master_get_devdata(master);
3156 + platform_set_drvdata(pdev, sp);
3157 + sp->info = pdev->dev.platform_data;
3159 + dev_err(&pdev->dev, "can't operate without platform data\n");
3164 + master->num_chipselect = 1;
3165 + master->bus_num = 2; /* FIXME: use dynamic number */
3167 + sp->master = spi_master_get(master);
3168 + sp->glamo = sp->info->glamo;
3170 + sp->bitbang.master = sp->master;
3171 + sp->bitbang.chipselect = glamo_spigpio_chipsel;
3172 + sp->bitbang.txrx_word[SPI_MODE_0] = glamo_spigpio_txrx_mode0;
3173 + sp->bitbang.txrx_word[SPI_MODE_1] = glamo_spigpio_txrx_mode1;
3174 + sp->bitbang.txrx_word[SPI_MODE_2] = glamo_spigpio_txrx_mode2;
3175 + sp->bitbang.txrx_word[SPI_MODE_3] = glamo_spigpio_txrx_mode3;
3177 + /* set state of spi pins */
3178 + glamo_gpio_setpin(sp->glamo, sp->info->pin_clk, 0);
3179 + glamo_gpio_setpin(sp->glamo, sp->info->pin_mosi, 0);
3180 + glamo_gpio_setpin(sp->glamo, sp->info->pin_cs, 1);
3182 + glamo_gpio_cfgpin(sp->glamo, sp->info->pin_clk);
3183 + glamo_gpio_cfgpin(sp->glamo, sp->info->pin_mosi);
3184 + glamo_gpio_cfgpin(sp->glamo, sp->info->pin_cs);
3185 + if (sp->info->pin_miso)
3186 + glamo_gpio_cfgpin(sp->glamo, sp->info->pin_miso);
3188 + /* bring the LCM panel out of reset if it isn't already */
3190 + glamo_gpio_setpin(sp->glamo, GLAMO_GPIO4, 1);
3191 + glamo_gpio_cfgpin(sp->glamo, GLAMO_GPIO4_OUTPUT);
3195 + sp->dev = &pdev->dev;
3197 + sp->bitbang.setup_transfer = glamo_spi_setupxfer;
3198 + sp->bitbang.txrx_bufs = glamo_spi_txrx;
3199 + sp->bitbang.master->setup = glamo_spi_setup;
3202 + ret = spi_bitbang_start(&sp->bitbang);
3204 + goto err_no_bitbang;
3206 + /* register the chips to go with the board */
3208 + for (i = 0; i < sp->info->board_size; i++) {
3209 + dev_info(&pdev->dev, "registering %p: %s\n",
3210 + &sp->info->board_info[i],
3211 + sp->info->board_info[i].modalias);
3213 + sp->info->board_info[i].controller_data = sp;
3214 + spi_new_device(master, sp->info->board_info + i);
3220 + platform_set_drvdata(pdev, NULL);
3222 + spi_master_put(sp->bitbang.master);
3228 +static int glamo_spigpio_remove(struct platform_device *pdev)
3230 + struct glamo_spigpio *sp = platform_get_drvdata(pdev);
3232 + spi_bitbang_stop(&sp->bitbang);
3233 + spi_master_put(sp->bitbang.master);
3238 +#define glamo_spigpio_suspend NULL
3239 +#define glamo_spigpio_resume NULL
3241 +static struct platform_driver glamo_spi_drv = {
3242 + .probe = glamo_spigpio_probe,
3243 + .remove = glamo_spigpio_remove,
3244 + .suspend = glamo_spigpio_suspend,
3245 + .resume = glamo_spigpio_resume,
3247 + .name = "glamo-spi-gpio",
3248 + .owner = THIS_MODULE,
3252 +static int __init glamo_spi_init(void)
3254 + return platform_driver_register(&glamo_spi_drv);
3257 +static void __exit glamo_spi_exit(void)
3259 + platform_driver_unregister(&glamo_spi_drv);
3262 +module_init(glamo_spi_init);
3263 +module_exit(glamo_spi_exit);
3265 +MODULE_DESCRIPTION("Smedia Glamo 336x/337x LCM serial command SPI Driver");
3266 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>")
3267 +MODULE_LICENSE("GPL");
3268 diff --git a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h
3269 index 996f654..9522cd1 100644
3270 --- a/include/asm-arm/arch-s3c2410/irqs.h
3271 +++ b/include/asm-arm/arch-s3c2410/irqs.h
3272 @@ -155,9 +155,37 @@
3273 #define IRQ_S3C2443_AC97 S3C2410_IRQSUB(28)
3275 #ifdef CONFIG_CPU_S3C2443
3276 -#define NR_IRQS (IRQ_S3C2443_AC97+1)
3277 +#define _NR_IRQS (IRQ_S3C2443_AC97+1)
3279 -#define NR_IRQS (IRQ_S3C2440_AC97+1)
3280 +#define _NR_IRQS (IRQ_S3C2440_AC97+1)
3284 + * The next 16 interrupts are for board specific purposes. Since
3285 + * the kernel can only run on one machine at a time, we can re-use
3286 + * these. If you need more, increase IRQ_BOARD_END, but keep it
3287 + * within sensible limits.
3289 +#define IRQ_BOARD_START _NR_IRQS
3290 +#define IRQ_BOARD_END (_NR_IRQS + 10)
3292 +#if defined(CONFIG_MACH_NEO1973_GTA02)
3293 +#define NR_IRQS (IRQ_BOARD_END)
3295 +#define NR_IRQS (IRQ_BOARD_START)
3298 +/* Neo1973 GTA02 interrupts */
3299 +#define NEO1973_GTA02_IRQ(x) (IRQ_BOARD_START + (x))
3300 +#define IRQ_GLAMO(x) NEO1973_GTA02_IRQ(x)
3301 +#define IRQ_GLAMO_HOSTBUS IRQ_GLAMO(0)
3302 +#define IRQ_GLAMO_JPEG IRQ_GLAMO(1)
3303 +#define IRQ_GLAMO_MPEG IRQ_GLAMO(2)
3304 +#define IRQ_GLAMO_MPROC1 IRQ_GLAMO(3)
3305 +#define IRQ_GLAMO_MPROC0 IRQ_GLAMO(4)
3306 +#define IRQ_GLAMO_CMDQUEUE IRQ_GLAMO(5)
3307 +#define IRQ_GLAMO_2D IRQ_GLAMO(6)
3308 +#define IRQ_GLAMO_MMC IRQ_GLAMO(7)
3309 +#define IRQ_GLAMO_RISC IRQ_GLAMO(8)
3311 #endif /* __ASM_ARCH_IRQ_H */
3312 diff --git a/include/linux/glamo-gpio.h b/include/linux/glamo-gpio.h
3313 new file mode 100644
3314 index 0000000..d00f7e9
3316 +++ b/include/linux/glamo-gpio.h
3318 +#ifndef __GLAMO_GPIO_H
3319 +#define __GLAMO_GPIO_H
3323 +#define GLAMO_GPIO_BANKA 0x0000
3324 +#define GLAMO_GPIO_BANKB 0x1000
3325 +#define GLAMO_GPIO_BANKC 0x2000
3326 +#define GLAMO_GPIO_BANKD 0x3000
3328 +#define GLAMO_GPIONO(bank, pin) ((bank & 0xf000) | ((pin & 0xf) << 8))
3330 +#define GLAMO_GPIO_F_IN 0x0010
3331 +#define GLAMO_GPIO_F_OUT 0x0020
3332 +#define GLAMO_GPIO_F_FUNC 0x0030
3334 +#define GLAMO_GPIO0 GLAMO_GPIONO(GLAMO_GPIO_BANKA, 0)
3335 +#define GLAMO_GPIO0_INPUT (GLAMO_GPIO0 | GLAMO_GPIO_F_IN)
3336 +#define GLAMO_GPIO0_OUTPUT (GLAMO_GPIO0 | GLAMO_GPIO_F_OUT)
3337 +#define GLAMO_GPIO0_HA20 (GLAMO_GPIO0 | GLAMO_GPIO_F_FUNC)
3339 +#define GLAMO_GPIO1 GLAMO_GPIONO(GLAMO_GPIO_BANKA, 1)
3340 +#define GLAMO_GPIO1_INPUT (GLAMO_GPIO1 | GLAMO_GPIO_F_IN)
3341 +#define GLAMO_GPIO1_OUTPUT (GLAMO_GPIO1 | GLAMO_GPIO_F_OUT)
3342 +#define GLAMO_GPIO1_HA21 (GLAMO_GPIO1 | GLAMO_GPIO_F_FUNC)
3344 +#define GLAMO_GPIO2 GLAMO_GPIONO(GLAMO_GPIO_BANKA, 2)
3345 +#define GLAMO_GPIO2_INPUT (GLAMO_GPIO2 | GLAMO_GPIO_F_IN)
3346 +#define GLAMO_GPIO2_OUTPUT (GLAMO_GPIO2 | GLAMO_GPIO_F_OUT)
3347 +#define GLAMO_GPIO2_HA22 (GLAMO_GPIO2 | GLAMO_GPIO_F_FUNC)
3349 +#define GLAMO_GPIO3 GLAMO_GPIONO(GLAMO_GPIO_BANKA, 3)
3350 +#define GLAMO_GPIO3_INPUT (GLAMO_GPIO3 | GLAMO_GPIO_F_IN)
3351 +#define GLAMO_GPIO3_OUTPUT (GLAMO_GPIO3 | GLAMO_GPIO_F_OUT)
3352 +#define GLAMO_GPIO3_HA23 (GLAMO_GPIO3 | GLAMO_GPIO_F_FUNC)
3354 +#define GLAMO_GPIO4 GLAMO_GPIONO(GLAMO_GPIO_BANKB, 0)
3355 +#define GLAMO_GPIO4_INPUT (GLAMO_GPIO4 | GLAMO_GPIO_F_IN)
3356 +#define GLAMO_GPIO4_OUTPUT (GLAMO_GPIO4 | GLAMO_GPIO_F_OUT)
3357 +#define GLAMO_GPIO4_nLCS0 (GLAMO_GPIO4 | GLAMO_GPIO_F_FUNC)
3359 +#define GLAMO_GPIO5 GLAMO_GPIONO(GLAMO_GPIO_BANKB, 1)
3360 +#define GLAMO_GPIO5_INPUT (GLAMO_GPIO5 | GLAMO_GPIO_F_IN)
3361 +#define GLAMO_GPIO5_OUTPUT (GLAMO_GPIO5 | GLAMO_GPIO_F_OUT)
3362 +#define GLAMO_GPIO5_nLCS1 (GLAMO_GPIO5 | GLAMO_GPIO_F_FUNC)
3364 +#define GLAMO_GPIO6 GLAMO_GPIONO(GLAMO_GPIO_BANKB, 2)
3365 +#define GLAMO_GPIO6_INPUT (GLAMO_GPIO6 | GLAMO_GPIO_F_IN)
3366 +#define GLAMO_GPIO6_OUTPUT (GLAMO_GPIO6 | GLAMO_GPIO_F_OUT)
3367 +#define GLAMO_GPIO6_LDCLK (GLAMO_GPIO6 | GLAMO_GPIO_F_FUNC)
3369 +#define GLAMO_GPIO7 GLAMO_GPIONO(GLAMO_GPIO_BANKB, 3)
3370 +#define GLAMO_GPIO7_INPUT (GLAMO_GPIO7 | GLAMO_GPIO_F_IN)
3371 +#define GLAMO_GPIO7_OUTPUT (GLAMO_GPIO7 | GLAMO_GPIO_F_OUT)
3372 +#define GLAMO_GPIO7_nLDE (GLAMO_GPIO7 | GLAMO_GPIO_F_FUNC)
3374 +#define GLAMO_GPIO8 GLAMO_GPIONO(GLAMO_GPIO_BANKC, 0)
3375 +#define GLAMO_GPIO8_INPUT (GLAMO_GPIO8 | GLAMO_GPIO_F_IN)
3376 +#define GLAMO_GPIO8_OUTPUT (GLAMO_GPIO8 | GLAMO_GPIO_F_OUT)
3377 +#define GLAMO_GPIO8_LD16 (GLAMO_GPIO8 | GLAMO_GPIO_F_FUNC)
3379 +#define GLAMO_GPIO9 GLAMO_GPIONO(GLAMO_GPIO_BANKC, 1)
3380 +#define GLAMO_GPIO9_INPUT (GLAMO_GPIO9 | GLAMO_GPIO_F_IN)
3381 +#define GLAMO_GPIO9_OUTPUT (GLAMO_GPIO9 | GLAMO_GPIO_F_OUT)
3382 +#define GLAMO_GPIO9_LD17 (GLAMO_GPIO9 | GLAMO_GPIO_F_FUNC)
3384 +#define GLAMO_GPIO10 GLAMO_GPIONO(GLAMO_GPIO_BANKC, 2)
3385 +#define GLAMO_GPIO10_INPUT (GLAMO_GPIO10 | GLAMO_GPIO_F_IN)
3386 +#define GLAMO_GPIO10_OUTPUT (GLAMO_GPIO10 | GLAMO_GPIO_F_OUT)
3387 +#define GLAMO_GPIO10_LSCK (GLAMO_GPIO10 | GLAMO_GPIO_F_FUNC)
3389 +#define GLAMO_GPIO11 GLAMO_GPIONO(GLAMO_GPIO_BANKC, 3)
3390 +#define GLAMO_GPIO11_INPUT (GLAMO_GPIO11 | GLAMO_GPIO_F_IN)
3391 +#define GLAMO_GPIO11_OUTPUT (GLAMO_GPIO11 | GLAMO_GPIO_F_OUT)
3392 +#define GLAMO_GPIO11_LSDA (GLAMO_GPIO11 | GLAMO_GPIO_F_FUNC)
3394 +#define GLAMO_GPIO12 GLAMO_GPIONO(GLAMO_GPIO_BANKD, 0)
3395 +#define GLAMO_GPIO12_INPUT (GLAMO_GPIO12 | GLAMO_GPIO_F_IN)
3396 +#define GLAMO_GPIO12_OUTPUT (GLAMO_GPIO12 | GLAMO_GPIO_F_OUT)
3397 +#define GLAMO_GPIO12_LSA0 (GLAMO_GPIO12 | GLAMO_GPIO_F_FUNC)
3400 +#define REG_OF_GPIO(gpio) (((gpio & 0xf000) >> 12)*2 \
3401 + + GLAMO_REG_GPIO_GEN1)
3402 +#define NUM_OF_GPIO(gpio) ((gpio & 0x0f00) >> 8)
3403 +#define GPIO_OUT_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 0))
3404 +#define OUTPUT_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 4))
3405 +#define INPUT_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 8))
3406 +#define FUNC_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 12))
3408 +void glamo_gpio_setpin(struct glamo_core *glamo, unsigned int pin,
3409 + unsigned int value);
3411 +int glamo_gpio_getpin(struct glamo_core *glamo, unsigned int pin);
3413 +void glamo_gpio_cfgpin(struct glamo_core *glamo, unsigned int pinfunc);
3416 +#endif /* _GLAMO_GPIO */
3417 diff --git a/include/linux/glamofb.h b/include/linux/glamofb.h
3418 new file mode 100644
3419 index 0000000..24742a2
3421 +++ b/include/linux/glamofb.h
3423 +#ifndef _LINUX_GLAMOFB_H
3424 +#define _LINUX_GLAMOFB_H
3426 +#include <linux/spi/glamo.h>
3428 +struct glamofb_val {
3429 + unsigned int defval;
3436 +struct glamofb_platform_data {
3437 + int width, height;
3439 + int left_margin, right_margin;
3440 + int upper_margin, lower_margin;
3441 + int hsync_len, vsync_len;
3444 + struct glamofb_val xres;
3445 + struct glamofb_val yres;
3446 + struct glamofb_val bpp;
3448 + struct glamo_spi_info *spi_info;
3449 + struct glamo_spigpio_info *spigpio_info;
3450 + struct glamo_core *glamo;
3452 + /* glamo mmc platform specific info */
3453 + void (*glamo_set_mci_power)(unsigned char power_mode,
3454 + unsigned short vdd);
3455 + int (*glamo_irq_is_wired)(void);
3458 +void glamofb_cmd_mode(struct glamofb_handle *gfb, int on);
3459 +int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val);
3462 diff --git a/include/linux/spi/glamo.h b/include/linux/spi/glamo.h
3463 new file mode 100644
3464 index 0000000..86419ea
3466 +++ b/include/linux/spi/glamo.h
3468 +#ifndef __GLAMO_SPI_H
3469 +#define __GLAMO_SPI_H
3471 +#include <linux/glamo-gpio.h>
3473 +struct spi_board_info;
3474 +struct glamofb_handle;
3477 +struct glamo_spi_info {
3478 + unsigned long board_size;
3479 + struct spi_board_info *board_info;
3480 + struct glamofb_handle *glamofb_handle;
3483 +struct glamo_spigpio_info {
3484 + unsigned int pin_clk;
3485 + unsigned int pin_mosi;
3486 + unsigned int pin_miso;
3487 + unsigned int pin_cs;
3489 + unsigned int board_size;
3490 + struct spi_board_info *board_info;
3491 + struct glamo_core *glamo;