bump to 2.6.30-rc6

SVN-Revision: 15918
This commit is contained in:
Lars-Peter Clausen
2009-05-18 17:55:41 +00:00
parent 267af10b33
commit f5affd4f36
159 changed files with 55656 additions and 1 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,812 @@
Index: linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/pwm.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/pwm.h 2009-05-18 19:08:30.000000000 +0200
@@ -0,0 +1,45 @@
+#ifndef __S3C2410_PWM_H
+#define __S3C2410_PWM_H
+
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <mach/io.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <plat/regs-timer.h>
+
+enum pwm_timer {
+ PWM0,
+ PWM1,
+ PWM2,
+ PWM3,
+ PWM4
+};
+
+struct s3c2410_pwm {
+ enum pwm_timer timerid;
+ struct clk *pclk;
+ unsigned long pclk_rate;
+ unsigned long prescaler;
+ unsigned long divider;
+ unsigned long counter;
+ unsigned long comparer;
+};
+
+struct s3c24xx_pwm_platform_data{
+ /* callback to attach platform children (to enforce suspend / resume
+ * ordering */
+ void (*attach_child_devices)(struct device *parent_device);
+};
+
+int s3c2410_pwm_init(struct s3c2410_pwm *s3c2410_pwm);
+int s3c2410_pwm_enable(struct s3c2410_pwm *s3c2410_pwm);
+int s3c2410_pwm_disable(struct s3c2410_pwm *s3c2410_pwm);
+int s3c2410_pwm_start(struct s3c2410_pwm *s3c2410_pwm);
+int s3c2410_pwm_stop(struct s3c2410_pwm *s3c2410_pwm);
+int s3c2410_pwm_duty_cycle(int reg_value, struct s3c2410_pwm *s3c2410_pwm);
+int s3c2410_pwm_dumpregs(void);
+
+#endif /* __S3C2410_PWM_H */
Index: linux-2.6.30-rc6/arch/arm/plat-s3c/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/Kconfig 2009-05-18 19:08:29.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/plat-s3c/Kconfig 2009-05-18 19:08:30.000000000 +0200
@@ -157,6 +157,11 @@
help
Internal configuration for S3C DMA core
+config S3C_PWM
+ bool
+ help
+ PWM timer code for the S3C2410, and similar processors
+
# device definitions to compile in
config S3C_DEV_HSMMC
Index: linux-2.6.30-rc6/arch/arm/plat-s3c/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/Makefile 2009-05-18 19:08:29.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/plat-s3c/Makefile 2009-05-18 19:08:30.000000000 +0200
@@ -35,5 +35,6 @@
obj-y += dev-i2c0.o
obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o
obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o
+obj-$(CONFIG_S3C_PWM) += pwm.o
obj-$(CONFIG_S3C_DMA) += dma.o
Index: linux-2.6.30-rc6/arch/arm/plat-s3c/pwm.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.30-rc6/arch/arm/plat-s3c/pwm.c 2009-05-18 19:08:30.000000000 +0200
@@ -0,0 +1,288 @@
+/*
+ * arch/arm/plat-s3c/pwm.c
+ *
+ * Copyright (c) by Javi Roman <javiroman@kernel-labs.org>
+ * for the Openmoko Project.
+ *
+ * S3C2410A SoC PWM support
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <mach/hardware.h>
+#include <plat/regs-timer.h>
+#include <plat/pwm.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_PM
+ static unsigned long standby_reg_tcon;
+ static unsigned long standby_reg_tcfg0;
+ static unsigned long standby_reg_tcfg1;
+#endif
+
+int s3c2410_pwm_disable(struct s3c2410_pwm *pwm)
+{
+ unsigned long tcon;
+
+ /* stop timer */
+ tcon = __raw_readl(S3C2410_TCON);
+ tcon &= 0xffffff00;
+ __raw_writel(tcon, S3C2410_TCON);
+
+ clk_disable(pwm->pclk);
+ clk_put(pwm->pclk);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_disable);
+
+int s3c2410_pwm_init(struct s3c2410_pwm *pwm)
+{
+ pwm->pclk = clk_get(NULL, "timers");
+ if (IS_ERR(pwm->pclk))
+ return PTR_ERR(pwm->pclk);
+
+ clk_enable(pwm->pclk);
+ pwm->pclk_rate = clk_get_rate(pwm->pclk);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_init);
+
+int s3c2410_pwm_enable(struct s3c2410_pwm *pwm)
+{
+ unsigned long tcfg0, tcfg1, tcnt, tcmp;
+
+ /* control registers bits */
+ tcfg1 = __raw_readl(S3C2410_TCFG1);
+ tcfg0 = __raw_readl(S3C2410_TCFG0);
+
+ /* divider & scaler slection */
+ switch (pwm->timerid) {
+ case PWM0:
+ tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
+ tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
+ break;
+ case PWM1:
+ tcfg1 &= ~S3C2410_TCFG1_MUX1_MASK;
+ tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
+ break;
+ case PWM2:
+ tcfg1 &= ~S3C2410_TCFG1_MUX2_MASK;
+ tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
+ break;
+ case PWM3:
+ tcfg1 &= ~S3C2410_TCFG1_MUX3_MASK;
+ tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
+ break;
+ case PWM4:
+ /* timer four is not capable of doing PWM */
+ break;
+ default:
+ clk_disable(pwm->pclk);
+ clk_put(pwm->pclk);
+ return -1;
+ }
+
+ /* divider & scaler values */
+ tcfg1 |= pwm->divider;
+ __raw_writel(tcfg1, S3C2410_TCFG1);
+
+ switch (pwm->timerid) {
+ case PWM0:
+ case PWM1:
+ tcfg0 |= pwm->prescaler;
+ __raw_writel(tcfg0, S3C2410_TCFG0);
+ break;
+ default:
+ if ((tcfg0 | pwm->prescaler) != tcfg0) {
+ printk(KERN_WARNING "not changing prescaler of PWM %u,"
+ " since it's shared with timer4 (clock tick)\n",
+ pwm->timerid);
+ }
+ break;
+ }
+
+ /* timer count and compare buffer initial values */
+ tcnt = pwm->counter;
+ tcmp = pwm->comparer;
+
+ __raw_writel(tcnt, S3C2410_TCNTB(pwm->timerid));
+ __raw_writel(tcmp, S3C2410_TCMPB(pwm->timerid));
+
+ /* ensure timer is stopped */
+ s3c2410_pwm_stop(pwm);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_enable);
+
+int s3c2410_pwm_start(struct s3c2410_pwm *pwm)
+{
+ unsigned long tcon;
+
+ tcon = __raw_readl(S3C2410_TCON);
+
+ switch (pwm->timerid) {
+ case PWM0:
+ tcon |= S3C2410_TCON_T0START;
+ tcon &= ~S3C2410_TCON_T0MANUALUPD;
+ break;
+ case PWM1:
+ tcon |= S3C2410_TCON_T1START;
+ tcon &= ~S3C2410_TCON_T1MANUALUPD;
+ break;
+ case PWM2:
+ tcon |= S3C2410_TCON_T2START;
+ tcon &= ~S3C2410_TCON_T2MANUALUPD;
+ break;
+ case PWM3:
+ tcon |= S3C2410_TCON_T3START;
+ tcon &= ~S3C2410_TCON_T3MANUALUPD;
+ break;
+ case PWM4:
+ /* timer four is not capable of doing PWM */
+ default:
+ return -ENODEV;
+ }
+
+ __raw_writel(tcon, S3C2410_TCON);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_start);
+
+int s3c2410_pwm_stop(struct s3c2410_pwm *pwm)
+{
+ unsigned long tcon;
+
+ tcon = __raw_readl(S3C2410_TCON);
+
+ switch (pwm->timerid) {
+ case PWM0:
+ tcon &= ~0x00000000;
+ tcon |= S3C2410_TCON_T0RELOAD;
+ tcon |= S3C2410_TCON_T0MANUALUPD;
+ break;
+ case PWM1:
+ tcon &= ~0x00000080;
+ tcon |= S3C2410_TCON_T1RELOAD;
+ tcon |= S3C2410_TCON_T1MANUALUPD;
+ break;
+ case PWM2:
+ tcon &= ~0x00000800;
+ tcon |= S3C2410_TCON_T2RELOAD;
+ tcon |= S3C2410_TCON_T2MANUALUPD;
+ break;
+ case PWM3:
+ tcon &= ~0x00008000;
+ tcon |= S3C2410_TCON_T3RELOAD;
+ tcon |= S3C2410_TCON_T3MANUALUPD;
+ break;
+ case PWM4:
+ /* timer four is not capable of doing PWM */
+ default:
+ return -ENODEV;
+ }
+
+ __raw_writel(tcon, S3C2410_TCON);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_stop);
+
+int s3c2410_pwm_duty_cycle(int reg_value, struct s3c2410_pwm *pwm)
+{
+ __raw_writel(reg_value, S3C2410_TCMPB(pwm->timerid));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_duty_cycle);
+
+int s3c2410_pwm_dumpregs(void)
+{
+ printk(KERN_INFO "TCON: %08lx, TCFG0: %08lx, TCFG1: %08lx\n",
+ (unsigned long) __raw_readl(S3C2410_TCON),
+ (unsigned long) __raw_readl(S3C2410_TCFG0),
+ (unsigned long) __raw_readl(S3C2410_TCFG1));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s3c2410_pwm_dumpregs);
+
+static int __init s3c24xx_pwm_probe(struct platform_device *pdev)
+{
+ struct s3c24xx_pwm_platform_data *pdata = pdev->dev.platform_data;
+
+ dev_info(&pdev->dev, "s3c24xx_pwm is registered \n");
+
+ /* if platform was interested, give him a chance to register
+ * platform devices that switch power with us as the parent
+ * at registration time -- ensures suspend / resume ordering
+ */
+ if (pdata)
+ if (pdata->attach_child_devices)
+ (pdata->attach_child_devices)(&pdev->dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int s3c24xx_pwm_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ /* PWM config should be kept in suspending */
+ standby_reg_tcon = __raw_readl(S3C2410_TCON);
+ standby_reg_tcfg0 = __raw_readl(S3C2410_TCFG0);
+ standby_reg_tcfg1 = __raw_readl(S3C2410_TCFG1);
+
+ return 0;
+}
+
+static int s3c24xx_pwm_resume(struct platform_device *pdev)
+{
+ __raw_writel(standby_reg_tcon, S3C2410_TCON);
+ __raw_writel(standby_reg_tcfg0, S3C2410_TCFG0);
+ __raw_writel(standby_reg_tcfg1, S3C2410_TCFG1);
+
+ return 0;
+}
+#else
+#define s3c24xx_pwm_suspend NULL
+#define s3c24xx_pwm_resume NULL
+#endif
+
+static struct platform_driver s3c24xx_pwm_driver = {
+ .driver = {
+ .name = "s3c24xx_pwm",
+ .owner = THIS_MODULE,
+ },
+ .probe = s3c24xx_pwm_probe,
+ .suspend = s3c24xx_pwm_suspend,
+ .resume = s3c24xx_pwm_resume,
+};
+
+static int __init s3c24xx_pwm_init(void)
+{
+ return platform_driver_register(&s3c24xx_pwm_driver);
+}
+
+static void __exit s3c24xx_pwm_exit(void)
+{
+}
+
+MODULE_AUTHOR("Javi Roman <javiroman@kernel-labs.org>");
+MODULE_LICENSE("GPL");
+
+module_init(s3c24xx_pwm_init);
+module_exit(s3c24xx_pwm_exit);
Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/pwm-clock.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/pwm-clock.c 2009-05-18 19:08:30.000000000 +0200
@@ -0,0 +1,437 @@
+/* linux/arch/arm/plat-s3c24xx/pwm-clock.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ * Copyright (c) 2007, 2008 Ben Dooks
+ * Ben Dooks <ben-linux@fluff.org>
+ *
+ * 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.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+#include <asm/plat-s3c/regs-timer.h>
+
+/* Each of the timers 0 through 5 go through the following
+ * clock tree, with the inputs depending on the timers.
+ *
+ * pclk ---- [ prescaler 0 ] -+---> timer 0
+ * +---> timer 1
+ *
+ * pclk ---- [ prescaler 1 ] -+---> timer 2
+ * +---> timer 3
+ * \---> timer 4
+ *
+ * Which are fed into the timers as so:
+ *
+ * prescaled 0 ---- [ div 2,4,8,16 ] ---\
+ * [mux] -> timer 0
+ * tclk 0 ------------------------------/
+ *
+ * prescaled 0 ---- [ div 2,4,8,16 ] ---\
+ * [mux] -> timer 1
+ * tclk 0 ------------------------------/
+ *
+ *
+ * prescaled 1 ---- [ div 2,4,8,16 ] ---\
+ * [mux] -> timer 2
+ * tclk 1 ------------------------------/
+ *
+ * prescaled 1 ---- [ div 2,4,8,16 ] ---\
+ * [mux] -> timer 3
+ * tclk 1 ------------------------------/
+ *
+ * prescaled 1 ---- [ div 2,4,8, 16 ] --\
+ * [mux] -> timer 4
+ * tclk 1 ------------------------------/
+ *
+ * Since the mux and the divider are tied together in the
+ * same register space, it is impossible to set the parent
+ * and the rate at the same time. To avoid this, we add an
+ * intermediate 'prescaled-and-divided' clock to select
+ * as the parent for the timer input clock called tdiv.
+ *
+ * prescaled clk --> pwm-tdiv ---\
+ * [ mux ] --> timer X
+ * tclk -------------------------/
+*/
+
+static unsigned long clk_pwm_scaler_getrate(struct clk *clk)
+{
+ unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0);
+
+ if (clk->id == 1) {
+ tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK;
+ tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT;
+ } else {
+ tcfg0 &= S3C2410_TCFG_PRESCALER0_MASK;
+ }
+
+ return clk_get_rate(clk->parent) / (tcfg0 + 1);
+}
+
+/* TODO - add set rate calls. */
+
+static struct clk clk_timer_scaler[] = {
+ [0] = {
+ .name = "pwm-scaler0",
+ .id = -1,
+ .get_rate = clk_pwm_scaler_getrate,
+ },
+ [1] = {
+ .name = "pwm-scaler1",
+ .id = -1,
+ .get_rate = clk_pwm_scaler_getrate,
+ },
+};
+
+static struct clk clk_timer_tclk[] = {
+ [0] = {
+ .name = "pwm-tclk0",
+ .id = -1,
+ },
+ [1] = {
+ .name = "pwm-tclk1",
+ .id = -1,
+ },
+};
+
+struct pwm_tdiv_clk {
+ struct clk clk;
+ unsigned int divisor;
+};
+
+static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk)
+{
+ return container_of(clk, struct pwm_tdiv_clk, clk);
+}
+
+static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
+{
+ return 1 << (1 + tcfg1);
+}
+
+static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk)
+{
+ unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
+ unsigned int divisor;
+
+ tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
+ tcfg1 &= S3C2410_TCFG1_MUX_MASK;
+
+ if (tcfg1 == S3C2410_TCFG1_MUX_TCLK)
+ divisor = to_tdiv(clk)->divisor;
+ else
+ divisor = tcfg_to_divisor(tcfg1);
+
+ return clk_get_rate(clk->parent) / divisor;
+}
+
+static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ unsigned long parent_rate;
+ unsigned long divisor;
+
+ parent_rate = clk_get_rate(clk->parent);
+ divisor = parent_rate / rate;
+
+ if (divisor <= 2)
+ divisor = 2;
+ else if (divisor <= 4)
+ divisor = 4;
+ else if (divisor <= 8)
+ divisor = 8;
+ else
+ divisor = 16;
+
+ return parent_rate / divisor;
+}
+
+static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk)
+{
+ unsigned long bits;
+
+ switch (divclk->divisor) {
+ case 2:
+ bits = S3C2410_TCFG1_MUX_DIV2;
+ break;
+ case 4:
+ bits = S3C2410_TCFG1_MUX_DIV4;
+ break;
+ case 8:
+ bits = S3C2410_TCFG1_MUX_DIV8;
+ break;
+ case 16:
+ default:
+ bits = S3C2410_TCFG1_MUX_DIV16;
+ break;
+ }
+
+ return bits;
+}
+
+static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk)
+{
+ unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
+ unsigned long bits = clk_pwm_tdiv_bits(divclk);
+ unsigned long flags;
+ unsigned long shift = S3C2410_TCFG1_SHIFT(divclk->clk.id);
+
+ local_irq_save(flags);
+
+ tcfg1 = __raw_readl(S3C2410_TCFG1);
+ tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
+ tcfg1 |= bits << shift;
+ __raw_writel(tcfg1, S3C2410_TCFG1);
+
+ local_irq_restore(flags);
+}
+
+static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct pwm_tdiv_clk *divclk = to_tdiv(clk);
+ unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long divisor;
+
+ tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
+ tcfg1 &= S3C2410_TCFG1_MUX_MASK;
+
+ rate = clk_round_rate(clk, rate);
+ divisor = parent_rate / rate;
+
+ if (divisor > 16)
+ return -EINVAL;
+
+ divclk->divisor = divisor;
+
+ /* Update the current MUX settings if we are currently
+ * selected as the clock source for this clock. */
+
+ if (tcfg1 != S3C2410_TCFG1_MUX_TCLK)
+ clk_pwm_tdiv_update(divclk);
+
+ return 0;
+}
+
+static struct pwm_tdiv_clk clk_timer_tdiv[] = {
+ [0] = {
+ .clk = {
+ .name = "pwm-tdiv",
+ .parent = &clk_timer_scaler[0],
+ .get_rate = clk_pwm_tdiv_get_rate,
+ .set_rate = clk_pwm_tdiv_set_rate,
+ .round_rate = clk_pwm_tdiv_round_rate,
+ },
+ },
+ [1] = {
+ .clk = {
+ .name = "pwm-tdiv",
+ .parent = &clk_timer_scaler[0],
+ .get_rate = clk_pwm_tdiv_get_rate,
+ .set_rate = clk_pwm_tdiv_set_rate,
+ .round_rate = clk_pwm_tdiv_round_rate,
+ }
+ },
+ [2] = {
+ .clk = {
+ .name = "pwm-tdiv",
+ .parent = &clk_timer_scaler[1],
+ .get_rate = clk_pwm_tdiv_get_rate,
+ .set_rate = clk_pwm_tdiv_set_rate,
+ .round_rate = clk_pwm_tdiv_round_rate,
+ },
+ },
+ [3] = {
+ .clk = {
+ .name = "pwm-tdiv",
+ .parent = &clk_timer_scaler[1],
+ .get_rate = clk_pwm_tdiv_get_rate,
+ .set_rate = clk_pwm_tdiv_set_rate,
+ .round_rate = clk_pwm_tdiv_round_rate,
+ },
+ },
+ [4] = {
+ .clk = {
+ .name = "pwm-tdiv",
+ .parent = &clk_timer_scaler[1],
+ .get_rate = clk_pwm_tdiv_get_rate,
+ .set_rate = clk_pwm_tdiv_set_rate,
+ .round_rate = clk_pwm_tdiv_round_rate,
+ },
+ },
+};
+
+static int __init clk_pwm_tdiv_register(unsigned int id)
+{
+ struct pwm_tdiv_clk *divclk = &clk_timer_tdiv[id];
+ unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
+
+ tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
+ tcfg1 &= S3C2410_TCFG1_MUX_MASK;
+
+ divclk->clk.id = id;
+ divclk->divisor = tcfg_to_divisor(tcfg1);
+
+ return s3c24xx_register_clock(&divclk->clk);
+}
+
+static inline struct clk *s3c24xx_pwmclk_tclk(unsigned int id)
+{
+ return (id >= 2) ? &clk_timer_tclk[1] : &clk_timer_tclk[0];
+}
+
+static inline struct clk *s3c24xx_pwmclk_tdiv(unsigned int id)
+{
+ return &clk_timer_tdiv[id].clk;
+}
+
+static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent)
+{
+ unsigned int id = clk->id;
+ unsigned long tcfg1;
+ unsigned long flags;
+ unsigned long bits;
+ unsigned long shift = S3C2410_TCFG1_SHIFT(id);
+
+ if (parent == s3c24xx_pwmclk_tclk(id))
+ bits = S3C2410_TCFG1_MUX_TCLK << shift;
+ else if (parent == s3c24xx_pwmclk_tdiv(id))
+ bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift;
+ else
+ return -EINVAL;
+
+ clk->parent = parent;
+
+ local_irq_save(flags);
+
+ tcfg1 = __raw_readl(S3C2410_TCFG1);
+ tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
+ __raw_writel(tcfg1 | bits, S3C2410_TCFG1);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static struct clk clk_tin[] = {
+ [0] = {
+ .name = "pwm-tin",
+ .id = 0,
+ .set_parent = clk_pwm_tin_set_parent,
+ },
+ [1] = {
+ .name = "pwm-tin",
+ .id = 1,
+ .set_parent = clk_pwm_tin_set_parent,
+ },
+ [2] = {
+ .name = "pwm-tin",
+ .id = 2,
+ .set_parent = clk_pwm_tin_set_parent,
+ },
+ [3] = {
+ .name = "pwm-tin",
+ .id = 3,
+ .set_parent = clk_pwm_tin_set_parent,
+ },
+ [4] = {
+ .name = "pwm-tin",
+ .id = 4,
+ .set_parent = clk_pwm_tin_set_parent,
+ },
+};
+
+static __init int clk_pwm_tin_register(struct clk *pwm)
+{
+ unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
+ unsigned int id = pwm->id;
+
+ struct clk *parent;
+ int ret;
+
+ ret = s3c24xx_register_clock(pwm);
+ if (ret < 0)
+ return ret;
+
+ tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
+ tcfg1 &= S3C2410_TCFG1_MUX_MASK;
+
+ if (tcfg1 == S3C2410_TCFG1_MUX_TCLK)
+ parent = s3c24xx_pwmclk_tclk(id);
+ else
+ parent = s3c24xx_pwmclk_tdiv(id);
+
+ return clk_set_parent(pwm, parent);
+}
+
+static __init int s3c24xx_pwmclk_init(void)
+{
+ struct clk *clk_timers;
+ unsigned int clk;
+ int ret;
+
+ clk_timers = clk_get(NULL, "timers");
+ if (IS_ERR(clk_timers)) {
+ printk(KERN_ERR "%s: no parent clock\n", __func__);
+ return -EINVAL;
+ }
+
+ for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) {
+ clk_timer_scaler[clk].parent = clk_timers;
+ ret = s3c24xx_register_clock(&clk_timer_scaler[clk]);
+ if (ret < 0) {
+ printk(KERN_ERR "error adding pwm scaler%d clock\n", clk);
+ goto err;
+ }
+ }
+
+ for (clk = 0; clk < ARRAY_SIZE(clk_timer_tclk); clk++) {
+ ret = s3c24xx_register_clock(&clk_timer_tclk[clk]);
+ if (ret < 0) {
+ printk(KERN_ERR "error adding pww tclk%d\n", clk);
+ goto err;
+ }
+ }
+
+ for (clk = 0; clk < ARRAY_SIZE(clk_timer_tdiv); clk++) {
+ ret = clk_pwm_tdiv_register(clk);
+ if (ret < 0) {
+ printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk);
+ goto err;
+ }
+ }
+
+ for (clk = 0; clk < ARRAY_SIZE(clk_tin); clk++) {
+ ret = clk_pwm_tin_register(&clk_tin[clk]);
+ if (ret < 0) {
+ printk(KERN_ERR "error adding pwm%d tin clock\n", clk);
+ goto err;
+ }
+ }
+
+ return 0;
+
+ err:
+ return ret;
+}
+
+arch_initcall(s3c24xx_pwmclk_init);

View File

@@ -0,0 +1,488 @@
Index: linux-2.6.30-rc6/arch/arm/plat-s3c/dev-usb.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.30-rc6/arch/arm/plat-s3c/dev-usb.c 2009-05-18 19:08:30.000000000 +0200
@@ -0,0 +1,50 @@
+/* linux/arch/arm/plat-s3c/dev-usb.c
+ *
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * S3C series device definition for USB host
+ *
+ * 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/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+
+static struct resource s3c_usb_resource[] = {
+ [0] = {
+ .start = S3C24XX_PA_USBHOST,
+ .end = S3C24XX_PA_USBHOST + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_USBH,
+ .end = IRQ_USBH,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static u64 s3c_device_usb_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_usb = {
+ .name = "s3c-ohci",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_usb_resource),
+ .resource = s3c_usb_resource,
+ .dev = {
+ .dma_mask = &s3c_device_usb_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+
+EXPORT_SYMBOL(s3c_device_usb);
Index: linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/regs-usb-hs-otg.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/regs-usb-hs-otg.h 2009-05-18 19:08:30.000000000 +0200
@@ -0,0 +1,360 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-udc.h
+ *
+ * Copyright (C) 2008 Samsung Electronics
+ * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
+ *
+ * This include file 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.
+*/
+
+#ifndef __ASM_ARCH_REGS_USB_HS_OTG_H
+#define __ASM_ARCH_REGS_USB_HS_OTG_H
+
+/* USB2.0 OTG Controller register */
+#define S3C_USBOTG_PHYREG(x) ((x) + 0x100000 /* S3C64XX_VA_OTGSFR */)
+#define S3C_USBOTG_PHYPWR S3C_USBOTG_PHYREG(0x0)
+#define S3C_USBOTG_PHYCLK S3C_USBOTG_PHYREG(0x4)
+#define S3C_USBOTG_RSTCON S3C_USBOTG_PHYREG(0x8)
+
+/* USB2.0 OTG Controller register */
+/* Core Global Registers */
+#define S3C_USBOTGREG(x) ((x) /*+ S3C64XX_VA_OTG */)
+/* OTG Control & Status */
+#define S3C_UDC_OTG_GOTGCTL S3C_USBOTGREG(0x000)
+/* OTG Interrupt */
+#define S3C_UDC_OTG_GOTGINT S3C_USBOTGREG(0x004)
+/* Core AHB Configuration */
+#define S3C_UDC_OTG_GAHBCFG S3C_USBOTGREG(0x008)
+/* Core USB Configuration */
+#define S3C_UDC_OTG_GUSBCFG S3C_USBOTGREG(0x00C)
+/* Core Reset */
+#define S3C_UDC_OTG_GRSTCTL S3C_USBOTGREG(0x010)
+/* Core Interrupt */
+#define S3C_UDC_OTG_GINTSTS S3C_USBOTGREG(0x014)
+/* Core Interrupt Mask */
+#define S3C_UDC_OTG_GINTMSK S3C_USBOTGREG(0x018)
+/* Receive Status Debug Read/Status Read */
+#define S3C_UDC_OTG_GRXSTSR S3C_USBOTGREG(0x01C)
+/* Receive Status Debug Pop/Status Pop */
+#define S3C_UDC_OTG_GRXSTSP S3C_USBOTGREG(0x020)
+/* Receive FIFO Size */
+#define S3C_UDC_OTG_GRXFSIZ S3C_USBOTGREG(0x024)
+/* Non-Periodic Transmit FIFO Size */
+#define S3C_UDC_OTG_GNPTXFSIZ S3C_USBOTGREG(0x028)
+/* Non-Periodic Transmit FIFO/Queue Status */
+#define S3C_UDC_OTG_GNPTXSTS S3C_USBOTGREG(0x02C)
+
+/* Host Periodic Transmit FIFO Size */
+#define S3C_UDC_OTG_HPTXFSIZ S3C_USBOTGREG(0x100)
+/* Device Periodic Transmit FIFO-1 Size */
+#define S3C_UDC_OTG_DPTXFSIZ1 S3C_USBOTGREG(0x104)
+/* Device Periodic Transmit FIFO-2 Size */
+#define S3C_UDC_OTG_DPTXFSIZ2 S3C_USBOTGREG(0x108)
+/* Device Periodic Transmit FIFO-3 Size */
+#define S3C_UDC_OTG_DPTXFSIZ3 S3C_USBOTGREG(0x10C)
+/* Device Periodic Transmit FIFO-4 Size */
+#define S3C_UDC_OTG_DPTXFSIZ4 S3C_USBOTGREG(0x110)
+/* Device Periodic Transmit FIFO-5 Size */
+#define S3C_UDC_OTG_DPTXFSIZ5 S3C_USBOTGREG(0x114)
+/* Device Periodic Transmit FIFO-6 Size */
+#define S3C_UDC_OTG_DPTXFSIZ6 S3C_USBOTGREG(0x118)
+/* Device Periodic Transmit FIFO-7 Size */
+#define S3C_UDC_OTG_DPTXFSIZ7 S3C_USBOTGREG(0x11C)
+/* Device Periodic Transmit FIFO-8 Size */
+#define S3C_UDC_OTG_DPTXFSIZ8 S3C_USBOTGREG(0x120)
+/* Device Periodic Transmit FIFO-9 Size */
+#define S3C_UDC_OTG_DPTXFSIZ9 S3C_USBOTGREG(0x124)
+/* Device Periodic Transmit FIFO-10 Size */
+#define S3C_UDC_OTG_DPTXFSIZ10 S3C_USBOTGREG(0x128)
+/* Device Periodic Transmit FIFO-11 Size */
+#define S3C_UDC_OTG_DPTXFSIZ11 S3C_USBOTGREG(0x12C)
+/* Device Periodic Transmit FIFO-12 Size */
+#define S3C_UDC_OTG_DPTXFSIZ12 S3C_USBOTGREG(0x130)
+/* Device Periodic Transmit FIFO-13 Size */
+#define S3C_UDC_OTG_DPTXFSIZ13 S3C_USBOTGREG(0x134)
+/* Device Periodic Transmit FIFO-14 Size */
+#define S3C_UDC_OTG_DPTXFSIZ14 S3C_USBOTGREG(0x138)
+/* Device Periodic Transmit FIFO-15 Size */
+#define S3C_UDC_OTG_DPTXFSIZ15 S3C_USBOTGREG(0x13C)
+
+/* Host Mode Registers
+ * Host Global Registers */
+/* Host Configuration */
+#define S3C_UDC_OTG_HCFG S3C_USBOTGREG(0x400)
+/* Host Frame Interval */
+#define S3C_UDC_OTG_HFIR S3C_USBOTGREG(0x404)
+/* Host Frame Number/Frame Time Remaining */
+#define S3C_UDC_OTG_HFNUM S3C_USBOTGREG(0x408)
+/* Host Periodic Transmit FIFO/Queue Status */
+#define S3C_UDC_OTG_HPTXSTS S3C_USBOTGREG(0x410)
+/* Host All Channels Interrupt */
+#define S3C_UDC_OTG_HAINT S3C_USBOTGREG(0x414)
+/* Host All Channels Interrupt Mask */
+#define S3C_UDC_OTG_HAINTMSK S3C_USBOTGREG(0x418)
+
+/* Host Port Control & Status Registers */
+#define S3C_UDC_OTG_HPRT S3C_USBOTGREG(0x440)
+
+/* Host Channel-Specific Registers */
+/* Host Channel-0 Characteristics */
+#define S3C_UDC_OTG_HCCHAR0 S3C_USBOTGREG(0x500)
+/* Host Channel-0 Split Control */
+#define S3C_UDC_OTG_HCSPLT0 S3C_USBOTGREG(0x504)
+/* Host Channel-0 Interrupt */
+#define S3C_UDC_OTG_HCINT0 S3C_USBOTGREG(0x508)
+/* Host Channel-0 Interrupt Mask */
+#define S3C_UDC_OTG_HCINTMSK0 S3C_USBOTGREG(0x50C)
+/* Host Channel-0 Transfer Size */
+#define S3C_UDC_OTG_HCTSIZ0 S3C_USBOTGREG(0x510)
+/* Host Channel-0 DMA Address */
+#define S3C_UDC_OTG_HCDMA0 S3C_USBOTGREG(0x514)
+
+/* Device Mode Registers
+ * Device Global Registers */
+/* Device Configuration */
+#define S3C_UDC_OTG_DCFG S3C_USBOTGREG(0x800)
+/* Device Control */
+#define S3C_UDC_OTG_DCTL S3C_USBOTGREG(0x804)
+/* Device Status */
+#define S3C_UDC_OTG_DSTS S3C_USBOTGREG(0x808)
+/* Device IN Endpoint Common Interrupt Mask */
+#define S3C_UDC_OTG_DIEPMSK S3C_USBOTGREG(0x810)
+/* Device OUT Endpoint Common Interrupt Mask */
+#define S3C_UDC_OTG_DOEPMSK S3C_USBOTGREG(0x814)
+/* Device All Endpoints Interrupt */
+#define S3C_UDC_OTG_DAINT S3C_USBOTGREG(0x818)
+/* Device All Endpoints Interrupt Mask */
+#define S3C_UDC_OTG_DAINTMSK S3C_USBOTGREG(0x81C)
+/* Device IN Token Sequence Learning Queue Read 1 */
+#define S3C_UDC_OTG_DTKNQR1 S3C_USBOTGREG(0x820)
+/* Device IN Token Sequence Learning Queue Read 2 */
+#define S3C_UDC_OTG_DTKNQR2 S3C_USBOTGREG(0x824)
+/* Device VBUS Discharge Time */
+#define S3C_UDC_OTG_DVBUSDIS S3C_USBOTGREG(0x828)
+/* Device VBUS Pulsing Time */
+#define S3C_UDC_OTG_DVBUSPULSE S3C_USBOTGREG(0x82C)
+/* Device IN Token Sequence Learning Queue Read 3 */
+#define S3C_UDC_OTG_DTKNQR3 S3C_USBOTGREG(0x830)
+/* Device IN Token Sequence Learning Queue Read 4 */
+#define S3C_UDC_OTG_DTKNQR4 S3C_USBOTGREG(0x834)
+
+/* Device Logical IN Endpoint-Specific Registers */
+/* Device IN Endpoint 0 Control */
+#define S3C_UDC_OTG_DIEPCTL0 S3C_USBOTGREG(0x900)
+/* Device IN Endpoint 0 Interrupt */
+#define S3C_UDC_OTG_DIEPINT0 S3C_USBOTGREG(0x908)
+/* Device IN Endpoint 0 Transfer Size */
+#define S3C_UDC_OTG_DIEPTSIZ0 S3C_USBOTGREG(0x910)
+/* Device IN Endpoint 0 DMA Address */
+#define S3C_UDC_OTG_DIEPDMA0 S3C_USBOTGREG(0x914)
+
+/* Device IN Endpoint 2 Control */
+#define S3C_UDC_OTG_DIEPCTL2 S3C_USBOTGREG(0x940)
+/* Device IN Endpoint 2 Interrupt */
+#define S3C_UDC_OTG_DIEPINT2 S3C_USBOTGREG(0x948)
+/* Device IN Endpoint 2 Transfer Size */
+#define S3C_UDC_OTG_DIEPTSIZ2 S3C_USBOTGREG(0x950)
+/* Device IN Endpoint 2 DMA Address */
+#define S3C_UDC_OTG_DIEPDMA2 S3C_USBOTGREG(0x954)
+
+/* Device IN Endpoint 3 Control */
+#define S3C_UDC_OTG_DIEPCTL3 S3C_USBOTGREG(0x960)
+/* Device IN Endpoint 3 Interrupt */
+#define S3C_UDC_OTG_DIEPINT3 S3C_USBOTGREG(0x968)
+/* Device IN Endpoint 3 Transfer Size */
+#define S3C_UDC_OTG_DIEPTSIZ3 S3C_USBOTGREG(0x970)
+/* Device IN Endpoint 3 DMA Address */
+#define S3C_UDC_OTG_DIEPDMA3 S3C_USBOTGREG(0x974)
+
+/* Device Logical OUT Endpoint-Specific Registers */
+/* Device OUT Endpoint 0 Control */
+#define S3C_UDC_OTG_DOEPCTL0 S3C_USBOTGREG(0xB00)
+/* Device OUT Endpoint 0 Interrupt */
+#define S3C_UDC_OTG_DOEPINT0 S3C_USBOTGREG(0xB08)
+/* Device OUT Endpoint 0 Transfer Size */
+#define S3C_UDC_OTG_DOEPTSIZ0 S3C_USBOTGREG(0xB10)
+/* Device OUT Endpoint 0 DMA Address */
+#define S3C_UDC_OTG_DOEPDMA0 S3C_USBOTGREG(0xB14)
+
+/* Device OUT Endpoint 1 Control */
+#define S3C_UDC_OTG_DOEPCTL1 S3C_USBOTGREG(0xB20)
+/* Device OUT Endpoint 1 Interrupt */
+#define S3C_UDC_OTG_DOEPINT1 S3C_USBOTGREG(0xB28)
+/* Device OUT Endpoint 1 Transfer Size */
+#define S3C_UDC_OTG_DOEPTSIZ1 S3C_USBOTGREG(0xB30)
+/* Device OUT Endpoint 1 DMA Address */
+#define S3C_UDC_OTG_DOEPDMA1 S3C_USBOTGREG(0xB34)
+
+/* Endpoint FIFO address */
+#define S3C_UDC_OTG_EP0_FIFO S3C_USBOTGREG(0x1000)
+#define S3C_UDC_OTG_EP1_FIFO S3C_USBOTGREG(0x2000)
+#define S3C_UDC_OTG_EP2_FIFO S3C_USBOTGREG(0x3000)
+#define S3C_UDC_OTG_EP3_FIFO S3C_USBOTGREG(0x4000)
+#define S3C_UDC_OTG_EP4_FIFO S3C_USBOTGREG(0x5000)
+#define S3C_UDC_OTG_EP5_FIFO S3C_USBOTGREG(0x6000)
+#define S3C_UDC_OTG_EP6_FIFO S3C_USBOTGREG(0x7000)
+#define S3C_UDC_OTG_EP7_FIFO S3C_USBOTGREG(0x8000)
+#define S3C_UDC_OTG_EP8_FIFO S3C_USBOTGREG(0x9000)
+
+/* S3C_USBOTG_PHYPWR */
+#define OTG_ENABLE (0x0<<4)
+#define OTG_DISABLE (0x1<<4)
+#define ANALOG_PWR_UP (0x0<<3)
+#define ANALOG_PWR_DOWN (0x1<<3)
+#define SUSPEND_DISABLE (0x0<<0)
+#define SUSPEND_ENABLE (0x1<<0)
+
+/* S3C_USBOTG_PHYCLK */
+#define REF_CLK_CRYSTAL (0x0<<5)
+#define REF_CLK_OSCC (0x1<<5)
+
+/* S3C_USBOTG_RSTCON */
+#define SW_RST_OFF (0x0<<0)
+#define SW_RST_ON (0x1<<0)
+
+/* S3C_UDC_OTG_GOTGCTL */
+#define B_SESSION_VALID (0x1<<19)
+#define A_SESSION_VALID (0x1<<18)
+
+/* S3C_UDC_OTG_GAHBCFG */
+#define PTXFE_HALF (0x0<<8)
+#define PTXFE_ZERO (0x1<<8)
+#define NPTXFE_HALF (0x0<<7)
+#define NPTXFE_ZERO (0x1<<7)
+#define MODE_SLAVE (0x0<<5)
+#define MODE_DMA (0x1<<5)
+#define BURST_SINGLE (0x0<<1)
+#define BURST_INCR (0x1<<1)
+#define BURST_INCR4 (0x3<<1)
+#define BURST_INCR8 (0x5<<1)
+#define BURST_INCR16 (0x7<<1)
+#define GBL_INT_UNMASK (0x1<<0)
+#define GBL_INT_MASK (0x0<<0)
+
+/* S3C_UDC_OTG_GUSBCFG */
+#define PHY_CLK_480M (0x0<<15)
+#define PHY_CLK_48M (0x1<<15)
+#define TXFIFO_RE_DIS (0x0<<14)
+#define TXFIFO_RE_EN (0x1<<14)
+#define TURN_AROUND (0x5<<10)
+#define HNP_DISABLE (0x0<<9)
+#define HNP_ENABLE (0x1<<9)
+#define SRP_DISABLE (0x0<<8)
+#define SRP_ENABLE (0x1<<8)
+#define ULPI_DDR (0x0<<7)
+#define HS_UTMI (0x0<<6)
+#define INTERF_UTMI (0x0<<4)
+#define INTERF_ULPI (0x1<<4)
+#define PHY_INTERF_8 (0x0<<3)
+#define PHY_INTERF_16 (0x1<<3)
+#define TIME_OUT_CAL (0x7<<0)
+
+/* S3C_UDC_OTG_GRSTCTL */
+#define AHB_MASTER_IDLE (1u<<31)
+#define CORE_SOFT_RESET (0x1<<0)
+
+/* S3C_UDC_OTG_GINTSTS/S3C_UDC_OTG_GINTMSK core interrupt register */
+#define INT_RESUME (0x1<<31)
+#define INT_DISCONN (0x1<<29)
+#define INT_CONN_CNG (0x1<<28)
+#define INT_OUT_EP (0x1<<19)
+#define INT_IN_EP (0x1<<18)
+#define INT_ENUMDONE (0x1<<13)
+#define INT_RESET (0x1<<12)
+#define INT_SUSPEND (0x1<<11)
+#define INT_EARLY_SUSPEND (0x1<<10)
+#define INT_TX_FIFO_EMPTY (0x1<<5)
+#define INT_RX_FIFO_NOT_EMPTY (0x1<<4)
+#define INT_SOF (0x1<<3)
+#define INT_DEV_MODE (0x0<<0)
+#define INT_HOST_MODE (0x1<<1)
+
+#define FULL_SPEED_CONTROL_PKT_SIZE 8
+#define FULL_SPEED_BULK_PKT_SIZE 64
+
+#define HIGH_SPEED_CONTROL_PKT_SIZE 64
+#define HIGH_SPEED_BULK_PKT_SIZE 512
+
+/* S3C_UDC_OTG_DSTS */
+#define RX_FIFO_SIZE (2048<<0)
+#define NPTX_FIFO_START_ADDR (RX_FIFO_SIZE<<0)
+#define NPTX_FIFO_SIZE (2048<<16)
+#define PTX_FIFO_SIZE (2048<<16)
+#define USB_HIGH_30_60MHZ (0x0<<1)
+#define USB_FULL_30_60MHZ (0x1<<1)
+#define USB_LOW_6MHZ (0x2<<1)
+#define USB_FULL_48MHZ (0x3<<1)
+
+/* S3C_UDC_OTG_GRXSTSP */
+#define BYTE_COUNT(x) ((x & (0x7FF<<4)) >> 4)
+#define PKT_STS(x) ((x & (0xF<<17)) >> 17)
+#define EP_NUM(x) (x & 0xF)
+
+#define OUT_PKT_RECEIVED (0x2)
+#define OUT_COMPLELTED (0x3)
+#define SETUP_COMPLETED (0x4)
+#define SETUP_PKT_RECEIVED (0x6)
+
+/* S3C_UDC_OTG_DCFG */
+#define EP_MIS_CNT(x) (x<<18)
+#define DEVICE_ADDR(x) (x<<4)
+#define SPEED_2_HIGH (0x0<<0)
+#define SPEED_2_FULL (0x1<<0)
+#define SPEED_1_LOW (0x2<<0)
+#define SPEED_1_FULL (0x3<<0)
+
+/* S3C_UDC_OTG_DCTL device control register */
+#define NORMAL_OPERATION (0x1<<0)
+#define SOFT_DISCONNECT (0x1<<1)
+
+/* S3C_UDC_OTG_DSTS */
+#define ENUM_SPEED(x) (x & (0x3<<1))
+#define FRAME_CNT(x) (x & (0x3ff<<8))
+
+/* S3C_UDC_OTG_DAINT device all endpoint interrupt register */
+#define S3C_UDC_INT_IN_EP0 (0x1<<0)
+#define S3C_UDC_INT_IN_EP2 (0x1<<2)
+#define S3C_UDC_INT_IN_EP3 (0x1<<3)
+#define S3C_UDC_INT_OUT_EP0 (0x1<<16)
+#define S3C_UDC_INT_OUT_EP1 (0x1<<17)
+#define S3C_UDC_INT_OUT_EP4 (0x1<<20)
+
+/* S3C_UDC_OTG_DIEPCTL0/DOEPCTL0 device control
+ IN/OUT endpoint 0 control register */
+#define DEPCTL_EPENA (0x1<<31)
+#define DEPCTL_EPDIS (0x1<<30)
+#define DEPCTL_SNAK (0x1<<27)
+#define DEPCTL_CNAK (0x1<<26)
+#define DEPCTL_CTRL_TYPE (0x0<<18)
+#define DEPCTL_ISO_TYPE (0x1<<18)
+#define DEPCTL_BULK_TYPE (0x2<<18)
+#define DEPCTL_INTR_TYPE (0x3<<18)
+#define DEPCTL_USBACTEP (0x1<<15)
+#define DEPCTL0_MPS_64 (0x0<<0)
+#define DEPCTL0_MPS_32 (0x1<<0)
+#define DEPCTL0_MPS_16 (0x2<<0)
+#define DEPCTL0_MPS_8 (0x3<<0)
+
+/* S3C_UDC_OTG_DIEPINTn */
+#define IN_EP_NAK_EFF (0x1<<6)
+#define IN_TK_EPMIS (0x1<<5)
+#define IN_TK_TXFEMP (0x1<<4)
+#define IN_EP_TIMEOUT (0x1<<3)
+
+/* S3C_UDC_OTG_DOEPINTn */
+#define BACK2BACK_SETUP (0x1<<6)
+#define OUT_TK_EP_DIS (0x1<<4)
+#define SETUP_PHASE_DONE (0x1<<3)
+
+/* S3C_UDC_OTG_DIEPINTn/DOEPINTn */
+#define AHB_ERROR (0x1<<2)
+#define EPDISBLD (0x1<<1)
+#define TRANSFER_DONE (0x1<<0)
+
+/* S3C_UDC_OTG_DIEPTSIZn */
+#define PKT_CNT(x) (x<<19)
+#define XFERSIZE(x) (x<<0)
+
+#endif
Index: linux-2.6.30-rc6/arch/arm/plat-s3c/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/Kconfig 2009-05-18 19:08:30.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/plat-s3c/Kconfig 2009-05-18 19:08:30.000000000 +0200
@@ -184,4 +184,9 @@
help
Compile in platform device definition for framebuffer
+config S3C_DEV_USB_HOST
+ bool
+ help
+ Compile in platform device definition for USB host.
+
endif
Index: linux-2.6.30-rc6/arch/arm/plat-s3c/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/Makefile 2009-05-18 19:08:30.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/plat-s3c/Makefile 2009-05-18 19:08:30.000000000 +0200
@@ -35,6 +35,8 @@
obj-y += dev-i2c0.o
obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o
obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o
+obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o
+
obj-$(CONFIG_S3C_PWM) += pwm.o
obj-$(CONFIG_S3C_DMA) += dma.o
Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/devs.c
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/devs.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/devs.c 2009-05-18 19:08:30.000000000 +0200
@@ -136,36 +136,6 @@
struct platform_device *s3c24xx_uart_devs[4] = {
};
-/* USB Host Controller */
-
-static struct resource s3c_usb_resource[] = {
- [0] = {
- .start = S3C24XX_PA_USBHOST,
- .end = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_USBH,
- .end = IRQ_USBH,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static u64 s3c_device_usb_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_usb = {
- .name = "s3c2410-ohci",
- .id = -1,
- .num_resources = ARRAY_SIZE(s3c_usb_resource),
- .resource = s3c_usb_resource,
- .dev = {
- .dma_mask = &s3c_device_usb_dmamask,
- .coherent_dma_mask = 0xffffffffUL
- }
-};
-
-EXPORT_SYMBOL(s3c_device_usb);
-
/* LCD Controller */
static struct resource s3c_lcd_resource[] = {

View File

@@ -0,0 +1,294 @@
Index: linux-2.6.30-rc6/arch/arm/kernel/fiq.c
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/kernel/fiq.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/kernel/fiq.c 2009-05-18 19:08:30.000000000 +0200
@@ -8,6 +8,8 @@
*
* FIQ support re-written by Russell King to be more generic
*
+ * FIQ handler in C supoprt written by Andy Green <andy@openmoko.com>
+ *
* We now properly support a method by which the FIQ handlers can
* be stacked onto the vector. We still do not support sharing
* the FIQ vector itself.
@@ -124,6 +126,83 @@
: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
}
+/* -------- FIQ handler in C ---------
+ *
+ * Major Caveats for using this
+ * ---------------------------
+ * *
+ * * 1) it CANNOT touch any vmalloc()'d memory, only memory
+ * that was kmalloc()'d. Static allocations in the monolithic kernel
+ * are kmalloc()'d so they are okay. You can touch memory-mapped IO, but
+ * the pointer for it has to have been stored in kmalloc'd memory. The
+ * reason for this is simple: every now and then Linux turns off interrupts
+ * and reorders the paging tables. If a FIQ happens during this time, the
+ * virtual memory space can be partly or entirely disordered or missing.
+ *
+ * 2) Because vmalloc() is used when a module is inserted, THIS FIQ
+ * ISR HAS TO BE IN THE MONOLITHIC KERNEL, not a module. But the way
+ * it is set up, you can all to enable and disable it from your module
+ * and intercommunicate with it through struct fiq_ipc
+ * fiq_ipc which you can define in
+ * asm/archfiq_ipc_type.h. The reason is the same as above, a
+ * FIQ could happen while even the ISR is not present in virtual memory
+ * space due to pagetables being changed at the time.
+ *
+ * 3) You can't call any Linux API code except simple macros
+ * - understand that FIQ can come in at any time, no matter what
+ * state of undress the kernel may privately be in, thinking it
+ * locked the door by turning off interrupts... FIQ is an
+ * unstoppable monster force (which is its value)
+ * - they are not vmalloc()'d memory safe
+ * - they might do crazy stuff like sleep: FIQ pisses fire and
+ * is not interested in 'sleep' that the weak seem to need
+ * - calling APIs from FIQ can re-enter un-renterable things
+ * - summary: you cannot interoperate with linux APIs directly in the FIQ ISR
+ *
+ * If you follow these rules, it is fantastic, an extremely powerful, solid,
+ * genuine hard realtime feature.
+ */
+
+static void (*current_fiq_c_isr)(void);
+#define FIQ_C_ISR_STACK_SIZE 256
+
+static void __attribute__((naked)) __jump_to_isr(void)
+{
+ asm __volatile__ ("mov pc, r8");
+}
+
+
+static void __attribute__((naked)) __actual_isr(void)
+{
+ asm __volatile__ (
+ "stmdb sp!, {r0-r12, lr};"
+ "mov fp, sp;"
+ );
+
+ current_fiq_c_isr();
+
+ asm __volatile__ (
+ "ldmia sp!, {r0-r12, lr};"
+ "subs pc, lr, #4;"
+ );
+}
+
+void set_fiq_c_handler(void (*isr)(void))
+{
+ struct pt_regs regs;
+
+ memset(&regs, 0, sizeof(regs));
+ regs.ARM_r8 = (unsigned long) __actual_isr;
+ regs.ARM_sp = 0xffff001c + FIQ_C_ISR_STACK_SIZE;
+
+ set_fiq_handler(__jump_to_isr, 4);
+
+ current_fiq_c_isr = isr;
+
+ set_fiq_regs(&regs);
+}
+/* -------- FIQ handler in C ---------*/
+
int claim_fiq(struct fiq_handler *f)
{
int ret = 0;
Index: linux-2.6.30-rc6/arch/arm/include/asm/fiq.h
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/include/asm/fiq.h 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/include/asm/fiq.h 2009-05-18 19:08:30.000000000 +0200
@@ -29,8 +29,9 @@
extern int claim_fiq(struct fiq_handler *f);
extern void release_fiq(struct fiq_handler *f);
extern void set_fiq_handler(void *start, unsigned int length);
-extern void set_fiq_regs(struct pt_regs *regs);
-extern void get_fiq_regs(struct pt_regs *regs);
+extern void set_fiq_c_handler(void (*handler)(void));
+extern void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs);
+extern void __attribute__((naked)) get_fiq_regs(struct pt_regs *regs);
extern void enable_fiq(int fiq);
extern void disable_fiq(int fiq);
Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/include/plat/irq.h
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/include/plat/irq.h 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/include/plat/irq.h 2009-05-18 19:08:30.000000000 +0200
@@ -12,6 +12,7 @@
#include <linux/io.h>
+#include <mach/irqs.h>
#include <mach/hardware.h>
#include <mach/regs-irq.h>
#include <mach/regs-gpio.h>
@@ -31,8 +32,15 @@
{
unsigned long mask;
unsigned long submask;
+#ifdef CONFIG_S3C2440_C_FIQ
+ unsigned long flags;
+#endif
submask = __raw_readl(S3C2410_INTSUBMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_save_flags(flags);
+ local_fiq_disable();
+#endif
mask = __raw_readl(S3C2410_INTMSK);
submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
@@ -45,6 +53,9 @@
/* write back masks */
__raw_writel(submask, S3C2410_INTSUBMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_irq_restore(flags);
+#endif
}
@@ -53,8 +64,15 @@
{
unsigned long mask;
unsigned long submask;
+#ifdef CONFIG_S3C2440_C_FIQ
+ unsigned long flags;
+#endif
submask = __raw_readl(S3C2410_INTSUBMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_save_flags(flags);
+ local_fiq_disable();
+#endif
mask = __raw_readl(S3C2410_INTMSK);
submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
@@ -63,6 +81,9 @@
/* write back masks */
__raw_writel(submask, S3C2410_INTSUBMSK);
__raw_writel(mask, S3C2410_INTMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_irq_restore(flags);
+#endif
}
Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/irq.c
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/irq.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/irq.c 2009-05-18 19:08:30.000000000 +0200
@@ -28,6 +28,8 @@
#include <asm/mach/irq.h>
#include <plat/regs-irqtype.h>
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
#include <plat/cpu.h>
#include <plat/pm.h>
@@ -37,12 +39,20 @@
s3c_irq_mask(unsigned int irqno)
{
unsigned long mask;
-
+#ifdef CONFIG_S3C2440_C_FIQ
+ unsigned long flags;
+#endif
irqno -= IRQ_EINT0;
-
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_save_flags(flags);
+ local_fiq_disable();
+#endif
mask = __raw_readl(S3C2410_INTMSK);
mask |= 1UL << irqno;
__raw_writel(mask, S3C2410_INTMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_irq_restore(flags);
+#endif
}
static inline void
@@ -59,9 +69,19 @@
{
unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
unsigned long mask;
-
+#ifdef CONFIG_S3C2440_C_FIQ
+ unsigned long flags;
+#endif
+
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_save_flags(flags);
+ local_fiq_disable();
+#endif
mask = __raw_readl(S3C2410_INTMSK);
__raw_writel(mask|bitval, S3C2410_INTMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_irq_restore(flags);
+#endif
__raw_writel(bitval, S3C2410_SRCPND);
__raw_writel(bitval, S3C2410_INTPND);
@@ -72,15 +92,25 @@
s3c_irq_unmask(unsigned int irqno)
{
unsigned long mask;
+#ifdef CONFIG_S3C2440_C_FIQ
+ unsigned long flags;
+#endif
if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
irqdbf2("s3c_irq_unmask %d\n", irqno);
irqno -= IRQ_EINT0;
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_save_flags(flags);
+ local_fiq_disable();
+#endif
mask = __raw_readl(S3C2410_INTMSK);
mask &= ~(1UL << irqno);
__raw_writel(mask, S3C2410_INTMSK);
+#ifdef CONFIG_S3C2440_C_FIQ
+ local_irq_restore(flags);
+#endif
}
struct irq_chip s3c_irq_level_chip = {
@@ -523,26 +553,26 @@
last = 0;
for (i = 0; i < 4; i++) {
- pend = __raw_readl(S3C2410_INTPND);
+ pend = __raw_readl(S3C2410_SUBSRCPND);
if (pend == 0 || pend == last)
break;
- __raw_writel(pend, S3C2410_SRCPND);
- __raw_writel(pend, S3C2410_INTPND);
- printk("irq: clearing pending status %08x\n", (int)pend);
+ printk("irq: clearing subpending status %08x\n", (int)pend);
+ __raw_writel(pend, S3C2410_SUBSRCPND);
last = pend;
}
last = 0;
for (i = 0; i < 4; i++) {
- pend = __raw_readl(S3C2410_SUBSRCPND);
+ pend = __raw_readl(S3C2410_INTPND);
if (pend == 0 || pend == last)
break;
- printk("irq: clearing subpending status %08x\n", (int)pend);
- __raw_writel(pend, S3C2410_SUBSRCPND);
+ __raw_writel(pend, S3C2410_SRCPND);
+ __raw_writel(pend, S3C2410_INTPND);
+ printk("irq: clearing pending status %08x\n", (int)pend);
last = pend;
}

View File

@@ -0,0 +1,50 @@
Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/Kconfig 2009-05-18 19:08:29.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/Kconfig 2009-05-18 19:08:31.000000000 +0200
@@ -112,4 +112,20 @@
help
Common machine code for SMDK2410 and SMDK2440
+config MACH_NEO1973
+ bool
+ select RFKILL
+ select SERIAL_SAMSUNG
+ select SERIAL_SAMSUNG_CONSOLE
+ help
+ Common machine code for Neo1973 hardware
+
+config MACH_NEO1973
+ bool
+ select RFKILL
+ select SERIAL_SAMSUNG
+ select SERIAL_SAMSUNG_CONSOLE
+ help
+ Common machine code for Neo1973 hardware
+
endif
Index: linux-2.6.30-rc6/arch/arm/mach-s3c2442/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/mach-s3c2442/Makefile 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/mach-s3c2442/Makefile 2009-05-18 19:08:31.000000000 +0200
@@ -14,3 +14,9 @@
# Machine support
+obj-$(CONFIG_MACH_NEO1973) += \
+ gta02-pm-gsm.o \
+ gta02-pm-gps.o \
+ gta02-pm-bt.o \
+ gta02-pm-wlan.o \
+ gta02-shadow.o
Index: linux-2.6.30-rc6/drivers/misc/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/drivers/misc/Makefile 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/misc/Makefile 2009-05-18 19:08:31.000000000 +0200
@@ -21,3 +21,6 @@
obj-$(CONFIG_ISL29003) += isl29003.o
obj-$(CONFIG_C2PORT) += c2port/
obj-y += eeprom/
+obj-$(CONFIG_MACH_NEO1973) += gta02_pm_host.o \
+ gta02_pm_resume_reason.o
+

View File

@@ -0,0 +1,91 @@
Index: linux-2.6.30-rc6/arch/arm/mach-s3c2442/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/mach-s3c2442/Kconfig 2009-05-18 19:08:29.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/mach-s3c2442/Kconfig 2009-05-18 19:08:31.000000000 +0200
@@ -25,6 +25,20 @@
depends on ARCH_S3C2440
select CPU_S3C2442
+config MACH_NEO1973_GTA02
+ bool "Openmoko Freerunner GSM Phone (GTA02 Hardware)"
+ select CPU_S3C2442
+ select MFD_PCF50633
+ select PCF50633_GPIO
+ select I2C
+ select POWER_SUPPLY
+ select MACH_NEO1973
+ select S3C_PWM
+ select FIQ
+ select S3C_DEV_USB_HOST
+ help
+ Say Y here if you are using the Openmoko Freerunner GSM Phone
+
endmenu
Index: linux-2.6.30-rc6/arch/arm/mach-s3c2442/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/mach-s3c2442/Makefile 2009-05-18 19:08:31.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/mach-s3c2442/Makefile 2009-05-18 19:08:31.000000000 +0200
@@ -9,8 +9,11 @@
obj-n :=
obj- :=
+obj-$(CONFIG_S3C2440_C_FIQ) += fiq_c_isr.o
+
obj-$(CONFIG_CPU_S3C2442) += s3c2442.o
obj-$(CONFIG_CPU_S3C2442) += clock.o
+obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o
# Machine support
Index: linux-2.6.30-rc6/arch/arm/mach-s3c2410/include/mach/irqs.h
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/mach-s3c2410/include/mach/irqs.h 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/mach-s3c2410/include/mach/irqs.h 2009-05-18 19:08:31.000000000 +0200
@@ -153,9 +153,9 @@
#define IRQ_S3C2443_AC97 S3C2410_IRQSUB(28)
#ifdef CONFIG_CPU_S3C2443
-#define NR_IRQS (IRQ_S3C2443_AC97+1)
+#define _NR_IRQS (IRQ_S3C2443_AC97+1)
#else
-#define NR_IRQS (IRQ_S3C2440_AC97+1)
+#define _NR_IRQS (IRQ_S3C2440_AC97+1)
#endif
/* compatibility define. */
@@ -167,4 +167,33 @@
/* Our FIQs are routable from IRQ_EINT0 to IRQ_ADCPARENT */
#define FIQ_START IRQ_EINT0
+
+/*
+ * The next 16 interrupts are for board specific purposes. Since
+ * the kernel can only run on one machine at a time, we can re-use
+ * these. If you need more, increase IRQ_BOARD_END, but keep it
+ * within sensible limits.
+ */
+#define IRQ_BOARD_START _NR_IRQS
+#define IRQ_BOARD_END (_NR_IRQS + 10)
+
+#if defined(CONFIG_MACH_NEO1973_GTA02)
+#define NR_IRQS (IRQ_BOARD_END)
+#else
+#define NR_IRQS (IRQ_BOARD_START)
+#endif
+
+/* Neo1973 GTA02 interrupts */
+#define NEO1973_GTA02_IRQ(x) (IRQ_BOARD_START + (x))
+#define IRQ_GLAMO(x) NEO1973_GTA02_IRQ(x)
+#define IRQ_GLAMO_HOSTBUS IRQ_GLAMO(0)
+#define IRQ_GLAMO_JPEG IRQ_GLAMO(1)
+#define IRQ_GLAMO_MPEG IRQ_GLAMO(2)
+#define IRQ_GLAMO_MPROC1 IRQ_GLAMO(3)
+#define IRQ_GLAMO_MPROC0 IRQ_GLAMO(4)
+#define IRQ_GLAMO_CMDQUEUE IRQ_GLAMO(5)
+#define IRQ_GLAMO_2D IRQ_GLAMO(6)
+#define IRQ_GLAMO_MMC IRQ_GLAMO(7)
+#define IRQ_GLAMO_RISC IRQ_GLAMO(8)
+
#endif /* __ASM_ARCH_IRQ_H */

View File

@@ -0,0 +1,154 @@
Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/devs.c
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/devs.c 2009-05-18 19:08:30.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/devs.c 2009-05-18 19:08:31.000000000 +0200
@@ -26,6 +26,8 @@
#include <asm/mach/irq.h>
#include <mach/fb.h>
#include <mach/hardware.h>
+#include <mach/ts.h>
+#include <asm/io.h>
#include <asm/irq.h>
#include <plat/regs-serial.h>
@@ -199,6 +201,24 @@
EXPORT_SYMBOL(s3c_device_nand);
+/* Touchscreen */
+struct platform_device s3c_device_ts = {
+ .name = "s3c2410-ts",
+ .id = -1,
+};
+
+EXPORT_SYMBOL(s3c_device_ts);
+
+static struct s3c2410_ts_mach_info s3c2410ts_info;
+
+void set_s3c2410ts_info(const struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
+{
+ memcpy(&s3c2410ts_info, hard_s3c2410ts_info,
+ sizeof(struct s3c2410_ts_mach_info));
+ s3c_device_ts.dev.platform_data = &s3c2410ts_info;
+}
+EXPORT_SYMBOL(set_s3c2410ts_info);
+
/* USB Device (Gadget)*/
static struct resource s3c_usbgadget_resource[] = {
Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/s3c244x.c
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/s3c244x.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/s3c244x.c 2009-05-18 19:08:31.000000000 +0200
@@ -59,6 +59,8 @@
s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
}
+extern struct platform_device s3c_device_ts;
+
void __init s3c244x_map_io(void)
{
/* register our io-tables */
@@ -70,6 +72,7 @@
s3c_device_sdi.name = "s3c2440-sdi";
s3c_device_i2c0.name = "s3c2440-i2c";
s3c_device_nand.name = "s3c2440-nand";
+ s3c_device_ts.name = "s3c2440-ts";
s3c_device_usbgadget.name = "s3c2440-usbgadget";
}
Index: linux-2.6.30-rc6/drivers/input/touchscreen/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/drivers/input/touchscreen/Kconfig 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/input/touchscreen/Kconfig 2009-05-18 19:08:31.000000000 +0200
@@ -124,6 +124,24 @@
To compile this driver as a module, choose M here: the
module will be called fujitsu-ts.
+config TOUCHSCREEN_S3C2410
+ tristate "Samsung S3C2410 touchscreen input driver"
+ depends on ARCH_S3C2410 && INPUT && INPUT_TOUCHSCREEN
+ select SERIO
+ help
+ Say Y here if you have the s3c2410 touchscreen.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s3c2410_ts.
+
+config TOUCHSCREEN_S3C2410_DEBUG
+ boolean "Samsung S3C2410 touchscreen debug messages"
+ depends on TOUCHSCREEN_S3C2410
+ help
+ Select this if you want debug messages
+
config TOUCHSCREEN_GUNZE
tristate "Gunze AHL-51S touchscreen"
select SERIO
Index: linux-2.6.30-rc6/drivers/input/touchscreen/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/drivers/input/touchscreen/Makefile 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/input/touchscreen/Makefile 2009-05-18 19:08:31.000000000 +0200
@@ -37,3 +37,4 @@
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
+obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
Index: linux-2.6.30-rc6/arch/arm/mach-s3c2410/include/mach/ts.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.30-rc6/arch/arm/mach-s3c2410/include/mach/ts.h 2009-05-18 19:08:31.000000000 +0200
@@ -0,0 +1,35 @@
+/* arch/arm/mach-s3c2410/include/mach/ts.h
+ *
+ * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ *
+ * 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.
+ *
+ *
+ * Changelog:
+ * 24-Mar-2005 RTP Created file
+ * 03-Aug-2005 RTP Renamed to ts.h
+ */
+
+#ifndef __ASM_ARM_TS_H
+#define __ASM_ARM_TS_H
+
+#include <linux/touchscreen/ts_filter.h>
+
+struct s3c2410_ts_mach_info {
+ /* Touchscreen delay. */
+ int delay;
+ /* Prescaler value. */
+ int presc;
+ /*
+ * Null-terminated array of pointers to filter APIs and configurations
+ * we want to use. In the same order they will be applied.
+ */
+ const struct ts_filter_chain_configuration *filter_config;
+};
+
+void set_s3c2410ts_info(const struct s3c2410_ts_mach_info *hard_s3c2410ts_info);
+
+#endif /* __ASM_ARM_TS_H */
Index: linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/devs.h
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/include/plat/devs.h 2009-05-18 19:07:48.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/devs.h 2009-05-18 19:08:31.000000000 +0200
@@ -50,10 +50,11 @@
extern struct platform_device s3c_device_usbgadget;
+extern struct platform_device s3c_device_ts;
+
/* s3c2440 specific devices */
#ifdef CONFIG_CPU_S3C2440
extern struct platform_device s3c_device_camif;
-
#endif

View File

@@ -0,0 +1,32 @@
Index: linux-2.6.30-rc6/drivers/input/keyboard/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/drivers/input/keyboard/Kconfig 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/input/keyboard/Kconfig 2009-05-18 19:08:32.000000000 +0200
@@ -332,4 +332,15 @@
To compile this driver as a module, choose M here: the
module will be called sh_keysc.
+config KEYBOARD_GTA02
+ tristate "Openmoko Freerunner buttons"
+ depends on MACH_NEO1973
+ default y
+ help
+ Say Y here to enable the buttons on the Openmoko Freerunner
+ GSM phone.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gta02kbd.
+
endif
Index: linux-2.6.30-rc6/drivers/input/keyboard/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/drivers/input/keyboard/Makefile 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/input/keyboard/Makefile 2009-05-18 19:08:32.000000000 +0200
@@ -14,6 +14,7 @@
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
+obj-$(CONFIG_KEYBOARD_GTA02) += gta02kbd.o
obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o

View File

@@ -0,0 +1,72 @@
Index: linux-2.6.30-rc6/drivers/input/touchscreen/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/drivers/input/touchscreen/Kconfig 2009-05-18 19:08:31.000000000 +0200
+++ linux-2.6.30-rc6/drivers/input/touchscreen/Kconfig 2009-05-18 19:08:32.000000000 +0200
@@ -11,6 +11,54 @@
if INPUT_TOUCHSCREEN
+menuconfig TOUCHSCREEN_FILTER
+ boolean "Touchscreen Filtering"
+ depends on INPUT_TOUCHSCREEN
+ select TOUCHSCREEN_FILTER_GROUP
+ select TOUCHSCREEN_FILTER_MEDIAN
+ select TOUCHSCREEN_FILTER_MEAN
+ select TOUCHSCREEN_FILTER_LINEAR
+ help
+ Select this to include kernel touchscreen filter support. The filters
+ can be combined in any order in your machine init and the parameters
+ for them can also be set there.
+
+if TOUCHSCREEN_FILTER
+
+config TOUCHSCREEN_FILTER_GROUP
+ bool "Group Touchscreen Filter"
+ depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
+ default Y
+ help
+ Say Y here if you want to use the Group touchscreen filter, it
+ avoids using atypical samples.
+
+config TOUCHSCREEN_FILTER_MEDIAN
+ bool "Median Average Touchscreen Filter"
+ depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
+ default Y
+ help
+ Say Y here if you want to use the Median touchscreen filter, it's
+ highly effective if you data is noisy with occasional excursions.
+
+config TOUCHSCREEN_FILTER_MEAN
+ bool "Mean Average Touchscreen Filter"
+ depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
+ default Y
+ help
+ Say Y here if you want to use the Mean touchscreen filter, it
+ can further improve decent quality data by removing jitter
+
+config TOUCHSCREEN_FILTER_LINEAR
+ bool "Linear Touchscreen Filter"
+ depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
+ default Y
+ help
+ Say Y here if you want to use the Linear touchscreen filter, it
+ enables the use of calibration data for the touchscreen.
+
+endif
+
config TOUCHSCREEN_ADS7846
tristate "ADS7846/TSC2046 and ADS7843 based touchscreens"
depends on SPI_MASTER
Index: linux-2.6.30-rc6/drivers/input/touchscreen/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/drivers/input/touchscreen/Makefile 2009-05-18 19:08:31.000000000 +0200
+++ linux-2.6.30-rc6/drivers/input/touchscreen/Makefile 2009-05-18 19:08:32.000000000 +0200
@@ -38,3 +38,8 @@
obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
+obj-$(CONFIG_TOUCHSCREEN_FILTER) += ts_filter_chain.o
+obj-$(CONFIG_TOUCHSCREEN_FILTER_GROUP) += ts_filter_group.o
+obj-$(CONFIG_TOUCHSCREEN_FILTER_LINEAR) += ts_filter_linear.o
+obj-$(CONFIG_TOUCHSCREEN_FILTER_MEDIAN) += ts_filter_median.o
+obj-$(CONFIG_TOUCHSCREEN_FILTER_MEAN) += ts_filter_mean.o

View File

@@ -0,0 +1,37 @@
Index: linux-2.6.30-rc6/drivers/mfd/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/drivers/mfd/Kconfig 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/mfd/Kconfig 2009-05-18 19:08:32.000000000 +0200
@@ -241,6 +241,8 @@
Say yes here if you want to include support GPIO for pins on
the PCF50633 chip.
+source "drivers/mfd/glamo/Kconfig"
+
endmenu
menu "Multimedia Capabilities Port drivers"
Index: linux-2.6.30-rc6/drivers/mfd/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/drivers/mfd/Makefile 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/mfd/Makefile 2009-05-18 19:08:32.000000000 +0200
@@ -4,6 +4,7 @@
obj-$(CONFIG_MFD_SM501) += sm501.o
obj-$(CONFIG_MFD_ASIC3) += asic3.o
+obj-$(CONFIG_MFD_GLAMO) += glamo/
obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
Index: linux-2.6.30-rc6/include/linux/fb.h
===================================================================
--- linux-2.6.30-rc6.orig/include/linux/fb.h 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/include/linux/fb.h 2009-05-18 19:08:32.000000000 +0200
@@ -124,6 +124,7 @@
#define FB_ACCEL_TRIDENT_BLADE3D 52 /* Trident Blade3D */
#define FB_ACCEL_TRIDENT_BLADEXP 53 /* Trident BladeXP */
#define FB_ACCEL_CIRRUS_ALPINE 53 /* Cirrus Logic 543x/544x/5480 */
+#define FB_ACCEL_GLAMO 50 /* SMedia Glamo */
#define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */
#define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */
#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */

View File

@@ -0,0 +1,35 @@
Index: linux-2.6.30-rc6/drivers/power/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/drivers/power/Kconfig 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/power/Kconfig 2009-05-18 19:08:32.000000000 +0200
@@ -88,4 +88,16 @@
help
Say Y to include support for NXP PCF50633 Main Battery Charger.
+config BATTERY_BQ27000_HDQ
+ tristate "BQ27000 HDQ battery monitor driver"
+ help
+ Say Y to enable support for the battery on the Neo Freerunner
+
+config HDQ_GPIO_BITBANG
+ bool "Generic gpio based HDQ bitbang"
+ help
+ Say Y to enable supoort for generic gpio based HDQ bitbang driver.
+ This can not be built as a module.
+
endif # POWER_SUPPLY
+
Index: linux-2.6.30-rc6/drivers/power/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/drivers/power/Makefile 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/power/Makefile 2009-05-18 19:08:32.000000000 +0200
@@ -25,4 +25,7 @@
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
-obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
\ No newline at end of file
+obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
+obj-$(CONFIG_BATTERY_BQ27000_HDQ) += bq27000_battery.o
+
+obj-$(CONFIG_HDQ_GPIO_BITBANG) += hdq.o

View File

@@ -0,0 +1,37 @@
Index: linux-2.6.30-rc6/drivers/leds/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/drivers/leds/Kconfig 2009-05-18 19:07:07.000000000 +0200
+++ linux-2.6.30-rc6/drivers/leds/Kconfig 2009-05-18 19:08:33.000000000 +0200
@@ -227,6 +227,19 @@
This option enables support for BD2802GU RGB LED driver chips
accessed via the I2C bus.
+config LEDS_GTA02_VIBRATOR
+ tristate "Vibrator Support for the Openmoko Freerunner GSM phone"
+ depends on LEDS_CLASS && MACH_NEO1973_GTA02
+ help
+ This option enables support for the vibrator on the Openmoko Freerunner.
+
+config LEDS_GTA02
+ tristate "LED Support for the Openmoko Freerunner GSM phone"
+ depends on LEDS_CLASS && MACH_NEO1973_GTA02
+ help
+ This option enables support for the LEDs on the Openmoko Freerunner.
+
+
comment "LED Triggers"
config LEDS_TRIGGERS
Index: linux-2.6.30-rc6/drivers/leds/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/drivers/leds/Makefile 2009-05-18 19:07:07.000000000 +0200
+++ linux-2.6.30-rc6/drivers/leds/Makefile 2009-05-18 19:08:33.000000000 +0200
@@ -30,6 +30,8 @@
# LED SPI Drivers
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
+obj-$(CONFIG_LEDS_GTA02_VIBRATOR) += leds-gta02-vibrator.o
+obj-$(CONFIG_LEDS_GTA02) += leds-gta02.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o

View File

@@ -0,0 +1,30 @@
Index: linux-2.6.30-rc6/drivers/video/display/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/drivers/video/display/Kconfig 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/video/display/Kconfig 2009-05-18 19:08:33.000000000 +0200
@@ -21,4 +21,15 @@
comment "Display hardware drivers"
depends on DISPLAY_SUPPORT
+config DISPLAY_JBT6K74
+ tristate "TPO JBT6K74-AS TFT display ASIC control interface"
+ depends on SPI_MASTER && SYSFS
+ help
+ SPI driver for the control interface of TFT panels containing
+ the TPO JBT6K74-AS controller ASIC, such as the TPO TD028TTEC1
+ TFT diplay module used in the Openmoko Freerunner GSM phone.
+
+ The control interface is required for display operation, as it
+ controls power management, display timing and gamma calibration.
+
endmenu
Index: linux-2.6.30-rc6/drivers/video/display/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/drivers/video/display/Makefile 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/video/display/Makefile 2009-05-18 19:08:33.000000000 +0200
@@ -3,4 +3,5 @@
display-objs := display-sysfs.o
obj-$(CONFIG_DISPLAY_SUPPORT) += display.o
+obj-$(CONFIG_DISPLAY_JBT6K74) += jbt6k74.o

View File

@@ -0,0 +1,375 @@
Index: linux-2.6.30-rc6/drivers/mfd/pcf50633-core.c
===================================================================
--- linux-2.6.30-rc6.orig/drivers/mfd/pcf50633-core.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/mfd/pcf50633-core.c 2009-05-18 19:08:33.000000000 +0200
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/sysfs.h>
+#include <linux/device.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/interrupt.h>
@@ -345,6 +346,8 @@
goto out;
}
+ pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN, 0x04 ); /* defeat 8s death from lowsys on A5 */
+
/* We immediately read the usb and adapter status. We thus make sure
* only of USBINS/USBREM IRQ handlers are called */
if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) {
@@ -443,7 +446,8 @@
dev_dbg(pcf->dev, "pcf50633_irq\n");
get_device(pcf->dev);
- disable_irq(pcf->irq);
+ disable_irq_nosync(pcf->irq);
+
schedule_work(&pcf->irq_work);
return IRQ_HANDLED;
@@ -482,13 +486,13 @@
}
#ifdef CONFIG_PM
-static int pcf50633_suspend(struct device *dev, pm_message_t state)
+static int pcf50633_suspend(struct i2c_client *client, pm_message_t state)
{
struct pcf50633 *pcf;
int ret = 0, i;
u8 res[5];
- pcf = dev_get_drvdata(dev);
+ pcf = i2c_get_clientdata(client);
/* Make sure our interrupt handlers are not called
* henceforth */
@@ -523,12 +527,12 @@
return ret;
}
-static int pcf50633_resume(struct device *dev)
+static int pcf50633_resume(struct i2c_client *client)
{
struct pcf50633 *pcf;
int ret;
- pcf = dev_get_drvdata(dev);
+ pcf = i2c_get_clientdata(client);
/* Write the saved mask registers */
ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
@@ -625,6 +629,7 @@
}
if (client->irq) {
+ set_irq_handler(client->irq, handle_level_irq);
ret = request_irq(client->irq, pcf50633_irq,
IRQF_TRIGGER_LOW, "pcf50633", pcf);
@@ -683,12 +688,12 @@
static struct i2c_driver pcf50633_driver = {
.driver = {
.name = "pcf50633",
- .suspend = pcf50633_suspend,
- .resume = pcf50633_resume,
},
.id_table = pcf50633_id_table,
.probe = pcf50633_probe,
.remove = __devexit_p(pcf50633_remove),
+ .suspend = pcf50633_suspend,
+ .resume = pcf50633_resume,
};
static int __init pcf50633_init(void)
Index: linux-2.6.30-rc6/drivers/power/pcf50633-charger.c
===================================================================
--- linux-2.6.30-rc6.orig/drivers/power/pcf50633-charger.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/power/pcf50633-charger.c 2009-05-18 19:08:33.000000000 +0200
@@ -36,6 +36,7 @@
struct power_supply usb;
struct power_supply adapter;
+ struct power_supply ac;
struct delayed_work charging_restart_work;
};
@@ -47,16 +48,21 @@
u8 bits;
int charging_start = 1;
u8 mbcs2, chgmod;
+ unsigned int mbcc5;
- if (ma >= 1000)
+ if (ma >= 1000) {
bits = PCF50633_MBCC7_USB_1000mA;
- else if (ma >= 500)
+ ma = 1000;
+ } else if (ma >= 500) {
bits = PCF50633_MBCC7_USB_500mA;
- else if (ma >= 100)
+ ma = 500;
+ } else if (ma >= 100) {
bits = PCF50633_MBCC7_USB_100mA;
- else {
+ ma = 100;
+ } else {
bits = PCF50633_MBCC7_USB_SUSPEND;
charging_start = 0;
+ ma = 0;
}
ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7,
@@ -66,7 +72,22 @@
else
dev_info(pcf->dev, "usb curlim to %d mA\n", ma);
- /* Manual charging start */
+ /*
+ * We limit the charging current to be the USB current limit.
+ * The reason is that on pcf50633, when it enters PMU Standby mode,
+ * which it does when the device goes "off", the USB current limit
+ * reverts to the variant default. In at least one common case, that
+ * default is 500mA. By setting the charging current to be the same
+ * as the USB limit we set here before PMU standby, we enforce it only
+ * using the correct amount of current even when the USB current limit
+ * gets reset to the wrong thing
+ */
+
+ mbcc5 = (ma << 8) / mbc->pcf->pdata->chg_ref_current_ma;
+ if (mbcc5 > 255)
+ mbcc5 = 255;
+ pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5);
+
mbcs2 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
@@ -81,7 +102,7 @@
PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME);
mbc->usb_active = charging_start;
-
+
power_supply_changed(&mbc->usb);
return ret;
@@ -156,9 +177,44 @@
static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim);
+static ssize_t
+show_chglim(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
+ u8 mbcc5 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC5);
+ unsigned int ma;
+
+ ma = (mbc->pcf->pdata->chg_ref_current_ma * mbcc5) >> 8;
+
+ return sprintf(buf, "%u\n", ma);
+}
+
+static ssize_t set_chglim(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
+ unsigned long ma;
+ unsigned int mbcc5;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &ma);
+ if (ret)
+ return -EINVAL;
+
+ mbcc5 = (ma << 8) / mbc->pcf->pdata->chg_ref_current_ma;
+ if (mbcc5 > 255)
+ mbcc5 = 255;
+ pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5);
+
+ return count;
+}
+
+static DEVICE_ATTR(chg_curlim, S_IRUGO | S_IWUSR, show_chglim, set_chglim);
+
static struct attribute *pcf50633_mbc_sysfs_entries[] = {
&dev_attr_chgmode.attr,
&dev_attr_usb_curlim.attr,
+ &dev_attr_chg_curlim.attr,
NULL,
};
@@ -239,6 +295,7 @@
power_supply_changed(&mbc->usb);
power_supply_changed(&mbc->adapter);
+ power_supply_changed(&mbc->ac);
if (mbc->pcf->pdata->mbc_event_callback)
mbc->pcf->pdata->mbc_event_callback(mbc->pcf, irq);
@@ -248,8 +305,7 @@
enum power_supply_property psp,
union power_supply_propval *val)
{
- struct pcf50633_mbc *mbc = container_of(psy,
- struct pcf50633_mbc, adapter);
+ struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, adapter);
int ret = 0;
switch (psp) {
@@ -269,10 +325,34 @@
{
struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb);
int ret = 0;
+ u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) &
+ PCF50633_MBCC7_USB_MASK;
switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
- val->intval = mbc->usb_online;
+ val->intval = mbc->usb_online &&
+ (usblim <= PCF50633_MBCC7_USB_500mA);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int ac_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, ac);
+ int ret = 0;
+ u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) &
+ PCF50633_MBCC7_USB_MASK;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = mbc->usb_online &&
+ (usblim == PCF50633_MBCC7_USB_1000mA);
break;
default:
ret = -EINVAL;
@@ -337,6 +417,17 @@
mbc->usb.supplied_to = mbc->pcf->pdata->batteries;
mbc->usb.num_supplicants = mbc->pcf->pdata->num_batteries;
+ mbc->ac.name = "ac";
+ mbc->ac.type = POWER_SUPPLY_TYPE_MAINS;
+ mbc->ac.properties = power_props;
+ mbc->ac.num_properties = ARRAY_SIZE(power_props);
+ mbc->ac.get_property = ac_get_property;
+ mbc->ac.supplied_to = mbc->pcf->pdata->batteries;
+ mbc->ac.num_supplicants = mbc->pcf->pdata->num_batteries;
+
+ INIT_DELAYED_WORK(&mbc->charging_restart_work,
+ pcf50633_mbc_charging_restart);
+
ret = power_supply_register(&pdev->dev, &mbc->adapter);
if (ret) {
dev_err(mbc->pcf->dev, "failed to register adapter\n");
@@ -352,9 +443,15 @@
return ret;
}
- INIT_DELAYED_WORK(&mbc->charging_restart_work,
- pcf50633_mbc_charging_restart);
-
+ ret = power_supply_register(&pdev->dev, &mbc->ac);
+ if (ret) {
+ dev_err(mbc->pcf->dev, "failed to register ac\n");
+ power_supply_unregister(&mbc->adapter);
+ power_supply_unregister(&mbc->usb);
+ kfree(mbc);
+ return ret;
+ }
+
ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group);
if (ret)
dev_err(mbc->pcf->dev, "failed to create sysfs entries\n");
Index: linux-2.6.30-rc6/drivers/rtc/rtc-pcf50633.c
===================================================================
--- linux-2.6.30-rc6.orig/drivers/rtc/rtc-pcf50633.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/rtc/rtc-pcf50633.c 2009-05-18 19:08:33.000000000 +0200
@@ -58,6 +58,7 @@
struct pcf50633_rtc {
int alarm_enabled;
int second_enabled;
+ int alarm_pending;
struct pcf50633 *pcf;
struct rtc_device *rtc_dev;
@@ -70,7 +71,7 @@
rtc->tm_hour = bcd2bin(pcf->time[PCF50633_TI_HOUR]);
rtc->tm_wday = bcd2bin(pcf->time[PCF50633_TI_WKDAY]);
rtc->tm_mday = bcd2bin(pcf->time[PCF50633_TI_DAY]);
- rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]);
+ rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]) - 1;
rtc->tm_year = bcd2bin(pcf->time[PCF50633_TI_YEAR]) + 100;
}
@@ -81,7 +82,7 @@
pcf->time[PCF50633_TI_HOUR] = bin2bcd(rtc->tm_hour);
pcf->time[PCF50633_TI_WKDAY] = bin2bcd(rtc->tm_wday);
pcf->time[PCF50633_TI_DAY] = bin2bcd(rtc->tm_mday);
- pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon);
+ pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon + 1);
pcf->time[PCF50633_TI_YEAR] = bin2bcd(rtc->tm_year % 100);
}
@@ -209,6 +210,7 @@
rtc = dev_get_drvdata(dev);
alrm->enabled = rtc->alarm_enabled;
+ alrm->pending = rtc->alarm_pending;
ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA,
PCF50633_TI_EXTENT, &pcf_tm.time[0]);
@@ -244,9 +246,12 @@
/* Returns 0 on success */
ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA,
PCF50633_TI_EXTENT, &pcf_tm.time[0]);
+ if (!alrm->enabled)
+ rtc->alarm_pending = 0;
- if (!alarm_masked)
+ if (!alarm_masked || alrm->enabled)
pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
+ rtc->alarm_enabled = alrm->enabled;
return ret;
}
@@ -267,6 +272,7 @@
switch (irq) {
case PCF50633_IRQ_ALARM:
rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+ rtc->alarm_pending = 1;
break;
case PCF50633_IRQ_SECOND:
rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
Index: linux-2.6.30-rc6/include/linux/mfd/pcf50633/core.h
===================================================================
--- linux-2.6.30-rc6.orig/include/linux/mfd/pcf50633/core.h 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/include/linux/mfd/pcf50633/core.h 2009-05-18 19:08:33.000000000 +0200
@@ -31,6 +31,8 @@
int charging_restart_interval;
+ int chg_ref_current_ma;
+
/* Callbacks */
void (*probe_done)(struct pcf50633 *);
void (*mbc_event_callback)(struct pcf50633 *, int);
@@ -208,7 +210,8 @@
};
/* misc. registers */
-#define PCF50633_REG_OOCSHDWN 0x0c
+#define PCF50633_REG_OOCSHDWN 0x0c
+#define PCF50633_OOCSHDWN_GOSTDBY 0x01
/* LED registers */
#define PCF50633_REG_LEDOUT 0x28

View File

@@ -0,0 +1,29 @@
Index: linux-2.6.30-rc6/drivers/input/misc/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/drivers/input/misc/Kconfig 2009-05-18 19:07:07.000000000 +0200
+++ linux-2.6.30-rc6/drivers/input/misc/Kconfig 2009-05-18 19:08:33.000000000 +0200
@@ -220,6 +220,15 @@
Say Y here if you want to support the built-in real time clock
of the HP SDC controller.
+config INPUT_LIS302DL
+ tristate "STmicro LIS302DL 3-axis accelerometer"
+ depends on SPI_MASTER
+ help
+ SPI driver for the STmicro LIS302DL 3-axis accelerometer.
+
+ The userspece interface is a 3-axis (X/Y/Z) relative movement
+ Linux input device, reporting REL_[XYZ] events.
+
config INPUT_PCF50633_PMU
tristate "PCF50633 PMU events"
depends on MFD_PCF50633
Index: linux-2.6.30-rc6/drivers/input/misc/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/drivers/input/misc/Makefile 2009-05-18 19:07:07.000000000 +0200
+++ linux-2.6.30-rc6/drivers/input/misc/Makefile 2009-05-18 19:08:33.000000000 +0200
@@ -25,3 +25,4 @@
obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
obj-$(CONFIG_INPUT_GPIO_BUTTONS) += gpio_buttons.o
+obj-$(CONFIG_INPUT_LIS302DL) += lis302dl.o

View File

@@ -0,0 +1,432 @@
Index: linux-2.6.30-rc6/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/mach-s3c2410/include/mach/spi-gpio.h 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/mach-s3c2410/include/mach/spi-gpio.h 2009-05-18 19:08:34.000000000 +0200
@@ -21,7 +21,8 @@
int num_chipselect;
int bus_num;
- void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
+ int non_blocking_transfer;
+ void (*chip_select)(struct s3c2410_spigpio_info *spi, int csid, int cs);
};
Index: linux-2.6.30-rc6/drivers/spi/spi_bitbang.c
===================================================================
--- linux-2.6.30-rc6.orig/drivers/spi/spi_bitbang.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/spi/spi_bitbang.c 2009-05-18 19:08:34.000000000 +0200
@@ -264,6 +264,123 @@
* Drivers can provide word-at-a-time i/o primitives, or provide
* transfer-at-a-time ones to leverage dma or fifo hardware.
*/
+
+/* Synchronous non blocking transfer */
+int
+spi_bitbang_transfer_sync(struct spi_device *spi, struct spi_message *m)
+{
+ struct spi_bitbang *bitbang = spi_master_get_devdata(spi->master);
+ struct spi_transfer *t;
+ unsigned long flags;
+ int cs_change = 1;
+ int status;
+ int nsecs;
+ int (*setup_transfer)(struct spi_device *, struct spi_transfer *);
+
+ /* FIXME this is made-up ... the correct value is known to
+ * word-at-a-time bitbang code, and presumably chipselect()
+ * should enforce these requirements too?
+ */
+ nsecs = 100;
+ cs_change = 1;
+ status = 0;
+ setup_transfer = NULL;
+
+ local_irq_save(flags);
+ list_for_each_entry (t, &m->transfers, transfer_list) {
+ /* override or restore speed and wordsize */
+ if (t->speed_hz || t->bits_per_word) {
+ setup_transfer = bitbang->setup_transfer;
+ if (!setup_transfer) {
+ status = -ENOPROTOOPT;
+ break;
+ }
+ }
+ if (setup_transfer) {
+ status = setup_transfer(spi, t);
+ if (status < 0)
+ break;
+ }
+
+ /* set up default clock polarity, and activate chip;
+ * this implicitly updates clock and spi modes as
+ * previously recorded for this device via setup().
+ * (and also deselects any other chip that might be
+ * selected ...)
+ */
+
+ if (cs_change) {
+ bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
+ ndelay(nsecs);
+ }
+
+ cs_change = t->cs_change;
+ if (!t->tx_buf && !t->rx_buf && t->len) {
+ status = -EINVAL;
+ break;
+ }
+
+ /* transfer data. the lower level code handles any
+ * new dma mappings it needs. our caller always gave
+ * us dma-safe buffers.
+ */
+ if (t->len) {
+ /* REVISIT dma API still needs a designated
+ * DMA_ADDR_INVALID; ~0 might be better.
+ */
+ if (!m->is_dma_mapped)
+ t->rx_dma = t->tx_dma = 0;
+ status = bitbang->txrx_bufs(spi, t);
+ }
+
+ if (status > 0)
+ m->actual_length += status;
+ if (status != t->len) {
+ /* always report some kind of error */
+ if (status >= 0)
+ status = -EREMOTEIO;
+ break;
+ }
+ status = 0;
+ /* protocol tweaks before next transfer */
+ if (t->delay_usecs)
+ udelay(t->delay_usecs);
+ if (!cs_change)
+ continue;
+ if (t->transfer_list.next == &m->transfers)
+ break;
+ /* sometimes a short mid-message deselect of the chip
+ * may be needed to terminate a mode or command
+ */
+ ndelay(nsecs);
+ bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+ ndelay(nsecs);
+ }
+
+ m->status = status;
+ if (m->complete)
+ m->complete(m->context);
+
+ /* restore speed and wordsize */
+ if (setup_transfer)
+ setup_transfer(spi, NULL);
+
+ /* normally deactivate chipselect ... unless no error and
+ * cs_change has hinted that the next message will probably
+ * be for this chip too.
+ */
+ if (!(status == 0 && cs_change)) {
+ ndelay(nsecs);
+ bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+ ndelay(nsecs);
+ }
+
+ local_irq_restore(flags);
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_transfer_sync);
+
static void bitbang_work(struct work_struct *work)
{
struct spi_bitbang *bitbang =
@@ -274,120 +391,13 @@
bitbang->busy = 1;
while (!list_empty(&bitbang->queue)) {
struct spi_message *m;
- struct spi_device *spi;
- unsigned nsecs;
- struct spi_transfer *t = NULL;
- unsigned tmp;
- unsigned cs_change;
- int status;
- int (*setup_transfer)(struct spi_device *,
- struct spi_transfer *);
m = container_of(bitbang->queue.next, struct spi_message,
queue);
list_del_init(&m->queue);
- spin_unlock_irqrestore(&bitbang->lock, flags);
-
- /* FIXME this is made-up ... the correct value is known to
- * word-at-a-time bitbang code, and presumably chipselect()
- * should enforce these requirements too?
- */
- nsecs = 100;
-
- spi = m->spi;
- tmp = 0;
- cs_change = 1;
- status = 0;
- setup_transfer = NULL;
-
- list_for_each_entry (t, &m->transfers, transfer_list) {
-
- /* override or restore speed and wordsize */
- if (t->speed_hz || t->bits_per_word) {
- setup_transfer = bitbang->setup_transfer;
- if (!setup_transfer) {
- status = -ENOPROTOOPT;
- break;
- }
- }
- if (setup_transfer) {
- status = setup_transfer(spi, t);
- if (status < 0)
- break;
- }
-
- /* set up default clock polarity, and activate chip;
- * this implicitly updates clock and spi modes as
- * previously recorded for this device via setup().
- * (and also deselects any other chip that might be
- * selected ...)
- */
- if (cs_change) {
- bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
- ndelay(nsecs);
- }
- cs_change = t->cs_change;
- if (!t->tx_buf && !t->rx_buf && t->len) {
- status = -EINVAL;
- break;
- }
-
- /* transfer data. the lower level code handles any
- * new dma mappings it needs. our caller always gave
- * us dma-safe buffers.
- */
- if (t->len) {
- /* REVISIT dma API still needs a designated
- * DMA_ADDR_INVALID; ~0 might be better.
- */
- if (!m->is_dma_mapped)
- t->rx_dma = t->tx_dma = 0;
- status = bitbang->txrx_bufs(spi, t);
- }
- if (status > 0)
- m->actual_length += status;
- if (status != t->len) {
- /* always report some kind of error */
- if (status >= 0)
- status = -EREMOTEIO;
- break;
- }
- status = 0;
-
- /* protocol tweaks before next transfer */
- if (t->delay_usecs)
- udelay(t->delay_usecs);
-
- if (!cs_change)
- continue;
- if (t->transfer_list.next == &m->transfers)
- break;
-
- /* sometimes a short mid-message deselect of the chip
- * may be needed to terminate a mode or command
- */
- ndelay(nsecs);
- bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
- ndelay(nsecs);
- }
-
- m->status = status;
- m->complete(m->context);
-
- /* restore speed and wordsize */
- if (setup_transfer)
- setup_transfer(spi, NULL);
-
- /* normally deactivate chipselect ... unless no error and
- * cs_change has hinted that the next message will probably
- * be for this chip too.
- */
- if (!(status == 0 && cs_change)) {
- ndelay(nsecs);
- bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
- ndelay(nsecs);
- }
+ spin_unlock_irqrestore(&bitbang->lock, flags);
+ spi_bitbang_transfer_sync(m->spi, m);
spin_lock_irqsave(&bitbang->lock, flags);
}
bitbang->busy = 0;
@@ -459,6 +469,9 @@
if (!bitbang->master->transfer)
bitbang->master->transfer = spi_bitbang_transfer;
+ if (!bitbang->master->transfer_sync && bitbang->non_blocking_transfer)
+ bitbang->master->transfer_sync = spi_bitbang_transfer_sync;
+
if (!bitbang->txrx_bufs) {
bitbang->use_dma = 0;
bitbang->txrx_bufs = spi_bitbang_bufs;
Index: linux-2.6.30-rc6/drivers/spi/spi_s3c24xx_gpio.c
===================================================================
--- linux-2.6.30-rc6.orig/drivers/spi/spi_s3c24xx_gpio.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/spi/spi_s3c24xx_gpio.c 2009-05-18 19:08:34.000000000 +0200
@@ -91,7 +91,7 @@
struct s3c2410_spigpio *sg = spidev_to_sg(dev);
if (sg->info && sg->info->chip_select)
- (sg->info->chip_select)(sg->info, value);
+ (sg->info->chip_select)(sg->info, dev->chip_select, value);
}
static int s3c2410_spigpio_probe(struct platform_device *dev)
@@ -112,14 +112,17 @@
platform_set_drvdata(dev, sp);
- /* copy in the plkatform data */
+ /* copy in the platform data */
info = sp->info = dev->dev.platform_data;
+ master->num_chipselect = info->num_chipselect;
+
/* setup spi bitbang adaptor */
sp->bitbang.master = spi_master_get(master);
sp->bitbang.master->bus_num = info->bus_num;
sp->bitbang.master->num_chipselect = info->num_chipselect;
sp->bitbang.chipselect = s3c2410_spigpio_chipselect;
+ sp->bitbang.non_blocking_transfer = info->non_blocking_transfer;
sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1;
Index: linux-2.6.30-rc6/include/linux/mmc/core.h
===================================================================
--- linux-2.6.30-rc6.orig/include/linux/mmc/core.h 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/include/linux/mmc/core.h 2009-05-18 19:08:34.000000000 +0200
@@ -129,6 +129,8 @@
struct mmc_host;
struct mmc_card;
+extern void mmc_flush_scheduled_work(void);
+
extern void mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
Index: linux-2.6.30-rc6/include/linux/mmc/sdio_ids.h
===================================================================
--- linux-2.6.30-rc6.orig/include/linux/mmc/sdio_ids.h 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/include/linux/mmc/sdio_ids.h 2009-05-18 19:08:34.000000000 +0200
@@ -25,5 +25,9 @@
#define SDIO_VENDOR_ID_MARVELL 0x02df
#define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103
+#define SDIO_DEVICE_ID_MARVELL_88W8688 0x9104
+#define SDIO_VENDOR_ID_ATHEROS 0x0271
+#define SDIO_DEVICE_ID_ATHEROS_AR6001 0x0100
+#define SDIO_DEVICE_ID_ATHEROS_AR6002 0x0200
#endif
Index: linux-2.6.30-rc6/include/linux/spi/spi_bitbang.h
===================================================================
--- linux-2.6.30-rc6.orig/include/linux/spi/spi_bitbang.h 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/include/linux/spi/spi_bitbang.h 2009-05-18 19:08:34.000000000 +0200
@@ -31,6 +31,9 @@
u8 use_dma;
u8 flags; /* extra spi->mode support */
+ /* Support for synchronous non blocking transfers */
+ int non_blocking_transfer;
+
struct spi_master *master;
/* setup_transfer() changes clock and/or wordsize to match settings
@@ -62,6 +65,8 @@
extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m);
extern int spi_bitbang_setup_transfer(struct spi_device *spi,
struct spi_transfer *t);
+extern int spi_bitbang_transfer_sync(struct spi_device *spi,
+ struct spi_message *m);
/* start or stop queue processing */
extern int spi_bitbang_start(struct spi_bitbang *spi);
Index: linux-2.6.30-rc6/include/linux/spi/spi.h
===================================================================
--- linux-2.6.30-rc6.orig/include/linux/spi/spi.h 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/include/linux/spi/spi.h 2009-05-18 19:08:34.000000000 +0200
@@ -204,7 +204,6 @@
* SPI slaves, and are numbered from zero to num_chipselects.
* each slave has a chipselect signal, but it's common that not
* every chipselect is connected to a slave.
- * @dma_alignment: SPI controller constraint on DMA buffers alignment.
* @setup: updates the device mode and clocking records used by a
* device's SPI controller; protocol code may call this. This
* must fail if an unrecognized or unsupported mode is requested.
@@ -240,17 +239,7 @@
*/
u16 num_chipselect;
- /* some SPI controllers pose alignment requirements on DMAable
- * buffers; let protocol drivers know about these requirements.
- */
- u16 dma_alignment;
-
- /* Setup mode and clock, etc (spi driver may call many times).
- *
- * IMPORTANT: this may be called when transfers to another
- * device are active. DO NOT UPDATE SHARED REGISTERS in ways
- * which could break those transfers.
- */
+ /* setup mode and clock, etc (spi driver may call many times) */
int (*setup)(struct spi_device *spi);
/* bidirectional bulk transfers
@@ -275,6 +264,13 @@
int (*transfer)(struct spi_device *spi,
struct spi_message *mesg);
+ /*
+ * Synchronous non blocking transfer function. Should guarantee
+ * data availability when it returns
+ */
+ int (*transfer_sync)(struct spi_device *spi,
+ struct spi_message *mesg);
+
/* called on release() to free memory provided by spi_master */
void (*cleanup)(struct spi_device *spi);
};
@@ -584,6 +580,29 @@
return spi->master->transfer(spi, message);
}
+/**
+ * spi_non_blocking_transfer - Synchronous, non blocking transfer
+ * @spi: device with which data will be exchanged
+ * @message: describes the data transfers with optional completion handlers
+ * Context: any (irqs may be blocked, etc)
+ *
+ * Data is guaranteed to be written or read when this function returns.
+ *
+ * Note : This may not be supported by all spi masters.
+ */
+
+static inline int
+spi_non_blocking_transfer(struct spi_device *spi, struct spi_message *message)
+{
+ if (unlikely(!spi->master->transfer_sync)) {
+ dev_err(&spi->master->dev,
+ "non-blocking transfers not supported\n");
+ return -EIO;
+ }
+
+ return spi->master->transfer_sync(spi, message);
+}
+
/*---------------------------------------------------------------------------*/
/* All these synchronous SPI transfer routines are utilities layered

View File

@@ -0,0 +1,25 @@
Index: linux-2.6.30-rc6/arch/arm/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/Kconfig 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/Kconfig 2009-05-18 19:08:34.000000000 +0200
@@ -1401,6 +1401,8 @@
source "drivers/uwb/Kconfig"
+source "drivers/ar6000/Kconfig"
+
source "drivers/mmc/Kconfig"
source "drivers/memstick/Kconfig"
Index: linux-2.6.30-rc6/drivers/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/drivers/Makefile 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/Makefile 2009-05-18 19:08:34.000000000 +0200
@@ -91,6 +91,7 @@
obj-y += idle/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_MEMSTICK) += memstick/
+obj-$(CONFIG_AR6000_WLAN) += ar6000/
obj-$(CONFIG_NEW_LEDS) += leds/
obj-$(CONFIG_INFINIBAND) += infiniband/
obj-$(CONFIG_SGI_SN) += sn/

View File

@@ -0,0 +1,485 @@
Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/time.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/time.c 2009-05-18 19:08:34.000000000 +0200
@@ -0,0 +1,480 @@
+/* linux/arch/arm/plat-s3c24xx/time.c
+ *
+ * Copyright (C) 2003-2005 Simtec Electronics
+ * Ben Dooks, <ben@simtec.co.uk>
+ *
+ * dyn_tick support by Andrzej Zaborowski based on omap_dyn_tick_timer.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/system.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <mach/map.h>
+#include <asm/plat-s3c/regs-timer.h>
+#include <mach/regs-irq.h>
+#include <asm/mach/time.h>
+
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+static unsigned long timer_startval;
+static unsigned long timer_usec_ticks;
+static struct work_struct resume_work;
+
+unsigned long pclk;
+struct clk *clk;
+
+#define TIMER_USEC_SHIFT 16
+
+/* we use the shifted arithmetic to work out the ratio of timer ticks
+ * to usecs, as often the peripheral clock is not a nice even multiple
+ * of 1MHz.
+ *
+ * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok
+ * for the current HZ value of 200 without producing overflows.
+ *
+ * Original patch by Dimitry Andric, updated by Ben Dooks
+*/
+
+
+/* timer_mask_usec_ticks
+ *
+ * given a clock and divisor, make the value to pass into timer_ticks_to_usec
+ * to scale the ticks into usecs
+*/
+
+static inline unsigned long
+timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk)
+{
+ unsigned long den = pclk / 1000;
+
+ return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den;
+}
+
+/* timer_ticks_to_usec
+ *
+ * convert timer ticks to usec.
+*/
+
+static inline unsigned long timer_ticks_to_usec(unsigned long ticks)
+{
+ unsigned long res;
+
+ res = ticks * timer_usec_ticks;
+ res += 1 << (TIMER_USEC_SHIFT - 4); /* round up slightly */
+
+ return res >> TIMER_USEC_SHIFT;
+}
+
+/***
+ * Returns microsecond since last clock interrupt. Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ * IRQs are disabled before entering here from do_gettimeofday()
+ */
+
+#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0))
+
+unsigned long s3c2410_gettimeoffset (void)
+{
+ unsigned long tdone;
+ unsigned long irqpend;
+ unsigned long tval;
+
+ /* work out how many ticks have gone since last timer interrupt */
+
+ tval = __raw_readl(S3C2410_TCNTO(4));
+ tdone = timer_startval - tval;
+
+ /* check to see if there is an interrupt pending */
+
+ irqpend = __raw_readl(S3C2410_SRCPND);
+ if (irqpend & SRCPND_TIMER4) {
+ /* re-read the timer, and try and fix up for the missed
+ * interrupt. Note, the interrupt may go off before the
+ * timer has re-loaded from wrapping.
+ */
+
+ tval = __raw_readl(S3C2410_TCNTO(4));
+ tdone = timer_startval - tval;
+
+ if (tval != 0)
+ tdone += timer_startval;
+ }
+
+ return timer_ticks_to_usec(tdone);
+}
+
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+s3c2410_timer_interrupt(int irq, void *dev_id)
+{
+ timer_tick();
+ return IRQ_HANDLED;
+}
+
+static struct irqaction s3c2410_timer_irq = {
+ .name = "S3C2410 Timer Tick",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = s3c2410_timer_interrupt,
+};
+
+#define use_tclk1_12() ( \
+ machine_is_bast() || \
+ machine_is_vr1000() || \
+ machine_is_anubis() || \
+ machine_is_osiris() )
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ *
+ * Currently we only use timer4, as it is the only timer which has no
+ * other function that can be exploited externally
+ */
+static void s3c2410_timer_setup (void)
+{
+ unsigned long tcon;
+ unsigned long tcnt;
+ unsigned long tcfg1;
+ unsigned long tcfg0;
+
+ tcnt = 0xffff; /* default value for tcnt */
+
+ /* read the current timer configuration bits */
+
+ tcon = __raw_readl(S3C2410_TCON);
+ tcfg1 = __raw_readl(S3C2410_TCFG1);
+ tcfg0 = __raw_readl(S3C2410_TCFG0);
+
+ /* configure the system for whichever machine is in use */
+
+ if (use_tclk1_12()) {
+ /* timer is at 12MHz, scaler is 1 */
+ timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
+ tcnt = 12000000 / HZ;
+
+ tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
+ tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
+ } else {
+ /* since values around 50 to
+ * 70MHz are not values we can directly generate the timer
+ * value from, we need to pre-scale and divide before using it.
+ *
+ * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz
+ * (8.45 ticks per usec)
+ */
+
+ /* configure clock tick */
+ timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
+ printk("timer_usec_ticks = %lu\n", timer_usec_ticks);
+
+ tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
+ tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
+
+ tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
+ tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
+
+ tcnt = (pclk / 6) / HZ;
+ }
+
+ /* timers reload after counting zero, so reduce the count by 1 */
+
+ tcnt--;
+
+ printk("timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n",
+ tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks);
+
+ /* check to see if timer is within 16bit range... */
+ if (tcnt > 0xffff) {
+ panic("setup_timer: HZ is too small, cannot configure timer!");
+ return;
+ }
+
+ __raw_writel(tcfg1, S3C2410_TCFG1);
+ __raw_writel(tcfg0, S3C2410_TCFG0);
+
+ timer_startval = tcnt;
+ __raw_writel(tcnt, S3C2410_TCNTB(4));
+
+ /* ensure timer is stopped... */
+
+ tcon &= ~(7<<20);
+ tcon |= S3C2410_TCON_T4RELOAD;
+ tcon |= S3C2410_TCON_T4MANUALUPD;
+
+ __raw_writel(tcon, S3C2410_TCON);
+ __raw_writel(tcnt, S3C2410_TCNTB(4));
+ __raw_writel(tcnt, S3C2410_TCMPB(4));
+
+ /* start the timer running */
+ tcon |= S3C2410_TCON_T4START;
+ tcon &= ~S3C2410_TCON_T4MANUALUPD;
+ __raw_writel(tcon, S3C2410_TCON);
+
+ __raw_writel(__raw_readl(S3C2410_INTMSK) & (~(1UL << 14)),
+ S3C2410_INTMSK);
+
+}
+
+struct sys_timer s3c24xx_timer;
+static void timer_resume_work(struct work_struct *work)
+{
+ clk_enable(clk);
+
+#ifdef CONFIG_NO_IDLE_HZ
+ if (s3c24xx_timer.dyn_tick->state & DYN_TICK_ENABLED)
+ s3c24xx_timer.dyn_tick->enable();
+ else
+#endif
+ s3c2410_timer_setup();
+}
+
+static void __init s3c2410_timer_init (void)
+{
+ if (!use_tclk1_12()) {
+ /* for the h1940 (and others), we use the pclk from the core
+ * to generate the timer values.
+ */
+
+ /* this is used as default if no other timer can be found */
+ clk = clk_get(NULL, "timers");
+ if (IS_ERR(clk))
+ panic("failed to get clock for system timer");
+
+ clk_enable(clk);
+
+ pclk = clk_get_rate(clk);
+ printk("pclk = %lu\n", pclk);
+ }
+
+ INIT_WORK(&resume_work, timer_resume_work);
+ s3c2410_timer_setup();
+ setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
+}
+
+static void s3c2410_timer_resume_work(struct work_struct *work)
+{
+ s3c2410_timer_setup();
+}
+
+static void s3c2410_timer_resume(void)
+{
+ static DECLARE_WORK(work, s3c2410_timer_resume_work);
+ int res;
+
+ res = schedule_work(&work);
+ if (!res)
+ printk(KERN_ERR
+ "s3c2410_timer_resume_work already queued ???\n");
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+/*
+ * We'll set a constant prescaler so we don't have to bother setting it
+ * when reprogramming and so that we avoid costly divisions.
+ *
+ * (2 * HZ) << INPUT_FREQ_SHIFT is the desired frequency after prescaler.
+ * At HZ == 200, HZ * 1024 should work for PCLKs of up to ~53.5 MHz.
+ */
+#define INPUT_FREQ_SHIFT 9
+
+static int ticks_last;
+static int ticks_left;
+static uint32_t tcnto_last;
+
+static inline int s3c24xx_timer_read(void)
+{
+ uint32_t tcnto = __raw_readl(S3C2410_TCNTO(4));
+
+ /*
+ * WARNING: sometimes we get called before TCNTB has been
+ * loaded into the counter and TCNTO then returns its previous
+ * value and kill us, so don't do anything before counter is
+ * reloaded.
+ */
+ if (unlikely(tcnto == tcnto_last))
+ return ticks_last;
+
+ tcnto_last = -1;
+ return tcnto <<
+ ((__raw_readl(S3C2410_TCFG1) >> S3C2410_TCFG1_MUX4_SHIFT) & 3);
+}
+
+static inline void s3c24xx_timer_program(int ticks)
+{
+ uint32_t tcon = __raw_readl(S3C2410_TCON) & ~(7 << 20);
+ uint32_t tcfg1 = __raw_readl(S3C2410_TCFG1) & ~S3C2410_TCFG1_MUX4_MASK;
+
+ /* Just make sure the timer is stopped. */
+ __raw_writel(tcon, S3C2410_TCON);
+
+ /* TODO: add likely()ies / unlikely()ies */
+ if (ticks >> 18) {
+ ticks_last = min(ticks, 0xffff << 3);
+ ticks_left = ticks - ticks_last;
+ __raw_writel(tcfg1 | S3C2410_TCFG1_MUX4_DIV16, S3C2410_TCFG1);
+ __raw_writel(ticks_last >> 3, S3C2410_TCNTB(4));
+ } else if (ticks >> 17) {
+ ticks_last = ticks;
+ ticks_left = 0;
+ __raw_writel(tcfg1 | S3C2410_TCFG1_MUX4_DIV8, S3C2410_TCFG1);
+ __raw_writel(ticks_last >> 2, S3C2410_TCNTB(4));
+ } else if (ticks >> 16) {
+ ticks_last = ticks;
+ ticks_left = 0;
+ __raw_writel(tcfg1 | S3C2410_TCFG1_MUX4_DIV4, S3C2410_TCFG1);
+ __raw_writel(ticks_last >> 1, S3C2410_TCNTB(4));
+ } else {
+ ticks_last = ticks;
+ ticks_left = 0;
+ __raw_writel(tcfg1 | S3C2410_TCFG1_MUX4_DIV2, S3C2410_TCFG1);
+ __raw_writel(ticks_last >> 0, S3C2410_TCNTB(4));
+ }
+
+ tcnto_last = __raw_readl(S3C2410_TCNTO(4));
+ __raw_writel(tcon | S3C2410_TCON_T4MANUALUPD,
+ S3C2410_TCON);
+ __raw_writel(tcon | S3C2410_TCON_T4START,
+ S3C2410_TCON);
+}
+
+/*
+ * If we have already waited all the time we were supposed to wait,
+ * kick the timer, setting the longest allowed timeout value just
+ * for time-keeping.
+ */
+static inline void s3c24xx_timer_program_idle(void)
+{
+ s3c24xx_timer_program(0xffff << 3);
+}
+
+static inline void s3c24xx_timer_update(int restart)
+{
+ int ticks_cur = s3c24xx_timer_read();
+ int jiffies_elapsed = (ticks_last - ticks_cur) >> INPUT_FREQ_SHIFT;
+ int subjiffy = ticks_last - (jiffies_elapsed << INPUT_FREQ_SHIFT);
+
+ if (restart) {
+ if (ticks_left >= (1 << INPUT_FREQ_SHIFT))
+ s3c24xx_timer_program(ticks_left);
+ else
+ s3c24xx_timer_program_idle();
+ ticks_last += subjiffy;
+ } else
+ ticks_last = subjiffy;
+
+ while (jiffies_elapsed --)
+ timer_tick();
+}
+
+/* Called when the timer expires. */
+static irqreturn_t s3c24xx_timer_handler(int irq, void *dev_id)
+{
+ tcnto_last = -1;
+ s3c24xx_timer_update(1);
+
+ return IRQ_HANDLED;
+}
+
+/* Called to update jiffies with time elapsed. */
+static irqreturn_t s3c24xx_timer_handler_dyn_tick(int irq, void *dev_id)
+{
+ s3c24xx_timer_update(0);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Programs the next timer interrupt needed. Called when dynamic tick is
+ * enabled, and to reprogram the ticks to skip from pm_idle. The CPU goes
+ * to sleep directly after this.
+ */
+static void s3c24xx_timer_reprogram_dyn_tick(unsigned long next_jiffies)
+{
+ int subjiffy_left = ticks_last - s3c24xx_timer_read();
+
+ s3c24xx_timer_program(max((int) next_jiffies, 1) << INPUT_FREQ_SHIFT);
+ ticks_last += subjiffy_left;
+}
+
+static unsigned long s3c24xx_timer_offset_dyn_tick(void)
+{
+ /* TODO */
+ return 0;
+}
+
+static int s3c24xx_timer_enable_dyn_tick(void)
+{
+ /* Set our constant prescaler. */
+ uint32_t tcfg0 = __raw_readl(S3C2410_TCFG0);
+ int prescaler =
+ max(min(256, (int) pclk / (HZ << (INPUT_FREQ_SHIFT + 1))), 1);
+
+ tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
+ tcfg0 |= (prescaler - 1) << S3C2410_TCFG_PRESCALER1_SHIFT;
+ __raw_writel(tcfg0, S3C2410_TCFG0);
+
+ /* Override handlers. */
+ s3c2410_timer_irq.handler = s3c24xx_timer_handler;
+ s3c24xx_timer.offset = s3c24xx_timer_offset_dyn_tick;
+
+ printk(KERN_INFO "dyn_tick enabled on s3c24xx timer 4, "
+ "%li Hz pclk with prescaler %i\n", pclk, prescaler);
+
+ s3c24xx_timer_program_idle();
+
+ return 0;
+}
+
+static int s3c24xx_timer_disable_dyn_tick(void)
+{
+ s3c2410_timer_irq.handler = s3c2410_timer_interrupt;
+ s3c24xx_timer.offset = s3c2410_gettimeoffset;
+ s3c2410_timer_setup();
+
+ return 0;
+}
+
+static struct dyn_tick_timer s3c24xx_dyn_tick_timer = {
+ .enable = s3c24xx_timer_enable_dyn_tick,
+ .disable = s3c24xx_timer_disable_dyn_tick,
+ .reprogram = s3c24xx_timer_reprogram_dyn_tick,
+ .handler = s3c24xx_timer_handler_dyn_tick,
+};
+#endif /* CONFIG_NO_IDLE_HZ */
+
+struct sys_timer s3c24xx_timer = {
+ .init = s3c2410_timer_init,
+ .offset = s3c2410_gettimeoffset,
+ .resume = s3c2410_timer_resume,
+#ifdef CONFIG_NO_IDLE_HZ
+ .dyn_tick = &s3c24xx_dyn_tick_timer,
+#endif
+};

View File

@@ -0,0 +1,47 @@
Index: linux-2.6.30-rc6/include/linux/vt.h
===================================================================
--- linux-2.6.30-rc6.orig/include/linux/vt.h 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/include/linux/vt.h 2009-05-18 19:08:35.000000000 +0200
@@ -18,8 +18,19 @@
* resizing).
*/
#define MIN_NR_CONSOLES 1 /* must be at least 1 */
+#if (CONFIG_NR_TTY_DEVICES < 4)
+/* Lower Limit */
+#define MAX_NR_CONSOLES 4 /* serial lines start at 64 */
+#define MAX_NR_USER_CONSOLES 4 /* must be root to allocate above this */
+#elif (CONFIG_NR_TTY_DEVICES > 63)
+/* Upper Limit */
#define MAX_NR_CONSOLES 63 /* serial lines start at 64 */
#define MAX_NR_USER_CONSOLES 63 /* must be root to allocate above this */
+#else
+/* They chose a sensible number */
+#define MAX_NR_CONSOLES CONFIG_NR_TTY_DEVICES
+#define MAX_NR_USER_CONSOLES CONFIG_NR_TTY_DEVICES
+#endif
/* Note: the ioctl VT_GETSTATE does not work for
consoles 16 and higher (since it returns a short) */
Index: linux-2.6.30-rc6/drivers/char/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/drivers/char/Kconfig 2009-05-18 19:07:07.000000000 +0200
+++ linux-2.6.30-rc6/drivers/char/Kconfig 2009-05-18 19:08:35.000000000 +0200
@@ -66,6 +66,18 @@
If unsure, say Y.
+config NR_TTY_DEVICES
+ int "Maximum tty device number"
+ depends on VT
+ default 63
+ ---help---
+ This is the highest numbered device created in /dev. You will actually have
+ NR_TTY_DEVICES+1 devices in /dev. The default is 63, which will result in
+ 64 /dev entries. The lowest number you can set is 11, anything below that,
+ and it will default to 11. 63 is also the upper limit so we don't overrun
+ the serial consoles.
+
+
config HW_CONSOLE
bool
depends on VT && !S390 && !UML

View File

@@ -0,0 +1,150 @@
Index: linux-2.6.30-rc6/sound/soc/s3c24xx/Kconfig
===================================================================
--- linux-2.6.30-rc6.orig/sound/soc/s3c24xx/Kconfig 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/sound/soc/s3c24xx/Kconfig 2009-05-18 19:08:35.000000000 +0200
@@ -42,10 +42,20 @@
tristate "SoC I2S Audio support for Jive"
depends on SND_S3C24XX_SOC && MACH_JIVE
select SND_SOC_WM8750
+ select SND_SOC_WM8750_SPI
select SND_S3C2412_SOC_I2S
help
Sat Y if you want to add support for SoC audio on the Jive.
+config SND_S3C24XX_SOC_NEO1973_GTA02_WM8753
+ tristate "SoC I2S Audio support for Openmoko Freerunner - WM8753"
+ depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA02
+ select SND_S3C24XX_SOC_I2S
+ select SND_SOC_WM8753
+ help
+ Say Y if you want to add support for SoC audio on Openmoko Freerunner
+ with the WM8753 codec
+
config SND_S3C24XX_SOC_SMDK2443_WM9710
tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
depends on SND_S3C24XX_SOC && MACH_SMDK2443
Index: linux-2.6.30-rc6/sound/soc/s3c24xx/Makefile
===================================================================
--- linux-2.6.30-rc6.orig/sound/soc/s3c24xx/Makefile 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/sound/soc/s3c24xx/Makefile 2009-05-18 19:08:35.000000000 +0200
@@ -19,9 +19,11 @@
snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
+snd-soc-neo1973-gta02-wm8753-objs := gta02_wm8753.o
obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
+obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o
Index: linux-2.6.30-rc6/sound/soc/s3c24xx/s3c24xx-i2s.c
===================================================================
--- linux-2.6.30-rc6.orig/sound/soc/s3c24xx/s3c24xx-i2s.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/sound/soc/s3c24xx/s3c24xx-i2s.c 2009-05-18 19:08:35.000000000 +0200
@@ -284,11 +284,14 @@
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- if (!s3c24xx_snd_is_clkmaster()) {
- ret = s3c24xx_snd_lrsync();
- if (ret)
- goto exit_err;
- }
+ if (!s3c24xx_snd_is_clkmaster())
+ /* we ignore the return code, if it sync'd then fine,
+ * if it didn't sync, which happens after resume the
+ * first time when there was a live stream at suspend,
+ * just let it timeout, the stream picks up OK after
+ * that and LRCK is evidently working again.
+ */
+ s3c24xx_snd_lrsync();
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
s3c24xx_snd_rxctrl(1);
@@ -308,7 +311,6 @@
break;
}
-exit_err:
return ret;
}
Index: linux-2.6.30-rc6/sound/soc/s3c24xx/s3c24xx-pcm.c
===================================================================
--- linux-2.6.30-rc6.orig/sound/soc/s3c24xx/s3c24xx-pcm.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/sound/soc/s3c24xx/s3c24xx-pcm.c 2009-05-18 19:08:35.000000000 +0200
@@ -75,11 +75,18 @@
{
struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
dma_addr_t pos = prtd->dma_pos;
+ unsigned int limit;
int ret;
pr_debug("Entered %s\n", __func__);
- while (prtd->dma_loaded < prtd->dma_limit) {
+ if (s3c_dma_has_circular()) {
+ limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
+ } else
+ limit = prtd->dma_limit;
+
+
+ while (prtd->dma_loaded < limit) {
unsigned long len = prtd->dma_period;
pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
@@ -123,7 +130,7 @@
snd_pcm_period_elapsed(substream);
spin_lock(&prtd->lock);
- if (prtd->state & ST_RUNNING) {
+ if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
prtd->dma_loaded--;
s3c24xx_pcm_enqueue(substream);
}
@@ -164,6 +171,11 @@
printk(KERN_ERR "failed to get dma channel\n");
return ret;
}
+
+ /* use the circular buffering if we have it available. */
+ if (s3c_dma_has_circular())
+ s3c2410_dma_setflags(prtd->params->channel,
+ S3C2410_DMAF_CIRCULAR);
}
s3c2410_dma_set_buffdone_fn(prtd->params->channel,
@@ -218,24 +230,17 @@
* sync to pclk, half-word transfers to the IIS-FIFO. */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
s3c2410_dma_devconfig(prtd->params->channel,
- S3C2410_DMASRC_MEM, S3C2410_DISRCC_INC |
- S3C2410_DISRCC_APB, prtd->params->dma_addr);
-
- s3c2410_dma_config(prtd->params->channel,
- prtd->params->dma_size,
- S3C2410_DCON_SYNC_PCLK |
- S3C2410_DCON_HANDSHAKE);
+ S3C2410_DMASRC_MEM,
+ prtd->params->dma_addr);
} else {
- s3c2410_dma_config(prtd->params->channel,
- prtd->params->dma_size,
- S3C2410_DCON_HANDSHAKE |
- S3C2410_DCON_SYNC_PCLK);
-
s3c2410_dma_devconfig(prtd->params->channel,
- S3C2410_DMASRC_HW, 0x3,
- prtd->params->dma_addr);
+ S3C2410_DMASRC_HW,
+ prtd->params->dma_addr);
}
+ s3c2410_dma_config(prtd->params->channel,
+ prtd->params->dma_size);
+
/* flush the DMA channel */
s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
prtd->dma_loaded = 0;

View File

@@ -0,0 +1,230 @@
Index: linux-2.6.30-rc6/drivers/usb/gadget/s3c2410_udc.c
===================================================================
--- linux-2.6.30-rc6.orig/drivers/usb/gadget/s3c2410_udc.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/usb/gadget/s3c2410_udc.c 2009-05-18 19:08:35.000000000 +0200
@@ -74,6 +74,7 @@
static u64 rsrc_start;
static u64 rsrc_len;
static struct dentry *s3c2410_udc_debugfs_root;
+static struct timer_list vbus_poll_timer;
static inline u32 udc_read(u32 reg)
{
@@ -134,6 +135,8 @@
return 0;
}
#endif
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
{
u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg;
@@ -197,6 +200,7 @@
.release = single_release,
.owner = THIS_MODULE,
};
+#endif
/* io macros */
@@ -843,6 +847,7 @@
u32 ep_csr1;
u32 idx;
+handle_ep_again:
if (likely (!list_empty(&ep->queue)))
req = list_entry(ep->queue.next,
struct s3c2410_request, queue);
@@ -882,6 +887,8 @@
if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
s3c2410_udc_read_fifo(ep,req);
+ if (s3c2410_udc_fifo_count_out())
+ goto handle_ep_again;
}
}
}
@@ -1520,6 +1527,20 @@
return IRQ_HANDLED;
}
+static void s3c2410_udc_vbus_poll(unsigned long _data)
+{
+ struct s3c2410_udc *data = (struct s3c2410_udc *)_data;
+ int v;
+
+ dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+ if (udc_info && udc_info->get_vbus_status) {
+ v = udc_info->get_vbus_status();
+ if ((v > -1) && (v != data->vbus))
+ s3c2410_udc_vbus_session(&data->gadget, v);
+ mod_timer(&vbus_poll_timer, jiffies + msecs_to_jiffies(900));
+ }
+}
+
static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
{
dprintk(DEBUG_NORMAL, "%s()\n", __func__);
@@ -1677,6 +1698,11 @@
goto register_error;
}
+ if (udc_info && udc_info->get_vbus_status && !udc_info->vbus_pin) {
+ mod_timer(&vbus_poll_timer, jiffies + msecs_to_jiffies(50));
+ return 0; /* just return, vbus change will enable udc */
+ }
+
/* Enable udc */
s3c2410_udc_enable(udc);
@@ -1707,6 +1733,7 @@
if (driver->disconnect)
driver->disconnect(&udc->gadget);
+ driver->unbind(&udc->gadget);
device_del(&udc->gadget.dev);
udc->driver = NULL;
@@ -1893,10 +1920,16 @@
}
dev_dbg(dev, "got irq %i\n", irq);
+ } else if (udc_info && udc_info->get_vbus_status) {
+ udc->vbus = 0;
+ init_timer(&vbus_poll_timer);
+ vbus_poll_timer.function = s3c2410_udc_vbus_poll;
+ vbus_poll_timer.data = (unsigned long) udc;
} else {
udc->vbus = 1;
}
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
if (s3c2410_udc_debugfs_root) {
udc->regs_info = debugfs_create_file("registers", S_IRUGO,
s3c2410_udc_debugfs_root,
@@ -1904,6 +1937,7 @@
if (!udc->regs_info)
dev_warn(dev, "debugfs file creation failed\n");
}
+#endif
dev_dbg(dev, "probe ok\n");
@@ -1939,6 +1973,8 @@
if (udc_info && udc_info->vbus_pin > 0) {
irq = gpio_to_irq(udc_info->vbus_pin);
free_irq(irq, udc);
+ } else if (udc_info && udc_info->get_vbus_status) {
+ del_timer_sync(&vbus_poll_timer);
}
free_irq(IRQ_USBD, udc);
@@ -2013,12 +2049,14 @@
dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
if (IS_ERR(s3c2410_udc_debugfs_root)) {
printk(KERN_ERR "%s: debugfs dir creation failed %ld\n",
gadget_name, PTR_ERR(s3c2410_udc_debugfs_root));
s3c2410_udc_debugfs_root = NULL;
}
+#endif
retval = platform_driver_register(&udc_driver_2410);
if (retval)
Index: linux-2.6.30-rc6/drivers/usb/host/ohci-s3c2410.c
===================================================================
--- linux-2.6.30-rc6.orig/drivers/usb/host/ohci-s3c2410.c 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/drivers/usb/host/ohci-s3c2410.c 2009-05-18 19:08:35.000000000 +0200
@@ -21,6 +21,8 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <mach/regs-gpio.h>
#include <plat/usb-control.h>
#define valid_port(idx) ((idx) == 1 || (idx) == 2)
@@ -306,6 +308,42 @@
local_irq_restore(flags);
}
+/* switching of USB pads */
+static ssize_t show_usb_mode(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ if (__raw_readl(S3C24XX_MISCCR) & S3C2410_MISCCR_USBHOST)
+ return sprintf(buf, "host\n");
+
+ return sprintf(buf, "device\n");
+}
+
+static ssize_t set_usb_mode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (!strncmp(buf, "host", 4)) {
+ printk(KERN_WARNING "s3c2410: changing usb to host\n");
+ s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST,
+ S3C2410_MISCCR_USBHOST);
+ /* FIXME:
+ * - call machine-specific disable-pullup function i
+ * - enable +Vbus (if hardware supports it)
+ */
+ s3c2410_gpio_setpin(S3C2410_GPB9, 0);
+ } else if (!strncmp(buf, "device", 6)) {
+ printk(KERN_WARNING "s3c2410: changing usb to device\n");
+ s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, 0);
+ s3c2410_gpio_setpin(S3C2410_GPB9, 1);
+ } else {
+ printk(KERN_WARNING "s3c2410: unknown mode\n");
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(usb_mode, S_IRUGO | S_IWUSR, show_usb_mode, set_usb_mode);
+
/* may be called without controller electrically present */
/* may be called with controller, bus, and devices active */
@@ -486,15 +524,23 @@
return 0;
}
+static int ohci_hcd_s3c2410_drv_resume(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+ ohci_finish_controller_resume(hcd);
+ return 0;
+}
+
static struct platform_driver ohci_hcd_s3c2410_driver = {
.probe = ohci_hcd_s3c2410_drv_probe,
.remove = ohci_hcd_s3c2410_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
/*.suspend = ohci_hcd_s3c2410_drv_suspend, */
- /*.resume = ohci_hcd_s3c2410_drv_resume, */
+ .resume = ohci_hcd_s3c2410_drv_resume,
.driver = {
.owner = THIS_MODULE,
- .name = "s3c2410-ohci",
+ .name = "s3c-ohci",
},
};
Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/include/plat/udc.h
===================================================================
--- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/include/plat/udc.h 2009-05-16 06:12:57.000000000 +0200
+++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/include/plat/udc.h 2009-05-18 19:08:35.000000000 +0200
@@ -27,6 +27,7 @@
struct s3c2410_udc_mach_info {
void (*udc_command)(enum s3c2410_udc_cmd_e);
void (*vbus_draw)(unsigned int ma);
+ int (*get_vbus_status)(void);
unsigned int vbus_pin;
unsigned char vbus_pin_inverted;
};