From b4066ae91a2443ba1b8174ebd7abede8f2a47062 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 28 Jun 2009 20:25:00 +0000 Subject: [PATCH] Fix freerunner gsm modem pm. SVN-Revision: 16609 --- .../arch/arm/mach-s3c2442/gta02-pm-gsm.c | 59 ++++++++++++++++--- .../s3c24xx/patches-2.6.30/110-serial.patch | 40 +++++++++++++ 2 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 target/linux/s3c24xx/patches-2.6.30/110-serial.patch diff --git a/target/linux/s3c24xx/files-2.6.30/arch/arm/mach-s3c2442/gta02-pm-gsm.c b/target/linux/s3c24xx/files-2.6.30/arch/arm/mach-s3c2442/gta02-pm-gsm.c index 2f1da04f5bef..afb4182bf33d 100644 --- a/target/linux/s3c24xx/files-2.6.30/arch/arm/mach-s3c2442/gta02-pm-gsm.c +++ b/target/linux/s3c24xx/files-2.6.30/arch/arm/mach-s3c2442/gta02-pm-gsm.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -31,16 +30,36 @@ #include #include #include +#include int gta_gsm_interrupts; EXPORT_SYMBOL(gta_gsm_interrupts); +extern void s3c24xx_serial_console_set_silence(int); + struct gta02pm_priv { int gpio_ndl_gsm; + struct console *con; }; static struct gta02pm_priv gta02_gsm; +static struct console *find_s3c24xx_console(void) +{ + struct console *con; + + acquire_console_sem(); + + for (con = console_drivers; con; con = con->next) { + if (!strcmp(con->name, "ttySAC")) + break; + } + + release_console_sem(); + + return con; +} + static ssize_t gsm_read(struct device *dev, struct device_attribute *attr, char *buf) { @@ -63,19 +82,30 @@ out_1: static void gsm_on_off(struct device *dev, int on) { if (!on) { - /* - * Do not drive into powered-down GSM side - * GTA02 only, because on GTA01 maybe serial - * is used otherwise. - */ s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPIO_INPUT); s3c2410_gpio_cfgpin(S3C2410_GPH2, S3C2410_GPIO_INPUT); pcf50633_gpio_set(gta02_pcf, PCF50633_GPIO2, 0); + if (gta02_gsm.con) { + s3c24xx_serial_console_set_silence(0); + console_start(gta02_gsm.con); + + dev_dbg(dev, "powered down gta02 GSM, enabling " + "serial console\n"); + } + return; } + if (gta02_gsm.con) { + dev_dbg(dev, "powering up GSM, thus " + "disconnecting serial console\n"); + + console_stop(gta02_gsm.con); + s3c24xx_serial_console_set_silence(1); + } + /* allow UART to talk to GSM side now we will power it */ s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_nRTS0); s3c2410_gpio_cfgpin(S3C2410_GPH2, S3C2410_GPH2_TXD0); @@ -84,6 +114,10 @@ static void gsm_on_off(struct device *dev, int on) msleep(100); + gta02_gpb_setpin(GTA02_GPIO_MODEM_ON, 1); + msleep(500); + gta02_gpb_setpin(GTA02_GPIO_MODEM_ON, 0); + /* * workaround for calypso firmware moko10 and earlier, * without this it will leave IRQ line high after @@ -188,6 +222,11 @@ static int gta02_gsm_resume(struct platform_device *pdev) /* GPIO state is saved/restored by S3C2410 core GPIO driver, so we * don't need to do much here. */ + /* Make sure that the kernel console on the serial port is still + * disabled. FIXME: resume ordering race with serial driver! */ + if (gta02_gsm.con && s3c2410_gpio_getpin(GTA02_GPIO_MODEM_ON)) + console_stop(gta02_gsm.con); + s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, gta02_gsm.gpio_ndl_gsm); return 0; @@ -222,13 +261,17 @@ static int __init gta02_gsm_probe(struct platform_device *pdev) case GTA02v6_SYSTEM_REV: break; default: - /* TODO: fail */ - dev_warn(&pdev->dev, "Unknown Neo1973 Revision 0x%x, " + dev_warn(&pdev->dev, "Unknown Freerunner Revision 0x%x, " "some PM features not available!!!\n", system_rev); break; } + gta02_gsm.con = find_s3c24xx_console(); + if (!gta02_gsm.con) + dev_warn(&pdev->dev, + "cannot find S3C24xx console driver\n"); + /* note that download initially disabled, and enforce that */ gta02_gsm.gpio_ndl_gsm = 1; s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, 1); diff --git a/target/linux/s3c24xx/patches-2.6.30/110-serial.patch b/target/linux/s3c24xx/patches-2.6.30/110-serial.patch new file mode 100644 index 000000000000..edb3aa5ac5e8 --- /dev/null +++ b/target/linux/s3c24xx/patches-2.6.30/110-serial.patch @@ -0,0 +1,40 @@ +diff -urNX /opt/Projects/openmoko-linux-2.6/orig/dontdiff /opt/Projects/openmoko-linux-2.6/orig/linux-2.6.29-rc3/drivers/serial/samsung.c /opt/Projects/openmoko-linux-2.6/drivers/serial/samsung.c +--- a/drivers/serial/samsung.c 2009-01-28 19:49:30.000000000 +0100 ++++ b/drivers/serial/samsung.c 2009-05-16 13:25:47.000000000 +0200 +@@ -1208,6 +1355,13 @@ + #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE + + static struct uart_port *cons_uart; ++static int cons_silenced; ++ ++void s3c24xx_serial_console_set_silence(int silenced) ++{ ++ cons_silenced = silenced; ++} ++EXPORT_SYMBOL(s3c24xx_serial_console_set_silence); + + static int + s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) +@@ -1232,9 +1386,21 @@ + s3c24xx_serial_console_putchar(struct uart_port *port, int ch) + { + unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); ++ unsigned int umcon = rd_regl(cons_uart, S3C2410_UMCON); ++ ++ if (cons_silenced) ++ return; ++ ++ /* If auto HW flow control enabled, temporarily turn it off */ ++ if (umcon & S3C2410_UMCOM_AFC) ++ wr_regl(port, S3C2410_UMCON, (umcon & !S3C2410_UMCOM_AFC)); ++ + while (!s3c24xx_serial_console_txrdy(port, ufcon)) + barrier(); + wr_regb(cons_uart, S3C2410_UTXH, ch); ++ ++ if (umcon & S3C2410_UMCOM_AFC) ++ wr_regl(port, S3C2410_UMCON, umcon); + } + + static void + -- 2.30.2