bump to 2.6.30-rc6
SVN-Revision: 15918
This commit is contained in:
2265
target/linux/s3c24xx/patches-2.6.30/001-merge-openmoko.patch
Normal file
2265
target/linux/s3c24xx/patches-2.6.30/001-merge-openmoko.patch
Normal file
File diff suppressed because it is too large
Load Diff
1318
target/linux/s3c24xx/patches-2.6.30/010-s3c-dma.patch
Normal file
1318
target/linux/s3c24xx/patches-2.6.30/010-s3c-dma.patch
Normal file
File diff suppressed because it is too large
Load Diff
812
target/linux/s3c24xx/patches-2.6.30/011-s3c-pwm.patch
Normal file
812
target/linux/s3c24xx/patches-2.6.30/011-s3c-pwm.patch
Normal 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);
|
||||
488
target/linux/s3c24xx/patches-2.6.30/012-s3c-usb.patch
Normal file
488
target/linux/s3c24xx/patches-2.6.30/012-s3c-usb.patch
Normal 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[] = {
|
||||
294
target/linux/s3c24xx/patches-2.6.30/013-fiq_c_handler.patch
Normal file
294
target/linux/s3c24xx/patches-2.6.30/013-fiq_c_handler.patch
Normal 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" (®s->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(®s, 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(®s);
|
||||
+}
|
||||
+/* -------- 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;
|
||||
}
|
||||
|
||||
50
target/linux/s3c24xx/patches-2.6.30/014-neo1973_mach.patch
Normal file
50
target/linux/s3c24xx/patches-2.6.30/014-neo1973_mach.patch
Normal 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
|
||||
+
|
||||
91
target/linux/s3c24xx/patches-2.6.30/015-mach-gta02.patch
Normal file
91
target/linux/s3c24xx/patches-2.6.30/015-mach-gta02.patch
Normal 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 */
|
||||
@@ -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
|
||||
32
target/linux/s3c24xx/patches-2.6.30/051-gta02kbd.patch
Normal file
32
target/linux/s3c24xx/patches-2.6.30/051-gta02kbd.patch
Normal 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
|
||||
@@ -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
|
||||
37
target/linux/s3c24xx/patches-2.6.30/053-glamo.patch
Normal file
37
target/linux/s3c24xx/patches-2.6.30/053-glamo.patch
Normal 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 */
|
||||
35
target/linux/s3c24xx/patches-2.6.30/054-bq27000.patch
Normal file
35
target/linux/s3c24xx/patches-2.6.30/054-bq27000.patch
Normal 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
|
||||
37
target/linux/s3c24xx/patches-2.6.30/055-gta02-leds.patch
Normal file
37
target/linux/s3c24xx/patches-2.6.30/055-gta02-leds.patch
Normal 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
|
||||
30
target/linux/s3c24xx/patches-2.6.30/055-jbt6k74.patch
Normal file
30
target/linux/s3c24xx/patches-2.6.30/055-jbt6k74.patch
Normal 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
|
||||
|
||||
375
target/linux/s3c24xx/patches-2.6.30/056-pcf50633.patch
Normal file
375
target/linux/s3c24xx/patches-2.6.30/056-pcf50633.patch
Normal 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
|
||||
29
target/linux/s3c24xx/patches-2.6.30/057-lis302dl.patch
Normal file
29
target/linux/s3c24xx/patches-2.6.30/057-lis302dl.patch
Normal 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
|
||||
@@ -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
|
||||
25
target/linux/s3c24xx/patches-2.6.30/068-ar6000.patch
Normal file
25
target/linux/s3c24xx/patches-2.6.30/068-ar6000.patch
Normal 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/
|
||||
485
target/linux/s3c24xx/patches-2.6.30/070-s3c24xx-time.patch
Normal file
485
target/linux/s3c24xx/patches-2.6.30/070-s3c24xx-time.patch
Normal 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
|
||||
+};
|
||||
47
target/linux/s3c24xx/patches-2.6.30/080-nr-tty-devices.patch
Normal file
47
target/linux/s3c24xx/patches-2.6.30/080-nr-tty-devices.patch
Normal 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
|
||||
150
target/linux/s3c24xx/patches-2.6.30/090-sound.patch
Normal file
150
target/linux/s3c24xx/patches-2.6.30/090-sound.patch
Normal 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;
|
||||
230
target/linux/s3c24xx/patches-2.6.30/100-udc-poll-vbus.patch
Normal file
230
target/linux/s3c24xx/patches-2.6.30/100-udc-poll-vbus.patch
Normal 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;
|
||||
};
|
||||
Reference in New Issue
Block a user