* [RFC 2.6.27 2/2] mach-pxa: add AM300 platform driver
@ 2008-12-21 10:59 Jaya Kumar
2008-12-23 8:47 ` Eric Miao
0 siblings, 1 reply; 5+ messages in thread
From: Jaya Kumar @ 2008-12-21 10:59 UTC (permalink / raw)
Cc: linux-fbdev-devel, Geert Uytterhoeven, Eric Miao, Jaya Kumar,
linux-arm-kernel
This patch adds support for the AM300 platform driver.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Eric Miao <eric.miao@marvell.com>
Cc: Krzysztof Helt <krzysztof.h1@poczta.fm>
Cc: linux-fbdev-devel@lists.sourceforge.net
Cc: linux-arm-kernel@lists.arm.linux.org.uk
---
arch/arm/mach-pxa/Kconfig | 3 +
arch/arm/mach-pxa/Makefile | 1 +
arch/arm/mach-pxa/am300epd.c | 335 ++++++++++++++++++++++++++++++
arch/arm/mach-pxa/gumstix.c | 6 +
arch/arm/mach-pxa/include/mach/gumstix.h | 1 +
5 files changed, 346 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-pxa/am300epd.c
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 94e3adb..768618b 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -40,6 +40,9 @@ choice
config GUMSTIX_AM200EPD
bool "Enable AM200EPD board support"
+config GUMSTIX_AM300EPD
+ bool "Enable AM300EPD board support"
+
endchoice
config MACH_INTELMOTE2
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 7b28bb5..764f111 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_CPU_PXA930) += pxa930.o
# Specific board support
obj-$(CONFIG_ARCH_GUMSTIX) += gumstix.o
obj-$(CONFIG_GUMSTIX_AM200EPD) += am200epd.o
+obj-$(CONFIG_GUMSTIX_AM300EPD) += am300epd.o
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
diff --git a/arch/arm/mach-pxa/am300epd.c b/arch/arm/mach-pxa/am300epd.c
new file mode 100644
index 0000000..e060ef8
--- /dev/null
+++ b/arch/arm/mach-pxa/am300epd.c
@@ -0,0 +1,335 @@
+/*
+ * am300epd.c -- Platform device for AM300 EPD kit
+ *
+ * Copyright (C) 2008, Jaya Kumar
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * This work was made possible by help and equipment support from E-Ink
+ * Corporation. http://support.eink.com/community
+ *
+ * This driver is written to be used with the Broadsheet display controller.
+ * on the AM300 EPD prototype kit/development kit with an E-Ink 800x600
+ * Vizplex EPD on a Gumstix board using the Broadsheet interface board.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+
+#include <mach/gumstix.h>
+#include <mach/mfp-pxa25x.h>
+#include <mach/pxafb.h>
+
+#include "generic.h"
+
+#include <video/broadsheetfb.h>
+
+static unsigned int panel_type = 6;
+static struct platform_device *am300_device;
+static struct broadsheet_board am300_board;
+
+static unsigned long am300_pin_config[] __initdata = {
+ GPIO16_GPIO,
+ GPIO17_GPIO,
+ GPIO32_GPIO,
+ GPIO48_GPIO,
+ GPIO49_GPIO,
+ GPIO51_GPIO,
+ GPIO74_GPIO,
+ GPIO75_GPIO,
+ GPIO76_GPIO,
+ GPIO77_GPIO,
+
+ /* this is the 16-bit hdb bus 58-73 */
+ GPIO58_GPIO,
+ GPIO59_GPIO,
+ GPIO60_GPIO,
+ GPIO61_GPIO,
+
+ GPIO62_GPIO,
+ GPIO63_GPIO,
+ GPIO64_GPIO,
+ GPIO65_GPIO,
+
+ GPIO66_GPIO,
+ GPIO67_GPIO,
+ GPIO68_GPIO,
+ GPIO69_GPIO,
+
+ GPIO70_GPIO,
+ GPIO71_GPIO,
+ GPIO72_GPIO,
+ GPIO73_GPIO,
+};
+
+/* register offsets for gpio control */
+#define PWR_GPIO_PIN 16
+#define CFG_GPIO_PIN 17
+#define RDY_GPIO_PIN 32
+#define DC_GPIO_PIN 48
+#define RST_GPIO_PIN 49
+#define LED_GPIO_PIN 51
+#define RD_GPIO_PIN 74
+#define WR_GPIO_PIN 75
+#define CS_GPIO_PIN 76
+#define IRQ_GPIO_PIN 77
+
+/* hdb bus */
+#define DB0_GPIO_PIN 58
+#define DB15_GPIO_PIN 73
+
+static int gpios[] = { PWR_GPIO_PIN, CFG_GPIO_PIN, RDY_GPIO_PIN, DC_GPIO_PIN,
+ RST_GPIO_PIN, RD_GPIO_PIN, WR_GPIO_PIN, CS_GPIO_PIN,
+ IRQ_GPIO_PIN, LED_GPIO_PIN };
+static char *gpio_names[] = { "PWR", "CFG", "RDY", "DC", "RST", "RD", "WR",
+ "CS", "IRQ", "LED" };
+
+static int am300_wait_for_rdy(struct broadsheetfb_par *par)
+{
+ unsigned long flags;
+ DEFINE_WAIT(wait);
+
+ spin_lock_irqsave(par->lock, flags);
+ while (!gpio_get_value(RDY_GPIO_PIN)) {
+ prepare_to_wait(&par->waitq, &wait, TASK_INTERRUPTIBLE);
+
+ spin_unlock_irqrestore(par->lock, flags);
+ schedule();
+ spin_lock_irqsave(par->lock, flags);
+ }
+ finish_wait(&par->waitq, &wait);
+
+ spin_unlock_irqrestore(par->lock, flags);
+ return 0;
+
+}
+
+static int am300_init_gpio_regs(struct broadsheetfb_par *par)
+{
+ int i;
+ int err;
+ char dbname[8];
+
+ for (i = 0; i < ARRAY_SIZE(gpios); i++) {
+ err = gpio_request(gpios[i], gpio_names[i]);
+ if (err) {
+ dev_err(&am300_device->dev, "failed requesting "
+ "gpio %s, err=%d\n", gpio_names[i], err);
+ goto err_req_gpio;
+ }
+ }
+
+ /* we also need to take care of the hdb bus */
+ for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++) {
+ sprintf(dbname, "DB%d", i);
+ err = gpio_request(i, dbname);
+ if (err) {
+ dev_err(&am300_device->dev, "failed requesting "
+ "gpio %d, err=%d\n", i, err);
+ while (i >= DB0_GPIO_PIN)
+ gpio_free(i--);
+ i = ARRAY_SIZE(gpios) - 1;
+ goto err_req_gpio;
+ }
+ }
+
+ /* setup the outputs and init values */
+ gpio_direction_output(PWR_GPIO_PIN, 0);
+ gpio_direction_output(CFG_GPIO_PIN, 1);
+ gpio_direction_output(DC_GPIO_PIN, 0);
+ gpio_direction_output(RD_GPIO_PIN, 1);
+ gpio_direction_output(WR_GPIO_PIN, 1);
+ gpio_direction_output(CS_GPIO_PIN, 1);
+ gpio_direction_output(RST_GPIO_PIN, 0);
+
+ /* setup the inputs */
+ gpio_direction_input(RDY_GPIO_PIN);
+ gpio_direction_input(IRQ_GPIO_PIN);
+
+ /* start the hdb bus as an input */
+ for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
+ gpio_direction_output(i, 0);
+
+ /* go into command mode */
+ gpio_set_value(CFG_GPIO_PIN, 1);
+ gpio_set_value(RST_GPIO_PIN, 0);
+ mdelay(10);
+ gpio_set_value(RST_GPIO_PIN, 1);
+ mdelay(10);
+ am300_wait_for_rdy(par);
+
+ return 0;
+
+err_req_gpio:
+ while (i > 0)
+ gpio_free(gpios[i--]);
+
+ return err;
+}
+
+static int am300_init_board(struct broadsheetfb_par *par)
+{
+ int ret;
+
+ /* setup pins */
+ ret = am300_init_gpio_regs(par);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void am300_cleanup(struct broadsheetfb_par *par)
+{
+ int i;
+
+ free_irq(IRQ_GPIO(RDY_GPIO_PIN), par);
+
+ for (i = 0; i < ARRAY_SIZE(gpios); i++)
+ gpio_free(gpios[i]);
+
+ for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
+ gpio_free(i);
+
+}
+
+static u16 am300_get_hdb(struct broadsheetfb_par *par)
+{
+ u16 res = 0;
+ int i;
+
+ for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
+ res |= (gpio_get_value(DB0_GPIO_PIN + i)) ? (1 << i) : 0;
+
+ return res;
+}
+
+static void am300_set_hdb(struct broadsheetfb_par *par, u16 data)
+{
+ int i;
+
+ for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
+ gpio_set_value(DB0_GPIO_PIN + i, (data >> i) & 0x01);
+}
+
+
+static void am300_set_ctl(struct broadsheetfb_par *par, unsigned char bit,
+ u8 state)
+{
+ switch (bit) {
+ case BS_CS:
+ gpio_set_value(CS_GPIO_PIN, state);
+ break;
+ case BS_DC:
+ gpio_set_value(DC_GPIO_PIN, state);
+ break;
+ case BS_WR:
+ gpio_set_value(WR_GPIO_PIN, state);
+ break;
+ }
+}
+
+static int am300_get_panel_type(void)
+{
+ return panel_type;
+}
+
+static irqreturn_t am300_handle_irq(int irq, void *dev_id)
+{
+ unsigned long flags;
+ struct broadsheetfb_par *par = dev_id;
+
+ spin_lock_irqsave(par->lock, flags);
+ wake_up_interruptible(&par->waitq);
+ spin_unlock_irqrestore(par->lock, flags);
+ return IRQ_HANDLED;
+}
+
+static int am300_setup_irq(struct fb_info *info)
+{
+ int ret;
+ struct broadsheetfb_par *par = info->par;
+
+ spin_lock_init(&par->lock);
+
+ ret = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am300_handle_irq,
+ IRQF_DISABLED|IRQF_TRIGGER_RISING,
+ "AM300", par);
+ if (ret)
+ dev_err(&am300_device->dev, "request_irq failed: %d\n", ret);
+
+ return ret;
+}
+
+static int am300_wait_event(struct broadsheetfb_par *par)
+{
+ return wait_event_timeout(par->waitq, gpio_get_value(RDY_GPIO_PIN), HZ);
+}
+
+static int am300_wait_event_intr(struct broadsheetfb_par *par)
+{
+ return wait_event_interruptible_timeout(par->waitq,
+ gpio_get_value(RDY_GPIO_PIN), HZ);
+}
+
+static struct broadsheet_board am300_board = {
+ .owner = THIS_MODULE,
+ .init = am300_init_board,
+ .cleanup = am300_cleanup,
+ .set_hdb = am300_set_hdb,
+ .get_hdb = am300_get_hdb,
+ .set_ctl = am300_set_ctl,
+ .wait_for_rdy = am300_wait_for_rdy,
+ .get_panel_type = am300_get_panel_type,
+ .setup_irq = am300_setup_irq,
+ .wait_event = am300_wait_event,
+ .wait_event_intr = am300_wait_event_intr,
+};
+
+int __init am300_init(void)
+{
+ int ret;
+
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(am300_pin_config));
+
+ /* request our platform independent driver */
+ request_module("broadsheetfb");
+
+ am300_device = platform_device_alloc("broadsheetfb", -1);
+ if (!am300_device)
+ return -ENOMEM;
+
+ /* the am300_board that will be seen by broadsheetfb is a copy */
+ platform_device_add_data(am300_device, &am300_board,
+ sizeof(am300_board));
+
+ ret = platform_device_add(am300_device);
+
+ if (ret) {
+ platform_device_put(am300_device);
+ return ret;
+ }
+
+ return 0;
+}
+
+module_param(panel_type, uint, 0);
+MODULE_PARM_DESC(panel_type, "Select the panel type: 6, 8, 97");
+
+module_init(am300_init);
+
+MODULE_DESCRIPTION("board driver for am300 epd kit");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index e296ce1..9cb4a07 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -191,6 +191,11 @@ int __attribute__((weak)) am200_init(void)
return 0;
}
+int __attribute__((weak)) am300_init(void)
+{
+ return 0;
+}
+
static void __init carrier_board_init(void)
{
/*
@@ -198,6 +203,7 @@ static void __init carrier_board_init(void)
* they cannot be detected programatically
*/
am200_init();
+ am300_init();
}
static void __init gumstix_init(void)
diff --git a/arch/arm/mach-pxa/include/mach/gumstix.h b/arch/arm/mach-pxa/include/mach/gumstix.h
index 099f54a..06abd41 100644
--- a/arch/arm/mach-pxa/include/mach/gumstix.h
+++ b/arch/arm/mach-pxa/include/mach/gumstix.h
@@ -97,4 +97,5 @@ has detected a cable insertion; driven low otherwise. */
/* for expansion boards that can't be programatically detected */
extern int am200_init(void);
+extern int am300_init(void);
--
1.5.2.3
------------------------------------------------------------------------------
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [RFC 2.6.27 2/2] mach-pxa: add AM300 platform driver
2008-12-21 10:59 [RFC 2.6.27 2/2] mach-pxa: add AM300 platform driver Jaya Kumar
@ 2008-12-23 8:47 ` Eric Miao
2008-12-23 9:24 ` Lothar Waßmann
2008-12-24 5:25 ` Jaya Kumar
0 siblings, 2 replies; 5+ messages in thread
From: Eric Miao @ 2008-12-23 8:47 UTC (permalink / raw)
To: Jaya Kumar
Cc: Eric Miao, linux-fbdev-devel, Geert Uytterhoeven,
linux-arm-kernel
On Sun, Dec 21, 2008 at 6:59 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> This patch adds support for the AM300 platform driver.
>
Patch looks good, I feel I'm nit-picking. Anyway , see my comments below:
> +/* register offsets for gpio control */
> +#define PWR_GPIO_PIN 16
> +#define CFG_GPIO_PIN 17
> +#define RDY_GPIO_PIN 32
> +#define DC_GPIO_PIN 48
> +#define RST_GPIO_PIN 49
> +#define LED_GPIO_PIN 51
> +#define RD_GPIO_PIN 74
> +#define WR_GPIO_PIN 75
> +#define CS_GPIO_PIN 76
> +#define IRQ_GPIO_PIN 77
> +
> +/* hdb bus */
> +#define DB0_GPIO_PIN 58
> +#define DB15_GPIO_PIN 73
indentation?
> +
> +static int gpios[] = { PWR_GPIO_PIN, CFG_GPIO_PIN, RDY_GPIO_PIN, DC_GPIO_PIN,
> + RST_GPIO_PIN, RD_GPIO_PIN, WR_GPIO_PIN, CS_GPIO_PIN,
> + IRQ_GPIO_PIN, LED_GPIO_PIN };
> +static char *gpio_names[] = { "PWR", "CFG", "RDY", "DC", "RST", "RD", "WR",
> + "CS", "IRQ", "LED" };
> +
> +static int am300_wait_for_rdy(struct broadsheetfb_par *par)
> +{
> + unsigned long flags;
> + DEFINE_WAIT(wait);
> +
> + spin_lock_irqsave(par->lock, flags);
> + while (!gpio_get_value(RDY_GPIO_PIN)) {
> + prepare_to_wait(&par->waitq, &wait, TASK_INTERRUPTIBLE);
> +
> + spin_unlock_irqrestore(par->lock, flags);
> + schedule();
> + spin_lock_irqsave(par->lock, flags);
> + }
> + finish_wait(&par->waitq, &wait);
> +
> + spin_unlock_irqrestore(par->lock, flags);
wait_event() might be the perfect choice for the above case, unless your
spin_lock_* is really doing something useful, which I doubt it is actually
protecting something.
> + return 0;
> +
> +}
> +
> +static int am300_init_gpio_regs(struct broadsheetfb_par *par)
> +{
> + int i;
> + int err;
> + char dbname[8];
> +
> + for (i = 0; i < ARRAY_SIZE(gpios); i++) {
> + err = gpio_request(gpios[i], gpio_names[i]);
> + if (err) {
> + dev_err(&am300_device->dev, "failed requesting "
> + "gpio %s, err=%d\n", gpio_names[i], err);
> + goto err_req_gpio;
> + }
> + }
> +
> + /* we also need to take care of the hdb bus */
> + for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++) {
> + sprintf(dbname, "DB%d", i);
> + err = gpio_request(i, dbname);
> + if (err) {
> + dev_err(&am300_device->dev, "failed requesting "
> + "gpio %d, err=%d\n", i, err);
> + while (i >= DB0_GPIO_PIN)
> + gpio_free(i--);
> + i = ARRAY_SIZE(gpios) - 1;
> + goto err_req_gpio;
> + }
> + }
> +
> + /* setup the outputs and init values */
> + gpio_direction_output(PWR_GPIO_PIN, 0);
> + gpio_direction_output(CFG_GPIO_PIN, 1);
> + gpio_direction_output(DC_GPIO_PIN, 0);
> + gpio_direction_output(RD_GPIO_PIN, 1);
> + gpio_direction_output(WR_GPIO_PIN, 1);
> + gpio_direction_output(CS_GPIO_PIN, 1);
> + gpio_direction_output(RST_GPIO_PIN, 0);
> +
> + /* setup the inputs */
> + gpio_direction_input(RDY_GPIO_PIN);
> + gpio_direction_input(IRQ_GPIO_PIN);
> +
> + /* start the hdb bus as an input */
> + for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
> + gpio_direction_output(i, 0);
> +
> + /* go into command mode */
> + gpio_set_value(CFG_GPIO_PIN, 1);
> + gpio_set_value(RST_GPIO_PIN, 0);
> + mdelay(10);
which deserves a msleep(10) if the timing is relaxed enough.
> + gpio_set_value(RST_GPIO_PIN, 1);
> + mdelay(10);
> + am300_wait_for_rdy(par);
> +
> + return 0;
> +
> +err_req_gpio:
> + while (i > 0)
> + gpio_free(gpios[i--]);
> +
> + return err;
> +}
> +
> +static int am300_init_board(struct broadsheetfb_par *par)
> +{
> + int ret;
> +
> + /* setup pins */
> + ret = am300_init_gpio_regs(par);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
which can be shortened to one statement 'return am300_init_gpio_regs(par)'
> +
------------------------------------------------------------------------------
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC 2.6.27 2/2] mach-pxa: add AM300 platform driver
2008-12-23 8:47 ` Eric Miao
@ 2008-12-23 9:24 ` Lothar Waßmann
2008-12-24 5:25 ` Jaya Kumar
1 sibling, 0 replies; 5+ messages in thread
From: Lothar Waßmann @ 2008-12-23 9:24 UTC (permalink / raw)
To: Eric Miao
Cc: Jaya Kumar, Geert Uytterhoeven, Eric Miao, Krzysztof Helt,
linux-fbdev-devel, linux-arm-kernel
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1292 bytes --]
Hi,
Eric Miao writes:
> On Sun, Dec 21, 2008 at 6:59 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> > This patch adds support for the AM300 platform driver.
> >
>
> Patch looks good, I feel I'm nit-picking. Anyway , see my comments below:
>
[...]
> > +static int am300_wait_for_rdy(struct broadsheetfb_par *par)
> > +{
> > + unsigned long flags;
> > + DEFINE_WAIT(wait);
> > +
> > + spin_lock_irqsave(par->lock, flags);
> > + while (!gpio_get_value(RDY_GPIO_PIN)) {
> > + prepare_to_wait(&par->waitq, &wait, TASK_INTERRUPTIBLE);
^^^^^^^^^^^^^
This should be TASK_UNINTERRUPTIBLE, or the case of an interrupted
wait need to be handled in some way!
> wait_event() might be the perfect choice for the above case, unless your
>
... which would also fix the above bug.
Lothar Wa���mann
--
___________________________________________________________
Ka-Ro electronics GmbH | Pascalstra���e 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch���ftsf���hrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996
www.karo-electronics.de | info@karo-electronics.de
___________________________________________________________
[-- Attachment #2: Type: text/plain, Size: 271 bytes --]
-------------------------------------------------------------------
List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ: http://www.arm.linux.org.uk/mailinglists/faq.php
Etiquette: http://www.arm.linux.org.uk/mailinglists/etiquette.php
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC 2.6.27 2/2] mach-pxa: add AM300 platform driver
2008-12-23 8:47 ` Eric Miao
2008-12-23 9:24 ` Lothar Waßmann
@ 2008-12-24 5:25 ` Jaya Kumar
1 sibling, 0 replies; 5+ messages in thread
From: Jaya Kumar @ 2008-12-24 5:25 UTC (permalink / raw)
To: Eric Miao
Cc: Eric Miao, linux-fbdev-devel, Geert Uytterhoeven,
linux-arm-kernel
On Tue, Dec 23, 2008 at 3:47 AM, Eric Miao <eric.y.miao@gmail.com> wrote:
> On Sun, Dec 21, 2008 at 6:59 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>> This patch adds support for the AM300 platform driver.
>>
>
> Patch looks good, I feel I'm nit-picking. Anyway , see my comments below:
>
>> +/* register offsets for gpio control */
>> +#define PWR_GPIO_PIN 16
>> +#define CFG_GPIO_PIN 17
>> +#define RDY_GPIO_PIN 32
>> +#define DC_GPIO_PIN 48
>> +#define RST_GPIO_PIN 49
>> +#define LED_GPIO_PIN 51
>> +#define RD_GPIO_PIN 74
>> +#define WR_GPIO_PIN 75
>> +#define CS_GPIO_PIN 76
>> +#define IRQ_GPIO_PIN 77
>> +
>> +/* hdb bus */
>> +#define DB0_GPIO_PIN 58
>> +#define DB15_GPIO_PIN 73
>
> indentation?
Ok, will fix.
>> + gpio_set_value(RST_GPIO_PIN, 0);
>> + mdelay(10);
>
> which deserves a msleep(10) if the timing is relaxed enough.
True. Will fix.
>
>> + gpio_set_value(RST_GPIO_PIN, 1);
>> + mdelay(10);
>> + am300_wait_for_rdy(par);
>> +
>> + return 0;
>> +
>> +err_req_gpio:
>> + while (i > 0)
>> + gpio_free(gpios[i--]);
>> +
>> + return err;
>> +}
>> +
>> +static int am300_init_board(struct broadsheetfb_par *par)
>> +{
>> + int ret;
>> +
>> + /* setup pins */
>> + ret = am300_init_gpio_regs(par);
>> + if (ret)
>> + return ret;
>> +
>> + return 0;
>> +}
>
> which can be shortened to one statement 'return am300_init_gpio_regs(par)'
>
Yes, sorry, there was other stuff I had been doing in that function
while trying to trim down the board init to the minimum needed for
things to work. Okay, will fix.
Thanks,
jaya
------------------------------------------------------------------------------
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC 2.6.27 2/2] mach-pxa: add AM300 platform driver
2008-12-25 12:51 [RFC 2.6.27 1/2] fbdev: add E-Ink Broadsheet controller support v2 Jaya Kumar
@ 2008-12-25 12:51 ` Jaya Kumar
0 siblings, 0 replies; 5+ messages in thread
From: Jaya Kumar @ 2008-12-25 12:51 UTC (permalink / raw)
Cc: linux-fbdev-devel, Geert Uytterhoeven, Eric Miao, Jaya Kumar,
linux-arm-kernel
This patch adds support for the AM300 platform driver.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Eric Miao <eric.miao@marvell.com>
Cc: Krzysztof Helt <krzysztof.h1@poczta.fm>
Cc: linux-fbdev-devel@lists.sourceforge.net
Cc: linux-arm-kernel@lists.arm.linux.org.uk
---
arch/arm/mach-pxa/Kconfig | 3 +
arch/arm/mach-pxa/Makefile | 1 +
arch/arm/mach-pxa/am300epd.c | 294 ++++++++++++++++++++++++++++++
arch/arm/mach-pxa/gumstix.c | 6 +
arch/arm/mach-pxa/include/mach/gumstix.h | 1 +
5 files changed, 305 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-pxa/am300epd.c
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 94e3adb..768618b 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -40,6 +40,9 @@ choice
config GUMSTIX_AM200EPD
bool "Enable AM200EPD board support"
+config GUMSTIX_AM300EPD
+ bool "Enable AM300EPD board support"
+
endchoice
config MACH_INTELMOTE2
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 7b28bb5..764f111 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_CPU_PXA930) += pxa930.o
# Specific board support
obj-$(CONFIG_ARCH_GUMSTIX) += gumstix.o
obj-$(CONFIG_GUMSTIX_AM200EPD) += am200epd.o
+obj-$(CONFIG_GUMSTIX_AM300EPD) += am300epd.o
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
diff --git a/arch/arm/mach-pxa/am300epd.c b/arch/arm/mach-pxa/am300epd.c
new file mode 100644
index 0000000..26ce52e
--- /dev/null
+++ b/arch/arm/mach-pxa/am300epd.c
@@ -0,0 +1,294 @@
+/*
+ * am300epd.c -- Platform device for AM300 EPD kit
+ *
+ * Copyright (C) 2008, Jaya Kumar
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * This work was made possible by help and equipment support from E-Ink
+ * Corporation. http://support.eink.com/community
+ *
+ * This driver is written to be used with the Broadsheet display controller.
+ * on the AM300 EPD prototype kit/development kit with an E-Ink 800x600
+ * Vizplex EPD on a Gumstix board using the Broadsheet interface board.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+
+#include <mach/gumstix.h>
+#include <mach/mfp-pxa25x.h>
+#include <mach/pxafb.h>
+
+#include "generic.h"
+
+#include <video/broadsheetfb.h>
+
+static unsigned int panel_type = 6;
+static struct platform_device *am300_device;
+static struct broadsheet_board am300_board;
+
+static unsigned long am300_pin_config[] __initdata = {
+ GPIO16_GPIO,
+ GPIO17_GPIO,
+ GPIO32_GPIO,
+ GPIO48_GPIO,
+ GPIO49_GPIO,
+ GPIO51_GPIO,
+ GPIO74_GPIO,
+ GPIO75_GPIO,
+ GPIO76_GPIO,
+ GPIO77_GPIO,
+
+ /* this is the 16-bit hdb bus 58-73 */
+ GPIO58_GPIO,
+ GPIO59_GPIO,
+ GPIO60_GPIO,
+ GPIO61_GPIO,
+
+ GPIO62_GPIO,
+ GPIO63_GPIO,
+ GPIO64_GPIO,
+ GPIO65_GPIO,
+
+ GPIO66_GPIO,
+ GPIO67_GPIO,
+ GPIO68_GPIO,
+ GPIO69_GPIO,
+
+ GPIO70_GPIO,
+ GPIO71_GPIO,
+ GPIO72_GPIO,
+ GPIO73_GPIO,
+};
+
+/* register offsets for gpio control */
+#define PWR_GPIO_PIN 16
+#define CFG_GPIO_PIN 17
+#define RDY_GPIO_PIN 32
+#define DC_GPIO_PIN 48
+#define RST_GPIO_PIN 49
+#define LED_GPIO_PIN 51
+#define RD_GPIO_PIN 74
+#define WR_GPIO_PIN 75
+#define CS_GPIO_PIN 76
+#define IRQ_GPIO_PIN 77
+
+/* hdb bus */
+#define DB0_GPIO_PIN 58
+#define DB15_GPIO_PIN 73
+
+static int gpios[] = { PWR_GPIO_PIN, CFG_GPIO_PIN, RDY_GPIO_PIN, DC_GPIO_PIN,
+ RST_GPIO_PIN, RD_GPIO_PIN, WR_GPIO_PIN, CS_GPIO_PIN,
+ IRQ_GPIO_PIN, LED_GPIO_PIN };
+static char *gpio_names[] = { "PWR", "CFG", "RDY", "DC", "RST", "RD", "WR",
+ "CS", "IRQ", "LED" };
+
+static int am300_wait_event_intr(struct broadsheetfb_par *par)
+{
+ return wait_event_interruptible_timeout(par->waitq,
+ gpio_get_value(RDY_GPIO_PIN), HZ);
+}
+
+static int am300_init_gpio_regs(struct broadsheetfb_par *par)
+{
+ int i;
+ int err;
+ char dbname[8];
+
+ for (i = 0; i < ARRAY_SIZE(gpios); i++) {
+ err = gpio_request(gpios[i], gpio_names[i]);
+ if (err) {
+ dev_err(&am300_device->dev, "failed requesting "
+ "gpio %s, err=%d\n", gpio_names[i], err);
+ goto err_req_gpio;
+ }
+ }
+
+ /* we also need to take care of the hdb bus */
+ for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++) {
+ sprintf(dbname, "DB%d", i);
+ err = gpio_request(i, dbname);
+ if (err) {
+ dev_err(&am300_device->dev, "failed requesting "
+ "gpio %d, err=%d\n", i, err);
+ while (i >= DB0_GPIO_PIN)
+ gpio_free(i--);
+ i = ARRAY_SIZE(gpios) - 1;
+ goto err_req_gpio;
+ }
+ }
+
+ /* setup the outputs and init values */
+ gpio_direction_output(PWR_GPIO_PIN, 0);
+ gpio_direction_output(CFG_GPIO_PIN, 1);
+ gpio_direction_output(DC_GPIO_PIN, 0);
+ gpio_direction_output(RD_GPIO_PIN, 1);
+ gpio_direction_output(WR_GPIO_PIN, 1);
+ gpio_direction_output(CS_GPIO_PIN, 1);
+ gpio_direction_output(RST_GPIO_PIN, 0);
+
+ /* setup the inputs */
+ gpio_direction_input(RDY_GPIO_PIN);
+ gpio_direction_input(IRQ_GPIO_PIN);
+
+ /* start the hdb bus as an input */
+ for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
+ gpio_direction_output(i, 0);
+
+ /* go into command mode */
+ gpio_set_value(CFG_GPIO_PIN, 1);
+ gpio_set_value(RST_GPIO_PIN, 0);
+ msleep(10);
+ gpio_set_value(RST_GPIO_PIN, 1);
+ msleep(10);
+ am300_wait_event_intr(par);
+
+ return 0;
+
+err_req_gpio:
+ while (i > 0)
+ gpio_free(gpios[i--]);
+
+ return err;
+}
+
+static int am300_init_board(struct broadsheetfb_par *par)
+{
+ return am300_init_gpio_regs(par);
+}
+
+static void am300_cleanup(struct broadsheetfb_par *par)
+{
+ int i;
+
+ free_irq(IRQ_GPIO(RDY_GPIO_PIN), par);
+
+ for (i = 0; i < ARRAY_SIZE(gpios); i++)
+ gpio_free(gpios[i]);
+
+ for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
+ gpio_free(i);
+
+}
+
+static u16 am300_get_hdb(struct broadsheetfb_par *par)
+{
+ u16 res = 0;
+ int i;
+
+ for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
+ res |= (gpio_get_value(DB0_GPIO_PIN + i)) ? (1 << i) : 0;
+
+ return res;
+}
+
+static void am300_set_hdb(struct broadsheetfb_par *par, u16 data)
+{
+ int i;
+
+ for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
+ gpio_set_value(DB0_GPIO_PIN + i, (data >> i) & 0x01);
+}
+
+
+static void am300_set_ctl(struct broadsheetfb_par *par, unsigned char bit,
+ u8 state)
+{
+ switch (bit) {
+ case BS_CS:
+ gpio_set_value(CS_GPIO_PIN, state);
+ break;
+ case BS_DC:
+ gpio_set_value(DC_GPIO_PIN, state);
+ break;
+ case BS_WR:
+ gpio_set_value(WR_GPIO_PIN, state);
+ break;
+ }
+}
+
+static int am300_get_panel_type(void)
+{
+ return panel_type;
+}
+
+static irqreturn_t am300_handle_irq(int irq, void *dev_id)
+{
+ struct broadsheetfb_par *par = dev_id;
+
+ wake_up_interruptible(&par->waitq);
+ return IRQ_HANDLED;
+}
+
+static int am300_setup_irq(struct fb_info *info)
+{
+ int ret;
+ struct broadsheetfb_par *par = info->par;
+
+ ret = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am300_handle_irq,
+ IRQF_DISABLED|IRQF_TRIGGER_RISING,
+ "AM300", par);
+ if (ret)
+ dev_err(&am300_device->dev, "request_irq failed: %d\n", ret);
+
+ return ret;
+}
+
+static struct broadsheet_board am300_board = {
+ .owner = THIS_MODULE,
+ .init = am300_init_board,
+ .cleanup = am300_cleanup,
+ .set_hdb = am300_set_hdb,
+ .get_hdb = am300_get_hdb,
+ .set_ctl = am300_set_ctl,
+ .wait_for_rdy = am300_wait_event_intr,
+ .get_panel_type = am300_get_panel_type,
+ .setup_irq = am300_setup_irq,
+};
+
+int __init am300_init(void)
+{
+ int ret;
+
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(am300_pin_config));
+
+ /* request our platform independent driver */
+ request_module("broadsheetfb");
+
+ am300_device = platform_device_alloc("broadsheetfb", -1);
+ if (!am300_device)
+ return -ENOMEM;
+
+ /* the am300_board that will be seen by broadsheetfb is a copy */
+ platform_device_add_data(am300_device, &am300_board,
+ sizeof(am300_board));
+
+ ret = platform_device_add(am300_device);
+
+ if (ret) {
+ platform_device_put(am300_device);
+ return ret;
+ }
+
+ return 0;
+}
+
+module_param(panel_type, uint, 0);
+MODULE_PARM_DESC(panel_type, "Select the panel type: 6, 8, 97");
+
+MODULE_DESCRIPTION("board driver for am300 epd kit");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index e296ce1..9cb4a07 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -191,6 +191,11 @@ int __attribute__((weak)) am200_init(void)
return 0;
}
+int __attribute__((weak)) am300_init(void)
+{
+ return 0;
+}
+
static void __init carrier_board_init(void)
{
/*
@@ -198,6 +203,7 @@ static void __init carrier_board_init(void)
* they cannot be detected programatically
*/
am200_init();
+ am300_init();
}
static void __init gumstix_init(void)
diff --git a/arch/arm/mach-pxa/include/mach/gumstix.h b/arch/arm/mach-pxa/include/mach/gumstix.h
index 099f54a..06abd41 100644
--- a/arch/arm/mach-pxa/include/mach/gumstix.h
+++ b/arch/arm/mach-pxa/include/mach/gumstix.h
@@ -97,4 +97,5 @@ has detected a cable insertion; driven low otherwise. */
/* for expansion boards that can't be programatically detected */
extern int am200_init(void);
+extern int am300_init(void);
--
1.5.2.3
------------------------------------------------------------------------------
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-12-25 12:51 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-21 10:59 [RFC 2.6.27 2/2] mach-pxa: add AM300 platform driver Jaya Kumar
2008-12-23 8:47 ` Eric Miao
2008-12-23 9:24 ` Lothar Waßmann
2008-12-24 5:25 ` Jaya Kumar
-- strict thread matches above, loose matches on Subject: below --
2008-12-25 12:51 [RFC 2.6.27 1/2] fbdev: add E-Ink Broadsheet controller support v2 Jaya Kumar
2008-12-25 12:51 ` [RFC 2.6.27 2/2] mach-pxa: add AM300 platform driver Jaya Kumar
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.