From 8ca48d1b67041a96ff65edd5c2e4ed79609aa271 Mon Sep 17 00:00:00 2001 From: blogic Date: Mon, 26 Sep 2011 09:35:02 +0000 Subject: [PATCH] [lantiq] * rebase 3.0 patches * fold some fixes into existing patches git-svn-id: svn://svn.openwrt.org/openwrt/trunk@28308 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../lantiq/patches-3.0/020-xway-fix-mtd.patch | 4 +- .../linux/lantiq/patches-3.0/030-lmo-queue.patch | 6 +- .../lantiq/patches-3.0/110-falcon_board.patch | 132 ++- .../linux/lantiq/patches-3.0/120-falcon-i2c.patch | 898 +++++++++++---------- .../lantiq/patches-3.0/130-falcon-spi-flash.patch | 4 +- .../lantiq/patches-3.0/150-falcon-easy98020.patch | 4 +- .../lantiq/patches-3.0/160-falcon-95C3AM1.patch | 6 +- .../patches-3.0/170-falcon-dm9000-polling.patch | 16 +- .../lantiq/patches-3.0/180-falcon-linux3.0.patch | 32 +- .../patches-3.0/190-falcon-fix_include.patch | 7 +- .../lantiq/patches-3.0/200-netif_receive_skb.patch | 2 +- .../lantiq/patches-3.0/210-mtd_uimage_split.patch | 8 +- .../lantiq/patches-3.0/230-cmdline_hack.patch | 2 +- .../lantiq/patches-3.0/240-udp_redirect.patch | 14 +- target/linux/lantiq/patches-3.0/250-mt-vpe.patch | 4 +- .../lantiq/patches-3.0/260-ar9-cache-split.patch | 6 +- target/linux/lantiq/patches-3.0/410-spi2.patch | 4 +- target/linux/lantiq/patches-3.0/420-spi3.patch | 2 +- target/linux/lantiq/patches-3.0/440-dwc_otg.patch | 6 +- .../lantiq/patches-3.0/450-mach-arv45xx.patch | 6 +- .../lantiq/patches-3.0/460-mach-dgn3500.patch | 6 +- .../lantiq/patches-3.0/470-mach-gigasx76x.patch | 6 +- .../lantiq/patches-3.0/480-mach-easy98020.patch | 27 + .../lantiq/patches-3.0/510-register_madwifi.patch | 4 +- .../lantiq/patches-3.0/520-register_buttons.patch | 4 +- .../lantiq/patches-3.0/530-register_tapi.patch | 6 +- .../lantiq/patches-3.0/550-register_ebu.patch | 2 +- .../lantiq/patches-3.0/998-easy98000-asc1.patch | 59 ++ 28 files changed, 729 insertions(+), 548 deletions(-) create mode 100644 target/linux/lantiq/patches-3.0/480-mach-easy98020.patch create mode 100644 target/linux/lantiq/patches-3.0/998-easy98000-asc1.patch diff --git a/target/linux/lantiq/patches-3.0/020-xway-fix-mtd.patch b/target/linux/lantiq/patches-3.0/020-xway-fix-mtd.patch index 051ba86cf4..d74fcb69d5 100644 --- a/target/linux/lantiq/patches-3.0/020-xway-fix-mtd.patch +++ b/target/linux/lantiq/patches-3.0/020-xway-fix-mtd.patch @@ -1,6 +1,6 @@ --- a/arch/mips/lantiq/xway/mach-easy50601.c +++ b/arch/mips/lantiq/xway/mach-easy50601.c -@@ -32,12 +32,7 @@ +@@ -32,12 +32,7 @@ static struct mtd_partition easy50601_pa { .name = "linux", .offset = 0x20000, @@ -16,7 +16,7 @@ --- a/arch/mips/lantiq/xway/mach-easy50712.c +++ b/arch/mips/lantiq/xway/mach-easy50712.c -@@ -34,12 +34,7 @@ +@@ -34,12 +34,7 @@ static struct mtd_partition easy50712_pa { .name = "linux", .offset = 0x20000, diff --git a/target/linux/lantiq/patches-3.0/030-lmo-queue.patch b/target/linux/lantiq/patches-3.0/030-lmo-queue.patch index feaa237774..2cb1d08231 100644 --- a/target/linux/lantiq/patches-3.0/030-lmo-queue.patch +++ b/target/linux/lantiq/patches-3.0/030-lmo-queue.patch @@ -11,7 +11,7 @@ --- a/arch/mips/lantiq/clk.c +++ b/arch/mips/lantiq/clk.c -@@ -100,6 +100,17 @@ +@@ -100,6 +100,17 @@ void clk_put(struct clk *clk) } EXPORT_SYMBOL(clk_put); @@ -39,7 +39,7 @@ #include #include -@@ -105,6 +106,7 @@ +@@ -99,6 +100,7 @@ void ltq_mask_and_ack_irq(struct irq_dat ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier); ltq_icu_w32((1 << irq_nr), isr); } @@ -58,7 +58,7 @@ void __init plat_mem_setup(void) { /* assume 16M as default incase uboot fails to pass proper ramsize */ -@@ -40,8 +42,8 @@ +@@ -40,8 +42,8 @@ void __init plat_mem_setup(void) } envp++; } diff --git a/target/linux/lantiq/patches-3.0/110-falcon_board.patch b/target/linux/lantiq/patches-3.0/110-falcon_board.patch index aa38f87890..ec52d42d41 100644 --- a/target/linux/lantiq/patches-3.0/110-falcon_board.patch +++ b/target/linux/lantiq/patches-3.0/110-falcon_board.patch @@ -72,7 +72,7 @@ +EXPORT_SYMBOL(ltq_get_fpi_hz); --- /dev/null +++ b/arch/mips/lantiq/falcon/devices.c -@@ -0,0 +1,254 @@ +@@ -0,0 +1,258 @@ +#include +#include +#include @@ -109,6 +109,10 @@ +unsigned char ltq_ethaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +EXPORT_SYMBOL(ltq_ethaddr); + ++/* create dummy ebu spinlock for drivers shared with XWAY targets */ ++DEFINE_SPINLOCK(ebu_lock); ++EXPORT_SYMBOL_GPL(ebu_lock); ++ +static int __init +falcon_set_ethaddr(char *str) +{ @@ -793,7 +797,7 @@ +EXPORT_SYMBOL(sys_gpe_hw_is_activated); --- /dev/null +++ b/arch/mips/lantiq/falcon/gpio.c -@@ -0,0 +1,463 @@ +@@ -0,0 +1,505 @@ +/* + * 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 @@ -842,6 +846,8 @@ +#define gpio_w32(val, reg) __raw_writel(val, reg) +#define gpio_w32_mask(clear, set, reg) gpio_w32((gpio_r32(reg) & ~(clear)) | (set), reg) + ++#define MAX_PORTS 5 ++#define PINS_PER_PORT 32 + +/** register structure for padctrl + (mainly needed for mux control) */ @@ -926,6 +932,8 @@ + unsigned int chained_irq; +}; + ++static struct falcon_gpio_port ltq_gpio_port[MAX_PORTS]; ++ +static int gpio_exported = 0; +static int __init gpio_export_setup(char *str) +{ @@ -946,13 +954,6 @@ + return 0; +} + -+static int falcon_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value) -+{ -+ struct falcon_gpio_port *gpio_port = to_falcon_gpio_port(chip); -+ gpio_w32(1<port->dirset); -+ return 0; -+} -+ +static void falcon_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) +{ + struct falcon_gpio_port *gpio_port = to_falcon_gpio_port(chip); @@ -962,6 +963,14 @@ + gpio_w32(1<port->outclr); +} + ++static int falcon_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value) ++{ ++ struct falcon_gpio_port *gpio_port = to_falcon_gpio_port(chip); ++ falcon_gpio_set(chip, offset, value); ++ gpio_w32(1<port->dirset); ++ return 0; ++} ++ +static int falcon_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct falcon_gpio_port *gpio_port = to_falcon_gpio_port(chip); @@ -1038,6 +1047,46 @@ + gpio_w32(1<port->irncr); +} + ++int ltq_gpio_mux_set(unsigned int pin, unsigned int mux) ++{ ++ int port = pin / 100; ++ int offset = pin % 100; ++ struct falcon_gpio_port *gpio_port; ++ ++ if (offset >= PINS_PER_PORT || port >= MAX_PORTS) ++ return -EINVAL; ++ ++ gpio_port = <q_gpio_port[port]; ++ gpio_w32(mux, &gpio_port->pad->muxc[offset]); ++ ++ return 0; ++} ++EXPORT_SYMBOL(ltq_gpio_mux_set); ++ ++int ltq_gpio_request(unsigned int pin, unsigned int alt0, ++ unsigned int alt1, unsigned int dir, const char *name) ++{ ++ int port = pin / 100; ++ int offset = pin % 100; ++ unsigned int mux = (alt0 & 1) + (alt1 & 1) * 2; ++ ++ if (offset >= PINS_PER_PORT || port >= MAX_PORTS) ++ return -EINVAL; ++ ++ if (gpio_request(pin, name)) { ++ pr_err("failed to setup lantiq gpio: %s\n", name); ++ return -EBUSY; ++ } ++ ++ if (dir) ++ gpio_direction_output(pin, 1); ++ else ++ gpio_direction_input(pin); ++ ++ return ltq_gpio_mux_set(pin, mux); ++} ++EXPORT_SYMBOL(ltq_gpio_request); ++ +static struct irq_chip falcon_gpio_irq_chip; +static int falcon_gpio_irq_type(struct irq_data *d, unsigned int type) +{ @@ -1115,16 +1164,16 @@ + struct resource *gpiores, *padres; + int irq; + ++ if (pdev->id >= MAX_PORTS) ++ return -ENODEV; ++ + gpiores = platform_get_resource(pdev, IORESOURCE_MEM, 0); + padres = platform_get_resource(pdev, IORESOURCE_MEM, 1); + irq = platform_get_irq(pdev, 0); + if (!gpiores || !padres) + return -ENODEV; + -+ gpio_port = kzalloc(sizeof(*gpio_port), GFP_KERNEL); -+ if (gpio_port == NULL) -+ return -ENOMEM; -+ ++ gpio_port = <q_gpio_port[pdev->id]; + gpio_port->gpio_chip.label = "falcon-gpio"; + gpio_port->gpio_chip.direction_input = falcon_gpio_direction_input; + gpio_port->gpio_chip.direction_output = falcon_gpio_direction_output; @@ -1200,7 +1249,6 @@ + iounmap(gpio_port->port); + if (gpio_port->pad) + iounmap(gpio_port->pad); -+ kfree(gpio_port); + return ret; +} + @@ -1218,8 +1266,6 @@ + iounmap(gpio_port->port); + if (gpio_port->pad) + iounmap(gpio_port->pad); -+ if (ret == 0) -+ kfree(gpio_port); + + return ret; +} @@ -1278,7 +1324,7 @@ +#endif --- /dev/null +++ b/arch/mips/lantiq/falcon/reset.c -@@ -0,0 +1,80 @@ +@@ -0,0 +1,95 @@ +/* + * 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 @@ -1305,6 +1351,22 @@ +#define WDT_PW2 0x00DC0000 +#define WDT_REG_BASE (KSEG1 | 0x1F8803F0) + ++struct gpon_reg_boot { ++ /* bootrom related virtual registers */ ++ unsigned int rvec; ++ unsigned int nvec; ++ unsigned int evec; ++ unsigned int cp0_status; ++ unsigned int cp0_epc; ++ unsigned int cp0_eepc; ++ unsigned int size; ++ unsigned int cfg_stat; ++ /* additional virtual registers */ ++ unsigned int magic0; /* magic for valid reboot */ ++ unsigned int magic1; /* -"- */ ++ unsigned int bcount; /* reboot counter, used by u-boot */ ++} * const pBOOT = (struct gpon_reg_boot *)GPON_SBS0RAM_BASE; ++ +/* This function is used by the watchdog driver */ +int ltq_reset_cause(void) +{ @@ -1317,11 +1379,11 @@ +{ + printk(KERN_NOTICE "System restart\n"); + local_irq_disable(); -+ ltq_w32(0, (void*)0xBF200000); /* reset Bootreg RVEC */ -+#if 0 -+ ltq_w32(RBT_CPU_TRIG, &pSYS1->rbt); -+#else -+ /* use workaround via watchdog timer */ ++ /* write magic to signal a valid restart */ ++ ltq_w32(0x4C545100, &pBOOT->magic0); /* 'LTQ\0' */ ++ ltq_w32(0x0051544C, &pBOOT->magic1); /* '\0QTL' */ ++ ltq_w32(0, &pBOOT->rvec); /* reset Bootreg RVEC */ ++ /* reset via watchdog timer, to ensure reset of all hardware components */ + ltq_w32(WDT_PW1, (void*)WDT_REG_BASE); + ltq_w32(WDT_PW2 | + (0x3 << 26) | /* PWL */ @@ -1329,7 +1391,6 @@ + (0x1 << 31) | /* enable */ + (1), /* reload */ + (void*)WDT_REG_BASE); -+#endif + for(;;); +} + @@ -1778,7 +1839,7 @@ +#endif --- a/arch/mips/lantiq/Kconfig +++ b/arch/mips/lantiq/Kconfig -@@ -16,8 +16,12 @@ +@@ -16,8 +16,12 @@ config SOC_XWAY bool "XWAY" select SOC_TYPE_XWAY select HW_HAS_PCI @@ -1793,21 +1854,21 @@ endif --- a/arch/mips/lantiq/Makefile +++ b/arch/mips/lantiq/Makefile -@@ -9,3 +9,4 @@ +@@ -9,3 +9,4 @@ obj-y := irq.o setup.o clk.o prom.o devi obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_SOC_TYPE_XWAY) += xway/ +obj-$(CONFIG_SOC_FALCON) += falcon/ --- a/arch/mips/lantiq/Platform +++ b/arch/mips/lantiq/Platform -@@ -6,3 +6,4 @@ +@@ -6,3 +6,4 @@ platform-$(CONFIG_LANTIQ) += lantiq/ cflags-$(CONFIG_LANTIQ) += -I$(srctree)/arch/mips/include/asm/mach-lantiq load-$(CONFIG_LANTIQ) = 0xffffffff80002000 cflags-$(CONFIG_SOC_TYPE_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway +cflags-$(CONFIG_SOC_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon --- a/arch/mips/lantiq/machtypes.h +++ b/arch/mips/lantiq/machtypes.h -@@ -15,6 +15,12 @@ +@@ -15,6 +15,12 @@ enum lantiq_mach_type { LTQ_MACH_GENERIC = 0, LTQ_MACH_EASY50712, /* Danube evaluation board */ LTQ_MACH_EASY50601, /* Amazon SE evaluation board */ @@ -2035,3 +2096,20 @@ + +module_init(easy98000_addon_init); +module_exit(easy98000_addon_exit); +--- a/arch/mips/lantiq/prom.c ++++ b/arch/mips/lantiq/prom.c +@@ -45,10 +45,12 @@ static void __init prom_init_cmdline(voi + char **argv = (char **) KSEG1ADDR(fw_arg1); + int i; + ++ arcs_cmdline[0] = '\0'; ++ + for (i = 0; i < argc; i++) { +- char *p = (char *) KSEG1ADDR(argv[i]); ++ char *p = (char *) KSEG1ADDR(argv[i]); + +- if (p && *p) { ++ if (CPHYSADDR(p) && *p) { + strlcat(arcs_cmdline, p, sizeof(arcs_cmdline)); + strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); + } diff --git a/target/linux/lantiq/patches-3.0/120-falcon-i2c.patch b/target/linux/lantiq/patches-3.0/120-falcon-i2c.patch index c5d39c8c21..2def0a802a 100644 --- a/target/linux/lantiq/patches-3.0/120-falcon-i2c.patch +++ b/target/linux/lantiq/patches-3.0/120-falcon-i2c.patch @@ -9,7 +9,7 @@ ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig -@@ -282,6 +282,10 @@ config I2C_POWERMAC +@@ -284,6 +284,10 @@ config I2C_POWERMAC comment "I2C system bus drivers (mostly embedded / system-on-chip)" @@ -22,41 +22,49 @@ depends on ARCH_AT91 && EXPERIMENTAL && BROKEN --- /dev/null +++ b/drivers/i2c/busses/i2c-falcon.c -@@ -0,0 +1,803 @@ +@@ -0,0 +1,815 @@ +/* -+ * 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. ++ * Lantiq FALC(tm) ON - I2C bus adapter + * -+ * 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. ++ * Parts based on i2c-designware.c and other i2c drivers from Linux 2.6.33 + * -+ * 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. ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* #define DEBUG */ + ++#include +#include -+#include -+#include -+#include ++#include ++#include /* for kzalloc, kfree */ +#include -+#include -+#include -+#include +#include ++#include ++#include +#include -+#include ++#include ++#include ++#include ++#include ++ ++#include + +/* CURRENT ISSUES: + * - no high speed support -+ * - rx issue with "address mode" & "tx end" interrupts -+ * - ten bit mode is not tested ++ * - supports only master mode ++ * - ten bit mode is not tested (no slave devices) + */ + +/* mapping for access macros */ @@ -69,32 +77,34 @@ +#define i2c (priv->membase) +#include + -+/* enable hacks to overcome current issue */ -+#define FALCON_FIX_ME -+ -+#define FALCON_I2C_ADDR 0x00 -+#define FALCON_I2C_READY_TIMEOUT 1000 -+#define FALCON_I2C_WAIT_TIMEOUT 10 -+ +#define DRV_NAME "i2c-falcon" ++#define DRV_VERSION "1.01" + -+#if defined(DEBUG) -+#define static /* no static functions for better debugging */ ++#define FALCON_I2C_BUSY_TIMEOUT 20 /* ms */ ++ ++#ifdef DEBUG ++#define FALCON_I2C_XFER_TIMEOUT 25*HZ ++#else ++#define FALCON_I2C_XFER_TIMEOUT HZ ++#endif ++#if defined(DEBUG) && 0 ++#define PRINTK(arg...) printk(arg) ++#else ++#define PRINTK(arg...) do {} while (0) +#endif + ++#define FALCON_I2C_IMSC_DEFAULT_MASK (I2C_IMSC_I2C_P_INT_EN | \ ++ I2C_IMSC_I2C_ERR_INT_EN) ++ +#define FALCON_I2C_ARB_LOST (1 << 0) +#define FALCON_I2C_NACK (1 << 1) +#define FALCON_I2C_RX_UFL (1 << 2) +#define FALCON_I2C_RX_OFL (1 << 3) +#define FALCON_I2C_TX_UFL (1 << 4) +#define FALCON_I2C_TX_OFL (1 << 5) -+#define FALCON_I2C_BURST_REQ (1 << 6) -+#define FALCON_I2C_RX (1 << 7) -+#define FALCON_I2C_TX_END (1 << 8) -+#define FALCON_I2C_ADDR_MATCH (1 << 9) /* doesn't trigger */ + +struct falcon_i2c { -+ spinlock_t lock; ++ struct mutex mutex; + + enum { + FALCON_I2C_MODE_100 = 1, @@ -102,504 +112,482 @@ + FALCON_I2C_MODE_3400 = 3 + } mode; /* current speed mode */ + -+ int ten_bit; /* current address mode */ -+ unsigned long status; /* bus events holder */ + struct clk *clk; /* clock input for i2c hardware block */ + struct gpon_reg_i2c __iomem *membase; /* base of mapped registers */ + int irq_lb, irq_b, irq_err, irq_p; /* last burst, burst, error, + protocol IRQs */ -+ struct completion done; ++ + struct i2c_adapter adap; + struct device *dev; -+}; + -+#define FALCON_I2C_ERROR_MASK (FALCON_I2C_NACK \ -+ | FALCON_I2C_ARB_LOST \ -+ | FALCON_I2C_RX_OFL \ -+ | FALCON_I2C_RX_UFL \ -+ | FALCON_I2C_TX_OFL \ -+ | FALCON_I2C_TX_UFL) ++ struct completion cmd_complete; ++ ++ /* message transfer data */ ++ /* current message */ ++ struct i2c_msg *current_msg; ++ /* number of messages to handle */ ++ int msgs_num; ++ /* current buffer */ ++ u8 *msg_buf; ++ /* remaining length of current buffer */ ++ u32 msg_buf_len; ++ /* error status of the current transfer */ ++ int msg_err; ++ ++ /* master status codes */ ++ enum { ++ STATUS_IDLE, ++ STATUS_ADDR, /* address phase */ ++ STATUS_WRITE, ++ STATUS_READ, ++ STATUS_READ_END, ++ STATUS_STOP ++ } status; ++}; + -+#define FALCON_I2C_ERROR(priv) (priv->status & FALCON_I2C_ERROR_MASK) -+#define FALCON_I2C_ERROR_CLEAR(priv) do { \ -+ priv->status &= \ -+ ~FALCON_I2C_ERROR_MASK; \ -+ } while (0) ++static irqreturn_t falcon_i2c_isr(int irq, void *dev_id); + -+static void falcon_addr_configure(struct falcon_i2c *priv, int ten_bit) ++static inline void enable_burst_irq(struct falcon_i2c *priv) +{ -+ u32 ten_bit_mask = ten_bit ? I2C_ADDR_CFG_TBAM_10bit : 0; -+ -+ /* configure address */ -+ i2c_w32(I2C_ADDR_CFG_SOPE_EN /* generate stop when no more data in the -+ fifo */ -+ | I2C_ADDR_CFG_SONA_EN /* generate stop when NA received */ -+ | I2C_ADDR_CFG_MnS_EN /* we are master device */ -+ | ten_bit_mask -+ | FALCON_I2C_ADDR, /* our address */ -+ addr_cfg); ++ i2c_w32_mask(0, I2C_IMSC_LBREQ_INT_EN | I2C_IMSC_BREQ_INT_EN, imsc); +} -+ -+static irqreturn_t falcon_i2c_isr(int irq, void *dev_id) ++static inline void disable_burst_irq(struct falcon_i2c *priv) +{ -+ u32 i_raw, i_pro, i_err; -+ struct falcon_i2c *priv = dev_id; -+ unsigned long flags; -+ unsigned int old_status; -+ -+ spin_lock_irqsave(&priv->lock, flags); -+ -+ old_status = (unsigned int)priv->status; -+ -+ i_raw = i2c_r32(mis); -+ -+ /* protocol interrupt */ -+ if (i_raw & I2C_RIS_I2C_P_INT_INTOCC) { -+ i_pro = i2c_r32(p_irqss); ++ i2c_w32_mask(I2C_IMSC_LBREQ_INT_EN | I2C_IMSC_BREQ_INT_EN, 0, imsc); ++} + -+ /* tx -> rx switch */ -+ if (i_pro & I2C_P_IRQSS_RX) -+ priv->status |= FALCON_I2C_RX; ++static void prepare_msg_send_addr(struct falcon_i2c *priv) ++{ ++ struct i2c_msg *msg = priv->current_msg; ++ int rd = !!(msg->flags & I2C_M_RD); /* extends to 0 or 1 */ ++ u16 addr = msg->addr; ++ ++ /* new i2c_msg */ ++ priv->msg_buf = msg->buf; ++ priv->msg_buf_len = msg->len; ++ if (rd) ++ priv->status = STATUS_READ; ++ else ++ priv->status = STATUS_WRITE; + -+ /* tx end */ -+ if (i_pro & I2C_P_IRQSS_TX_END) -+ priv->status |= FALCON_I2C_TX_END; ++ /* send slave address */ ++ if (msg->flags & I2C_M_TEN) { ++ i2c_w32(0xf0 | ((addr & 0x300) >> 7) | rd, txd); ++ i2c_w32(addr & 0xff, txd); ++ } else ++ i2c_w32((addr & 0x7f) << 1 | rd, txd); ++} + -+ /* not acknowledge */ -+ if (i_pro & I2C_P_IRQSS_NACK) -+ priv->status |= FALCON_I2C_NACK; ++static void set_tx_len(struct falcon_i2c *priv) ++{ ++ struct i2c_msg *msg = priv->current_msg; ++ int len = (msg->flags & I2C_M_TEN) ? 2 : 1; + -+ /* arbitration lost */ -+ if (i_pro & I2C_P_IRQSS_AL) -+ priv->status |= FALCON_I2C_ARB_LOST; ++ PRINTK("set_tx_len %cX\n", (msg->flags & I2C_M_RD)?'R':'T'); + -+ /* address match */ -+ if (i_pro & I2C_P_IRQSS_AM) -+ priv->status |= FALCON_I2C_ADDR_MATCH; ++ priv->status = STATUS_ADDR; + -+ i2c_w32(i_pro, p_irqsc); ++ if (!(msg->flags & I2C_M_RD)) { ++ len += msg->len; ++ } else { ++ /* set maximum received packet size (before rx int!) */ ++ i2c_w32(msg->len, mrps_ctrl); + } ++ i2c_w32(len, tps_ctrl); ++ enable_burst_irq(priv); ++} + -+ /* error interrupt */ -+ if (i_raw & I2C_RIS_I2C_ERR_INT_INTOCC) { -+ i_err = i2c_r32(err_irqss); -+ -+ /* tx fifo overflow */ -+ if (i_err & I2C_ERR_IRQSS_TXF_OFL) -+ priv->status |= FALCON_I2C_TX_OFL; -+ -+ /* tx fifo underflow */ -+ if (i_err & I2C_ERR_IRQSS_TXF_UFL) -+ priv->status |= FALCON_I2C_TX_UFL; -+ -+ /* rx fifo overflow */ -+ if (i_err & I2C_ERR_IRQSS_RXF_OFL) -+ priv->status |= FALCON_I2C_RX_OFL; -+ -+ /* rx fifo underflow */ -+ if (i_err & I2C_ERR_IRQSS_RXF_UFL) -+ priv->status |= FALCON_I2C_RX_UFL; ++static int falcon_i2c_hw_init(struct i2c_adapter *adap) ++{ ++ struct falcon_i2c *priv = i2c_get_adapdata(adap); + -+ i2c_w32(i_err, err_irqsc); -+ } ++ /* disable bus */ ++ i2c_w32_mask(I2C_RUN_CTRL_RUN_EN, 0, run_ctrl); + -+ /* burst request */ -+ if (i_raw & I2C_RIS_BREQ_INT_INTOCC) { -+ i2c_w32_mask(I2C_IMSC_BREQ_INT_EN, 0, imsc); -+ i2c_w32_mask(0, I2C_ICR_BREQ_INT_CLR, icr); ++#ifndef DEBUG ++ /* set normal operation clock divider */ ++ i2c_w32(1 << I2C_CLC_RMC_OFFSET, clc); ++#else ++ /* for debugging a higher divider value! */ ++ i2c_w32(0xF0 << I2C_CLC_RMC_OFFSET, clc); ++#endif + -+ priv->status |= FALCON_I2C_BURST_REQ; ++ /* set frequency */ ++ if (priv->mode == FALCON_I2C_MODE_100) { ++ dev_dbg(priv->dev, "set standard mode (100 kHz)\n"); ++ i2c_w32(0, fdiv_high_cfg); ++ i2c_w32((1 << I2C_FDIV_CFG_INC_OFFSET) | ++ (499 << I2C_FDIV_CFG_DEC_OFFSET), ++ fdiv_cfg); ++ } else if (priv->mode == FALCON_I2C_MODE_400) { ++ dev_dbg(priv->dev, "set fast mode (400 kHz)\n"); ++ i2c_w32(0, fdiv_high_cfg); ++ i2c_w32((1 << I2C_FDIV_CFG_INC_OFFSET) | ++ (124 << I2C_FDIV_CFG_DEC_OFFSET), ++ fdiv_cfg); ++ } else if (priv->mode == FALCON_I2C_MODE_3400) { ++ dev_dbg(priv->dev, "set high mode (3.4 MHz)\n"); ++ i2c_w32(0, fdiv_cfg); ++ /* TODO recalculate value for 100MHz input */ ++ i2c_w32((41 << I2C_FDIV_HIGH_CFG_INC_OFFSET) | ++ (152 << I2C_FDIV_HIGH_CFG_DEC_OFFSET), ++ fdiv_high_cfg); ++ } else { ++ dev_warn(priv->dev, "unknown mode\n"); ++ return -ENODEV; + } + -+ /* last burst request */ -+ if (i_raw & I2C_RIS_LBREQ_INT_INTOCC) { -+ i2c_w32_mask(I2C_IMSC_LBREQ_INT_EN, 0, imsc); -+ i2c_w32_mask(0, I2C_ICR_LBREQ_INT_CLR, icr); -+ -+ priv->status |= FALCON_I2C_BURST_REQ; -+ } ++ /* configure fifo */ ++ i2c_w32(I2C_FIFO_CFG_TXFC | /* tx fifo as flow controller */ ++ I2C_FIFO_CFG_RXFC | /* rx fifo as flow controller */ ++ I2C_FIFO_CFG_TXFA_TXFA2 | /* tx fifo 4-byte aligned */ ++ I2C_FIFO_CFG_RXFA_RXFA2 | /* rx fifo 4-byte aligned */ ++ I2C_FIFO_CFG_TXBS_TXBS0 | /* tx fifo burst size is 1 word */ ++ I2C_FIFO_CFG_RXBS_RXBS0, /* rx fifo burst size is 1 word */ ++ fifo_cfg); + -+ if (old_status != (unsigned int)priv->status) -+ complete(&priv->done); ++ /* configure address */ ++ i2c_w32(I2C_ADDR_CFG_SOPE_EN | /* generate stop when no more data in the ++ fifo */ ++ I2C_ADDR_CFG_SONA_EN | /* generate stop when NA received */ ++ I2C_ADDR_CFG_MnS_EN | /* we are master device */ ++ 0, /* our slave address (not used!) */ ++ addr_cfg); + -+ spin_unlock_irqrestore(&priv->lock, flags); ++ /* enable bus */ ++ i2c_w32_mask(0, I2C_RUN_CTRL_RUN_EN, run_ctrl); + -+ return IRQ_HANDLED; ++ return 0; +} + -+static int falcon_i2c_ready(struct falcon_i2c *priv) ++static int falcon_i2c_wait_bus_not_busy(struct falcon_i2c *priv) +{ -+ int timeout; -+ u32 bus_stat; -+ unsigned long flags; -+ int ret; -+ -+ for (timeout = 0; timeout < FALCON_I2C_READY_TIMEOUT; timeout++) { -+ bus_stat = i2c_r32(bus_stat); -+ -+ if (bus_stat & I2C_BUS_STAT_BS_SC) { -+ cpu_relax(); -+ } else { -+ spin_lock_irqsave(&priv->lock, flags); ++ int timeout = FALCON_I2C_BUSY_TIMEOUT; + -+ if (FALCON_I2C_ERROR(priv)) { -+ ret = priv->status; -+ -+ dev_dbg(priv->dev, "bus ready wait error 0x%08lx\n", priv->status); -+ -+ FALCON_I2C_ERROR_CLEAR(priv); -+ } else { -+ ret = 0; -+ } -+ -+ spin_unlock_irqrestore(&priv->lock, flags); -+ -+ return ret; ++ while ((i2c_r32(bus_stat) & I2C_BUS_STAT_BS_MASK) ++ != I2C_BUS_STAT_BS_FREE) { ++ if (timeout <= 0) { ++ dev_warn(priv->dev, "timeout waiting for bus ready\n"); ++ return -ETIMEDOUT; + } ++ timeout--; ++ mdelay(1); + } + -+ dev_dbg(priv->dev, "bus ready wait timeout\n"); -+ -+ return -ETIME; ++ return 0; +} + -+static int falcon_i2c_wait(struct falcon_i2c *priv, unsigned long status) ++static void falcon_i2c_tx(struct falcon_i2c *priv, int last) +{ -+ int ret = 0; -+ unsigned long flags; -+ unsigned int timeout; -+ -+ spin_lock_irqsave(&priv->lock, flags); -+ -+ priv->status &= FALCON_I2C_BURST_REQ; -+ -+ /* check if the event already occurred */ -+ if ((priv->status & status) == status) { -+ priv->status &= ~status; -+ spin_unlock_irqrestore(&priv->lock, flags); -+ -+ return 0; ++ if (priv->msg_buf_len && priv->msg_buf) { ++ i2c_w32(*priv->msg_buf, txd); ++ ++ if (--priv->msg_buf_len) ++ priv->msg_buf++; ++ else ++ priv->msg_buf = NULL; ++ } else ++ last = 1; ++ ++ if (last) { ++ disable_burst_irq(priv); + } ++} + -+ spin_unlock_irqrestore(&priv->lock, flags); -+ -+ /* unmask burst interrupts */ -+ i2c_w32_mask(0, I2C_IMSC_LBREQ_INT_EN | I2C_IMSC_BREQ_INT_EN, imsc); -+ -+ for (timeout = 0; timeout < FALCON_I2C_WAIT_TIMEOUT; timeout++) { -+ /* wait for the data request */ -+ wait_for_completion_timeout(&priv->done, HZ / 10); -+ -+ /* handle errors */ -+ spin_lock_irqsave(&priv->lock, flags); -+ -+ if (FALCON_I2C_ERROR(priv)) { -+ dev_dbg(priv->dev, "wait error 0x%08lx (waiting for 0x%08lx)\n", -+ priv->status, -+ status); -+ -+ if (priv->status & FALCON_I2C_NACK) -+ ret = -ENXIO; -+ else -+ ret = -EREMOTEIO; -+ -+ FALCON_I2C_ERROR_CLEAR(priv); -+ } else { -+ if ((priv->status & status) == status) { -+ priv->status &= ~status; -+ spin_unlock_irqrestore(&priv->lock, flags); -+ -+ return 0; ++static void falcon_i2c_rx(struct falcon_i2c *priv, int last) ++{ ++ u32 fifo_stat,timeout; ++ if (priv->msg_buf_len && priv->msg_buf) { ++ timeout = 5000000; ++ do { ++ fifo_stat = i2c_r32(ffs_stat); ++ } while (!fifo_stat && --timeout); ++ if (!timeout) { ++ last = 1; ++ PRINTK("\nrx timeout\n"); ++ goto err; ++ } ++ while (fifo_stat) { ++ *priv->msg_buf = i2c_r32(rxd); ++ if (--priv->msg_buf_len) ++ priv->msg_buf++; ++ else { ++ priv->msg_buf = NULL; ++ last = 1; ++ break; + } ++ #if 0 ++ fifo_stat = i2c_r32(ffs_stat); ++ #else ++ /* do not read more than burst size, otherwise no "last ++ burst" is generated and the transaction is blocked! */ ++ fifo_stat = 0; ++ #endif ++ } ++ } else { ++ last = 1; ++ } ++err: ++ if (last) { ++ disable_burst_irq(priv); ++ ++ if (priv->status == STATUS_READ_END) { ++ /* do the STATUS_STOP and complete() here, as sometimes ++ the tx_end is already seen before this is finished */ ++ priv->status = STATUS_STOP; ++ complete(&priv->cmd_complete); ++ } else { ++ i2c_w32(I2C_ENDD_CTRL_SETEND, endd_ctrl); ++ priv->status = STATUS_READ_END; + } -+ -+ spin_unlock_irqrestore(&priv->lock, flags); -+ -+ if (ret) -+ return ret; + } -+ -+ dev_dbg(priv->dev, "wait timeout error 0x%08lx (waiting for 0x%08lx)\n", -+ priv->status, -+ status); -+ -+ return -ETIME; +} + -+static int falcon_i2c_tx(struct falcon_i2c *priv, int ten_bit, u16 addr, -+ u8 *buf, int len) ++static void falcon_i2c_xfer_init(struct falcon_i2c *priv) +{ -+ int i; -+ int ret; -+ -+ dev_dbg(priv->dev, "%s\n", __func__); -+ -+ /* tell fifo the number of bytes we are going to send */ -+ i2c_w32(len + (ten_bit ? 2 : 1), tps_ctrl); -+ -+ /* wait for the data request */ -+ ret = falcon_i2c_wait(priv, FALCON_I2C_BURST_REQ); -+ if (ret) -+ return ret; -+ -+ /* send slave address */ -+ if (ten_bit) { -+ i2c_w32(0x78 | ((addr >> 7) & 0x7), txd); -+ i2c_w32(0x78 | ((addr & 0x7f) << 1) | 0, txd); -+ } else { -+ i2c_w32((addr << 1) | 0, txd); -+ } ++ /* enable interrupts */ ++ i2c_w32(FALCON_I2C_IMSC_DEFAULT_MASK, imsc); + -+ /* fill fifo */ -+ for (i = 0; i < len; i++) { -+ ret = falcon_i2c_wait(priv, FALCON_I2C_BURST_REQ); -+ if (ret) -+ return ret; ++ /* trigger transfer of first msg */ ++ set_tx_len(priv); ++} + -+ i2c_w32(buf[i], txd); ++static void dump_msgs(struct i2c_msg msgs[], int num, int rx) ++{ ++#if defined(DEBUG) ++ int i, j; ++ printk("Messages %d %s\n", num, rx ? "out" : "in"); ++ for (i = 0; i < num; i++) { ++ printk("%2d %cX Msg(%d) addr=0x%X: ", i, ++ (msgs[i].flags & I2C_M_RD)?'R':'T', ++ msgs[i].len, msgs[i].addr); ++ if (!(msgs[i].flags & I2C_M_RD) || rx) { ++ for (j = 0; j < msgs[i].len; j++) ++ printk("%02X ", msgs[i].buf[j]); ++ } ++ printk("\n"); + } ++#endif ++} + -+ return falcon_i2c_wait(priv, FALCON_I2C_TX_END); ++static void falcon_i2c_release_bus(struct falcon_i2c *priv) ++{ ++ if ((i2c_r32(bus_stat) & I2C_BUS_STAT_BS_MASK) == I2C_BUS_STAT_BS_BM) ++ i2c_w32(I2C_ENDD_CTRL_SETEND, endd_ctrl); +} + -+static int falcon_i2c_rx(struct falcon_i2c *priv, int ten_bit, u16 addr, -+ u8 *buf, int len) ++static int falcon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ++ int num) +{ -+ int i; ++ struct falcon_i2c *priv = i2c_get_adapdata(adap); + int ret; + -+ dev_dbg(priv->dev, "%s\n", __func__); ++ dev_dbg(priv->dev, "xfer %u messages\n", num); ++ dump_msgs(msgs, num, 0); + -+ /* we need to transmit address only */ -+ i2c_w32(ten_bit ? 2 : 1, tps_ctrl); ++ mutex_lock(&priv->mutex); + -+ /* set maximum received packet size */ -+ i2c_w32(len, mrps_ctrl); ++ INIT_COMPLETION(priv->cmd_complete); ++ priv->current_msg = msgs; ++ priv->msgs_num = num; ++ priv->msg_err = 0; ++ priv->status = STATUS_IDLE; + -+ /* wait for the data request */ -+ ret = falcon_i2c_wait(priv, FALCON_I2C_BURST_REQ); ++ /* wait for the bus to become ready */ ++ ret = falcon_i2c_wait_bus_not_busy(priv); + if (ret) -+ return ret; -+ -+ /* write down the address */ -+ if (ten_bit) { -+ i2c_w32(0x78 | ((addr >> 7) & 0x7), txd); -+ i2c_w32(0x78 | ((addr & 0x7f) << 1) | 1, txd); -+ } else { -+ i2c_w32((addr << 1) | 1, txd); ++ goto done; ++ ++ while (priv->msgs_num) { ++ /* start the transfers */ ++ falcon_i2c_xfer_init(priv); ++ ++ /* wait for transfers to complete */ ++ ret = wait_for_completion_interruptible_timeout( ++ &priv->cmd_complete, FALCON_I2C_XFER_TIMEOUT); ++ if (ret == 0) { ++ dev_err(priv->dev, "controller timed out\n"); ++ falcon_i2c_hw_init(adap); ++ ret = -ETIMEDOUT; ++ goto done; ++ } else if (ret < 0) ++ goto done; ++ ++ if (priv->msg_err) { ++ if (priv->msg_err & FALCON_I2C_NACK) ++ ret = -ENXIO; ++ else ++ ret = -EREMOTEIO; ++ goto done; ++ } ++ if (--priv->msgs_num) { ++ priv->current_msg++; ++ } + } ++ /* no error? */ ++ ret = num; + -+ /* wait for the read request */ -+ ret = falcon_i2c_wait(priv, FALCON_I2C_TX_END -+#ifndef FALCON_FIX_ME -+ | FALCON_I2C_ADDR_MATCH -+#endif -+ | FALCON_I2C_RX); ++done: ++ falcon_i2c_release_bus(priv); + -+ if (ret) -+ return ret; ++ mutex_unlock(&priv->mutex); + -+ /* read bytes */ -+ for (i = 0; i < len; i++) { -+#ifdef FALCON_FIX_ME -+ while (i2c_r32(rps_stat) == 0) -+ cpu_relax(); -+#else -+ ret = falcon_i2c_wait(priv, FALCON_I2C_BURST_REQ); -+ -+ if (ret) -+ return ret; -+#endif -+ -+ buf[i] = i2c_r32(rxd); -+ } ++ if (ret>=0) ++ dump_msgs(msgs, num, 1); + -+#ifndef FALCON_FIX_ME -+ /* wait for transmission end */ -+ return falcon_i2c_wait(priv, FALCON_I2C_TX_END); -+#else -+ return 0; -+#endif ++ PRINTK("XFER ret %d\n", ret); ++ return ret; +} + -+static int falcon_i2c_xfer_msg(struct falcon_i2c *priv, struct i2c_msg *msg) ++static irqreturn_t falcon_i2c_isr_burst(int irq, void *dev_id) +{ -+ int ret; -+ int ten_bit; -+ unsigned long flags; -+ -+ dev_dbg(priv->dev, "%s %u byte(s) %s 0x%02x\n", -+ (msg->flags & I2C_M_RD) ? "read" : "write", msg->len, -+ (msg->flags & I2C_M_RD) ? "from" : "to", msg->addr); ++ struct falcon_i2c *priv = dev_id; ++ struct i2c_msg *msg = priv->current_msg; ++ int last = (irq == priv->irq_lb); + -+ if (msg->flags & I2C_M_TEN) -+ ten_bit = 1; ++ if (last) ++ PRINTK("LB "); + else -+ ten_bit = 0; ++ PRINTK("B "); ++ ++ if (msg->flags & I2C_M_RD) { ++ switch (priv->status) { ++ case STATUS_ADDR: ++ PRINTK("X"); ++ prepare_msg_send_addr(priv); ++ disable_burst_irq(priv); ++ break; ++ case STATUS_READ: ++ case STATUS_READ_END: ++ PRINTK("R"); ++ falcon_i2c_rx(priv, last); ++ break; ++ default: ++ disable_burst_irq(priv); ++ printk("Status R %d\n", priv->status); ++ break; ++ } ++ } else { ++ switch (priv->status) { ++ case STATUS_ADDR: ++ PRINTK("x"); ++ prepare_msg_send_addr(priv); ++ break; ++ case STATUS_WRITE: ++ PRINTK("w"); ++ falcon_i2c_tx(priv, last); ++ break; ++ default: ++ disable_burst_irq(priv); ++ printk("Status W %d\n", priv->status); ++ break; ++ } ++ } + -+ /* reconfigure bus if need to send message in different address mode */ -+ spin_lock_irqsave(&priv->lock, flags); -+ if (ten_bit != priv->ten_bit) { ++ i2c_w32(I2C_ICR_BREQ_INT_CLR | I2C_ICR_LBREQ_INT_CLR, icr); ++ return IRQ_HANDLED; ++} + -+ /* disable bus */ -+ i2c_w32_mask(I2C_RUN_CTRL_RUN_EN, 0, run_ctrl); ++static void falcon_i2c_isr_prot(struct falcon_i2c *priv) ++{ ++ u32 i_pro = i2c_r32(p_irqss); + -+ /* reconfigure address */ -+ falcon_addr_configure(priv, ten_bit); ++ PRINTK("i2c-p"); + -+ /* enable bus */ -+ i2c_w32_mask(0, I2C_RUN_CTRL_RUN_EN, run_ctrl); ++ /* not acknowledge */ ++ if (i_pro & I2C_P_IRQSS_NACK) { ++ priv->msg_err |= FALCON_I2C_NACK; ++ PRINTK(" nack"); ++ } + -+ priv->ten_bit = ten_bit; ++ /* arbitration lost */ ++ if (i_pro & I2C_P_IRQSS_AL) { ++ priv->msg_err |= FALCON_I2C_ARB_LOST; ++ PRINTK(" arb-lost"); + } -+ spin_unlock_irqrestore(&priv->lock, flags); ++ /* tx -> rx switch */ ++ if (i_pro & I2C_P_IRQSS_RX) ++ PRINTK(" rx"); + -+ /* read/write actual message */ -+ if (msg->flags & I2C_M_RD) -+ ret = falcon_i2c_rx(priv, ten_bit, msg->addr, msg->buf, -+ msg->len); -+ else -+ ret = falcon_i2c_tx(priv, ten_bit, msg->addr, msg->buf, -+ msg->len); ++ /* tx end */ ++ if (i_pro & I2C_P_IRQSS_TX_END) ++ PRINTK(" txend"); ++ PRINTK("\n"); + -+ if (ret) -+ return ret; ++ if (!priv->msg_err) { ++ /* tx -> rx switch */ ++ if (i_pro & I2C_P_IRQSS_RX) { ++ priv->status = STATUS_READ; ++ enable_burst_irq(priv); ++ } ++ if (i_pro & I2C_P_IRQSS_TX_END) { ++ if (priv->status == STATUS_READ) ++ priv->status = STATUS_READ_END; ++ else { ++ disable_burst_irq(priv); ++ priv->status = STATUS_STOP; ++ } ++ } ++ } + -+ return 0; ++ i2c_w32(i_pro, p_irqsc); +} + -+static int falcon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, -+ int num) ++static irqreturn_t falcon_i2c_isr(int irq, void *dev_id) +{ -+ int i; -+ int ret; -+ unsigned long flags; -+ struct falcon_i2c *priv = i2c_get_adapdata(adap); ++ u32 i_raw, i_err=0; ++ struct falcon_i2c *priv = dev_id; + -+ dev_dbg(priv->dev, "xfer %u messages\n", num); ++ i_raw = i2c_r32(mis); ++ PRINTK("i_raw 0x%08X\n", i_raw); + -+ /* transfer each message */ -+ for (i = 0; i < num; i++) { -+#ifdef FALCON_FIX_ME -+ /* disable bus */ -+ i2c_w32_mask(I2C_RUN_CTRL_RUN_EN, 0, run_ctrl); -+ /* enable bus */ -+ i2c_w32_mask(0, I2C_RUN_CTRL_RUN_EN, run_ctrl); -+#endif ++ /* error interrupt */ ++ if (i_raw & I2C_RIS_I2C_ERR_INT_INTOCC) { ++ i_err = i2c_r32(err_irqss); ++ PRINTK("i_err 0x%08X bus_stat 0x%04X\n", ++ i_err, i2c_r32(bus_stat)); + -+ /* clear bus status */ -+ spin_lock_irqsave(&priv->lock, flags); -+ priv->status = 0; -+ spin_unlock_irqrestore(&priv->lock, flags); ++ /* tx fifo overflow (8) */ ++ if (i_err & I2C_ERR_IRQSS_TXF_OFL) ++ priv->msg_err |= FALCON_I2C_TX_OFL; + -+ /* wait for the bus to become ready */ -+ ret = falcon_i2c_ready(priv); -+ if (ret) -+ return ret; ++ /* tx fifo underflow (4) */ ++ if (i_err & I2C_ERR_IRQSS_TXF_UFL) ++ priv->msg_err |= FALCON_I2C_TX_UFL; + -+ /* transfer message */ -+ ret = falcon_i2c_xfer_msg(priv, &msg[i]); ++ /* rx fifo overflow (2) */ ++ if (i_err & I2C_ERR_IRQSS_RXF_OFL) ++ priv->msg_err |= FALCON_I2C_RX_OFL; + -+ if (ret) -+ return ret; ++ /* rx fifo underflow (1) */ ++ if (i_err & I2C_ERR_IRQSS_RXF_UFL) ++ priv->msg_err |= FALCON_I2C_RX_UFL; + -+ /* check for unhandled errors */ -+ spin_lock_irqsave(&priv->lock, flags); -+ if (FALCON_I2C_ERROR(priv)) -+ ret = priv->status; -+ spin_unlock_irqrestore(&priv->lock, flags); ++ i2c_w32(i_err, err_irqsc); ++ } + -+ if (ret) { -+ dev_warn(priv->dev, "message %u unhandled error 0x%x\n", -+ i, ret); ++ /* protocol interrupt */ ++ if (i_raw & I2C_RIS_I2C_P_INT_INTOCC) ++ falcon_i2c_isr_prot(priv); + -+ return ret; -+ } -+ } ++ if ((priv->msg_err) || (priv->status == STATUS_STOP)) ++ complete(&priv->cmd_complete); + -+ return 0; ++ return IRQ_HANDLED; +} + -+static u32 falcon_i2c_func(struct i2c_adapter *adap) ++static u32 falcon_i2c_functionality(struct i2c_adapter *adap) +{ -+ return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL; ++ return I2C_FUNC_I2C | ++ I2C_FUNC_10BIT_ADDR | ++ I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm falcon_i2c_algorithm = { + .master_xfer = falcon_i2c_xfer, -+ .functionality = falcon_i2c_func, ++ .functionality = falcon_i2c_functionality, +}; + -+static int falcon_i2c_hw_init(struct i2c_adapter *adap) -+{ -+ struct falcon_i2c *priv = i2c_get_adapdata(adap); -+ -+ /* disable bus */ -+ i2c_w32_mask(I2C_RUN_CTRL_RUN_EN, 0, run_ctrl); -+ -+ /* set normal operation clock divider */ -+ i2c_w32(1 << I2C_CLC_RMC_OFFSET, clc); -+ -+ /* set frequency */ -+ if (priv->mode == FALCON_I2C_MODE_100) { -+ dev_dbg(priv->dev, "set standard mode (100 kHz)\n"); -+ -+ i2c_w32(0, fdiv_high_cfg); -+ -+ i2c_w32((1 << I2C_FDIV_CFG_INC_OFFSET) -+ | (499 << I2C_FDIV_CFG_DEC_OFFSET), -+ fdiv_cfg); -+ } else if (priv->mode == FALCON_I2C_MODE_400) { -+ dev_dbg(priv->dev, "set fast mode (400 kHz)\n"); -+ -+ i2c_w32(0, fdiv_high_cfg); -+ -+ i2c_w32((1 << I2C_FDIV_CFG_INC_OFFSET) -+ | (124 << I2C_FDIV_CFG_DEC_OFFSET), -+ fdiv_cfg); -+ } else if (priv->mode == FALCON_I2C_MODE_3400) { -+ dev_dbg(priv->dev, "set high mode (3.4 MHz)\n"); -+ -+ i2c_w32(0, fdiv_cfg); -+ -+ /* TODO recalculate value for 100MHz input */ -+ i2c_w32((41 << I2C_FDIV_CFG_INC_OFFSET) -+ | (152 << I2C_FDIV_CFG_DEC_OFFSET), -+ fdiv_high_cfg); -+ } else { -+ dev_warn(priv->dev, "unknown mode\n"); -+ -+ return -ENODEV; -+ } -+ -+ /* configure fifo */ -+ i2c_w32(I2C_FIFO_CFG_TXFC /* tx fifo as flow controller */ -+ | I2C_FIFO_CFG_RXFC /* rx fifo as flow controller */ -+ | I2C_FIFO_CFG_TXFA_TXFA2 /* tx fifo 4-byte aligned */ -+ | I2C_FIFO_CFG_RXFA_RXFA2 /* rx fifo 4-byte aligned */ -+ | I2C_FIFO_CFG_TXBS_TXBS0 /* tx fifo burst size is 1 word */ -+ | I2C_FIFO_CFG_RXBS_RXBS0, /* rx fifo burst size is 1 word */ -+ fifo_cfg); -+ -+ /* configure address */ -+ falcon_addr_configure(priv, priv->ten_bit); -+ -+ /* enable bus */ -+ i2c_w32_mask(0, I2C_RUN_CTRL_RUN_EN, run_ctrl); -+ -+ /* mask burst interrupts */ -+ i2c_w32_mask(I2C_IMSC_LBREQ_INT_EN | I2C_IMSC_BREQ_INT_EN, 0, imsc); -+ -+ /* enable interrupts */ -+ i2c_w32(I2C_IMSC_LBREQ_INT_EN -+ | I2C_IMSC_BREQ_INT_EN -+ | I2C_IMSC_I2C_P_INT_EN -+ | I2C_IMSC_I2C_ERR_INT_EN, -+ imsc); -+ -+ return 0; -+} -+ +static int __devinit falcon_i2c_probe(struct platform_device *pdev) +{ + int ret = 0; @@ -649,12 +637,26 @@ + strlcpy(adap->name, DRV_NAME "-adapter", sizeof(adap->name)); + adap->algo = &falcon_i2c_algorithm; + -+ priv->ten_bit = 0; + priv->mode = FALCON_I2C_MODE_100; + priv->clk = clk; + priv->dev = &pdev->dev; + -+ spin_lock_init(&priv->lock); ++ init_completion(&priv->cmd_complete); ++ mutex_init(&priv->mutex); ++ ++ ret = ltq_gpio_request(107, 0, 0, 0, DRV_NAME":sda"); ++ if (ret) { ++ dev_err(&pdev->dev, "I2C gpio 107 (sda) not available\n"); ++ ret = -ENXIO; ++ goto err_free_priv; ++ } ++ ret = ltq_gpio_request(108, 0, 0, 0, DRV_NAME":scl"); ++ if (ret) { ++ gpio_free(107); ++ dev_err(&pdev->dev, "I2C gpio 108 (scl) not available\n"); ++ ret = -ENXIO; ++ goto err_free_priv; ++ } + + ioarea = request_mem_region(mmres->start, resource_size(mmres), + pdev->name); @@ -662,7 +664,7 @@ + if (ioarea == NULL) { + dev_err(&pdev->dev, "I2C region already claimed\n"); + ret = -ENXIO; -+ goto err_free_priv; ++ goto err_free_gpio; + } + + /* map memory */ @@ -674,7 +676,7 @@ + } + + priv->irq_lb = irqres_lb->start; -+ ret = request_irq(priv->irq_lb, falcon_i2c_isr, IRQF_DISABLED, ++ ret = request_irq(priv->irq_lb, falcon_i2c_isr_burst, IRQF_DISABLED, + irqres_lb->name, priv); + if (ret) { + dev_err(&pdev->dev, "can't get last burst IRQ %d\n", irqres_lb->start); @@ -683,7 +685,7 @@ + } + + priv->irq_b = irqres_b->start; -+ ret = request_irq(priv->irq_b, falcon_i2c_isr, IRQF_DISABLED, ++ ret = request_irq(priv->irq_b, falcon_i2c_isr_burst, IRQF_DISABLED, + irqres_b->name, priv); + if (ret) { + dev_err(&pdev->dev, "can't get burst IRQ %d\n", irqres_b->start); @@ -728,8 +730,6 @@ + (i2c_r32(id) & I2C_ID_ID_MASK) >> I2C_ID_ID_OFFSET, + (i2c_r32(id) & I2C_ID_REV_MASK) >> I2C_ID_REV_OFFSET); + -+ init_completion(&priv->done); -+ + /* initialize HW */ + ret = falcon_i2c_hw_init(adap); + if (ret) { @@ -737,6 +737,8 @@ + goto err_remove_adapter; + } + ++ dev_info(&pdev->dev, "version %s\n", DRV_VERSION); ++ + return 0; + +err_remove_adapter: @@ -761,6 +763,10 @@ +err_release_region: + release_mem_region(mmres->start, resource_size(mmres)); + ++err_free_gpio: ++ gpio_free(108); ++ gpio_free(107); ++ +err_free_priv: + kfree(priv); + @@ -784,6 +790,11 @@ + free_irq(priv->irq_err, priv); + free_irq(priv->irq_p, priv); + ++ iounmap(priv->membase); ++ ++ gpio_free(108); ++ gpio_free(107); ++ + kfree(priv); + + mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -810,7 +821,7 @@ + ret = platform_driver_register(&falcon_i2c_driver); + + if (ret) -+ printk(KERN_DEBUG DRV_NAME ": can't register platform driver"); ++ pr_debug(DRV_NAME ": can't register platform driver\n"); + + return ret; +} @@ -824,5 +835,6 @@ +module_exit(falcon_i2c_exit); + +MODULE_DESCRIPTION("Lantiq FALC(tm) ON - I2C bus adapter"); -+MODULE_ALIAS("platform:i2c_falcon"); ++MODULE_ALIAS("platform:" DRV_NAME); +MODULE_LICENSE("GPL"); ++MODULE_VERSION(DRV_VERSION); diff --git a/target/linux/lantiq/patches-3.0/130-falcon-spi-flash.patch b/target/linux/lantiq/patches-3.0/130-falcon-spi-flash.patch index 94f13c98b2..cf618e046d 100644 --- a/target/linux/lantiq/patches-3.0/130-falcon-spi-flash.patch +++ b/target/linux/lantiq/patches-3.0/130-falcon-spi-flash.patch @@ -1,6 +1,6 @@ --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile -@@ -55,6 +55,7 @@ obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci. +@@ -56,6 +56,7 @@ obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci. obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o @@ -484,7 +484,7 @@ +MODULE_DESCRIPTION("Lantiq Falcon SPI controller driver"); --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -210,6 +210,10 @@ config SPI_MPC52xx +@@ -219,6 +219,10 @@ config SPI_MPC52xx This drivers supports the MPC52xx SPI controller in master SPI mode. diff --git a/target/linux/lantiq/patches-3.0/150-falcon-easy98020.patch b/target/linux/lantiq/patches-3.0/150-falcon-easy98020.patch index 7defccba04..7ddf77ab21 100644 --- a/target/linux/lantiq/patches-3.0/150-falcon-easy98020.patch +++ b/target/linux/lantiq/patches-3.0/150-falcon-easy98020.patch @@ -116,7 +116,7 @@ + easy98020_init); --- a/arch/mips/lantiq/falcon/Kconfig +++ b/arch/mips/lantiq/falcon/Kconfig -@@ -6,6 +6,10 @@ +@@ -6,6 +6,10 @@ config LANTIQ_MACH_EASY98000 bool "Easy98000" default y @@ -129,7 +129,7 @@ endif --- a/arch/mips/lantiq/falcon/Makefile +++ b/arch/mips/lantiq/falcon/Makefile -@@ -3,3 +3,4 @@ +@@ -3,3 +3,4 @@ obj-y += softdog_vpe.o obj-$(CONFIG_LANTIQ_MACH_EASY98000) += addon-easy98000.o obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o obj-$(CONFIG_LANTIQ_MACH_EASY98000) += dev-leds-easy98000-cpld.o diff --git a/target/linux/lantiq/patches-3.0/160-falcon-95C3AM1.patch b/target/linux/lantiq/patches-3.0/160-falcon-95C3AM1.patch index f18d42c07f..7245eb5b62 100644 --- a/target/linux/lantiq/patches-3.0/160-falcon-95C3AM1.patch +++ b/target/linux/lantiq/patches-3.0/160-falcon-95C3AM1.patch @@ -102,7 +102,7 @@ + board_95C3AM1_init); --- a/arch/mips/lantiq/falcon/Kconfig +++ b/arch/mips/lantiq/falcon/Kconfig -@@ -10,6 +10,10 @@ +@@ -10,6 +10,10 @@ config LANTIQ_MACH_EASY98020 bool "Easy98020" default y @@ -115,14 +115,14 @@ endif --- a/arch/mips/lantiq/falcon/Makefile +++ b/arch/mips/lantiq/falcon/Makefile -@@ -4,3 +4,4 @@ +@@ -4,3 +4,4 @@ obj-$(CONFIG_LANTIQ_MACH_EASY98000) += a obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o obj-$(CONFIG_LANTIQ_MACH_EASY98000) += dev-leds-easy98000-cpld.o obj-$(CONFIG_LANTIQ_MACH_EASY98020) += mach-easy98020.o +obj-$(CONFIG_LANTIQ_MACH_95C3AM1) += mach-95C3AM1.o --- a/arch/mips/lantiq/machtypes.h +++ b/arch/mips/lantiq/machtypes.h -@@ -21,6 +21,7 @@ +@@ -21,6 +21,7 @@ enum lantiq_mach_type { LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial Flash */ LANTIQ_MACH_EASY98000NAND, /* Falcon Eval Board, NAND Flash */ LANTIQ_MACH_EASY98020, /* Falcon Reference Board */ diff --git a/target/linux/lantiq/patches-3.0/170-falcon-dm9000-polling.patch b/target/linux/lantiq/patches-3.0/170-falcon-dm9000-polling.patch index 83763182e5..64313c5968 100644 --- a/target/linux/lantiq/patches-3.0/170-falcon-dm9000-polling.patch +++ b/target/linux/lantiq/patches-3.0/170-falcon-dm9000-polling.patch @@ -8,7 +8,7 @@ #include #include #include -@@ -125,6 +126,8 @@ +@@ -125,6 +126,8 @@ typedef struct board_info { struct delayed_work phy_poll; struct net_device *ndev; @@ -17,7 +17,7 @@ spinlock_t lock; struct mii_if_info mii; -@@ -824,6 +827,8 @@ +@@ -824,6 +827,8 @@ static void dm9000_timeout(struct net_de netif_stop_queue(dev); dm9000_reset(db); dm9000_init_dm9000(dev); @@ -26,7 +26,7 @@ /* We can accept TX packets again */ dev->trans_start = jiffies; /* prevent tx timeout */ netif_wake_queue(dev); -@@ -895,6 +900,12 @@ +@@ -895,6 +900,12 @@ dm9000_start_xmit(struct sk_buff *skb, s /* free this SKB */ dev_kfree_skb(skb); @@ -39,7 +39,7 @@ return NETDEV_TX_OK; } -@@ -1136,6 +1147,18 @@ +@@ -1136,6 +1147,18 @@ static void dm9000_poll_controller(struc } #endif @@ -58,7 +58,7 @@ /* * Open the interface. * The interface is opened whenever "ifconfig" actives it. -@@ -1149,14 +1172,15 @@ +@@ -1149,14 +1172,15 @@ dm9000_open(struct net_device *dev) if (netif_msg_ifup(db)) dev_dbg(db->dev, "enabling %s\n", dev->name); @@ -80,7 +80,7 @@ /* GPIO0 on pre-activate PHY, Reg 1F is not set by reset */ iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */ mdelay(1); /* delay needs by DM9000B */ -@@ -1165,8 +1189,14 @@ +@@ -1165,8 +1189,14 @@ dm9000_open(struct net_device *dev) dm9000_reset(db); dm9000_init_dm9000(dev); @@ -97,7 +97,7 @@ /* Init driver variable */ db->dbug_cnt = 0; -@@ -1174,6 +1204,9 @@ +@@ -1174,6 +1204,9 @@ dm9000_open(struct net_device *dev) mii_check_media(&db->mii, netif_msg_link(db), 1); netif_start_queue(dev); @@ -107,7 +107,7 @@ dm9000_schedule_poll(db); return 0; -@@ -1371,6 +1404,7 @@ +@@ -1371,6 +1404,7 @@ dm9000_probe(struct platform_device *pde mutex_init(&db->addr_lock); INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work); diff --git a/target/linux/lantiq/patches-3.0/180-falcon-linux3.0.patch b/target/linux/lantiq/patches-3.0/180-falcon-linux3.0.patch index 6dcfef376a..3dd79640e7 100644 --- a/target/linux/lantiq/patches-3.0/180-falcon-linux3.0.patch +++ b/target/linux/lantiq/patches-3.0/180-falcon-linux3.0.patch @@ -1,6 +1,6 @@ --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c -@@ -51,6 +51,7 @@ +@@ -52,6 +52,7 @@ #define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y)) #define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x)) @@ -8,7 +8,7 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = { LTQ_EIU_IR0, LTQ_EIU_IR1, -@@ -59,6 +60,7 @@ +@@ -60,6 +61,7 @@ static unsigned short ltq_eiu_irq[MAX_EI LTQ_EIU_IR4, LTQ_EIU_IR5, }; @@ -16,7 +16,7 @@ static struct resource ltq_icu_resource = { .name = "icu", -@@ -67,15 +69,19 @@ +@@ -68,15 +70,19 @@ static struct resource ltq_icu_resource .flags = IORESOURCE_MEM, }; @@ -36,7 +36,7 @@ void ltq_disable_irq(struct irq_data *d) { -@@ -120,6 +126,7 @@ +@@ -122,6 +128,7 @@ void ltq_enable_irq(struct irq_data *d) ltq_icu_w32(ltq_icu_r32(ier) | (1 << irq_nr), ier); } @@ -44,7 +44,7 @@ static unsigned int ltq_startup_eiu_irq(struct irq_data *d) { int i; -@@ -159,6 +166,7 @@ +@@ -161,6 +168,7 @@ static void ltq_shutdown_eiu_irq(struct } } } @@ -52,7 +52,7 @@ static struct irq_chip ltq_irq_type = { "icu", -@@ -170,6 +178,7 @@ +@@ -172,6 +180,7 @@ static struct irq_chip ltq_irq_type = { .irq_mask_ack = ltq_mask_and_ack_irq, }; @@ -60,7 +60,7 @@ static struct irq_chip ltq_eiu_type = { "eiu", .irq_startup = ltq_startup_eiu_irq, -@@ -181,6 +190,7 @@ +@@ -183,6 +192,7 @@ static struct irq_chip ltq_eiu_type = { .irq_mask = ltq_disable_irq, .irq_mask_ack = ltq_mask_and_ack_irq, }; @@ -68,7 +68,7 @@ static void ltq_hw_irqdispatch(int module) { -@@ -196,10 +206,12 @@ +@@ -198,10 +208,12 @@ static void ltq_hw_irqdispatch(int modul irq = __fls(irq); do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module)); @@ -81,7 +81,7 @@ } #define DEFINE_HWx_IRQDISPATCH(x) \ -@@ -262,6 +274,7 @@ +@@ -264,6 +276,7 @@ void __init arch_init_irq(void) if (!ltq_icu_membase) panic("Failed to remap icu memory\n"); @@ -89,7 +89,7 @@ if (insert_resource(&iomem_resource, <q_eiu_resource) < 0) panic("Failed to insert eiu memory\n"); -@@ -273,6 +286,7 @@ +@@ -275,6 +288,7 @@ void __init arch_init_irq(void) resource_size(<q_eiu_resource)); if (!ltq_eiu_membase) panic("Failed to remap eiu memory\n"); @@ -97,7 +97,7 @@ /* make sure all irqs are turned off by default */ for (i = 0; i < 5; i++) -@@ -298,6 +312,7 @@ +@@ -300,6 +314,7 @@ void __init arch_init_irq(void) for (i = INT_NUM_IRQ0; i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++) @@ -105,7 +105,7 @@ if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) || (i == LTQ_EIU_IR2)) irq_set_chip_and_handler(i, <q_eiu_type, -@@ -308,6 +323,7 @@ +@@ -310,6 +325,7 @@ void __init arch_init_irq(void) irq_set_chip_and_handler(i, <q_eiu_type, handle_level_irq); else @@ -115,7 +115,7 @@ --- a/arch/mips/lantiq/clk.c +++ b/arch/mips/lantiq/clk.c -@@ -46,6 +46,7 @@ +@@ -46,6 +46,7 @@ static struct clk cpu_clk_generic[] = { }, }; @@ -123,7 +123,7 @@ static struct resource ltq_cgu_resource = { .name = "cgu", .start = LTQ_CGU_BASE_ADDR, -@@ -55,6 +56,7 @@ +@@ -55,6 +56,7 @@ static struct resource ltq_cgu_resource /* remapped clock register range */ void __iomem *ltq_cgu_membase; @@ -131,7 +131,7 @@ void clk_init(void) { -@@ -120,6 +122,7 @@ +@@ -131,6 +133,7 @@ void __init plat_time_init(void) { struct clk *clk; @@ -139,7 +139,7 @@ if (insert_resource(&iomem_resource, <q_cgu_resource) < 0) panic("Failed to insert cgu memory\n"); -@@ -133,6 +136,7 @@ +@@ -144,6 +147,7 @@ void __init plat_time_init(void) pr_err("Failed to remap cgu memory\n"); unreachable(); } diff --git a/target/linux/lantiq/patches-3.0/190-falcon-fix_include.patch b/target/linux/lantiq/patches-3.0/190-falcon-fix_include.patch index 332ba93712..371a94bb5c 100644 --- a/target/linux/lantiq/patches-3.0/190-falcon-fix_include.patch +++ b/target/linux/lantiq/patches-3.0/190-falcon-fix_include.patch @@ -1,6 +1,6 @@ --- /dev/null +++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h -@@ -0,0 +1,40 @@ +@@ -0,0 +1,45 @@ +/* + * 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 @@ -39,5 +39,10 @@ +#define LTQ_WDT_BASE_ADDR 0x1F8803F0 +#define LTQ_WDT_SIZE 0x10 + ++extern int ltq_gpio_request(unsigned int pin, unsigned int alt0, ++ unsigned int alt1, unsigned int dir, ++ const char *name); ++extern int ltq_gpio_mux_set(unsigned int pin, unsigned int mux); ++ +#endif /* CONFIG_SOC_FALCON */ +#endif /* _LTQ_XWAY_H__ */ diff --git a/target/linux/lantiq/patches-3.0/200-netif_receive_skb.patch b/target/linux/lantiq/patches-3.0/200-netif_receive_skb.patch index 7e870e28f9..120266c999 100644 --- a/target/linux/lantiq/patches-3.0/200-netif_receive_skb.patch +++ b/target/linux/lantiq/patches-3.0/200-netif_receive_skb.patch @@ -1,6 +1,6 @@ --- a/drivers/net/lantiq_etop.c +++ b/drivers/net/lantiq_etop.c -@@ -155,8 +155,12 @@ +@@ -147,8 +147,12 @@ ltq_etop_hw_receive(struct ltq_etop_chan skb_put(skb, len); skb->dev = ch->netdev; diff --git a/target/linux/lantiq/patches-3.0/210-mtd_uimage_split.patch b/target/linux/lantiq/patches-3.0/210-mtd_uimage_split.patch index 16173a3d27..6c6a45ac04 100644 --- a/target/linux/lantiq/patches-3.0/210-mtd_uimage_split.patch +++ b/target/linux/lantiq/patches-3.0/210-mtd_uimage_split.patch @@ -1,7 +1,7 @@ --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig -@@ -57,6 +57,10 @@ config MTD_ROOTFS_SPLIT - depends on MTD_PARTITIONS +@@ -41,6 +41,10 @@ config MTD_ROOTFS_SPLIT + bool "Automatically split 'rootfs' partition for squashfs" default y +config MTD_UIMAGE_SPLIT @@ -13,7 +13,7 @@ ---help--- --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c -@@ -860,6 +860,82 @@ static int refresh_rootfs_split(struct m +@@ -861,6 +861,82 @@ static int refresh_rootfs_split(struct m } #endif /* CONFIG_MTD_ROOTFS_SPLIT */ @@ -96,7 +96,7 @@ /* * This function, given a master MTD object and a partition table, creates * and registers slave MTD objects which are bound to the master according to -@@ -893,6 +969,17 @@ int add_mtd_partitions(struct mtd_info * +@@ -894,6 +970,17 @@ int add_mtd_partitions(struct mtd_info * add_mtd_device(&slave->mtd); diff --git a/target/linux/lantiq/patches-3.0/230-cmdline_hack.patch b/target/linux/lantiq/patches-3.0/230-cmdline_hack.patch index 3b8c581763..8ce57ba0aa 100644 --- a/target/linux/lantiq/patches-3.0/230-cmdline_hack.patch +++ b/target/linux/lantiq/patches-3.0/230-cmdline_hack.patch @@ -35,7 +35,7 @@ static void __init prom_init_cmdline(void) { int argc = fw_arg0; -@@ -53,6 +81,7 @@ static void __init prom_init_cmdline(voi +@@ -55,6 +83,7 @@ static void __init prom_init_cmdline(voi strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); } } diff --git a/target/linux/lantiq/patches-3.0/240-udp_redirect.patch b/target/linux/lantiq/patches-3.0/240-udp_redirect.patch index d66ca55cc4..79ecb7c2b2 100644 --- a/target/linux/lantiq/patches-3.0/240-udp_redirect.patch +++ b/target/linux/lantiq/patches-3.0/240-udp_redirect.patch @@ -250,7 +250,7 @@ --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -14,6 +14,9 @@ obj-y := route.o inetpeer.o protocol - inet_fragment.o + inet_fragment.o ping.o obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o +ifneq ($(CONFIG_IFX_UDP_REDIRECT),) @@ -279,9 +279,9 @@ - int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); + int (*getfrag)(void *, char *, int, int, int, struct sk_buff *) = NULL; struct sk_buff *skb; + struct ip_options_data opt_copy; - if (len > 0xFFFF) -@@ -818,7 +822,13 @@ int udp_sendmsg(struct kiocb *iocb, stru +@@ -819,7 +823,13 @@ int udp_sendmsg(struct kiocb *iocb, stru ipc.opt = NULL; ipc.tx_flags = 0; @@ -294,9 +294,9 @@ +#endif /* IFX_UDP_REDIRECT */ + getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; + fl4 = &inet->cork.fl.u.ip4; if (up->pending) { - /* -@@ -1608,6 +1618,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, +@@ -1619,6 +1629,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct rtable *rt = skb_rtable(skb); __be32 saddr, daddr; struct net *net = dev_net(skb->dev); @@ -304,7 +304,7 @@ /* * Validate the packet. -@@ -1640,7 +1651,16 @@ int __udp4_lib_rcv(struct sk_buff *skb, +@@ -1651,7 +1662,16 @@ int __udp4_lib_rcv(struct sk_buff *skb, sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable); if (sk != NULL) { @@ -322,7 +322,7 @@ sock_put(sk); /* a return value > 0 means to resubmit the input, but -@@ -1937,7 +1957,7 @@ struct proto udp_prot = { +@@ -1948,7 +1968,7 @@ struct proto udp_prot = { .clear_sk = sk_prot_clear_portaddr_nulls, }; EXPORT_SYMBOL(udp_prot); diff --git a/target/linux/lantiq/patches-3.0/250-mt-vpe.patch b/target/linux/lantiq/patches-3.0/250-mt-vpe.patch index 6bb38b44ca..4a8e8d5534 100644 --- a/target/linux/lantiq/patches-3.0/250-mt-vpe.patch +++ b/target/linux/lantiq/patches-3.0/250-mt-vpe.patch @@ -1,6 +1,6 @@ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -1871,6 +1871,28 @@ config MIPS_VPE_LOADER +@@ -1905,6 +1905,28 @@ config MIPS_VPE_LOADER Includes a loader for loading an elf relocatable object onto another VPE and running it. @@ -140,7 +140,7 @@ #define read_tc_gpr_sp() mftgpr(29) --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile -@@ -85,7 +85,8 @@ obj-$(CONFIG_MIPS32_O32) += binfmt_elfo3 +@@ -86,7 +86,8 @@ obj-$(CONFIG_MIPS32_O32) += binfmt_elfo3 obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_PROC_FS) += proc.o diff --git a/target/linux/lantiq/patches-3.0/260-ar9-cache-split.patch b/target/linux/lantiq/patches-3.0/260-ar9-cache-split.patch index 254fc61aa3..5ae2d11569 100644 --- a/target/linux/lantiq/patches-3.0/260-ar9-cache-split.patch +++ b/target/linux/lantiq/patches-3.0/260-ar9-cache-split.patch @@ -1,6 +1,6 @@ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -1878,6 +1878,28 @@ config IFX_VPE_EXT +@@ -1912,6 +1912,28 @@ config IFX_VPE_EXT help IFX included extensions in APRP @@ -113,7 +113,7 @@ write_vpe_c0_cause(0); --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c -@@ -1345,6 +1345,106 @@ static int __init setcoherentio(char *st +@@ -1346,6 +1346,106 @@ static int __init setcoherentio(char *st __setup("coherentio", setcoherentio); #endif @@ -220,7 +220,7 @@ void __cpuinit r4k_cache_init(void) { extern void build_clear_page(void); -@@ -1364,6 +1464,78 @@ void __cpuinit r4k_cache_init(void) +@@ -1365,6 +1465,78 @@ void __cpuinit r4k_cache_init(void) break; } diff --git a/target/linux/lantiq/patches-3.0/410-spi2.patch b/target/linux/lantiq/patches-3.0/410-spi2.patch index ee07188ed2..e7909caecd 100644 --- a/target/linux/lantiq/patches-3.0/410-spi2.patch +++ b/target/linux/lantiq/patches-3.0/410-spi2.patch @@ -10,7 +10,7 @@ Signed-off-by: Daniel Schwierzeck --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -193,6 +193,14 @@ +@@ -202,6 +202,14 @@ config SPI_IMX This enables using the Freescale i.MX SPI controllers in master mode. @@ -27,7 +27,7 @@ Signed-off-by: Daniel Schwierzeck depends on PARPORT && EXPERIMENTAL --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile -@@ -26,6 +26,7 @@ +@@ -27,6 +27,7 @@ obj-$(CONFIG_SPI_EP93XX) += ep93xx_spi. obj-$(CONFIG_SPI_GPIO) += spi_gpio.o obj-$(CONFIG_SPI_GPIO_OLD) += spi_gpio_old.o obj-$(CONFIG_SPI_IMX) += spi_imx.o diff --git a/target/linux/lantiq/patches-3.0/420-spi3.patch b/target/linux/lantiq/patches-3.0/420-spi3.patch index 62b68d343e..f4bc661a18 100644 --- a/target/linux/lantiq/patches-3.0/420-spi3.patch +++ b/target/linux/lantiq/patches-3.0/420-spi3.patch @@ -34,7 +34,7 @@ Signed-off-by: Daniel Schwierzeck #include #include -@@ -119,3 +120,41 @@ +@@ -119,3 +120,41 @@ ltq_register_etop(struct ltq_eth_data *e platform_device_register(<q_etop); } } diff --git a/target/linux/lantiq/patches-3.0/440-dwc_otg.patch b/target/linux/lantiq/patches-3.0/440-dwc_otg.patch index b833454705..73222ccacd 100644 --- a/target/linux/lantiq/patches-3.0/440-dwc_otg.patch +++ b/target/linux/lantiq/patches-3.0/440-dwc_otg.patch @@ -1,6 +1,6 @@ --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig -@@ -116,6 +116,8 @@ +@@ -116,6 +116,8 @@ source "drivers/usb/wusbcore/Kconfig" source "drivers/usb/host/Kconfig" @@ -11,7 +11,7 @@ source "drivers/usb/renesas_usbhs/Kconfig" --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile -@@ -28,6 +28,8 @@ +@@ -28,6 +28,8 @@ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ obj-$(CONFIG_USB_WUSB) += wusbcore/ @@ -15615,7 +15615,7 @@ +#endif --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c -@@ -2879,11 +2879,11 @@ +@@ -2885,11 +2885,11 @@ hub_port_init (struct usb_hub *hub, stru udev->ttport = hdev->ttport; } else if (udev->speed != USB_SPEED_HIGH && hdev->speed == USB_SPEED_HIGH) { diff --git a/target/linux/lantiq/patches-3.0/450-mach-arv45xx.patch b/target/linux/lantiq/patches-3.0/450-mach-arv45xx.patch index 711dd76768..a05d1a519c 100644 --- a/target/linux/lantiq/patches-3.0/450-mach-arv45xx.patch +++ b/target/linux/lantiq/patches-3.0/450-mach-arv45xx.patch @@ -1,6 +1,6 @@ --- a/arch/mips/lantiq/xway/Kconfig +++ b/arch/mips/lantiq/xway/Kconfig -@@ -6,6 +6,10 @@ +@@ -6,6 +6,10 @@ config LANTIQ_MACH_EASY50712 bool "Easy50712 - Danube" default y @@ -13,7 +13,7 @@ endif --- a/arch/mips/lantiq/xway/Makefile +++ b/arch/mips/lantiq/xway/Makefile -@@ -5,3 +5,4 @@ +@@ -5,3 +5,4 @@ obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o @@ -518,7 +518,7 @@ + arv752dpw22_init); --- a/arch/mips/lantiq/machtypes.h +++ b/arch/mips/lantiq/machtypes.h -@@ -22,6 +22,17 @@ +@@ -22,6 +22,17 @@ enum lantiq_mach_type { LANTIQ_MACH_EASY98000NAND, /* Falcon Eval Board, NAND Flash */ LANTIQ_MACH_EASY98020, /* Falcon Reference Board */ LANTIQ_MACH_95C3AM1, /* Board 95C3AM1 */ diff --git a/target/linux/lantiq/patches-3.0/460-mach-dgn3500.patch b/target/linux/lantiq/patches-3.0/460-mach-dgn3500.patch index 1d074ec85d..dc904255f2 100644 --- a/target/linux/lantiq/patches-3.0/460-mach-dgn3500.patch +++ b/target/linux/lantiq/patches-3.0/460-mach-dgn3500.patch @@ -1,6 +1,6 @@ --- a/arch/mips/lantiq/machtypes.h +++ b/arch/mips/lantiq/machtypes.h -@@ -33,6 +33,9 @@ +@@ -33,6 +33,9 @@ enum lantiq_mach_type { LANTIQ_MACH_ARV752DPW, /* Arcor easybox a802 */ LANTIQ_MACH_ARV752DPW22, /* Arcor easybox a803 */ LANTIQ_MACH_ARV7518PW, /* ASTORIA */ @@ -12,7 +12,7 @@ #endif --- a/arch/mips/lantiq/xway/Kconfig +++ b/arch/mips/lantiq/xway/Kconfig -@@ -10,6 +10,10 @@ +@@ -10,6 +10,10 @@ config LANTIQ_MACH_ARV45XX bool "ARV45XX" default y @@ -25,7 +25,7 @@ endif --- a/arch/mips/lantiq/xway/Makefile +++ b/arch/mips/lantiq/xway/Makefile -@@ -6,3 +6,4 @@ +@@ -6,3 +6,4 @@ obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o obj-$(CONFIG_LANTIQ_MACH_ARV45XX) += mach-arv45xx.o diff --git a/target/linux/lantiq/patches-3.0/470-mach-gigasx76x.patch b/target/linux/lantiq/patches-3.0/470-mach-gigasx76x.patch index 3cce208ec2..2c55032a62 100644 --- a/target/linux/lantiq/patches-3.0/470-mach-gigasx76x.patch +++ b/target/linux/lantiq/patches-3.0/470-mach-gigasx76x.patch @@ -1,6 +1,6 @@ --- a/arch/mips/lantiq/xway/Kconfig +++ b/arch/mips/lantiq/xway/Kconfig -@@ -14,6 +14,10 @@ +@@ -14,6 +14,10 @@ config LANTIQ_MACH_NETGEAR bool "Netgear" default y @@ -13,7 +13,7 @@ endif --- a/arch/mips/lantiq/xway/Makefile +++ b/arch/mips/lantiq/xway/Makefile -@@ -7,3 +7,4 @@ +@@ -7,3 +7,4 @@ obj-$(CONFIG_LANTIQ_MACH_EASY50712) += m obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o obj-$(CONFIG_LANTIQ_MACH_ARV45XX) += mach-arv45xx.o obj-$(CONFIG_LANTIQ_MACH_NETGEAR) += mach-netgear.o @@ -132,7 +132,7 @@ + gigasx76x_init); --- a/arch/mips/lantiq/machtypes.h +++ b/arch/mips/lantiq/machtypes.h -@@ -36,6 +36,9 @@ +@@ -36,6 +36,9 @@ enum lantiq_mach_type { /* Netgear */ LANTIQ_MACH_DGN3500B, /* Netgear DGN3500 */ diff --git a/target/linux/lantiq/patches-3.0/480-mach-easy98020.patch b/target/linux/lantiq/patches-3.0/480-mach-easy98020.patch new file mode 100644 index 0000000000..46bd9db146 --- /dev/null +++ b/target/linux/lantiq/patches-3.0/480-mach-easy98020.patch @@ -0,0 +1,27 @@ +--- a/arch/mips/lantiq/falcon/mach-easy98020.c ++++ b/arch/mips/lantiq/falcon/mach-easy98020.c +@@ -111,3 +111,13 @@ MIPS_MACHINE(LANTIQ_MACH_EASY98020, + "EASY98020", + "EASY98020 Eval Board", + easy98020_init); ++ ++MIPS_MACHINE(LANTIQ_MACH_EASY98020_1LAN, ++ "EASY98020_1LAN", ++ "EASY98020 Eval Board (1 LAN port)", ++ easy98020_init); ++ ++MIPS_MACHINE(LANTIQ_MACH_EASY98020_2LAN, ++ "EASY98020_2LAN", ++ "EASY98020 Eval Board (2 LAN ports)", ++ easy98020_init); +--- a/arch/mips/lantiq/machtypes.h ++++ b/arch/mips/lantiq/machtypes.h +@@ -21,6 +21,8 @@ enum lantiq_mach_type { + LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial Flash */ + LANTIQ_MACH_EASY98000NAND, /* Falcon Eval Board, NAND Flash */ + LANTIQ_MACH_EASY98020, /* Falcon Reference Board */ ++ LANTIQ_MACH_EASY98020_1LAN, /* Falcon Reference Board (1 LAN port) */ ++ LANTIQ_MACH_EASY98020_2LAN, /* Falcon Reference Board (2 LAN ports) */ + LANTIQ_MACH_95C3AM1, /* Board 95C3AM1 */ + + /* Arcadyan */ diff --git a/target/linux/lantiq/patches-3.0/510-register_madwifi.patch b/target/linux/lantiq/patches-3.0/510-register_madwifi.patch index c09c38d27b..9a8575fa7e 100644 --- a/target/linux/lantiq/patches-3.0/510-register_madwifi.patch +++ b/target/linux/lantiq/patches-3.0/510-register_madwifi.patch @@ -1,6 +1,6 @@ --- a/arch/mips/lantiq/xway/devices.c +++ b/arch/mips/lantiq/xway/devices.c -@@ -121,6 +121,16 @@ +@@ -121,6 +121,16 @@ ltq_register_etop(struct ltq_eth_data *e } } @@ -19,7 +19,7 @@ .start = LTQ_SSC_BASE_ADDR, --- a/arch/mips/lantiq/xway/devices.h +++ b/arch/mips/lantiq/xway/devices.h -@@ -19,5 +19,6 @@ +@@ -19,5 +19,6 @@ extern void ltq_register_ase_asc(void); extern void ltq_register_etop(struct ltq_eth_data *eth); extern void ltq_register_spi(struct ltq_spi_platform_data *pdata, struct spi_board_info const *info, unsigned n); diff --git a/target/linux/lantiq/patches-3.0/520-register_buttons.patch b/target/linux/lantiq/patches-3.0/520-register_buttons.patch index 4674437f81..df48d7cfd9 100644 --- a/target/linux/lantiq/patches-3.0/520-register_buttons.patch +++ b/target/linux/lantiq/patches-3.0/520-register_buttons.patch @@ -1,6 +1,6 @@ --- a/arch/mips/lantiq/xway/devices.c +++ b/arch/mips/lantiq/xway/devices.c -@@ -131,6 +131,26 @@ +@@ -131,6 +131,26 @@ ltq_register_madwifi_eep(void) lantiq_emulate_madwifi_eep = 1; } @@ -37,7 +37,7 @@ extern void ltq_register_gpio(void); extern void ltq_register_gpio_stp(void); -@@ -20,5 +21,6 @@ +@@ -20,5 +21,6 @@ extern void ltq_register_etop(struct ltq extern void ltq_register_spi(struct ltq_spi_platform_data *pdata, struct spi_board_info const *info, unsigned n); extern void ltq_register_madwifi_eep(void); diff --git a/target/linux/lantiq/patches-3.0/530-register_tapi.patch b/target/linux/lantiq/patches-3.0/530-register_tapi.patch index 286c0f0234..e2b0b30649 100644 --- a/target/linux/lantiq/patches-3.0/530-register_tapi.patch +++ b/target/linux/lantiq/patches-3.0/530-register_tapi.patch @@ -1,6 +1,6 @@ --- a/arch/mips/lantiq/devices.c +++ b/arch/mips/lantiq/devices.c -@@ -120,3 +120,20 @@ +@@ -120,3 +120,20 @@ void __init ltq_register_pci(struct ltq_ pr_err("kernel is compiled without PCI support\n"); } #endif @@ -23,7 +23,7 @@ +} --- a/arch/mips/lantiq/devices.h +++ b/arch/mips/lantiq/devices.h -@@ -19,5 +19,6 @@ +@@ -19,5 +19,6 @@ extern void ltq_register_nor(struct phys extern void ltq_register_wdt(void); extern void ltq_register_asc(int port); extern void ltq_register_pci(struct ltq_pci_data *data); @@ -32,7 +32,7 @@ #endif --- a/arch/mips/lantiq/xway/mach-easy50712.c +++ b/arch/mips/lantiq/xway/mach-easy50712.c -@@ -61,6 +61,7 @@ +@@ -61,6 +61,7 @@ static void __init easy50712_init(void) ltq_register_nor(&easy50712_flash_data); ltq_register_pci(<q_pci_data); ltq_register_etop(<q_eth_data); diff --git a/target/linux/lantiq/patches-3.0/550-register_ebu.patch b/target/linux/lantiq/patches-3.0/550-register_ebu.patch index 92057d2059..564c166000 100644 --- a/target/linux/lantiq/patches-3.0/550-register_ebu.patch +++ b/target/linux/lantiq/patches-3.0/550-register_ebu.patch @@ -1,6 +1,6 @@ --- a/arch/mips/lantiq/xway/devices.c +++ b/arch/mips/lantiq/xway/devices.c -@@ -151,6 +151,29 @@ +@@ -151,6 +151,29 @@ ltq_register_gpio_buttons(struct gpio_bu platform_device_register(<q_gpio_buttons_platform_device); } diff --git a/target/linux/lantiq/patches-3.0/998-easy98000-asc1.patch b/target/linux/lantiq/patches-3.0/998-easy98000-asc1.patch new file mode 100644 index 0000000000..6d6aea86ee --- /dev/null +++ b/target/linux/lantiq/patches-3.0/998-easy98000-asc1.patch @@ -0,0 +1,59 @@ +activate serial driver for ASC1 if "use_asc1=x" is given on kernel commandline +mux setup for pins is done via late_initcall, when the gpio driver is initialized + +only implemented for EASY98000, generic version t.b.d. +--- a/arch/mips/lantiq/falcon/devices.c ++++ b/arch/mips/lantiq/falcon/devices.c +@@ -75,6 +75,7 @@ void __init falcon_register_asc(int port + case 1: + platform_device_register_simple("ltq_asc", 1, + falcon_asc1_resources, ARRAY_SIZE(falcon_asc1_resources)); ++ sys1_hw_activate(ACTS_ASC1_ACT); + break; + default: + break; +--- a/arch/mips/lantiq/falcon/mach-easy98000.c ++++ b/arch/mips/lantiq/falcon/mach-easy98000.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include "../machtypes.h" + +@@ -206,9 +207,34 @@ static void __init easy98000_spi_gpio_in + platform_device_register(&easy98000_spi_gpio_device); + } + ++static int register_asc1 = 0; ++static int __init parse_asc1(char *p) ++{ ++ register_asc1 = 1; ++ return 0; ++} ++__setup("use_asc1", parse_asc1); ++ ++#define MUXC_SIF_RX_PIN 112 ++#define MUXC_SIF_TX_PIN 113 ++ ++static int __init asc1_mux_setup(void) ++{ ++ if (register_asc1) { ++ if (ltq_gpio_request(MUXC_SIF_RX_PIN, 1, 1, 0, "asc1-rx")) ++ return -1; ++ if (ltq_gpio_request(MUXC_SIF_TX_PIN, 1, 1, 1, "asc1-tx")) ++ return -1; ++ } ++ return 0; ++} ++late_initcall(asc1_mux_setup); ++ + static void __init easy98000_init_common(void) + { + falcon_register_asc(0); ++ if (register_asc1) ++ falcon_register_asc(1); + falcon_register_gpio(); + falcon_register_wdt(); + falcon_register_i2c(); -- 2.11.0