summaryrefslogtreecommitdiffstats
path: root/target/linux/xburst/files-2.6.32/arch/mips/jz4740
diff options
context:
space:
mode:
authorlars <lars@3c298f89-4303-0410-b956-a3cf2f4a3e73>2010-01-11 04:44:45 +0000
committerlars <lars@3c298f89-4303-0410-b956-a3cf2f4a3e73>2010-01-11 04:44:45 +0000
commit809c03fe4c0f90c640b26e6a2792553b592c68f2 (patch)
tree9f8851bc32dbcd5a39bcb13ecf294dff3902aeab /target/linux/xburst/files-2.6.32/arch/mips/jz4740
parent19682a7752733bc6a45026d69c27575b9b7755fd (diff)
Merge xburst target.
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@19098 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/xburst/files-2.6.32/arch/mips/jz4740')
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/Kconfig35
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/Makefile18
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-n526.c346
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-qi_lb60.c394
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/clock.c795
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/dma.c338
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/gpio.c490
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/irq.c130
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/platform.c246
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/pm.c77
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/prom.c111
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/reset.c50
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/setup.c108
-rw-r--r--target/linux/xburst/files-2.6.32/arch/mips/jz4740/time.c262
14 files changed, 3400 insertions, 0 deletions
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/Kconfig b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/Kconfig
new file mode 100644
index 000000000..015e0560d
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/Kconfig
@@ -0,0 +1,35 @@
+choice
+ prompt "Machine type"
+ depends on MACH_JZ
+ default JZ4740_QI_LB60
+
+config JZ4740_QI_LB60
+ bool "Qi Hardware Ben NanoNote"
+ select DMA_NONCOHERENT
+ select SOC_JZ4740
+
+config JZ4740_N526
+ bool "Hanvon n526 eBook reader"
+ select DMA_NONCOHERENT
+ select SOC_JZ4740
+
+
+endchoice
+
+config SOC_JZ4740
+ bool
+ select JZSOC
+ select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
+ select SYS_HAS_EARLY_PRINTK
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select IRQ_CPU
+
+config JZSOC
+ bool
+ select JZRISC
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_SUPPORTS_32BIT_KERNEL
+
+config JZRISC
+ bool
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/Makefile b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/Makefile
new file mode 100644
index 000000000..19fc95ce5
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Ingenic JZ4740.
+#
+
+# Object file lists.
+
+obj-y += prom.o irq.o time.o reset.o setup.o dma.o \
+ gpio.o clock.o platform.o
+
+# board specific support
+
+obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o
+obj-$(CONFIG_JZ4740_N526) += board-n526.o
+
+# PM support
+
+obj-$(CONFIG_PM) +=pm.o
+
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-n526.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-n526.c
new file mode 100644
index 000000000..fa4627807
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-n526.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
+ * N526 eBook reader 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-jz4740/platform.h>
+
+#include <linux/mtd/jz4740_nand.h>
+#include <linux/jz4740_fb.h>
+#include <linux/power_supply.h>
+#include <linux/power/jz4740-battery.h>
+#include <linux/mmc/jz4740_mmc.h>
+
+#include <video/broadsheetfb.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+
+/* NAND */
+static struct nand_ecclayout n526_ecclayout = {
+ .eccbytes = 36,
+ .eccpos = {
+ 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41},
+ .oobfree = {
+ {.offset = 2,
+ .length = 4},
+ {.offset = 42,
+ .length = 22}}
+};
+
+static struct mtd_partition n526_partitions[] = {
+ { .name = "NAND BOOT partition",
+ .offset = 0 * 0x100000,
+ .size = 4 * 0x100000,
+ },
+ { .name = "NAND KERNEL partition",
+ .offset = 4 * 0x100000,
+ .size = 4 * 0x100000,
+ },
+ { .name = "NAND ROOTFS partition",
+ .offset = 16 * 0x100000,
+ .size = 498 * 0x100000,
+ },
+};
+
+static struct jz_nand_platform_data n526_nand_pdata = {
+ .ecc_layout = &n526_ecclayout,
+ .partitions = n526_partitions,
+ .num_partitions = ARRAY_SIZE(n526_partitions),
+ .busy_gpio = 94,
+};
+
+
+/* Battery */
+/*static struct jz_batt_info n526_battery_pdata = {
+ .dc_dect_gpio = GPIO_DC_DETE_N,
+ .usb_dect_gpio = GPIO_USB_DETE,
+ .charg_stat_gpio = GPIO_CHARG_STAT_N,
+
+ .min_voltag = 3600000,
+ .max_voltag = 4200000,
+ .batt_tech = POWER_SUPPLY_TECHNOLOGY_LIPO,
+};*/
+
+
+static struct jz4740_mmc_platform_data n526_mmc_pdata = {
+ .gpio_card_detect = JZ_GPIO_PORTD(7),
+ .card_detect_active_low = 1,
+ .gpio_read_only = -1,
+ .gpio_power = JZ_GPIO_PORTD(17),
+ .power_active_low = 1,
+};
+
+static struct gpio_led n526_leds[] = {
+ {
+ .name = "n526:blue:power",
+ .gpio = JZ_GPIO_PORTD(28),
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ }
+};
+
+static struct gpio_led_platform_data n526_leds_pdata = {
+ .leds = n526_leds,
+ .num_leds = ARRAY_SIZE(n526_leds),
+};
+
+static struct platform_device n526_leds_device = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &n526_leds_pdata,
+ },
+};
+
+static void __init board_gpio_setup(void)
+{
+ /* We only need to enable/disable pullup here for pins used in generic
+ * drivers. Everything else is done by the drivers themselfs. */
+ jz_gpio_disable_pullup(JZ_GPIO_PORTD(17));
+ jz_gpio_enable_pullup(JZ_GPIO_PORTD(7));
+ jz_gpio_disable_pullup(JZ_GPIO_PORTC(19));
+ jz_gpio_disable_pullup(JZ_GPIO_PORTC(20));
+ jz_gpio_disable_pullup(JZ_GPIO_PORTC(21));
+ jz_gpio_disable_pullup(JZ_GPIO_PORTC(23));
+}
+
+
+static const int n526_eink_ctrl_gpios[] = {
+ 0,
+ JZ_GPIO_PORTC(23),
+ JZ_GPIO_PORTC(19),
+ JZ_GPIO_PORTC(20),
+};
+
+static void n526_eink_set_ctl(struct broadsheetfb_par * par, unsigned char ctrl, u8
+value)
+{
+ gpio_set_value(n526_eink_ctrl_gpios[ctrl], value);
+}
+
+
+static int n526_eink_wait(struct broadsheetfb_par *par)
+{
+ int i = 0;
+ wait_event(par->waitq, gpio_get_value(JZ_GPIO_PORTB(17)));
+
+ return 0;
+}
+
+static u16 n526_eink_get_hdb(struct broadsheetfb_par *par)
+{
+ u16 value = 0;
+ jz_gpio_port_direction_input(JZ_GPIO_PORTC(0), 0xffff);
+ gpio_set_value(JZ_GPIO_PORTC(21), 0);
+ mdelay(100);
+
+ value = jz_gpio_port_get_value(JZ_GPIO_PORTC(0), 0xffff);
+
+ gpio_set_value(JZ_GPIO_PORTC(21), 1);
+ jz_gpio_port_direction_output(JZ_GPIO_PORTC(0), 0xffff);
+ return value;
+}
+
+static void n526_eink_set_hdb(struct broadsheetfb_par *par, u16 value)
+{
+ jz_gpio_port_set_value(JZ_GPIO_PORTC(0), value, 0xffff);
+}
+
+static int n526_eink_init(struct broadsheetfb_par *par)
+{
+ int i = 0;
+
+ gpio_request(JZ_GPIO_PORTD(1), "display reset?");
+ gpio_direction_output(JZ_GPIO_PORTD(1), 1);
+ mdelay(10);
+ gpio_set_value(JZ_GPIO_PORTD(1), 0);
+
+ gpio_request(JZ_GPIO_PORTB(18), "foobar");
+ gpio_direction_output(JZ_GPIO_PORTB(18), 0);
+
+ gpio_request(JZ_GPIO_PORTB(29), "foobar");
+ gpio_direction_output(JZ_GPIO_PORTB(29), 1);
+
+
+ for(i = 1; i < ARRAY_SIZE(n526_eink_ctrl_gpios); ++i) {
+ gpio_request(n526_eink_ctrl_gpios[i], "foobar");
+ gpio_direction_output(n526_eink_ctrl_gpios[i], 0);
+ }
+
+ gpio_request(JZ_GPIO_PORTC(22), "foobar");
+ gpio_direction_input(JZ_GPIO_PORTC(22));
+ gpio_request(JZ_GPIO_PORTC(21), "foobar");
+ gpio_direction_output(JZ_GPIO_PORTC(21), 1);
+
+ for(i = 0; i < 16; ++i) {
+ gpio_request(JZ_GPIO_PORTC(i), "display data");
+ }
+ jz_gpio_port_direction_output(JZ_GPIO_PORTC(0), 0xffff);
+
+ gpio_direction_output(JZ_GPIO_PORTB(18), 1);
+
+ return 0;
+}
+
+static irqreturn_t n526_eink_busy_irq(int irq, void *devid)
+{
+ struct broadsheetfb_par *par = devid;
+ wake_up(&par->waitq);
+
+ return IRQ_HANDLED;
+}
+
+static int n526_eink_setup_irq(struct fb_info *info)
+{
+ int ret;
+ struct broadsheetfb_par *par = info->par;
+
+ gpio_request(JZ_GPIO_PORTB(17), "foobar");
+ gpio_direction_input(JZ_GPIO_PORTB(17));
+
+ ret = request_irq(gpio_to_irq(JZ_GPIO_PORTB(17)), n526_eink_busy_irq,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING,
+ "eInk busyline", par);
+ if (ret)
+ printk("n526 display: Failed to request busyline irq: %d\n", ret);
+ return 0;
+}
+
+static void n526_eink_cleanup(struct broadsheetfb_par *par)
+{
+}
+
+static struct broadsheet_board broadsheet_pdata = {
+ .owner = THIS_MODULE,
+ .init = n526_eink_init,
+ .wait_for_rdy = n526_eink_wait,
+ .set_ctl = n526_eink_set_ctl,
+ .set_hdb = n526_eink_set_hdb,
+ .get_hdb = n526_eink_get_hdb,
+ .cleanup = n526_eink_cleanup,
+ .setup_irq = n526_eink_setup_irq,
+};
+
+static struct platform_device n526_broadsheet_device = {
+ .name = "broadsheetfb",
+ .id = -1,
+ .dev = {
+ .platform_data = &broadsheet_pdata,
+ },
+};
+
+static struct gpio_keys_button qi_lb60_gpio_keys_buttons[] = {
+ [0] = {
+ .code = KEY_ENTER,
+ .gpio = 0,
+ .active_low = 1,
+ .desc = "Power",
+ },
+};
+
+static struct gpio_keys_platform_data qi_lb60_gpio_keys_data = {
+ .nbuttons = ARRAY_SIZE(qi_lb60_gpio_keys_buttons),
+ .buttons = qi_lb60_gpio_keys_buttons,
+};
+
+static struct platform_device qi_lb60_gpio_keys = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &qi_lb60_gpio_keys_data,
+ }
+};
+
+static struct i2c_gpio_platform_data n526_i2c_pdata = {
+ .sda_pin = JZ_GPIO_PORTD(23),
+ .scl_pin = JZ_GPIO_PORTD(24),
+ .udelay = 2,
+ .timeout = 3 * HZ,
+};
+
+static struct platform_device n526_i2c_device = {
+ .name = "i2c-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &n526_i2c_pdata,
+ },
+};
+
+static struct i2c_board_info n526_i2c_board_info = {
+ .type = "n526-lpc",
+ .addr = 0x54,
+};
+
+
+static struct platform_device *jz_platform_devices[] __initdata = {
+ &jz4740_usb_ohci_device,
+ &jz4740_usb_gdt_device,
+ &jz4740_mmc_device,
+ &jz4740_nand_device,
+ &jz4740_i2s_device,
+ &jz4740_codec_device,
+ &jz4740_rtc_device,
+ &n526_leds_device,
+ &n526_broadsheet_device,
+ &qi_lb60_gpio_keys,
+ &n526_i2c_device,
+};
+
+
+static int __init n526_init_platform_devices(void)
+{
+
+ jz4740_nand_device.dev.platform_data = &n526_nand_pdata;
+/* jz4740_battery_device.dev.platform_data = &n526_battery_pdata;*/
+ jz4740_mmc_device.dev.platform_data = &n526_mmc_pdata;
+
+ n526_i2c_board_info.irq = gpio_to_irq(JZ_GPIO_PORTD(14)),
+ i2c_register_board_info(0, &n526_i2c_board_info, 1);
+
+ return platform_add_devices(jz_platform_devices,
+ ARRAY_SIZE(jz_platform_devices));
+
+}
+
+
+extern int jz_gpiolib_init(void);
+extern int jz_init_clocks(unsigned long extal);
+
+static int __init n526_board_setup(void)
+{
+ if (jz_gpiolib_init())
+ panic("Failed to initalize jz gpio\n");
+ jz_init_clocks(12000000);
+
+ board_gpio_setup();
+
+ if (n526_init_platform_devices())
+ panic("Failed to initalize platform devices\n");
+
+ return 0;
+}
+
+arch_initcall(n526_board_setup);
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-qi_lb60.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-qi_lb60.c
new file mode 100644
index 000000000..5d22e2037
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-qi_lb60.c
@@ -0,0 +1,394 @@
+/*
+ * linux/arch/mips/jz4740/board-qi_lb60.c
+ *
+ * QI_LB60 setup routines.
+ *
+ * Copyright (c) 2009 Qi Hardware inc.,
+ * Author: Xiangfu Liu <xiangfu@qi-hardware.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or later
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-jz4740/board-qi_lb60.h>
+#include <asm/mach-jz4740/platform.h>
+
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/mtd/jz4740_nand.h>
+#include <linux/jz4740_fb.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/mtd/jz4740_nand.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/power_supply.h>
+#include <linux/power/jz4740-battery.h>
+#include <linux/mmc/jz4740_mmc.h>
+
+
+/* NAND */
+static struct nand_ecclayout qi_lb60_ecclayout_1gb = {
+ .eccbytes = 36,
+ .eccpos = {
+ 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41},
+ .oobfree = {
+ {.offset = 2,
+ .length = 4},
+ {.offset = 42,
+ .length = 22}}
+};
+
+static struct mtd_partition qi_lb60_partitions_1gb[] = {
+ { .name = "NAND BOOT partition",
+ .offset = 0 * 0x100000,
+ .size = 4 * 0x100000,
+ },
+ { .name = "NAND KERNEL partition",
+ .offset = 4 * 0x100000,
+ .size = 4 * 0x100000,
+ },
+ { .name = "NAND ROOTFS partition",
+ .offset = 8 * 0x100000,
+ .size = (504 + 512) * 0x100000,
+ },
+};
+
+static struct nand_ecclayout qi_lb60_ecclayout_2gb = {
+ .eccbytes = 72,
+ .eccpos = {
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 82, 83},
+ .oobfree = {
+ {.offset = 2,
+ .length = 10},
+ {.offset = 84,
+ .length = 44}}
+};
+
+static struct mtd_partition qi_lb60_partitions_2gb[] = {
+ { .name = "NAND BOOT partition",
+ .offset = 0 * 0x100000,
+ .size = 4 * 0x100000,
+ },
+ { .name = "NAND KERNEL partition",
+ .offset = 4 * 0x100000,
+ .size = 4 * 0x100000,
+ },
+ { .name = "NAND ROOTFS partition",
+ .offset = 8 * 0x100000,
+ .size = (504 + 512 + 1024) * 0x100000,
+ },
+};
+
+static void qi_lb60_nand_ident(struct platform_device *pdev,
+ struct nand_chip *chip,
+ struct mtd_partition **partitions,
+ int *num_partitions)
+{
+ if (chip->page_shift == 12) {
+ chip->ecc.layout = &qi_lb60_ecclayout_2gb;
+ *partitions = qi_lb60_partitions_2gb;
+ *num_partitions = ARRAY_SIZE(qi_lb60_partitions_2gb);
+ } else {
+ chip->ecc.layout = &qi_lb60_ecclayout_1gb;
+ *partitions = qi_lb60_partitions_1gb;
+ *num_partitions = ARRAY_SIZE(qi_lb60_partitions_1gb);
+ }
+}
+
+static struct jz_nand_platform_data qi_lb60_nand_pdata = {
+ .ident_callback = qi_lb60_nand_ident,
+ .busy_gpio = 94,
+};
+
+
+/* Keyboard*/
+
+/* #define KEEP_UART_ALIVE
+ * don't define this. the keyboard and keyboard both work
+ */
+
+#define KEY_QI_QI KEY_F13
+#define KEY_QI_UPRED KEY_RIGHTALT
+#define KEY_QI_VOLUP KEY_VOLUMEUP
+#define KEY_QI_VOLDOWN KEY_VOLUMEDOWN
+#define KEY_QI_FN KEY_LEFTCTRL
+
+static const uint32_t qi_lb60_keymap[] = {
+ KEY(0, 0, KEY_F1), /* S2 */
+ KEY(0, 1, KEY_F2), /* S3 */
+ KEY(0, 2, KEY_F3), /* S4 */
+ KEY(0, 3, KEY_F4), /* S5 */
+ KEY(0, 4, KEY_F5), /* S6 */
+ KEY(0, 5, KEY_F6), /* S7 */
+ KEY(0, 6, KEY_F7), /* S8 */
+
+ KEY(1, 0, KEY_Q), /* S10 */
+ KEY(1, 1, KEY_W), /* S11 */
+ KEY(1, 2, KEY_E), /* S12 */
+ KEY(1, 3, KEY_R), /* S13 */
+ KEY(1, 4, KEY_T), /* S14 */
+ KEY(1, 5, KEY_Y), /* S15 */
+ KEY(1, 6, KEY_U), /* S16 */
+ KEY(1, 7, KEY_I), /* S17 */
+ KEY(2, 0, KEY_A), /* S18 */
+ KEY(2, 1, KEY_S), /* S19 */
+ KEY(2, 2, KEY_D), /* S20 */
+ KEY(2, 3, KEY_F), /* S21 */
+ KEY(2, 4, KEY_G), /* S22 */
+ KEY(2, 5, KEY_H), /* S23 */
+ KEY(2, 6, KEY_J), /* S24 */
+ KEY(2, 7, KEY_K), /* S25 */
+ KEY(3, 0, KEY_ESC), /* S26 */
+ KEY(3, 1, KEY_Z), /* S27 */
+ KEY(3, 2, KEY_X), /* S28 */
+ KEY(3, 3, KEY_C), /* S29 */
+ KEY(3, 4, KEY_V), /* S30 */
+ KEY(3, 5, KEY_B), /* S31 */
+ KEY(3, 6, KEY_N), /* S32 */
+ KEY(3, 7, KEY_M), /* S33 */
+ KEY(4, 0, KEY_TAB), /* S34 */
+ KEY(4, 1, KEY_CAPSLOCK), /* S35 */
+ KEY(4, 2, KEY_BACKSLASH), /* S36 */
+ KEY(4, 3, KEY_APOSTROPHE), /* S37 */
+ KEY(4, 4, KEY_COMMA), /* S38 */
+ KEY(4, 5, KEY_DOT), /* S39 */
+ KEY(4, 6, KEY_SLASH), /* S40 */
+ KEY(4, 7, KEY_UP), /* S41 */
+ KEY(5, 0, KEY_O), /* S42 */
+ KEY(5, 1, KEY_L), /* S43 */
+ KEY(5, 2, KEY_EQUAL), /* S44 */
+ KEY(5, 3, KEY_QI_UPRED), /* S45 */
+ KEY(5, 4, KEY_SPACE), /* S46 */
+ KEY(5, 5, KEY_QI_QI), /* S47 */
+ KEY(5, 6, KEY_RIGHTCTRL), /* S48 */
+ KEY(5, 7, KEY_LEFT), /* S49 */
+ KEY(6, 0, KEY_F8), /* S50 */
+ KEY(6, 1, KEY_P), /* S51 */
+ KEY(6, 2, KEY_BACKSPACE),/* S52 */
+ KEY(6, 3, KEY_ENTER), /* S53 */
+ KEY(6, 4, KEY_QI_VOLUP), /* S54 */
+ KEY(6, 5, KEY_QI_VOLDOWN), /* S55 */
+ KEY(6, 6, KEY_DOWN), /* S56 */
+ KEY(6, 7, KEY_RIGHT), /* S57 */
+
+#ifndef KEEP_UART_ALIVE
+ KEY(7, 0, KEY_LEFTSHIFT), /* S58 */
+ KEY(7, 1, KEY_LEFTALT), /* S59 */
+ KEY(7, 2, KEY_QI_FN), /* S60 */
+#endif
+};
+
+static const struct matrix_keymap_data qi_lb60_keymap_data = {
+ .keymap = qi_lb60_keymap,
+ .keymap_size = ARRAY_SIZE(qi_lb60_keymap),
+};
+
+static const unsigned int qi_lb60_keypad_cols[] = {
+ 74, 75, 76, 77, 78, 79, 80, 81,
+};
+
+static const unsigned int qi_lb60_keypad_rows[] = {
+ 114, 115, 116, 117, 118, 119, 120,
+#ifndef KEEP_UART_ALIVE
+ 122,
+#endif
+};
+
+static struct matrix_keypad_platform_data qi_lb60_pdata = {
+ .keymap_data = &qi_lb60_keymap_data,
+ .col_gpios = qi_lb60_keypad_cols,
+ .row_gpios = qi_lb60_keypad_rows,
+ .num_col_gpios = ARRAY_SIZE(qi_lb60_keypad_cols),
+ .num_row_gpios = ARRAY_SIZE(qi_lb60_keypad_rows),
+ .col_scan_delay_us = 10,
+ .debounce_ms = 10,
+ .wakeup = 1,
+ .active_low = 1,
+};
+
+static struct platform_device qi_lb60_keypad = {
+ .name = "matrix-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &qi_lb60_pdata,
+ },
+};
+
+/* Display */
+static struct fb_videomode qi_lb60_video_modes[] = {
+ {
+ .name = "320x240",
+ .xres = 320,
+ .yres = 240,
+ .pixclock = 700000,
+ .left_margin = 140,
+ .right_margin = 273,
+ .upper_margin = 20,
+ .lower_margin = 2,
+ .hsync_len = 1,
+ .vsync_len = 1,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+};
+
+static struct jz4740_fb_platform_data qi_lb60_fb_pdata = {
+ .width = 60,
+ .height = 45,
+ .num_modes = ARRAY_SIZE(qi_lb60_video_modes),
+ .modes = qi_lb60_video_modes,
+ .bpp = 24,
+ .lcd_type = JZ_LCD_TYPE_8BIT_SERIAL,
+};
+
+
+struct spi_gpio_platform_data spigpio_platform_data = {
+ .sck = JZ_GPIO_PORTC(23),
+ .mosi = JZ_GPIO_PORTC(22),
+ .miso = JZ_GPIO_PORTC(22),
+ .num_chipselect = 1,
+};
+
+static struct platform_device spigpio_device = {
+ .name = "spi_gpio",
+ .id = 1,
+ .dev = {
+ .platform_data = &spigpio_platform_data,
+ },
+};
+
+static struct spi_board_info qi_lb60_spi_board_info[] = {
+ {
+ .modalias = "gpm940b0",
+ .controller_data = (void*)JZ_GPIO_PORTC(21),
+ .chip_select = 0,
+ .bus_num = 1,
+ .max_speed_hz = 30 * 1000,
+ },
+};
+
+/* Battery */
+static struct jz_batt_info qi_lb60_battery_pdata = {
+ .dc_dect_gpio = GPIO_DC_DETE_N,
+ .usb_dect_gpio = GPIO_USB_DETE,
+ .charg_stat_gpio = GPIO_CHARG_STAT_N,
+
+ .min_voltag = 3600000,
+ .max_voltag = 4200000,
+ .batt_tech = POWER_SUPPLY_TECHNOLOGY_LIPO,
+};
+
+/* GPIO Key: power */
+static struct gpio_keys_button qi_lb60_gpio_keys_buttons[] = {
+ [0] = {
+ .code = KEY_POWER,
+ .gpio = GPIO_WAKEUP_N,
+ .active_low = 1,
+ .desc = "Power",
+ .wakeup = 1,
+ },
+};
+
+static struct gpio_keys_platform_data qi_lb60_gpio_keys_data = {
+ .nbuttons = ARRAY_SIZE(qi_lb60_gpio_keys_buttons),
+ .buttons = qi_lb60_gpio_keys_buttons,
+};
+
+static struct platform_device qi_lb60_gpio_keys = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &qi_lb60_gpio_keys_data,
+ }
+};
+
+static struct jz4740_mmc_platform_data qi_lb60_mmc_pdata = {
+ .gpio_card_detect = JZ_GPIO_PORTD(0),
+ .gpio_read_only = -1,
+ .gpio_power = JZ_GPIO_PORTD(2),
+ .power_active_low = 1,
+};
+
+static struct platform_device *jz_platform_devices[] __initdata = {
+ &jz4740_usb_ohci_device,
+ &jz4740_usb_gdt_device,
+ &jz4740_mmc_device,
+ &jz4740_nand_device,
+ &qi_lb60_keypad,
+ &spigpio_device,
+ &jz4740_framebuffer_device,
+ &jz4740_i2s_device,
+ &jz4740_codec_device,
+ &jz4740_rtc_device,
+ &jz4740_adc_device,
+ &jz4740_battery_device,
+ &qi_lb60_gpio_keys,
+};
+
+static void __init board_gpio_setup(void)
+{
+ /* We only need to enable/disable pullup here for pins used in generic
+ * drivers. Everything else is done by the drivers themselfs. */
+ jz_gpio_disable_pullup(GPIO_SD_VCC_EN_N);
+ jz_gpio_disable_pullup(GPIO_SD_CD_N);
+}
+
+static int __init qi_lb60_init_platform_devices(void)
+{
+ jz4740_framebuffer_device.dev.platform_data = &qi_lb60_fb_pdata;
+ jz4740_nand_device.dev.platform_data = &qi_lb60_nand_pdata;
+ jz4740_battery_device.dev.platform_data = &qi_lb60_battery_pdata;
+ jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata;
+
+ spi_register_board_info(qi_lb60_spi_board_info,
+ ARRAY_SIZE(qi_lb60_spi_board_info));
+
+ return platform_add_devices(jz_platform_devices,
+ ARRAY_SIZE(jz_platform_devices));
+
+}
+extern int jz_gpiolib_init(void);
+extern int jz_init_clocks(unsigned long extal);
+
+static __init int board_avt2(char *str)
+{
+ qi_lb60_mmc_pdata.card_detect_active_low = 1;
+
+ return 1;
+}
+
+__setup("avt2", board_avt2);
+
+static int __init qi_lb60_board_setup(void)
+{
+ printk("Qi Hardware JZ4740 QI_LB60 setup\n");
+ if (jz_gpiolib_init())
+ panic("Failed to initalize jz gpio\n");
+ jz_init_clocks(12000000);
+
+ board_gpio_setup();
+
+ if (qi_lb60_init_platform_devices())
+ panic("Failed to initalize platform devices\n");
+
+ return 0;
+}
+
+arch_initcall(qi_lb60_board_setup);
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/clock.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/clock.c
new file mode 100644
index 000000000..853c6d867
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/clock.c
@@ -0,0 +1,795 @@
+/*
+ * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4740 SoC TCU 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/err.h>
+
+#define JZ_REG_CLOCK_CTRL 0x00
+#define JZ_REG_CLOCK_PLL 0x10
+#define JZ_REG_CLOCK_GATE 0x20
+#define JZ_REG_CLOCK_I2S 0x60
+#define JZ_REG_CLOCK_LCD 0x64
+#define JZ_REG_CLOCK_MMC 0x68
+#define JZ_REG_CLOCK_UHC 0x6C
+#define JZ_REG_CLOCK_SPI 0x74
+
+#define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31)
+#define JZ_CLOCK_CTRL_KO_ENABLE BIT(30)
+#define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29)
+#define JZ_CLOCK_CTRL_UDIV_MASK 0x1f800000
+#define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22)
+#define JZ_CLOCK_CTRL_PLL_HALF BIT(21)
+#define JZ_CLOCK_CTRL_LDIV_MASK 0x001f0000
+#define JZ_CLOCK_CTRL_UDIV_OFFSET 23
+#define JZ_CLOCK_CTRL_LDIV_OFFSET 16
+#define JZ_CLOCK_CTRL_MDIV_OFFSET 12
+#define JZ_CLOCK_CTRL_PDIV_OFFSET 8
+#define JZ_CLOCK_CTRL_HDIV_OFFSET 4
+#define JZ_CLOCK_CTRL_CDIV_OFFSET 0
+
+#define JZ_CLOCK_GATE_UART0 BIT(0)
+#define JZ_CLOCK_GATE_TCU BIT(1)
+#define JZ_CLOCK_GATE_RTC BIT(2)
+#define JZ_CLOCK_GATE_I2C BIT(3)
+#define JZ_CLOCK_GATE_SPI BIT(4)
+#define JZ_CLOCK_GATE_AIC_PCLK BIT(5)
+#define JZ_CLOCK_GATE_AIC BIT(6)
+#define JZ_CLOCK_GATE_MMC BIT(7)
+#define JZ_CLOCK_GATE_ADC BIT(8)
+#define JZ_CLOCK_GATE_CIM BIT(9)
+#define JZ_CLOCK_GATE_LCD BIT(10)
+#define JZ_CLOCK_GATE_UDC BIT(11)
+#define JZ_CLOCK_GATE_DMAC BIT(12)
+#define JZ_CLOCK_GATE_IPU BIT(13)
+#define JZ_CLOCK_GATE_UHC BIT(14)
+#define JZ_CLOCK_GATE_UART1 BIT(15)
+
+#define JZ_CLOCK_I2S_DIV_MASK 0x01ff
+
+#define JZ_CLOCK_LCD_DIV_MASK 0x01ff
+
+#define JZ_CLOCK_MMC_DIV_MASK 0x001f
+
+#define JZ_CLOCK_UHC_DIV_MASK 0x000f
+
+#define JZ_CLOCK_SPI_SRC_PLL BIT(31)
+#define JZ_CLOCK_SPI_DIV_MASK 0x000f
+
+#define JZ_CLOCK_PLL_M_MASK 0x01ff
+#define JZ_CLOCK_PLL_N_MASK 0x001f
+#define JZ_CLOCK_PLL_OD_MASK 0x0003
+#define JZ_CLOCK_PLL_STABLE BIT(10)
+#define JZ_CLOCK_PLL_BYPASS BIT(9)
+#define JZ_CLOCK_PLL_ENABLED BIT(8)
+#define JZ_CLOCK_PLL_STABLIZE_MASK 0x000f
+#define JZ_CLOCK_PLL_M_OFFSET 23
+#define JZ_CLOCK_PLL_N_OFFSET 18
+#define JZ_CLOCK_PLL_OD_OFFSET 16
+
+static void __iomem *jz_clock_base;
+static spinlock_t jz_clock_lock;
+static LIST_HEAD(jz_clocks);
+
+struct clk {
+ const char *name;
+ struct clk* parent;
+
+ uint32_t gate_bit;
+
+ unsigned long (*get_rate)(struct clk* clk);
+ unsigned long (*round_rate)(struct clk *clk, unsigned long rate);
+ int (*set_rate)(struct clk* clk, unsigned long rate);
+ int (*enable)(struct clk* clk);
+ int (*disable)(struct clk* clk);
+
+ int (*set_parent)(struct clk* clk, struct clk *parent);
+ struct list_head list;
+};
+
+struct main_clk {
+ struct clk clk;
+ uint32_t div_offset;
+};
+
+struct divided_clk {
+ struct clk clk;
+ uint32_t reg;
+ uint32_t mask;
+};
+
+struct static_clk {
+ struct clk clk;
+ unsigned long rate;
+};
+
+static uint32_t jz_clk_reg_read(int reg)
+{
+ return readl(jz_clock_base + reg);
+}
+
+static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask)
+{
+ uint32_t val2;
+
+ spin_lock(&jz_clock_lock);
+ val2 = readl(jz_clock_base + reg);
+ val2 &= ~mask;
+ val2 |= val;
+ writel(val2, jz_clock_base + reg);
+ spin_unlock(&jz_clock_lock);
+}
+
+static void jz_clk_reg_set_bits(int reg, uint32_t mask)
+{
+ uint32_t val;
+
+ spin_lock(&jz_clock_lock);
+ val = readl(jz_clock_base + reg);
+ val |= mask;
+ writel(val, jz_clock_base + reg);
+ spin_unlock(&jz_clock_lock);
+}
+
+static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
+{
+ uint32_t val;
+
+ spin_lock(&jz_clock_lock);
+ val = readl(jz_clock_base + reg);
+ val &= ~mask;
+ writel(val, jz_clock_base + reg);
+ spin_unlock(&jz_clock_lock);
+}
+
+static int jz_clk_enable_gating(struct clk *clk)
+{
+ jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
+ return 0;
+}
+
+static int jz_clk_disable_gating(struct clk *clk)
+{
+ jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
+ return 0;
+}
+
+static unsigned long jz_clk_static_get_rate(struct clk *clk)
+{
+ return ((struct static_clk*)clk)->rate;
+}
+
+static int jz_clk_ko_enable(struct clk* clk)
+{
+ jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
+ return 0;
+}
+
+static int jz_clk_ko_disable(struct clk* clk)
+{
+ jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
+ return 0;
+}
+
+
+static const int pllno[] = {1, 2, 2, 4};
+
+static unsigned long jz_clk_pll_get_rate(struct clk *clk)
+{
+ uint32_t val;
+ int m;
+ int n;
+ int od;
+
+ val = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
+
+ if (val & JZ_CLOCK_PLL_BYPASS)
+ return clk_get_rate(clk->parent);
+
+ m = ((val >> 23) & 0x1ff) + 2;
+ n = ((val >> 18) & 0x1f) + 2;
+ od = (val >> 16) & 0x3;
+
+ return clk_get_rate(clk->parent) * (m / n) / pllno[od];
+}
+
+static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
+{
+ uint32_t reg;
+
+ reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
+ if (reg & JZ_CLOCK_CTRL_PLL_HALF)
+ return jz_clk_pll_get_rate(clk->parent);
+ return jz_clk_pll_get_rate(clk->parent) >> 1;
+}
+
+
+
+static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+
+static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
+ int div;
+
+ div = parent_rate / rate;
+ if (div > 32)
+ return parent_rate / 32;
+ else if (div < 1)
+ return parent_rate;
+
+ div &= (0x3 << (ffs(div) - 1));
+
+ return parent_rate / div;
+}
+
+static unsigned long jz_clk_main_get_rate(struct clk *clk) {
+ struct main_clk *mclk = (struct main_clk*)clk;
+ uint32_t div;
+
+ div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
+
+ div >>= mclk->div_offset;
+ div &= 0xf;
+
+ if (div >= ARRAY_SIZE(jz_clk_main_divs))
+ div = ARRAY_SIZE(jz_clk_main_divs) - 1;
+
+ return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div];
+}
+
+static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct main_clk *mclk = (struct main_clk*)clk;
+ int i;
+ int div;
+ unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
+
+ rate = jz_clk_main_round_rate(clk, rate);
+
+ div = parent_rate / rate;
+
+ i = (ffs(div) - 1) << 1;
+ if (i > 0 && !(div & BIT(i-1)))
+ i -= 1;
+
+ jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset,
+ 0xf << mclk->div_offset);
+
+ return 0;
+}
+
+
+static struct static_clk jz_clk_ext = {
+ .clk = {
+ .name = "ext",
+ .get_rate = jz_clk_static_get_rate,
+ },
+};
+
+static struct clk jz_clk_pll = {
+ .name = "pll",
+ .parent = &jz_clk_ext.clk,
+ .get_rate = jz_clk_pll_get_rate,
+};
+
+static struct clk jz_clk_pll_half = {
+ .name = "pll half",
+ .parent = &jz_clk_pll,
+ .get_rate = jz_clk_pll_half_get_rate,
+};
+
+static struct main_clk jz_clk_cpu = {
+ .clk = {
+ .name = "cclk",
+ .parent = &jz_clk_pll,
+ .get_rate = jz_clk_main_get_rate,
+ .set_rate = jz_clk_main_set_rate,
+ .round_rate = jz_clk_main_round_rate,
+ },
+ .div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET,
+};
+
+static struct main_clk jz_clk_memory = {
+ .clk = {
+ .name = "mclk",
+ .parent = &jz_clk_pll,
+ .get_rate = jz_clk_main_get_rate,
+ .set_rate = jz_clk_main_set_rate,
+ .round_rate = jz_clk_main_round_rate,
+ },
+ .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET,
+};
+
+static struct main_clk jz_clk_high_speed_peripheral = {
+ .clk = {
+ .name = "hclk",
+ .parent = &jz_clk_pll,
+ .get_rate = jz_clk_main_get_rate,
+ .set_rate = jz_clk_main_set_rate,
+ .round_rate = jz_clk_main_round_rate,
+ },
+ .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET,
+};
+
+
+static struct main_clk jz_clk_low_speed_peripheral = {
+ .clk = {
+ .name = "pclk",
+ .parent = &jz_clk_pll,
+ .get_rate = jz_clk_main_get_rate,
+ .set_rate = jz_clk_main_set_rate,
+ },
+ .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET,
+};
+
+static struct clk jz_clk_ko = {
+ .name = "cko",
+ .parent = &jz_clk_memory.clk,
+ .enable = jz_clk_ko_enable,
+ .disable = jz_clk_ko_disable,
+};
+
+static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent)
+{
+ if (parent == &jz_clk_pll)
+ jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
+ else if(parent == &jz_clk_ext.clk)
+ jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
+ else
+ return -EINVAL;
+
+ clk->parent = parent;
+
+ return 0;
+}
+
+static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent)
+{
+ if (parent == &jz_clk_pll_half)
+ jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
+ else if(parent == &jz_clk_ext.clk)
+ jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
+ else
+ return -EINVAL;
+
+ clk->parent = parent;
+
+ return 0;
+}
+
+static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent)
+{
+ if (parent == &jz_clk_pll_half)
+ jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
+ else if(parent == &jz_clk_ext.clk)
+ jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
+ else
+ return -EINVAL;
+
+ clk->parent = parent;
+
+ return 0;
+}
+
+static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate)
+{
+ int div;
+
+ if (clk->parent == &jz_clk_ext.clk)
+ return -EINVAL;
+
+ div = clk_get_rate(clk->parent) / rate - 1;
+
+ if (div < 0)
+ div = 0;
+ else if (div > 63)
+ div = 63;
+
+ jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET,
+ JZ_CLOCK_CTRL_UDIV_MASK);
+ return 0;
+}
+
+static unsigned long jz_clk_udc_get_rate(struct clk *clk)
+{
+ int div;
+
+ if (clk->parent == &jz_clk_ext.clk)
+ return clk_get_rate(clk->parent);
+
+ div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK);
+ div >>= JZ_CLOCK_CTRL_UDIV_OFFSET;
+ div += 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static unsigned long jz_clk_divided_get_rate(struct clk *clk)
+{
+ struct divided_clk *dclk = (struct divided_clk*)clk;
+ int div;
+
+ if (clk->parent == &jz_clk_ext.clk)
+ return clk_get_rate(clk->parent);
+
+ div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct divided_clk *dclk = (struct divided_clk*)clk;
+ int div;
+
+ if (clk->parent == &jz_clk_ext.clk)
+ return -EINVAL;
+
+ div = clk_get_rate(clk->parent) / rate - 1;
+
+ if (div < 0)
+ div = 0;
+ else if(div > dclk->mask)
+ div = dclk->mask;
+
+ jz_clk_reg_write_mask(dclk->reg, div, dclk->mask);
+
+ return 0;
+}
+
+static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate)
+{
+ int div;
+ unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent);
+
+ if (rate > 150000000)
+ return 150000000;
+
+ div = parent_rate / rate;
+ if (div < 1)
+ div = 1;
+ else if(div > 32)
+ div = 32;
+
+ return parent_rate / div;
+}
+
+static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int div;
+
+ if (rate > 150000000)
+ return -EINVAL;
+
+ div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1;
+ if (div < 0)
+ div = 0;
+ else if(div > 31)
+ div = 31;
+
+ jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET,
+ JZ_CLOCK_CTRL_LDIV_MASK);
+
+ return 0;
+}
+
+static unsigned long jz_clk_ldclk_get_rate(struct clk *clk)
+{
+ int div;
+
+ div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK;
+ div >>= JZ_CLOCK_CTRL_LDIV_OFFSET;
+
+ return jz_clk_pll_half_get_rate(clk->parent) / (div + 1);
+}
+
+static struct clk jz_clk_ld = {
+ .name = "lcd",
+ .parent = &jz_clk_pll_half,
+ .set_rate = jz_clk_ldclk_set_rate,
+ .get_rate = jz_clk_ldclk_get_rate,
+ .round_rate = jz_clk_ldclk_round_rate,
+};
+
+static struct divided_clk jz_clk_lp = {
+ .clk = {
+ .name = "lcd_pclk",
+ .parent = &jz_clk_pll_half,
+ },
+ .reg = JZ_REG_CLOCK_LCD,
+ .mask = JZ_CLOCK_LCD_DIV_MASK,
+};
+
+static struct clk jz_clk_cim_mclk = {
+ .name = "cim_mclk",
+ .parent = &jz_clk_high_speed_peripheral.clk,
+};
+
+static struct static_clk jz_clk_cim_pclk = {
+ .clk = {
+ .name = "cim_pclk",
+ .gate_bit = JZ_CLOCK_GATE_CIM,
+ .get_rate = jz_clk_static_get_rate,
+ .enable = jz_clk_enable_gating,
+ .disable = jz_clk_disable_gating,
+ },
+};
+
+static struct divided_clk jz_clk_i2s = {
+ .clk = {
+ .name = "i2s",
+ .parent = &jz_clk_ext.clk,
+ .gate_bit = JZ_CLOCK_GATE_AIC,
+ .set_rate = jz_clk_divided_set_rate,
+ .get_rate = jz_clk_divided_get_rate,
+ .enable = jz_clk_enable_gating,
+ .disable = jz_clk_disable_gating,
+ .set_parent = jz_clk_i2s_set_parent,
+ },
+ .reg = JZ_REG_CLOCK_I2S,
+ .mask = JZ_CLOCK_I2S_DIV_MASK,
+};
+
+static struct divided_clk jz_clk_mmc = {
+ .clk = {
+ .name = "mmc",
+ .parent = &jz_clk_pll_half,
+ .gate_bit = JZ_CLOCK_GATE_MMC,
+ .set_rate = jz_clk_divided_set_rate,
+ .get_rate = jz_clk_divided_get_rate,
+ .enable = jz_clk_enable_gating,
+ .disable = jz_clk_disable_gating,
+ },
+ .reg = JZ_REG_CLOCK_MMC,
+ .mask = JZ_CLOCK_MMC_DIV_MASK,
+};
+
+static struct divided_clk jz_clk_uhc = {
+ .clk = {
+ .name = "uhc",
+ .parent = &jz_clk_pll_half,
+ .gate_bit = JZ_CLOCK_GATE_UHC,
+ .set_rate = jz_clk_divided_set_rate,
+ .get_rate = jz_clk_divided_get_rate,
+ .enable = jz_clk_enable_gating,
+ .disable = jz_clk_disable_gating,
+ },
+ .reg = JZ_REG_CLOCK_UHC,
+ .mask = JZ_CLOCK_UHC_DIV_MASK,
+};
+
+static struct clk jz_clk_udc = {
+ .name = "udc",
+ .parent = &jz_clk_ext.clk,
+ .set_parent = jz_clk_udc_set_parent,
+ .set_rate = jz_clk_udc_set_rate,
+ .get_rate = jz_clk_udc_get_rate,
+};
+
+static struct divided_clk jz_clk_spi = {
+ .clk = {
+ .name = "spi",
+ .parent = &jz_clk_ext.clk,
+ .gate_bit = JZ_CLOCK_GATE_SPI,
+ .set_rate = jz_clk_divided_set_rate,
+ .get_rate = jz_clk_divided_get_rate,
+ .enable = jz_clk_enable_gating,
+ .disable = jz_clk_disable_gating,
+ .set_parent = jz_clk_spi_set_parent,
+ },
+ .reg = JZ_REG_CLOCK_SPI,
+ .mask = JZ_CLOCK_SPI_DIV_MASK,
+};
+
+static struct clk jz_clk_uart0 = {
+ .name = "uart0",
+ .parent = &jz_clk_ext.clk,
+ .gate_bit = JZ_CLOCK_GATE_UART0,
+ .enable = jz_clk_enable_gating,
+ .disable = jz_clk_disable_gating,
+};
+
+static struct clk jz_clk_uart1 = {
+ .name = "uart1",
+ .parent = &jz_clk_ext.clk,
+ .gate_bit = JZ_CLOCK_GATE_UART1,
+ .enable = jz_clk_enable_gating,
+ .disable = jz_clk_disable_gating,
+};
+
+static struct clk jz_clk_dma = {
+ .name = "dma",
+ .parent = &jz_clk_high_speed_peripheral.clk,
+ .gate_bit = JZ_CLOCK_GATE_UART0,
+ .enable = jz_clk_enable_gating,
+ .disable = jz_clk_disable_gating,
+};
+
+static struct clk jz_clk_ipu = {
+ .name = "ipu",
+ .parent = &jz_clk_high_speed_peripheral.clk,
+ .gate_bit = JZ_CLOCK_GATE_IPU,
+ .enable = jz_clk_enable_gating,
+ .disable = jz_clk_disable_gating,
+};
+
+static struct clk jz_clk_adc = {
+ .name = "adc",
+ .parent = &jz_clk_ext.clk,
+ .gate_bit = JZ_CLOCK_GATE_ADC,
+ .enable = jz_clk_enable_gating,
+ .disable = jz_clk_disable_gating,
+};
+
+static struct clk jz_clk_i2c = {
+ .name = "i2c",
+ .parent = &jz_clk_ext.clk,
+ .gate_bit = JZ_CLOCK_GATE_I2C,
+ .enable = jz_clk_enable_gating,
+ .disable = jz_clk_disable_gating,
+};
+
+static struct static_clk jz_clk_rtc = {
+ .clk = {
+ .name = "rtc",
+ .gate_bit = JZ_CLOCK_GATE_RTC,
+ .enable = jz_clk_enable_gating,
+ .disable = jz_clk_disable_gating,
+ },
+ .rate = 32768,
+};
+
+int clk_enable(struct clk *clk)
+{
+ if (!clk->enable)
+ return -EINVAL;
+
+ return clk->enable(clk);
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+ if (clk->disable)
+ clk->disable(clk);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (clk->get_rate)
+ return clk->get_rate(clk);
+ if (clk->parent)
+ return clk_get_rate(clk->parent);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ if (!clk->set_rate)
+ return -EINVAL;
+ return clk->set_rate(clk, rate);
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (clk->round_rate)
+ return clk->round_rate(clk, rate);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ int ret;
+
+ if (!clk->set_parent)
+ return -EINVAL;
+
+ clk->disable(clk);
+ ret = clk->set_parent(clk, parent);
+ clk->enable(clk);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+
+struct clk *clk_get(struct device *dev, const char *name)
+{
+ struct clk *clk;
+
+ list_for_each_entry(clk, &jz_clocks, list) {
+ if (strcmp(clk->name, name) == 0)
+ return clk;
+ }
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL_GPL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL_GPL(clk_put);
+
+inline static void clk_add(struct clk *clk)
+{
+ list_add_tail(&clk->list, &jz_clocks);
+}
+
+static void clk_register_clks(void)
+{
+ clk_add(&jz_clk_ext.clk);
+ clk_add(&jz_clk_pll);
+ clk_add(&jz_clk_pll_half);
+ clk_add(&jz_clk_cpu.clk);
+ clk_add(&jz_clk_high_speed_peripheral.clk);
+ clk_add(&jz_clk_low_speed_peripheral.clk);
+ clk_add(&jz_clk_ko);
+ clk_add(&jz_clk_ld);
+ clk_add(&jz_clk_lp.clk);
+ clk_add(&jz_clk_cim_mclk);
+ clk_add(&jz_clk_cim_pclk.clk);
+ clk_add(&jz_clk_i2s.clk);
+ clk_add(&jz_clk_mmc.clk);
+ clk_add(&jz_clk_uhc.clk);
+ clk_add(&jz_clk_udc);
+ clk_add(&jz_clk_uart0);
+ clk_add(&jz_clk_uart1);
+ clk_add(&jz_clk_dma);
+ clk_add(&jz_clk_ipu);
+ clk_add(&jz_clk_adc);
+ clk_add(&jz_clk_i2c);
+ clk_add(&jz_clk_rtc.clk);
+}
+
+int jz_init_clocks(unsigned long ext_rate)
+{
+ uint32_t val;
+
+ jz_clock_base = ioremap(0x10000000, 0x100);
+ if (!jz_clock_base)
+ return -EBUSY;
+
+ jz_clk_ext.rate = ext_rate;
+
+ val = jz_clk_reg_read(JZ_REG_CLOCK_SPI);
+
+ if (val & JZ_CLOCK_SPI_SRC_PLL)
+ jz_clk_spi.clk.parent = &jz_clk_pll_half;
+
+ val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
+
+ if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL)
+ jz_clk_i2s.clk.parent = &jz_clk_pll_half;
+
+ if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL)
+ jz_clk_udc.parent = &jz_clk_pll_half;
+
+ clk_register_clks();
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(jz_init_clocks);
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/dma.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/dma.c
new file mode 100644
index 000000000..e43fb743f
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/dma.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4740 SoC DMA 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
+#include <linux/dma-mapping.h>
+#include <asm/mach-jz4740/dma.h>
+#include <asm/mach-jz4740/regs.h>
+
+#define JZ_REG_DMA_SRC_ADDR(x) (0x00 + (x) * 0x20)
+#define JZ_REG_DMA_DST_ADDR(x) (0x04 + (x) * 0x20)
+#define JZ_REG_DMA_TRANSFER_COUNT(x) (0x08 + (x) * 0x20)
+#define JZ_REG_DMA_REQ_TYPE(x) (0x0C + (x) * 0x20)
+#define JZ_REG_DMA_STATUS_CTRL(x) (0x10 + (x) * 0x20)
+#define JZ_REG_DMA_CMD(x) (0x14 + (x) * 0x20)
+#define JZ_REG_DMA_DESC_ADDR(x) (0x18 + (x) * 0x20)
+
+#define JZ_REG_DMA_CTRL 0x300
+#define JZ_REG_DMA_IRQ 0x304
+#define JZ_REG_DMA_DOORBELL 0x308
+#define JZ_REG_DMA_DOORBELL_SET 0x30C
+
+#define JZ_DMA_STATUS_CTRL_NO_DESC BIT(31)
+#define JZ_DMA_STATUS_CTRL_DESC_INV BIT(6)
+#define JZ_DMA_STATUS_CTRL_ADDR_ERR BIT(4)
+#define JZ_DMA_STATUS_CTRL_TRANSFER_DONE BIT(3)
+#define JZ_DMA_STATUS_CTRL_HALT BIT(2)
+#define JZ_DMA_STATUS_CTRL_COUNT_TERMINATE BIT(1)
+#define JZ_DMA_STATUS_CTRL_ENABLE BIT(0)
+
+#define JZ_DMA_CMD_SRC_INC BIT(23)
+#define JZ_DMA_CMD_DST_INC BIT(22)
+#define JZ_DMA_CMD_RDIL_MASK (0xf << 16)
+#define JZ_DMA_CMD_SRC_WIDTH_MASK (0x3 << 14)
+#define JZ_DMA_CMD_DST_WIDTH_MASK (0x3 << 12)
+#define JZ_DMA_CMD_INTERVAL_LENGTH_MASK (0x7 << 8)
+#define JZ_DMA_CMD_BLOCK_MODE BIT(7)
+#define JZ_DMA_CMD_DESC_VALID BIT(4)
+#define JZ_DMA_CMD_DESC_VALID_MODE BIT(3)
+#define JZ_DMA_CMD_VALID_IRQ_ENABLE BIT(2)
+#define JZ_DMA_CMD_TRANSFER_IRQ_ENABLE BIT(1)
+#define JZ_DMA_CMD_LINK_ENABLE BIT(0)
+
+#define JZ_DMA_CMD_FLAGS_OFFSET 22
+#define JZ_DMA_CMD_RDIL_OFFSET 16
+#define JZ_DMA_CMD_SRC_WIDTH_OFFSET 14
+#define JZ_DMA_CMD_DST_WIDTH_OFFSET 12
+#define JZ_DMA_CMD_TRANSFER_SIZE_OFFSET 8
+#define JZ_DMA_CMD_MODE_OFFSET 7
+
+#define JZ_DMA_CTRL_PRIORITY_MASK (0x3 << 8)
+#define JZ_DMA_CTRL_HALT BIT(3)
+#define JZ_DMA_CTRL_ADDRESS_ERROR BIT(2)
+#define JZ_DMA_CTRL_ENABLE BIT(0)
+
+
+static void __iomem *jz4740_dma_base;
+static spinlock_t jz4740_dma_lock;
+
+static inline uint32_t jz4740_dma_read(size_t reg)
+{
+ return readl(jz4740_dma_base + reg);
+}
+
+static inline void jz4740_dma_write(size_t reg, uint32_t val)
+{
+ writel(val, jz4740_dma_base + reg);
+}
+
+static inline void jz4740_dma_write_mask(size_t reg, uint32_t val, uint32_t mask)
+{
+ uint32_t val2;
+ val2 = jz4740_dma_read(reg);
+ val2 &= ~mask;
+ val2 |= val;
+ jz4740_dma_write(reg, val2);
+}
+
+struct jz4740_dma_chan {
+ unsigned int id;
+ void *dev;
+ const char *name;
+
+ enum jz4740_dma_flags flags;
+ uint32_t transfer_shift;
+
+ jz4740_dma_complete_callback_t complete_cb;
+
+ unsigned used:1;
+};
+
+#define JZ4740_DMA_CHANNEL(_id) { .id = _id }
+
+struct jz4740_dma_chan jz4740_dma_channels[] = {
+ JZ4740_DMA_CHANNEL(0),
+ JZ4740_DMA_CHANNEL(1),
+ JZ4740_DMA_CHANNEL(2),
+ JZ4740_DMA_CHANNEL(3),
+ JZ4740_DMA_CHANNEL(4),
+ JZ4740_DMA_CHANNEL(5),
+};
+
+struct jz4740_dma_chan* jz4740_dma_request(void *dev, const char *name)
+{
+ unsigned int i;
+ struct jz4740_dma_chan *dma = NULL;
+
+ spin_lock(&jz4740_dma_lock);
+
+ for (i = 0; i < ARRAY_SIZE(jz4740_dma_channels); ++i) {
+ if (!jz4740_dma_channels[i].used) {
+ dma = &jz4740_dma_channels[i];
+ dma->used = 1;
+ break;
+ }
+ }
+
+ spin_unlock(&jz4740_dma_lock);
+
+ if (!dma)
+ return NULL;
+
+ dma->dev = dev;
+ dma->name = name;
+
+ return dma;
+}
+
+void jz4740_dma_configure(struct jz4740_dma_chan *dma,
+ const struct jz4740_dma_config *config)
+{
+ uint32_t cmd;
+ uint32_t ctrl;
+
+ switch(config->transfer_size) {
+ case JZ4740_DMA_TRANSFER_SIZE_2BYTE:
+ dma->transfer_shift = 1;
+ break;
+ case JZ4740_DMA_TRANSFER_SIZE_4BYTE:
+ dma->transfer_shift = 2;
+ break;
+ case JZ4740_DMA_TRANSFER_SIZE_16BYTE:
+ dma->transfer_shift = 4;
+ break;
+ case JZ4740_DMA_TRANSFER_SIZE_32BYTE:
+ dma->transfer_shift = 5;
+ break;
+ default:
+ dma->transfer_shift = 0;
+ break;
+ }
+
+ cmd = config->flags << JZ_DMA_CMD_FLAGS_OFFSET;
+ cmd |= config->src_width << JZ_DMA_CMD_SRC_WIDTH_OFFSET;
+ cmd |= config->dst_width << JZ_DMA_CMD_DST_WIDTH_OFFSET;
+ cmd |= config->transfer_size << JZ_DMA_CMD_TRANSFER_SIZE_OFFSET;
+ cmd |= config->mode << JZ_DMA_CMD_MODE_OFFSET;
+ cmd |= JZ_DMA_CMD_TRANSFER_IRQ_ENABLE;
+
+ ctrl = JZ_DMA_STATUS_CTRL_NO_DESC;
+ ctrl |= JZ_DMA_STATUS_CTRL_HALT;
+
+ jz4740_dma_write(JZ_REG_DMA_CMD(dma->id), cmd);
+ jz4740_dma_write(JZ_REG_DMA_STATUS_CTRL(dma->id), ctrl);
+ jz4740_dma_write(JZ_REG_DMA_REQ_TYPE(dma->id), config->request_type);
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_configure);
+
+void jz4740_dma_set_src_addr(struct jz4740_dma_chan *dma, dma_addr_t src)
+{
+ jz4740_dma_write(JZ_REG_DMA_SRC_ADDR(dma->id), src);
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_set_src_addr);
+
+void jz4740_dma_set_dst_addr(struct jz4740_dma_chan *dma, dma_addr_t dst)
+{
+ jz4740_dma_write(JZ_REG_DMA_DST_ADDR(dma->id), dst);
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_set_dst_addr);
+
+void jz4740_dma_set_transfer_count(struct jz4740_dma_chan *dma, uint32_t count)
+{
+ count >>= dma->transfer_shift;
+ jz4740_dma_write(JZ_REG_DMA_TRANSFER_COUNT(dma->id), count);
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_set_transfer_count);
+
+void jz4740_dma_set_complete_cb(struct jz4740_dma_chan *dma,
+ jz4740_dma_complete_callback_t cb)
+{
+ dma->complete_cb = cb;
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_set_complete_cb);
+
+void jz4740_dma_free(struct jz4740_dma_chan *dma)
+{
+ dma->dev = NULL;
+ dma->complete_cb = NULL;
+ dma->used = 0;
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_free);
+
+void jz4740_dma_enable(struct jz4740_dma_chan *dma)
+{
+ jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id),
+ JZ_DMA_STATUS_CTRL_ENABLE,
+ JZ_DMA_STATUS_CTRL_ENABLE | JZ_DMA_STATUS_CTRL_HALT);
+
+ jz4740_dma_write_mask(JZ_REG_DMA_CTRL,
+ JZ_DMA_CTRL_ENABLE,
+ JZ_DMA_CTRL_ENABLE | JZ_DMA_CTRL_HALT);
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_enable);
+
+void jz4740_dma_disable(struct jz4740_dma_chan *dma)
+{
+ jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0,
+ JZ_DMA_STATUS_CTRL_ENABLE);
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_disable);
+
+uint32_t jz4740_dma_get_residue(const struct jz4740_dma_chan *dma)
+{
+ uint32_t residue;
+ residue = jz4740_dma_read(JZ_REG_DMA_TRANSFER_COUNT(dma->id));
+ return residue << dma->transfer_shift;
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_get_residue);
+
+static void jz4740_dma_chan_irq(struct jz4740_dma_chan *dma)
+{
+ uint32_t status;
+
+ status = jz4740_dma_read(JZ_REG_DMA_STATUS_CTRL(dma->id));
+
+ jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0,
+ JZ_DMA_STATUS_CTRL_ENABLE | JZ_DMA_STATUS_CTRL_TRANSFER_DONE);
+
+ if (dma->complete_cb)
+ dma->complete_cb(dma, 0, dma->dev);
+}
+
+static irqreturn_t jz4740_dma_irq(int irq, void *dev_id)
+{
+ uint32_t irq_status;
+ unsigned int i;
+
+ irq_status = readl(jz4740_dma_base + JZ_REG_DMA_IRQ);
+
+ for (i = 0; i < 6; ++i) {
+ if (irq_status & (1 << i))
+ jz4740_dma_chan_irq(&jz4740_dma_channels[i]);
+ }
+
+ return IRQ_HANDLED;
+}
+
+#if 0
+static struct jz4740_dma_config dma_test_config = {
+ .src_width = JZ4740_DMA_WIDTH_32BIT,
+ .dst_width = JZ4740_DMA_WIDTH_32BIT,
+ .transfer_size = JZ4740_DMA_TRANSFER_SIZE_4BYTE,
+ .request_type = JZ4740_DMA_TYPE_AUTO_REQUEST,
+ .flags = JZ4740_DMA_SRC_AUTOINC | JZ4740_DMA_DST_AUTOINC,
+ .mode = JZ4740_DMA_MODE_BLOCK,
+};
+
+static void jz4740_dma_test(void)
+{
+ uint32_t *buf1, *buf2;
+ dma_addr_t addr1, addr2;
+ struct jz4740_dma_chan *dma = jz4740_dma_request(NULL, "dma test");
+ int i;
+
+ printk("STARTING DMA TEST\n");
+
+ buf1 = dma_alloc_coherent(NULL,
+ 0x1000,
+ &addr1, GFP_KERNEL);
+ buf2 = dma_alloc_coherent(NULL,
+ 0x1000,
+ &addr2, GFP_KERNEL);
+
+ for (i = 0; i < 0x400; ++i)
+ buf1[i] = i;
+
+
+ jz4740_dma_configure(dma, &dma_test_config);
+ jz4740_dma_set_src_addr(dma, addr1);
+ jz4740_dma_set_dst_addr(dma, addr2);
+ jz4740_dma_set_transfer_count(dma, 0x1000);
+
+ jz4740_dma_enable(dma);
+ mdelay(2000);
+
+ for (i = 0; i < 0x400; ++i) {
+ if (buf2[i] != i)
+ printk("OH MY GOD: %x %x\n", i, buf2[i]);
+ }
+
+ printk("DMA TEST DONE\n");
+}
+#endif
+
+static int jz4740_dma_init(void)
+{
+ unsigned int ret;
+
+ jz4740_dma_base = ioremap(CPHYSADDR(DMAC_BASE), 0x400);
+
+ if (!jz4740_dma_base)
+ return -EBUSY;
+
+ spin_lock_init(&jz4740_dma_lock);
+
+ ret = request_irq(JZ_IRQ_DMAC, jz4740_dma_irq, 0, "DMA", NULL);
+
+ if (ret)
+ printk("JZ4740 DMA: Failed to request irq: %d\n", ret);
+
+ return ret;
+}
+arch_initcall(jz4740_dma_init);
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/gpio.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/gpio.c
new file mode 100644
index 000000000..30f83fa09
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/gpio.c
@@ -0,0 +1,490 @@
+/*
+ * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4740 platform GPIO 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/spinlock.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+
+#define JZ_GPIO_BASE_A (32*0)
+#define JZ_GPIO_BASE_B (32*1)
+#define JZ_GPIO_BASE_C (32*2)
+#define JZ_GPIO_BASE_D (32*3)
+
+#define JZ_GPIO_NUM_A 32
+#define JZ_GPIO_NUM_B 32
+#define JZ_GPIO_NUM_C 31
+#define JZ_GPIO_NUM_D 32
+
+#define JZ_IRQ_GPIO_BASE_A (JZ_IRQ_GPIO(0) + JZ_GPIO_BASE_A)
+#define JZ_IRQ_GPIO_BASE_B (JZ_IRQ_GPIO(0) + JZ_GPIO_BASE_B)
+#define JZ_IRQ_GPIO_BASE_C (JZ_IRQ_GPIO(0) + JZ_GPIO_BASE_C)
+#define JZ_IRQ_GPIO_BASE_D (JZ_IRQ_GPIO(0) + JZ_GPIO_BASE_D)
+
+#define JZ_IRQ_GPIO_A(num) (JZ_IRQ_GPIO_BASE_A + num)
+#define JZ_IRQ_GPIO_B(num) (JZ_IRQ_GPIO_BASE_B + num)
+#define JZ_IRQ_GPIO_C(num) (JZ_IRQ_GPIO_BASE_C + num)
+#define JZ_IRQ_GPIO_D(num) (JZ_IRQ_GPIO_BASE_D + num)
+
+#define JZ_REG_GPIO_PIN 0x00
+#define JZ_REG_GPIO_DATA 0x10
+#define JZ_REG_GPIO_DATA_SET 0x14
+#define JZ_REG_GPIO_DATA_CLEAR 0x18
+#define JZ_REG_GPIO_MASK 0x20
+#define JZ_REG_GPIO_MASK_SET 0x24
+#define JZ_REG_GPIO_MASK_CLEAR 0x28
+#define JZ_REG_GPIO_PULL 0x30
+#define JZ_REG_GPIO_PULL_SET 0x34
+#define JZ_REG_GPIO_PULL_CLEAR 0x38
+#define JZ_REG_GPIO_FUNC 0x40
+#define JZ_REG_GPIO_FUNC_SET 0x44
+#define JZ_REG_GPIO_FUNC_CLEAR 0x48
+#define JZ_REG_GPIO_SELECT 0x50
+#define JZ_REG_GPIO_SELECT_SET 0x54
+#define JZ_REG_GPIO_SELECT_CLEAR 0x58
+#define JZ_REG_GPIO_DIRECTION 0x60
+#define JZ_REG_GPIO_DIRECTION_SET 0x64
+#define JZ_REG_GPIO_DIRECTION_CLEAR 0x68
+#define JZ_REG_GPIO_TRIGGER 0x70
+#define JZ_REG_GPIO_TRIGGER_SET 0x74
+#define JZ_REG_GPIO_TRIGGER_CLEAR 0x78
+#define JZ_REG_GPIO_FLAG 0x80
+#define JZ_REG_GPIO_FLAG_CLEAR 0x14
+
+#define CHIP_TO_REG(chip, reg) (jz_gpio_base + (((chip)->base) << 3) + reg)
+
+#define GPIO_TO_BIT(gpio) BIT(gpio & 0x1f)
+#define GPIO_TO_REG(gpio, reg) (jz_gpio_base + ((gpio >> 5) << 8) + reg)
+
+static void __iomem *jz_gpio_base;
+
+struct jz_gpio_chip {
+ unsigned int irq;
+ unsigned int irq_base;
+ uint32_t wakeup;
+ uint32_t suspend_mask;
+ uint32_t edge_trigger_both;
+ spinlock_t lock;
+ struct gpio_chip gpio_chip;
+ struct irq_chip irq_chip;
+};
+
+static struct jz_gpio_chip *jz_irq_to_chip(unsigned int irq)
+{
+ return get_irq_chip_data(irq);
+}
+
+static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg)
+{
+ writel(GPIO_TO_BIT(gpio), GPIO_TO_REG(gpio, reg));
+}
+
+int jz_gpio_set_function(int gpio, enum jz_gpio_function function)
+{
+ if (function == JZ_GPIO_FUNC_NONE) {
+ jz_gpio_write_bit(gpio, JZ_REG_GPIO_FUNC_CLEAR);
+ jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_CLEAR);
+ jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_CLEAR);
+ } else {
+ jz_gpio_write_bit(gpio, JZ_REG_GPIO_FUNC_SET);
+ switch (function) {
+ case JZ_GPIO_FUNC1:
+ jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_CLEAR);
+ break;
+ case JZ_GPIO_FUNC3:
+ jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_SET);
+ case JZ_GPIO_FUNC2: /* Falltrough */
+ jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_SET);
+ break;
+ default:
+ BUG();
+ break;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(jz_gpio_set_function);
+
+int jz_gpio_bulk_request(const struct jz_gpio_bulk_request *request, size_t num)
+{
+ size_t i;
+ int ret;
+
+ for (i = 0; i < num; ++i, ++request) {
+ ret = gpio_request(request->gpio, request->name);
+ if (ret)
+ goto err;
+ jz_gpio_set_function(request->gpio, request->function);
+ }
+
+ return 0;
+err:
+ for (--request; i > 0; --i, --request)
+ gpio_free(request->gpio);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(jz_gpio_bulk_request);
+
+void jz_gpio_bulk_free(const struct jz_gpio_bulk_request *request, size_t num)
+{
+ size_t i;
+
+ for (i = 0; i < num; ++i, ++request) {
+ gpio_free(request->gpio);
+ jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE);
+ }
+
+}
+EXPORT_SYMBOL_GPL(jz_gpio_bulk_free);
+
+void jz_gpio_bulk_suspend(const struct jz_gpio_bulk_request *request, size_t num)
+{
+ size_t i;
+
+ for (i = 0; i < num; ++i, ++request) {
+ jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE);
+ jz_gpio_write_bit(request->gpio, JZ_REG_GPIO_DIRECTION_SET);
+ }
+}
+EXPORT_SYMBOL_GPL(jz_gpio_bulk_suspend);
+
+void jz_gpio_bulk_resume(const struct jz_gpio_bulk_request *request, size_t num)
+{
+ size_t i;
+
+ for (i = 0; i < num; ++i, ++request) {
+ jz_gpio_set_function(request->gpio, request->function);
+ }
+}
+EXPORT_SYMBOL_GPL(jz_gpio_bulk_resume);
+
+void jz_gpio_enable_pullup(unsigned gpio)
+{
+ jz_gpio_write_bit(gpio, JZ_REG_GPIO_PULL_CLEAR);
+}
+EXPORT_SYMBOL_GPL(jz_gpio_enable_pullup);
+
+void jz_gpio_disable_pullup(unsigned gpio)
+{
+ jz_gpio_write_bit(gpio, JZ_REG_GPIO_PULL_SET);
+}
+EXPORT_SYMBOL_GPL(jz_gpio_disable_pullup);
+
+static int jz_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+ return !!(readl(CHIP_TO_REG(chip, JZ_REG_GPIO_PIN)) & BIT(gpio));
+}
+
+static void jz_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
+{
+ uint32_t __iomem *reg = CHIP_TO_REG(chip, JZ_REG_GPIO_DATA_SET);
+ reg += !value;
+ writel(BIT(gpio), reg);
+}
+
+static int jz_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
+{
+ writel(BIT(gpio), CHIP_TO_REG(chip, JZ_REG_GPIO_DIRECTION_SET));
+ jz_gpio_set_value(chip, gpio, value);
+
+ return 0;
+}
+
+static int jz_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+ writel(BIT(gpio), CHIP_TO_REG(chip, JZ_REG_GPIO_DIRECTION_CLEAR));
+
+ return 0;
+}
+
+int jz_gpio_port_direction_input(int port, uint32_t mask)
+{
+ writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_CLEAR));
+
+ return 0;
+}
+EXPORT_SYMBOL(jz_gpio_port_direction_input);
+
+int jz_gpio_port_direction_output(int port, uint32_t mask)
+{
+ writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_SET));
+
+ return 0;
+}
+EXPORT_SYMBOL(jz_gpio_port_direction_output);
+
+void jz_gpio_port_set_value(int port, uint32_t value, uint32_t mask)
+{
+ writel((~value) & mask, GPIO_TO_REG(port, JZ_REG_GPIO_DATA_CLEAR));
+ writel(value & mask, GPIO_TO_REG(port, JZ_REG_GPIO_DATA_SET));
+}
+EXPORT_SYMBOL(jz_gpio_port_set_value);
+
+uint32_t jz_gpio_port_get_value(int port, uint32_t mask)
+{
+ uint32_t value = readl(GPIO_TO_REG(port, JZ_REG_GPIO_PIN));
+
+ return value & mask;
+}
+EXPORT_SYMBOL(jz_gpio_port_get_value);
+
+
+#define IRQ_TO_GPIO(irq) (irq - JZ_IRQ_GPIO(0))
+#define IRQ_TO_BIT(irq) BIT(IRQ_TO_GPIO(irq) & 0x1f)
+
+#define IRQ_TO_REG(irq, reg) GPIO_TO_REG(IRQ_TO_GPIO(irq), reg)
+
+static void jz_gpio_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
+{
+ uint32_t flag;
+ unsigned int gpio_irq;
+ unsigned int gpio_bank;
+ struct jz_gpio_chip *chip = get_irq_desc_data(desc);
+
+ gpio_bank = JZ_IRQ_GPIO0 - irq;
+
+ flag = readl(jz_gpio_base + (gpio_bank << 8) + JZ_REG_GPIO_FLAG);
+
+ gpio_irq = ffs(flag) - 1;
+
+ if (chip->edge_trigger_both & BIT(gpio_irq)) {
+ uint32_t value = readl(CHIP_TO_REG(&chip->gpio_chip, JZ_REG_GPIO_PIN));
+ if (value & BIT(gpio_irq)) {
+ writel(BIT(gpio_irq),
+ CHIP_TO_REG(&chip->gpio_chip, JZ_REG_GPIO_DIRECTION_CLEAR));
+ } else {
+ writel(BIT(gpio_irq),
+ CHIP_TO_REG(&chip->gpio_chip, JZ_REG_GPIO_DIRECTION_SET));
+ }
+ }
+
+ gpio_irq += (gpio_bank << 5) + JZ_IRQ_GPIO(0);
+
+ generic_handle_irq(gpio_irq);
+};
+
+static inline void jz_gpio_set_irq_bit(unsigned int irq, unsigned int reg)
+{
+ writel(IRQ_TO_BIT(irq), IRQ_TO_REG(irq, reg));
+}
+
+static void jz_gpio_irq_mask(unsigned int irq)
+{
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_SET);
+};
+
+static void jz_gpio_irq_unmask(unsigned int irq)
+{
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_CLEAR);
+};
+
+/* TODO: Check if function is gpio */
+static unsigned int jz_gpio_irq_startup(unsigned int irq)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_SET);
+
+ jz_gpio_irq_unmask(irq);
+ desc->status &= ~IRQ_MASKED;
+
+ return 0;
+}
+
+static void jz_gpio_irq_shutdown(unsigned int irq)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ jz_gpio_irq_mask(irq);
+ desc->status |= IRQ_MASKED;
+
+ /* Set direction to input */
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR);
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_CLEAR);
+}
+
+static void jz_gpio_irq_ack(unsigned int irq)
+{
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_FLAG_CLEAR);
+};
+
+static int jz_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
+{
+ struct jz_gpio_chip *chip = jz_irq_to_chip(irq);
+ struct irq_desc *desc = irq_to_desc(irq);
+
+ jz_gpio_irq_mask(irq);
+
+ if (flow_type == IRQ_TYPE_EDGE_BOTH) {
+ uint32_t value = readl(IRQ_TO_REG(irq, JZ_REG_GPIO_PIN));
+ if (value & IRQ_TO_BIT(irq))
+ flow_type = IRQ_TYPE_EDGE_FALLING;
+ else
+ flow_type = IRQ_TYPE_EDGE_RISING;
+ chip->edge_trigger_both |= IRQ_TO_BIT(irq);
+ } else {
+ chip->edge_trigger_both &= ~IRQ_TO_BIT(irq);
+ }
+
+ switch(flow_type) {
+ case IRQ_TYPE_EDGE_RISING:
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET);
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR);
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET);
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET);
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR);
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR);
+ jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!(desc->status & IRQ_MASKED))
+ jz_gpio_irq_unmask(irq);
+
+ return 0;
+}
+
+static int jz_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+{
+ struct jz_gpio_chip *chip = jz_irq_to_chip(irq);
+ spin_lock(&chip->lock);
+ if (on)
+ chip->wakeup |= IRQ_TO_BIT(irq);
+ else
+ chip->wakeup &= ~IRQ_TO_BIT(irq);
+ spin_unlock(&chip->lock);
+
+ set_irq_wake(chip->irq, !!(chip->wakeup));
+ return 0;
+}
+
+int gpio_to_irq(unsigned gpio)
+{
+ return JZ_IRQ_GPIO(0) + gpio;
+}
+EXPORT_SYMBOL_GPL(gpio_to_irq);
+
+int irq_to_gpio(unsigned gpio)
+{
+ return IRQ_TO_GPIO(gpio);
+}
+EXPORT_SYMBOL_GPL(irq_to_gpio);
+
+#define JZ_GPIO_CHIP(_bank) { \
+ .irq_base = JZ_IRQ_GPIO_BASE_ ## _bank, \
+ .gpio_chip = { \
+ .label = "Bank " # _bank, \
+ .owner = THIS_MODULE, \
+ .set = jz_gpio_set_value, \
+ .get = jz_gpio_get_value, \
+ .direction_output = jz_gpio_direction_output, \
+ .direction_input = jz_gpio_direction_input, \
+ .base = JZ_GPIO_BASE_ ## _bank, \
+ .ngpio = JZ_GPIO_NUM_ ## _bank, \
+ }, \
+ .irq_chip = { \
+ .name = "GPIO Bank " # _bank, \
+ .mask = jz_gpio_irq_mask, \
+ .unmask = jz_gpio_irq_unmask, \
+ .ack = jz_gpio_irq_ack, \
+ .startup = jz_gpio_irq_startup, \
+ .shutdown = jz_gpio_irq_shutdown, \
+ .set_type = jz_gpio_irq_set_type, \
+ .set_wake = jz_gpio_irq_set_wake, \
+ }, \
+}
+
+static struct jz_gpio_chip jz_gpio_chips[] = {
+ JZ_GPIO_CHIP(A),
+ JZ_GPIO_CHIP(B),
+ JZ_GPIO_CHIP(C),
+ JZ_GPIO_CHIP(D),
+};
+
+static int jz_gpio_suspend(struct sys_device *dev, pm_message_t state)
+{
+ struct jz_gpio_chip *chip = jz_gpio_chips;
+ int i, gpio;
+ for (i = 0; i < ARRAY_SIZE(jz_gpio_chips); ++i, ++chip) {
+ gpio = chip->gpio_chip.base;
+ chip->suspend_mask = readl(GPIO_TO_REG(gpio, JZ_REG_GPIO_MASK));
+ writel(~(chip->wakeup), GPIO_TO_REG(gpio, JZ_REG_GPIO_MASK_SET));
+ }
+
+ return 0;
+}
+
+static int jz_gpio_resume(struct sys_device *dev)
+{
+ struct jz_gpio_chip *chip = jz_gpio_chips;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(jz_gpio_chips); ++i, ++chip) {
+ writel(~(chip->suspend_mask), GPIO_TO_REG(chip->gpio_chip.base, JZ_REG_GPIO_MASK_CLEAR));
+ }
+
+ return 0;
+}
+
+static struct sysdev_class jz_gpio_sysdev = {
+ .name = "JZ4740 GPIO",
+ .suspend = jz_gpio_suspend,
+ .resume = jz_gpio_resume,
+};
+
+int __init jz_gpiolib_init(void)
+{
+ struct jz_gpio_chip *chip = jz_gpio_chips;
+ int i, irq;
+
+ jz_gpio_base = ioremap(0x10010000, 0x400);
+
+ for (i = 0; i < ARRAY_SIZE(jz_gpio_chips); ++i, ++chip) {
+ gpiochip_add(&chip->gpio_chip);
+ spin_lock_init(&chip->lock);
+ chip->irq = JZ_IRQ_INTC_GPIO(i);
+ set_irq_data(chip->irq, chip);
+ set_irq_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
+ for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) {
+ set_irq_chip_and_handler(irq, &chip->irq_chip, handle_level_irq);
+ set_irq_chip_data(irq, chip);
+ }
+ }
+
+ sysdev_class_register(&jz_gpio_sysdev);
+
+ printk("JZ GPIO initalized\n");
+
+ return 0;
+}
+
+
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/irq.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/irq.c
new file mode 100644
index 000000000..2167f2d4c
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/irq.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4740 platform IRQ 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/irq_cpu.h>
+
+static void __iomem *jz_intc_base;
+static uint32_t jz_intc_wakeup;
+static uint32_t jz_intc_saved;
+
+#define JZ_REG_BASE_INTC 0x10001000
+
+#define JZ_REG_INTC_STATUS 0x00
+#define JZ_REG_INTC_MASK 0x04
+#define JZ_REG_INTC_SET_MASK 0x08
+#define JZ_REG_INTC_CLEAR_MASK 0x0c
+#define JZ_REG_INTC_PENDING 0x10
+
+#define IRQ_BIT(x) BIT((x) - JZ_IRQ_BASE)
+
+static void intc_irq_unmask(unsigned int irq)
+{
+ writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
+}
+
+static void intc_irq_mask(unsigned int irq)
+{
+ writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_SET_MASK);
+}
+
+static void intc_irq_ack(unsigned int irq)
+{
+ writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_PENDING);
+}
+
+static int intc_irq_set_wake(unsigned int irq, unsigned int on)
+{
+ if (on)
+ jz_intc_wakeup |= IRQ_BIT(irq);
+ else
+ jz_intc_wakeup &= ~IRQ_BIT(irq);
+
+ return 0;
+}
+
+static struct irq_chip intc_irq_type = {
+ .name = "INTC",
+ .mask = intc_irq_mask,
+ .unmask = intc_irq_unmask,
+ .ack = intc_irq_ack,
+ .set_wake = intc_irq_set_wake,
+};
+
+static irqreturn_t jz4740_cascade(int irq, void *data)
+{
+ uint32_t irq_reg;
+ irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
+
+ if (irq_reg) {
+ generic_handle_irq(ffs(irq_reg) - 1 + JZ_IRQ_BASE);
+ return IRQ_HANDLED;
+ }
+
+ return 0;
+}
+
+static struct irqaction jz4740_cascade_action = {
+ .handler = jz4740_cascade,
+ .name = "JZ4740 cascade interrupt"
+};
+
+void __init arch_init_irq(void)
+{
+ int i;
+ mips_cpu_irq_init();
+
+ jz_intc_base = ioremap(JZ_REG_BASE_INTC, 0x14);
+
+ for (i = JZ_IRQ_BASE; i < JZ_IRQ_BASE + 32; i++) {
+ intc_irq_mask(i);
+ set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq);
+ }
+
+ setup_irq(2, &jz4740_cascade_action);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+ if (pending & STATUSF_IP2)
+ jz4740_cascade(2, NULL);
+ else if(pending & STATUSF_IP3)
+ do_IRQ(3);
+ else
+ spurious_interrupt();
+}
+
+/* TODO: Use sysdev */
+void jz4740_intc_suspend(void)
+{
+ jz_intc_saved = readl(jz_intc_base + JZ_REG_INTC_MASK);
+ writel(~jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_SET_MASK);
+}
+
+void jz4740_intc_resume(void)
+{
+ writel(~jz_intc_saved, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
+}
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/platform.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/platform.c
new file mode 100644
index 000000000..4e379294a
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/platform.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4740 platform devices
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/resource.h>
+
+#include <asm/mach-jz4740/platform.h>
+#include <asm/mach-jz4740/regs.h>
+#include <asm/mach-jz4740/irq.h>
+
+/* OHCI (USB full speed host controller) */
+static struct resource jz4740_usb_ohci_resources[] = {
+ [0] = {
+ .start = CPHYSADDR(UHC_BASE),
+ .end = CPHYSADDR(UHC_BASE) + 0x10000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = JZ_IRQ_UHC,
+ .end = JZ_IRQ_UHC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* The dmamask must be set for OHCI to work */
+static u64 ohci_dmamask = ~(u32)0;
+
+struct platform_device jz4740_usb_ohci_device = {
+ .name = "jz-ohci",
+ .id = 0,
+ .dev = {
+ .dma_mask = &ohci_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(jz4740_usb_ohci_resources),
+ .resource = jz4740_usb_ohci_resources,
+};
+
+/* UDC (USB gadget controller) */
+static struct resource jz4740_usb_gdt_resources[] = {
+ [0] = {
+ .start = CPHYSADDR(UDC_BASE),
+ .end = CPHYSADDR(UDC_BASE) + 0x10000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = JZ_IRQ_UDC,
+ .end = JZ_IRQ_UDC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 jz4740_udc_dmamask = ~(u32)0;
+
+struct platform_device jz4740_usb_gdt_device = {
+ .name = "jz-udc",
+ .id = -1,
+ .dev = {
+ .dma_mask = &jz4740_udc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(jz4740_usb_gdt_resources),
+ .resource = jz4740_usb_gdt_resources,
+};
+
+/** MMC/SD controller **/
+static struct resource jz4740_mmc_resources[] = {
+ [0] = {
+ .start = CPHYSADDR(MSC_BASE),
+ .end = CPHYSADDR(MSC_BASE) + 0x10000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = JZ_IRQ_MSC,
+ .end = JZ_IRQ_MSC,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static u64 jz4740_mmc_dmamask = ~(u32)0;
+
+struct platform_device jz4740_mmc_device = {
+ .name = "jz4740-mmc",
+ .id = 0,
+ .dev = {
+ .dma_mask = &jz4740_mmc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(jz4740_mmc_resources),
+ .resource = jz4740_mmc_resources,
+};
+
+static struct resource jz4740_rtc_resources[] = {
+ [0] = {
+ .start = CPHYSADDR(RTC_BASE),
+ .end = CPHYSADDR(RTC_BASE) + 0x10,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = JZ_IRQ_RTC,
+ .end = JZ_IRQ_RTC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device jz4740_rtc_device = {
+ .name = "jz4740-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(jz4740_rtc_resources),
+ .resource = jz4740_rtc_resources,
+};
+
+/** I2C controller **/
+static struct resource jz4740_i2c_resources[] = {
+ [0] = {
+ .start = CPHYSADDR(I2C_BASE),
+ .end = CPHYSADDR(I2C_BASE) + 0x10000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = JZ_IRQ_I2C,
+ .end = JZ_IRQ_I2C,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static u64 jz4740_i2c_dmamask = ~(u32)0;
+
+struct platform_device jz4740_i2c_device = {
+ .name = "jz_i2c",
+ .id = 0,
+ .dev = {
+ .dma_mask = &jz4740_i2c_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(jz4740_i2c_resources),
+ .resource = jz4740_i2c_resources,
+};
+
+static struct resource jz4740_nand_resources[] = {
+ [0] = {
+ .start = CPHYSADDR(EMC_BASE),
+ .end = CPHYSADDR(EMC_BASE) + 0x10000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device jz4740_nand_device = {
+ .name = "jz4740-nand",
+ .num_resources = ARRAY_SIZE(jz4740_nand_resources),
+ .resource = jz4740_nand_resources,
+};
+
+static struct resource jz4740_framebuffer_resources[] = {
+ [0] = {
+ .start = CPHYSADDR(LCD_BASE),
+ .end = CPHYSADDR(LCD_BASE) + 0x10000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static u64 jz4740_fb_dmamask = ~(u32)0;
+
+struct platform_device jz4740_framebuffer_device = {
+ .name = "jz4740-fb",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(jz4740_framebuffer_resources),
+ .resource = jz4740_framebuffer_resources,
+ .dev = {
+ .dma_mask = &jz4740_fb_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+static struct resource jz4740_i2s_resources[] = {
+ [0] = {
+ .start = CPHYSADDR(AIC_BASE),
+ .end = CPHYSADDR(AIC_BASE) + 0x38 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device jz4740_i2s_device = {
+ .name = "jz4740-i2s",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(jz4740_i2s_resources),
+ .resource = jz4740_i2s_resources,
+};
+
+static struct resource jz4740_codec_resources[] = {
+ [0] = {
+ .start = CPHYSADDR(AIC_BASE) + 0x80,
+ .end = CPHYSADDR(AIC_BASE) + 0x88 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device jz4740_codec_device = {
+ .name = "jz4740-codec",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(jz4740_codec_resources),
+ .resource = jz4740_codec_resources,
+};
+
+static struct resource jz4740_adc_resources[] = {
+ [0] = {
+ .start = CPHYSADDR(SADC_BASE),
+ .end = CPHYSADDR(SADC_BASE) + 0x30,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = JZ_IRQ_SADC,
+ .end = JZ_IRQ_SADC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device jz4740_adc_device = {
+ .name = "jz4740-adc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(jz4740_adc_resources),
+ .resource = jz4740_adc_resources,
+};
+
+struct platform_device jz4740_battery_device = {
+ .name = "jz4740-battery",
+ .id = -1,
+ .dev = {
+ .parent = &jz4740_adc_device.dev
+ },
+};
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/pm.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/pm.c
new file mode 100644
index 000000000..d19bb81f0
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/pm.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4740 SoC power management 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/suspend.h>
+#include <asm/mach-jz4740/regs.h>
+
+extern void jz4740_intc_suspend(void);
+extern void jz4740_intc_resume(void);
+
+static int jz_pm_enter(suspend_state_t state)
+{
+ unsigned long nfcsr = REG_EMC_NFCSR;
+ uint32_t scr = REG_CPM_SCR;
+
+ /* Disable nand flash */
+ REG_EMC_NFCSR = ~0xff;
+
+ udelay(100);
+
+ /*stop udc and usb*/
+ REG_CPM_SCR &= ~( 1<<6 | 1<<7);
+ REG_CPM_SCR |= 0<<6 | 1<<7;
+
+ jz4740_intc_suspend();
+
+ /* Enter SLEEP mode */
+ REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;
+ REG_CPM_LCR |= CPM_LCR_LPM_SLEEP;
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+
+ /* Restore to IDLE mode */
+ REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;
+ REG_CPM_LCR |= CPM_LCR_LPM_IDLE;
+
+ /* Restore nand flash control register */
+ REG_EMC_NFCSR = nfcsr;
+
+ jz4740_intc_resume();
+
+ /* Restore sleep control register */
+ REG_CPM_SCR = scr;
+
+ return 0;
+}
+
+static struct platform_suspend_ops jz_pm_ops = {
+ .valid = suspend_valid_only_mem,
+ .enter = jz_pm_enter,
+};
+
+/*
+ * Initialize power interface
+ */
+int __init jz_pm_init(void)
+{
+ suspend_set_ops(&jz_pm_ops);
+ return 0;
+
+}
+late_initcall(jz_pm_init);
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/prom.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/prom.c
new file mode 100644
index 000000000..e28d8154c
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/prom.c
@@ -0,0 +1,111 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * PROM library initialisation code, supports YAMON and U-Boot.
+ *
+ * Copyright 2000, 2001, 2006 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/mach-jz4740/regs.h>
+
+/* #define DEBUG_CMDLINE */
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+
+char *prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+
+void prom_init_cmdline(void)
+{
+ char *cp, *c;
+ size_t i = 1;
+
+ cp = &(arcs_cmdline[0]);
+ while(i < prom_argc) {
+ c = prom_argv[i];
+ while (*c) {
+ *cp++ = *c++;
+ }
+ *cp++ = ' ';
+ i++;
+ }
+ if (i > 1) {
+ *(cp - 1) = '\0';
+ }
+
+}
+
+void __init prom_init(void)
+{
+ unsigned long memsize;
+
+ prom_argc = (int) fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (char **) fw_arg2;
+
+ mips_machtype = MACH_INGENIC_JZ4740;
+
+ prom_init_cmdline();
+ memsize = 0x04000000;
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+/* used by early printk */
+void prom_putchar(char c)
+{
+ volatile u8 *uart_lsr = (volatile u8 *)(UART0_BASE + OFF_LSR);
+ volatile u8 *uart_tdr = (volatile u8 *)(UART0_BASE + OFF_TDR);
+
+ /* Wait for fifo to shift out some bytes */
+ while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) );
+
+ *uart_tdr = (u8)c;
+}
+
+const char *get_system_type(void)
+{
+ return "JZ4740";
+}
+
+EXPORT_SYMBOL(prom_getcmdline);
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/reset.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/reset.c
new file mode 100644
index 000000000..a4b2292f1
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/reset.c
@@ -0,0 +1,50 @@
+/*
+ * linux/arch/mips/jz4740/reset.c
+ *
+ * JZ4740 reset routines.
+ *
+ * Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
+ * Author: <yliu@ingenic.cn>
+ *
+ * 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/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/mach-jz4740/regs.h>
+#include <asm/mach-jz4740/timer.h>
+#include <asm/mach-jz4740/jz4740.h>
+
+void jz_restart(char *command)
+{
+ printk(KERN_NOTICE "Restarting after 4 ms\n");
+ REG_WDT_TCSR = WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN;
+ REG_WDT_TCNT = 0;
+ REG_WDT_TDR = JZ_EXTAL/1000; /* reset after 4ms */
+ jz4740_timer_enable_watchdog();
+ REG_WDT_TCER = WDT_TCER_TCEN; /* wdt start */
+ while (1);
+}
+
+void jz_halt(void)
+{
+ /* Put CPU to power down mode */
+ while (!(REG_RTC_RCR & RTC_RCR_WRDY));
+ REG_RTC_HCR = RTC_HCR_PD;
+
+ while (1)
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+}
+
+void jz_power_off(void)
+{
+ jz_halt();
+}
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/setup.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/setup.c
new file mode 100644
index 000000000..3f12e2e79
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/setup.c
@@ -0,0 +1,108 @@
+/*
+ * linux/arch/mips/jz4740/common/setup.c
+ *
+ * JZ4740 common setup routines.
+ *
+ * Copyright (C) 2006 Ingenic Semiconductor Inc.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/time.h>
+#include <asm/mach-jz4740/jz4740.h>
+#include <asm/mach-jz4740/regs.h>
+#include <asm/mach-jz4740/clock.h>
+#include <asm/mach-jz4740/serial.h>
+
+extern char *__init prom_getcmdline(void);
+extern void __init jz_board_setup(void);
+extern void jz_restart(char *);
+extern void jz_halt(void);
+extern void jz_power_off(void);
+extern void jz_time_init(void);
+
+static void __init soc_cpm_setup(void)
+{
+ /* Enable CKO to external memory */
+ __cpm_enable_cko();
+
+ /* CPU enters IDLE mode when executing 'wait' instruction */
+ __cpm_idle_mode();
+}
+
+
+static void __init jz_serial_setup(void)
+{
+#ifdef CONFIG_SERIAL_8250
+ struct uart_port s;
+ REG8(UART0_FCR) |= UARTFCR_UUE; /* enable UART module */
+ memset(&s, 0, sizeof(s));
+ s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+ s.iotype = SERIAL_IO_MEM;
+ s.regshift = 2;
+ s.uartclk = JZ_EXTAL;
+
+ s.line = 0;
+ s.membase = (u8 *)UART0_BASE;
+ s.irq = JZ_IRQ_UART0;
+ if (early_serial_setup(&s) != 0) {
+ printk(KERN_ERR "Serial ttyS0 setup failed!\n");
+ }
+
+ s.line = 1;
+ s.membase = (u8 *)UART1_BASE;
+ s.irq = JZ_IRQ_UART1;
+ if (early_serial_setup(&s) != 0) {
+ printk(KERN_ERR "Serial ttyS1 setup failed!\n");
+ }
+#endif
+}
+
+void __init plat_mem_setup(void)
+{
+ char *argptr;
+
+ argptr = prom_getcmdline();
+
+ /* IO/MEM resources. Which will be the addtion value in `inX' and
+ * `outX' macros defined in asm/io.h */
+ set_io_port_base(0);
+ ioport_resource.start = 0x00000000;
+ ioport_resource.end = 0xffffffff;
+ iomem_resource.start = 0x00000000;
+ iomem_resource.end = 0xffffffff;
+
+ _machine_restart = jz_restart;
+ _machine_halt = jz_halt;
+ pm_power_off = jz_power_off;
+ soc_cpm_setup();
+ jz_serial_setup();
+}
+
diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/time.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/time.c
new file mode 100644
index 000000000..b811fcd44
--- /dev/null
+++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/time.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4740 platform timer 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+
+#include <asm/mach-jz4740/irq.h>
+#include <asm/mach-jz4740/jz4740.h>
+#include <asm/time.h>
+
+#define JZ_REG_TIMER_STOP 0x1C
+#define JZ_REG_TIMER_STOP_SET 0x2C
+#define JZ_REG_TIMER_STOP_CLEAR 0x3C
+#define JZ_REG_TIMER_ENABLE 0x10
+#define JZ_REG_TIMER_ENABLE_SET 0x14
+#define JZ_REG_TIMER_ENABLE_CLEAR 0x18
+#define JZ_REG_TIMER_FLAG 0x20
+#define JZ_REG_TIMER_FLAG_SET 0x24
+#define JZ_REG_TIMER_FLAG_CLEAR 0x28
+#define JZ_REG_TIMER_MASK 0x30
+#define JZ_REG_TIMER_MASK_SET 0x34
+#define JZ_REG_TIMER_MASK_CLEAR 0x38
+
+#define JZ_REG_TIMER_DFR(x) (((x) * 0x10) + 0x40)
+#define JZ_REG_TIMER_DHR(x) (((x) * 0x10) + 0x44)
+#define JZ_REG_TIMER_CNT(x) (((x) * 0x10) + 0x48)
+#define JZ_REG_TIMER_CTRL(x) (((x) * 0x10) + 0x4C)
+
+#define JZ_TIMER_IRQ_HALF(x) BIT((x) + 0x10)
+#define JZ_TIMER_IRQ_FULL(x) BIT(x)
+
+#define JZ_TIMER_CTRL_PWM_ACTIVE_LOW BIT(8)
+#define JZ_TIMER_CTRL_PWM_ENABLE BIT(7)
+#define JZ_TIMER_CTRL_PRESCALE_MASK 0x1c
+#define JZ_TIMER_CTRL_PRESCALE_OFFSET 0x3
+#define JZ_TIMER_CTRL_PRESCALE_1 (0 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_4 (1 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_16 (2 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_64 (3 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_256 (4 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_1024 (5 << 3)
+
+#define JZ_TIMER_CTRL_SRC_EXT BIT(2)
+#define JZ_TIMER_CTRL_SRC_RTC BIT(1)
+#define JZ_TIMER_CTRL_SRC_PCLK BIT(0)
+
+static void __iomem *jz4740_timer_base;
+static uint16_t jz4740_jiffies_per_tick;
+
+void jz4740_timer_enable_watchdog(void)
+{
+ writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR);
+}
+
+void jz4740_timer_disable_watchdog(void)
+{
+ writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_SET);
+}
+
+static inline void jz4740_timer_set_period(unsigned int timer, uint16_t period)
+{
+ writew(period, jz4740_timer_base + JZ_REG_TIMER_DFR(timer));
+}
+
+static inline void jz4740_timer_set_duty(unsigned int timer, uint16_t duty)
+{
+ writew(duty, jz4740_timer_base + JZ_REG_TIMER_DHR(timer));
+}
+
+static void jz4740_init_timer(void)
+{
+ uint16_t val = 0;
+ val |= JZ_TIMER_CTRL_PRESCALE_16;
+ val |= JZ_TIMER_CTRL_SRC_EXT;
+
+ writew(val, jz4740_timer_base + JZ_REG_TIMER_CTRL(0));
+ writew(0xffff, jz4740_timer_base + JZ_REG_TIMER_DFR(0));
+ writew(val, jz4740_timer_base + JZ_REG_TIMER_CTRL(1));
+ writew(0xffff, jz4740_timer_base + JZ_REG_TIMER_DFR(1));
+}
+
+static void jz4740_timer_enable(unsigned int timer)
+{
+ writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR);
+ writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_SET);
+}
+
+static void jz4740_timer_disable(unsigned int timer)
+{
+ writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_CLEAR);
+ writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_SET);
+}
+
+static void jz4740_timer_irq_full_enable(unsigned int timer)
+{
+ writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
+ writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_CLEAR);
+}
+
+static int jz4740_timer_irq_full_is_enabled(unsigned int timer)
+{
+ return !(readl(jz4740_timer_base + JZ_REG_TIMER_MASK) &
+ JZ_TIMER_IRQ_FULL(timer));
+}
+
+static void jz4740_timer_irq_full_disable(unsigned int timer)
+{
+ writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_SET);
+}
+
+static void jz4740_timer_irq_half_enable(unsigned int timer)
+{
+ writel(JZ_TIMER_IRQ_HALF(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
+ writel(JZ_TIMER_IRQ_HALF(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_CLEAR);
+}
+
+static void jz4740_timer_irq_half_disable(unsigned int timer)
+{
+ writel(JZ_TIMER_IRQ_HALF(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_SET);
+}
+
+static cycle_t jz4740_clocksource_read(struct clocksource *cs)
+{
+ uint16_t val;
+ val = readw(jz4740_timer_base + JZ_REG_TIMER_CNT(1));
+ return val;
+}
+
+static struct clocksource jz4740_clocksource = {
+ .name = "jz4740-timer",
+ .rating = 200,
+ .read = jz4740_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(16),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static irqreturn_t jz4740_clockevent_irq(int irq, void *devid)
+{
+ struct clock_event_device *cd = devid;
+
+ writel(JZ_TIMER_IRQ_FULL(0), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
+
+ if (cd->mode != CLOCK_EVT_MODE_PERIODIC) {
+ jz4740_timer_disable(0);
+ cd->event_handler(cd);
+ } else {
+ cd->event_handler(cd);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void jz4740_clockevent_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *cd)
+{
+ switch(mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ writew(0x0, jz4740_timer_base + JZ_REG_TIMER_CNT(0));
+ writew(jz4740_jiffies_per_tick, jz4740_timer_base + JZ_REG_TIMER_DFR(0));
+ case CLOCK_EVT_MODE_RESUME:
+ jz4740_timer_irq_full_enable(0);
+ jz4740_timer_enable(0);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ jz4740_timer_disable(0);
+ break;
+ default:
+ break;
+ }
+}
+
+static int jz4740_clockevent_set_next(unsigned long evt, struct
+clock_event_device *cd)
+{
+ writew(0x0, jz4740_timer_base + JZ_REG_TIMER_CNT(0));
+ writew(evt, jz4740_timer_base + JZ_REG_TIMER_DFR(0));
+ jz4740_timer_enable(0);
+
+ return 0;
+}
+
+static struct clock_event_device jz4740_clockevent = {
+ .name = "jz4740-timer",
+ .features = CLOCK_EVT_FEAT_PERIODIC,
+ .set_next_event = jz4740_clockevent_set_next,
+ .set_mode = jz4740_clockevent_set_mode,
+ .rating = 200,
+ .irq = JZ_IRQ_TCU0,
+};
+
+static struct irqaction jz_irqaction = {
+ .handler = jz4740_clockevent_irq,
+ .flags = IRQF_PERCPU | IRQF_TIMER | IRQF_DISABLED,
+ .name = "jz4740-timerirq",
+ .dev_id = &jz4740_clockevent,
+};
+
+
+void __init plat_time_init(void)
+{
+ int ret;
+ uint32_t clk_rate;
+ struct clk *ext_clk;
+
+ jz4740_timer_base = ioremap(CPHYSADDR(TCU_BASE), 0x100);
+
+ if (!jz4740_timer_base) {
+ printk(KERN_ERR "Failed to ioremap timer registers");
+ return;
+ }
+
+ /*ext_clk = clk_get(NULL, "ext");
+ clk_rate = clk_get_rate(ext_clk) >> 4;
+ clk_put(ext_clk);*/
+
+
+ clk_rate = JZ_EXTAL >> 4;
+
+ jz4740_jiffies_per_tick = DIV_ROUND_CLOSEST(clk_rate, HZ);
+
+ clockevent_set_clock(&jz4740_clockevent, clk_rate);
+ jz4740_clockevent.min_delta_ns = clockevent_delta2ns(100, &jz4740_clockevent);
+ jz4740_clockevent.max_delta_ns = clockevent_delta2ns(0xffff, &jz4740_clockevent);
+ jz4740_clockevent.cpumask = cpumask_of(0);
+
+ clockevents_register_device(&jz4740_clockevent);
+
+ clocksource_set_clock(&jz4740_clocksource, clk_rate);
+ ret = clocksource_register(&jz4740_clocksource);
+
+ if (ret)
+ printk(KERN_ERR "Failed to register clocksource: %d\n", ret);
+
+ setup_irq(JZ_IRQ_TCU0, &jz_irqaction);
+
+ jz4740_init_timer();
+ writew(jz4740_jiffies_per_tick, jz4740_timer_base + JZ_REG_TIMER_DFR(0));
+ jz4740_timer_irq_half_disable(0);
+ jz4740_timer_irq_full_enable(0);
+ jz4740_timer_enable(0);
+
+ jz4740_timer_irq_half_disable(1);
+ jz4740_timer_irq_full_disable(1);
+
+ jz4740_timer_enable(1);
+}