collie: charger partially working

From: Pavel Machek
Date: Tue Jul 04 2006 - 19:43:53 EST


Hi!

I got battery reading/charging code at collie to somehow working
state, and to my surprise, battery voltage actually went _down_ when I
enabled my charge-control code.

I was suspecting something strange before (battery was warm to touch
when it should not have been charged, it was charged too fast when
charger was off), and this confirms it: it looks like default collie
bootstate is with charger _enabled_.

It does not actually harm, because hardware charger knows when to stop
charging itself, but...

My bigdiff attached -- warning, it is ugly at places. Help determining
right thresholds for...

struct battery_thresh collie_battery_levels_acin[] = {
struct battery_thresh collie_battery_levels[] = {

...would be nice. I guess that just takes little patience: discharge
collie, and notice how voltage changes with time. (I believe some oz
had quite accurate gauges?)

Warning #2: this plays with lithium. But I guess older versions abused
lithium in much worse ways, so...

(I'd not leave collie unattended with both battery and charger plugged
in, though.)

Question: sharpsl_pm only checks if temperature > limit,
AFAICS. Should not it check if temperature is between two limits? IIRC
li-ions should not be charged when room temperature is <5 Celsius or
>40 Celsius or so...

Pavel

diff --git a/Makefile b/Makefile
index 11a850c..ab4eba2 100644
--- a/Makefile
+++ b/Makefile
@@ -149,10 +149,7 @@ export srctree objtree VPATH TOPDIR
# then ARCH is assigned, getting whatever value it gets normally, and
# SUBARCH is subsequently ignored.

-SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
- -e s/arm.*/arm/ -e s/sa110/arm/ \
- -e s/s390x/s390/ -e s/parisc64/parisc/ \
- -e s/ppc.*/powerpc/ -e s/mips.*/mips/ )
+SUBARCH := arm

# Cross compiling and selecting different set of gcc/bin-utils
# ---------------------------------------------------------------------------
@@ -174,7 +171,7 @@ SUBARCH := $(shell uname -m | sed -e s/i
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile

ARCH ?= $(SUBARCH)
-CROSS_COMPILE ?=
+CROSS_COMPILE ?= /scratchbox/compilers/arm-gcc-3.3.4-glibc-2.3.2/bin/arm-linux-

# Architecture as present in compile.h
UTS_MACHINE := $(ARCH)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index f81a623..766a737 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -690,7 +690,7 @@ config XIP_PHYS_ADDR

endmenu

-if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP)
+if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_PXA)

menu "CPU Frequency scaling"

@@ -717,6 +717,18 @@ config CPU_FREQ_INTEGRATOR

If in doubt, say Y.

+config CPU_FREQ_PXA25x
+ bool
+ select CPU_FREQ_TABLE
+ depends on CPU_FREQ && PXA25x
+ default y
+
+config CPU_FREQ_PXA27x
+ bool
+ select CPU_FREQ_TABLE
+ depends on CPU_FREQ && PXA27x
+ default y
+
endmenu

endif
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index ec9c400..73ead54 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -56,6 +56,12 @@ $(obj)/compressed/vmlinux: $(obj)/Image
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
@echo ' Kernel: $@ is ready'
+ @ls -al $@
+ @wc -c $@ | ( read SIZE Y; \
+ if [ $$SIZE -gt 1294336 ]; then \
+ echo ' Kernel is too big, would kill spitz'; \
+ rm $@; \
+ fi )

endif

diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index fbc3ab0..fdafed7 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -506,7 +506,7 @@ locomo_init_one_child(struct locomo *lch
goto out;
}

- strncpy(dev->dev.bus_id,info->name,sizeof(dev->dev.bus_id));
+ strncpy(dev->dev.bus_id, info->name, sizeof(dev->dev.bus_id));
/*
* If the parent device has a DMA mask associated with it,
* propagate it down to the children.
@@ -729,7 +729,6 @@ __locomo_probe(struct device *me, struct

for (i = 0; i < ARRAY_SIZE(locomo_devices); i++)
locomo_init_one_child(lchip, &locomo_devices[i]);
-
return 0;

out:
@@ -1046,6 +1045,8 @@ void locomo_m62332_senddata(struct locom
* Frontlight control
*/

+#define LOCOMO_GPIO9 (1<<9)
+
static struct locomo *locomo_chip_driver(struct locomo_dev *ldev);

void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf)
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index 045e37e..12beac3 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -12,7 +12,7 @@
*
*/

-#undef DEBUG
+#define DEBUG

#include <linux/module.h>
#include <linux/timer.h>
@@ -28,11 +28,17 @@
#include <asm/mach-types.h>
#include <asm/irq.h>
#include <asm/apm.h>
+
+#ifndef CONFIG_SA1100_COLLIE
#include <asm/arch/pm.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/sharpsl.h>
+#endif
#include <asm/hardware/sharpsl_pm.h>

+#define dev_dbg(a, b...) printk(b)
+
+
/*
* Constants
*/
@@ -155,6 +161,7 @@ static void sharpsl_battery_thread(void
dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %d\n", voltage,
sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies);

+#ifndef CONFIG_SA1100_COLLIE
/* If battery is low. limit backlight intensity to save power. */
if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
&& ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) ||
@@ -167,6 +174,7 @@ static void sharpsl_battery_thread(void
sharpsl_pm.machinfo->backlight_limit(0);
sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT;
}
+#endif

/* Suspend if critical battery level */
if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
@@ -276,13 +284,21 @@ static void sharpsl_chrg_full_timer(unsi
dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n");
if (sharpsl_pm.charge_mode == CHRG_ON)
sharpsl_charge_off();
- } else if (sharpsl_pm.full_count < 2) {
+ return;
+ }
+#ifndef CONFIG_SA1100_COLLIE
+ if (sharpsl_pm.full_count < 2) {
dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n");
schedule_work(&toggle_charger);
- } else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) {
+ return;
+ }
+ if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) {
dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n");
schedule_work(&toggle_charger);
- } else {
+ return;
+ }
+#endif
+ {
sharpsl_charge_off();
sharpsl_pm.charge_mode = CHRG_DONE;
dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n");
@@ -294,6 +310,7 @@ static void sharpsl_chrg_full_timer(unsi
delay until after that has been processed */
irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id, struct pt_regs *fp)
{
+ printk("charge full interrupt came\n");
if (sharpsl_pm.flags & SHARPSL_SUSPENDED)
return IRQ_HANDLED;

@@ -412,8 +429,10 @@ static int sharpsl_check_battery_temp(vo
val = get_select_val(buff);

dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val);
- if (val > sharpsl_pm.machinfo->charge_on_temp)
+ if (val > sharpsl_pm.machinfo->charge_on_temp) {
+ printk(KERN_WARNING "Not charging: temperature out of limits.\n");
return -1;
+ }

return 0;
}
@@ -502,6 +521,7 @@ static void corgi_goto_sleep(unsigned lo
dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG);
/* not charging and AC-IN! */

+#ifndef CONFIG_SA1100_COLLIE
if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN))) {
dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n");
sharpsl_pm.charge_mode = CHRG_OFF;
@@ -532,6 +552,7 @@ static void corgi_goto_sleep(unsigned lo
sharpsl_pm.machinfo->postsuspend();

dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n",PEDR);
+#endif
}

static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
@@ -629,6 +650,7 @@ static int sharpsl_fatal_check(void)

static int sharpsl_off_charge_error(void)
{
+ panic("collie: not off charging\n");
dev_err(sharpsl_pm.dev, "Offline Charger: Error occured.\n");
sharpsl_pm.machinfo->charge(0);
sharpsl_pm_led(SHARPSL_LED_ERROR);
@@ -645,6 +667,7 @@ static int sharpsl_off_charge_battery(vo
{
int time;

+ panic("off_charging -- not on collie\n");
dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode);

if (sharpsl_pm.charge_mode == CHRG_OFF) {
@@ -761,9 +784,11 @@ static void sharpsl_apm_get_power_status

static struct pm_ops sharpsl_pm_ops = {
.pm_disk_mode = PM_DISK_FIRMWARE,
+#ifndef CONFIG_SA1100_COLLIE
.prepare = pxa_pm_prepare,
.enter = corgi_pxa_pm_enter,
.finish = pxa_pm_finish,
+#endif
};

static int __init sharpsl_pm_probe(struct platform_device *pdev)
@@ -773,6 +798,7 @@ static int __init sharpsl_pm_probe(struc

sharpsl_pm.dev = &pdev->dev;
sharpsl_pm.machinfo = pdev->dev.platform_data;
+
sharpsl_pm.charge_mode = CHRG_OFF;
sharpsl_pm.flags = 0;

diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 35a052f..b7607df 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -56,8 +56,6 @@ void dump_backtrace_entry(unsigned long
#ifdef CONFIG_KALLSYMS
printk("[<%08lx>] ", where);
print_symbol("(%s) ", where);
- printk("from [<%08lx>] ", from);
- print_symbol("(%s)\n", from);
#else
printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
#endif
@@ -156,6 +154,7 @@ static void dump_backtrace(struct pt_reg
unsigned int fp;
int ok = 1;

+#if 0
printk("Backtrace: ");
fp = regs->ARM_fp;
if (!fp) {
@@ -170,6 +169,7 @@ static void dump_backtrace(struct pt_reg

if (ok)
c_backtrace(fp, processor_mode(regs));
+#endif
}

void dump_stack(void)
@@ -209,10 +209,13 @@ static void __die(const char *str, int e
tsk->comm, tsk->pid, thread + 1);

if (!user_mode(regs) || in_interrupt()) {
+#if 0
dump_mem("Stack: ", regs->ARM_sp,
THREAD_SIZE + (unsigned long)task_stack_page(tsk));
+#endif
+
dump_backtrace(regs, tsk);
- dump_instr(regs);
+// dump_instr(regs);
}
}

diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 3ca574e..e3ac6ab 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -181,6 +181,6 @@ SECTIONS
* These must never be empty
* If you have to comment these two assert statements out, your
* binutils is too old (for other reasons as well)
- */
ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
+*/
diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h
index da4769c..c92544d 100644
--- a/arch/arm/mach-pxa/sharpsl.h
+++ b/arch/arm/mach-pxa/sharpsl.h
@@ -12,6 +12,9 @@
/*
* SharpSL SSP Driver
*/
+
+#include <linux/interrupt.h>
+
struct corgissp_machinfo {
int port;
int cs_lcdcon;
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
index e27f150..b90534b 100644
--- a/arch/arm/mach-sa1100/Makefile
+++ b/arch/arm/mach-sa1100/Makefile
@@ -24,6 +24,9 @@ obj-$(CONFIG_SA1100_CERF) += cerf.o
led-$(CONFIG_SA1100_CERF) += leds-cerf.o

obj-$(CONFIG_SA1100_COLLIE) += collie.o
+obj-$(CONFIG_SA1100_COLLIE) += collie_pm.o
+obj-$(CONFIG_SA1100_COLLIE) += sharpsl_pm.o
+obj-$(CONFIG_SA1100_COLLIE) += collie_batswitch.o

obj-$(CONFIG_SA1100_H3600) += h3600.o

diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index a6bab50..5e2a84e 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -83,8 +83,8 @@ static struct scoop_pcmcia_config collie


static struct mcp_plat_data collie_mcp_data = {
- .mccr0 = MCCR0_ADM,
- .sclk_rate = 11981000,
+ .mccr0 = MCCR0_ADM | MCCR0_ExtClk,
+ .sclk_rate = 9216000,
};

#ifdef CONFIG_SHARP_LOCOMO
@@ -209,7 +209,8 @@ static void collie_set_vpp(int vpp)
}

static struct flash_platform_data collie_flash_data = {
- .map_name = "cfi_probe",
+// .map_name = "jedec_probe",
+ .map_name = "sharp",
.set_vpp = collie_set_vpp,
.parts = collie_partitions,
.nr_parts = ARRAY_SIZE(collie_partitions),
@@ -228,14 +229,17 @@ static void __init collie_init(void)
int ret = 0;

/* cpu initialize */
- GAFR = ( GPIO_SSP_TXD | \
+ GAFR = ( GPIO_LDD8 | GPIO_LDD9 | GPIO_LDD10 | GPIO_LDD11 | GPIO_LDD12 | \
+ GPIO_LDD13 | GPIO_LDD14 | GPIO_LDD15 | GPIO_SSP_TXD | \
GPIO_SSP_SCLK | GPIO_SSP_SFRM | GPIO_SSP_CLK | GPIO_TIC_ACK | \
GPIO_32_768kHz );

+
GPDR = ( GPIO_LDD8 | GPIO_LDD9 | GPIO_LDD10 | GPIO_LDD11 | GPIO_LDD12 | \
GPIO_LDD13 | GPIO_LDD14 | GPIO_LDD15 | GPIO_SSP_TXD | \
GPIO_SSP_SCLK | GPIO_SSP_SFRM | GPIO_SDLC_SCLK | \
GPIO_SDLC_AAF | GPIO_UART_SCLK1 | GPIO_32_768kHz );
+
GPLR = GPIO_GPIO18;

// PPC pin setting
@@ -243,13 +247,61 @@ static void __init collie_init(void)
PPC_LDD6 | PPC_LDD7 | PPC_L_PCLK | PPC_L_LCLK | PPC_L_FCLK | PPC_L_BIAS | \
PPC_TXD1 | PPC_TXD2 | PPC_RXD2 | PPC_TXD3 | PPC_TXD4 | PPC_SCLK | PPC_SFRM );

+#if 1
+ PPSR = ( PPC_RXD2 | PPC_RXD3 );
+#endif
PSDR = ( PPC_RXD1 | PPC_RXD2 | PPC_RXD3 | PPC_RXD4 );

+#if 0
+ /* locomo initialize */
+ LCM_ICR = 0;
+ /* KEYBOARD */
+ LCM_KIC = 0;
+ /* GPIO */
+ LCM_GPO = 0;
+ LCM_GPE = ( LCM_GPIO(2) | LCM_GPIO(3) | LCM_GPIO(13) | LCM_GPIO(14) );
+ LCM_GPD = ( LCM_GPIO(2) | LCM_GPIO(3) | LCM_GPIO(13) | LCM_GPIO(14) );
+ LCM_GIE = 0;
+ /* FrontLight */
+ LCM_ALS = 0;
+ LCM_ALD = 0;
+ /* Longtime timer */
+ LCM_LTINT = 0;
+ /* SPI */
+ LCM_SPIIE = 0;
+#endif
+
GAFR |= GPIO_32_768kHz;
GPDR |= GPIO_32_768kHz;
TUCR = TUCR_32_768kHz;

+ /* MCP ExtClk */
+ GAFR |= GPIO_MCP_CLK;
+ GPDR &= ~GPIO_MCP_CLK;
+
+#if 0
+ LCM_ASD = (6+8+320+30)-10;/* synchronize lccr1 setting : colliefb.c */
+ LCM_ASD |= 0x8000;
+ LCM_HSD = (6+8+320+30)-10-128+4;
+ LCM_HSD |= 0x8000;
+ LCM_HSC = 128/8;
+
+ LCM_TADC = 0x80; /* XON */
+ udelay(1000);
+ LCM_TADC |= 0x10; /* CLK9MEN */
+ udelay(100);
+
+ LCM_DAC |= (LCM_DAC_SCLOEB | LCM_DAC_SDAOEB); /* init DAC */
+#endif
+
+ // Reset Codec
+ GAFR &= ~COLLIE_GPIO_UCB1x00_RESET;
+ GPDR |= COLLIE_GPIO_UCB1x00_RESET;
+ GPSR |= COLLIE_GPIO_UCB1x00_RESET;
+
+#ifdef CONFIG_PCMCIA_SA1100
platform_scoop_config = &collie_pcmcia_config;
+#endif

ret = platform_add_devices(devices, ARRAY_SIZE(devices));
if (ret) {
diff --git a/arch/arm/mach-sa1100/collie_batswitch.c b/arch/arm/mach-sa1100/collie_batswitch.c
new file mode 100644
index 0000000..9df53ba
--- /dev/null
+++ b/arch/arm/mach-sa1100/collie_batswitch.c
@@ -0,0 +1,151 @@
+/*
+ * drivers/misc/collie_batswitch.c
+ *
+ * Handling for the Collie battery switch
+ *
+ * 1) immediately suspend if switch isnt flipped during initial boot
+ * 2) abort resume and resuspend if bat switch isnt flipped when unit
+ * awakens.
+ * 3) register an interrupt handler so that flipping the switch results
+ * in the user expected "soft reset"
+ *
+ * Copyright (C) 2003 Chris Larson <kergoth@xxxxxxxxxxxxx>
+ *
+ * Updated Mar 27, 2004 by John Lenz <lenz@xxxxxxxxxxx> to work
+ * with 2.6
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/arch/collie.h>
+
+static inline int batswitch_status(void)
+{
+ return GPLR & COLLIE_GPIO_MAIN_BAT_LOW;
+}
+
+#ifdef CONFIG_PM
+/* item #2 from comments */
+static int batswitch_pm_callback(struct pm_dev* pm_dev, pm_request_t req, void *data)
+{
+ switch (req) {
+ case PM_SUSPEND:
+ disable_irq(COLLIE_IRQ_GPIO_MAIN_BAT_LOW);
+ break;
+ case PM_RESUME:
+ if (batswitch_status() == 0) {
+ printk("return to suspend\n");
+ return 1;
+ }
+ enable_irq(COLLIE_IRQ_GPIO_MAIN_BAT_LOW);
+ break;
+ }
+ return 0;
+}
+#endif
+
+/* item #3 from comments */
+extern asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void * arg);
+
+static void batswitch_routine(unsigned long arg)
+{
+ mdelay(10);
+ if (batswitch_status()) {
+ printk("cancel emergency off\n");
+ return;
+ }
+
+ pm_send_all(PM_SUSPEND, (void *)3);
+ pm_suspend(PM_SUSPEND_MEM);
+ sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART, NULL);
+}
+
+DECLARE_TASKLET(batswitch_tasklet, batswitch_routine, 0);
+
+static irqreturn_t batswitch_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (batswitch_status() == 0)
+ tasklet_schedule(&batswitch_tasklet);
+
+ return IRQ_HANDLED;
+}
+
+extern int sa11x0_pm_enter(u32 state);
+
+#if 0
+int batswitch_suspend(void)
+{
+ int retval;
+
+ retval = pm_send_all(PM_SUSPEND, (void *)3);
+
+ if (retval == 0) {
+ int resumeval = 1;
+ while ((retval == 0) && (resumeval != 0)) {
+ retval = sa11x0_pm_enter(PM_SUSPEND_MEM);
+ resumeval = pm_send_all(PM_RESUME, (void *)0);
+ }
+ }
+
+ return retval;
+}
+#endif
+
+#ifdef CONFIG_PM
+static int __init batswitch_checkswitch(void)
+{
+ /* suspend if we were reset */
+ /*if (RCSR == 0x01)
+ pm_suspend(PM_SUSPEND_MEM);*/
+
+ /* item #1 from comments */
+ if (batswitch_status() == 0) {
+ /*pm_suspend(PM_SUSPEND_MEM);*/
+ sa11x0_pm_enter(PM_SUSPEND_MEM);
+ }
+
+ return 0;
+}
+#endif
+
+static int __init batswitch_registerirq(void)
+{
+
+#ifdef CONFIG_PM
+ pm_register(PM_SYS_DEV, 0, batswitch_pm_callback);
+#endif
+
+ /* set COLLIE_IRQ_GPIO_MAIN_BAT_LOW to be an edge triggered interrupt */
+
+ if (request_irq(COLLIE_IRQ_GPIO_MAIN_BAT_LOW,
+ batswitch_interrupt,
+ SA_INTERRUPT,
+ "batswitch",
+ &batswitch_tasklet)) {
+ printk(KERN_INFO "Battery switch install error: Could not register irq handler.\n");
+ }
+
+ return 0;
+}
+
+//arch_initcall(batswitch_checkswitch);
+device_initcall(batswitch_registerirq);
diff --git a/arch/arm/mach-sa1100/collie_pm.c b/arch/arm/mach-sa1100/collie_pm.c
index 45b1e71..c4eee79 100644
--- a/arch/arm/mach-sa1100/collie_pm.c
+++ b/arch/arm/mach-sa1100/collie_pm.c
@@ -70,6 +70,8 @@ static void collie_measure_temp(int on)
ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_TMP_ON);
}

+extern struct platform_device colliescoop_device;
+
static void collie_charge(int on)
{
if (on) {
@@ -77,6 +79,7 @@ static void collie_charge(int on)
} else {
printk("Should stop charger\n");
}
+#define I_AM_SURE
#ifdef I_AM_SURE

/* Zaurus seems to contain LTC1731 ; it should know when to
@@ -146,10 +149,10 @@ int collie_read_main_battery(void)
ucb1x00_adc_enable(ucb);
ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_BBAT_ON);
ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_MBAT_ON, 0);
- /* gives values 160..255 with battery removed... and
- 145..255 with battery inserted. (on AC), goes as low as
- 80 on DC. */
+
+ mdelay(1);
voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_SYNC);
+// printk("[%d]", voltage);

ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_MBAT_ON);
ucb1x00_adc_disable(ucb);
@@ -192,7 +195,7 @@ static unsigned long read_devdata(int wh
case SHARPSL_BATT_TEMP:
return collie_read_temp();
case SHARPSL_ACIN_VOLT:
- return 0x1;
+ return 500;
case SHARPSL_STATUS_ACIN: {
int ret = GPLR & COLLIE_GPIO_AC_IN;
printk("AC status = %d\n", ret);
@@ -208,10 +211,33 @@ static unsigned long read_devdata(int wh
}
}

+struct battery_thresh collie_battery_levels_acin[] = {
+ { 420, 100},
+ { 417, 95},
+ { 415, 90},
+ { 413, 80},
+ { 411, 75},
+ { 408, 70},
+ { 406, 60},
+ { 403, 50},
+ { 398, 40},
+ { 391, 25},
+ { 10, 5},
+ { 0, 0},
+};
+
struct battery_thresh collie_battery_levels[] = {
- { 368, 100},
- { 358, 25},
- { 356, 5},
+ { 394, 100},
+ { 390, 95},
+ { 380, 90},
+ { 370, 80},
+ { 368, 75}, /* From sharp code: battery high with frontlight */
+ { 366, 70}, /* 60..90 -- fake values invented by me for testing */
+ { 364, 60},
+ { 362, 50},
+ { 360, 40},
+ { 358, 25}, /* From sharp code: battery low with frontlight */
+ { 356, 5}, /* From sharp code: battery verylow with frontlight */
{ 0, 0},
};

@@ -226,13 +252,21 @@ struct sharpsl_charger_machinfo collie_p
.postsuspend = collie_postsuspend,
.charger_wakeup = collie_charger_wakeup,
.should_wakeup = collie_should_wakeup,
- .bat_levels = 3,
+ .bat_levels = 12,
.bat_levels_noac = collie_battery_levels,
- .bat_levels_acin = collie_battery_levels,
+ .bat_levels_acin = collie_battery_levels_acin,
.status_high_acin = 368,
.status_low_acin = 358,
.status_high_noac = 368,
.status_low_noac = 358,
+ .charge_on_volt = 350, /* spitz uses 2.90V, but lets play it safe. */
+ .charge_on_temp = 550,
+ .charge_acin_high = 550, /* collie does not seem to have sensor for this, anyway */
+ .charge_acin_low = 450, /* ignored, too */
+ .fatal_acin_volt = 356,
+ .fatal_noacin_volt = 356,
+
+ .batfull_irq = 1, /* We do not want periodical charge restarts */
};

static int __init collie_pm_ucb_add(struct ucb1x00_dev *pdev)
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index 786c853..f363074 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -54,7 +54,7 @@ enum { SLEEP_SAVE_SP = 0,
};


-static int sa11x0_pm_enter(suspend_state_t state)
+int sa11x0_pm_enter(suspend_state_t state)
{
unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
struct timespec delta, rtc;
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 6e0f446..794a581 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -115,7 +115,7 @@ $(obj)/qtronixmap.o: $(obj)/qtronixmap.c
# Uncomment if you're changing the keymap and have an appropriate
# loadkeys version for the map. By default, we'll use the shipped
# versions.
-# GENERATE_KEYMAP := 1
+ GENERATE_KEYMAP := 1

ifdef GENERATE_KEYMAP

diff --git a/drivers/char/defkeymap.map b/drivers/char/defkeymap.map
index 50b30ca..ecf23c2 100644
--- a/drivers/char/defkeymap.map
+++ b/drivers/char/defkeymap.map
@@ -1,264 +1,169 @@
-# Default kernel keymap. This uses 7 modifier combinations.
-keymaps 0-2,4-5,8,12
-# Change the above line into
-# keymaps 0-2,4-6,8,12
-# in case you want the entries
-# altgr control keycode 83 = Boot
-# altgr control keycode 111 = Boot
-# below.
-#
-# In fact AltGr is used very little, and one more keymap can
-# be saved by mapping AltGr to Alt (and adapting a few entries):
-# keycode 100 = Alt
-#
+# Note:
+# The way in which the modifiers are handled are quite different
+# than how they were handled in the 2.4.6-rmk1-np2-embedix kernel.
+#
+# Here, we simply pass up Fn as Control, and the german accent key
+# as Altgr, and simply use a proper keymap. Said keymap is as
+# follows.
+# keymaps 0-2,4-5,8,12,20
keycode 1 = Escape Escape
- alt keycode 1 = Meta_Escape
-keycode 2 = one exclam
- alt keycode 2 = Meta_one
-keycode 3 = two at at
- control keycode 3 = nul
- shift control keycode 3 = nul
- alt keycode 3 = Meta_two
-keycode 4 = three numbersign
- control keycode 4 = Escape
- alt keycode 4 = Meta_three
-keycode 5 = four dollar dollar
- control keycode 5 = Control_backslash
- alt keycode 5 = Meta_four
-keycode 6 = five percent
- control keycode 6 = Control_bracketright
- alt keycode 6 = Meta_five
-keycode 7 = six asciicircum
- control keycode 7 = Control_asciicircum
- alt keycode 7 = Meta_six
-keycode 8 = seven ampersand braceleft
- control keycode 8 = Control_underscore
- alt keycode 8 = Meta_seven
-keycode 9 = eight asterisk bracketleft
- control keycode 9 = Delete
- alt keycode 9 = Meta_eight
-keycode 10 = nine parenleft bracketright
- alt keycode 10 = Meta_nine
-keycode 11 = zero parenright braceright
- alt keycode 11 = Meta_zero
-keycode 12 = minus underscore backslash
- control keycode 12 = Control_underscore
- shift control keycode 12 = Control_underscore
- alt keycode 12 = Meta_minus
-keycode 13 = equal plus
- alt keycode 13 = Meta_equal
-keycode 14 = Delete Delete
- control keycode 14 = BackSpace
- alt keycode 14 = Meta_Delete
+keycode 14 = BackSpace
+ shift keycode 14 = BackSpace
+ control keycode 14 = Delete
+ shiftl control keycode 14 = bracketleft
+ control shiftr keycode 14 = bracketleft
keycode 15 = Tab Tab
- alt keycode 15 = Meta_Tab
+ shift keycode 15 = backslash
+ control keycode 15 = Caps_Lock
+ shiftl control keycode 15 = Caps_Lock
+ control shiftr keycode 15 = Caps_Lock
keycode 16 = q
+ control keycode 16 = one
+ shiftl control keycode 16 = Control_q
+ control shiftr keycode 16 = Meta_q
keycode 17 = w
-keycode 18 = e
- altgr keycode 18 = Hex_E
+ control keycode 17 = two
+ shiftl control keycode 17 = Control_w
+ control shiftr keycode 17 = Meta_w
+keycode 18 = e
+ control keycode 18 = three
+ shiftl control keycode 18 = Control_e
+ control shiftr keycode 18 = Meta_e
keycode 19 = r
+ control keycode 19 = four
+ shiftr control keycode 19 = Control_r
+ control shiftl keycode 19 = Meta_r
keycode 20 = t
+ control keycode 20 = five
+ shiftl control keycode 20 = Control_t
+ control shiftr keycode 20 = Meta_t
keycode 21 = y
+ control keycode 21 = six
+ shiftl control keycode 21 = Control_y
+ control shiftr keycode 21 = Meta_y
keycode 22 = u
+ control keycode 22 = seven
+ shiftl control keycode 22 = Control_u
+ control shiftr keycode 22 = Meta_u
keycode 23 = i
+ control keycode 23 = eight
+ shiftl control keycode 23 = Control_i
+ control shiftr keycode 23 = Meta_i
keycode 24 = o
+ control keycode 24 = nine
+ shiftl control keycode 24 = Control_o
+ control shiftr keycode 24 = Meta_o
keycode 25 = p
-keycode 26 = bracketleft braceleft
- control keycode 26 = Escape
- alt keycode 26 = Meta_bracketleft
-keycode 27 = bracketright braceright asciitilde
- control keycode 27 = Control_bracketright
- alt keycode 27 = Meta_bracketright
+ control keycode 25 = zero
+ shiftl control keycode 25 = Control_p
+ control shiftr keycode 25 = Meta_p
keycode 28 = Return
- alt keycode 28 = Meta_Control_m
+ control keycode 28 = greater
+ shiftl control keycode 28 = braceright
+ control shiftr keycode 28 = braceright
keycode 29 = Control
-keycode 30 = a
- altgr keycode 30 = Hex_A
+keycode 30 = a
+ control keycode 30 = exclam
+ shiftl control keycode 30 = Control_a
+ control shiftr keycode 30 = Meta_a
keycode 31 = s
-keycode 32 = d
- altgr keycode 32 = Hex_D
-keycode 33 = f
- altgr keycode 33 = Hex_F
+ control keycode 31 = at
+ shiftl control keycode 31 = Control_s
+ control shiftr keycode 31 = Meta_s
+keycode 32 = d
+ control keycode 32 = numbersign
+ shiftl control keycode 32 = Control_d
+ control shiftr keycode 32 = Meta_d
+keycode 33 = f
+ control keycode 33 = dollar
+ shiftl control keycode 33 = Control_f
+ control shiftr keycode 33 = Meta_f
keycode 34 = g
+ control keycode 34 = percent
+ shiftl control keycode 34 = Control_g
+ control shiftr keycode 34 = Meta_g
keycode 35 = h
+ control keycode 35 = underscore
+ shiftl control keycode 35 = BackSpace
+ control shiftr keycode 35 = BackSpace
keycode 36 = j
+ control keycode 36 = ampersand
+ shiftl control keycode 36 = Linefeed
+ control shiftr keycode 36 = Linefeed
keycode 37 = k
+ control keycode 37 = asterisk
+ shiftl control keycode 37 = Control_k
+ control shiftr keycode 37 = Meta_k
keycode 38 = l
-keycode 39 = semicolon colon
- alt keycode 39 = Meta_semicolon
-keycode 40 = apostrophe quotedbl
- control keycode 40 = Control_g
- alt keycode 40 = Meta_apostrophe
-keycode 41 = grave asciitilde
- control keycode 41 = nul
- alt keycode 41 = Meta_grave
+ control keycode 38 = parenleft
+ shiftl control keycode 38 = Control_l
+ control shiftr keycode 38 = Meta_l
+keycode 40 = apostrophe quotedbl
+ control keycode 40 = asciitilde
+ shiftl control keycode 40 = asciicircum
+ control shiftr keycode 40 = asciicircum
keycode 42 = Shift
-keycode 43 = backslash bar
- control keycode 43 = Control_backslash
- alt keycode 43 = Meta_backslash
keycode 44 = z
+ control keycode 44 = Control_z
+ shiftl control keycode 44 = Control_z
+ control shiftr keycode 44 = Meta_z
keycode 45 = x
-keycode 46 = c
- altgr keycode 46 = Hex_C
+ control keycode 45 = Control_x
+ shiftl control keycode 45 = Control_x
+ control shiftr keycode 45 = Meta_x
+keycode 46 = c
+ control keycode 46 = Control_c
+ shiftl control keycode 46 = Control_c
+ control shiftr keycode 46 = Meta_c
keycode 47 = v
-keycode 48 = b
- altgr keycode 48 = Hex_B
+ control keycode 47 = Control_v
+ shiftl control keycode 47 = Control_v
+ control shiftr keycode 47 = Meta_v
+## current location ##
+keycode 48 = b
+ control keycode 48 = minus
+ shiftl control keycode 48 = Control_b
+ control shiftr keycode 48 = Meta_b
keycode 49 = n
+ control keycode 49 = plus
+ shiftl control keycode 49 = Control_n
+ control shiftr keycode 49 = Meta_n
keycode 50 = m
-keycode 51 = comma less
- alt keycode 51 = Meta_comma
-keycode 52 = period greater
- control keycode 52 = Compose
- alt keycode 52 = Meta_period
-keycode 53 = slash question
- control keycode 53 = Delete
- alt keycode 53 = Meta_slash
+ control keycode 50 = equal
+ shiftl control keycode 50 = Control_m
+ control shiftr keycode 50 = Meta_m
+keycode 51 = comma
+ shift keycode 51 = semicolon
+ control keycode 51 = parenright
+ shiftl control keycode 51 = bracketright
+ control shiftr keycode 51 = bracketright
+keycode 52 = period
+ shift keycode 52 = colon
+ control keycode 52 = less
+ shiftl control keycode 52 = braceleft
+ control shiftr keycode 52 = braceleft
+keycode 53 = slash
+ shift keycode 53 = question
+ control keycode 53 = Num_Lock
+ shiftl control keycode 53 = Num_Lock
+ control shiftr keycode 53 = Num_Lock
keycode 54 = Shift
keycode 55 = KP_Multiply
keycode 56 = Alt
-keycode 57 = space space
- control keycode 57 = nul
- alt keycode 57 = Meta_space
-keycode 58 = Caps_Lock
-keycode 59 = F1 F11 Console_13
- control keycode 59 = F1
- alt keycode 59 = Console_1
- control alt keycode 59 = Console_1
-keycode 60 = F2 F12 Console_14
- control keycode 60 = F2
- alt keycode 60 = Console_2
- control alt keycode 60 = Console_2
-keycode 61 = F3 F13 Console_15
- control keycode 61 = F3
- alt keycode 61 = Console_3
- control alt keycode 61 = Console_3
-keycode 62 = F4 F14 Console_16
- control keycode 62 = F4
- alt keycode 62 = Console_4
- control alt keycode 62 = Console_4
-keycode 63 = F5 F15 Console_17
- control keycode 63 = F5
- alt keycode 63 = Console_5
- control alt keycode 63 = Console_5
-keycode 64 = F6 F16 Console_18
- control keycode 64 = F6
- alt keycode 64 = Console_6
- control alt keycode 64 = Console_6
-keycode 65 = F7 F17 Console_19
- control keycode 65 = F7
- alt keycode 65 = Console_7
- control alt keycode 65 = Console_7
-keycode 66 = F8 F18 Console_20
- control keycode 66 = F8
- alt keycode 66 = Console_8
- control alt keycode 66 = Console_8
-keycode 67 = F9 F19 Console_21
- control keycode 67 = F9
- alt keycode 67 = Console_9
- control alt keycode 67 = Console_9
-keycode 68 = F10 F20 Console_22
- control keycode 68 = F10
- alt keycode 68 = Console_10
- control alt keycode 68 = Console_10
-keycode 69 = Num_Lock
- shift keycode 69 = Bare_Num_Lock
-keycode 70 = Scroll_Lock Show_Memory Show_Registers
- control keycode 70 = Show_State
- alt keycode 70 = Scroll_Lock
-keycode 71 = KP_7
- alt keycode 71 = Ascii_7
- altgr keycode 71 = Hex_7
-keycode 72 = KP_8
- alt keycode 72 = Ascii_8
- altgr keycode 72 = Hex_8
-keycode 73 = KP_9
- alt keycode 73 = Ascii_9
- altgr keycode 73 = Hex_9
-keycode 74 = KP_Subtract
-keycode 75 = KP_4
- alt keycode 75 = Ascii_4
- altgr keycode 75 = Hex_4
-keycode 76 = KP_5
- alt keycode 76 = Ascii_5
- altgr keycode 76 = Hex_5
-keycode 77 = KP_6
- alt keycode 77 = Ascii_6
- altgr keycode 77 = Hex_6
-keycode 78 = KP_Add
-keycode 79 = KP_1
- alt keycode 79 = Ascii_1
- altgr keycode 79 = Hex_1
-keycode 80 = KP_2
- alt keycode 80 = Ascii_2
- altgr keycode 80 = Hex_2
-keycode 81 = KP_3
- alt keycode 81 = Ascii_3
- altgr keycode 81 = Hex_3
-keycode 82 = KP_0
- alt keycode 82 = Ascii_0
- altgr keycode 82 = Hex_0
-keycode 83 = KP_Period
-# altgr control keycode 83 = Boot
- control alt keycode 83 = Boot
-keycode 84 = Last_Console
-keycode 85 =
-keycode 86 = less greater bar
- alt keycode 86 = Meta_less
-keycode 87 = F11 F11 Console_23
- control keycode 87 = F11
- alt keycode 87 = Console_11
- control alt keycode 87 = Console_11
-keycode 88 = F12 F12 Console_24
- control keycode 88 = F12
- alt keycode 88 = Console_12
- control alt keycode 88 = Console_12
-keycode 89 =
-keycode 90 =
-keycode 91 =
-keycode 92 =
-keycode 93 =
-keycode 94 =
-keycode 95 =
-keycode 96 = KP_Enter
+keycode 57 = space
+ shift keycode 57 = bar
+ control keycode 57 = nul
+ shiftl control keycode 57 = grave
+ control shiftr keycode 57 = grave
keycode 97 = Control
-keycode 98 = KP_Divide
keycode 99 = Control_backslash
control keycode 99 = Control_backslash
- alt keycode 99 = Control_backslash
keycode 100 = AltGr
-keycode 101 = Break
-keycode 102 = Find
keycode 103 = Up
-keycode 104 = Prior
- shift keycode 104 = Scroll_Backward
keycode 105 = Left
- alt keycode 105 = Decr_Console
keycode 106 = Right
- alt keycode 106 = Incr_Console
keycode 107 = Select
keycode 108 = Down
-keycode 109 = Next
- shift keycode 109 = Scroll_Forward
-keycode 110 = Insert
-keycode 111 = Remove
-# altgr control keycode 111 = Boot
- control alt keycode 111 = Boot
-keycode 112 = Macro
-keycode 113 = F13
-keycode 114 = F14
-keycode 115 = Help
-keycode 116 = Do
-keycode 117 = F17
-keycode 118 = KP_MinPlus
-keycode 119 = Pause
-keycode 120 =
-keycode 121 =
-keycode 122 =
-keycode 123 =
-keycode 124 =
-keycode 125 =
-keycode 126 =
-keycode 127 =
string F1 = "\033[[A"
string F2 = "\033[[B"
string F3 = "\033[[C"
diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c
index 3b87951..e832d9f 100644
--- a/drivers/leds/leds-locomo.c
+++ b/drivers/leds/leds-locomo.c
@@ -50,7 +50,7 @@ static struct led_classdev locomo_led0 =

static struct led_classdev locomo_led1 = {
.name = "locomo:green",
- .default_trigger = "nand-disk",
+ .default_trigger = "heartbeat",
.brightness_set = locomoled_brightness_set1,
};

diff --git a/drivers/leds/ledscore.c b/drivers/leds/ledscore.c
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fc3c885..3fa0aca 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -19,6 +19,10 @@ config MCP_UCB1200
tristate "Support for UCB1200 / UCB1300"
depends on MCP

+config MCP_UCB1200_AUDIO
+ tristate "Audio / Telephony interface support"
+ depends on MCP_UCB1200 && SOUND
+
config MCP_UCB1200_TS
tristate "Touchscreen interface support"
depends on MCP_UCB1200 && INPUT
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index adb29b5..9563c66 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -6,7 +6,8 @@ obj-$(CONFIG_MCP) += mcp-core.o
obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
-
+obj-$(CONFIG_MCP_UCB1200_AUDIO) += ucb1x00-audio.o
+
ifeq ($(CONFIG_SA1100_ASSABET),y)
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
endif
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index 1eab7cf..f13f820 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -170,6 +170,16 @@ static int mcp_sa11x0_probe(struct platf
ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
}

+ if (machine_is_collie()) {
+ GAFR &= ~(GPIO_GPIO(16));
+ GPDR |= GPIO_GPIO(16);
+ GPSR |= GPIO_GPIO(16);
+
+ /* MCP ExtClk */
+ GAFR |= GPIO_MCP_CLK;
+ GPDR &= ~GPIO_MCP_CLK;
+ }
+
/*
* Setup the PPC unit correctly.
*/
@@ -185,7 +195,32 @@ static int mcp_sa11x0_probe(struct platf
*/
Ser4MCSR = -1;
Ser4MCCR1 = data->mccr1;
- Ser4MCCR0 = data->mccr0 | 0x7f7f;
+#if 1
+ if (machine_is_collie()) {
+/* Gives 0/1023 for battery reading. Actually works.. but gives same range as below */
+ Ser4MCCR0 = MCCR0_ADM | MCCR0_ExtClk;
+/* From sharp's colliebuzzer. Gives 896 for battery & temp
+ int asd = (9216000 / ( 32 * 11025 ));
+ Ser4MCCR0 &= ~MCCR0_MCE;
+ Ser4MCCR0 &= ~0xff;
+ Ser4MCCR0 |= ( MCCR0_ATE |MCCR0_ADM | MCCR0_ECS | asd);
+ Ser4MCCR0 |= MCCR0_MCE;
+ Ser4MCSR = 0xffffffff;
+ */
+/* Sharp seems to initialize it like this: only gives timeouts :-(
+ Ser4MCCR0 = 0;
+ */
+/* Heh, this seems to give 1010 for battery & temp
+ Ser4MCCR0 = MCCR0_ATE | MCCR0_ECS;
+ */
+/*
+ Can't detect interrupt with this :-(.
+ Ser4MCCR0 = MCCR0_ATE;
+*/
+ } else
+#endif
+ Ser4MCCR0 = data->mccr0 | 0x7f7f;
+

/*
* Calculate the read/write timeout (us) from the bit clock
diff --git a/drivers/mfd/ucb1x00-audio.c b/drivers/mfd/ucb1x00-audio.c
new file mode 100644
index 0000000..b81fa48
--- /dev/null
+++ b/drivers/mfd/ucb1x00-audio.c
@@ -0,0 +1,434 @@
+/*
+ * linux/drivers/mfd/ucb1x00-audio.c
+ *
+ * Copyright (C) 2001 Russell King, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <linux/list.h>
+#include <linux/device.h>
+
+#include <asm/dma.h>
+#include <asm/hardware.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include "ucb1x00.h"
+
+#include "../../sound/oss/sa1100-audio.h"
+
+#define MAGIC 0x41544154
+
+struct ucb1x00_audio {
+ struct file_operations fops;
+ struct file_operations mops;
+ struct ucb1x00 *ucb;
+ audio_stream_t output_stream;
+ audio_stream_t input_stream;
+ audio_state_t state;
+ unsigned int rate;
+ int dev_id;
+ int mix_id;
+ unsigned int daa_oh_bit;
+ unsigned int telecom;
+ unsigned int magic;
+ unsigned int ctrl_a;
+ unsigned int ctrl_b;
+
+ /* mixer info */
+ unsigned int mod_cnt;
+ unsigned short output_level;
+ unsigned short input_level;
+};
+
+struct ucb1x00_devdata {
+ struct ucb1x00_audio audio;
+ struct ucb1x00_audio telecom;
+};
+
+#define REC_MASK (SOUND_MASK_VOLUME | SOUND_MASK_MIC)
+#define DEV_MASK REC_MASK
+
+static int
+ucb1x00_mixer_ioctl(struct inode *ino, struct file *filp, uint cmd, ulong arg)
+{
+ struct ucb1x00_audio *ucba;
+ unsigned int val, gain;
+ int ret = 0;
+
+ ucba = list_entry(filp->f_op, struct ucb1x00_audio, mops);
+
+ if (_IOC_TYPE(cmd) != 'M')
+ return -EINVAL;
+
+ if (cmd == SOUND_MIXER_INFO) {
+ struct mixer_info mi;
+
+ strncpy(mi.id, "UCB1x00", sizeof(mi.id));
+ strncpy(mi.name, "Philips UCB1x00", sizeof(mi.name));
+ mi.modify_counter = ucba->mod_cnt;
+ return copy_to_user((void *)arg, &mi, sizeof(mi)) ? -EFAULT : 0;
+ }
+
+ if (_IOC_DIR(cmd) & _IOC_WRITE) {
+ unsigned int left, right;
+
+ ret = get_user(val, (unsigned int *)arg);
+ if (ret)
+ goto out;
+
+ left = val & 255;
+ right = val >> 8;
+
+ if (left > 100)
+ left = 100;
+ if (right > 100)
+ right = 100;
+
+ gain = (left + right) / 2;
+
+ ret = -EINVAL;
+ if (!ucba->telecom) {
+ switch(_IOC_NR(cmd)) {
+ case SOUND_MIXER_VOLUME:
+ ucba->output_level = gain | gain << 8;
+ ucba->mod_cnt++;
+ ucba->ctrl_b = (ucba->ctrl_b & 0xff00) |
+ ((gain * 31) / 100);
+ ucb1x00_reg_write(ucba->ucb, UCB_AC_B,
+ ucba->ctrl_b);
+ ret = 0;
+ break;
+
+ case SOUND_MIXER_MIC:
+ ucba->input_level = gain | gain << 8;
+ ucba->mod_cnt++;
+ ucba->ctrl_a = (ucba->ctrl_a & 0x7f) |
+ (((gain * 31) / 100) << 7);
+ ucb1x00_reg_write(ucba->ucb, UCB_AC_A,
+ ucba->ctrl_a);
+ ret = 0;
+ break;
+ }
+ }
+ }
+
+ if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
+ switch (_IOC_NR(cmd)) {
+ case SOUND_MIXER_VOLUME:
+ val = ucba->output_level;
+ break;
+
+ case SOUND_MIXER_MIC:
+ val = ucba->input_level;
+ break;
+
+ case SOUND_MIXER_RECSRC:
+ case SOUND_MIXER_RECMASK:
+ val = ucba->telecom ? 0 : REC_MASK;
+ break;
+
+ case SOUND_MIXER_DEVMASK:
+ val = ucba->telecom ? 0 : DEV_MASK;
+ break;
+
+ case SOUND_MIXER_CAPS:
+ case SOUND_MIXER_STEREODEVS:
+ val = 0;
+ break;
+
+ default:
+ val = 0;
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret == 0)
+ ret = put_user(val, (int *)arg);
+ }
+ out:
+ return ret;
+}
+
+static int ucb1x00_audio_setrate(struct ucb1x00_audio *ucba, int rate)
+{
+ unsigned int div_rate = ucb1x00_clkrate(ucba->ucb) / 32;
+ unsigned int div;
+
+ div = (div_rate + (rate / 2)) / rate;
+ if (div < 6)
+ div = 6;
+ if (div > 127)
+ div = 127;
+
+ ucba->ctrl_a = (ucba->ctrl_a & ~0x7f) | div;
+
+ if (ucba->telecom) {
+ ucb1x00_reg_write(ucba->ucb, UCB_TC_B, 0);
+ ucb1x00_set_telecom_divisor(ucba->ucb, div * 32);
+ ucb1x00_reg_write(ucba->ucb, UCB_TC_A, ucba->ctrl_a);
+ ucb1x00_reg_write(ucba->ucb, UCB_TC_B, ucba->ctrl_b);
+ } else {
+ ucb1x00_reg_write(ucba->ucb, UCB_AC_B, 0);
+ ucb1x00_set_audio_divisor(ucba->ucb, div * 32);
+ ucb1x00_reg_write(ucba->ucb, UCB_AC_A, ucba->ctrl_a);
+ ucb1x00_reg_write(ucba->ucb, UCB_AC_B, ucba->ctrl_b);
+ }
+
+ ucba->rate = div_rate / div;
+
+ return ucba->rate;
+}
+
+static int ucb1x00_audio_getrate(struct ucb1x00_audio *ucba)
+{
+ return ucba->rate;
+}
+
+static void ucb1x00_audio_startup(void *data)
+{
+ struct ucb1x00_audio *ucba = data;
+
+ ucb1x00_enable(ucba->ucb);
+ ucb1x00_audio_setrate(ucba, ucba->rate);
+
+ ucb1x00_reg_write(ucba->ucb, UCB_MODE, UCB_MODE_DYN_VFLAG_ENA);
+
+ /*
+ * Take off-hook
+ */
+ if (ucba->daa_oh_bit)
+ ucb1x00_io_write(ucba->ucb, 0, ucba->daa_oh_bit);
+}
+
+static void ucb1x00_audio_shutdown(void *data)
+{
+ struct ucb1x00_audio *ucba = data;
+
+ /*
+ * Place on-hook
+ */
+ if (ucba->daa_oh_bit)
+ ucb1x00_io_write(ucba->ucb, ucba->daa_oh_bit, 0);
+
+ ucb1x00_reg_write(ucba->ucb, ucba->telecom ? UCB_TC_B : UCB_AC_B, 0);
+ ucb1x00_disable(ucba->ucb);
+}
+
+static int
+ucb1x00_audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+{
+ struct ucb1x00_audio *ucba;
+ int val, ret = 0;
+
+ ucba = list_entry(file->f_op, struct ucb1x00_audio, fops);
+
+ /*
+ * Make sure we have our magic number
+ */
+ if (ucba->magic != MAGIC)
+ return -ENODEV;
+
+ switch (cmd) {
+ case SNDCTL_DSP_STEREO:
+ ret = get_user(val, (int *)arg);
+ if (ret)
+ return ret;
+ if (val != 0)
+ return -EINVAL;
+ val = 0;
+ break;
+
+ case SNDCTL_DSP_CHANNELS:
+ case SOUND_PCM_READ_CHANNELS:
+ val = 1;
+ break;
+
+ case SNDCTL_DSP_SPEED:
+ ret = get_user(val, (int *)arg);
+ if (ret)
+ return ret;
+ val = ucb1x00_audio_setrate(ucba, val);
+ break;
+
+ case SOUND_PCM_READ_RATE:
+ val = ucb1x00_audio_getrate(ucba);
+ break;
+
+ case SNDCTL_DSP_SETFMT:
+ case SNDCTL_DSP_GETFMTS:
+ val = AFMT_S16_LE;
+ break;
+
+ default:
+ return ucb1x00_mixer_ioctl(inode, file, cmd, arg);
+ }
+
+ return put_user(val, (int *)arg);
+}
+
+static int ucb1x00_audio_open(struct inode *inode, struct file *file)
+{
+ struct ucb1x00_audio *ucba;
+
+ ucba = list_entry(file->f_op, struct ucb1x00_audio, fops);
+
+ return sa1100_audio_attach(inode, file, &ucba->state);
+}
+
+static int
+ucb1x00_audio_add_one(struct ucb1x00 *ucb, struct ucb1x00_audio *a, int telecom)
+{
+ memset(a, 0, sizeof(*a));
+
+ a->magic = MAGIC;
+ a->ucb = ucb;
+ a->fops.owner = THIS_MODULE;
+ a->fops.open = ucb1x00_audio_open;
+ a->mops.owner = THIS_MODULE;
+ a->mops.ioctl = ucb1x00_mixer_ioctl;
+ a->state.output_stream = &a->output_stream;
+ a->state.input_stream = &a->input_stream;
+ a->state.data = a;
+ a->state.hw_init = ucb1x00_audio_startup;
+ a->state.hw_shutdown = ucb1x00_audio_shutdown;
+ a->state.client_ioctl = ucb1x00_audio_ioctl;
+
+ /* There is a bug in the StrongARM causes corrupt MCP data to be sent to
+ * the codec when the FIFOs are empty and writes are made to the OS timer
+ * match register 0. To avoid this we must make sure that data is always
+ * sent to the codec.
+ */
+ a->state.need_tx_for_rx = 1;
+
+ init_MUTEX(&a->state.sem);
+ a->rate = 8000;
+ a->telecom = telecom;
+ a->input_stream.dev = ucb->cdev.dev;
+ a->output_stream.dev = ucb->cdev.dev;
+ a->ctrl_a = 0;
+
+ if (a->telecom) {
+ a->input_stream.dma_dev = ucb->mcp->dma_telco_rd;
+ a->input_stream.id = "UCB1x00 telco in";
+ a->output_stream.dma_dev = ucb->mcp->dma_telco_wr;
+ a->output_stream.id = "UCB1x00 telco out";
+ a->ctrl_b = UCB_TC_B_IN_ENA|UCB_TC_B_OUT_ENA;
+#if 0
+ a->daa_oh_bit = UCB_IO_8;
+
+ ucb1x00_enable(ucb);
+ ucb1x00_io_write(ucb, a->daa_oh_bit, 0);
+ ucb1x00_io_set_dir(ucb, UCB_IO_7 | UCB_IO_6, a->daa_oh_bit);
+ ucb1x00_disable(ucb);
+#endif
+ } else {
+ a->input_stream.dma_dev = ucb->mcp->dma_audio_rd;
+ a->input_stream.id = "UCB1x00 audio in";
+ a->output_stream.dma_dev = ucb->mcp->dma_audio_wr;
+ a->output_stream.id = "UCB1x00 audio out";
+ a->ctrl_b = UCB_AC_B_IN_ENA|UCB_AC_B_OUT_ENA;
+ }
+
+ a->dev_id = register_sound_dsp(&a->fops, -1);
+ a->mix_id = register_sound_mixer(&a->mops, -1);
+
+ printk("Sound: UCB1x00 %s: dsp id %d mixer id %d\n",
+ a->telecom ? "telecom" : "audio",
+ a->dev_id, a->mix_id);
+
+ return 0;
+}
+
+static void ucb1x00_audio_remove_one(struct ucb1x00_audio *a)
+{
+ unregister_sound_dsp(a->dev_id);
+ unregister_sound_mixer(a->mix_id);
+}
+
+static int ucb1x00_audio_add(struct ucb1x00_dev *dev)
+{
+ struct ucb1x00_devdata *dd;
+ struct ucb1x00 *ucb = dev->ucb;
+
+ if (ucb->cdev.dev == NULL || ucb->cdev.dev->dma_mask == NULL)
+ return -ENXIO;
+
+ dd = kmalloc(sizeof(struct ucb1x00_devdata), GFP_KERNEL);
+ if (!dd)
+ return -ENOMEM;
+
+ ucb1x00_audio_add_one(ucb, &dd->audio, 0);
+ ucb1x00_audio_add_one(ucb, &dd->telecom, 1);
+
+ dev->priv = dd;
+
+ return 0;
+}
+
+static void ucb1x00_audio_remove(struct ucb1x00_dev *dev)
+{
+ struct ucb1x00_devdata *dd = dev->priv;
+
+ ucb1x00_audio_remove_one(&dd->audio);
+ ucb1x00_audio_remove_one(&dd->telecom);
+ kfree(dd);
+}
+
+#ifdef CONFIG_PM
+static int ucb1x00_audio_suspend(struct ucb1x00_dev *dev, pm_message_t state)
+{
+ struct ucb1x00_devdata *dd = dev->priv;
+
+ sa1100_audio_suspend(&dd->audio.state, state);
+ sa1100_audio_suspend(&dd->telecom.state, state);
+
+ return 0;
+}
+
+static int ucb1x00_audio_resume(struct ucb1x00_dev *dev)
+{
+ struct ucb1x00_devdata *dd = dev->priv;
+
+ sa1100_audio_resume(&dd->audio.state);
+ sa1100_audio_resume(&dd->telecom.state);
+
+ return 0;
+}
+#else
+#define ucb1x00_audio_suspend NULL
+#define ucb1x00_audio_resume NULL
+#endif
+
+static struct ucb1x00_driver ucb1x00_audio_driver = {
+ .add = ucb1x00_audio_add,
+ .remove = ucb1x00_audio_remove,
+ .suspend = ucb1x00_audio_suspend,
+ .resume = ucb1x00_audio_resume,
+};
+
+static int __init ucb1x00_audio_init(void)
+{
+ return ucb1x00_register_driver(&ucb1x00_audio_driver);
+}
+
+static void __exit ucb1x00_audio_exit(void)
+{
+ ucb1x00_unregister_driver(&ucb1x00_audio_driver);
+}
+
+module_init(ucb1x00_audio_init);
+module_exit(ucb1x00_audio_exit);
+
+MODULE_AUTHOR("Russell King <rmk@xxxxxxxxxxxxxxxx>");
+MODULE_DESCRIPTION("UCB1x00 telecom/audio driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index 632bc21..dd973b0 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -28,7 +28,9 @@
#include <asm/dma.h>
#include <asm/hardware.h>

+#include "mcp.h"
#include "ucb1x00.h"
+#include <asm/mach-types.h>

static DEFINE_MUTEX(ucb1x00_mutex);
static LIST_HEAD(ucb1x00_drivers);
@@ -473,15 +475,17 @@ static int ucb1x00_probe(struct mcp *mcp
{
struct ucb1x00 *ucb;
struct ucb1x00_driver *drv;
- unsigned int id;
+ unsigned int id = UCB_ID_1200;
int ret = -ENODEV;

mcp_enable(mcp);
- id = mcp_reg_read(mcp, UCB_ID);
+ if (!machine_is_collie()) {
+ id = mcp_reg_read(mcp, UCB_ID);

- if (id != UCB_ID_1200 && id != UCB_ID_1300) {
- printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
- goto err_disable;
+ if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) {
+ printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
+ goto err_disable;
+ }
}

ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
@@ -501,10 +505,11 @@ static int ucb1x00_probe(struct mcp *mcp

ucb->id = id;
ucb->mcp = mcp;
- ucb->irq = ucb1x00_detect_irq(ucb);
+ ucb->irq = ucb1x00_detect_irq(ucb); /* 44 */
if (ucb->irq == NO_IRQ) {
printk(KERN_ERR "UCB1x00: IRQ probe failed\n");
ret = -ENODEV;
+ panic("UCB1x00: We really want our interrupt\n");
goto err_free;
}

diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index 0277681..b407c0e 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -39,7 +39,6 @@

#include "ucb1x00.h"

-
struct ucb1x00_ts {
struct input_dev *idev;
struct ucb1x00 *ucb;
@@ -55,12 +54,37 @@ struct ucb1x00_ts {

static int adcsync;

+/**********************************
+
+ ................
+ . . = 340
+ . .
+ . ^.
+ . ^.
+ . ^.
+ . ^.
+ . .
+ . X. = 10
+ . <<<<<<<< Y .
+ ................
+ . Sharp =200
+ . .
+ . - O - .
+ . .
+ ................
+
+**********************************/
+
+
+
static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
{
struct input_dev *idev = ts->idev;
+
input_report_abs(idev, ABS_X, x);
input_report_abs(idev, ABS_Y, y);
input_report_abs(idev, ABS_PRESSURE, pressure);
+ input_report_key(idev, BTN_TOUCH, 1);
input_sync(idev);
}

@@ -68,6 +92,7 @@ static inline void ucb1x00_ts_event_rele
{
struct input_dev *idev = ts->idev;
input_report_abs(idev, ABS_PRESSURE, 0);
+ input_report_key(idev, BTN_TOUCH, 0);
input_sync(idev);
}

@@ -86,6 +111,7 @@ static inline void ucb1x00_ts_mode_int(s
* Switch to pressure mode, and read pressure. We don't need to wait
* here, since both plates are being driven.
*/
+/* set_read_pressure() in sharp code */
static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
{
if (machine_is_collie()) {
@@ -129,7 +155,7 @@ static inline unsigned int ucb1x00_ts_re
UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);

- udelay(55);
+ udelay(550);

return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
}
@@ -157,7 +183,7 @@ static inline unsigned int ucb1x00_ts_re
UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);

- udelay(55);
+ udelay(550);

return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
}
@@ -224,10 +250,14 @@ static int ucb1x00_thread(void *_ts)
ts->restart = 0;

ucb1x00_adc_enable(ts->ucb);
-
- x = ucb1x00_ts_read_xpos(ts);
- y = ucb1x00_ts_read_ypos(ts);
p = ucb1x00_ts_read_pressure(ts);
+ ucb1x00_adc_disable(ts->ucb);
+ ucb1x00_adc_enable(ts->ucb);
+ y = ucb1x00_ts_read_ypos(ts);
+ ucb1x00_adc_disable(ts->ucb);
+ ucb1x00_adc_enable(ts->ucb);
+ x = ucb1x00_ts_read_xpos(ts);
+ x = ucb1x00_ts_read_xpos(ts);

/*
* Switch back to interrupt mode.
@@ -255,7 +285,9 @@ static int ucb1x00_thread(void *_ts)
valid = 0;
}

- timeout = MAX_SCHEDULE_TIMEOUT;
+ /* With battery sensing on collie enabled, interrupts do not work quite well.
+ This works around it */
+ timeout = HZ/10;
} else {
ucb1x00_disable(ts->ucb);

@@ -316,6 +348,10 @@ static int ucb1x00_ts_open(struct input_
ts->y_res = ucb1x00_ts_read_yres(ts);
ucb1x00_adc_disable(ts->ucb);

+ if (machine_is_collie()) {
+ ucb1x00_io_set_dir(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
+ }
+
ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd");
if (!IS_ERR(ts->rtask)) {
ret = 0;
@@ -396,6 +432,10 @@ static int ucb1x00_ts_add(struct ucb1x00
__set_bit(ABS_X, ts->idev->absbit);
__set_bit(ABS_Y, ts->idev->absbit);
__set_bit(ABS_PRESSURE, ts->idev->absbit);
+ input_set_abs_params(ts->idev, ABS_X, 0, 450, 0, 0);
+ input_set_abs_params(ts->idev, ABS_Y, 200, 800, 0, 0);
+ input_set_abs_params(ts->idev, ABS_PRESSURE, 400, 800, 0, 0);
+

input_register_device(ts->idev);

@@ -435,3 +475,69 @@ module_exit(ucb1x00_ts_exit);
MODULE_AUTHOR("Russell King <rmk@xxxxxxxxxxxxxxxx>");
MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
MODULE_LICENSE("GPL");
+
+#if 0
+
+static void
+ts_take_ownership(void)
+{
+ /* put back in ts int mode */
+ ucb1200_write_reg(UCB1200_REG_TS_CTL,
+ TSPX_POW | TSMX_POW | TSPY_GND | TSMY_GND |
+ TSC_MODE_INT);
+
+ ucb1200_enable_irq(IRQ_UCB1200_ADC);
+ set_read_pressure();
+}
+
+static void adcx_take_ownership(void);
+
+static void wait_for_action(void)
+{
+ adc_owner = ADC_OWNER_TS;
+ ts_state = PRESSED;
+ sample = 0;
+
+ ucb1200_set_irq_edge(TSPX_INT, GPIO_RISING_EDGE);
+ ucb1200_enable_irq(IRQ_UCB1200_TSPX);
+
+ ucb1200_stop_adc();
+
+ ucb1200_unlock_adc(ucb1200_ts_interrupt);
+
+ ucb1200_write_reg(UCB1200_REG_TS_CTL,
+ TSPX_POW | TSMX_POW | TSPY_GND | TSMY_GND |
+ TSC_MODE_INT);
+
+ /* if adc is waiting, start it */
+ if (adcx_state == ADCX_SAMPLE) {
+ adcx_take_ownership();
+ }
+ idleCancel = 0;
+}
+
+
+static void
+adcx_take_ownership(void)
+{
+ u16 inp = 0;
+
+ adc_owner = ADC_OWNER_ADCX;
+
+ /* take out of ts int mode */
+ ucb1200_write_reg(UCB1200_REG_TS_CTL,
+ TSPX_POW | TSMX_POW | TSPY_GND | TSMY_GND);
+
+ ucb1200_enable_irq(IRQ_UCB1200_ADC);
+
+ switch (adcx_channel) {
+ case 0: inp = ADC_INPUT_AD0; break;
+ case 1: inp = ADC_INPUT_AD1; break;
+ case 2: inp = ADC_INPUT_AD2; break;
+ case 3: inp = ADC_INPUT_AD3; break;
+ }
+
+ ucb1200_start_adc(inp);
+}
+
+#endif
diff --git a/drivers/mfd/ucb1x00.h b/drivers/mfd/ucb1x00.h
index 9c9a647..ca8df80 100644
--- a/drivers/mfd/ucb1x00.h
+++ b/drivers/mfd/ucb1x00.h
@@ -94,6 +94,7 @@
#define UCB_ID 0x0c
#define UCB_ID_1200 0x1004
#define UCB_ID_1300 0x1005
+#define UCB_ID_TC35143 0x9712

#define UCB_MODE 0x0d
#define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
diff --git a/drivers/misc/mcp-ac97.c b/drivers/misc/mcp-ac97.c
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/misc/mcp-core.c b/drivers/misc/mcp-core.c
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/misc/mcp-sa1100.c b/drivers/misc/mcp-sa1100.c
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/misc/ucb1x00-assabet.c b/drivers/misc/ucb1x00-assabet.c
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/misc/ucb1x00-audio.c b/drivers/misc/ucb1x00-audio.c
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/misc/ucb1x00-core.c b/drivers/misc/ucb1x00-core.c
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
index 967abbe..c5212ee 100644
--- a/drivers/mtd/chips/sharp.c
+++ b/drivers/mtd/chips/sharp.c
@@ -25,13 +25,13 @@
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/errno.h>
+#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/cfi.h>
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/slab.h>

#define CMD_RESET 0xffffffff
#define CMD_READ_ID 0x90909090
@@ -60,13 +60,15 @@

#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT)

+#define BLOCK_MASK 0xfffe0000
+
/* Configuration options */

-#undef AUTOUNLOCK /* automatically unlocks blocks before erasing */
+#define AUTOUNLOCK /* automatically unlocks blocks before erasing */

static struct mtd_info *sharp_probe(struct map_info *);

-static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd);
+static int sharp_probe_map(struct map_info *map, struct mtd_info *mtd);

static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
@@ -83,7 +85,7 @@ static int sharp_write_oneword(struct ma
static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
unsigned long adr);
#ifdef AUTOUNLOCK
-static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
+static inline void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
unsigned long adr);
#endif

@@ -105,6 +107,13 @@ static struct mtd_chip_driver sharp_chip
.module = THIS_MODULE
};

+static void sharp_udelay(unsigned long i) {
+ if (in_interrupt()) {
+ udelay(i);
+ } else {
+ schedule();
+ }
+}

static struct mtd_info *sharp_probe(struct map_info *map)
{
@@ -144,7 +153,7 @@ static struct mtd_info *sharp_probe(stru
mtd->name = map->name;

memset(sharp, 0, sizeof(*sharp));
- sharp->chipshift = 23;
+ sharp->chipshift = 24;
sharp->numchips = 1;
sharp->chips[0].start = 0;
sharp->chips[0].state = FL_READY;
@@ -179,8 +188,9 @@ static int sharp_probe_map(struct map_in

read0 = map_read(map, base+0);
read4 = map_read(map, base+4);
- if(read0.x[0] == 0x89898989){
- printk("Looks like sharp flash\n");
+ if (read0.x[0] == 0x00b000b0) {
+ printk("Sharp chip, %lx, %lx, width = %d\n", read0.x[0], read4.x[0], width);
+ /* Prints b000b0, b000b0, width = 4 on collie */
switch(read4.x[0]){
case 0xaaaaaaaa:
case 0xa0a0a0a0:
@@ -195,18 +205,16 @@ static int sharp_probe_map(struct map_in
mtd->erasesize = 0x10000 * width;
mtd->size = 0x100000 * width;
return width;
-#if 0
- case 0x00000000: /* unknown */
- /* XX - LH28F004SCT 512kx8, 8 64k blocks*/
- mtd->erasesize = 0x10000 * width;
- mtd->size = 0x80000 * width;
+ case 0x00b000b0:
+ /* a6 - LH28F640BFHE 8 64k * 2 chip blocks*/
+ mtd->erasesize = 0x10000 * width / 2;
+ mtd->size = 0x800000 * width / 2;
return width;
-#endif
default:
printk("Sort-of looks like sharp flash, 0x%08lx 0x%08lx\n",
read0.x[0], read4.x[0]);
}
- }else if((map_read(map, base+0).x[0] == CMD_READ_ID)){
+ } else if ((map_read(map, base+0).x[0] == CMD_READ_ID)){
/* RAM, probably */
printk("Looks like RAM\n");
map_write(map, tmp, base+0);
@@ -221,7 +229,6 @@ static int sharp_probe_map(struct map_in
/* This function returns with the chip->mutex lock held. */
static int sharp_wait(struct map_info *map, struct flchip *chip)
{
- int i;
map_word status;
unsigned long timeo = jiffies + HZ;
DECLARE_WAITQUEUE(wait, current);
@@ -230,27 +237,30 @@ static int sharp_wait(struct map_info *m
retry:
spin_lock_bh(chip->mutex);

- switch(chip->state){
+ switch (chip->state) {
case FL_READY:
sharp_send_cmd(map, CMD_READ_STATUS, adr);
chip->state = FL_STATUS;
case FL_STATUS:
- for(i=0;i<100;i++){
- status = map_read(map, adr);
- if((status.x[0] & SR_READY)==SR_READY)
- break;
- udelay(1);
+ status = map_read(map, adr);
+ if ((status.x[0] & SR_READY) == SR_READY)
+ break;
+ spin_unlock_bh(chip->mutex);
+ if (time_after(jiffies, timeo)) {
+ printk("Waiting for chip to be ready timed out in erase\n");
+ return -EIO;
}
- break;
+ sharp_udelay(1);
+ goto retry;
default:
- printk("Waiting for chip\n");
-
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);

spin_unlock_bh(chip->mutex);

- schedule();
+ sharp_udelay(1);
+
+ set_current_state(TASK_RUNNING);
remove_wait_queue(&chip->wq, &wait);

if(signal_pending(current))
@@ -355,22 +365,24 @@ static int sharp_write_oneword(struct ma
unsigned long adr, __u32 datum)
{
int ret;
- int timeo;
int try;
int i;
map_word data, status;

status.x[0] = 0;
ret = sharp_wait(map,chip);
+ if (ret < 0)
+ return ret;
+
+ for (try=0; try<10; try++) {
+ long timeo;

- for(try=0;try<10;try++){
sharp_send_cmd(map, CMD_BYTE_WRITE, adr);
/* cpu_to_le32 -> hack to fix the writel be->le conversion */
data.x[0] = cpu_to_le32(datum);
map_write(map, data, adr);

chip->state = FL_WRITING;
-
timeo = jiffies + (HZ/2);

sharp_send_cmd(map, CMD_READ_STATUS, adr);
@@ -379,11 +391,20 @@ static int sharp_write_oneword(struct ma
if((status.x[0] & SR_READY) == SR_READY)
break;
}
+#ifdef AUTOUNLOCK
+ if (status.x[0] & SR_PROTECT) { /* lock block */
+ sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
+ sharp_unlock_oneblock(map,chip,adr);
+ sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
+ sharp_send_cmd(map, CMD_RESET, adr);
+ continue;
+ }
+#endif
if(i==100){
printk("sharp: timed out writing\n");
}

- if(!(status.x[0] & SR_ERRORS))
+ if (!(status.x[0] & SR_ERRORS))
break;

printk("sharp: error writing byte at addr=%08lx status=%08lx\n", adr, status.x[0]);
@@ -393,8 +414,7 @@ static int sharp_write_oneword(struct ma
sharp_send_cmd(map, CMD_RESET, adr);
chip->state = FL_READY;

- wake_up(&chip->wq);
- spin_unlock_bh(chip->mutex);
+ sharp_release(chip);

return 0;
}
@@ -406,7 +426,6 @@ static int sharp_erase(struct mtd_info *
unsigned long adr,len;
int chipnum, ret=0;

-//printk("sharp_erase()\n");
if(instr->addr & (mtd->erasesize - 1))
return -EINVAL;
if(instr->len & (mtd->erasesize - 1))
@@ -422,8 +441,13 @@ static int sharp_erase(struct mtd_info *
ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr);
if(ret)return ret;

- adr += mtd->erasesize;
- len -= mtd->erasesize;
+ if (adr >= 0xfe0000) {
+ adr += mtd->erasesize / 8;
+ len -= mtd->erasesize / 8;
+ } else {
+ adr += mtd->erasesize;
+ len -= mtd->erasesize;
+ }
if(adr >> sharp->chipshift){
adr = 0;
chipnum++;
@@ -438,7 +462,7 @@ static int sharp_erase(struct mtd_info *
return 0;
}

-static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
+static inline int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
unsigned long adr)
{
int ret;
@@ -449,31 +473,27 @@ static int sharp_do_wait_for_ready(struc
sharp_send_cmd(map, CMD_READ_STATUS, adr);
status = map_read(map, adr);

- timeo = jiffies + HZ;
+ timeo = jiffies + HZ * 10;

- while(time_before(jiffies, timeo)){
+ while (time_before(jiffies, timeo)) {
sharp_send_cmd(map, CMD_READ_STATUS, adr);
status = map_read(map, adr);
- if((status.x[0] & SR_READY)==SR_READY){
+ if ((status.x[0] & SR_READY) == SR_READY) {
ret = 0;
goto out;
}
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);

- //spin_unlock_bh(chip->mutex);
+ spin_unlock_bh(chip->mutex);

schedule_timeout(1);
schedule();
- remove_wait_queue(&chip->wq, &wait);

- //spin_lock_bh(chip->mutex);
-
- if (signal_pending(current)){
- ret = -EINTR;
- goto out;
- }
+ spin_lock_bh(chip->mutex);

+ remove_wait_queue(&chip->wq, &wait);
+ set_current_state(TASK_RUNNING);
}
ret = -ETIME;
out:
@@ -484,11 +504,11 @@ static int sharp_erase_oneblock(struct m
unsigned long adr)
{
int ret;
- //int timeo;
map_word status;
- //int i;

-//printk("sharp_erase_oneblock()\n");
+ ret = sharp_wait(map,chip);
+ if (ret < 0)
+ return ret;

#ifdef AUTOUNLOCK
/* This seems like a good place to do an unlock */
@@ -501,53 +521,43 @@ static int sharp_erase_oneblock(struct m
chip->state = FL_ERASING;

ret = sharp_do_wait_for_ready(map,chip,adr);
- if(ret<0)return ret;
+ if(ret<0) {
+ spin_unlock_bh(chip->mutex);
+ return ret;
+ }

sharp_send_cmd(map, CMD_READ_STATUS, adr);
status = map_read(map, adr);

- if(!(status.x[0] & SR_ERRORS)){
+ if (!(status.x[0] & SR_ERRORS)) {
sharp_send_cmd(map, CMD_RESET, adr);
chip->state = FL_READY;
- //spin_unlock_bh(chip->mutex);
+ spin_unlock_bh(chip->mutex);
return 0;
}

printk("sharp: error erasing block at addr=%08lx status=%08lx\n", adr, status.x[0]);
sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);

- //spin_unlock_bh(chip->mutex);
+ sharp_release(chip);

return -EIO;
}

#ifdef AUTOUNLOCK
-static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
+static inline void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
unsigned long adr)
{
- int i;
map_word status;

- sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_1, adr);
- sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_2, adr);
+ sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_1, adr & BLOCK_MASK);
+ sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_2, adr & BLOCK_MASK);

- udelay(100);
+ sharp_do_wait_for_ready(map,chip,adr);

status = map_read(map, adr);
- printk("status=%08lx\n", status.x[0]);
-
- for(i=0;i<1000;i++){
- //sharp_send_cmd(map, CMD_READ_STATUS, adr);
- status = map_read(map, adr);
- if((status.x[0] & SR_READY) == SR_READY)
- break;
- udelay(100);
- }
- if(i==1000){
- printk("sharp: timed out unlocking block\n");
- }

- if(!(status.x[0] & SR_ERRORS)){
+ if (!(status.x[0] & SR_ERRORS)) {
sharp_send_cmd(map, CMD_RESET, adr);
chip->state = FL_READY;
return;
@@ -560,25 +570,59 @@ static void sharp_unlock_oneblock(struct

static void sharp_sync(struct mtd_info *mtd)
{
- //printk("sharp_sync()\n");
}

static int sharp_suspend(struct mtd_info *mtd)
{
- printk("sharp_suspend()\n");
- return -EINVAL;
+ struct map_info *map = mtd->priv;
+ struct sharp_info *sharp = map->fldrv_priv;
+ int i;
+ struct flchip *chip;
+ int ret = 0;
+
+ for (i = 0; !ret && i < sharp->numchips; i++) {
+ chip = &sharp->chips[i];
+ ret = sharp_wait(map,chip);
+
+ if (ret) {
+ ret = -EAGAIN;
+ } else {
+ chip->state = FL_PM_SUSPENDED;
+ spin_unlock_bh(chip->mutex);
+ }
+ }
+ return ret;
}

static void sharp_resume(struct mtd_info *mtd)
{
- printk("sharp_resume()\n");
+ struct map_info *map = mtd->priv;
+ struct sharp_info *sharp = map->fldrv_priv;
+ int i;
+ struct flchip *chip;
+
+ for (i = 0; i < sharp->numchips; i++) {
+ chip = &sharp->chips[i];

+ spin_lock_bh(chip->mutex);
+
+ if (chip->state == FL_PM_SUSPENDED) {
+ /* We need to force it back to a known state */
+ sharp_send_cmd(map, CMD_RESET, chip->start);
+ chip->state = FL_READY;
+ wake_up(&chip->wq);
+ }
+
+ spin_unlock_bh(chip->mutex);
+ }
}

static void sharp_destroy(struct mtd_info *mtd)
{
- printk("sharp_destroy()\n");
+ struct map_info *map = mtd->priv;
+ struct sharp_info *sharp = map->fldrv_priv;

+ kfree(sharp);
}

static int __init sharp_probe_init(void)
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 83d0b2a..449431d 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -427,7 +427,7 @@ config MTD_CDB89712

config MTD_SA1100
tristate "CFI Flash device mapped on StrongARM SA11x0"
- depends on MTD_CFI && ARCH_SA1100 && MTD_PARTITIONS
+ depends on ARM && (MTD_CFI || MTD_SHARP) && ARCH_SA1100 && MTD_PARTITIONS
help
This enables access to the flash chips on most platforms based on
the SA1100 and SA1110, including the Assabet and the Compaq iPAQ.
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 950bf1c..90c1230 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -210,6 +210,10 @@ static int sa1100_probe_subdev(struct sa
goto err;
}
subdev->mtd->owner = THIS_MODULE;
+#ifdef CONFIG_SA1100_COLLIE
+ if (subdev->mtd->unlock) /* Should be only done when we are not using sharp map.. */
+ subdev->mtd->unlock(subdev->mtd, 0xc0000, subdev->mtd->size - 0xc0000);
+#endif

printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "
"%d-bit\n", phys, subdev->mtd->size >> 20,
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index c5b2a44..2a960a3 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -117,5 +117,5 @@ MODULE_AUTHOR("John Dorsey <john+@xxxxxx
MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11x0 Socket Controller");
MODULE_LICENSE("Dual MPL/GPL");

-fs_initcall(sa11x0_pcmcia_init);
+late_initcall(sa11x0_pcmcia_init);
module_exit(sa11x0_pcmcia_exit);
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index ecaa132..7b4bcf5 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -46,6 +46,7 @@
#include <asm/io.h>
#include <asm/system.h>

+#define DEBUG
#include "soc_common.h"

/* FIXME: platform dependent resource declaration has to move out of this file */
@@ -55,7 +56,7 @@

#ifdef DEBUG

-static int pc_debug;
+static int pc_debug = 15;
module_param(pc_debug, int, 0644);

void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func,
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index cbf260b..78a1eb6 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -274,7 +274,7 @@ static int setup_serial(struct pcmcia_de
port.iobase = iobase;
port.irq = irq;
port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
- port.uartclk = 1843200;
+ port.uartclk = 921600 * 16;
port.dev = &handle_to_dev(handle);
if (buggy_uart)
port.flags |= UPF_BUGGY_UART;
diff --git a/drivers/soc/.built-in.o.cmd b/drivers/soc/.built-in.o.cmd
new file mode 100644
index 0000000..23e5d99
--- /dev/null
+++ b/drivers/soc/.built-in.o.cmd
@@ -0,0 +1 @@
+cmd_drivers/soc/built-in.o := rm -f drivers/soc/built-in.o; /scratchbox/compilers/arm-gcc-3.3.4-glibc-2.3.2/bin/arm-linux-ar rcs drivers/soc/built-in.o
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/soc/built-in.o b/drivers/soc/built-in.o
new file mode 100644
index 0000000..8b277f0
--- /dev/null
+++ b/drivers/soc/built-in.o
@@ -0,0 +1 @@
+!<arch>
diff --git a/drivers/soc/tsc2101.c b/drivers/soc/tsc2101.c
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/soc/tsc2101.h b/drivers/soc/tsc2101.h
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
diff --git a/include/asm-arm/arch-pxa/pxa_keys.h b/include/asm-arm/arch-pxa/pxa_keys.h
new file mode 100644
index 0000000..e69de29
diff --git a/include/asm-arm/arch-sa1100/collie.h b/include/asm-arm/arch-sa1100/collie.h
index 14a344a..2078011 100644
--- a/include/asm-arm/arch-sa1100/collie.h
+++ b/include/asm-arm/arch-sa1100/collie.h
@@ -14,6 +14,8 @@
#define __ASM_ARCH_COLLIE_H


+#define Word16 u16
+
#define COLLIE_SCP_CHARGE_ON SCOOP_GPCR_PA11
#define COLLIE_SCP_DIAG_BOOT1 SCOOP_GPCR_PA12
#define COLLIE_SCP_DIAG_BOOT2 SCOOP_GPCR_PA13
@@ -81,4 +83,241 @@
#define COLLIE_TC35143_GPIO_OUT ( UCB_IO_1 | UCB_IO_3 | UCB_IO_4 | UCB_IO_6 | \
UCB_IO_7 | UCB_IO_8 | UCB_IO_9 )

+
+/*
+ * LoCoMo internal I/O mappings
+ *
+ * We have the following mapping:
+ * phys virt
+ * 40000000 f0000000
+ */
+
+/* LoCoMo I/O Base */
+#define LCM_BASE 0x40000000
+#define _LCM( x ) ((x) + LCM_BASE)
+
+#define LCM_p2v( x ) ((x) - LCM_BASE + 0xf0000000)
+#define LCM_v2p( x ) ((x) - 0xf0000000 + LCM_BASE)
+
+/* LCM version */
+#define _LCM_VER _LCM( 0x00 )
+
+/* Pin status */
+#define _LCM_ST _LCM( 0x04 )
+
+/* Pin status */
+#define _LCM_C32K _LCM( 0x08 )
+
+/* Interrupt controller */
+#define _LCM_ICR _LCM( 0x0C )
+
+/* MCS decoder for boot selecting */
+#define _LCM_MCSX0 _LCM( 0x10 )
+#define _LCM_MCSX1 _LCM( 0x14 )
+#define _LCM_MCSX2 _LCM( 0x18 )
+#define _LCM_MCSX3 _LCM( 0x1c )
+
+/* Touch panel controller */
+#define _LCM_ASD _LCM( 0x20 ) /* AD start delay */
+#define _LCM_HSD _LCM( 0x28 ) /* HSYS delay */
+#define _LCM_HSC _LCM( 0x2c ) /* HSYS period */
+#define _LCM_TADC _LCM( 0x30 ) /* tablet ADC clock */
+
+/* TFT signal */
+#define _LCM_TC _LCM( 0x38 ) /* TFT control signal */
+#define _LCM_CPSD _LCM( 0x3c ) /* CPS delay */
+
+/* Key controller */
+#define _LCM_KIB _LCM( 0x40 ) /* KIB level */
+#define _LCM_KSC _LCM( 0x44 ) /* KSTRB control */
+#define _LCM_KCMD _LCM( 0x48 ) /* KSTRB command */
+#define _LCM_KIC _LCM( 0x4c ) /* Key interrupt */
+
+/* Audio clock */
+#define _LCM_ACC _LCM( 0x54 )
+
+/* SPI interface */
+#define _LCM_SPIMD _LCM( 0x60 ) /* SPI mode setting */
+#define _LCM_SPICT _LCM( 0x64 ) /* SPI mode control */
+#define _LCM_SPIST _LCM( 0x68 ) /* SPI status */
+#define _LCM_SPIIS _LCM( 0x70 ) /* SPI interrupt status */
+#define _LCM_SPIWE _LCM( 0x74 ) /* SPI interrupt status write enable */
+#define _LCM_SPIIE _LCM( 0x78 ) /* SPI interrupt enable */
+#define _LCM_SPIIR _LCM( 0x7c ) /* SPI interrupt request */
+#define _LCM_SPITD _LCM( 0x80 ) /* SPI transfer data write */
+#define _LCM_SPIRD _LCM( 0x84 ) /* SPI receive data read */
+#define _LCM_SPITS _LCM( 0x88 ) /* SPI transfer data shift */
+#define _LCM_SPIRS _LCM( 0x8C ) /* SPI receive data shift */
+
+#define LCM_SPI_TEND (1 << 3) /* Transfer end bit */
+#define LCM_SPI_OVRN (1 << 2) /* Over Run bit */
+#define LCM_SPI_RFW (1 << 1) /* write buffer bit */
+#define LCM_SPI_RFR (1) /* read buffer bit */
+
+/* GPIO */
+#define _LCM_GPD _LCM( 0x90 ) /* GPIO direction */
+#define _LCM_GPE _LCM( 0x94 ) /* GPIO input enable */
+#define _LCM_GPL _LCM( 0x98 ) /* GPIO level */
+#define _LCM_GPO _LCM( 0x9c ) /* GPIO out data setteing */
+#define _LCM_GRIE _LCM( 0xa0 ) /* GPIO rise detection */
+#define _LCM_GFIE _LCM( 0xa4 ) /* GPIO fall detection */
+#define _LCM_GIS _LCM( 0xa8 ) /* GPIO edge detection status */
+#define _LCM_GWE _LCM( 0xac ) /* GPIO status write enable */
+#define _LCM_GIE _LCM( 0xb0 ) /* GPIO interrupt enable */
+#define _LCM_GIR _LCM( 0xb4 ) /* GPIO interrupt request */
+
+#define LCM_GPIO0 (1<<0)
+#define LCM_GPIO1 (1<<1)
+#define LCM_GPIO2 (1<<2)
+#define LCM_GPIO3 (1<<3)
+#define LCM_GPIO4 (1<<4)
+#define LCM_GPIO5 (1<<5)
+#define LCM_GPIO6 (1<<6)
+#define LCM_GPIO7 (1<<7)
+#define LCM_GPIO8 (1<<8)
+#define LCM_GPIO9 (1<<9)
+#define LCM_GPIO10 (1<<10)
+#define LCM_GPIO11 (1<<11)
+#define LCM_GPIO12 (1<<12)
+#define LCM_GPIO13 (1<<13)
+#define LCM_GPIO14 (1<<14)
+#define LCM_GPIO15 (1<<15)
+
+/* Front light adjustment controller */
+#define _LCM_ALS _LCM( 0xc8 ) /* Adjust light cycle */
+#define _LCM_ALD _LCM( 0xcc ) /* Adjust light duty */
+
+/* PCM audio interface */
+#define _LCM_PAIF _LCM( 0xd0 )
+
+/* Long time timer */
+#define _LCM_LTC _LCM( 0xd8 ) /* LTC interrupt setting */
+#define _LCM_LTINT _LCM( 0xdc ) /* LTC interrupt */
+
+/* DAC control signal for LCD (COMADJ ) */
+#define _LCM_DAC _LCM( 0xe0 )
+
+/* LED controller */
+#define _LCM_LPT0 _LCM( 0xe8 ) /* LEDPWM0 timer */
+#define _LCM_LPT1 _LCM( 0xec ) /* LEDPWM1 timer */
+
+#define LCM_VER (*((volatile Word16 *) LCM_p2v (_LCM_VER)))
+
+/* Pin status */
+#define LCM_ST (*((volatile Word16 *) LCM_p2v (_LCM_ST)))
+
+/* CLK32K status */
+#define LCM_C32K (*((volatile Word *) LCM_p2v (_LCM_C32K)))
+
+/* Interrupt controller */
+#define LCM_ICR (*((volatile Word16 *) LCM_p2v (_LCM_ICR)))
+
+/* MCS decoder for boot selecting */
+#define LCM_MCSX0 (*((volatile Word16 *) LCM_p2v (_LCM_MCSX0)))
+#define LCM_MCSX1 (*((volatile Word16 *) LCM_p2v (_LCM_MCSX1)))
+#define LCM_MCSX2 (*((volatile Word16 *) LCM_p2v (_LCM_MCSX2)))
+#define LCM_MCSX3 (*((volatile Word16 *) LCM_p2v (_LCM_MCSX3)))
+
+/* Touch panel controller */
+#define LCM_ASD (*((volatile Word16 *) LCM_p2v (_LCM_ASD)))
+#define LCM_HSD (*((volatile Word16 *) LCM_p2v (_LCM_HSD)))
+#define LCM_HSC (*((volatile Word16 *) LCM_p2v (_LCM_HSC)))
+#define LCM_TADC (*((volatile Word16 *) LCM_p2v (_LCM_TADC)))
+
+/* TFT signal */
+#define LCM_TC (*((volatile Word16 *) LCM_p2v (_LCM_TC)))
+#define LCM_CPSD (*((volatile Word16 *) LCM_p2v (_LCM_CPSD)))
+
+/* Key controller */
+#define LCM_KIB (*((volatile Word16 *) LCM_p2v (_LCM_KIB)))
+#define LCM_KSC (*((volatile Word16 *) LCM_p2v (_LCM_KSC)))
+#define LCM_KCMD (*((volatile Word16 *) LCM_p2v (_LCM_KCMD)))
+#define LCM_KIC (*((volatile Word16 *) LCM_p2v (_LCM_KIC)))
+
+/* Audio clock */
+#define LCM_ACC (*((volatile Word16 *) LCM_p2v (_LCM_ACC)))
+
+/* SPI interface */
+#define LCM_SPIMD (*((volatile Word16 *) LCM_p2v (_LCM_SPIMD)))
+#define LCM_SPICT (*((volatile Word16 *) LCM_p2v (_LCM_SPICT)))
+#define LCM_SPIST (*((volatile Word16 *) LCM_p2v (_LCM_SPIST)))
+#define LCM_SPIIS (*((volatile Word16 *) LCM_p2v (_LCM_SPIIS)))
+#define LCM_SPIWE (*((volatile Word16 *) LCM_p2v (_LCM_SPIWE)))
+#define LCM_SPIIE (*((volatile Word16 *) LCM_p2v (_LCM_SPIIE)))
+#define LCM_SPIIR (*((volatile Word16 *) LCM_p2v (_LCM_SPIIR)))
+#define LCM_SPITD (*((volatile Word16 *) LCM_p2v (_LCM_SPITD)))
+#define LCM_SPIRD (*((volatile Word16 *) LCM_p2v (_LCM_SPIRD)))
+#define LCM_SPITS (*((volatile Word16 *) LCM_p2v (_LCM_SPITS)))
+#define LCM_SPIRS (*((volatile Word16 *) LCM_p2v (_LCM_SPIRS)))
+
+/* GPIO */
+#define LCM_GPD (*((volatile Word16 *) LCM_p2v (_LCM_GPD)))
+#define LCM_GPE (*((volatile Word16 *) LCM_p2v (_LCM_GPE)))
+#define LCM_GPL (*((volatile Word16 *) LCM_p2v (_LCM_GPL)))
+#define LCM_GPO (*((volatile Word16 *) LCM_p2v (_LCM_GPO)))
+#define LCM_GRIE (*((volatile Word16 *) LCM_p2v (_LCM_GRIE)))
+#define LCM_GFIE (*((volatile Word16 *) LCM_p2v (_LCM_GFIE)))
+#define LCM_GIS (*((volatile Word16 *) LCM_p2v (_LCM_GIS)))
+#define LCM_GWE (*((volatile Word16 *) LCM_p2v (_LCM_GWE)))
+#define LCM_GIE (*((volatile Word16 *) LCM_p2v (_LCM_GIE)))
+#define LCM_GIR (*((volatile Word16 *) LCM_p2v (_LCM_GIR)))
+
+/* Front light adjustment controller */
+#define LCM_ALS (*((volatile Word16 *) LCM_p2v (_LCM_ALS)))
+#define LCM_ALD (*((volatile Word16 *) LCM_p2v (_LCM_ALD)))
+
+/* PCM audio interface */
+#define LCM_PAIF (*((volatile Word16 *) LCM_p2v (_LCM_PAIF)))
+
+/* Long time timer */
+#define LCM_LTC (*((volatile Word16 *) LCM_p2v (_LCM_LTC)))
+#define LCM_LTINT (*((volatile Word16 *) LCM_p2v (_LCM_LTINT)))
+
+/* DAC control signal */
+#define LCM_DAC (*((volatile Word16 *) LCM_p2v (_LCM_DAC)))
+
+/* DAC control */
+#define LCM_DAC_SCLOEB 0x08 /* SCL pin output data */
+#define LCM_DAC_TEST 0x04 /* Test bit */
+#define LCM_DAC_SDA 0x02 /* SDA pin level (read-only) */
+#define LCM_DAC_SDAOEB 0x01 /* SDA pin output data */
+/* LED controller */
+#define LCM_LPT0 (*((volatile Word16 *) LCM_p2v (_LCM_LPT0)))
+#define LCM_LPT1 (*((volatile Word16 *) LCM_p2v (_LCM_LPT1)))
+
+#define LCM_LPT_TOFH 0x80 /* */
+#define LCM_LPT_TOFL 0x08 /* */
+#define LCM_LPT_TOH(TOH) ((TOH & 0x7) << 4) /* */
+#define LCM_LPT_TOL(TOL) ((TOL & 0x7)) /* */
+
+/* Audio clock */
+#define LCM_ACC_XON 0x80 /* */
+#define LCM_ACC_XEN 0x40 /* */
+#define LCM_ACC_XSEL0 0x00 /* */
+#define LCM_ACC_XSEL1 0x20 /* */
+#define LCM_ACC_MCLKEN 0x10 /* */
+#define LCM_ACC_64FSEN 0x08 /* */
+#define LCM_ACC_CLKSEL000 0x00 /* mclk 2 */
+#define LCM_ACC_CLKSEL001 0x01 /* mclk 3 */
+#define LCM_ACC_CLKSEL010 0x02 /* mclk 4 */
+#define LCM_ACC_CLKSEL011 0x03 /* mclk 6 */
+#define LCM_ACC_CLKSEL100 0x04 /* mclk 8 */
+#define LCM_ACC_CLKSEL101 0x05 /* mclk 12 */
+
+/* PCM audio interface */
+#define LCM_PAIF_SCINV 0x20 /* */
+#define LCM_PAIF_SCEN 0x10 /* */
+#define LCM_PAIF_LRCRST 0x08 /* */
+#define LCM_PAIF_LRCEVE 0x04 /* */
+#define LCM_PAIF_LRCINV 0x02 /* */
+#define LCM_PAIF_LRCEN 0x01 /* */
+
+/* GPIO */
+#define LCM_GPIO(Nb) (0x01 << (Nb)) /* LoCoMo GPIO [0...15] */
+
+#define LCM_GPIO_DAC_ON LCM_GPIO (8) /* LoCoMo GPIO [8] */
+#define LCM_GPIO_DAC_SDATA LCM_GPIO (10) /* LoCoMo GPIO [10] */
+#define LCM_GPIO_DAC_SCK LCM_GPIO (11) /* LoCoMo GPIO [11] */
+#define LCM_GPIO_DAC_SLOAD LCM_GPIO (12) /* LoCoMo GPIO [12] */
+
#endif
diff --git a/include/linux/device.h b/include/linux/device.h
index 1e5f30d..ef34988 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -418,7 +418,7 @@ extern void firmware_unregister(struct s
/* debugging and troubleshooting/diagnostic helpers. */
extern const char *dev_driver_string(struct device *dev);
#define dev_printk(level, dev, format, arg...) \
- printk(level "%s %s: " format , dev_driver_string(dev) , (dev)->bus_id , ## arg)
+ printk(level "%s %s: " format , (!dev) ? "" : (dev)->driver ? (dev)->driver->name : "" , (dev)->bus_id , ## arg)

#ifdef DEBUG
#define dev_dbg(dev, format, arg...) \
diff --git a/include/linux/plist.h b/include/linux/plist.h
index b95818a..bdd64bb 100644
--- a/include/linux/plist.h
+++ b/include/linux/plist.h
@@ -76,6 +76,7 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/spinlock_types.h>
+#include <linux/kernel.h>

struct plist_head {
struct list_head prio_list;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 54a4f53..efee0fb 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2208,11 +2208,13 @@ void setup_per_zone_pages_min(void)
}

for_each_zone(zone) {
- u64 tmp;
+ volatile u32 tmp;

+ barrier();
spin_lock_irqsave(&zone->lru_lock, flags);
- tmp = (u64)pages_min * zone->present_pages;
- do_div(tmp, lowmem_pages);
+ barrier();
+ tmp = (u32)pages_min * zone->present_pages;
+ tmp = tmp / lowmem_pages;
if (is_highmem(zone)) {
/*
* __GFP_HIGH and PF_MEMALLOC allocations usually don't
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 5d4c4d0..efdb26a 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -179,13 +179,13 @@ unsigned long shrink_slab(unsigned long
return 1; /* Assume we'll be able to shrink next time */

list_for_each_entry(shrinker, &shrinker_list, list) {
- unsigned long long delta;
+ unsigned long delta;
unsigned long total_scan;
unsigned long max_pass = (*shrinker->shrinker)(0, gfp_mask);

delta = (4 * scanned) / shrinker->seeks;
- delta *= max_pass;
- do_div(delta, lru_pages + 1);
+ delta *= (*shrinker->shrinker)(0, gfp_mask);
+ delta = delta / (lru_pages + 1);
shrinker->nr += delta;
if (shrinker->nr < 0) {
printk(KERN_ERR "%s: nr=%ld\n",
diff --git a/sound/soc/.built-in.o.cmd b/sound/soc/.built-in.o.cmd
new file mode 100644
index 0000000..3d8f3fc
--- /dev/null
+++ b/sound/soc/.built-in.o.cmd
@@ -0,0 +1 @@
+cmd_sound/soc/built-in.o := rm -f sound/soc/built-in.o; /scratchbox/compilers/arm-gcc-3.3.4-glibc-2.3.2/bin/arm-linux-ar rcs sound/soc/built-in.o
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
new file mode 100644
index 0000000..e69de29
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
new file mode 100644
index 0000000..e69de29
diff --git a/sound/soc/built-in.o b/sound/soc/built-in.o
new file mode 100644
index 0000000..8b277f0
--- /dev/null
+++ b/sound/soc/built-in.o
@@ -0,0 +1 @@
+!<arch>
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
new file mode 100644
index 0000000..e69de29



--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/